(file) Return to CIMListener.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Listener

  1 karl  1.12 //%2003////////////////////////////////////////////////////////////////////////
  2 kumpf 1.1  //
  3 karl  1.12 // Copyright (c) 2000, 2001, 2002  BMC Software, Hewlett-Packard Development
  4            // Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
  6            // IBM Corp.; EMC Corporation, The Open Group.
  7 kumpf 1.1  //
  8            // Permission is hereby granted, free of charge, to any person obtaining a copy
  9            // of this software and associated documentation files (the "Software"), to
 10            // deal in the Software without restriction, including without limitation the
 11            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 12            // sell copies of the Software, and to permit persons to whom the Software is
 13            // furnished to do so, subject to the following conditions:
 14 kumpf 1.3  // 
 15 kumpf 1.1  // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 16            // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 17            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 18            // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 19            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 20            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 21            // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 22            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 23            //
 24            //==============================================================================
 25            //
 26 tony  1.8  // Author: Dong Xiang, EMC Corporation (xiang_dong@emc.com)
 27 kumpf 1.1  //
 28 dj.gorey 1.14 // Modified By:   Dan Gorey (djgorey@us.ibm.com)
 29 kumpf    1.1  //
 30               //%/////////////////////////////////////////////////////////////////////////////
 31               
 32 tony     1.8  #include "CIMListener.h"
 33 kumpf    1.1  
 34 tony     1.8  #include <Pegasus/Common/Exception.h>
 35               #include <Pegasus/Common/SSLContext.h>
 36               #include <Pegasus/Common/Monitor.h>
 37 kumpf    1.1  #include <Pegasus/Common/HTTPAcceptor.h>
 38 kumpf    1.11 #include <Pegasus/Common/PegasusVersion.h>
 39 kumpf    1.2  
 40 kumpf    1.1  #include <Pegasus/ExportServer/CIMExportResponseEncoder.h>
 41               #include <Pegasus/ExportServer/CIMExportRequestDecoder.h>
 42               
 43 tony     1.8  #include <Pegasus/Consumer/CIMIndicationConsumer.h>
 44               #include <Pegasus/Listener/CIMListenerIndicationDispatcher.h>
 45               
 46               PEGASUS_NAMESPACE_BEGIN
 47               /////////////////////////////////////////////////////////////////////////////
 48               // CIMListenerService
 49               /////////////////////////////////////////////////////////////////////////////
 50               class CIMListenerService
 51               {
 52               public:
 53               	CIMListenerService(Uint32 portNumber, SSLContext* sslContext=NULL);
 54               	CIMListenerService(CIMListenerService& svc);
 55                 ~CIMListenerService();
 56               
 57               	void				init();
 58               	/** bind to the port
 59               	*/
 60               	void				bind();
 61               	/** runForever Main runloop for the server.
 62               	*/
 63               	void runForever();
 64 tony     1.8  	
 65               	/** Call to gracefully shutdown the server.  The server connection socket
 66               	will be closed to disable new connections from clients.
 67               	*/
 68               	void stopClientConnection();
 69               	
 70               	/** Call to gracefully shutdown the server.  It is called when the server
 71               	has been stopped and is ready to be shutdown.  Next time runForever()
 72               	is called, the server shuts down.
 73               	*/
 74               	void shutdown();
 75               	
 76               	/** Return true if the server has shutdown, false otherwise.
 77               	*/
 78               	Boolean terminated() { return _dieNow; };
 79               	
 80               	/** Call to resume the sever.
 81               	*/
 82               	void resume();
 83               	
 84               	/** Call to set the CIMServer state.  Also inform the appropriate
 85 tony     1.8  	message queues about the current state of the CIMServer.
 86               	*/
 87               	void setState(Uint32 state);
 88               	
 89               	Uint32 getOutstandingRequestCount();
 90               
 91               	/** Returns the indication listener dispatcher
 92               	 */
 93               	CIMListenerIndicationDispatcher* getIndicationDispatcher() const;
 94               
 95                 /** Returns the indication listener dispatcher
 96               	 */
 97               	void setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher);
 98               
 99               	static PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL _listener_routine(void *param);
