version 1.2, 2004/06/28 22:51:39
|
version 1.32, 2006/08/09 21:13:00
|
|
|
//%2003//////////////////////////////////////////////////////////////////////// |
//%2006//////////////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Development |
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development |
// Company, L. P., IBM Corp., The Open Group, Tivoli Systems. |
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. |
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.; | // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.; |
// IBM Corp.; EMC Corporation, The Open Group. | // IBM Corp.; EMC Corporation, The Open Group. |
|
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.; |
|
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. |
|
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; VERITAS Software Corporation; The Open Group. |
|
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; Symantec Corporation; The Open Group. |
// | // |
// Permission is hereby granted, free of charge, to any person obtaining a copy | // Permission is hereby granted, free of charge, to any person obtaining a copy |
// of this software and associated documentation files (the "Software"), to | // of this software and associated documentation files (the "Software"), to |
|
|
// Author: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) | // Author: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) |
// Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com) | // Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com) |
// | // |
// Modified By: |
// Modified By: Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com) |
|
// Carol Ann Krug Graves, Hewlett-Packard Company |
|
// (carolann_graves@hp.com) |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
|
#include <Pegasus/Common/Signal.h> |
#include <Pegasus/Common/Config.h> | #include <Pegasus/Common/Config.h> |
#include <Pegasus/Common/Constants.h> | #include <Pegasus/Common/Constants.h> |
#include <Pegasus/Common/AutoPtr.h> | #include <Pegasus/Common/AutoPtr.h> |
|
|
| |
#if defined (PEGASUS_OS_TYPE_WINDOWS) | #if defined (PEGASUS_OS_TYPE_WINDOWS) |
#include <windows.h> // For CreateProcess() | #include <windows.h> // For CreateProcess() |
#else |
#elif defined (PEGASUS_OS_OS400) |
# if defined (PEGASUS_OS_OS400) |
|
# include <unistd.cleinc> | # include <unistd.cleinc> |
|
#elif defined (PEGASUS_OS_VMS) |
|
# include <perror.h> |
|
# include <climsgdef.h> |
|
# include <stdio.h> |
|
# include <stdlib.h> |
|
# include <string.h> |
|
# include <processes.h> |
|
# include <unixio.h> |
# else | # else |
# include <unistd.h> // For fork(), exec(), and _exit() | # include <unistd.h> // For fork(), exec(), and _exit() |
# endif |
|
#include <errno.h> | #include <errno.h> |
|
# include <sys/types.h> |
|
# if defined(PEGASUS_HAS_SIGNALS) |
|
# include <sys/wait.h> |
|
# endif |
#endif | #endif |
| |
#include "OOPProviderManagerRouter.h" | #include "OOPProviderManagerRouter.h" |
|
|
{ | { |
public: | public: |
OutstandingRequestEntry( | OutstandingRequestEntry( |
String messageId_, |
String originalMessageId_, |
|
CIMRequestMessage* requestMessage_, |
CIMResponseMessage*& responseMessage_, | CIMResponseMessage*& responseMessage_, |
Semaphore* responseReady_) | Semaphore* responseReady_) |
: messageId(messageId_), |
: originalMessageId(originalMessageId_), |
|
requestMessage(requestMessage_), |
responseMessage(responseMessage_), | responseMessage(responseMessage_), |
responseReady(responseReady_) | responseReady(responseReady_) |
{ | { |
} | } |
| |
String messageId; |
/** |
|
A unique value is substituted as the request messageId attribute to |
|
allow responses to be definitively correllated with requests. |
|
The original messageId value is stored here to avoid a race condition |
|
between the processing of a response chunk and the resetting of the |
|
original messageId in the request message. |
|
*/ |
|
String originalMessageId; |
|
CIMRequestMessage* requestMessage; |
CIMResponseMessage*& responseMessage; | CIMResponseMessage*& responseMessage; |
Semaphore* responseReady; | Semaphore* responseReady; |
}; | }; |
|
|
public: | public: |
ProviderAgentContainer( | ProviderAgentContainer( |
const String & moduleName, | const String & moduleName, |
PEGASUS_INDICATION_CALLBACK indicationCallback); |
const String & userName, |
|
Uint16 userContext, |
|
PEGASUS_INDICATION_CALLBACK_T indicationCallback, |
|
PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback, |
|
PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T providerModuleFailCallback, |
|
Boolean subscriptionInitComplete); |
| |
~ProviderAgentContainer(); | ~ProviderAgentContainer(); |
| |
Boolean isInitialized(); | Boolean isInitialized(); |
| |
|
String getModuleName() const; |
|
|
CIMResponseMessage* processMessage(CIMRequestMessage* request); | CIMResponseMessage* processMessage(CIMRequestMessage* request); |
void unloadIdleProviders(); | void unloadIdleProviders(); |
| |
|
|
with an error result. | with an error result. |
| |
Note: The caller must lock the _agentMutex. | Note: The caller must lock the _agentMutex. |
|
|
|
@param cleanShutdown Indicates whether the provider agent process |
|
exited cleanly. A value of true indicates that responses have been |
|
sent for all requests that have been processed. A value of false |
|
indicates that one or more requests may have been partially processed. |
*/ | */ |
void _uninitialize(); |
void _uninitialize(Boolean cleanShutdown); |
|
|
|
/** |
|
Performs the processMessage work, but does not retry on a transient |
|
error. |
|
*/ |
|
CIMResponseMessage* _processMessage(CIMRequestMessage* request); |
| |
/** | /** |
Read and process response messages from the Provider Agent until | Read and process response messages from the Provider Agent until |
the connection is closed. | the connection is closed. |
*/ | */ |
void _processResponses(); | void _processResponses(); |
static PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL |
static ThreadReturnType PEGASUS_THREAD_CDECL |
_responseProcessor(void* arg); | _responseProcessor(void* arg); |
| |
// | // |
|
|
String _moduleName; | String _moduleName; |
| |
/** | /** |
|
The user context in which this Provider Agent operates. |
|
*/ |
|
String _userName; |
|
|
|
/** |
|
User Context setting of the provider module served by this Provider |
|
Agent. |
|
*/ |
|
Uint16 _userContext; |
|
|
|
/** |
Callback function to which all generated indications are sent for | Callback function to which all generated indications are sent for |
processing. | processing. |
*/ | */ |
PEGASUS_INDICATION_CALLBACK _indicationCallback; |
PEGASUS_INDICATION_CALLBACK_T _indicationCallback; |
|
|
|
/** |
|
Callback function to which response chunks are sent for processing. |
|
*/ |
|
PEGASUS_RESPONSE_CHUNK_CALLBACK_T _responseChunkCallback; |
|
|
|
/** |
|
Callback function to be called upon detection of failure of a |
|
provider module. |
|
*/ |
|
PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T _providerModuleFailCallback; |
| |
/** | /** |
Indicates whether the Provider Agent is active. | Indicates whether the Provider Agent is active. |
|
|
*/ | */ |
AutoPtr<AnonymousPipe> _pipeToAgent; | AutoPtr<AnonymousPipe> _pipeToAgent; |
| |
|
#if defined(PEGASUS_HAS_SIGNALS) |
|
/** |
|
Process ID of the active Provider Agent. |
|
*/ |
|
pid_t _pid; |
|
#endif |
|
|
/** | /** |
The _outstandingRequestTable holds an entry for each request that has | The _outstandingRequestTable holds an entry for each request that has |
been sent to this Provider Agent for which no response has been | been sent to this Provider Agent for which no response has been |
|
|
the last provider module instance sent. | the last provider module instance sent. |
*/ | */ |
CIMInstance _providerModuleCache; | CIMInstance _providerModuleCache; |
|
|
|
/** |
|
The number of Provider Agent processes that are currently initialized |
|
(active). |
|
*/ |
|
static Uint32 _numProviderProcesses; |
|
|
|
/** |
|
The _numProviderProcessesMutex must be locked whenever reading or |
|
updating the _numProviderProcesses count. |
|
*/ |
|
static Mutex _numProviderProcessesMutex; |
|
|
|
/** |
|
The maximum number of Provider Agent processes that may be initialized |
|
(active) at one time. |
|
*/ |
|
static Uint32 _maxProviderProcesses; |
|
|
|
/** |
|
A value indicating that a request message has not been processed. |
|
A CIMResponseMessage pointer with this value indicates that the |
|
corresponding CIMRequestMessage has not been processed. This is |
|
used to indicate that a provider agent exited without starting to |
|
process the request, and that the request should be retried. |
|
*/ |
|
static CIMResponseMessage* _REQUEST_NOT_PROCESSED; |
|
|
|
/** |
|
Indicates whether the Indication Service has completed initialization. |
|
|
|
For more information, please see the description of the |
|
ProviderManagerRouter::_subscriptionInitComplete member variable. |
|
*/ |
|
Boolean _subscriptionInitComplete; |
}; | }; |
| |
|
Uint32 ProviderAgentContainer::_numProviderProcesses = 0; |
|
Mutex ProviderAgentContainer::_numProviderProcessesMutex; |
|
Uint32 ProviderAgentContainer::_maxProviderProcesses = PEG_NOT_FOUND; |
|
|
|
// Set this to a value that no valid CIMResponseMessage* will have. |
|
CIMResponseMessage* ProviderAgentContainer::_REQUEST_NOT_PROCESSED = |
|
reinterpret_cast<CIMResponseMessage*>(&_REQUEST_NOT_PROCESSED); |
|
|
ProviderAgentContainer::ProviderAgentContainer( | ProviderAgentContainer::ProviderAgentContainer( |
const String & moduleName, | const String & moduleName, |
PEGASUS_INDICATION_CALLBACK indicationCallback) |
const String & userName, |
|
Uint16 userContext, |
|
PEGASUS_INDICATION_CALLBACK_T indicationCallback, |
|
PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback, |
|
PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T providerModuleFailCallback, |
|
Boolean subscriptionInitComplete) |
: _moduleName(moduleName), | : _moduleName(moduleName), |
|
_userName(userName), |
|
_userContext(userContext), |
_indicationCallback(indicationCallback), | _indicationCallback(indicationCallback), |
_isInitialized(false) |
_responseChunkCallback(responseChunkCallback), |
|
_providerModuleFailCallback(providerModuleFailCallback), |
|
_isInitialized(false), |
|
_subscriptionInitComplete(subscriptionInitComplete) |
{ | { |
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, | PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, |
"ProviderAgentContainer::ProviderAgentContainer"); | "ProviderAgentContainer::ProviderAgentContainer"); |
|
|
// Ensure the destructor does not throw an exception | // Ensure the destructor does not throw an exception |
try | try |
{ | { |
|
if (isInitialized()) |
|
{ |
// Stop the responseProcessor thread by closing its connection | // Stop the responseProcessor thread by closing its connection |
_pipeFromAgent->closeReadHandle(); | _pipeFromAgent->closeReadHandle(); |
| |
// Wait for the responseProcessor thread to exit | // Wait for the responseProcessor thread to exit |
while (isInitialized()) | while (isInitialized()) |
{ | { |
pegasus_yield(); |
Threads::yield(); |
|
} |
} | } |
} | } |
catch (...) | catch (...) |
|
|
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, | PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, |
"ProviderAgentContainer::_startAgentProcess"); | "ProviderAgentContainer::_startAgentProcess"); |
| |
|
// |
|
// Serialize the starting of agent processes. If two agent processes are |
|
// started at the same time, they may get copies of each other's pipe |
|
// descriptors. If this happens, the cimserver will not get a pipe read |
|
// error when one of the agent processes exits, because the pipe will |
|
// still be writable by the other process. This locking control needs to |
|
// cover the period from where the pipes are created to where the agent |
|
// ends of the pipes are closed by the cimserver. |
|
// |
|
static Mutex agentStartupMutex; |
|
AutoMutex lock(agentStartupMutex); |
|
|
AutoPtr<AnonymousPipe> pipeFromAgent(new AnonymousPipe()); | AutoPtr<AnonymousPipe> pipeFromAgent(new AnonymousPipe()); |
AutoPtr<AnonymousPipe> pipeToAgent(new AnonymousPipe()); | AutoPtr<AnonymousPipe> pipeToAgent(new AnonymousPipe()); |
| |
|
|
| |
CloseHandle(piProcInfo.hProcess); | CloseHandle(piProcInfo.hProcess); |
CloseHandle(piProcInfo.hThread); | CloseHandle(piProcInfo.hThread); |
|
|
|
#elif defined (PEGASUS_OS_VMS) |
|
|
|
// |
|
// fork and exec the child process |
|
// |
|
int status; |
|
|
|
status = vfork (); |
|
switch (status) |
|
{ |
|
case 0: |
|
try |
|
{ |
|
// |
|
// Execute the cimprovagt program |
|
// |
|
String agentCommandPath = |
|
ConfigManager::getHomedPath(PEGASUS_PROVIDER_AGENT_PROC_NAME); |
|
CString agentCommandPathCString = agentCommandPath.getCString(); |
|
|
|
char readHandle[32]; |
|
char writeHandle[32]; |
|
pipeToAgent->exportReadHandle(readHandle); |
|
pipeFromAgent->exportWriteHandle(writeHandle); |
|
|
|
if ((status = execl(agentCommandPathCString, agentCommandPathCString, |
|
readHandle, writeHandle, |
|
(const char*)_moduleName.getCString(), (char*)0)) == -1); |
|
{ |
|
// If we're still here, there was an error |
|
Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
|
"execl() failed. errno = %d.", errno); |
|
_exit(1); |
|
} |
|
} |
|
catch (...) |
|
{ |
|
// There's not much we can do here in no man's land |
|
try |
|
{ |
|
PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
|
"Caught exception before calling execl()."); |
|
} |
|
catch (...) |
|
{ |
|
} |
|
_exit(1); |
|
} |
|
PEG_METHOD_EXIT(); |
|
return; |
|
break; |
|
|
|
case -1: |
|
Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2, |
|
"fork() failed. errno = %d.", errno); |
|
PEG_METHOD_EXIT(); |
|
throw Exception(MessageLoaderParms( |
|
"ProviderManager.OOPProviderManagerRouter.CIMPROVAGT_START_FAILED", |
|
"Failed to start cimprovagt \"$0\".", |
|
_moduleName)); |
|
break; |
|
|
|
default: |
|
// Close our copies of the agent's ends of the pipes |
|
pipeToAgent->closeReadHandle(); |
|
pipeFromAgent->closeWriteHandle(); |
|
|
|
_pipeToAgent.reset(pipeToAgent.release()); |
|
_pipeFromAgent.reset(pipeFromAgent.release()); |
|
|
|
PEG_METHOD_EXIT(); |
|
} |
|
#elif defined (PEGASUS_OS_OS400) |
|
|
|
//Out of process provider support for OS400 goes here when needed. |
|
|
#else | #else |
|
|
|
# ifndef PEGASUS_DISABLE_PROV_USERCTXT |
|
// Get and save the effective user name and the uid/gid for the user |
|
// context of the agent process |
|
|
|
String effectiveUserName = System::getEffectiveUserName(); |
|
PEGASUS_UID_T newUid = (PEGASUS_UID_T) -1; |
|
PEGASUS_GID_T newGid = (PEGASUS_GID_T) -1; |
|
if (_userName != effectiveUserName) |
|
{ |
|
if (!System::lookupUserId(_userName.getCString(), newUid, newGid)) |
|
{ |
|
throw PEGASUS_CIM_EXCEPTION_L( |
|
CIM_ERR_FAILED, |
|
MessageLoaderParms( |
|
"ProviderManager.OOPProviderManagerRouter." |
|
"USER_CONTEXT_CHANGE_FAILED", |
|
"Unable to change user context to \"$0\".", _userName)); |
|
} |
|
} |
|
# endif |
|
|
pid_t pid = fork(); | pid_t pid = fork(); |
if (pid < 0) | if (pid < 0) |
{ | { |
|
|
pipeToAgent->exportReadHandle(readHandle); | pipeToAgent->exportReadHandle(readHandle); |
pipeFromAgent->exportWriteHandle(writeHandle); | pipeFromAgent->exportWriteHandle(writeHandle); |
| |
|
# ifndef PEGASUS_DISABLE_PROV_USERCTXT |
|
// Set the user context of the Provider Agent process |
|
if (_userName != effectiveUserName) |
|
{ |
|
if (!System::changeUserContext(newUid, newGid)) |
|
{ |
|
Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
|
"System::changeUserContext() failed. userName = %s.", |
|
(const char*)_userName.getCString()); |
|
Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, |
|
Logger::WARNING, |
|
"ProviderManager.OOPProviderManagerRouter." |
|
"USER_CONTEXT_CHANGE_FAILED", |
|
"Unable to change user context to \"$0\".", _userName); |
|
_exit(1); |
|
} |
|
} |
|
# endif |
|
|
execl(agentCommandPathCString, agentCommandPathCString, | execl(agentCommandPathCString, agentCommandPathCString, |
readHandle, writeHandle, | readHandle, writeHandle, |
(const char*)_moduleName.getCString(), (char*)0); | (const char*)_moduleName.getCString(), (char*)0); |
|
|
_exit(1); | _exit(1); |
} | } |
} | } |
|
# if defined(PEGASUS_HAS_SIGNALS) |
|
_pid = pid; |
|
# endif |
#endif | #endif |
| |
// | // |
|
|
configManager->getPegasusHome(), | configManager->getPegasusHome(), |
configProperties, | configProperties, |
System::bindVerbose, | System::bindVerbose, |
|
_subscriptionInitComplete, |
QueueIdStack())); | QueueIdStack())); |
| |
// | // |
|
|
_moduleName)); | _moduleName)); |
} | } |
| |
// Do not wait for a response from the Provider Agent. (It isn't coming.) |
// Wait for a null response from the Provider Agent indicating it has |
|
// initialized successfully. |
|
|
|
CIMMessage* message; |
|
AnonymousPipe::Status readStatus; |
|
do |
|
{ |
|
readStatus = _pipeFromAgent->readMessage(message); |
|
} while (readStatus == AnonymousPipe::STATUS_INTERRUPT); |
|
|
|
if (readStatus != AnonymousPipe::STATUS_SUCCESS) |
|
{ |
|
PEG_METHOD_EXIT(); |
|
throw Exception(MessageLoaderParms( |
|
"ProviderManager.OOPProviderManagerRouter." |
|
"CIMPROVAGT_COMMUNICATION_FAILED", |
|
"Failed to communicate with cimprovagt \"$0\".", |
|
_moduleName)); |
|
} |
|
|
|
PEGASUS_ASSERT(message == 0); |
| |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
} | } |
|
|
return; | return; |
} | } |
| |
|
if (_maxProviderProcesses == PEG_NOT_FOUND) |
|
{ |
|
String maxProviderProcesses = ConfigManager::getInstance()-> |
|
getCurrentValue("maxProviderProcesses"); |
|
CString maxProviderProcessesString = maxProviderProcesses.getCString(); |
|
char* end = 0; |
|
_maxProviderProcesses = strtol(maxProviderProcessesString, &end, 10); |
|
} |
|
|
|
{ |
|
AutoMutex lock(_numProviderProcessesMutex); |
|
if ((_maxProviderProcesses != 0) && |
|
(_numProviderProcesses >= _maxProviderProcesses)) |
|
{ |
|
throw PEGASUS_CIM_EXCEPTION( |
|
CIM_ERR_FAILED, |
|
MessageLoaderParms( |
|
"ProviderManager.OOPProviderManagerRouter." |
|
"MAX_PROVIDER_PROCESSES_REACHED", |
|
"The maximum number of cimprovagt processes has been " |
|
"reached.")); |
|
} |
|
else |
|
{ |
|
_numProviderProcesses++; |
|
} |
|
} |
|
|
try | try |
{ | { |
_startAgentProcess(); | _startAgentProcess(); |
| |
_sendInitializationData(); |
|
|
|
_isInitialized = true; | _isInitialized = true; |
| |
|
_sendInitializationData(); |
|
|
// Start a thread to read and process responses from the Provider Agent | // Start a thread to read and process responses from the Provider Agent |
while (!MessageQueueService::get_thread_pool()->allocate_and_awaken( |
ThreadStatus rtn = PEGASUS_THREAD_OK; |
this, _responseProcessor)) |
while ((rtn = MessageQueueService::get_thread_pool()-> |
|
allocate_and_awaken(this, _responseProcessor)) != |
|
PEGASUS_THREAD_OK) |
|
{ |
|
if (rtn == PEGASUS_THREAD_INSUFFICIENT_RESOURCES) |
|
{ |
|
Threads::yield(); |
|
} |
|
else |
{ | { |
pegasus_yield(); |
Logger::put( |
|
Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE, |
|
"Not enough threads to process responses from the " |
|
"provider agent."); |
|
|
|
Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2, |
|
"Could not allocate thread to process responses from the " |
|
"provider agent."); |
|
|
|
throw Exception(MessageLoaderParms( |
|
"ProviderManager.OOPProviderManagerRouter." |
|
"CIMPROVAGT_THREAD_ALLOCATION_FAILED", |
|
"Failed to allocate thread for cimprovagt \"$0\".", |
|
_moduleName)); |
|
} |
} | } |
} | } |
catch (...) | catch (...) |
{ | { |
_isInitialized = false; |
// Closing the connection causes the agent process to exit |
_pipeToAgent.reset(); | _pipeToAgent.reset(); |
_pipeFromAgent.reset(); | _pipeFromAgent.reset(); |
|
|
|
#if defined(PEGASUS_HAS_SIGNALS) |
|
if (_isInitialized) |
|
{ |
|
// Harvest the status of the agent process to prevent a zombie |
|
Boolean keepWaiting = false; |
|
do |
|
{ |
|
pid_t status = waitpid(_pid, 0, 0); |
|
if (status == -1) |
|
{ |
|
if (errno == EINTR) |
|
{ |
|
keepWaiting = true; |
|
} |
|
else |
|
{ |
|
Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
|
"ProviderAgentContainer::_initialize(): " |
|
"waitpid failed; errno = %d.", errno); |
|
} |
|
} |
|
} while (keepWaiting); |
|
} |
|
#endif |
|
|
|
_isInitialized = false; |
|
|
|
{ |
|
AutoMutex lock(_numProviderProcessesMutex); |
|
_numProviderProcesses--; |
|
} |
|
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
throw; | throw; |
} | } |
|
|
} | } |
| |
// Note: Caller must lock _agentMutex | // Note: Caller must lock _agentMutex |
void ProviderAgentContainer::_uninitialize() |
void ProviderAgentContainer::_uninitialize(Boolean cleanShutdown) |
{ | { |
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, | PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, |
"ProviderAgentContainer::_uninitialize"); | "ProviderAgentContainer::_uninitialize"); |
|
|
| |
_providerModuleCache = CIMInstance(); | _providerModuleCache = CIMInstance(); |
| |
|
{ |
|
AutoMutex lock(_numProviderProcessesMutex); |
|
_numProviderProcesses--; |
|
} |
|
|
|
#if defined(PEGASUS_HAS_SIGNALS) |
|
// Harvest the status of the agent process to prevent a zombie |
|
Boolean keepWaiting = false; |
|
do |
|
{ |
|
pid_t status = waitpid(_pid, 0, 0); |
|
if (status == -1) |
|
{ |
|
if (errno == EINTR) |
|
{ |
|
keepWaiting = true; |
|
} |
|
else |
|
{ |
|
Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
|
"ProviderAgentContainer::_uninitialize(): " |
|
"waitpid failed; errno = %d.", errno); |
|
} |
|
} |
|
} while (keepWaiting); |
|
#endif |
|
|
_isInitialized = false; | _isInitialized = false; |
| |
// | // |
|
|
{ | { |
AutoMutex tableLock(_outstandingRequestTableMutex); | AutoMutex tableLock(_outstandingRequestTableMutex); |
| |
|
CIMResponseMessage* response = |
|
cleanShutdown ? _REQUEST_NOT_PROCESSED : 0; |
|
|
for (OutstandingRequestTable::Iterator i = | for (OutstandingRequestTable::Iterator i = |
_outstandingRequestTable.start(); | _outstandingRequestTable.start(); |
i != 0; i++) | i != 0; i++) |
{ | { |
PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2, | PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2, |
String("Completing messageId \"") + i.value()->messageId + |
String("Completing messageId \"") + i.key() + |
"\" with a null response."); | "\" with a null response."); |
i.value()->responseMessage = 0; |
i.value()->responseMessage = response; |
i.value()->responseReady->signal(); | i.value()->responseReady->signal(); |
} | } |
| |
_outstandingRequestTable.clear(); | _outstandingRequestTable.clear(); |
|
|
|
// |
|
// If not a clean shutdown, call the provider module failure |
|
// callback |
|
// |
|
if (!cleanShutdown) |
|
{ |
|
// |
|
// Call the provider module failure callback to |
|
// communicate the failure to the Provider Manager Service |
|
// Provider Manager Service will inform Indication Service |
|
// |
|
_providerModuleFailCallback (_moduleName, _userName, |
|
_userContext); |
|
} |
} | } |
} | } |
catch (...) | catch (...) |
|
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
} | } |
| |
|
String ProviderAgentContainer::getModuleName() const |
|
{ |
|
return _moduleName; |
|
} |
|
|
CIMResponseMessage* ProviderAgentContainer::processMessage( | CIMResponseMessage* ProviderAgentContainer::processMessage( |
CIMRequestMessage* request) | CIMRequestMessage* request) |
{ | { |
|
|
"ProviderAgentContainer::processMessage"); | "ProviderAgentContainer::processMessage"); |
| |
CIMResponseMessage* response; | CIMResponseMessage* response; |
|
|
|
do |
|
{ |
|
response = _processMessage(request); |
|
|
|
if (response == _REQUEST_NOT_PROCESSED) |
|
{ |
|
// Check for request message types that should not be retried. |
|
if ((request->getType() == |
|
CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) || |
|
(request->getType() == |
|
CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE) || |
|
(request->getType() == |
|
CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) || |
|
(request->getType() == |
|
CIM_DELETE_SUBSCRIPTION_REQUEST_MESSAGE)) |
|
{ |
|
response = request->buildResponse(); |
|
break; |
|
} |
|
else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE) |
|
{ |
|
CIMDisableModuleResponseMessage* dmResponse = |
|
dynamic_cast<CIMDisableModuleResponseMessage*>(response); |
|
PEGASUS_ASSERT(dmResponse != 0); |
|
|
|
Array<Uint16> operationalStatus; |
|
operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED); |
|
dmResponse->operationalStatus = operationalStatus; |
|
break; |
|
} |
|
} |
|
} while (response == _REQUEST_NOT_PROCESSED); |
|
|
|
PEG_METHOD_EXIT(); |
|
return response; |
|
} |
|
|
|
CIMResponseMessage* ProviderAgentContainer::_processMessage( |
|
CIMRequestMessage* request) |
|
{ |
|
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, |
|
"ProviderAgentContainer::_processMessage"); |
|
|
|
CIMResponseMessage* response; |
String originalMessageId = request->messageId; | String originalMessageId = request->messageId; |
| |
// These three variables are used for the provider module optimization. | // These three variables are used for the provider module optimization. |
|
|
// | // |
Semaphore waitSemaphore(0); | Semaphore waitSemaphore(0); |
OutstandingRequestEntry outstandingRequestEntry( | OutstandingRequestEntry outstandingRequestEntry( |
uniqueMessageId, response, &waitSemaphore); |
originalMessageId, request, response, &waitSemaphore); |
| |
// | // |
// Lock the Provider Agent Container while initializing the | // Lock the Provider Agent Container while initializing the |
|
|
// Get the provider module from the ProviderIdContainer to see if | // Get the provider module from the ProviderIdContainer to see if |
// we can optimize out the transmission of this instance to the | // we can optimize out the transmission of this instance to the |
// Provider Agent. (See the _providerModuleCache description.) | // Provider Agent. (See the _providerModuleCache description.) |
try |
if(request->operationContext.contains(ProviderIdContainer::NAME)) |
{ | { |
ProviderIdContainer pidc = request->operationContext.get( | ProviderIdContainer pidc = request->operationContext.get( |
ProviderIdContainer::NAME); | ProviderIdContainer::NAME); |
|
|
doProviderModuleOptimization = true; | doProviderModuleOptimization = true; |
} | } |
} | } |
catch (...) |
|
{ |
|
// No ProviderIdContainer to optimize |
|
} |
|
| |
// | // |
// Write the message to the pipe | // Write the message to the pipe |
|
|
Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2, | Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL2, |
"Failed to write message to pipe. writeStatus = %d.", | "Failed to write message to pipe. writeStatus = %d.", |
writeStatus); | writeStatus); |
throw Exception(MessageLoaderParms( |
|
"ProviderManager.OOPProviderManagerRouter." |
request->messageId = originalMessageId; |
"CIMPROVAGT_COMMUNICATION_FAILED", |
|
"Failed to communicate with cimprovagt \"$0\".", |
if (doProviderModuleOptimization) |
_moduleName)); |
{ |
|
request->operationContext.set(*origProviderId.get()); |
|
} |
|
|
|
// Remove this OutstandingRequestTable entry |
|
{ |
|
AutoMutex tableLock(_outstandingRequestTableMutex); |
|
Boolean removed = |
|
_outstandingRequestTable.remove(uniqueMessageId); |
|
PEGASUS_ASSERT(removed); |
|
} |
|
|
|
// A response value of _REQUEST_NOT_PROCESSED indicates |
|
// that the request was not processed by the provider |
|
// agent, so it can be retried safely. |
|
PEG_METHOD_EXIT(); |
|
return _REQUEST_NOT_PROCESSED; |
} | } |
| |
if (updateProviderModuleCache) | if (updateProviderModuleCache) |
|
|
_outstandingRequestTable.remove(uniqueMessageId); | _outstandingRequestTable.remove(uniqueMessageId); |
PEGASUS_ASSERT(removed); | PEGASUS_ASSERT(removed); |
} | } |
|
PEG_METHOD_EXIT(); |
throw; | throw; |
} | } |
} | } |
|
|
_outstandingRequestTable.remove(uniqueMessageId); | _outstandingRequestTable.remove(uniqueMessageId); |
PEGASUS_ASSERT(removed); | PEGASUS_ASSERT(removed); |
} | } |
|
PEG_METHOD_EXIT(); |
throw; | throw; |
} | } |
| |
|
// A response value of _REQUEST_NOT_PROCESSED indicates that the |
|
// provider agent process was terminating when the request was sent. |
|
// The request was not processed by the provider agent, so it can be |
|
// retried safely. |
|
if (response == _REQUEST_NOT_PROCESSED) |
|
{ |
|
PEG_METHOD_EXIT(); |
|
return response; |
|
} |
|
|
// A null response is returned when an agent connection is closed | // A null response is returned when an agent connection is closed |
// while requests remain outstanding. | // while requests remain outstanding. |
if (response == 0) | if (response == 0) |
|
|
void ProviderAgentContainer::unloadIdleProviders() | void ProviderAgentContainer::unloadIdleProviders() |
{ | { |
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, | PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, |
"ProviderAgentContainer::processMessage"); |
"ProviderAgentContainer::unloadIdleProviders"); |
| |
AutoMutex lock(_agentMutex); | AutoMutex lock(_agentMutex); |
if (_isInitialized) | if (_isInitialized) |
|
|
(readStatus == AnonymousPipe::STATUS_CLOSED)) | (readStatus == AnonymousPipe::STATUS_CLOSED)) |
{ | { |
AutoMutex lock(_agentMutex); | AutoMutex lock(_agentMutex); |
_uninitialize(); |
_uninitialize(false); |
|
return; |
|
} |
|
|
|
// A null message indicates that the provider agent process has |
|
// finished its processing and is ready to exit. |
|
if (message == 0) |
|
{ |
|
AutoMutex lock(_agentMutex); |
|
_uninitialize(true); |
return; | return; |
} | } |
| |
|
|
reinterpret_cast<CIMProcessIndicationRequestMessage*>( | reinterpret_cast<CIMProcessIndicationRequestMessage*>( |
message)); | message)); |
} | } |
|
else if (!message->isComplete()) |
|
{ |
|
CIMResponseMessage* response; |
|
response = dynamic_cast<CIMResponseMessage*>(message); |
|
PEGASUS_ASSERT(response != 0); |
|
|
|
// Get the OutstandingRequestEntry for this response chunk |
|
OutstandingRequestEntry* _outstandingRequestEntry = 0; |
|
{ |
|
AutoMutex tableLock(_outstandingRequestTableMutex); |
|
Boolean foundEntry = _outstandingRequestTable.lookup( |
|
response->messageId, _outstandingRequestEntry); |
|
PEGASUS_ASSERT(foundEntry); |
|
} |
|
|
|
// Put the original message ID into the response |
|
response->messageId = |
|
_outstandingRequestEntry->originalMessageId; |
|
|
|
// Call the response chunk callback to process the chunk |
|
_responseChunkCallback( |
|
_outstandingRequestEntry->requestMessage, response); |
|
} |
else | else |
{ | { |
CIMResponseMessage* response; | CIMResponseMessage* response; |
|
|
} | } |
} | } |
| |
PEG_METHOD_EXIT(); |
|
} | } |
| |
PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL |
ThreadReturnType PEGASUS_THREAD_CDECL |
ProviderAgentContainer::_responseProcessor(void* arg) | ProviderAgentContainer::_responseProcessor(void* arg) |
{ | { |
ProviderAgentContainer* pa = | ProviderAgentContainer* pa = |
|
|
| |
pa->_processResponses(); | pa->_processResponses(); |
| |
return(PEGASUS_THREAD_RETURN(0)); |
return(ThreadReturnType(0)); |
} | } |
| |
///////////////////////////////////////////////////////////////////////////// | ///////////////////////////////////////////////////////////////////////////// |
|
|
///////////////////////////////////////////////////////////////////////////// | ///////////////////////////////////////////////////////////////////////////// |
| |
OOPProviderManagerRouter::OOPProviderManagerRouter( | OOPProviderManagerRouter::OOPProviderManagerRouter( |
PEGASUS_INDICATION_CALLBACK indicationCallback) |
PEGASUS_INDICATION_CALLBACK_T indicationCallback, |
|
PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback, |
|
PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T providerModuleFailCallback) |
{ | { |
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, | PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, |
"OOPProviderManagerRouter::OOPProviderManagerRouter"); | "OOPProviderManagerRouter::OOPProviderManagerRouter"); |
| |
_indicationCallback = indicationCallback; | _indicationCallback = indicationCallback; |
|
_responseChunkCallback = responseChunkCallback; |
|
_providerModuleFailCallback = providerModuleFailCallback; |
|
_subscriptionInitComplete = false; |
| |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
} | } |
|
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
} | } |
| |
// Private, unimplemented constructor |
|
OOPProviderManagerRouter::OOPProviderManagerRouter() |
|
{ |
|
} |
|
|
|
// Private, unimplemented constructor |
|
OOPProviderManagerRouter::OOPProviderManagerRouter( |
|
const OOPProviderManagerRouter&) |
|
{ |
|
} |
|
|
|
// Private, unimplemented assignment operator |
|
OOPProviderManagerRouter& OOPProviderManagerRouter::operator=( |
|
const OOPProviderManagerRouter&) |
|
{ |
|
return *this; |
|
} |
|
|
|
Message* OOPProviderManagerRouter::processMessage(Message* message) | Message* OOPProviderManagerRouter::processMessage(Message* message) |
{ | { |
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, | PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, |
|
|
providerModule = dmReq->providerModule; | providerModule = dmReq->providerModule; |
} | } |
else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) || | else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) || |
|
(request->getType() == |
|
CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) || |
(request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)) | (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)) |
{ | { |
// This operation is not provider-specific | // This operation is not provider-specific |
|
|
// Just let the selecting thread notice when the agent connections | // Just let the selecting thread notice when the agent connections |
// are closed. | // are closed. |
} | } |
|
else if (request->getType () == |
|
CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) |
|
{ |
|
_subscriptionInitComplete = true; |
|
|
|
// |
|
// Forward the CIMSubscriptionInitCompleteRequestMessage to |
|
// all providers |
|
// |
|
response.reset (_forwardRequestToAllAgents (request)); |
|
} |
else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE) | else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE) |
{ | { |
CIMNotifyConfigChangeRequestMessage* notifyRequest = | CIMNotifyConfigChangeRequestMessage* notifyRequest = |
|
|
response.reset(request->buildResponse()); | response.reset(request->buildResponse()); |
} | } |
} | } |
else |
else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE) |
{ | { |
|
// Fan out the request to all Provider Agent processes for this module |
|
|
// Retrieve the provider module name | // Retrieve the provider module name |
String moduleName; | String moduleName; |
CIMValue nameValue = providerModule.getProperty( | CIMValue nameValue = providerModule.getProperty( |
providerModule.findProperty("Name")).getValue(); | providerModule.findProperty("Name")).getValue(); |
nameValue.get(moduleName); | nameValue.get(moduleName); |
| |
// Look up the Provider Agent for this module |
// Look up the Provider Agents for this module |
ProviderAgentContainer * pa = _lookupProviderAgent(moduleName); |
Array<ProviderAgentContainer*> paArray = |
PEGASUS_ASSERT(pa != 0); |
_lookupProviderAgents(moduleName); |
|
|
// Determine whether the Provider Agent has been initialized |
|
Boolean paInitialized = pa->isInitialized(); |
|
| |
if ((request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE) && |
for (Uint32 i=0; i<paArray.size(); i++) |
!paInitialized) |
|
{ | { |
// | // |
// Do not start up an agent process just to disable the module | // Do not start up an agent process just to disable the module |
// | // |
|
if (paArray[i]->isInitialized()) |
|
{ |
|
// |
|
// Forward the request to the provider agent |
|
// |
|
response.reset(paArray[i]->processMessage(request)); |
|
|
|
// Note: Do not uninitialize the ProviderAgentContainer here |
|
// when a disable module operation is successful. Just let the |
|
// selecting thread notice when the agent connection is closed. |
|
|
|
// Determine the success of the disable module operation |
|
CIMDisableModuleResponseMessage* dmResponse = |
|
dynamic_cast<CIMDisableModuleResponseMessage*>( |
|
response.get()); |
|
PEGASUS_ASSERT(dmResponse != 0); |
|
|
|
Boolean isStopped = false; |
|
for (Uint32 i=0; i < dmResponse->operationalStatus.size(); i++) |
|
{ |
|
if (dmResponse->operationalStatus[i] == |
|
CIM_MSE_OPSTATUS_VALUE_STOPPED) |
|
{ |
|
isStopped = true; |
|
break; |
|
} |
|
} |
|
|
|
// If the operation is unsuccessful, stop and return the error |
|
if ((dmResponse->cimException.getCode() != CIM_ERR_SUCCESS) || |
|
!isStopped) |
|
{ |
|
break; |
|
} |
|
} |
|
} |
|
|
|
// Use a default response if no Provider Agents were called |
|
if (!response.get()) |
|
{ |
response.reset(request->buildResponse()); | response.reset(request->buildResponse()); |
| |
CIMDisableModuleResponseMessage* dmResponse = | CIMDisableModuleResponseMessage* dmResponse = |
|
|
operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED); | operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_STOPPED); |
dmResponse->operationalStatus = operationalStatus; | dmResponse->operationalStatus = operationalStatus; |
} | } |
else if ((request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE) && |
} |
!paInitialized) |
else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE) |
|
{ |
|
// Fan out the request to all Provider Agent processes for this module |
|
|
|
// Retrieve the provider module name |
|
String moduleName; |
|
CIMValue nameValue = providerModule.getProperty( |
|
providerModule.findProperty("Name")).getValue(); |
|
nameValue.get(moduleName); |
|
|
|
// Look up the Provider Agents for this module |
|
Array<ProviderAgentContainer*> paArray = |
|
_lookupProviderAgents(moduleName); |
|
|
|
for (Uint32 i=0; i<paArray.size(); i++) |
{ | { |
// | // |
// Do not start up an agent process just to enable the module | // Do not start up an agent process just to enable the module |
// | // |
|
if (paArray[i]->isInitialized()) |
|
{ |
|
// |
|
// Forward the request to the provider agent |
|
// |
|
response.reset(paArray[i]->processMessage(request)); |
|
|
|
// Determine the success of the enable module operation |
|
CIMEnableModuleResponseMessage* emResponse = |
|
dynamic_cast<CIMEnableModuleResponseMessage*>( |
|
response.get()); |
|
PEGASUS_ASSERT(emResponse != 0); |
|
|
|
Boolean isOk = false; |
|
for (Uint32 i=0; i < emResponse->operationalStatus.size(); i++) |
|
{ |
|
if (emResponse->operationalStatus[i] == |
|
CIM_MSE_OPSTATUS_VALUE_OK) |
|
{ |
|
isOk = true; |
|
break; |
|
} |
|
} |
|
|
|
// If the operation is unsuccessful, stop and return the error |
|
if ((emResponse->cimException.getCode() != CIM_ERR_SUCCESS) || |
|
!isOk) |
|
{ |
|
break; |
|
} |
|
} |
|
} |
|
|
|
// Use a default response if no Provider Agents were called |
|
if (!response.get()) |
|
{ |
response.reset(request->buildResponse()); | response.reset(request->buildResponse()); |
| |
CIMEnableModuleResponseMessage* emResponse = | CIMEnableModuleResponseMessage* emResponse = |
|
|
operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK); | operationalStatus.append(CIM_MSE_OPSTATUS_VALUE_OK); |
emResponse->operationalStatus = operationalStatus; | emResponse->operationalStatus = operationalStatus; |
} | } |
|
} |
else | else |
{ | { |
// | // |
|
// Look up the Provider Agent for this module instance and requesting |
|
// user |
|
// |
|
ProviderAgentContainer* pa = _lookupProviderAgent(providerModule, |
|
request); |
|
PEGASUS_ASSERT(pa != 0); |
|
|
|
// |
// Forward the request to the provider agent | // Forward the request to the provider agent |
// | // |
response.reset(pa->processMessage(request)); | response.reset(pa->processMessage(request)); |
|
|
// Note: Do not uninitialize the ProviderAgentContainer here when |
|
// a disable module operation is successful.) Just let the |
|
// selecting thread notice when the agent connection is closed. |
|
} |
|
} | } |
| |
response->syncAttributes(request); | response->syncAttributes(request); |
|
|
} | } |
| |
ProviderAgentContainer* OOPProviderManagerRouter::_lookupProviderAgent( | ProviderAgentContainer* OOPProviderManagerRouter::_lookupProviderAgent( |
const String& moduleName) |
const CIMInstance& providerModule, |
|
CIMRequestMessage* request) |
|
{ |
|
// Retrieve the provider module name |
|
String moduleName; |
|
CIMValue nameValue = providerModule.getProperty( |
|
providerModule.findProperty("Name")).getValue(); |
|
nameValue.get(moduleName); |
|
|
|
// Retrieve the provider user context configuration |
|
Uint16 userContext = 0; |
|
Uint32 pos = providerModule.findProperty( |
|
PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT); |
|
if (pos != PEG_NOT_FOUND) |
|
{ |
|
CIMValue userContextValue = |
|
providerModule.getProperty(pos).getValue(); |
|
if (!userContextValue.isNull()) |
|
{ |
|
userContextValue.get(userContext); |
|
} |
|
} |
|
|
|
if (userContext == 0) |
|
{ |
|
userContext = PEGASUS_DEFAULT_PROV_USERCTXT; |
|
} |
|
|
|
String userName; |
|
|
|
if (userContext == PG_PROVMODULE_USERCTXT_REQUESTOR) |
|
{ |
|
if(request->operationContext.contains(IdentityContainer::NAME)) |
|
{ |
|
// User Name is in the OperationContext |
|
IdentityContainer ic = (IdentityContainer) |
|
request->operationContext.get(IdentityContainer::NAME); |
|
userName = ic.getUserName(); |
|
} |
|
//else |
|
//{ |
|
// If no IdentityContainer is present, default to the CIM |
|
// Server's user context |
|
//} |
|
|
|
// If authentication is disabled, use the CIM Server's user context |
|
if (!userName.size()) |
|
{ |
|
userName = System::getEffectiveUserName(); |
|
} |
|
} |
|
else if (userContext == PG_PROVMODULE_USERCTXT_DESIGNATED) |
|
{ |
|
// Retrieve the provider module designated user property value |
|
providerModule.getProperty(providerModule.findProperty( |
|
PEGASUS_PROPERTYNAME_MODULE_DESIGNATEDUSER)).getValue(). |
|
get(userName); |
|
} |
|
else if (userContext == PG_PROVMODULE_USERCTXT_CIMSERVER) |
|
{ |
|
userName = System::getEffectiveUserName(); |
|
} |
|
else // Privileged User |
{ | { |
|
PEGASUS_ASSERT(userContext == PG_PROVMODULE_USERCTXT_PRIVILEGED); |
|
userName = System::getPrivilegedUserName(); |
|
} |
|
|
|
PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4, |
|
"Module name = " + moduleName); |
|
Tracer::trace(TRC_PROVIDERMANAGER, Tracer::LEVEL4, |
|
"User context = %hd.", userContext); |
|
PEG_TRACE_STRING(TRC_PROVIDERMANAGER, Tracer::LEVEL4, |
|
"User name = " + userName); |
|
|
ProviderAgentContainer* pa = 0; | ProviderAgentContainer* pa = 0; |
|
String key = moduleName + ":" + userName; |
| |
AutoMutex lock(_providerAgentTableMutex); | AutoMutex lock(_providerAgentTableMutex); |
if (!_providerAgentTable.lookup(moduleName, pa)) |
if (!_providerAgentTable.lookup(key, pa)) |
{ | { |
pa = new ProviderAgentContainer(moduleName, _indicationCallback); |
pa = new ProviderAgentContainer( |
_providerAgentTable.insert(moduleName, pa); |
moduleName, userName, userContext, |
|
_indicationCallback, _responseChunkCallback, |
|
_providerModuleFailCallback, |
|
_subscriptionInitComplete); |
|
_providerAgentTable.insert(key, pa); |
} | } |
return pa; | return pa; |
} | } |
| |
|
Array<ProviderAgentContainer*> OOPProviderManagerRouter::_lookupProviderAgents( |
|
const String& moduleName) |
|
{ |
|
Array<ProviderAgentContainer*> paArray; |
|
|
|
AutoMutex lock(_providerAgentTableMutex); |
|
for (ProviderAgentTable::Iterator i = _providerAgentTable.start(); i; i++) |
|
{ |
|
if (i.value()->getModuleName() == moduleName) |
|
{ |
|
paArray.append(i.value()); |
|
} |
|
} |
|
return paArray; |
|
} |
|
|
CIMResponseMessage* OOPProviderManagerRouter::_forwardRequestToAllAgents( | CIMResponseMessage* OOPProviderManagerRouter::_forwardRequestToAllAgents( |
CIMRequestMessage* request) | CIMRequestMessage* request) |
{ | { |