version 1.50, 2007/09/07 18:34:11
|
version 1.50.4.4, 2008/07/17 11:57:00
|
|
|
#include <Pegasus/Common/PegasusVersion.h> | #include <Pegasus/Common/PegasusVersion.h> |
| |
#include <Pegasus/Common/MessageLoader.h> | #include <Pegasus/Common/MessageLoader.h> |
|
#include <Pegasus/Config/ConfigManager.h> |
| |
#include <Pegasus/ProviderManager2/CMPI/CMPIProvider.h> | #include <Pegasus/ProviderManager2/CMPI/CMPIProvider.h> |
#include <Pegasus/ProviderManager2/CMPI/CMPIProviderModule.h> | #include <Pegasus/ProviderManager2/CMPI/CMPIProviderModule.h> |
|
|
PEGASUS_USING_STD; | PEGASUS_USING_STD; |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
#undef IDLE_LIMIT |
|
#define IDLE_LIMIT 50 |
|
|
|
/* Thread deletion specific */ | /* Thread deletion specific */ |
Semaphore CMPILocalProviderManager::_pollingSem(0); | Semaphore CMPILocalProviderManager::_pollingSem(0); |
AtomicInt CMPILocalProviderManager::_stopPolling(0); | AtomicInt CMPILocalProviderManager::_stopPolling(0); |
|
|
Mutex CMPILocalProviderManager::_reaperMutex; | Mutex CMPILocalProviderManager::_reaperMutex; |
| |
CMPILocalProviderManager::CMPILocalProviderManager (): | CMPILocalProviderManager::CMPILocalProviderManager (): |
_idle_timeout (IDLE_LIMIT) |
_idle_timeout (PEGASUS_PROVIDER_IDLE_TIMEOUT_SECONDS) |
{ | { |
PEG_METHOD_ENTER( | PEG_METHOD_ENTER( |
TRC_PROVIDERMANAGER, | TRC_PROVIDERMANAGER, |
|
|
String location = *(parms->location); | String location = *(parms->location); |
| |
CMPIProvider *pr = 0; | CMPIProvider *pr = 0; |
CMPIProvider::OpProviderHolder * ph = |
OpProviderHolder * ph = |
reinterpret_cast < CMPIProvider::OpProviderHolder * >(ret); |
reinterpret_cast < OpProviderHolder * >(ret); |
| |
pr = _lookupProvider (providerName); | pr = _lookupProvider (providerName); |
| |
|
|
UNLOAD_PROVIDER"); | UNLOAD_PROVIDER"); |
CMPIProvider *pr = 0; | CMPIProvider *pr = 0; |
pr = _lookupProvider (*(parms->providerName)); | pr = _lookupProvider (*(parms->providerName)); |
|
|
|
// The provider table must be locked before unloading. |
|
AutoMutex lock (_providerTableMutex); |
if ((pr->getStatus () == CMPIProvider::INITIALIZED)) | if ((pr->getStatus () == CMPIProvider::INITIALIZED)) |
{ | { |
|
|
PEG_TRACE_STRING( | PEG_TRACE_STRING( |
TRC_PROVIDERMANAGER, | TRC_PROVIDERMANAGER, |
Tracer::LEVEL4, | Tracer::LEVEL4, |
"Unloading CMPIProvider: " + pr->getName()); | "Unloading CMPIProvider: " + pr->getName()); |
|
|
AutoMutex lock (_providerTableMutex); |
|
// The provider table must be locked before unloading. |
|
_providers.remove (pr->_name); |
|
_unloadProvider (pr); | _unloadProvider (pr); |
|
} |
|
if (pr->getStatus () == CMPIProvider::UNINITIALIZED) |
|
{ |
|
_providers.remove (pr->getNameWithType()); |
delete pr; | delete pr; |
|
|
} | } |
else | else |
{ | { |
// No need to have a memory leak. |
// Provider could not be unloaded due to pending operations. |
_providers.remove(pr->_name); |
ccode = -1; |
delete pr; |
|
} | } |
break; | break; |
} | } |
|
|
CMPIProvider *provider = 0; | CMPIProvider *provider = 0; |
// Locked provider mutex. | // Locked provider mutex. |
AutoMutex lock (_providerTableMutex); | AutoMutex lock (_providerTableMutex); |
|
Array<CMPIProvider*> unloadPendingProviders; |
| |
PEG_TRACE(( | PEG_TRACE(( |
TRC_PROVIDERMANAGER, | TRC_PROVIDERMANAGER, |
|
|
else | else |
{ | { |
_unloadProvider (provider); | _unloadProvider (provider); |
|
if (provider->getStatus () == |
|
CMPIProvider::UNINITIALIZED) |
|
{ |
delete provider; | delete provider; |
} | } |
|
else |
|
{ |
|
unloadPendingProviders.append(provider); |
|
} |
|
} |
|
} |
|
|
|
if (unloadPendingProviders.size()) |
|
{ |
|
_terminateUnloadPendingProviders( |
|
unloadPendingProviders); |
} | } |
// All the providers are removed. Clear the hash-table | // All the providers are removed. Clear the hash-table |
_providers.clear (); | _providers.clear (); |
|
|
continue; | continue; |
} | } |
| |
if (provider->_quantum == quantum) |
if (provider->getQuantum() == quantum) |
{ | { |
continue; | continue; |
} | } |
| |
provider->_quantum = quantum; |
provider->setQuantum(quantum); |
| |
if (provider->_current_operations.get ()) |
if (provider->getCurrentOperations()) |
{ | { |
PEG_TRACE_STRING( | PEG_TRACE_STRING( |
TRC_PROVIDERMANAGER, | TRC_PROVIDERMANAGER, |
|
|
{ | { |
// lock the provider mutex | // lock the provider mutex |
| |
AutoMutex pr_lock (provider->_statusMutex); |
AutoMutex pr_lock (provider->getStatusMutex()); |
| |
if (provider->tryTerminate () == false) | if (provider->tryTerminate () == false) |
{ | { |
|
|
continue; | continue; |
} | } |
| |
PEGASUS_ASSERT (provider->_module != 0); |
PEGASUS_ASSERT (provider->getModule() != 0); |
| |
// unload provider module | // unload provider module |
provider->_module->unloadModule (); |
provider->getModule()->unloadModule (); |
Logger::put (Logger::STANDARD_LOG, | Logger::put (Logger::STANDARD_LOG, |
System::CIMSERVER, | System::CIMSERVER, |
Logger::TRACE, | Logger::TRACE, |
|
|
Tracer::LEVEL4, | Tracer::LEVEL4, |
"Destroying CMPIProvider's CIMOM Handle " | "Destroying CMPIProvider's CIMOM Handle " |
+ provider->getName()); | + provider->getName()); |
delete provider->_cimom_handle; |
delete provider->getCIMOMHandle(); |
| |
// set provider status to UNINITIALIZED | // set provider status to UNINITIALIZED |
provider->reset (); | provider->reset (); |
|
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
return(0); | return(0); |
} | } |
|
|
|
Boolean CMPILocalProviderManager::isProviderActive(const String &providerName) |
|
{ |
|
PEG_METHOD_ENTER( |
|
TRC_PROVIDERMANAGER, |
|
"CMPILocalProviderManager::isProviderActive()"); |
|
|
|
String lProviderName("L"); |
|
lProviderName.append(providerName); |
|
String rProviderName("R"); |
|
rProviderName.append(providerName); |
|
|
|
AutoMutex mtx(_providerTableMutex); |
|
Boolean active = _providers.contains(lProviderName) || |
|
_providers.contains(rProviderName); |
|
|
|
PEG_METHOD_EXIT(); |
|
|
|
return active; |
|
} |
|
|
/* | /* |
// Cleanup the thread and upon deletion of it, call the CMPIProvider' | // Cleanup the thread and upon deletion of it, call the CMPIProvider' |
// "threadDeleted". to not, all the CMPIProvider ' | // "threadDeleted". to not, all the CMPIProvider ' |
|
|
| |
} | } |
| |
CMPIProvider::OpProviderHolder CMPILocalProviderManager:: |
OpProviderHolder CMPILocalProviderManager:: |
getRemoteProvider (const String & location, const String & providerName) | getRemoteProvider (const String & location, const String & providerName) |
{ | { |
CMPIProvider::OpProviderHolder ph; |
OpProviderHolder ph; |
CTRL_STRINGS | CTRL_STRINGS |
strings; | strings; |
Sint32 | Sint32 |
|
|
return ph; | return ph; |
} | } |
| |
CMPIProvider::OpProviderHolder CMPILocalProviderManager:: |
OpProviderHolder CMPILocalProviderManager:: |
getProvider (const String & fileName, const String & providerName) | getProvider (const String & fileName, const String & providerName) |
{ | { |
CMPIProvider::OpProviderHolder ph; |
OpProviderHolder ph; |
CTRL_STRINGS strings; | CTRL_STRINGS strings; |
Sint32 ccode; | Sint32 ccode; |
| |
|
|
| |
} | } |
| |
void CMPILocalProviderManager::unloadProvider( |
Boolean CMPILocalProviderManager::unloadProvider( |
const String & fileName, | const String & fileName, |
const String & providerName) | const String & providerName) |
{ | { |
|
|
strings.fileName = &fileName; | strings.fileName = &fileName; |
strings.providerName = &lproviderName; | strings.providerName = &lproviderName; |
strings.location = &String::EMPTY; | strings.location = &String::EMPTY; |
_provider_ctrl (UNLOAD_PROVIDER, &strings, (void *) 0); |
|
|
int lproviderStatus = 0; |
|
int rproviderStatus = 0; |
|
lproviderStatus = _provider_ctrl (UNLOAD_PROVIDER, &strings, (void *) 0); |
| |
strings.providerName = &rproviderName; | strings.providerName = &rproviderName; |
| |
_provider_ctrl (UNLOAD_PROVIDER, &strings, (void *) 0); |
rproviderStatus = _provider_ctrl (UNLOAD_PROVIDER, &strings, (void *) 0); |
| |
PEG_METHOD_EXIT (); | PEG_METHOD_EXIT (); |
|
return lproviderStatus != -1 && rproviderStatus != -1; |
} | } |
| |
void CMPILocalProviderManager::shutdownAllProviders () | void CMPILocalProviderManager::shutdownAllProviders () |
|
|
String exceptionMsg = moduleFileName; | String exceptionMsg = moduleFileName; |
{ | { |
// lock the provider status mutex | // lock the provider status mutex |
AutoMutex lock (provider->_statusMutex); |
AutoMutex lock (provider->getStatusMutex()); |
| |
if (provider->_status == CMPIProvider::INITIALIZED) |
if (provider->getStatus() == CMPIProvider::INITIALIZED) |
{ | { |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
// Initialization is already complete | // Initialization is already complete |
|
|
// load the provider | // load the provider |
try | try |
{ | { |
base = module->load (provider->_name); |
base = module->load (provider->getNameWithType()); |
moduleLoaded = true; | moduleLoaded = true; |
} | } |
catch (const Exception &e) | catch (const Exception &e) |
|
|
| |
CIMOMHandle *cimomHandle = new CIMOMHandle (); | CIMOMHandle *cimomHandle = new CIMOMHandle (); |
provider->set (module, base, cimomHandle); | provider->set (module, base, cimomHandle); |
provider->_quantum = 0; |
provider->setQuantum(0); |
| |
try | try |
{ | { |
provider->initialize (*(provider->_cimom_handle)); |
provider->initialize (*(provider->getCIMOMHandle())); |
} | } |
catch (const Exception &e) | catch (const Exception &e) |
{ | { |
|
|
} | } |
| |
// delete the cimom handle | // delete the cimom handle |
delete provider->_cimom_handle; |
delete provider->getCIMOMHandle(); |
// set provider status to UNINITIALIZED | // set provider status to UNINITIALIZED |
provider->reset (); | provider->reset (); |
| |
AutoMutex lock (_providerTableMutex); | AutoMutex lock (_providerTableMutex); |
_providers.remove (provider->_name); |
_providers.remove (provider->getNameWithType()); |
delete provider; | delete provider; |
| |
PEG_METHOD_EXIT (); | PEG_METHOD_EXIT (); |
|
|
return(provider); | return(provider); |
} | } |
| |
|
/* |
|
This method is called when CMPIProviderManager receives |
|
CIMStopAllProvidersRequestMessage and |
|
CMPILocalProviderManager::_provider_ctrl() method could not unload the |
|
provider(s) because of pending requests with the provider. We give grace |
|
time of (shutdownTimeout - 1) seconds to the unload pending providers |
|
to unload gracefully before terminating them forcibly. Note that this |
|
happens only when provider is running out-of-process and communication |
|
with CIMServer falied because of pipe read/write failures. |
|
*/ |
|
void CMPILocalProviderManager::_terminateUnloadPendingProviders( |
|
Array<CMPIProvider*> &unloadPendingProviders) |
|
{ |
|
PEG_METHOD_ENTER( |
|
TRC_PROVIDERMANAGER, |
|
"CMPILocalProviderManager::_terminateUnloadPendingProviders()"); |
|
|
|
PEG_TRACE(( |
|
TRC_PROVIDERMANAGER, |
|
Tracer::LEVEL3, |
|
"Unloading %u unload-pending providers.", |
|
unloadPendingProviders.size())); |
|
|
|
String configTimeout = |
|
ConfigManager::getInstance()->getCurrentValue("shutdownTimeout"); |
|
|
|
Uint32 timeoutValue = |
|
strtol(configTimeout.getCString(), (char **)0, 10); |
| |
void CMPILocalProviderManager::_unloadProvider (CMPIProvider * provider) |
for (Uint32 waitTime = timeoutValue - 1; waitTime > 0; waitTime--) |
|
{ |
|
Boolean unloadPending = false; |
|
for (Uint32 j = 0, n = unloadPendingProviders.size(); j < n; ++j) |
|
{ |
|
if (unloadPendingProviders[j]->getStatus() == |
|
CMPIProvider::INITIALIZED) |
|
{ |
|
_unloadProvider(unloadPendingProviders[j]); |
|
if (unloadPendingProviders[j]->getStatus() |
|
== CMPIProvider::INITIALIZED) |
|
{ |
|
unloadPending = true; |
|
} |
|
} |
|
} |
|
if (!unloadPending) |
|
{ |
|
break; |
|
} |
|
Threads::sleep(1000); |
|
} |
|
|
|
for (Uint32 j = 0, n = unloadPendingProviders.size(); j < n; ++j) |
|
{ |
|
if (unloadPendingProviders[j]->getStatus() == |
|
CMPIProvider::INITIALIZED) |
|
{ |
|
// Force unload |
|
_unloadProvider(unloadPendingProviders[j], true); |
|
} |
|
if (unloadPendingProviders[j]->getStatus() == |
|
CMPIProvider::UNINITIALIZED) |
|
{ |
|
delete unloadPendingProviders[j]; |
|
} |
|
} |
|
|
|
PEG_METHOD_EXIT(); |
|
} |
|
|
|
void CMPILocalProviderManager::_unloadProvider ( |
|
CMPIProvider * provider, |
|
Boolean forceUnload) |
{ | { |
// | // |
// NOTE: It is the caller's responsibility to make sure that | // NOTE: It is the caller's responsibility to make sure that |
|
|
Tracer::LEVEL4, | Tracer::LEVEL4, |
"Unloading Provider " + provider->getName()); | "Unloading Provider " + provider->getName()); |
| |
if (provider->_current_operations.get ()) |
if (provider->getCurrentOperations() && !forceUnload) |
{ | { |
PEG_TRACE_STRING( | PEG_TRACE_STRING( |
TRC_PROVIDERMANAGER, | TRC_PROVIDERMANAGER, |
|
|
} | } |
else | else |
{ | { |
|
if (provider->getCurrentOperations()) |
|
{ |
|
PEG_TRACE_STRING( |
|
TRC_PROVIDERMANAGER, |
|
Tracer::LEVEL1, |
|
"Terminating Provider with pending operations " + |
|
provider->getName()); |
|
} |
|
else |
|
{ |
PEG_TRACE_STRING( | PEG_TRACE_STRING( |
TRC_PROVIDERMANAGER, | TRC_PROVIDERMANAGER, |
Tracer::LEVEL4, | Tracer::LEVEL4, |
"Terminating Provider " + provider->getName()); | "Terminating Provider " + provider->getName()); |
|
} |
| |
// lock the provider mutex | // lock the provider mutex |
AutoMutex pr_lock (provider->_statusMutex); |
AutoMutex pr_lock (provider->getStatusMutex()); |
| |
try | try |
{ | { |
|
|
provider->getName()); | provider->getName()); |
} | } |
| |
|
if (provider->getStatus() == CMPIProvider::UNINITIALIZED) |
|
{ |
|
// unload provider module |
|
PEGASUS_ASSERT (provider->getModule() != 0); |
|
provider->getModule()->unloadModule (); |
|
Logger::put ( |
|
Logger::STANDARD_LOG, |
|
System::CIMSERVER, |
|
Logger::TRACE, |
|
"CMPILocalProviderManager::_provider_crtl - " |
|
"Unload provider $0", |
|
provider->getName ()); |
|
|
// delete the cimom handle | // delete the cimom handle |
PEG_TRACE_STRING( | PEG_TRACE_STRING( |
TRC_PROVIDERMANAGER, | TRC_PROVIDERMANAGER, |
Tracer::LEVEL4, | Tracer::LEVEL4, |
"Destroying CMPIProvider's CIMOM Handle " + | "Destroying CMPIProvider's CIMOM Handle " + |
provider->getName()); | provider->getName()); |
|
delete provider->getCIMOMHandle(); |
delete provider->_cimom_handle; |
|
PEGASUS_ASSERT (provider->_module != 0); |
|
|
|
// unload provider module |
|
provider->_module->unloadModule (); |
|
Logger::put (Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE, |
|
"CMPILocalProviderManager::_provider_crtl - Unload provider $0", |
|
provider->getName ()); |
|
| |
// set provider status to UNINITIALIZED | // set provider status to UNINITIALIZED |
provider->reset (); | provider->reset (); |
|
|
// Do not delete the provider. The function calling this function | // Do not delete the provider. The function calling this function |
// takes care of that. | // takes care of that. |
} | } |
|
} |
| |
PEG_METHOD_EXIT (); | PEG_METHOD_EXIT (); |
} | } |