1 karl 1.33 //%2006////////////////////////////////////////////////////////////////////////
|
2 schuur 1.1 //
|
3 karl 1.12 // 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 karl 1.16 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.33 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 schuur 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.16 //
|
21 schuur 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 // Author: Chip Vincent (cvincent@us.ibm.com)
33 //
34 // Modified By: Yi Zhou, Hewlett-Packard Company(yi_zhou@hp.com)
35 // Mike Day IBM Corporation (mdday@us.ibm.com)
36 // Adrian Schuur, schuur@de.ibm.com
|
37 dj.gorey 1.6 // Dan Gorey, IBM djgorey@us.ibm.com
|
38 r.kieninger 1.15 // Robert Kieninger, IBM kieningr@de.ibm.com
|
39 schuur 1.1 //
40 //%/////////////////////////////////////////////////////////////////////////////
41
|
42 schuur 1.10 #include "CMPI_Version.h"
43
|
44 schuur 1.1 #include <Pegasus/Common/Constants.h>
45 #include <Pegasus/Common/Tracer.h>
46 #include <Pegasus/Common/PegasusVersion.h>
47
|
48 konrad.r 1.26 #include <Pegasus/Common/MessageLoader.h>
49
|
50 schuur 1.1 #include <Pegasus/ProviderManager2/CMPI/CMPIProvider.h>
51 #include <Pegasus/ProviderManager2/CMPI/CMPIProviderModule.h>
52 #include <Pegasus/ProviderManager2/ProviderManagerService.h>
53
|
54 konrad.r 1.30 #include <Pegasus/ProviderManager2/CMPI/CMPILocalProviderManager.h>
|
55 kumpf 1.9
|
56 schuur 1.3 PEGASUS_USING_STD;
|
57 schuur 1.1 PEGASUS_NAMESPACE_BEGIN
|
58 konrad.r 1.27 #define DDD(X) if (_cmpi_trace) X;
59
60 extern int _cmpi_trace;
61
|
62 schuur 1.8 #undef IDLE_LIMIT
63 #define IDLE_LIMIT 50
|
64 konrad.r 1.30
65 /* Thread deletion specific */
66 Semaphore CMPILocalProviderManager::_pollingSem(0);
67 AtomicInt CMPILocalProviderManager::_stopPolling(0);
68 Thread *CMPILocalProviderManager::_reaperThread = 0;
69 DQueue <CMPILocalProviderManager::cleanupThreadRecord> CMPILocalProviderManager::_finishedThreadList(true);
70 Mutex CMPILocalProviderManager::_reaperMutex(0);
71
|
72 konrad.r 1.24 CMPILocalProviderManager::CMPILocalProviderManager (void):
73 _idle_timeout (IDLE_LIMIT)
|
74 r.kieninger 1.14 {
|
75 schuur 1.1 }
76
|
77 konrad.r 1.24 CMPILocalProviderManager::~CMPILocalProviderManager (void)
|
78 r.kieninger 1.14 {
|
79 konrad.r 1.24 Uint32 ccode;
|
80 dj.gorey 1.6
|
81 konrad.r 1.24 _provider_ctrl (UNLOAD_ALL_PROVIDERS, this, &ccode);
82 // Since all of the providers are deleted we can delete the
83 // modules too.
84 for (ModuleTable::Iterator j = _modules.start (); j != 0; j++)
85 {
86 CMPIProviderModule *module = j.value ();
87 delete module;
88 }
|
89 konrad.r 1.30
90 if (_reaperThread)
91 {
92 AutoMutex lock(_reaperMutex);
93 _stopPolling++;
94 _pollingSem.signal();
95 // Wait until it finishes itself.
96 _reaperThread->join();
97 delete _reaperThread;
98 _reaperThread = 0;
99 }
100 PEGASUS_ASSERT(_finishedThreadList.size() == 0);
101
|
102 schuur 1.1 }
103
|
104 konrad.r 1.24 Sint32
105 CMPILocalProviderManager::_provider_ctrl (CTRL code, void *parm, void *ret)
|
106 r.kieninger 1.14 {
|
107 r.kieninger 1.13
|
108 konrad.r 1.24 static Uint32 quantum;
109 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER, "_provider_ctrl");
|
110 r.kieninger 1.13
|
111 konrad.r 1.24 Sint32 ccode = 0;
112 CTRL_STRINGS *parms = reinterpret_cast < CTRL_STRINGS * >(parm);
|
113 r.kieninger 1.13
|
114 konrad.r 1.24 switch (code)
|
115 r.kieninger 1.14 {
116
117 case GET_PROVIDER:
|
118 konrad.r 1.24 {
|
119 r.kieninger 1.14
|
120 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
121 "_provider_ctrl::GET_PROVIDER");
|
122 r.kieninger 1.14
|
123 konrad.r 1.24 String providerName = *(parms->providerName);
124 String moduleFileName = *(parms->fileName);
125 String location = *(parms->location);
|
126 r.kieninger 1.14
|
127 konrad.r 1.24 CMPIProvider *pr = 0;
128 CMPIProvider::OpProviderHolder * ph =
129 reinterpret_cast < CMPIProvider::OpProviderHolder * >(ret);
|
130 r.kieninger 1.14
|
131 konrad.r 1.24 pr = _lookupProvider (providerName);
|
132 r.kieninger 1.15
|
133 konrad.r 1.24 if (pr->getStatus () != CMPIProvider::INITIALIZED)
134 {
135 pr->setLocation (location);
136 _initProvider (pr, moduleFileName);
|
137 r.kieninger 1.13
|
138 konrad.r 1.24 if (pr->getStatus () != CMPIProvider::INITIALIZED)
139 {
140 PEG_METHOD_EXIT ();
141 throw PEGASUS_CIM_EXCEPTION (CIM_ERR_FAILED,
142 "provider initialization failed");
143 }
144 }
|
145 r.kieninger 1.13
146
|
147 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
148 "Returning Provider" + providerName);
|
149 schuur 1.1
|
150 r.kieninger 1.15
|
151 konrad.r 1.24 ph->SetProvider (pr);
152 ph->GetProvider ().update_idle_timer ();
153 break;
154 }
|
155 r.kieninger 1.14
156 case UNLOAD_PROVIDER:
|
157 konrad.r 1.24 {
158
159 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
160 "_provider_ctrl::UNLOAD_PROVIDER");
|
161 konrad.r 1.30 CMPIProvider *pr = 0;
162 pr = _lookupProvider (*(parms->providerName));
|
163 konrad.r 1.24 if ((pr->getStatus () == CMPIProvider::INITIALIZED))
164 {
|
165 r.kieninger 1.14
|
166 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
|
167 konrad.r 1.26 "Unloading CMPIProvider: " + pr->getName());
|
168 r.kieninger 1.14
|
169 konrad.r 1.24 AutoMutex lock (_providerTableMutex);
170 // The provider table must be locked before unloading.
171 _providers.remove (pr->_name);
172 _unloadProvider (pr);
173 delete pr;
|
174 r.kieninger 1.14
|
175 konrad.r 1.24 }
|
176 konrad.r 1.25 else {
177 // No need to have a memory leak.
|
178 konrad.r 1.29 _providers.remove(pr->_name);
|
179 konrad.r 1.25 delete pr;
180 }
|
181 konrad.r 1.24 break;
182 }
|
183 schuur 1.1
|
184 r.kieninger 1.14 case LOOKUP_PROVIDER:
|
185 konrad.r 1.24 {
186
187 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
188 "_provider_ctrl::LOOKUP_PROVIDER");
|
189 schuur 1.1
|
190 konrad.r 1.24 AutoMutex lock (_providerTableMutex);
|
191 schuur 1.1
|
192 konrad.r 1.24 if (true == _providers.lookup (*(parms->providerName),
193 *(reinterpret_cast <
194 CMPIProvider * *>(ret))))
195 {
196 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
197 "Found CMPIProvider in cache: " +
198 *(parms->providerName));
199
200 (*(reinterpret_cast < CMPIProvider * *>(ret)))->
201 update_idle_timer ();
202 }
203 else
204 {
205
206 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
207 "Could not find CMPIProvider in cache: " +
208 *(parms->providerName));
209 ccode = -1;
210 }
|
211 dj.gorey 1.6
|
212 konrad.r 1.24 break;
213 }
|
214 schuur 1.1
|
215 konrad.r 1.24 case LOOKUP_MODULE:
216 {
|
217 schuur 1.1
|
218 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
219 "_provider_ctrl::LOOKUP_MODULE");
|
220 schuur 1.1
|
221 konrad.r 1.24 AutoMutex lock (_providerTableMutex);
|
222 schuur 1.1
|
223 konrad.r 1.24 if (false == _modules.lookup (*(parms->fileName),
224 *(reinterpret_cast <
225 CMPIProviderModule * *>(ret))))
226 {
227 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
228 "Could not find CMPIProvider Module in cache: "
229 + *(parms->fileName));
230 ccode = -1;
231 }
|
232 schuur 1.1
|
233 konrad.r 1.24 break;
234 }
|
235 schuur 1.1
|
236 konrad.r 1.24 case INSERT_PROVIDER:
237 {
|
238 r.kieninger 1.14
|
239 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
240 "_provider_ctrl::INSERT_PROVIDER");
|
241 schuur 1.1
|
242 konrad.r 1.24 AutoMutex lock (_providerTableMutex);
|
243 konrad.r 1.26
|
244 konrad.r 1.24 if (false == _providers.insert (*(parms->providerName),
245 *reinterpret_cast <
246 CMPIProvider * *>(parm)))
247 ccode = -1;
248 break;
249 }
250 case INSERT_MODULE:
251 {
252 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
253 "_provider_ctrl::INSERT_MODULE");
254 AutoMutex lock (_providerTableMutex);
255 if (false == _modules.insert (*(parms->fileName),
256 *reinterpret_cast <
257 CMPIProviderModule * *>(parm)))
258 ccode = -1;
259 break;
260 }
|
261 schuur 1.1
|
262 konrad.r 1.24 case UNLOAD_ALL_PROVIDERS:
263 {
264 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
265 "_provider_ctrl::UNLOAD_ALL_PROVIDERS");
266 CMPILocalProviderManager *myself =
267 reinterpret_cast < CMPILocalProviderManager * >(parm);
268 CMPIProvider *provider = 0;
269 // Locked provider mutex.
270 AutoMutex lock (_providerTableMutex);
|
271 dj.gorey 1.6
|
272 konrad.r 1.24 Tracer::trace (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
273 "providers in cache = %d", myself->_providers.size ());
274 ProviderTable::Iterator i = myself->_providers.start ();
275 try
276 {
277 for (; i != 0; i++)
278 {
|
279 r.kieninger 1.15
|
280 konrad.r 1.24 provider = i.value ();
281 PEGASUS_ASSERT (provider != 0);
282 if (provider->getStatus () == CMPIProvider::UNINITIALIZED)
283 {
284 // Delete the skeleton.
|
285 konrad.r 1.30 delete provider;
|
286 konrad.r 1.24 continue;
287 }
288 else
289 {
290 _unloadProvider (provider);
291 delete provider;
292 }
293 }
294 // All the providers are removed. Clear the hash-table
295 _providers.clear ();
|
296 r.kieninger 1.14 }
|
297 konrad.r 1.24 catch (...)
|
298 r.kieninger 1.14 {
|
299 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
300 "Unexpected Exception in UNLOAD_ALL_PROVIDERS.");
|
301 r.kieninger 1.14 }
|
302 konrad.r 1.24 break;
303 }
304 case UNLOAD_IDLE_PROVIDERS:
305 {
306 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
307 "_provider_ctrl::UNLOAD_IDLE_PROVIDERS");
308 AutoMutex lock (_providerTableMutex);
309
310 quantum++;
311 CMPILocalProviderManager *myself =
312 reinterpret_cast < CMPILocalProviderManager * >(parm);
|
313 kumpf 1.32 CMPIProvider *provider = 0;
|
314 konrad.r 1.24 Uint32 numProviders = myself->_providers.size ();
315
316 if (numProviders)
317 {
318 // Rather than removing the provider immediately while
319 // iterating through the list we remember all candidates
320 // for unload in a simple array.
321 CMPIProvider **unloadProviderArray =
322 new CMPIProvider *[numProviders];
323 Uint32 upaIndex = 0;
|
324 r.kieninger 1.15
|
325 r.kieninger 1.14 try
326 {
|
327 konrad.r 1.24 struct timeval now;
328 gettimeofday (&now, NULL);
329 ProviderTable::Iterator i = myself->_providers.start ();
330
331 for (; i != 0; i++)
|
332 r.kieninger 1.14 {
|
333 konrad.r 1.24 provider = i.value ();
334 PEGASUS_ASSERT (provider != 0);
335
336 if (provider->getStatus () == CMPIProvider::UNINITIALIZED)
|
337 r.kieninger 1.14 {
|
338 konrad.r 1.24 continue;
|
339 r.kieninger 1.14 }
|
340 konrad.r 1.24
341 if (provider->_quantum == quantum)
|
342 r.kieninger 1.14 {
|
343 konrad.r 1.24 continue;
|
344 r.kieninger 1.14 }
|
345 r.kieninger 1.15
|
346 konrad.r 1.24 provider->_quantum = quantum;
347
|
348 mike 1.31 if (provider->_current_operations.get ())
|
349 konrad.r 1.24 {
350 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
351 "CMPIProvider has pending operations: "
352 + provider->getName ());
|
353 r.kieninger 1.14
|
354 konrad.r 1.24 continue;
|
355 r.kieninger 1.15 }
|
356 r.kieninger 1.14
|
357 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
358 "Checking timeout data for CMPIProvider: "
359 + provider->getName ());
360 struct timeval timeout = { 0, 0 };
361 provider->get_idle_timer (&timeout);
362
363 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
364 " provider->unload_ok() returns: " +
365 provider->unload_ok ()? "true" : "false");
366
367 if (provider->unload_ok () == true &&
368 (now.tv_sec - timeout.tv_sec) >
369 ((Sint32) myself->_idle_timeout))
370 {
371 // Remember this provider to be unloaded
372 unloadProviderArray[upaIndex] = provider;
373 upaIndex++;
|
374 r.kieninger 1.14 }
|
375 konrad.r 1.24 //else cout<<"--- NOT unloaded: "+ provider->getName()<<endl;
|
376 r.kieninger 1.14 }
|
377 konrad.r 1.24
378 // Now finally we unload all providers that we identified as
379 // candidates above.
380 for (Uint32 index = 0; index < upaIndex; index++)
381 {
382 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
383 "Now trying to unload CMPIProvider " +
384 provider->getName ());
385 CMPIProvider *provider = unloadProviderArray[index];
386
387 // lock the provider mutex
388
389 AutoMutex pr_lock (provider->_statusMutex);
390
391 if (provider->tryTerminate () == false)
392 {
393 // provider not unloaded -- we are respecting this!
394 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
395 "Provider refused to unload: " +
|
396 konrad.r 1.26 unloadProviderArray[index]->getName());
|
397 konrad.r 1.24 continue;
398 }
399
|
400 mark.hamzy 1.28 // delete from _provider table
401 if (!_providers.remove (provider->_name))
402 {
403 PEGASUS_ASSERT (0);
404 }
405
|
406 konrad.r 1.24 // delete the cimom handle
407 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
408 "Destroying CMPIProvider's CIMOM Handle "
|
409 konrad.r 1.26 + provider->getName());
|
410 konrad.r 1.24 delete provider->_cimom_handle;
411
412 PEGASUS_ASSERT (provider->_module != 0);
413
414 // unload provider module
415 provider->_module->unloadModule ();
416 Logger::put (Logger::STANDARD_LOG, System::CIMSERVER,
417 Logger::TRACE,
418 "CMPILocalProviderManager::_provider_crtl - Unload provider $0",
419 provider->getName ());
420
421 // set provider status to UNINITIALIZED
422 provider->reset ();
423
424 delete provider;
|
425 r.kieninger 1.14 }
|
426 konrad.r 1.24 }
427 catch (...)
428 {
429 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
430 "Unexpected Exception in UNLOAD_IDLE_PROVIDERS.");
431 }
|
432 r.kieninger 1.15 delete unloadProviderArray;
|
433 konrad.r 1.24 } // if there are any providers
434 break;
435 }
|
436 r.kieninger 1.14
437 default:
|
438 konrad.r 1.24 ccode = -1;
439 break;
|
440 r.kieninger 1.14 }
|
441 konrad.r 1.24 PEG_METHOD_EXIT ();
442 return (ccode);
|
443 schuur 1.1 }
444
|
445 konrad.r 1.30
446
447 /*
448 * The reaper function polls out the threads from the global list (_finishedThreadList),
449 * joins them deletes them, and removes them from the CMPIProvider specific list.
450 */
451 PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL CMPILocalProviderManager::_reaper(void *parm)
452 {
453 Thread *myself = reinterpret_cast<Thread *>(parm);
454 do {
455 _pollingSem.wait();
456 // All of the threads are finished working. We just need to reap 'em
457 cleanupThreadRecord *rec = 0;
458
459 while (_finishedThreadList.size() >0 )
460 {
461 // Pull of the the threads from the global list.
462 rec = _finishedThreadList.remove_first();
463 DDD(cerr << "Reaping the thread " << rec->thread << " from " << rec->provider->getName() << endl);
464 rec->thread->join();
|
465 dave.sudlik 1.34 // remove the thread for the CMPIProvider, ...
466 rec->provider->threadDelete(rec->thread);
467 // ... and then delete the thread.
|
468 konrad.r 1.30 delete rec->thread;
469 delete rec;
470 }
471 }
|
472 mike 1.31 while (_stopPolling.get() == 0);
|
473 konrad.r 1.30 myself->exit_self( (PEGASUS_THREAD_RETURN) 0);
474 return (0);
475 }
476 /*
477 // Cleanup the thread and upon deletion of it, call the CMPIProvider' "threadDeleted".
478 // to not, all the CMPIProvider '
479 // Note that this function is called from the thread that finished with
480 // running the providers function, and returns immediately while scheduling the
481 // a cleanup procedure. If you want to wait until the thread is truly deleted,
482 // call 'waitUntilThreadsDone' - but DO NOT do it in the the thread that
483 // the Thread owns - you will wait forever.
484 //
485 // @argument t Thread that is not NULL and finished with running the provider function.
486 // @argument p CMPIProvider in which the 't' Thread was running.
487 */
488 void
489 CMPILocalProviderManager::cleanupThread(Thread *t, CMPIProvider *p)
490 {
491 PEGASUS_ASSERT( t != 0 && p != 0 );
492
493 PEGASUS_ASSERT ( p->isThreadOwner(t) );
494 konrad.r 1.30 // The mutex guards against a race condition for _reaperThread creation.
495 AutoMutex lock(_reaperMutex);
496
497 // Put the Thread and the CMPIProvider on the global list.
498 cleanupThreadRecord *record = new cleanupThreadRecord(t, p);
499 _finishedThreadList.insert_last (record);
500
501 if (_reaperThread == 0)
502 {
503 _reaperThread = new Thread(_reaper, NULL, false);
504 ThreadStatus rtn = PEGASUS_THREAD_OK;
505 while ( (rtn = _reaperThread->run()) != PEGASUS_THREAD_OK)
506 {
507 if (rtn == PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
508 pegasus_yield();
509 else
510 {
511 PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2, \
512 "Could not allocate thread to take care of deleting user threads. ");
513 delete _reaperThread; _reaperThread = 0;
514 return;
515 konrad.r 1.30 }
516 }
517 }/*
518 Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2, \
519 "Cleaning up provider thread (%p) from provider %s.",
520 t, (const char *)p->getName().getCString());*/
521 // Wake up the reaper.
522 _pollingSem.signal();
523
524 }
525
|
526 konrad.r 1.24 CMPIProvider::OpProviderHolder CMPILocalProviderManager::
527 getRemoteProvider (const String & location, const String & providerName)
528 {
529 CMPIProvider::OpProviderHolder ph;
530 CTRL_STRINGS
531 strings;
532 Sint32
533 ccode;
534 const String
535 proxy ("CMPIRProxyProvider");
536
537 String
538 rproviderName ("R");
539 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER,
540 "ProvidertManager::getRemoteProvider");
541
542 rproviderName.append (providerName);
543
544 strings.fileName = &proxy;
545 strings.providerName = &rproviderName;
546 strings.location = &location;
547 konrad.r 1.24
548 try
549 {
550 ccode = _provider_ctrl (GET_PROVIDER, &strings, &ph);
551 }
552 catch (const Exception & e)
553 {
|
554 konrad.r 1.27 DDD(cerr << "--- loading proxy: " << e.getMessage () << endl);
|
555 konrad.r 1.24 PEG_METHOD_EXIT ();
556 throw;
557 }
558 catch (...)
559 {
560 PEG_METHOD_EXIT ();
561 throw;
562 } CMPIProvider & prov = ph.GetProvider ();
|
563 schuur 1.10
|
564 konrad.r 1.24 PEG_METHOD_EXIT ();
565 return (ph);
|
566 schuur 1.1
567 }
568
|
569 konrad.r 1.24 CMPIProvider::OpProviderHolder CMPILocalProviderManager::
570 getProvider (const String & fileName, const String & providerName)
|
571 r.kieninger 1.14 {
|
572 konrad.r 1.24 CMPIProvider::OpProviderHolder ph;
573 CTRL_STRINGS
574 strings;
575 Sint32
576 ccode;
|
577 r.kieninger 1.15
|
578 konrad.r 1.24 String
579 lproviderName ("L");
580 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER, "ProviderManager::getProvider");
|
581 konrad.r 1.26 if (fileName.size() == 0)
582 {
583 throw Exception(MessageLoaderParms("ProviderManager.CMPI.CMPILocalProviderManager.CANNOT_FIND_LIBRARY",
584 "Provider library $0 was not found.",
585 fileName));
|
586 r.kieninger 1.15
|
587 konrad.r 1.26 }
|
588 konrad.r 1.24 lproviderName.append (providerName);
589 strings.fileName = &fileName;
590 strings.providerName = &lproviderName;
591 strings.location = &String::EMPTY;
|
592 r.kieninger 1.14
|
593 konrad.r 1.24 try
594 {
595 ccode = _provider_ctrl (GET_PROVIDER, &strings, &ph);
596 }
597 catch (const Exception & e)
598 {
|
599 konrad.r 1.27 DDD(cerr << "--- loading proxy: " << e.getMessage () << endl);
|
600 konrad.r 1.24 PEG_METHOD_EXIT ();
601 throw;
602 }
603 catch (...)
604 {
605 PEG_METHOD_EXIT ();
606 throw;
607 }
|
608 schuur 1.1
609
|
610 konrad.r 1.24 PEG_METHOD_EXIT ();
611 return (ph);
|
612 schuur 1.1
613 }
614
|
615 konrad.r 1.24 void
616 CMPILocalProviderManager::unloadProvider (const String & fileName,
617 const String & providerName)
|
618 r.kieninger 1.14 {
|
619 konrad.r 1.24 CTRL_STRINGS strings;
620 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER, "ProviderManager::unloadProvider");
|
621 konrad.r 1.25
622 String lproviderName ("L");
623 String rproviderName ("R");
624 lproviderName.append (providerName);
625 rproviderName.append (providerName);
626
|
627 konrad.r 1.24 strings.fileName = &fileName;
|
628 konrad.r 1.25 strings.providerName = &lproviderName;
629 strings.location = &String::EMPTY;
|
630 konrad.r 1.24 _provider_ctrl (UNLOAD_PROVIDER, &strings, (void *) 0);
|
631 konrad.r 1.25
632 strings.providerName = &rproviderName;
633
634 _provider_ctrl (UNLOAD_PROVIDER, &strings, (void *) 0);
635
|
636 konrad.r 1.24 PEG_METHOD_EXIT ();
|
637 r.kieninger 1.14 }
638
|
639 konrad.r 1.24 void
640 CMPILocalProviderManager::shutdownAllProviders (void)
|
641 r.kieninger 1.14 {
642
|
643 konrad.r 1.24 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER,
644 "ProviderManager::shutdownAllProviders");
645 _provider_ctrl (UNLOAD_ALL_PROVIDERS, (void *) this, (void *) 0);
646 PEG_METHOD_EXIT ();
|
647 r.kieninger 1.13 }
648
649
|
650 konrad.r 1.24 Boolean
651 CMPILocalProviderManager::hasActiveProviders ()
|
652 r.kieninger 1.14 {
|
653 konrad.r 1.24 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER,
654 "ProviderManager::hasActiveProviders");
|
655 r.kieninger 1.14
|
656 konrad.r 1.24 try
657 {
658 AutoMutex lock (_providerTableMutex);
659 Tracer::trace (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
660 "providers in _providers table = %d", _providers.size ());
|
661 r.kieninger 1.14
|
662 konrad.r 1.24 // Iterate through the _providers table looking for an active provider
663 for (ProviderTable::Iterator i = _providers.start (); i != 0; i++)
664 {
665 if (i.value ()->getStatus () == CMPIProvider::INITIALIZED)
666 {
667 PEG_METHOD_EXIT ();
668 return true;
669 }
670 }
671 }
672 catch (...)
673 {
674 // Unexpected exception; do not assume that no providers are loaded
675 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
676 "Unexpected Exception in hasActiveProviders.");
677 PEG_METHOD_EXIT ();
678 return true;
679 }
|
680 r.kieninger 1.14
|
681 konrad.r 1.24 // No active providers were found in the _providers table
682 PEG_METHOD_EXIT ();
683 return false;
|
684 r.kieninger 1.14 }
685
|
686 konrad.r 1.24 void
687 CMPILocalProviderManager::unloadIdleProviders (void)
|
688 r.kieninger 1.14 {
|
689 konrad.r 1.24 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER,
690 "ProviderManager::unloadIdleProviders");
|
691 r.kieninger 1.14
|
692 konrad.r 1.24 static struct timeval first = { 0, 0 }, now, last =
693 {
694 0, 0};
|
695 r.kieninger 1.15
|
696 konrad.r 1.24 if (first.tv_sec == 0)
|
697 r.kieninger 1.14 {
|
698 konrad.r 1.24 gettimeofday (&first, NULL);
|
699 r.kieninger 1.14 }
|
700 konrad.r 1.24 gettimeofday (&now, NULL);
|
701 r.kieninger 1.14
|
702 konrad.r 1.24 if (((now.tv_sec - first.tv_sec) > IDLE_LIMIT) &&
703 ((now.tv_sec - last.tv_sec) > IDLE_LIMIT))
|
704 r.kieninger 1.14 {
|
705 konrad.r 1.24 gettimeofday (&last, NULL);
706 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
707 "Checking for Idle providers to unload.");
708 try
709 {
710 _provider_ctrl (UNLOAD_IDLE_PROVIDERS, this, (void *) 0);
711 }
712 catch (...)
713 {
714 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
715 "Caught unexpected exception from UNLOAD_IDLE_PROVIDERS.");
716 }
|
717 r.kieninger 1.14 }
|
718 konrad.r 1.24 PEG_METHOD_EXIT ();
|
719 schuur 1.1 }
720
|
721 konrad.r 1.24 Array <
722 CMPIProvider * >CMPILocalProviderManager::getIndicationProvidersToEnable ()
|
723 carolann.graves 1.17 {
|
724 konrad.r 1.24 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER,
725 "CMPILocalProviderManager::getIndicationProvidersToEnable");
|
726 carolann.graves 1.17
|
727 konrad.r 1.24 Array < CMPIProvider * >enableProviders;
|
728 carolann.graves 1.17
|
729 konrad.r 1.24 Tracer::trace (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
730 "Number of providers in _providers table = %d",
731 _providers.size ());
|
732 carolann.graves 1.17
|
733 konrad.r 1.24 try
734 {
735 AutoMutex
736 lock (_providerTableMutex);
|
737 carolann.graves 1.17
|
738 konrad.r 1.24 //
739 // Iterate through the _providers table
740 //
741 for (ProviderTable::Iterator i = _providers.start (); i != 0; i++)
742 {
|
743 carolann.graves 1.17 //
|
744 konrad.r 1.24 // Enable any indication provider with current subscriptions
|
745 carolann.graves 1.17 //
|
746 konrad.r 1.24 CMPIProvider *
747 provider = i.value ();
748 if (provider->testSubscriptions ())
749 {
750 enableProviders.append (provider);
751 }
752 }
753
754 }
755 catch (const CIMException & e)
756 {
757 PEG_TRACE_STRING (TRC_DISCARDED_DATA, Tracer::LEVEL2,
758 "CIMException: " + e.getMessage ());
759 }
760 catch (const Exception & e)
761 {
762 PEG_TRACE_STRING (TRC_DISCARDED_DATA, Tracer::LEVEL2,
763 "Exception: " + e.getMessage ());
764 }
765 catch (...)
766 {
767 konrad.r 1.24 PEG_TRACE_STRING (TRC_DISCARDED_DATA, Tracer::LEVEL2,
768 "Unexpected error in getIndicationProvidersToEnable");
769 }
770
771 Tracer::trace (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
772 "Number of indication providers to enable = %d",
773 enableProviders.size ());
774
775 PEG_METHOD_EXIT ();
776 return enableProviders;
777 }
778
779 CMPIProvider *
780 CMPILocalProviderManager::_initProvider (CMPIProvider * provider,
781 const String & moduleFileName)
782 {
783 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER, "_initProvider");
|
784 carolann.graves 1.17
|
785 konrad.r 1.24 CMPIProviderModule *module = 0;
786 ProviderVector base;
|
787 carolann.graves 1.17
|
788 konrad.r 1.24 {
789 // lock the providerTable mutex
790 AutoMutex lock (_providerTableMutex);
|
791 carolann.graves 1.17
|
792 konrad.r 1.24 // lookup provider module
793 module = _lookupModule (moduleFileName);
794 } // unlock the providerTable mutex
|
795 schuur 1.1
|
796 konrad.r 1.24 Boolean deleteProvider = false;
|
797 konrad.r 1.26 String exceptionMsg = moduleFileName;
|
798 konrad.r 1.24 {
799 // lock the provider status mutex
800 AutoMutex lock (provider->_statusMutex);
|
801 r.kieninger 1.14
|
802 konrad.r 1.24 if (provider->_status == CMPIProvider::INITIALIZED)
803 {
804 // Initialization is already complete
805 return provider;
806 }
|
807 r.kieninger 1.14
|
808 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
809 "Loading/Linking Provider Module " + moduleFileName);
|
810 kumpf 1.18
|
811 konrad.r 1.24 // load the provider
812 try
813 {
814 base = module->load (provider->_name);
815 }
|
816 konrad.r 1.26 catch (const Exception &e)
817 {
818 exceptionMsg = e.getMessage();
819 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
820 "Exception caught Loading/Linking Provider Module " +
821 moduleFileName+ " error is: "+exceptionMsg);
822 deleteProvider =true;
823 }
|
824 konrad.r 1.24 catch (...)
|
825 kumpf 1.18 {
|
826 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
|
827 konrad.r 1.26 "Unknown exception caught Loading/Linking Provider Module " +
|
828 konrad.r 1.24 moduleFileName);
|
829 konrad.r 1.26 exceptionMsg = moduleFileName;
|
830 konrad.r 1.24 }
|
831 konrad.r 1.26 if (!deleteProvider)
832 {
833 // initialize the provider
834 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
835 "Initializing Provider " + provider->getName());
|
836 r.kieninger 1.14
|
837 konrad.r 1.26 CIMOMHandle *cimomHandle = new CIMOMHandle ();
838 provider->set (module, base, cimomHandle);
839 provider->_quantum = 0;
|
840 konrad.r 1.24
|
841 konrad.r 1.26 try
842 {
843 provider->initialize (*(provider->_cimom_handle));
844 }
845 catch (const Exception &e)
846 {
847 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
848 "Problem initializing: " + e.getMessage());
849 deleteProvider = true;
850 exceptionMsg = e.getMessage();
851 }
852 catch (...)
853 {
854 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL2,
855 "Unknown problem initializing " + provider->getName());
856 deleteProvider = true;
857 exceptionMsg = provider->getName();
858 }
859 } // unlock the provider status mutex
860 }
861 /* We wait until this moment to delete the provider b/c we need
862 konrad.r 1.26 be outside the scope for the AutoMutex for the provider. */
863 if (deleteProvider)
864 {
|
865 konrad.r 1.24 // delete the cimom handle
866 delete provider->_cimom_handle;
867 // set provider status to UNINITIALIZED
868 provider->reset ();
869 // unload provider module
870 module->unloadModule ();
|
871 r.kieninger 1.14
|
872 konrad.r 1.24 AutoMutex lock (_providerTableMutex);
|
873 konrad.r 1.26 _providers.remove (provider->_name);
|
874 konrad.r 1.24 delete provider;
|
875 konrad.r 1.26
876 PEG_METHOD_EXIT ();
877 throw Exception(exceptionMsg);
|
878 r.kieninger 1.14 }
879
|
880 konrad.r 1.24 PEG_METHOD_EXIT ();
881 return (provider);
|
882 r.kieninger 1.14 }
883
884
|
885 konrad.r 1.24 void
886 CMPILocalProviderManager::_unloadProvider (CMPIProvider * provider)
|
887 r.kieninger 1.14 {
|
888 konrad.r 1.24 //
889 // NOTE: It is the caller's responsibility to make sure that
890 // the ProviderTable mutex is locked before calling this method.
891 //
892 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER, "_unloadProvider");
|
893 r.kieninger 1.14
|
894 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
|
895 konrad.r 1.26 "Unloading Provider " + provider->getName());
|
896 r.kieninger 1.14
|
897 mike 1.31 if (provider->_current_operations.get ())
|
898 r.kieninger 1.14 {
|
899 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
900 "Provider cannot be unloaded due to pending operations: "
|
901 konrad.r 1.26 + provider->getName());
|
902 r.kieninger 1.14 }
|
903 konrad.r 1.24 else
|
904 r.kieninger 1.14 {
|
905 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
|
906 konrad.r 1.26 "Terminating Provider " + provider->getName());
|
907 konrad.r 1.24
|
908 r.kieninger 1.14
|
909 konrad.r 1.24 // lock the provider mutex
910 AutoMutex pr_lock (provider->_statusMutex);
|
911 r.kieninger 1.14
|
912 konrad.r 1.24 try
913 {
914 provider->terminate ();
915 }
916 catch (...)
917 {
918 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL3,
919 "Error occured terminating CMPI provider " +
|
920 konrad.r 1.26 provider->getName());
|
921 konrad.r 1.24 }
|
922 r.kieninger 1.14
|
923 konrad.r 1.24 // delete the cimom handle
924 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
925 "Destroying CMPIProvider's CIMOM Handle " +
|
926 konrad.r 1.26 provider->getName());
|
927 r.kieninger 1.14
|
928 konrad.r 1.24 delete provider->_cimom_handle;
929 PEGASUS_ASSERT (provider->_module != 0);
|
930 r.kieninger 1.14
|
931 konrad.r 1.24 // unload provider module
932 provider->_module->unloadModule ();
933 Logger::put (Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
934 "CMPILocalProviderManager::_provider_crtl - Unload provider $0",
935 provider->getName ());
|
936 r.kieninger 1.14
|
937 konrad.r 1.24 // set provider status to UNINITIALIZED
938 provider->reset ();
|
939 r.kieninger 1.14
|
940 konrad.r 1.24 // Do not delete the provider. The function calling this function
941 // takes care of that.
|
942 r.kieninger 1.14 }
|
943 r.kieninger 1.13
|
944 konrad.r 1.24 PEG_METHOD_EXIT ();
|
945 dj.gorey 1.6 }
946
|
947 konrad.r 1.24 CMPIProvider *
948 CMPILocalProviderManager::_lookupProvider (const String & providerName)
|
949 r.kieninger 1.14 {
|
950 konrad.r 1.24 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER, "_lookupProvider");
951 // lock the providerTable mutex
952 AutoMutex lock (_providerTableMutex);
953 // look up provider in cache
954 CMPIProvider *pr = 0;
955 if (true == _providers.lookup (providerName, pr))
|
956 r.kieninger 1.14 {
|
957 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
958 "Found Provider " + providerName +
959 " in CMPI Provider Manager Cache");
|
960 r.kieninger 1.14 }
|
961 konrad.r 1.24 else
|
962 r.kieninger 1.14 {
|
963 konrad.r 1.24 // create provider
964 pr = new CMPIProvider (providerName, 0, 0);
965 // insert provider in provider table
966 _providers.insert (providerName, pr);
|
967 r.kieninger 1.14
|
968 konrad.r 1.24 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
969 "Created provider " + pr->getName ());
|
970 r.kieninger 1.14 }
|
971 dj.gorey 1.6
|
972 konrad.r 1.24 PEG_METHOD_EXIT ();
973 return (pr);
|
974 dj.gorey 1.6 }
975
976
|
977 konrad.r 1.24 CMPIProviderModule *
978 CMPILocalProviderManager::_lookupModule (const String & moduleFileName)
|
979 r.kieninger 1.14 {
|
980 konrad.r 1.24 PEG_METHOD_ENTER (TRC_PROVIDERMANAGER, "_lookupModule");
|
981 r.kieninger 1.14
|
982 konrad.r 1.24 // look up provider module in cache
983 CMPIProviderModule *module = 0;
|
984 r.kieninger 1.14
|
985 konrad.r 1.24 if (true == _modules.lookup (moduleFileName, module))
|
986 r.kieninger 1.14 {
|
987 konrad.r 1.24 // found provider module in cache
988 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
989 "Found Provider Module" + moduleFileName +
990 " in Provider Manager Cache");
|
991 dj.gorey 1.6
|
992 konrad.r 1.24 }
993 else
994 {
995 // provider module not found in cache, create provider module
996 PEG_TRACE_STRING (TRC_PROVIDERMANAGER, Tracer::LEVEL4,
997 "Creating CMPI Provider Module " + moduleFileName);
|
998 r.kieninger 1.14
|
999 konrad.r 1.24 module = new CMPIProviderModule (moduleFileName);
|
1000 r.kieninger 1.14
|
1001 konrad.r 1.24 // insert provider module in module table
1002 _modules.insert (moduleFileName, module);
|
1003 r.kieninger 1.14 }
|
1004 dj.gorey 1.6
|
1005 konrad.r 1.24 PEG_METHOD_EXIT ();
1006 return (module);
|
1007 schuur 1.1 }
1008
1009 PEGASUS_NAMESPACE_END
|