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
00026
00027
00028
00029
00030
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "configure.h"
00034 #endif
00035
00036 #if HAVE_STDIO_H
00037 #include <stdio.h>
00038 #else
00039 #error "Need stdio.h"
00040 #endif
00041
00042 #if HAVE_UNISTD_H
00043 #include <unistd.h>
00044 #else
00045 #error "Need unistd.h"
00046 #endif
00047
00048 #if HAVE_FCNTL_H
00049 #include <fcntl.h>
00050 #else
00051 #error "Need fcntl.h"
00052 #endif
00053
00054 #if HAVE_SIGNAL_H
00055 #include <signal.h>
00056 #else
00057 #error "Need signal.h"
00058 #endif
00059
00060 #if HAVE_SYS_STAT_H
00061 #include <sys/stat.h>
00062 #else
00063 #error "Need sys/stat.h"
00064 #endif
00065
00066
00067 #include <iostream>
00068 #include <sstream>
00069 #include <fstream>
00070 #include <cstdio>
00071
00072 #include "SignalDispatcher.h"
00073 #include "XmlRpcDaemonShutdownSignalHandler.h"
00074 #include "XmlRpcDaemon.h"
00075
00076
00077 using namespace LiveSupport::Scheduler;
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 const std::string XmlRpcDaemon::configElementNameStr =
00088 "xmlRpcDaemon";
00089
00093 static const std::string confXmlRpcHostAttr = "xmlRpcHost";
00094
00098 static const std::string confXmlRpcPortAttr = "xmlRpcPort";
00099
00103 static const std::string confPidFileNameAttr = "pidFileName";
00104
00108 static const mode_t uMask = 022;
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 void
00120 XmlRpcDaemon :: configureXmlRpcDaemon(
00121 const xmlpp::Element & element)
00122 throw (std::invalid_argument,
00123 std::logic_error)
00124 {
00125 if (configured) {
00126 throw std::logic_error("already configured");
00127 }
00128
00129 const xmlpp::Attribute * attribute = 0;
00130 std::stringstream strStr;
00131
00132 if (element.get_name() != configElementNameStr) {
00133 std::string eMsg = "Bad configuration element ";
00134 eMsg += element.get_name();
00135 throw std::invalid_argument(eMsg);
00136 }
00137
00138 if (!(attribute = element.get_attribute(confXmlRpcHostAttr))) {
00139 std::string eMsg = "Missing attribute ";
00140 eMsg += confXmlRpcHostAttr;
00141 throw std::invalid_argument(eMsg);
00142 }
00143 xmlRpcHost = attribute->get_value();
00144
00145 if (!(attribute = element.get_attribute(confXmlRpcPortAttr))) {
00146 std::string eMsg = "Missing attribute ";
00147 eMsg += confXmlRpcPortAttr;
00148 throw std::invalid_argument(eMsg);
00149 }
00150 strStr.str(attribute->get_value());
00151 strStr >> xmlRpcPort;
00152
00153 if (!(attribute = element.get_attribute(confPidFileNameAttr))) {
00154 std::string eMsg = "Missing attribute ";
00155 eMsg += confPidFileNameAttr;
00156 throw std::invalid_argument(eMsg);
00157 }
00158 pidFileName = attribute->get_value();
00159
00160 configured = true;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170 bool
00171 XmlRpcDaemon :: daemonize(void) throw (std::runtime_error)
00172 {
00173 int i;
00174
00175 if (getppid() == 1) {
00176
00177 return true;
00178 }
00179
00180 i = fork();
00181 if (i < 0) {
00182 throw std::runtime_error("fork error");
00183 } else if (i > 0) {
00184
00185 return false;
00186 }
00187
00188 i = fork();
00189 if (i < 0) {
00190 throw std::runtime_error("fork error");
00191 } else if (i > 0) {
00192
00193 return false;
00194 }
00195
00196
00197
00198
00199 setsid();
00200
00201
00202 umask(uMask);
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 savePid();
00216
00217
00218 signal(SIGCHLD,SIG_IGN);
00219 signal(SIGTSTP,SIG_IGN);
00220 signal(SIGTTOU,SIG_IGN);
00221 signal(SIGTTIN,SIG_IGN);
00222
00223
00224 SignalDispatcher * signalDispatcher = SignalDispatcher::getInstance();
00225 XmlRpcDaemonShutdownSignalHandler * handler =
00226 new XmlRpcDaemonShutdownSignalHandler(this);
00227 signalDispatcher->registerHandler(SIGHUP, handler);
00228 signalDispatcher->registerHandler(SIGTERM, handler);
00229
00230
00231
00232 return true;
00233 }
00234
00235
00236
00237
00238
00239 void
00240 XmlRpcDaemon :: savePid(void) throw ()
00241 {
00242 std::ofstream pidFile(pidFileName.c_str());
00243 pidFile << getpid();
00244 pidFile.flush();
00245 pidFile.close();
00246 }
00247
00248
00249
00250
00251
00252 pid_t
00253 XmlRpcDaemon :: loadPid(void) throw ()
00254 {
00255 pid_t pid;
00256
00257 std::ifstream pidFile(pidFileName.c_str());
00258 if (pidFile.fail()) {
00259
00260 return 0;
00261 }
00262
00263 pidFile >> pid;
00264 pidFile.close();
00265
00266 return pid;
00267 }
00268
00269
00270
00271
00272
00273 void
00274 XmlRpcDaemon :: start (void) throw (std::logic_error)
00275 {
00276 checkForConfiguration();
00277
00278 if (isRunning()) {
00279 std::cout << "Campcaster Scheduler is already running.n";
00280 return;
00281 }
00282
00283 if (background) {
00284 if (!daemonize()) {
00285
00286 return;
00287 }
00288 }
00289
00290 startup();
00291 }
00292
00293
00294
00295
00296
00297 void
00298 XmlRpcDaemon :: startup (void) throw (std::logic_error)
00299 {
00300
00301 registerXmlRpcFunctions(xmlRpcServer);
00302
00303
00304 xmlRpcServer->enableIntrospection(true);
00305 xmlRpcServer->bindAndListen(xmlRpcPort);
00306 xmlRpcServer->work(-1.0);
00307 }
00308
00309
00310
00311
00312
00313 bool
00314 XmlRpcDaemon :: isRunning (void) throw (std::logic_error)
00315 {
00316 checkForConfiguration();
00317
00318 pid_t pid = loadPid();
00319
00320 if (pid && kill(pid, 0)) {
00321 if (errno == ESRCH) {
00322
00323 remove(pidFileName.c_str());
00324 pid = 0;
00325 }
00326 }
00327
00328 return pid;
00329 }
00330
00331
00332
00333
00334
00335 void
00336 XmlRpcDaemon :: stop (void) throw (std::logic_error)
00337 {
00338 checkForConfiguration();
00339
00340 pid_t pid = loadPid();
00341 if (pid) {
00342 kill(pid, SIGTERM);
00343 }
00344 }
00345
00346
00347
00348
00349
00350 void
00351 XmlRpcDaemon :: shutdown (void) throw (std::logic_error)
00352 {
00353 checkForConfiguration();
00354
00355 xmlRpcServer->shutdown();
00356 remove(pidFileName.c_str());
00357 }
00358
00359