1 karl 1.28 //%2005////////////////////////////////////////////////////////////////////////
|
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 kumpf 1.1 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
13 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
|
18 david.dillard 1.31 //
|
19 kumpf 1.1 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
20 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
22 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
|
30 tony 1.8 // Author: Dong Xiang, EMC Corporation (xiang_dong@emc.com)
|
31 kumpf 1.1 //
|
32 dj.gorey 1.14 // Modified By: Dan Gorey (djgorey@us.ibm.com)
|
33 a.arora 1.21 // Amit K Arora, IBM (amita@in.ibm.com) for PEP#183
|
34 kumpf 1.26 // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
35 david.dillard 1.31 // David Dillard, VERITAS Software Corp.
36 // (david.dillard@veritas.com)
|
37 vijay.eli 1.33 // Vijay Eli, IBM (vijay.eli@in.ibm.com) for bug#3425
|
38 kumpf 1.1 //
39 //%/////////////////////////////////////////////////////////////////////////////
40
|
41 tony 1.8 #include "CIMListener.h"
|
42 kumpf 1.1
|
43 tony 1.8 #include <Pegasus/Common/Exception.h>
44 #include <Pegasus/Common/SSLContext.h>
45 #include <Pegasus/Common/Monitor.h>
|
46 kumpf 1.1 #include <Pegasus/Common/HTTPAcceptor.h>
|
47 kumpf 1.11 #include <Pegasus/Common/PegasusVersion.h>
|
48 kumpf 1.2
|
49 kumpf 1.1 #include <Pegasus/ExportServer/CIMExportResponseEncoder.h>
50 #include <Pegasus/ExportServer/CIMExportRequestDecoder.h>
51
|
52 tony 1.8 #include <Pegasus/Consumer/CIMIndicationConsumer.h>
53 #include <Pegasus/Listener/CIMListenerIndicationDispatcher.h>
54
55 PEGASUS_NAMESPACE_BEGIN
56 /////////////////////////////////////////////////////////////////////////////
57 // CIMListenerService
58 /////////////////////////////////////////////////////////////////////////////
59 class CIMListenerService
60 {
61 public:
62 CIMListenerService(Uint32 portNumber, SSLContext* sslContext=NULL);
63 CIMListenerService(CIMListenerService& svc);
64 ~CIMListenerService();
65
66 void init();
67 /** bind to the port
68 */
69 void bind();
70 /** runForever Main runloop for the server.
71 */
72 void runForever();
|
73 david.dillard 1.31
|
74 tony 1.8 /** Call to gracefully shutdown the server. The server connection socket
75 will be closed to disable new connections from clients.
76 */
77 void stopClientConnection();
|
78 david.dillard 1.31
|
79 tony 1.8 /** Call to gracefully shutdown the server. It is called when the server
80 has been stopped and is ready to be shutdown. Next time runForever()
81 is called, the server shuts down.
82 */
83 void shutdown();
|
84 david.dillard 1.31
|
85 tony 1.8 /** Return true if the server has shutdown, false otherwise.
86 */
|
87 david.dillard 1.34 Boolean terminated() const { return _dieNow; };
|
88 david.dillard 1.31
|
89 tony 1.8 /** Call to resume the sever.
90 */
91 void resume();
|
92 david.dillard 1.31
|
93 tony 1.8 /** Call to set the CIMServer state. Also inform the appropriate
94 message queues about the current state of the CIMServer.
95 */
96 void setState(Uint32 state);
|
97 david.dillard 1.31
|
98 tony 1.8 Uint32 getOutstandingRequestCount();
99
100 /** Returns the indication listener dispatcher
101 */
102 CIMListenerIndicationDispatcher* getIndicationDispatcher() const;
103
|
104 david.dillard 1.34 /** Returns the indication listener dispatcher
|
105 tony 1.8 */
106 void setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher);
107
|
108 david.dillard 1.34 /** Returns the port number being used.
109 */
110 Uint32 getPortNumber() const;
111
|
112 tony 1.8 static PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL _listener_routine(void *param);
113
114 private:
|
115 david.dillard 1.34 Uint32 _portNumber;
|
116 tony 1.8 SSLContext* _sslContext;
|
117 david.dillard 1.34 Monitor* _monitor;
118 HTTPAcceptor* _acceptor;
|
119 dj.gorey 1.14
120 Boolean _dieNow;
|
121 tony 1.8
122 CIMListenerIndicationDispatcher* _dispatcher;
123
124 CIMExportResponseEncoder* _responseEncoder;
125 CIMExportRequestDecoder* _requestDecoder;
126
127 };
128
129 CIMListenerService::CIMListenerService(Uint32 portNumber, SSLContext* sslContext)
130 :_portNumber(portNumber)
131 ,_sslContext(sslContext)
132 ,_monitor(NULL)
133 ,_acceptor(NULL)
134 ,_dieNow(false)
135 ,_dispatcher(NULL)
136 ,_responseEncoder(NULL)
137 ,_requestDecoder(NULL)
138 {
139 }
140
141 CIMListenerService::CIMListenerService(CIMListenerService& svc)
142 tony 1.8 :_portNumber(svc._portNumber)
143 ,_sslContext(svc._sslContext)
144 ,_monitor(NULL)
145 ,_acceptor(NULL)
146 ,_dieNow(svc._dieNow)
147 ,_dispatcher(NULL)
148 ,_responseEncoder(NULL)
149 ,_requestDecoder(NULL)
150 {
151 }
152 CIMListenerService::~CIMListenerService()
153 {
154 // if port is alive, clean up the port
155 //if(_sslContext!=NULL)
156 // delete _sslContext;
157
158 if(_responseEncoder!=NULL)
159 delete _responseEncoder;
160
161 if(_requestDecoder!=NULL)
162 delete _requestDecoder;
|
163 kumpf 1.1
|
164 tony 1.8 //if(_dispatcher!=NULL)
165 // delete _dispatcher;
|
166 kumpf 1.1
|
167 tony 1.8 if(_monitor!=NULL)
168 delete _monitor;
|
169 kumpf 1.1
|
170 tony 1.8 if(_acceptor!=NULL)
171 delete _acceptor;
172 }
|
173 kumpf 1.1
|
174 tony 1.8 void CIMListenerService::init()
|
175 kumpf 1.1 {
|
176 tony 1.8 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::init");
|
177 kumpf 1.1
|
178 vijay.eli 1.33 if(NULL == _monitor) _monitor = new Monitor();
|
179 david.dillard 1.31
|
180 tony 1.8 //_dispatcher = new CIMListenerIndicationDispatcher();
|
181 kumpf 1.1
|
182 vijay.eli 1.33 if(NULL == _responseEncoder) _responseEncoder = new CIMExportResponseEncoder();
183 if(NULL == _requestDecoder) _requestDecoder = new CIMExportRequestDecoder(
184 _dispatcher,_responseEncoder->getQueueId());
|
185 tony 1.8
|
186 vijay.eli 1.33 if(NULL == _acceptor) _acceptor = new HTTPAcceptor(
|
187 david.dillard 1.31 _monitor,
188 _requestDecoder,
189 false,
190 _portNumber,
|
191 kumpf 1.19 _sslContext,
192 false);
|
193 kumpf 1.1
|
194 chuck 1.20 bind();
|
195 kumpf 1.1
|
196 chuck 1.20 PEG_METHOD_EXIT();
|
197 tony 1.8 }
|
198 david.dillard 1.34
|
199 tony 1.8 void CIMListenerService::bind()
200 {
|
201 chuck 1.20 if(_acceptor!=NULL)
202 { // Bind to the port
203 _acceptor->bind();
|
204 tony 1.8
|
205 chuck 1.20 PEGASUS_STD(cout) << "Listening on HTTP port " << _portNumber << PEGASUS_STD(endl);
|
206 david.dillard 1.31
|
207 chuck 1.20 //listener.addAcceptor(false, portNumberHttp, false);
208 Logger::put(Logger::STANDARD_LOG, System::CIMLISTENER, Logger::INFORMATION,
|
209 tony 1.8 "Listening on HTTP port $0.", _portNumber);
|
210 kumpf 1.1
|
211 chuck 1.20 }
|
212 tony 1.8 }
|
213 chuck 1.20
|
214 tony 1.8 void CIMListenerService::runForever()
215 {
|
216 chuck 1.20 static int modulator = 0;
|
217 kumpf 1.1
|
218 chuck 1.20 if(!_dieNow)
|
219 dj.gorey 1.14 {
|
220 david.dillard 1.31 if(false == _monitor->run(500000))
221 {
|
222 chuck 1.20 modulator++;
|
223 david.dillard 1.31 try
|
224 a.arora 1.21 {
225 //MessageQueueService::_check_idle_flag = 1;
226 //MessageQueueService::_polling_sem.signal();
|
227 kumpf 1.30 MessageQueueService::get_thread_pool()->cleanupIdleThreads();
|
228 a.arora 1.21 }
229 catch(...)
230 {
231 }
|
232 chuck 1.20 }
233 /*
234 if (handleShutdownSignal)
235 {
236 Tracer::trace(TRC_SERVER, Tracer::LEVEL3,
237 "CIMServer::runForever - signal received. Shutting down.");
238
239 ShutdownService::getInstance(this)->shutdown(true, 10, false);
240 handleShutdownSignal = false;
241 }
|
242 tony 1.8 */
|
243 chuck 1.20 }
|
244 tony 1.8 }
|
245 kumpf 1.1
|
246 tony 1.8 void CIMListenerService::shutdown()
247 {
248 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::shutdown()");
|
249 kumpf 1.1
|
250 tony 1.8 _dieNow = true;
|
251 a.arora 1.21 _monitor->tickle();
|
252 kumpf 1.1
|
253 kumpf 1.4 PEG_METHOD_EXIT();
|
254 kumpf 1.1 }
255
|
256 tony 1.8 void CIMListenerService::resume()
|
257 kumpf 1.1 {
|
258 tony 1.8 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::resume()");
|
259 kumpf 1.1
|
260 tony 1.8 if(_acceptor!=NULL)
261 _acceptor->reopenConnectionSocket();
|
262 kumpf 1.1
|
263 kumpf 1.4 PEG_METHOD_EXIT();
|
264 kumpf 1.1 }
265
|
266 tony 1.8 void CIMListenerService::stopClientConnection()
|
267 kumpf 1.1 {
|
268 tony 1.8 PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::stopClientConnection()");
|
269 kumpf 1.1
|
270 kumpf 1.10 // tell Monitor to stop listening for client connections
|
271 chuck 1.22 _monitor->stopListeningForConnections(true);
|
272 kumpf 1.10
273 //
274 // Wait 150 milliseconds to allow time for the Monitor to stop
275 // listening for client connections.
276 //
277 // This wait time is the timeout value for the select() call
278 // in the Monitor's run() method (currently set to 100
279 // milliseconds) plus a delta of 50 milliseconds. The reason
280 // for the wait here is to make sure that the Monitor entries
281 // are updated before closing the connection sockets.
282 //
|
283 a.arora 1.21 // pegasus_sleep(150); Not needed now due to the semaphore in the Monitor
|
284 david.dillard 1.31
|
285 tony 1.8 if(_acceptor!=NULL)
286 _acceptor->closeConnectionSocket();
|
287 kumpf 1.1
|
288 kumpf 1.4 PEG_METHOD_EXIT();
|
289 kumpf 1.1 }
290
|
291 chuck 1.23 Uint32 CIMListenerService::getOutstandingRequestCount()
292 {
293 return _acceptor->getOutstandingRequestCount();
294 }
|
295 tony 1.8
296 CIMListenerIndicationDispatcher* CIMListenerService::getIndicationDispatcher() const
|
297 kumpf 1.1 {
|
298 david.dillard 1.32 return _dispatcher;
|
299 tony 1.8 }
|
300 david.dillard 1.34
|
301 tony 1.8 void CIMListenerService::setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher)
302 {
|
303 david.dillard 1.32 _dispatcher = dispatcher;
|
304 kumpf 1.1 }
305
|
306 david.dillard 1.34 Uint32 CIMListenerService::getPortNumber() const
307 {
308
309 Uint32 portNumber = _portNumber;
310
311 if (( portNumber == 0 ) && ( _acceptor != 0 ))
312 {
313 portNumber = _acceptor->getPortNumber();
314 }
315
316 return(portNumber);
317 }
318
|
319 tony 1.8 PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL CIMListenerService::_listener_routine(void *param)
|
320 kumpf 1.1 {
|
321 david.dillard 1.32 AutoPtr<CIMListenerService> svc(reinterpret_cast<CIMListenerService *>(param));
|
322 kumpf 1.1
|
323 david.dillard 1.32 //svc->init(); bug 1394
324 while(!svc->terminated())
325 {
|
326 chuck 1.20 #if defined(PEGASUS_PLATFORM_DARWIN_PPC_GNU)
|
327 david.dillard 1.32 pthread_testcancel();
|
328 chuck 1.20 #endif
|
329 david.dillard 1.32 svc->runForever();
330 }
|
331 tony 1.8
|
332 david.dillard 1.32 return 0;
|
333 tony 1.8 }
334
335 /////////////////////////////////////////////////////////////////////////////
336 // CIMListenerRep
337 /////////////////////////////////////////////////////////////////////////////
338 class CIMListenerRep
339 {
340 public:
341 CIMListenerRep(Uint32 portNumber, SSLContext* sslContext=NULL);
342 ~CIMListenerRep();
343
344 Uint32 getPortNumber() const;
345
346 SSLContext* getSSLContext() const;
347 void setSSLContext(SSLContext* sslContext);
|
348 david.dillard 1.31
|
349 tony 1.8 void start();
350 void stop();
351
352 Boolean isAlive();
353
354 Boolean addConsumer(CIMIndicationConsumer* consumer);
355 Boolean removeConsumer(CIMIndicationConsumer* consumer);
356
357 private:
|
358 chuck 1.23 Boolean waitForPendingRequests(Uint32 shutdownTimeout);
359
360 Uint32 _portNumber;
361 SSLContext* _sslContext;
|
362 tony 1.8
363 CIMListenerIndicationDispatcher* _dispatcher;
|
364 chuck 1.23 ThreadPool* _thread_pool;
|
365 david.dillard 1.31 CIMListenerService* _svc;
|
366 chuck 1.20 Semaphore *_listener_sem;
|
367 tony 1.8 };
368
369 CIMListenerRep::CIMListenerRep(Uint32 portNumber, SSLContext* sslContext)
370 :_portNumber(portNumber)
371 ,_sslContext(sslContext)
372 ,_dispatcher(new CIMListenerIndicationDispatcher())
373 ,_thread_pool(NULL)
|
374 chuck 1.20 ,_svc(NULL)
375 ,_listener_sem(NULL)
|
376 tony 1.8 {
377 }
|
378 david.dillard 1.31
|
379 tony 1.8 CIMListenerRep::~CIMListenerRep()
380 {
|
381 david.dillard 1.31 // if port is alive, clean up the port
382 if (_thread_pool != 0)
383 {
384 // Block incoming export requests and unbind the port
385 _svc->stopClientConnection();
386
387 // Wait until pending export requests in the server are done.
388 waitForPendingRequests(10);
|
389 chuck 1.23
|
390 david.dillard 1.31 // Shutdown the CIMListenerService
391 _svc->shutdown();
392 }
|
393 chuck 1.20
394 delete _sslContext;
395 delete _dispatcher;
396 delete _thread_pool;
397 delete _listener_sem;
|
398 tony 1.8
|
399 chuck 1.20 // don't delete _svc, this is deleted by _listener_routine
|
400 tony 1.8 }
401
402 Uint32 CIMListenerRep::getPortNumber() const
403 {
|
404 david.dillard 1.34 Uint32 portNumber;
405
406 if ( _svc == 0 )
407 {
408 portNumber = _portNumber;
409 }
410 else portNumber = _svc->getPortNumber();
411
412 return portNumber;
|
413 tony 1.8 }
|
414 kumpf 1.1
|
415 tony 1.8 SSLContext* CIMListenerRep::getSSLContext() const
416 {
|
417 david.dillard 1.31 return _sslContext;
|
418 kumpf 1.1 }
|
419 david.dillard 1.31
|
420 tony 1.8 void CIMListenerRep::setSSLContext(SSLContext* sslContext)
421 {
|
422 david.dillard 1.31 delete _sslContext;
423 _sslContext = sslContext;
424 }
|
425 kumpf 1.1
|
426 tony 1.8 void CIMListenerRep::start()
|
427 kumpf 1.1 {
|
428 david.dillard 1.31 // spawn a thread to do this
429 if(_thread_pool==0)
|
430 chuck 1.20 {
|
431 david.dillard 1.31 AutoPtr<CIMListenerService> svc(new CIMListenerService(_portNumber,_sslContext));
|
432 chuck 1.20
|
433 david.dillard 1.31 svc->setIndicationDispatcher(_dispatcher);
434 svc->init();
|
435 chuck 1.20
|
436 david.dillard 1.31 struct timeval deallocateWait = {15, 0};
437 AutoPtr<ThreadPool> threadPool(new ThreadPool(0, "Listener", 0, 1, deallocateWait));
438 AutoPtr<Semaphore> sem(new Semaphore(0));
439 threadPool->allocate_and_awaken(svc.get(), CIMListenerService::_listener_routine, sem.get());
440 Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER, Logger::INFORMATION,
441 "CIMListener started");
442
443 PEGASUS_STD(cerr) << "CIMlistener started" << PEGASUS_STD(endl);
444
445 _svc = svc.release();
446 _thread_pool = threadPool.release();
447 _listener_sem = sem.release();
448 }
|
449 tony 1.8 }
|
450 kumpf 1.1
|
451 tony 1.8 void CIMListenerRep::stop()
452 {
|
453 chuck 1.20 if(_thread_pool!=NULL)
|
454 david.dillard 1.31 {
|
455 chuck 1.20 //
456 // Graceful shutdown of the listener service
457 //
458
459 // Block incoming export requests and unbind the port
460 _svc->stopClientConnection();
|
461 chuck 1.23
462 // Wait until pending export requests in the server are done.
|
463 chuck 1.24 waitForPendingRequests(10);
|
464 david.dillard 1.31
|
465 chuck 1.20 // Shutdown the CIMListenerService
466 _svc->shutdown();
467
468 // Wait for the _listener_routine thread to exit.
469 // The thread could be delivering an export, so give it 3sec.
470 // Note that _listener_routine deletes the CIMListenerService,
471 // so no need to delete _svc.
472 try
473 {
|
474 david.dillard 1.31 _listener_sem->time_wait(3000);
|
475 chuck 1.20 }
|
476 david.dillard 1.34 catch (const TimeOut &)
|
477 chuck 1.20 {
478 // No need to do anything, the thread pool will be deleted below
479 // to cancel the _listener_routine thread if it is still running.
480 }
481
482 delete _listener_sem;
483 _listener_sem = NULL;
|
484 david.dillard 1.31
|
485 chuck 1.20 // Delete the thread pool. This cancels the listener thread if it is still
486 // running.
487 delete _thread_pool;
488 _thread_pool = NULL;
489
490 Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER,
491 Logger::INFORMATION,
492 "CIMListener stopped");
493 }
|
494 kumpf 1.1 }
495
|
496 tony 1.8 Boolean CIMListenerRep::isAlive()
|
497 kumpf 1.1 {
|
498 tony 1.8 return (_thread_pool!=NULL)?true:false;
499 }
|
500 kumpf 1.1
|
501 tony 1.8 Boolean CIMListenerRep::addConsumer(CIMIndicationConsumer* consumer)
502 {
503 return _dispatcher->addConsumer(consumer);
504 }
505 Boolean CIMListenerRep::removeConsumer(CIMIndicationConsumer* consumer)
506 {
507 return _dispatcher->removeConsumer(consumer);
508 }
|
509 kumpf 1.1
|
510 chuck 1.23 Boolean CIMListenerRep::waitForPendingRequests(Uint32 shutdownTimeout)
511 {
512 // Wait for 10 sec max
513 Uint32 reqCount;
514 Uint32 countDown = shutdownTimeout * 10;
515 for (; countDown > 0; countDown--)
516 {
517 reqCount = _svc->getOutstandingRequestCount();
518 if (reqCount > 0)
519 pegasus_sleep(100);
520 else
521 return true;
522 }
|
523 david.dillard 1.31
|
524 chuck 1.23 return false;
|
525 david.dillard 1.31 }
|
526 chuck 1.23
|
527 tony 1.8 /////////////////////////////////////////////////////////////////////////////
528 // CIMListener
529 /////////////////////////////////////////////////////////////////////////////
530 CIMListener::CIMListener(Uint32 portNumber, SSLContext* sslContext)
531 :_rep(new CIMListenerRep(portNumber,sslContext))
532 {
533 }
534 CIMListener::~CIMListener()
535 {
536 if(_rep!=NULL)
|
537 tony 1.9 delete static_cast<CIMListenerRep*>(_rep);
|
538 tony 1.8 _rep=NULL;
539 }
|
540 david.dillard 1.31
|
541 tony 1.8 Uint32 CIMListener::getPortNumber() const
542 {
543 return static_cast<CIMListenerRep*>(_rep)->getPortNumber();
|
544 kumpf 1.1 }
545
|
546 tony 1.8 SSLContext* CIMListener::getSSLContext() const
547 {
548 return static_cast<CIMListenerRep*>(_rep)->getSSLContext();
549 }
550 void CIMListener::setSSLContext(SSLContext* sslContext)
551 {
552 static_cast<CIMListenerRep*>(_rep)->setSSLContext(sslContext);
553 }
554 void CIMListener::start()
|
555 kumpf 1.1 {
|
556 tony 1.8 static_cast<CIMListenerRep*>(_rep)->start();
557 }
558 void CIMListener::stop()
559 {
560 static_cast<CIMListenerRep*>(_rep)->stop();
561 }
|
562 kumpf 1.1
|
563 tony 1.8 Boolean CIMListener::isAlive()
564 {
565 return static_cast<CIMListenerRep*>(_rep)->isAlive();
566 }
|
567 kumpf 1.1
|
568 tony 1.8 Boolean CIMListener::addConsumer(CIMIndicationConsumer* consumer)
569 {
570 return static_cast<CIMListenerRep*>(_rep)->addConsumer(consumer);
571 }
572 Boolean CIMListener::removeConsumer(CIMIndicationConsumer* consumer)
573 {
574 return static_cast<CIMListenerRep*>(_rep)->removeConsumer(consumer);
|
575 kumpf 1.1 }
576
577 PEGASUS_NAMESPACE_END
|