100               
101               private:
102               	Uint32			_portNumber;
103               	SSLContext* _sslContext;
104 dj.gorey 1.15   #ifdef PEGASUS_USE_23HTTPMONITOR_CLIENT
105 tony     1.8  	Monitor*				_monitor;
106                 HTTPAcceptor*   _acceptor;
107 dj.gorey 1.14   #else
108                	monitor_2*				_monitor;
109                 pegasus_acceptor*   _acceptor;
110                 #endif 
111               
112                 Boolean					_dieNow;
113 tony     1.8  
114                 CIMListenerIndicationDispatcher* _dispatcher;
115               
116                 CIMExportResponseEncoder* _responseEncoder;
117                 CIMExportRequestDecoder*  _requestDecoder;
118               
119               };
120               
121               CIMListenerService::CIMListenerService(Uint32 portNumber, SSLContext* sslContext)
122               :_portNumber(portNumber)
123               ,_sslContext(sslContext)
124               ,_monitor(NULL)
125               ,_acceptor(NULL)
126               ,_dieNow(false)
127               ,_dispatcher(NULL)
128               ,_responseEncoder(NULL)
129               ,_requestDecoder(NULL)
130               {
131               }
132               
133               CIMListenerService::CIMListenerService(CIMListenerService& svc)
134 tony     1.8  :_portNumber(svc._portNumber)
135               ,_sslContext(svc._sslContext)
136               ,_monitor(NULL)
137               ,_acceptor(NULL)
138               ,_dieNow(svc._dieNow)
139               ,_dispatcher(NULL)
140               ,_responseEncoder(NULL)
141               ,_requestDecoder(NULL)
142               {
143               }
144               CIMListenerService::~CIMListenerService()
145               {
146               	// if port is alive, clean up the port
147               	//if(_sslContext!=NULL)
148               	//	delete _sslContext;
149               
150               	if(_responseEncoder!=NULL)
151               		delete _responseEncoder;
152               
153               	if(_requestDecoder!=NULL)
154               		delete _requestDecoder;
155 kumpf    1.1  
156 tony     1.8  	//if(_dispatcher!=NULL)
157               	//	delete _dispatcher;
158 kumpf    1.1  
159 tony     1.8  	if(_monitor!=NULL)
160               		delete _monitor;
161 kumpf    1.1  
162 tony     1.8  	if(_acceptor!=NULL)
163               		delete _acceptor;
164               }
165 kumpf    1.1  
166 tony     1.8  void CIMListenerService::init()
167 kumpf    1.1  {
168 tony     1.8  	PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::init");
169 kumpf    1.1  
170 dj.gorey 1.15   #ifdef PEGASUS_USE_23HTTPMONITOR_CLIENT
171 tony     1.8    _monitor = new Monitor(true);
172 dj.gorey 1.14   #else
173                 _monitor = new monitor_2();
174                 #endif
175                 
176 tony     1.8  	//_dispatcher = new CIMListenerIndicationDispatcher();
177 kumpf    1.1  
178 chuck    1.20   _responseEncoder = new CIMExportResponseEncoder();
179 tony     1.8    _requestDecoder = new CIMExportRequestDecoder(
180               		_dispatcher,
181               		_responseEncoder->getQueueId());
182               
183 dj.gorey 1.15   #ifdef PEGASUS_USE_23HTTPMONITOR_CLIENT
184 dj.gorey 1.14   _acceptor = new HTTPAcceptor(
185 tony     1.8  		 _monitor, 
186               		 _requestDecoder, 
187               		 false, 
188               		 _portNumber, 
189 kumpf    1.19 		 _sslContext,
190                                false);
191 dj.gorey 1.14   #else
192                 _acceptor = new pegasus_acceptor(_monitor,
193               		   _requestDecoder,
194               		   false,
195               		   _portNumber,
196               		   _sslContext);
197                 #endif
198 kumpf    1.1  
199 chuck    1.20   bind();
200 kumpf    1.1  
201 chuck    1.20   PEG_METHOD_EXIT();
202 tony     1.8  }
203               void CIMListenerService::bind()
204               {
205 chuck    1.20   if(_acceptor!=NULL)
206                   { // Bind to the port
207                     _acceptor->bind();
208 tony     1.8  
209 chuck    1.20       PEGASUS_STD(cout) << "Listening on HTTP port " << _portNumber << PEGASUS_STD(endl);
210 tony     1.8  		
211 chuck    1.20       //listener.addAcceptor(false, portNumberHttp, false);
212                     Logger::put(Logger::STANDARD_LOG, System::CIMLISTENER, Logger::INFORMATION,
213 tony     1.8                          "Listening on HTTP port $0.", _portNumber);
214 kumpf    1.1  
215 chuck    1.20     }
216 tony     1.8  }
217 chuck    1.20 
218 tony     1.8  void CIMListenerService::runForever()
219               {
220 chuck    1.20   static int modulator = 0;
221 kumpf    1.1  
222 chuck    1.20   if(!_dieNow)
223 dj.gorey 1.14     {
224 chuck    1.20 #ifdef PEGASUS_USE_23HTTPMONITOR_CLIENT
225                     if(false == _monitor->run(100)) 
226               	{	
227               	  modulator++;
228               	  if(!(modulator % 5000) )
229               	    {
230               	      try 
231               		{
232               		  //MessageQueueService::_check_idle_flag = 1;
233               		  //MessageQueueService::_polling_sem.signal();
234               		  MessageQueueService::get_thread_pool()->kill_idle_threads();
235 tony     1.8  		}
236 chuck    1.20 	      catch(...)
237 tony     1.8  		{
238               		}
239 chuck    1.20 	    }	
240               	}
241               /*
242                     if (handleShutdownSignal)
243                     {
244                       Tracer::trace(TRC_SERVER, Tracer::LEVEL3,
245               	"CIMServer::runForever - signal received.  Shutting down.");
246               
247               	ShutdownService::getInstance(this)->shutdown(true, 10, false);
248               	handleShutdownSignal = false;
249                     }
250 tony     1.8  */
251 chuck    1.20 #else
252                     _monitor->run();
253               #endif
254                   }
255 tony     1.8  }
256 kumpf    1.1  
257 tony     1.8  void CIMListenerService::shutdown()
258               {
259                   PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::shutdown()");
260 kumpf    1.1  
261 tony     1.8      _dieNow = true;
262 kumpf    1.1  
263 kumpf    1.4      PEG_METHOD_EXIT();
264 kumpf    1.1  }
265               
266 tony     1.8  void CIMListenerService::resume()
267 kumpf    1.1  {
268 tony     1.8      PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::resume()");
269 kumpf    1.1  
270 tony     1.8      if(_acceptor!=NULL)
271                       _acceptor->reopenConnectionSocket();
272 kumpf    1.1  
273 kumpf    1.4      PEG_METHOD_EXIT();
274 kumpf    1.1  }
275               
276 tony     1.8  void CIMListenerService::stopClientConnection()
277 kumpf    1.1  {
278 tony     1.8      PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::stopClientConnection()");
279 kumpf    1.1  
280 kumpf    1.10     // tell Monitor to stop listening for client connections
281 dj.gorey 1.15     #ifdef PEGASUS_USE_23HTTPMONITOR_CLIENT
282 kumpf    1.10     _monitor->stopListeningForConnections();
283 dj.gorey 1.14     #else
284                   _monitor->stop();
285                   #endif
286 kumpf    1.10 
287                   //
288                   // Wait 150 milliseconds to allow time for the Monitor to stop
289                   // listening for client connections.
290                   //
291                   // This wait time is the timeout value for the select() call
292                   // in the Monitor's run() method (currently set to 100
293                   // milliseconds) plus a delta of 50 milliseconds.  The reason
294                   // for the wait here is to make sure that the Monitor entries
295                   // are updated before closing the connection sockets.
296                   //
297                   pegasus_sleep(150);
298               
299 tony     1.8      if(_acceptor!=NULL)
300                   _acceptor->closeConnectionSocket();
301 kumpf    1.1  
302 kumpf    1.4      PEG_METHOD_EXIT();
303 kumpf    1.1  }
304               
305 tony     1.8  
306               CIMListenerIndicationDispatcher* CIMListenerService::getIndicationDispatcher() const
307 kumpf    1.1  {
308 tony     1.8  	return _dispatcher;
309               }
310               void CIMListenerService::setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher)
311               {
312               	_dispatcher = dispatcher;
313 kumpf    1.1  }
314               
315 tony     1.8  PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL CIMListenerService::_listener_routine(void *param)
316 kumpf    1.1  {
317 tony     1.8    CIMListenerService *svc = reinterpret_cast<CIMListenerService *>(param);
318 kumpf    1.1  
319 chuck    1.20   //svc->init(); bug 1394 
320                 while(!svc->terminated())
321                 {
322               #if defined(PEGASUS_PLATFORM_DARWIN_PPC_GNU)
323                   pthread_testcancel();
324               #endif
325                   svc->runForever();
326                 }
327                 delete svc;
328 tony     1.8  
329 chuck    1.20   return 0;
330 tony     1.8  }
331               static struct timeval create_time = {0, 1};
332               static struct timeval destroy_time = {15, 0};
333               static struct timeval deadlock_time = {0, 0};
334               
335               /////////////////////////////////////////////////////////////////////////////
336               // CIMListenerRep
337               /////////////////////////////////////////////////////////////////////////////
338               class CIMListenerRep
339               {
340               public:
341               	CIMListenerRep(Uint32 portNumber, SSLContext* sslContext=NULL);
342                 ~CIMListenerRep();
343               
344               	Uint32 getPortNumber() const;
345               
346               	SSLContext* getSSLContext() const;
347               	void setSSLContext(SSLContext* sslContext);
348               	
349               	void start();
350               	void stop();
351 tony     1.8  
352               	Boolean isAlive();
353               
354               	Boolean addConsumer(CIMIndicationConsumer* consumer);
355               	Boolean removeConsumer(CIMIndicationConsumer* consumer);
356               
357               private:
358               	Uint32			_portNumber;
359               	SSLContext* _sslContext;
360               
361                 CIMListenerIndicationDispatcher* _dispatcher;
362               	ThreadPool* _thread_pool;
363 chuck    1.20   CIMListenerService* _svc;  
364                 Semaphore *_listener_sem;
365 tony     1.8  };
366               
367               CIMListenerRep::CIMListenerRep(Uint32 portNumber, SSLContext* sslContext)
368               :_portNumber(portNumber)
369               ,_sslContext(sslContext)
370               ,_dispatcher(new CIMListenerIndicationDispatcher())
371               ,_thread_pool(NULL)
372 chuck    1.20 ,_svc(NULL)
373               ,_listener_sem(NULL)
374 tony     1.8  {
375               }
376               CIMListenerRep::~CIMListenerRep()
377               {
378 chuck    1.20   // if port is alive, clean up the port
379                 if (_thread_pool != NULL)
380                 {
381                   // Block incoming export requests and unbind the port
382                   _svc->stopClientConnection();
383                   
384                   // Shutdown the CIMListenerService
385                   _svc->shutdown();   
386                 }
387               
388                 if(_sslContext!=NULL)
389                   delete _sslContext;
390               
391                 if(_dispatcher!=NULL)
392                   delete _dispatcher;
393               
394                 if(_thread_pool!=NULL)
395                   delete _thread_pool;
396 tony     1.8  
397 chuck    1.20   if(_listener_sem!=NULL)
398                   delete _listener_sem;
399 tony     1.8  
400 chuck    1.20   // don't delete _svc, this is deleted by _listener_routine
401 tony     1.8  }
402               
403               Uint32 CIMListenerRep::getPortNumber() const
404               {
405               	return _portNumber;
406               }
407 kumpf    1.1  
408 tony     1.8  SSLContext* CIMListenerRep::getSSLContext() const
409               {
410               	return _sslContext;
411 kumpf    1.1  }
412 tony     1.8  void CIMListenerRep::setSSLContext(SSLContext* sslContext)
413               {
414               	if(_sslContext!=NULL)
415               		delete _sslContext;
416 kumpf    1.1  
417 tony     1.8  	_sslContext = sslContext;
418               }
419               void CIMListenerRep::start()
420 kumpf    1.1  {
421 chuck    1.20   // spawn a thread to do this
422                 if(_thread_pool==NULL)
423                 {
424                   CIMListenerService* svc = new CIMListenerService(_portNumber,_sslContext);
425                   try
426                   {
427                     // Try to initialize the service (bug 1394)
428                     svc->setIndicationDispatcher(_dispatcher);
429                     svc->init(); 
430                   }
431                   catch(...)
432                   {
433                     // Error. Exit without creating the ThreadPool, so that this listener
434                     // is not 'alive'
435                     delete svc;
436                     throw;
437                   }
438               
439                   _thread_pool = new ThreadPool(0, "Listener", 0, 1, 
440               				  create_time, destroy_time, deadlock_time);
441               
442 chuck    1.20     _listener_sem = new Semaphore(0);
443                   _thread_pool->allocate_and_awaken(svc,
444               				      CIMListenerService::_listener_routine,
445               				      _listener_sem);
446               
447                   _svc = svc;
448               
449                   Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER,
450               		Logger::INFORMATION,
451               		"CIMListener started");
452 chuck    1.17 
453 chuck    1.20     PEGASUS_STD(cerr) << "CIMlistener started" << PEGASUS_STD(endl);
454                 }
455 tony     1.8  }
456 kumpf    1.1  
457 tony     1.8  void CIMListenerRep::stop()
458               {
459 chuck    1.20   if(_thread_pool!=NULL)
460                 { 
461                   //
462                   // Graceful shutdown of the listener service
463                   //
464               
465                   // Block incoming export requests and unbind the port
466                   _svc->stopClientConnection();
467                   
468                   // Shutdown the CIMListenerService
469                   _svc->shutdown();
470               
471                   // Wait for the _listener_routine thread to exit.
472                   // The thread could be delivering an export, so give it 3sec.
473                   // Note that _listener_routine deletes the CIMListenerService,
474                   // so no need to delete _svc.
475                   try
476                   {
477                     _listener_sem->time_wait(3000); 
478                   }
479                   catch (TimeOut &)
480 chuck    1.20     {
481                     // No need to do anything, the thread pool will be deleted below
482                     // to cancel the _listener_routine thread if it is still running.
483                   }
484               
485                   delete _listener_sem;
486                   _listener_sem = NULL;
487                   
488                   // Delete the thread pool.  This cancels the listener thread if it is still
489                   // running.
490                   delete _thread_pool;
491                   _thread_pool = NULL;
492               
493                   Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER,
494               		Logger::INFORMATION,
495               		"CIMListener stopped");
496                 }
497 kumpf    1.1  }
498               
499 tony     1.8  Boolean CIMListenerRep::isAlive()
500 kumpf    1.1  {
501 tony     1.8  	return (_thread_pool!=NULL)?true:false;
502               }
503 kumpf    1.1  
504 tony     1.8  Boolean CIMListenerRep::addConsumer(CIMIndicationConsumer* consumer)
505               {
506               	return _dispatcher->addConsumer(consumer);
507               }
508               Boolean CIMListenerRep::removeConsumer(CIMIndicationConsumer* consumer)
509               {
510               	return _dispatcher->removeConsumer(consumer);
511               }
512 kumpf    1.1  
513 tony     1.8  /////////////////////////////////////////////////////////////////////////////
514               // CIMListener
515               /////////////////////////////////////////////////////////////////////////////
516               CIMListener::CIMListener(Uint32 portNumber, SSLContext* sslContext)
517               :_rep(new CIMListenerRep(portNumber,sslContext))
518               {
519               }
520               CIMListener::~CIMListener()
521               {
522               	if(_rep!=NULL)
523 tony     1.9  		delete static_cast<CIMListenerRep*>(_rep);
524 tony     1.8  	_rep=NULL;
525               }
526               	
527               Uint32 CIMListener::getPortNumber() const
528               {
529               	return static_cast<CIMListenerRep*>(_rep)->getPortNumber();
530 kumpf    1.1  }
531               
532 tony     1.8  SSLContext* CIMListener::getSSLContext() const
533               {
534               	return static_cast<CIMListenerRep*>(_rep)->getSSLContext();
535               }
536               void CIMListener::setSSLContext(SSLContext* sslContext)
537               {
538               	static_cast<CIMListenerRep*>(_rep)->setSSLContext(sslContext);
539               }
540               void CIMListener::start()
541 kumpf    1.1  {
542 tony     1.8  	static_cast<CIMListenerRep*>(_rep)->start();
543               }
544               void CIMListener::stop()
545               {
546               	static_cast<CIMListenerRep*>(_rep)->stop();
547               }
548 kumpf    1.1  
549 tony     1.8  Boolean CIMListener::isAlive()
550               {
551               	return static_cast<CIMListenerRep*>(_rep)->isAlive();
552               }
553 kumpf    1.1  
554 tony     1.8  Boolean CIMListener::addConsumer(CIMIndicationConsumer* consumer)
555               {
556               	return static_cast<CIMListenerRep*>(_rep)->addConsumer(consumer);
557               }
558               Boolean CIMListener::removeConsumer(CIMIndicationConsumer* consumer)
559               {
560               	return static_cast<CIMListenerRep*>(_rep)->removeConsumer(consumer);
561 kumpf    1.1  }
562               
563               PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2