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

  1 martin 1.22 //%LICENSE////////////////////////////////////////////////////////////////
  2 martin 1.23 //
  3 martin 1.22 // Licensed to The Open Group (TOG) under one or more contributor license
  4             // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
  5             // this work for additional information regarding copyright ownership.
  6             // Each contributor licenses this file to you under the OpenPegasus Open
  7             // Source License; you may not use this file except in compliance with the
  8             // License.
  9 martin 1.23 //
 10 martin 1.22 // Permission is hereby granted, free of charge, to any person obtaining a
 11             // copy of this software and associated documentation files (the "Software"),
 12             // to deal in the Software without restriction, including without limitation
 13             // the rights to use, copy, modify, merge, publish, distribute, sublicense,
 14             // and/or sell copies of the Software, and to permit persons to whom the
 15             // Software is furnished to do so, subject to the following conditions:
 16 martin 1.23 //
 17 martin 1.22 // The above copyright notice and this permission notice shall be included
 18             // in all copies or substantial portions of the Software.
 19 martin 1.23 //
 20 martin 1.22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 21 martin 1.23 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 22 martin 1.22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 23             // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 24             // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 25             // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 26             // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 27 martin 1.23 //
 28 martin 1.22 //////////////////////////////////////////////////////////////////////////
 29 h.sterling 1.1  //
 30                 //%/////////////////////////////////////////////////////////////////////////////
 31                 
 32                 #include <Pegasus/Common/Config.h>
 33                 #include <Pegasus/Common/System.h>
 34 kumpf      1.16 #include <Pegasus/Common/Time.h>
 35 h.sterling 1.1  
 36                 #include "ListenerService.h"
 37                 
 38                 PEGASUS_NAMESPACE_BEGIN
 39                 PEGASUS_USING_STD;
 40                 
 41                 static const int SHUTDOWN_TIMEOUT = 10; //seconds
 42                 
 43 kumpf      1.24 ListenerService::ListenerService(ConsumerManager* consumerManager) :
 44 h.sterling 1.1  _consumerManager(consumerManager),
 45                 _dispatcher(0),
 46                 _portNumber(0),
 47                 _useSSL(false),
 48                 _sslContext(0),
 49                 _initialized(0),
 50                 _running(0),
 51                 _dieNow(0),
 52                 _shutdownSem(0),
 53                 _monitor(0),
 54 venkat.puvvada 1.19 _ip6Acceptor(NULL),
 55                     _ip4Acceptor(NULL),
 56 h.sterling     1.1  _responseEncoder(0),
 57                     _requestDecoder(0),
 58                     _listening_thread(0),
 59                     _polling_thread(0)
 60                     {
 61                         PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::ListenerService");
 62                     
 63                     
 64                         PEG_METHOD_EXIT();
 65                     }
 66                     
 67                     ListenerService::~ListenerService()
 68                     {
 69                         PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::ListenerService");
 70                     
 71                         if (_running)
 72                         {
 73                             shutdownListener();
 74                         }
 75                     
 76                         if (_initialized)
 77 h.sterling     1.1      {
 78                             //cleanup everything we initialized
 79                     
 80 kumpf          1.12         delete _sslContext;
 81 h.sterling     1.1  
 82 kumpf          1.12         delete _dispatcher;
 83 h.sterling     1.1  
 84 kumpf          1.12         delete _responseEncoder;
 85 h.sterling     1.1  
 86 kumpf          1.12         delete _requestDecoder;
 87 h.sterling     1.1  
 88 kumpf          1.12         delete _shutdownSem;
 89 kumpf          1.24 
 90 h.sterling     1.1          //do not delete _consumerManager
 91                             //it is deleted by CIMListener
 92                         }
 93                     
 94                         PEG_METHOD_EXIT();
 95                     }
 96                     
 97                     ListenerService::ListenerService(const ListenerService& x)
 98                     {
 99                     }
