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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2