00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
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 }