📄 oopprovidermanagerrouter.cpp
字号:
//%2006//////////////////////////////////////////////////////////////////////////// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;// 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// of this software and associated documentation files (the "Software"), to// deal in the Software without restriction, including without limitation the// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or// sell copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions:// // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.////==============================================================================////%/////////////////////////////////////////////////////////////////////////////#include <Pegasus/Common/Signal.h>#include <Pegasus/Common/Config.h>#include <Pegasus/Common/Constants.h>#include <Pegasus/Common/AutoPtr.h>#include <Pegasus/Common/ArrayInternal.h>#include <Pegasus/Common/CIMMessage.h>#include <Pegasus/Common/CIMMessageSerializer.h>#include <Pegasus/Common/CIMMessageDeserializer.h>#include <Pegasus/Common/OperationContextInternal.h>#include <Pegasus/Common/System.h>#include <Pegasus/Common/AnonymousPipe.h>#include <Pegasus/Common/Tracer.h>#include <Pegasus/Common/Logger.h>#include <Pegasus/Common/Thread.h>#include <Pegasus/Common/MessageQueueService.h>#include <Pegasus/Config/ConfigManager.h>#if defined (PEGASUS_OS_TYPE_WINDOWS)# include <windows.h> // For CreateProcess()#elif defined (PEGASUS_OS_OS400)# 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# include <unistd.h> // For fork(), exec(), and _exit()# include <errno.h># include <sys/types.h># include <sys/resource.h># if defined(PEGASUS_HAS_SIGNALS)# include <sys/wait.h># endif#endif#include "OOPProviderManagerRouter.h"PEGASUS_USING_STD;PEGASUS_NAMESPACE_BEGIN/////////////////////////////////////////////////////////////////////////////// OutstandingRequestTable and OutstandingRequestEntry//////////////////////////////////////////////////////////////////////////////** An OutstandingRequestEntry represents a request message sent to a Provider Agent for which no response has been received. The request sender provides the message ID and a location for the response to be returned, and then waits on the semaphore. When a response matching the message ID is received, it is placed into the specified location and the semaphore is signaled. */class OutstandingRequestEntry{public: OutstandingRequestEntry( String originalMessageId_, CIMRequestMessage* requestMessage_, CIMResponseMessage*& responseMessage_, Semaphore* responseReady_) : originalMessageId(originalMessageId_), requestMessage(requestMessage_), responseMessage(responseMessage_), responseReady(responseReady_) { } /** 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; Semaphore* responseReady;};typedef HashTable<String, OutstandingRequestEntry*, EqualFunc<String>, HashFunc<String> > OutstandingRequestTable;/////////////////////////////////////////////////////////////////////////////// ProviderAgentContainer/////////////////////////////////////////////////////////////////////////////class ProviderAgentContainer{public: ProviderAgentContainer( const String & moduleName, const String & userName, Uint16 userContext, PEGASUS_INDICATION_CALLBACK_T indicationCallback, PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback, PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T providerModuleFailCallback, Boolean subscriptionInitComplete); ~ProviderAgentContainer(); Boolean isInitialized(); String getModuleName() const; CIMResponseMessage* processMessage(CIMRequestMessage* request); void unloadIdleProviders();private: // // Private methods // /** Unimplemented */ ProviderAgentContainer(); /** Unimplemented */ ProviderAgentContainer(const ProviderAgentContainer& pa); /** Unimplemented */ ProviderAgentContainer& operator=(const ProviderAgentContainer& pa); /** Start a Provider Agent process and establish a pipe connection with it. Note: The caller must lock the _agentMutex. */ void _startAgentProcess(); /** Send initialization data to the Provider Agent. Note: The caller must lock the _agentMutex. */ void _sendInitializationData(); /** Initialize the ProviderAgentContainer if it is not already initialized. Initialization includes starting the Provider Agent process, establishing a pipe connection with it, and starting a thread to read response messages from the Provider Agent. Note: The caller must lock the _agentMutex. */ void _initialize(); /** Uninitialize the ProviderAgentContainer if it is initialized. The connection is closed and outstanding requests are completed with an error result. 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(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 the connection is closed. */ void _processResponses(); static ThreadReturnType PEGASUS_THREAD_CDECL _responseProcessor(void* arg); // // Private data // /** The _agentMutex must be locked whenever writing to the Provider Agent connection, accessing the _isInitialized flag, or changing the Provider Agent state. */ Mutex _agentMutex; /** Name of the provider module served by this Provider Agent. */ 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 processing. */ 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. */ Boolean _isInitialized; /** Pipe connection used to read responses from the Provider Agent. */ AutoPtr<AnonymousPipe> _pipeFromAgent; /** Pipe connection used to write requests to the Provider Agent. */ 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 been sent to this Provider Agent for which no response has been received. Entries are added (by the writing thread) when a request is sent, and are removed (by the reading thread) when the response is received (or when it is determined that no response is forthcoming). */ OutstandingRequestTable _outstandingRequestTable; /** The _outstandingRequestTableMutex must be locked whenever reading or updating the _outstandingRequestTable. */ Mutex _outstandingRequestTableMutex; /** Holds the last provider module instance sent to the Provider Agent in a ProviderIdContainer. Since the provider module instance rarely changes, an optimization is used to send it only when it differs from the last provider module instance sent. */ 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( const String & moduleName, 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), _userName(userName), _userContext(userContext), _indicationCallback(indicationCallback), _responseChunkCallback(responseChunkCallback), _providerModuleFailCallback(providerModuleFailCallback), _isInitialized(false), _subscriptionInitComplete(subscriptionInitComplete){ PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, "ProviderAgentContainer::ProviderAgentContainer"); PEG_METHOD_EXIT();}ProviderAgentContainer::~ProviderAgentContainer(){ PEG_METHOD_ENTER(TRC_PROVIDERMANAGER, "ProviderAgentContainer::~ProviderAgentContainer"); // Ensure the destructor does not throw an exception try { if (isInitialized()) { // Stop the responseProcessor thread by closing its connection _pipeFromAgent->closeReadHandle(); // Wait for the responseProcessor thread to exit while (isInitialized()) { Threads::yield(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -