eyedbctl.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 
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <stdio.h>
00028 #include <eyedb/eyedb.h>
00029 #include "SessionLog.h"
00030 #include <unistd.h>
00031 #include <sys/wait.h>
00032 #include <signal.h>
00033 #include <eyedbsm/smd.h>
00034 #include <eyedblib/strutils.h>
00035 #include "comp_time.h"
00036 #include "lib/compile_builtin.h"
00037 
00038 using namespace eyedb;
00039 using namespace std;
00040 
00041 namespace eyedb {
00042   extern void printVersion();
00043 }
00044 
00045 static int
00046 usage(const char *prog)
00047 {
00048   cerr << "usage: " << prog << " ";
00049   cerr << "[-h|--help|-v|--version] [start|stop|status] [-f] [--creating-dbm] ";
00050   print_common_usage(cerr, true);
00051   cerr << endl;
00052   return 1;
00053 }
00054 
00055 static void help(const char *prog)
00056 {
00057   usage(prog);
00058   cerr << "\nProgram Options:\n";
00059   cerr << "  start [-f]     Launch the server. Set -f to force launch\n";
00060   cerr << "  stop [-f]      Stop the server. Set -f to force stop\n";
00061   cerr << "  status         Display status on the running server\n";
00062   cerr << "  --creating-dbm Bootstrap option for DBM database creation\n";
00063   print_common_help(cerr, true);
00064 }
00065 
00066 static void
00067 check(const char *opt, int i, int argc)
00068 {
00069   if (i >= argc - 1) {
00070     fprintf(stderr, "eyedb options: missing argument after '%s'\n", opt);
00071     exit(1);
00072   }
00073 }
00074 
00075 enum Command {
00076   Start = 1,
00077   Stop,
00078   CStatus
00079 };
00080 
00081 static void
00082 ld_libpath_manage()
00083 {
00084   static const char ld_libpath_env[] = "LD_LIBRARY_PATH";
00085   char *ld_library_path = getenv(ld_libpath_env);
00086   char env[2048];
00087   sprintf(env, "%s=%s%s%s", ld_libpath_env,
00088           eyedb::ServerConfig::getSValue("sopath"),
00089           (ld_library_path ? ":" : ""),
00090           (ld_library_path ? ld_library_path : ""));
00091   putenv(strdup(env));
00092 }
00093 
00094 static const char *sbindir;
00095 #define PIPE_SYNC
00096 
00097 extern char **environ;
00098 
00099 static int
00100 execute(const char *prog, const char *arg, Bool pipes)
00101 {
00102   int pid;
00103 
00104 #ifdef PIPE_SYNC
00105   int pfd[2];
00106   if (pipes && pipe(pfd) < 0) {
00107     fprintf(stderr, "eyedbctl: cannot create unnamed pipes\n");
00108     return 1;
00109   }
00110 #endif
00111 
00112   if ((pid = fork()) == 0) {
00113     std::string cmd = std::string(sbindir) + "/" + prog;
00114     char *argv[3];
00115 
00116     argv[0] = (char *)prog;
00117     argv[1] = (char *)arg;
00118     argv[2] = 0;
00119 #ifdef PIPE_SYNC
00120     if (pipes) {
00121       close(pfd[0]);
00122       putenv(strdup((std::string("EYEDBPFD=") + str_convert((long)pfd[1])).c_str()));
00123     }
00124 #endif
00125     if (execve(cmd.c_str(), argv, environ) < 0) {
00126       fprintf(stderr, "eyedbctl: cannot execute '%s'\n", cmd.c_str());
00127       return -1;
00128     }
00129   }
00130 
00131 #ifdef PIPE_SYNC
00132   if (pipes) {
00133     int status = 0;
00134     if (read(pfd[0], &status, sizeof(status)) != sizeof(status)) {
00135       fprintf(stderr, "eyedbctl: eyedbd smd start failed\n");
00136       return 0;
00137     }
00138       
00139     if (status)
00140       return -1;
00141   }
00142 #endif
00143   return pid;
00144 }
00145 
00146 static int
00147 startServer(int argc, char *argv[], const char *smdport)
00148 {
00149 #ifdef HAVE_EYEDBSMD
00150   smdcli_conn_t *conn = smdcli_open(smd_get_port());
00151   if (conn) {
00152     if (smdcli_declare(conn) < 0)
00153       return 1;
00154     smdcli_close(conn);
00155     conn = 0;
00156   }
00157   else if (execute("eyedbsmd", (std::string("--port=") + smdport).c_str(), True) < 0)
00158     return 1;
00159 #endif
00160 
00161 #ifdef PIPE_SYNC
00162   int pfd[2];
00163   if (pipe(pfd) < 0) {
00164     fprintf(stderr, "eyedbctl: cannot create unnamed pipes\n");
00165     return 1;
00166   }
00167 #endif
00168 
00169   int pid;
00170 
00171   if ((pid = fork()) == 0) {
00172     ld_libpath_manage();
00173     std::string cmd = std::string(sbindir) + "/eyedbd";
00174     std::string s = std::string("eyedbd");
00175 
00176     argv[0] = (char *)s.c_str();
00177 #ifdef PIPE_SYNC
00178     close(pfd[0]);
00179     putenv(strdup((std::string("EYEDBPFD=") + str_convert((long)pfd[1])).c_str()));
00180 #endif
00181     if (execve(cmd.c_str(), argv, environ) < 0) {
00182       kill(getppid(), SIGINT);
00183       fprintf(stderr, "eyedbctl: cannot execute '%s'\n", cmd.c_str());
00184     }
00185 
00186     exit(1);
00187   }
00188 
00189   if (pid < 0)
00190     return 1;
00191 
00192   close(pfd[1]);
00193   int status = 0;
00194 
00195 #ifdef PIPE_SYNC
00196   if (read(pfd[0], &status, sizeof(status)) != sizeof(status)) {
00197     fprintf(stderr, "eyedbctl: eyedbd daemon start failed\n");
00198     return 1;
00199   }
00200 
00201   if (!status)
00202     fprintf(stderr, "Starting EyeDB Server\n"
00203             " Version      V%s\n"
00204             " Compiled     %s\n"
00205             " Architecture %s\n"
00206             " Program Pid  %d\n",
00207             eyedb::getVersion(),
00208             getCompilationTime(),
00209             Architecture::getArchitecture()->getArch(),
00210             pid);
00211 #endif
00212 
00213   return status;
00214 }
00215 
00216 static void unlink_port(const char *port)
00217 {
00218   if (*port == '/' || strchr(port, ':') == 0) {
00219     unlink(port);
00220   }
00221 }
00222 
00223 static void unlink_ports(const char *smdport, const char *_listen)
00224 {
00225   char *listen = strdup(_listen);
00226   char *p = listen;
00227 
00228   for (;;) {
00229     char *q = strchr(p, ',');
00230     if (q)
00231       *q = 0;
00232     unlink_port(p);
00233     if (!q)
00234       break;
00235     p = q + 1;
00236   }
00237 
00238 #ifdef HAVE_EYEDBSMD
00239   unlink(smdport);
00240 #endif
00241 }
00242 
00243 static void make_host_port(const char *_listen, const char *&host,
00244                            const char *&port)
00245 {
00246   char *listen = strdup(_listen);
00247 
00248   char *p;
00249   if (p = strchr(listen, ','))
00250     *p = 0;
00251 
00252   if (p = strchr(listen, ':')) {
00253     *p = 0;
00254     host = listen;
00255     port = p+1;
00256   }
00257   else {
00258     host = "localhost";
00259     port = listen;
00260   }
00261 }
00262 
00263 static int checkPostInstall(Bool creatingDbm)
00264 {
00265   if (!creatingDbm) {
00266     const char *dbm = Database::getDefaultServerDBMDB();
00267     if (!dbm || access(dbm, R_OK)) {
00268       fprintf(stderr, "\nThe EYEDBDBM database file '%s' is not accessible\n",
00269               dbm);
00270       fprintf(stderr, "Did you run the post install script 'eyedb-postinstall.sh' ?\n");
00271       fprintf(stderr, "If yes, check your configuration or launch eyedbctl with option --creating-dbm\n");
00272       return 1;
00273     }
00274   }
00275   return 0;
00276 }
00277 
00278 int
00279 main(int argc, char *argv[])
00280 {
00281   const char *listen, *smdport, *s;
00282   eyedbsm::Status status;
00283   Bool force = False;
00284   Bool creatingDbm = False;
00285   string sv_host, sv_port;
00286 
00287   string sv_listen;
00288   try {
00289     if (argc < 2)
00290       return usage(argv[0]);
00291 
00292     Command cmd;
00293 
00294     if (!strcmp(argv[1], "start"))
00295       cmd = Start;
00296     else if (!strcmp(argv[1], "stop"))
00297       cmd = Stop;
00298     else if (!strcmp(argv[1], "status"))
00299       cmd = CStatus;
00300     else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
00301       help(argv[0]);
00302       return 0;
00303     }
00304     else if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) {
00305       eyedb::printVersion();
00306       return 0;
00307     }
00308     else
00309       return usage(argv[0]);
00310 
00311     eyedb::init(argc, argv, &sv_listen, false);
00312 
00313     listen = sv_listen.c_str();
00314 
00315     eyedb::Exception::setMode(eyedb::Exception::StatusMode);
00316 
00317     for (int i = 2; i < argc; i++) {
00318       char *s = argv[i];
00319       if (!strcmp(s, "-f"))
00320         force = True;
00321       else if (!strcmp(s, "--creating-dbm"))
00322         creatingDbm = True;
00323       else
00324         break;
00325     }
00326 
00327     std::string s_l;
00328     if (!*listen && (s = eyedb::ServerConfig::getSValue("listen")))
00329       listen = s;
00330 
00331     smdport = smd_get_port();
00332 
00333     if (cmd == Start && force) {
00334       unlink_ports(smdport, listen);
00335     }
00336 
00337     //    sbindir = eyedblib::CompileBuiltin::getSbindir();
00338     sbindir = ServerConfig::getSValue("@sbindir");
00339 
00340     int ac;
00341     char **av;
00342 
00343     if (cmd == Start) {
00344       int st = force + creatingDbm;
00345 
00346       if (checkPostInstall(creatingDbm))
00347         return 1;
00348 
00349       ac = argc - st;
00350       av = &argv[st+1];
00351     }
00352 
00353     const char *host, *port;
00354     make_host_port(listen, host, port);
00355     
00356     SessionLog sesslog(host, port, eyedb::ServerConfig::getSValue("tmpdir"),
00357                        True);
00358                        //(cmd == CStatus ? False : True));
00359 
00360 
00361     if (sesslog.getStatus()) {
00362       if (cmd == Start)
00363         return startServer(ac, av, smdport);
00364       if (sesslog.getStatus()->getStatus() == IDB_CONNECTION_LOG_FILE_ERROR) {
00365         cerr << "No EyeDB Server is running on " << host << ":" << port << endl;
00366         return 1;
00367       }
00368       sesslog.getStatus()->print();
00369       return 1;
00370     }
00371 
00372     if (cmd == Start)
00373       return startServer(ac, av, smdport);
00374 
00375     if (cmd == Stop) {
00376       Status status = sesslog.stopServers(force);
00377       if (status) {
00378         status->print();
00379         return 1;
00380       }
00381 
00382 #ifndef HAVE_EYEDBSMD
00383       return 0;
00384 #else
00385       smdcli_conn_t *conn = smdcli_open(smd_get_port());
00386       if (!conn) {
00387         fprintf(stderr, "cannot connect to eyedbsmd daemon\n");
00388         return 1;
00389       }
00390     
00391       int r = smdcli_stop(conn);
00392       smdcli_close(conn);
00393       conn = 0;
00394       return r;
00395 #endif
00396     }
00397 
00398     sesslog.display(stdout, force);
00399   }
00400   catch(Exception &e) {
00401     cerr << e << flush;
00402     return 1;
00403   }
00404 
00405   return 0;
00406 }

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