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

  1 karl  1.40 //%2006////////////////////////////////////////////////////////////////////////
  2 kumpf 1.1  //
  3 karl  1.25 // 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 karl  1.12 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.25 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.28 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.40 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13 kumpf 1.1  //
 14            // Permission is hereby granted, free of charge, to any person obtaining a copy
 15            // of this software and associated documentation files (the "Software"), to
 16            // deal in the Software without restriction, including without limitation the
 17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18            // sell copies of the Software, and to permit persons to whom the Software is
 19            // furnished to do so, subject to the following conditions:
 20 karl  1.40 // 
 21 kumpf 1.1  // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22            // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24            // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27            // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29            //
 30            //==============================================================================
 31            //
 32            //%/////////////////////////////////////////////////////////////////////////////
 33            
 34 tony  1.8  #include "CIMListener.h"
 35            #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 konrad.r 1.38 #include <Pegasus/Common/MessageLoader.h>
 41 kumpf    1.44 #include <Pegasus/Common/Time.h>
 42 kumpf    1.1  #include <Pegasus/ExportServer/CIMExportResponseEncoder.h>
 43               #include <Pegasus/ExportServer/CIMExportRequestDecoder.h>
 44 tony     1.8  #include <Pegasus/Consumer/CIMIndicationConsumer.h>
 45               #include <Pegasus/Listener/CIMListenerIndicationDispatcher.h>
 46               
 47               PEGASUS_NAMESPACE_BEGIN
 48 mike     1.41 
 49               ////////////////////////////////////////////////////////////////////////////////
 50               //
 51 tony     1.8  // CIMListenerService
 52 mike     1.41 //
 53               ////////////////////////////////////////////////////////////////////////////////
 54               
 55 tony     1.8  class CIMListenerService
 56               {
 57               public:
 58 mike     1.41     CIMListenerService(Uint32 portNumber, SSLContext * sslContext = NULL);
 59                   CIMListenerService(CIMListenerService & svc);
 60                   ~CIMListenerService();
 61               
 62                   void init();
 63               
 64                   /** bind to the port
 65                   */
 66                   void bind();
 67               
 68                   /** runForever Main runloop for the server.
 69                   */
 70                   void runForever();
 71               
 72                   /** Call to gracefully shutdown the server.  The server connection socket
 73                       will be closed to disable new connections from clients.
 74                   */
 75                   void stopClientConnection();
 76               
 77                   /** Call to gracefully shutdown the server.  It is called when the server
 78                       has been stopped and is ready to be shutdown.  Next time runForever()
 79 mike     1.41         is called, the server shuts down.
 80                   */
 81                   void shutdown();
 82               
 83                   /** Return true if the server has shutdown, false otherwise.
 84                   */
 85                   Boolean terminated() const
 86                   {
 87                       return _dieNow;
 88                   };
 89 david.dillard 1.34 
 90 mike          1.41     /** Call to resume the sever.
 91                        */
 92                        void resume();
 93                    
 94                        /** Call to set the CIMServer state.  Also inform the appropriate
 95                            message queues about the current state of the CIMServer.
 96                        */
 97                        void setState(Uint32 state);
 98                    
 99                        Uint32 getOutstandingRequestCount();
100                    
101                        /** Returns the indication listener dispatcher
102                        */
103                        CIMListenerIndicationDispatcher *getIndicationDispatcher() const;
104                    
105                        /** Returns the indication listener dispatcher
106                        */
107                        void setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher);
108                    
109                        /** Returns the port number being used.
110                        */
111 mike          1.41     Uint32 getPortNumber() const;
112                    
113 mike          1.42     static ThreadReturnType PEGASUS_THREAD_CDECL 
114 mike          1.41     _listener_routine(void *param);
115 tony          1.8  
116                    private:
117 mike          1.41     Uint32 _portNumber;
118                        SSLContext *_sslContext;
119                        Monitor *_monitor;
120                        Mutex _monitorMutex;
121 venkat.puvvada 1.47.6.2 #ifdef PEGASUS_ENABLE_IPV6
122 venkat.puvvada 1.47.6.1     HTTPAcceptor *_ip6Acceptor;
123                         #endif
124 venkat.puvvada 1.47.6.3 #if !defined (PEGASUS_ENABLE_IPV6) || defined (PEGASUS_OS_TYPE_WINDOWS)
125 venkat.puvvada 1.47.6.1     HTTPAcceptor *_ip4Acceptor;
126                         #endif
127 mike           1.41         Boolean _dieNow;
128                             CIMListenerIndicationDispatcher *_dispatcher;
129                             CIMExportResponseEncoder *_responseEncoder;
130                             CIMExportRequestDecoder *_requestDecoder;
131 tony           1.8      };
132                         
133 mike           1.41     CIMListenerService::CIMListenerService(
134                             Uint32 portNumber, 
135                             SSLContext * sslContext)
136                             :
137                             _portNumber(portNumber), 
138                             _sslContext(sslContext), 
139                             _monitor(NULL),
140 venkat.puvvada 1.47.6.2 #ifdef PEGASUS_ENABLE_IPV6
141 venkat.puvvada 1.47.6.1     _ip6Acceptor(NULL),
142                         #endif
143 venkat.puvvada 1.47.6.3 #if !defined (PEGASUS_ENABLE_IPV6) || defined (PEGASUS_OS_TYPE_WINDOWS)
144 venkat.puvvada 1.47.6.1     _ip4Acceptor(NULL),
145                         #endif
146 mike           1.41         _dieNow(false), 
147                             _dispatcher(NULL), 
148                             _responseEncoder(NULL),
149                             _requestDecoder(NULL)
150 tony           1.8      {
151                         }
152                         
153 mike           1.41     CIMListenerService::CIMListenerService(CIMListenerService & svc) :
154                             _portNumber(svc._portNumber), 
155                             _sslContext(svc._sslContext), 
156                             _monitor(NULL),
157 venkat.puvvada 1.47.6.2 #ifdef PEGASUS_ENABLE_IPV6
158 venkat.puvvada 1.47.6.1     _ip6Acceptor(NULL),
159                         #endif
160 venkat.puvvada 1.47.6.3 #if !defined (PEGASUS_ENABLE_IPV6) || defined (PEGASUS_OS_TYPE_WINDOWS)
161 venkat.puvvada 1.47.6.1     _ip4Acceptor(NULL),
162                         #endif
163 mike           1.41         _dieNow(svc._dieNow), 
164                             _dispatcher(NULL),
165                             _responseEncoder(NULL), 
166                             _requestDecoder(NULL)
167 tony           1.8      {
168                         }
169 mike           1.41     
170 tony           1.8      CIMListenerService::~CIMListenerService()
171                         {
172 kumpf          1.36         delete _responseEncoder;
173                             delete _requestDecoder;
174 venkat.puvvada 1.47.6.2 #ifdef PEGASUS_ENABLE_IPV6
175 venkat.puvvada 1.47.6.1     delete _ip6Acceptor;
176                         #endif
177 venkat.puvvada 1.47.6.3 #if !defined (PEGASUS_ENABLE_IPV6) || defined (PEGASUS_OS_TYPE_WINDOWS)
178 venkat.puvvada 1.47.6.1     delete _ip4Acceptor;
179                         #endif
180 kumpf          1.36         delete _monitor;
181 tony           1.8      }
182 kumpf          1.1      
183 tony           1.8      void CIMListenerService::init()
184 kumpf          1.1      {
185 mike           1.41         PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::init");
186 kumpf          1.1      
187 mike           1.41         if (NULL == _monitor)
188                                 _monitor = new Monitor();
189 david.dillard  1.31     
190 mike           1.41         // _dispatcher = new CIMListenerIndicationDispatcher();
191 kumpf          1.1      
192 mike           1.41         if (NULL == _responseEncoder)
193                                 _responseEncoder = new CIMExportResponseEncoder();
194 tony           1.8      
195 mike           1.41         if (NULL == _requestDecoder)
196                             {
197                                 _requestDecoder = new CIMExportRequestDecoder(
198                                     _dispatcher, _responseEncoder->getQueueId());
199                             }
200 venkat.puvvada 1.47.6.2 #ifdef PEGASUS_ENABLE_IPV6
201 venkat.puvvada 1.47.6.1     if (NULL == _ip6Acceptor)
202 mike           1.41         {
203 venkat.puvvada 1.47.6.1         _ip6Acceptor = new HTTPAcceptor(
204                                     _monitor, _requestDecoder, HTTPAcceptor::IPV6_CONNECTION,
205                                     _portNumber, _sslContext, false);
206 mike           1.41         }
207 venkat.puvvada 1.47.6.1 #endif
208 venkat.puvvada 1.47.6.3 #if !defined (PEGASUS_ENABLE_IPV6) || defined (PEGASUS_OS_TYPE_WINDOWS)
209 venkat.puvvada 1.47.6.1     if (NULL == _ip4Acceptor)
210                             {
211                                 _ip4Acceptor = new HTTPAcceptor(
212                                     _monitor, _requestDecoder, HTTPAcceptor::IPV4_CONNECTION,
213                                     _portNumber, _sslContext, false);
214                             }
215                         #endif
216 mike           1.41         bind();
217                         
218                             PEG_METHOD_EXIT();
219 tony           1.8      }
220 david.dillard  1.34     
221 tony           1.8      void CIMListenerService::bind()
222                         {
223 venkat.puvvada 1.47.6.2 #ifdef PEGASUS_ENABLE_IPV6
224 venkat.puvvada 1.47.6.1     if (_ip6Acceptor != NULL)
225 mike           1.41         {
226 venkat.puvvada 1.47.6.1         _ip6Acceptor->bind();
227                         
228                                 Logger::put(
229                                     Logger::STANDARD_LOG,
230                                     System::CIMLISTENER,
231                                     Logger::INFORMATION,
232                                     "IPV6, Listening on HTTP port $0.",
233                                     _portNumber);
234                             }
235                         #endif
236 venkat.puvvada 1.47.6.3 #if !defined (PEGASUS_ENABLE_IPV6) || defined (PEGASUS_OS_TYPE_WINDOWS)
237 venkat.puvvada 1.47.6.1     if (_ip4Acceptor != NULL)
238                             {
239                                 _ip4Acceptor->bind();
240 kumpf          1.1      
241 mike           1.41             Logger::put(
242                                     Logger::STANDARD_LOG, 
243                                     System::CIMLISTENER,
244                                     Logger::INFORMATION, 
245 venkat.puvvada 1.47.6.1             "IPV4, Listening on HTTP for port $0.",
246 mike           1.41                 _portNumber);
247 chuck          1.20         }
248 venkat.puvvada 1.47.6.1 #endif
249 tony           1.8      }
250 chuck          1.20     
251 tony           1.8      void CIMListenerService::runForever()
252                         {
253 mike           1.41         if (!_dieNow)
254 dj.gorey       1.14         {
255 kumpf          1.43             _monitor->run(500000);
256                                 static struct timeval lastIdleCleanupTime = {0, 0};
257                                 struct timeval now;
258 kumpf          1.44             Time::gettimeofday(&now);
259 kumpf          1.43             if (now.tv_sec - lastIdleCleanupTime.tv_sec > 300)
260 mike           1.41             {
261 kumpf          1.43                 lastIdleCleanupTime.tv_sec = now.tv_sec;
262 mike           1.41                 try
263                                     {
264                                         MessageQueueService::get_thread_pool()->cleanupIdleThreads();
265                                     }
266                                     catch(...)
267                                     {
268                                         // Ignore!
269                                     }
270                                 }
271 chuck          1.20         }
272 tony           1.8      }
273 kumpf          1.1      
274 tony           1.8      void CIMListenerService::shutdown()
275                         {
276                             PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::shutdown()");
277 kumpf          1.1      
278 mike           1.41         // This logic signals the thread currently executing _listener_routine()
279                             // to exit. That function deletes this instance of CIMListenerService, 
280                             // which deletes the _monitor member. We use a mutex to keep it from 
281                             // deleting the monitor until after tickle has been called.
282                             {
283                                 AutoMutex am(_monitorMutex);
284                                 _dieNow = true;
285                                 _monitor->tickle();
286                             }
287 kumpf          1.1      
288 kumpf          1.4          PEG_METHOD_EXIT();
289 kumpf          1.1      }
290                         
291 tony           1.8      void CIMListenerService::resume()
292 kumpf          1.1      {
293 tony           1.8          PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::resume()");
294 venkat.puvvada 1.47.6.2 #ifdef PEGASUS_ENABLE_IPV6
295 venkat.puvvada 1.47.6.1     if (_ip6Acceptor != NULL)
296                             {
297                                 _ip6Acceptor->reopenConnectionSocket();
298                             }
299                         #endif
300 venkat.puvvada 1.47.6.3 #if !defined (PEGASUS_ENABLE_IPV6) || defined (PEGASUS_OS_TYPE_WINDOWS)
301 venkat.puvvada 1.47.6.1     if (_ip4Acceptor != NULL)
302                             {
303                                 _ip4Acceptor->reopenConnectionSocket();
304                             }
305                         #endif
306 kumpf          1.4          PEG_METHOD_EXIT();
307 kumpf          1.1      }
308                         
309 tony           1.8      void CIMListenerService::stopClientConnection()
310 kumpf          1.1      {
311 mike           1.41         PEG_METHOD_ENTER(
312                                 TRC_LISTENER,
313                                 "CIMListenerService::stopClientConnection()");
314 kumpf          1.1      
315 kumpf          1.10         // tell Monitor to stop listening for client connections
316 chuck          1.22         _monitor->stopListeningForConnections(true);
317 venkat.puvvada 1.47.6.2 #ifdef PEGASUS_ENABLE_IPV6
318 venkat.puvvada 1.47.6.1     if (_ip6Acceptor != NULL)
319                             {
320                                 _ip6Acceptor->closeConnectionSocket();
321                             }
322                         #endif
323 venkat.puvvada 1.47.6.3 #if !defined (PEGASUS_ENABLE_IPV6) || defined (PEGASUS_OS_TYPE_WINDOWS)
324 venkat.puvvada 1.47.6.1     if (_ip4Acceptor != NULL)
325                             {
326                                 _ip4Acceptor->closeConnectionSocket();
327                             }
328                         #endif
329 kumpf          1.4          PEG_METHOD_EXIT();
330 kumpf          1.1      }
331                         
332 chuck          1.23     Uint32 CIMListenerService::getOutstandingRequestCount()
333                         {
334 venkat.puvvada 1.47.6.1     Uint32 cnt = 0;
335 venkat.puvvada 1.47.6.2 #ifdef PEGASUS_ENABLE_IPV6
336 venkat.puvvada 1.47.6.1     cnt = _ip6Acceptor->getOutstandingRequestCount();
337                         #endif
338 venkat.puvvada 1.47.6.3 #if !defined (PEGASUS_ENABLE_IPV6) || defined (PEGASUS_OS_TYPE_WINDOWS)
339 venkat.puvvada 1.47.6.1     cnt += _ip4Acceptor->getOutstandingRequestCount();
340                         #endif
341                         
342                             return cnt;
343 chuck          1.23     }
344 tony           1.8      
345 mike           1.41     CIMListenerIndicationDispatcher* 
346                         CIMListenerService::getIndicationDispatcher() const
347 kumpf          1.1      {
348 david.dillard  1.32         return _dispatcher;
349 tony           1.8      }
350 david.dillard  1.34     
351 mike           1.41     void CIMListenerService::setIndicationDispatcher(
352                             CIMListenerIndicationDispatcher* dispatcher)
353 tony           1.8      {
354 david.dillard  1.32         _dispatcher = dispatcher;
355 kumpf          1.1      }
356                         
357 david.dillard  1.34     Uint32 CIMListenerService::getPortNumber() const
358                         {
359                             Uint32 portNumber = _portNumber;
360                         
361 venkat.puvvada 1.47.6.2 #ifdef PEGASUS_ENABLE_IPV6
362 venkat.puvvada 1.47.6.1     if ((portNumber == 0) && (_ip6Acceptor != 0))
363 david.dillard  1.34         {
364 venkat.puvvada 1.47.6.1         portNumber = _ip6Acceptor->getPortNumber();
365 david.dillard  1.34         }
366 venkat.puvvada 1.47.6.1 #endif
367                         
368 venkat.puvvada 1.47.6.3 #if !defined (PEGASUS_ENABLE_IPV6) || defined (PEGASUS_OS_TYPE_WINDOWS)
369 venkat.puvvada 1.47.6.1     if ((portNumber == 0) && (_ip4Acceptor != 0))
370                             {
371                                 portNumber = _ip4Acceptor->getPortNumber();
372                             }
373                         #endif
374 david.dillard  1.34     
375 mike           1.41         return (portNumber);
376 david.dillard  1.34     }
377                         
378 mike           1.42     ThreadReturnType PEGASUS_THREAD_CDECL 
379 mike           1.41     CIMListenerService::_listener_routine(void *param)
380 kumpf          1.1      {
381 mike           1.41         CIMListenerService *svc = reinterpret_cast < CIMListenerService * >(param);
382 kumpf          1.1      
383 mike           1.41         try
384 david.dillard  1.32         {
385 mike           1.41             // svc->init(); bug 1394
386                                 while (!svc->terminated())
387                                 {
388 mike           1.46     #if defined(PEGASUS_OS_DARWIN)
389 mike           1.41                 pthread_testcancel();
390 chuck          1.20     #endif
391 mike           1.41                 svc->runForever();
392                                 }
393 david.dillard  1.32         }
394 mike           1.41         catch(...)
395                             {
396 marek          1.47             PEG_TRACE_CSTRING(TRC_SERVER, Tracer::LEVEL2,
397 mike           1.41                           "Unknown exception thrown in _listener_routine.");
398                             }
399                         
400                             // CAUTION: deleting the service also deletes the monitor whose tickle()
401                             // method may still be executing in another thread. This line of code was
402                             // most likely reached when the CIMListenerService::shutdown() method set
403                             // _dieNow to true and called Monitor::tickle(). We must wait until we
404                             // can obtain the _monitorMutex, indicating that we are no longer inside
405                             // Monitor::tickle().
406 mike           1.42         svc->_monitorMutex.lock();
407 mike           1.41         svc->_monitorMutex.unlock();
408                             delete svc;
409                         
410 david.dillard  1.32         return 0;
411 tony           1.8      }
412                         
413 mike           1.41     ////////////////////////////////////////////////////////////////////////////////
414                         //
415 tony           1.8      // CIMListenerRep
416 mike           1.41     //
417                         ////////////////////////////////////////////////////////////////////////////////
418                         
419 tony           1.8      class CIMListenerRep
420                         {
421                         public:
422 mike           1.41         CIMListenerRep(Uint32 portNumber, SSLContext * sslContext = NULL);
423                             ~CIMListenerRep();
424 tony           1.8      
425 mike           1.41         Uint32 getPortNumber() const;
426 tony           1.8      
427 mike           1.41         SSLContext *getSSLContext() const;
428                             void setSSLContext(SSLContext * sslContext);
429 david.dillard  1.31     
430 mike           1.41         void start();
431                             void stop();
432 tony           1.8      
433 mike           1.41         Boolean isAlive();
434 tony           1.8      
435 mike           1.41         Boolean addConsumer(CIMIndicationConsumer * consumer);
436                             Boolean removeConsumer(CIMIndicationConsumer * consumer);
437 tony           1.8      
438                         private:
439 mike           1.41         Boolean waitForPendingRequests(Uint32 shutdownTimeout);
440 chuck          1.23     
441 mike           1.41         Uint32 _portNumber;
442                             SSLContext *_sslContext;
443 tony           1.8      
444 mike           1.41         CIMListenerIndicationDispatcher *_dispatcher;
445                             ThreadPool *_thread_pool;
446                             CIMListenerService *_svc;
447                             Semaphore *_listener_sem;
448 tony           1.8      };
449                         
450 mike           1.41     CIMListenerRep::CIMListenerRep(
451                             Uint32 portNumber, 
452                             SSLContext * sslContext)
453                             :
454                             _portNumber(portNumber), 
455                             _sslContext(sslContext),
456                             _dispatcher(new CIMListenerIndicationDispatcher()), 
457                             _thread_pool(NULL),
458                             _svc(NULL), 
459                             _listener_sem(NULL)
460 tony           1.8      {
461                         }
462 david.dillard  1.31     
463 tony           1.8      CIMListenerRep::~CIMListenerRep()
464                         {
465 david.dillard  1.31         // if port is alive, clean up the port
466                             if (_thread_pool != 0)
467                             {
468                                 // Block incoming export requests and unbind the port
469                                 _svc->stopClientConnection();
470                         
471                                 // Wait until pending export requests in the server are done.
472                                 waitForPendingRequests(10);
473 chuck          1.23     
474 david.dillard  1.31             // Shutdown the CIMListenerService
475                                 _svc->shutdown();
476                             }
477 chuck          1.20     
478                             delete _sslContext;
479                             delete _dispatcher;
480                             delete _thread_pool;
481                             delete _listener_sem;
482 tony           1.8      
483 mike           1.41         // don't delete _svc, this is deleted by _listener_routine
484 tony           1.8      }
485                         
486                         Uint32 CIMListenerRep::getPortNumber() const
487                         {
488 david.dillard  1.34         Uint32 portNumber;
489                         
490 mike           1.41         if (_svc == 0)
491 david.dillard  1.34             portNumber = _portNumber;
492 mike           1.41         else
493                                 portNumber = _svc->getPortNumber();
494 david.dillard  1.34     
495                             return portNumber;
496 tony           1.8      }
497 kumpf          1.1      
498 mike           1.41     SSLContext *CIMListenerRep::getSSLContext() const
499 tony           1.8      {
500 david.dillard  1.31         return _sslContext;
501 kumpf          1.1      }
502 david.dillard  1.31     
503 mike           1.41     void CIMListenerRep::setSSLContext(SSLContext * sslContext)
504 tony           1.8      {
505 david.dillard  1.31         delete _sslContext;
506                             _sslContext = sslContext;
507                         }
508 kumpf          1.1      
509 tony           1.8      void CIMListenerRep::start()
510 kumpf          1.1      {
511 david.dillard  1.31         // spawn a thread to do this
512 mike           1.41         if (_thread_pool == 0)
513 chuck          1.20         {
514 mike           1.41             AutoPtr < CIMListenerService >
515                                     svc(new CIMListenerService(_portNumber, _sslContext));
516 chuck          1.20     
517 david.dillard  1.31             svc->setIndicationDispatcher(_dispatcher);
518                                 svc->init();
519 chuck          1.20     
520 mike           1.41             struct timeval deallocateWait = { 15, 0 };
521                                 AutoPtr < ThreadPool >
522                                     threadPool(new ThreadPool(0, "Listener", 0, 1, deallocateWait));
523                                 AutoPtr < Semaphore > sem(new Semaphore(0));
524                         
525                                 if (threadPool->allocate_and_awaken(
526                                     svc.get(), CIMListenerService::_listener_routine, sem.get()) 
527                                     != PEGASUS_THREAD_OK)
528                                 {
529                                     Logger::put(
530 yi.zhou        1.45                     Logger::STANDARD_LOG, System::CIMLISTENER,
531 mike           1.41                     Logger::TRACE,
532                                         "Not enough threads to start CIMListernerService.");
533                         
534 marek          1.47                 PEG_TRACE_CSTRING(
535 mike           1.41                     TRC_SERVER, 
536                                         Tracer::LEVEL2,
537                                         "Could not allocate thread for "
538                                         "CIMListenerService::_listener_routine.");
539                                     throw
540                                         Exception(MessageLoaderParms(
541                                             "Listener.CIMListener.CANNOT_ALLOCATE_THREAD",
542                                             "Could not allocate thread."));
543 konrad.r       1.38             }
544 mike           1.41     
545                                 Logger::put(
546                                     Logger::STANDARD_LOG, 
547                                     System::CIMLISTENER,
548                                     Logger::INFORMATION, 
549                                     "CIMListener started");
550 david.dillard  1.31     
551                                 _svc = svc.release();
552                                 _thread_pool = threadPool.release();
553                                 _listener_sem = sem.release();
554                             }
555 tony           1.8      }
556 kumpf          1.1      
557 tony           1.8      void CIMListenerRep::stop()
558                         {
559 mike           1.41         if (_thread_pool != NULL)
560 chuck          1.20         {
561 mike           1.41             // 
562                                 // Graceful shutdown of the listener service
563                                 // 
564                         
565                                 // Block incoming export requests and unbind the port
566                                 _svc->stopClientConnection();
567                         
568                                 // Wait until pending export requests in the server are done.
569                                 waitForPendingRequests(10);
570                         
571                                 // Shutdown the CIMListenerService
572                                 _svc->shutdown();
573 chuck          1.20     
574 mike           1.41             // Wait for the _listener_routine thread to exit.
575                                 // The thread could be delivering an export, so give it 3sec.
576                                 // Note that _listener_routine deletes the CIMListenerService,
577                                 // so no need to delete _svc.
578                                 try
579                                 {
580                                     _listener_sem->time_wait(3000);
581                                 }
582                                 catch(const TimeOut &)
583                                 {
584                                     // No need to do anything, the thread pool will be deleted below
585                                     // to cancel the _listener_routine thread if it is still running.
586                                 }
587 david.dillard  1.31     
588 mike           1.41             delete _listener_sem;
589                                 _listener_sem = NULL;
590 chuck          1.20     
591 mike           1.41             // Delete the thread pool.  This cancels the listener thread if it is 
592                                 // still
593                                 // running.
594                                 delete _thread_pool;
595                                 _thread_pool = NULL;
596                         
597                                 Logger::put(
598                                     Logger::STANDARD_LOG, System::CIMLISTENER,
599                                     Logger::INFORMATION, "CIMListener stopped");
600                             }
601 kumpf          1.1      }
602                         
603 tony           1.8      Boolean CIMListenerRep::isAlive()
604 kumpf          1.1      {
605 mike           1.41         return (_thread_pool != NULL) ? true : false;
606 tony           1.8      }
607 kumpf          1.1      
608 mike           1.41     Boolean CIMListenerRep::addConsumer(CIMIndicationConsumer * consumer)
609 tony           1.8      {
610 mike           1.41         return _dispatcher->addConsumer(consumer);
611 tony           1.8      }
612 mike           1.41     
613                         Boolean CIMListenerRep::removeConsumer(CIMIndicationConsumer * consumer)
614 tony           1.8      {
615 mike           1.41         return _dispatcher->removeConsumer(consumer);
616 tony           1.8      }
617 kumpf          1.1      
618 chuck          1.23     Boolean CIMListenerRep::waitForPendingRequests(Uint32 shutdownTimeout)
619                         {
620 mike           1.41         // Wait for 10 sec max
621                             Uint32 reqCount;
622                             Uint32 countDown = shutdownTimeout * 10;
623                         
624                             for (; countDown > 0; countDown--)
625                             {
626                                 reqCount = _svc->getOutstandingRequestCount();
627                                 if (reqCount > 0)
628 mike           1.42                 Threads::sleep(100);
629 mike           1.41             else
630                                     return true;
631                             }
632 david.dillard  1.31     
633 mike           1.41         return false;
634 david.dillard  1.31     }
635 chuck          1.23     
636 tony           1.8      /////////////////////////////////////////////////////////////////////////////
637 mike           1.41     //
638 tony           1.8      // CIMListener
639 mike           1.41     //
640 tony           1.8      /////////////////////////////////////////////////////////////////////////////
641 mike           1.41     
642                         CIMListener::CIMListener(
643                             Uint32 portNumber, 
644                             SSLContext * sslContext) 
645                             :
646                             _rep(new CIMListenerRep(portNumber, sslContext))
647 tony           1.8      {
648                         }
649 mike           1.41     
650 tony           1.8      CIMListener::~CIMListener()
651                         {
652 mike           1.41         if (_rep != NULL)
653                                 delete static_cast < CIMListenerRep * >(_rep);
654                             _rep = NULL;
655 tony           1.8      }
656 david.dillard  1.31     
657 tony           1.8      Uint32 CIMListener::getPortNumber() const
658                         {
659 mike           1.41         return static_cast < CIMListenerRep * >(_rep)->getPortNumber();
660 kumpf          1.1      }
661                         
662 mike           1.41     SSLContext *CIMListener::getSSLContext() const
663 tony           1.8      {
664 mike           1.41         return static_cast < CIMListenerRep * >(_rep)->getSSLContext();
665 tony           1.8      }
666 mike           1.41     
667                         void CIMListener::setSSLContext(SSLContext * sslContext)
668 tony           1.8      {
669 mike           1.41         static_cast < CIMListenerRep * >(_rep)->setSSLContext(sslContext);
670 tony           1.8      }
671 mike           1.41     
672 tony           1.8      void CIMListener::start()
673 kumpf          1.1      {
674 mike           1.41         static_cast < CIMListenerRep * >(_rep)->start();
675 tony           1.8      }
676 mike           1.41     
677 tony           1.8      void CIMListener::stop()
678                         {
679 mike           1.41         static_cast < CIMListenerRep * >(_rep)->stop();
680 tony           1.8      }
681 kumpf          1.1      
682 aruran.ms      1.35     Boolean CIMListener::isAlive() const
683 tony           1.8      {
684 mike           1.41         return static_cast < CIMListenerRep * >(_rep)->isAlive();
685 tony           1.8      }
686 kumpf          1.1      
687 mike           1.41     Boolean CIMListener::addConsumer(CIMIndicationConsumer * consumer)
688 tony           1.8      {
689 mike           1.41         return static_cast < CIMListenerRep * >(_rep)->addConsumer(consumer);
690 tony           1.8      }
691 mike           1.41     
692                         Boolean CIMListener::removeConsumer(CIMIndicationConsumer * consumer)
693 tony           1.8      {
694 mike           1.41         return static_cast < CIMListenerRep * >(_rep)->removeConsumer(consumer);
695 kumpf          1.1      }
696                         
697                         PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2