100                     
101 kumpf          1.24 Boolean ListenerService::initializeListener(Uint32 portNumber,
102 venkat.puvvada 1.19     Boolean useSSL, SSLContext* sslContext)
103 h.sterling     1.1  {
104                         PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::initializeListener");
105                     
106                         if (_initialized)
107                         {
108 venkat.puvvada 1.19         PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2,
109                                 "Warning: The listener is already initialized.");
110 h.sterling     1.1          return true;
111                         }
112                     
113                         _portNumber = portNumber;
114                         _useSSL = useSSL;
115                         _sslContext = sslContext;
116                     
117 carson.hovey   1.2      if (_useSSL && (_sslContext == NULL))
118 h.sterling     1.1      {
119 venkat.puvvada 1.19         throw Exception(MessageLoaderParms(
120                                 "DynListener.ListenerService.INVALID_SSL_CONFIGURATION",
121                                 "Invalid SSL configuration: No SSLContext was specified."));
122 h.sterling     1.1      }
123                     
124                         if (!_useSSL && _sslContext)
125                         {
126 venkat.puvvada 1.19         PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2,
127                             "Warning: An SSLContext was specified for a non-SSL configuration.");
128 h.sterling     1.1      }
129                     
130                         _dispatcher = new DynamicListenerIndicationDispatcher(_consumerManager);
131                     
132                         _responseEncoder = new CIMExportResponseEncoder();
133                     
134                         _requestDecoder = new CIMExportRequestDecoder(_dispatcher,
135 venkat.puvvada 1.19                                          _responseEncoder->getQueueId());
136 h.sterling     1.1  
137                         _shutdownSem = new Semaphore(0);
138                     
139                         _initialized = true;
140                     
141                         PEG_METHOD_EXIT();
142                         return true;
143                     }
144                     
145                     Boolean ListenerService::runListener()
146                     {
147                         PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::runListener");
148                     
149                         if (!_initialized)
150                         {
151 venkat.puvvada 1.19         throw Exception(MessageLoaderParms(
152                                 "DynListener.ListenerService.NOT_INITIALIZED",
153                                 "Error: You must initialize the listener prior to running it."));
154 h.sterling     1.1      }
155                     
156                         if (_running)
157                         {
158 venkat.puvvada 1.19         throw Exception(MessageLoaderParms(
159                                 "DynListener.ListenerService.ALREADY_RUNNING",
160                                 "Error: The listener is already running."));
161 h.sterling     1.1      }
162 kumpf          1.24 
163 h.sterling     1.1      _monitor = new Monitor();
164                     
165 dave.sudlik    1.18 #ifdef PEGASUS_ENABLE_IPV6
166 venkat.puvvada 1.19     if (System::isIPv6StackActive())
167                         {
168                             _ip6Acceptor = new HTTPAcceptor(
169 kumpf          1.24                                 _monitor,
170                                                     _requestDecoder,
171 dave.sudlik    1.18                                 HTTPAcceptor::IPV6_CONNECTION,
172 kumpf          1.24                                 _portNumber,
173 h.sterling     1.1                                  _sslContext,
174                                                     false);
175 venkat.puvvada 1.19     }
176                     #ifndef PEGASUS_OS_TYPE_WINDOWS
177                         else
178                     #endif
179 dave.sudlik    1.18 #endif
180 venkat.puvvada 1.19     {
181                             _ip4Acceptor = new HTTPAcceptor(
182 kumpf          1.24                                 _monitor,
183                                                     _requestDecoder,
184                                                     HTTPAcceptor::IPV4_CONNECTION,
185                                                     _portNumber,
186 dave.sudlik    1.18                                 _sslContext,
187                                                     false);
188 venkat.puvvada 1.19     }
189 h.sterling     1.1  
190                         //create listening thread
191                         _listening_thread = new Thread(_listener_routine, this, 0);
192                     
193                         //bind listener socket
194 venkat.puvvada 1.19     if (_ip6Acceptor)
195                         {
196                             _ip6Acceptor->bind();
197                         }
198                         if (_ip4Acceptor)
199 kumpf          1.24     {
200 venkat.puvvada 1.19         _ip4Acceptor->bind();
201                         }
202 h.sterling     1.1  
203                         //start listening thread
204 konrad.r       1.9      ThreadStatus rtn = PEGASUS_THREAD_OK;
205                         while ( (rtn = _listening_thread->run()) != PEGASUS_THREAD_OK)
206 h.sterling     1.1      {
207 venkat.puvvada 1.19     if (rtn == PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
208                                 Threads::yield();
209                         else {
210 kumpf          1.24         // We need to set _running to true so that we can shutdown the
211 venkat.puvvada 1.19         // rest of the classes
212                             delete _listening_thread; _listening_thread = 0;
213                                 _running = true;
214 kumpf          1.24         shutdownListener();
215 venkat.puvvada 1.19             throw Exception(MessageLoaderParms(
216                                     "DynListener.ListenerService.CANNOT_ALLOCATE_THREAD",
217                                     "Error: Cannot allocate thread."));
218                         }
219 kumpf          1.24 
220 h.sterling     1.1      }
221 kumpf          1.24 
222 h.sterling     1.1      if (_consumerManager->getEnableConsumerUnload())
223                         {
224                             //create polling thread
225                             _polling_thread = new Thread(_polling_routine , this, 0);
226 kumpf          1.24 
227 h.sterling     1.1          //start polling thread
228 konrad.r       1.9          while ( (rtn=_polling_thread->run()) != PEGASUS_THREAD_OK)
229 h.sterling     1.1          {
230 venkat.puvvada 1.19            if (rtn == PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
231                                     Threads::yield();
232                                else
233                                {
234                                   /* We should delete them the objects, but there is a question
235 konrad.r       1.9                     of how to turn of the _listening_thread? */
236 venkat.puvvada 1.19               delete _polling_thread; _polling_thread = 0;
237                                   _running = true;
238 kumpf          1.24               shutdownListener();
239 venkat.puvvada 1.19               throw Exception(MessageLoaderParms(
240                                       "DynListener.ListenerService.CANNOT_ALLOCATE_THREAD",
241                                       "Error: Cannot allocate thread."));
242                                 }
243 h.sterling     1.1          }
244                         }
245                     
246                         _running = true;
247                     
248                         PEG_METHOD_EXIT();
249                         return true;
250                     }
251                     
252 kumpf          1.24 ThreadReturnType PEGASUS_THREAD_CDECL
253 venkat.puvvada 1.19      ListenerService::_listener_routine(void *param)
254 h.sterling     1.1  {
255                         PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::_listener_routine");
256                     
257                         Thread *myself = reinterpret_cast<Thread *>(param);
258 kumpf          1.24     ListenerService* listenerService =
259 venkat.puvvada 1.19         reinterpret_cast<ListenerService*>(myself->get_parm());
260 h.sterling     1.1  
261 kumpf          1.15     while (!(listenerService->_dieNow))
262 h.sterling     1.1      {
263 kumpf          1.15          listenerService->_monitor->run(30000);
264                              static struct timeval lastIdleCleanupTime = {0, 0};
265                              struct timeval now;
266 kumpf          1.16          Time::gettimeofday(&now);
267 kumpf          1.15          if (now.tv_sec - lastIdleCleanupTime.tv_sec > 300)
268                              {
269                                  lastIdleCleanupTime.tv_sec = now.tv_sec;
270 kumpf          1.24              try
271 kumpf          1.15              {
272                                      MessageQueueService::get_thread_pool()->cleanupIdleThreads();
273                                  }
274                                  catch(...)
275                                  {
276                                  }
277                              }
278                         }
279                     
280 kumpf          1.24     PEG_TRACE_CSTRING(TRC_LISTENER,
281 kumpf          1.15                      Tracer::LEVEL4,
282                                          "ListenerService::Stopping _listener_routine");
283 h.sterling     1.1      PEG_METHOD_EXIT();
284                         return 0;  //success
285                     }
286                     
287                     
288 kumpf          1.24 ThreadReturnType PEGASUS_THREAD_CDECL
289 venkat.puvvada 1.19     ListenerService::_polling_routine(void *param)
290 h.sterling     1.1  {
291                         PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::_polling_routine");
292                     
293                         Thread *myself = reinterpret_cast<Thread *>(param);
294 venkat.puvvada 1.19     ListenerService* listenerService =
295                             reinterpret_cast<ListenerService*>(myself->get_parm());
296 h.sterling     1.1  
297                         while (true)
298                         {
299 kumpf          1.21         //do a timed wait so we do can process a shutdown signal immediately
300                             if (listenerService->_shutdownSem->time_wait(
301                                 listenerService->_consumerManager->getIdleTimeout()))
302 h.sterling     1.1          {
303                                 if (listenerService->_dieNow)
304                                 {
305                                     //shutdown
306                                     break;
307                                 }
308 venkat.puvvada 1.19         }
309 kumpf          1.21         else
310 h.sterling     1.1          {
311                                 //time to check for idle consumers
312 venkat.puvvada 1.19             PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL3,
313                                    "Unloading idle consumers");
314 h.sterling     1.1              listenerService->_consumerManager->unloadIdleConsumers();
315                             }
316                         }
317                     
318                         PEG_METHOD_EXIT();
319                         return 0; //success
320                     }
321                     
322                     Boolean ListenerService::shutdownListener()
323                     {
324                         PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::shutdownListener");
325                     
326                         if (!_running)
327                         {
328 marek          1.20         PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2,
329 venkat.puvvada 1.19             "Warning: The listener is not currently running.");
330 h.sterling     1.1  
331                             return true;
332                         }
333                     
334                         Boolean gracefulShutdown = true;
335                     
336                         //stop the monitor from accepting connections
337                         _monitor->stopListeningForConnections(true);
338                     
339 venkat.puvvada 1.19     if (_ip6Acceptor)
340                         {
341                             _ip6Acceptor->closeConnectionSocket();
342                         }
343                         if (_ip4Acceptor)
344                         {
345                             _ip4Acceptor->closeConnectionSocket();
346                         }
347 h.sterling     1.1  
348                         //allow client threads to complete, wait 10 sec max
349 venkat.puvvada 1.19     PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL4,
350                             "ListenerService::Waiting for outstanding requests...");
351 h.sterling     1.1      Uint32 reqCount;
352                         Uint32 countDown = SHUTDOWN_TIMEOUT;
353                         for (; countDown > 0; countDown--)
354                         {
355 dave.sudlik    1.18         reqCount = 0;
356 venkat.puvvada 1.19         if (_ip6Acceptor)
357                             {
358                                 reqCount = _ip6Acceptor->getOutstandingRequestCount();
359                             }
360                             if (_ip4Acceptor)
361                             {
362                                 reqCount += _ip4Acceptor->getOutstandingRequestCount();
363                             }
364 h.sterling     1.1          if (reqCount > 0)
365                             {
366 mike           1.13             Threads::sleep(1000);
367 h.sterling     1.1          } else
368                             {
369                                 break;
370                             }
371                         }
372                     
373 venkat.puvvada 1.19     PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL4,
374                             "ListenerService::Finished waiting for outstanding requests.");
375 h.sterling     1.1  
376                         if (reqCount > 0)
377                         {
378 venkat.puvvada 1.19         PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2,
379                                 "ListenerService::Did not successfully process"
380                                 " all incoming requests to the acceptor.");
381 h.sterling     1.1          gracefulShutdown = false;
382                         }
383                     
384                         //stop the monitor thread and idle thread
385                         _dieNow = true;
386                     
387                         //ATTN: This is ghetto and needs to be fixed
388                         //signal twice, once for polling thread, once for listener thread
389                         //have to signal before both join calls so we do not hit a deadlock
390                         _shutdownSem->signal();
391                         _shutdownSem->signal();
392                     
393                         _monitor->tickle();
394                     
395                         //stop listener thread
396                         try
397                         {
398                             _listening_thread->join();
399                             delete _listening_thread;
400                             _listening_thread = 0;
401                     
402 venkat.puvvada 1.19     }
403                         catch (...)
404 h.sterling     1.1      {
405 venkat.puvvada 1.19         PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2,
406                                 "Did not successfully stop monitor thread");
407 h.sterling     1.1          gracefulShutdown = false;
408                         }
409                     
410                         //stop polling thread
411                         if (_polling_thread) //may not be started if polling is disabled
412                         {
413                             try
414                             {
415                                 _polling_thread->join();
416                                 delete _polling_thread;
417                                 _polling_thread = 0;
418                     
419 venkat.puvvada 1.19         }
420                             catch (...)
421 h.sterling     1.1          {
422 venkat.puvvada 1.19             PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2,
423                                     "Did not successfully stop polling thread");
424 h.sterling     1.1              gracefulShutdown = false;
425                             }
426                         }
427 h.sterling     1.8      //delete acceptor
428 dave.sudlik    1.18     delete _ip6Acceptor;
429                         _ip6Acceptor = 0;
430                         delete _ip4Acceptor;
431                         _ip4Acceptor = 0;
432 h.sterling     1.8  
433 h.sterling     1.1      //delete monitor
434                         delete _monitor;
435                         _monitor = 0;
436                     
437 marek          1.17     PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2, "Listener stopped.");
438 h.sterling     1.1  
439                         //reset status values
440                         _running = false;
441                         _dieNow = false;
442                     
443 venkat.puvvada 1.19     if (gracefulShutdown)
444                         {
445 marek          1.20         PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL3,
446 venkat.puvvada 1.19             "Listener shutdown gracefully");
447 kumpf          1.24     }
448 h.sterling     1.1  
449                         PEG_METHOD_EXIT();
450                         return(gracefulShutdown);
451                     }
452                     
453 aruran.ms      1.7  Boolean ListenerService::isAlive() const throw()
454 h.sterling     1.1  {
455                         return _running;
456                     }
457                     
458                     //ATTN: Methods for old CIMListener interface...do we need them now?
459                     Uint32 ListenerService::getPortNumber() const
460                     {
461                         return _portNumber;
462                     }
463                     
464                     
465                     PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2