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

  1 karl  1.11 //%2006////////////////////////////////////////////////////////////////////////
  2 h.sterling 1.1  //
  3                 // 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                 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8                 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9                 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10                 // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl       1.11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12                 // EMC Corporation; Symantec Corporation; The Open Group.
 13 h.sterling 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                 // 
 21                 // 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 venkat.puvvada 1.16.18.3 // NOCHKSRC
 35                          
 36 h.sterling     1.1       #include <Pegasus/Common/Config.h>
 37                          #include <Pegasus/Common/System.h>
 38 kumpf          1.16      #include <Pegasus/Common/Time.h>
 39 h.sterling     1.1       
 40                          #include "ListenerService.h"
 41                          
 42                          PEGASUS_NAMESPACE_BEGIN
 43                          PEGASUS_USING_STD;
 44                          
 45                          static const int SHUTDOWN_TIMEOUT = 10; //seconds
 46                          
 47                          ListenerService::ListenerService(ConsumerManager* consumerManager) : 
 48                          _consumerManager(consumerManager),
 49                          _dispatcher(0),
 50                          _portNumber(0),
 51                          _useSSL(false),
 52                          _sslContext(0),
 53                          _initialized(0),
 54                          _running(0),
 55                          _dieNow(0),
 56                          _shutdownSem(0),
 57                          _monitor(0),
 58 venkat.puvvada 1.16.18.3 _ip6Acceptor(NULL),
 59                          _ip4Acceptor(NULL),
 60 h.sterling     1.1       _responseEncoder(0),
 61                          _requestDecoder(0),
 62                          _listening_thread(0),
 63                          _polling_thread(0)
 64                          {
 65                              PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::ListenerService");
 66                          
 67                          
 68                              PEG_METHOD_EXIT();
 69                          }
 70                          
 71                          ListenerService::~ListenerService()
 72                          {
 73                              PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::ListenerService");
 74                          
 75                              if (_running)
 76                              {
 77                                  shutdownListener();
 78                              }
 79                          
 80                              if (_initialized)
 81 h.sterling     1.1           {
 82                                  //cleanup everything we initialized
 83                          
 84 kumpf          1.12              delete _sslContext;
 85 h.sterling     1.1       
 86 kumpf          1.12              delete _dispatcher;
 87 h.sterling     1.1       
 88 kumpf          1.12              delete _responseEncoder;
 89 h.sterling     1.1       
 90 kumpf          1.12              delete _requestDecoder;
 91 h.sterling     1.1       
 92 kumpf          1.12              delete _shutdownSem;
 93 h.sterling     1.1               
 94                                  //do not delete _consumerManager
 95                                  //it is deleted by CIMListener
 96                              }
 97                          
 98                              PEG_METHOD_EXIT();
 99                          }
