OmniEvents
|
00001 // Package : omniEvents 00002 // main.cc Created : 2004/08/01 00003 // Author : Alex Tingle. 00004 // 00005 // Copyright (C) 1998 Paul Nader, 2004-2005 Alex Tingle. 00006 // 00007 // This file is part of the omniEvents application. 00008 // 00009 // omniEvents is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Lesser General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2.1 of the License, or (at your option) any later version. 00013 // 00014 // omniEvents is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Lesser General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Lesser General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 // 00023 // Description: 00024 // Event Services Channel Factory implementation. The factory registers 00025 // itself with the naming service. Clients wishing to create event 00026 // channels can either use the factory by resolving its name with the 00027 // naming service or create in-process channels. 00028 // 00029 00030 #ifdef HAVE_CONFIG_H 00031 # include "config.h" 00032 #endif 00033 00034 #ifdef HAVE_GETOPT 00035 # include <unistd.h> 00036 extern char* optarg; 00037 extern int optind; 00038 #else 00039 # include "getopt.h" 00040 #endif 00041 00042 #include "main.h" 00043 #include "omniEvents.h" 00044 #include "naming.h" 00045 #include "omniEventsLog.h" 00046 #include "EventChannelFactory.h" 00047 #include "Orb.h" 00048 #include "daemon.h" 00049 #include "version.h" 00050 00051 #if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGSET) 00052 # include <signal.h> 00053 # define SIGSET(sig,func) ::sigset(sig,func) 00054 #elif defined(HAVE_SIGNAL_H) 00055 # include <signal.h> 00056 # define SIGSET(sig,func) ::signal(sig,func) 00057 #endif 00058 00059 #ifdef HAVE_OMNIORB4 00060 # include <omniORB4/internal/orbOptions.h> 00061 #endif 00062 00063 #include <cstdlib> 00064 #include <stdio.h> // for sprintf 00065 00066 int main(int argc, char** argv) 00067 { 00068 OmniEvents::Daemon daemon(argc,argv); 00069 00070 #ifdef HAVE_OMNIORB4 00071 try 00072 { 00073 // Duplicate argv & argc. 00074 int originalArgc =argc; 00075 char** originalArgv =new char*[originalArgc]; 00076 for(int i=0; i<originalArgc; ++i) 00077 originalArgv[i]=strdup(argv[i]); 00078 00079 // Remove ORB arguments from argc & argv. 00080 try { 00081 omni::orbOptions::singleton().extractInitOptions(argc,argv); 00082 } 00083 catch(...) { 00084 argc=originalArgc; 00085 argv=originalArgv; 00086 } 00087 #endif 00088 00089 using namespace OmniEvents; 00090 00091 // 00092 // Process Options 00093 const char* endPointNoListen =NULL; 00094 int port =0; 00095 const char* logDir =NULL; 00096 const char* factoryName ="EventChannelFactory"; 00097 bool verbose =false; 00098 00099 int c; 00100 while ((c = getopt(argc,argv,"O:a:p:l:P:N:dft:vVh")) != EOF) 00101 { 00102 switch (c) 00103 { 00104 case 'O': break; // Helps protect us from -ORB arguments. 00105 00106 // Initialisation options (only useful on first run) 00107 case 'a': endPointNoListen=optarg; 00108 break; 00109 00110 case 'p': port=atoi(optarg); 00111 if (port <= 0) 00112 { 00113 cerr<<"\nError: port must be a positive integer"<<endl; 00114 usage(argc,argv); 00115 } 00116 break; 00117 00118 // Other options 00119 case 'l': logDir=optarg; 00120 break; 00121 00122 case 'P': daemon.pidfile(optarg); 00123 break; 00124 00125 case 'N': factoryName=optarg; 00126 break; 00127 00128 case 'd': cerr<<"Option '-d' is deprecated. Use '-f' instead."<<endl; 00129 daemon.foreground(true); 00130 break; 00131 00132 case 'f': daemon.foreground(true); 00133 break; 00134 00135 // Informational options 00136 case 't': daemon.tracefile(optarg); 00137 break; 00138 00139 case 'v': verbose=true; 00140 break; 00141 00142 case 'V': cout<<OmniEvents::version()<<endl; 00143 ::exit(0); 00144 00145 case 'h': 00146 default : usage(argc,argv); 00147 break; 00148 } 00149 } 00150 00151 // 00152 // Create database instance. 00153 omniEventsLog logfile(logDir); 00154 PersistNode* initialState =NULL; 00155 if(logfile.fileExists(logfile.activeFilename())) 00156 { 00157 // Read library file. 00158 initialState=logfile.parse(); 00159 // Check for incompatibilities between options and the file. 00160 if(port && port!=initialState->child("ecf")->attrLong("port")) 00161 { 00162 cerr<< 00163 "Error: Option '-p "<<port<<"' conflicts with value '"<< 00164 initialState->child("ecf")->attrLong("port")<<"'\n stored in" 00165 " database file '"<<logfile.activeFilename()<<"'.\n" 00166 " Either delete the file to clear the database, or do not use the" 00167 " '-p' option."<<endl; 00168 exit(1); 00169 } 00170 if(endPointNoListen && string(endPointNoListen)!= 00171 initialState->child("ecf")->attrString("endPointNoListen")) 00172 { 00173 cerr<< 00174 "Error: Option '-a "<<endPointNoListen<<"' conflicts with value '"<< 00175 initialState->child("ecf")->attrString("endPointNoListen")<<"'\n" 00176 " stored in database file '"<<logfile.activeFilename()<<"'.\n" 00177 " Either delete the file to clear the database, or do not use the" 00178 " '-a' option."<<endl; 00179 exit(1); 00180 } 00181 } 00182 else if(logfile.fileExists(logfile.backupFilename())) 00183 { 00184 // Quit with an error. 00185 cerr << 00186 "Error: backup file '" << logfile.backupFilename() << "' exists.\n" 00187 " Rename it to '" << logfile.activeFilename() << "'\n" 00188 " to recover the server's state, or delete it to create a new\n" 00189 " database file." << endl; 00190 exit(1); 00191 } 00192 else 00193 { 00194 // Create initial state without a library file. 00195 initialState=logfile.bootstrap(port?port:11169,endPointNoListen); 00196 } 00197 port=initialState->child("ecf")->attrLong("port",port); 00198 string endPoint2=initialState->child("ecf")->attrString("endPointNoListen"); 00199 00200 // 00201 // Daemonise 00202 daemon.daemonize(); 00203 00204 // 00205 // Initialise orb & POAs. 00206 #ifdef HAVE_OMNIORB4 00207 char endPoint[64]; 00208 sprintf(endPoint,"giop:::%d",port); 00209 if(endPoint2.empty()) 00210 { 00211 const char* opts[][2] ={ {"endPoint",endPoint}, {0,0} }; 00212 Orb::inst()._orb=CORBA::ORB_init(originalArgc,originalArgv,"omniORB4",opts); 00213 } 00214 else 00215 { 00216 const char* opts[][2] ={ 00217 {"endPoint",endPoint}, 00218 {"endPointNoListen",endPoint2.c_str()}, 00219 {0,0} }; 00220 Orb::inst()._orb=CORBA::ORB_init(originalArgc,originalArgv,"omniORB4",opts); 00221 } 00222 #else 00223 insertArgs(argc, argv, 1, 2); 00224 argv[1] = strdup("-ORBpoa_iiop_port"); 00225 argv[2] = new char[32 + 1]; 00226 sprintf(argv[2], "%d", port); 00227 Orb::inst()._orb=CORBA::ORB_init(argc,argv); 00228 #endif 00229 Orb::inst().resolveInitialReferences(); 00230 { 00231 PortableServer::POAManager_var pman; 00232 pman=Orb::inst()._RootPOA->the_POAManager(); 00233 pman->activate(); 00234 pman=Orb::inst()._omniINSPOA->the_POAManager(); 00235 pman->activate(); 00236 } 00237 00238 // 00239 // If omniEvents is restarting then the omniEventsLog object 00240 // will take care of creating the factory and any subordinate 00241 // event channels, proxies, etc under it. 00242 logfile.incarnateFactory(initialState); 00243 delete initialState; // Tidy up. 00244 initialState=NULL; 00245 00246 { 00247 // 00248 // Register factory with the Naming Service. 00249 omniEvents::EventChannelFactory_var factory( logfile.factory()->_this() ); 00250 bindName2Object( 00251 Orb::inst()._NameService.in(), 00252 str2name(factoryName), 00253 factory.in() 00254 ); 00255 00256 // 00257 // Print the factory IOR. 00258 if(verbose) 00259 { 00260 DB(1,"Starting omniEvents on port "<<port) 00261 if(!endPoint2.empty()) 00262 DB(1,"Alternate endPoint "<<endPoint2.c_str()) 00263 CORBA::String_var iorstr = 00264 Orb::inst()._orb->object_to_string(factory.in()); 00265 DB(1,iorstr.in()) 00266 } 00267 } // factory reference is released. 00268 00269 #ifdef HAVE_SIGNAL_H 00270 SIGSET(SIGINT , ::OmniEvents_Orb_shutdown); 00271 SIGSET(SIGTERM, ::OmniEvents_Orb_shutdown); 00272 # ifdef SIGUSR1 00273 SIGSET(SIGUSR1, ::OmniEvents_Orb_bumpTraceLevel); 00274 # endif 00275 # ifdef SIGPIPE 00276 SIGSET(SIGPIPE, SIG_IGN); // Ignore broken pipes 00277 # endif 00278 #endif 00279 00280 daemon.runningOk(); 00281 00282 // 00283 // Start the background tasks. 00284 logfile.runWorker(); // Logfile's worker thread. 00285 Orb::inst().run(); // Use the main thread to collect orphaned responses. 00286 00287 DB(1,"Shutdown requested.") 00288 Orb::inst()._orb->shutdown(1); // Synchronous shutdown 00289 Orb::inst()._orb->destroy(); // clean up 00290 00291 return 0; // Delete any pidfile & exit. 00292 00293 #ifdef HAVE_OMNIORB4 00294 } 00295 catch (CORBA::SystemException& ex) { 00296 DB(0,"System exception: "<<ex._name()<<" ("<<NP_MINORSTRING(ex)<<")") 00297 } 00298 catch (CORBA::Exception& ex) { 00299 DB(0,"CORBA exception: "<<ex._name()) 00300 } 00301 return 1; 00302 #endif 00303 } // end main() 00304 00305 00306 // 00307 // Signal handlers. 00308 // 00309 00310 extern "C" 00311 { 00312 void OmniEvents_Orb_shutdown(int signum) 00313 { 00314 OmniEvents::Orb::inst().shutdown(signum); 00315 } 00316 00317 void OmniEvents_Orb_bumpTraceLevel(int signum) 00318 { 00319 omniORB::traceLevel=(omniORB::traceLevel+5)%45; 00320 DB(0,"TRACE LEVEL BUMPED TO "<<omniORB::traceLevel<<" BY SIGNAL "<<signum) 00321 } 00322 }