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
|