OmniEvents
main.cc
Go to the documentation of this file.
1// Package : omniEvents
2// main.cc Created : 2004/08/01
3// Author : Alex Tingle.
4//
5// Copyright (C) 1998 Paul Nader, 2004-2005 Alex Tingle.
6//
7// This file is part of the omniEvents application.
8//
9// omniEvents is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// omniEvents is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22//
23// Description:
24// Event Services Channel Factory implementation. The factory registers
25// itself with the naming service. Clients wishing to create event
26// channels can either use the factory by resolving its name with the
27// naming service or create in-process channels.
28//
29
30#ifdef HAVE_CONFIG_H
31# include "config.h"
32#endif
33
34#ifdef HAVE_GETOPT
35# include <unistd.h>
36extern char* optarg;
37extern int optind;
38#else
39# include "getopt.h"
40#endif
41
42#include "main.h"
43#include "omniEvents.h"
44#include "naming.h"
45#include "omniEventsLog.h"
46#include "EventChannelFactory.h"
47#include "Orb.h"
48#include "daemon.h"
49#include "version.h"
50
51#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGSET)
52# include <signal.h>
53# define SIGSET(sig,func) ::sigset(sig,func)
54#elif defined(HAVE_SIGNAL_H)
55# include <signal.h>
56# define SIGSET(sig,func) ::signal(sig,func)
57#endif
58
59#ifdef HAVE_OMNIORB4
60# include <omniORB4/internal/orbOptions.h>
61#endif
62
63#include <cstdlib>
64#include <stdio.h> // for sprintf
65
66int main(int argc, char** argv)
67{
68 OmniEvents::Daemon daemon(argc,argv);
69
70#ifdef HAVE_OMNIORB4
71 try
72 {
73 // Duplicate argv & argc.
74 int originalArgc =argc;
75 char** originalArgv =new char*[originalArgc];
76 for(int i=0; i<originalArgc; ++i)
77 originalArgv[i]=strdup(argv[i]);
79 // Remove ORB arguments from argc & argv.
80 try {
81 omni::orbOptions::singleton().extractInitOptions(argc,argv);
82 }
83 catch(...) {
84 argc=originalArgc;
85 argv=originalArgv;
86 }
87#endif
88
89 using namespace OmniEvents;
90
91 //
92 // Process Options
93 const char* endPointNoListen =NULL;
94 int port =0;
95 const char* logDir =NULL;
96 const char* factoryName ="EventChannelFactory";
97 bool verbose =false;
98
99 int c;
100 while ((c = getopt(argc,argv,"O:a:p:l:P:N:dft:vVh")) != EOF)
101 {
102 switch (c)
103 {
104 case 'O': break; // Helps protect us from -ORB arguments.
105
106 // Initialisation options (only useful on first run)
107 case 'a': endPointNoListen=optarg;
108 break;
109
110 case 'p': port=atoi(optarg);
111 if (port <= 0)
112 {
113 cerr<<"\nError: port must be a positive integer"<<endl;
114 usage(argc,argv);
115 }
116 break;
117
118 // Other options
119 case 'l': logDir=optarg;
120 break;
121
122 case 'P': daemon.pidfile(optarg);
123 break;
124
125 case 'N': factoryName=optarg;
126 break;
127
128 case 'd': cerr<<"Option '-d' is deprecated. Use '-f' instead."<<endl;
129 daemon.foreground(true);
130 break;
131
132 case 'f': daemon.foreground(true);
133 break;
134
135 // Informational options
136 case 't': daemon.tracefile(optarg);
137 break;
138
139 case 'v': verbose=true;
140 break;
141
142 case 'V': cout<<OmniEvents::version()<<endl;
143 ::exit(0);
144
145 case 'h':
146 default : usage(argc,argv);
147 break;
148 }
149 }
150
151 //
152 // Create database instance.
153 omniEventsLog logfile(logDir);
154 PersistNode* initialState =NULL;
155 if(logfile.fileExists(logfile.activeFilename()))
156 {
157 // Read library file.
158 initialState=logfile.parse();
159 // Check for incompatibilities between options and the file.
160 if(port && port!=initialState->child("ecf")->attrLong("port"))
161 {
162 cerr<<
163 "Error: Option '-p "<<port<<"' conflicts with value '"<<
164 initialState->child("ecf")->attrLong("port")<<"'\n stored in"
165 " database file '"<<logfile.activeFilename()<<"'.\n"
166 " Either delete the file to clear the database, or do not use the"
167 " '-p' option."<<endl;
168 exit(1);
169 }
170 if(endPointNoListen && string(endPointNoListen)!=
171 initialState->child("ecf")->attrString("endPointNoListen"))
172 {
173 cerr<<
174 "Error: Option '-a "<<endPointNoListen<<"' conflicts with value '"<<
175 initialState->child("ecf")->attrString("endPointNoListen")<<"'\n"
176 " stored in database file '"<<logfile.activeFilename()<<"'.\n"
177 " Either delete the file to clear the database, or do not use the"
178 " '-a' option."<<endl;
179 exit(1);
180 }
181 }
182 else if(logfile.fileExists(logfile.backupFilename()))
183 {
184 // Quit with an error.
185 cerr <<
186 "Error: backup file '" << logfile.backupFilename() << "' exists.\n"
187 " Rename it to '" << logfile.activeFilename() << "'\n"
188 " to recover the server's state, or delete it to create a new\n"
189 " database file." << endl;
190 exit(1);
191 }
192 else
193 {
194 // Create initial state without a library file.
195 initialState=logfile.bootstrap(port?port:11169,endPointNoListen);
196 }
197 port=initialState->child("ecf")->attrLong("port",port);
198 string endPoint2=initialState->child("ecf")->attrString("endPointNoListen");
199
200 //
201 // Daemonise
203
204 //
205 // Initialise orb & POAs.
206#ifdef HAVE_OMNIORB4
207 char endPoint[64];
208 sprintf(endPoint,"giop:::%d",port);
209 if(endPoint2.empty())
210 {
211 const char* opts[][2] ={ {"endPoint",endPoint}, {0,0} };
212 Orb::inst()._orb=CORBA::ORB_init(originalArgc,originalArgv,"omniORB4",opts);
213 }
214 else
215 {
216 const char* opts[][2] ={
217 {"endPoint",endPoint},
218 {"endPointNoListen",endPoint2.c_str()},
219 {0,0} };
220 Orb::inst()._orb=CORBA::ORB_init(originalArgc,originalArgv,"omniORB4",opts);
221 }
222#else
223 insertArgs(argc, argv, 1, 2);
224 argv[1] = strdup("-ORBpoa_iiop_port");
225 argv[2] = new char[32 + 1];
226 sprintf(argv[2], "%d", port);
227 Orb::inst()._orb=CORBA::ORB_init(argc,argv);
228#endif
229 Orb::inst().resolveInitialReferences();
230 {
231 PortableServer::POAManager_var pman;
232 pman=Orb::inst()._RootPOA->the_POAManager();
233 pman->activate();
234 pman=Orb::inst()._omniINSPOA->the_POAManager();
235 pman->activate();
236 }
237
238 //
239 // If omniEvents is restarting then the omniEventsLog object
240 // will take care of creating the factory and any subordinate
241 // event channels, proxies, etc under it.
242 logfile.incarnateFactory(initialState);
243 delete initialState; // Tidy up.
244 initialState=NULL;
245
246 {
247 //
248 // Register factory with the Naming Service.
249 omniEvents::EventChannelFactory_var factory( logfile.factory()->_this() );
251 Orb::inst()._NameService.in(),
252 str2name(factoryName),
253 factory.in()
254 );
255
256 //
257 // Print the factory IOR.
258 if(verbose)
259 {
260 DB(1,"Starting omniEvents on port "<<port)
261 if(!endPoint2.empty())
262 DB(1,"Alternate endPoint "<<endPoint2.c_str())
263 CORBA::String_var iorstr =
264 Orb::inst()._orb->object_to_string(factory.in());
265 DB(1,iorstr.in())
266 }
267 } // factory reference is released.
268
269#ifdef HAVE_SIGNAL_H
270 SIGSET(SIGINT , ::OmniEvents_Orb_shutdown);
271 SIGSET(SIGTERM, ::OmniEvents_Orb_shutdown);
272# ifdef SIGUSR1
273 SIGSET(SIGUSR1, ::OmniEvents_Orb_bumpTraceLevel);
274# endif
275# ifdef SIGPIPE
276 SIGSET(SIGPIPE, SIG_IGN); // Ignore broken pipes
277# endif
278#endif
279
281
282 //
283 // Start the background tasks.
284 logfile.runWorker(); // Logfile's worker thread.
285 Orb::inst().run(); // Use the main thread to collect orphaned responses.
286
287 DB(1,"Shutdown requested.")
288 Orb::inst()._orb->shutdown(1); // Synchronous shutdown
289 Orb::inst()._orb->destroy(); // clean up
290
291 return 0; // Delete any pidfile & exit.
292
293#ifdef HAVE_OMNIORB4
294 }
295 catch (CORBA::SystemException& ex) {
296 DB(0,"System exception: "<<ex._name()<<" ("<<NP_MINORSTRING(ex)<<")")
297 }
298 catch (CORBA::Exception& ex) {
299 DB(0,"CORBA exception: "<<ex._name())
300 }
301 return 1;
302#endif
303} // end main()
304
305
306//
307// Signal handlers.
308//
309
310extern "C"
311{
312 void OmniEvents_Orb_shutdown(int signum)
313 {
315 }
316
318 {
319 omniORB::traceLevel=(omniORB::traceLevel+5)%45;
320 DB(0,"TRACE LEVEL BUMPED TO "<<omniORB::traceLevel<<" BY SIGNAL "<<signum)
321 }
322}
int bindName2Object(CosNaming::NamingContext_ptr namingContext, const CosNaming::Name &name, CORBA::Object_ptr obj)
Binds CosNaming::Name to object in the naming service.
Definition naming.cc:149
CosNaming::Name str2name(const char *namestr)
Converts stringified name to naming service name.
Definition naming.cc:117
int main(int argc, char **argv)
The main process entry point.
Definition main.cc:66
void OmniEvents_Orb_shutdown(int signum)
Signal handler, sets Orb::_shutdownRequested.
Definition main.cc:312
void OmniEvents_Orb_bumpTraceLevel(int signum)
Signal handler, each call to this method 'bumps' up the trace level by 5, modulo 45.
Definition main.cc:317
int optind
Definition getopt.cc:82
char * optarg
Definition getopt.cc:83
int getopt(int argc, char *argv[], const char *optionS)
Definition getopt.cc:88
#define DB(l, x)
Definition Orb.h:49
#define NP_MINORSTRING(systemException)
Definition Orb.h:52
static void usage(int argc, char **argv)
Definition eventc.cc:426
void insertArgs(int &argc, char **&argv, int idx, int nargs)
Utility function, used to manipulate argv when using omniORB3.
Definition omniEvents.cc:97
DaemonImpl daemon
Singleton - only at file scope.
const char * version()
Returns the constant version ID and copyright string.
Definition version.cc:32
Interface class that contains various methods for running omniEvents as a background task.
Definition daemon.h:33
void runningOk()
Called to signal that all startup operations have completed OK.
void foreground(bool val)
Set _foreground.
void tracefile(const char *val)
Set _tracefile.
void pidfile(const char *val)
Set _pidfile.
void daemonize()
Puts the current process into the background.
Singleton class that owns the ORB and various initial references.
Definition Orb.h:70
void shutdown(int)
Sets _shutdownRequested.
Definition Orb.h:126
static Orb & inst()
Definition Orb.h:81
string attrString(const string &key, const string &fallback="") const
long attrLong(const string &key, long fallback=0) const
PersistNode * child(const string &key) const