100                          
101                          ListenerService::ListenerService(const ListenerService& x)
102                          {
103                          }
104                          
105                          Boolean ListenerService::initializeListener(Uint32 portNumber, Boolean useSSL, SSLContext* sslContext)
106                          {
107                              PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::initializeListener");
108                          
109                              if (_initialized)
110                              {
111 marek          1.16.18.1         PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2, "Warning: The listener is already initialized.");
112 h.sterling     1.1               return true;
113                              }
114                          
115                              _portNumber = portNumber;
116                              _useSSL = useSSL;
117                              _sslContext = sslContext;
118                          
119 carson.hovey   1.2           if (_useSSL && (_sslContext == NULL))
120 h.sterling     1.1           {
121                                  throw Exception(MessageLoaderParms("DynListener.ListenerService.INVALID_SSL_CONFIGURATION",
122                                                                     "Invalid SSL configuration: No SSLContext was specified."));
123                              }
124                          
125                              if (!_useSSL && _sslContext)
126                              {
127 marek          1.16.18.1         PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2, "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                                                                            _responseEncoder->getQueueId());
136                          
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 h.sterling     1.1           if (!_initialized)
150                              {
151                                  throw Exception(MessageLoaderParms("DynListener.ListenerService.NOT_INITIALIZED",
152                                                                     "Error: You must initialize the listener prior to running it."));
153                              }
154                          
155                              if (_running)
156                              {
157                                  throw Exception(MessageLoaderParms("DynListener.ListenerService.ALREADY_RUNNING",
158                                                                     "Error: The listener is already running."));
159                              }
160                              
161                              _monitor = new Monitor();
162                          
163 dave.sudlik    1.16.18.2 #ifdef PEGASUS_ENABLE_IPV6
164 venkat.puvvada 1.16.18.3     if (System::isIPv6StackActive())
165                              {
166                                  _ip6Acceptor = new HTTPAcceptor(
167 h.sterling     1.1                                       _monitor, 
168                                                          _requestDecoder, 
169 dave.sudlik    1.16.18.2                                 HTTPAcceptor::IPV6_CONNECTION,
170 h.sterling     1.1                                       _portNumber, 
171                                                          _sslContext,
172                                                          false);
173 venkat.puvvada 1.16.18.3     }
174                          #ifndef PEGASUS_OS_TYPE_WINDOWS
175                              else
176 dave.sudlik    1.16.18.2 #endif
177 venkat.puvvada 1.16.18.3 #endif
178                              {
179                                  _ip4Acceptor = new HTTPAcceptor(
180 dave.sudlik    1.16.18.2                                 _monitor, 
181                                                          _requestDecoder, 
182                                                          HTTPAcceptor::IPV4_CONNECTION, 
183                                                          _portNumber, 
184                                                          _sslContext,
185                                                          false);
186 venkat.puvvada 1.16.18.3     }
187 h.sterling     1.1       
188                              //create listening thread
189                              _listening_thread = new Thread(_listener_routine, this, 0);
190                          
191                              //bind listener socket
192 venkat.puvvada 1.16.18.3     if (_ip6Acceptor)
193                              {
194                                  _ip6Acceptor->bind();
195                              }
196                              if (_ip4Acceptor)
197                              {    
198                                  _ip4Acceptor->bind();
199                              }
200 h.sterling     1.1       
201                              //start listening thread
202 konrad.r       1.9           ThreadStatus rtn = PEGASUS_THREAD_OK;
203                              while ( (rtn = _listening_thread->run()) != PEGASUS_THREAD_OK)
204 h.sterling     1.1           {
205 konrad.r       1.9       	if (rtn == PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
206 mike           1.13              	Threads::yield();
207 konrad.r       1.9       	else {
208                          		// We need to set _running to true so that we can shutdown the 
209                          		// rest of the classes
210                          		delete _listening_thread; _listening_thread = 0;
211                              		_running = true;
212                          		shutdownListener();		
213                                  	throw Exception(MessageLoaderParms("DynListener.ListenerService.CANNOT_ALLOCATE_THREAD",
214                                                                     "Error: Cannot allocate thread."));
215                          	}
216                          	
217 h.sterling     1.1           }
218                              
219                              if (_consumerManager->getEnableConsumerUnload())
220                              {
221                                  //create polling thread
222                                  _polling_thread = new Thread(_polling_routine , this, 0);
223                              
224                                  //start polling thread
225 konrad.r       1.9               while ( (rtn=_polling_thread->run()) != PEGASUS_THREAD_OK)
226 h.sterling     1.1               {
227 konrad.r       1.9       	   if (rtn == PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
228 mike           1.13                  Threads::yield();
229 konrad.r       1.9       	   else
230                          	   {
231                          		/* We should delete them the objects, but there is a question
232                                             of how to turn of the _listening_thread? */
233                          		delete _polling_thread; _polling_thread = 0;
234                              		_running = true;
235                          		shutdownListener();		
236                                  	throw Exception(MessageLoaderParms("DynListener.ListenerService.CANNOT_ALLOCATE_THREAD",
237                                                                     "Error: Cannot allocate thread."));
238                          	    }
239 h.sterling     1.1               }
240                              }
241                          
242                              _running = true;
243                          
244                              PEG_METHOD_EXIT();
245                              return true;
246                          }
247                          
248 mike           1.13      ThreadReturnType PEGASUS_THREAD_CDECL ListenerService::_listener_routine(void *param)
249 h.sterling     1.1       {
250                              PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::_listener_routine");
251                          
252                              Thread *myself = reinterpret_cast<Thread *>(param);
253                              ListenerService* listenerService = reinterpret_cast<ListenerService*>(myself->get_parm());
254                          
255 kumpf          1.15          while (!(listenerService->_dieNow))
256 h.sterling     1.1           {
257 kumpf          1.15               listenerService->_monitor->run(30000);
258                                   static struct timeval lastIdleCleanupTime = {0, 0};
259                                   struct timeval now;
260 kumpf          1.16               Time::gettimeofday(&now);
261 kumpf          1.15               if (now.tv_sec - lastIdleCleanupTime.tv_sec > 300)
262                                   {
263                                       lastIdleCleanupTime.tv_sec = now.tv_sec;
264                                       try 
265                                       {
266                                           MessageQueueService::get_thread_pool()->cleanupIdleThreads();
267                                       }
268                                       catch(...)
269                                       {
270                                       }
271                                   }
272                              }
273                          
274 marek          1.16.18.1     PEG_TRACE_CSTRING(TRC_LISTENER, 
275 kumpf          1.15                           Tracer::LEVEL4,
276                                               "ListenerService::Stopping _listener_routine");
277 h.sterling     1.1           PEG_METHOD_EXIT();
278                              return 0;  //success
279                          }
280                          
281                          
282 mike           1.13      ThreadReturnType PEGASUS_THREAD_CDECL ListenerService::_polling_routine(void *param)
283 h.sterling     1.1       {
284                              PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::_polling_routine");
285                          
286                              Thread *myself = reinterpret_cast<Thread *>(param);
287                              ListenerService* listenerService = reinterpret_cast<ListenerService*>(myself->get_parm());
288                          
289                              while (true)
290                              {
291                                  try
292                                  {
293                                      //do a timed wait so we do can process a shutdown signal immediately
294 h.sterling     1.10                  listenerService->_shutdownSem->time_wait(listenerService->_consumerManager->getIdleTimeout());
295 h.sterling     1.1       
296                                      if (listenerService->_dieNow)
297                                      {
298                                          //shutdown
299                                          break;
300                                      }
301                          
302 kumpf          1.14              } catch (TimeOut&)
303 h.sterling     1.1               {
304                                      //time to check for idle consumers
305 marek          1.16.18.1             PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL3, "Unloading idle consumers");
306 h.sterling     1.1                   listenerService->_consumerManager->unloadIdleConsumers();
307                                  }
308                              }
309                          
310                              PEG_METHOD_EXIT();
311                              return 0; //success
312                          }
313                          
314                          Boolean ListenerService::shutdownListener()
315                          {
316                              PEG_METHOD_ENTER(TRC_LISTENER, "ListenerService::shutdownListener");
317                          
318                              if (!_running)
319                              {
320 marek          1.16.18.1         PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL4, "Warning: The listener is not currently running.");
321 h.sterling     1.1       
322                                  return true;
323                              }
324                          
325                              Boolean gracefulShutdown = true;
326                          
327                              //stop the monitor from accepting connections
328                              _monitor->stopListeningForConnections(true);
329                          
330 venkat.puvvada 1.16.18.3     if (_ip6Acceptor)
331                              {
332                                  _ip6Acceptor->closeConnectionSocket();
333                              }
334                              if (_ip4Acceptor)
335                              {
336                                  _ip4Acceptor->closeConnectionSocket();
337                              }
338 h.sterling     1.1       
339                              //allow client threads to complete, wait 10 sec max
340 marek          1.16.18.1     PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL4, "ListenerService::Waiting for outstanding requests...");
341 h.sterling     1.1           Uint32 reqCount;
342                              Uint32 countDown = SHUTDOWN_TIMEOUT;
343                              for (; countDown > 0; countDown--)
344                              {
345 dave.sudlik    1.16.18.2         reqCount = 0;
346 venkat.puvvada 1.16.18.3         if (_ip6Acceptor)
347                                  {
348                                      reqCount = _ip6Acceptor->getOutstandingRequestCount();
349                                  }
350                                  if (_ip4Acceptor)
351                                  {
352                                      reqCount += _ip4Acceptor->getOutstandingRequestCount();
353                                  }
354 h.sterling     1.1               if (reqCount > 0)
355                                  {
356 mike           1.13                  Threads::sleep(1000);
357 h.sterling     1.1               } else
358                                  {
359                                      break;
360                                  }
361                              }
362                          
363 marek          1.16.18.1     PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL4, "ListenerService::Finished waiting for outstanding requests.");
364 h.sterling     1.1       
365                              if (reqCount > 0)
366                              {
367 marek          1.16.18.1         PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2, "ListenerService::Did not successfully process all incoming requests to the acceptor.");
368 h.sterling     1.1               gracefulShutdown = false;
369                              }
370                          
371                              //stop the monitor thread and idle thread
372                              _dieNow = true;
373                          
374                              //ATTN: This is ghetto and needs to be fixed
375                              //signal twice, once for polling thread, once for listener thread
376                              //have to signal before both join calls so we do not hit a deadlock
377                              _shutdownSem->signal();
378                              _shutdownSem->signal();
379                          
380                              _monitor->tickle();
381                          
382                              //stop listener thread
383                              try
384                              {
385                                  _listening_thread->join();
386                                  delete _listening_thread;
387                                  _listening_thread = 0;
388                          
389 h.sterling     1.1           } catch (...)
390                              {
391 marek          1.16.18.1         PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2, "Did not successfully stop monitor thread");
392 h.sterling     1.1               gracefulShutdown = false;
393                              }
394                          
395                              //stop polling thread
396                              if (_polling_thread) //may not be started if polling is disabled
397                              {
398                                  try
399                                  {
400                                      _polling_thread->join();
401                                      delete _polling_thread;
402                                      _polling_thread = 0;
403                          
404                                  } catch (...)
405                                  {
406 marek          1.16.18.1             PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2, "Did not successfully stop polling thread");
407 h.sterling     1.1                   gracefulShutdown = false;
408                                  }
409                              }
410 h.sterling     1.8           //delete acceptor
411 dave.sudlik    1.16.18.2     delete _ip6Acceptor;
412                              _ip6Acceptor = 0;
413                              delete _ip4Acceptor;
414                              _ip4Acceptor = 0;
415 h.sterling     1.8       
416 h.sterling     1.1           //delete monitor
417                              delete _monitor;
418                              _monitor = 0;
419                          
420 marek          1.16.18.1     PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL2, "Listener stopped.");
421 h.sterling     1.1       
422                              //reset status values
423                              _running = false;
424                              _dieNow = false;
425                          
426 h.sterling     1.6       	if (gracefulShutdown)
427                          	{
428 marek          1.16.18.1 		PEG_TRACE_CSTRING(TRC_LISTENER, Tracer::LEVEL4, "Listener shutdown gracefully");
429 h.sterling     1.6       	} 
430 h.sterling     1.1       
431                              PEG_METHOD_EXIT();
432                              return(gracefulShutdown);
433                          }
434                          
435 aruran.ms      1.7       Boolean ListenerService::isAlive() const throw()
436 h.sterling     1.1       {
437                              return _running;
438                          }
439                          
440                          //ATTN: Methods for old CIMListener interface...do we need them now?
441                          Uint32 ListenerService::getPortNumber() const
442                          {
443                              return _portNumber;
444                          }
445                          
446                          
447                          PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2