00001 #define MD_MAIN
00002 #include "auc-md.h"
00003
00004 #include <stdio.h>
00005 #include <fcntl.h>
00006 #include <signal.h>
00007 #include <unistd.h>
00008
00009 using namespace std;
00010
00011 const char *mdOrKb;
00012
00013 void setSignals();
00014 void signal_handler(int);
00015 void usage();
00016 void md() {
00017
00018 bool daemonized=false;
00019 int i,lfp,rc;
00020 char str[32];
00021
00022 if (thisConfig->daemonized) {
00023
00024 rc = fork();
00025 if (rc < 0) {
00026 puts("Can't initialize process!");
00027 exit(1);
00028 }
00029
00030 if (getpid() == thisConfig->shellProcess)
00031 exit(0);
00032
00033 setsid();
00034 for (i=getdtablesize();i>=0;--i) close(i);
00035 i=open("/dev/null",O_RDWR); dup(i); dup(i);
00036 umask(027);
00037 chdir(RUNNING_DIR);
00038 lfp=open(MD_LOCK_FILE,O_RDWR|O_CREAT,0640);
00039 if (lfp<0) {printf("Can't open lockfile(%d)! Ctl-C me."); exit(1);}
00040 if ((rc=lockf(lfp,F_TLOCK,0))<0)
00041 {printf("Can't lock lockfile (%d)! Ctl-C me.",rc); exit(0);}
00042
00043 thisConfig->daemonProcess = getpid();
00044
00045 sprintf(str,"%d\n",getpid());
00046 write(lfp,str,strlen(str));
00047 daemonized = true;
00048
00049 }
00050
00051 setSignals();
00052
00053 try {
00054
00055 theseLogs = new mdLogger();
00056 theseLogs->init();
00057
00058 theseLogs->logN(1,MD_NAME " " MD_VERSION " compiled on " __DATE__ " @ " __TIME__ "(%d)",thisConfig->daemonProcess);
00059 if (daemonized) theseLogs->logN(1,"(detached from %d)",thisConfig->shellProcess);
00060
00061 boost::thread foreground(runMasterDaemon);
00062 boost::thread background(runDataLayer);
00063
00064 xmlrpc_c::serverAbyss myAbyssServer(
00065 thisConfig->api_registry,
00066 thisConfig->xmlrpcPort,
00067 thisConfig->xmlrpcLogpath
00068 );
00069
00070 if (!foreground.joinable()) {
00071 theseLogs->logN(0,"Fatal Error: couldn't start server core!");
00072 exit(1);
00073 }
00074
00075 if (background.joinable()) {
00076 theseLogs->logN(2,"%s %d","Accepting API Requests on Port",thisConfig->xmlrpcPort);
00077 myAbyssServer.run();
00078 background.join();
00079 } else
00080 theseLogs->logN(0,"Fatal Error: couldn't start background data layer!");
00081 }
00082 catch (XmlRpcFault::XmlRpcFault& e)
00083 {
00084 theseLogs->logN(1,"xmlrpc_c fault: %s",e.getFaultString().c_str());
00085 exit(1);
00086 }
00087 catch (std::exception& e)
00088 {
00089 theseLogs->logN(1,"Exception: %s",e.what());
00090 exit(1);
00091 }
00092 catch (...) {
00093 theseLogs->logN(1,"General Fault!");
00094 exit(1);
00095 }
00096
00097 }
00098 int
00099 main(int const argc,
00100 const char ** const argv) {
00101
00102 char msg[512];
00103 const char *exeName,*banner = MD_NAME " " MD_VERSION " compiled on " __DATE__ " @ " __TIME__ "(%d)\n";
00104 int mthParm, rc = 0;
00105
00106 thisConfig = new masterDaemonConfig();
00107 thisConfig->shellProcess = getpid();
00108
00109 exeName = (strcspn(argv[0],"./") == strlen(argv[0])) ? argv[0] : strrchr(argv[0],'/') + 1;
00110 mdOrKb = exeName;
00111
00112 if (argc < 3 || argc > 6) usage();
00113
00114 thisConfig->telemetryPort = atoi(argv[1]);
00115 thisConfig->xmlrpcPort = atoi(argv[2]);
00116
00117 if (thisConfig->telemetryPort < 1000 || thisConfig->telemetryPort > 65535)
00118 {
00119 std::cerr << "The <telemetry-udp-port> value is invalid.\n";
00120 return 1;
00121 }
00122
00123 if (thisConfig->xmlrpcPort < 1000 || thisConfig->xmlrpcPort > 65535)
00124 {
00125 std::cerr << "The <xmlrpc-socket-port> value is invalid.\n";
00126 return 1;
00127 }
00128
00129 if (thisConfig->xmlrpcPort == thisConfig->telemetryPort)
00130 {
00131 std::cerr << "The <xmlrpc-socket-port> and <telemetry-udp-port> cannot be the same.\n";
00132 return 1;
00133 }
00134
00135 for (mthParm=3;mthParm < argc;mthParm++) {
00136 if (*argv[mthParm] == '!') {
00137 thisConfig->daemonized = false;
00138 }
00139 else
00140 if (!strncmp(argv[mthParm],"logs=",4)) {
00141 thisConfig->log_path = std::string(argv[mthParm]+4);
00142 thisConfig->logPath = thisConfig->log_path.c_str();
00143 }
00144 else
00145 if (!strncmp(argv[mthParm],"cfg=",3)) {
00146 thisConfig->cfg_path = std::string(argv[mthParm]+3);
00147 thisConfig->configPath = thisConfig->cfg_path.c_str();
00148 }
00149 else usage();
00150 }
00151
00152 if (!thisConfig->daemonized) printf(banner,thisConfig->shellProcess);
00153 md();
00154 while(!thisConfig->halt) sleep(5);
00155
00156 }
00157 void setSignals() {
00158
00159 signal(SIGCHLD,SIG_IGN);
00160 signal(SIGTSTP,SIG_IGN);
00161 signal(SIGTTOU,SIG_IGN);
00162 signal(SIGTTIN,SIG_IGN);
00163 signal(SIGSEGV,signal_handler);
00164 signal(SIGUSR1,signal_handler);
00165 signal(SIGUSR2,signal_handler);
00166 signal(SIGHUP,signal_handler);
00167 signal(SIGTERM,signal_handler);
00168
00169 }
00170 void signal_handler(int sig)
00171 {
00172 switch(sig) {
00173 case SIGSEGV:
00174 theseLogs->logN(0,"SEGV ABEND.");
00175 exit(NOT_OK);
00176 break;
00177 case SIGUSR1:
00178 break;
00179 case SIGUSR2:
00180 break;
00181 case SIGHUP:
00182 theseLogs->logN(0,"hangup signal caught, currently md ignores this.");
00183 break;
00184 case SIGTERM:
00185 theseLogs->logN(0,"terminate signal caught, auc-md will shutdown.");
00186 exit(0);
00187 break;
00188 }
00189 }
00190 void usage() {
00191
00192 std::cerr << "Usage: " << mdOrKb << " <telemetry-udp-port> <xmlrpc-socket-port> [cfg=<path>] [log=<path>] [!] \n\n"
00193 " where \n\nconfig directory defaults to the current directory \n"
00194 "log directory to /tmp \nand ! indicates do not daemonize (for diagnostic purposes)\n\n";
00195 exit(1);
00196
00197 }