eyedbsmd.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021    Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 #include <eyedbconfig.h>
00025 
00026 #if TIME_WITH_SYS_TIME
00027 #include <sys/time.h>
00028 #include <time.h>
00029 #else
00030 #if HAVE_SYS_TIME_H
00031 #include <sys/time.h>
00032 #else
00033 #include <time.h>
00034 #endif
00035 #endif
00036 
00037 #include <sys/types.h>
00038 #include <sys/socket.h>
00039 #include <sys/uio.h>
00040 #include <sys/un.h>
00041 #include <netdb.h>
00042 #include <netinet/in.h>
00043 #include <unistd.h>
00044 #include <sys/wait.h>
00045 #include <sys/types.h>
00046 #include <sys/select.h>
00047 #include <signal.h>
00048 #include <unistd.h>
00049 #include <fcntl.h>
00050 #include <sys/stat.h>
00051 #include <errno.h>
00052 // #include <limits.h>
00053 
00054 #include <eyedblib/rpc_lib.h>
00055 #include <eyedblib/stdlist.h>
00056 #include <eyedblib/semlib.h>
00057 #include <eyedblib/filelib.h>
00058 #include <eyedblib/filelib.h>
00059 #include <eyedbsm/smd.h>
00060 #include <eyedblib/log.h>
00061 #include <kern_p.h>
00062 
00063 #define USE_INODE
00064 
00065 using namespace eyedbsm;
00066 
00067 static int smd_refcnt;
00068 
00069 //#define TRACE
00070 static void clean_exit(int from);
00071 
00072 class Reference {
00073 
00074 protected:
00075   Reference() {
00076     refcnt = 1;
00077   }
00078 
00079   void incrRefCount() {
00080     refcnt++;
00081   }
00082 
00083   int decrRefCount() {
00084     return --refcnt;
00085   }
00086 
00087 public:
00088   int getRefCount() const {
00089     return refcnt;
00090   }
00091 
00092 private:
00093   int refcnt;
00094 };
00095 
00096 #ifdef HAVE_SEMAPHORE_POLICY_SYSV_IPC
00097 class Semaphore : public Reference {
00098   int key;
00099   int excl;
00100   static std::list<Semaphore *> sem_list;
00101 
00102   Semaphore(int _key, int _excl) : Reference() {
00103     key = _key;
00104     excl = _excl;
00105 #ifdef TRACE
00106     fprintf(stderr, "eyedbsmd: creating semaphore ");
00107     trace();
00108     fprintf(stderr, "\n");
00109 #endif
00110     sem_list.push_back(this);
00111   }
00112 
00113 public:
00114   int isExcl() const {
00115     return excl;
00116   }
00117 
00118   int getKey() const {
00119     return key;
00120   }
00121 
00122   void release() {
00123 #ifdef TRACE
00124     fprintf(stderr, "eyedbsmd: releasing semaphore 0x%08x [refcnt:%d]\n", key, getRefCount());
00125 #endif
00126     if (!decrRefCount()) {
00127       bool r = std_list_erase(sem_list, this);
00128       if (!r)
00129         std::cerr << "Warning: semaphore::release " << key << "not found\n";
00130       delete this;
00131     }
00132   }
00133 
00134   ~Semaphore() {
00135 #ifdef TRACE
00136     fprintf(stderr, "eyedbsmd: deleting key 0x%08x\n", key);
00137 #endif
00138     ut_sem_rm(ut_sem_open(key));
00139   }
00140 
00141   void trace() {
00142     fprintf(stderr, "eyedbsmd: key 0x%08x [%s]", key, (excl ? "excl" : "shared"));
00143   }
00144 
00145   static Semaphore *find(int excl) {
00146     int key;
00147     Semaphore *sem;
00148 
00149     if (ut_sem_find(&key, excl) >= 0)
00150       return new Semaphore(key, excl);
00151 
00152     std::list<Semaphore *>::const_iterator begin = sem_list.begin();
00153     std::list<Semaphore *>::const_iterator end = sem_list.end();
00154 
00155     while (begin != end ) {
00156       Semaphore *sem = *begin;
00157       if (!sem->isExcl()) {
00158         sem->incrRefCount();
00159         return sem;
00160       }
00161       ++begin;
00162     }
00163 
00164 #ifdef TRACE
00165     fprintf(stderr, "eyedbsmd: cannot find any semaphore\n");
00166 #endif
00167     return 0;
00168   }
00169 
00170   static void traceList() {
00171     std::list<Semaphore *>::const_iterator begin = sem_list.begin();
00172     std::list<Semaphore *>::const_iterator end = sem_list.end();
00173 
00174     while (begin != end ) {
00175       Semaphore *sem = *begin;
00176       sem->trace();
00177       ++begin;
00178     }
00179   }
00180 };
00181 #endif
00182 
00183 class DbFile : public Reference {
00184 #ifdef USE_INODE
00185   ino_t ino;
00186   dev_t dev; 
00187   char *dbfile;
00188 #else
00189   char *dbfile;
00190 #endif
00191 
00192 #ifdef HAVE_SEMAPHORE_POLICY_SYSV_IPC
00193   Semaphore *sm[ESM_NSEMS];
00194 #endif
00195   static std::list<DbFile *> dbfile_list;
00196 
00197   DbFile(const char *_dbfile) : Reference() {
00198 #ifdef USE_INODE
00199     struct stat st;
00200     if (stat(_dbfile, &st) >= 0) {
00201       ino = st.st_ino;
00202       dev = st.st_dev;
00203     }
00204     else {
00205 #ifdef TRACE
00206       fprintf(stderr, "eyedbsmd: cannot stat file %s\n", _dbfile);
00207 #endif
00208       ino = 0;
00209       dev = 0;
00210     }
00211 
00212     dbfile = strdup(_dbfile);
00213 #else
00214     dbfile = strdup(_dbfile);
00215 #endif
00216 
00217 #ifdef HAVE_SEMAPHORE_POLICY_SYSV_IPC
00218     sm[0] = Semaphore::find(1);
00219     sm[1] = Semaphore::find(0);
00220 #endif
00221     dbfile_list.push_back(this);
00222 #ifdef TRACE
00223     fprintf(stderr, "eyedbsmd: creating dbfile ");
00224     trace();
00225     fprintf(stderr, "\n");
00226 #endif
00227   }
00228 
00229   ~DbFile() {
00230     free(dbfile);
00231 #ifdef TRACE
00232     fprintf(stderr, "eyedbsmd: deleting dbfile %s\n", getDbfile());
00233 #endif
00234 #ifdef HAVE_SEMAPHORE_POLICY_SYSV_IPC
00235     for (int i = 0; i < ESM_NSEMS; i++)
00236       if (sm[i]) sm[i]->release();
00237 #endif
00238   }
00239 
00240 public:
00241 
00242 #ifdef HAVE_SEMAPHORE_POLICY_SYSV_IPC
00243   int getSemaphores(int sx[]) const {
00244     for (int i = 0; i < ESM_NSEMS; i++)
00245       sx[i] = (sm[i] ? sm[i]->getKey() : 0);
00246 
00247     return 0;
00248   }
00249 #endif
00250 
00251 #if 0
00252   const char *getDbfile() const {
00253     static std::string st_dbfile;
00254     char buf[64];
00255     sprintf(buf, "dev=%d,ino=%d", dev, ino);
00256     st_dbfile = buf;
00257     return st_dbfile.c_str();
00258   }
00259 #else
00260   const char *getDbfile() const {
00261     return dbfile;
00262   }
00263 #endif
00264 
00265   void release() {
00266 #ifdef TRACE
00267     fprintf(stderr, "eyedbsmd: releasing dbfile %s [refcnt:%d]\n", getDbfile(), getRefCount());
00268 #endif
00269     if (!decrRefCount()) {
00270       bool r = std_list_erase(dbfile_list, this);
00271 #ifdef TRACE
00272       if (!r)
00273         std::cerr << "Warning: DbFile::release " << getDbfile() << "not found\n";
00274 #endif
00275       delete this;
00276     }
00277   }
00278 
00279   static DbFile *find(const char *dbfile, int get_sems, int &found) {
00280     std::list<DbFile *>::const_iterator begin = dbfile_list.begin();
00281     std::list<DbFile *>::const_iterator end = dbfile_list.end();
00282     DbFile *dbf;
00283 
00284 #ifdef USE_INODE
00285     struct stat st;
00286     ino_t ino;
00287     dev_t dev; 
00288 
00289     if (stat(dbfile, &st) >= 0) {
00290       ino = st.st_ino;
00291       dev = st.st_dev;
00292     }
00293     else {
00294       ino = 0;
00295       dev = 0;
00296     }
00297 
00298     while (begin != end) {
00299       dbf = *begin;
00300       if (ino && dev) {
00301         if (dbf->ino == ino && dbf->dev == dev) {
00302           if (get_sems)
00303             dbf->incrRefCount();
00304           found = 1;
00305           return dbf;
00306         }
00307       }
00308       else {
00309         if (!strcmp(dbf->dbfile, dbfile)) {
00310           if (get_sems)
00311             dbf->incrRefCount();
00312           found = 1;
00313           return dbf;
00314         }
00315       }
00316       ++begin;
00317     }
00318 #else
00319     while (begin != end) {
00320       dbf = *begin;
00321       if (!strcmp(dbf->dbfile, dbfile)) {
00322         if (get_sems)
00323           dbf->incrRefCount();
00324         found = 1;
00325         return dbf;
00326       }
00327       ++begin;
00328     }
00329 #endif
00330 
00331     found = 0;
00332     if (get_sems) {
00333       dbf = new DbFile(dbfile);
00334       
00335       Status s = dbCleanup(dbfile);
00336       if (s && s->err != CANNOT_LOCK_SHMFILE)
00337         statusPrint(s, "eyedbsmd");
00338 #ifdef TRACE
00339       if (s)
00340         statusPrint(s, "eyedbsmd");
00341 #endif
00342       return dbf;
00343     }
00344     return 0;
00345   }
00346 
00347   void trace() {
00348     fprintf(stderr, "eyedbsmd: %s, ", getDbfile());
00349 #ifdef HAVE_SEMAPHORE_POLICY_SYSV_IPC
00350     for (int i = 0; i < ESM_NSEMS; i++) {
00351       if (i) fprintf(stderr, ", ");
00352       if (!sm[i]) fprintf(stderr, "*");
00353       else sm[i]->trace();
00354     }
00355 #endif
00356   }
00357 
00358   static void traceList() {
00359     std::list<DbFile *>::const_iterator begin = dbfile_list.begin();
00360     std::list<DbFile *>::const_iterator end = dbfile_list.end();
00361     DbFile *dbf;
00362 
00363     while (begin != end) {
00364       dbf = *begin;
00365       dbf->trace();
00366       fprintf(stderr, "\n");
00367       ++begin;
00368     }
00369   }
00370 };
00371 
00372 class Client {
00373   int fd;
00374   static std::list<Client *> client_list;
00375   std::list<DbFile *> dbfile_list;
00376 
00377 public:
00378   Client(int _fd) {
00379     fd = _fd;
00380 #ifdef TRACE
00381     fprintf(stderr, "eyedbsmd: creating client %d\n", fd);
00382 #endif
00383     client_list.push_back(this);
00384   }
00385 
00386   void addDbFile(DbFile *dbf) {
00387     dbfile_list.push_back(dbf);
00388 
00389 #ifdef TRACE
00390     if (dbf)
00391       fprintf(stderr, "eyedbsmd: adding dbfile %s to client %d [refcnt:%d]\n", dbf->getDbfile(), fd,
00392               dbf->getRefCount());
00393     else
00394       fprintf(stderr, "eyedbsmd: adding null dbfile\n");
00395 #endif
00396   }
00397 
00398   void rmDbFile(DbFile *dbf) {
00399 #ifdef TRACE
00400     if (dbf)
00401       fprintf(stderr, "eyedbsmd: removing dbfile %s from client %d\n", dbf->getDbfile(), fd);
00402     else
00403       fprintf(stderr, "eyedbsmd: removing null dbfile\n");
00404 #endif
00405     std::list<DbFile *>::iterator db_begin = dbfile_list.begin();
00406     std::list<DbFile *>::iterator db_end = dbfile_list.end();
00407     while (db_begin != db_end) {
00408       DbFile *xdbf = *db_begin;
00409       if (xdbf == dbf) {
00410         dbf->release();
00411         bool r = std_list_erase(dbfile_list, dbf);
00412 #ifdef TRACE
00413         if (!r)
00414           std::cerr << "Warning: rmDbFile not found\n";
00415 #endif
00416         return;
00417       }
00418       ++db_begin;
00419     }
00420 
00421 #ifdef TRACE
00422     fprintf(stderr, "eyedbsmd: dbfile %s not found in client %d\n", dbf->getDbfile(), fd);
00423 #endif
00424   }
00425 
00426   ~Client() {
00427 #ifdef TRACE
00428     fprintf(stderr, "eyedbsmd: releasing client %d\n", fd);
00429 #endif
00430     std::list<DbFile *>::iterator db_begin = dbfile_list.begin();
00431     std::list<DbFile *>::iterator db_end = dbfile_list.end();
00432     while (db_begin != db_end) {
00433       DbFile *dbf = *db_begin;
00434       dbf->release();
00435       ++db_begin;
00436     }
00437     bool r = std_list_erase(client_list, this);
00438 #ifdef TRACE
00439     if (!r)
00440       std::cerr << "Warning: Client not found\n";
00441 #endif
00442   }
00443 
00444   static void clean_all() {
00445     std::list<Client *>::iterator cl_begin = client_list.begin();
00446     std::list<Client *>::iterator cl_end = client_list.end();
00447 
00448     while (cl_begin != cl_end) {
00449       Client *client = *cl_begin;
00450       std::list<DbFile *>::iterator db_begin = client->dbfile_list.begin();
00451       std::list<DbFile *>::iterator db_end = client->dbfile_list.end();
00452       while (db_begin != db_end) {
00453         DbFile *dbf = *db_begin;
00454         dbf->release();
00455         ++db_begin;
00456       }
00457       ++cl_begin;
00458     }
00459   }
00460 
00461   static Client *find(int fd) {
00462     std::list<Client *>::iterator begin = client_list.begin();
00463     std::list<Client *>::iterator end = client_list.end();
00464     while (begin != end) {
00465       Client *client = *begin;
00466       if (client->fd == fd)
00467         return client;
00468       ++begin;
00469     }
00470 
00471     return 0;
00472   }
00473 };
00474 
00475 std::list<DbFile *> DbFile::dbfile_list;
00476 
00477 #ifdef HAVE_SEMAPHORE_POLICY_SYSV_IPC
00478 std::list<Semaphore *> Semaphore::sem_list;
00479 #endif
00480 
00481 std::list<Client *> Client::client_list;
00482 
00483 static void
00484 unit_test()
00485 {
00486   DbFile *dbf1, *dbf2, *dbf3;
00487   int found;
00488   dbf1 = DbFile::find("foo.dbs", 1, found);
00489   dbf2 = DbFile::find("goo.dbs", 1, found);
00490   dbf3 = DbFile::find("foo.dbs", 1, found);
00491 
00492   DbFile::traceList();
00493 
00494   fprintf(stderr, "continue> ");
00495   getchar();
00496 
00497   dbf1->release();
00498   dbf2->release();
00499   dbf3->release();
00500 }
00501 
00502 static struct sockaddr_un sock_un_name;
00503 
00504 static int
00505 port_open(const char *port)
00506 {
00507   int sockun_fd;
00508   int v = 1;
00509 
00510   rpc_checkAFUnixPort(port);
00511   
00512   if ((sockun_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
00513     fprintf(stderr, "eyedbsmd: unable to create unix socket port `%d'\n", port);
00514     return -1;
00515   }
00516   
00517   if (setsockopt(sockun_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&v, sizeof(v)) <
00518       0) {
00519     fprintf(stderr, "eyedbsmd: setsockopt reuseaddr\n");
00520     return -1;
00521   }
00522 
00523   sock_un_name.sun_family = AF_UNIX;
00524   strcpy(sock_un_name.sun_path, port);
00525 
00526   if (bind(sockun_fd, (struct sockaddr *)&sock_un_name,
00527            sizeof(sock_un_name)) < 0 ) {
00528     fprintf(stderr, "eyedbsmd: bind: failing on port %s (%s)\n", port,
00529             strerror(errno));
00530     fprintf(stderr, "\nPerharps another eyedbsmd is running on port:\n%s\n",
00531             port);
00532     fprintf(stderr, "\nIf no, unlink this port as follows:\n");
00533     fprintf(stderr, "rm -f %s\n", port);
00534     fprintf(stderr, "and relaunch the server.\n");
00535     return -1;
00536   }
00537 
00538   chmod(port, 0777);
00539   if (sockun_fd >= 0 && listen(sockun_fd, 2) < 0 ) {
00540     fprintf(stderr, "eyedbsmd: listen: failing on port %s (%s)\n", port,
00541             strerror(errno));
00542     return -1;
00543   }
00544 
00545   return sockun_fd;
00546 }
00547 
00548 static void
00549 clear_client(fd_set &fds, int fd, int &max_fd)
00550 {
00551   Client *client = Client::find(fd);
00552   delete client;
00553   FD_CLR(fd, &fds);
00554   close(fd);
00555   if (max_fd == fd)
00556     --max_fd;
00557 }
00558 
00559 static const char *
00560 string_message(int msg)
00561 {
00562   if (msg == SMD_INIT)
00563     return "SMD_INIT";
00564 
00565   if (msg == SMD_INIT_GETSEMS)
00566     return "SMD_INIT_GETSEMS";
00567 
00568   if (msg == SMD_RELEASE)
00569     return "SMD_RELEASE";
00570 
00571   if (msg == SMD_STATUS)
00572     return "SMD_STATUS";
00573 
00574   if (msg == SMD_DECL)
00575     return "SMD_DECL";
00576 
00577   if (msg == SMD_UNDECL)
00578     return "SMD_UNDECL";
00579 
00580   if (msg == SMD_STOP)
00581     return "SMD_STOP";
00582 
00583   return "UNKNOWN";
00584 }
00585 
00586 static int
00587 manage_message(int fd)
00588 {
00589   int msg;
00590   Client *client = Client::find(fd);
00591   if (!client)
00592     return 0;
00593 
00594   if (rpc_socketRead(fd, &msg, sizeof(msg)) != sizeof(msg))
00595     return 0;
00596 
00597   /*
00598   time_t t0 = time(0);
00599   fprintf(stderr, "Getting Message '%s' at %s", string_message(msg),
00600           ctime(&t0));
00601   fflush(stderr);
00602   */
00603 
00604   if (msg == SMD_INIT || msg == SMD_INIT_GETSEMS || msg == SMD_RELEASE) {
00605     int len;
00606     if (rpc_socketRead(fd, &len, sizeof(len)) != sizeof(len))
00607       return 0;
00608 
00609     char *dbfile = new char[len];
00610     if (rpc_socketRead(fd, dbfile, len) != len)
00611       return 0;
00612 
00613     int found;
00614     DbFile *dbf = DbFile::find(dbfile, (msg == SMD_INIT_GETSEMS ||
00615                                         msg == SMD_INIT), found);
00616     delete [] dbfile;
00617     
00618     if (msg == SMD_INIT_GETSEMS) {
00619 #ifdef HAVE_SEMAPHORE_POLICY_SYSV_IPC
00620       client->addDbFile(dbf);
00621 
00622       int sm[ESM_NSEMS];
00623       dbf->getSemaphores(sm);
00624       
00625       if (rpc_socketWrite(fd, sm, sizeof(int)*ESM_NSEMS) !=
00626           sizeof(int)*ESM_NSEMS)
00627         return 0;
00628 #else
00629       assert(0);
00630 #endif
00631     }
00632     else if (msg == SMD_INIT) {
00633       client->addDbFile(dbf);
00634       if (rpc_socketWrite(fd, &msg, sizeof(msg)) != sizeof(msg))
00635         return 0;
00636     }
00637     else
00638       client->rmDbFile(dbf);
00639   }
00640   else if (msg == SMD_STATUS) {
00641     fprintf(stderr, "eyedbsmd: Reference Count: %d\n", smd_refcnt);
00642     DbFile::traceList();
00643 #ifdef HAVE_SEMAPHORE_POLICY_SYSV_IPC
00644     Semaphore::traceList();
00645 #endif
00646   }
00647   else if (msg == SMD_DECL)
00648     smd_refcnt++;
00649   else if (msg == SMD_UNDECL) {
00650     if (smd_refcnt > 0)
00651       --smd_refcnt;
00652   }
00653   else if (msg == SMD_STOP) {
00654 #ifdef TRACE
00655     fprintf(stderr, "eyedbsmd: smd_refcnt %d\n", smd_refcnt);
00656 #endif
00657     Client::clean_all();
00658     clean_exit(1);
00659     exit(0);
00660   }
00661   else {
00662     fprintf(stderr, "eyedbsmd: unknown message %x\n", msg);
00663     return 0;
00664   }
00665 
00666   return 1;
00667 }
00668 
00669 static void
00670 net_main_loop(int sock_fd)
00671 {
00672   fd_set fds;
00673   int max_fd = sock_fd, fd;
00674 
00675   FD_ZERO(&fds);
00676   FD_SET(sock_fd, &fds);
00677   
00678   for (;;) {
00679 #ifdef TRACE
00680     fprintf(stderr, "eyedbsmd: \nwaiting on socket %d, maxfd %d\n", sock_fd, max_fd);
00681 #endif
00682     fd_set fdt = fds;
00683     if (select (max_fd+1, &fdt, 0, 0, 0) < 0) {
00684       perror("select");
00685       continue;
00686     }
00687 
00688     for (fd = 0; fd <= max_fd; fd++)
00689       if (FD_ISSET(fd, &fdt))  {
00690         if (fd == sock_fd) {
00691           struct sockaddr *sock_addr;
00692 #if defined(ORIGIN) || defined(ALPHA)
00693           int length;
00694 #else
00695           socklen_t length;
00696 #endif
00697           int input_fd;
00698 
00699           sock_addr = (struct sockaddr *)&sock_un_name;
00700           length = sizeof(sock_un_name);
00701 
00702           if ((input_fd = accept(fd, sock_addr, &length)) < 0) {
00703             perror("accept");
00704             continue;
00705           }
00706 
00707           new Client(input_fd);
00708           FD_SET(input_fd, &fds);
00709           if (input_fd > max_fd)
00710             max_fd = input_fd;
00711         }
00712         else if (!manage_message(fd)) {
00713           clear_client(fds, fd, max_fd);
00714           continue;
00715         }
00716       }
00717   }
00718 }
00719 
00720 static const char *port;
00721 
00722 static void
00723 clean_exit(int from)
00724 {
00725 #ifdef TRACE
00726   fprintf(stderr, "eyedbsmd: clean_exit(%d)\n", from);
00727 #endif
00728   unlink(port);
00729 }
00730 
00731 static void
00732 signal_handler(int sig) 
00733 {
00734 #ifdef TRACE
00735   fprintf(stderr, "eyedbsmd: receive signal #%d\n", sig);
00736 #endif
00737   sleep(1000);
00738   clean_exit(2);
00739   exit(sig);
00740 }
00741 
00742 static int
00743 notice(int status)
00744 {
00745   const char *s;
00746   if (s = getenv("EYEDBPFD")) {
00747     int pfd = atoi(s);
00748     if (pfd > 0) {
00749       write(pfd, &status, sizeof(status));
00750       close(pfd);
00751     }
00752   }
00753 
00754   return status;
00755 }
00756 
00757 static void
00758 init()
00759 {
00760   signal(SIGHUP,  SIG_IGN);
00761   signal(SIGINT,  SIG_IGN);
00762   //  signal(SIGTERM, signal_handler);
00763   signal(SIGQUIT, signal_handler);
00764   signal(SIGSEGV, signal_handler);
00765   signal(SIGBUS,  signal_handler);
00766   signal(SIGABRT, signal_handler);
00767 }
00768 
00769 static int
00770 usage(const char *prog) {
00771   fprintf(stderr, "usage: %s [-p PORT|--port=PORT] [--status] [--stop]\n", prog);
00772   return notice(1);
00773 }
00774 
00775 int
00776 main(int argc, char *argv[])
00777 {
00778   enum Action {
00779     Daemon = 1,
00780     Status,
00781     Stop
00782   } action;
00783 
00784   action = Daemon;
00785 
00786   static const char port_opt[] = "--port=";
00787   unsigned int port_len = strlen(port_opt);
00788 
00789   for (int n = 1; n < argc; n++) {
00790     const char *s = argv[n];
00791     if (*s == '-') {
00792       if (!strcmp(s, "-p")) {
00793         if (n == argc-1)
00794           return usage(argv[0]);
00795         smd_set_port(argv[++n]);
00796       } 
00797       else if (!strncmp(s, port_opt, port_len)) {
00798         smd_set_port(&argv[n][port_len]);
00799       } 
00800       else if (!strcmp(s, "--status")) {
00801         action = Status;
00802       }
00803       else if (!strcmp(s, "--stop")) {
00804         action = Stop;
00805       }
00806       else
00807         return usage(argv[0]);
00808     }
00809     else
00810       return usage(argv[0]);
00811   }
00812 
00813   if (action != Daemon) {
00814     smdcli_conn_t *conn = smdcli_open(smd_get_port());
00815 
00816     if (!conn)
00817       return 1;
00818 
00819     if (action == Stop)
00820       return smdcli_stop(conn);
00821 
00822     return smdcli_status(conn);
00823   }
00824 
00825   const char *logmask = getenv("IDB_LOG_MASK");
00826   if (logmask) {
00827     utlogInit(argv[0], "stderr");
00828     sscanf(logmask, "%llx", &eyedblib::log_mask);
00829   }
00830 
00831   port = smd_get_port();
00832 
00833   eyedbsm::init();
00834   ::init();
00835 
00836   int sock_fd = port_open(port);
00837   if (sock_fd < 0)
00838     return notice(1);
00839 
00840   smd_refcnt = 1;
00841   (void)notice(0);
00842 
00843 #ifndef TRACE
00844   close(0);
00845   close(1);
00846   close(2);
00847 #endif
00848   net_main_loop(sock_fd);
00849 
00850   clean_exit(3);
00851   return notice(0);
00852 }

Generated on Mon Dec 22 18:15:54 2008 for eyedb by  doxygen 1.5.3