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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2