TITLE: PEP 349 implementation.
DESCRIPTION: Improve the availability of the CIMOM by better isolation from faulty providers.
$(MAKE) --directory=$(PEGASUS_ROOT) -f TestMakefile runCBATestSuites
$(MAKE) --directory=$(PEGASUS_ROOT) -f TestMakefile run_SDK_TS1
$(MAKE) --directory=$(PEGASUS_ROOT) -f TestMakefile run_ExportClientSSL_TS1
+ $(MAKE) --directory=$(PEGASUS_ROOT) -f TestMakefile run_Cimserver_Availability
ifeq ($(PEGASUS_ENABLE_CMPI_PROVIDER_MANAGER),true)
$(MAKE) --directory=$(PEGASUS_ROOT) -f TestMakefile run_Cmpi_Sub
endif
TESTSUITE_CMDS="$(IDLE_CONNECTION_TIMEOUT_1_TEST_CMDS)"
###############################################################################
-
###############################################################################
## idleConnectionTimeout Test Suite 2: uses IdleConnectionTimeout client test
##
TESTSUITE_CMDS="$(IDLE_CONNECTION_TIMEOUT_2_TEST_CMDS)"
###############################################################################
+###############################################################################
+## cimserver thread limit test:
+##
+## Configuration Options: none
+##
+###############################################################################
+CIMSERVER_THREAD_LIMIT_TEST_CONFIG_OPTIONS = forceProviderProcesses=true
+CIMSERVER_THREAD_LIMIT_TEST_CMDS = \
+ $(MAKE)@@--directory \
+ $(PEGASUS_ROOT)/src/Providers/TestProviders/FaultyInstanceProvider/testclient \
+ -f@@Makefile@@runAvailabilityTest
+run_Cimserver_Availability: FORCE
+ $(MAKE) -f $(PEGASUS_ROOT)/TestMakefile runTestSuite \
+ CIMSERVER_CONFIG_OPTIONS="$(CIMSERVER_THREAD_LIMIT_TEST_CONFIG_OPTIONS)" \
+ TESTSUITE_CMDS="$(CIMSERVER_THREAD_LIMIT_TEST_CMDS)"
+###############################################################################
###############################################################################
## cimsub CLI Test Suite 1: PG_InterOp Tests
MessageType type_,
const String& messageId_,
const CIMException& cimException_,
- const QueueIdStack& queueIds_)
+ const QueueIdStack& queueIds_,
+ Boolean isAsyncResponsePending_)
:
CIMMessage(type_, messageId_),
queueIds(queueIds_),
- cimException(cimException_)
+ cimException(cimException_),
+ isAsyncResponsePending(isAsyncResponsePending_)
{
}
MessageType type_,
const String& messageId_,
const CIMException& cimException_,
- const QueueIdStack& queueIds_);
+ const QueueIdStack& queueIds_,
+ Boolean isAsyncResponsePending=false);
void syncAttributes(const CIMRequestMessage* request);
QueueIdStack queueIds;
CIMException cimException;
+
+ // This flag indicates if the response will arrive asynchronously.
+ Boolean isAsyncResponsePending;
+
};
//
}
+void AsyncLegacyOperationStart::put_action(Message *act_)
+{
+ _act = act_;
+}
+
AsyncLegacyOperationResult::AsyncLegacyOperationResult(
AsyncOpNode* operation,
Message* result)
Message* get_action();
+ void put_action(Message *action);
+
private:
friend class MessageQueueService;
friend class cimom;
// HTTPConnection::handleEnqueue(), we are running a risk of
// accessing a deleted object and crashing cimserver.
AutoMutex connectionLock(_connection_mut);
- _socket->close();
+ _socket->close();
PEG_METHOD_EXIT();
}
handleEnqueue(message);
}
+Boolean HTTPConnection::isActive()
+{
+ PEG_METHOD_ENTER(TRC_HTTP, "HTTPConnection::isActive");
+ if(needsReconnect())
+ {
+ PEG_METHOD_EXIT();
+ return false;
+ }
+ else
+ {
+ PEG_METHOD_EXIT();
+ return true;
+ }
+}
+
+
void HTTPConnection::handleInternalServerError(
Uint32 respMsgIndex,
Boolean isComplete)
virtual void enqueue(Message *);
+ /**
+ In this specialization of isActive a check is performed on the
+ non-blocking socket to see if it is active by reading 1 byte. Since the
+ current thread is processing the request, its safe to try to read 1 byte
+ from the socket as there should be no data on the socket. If read
+ returns a message of size zero, it is an indication that the client has
+ closed the connection and the socket at the server end can be closed.
+ */
+ virtual Boolean isActive();
+
/** This method is called whenever a SocketMessage is enqueued
on the input queue of the HTTPConnection object.
*/
return message;
}
+Boolean MessageQueue::isActive()
+{
+ return true;
+}
+
const char* MessageQueue::getQueueName() const
{
return _name;
*/
virtual Message* dequeue();
+ /**
+ This function will indicate whether the MessageQueue is active or not.
+ By default this function will return true and do nothing else.
+ */
+ virtual Boolean isActive();
+
/** Returns true if there are no messages on the queue. */
Boolean isEmpty() const { return (Boolean) _messageList.is_empty(); }
return false;
}
-void BasicProviderManagerRouter::unloadIdleProviders()
+void BasicProviderManagerRouter::idleTimeCleanup()
{
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
- "BasicProviderManagerRouter::unloadIdleProviders");
+ "BasicProviderManagerRouter::idleTimeCleanup");
//
// Save pointers to the ProviderManagerContainers so we don't hold the
*/
Boolean hasActiveProviders();
- virtual void unloadIdleProviders();
+ virtual void idleTimeCleanup();
private:
BasicProviderManagerRouter();
static String _GROUP_PREFIX = "grp:";
static String _MODULE_PREFIX = "mod:";
+static struct timeval deallocateWait = {300, 0};
+
+// This calss is used to aggregate the responses sent when a single requests can
+// result in many responses and these responses need to be aggregated before a
+// response is sent back to the ProviderManageService.
+class RespAggCounter
+{
+public:
+ RespAggCounter(Uint32 count):
+ _expectedResponseCount(count),
+ _receivedResponseCount(0)
+ {
+ }
+
+ Boolean isComplete(CIMException &e)
+ {
+ AutoMutex mtx(_mutex);
+ if (e.getCode() != CIM_ERR_SUCCESS)
+ {
+ _exception = e;
+ }
+ _receivedResponseCount++;
+ return _receivedResponseCount == _expectedResponseCount ;
+ }
+
+ CIMException getException()
+ {
+ return _exception;
+ }
+
+private:
+ Mutex _mutex;
+ Uint32 _expectedResponseCount, _receivedResponseCount ;
+ CIMException _exception;
+};
+
+
/////////////////////////////////////////////////////////////////////////////
// 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.
- */
+ returned. When a response matching the message ID is received, the
+ OutstandingRequestEntry is updated to indicate that the response
+ will arrive asynchronously. This entry will be deleted
+ when the response arrives. */
class OutstandingRequestEntry
{
public:
String originalMessageId_,
CIMRequestMessage* requestMessage_,
CIMResponseMessage*& responseMessage_,
- Semaphore* responseReady_)
+ RespAggCounter* respAggregator_=NULL)
: originalMessageId(originalMessageId_),
requestMessage(requestMessage_),
responseMessage(responseMessage_),
- responseReady(responseReady_)
+ respAggregator(respAggregator_)
{
}
String originalMessageId;
CIMRequestMessage* requestMessage;
CIMResponseMessage*& responseMessage;
- Semaphore* responseReady;
+
+ // The aggregator object which aggregates the responses for requests
+ // like CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE etc.
+ RespAggCounter* respAggregator;
};
-typedef HashTable<String, OutstandingRequestEntry*, EqualFunc<String>,
+typedef HashTable<String, SharedPtr<OutstandingRequestEntry>, EqualFunc<String>,
HashFunc<String> > OutstandingRequestTable;
+class RetryThreadParam{
+public:
+ ProviderAgentContainer *pac;
+ Array<CIMRequestMessage *> retryRequestArray;
+};
+
/////////////////////////////////////////////////////////////////////////////
// ProviderAgentContainer
PEGASUS_INDICATION_CALLBACK_T indicationCallback,
PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T providerModuleFailCallback,
- Boolean subscriptionInitComplete);
+ PEGASUS_ASYNC_RESPONSE_CALLBACK_T asyncResponseCallback,
+ Boolean subscriptionInitComplete,
+ ThreadPool * threadPool);
~ProviderAgentContainer();
String getGroupNameWithType() const;
- CIMResponseMessage* processMessage(CIMRequestMessage* request);
+ CIMResponseMessage* processMessage(CIMRequestMessage* request,
+ RespAggCounter * respAggregator=NULL);
+
void unloadIdleProviders();
+ /**
+ Check if the pending responses in the _outstandingRequestTable
+ have active client connections. If not then create a response
+ to indicate that this client connection can be closed. The
+ entry for this request is also deleted from the
+ _outstandingRequestTable. This function is called at regular
+ intervals along with unloadIdleProviders
+ */
+ void cleanDisconnectedClientRequests();
+
private:
//
// Private methods
Performs the processMessage work, but does not retry on a transient
error.
*/
- CIMResponseMessage* _processMessage(CIMRequestMessage* request);
+ CIMResponseMessage* _processMessage(CIMRequestMessage* request,
+ RespAggCounter *respAggregator);
/**
Read and process response messages from the Provider Agent until
the connection is closed.
*/
void _processResponses();
+
+ void _sendResponse(CIMRequestMessage *request,
+ CIMResponseMessage *response);
+
static ThreadReturnType PEGASUS_THREAD_CDECL
_responseProcessor(void* arg);
void _processGetSCMOClassRequest(
ProvAgtGetScmoClassRequestMessage* request);
+ /**
+ This function will fetch the bottom most queueid from the
+ QueueIdStack of the request message and check if the queue isActive().
+ */
+ Boolean _isClientActive(CIMRequestMessage *request_);
+
+ /**
+ This thread will retry the request if the provider goes down
+ before the request is processed.
+ */
+ static ThreadReturnType PEGASUS_THREAD_CDECL _retryRequestHandler(
+ void* arg) ;
+
//
// Private data
//
*/
PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T _providerModuleFailCallback;
+ /**
+ Callback function for async response.
+ */
+ PEGASUS_ASYNC_RESPONSE_CALLBACK_T _asyncResponseCallback;
+
/**
Indicates whether the Provider Agent is active.
*/
*/
Boolean _subscriptionInitComplete;
+ /**
+ OOPProviderManagerRouter ThreadPool pointer.
+ */
+ ThreadPool* _threadPool;
+
};
Uint32 ProviderAgentContainer::_numProviderProcesses = 0;
PEGASUS_INDICATION_CALLBACK_T indicationCallback,
PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T providerModuleFailCallback,
- Boolean subscriptionInitComplete)
+ PEGASUS_ASYNC_RESPONSE_CALLBACK_T asyncResponseCallback,
+ Boolean subscriptionInitComplete,
+ ThreadPool* threadPool)
:
_groupNameWithType(groupName),
_userName(userName),
_indicationCallback(indicationCallback),
_responseChunkCallback(responseChunkCallback),
_providerModuleFailCallback(providerModuleFailCallback),
+ _asyncResponseCallback(asyncResponseCallback),
_isInitialized(false),
- _subscriptionInitComplete(subscriptionInitComplete)
+ _subscriptionInitComplete(subscriptionInitComplete),
+ _threadPool(threadPool)
{
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
"ProviderAgentContainer::ProviderAgentContainer");
pid = _pid;
#endif
+ // In case of a clean shutdown requests which could not be processed are
+ // retried in a new thread.
+ Array<CIMRequestMessage *> retryReqArray;
+
//
// Complete with null responses all outstanding requests on this
// connection
{
AutoMutex tableLock(_outstandingRequestTableMutex);
- CIMResponseMessage* response =
- cleanShutdown ? _REQUEST_NOT_PROCESSED : 0;
-
for (OutstandingRequestTable::Iterator i =
_outstandingRequestTable.start();
i != 0; i++)
{
- PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
- "Completing messageId \"%s\" with a null response.",
- (const char*)i.key().getCString()));
- i.value()->responseMessage = response;
- i.value()->responseReady->signal();
- }
+ Boolean sendResponseNow = false;
+ CIMResponseMessage *response;
+
+ if(cleanShutdown)
+ {
+ MessageType msgType = i.value()->requestMessage->getType();
+
+ if(msgType == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE ||
+ msgType == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE ||
+ msgType ==
+ CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE ||
+ msgType ==
+ CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE ||
+ msgType == CIM_DELETE_SUBSCRIPTION_REQUEST_MESSAGE)
+ {
+ response = i.value()->requestMessage->buildResponse();
+ sendResponseNow = true;
+ }
+ else
+ {
+ // retry the request
+ retryReqArray.append(i.value()->requestMessage);
+ }
+ }
+ else
+ {
+ response = i.value()->requestMessage->buildResponse();
+ response->cimException = PEGASUS_CIM_EXCEPTION(
+ CIM_ERR_FAILED,
+ MessageLoaderParms(
+ "ProviderManager.OOPProviderManagerRouter."
+ "CIMPROVAGT_CONNECTION_LOST",
+ "Lost connection with cimprovagt \"$0\".",
+ _moduleOrGroupName));
+ sendResponseNow = true;
+ }
+
+ if(sendResponseNow)
+ {
+ PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
+ "Completing messageId \"%s\" with a default response.",
+ (const char*)i.key().getCString()));
+ response->setComplete(true);
+ _asyncResponseCallback(
+ i.value()->requestMessage,
+ response);
+ }
+ // delete the response aggregator
+ delete i.value()->respAggregator;
+ }
_outstandingRequestTable.clear();
}
+ if(retryReqArray.size() > 0 )
+ {
+ ThreadStatus rtn = PEGASUS_THREAD_OK;
+ AutoPtr<RetryThreadParam> parms(new RetryThreadParam());
+ parms->pac = this;
+ parms->retryRequestArray = retryReqArray;
+
+ Boolean didRetry = true;
+
+ while((rtn = _threadPool->allocate_and_awaken(
+ (void*)parms.release(),
+ ProviderAgentContainer::_retryRequestHandler))
+ != PEGASUS_THREAD_OK)
+ {
+ if(rtn == PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
+ {
+ Threads::yield();
+ }
+ else
+ {
+ PEG_TRACE((TRC_PROVIDERMANAGER,
+ Tracer::LEVEL1,
+ "Could not allocate thread to retry "
+ "request in %s",
+ (const char *)_moduleOrGroupName. \
+ getCString()));
+ didRetry = false;
+ }
+ }
+
+ if(!didRetry)
+ {
+ for(Uint32 i=0; i<retryReqArray.size(); i++)
+ {
+ CIMResponseMessage *response =
+ retryReqArray[i]->buildResponse();
+ response->setComplete(true);
+ response->cimException =
+ PEGASUS_CIM_EXCEPTION(
+ CIM_ERR_FAILED,
+ MessageLoaderParms("ProviderManager."
+ "OOPProviderManagerRouter."
+ "REQUEST_RETRY_THREAD_"
+ "ALLOCATION_FAILED",
+ "Failed to allocate a thread to "
+ "retry a request in \"$0\".",
+ _moduleOrGroupName));
+
+ _asyncResponseCallback(
+ retryReqArray[i],
+ response);
+ }
+ }
+ }
+
//
// If not a clean shutdown, call the provider module failure callback
//
}
CIMResponseMessage* ProviderAgentContainer::processMessage(
- CIMRequestMessage* request)
+ CIMRequestMessage* request,RespAggCounter* respAggregator)
{
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
"ProviderAgentContainer::processMessage");
CIMResponseMessage* response;
+ MessageType msgType = request->getType();
do
{
- response = _processMessage(request);
+ response = _processMessage(request,respAggregator);
if (response == _REQUEST_NOT_PROCESSED)
{
}
} while (response == _REQUEST_NOT_PROCESSED);
- if (request->getType() == CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE)
+ if (msgType == CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE)
{
_subscriptionInitComplete = true;
}
- else if (request->getType() ==
+ else if (msgType ==
CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE)
{
_subscriptionInitComplete = false;
}
-
PEG_METHOD_EXIT();
return response;
}
CIMResponseMessage* ProviderAgentContainer::_processMessage(
- CIMRequestMessage* request)
+ CIMRequestMessage* request, RespAggCounter *respAggregator)
{
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
"ProviderAgentContainer::_processMessage");
//
// Set up the OutstandingRequestEntry for this request
//
- Semaphore waitSemaphore(0);
- OutstandingRequestEntry outstandingRequestEntry(
- originalMessageId, request, response, &waitSemaphore);
+ SharedPtr<OutstandingRequestEntry> outstandingRequestEntry(
+ new OutstandingRequestEntry(
+ originalMessageId,
+ request,
+ response,
+ respAggregator));
//
// Lock the Provider Agent Container while initializing the
AutoMutex tableLock(_outstandingRequestTableMutex);
_outstandingRequestTable.insert(
- uniqueMessageId, &outstandingRequestEntry);
+ uniqueMessageId, outstandingRequestEntry);
}
// Get the provider module from the ProviderIdContainer to see if
(const char*)uniqueMessageId.getCString()));
request->messageId = uniqueMessageId;
- AnonymousPipe::Status writeStatus =
+ AnonymousPipe::Status writeStatus =
_pipeToAgent->writeMessage(request);
request->messageId = originalMessageId;
if (doProviderModuleOptimization)
{
request->operationContext.set(*origProviderId.get());
- }
+ }
if (writeStatus != AnonymousPipe::STATUS_SUCCESS)
{
{
_providerModuleCache = origProviderId->getModule();
}
+
+ response = request->buildResponse();
+ response->isAsyncResponsePending = true;
+ PEG_METHOD_EXIT();
+
+ return response;
}
catch (...)
{
throw;
}
}
-
- //
- // Wait for the response
- //
- try
- {
- // Must not hold _agentMutex while waiting for the response
- waitSemaphore.wait();
- }
- catch (...)
- {
- // Remove the OutstandingRequestTable entry for this request
- {
- AutoMutex tableLock(_outstandingRequestTableMutex);
- Boolean removed =
- _outstandingRequestTable.remove(uniqueMessageId);
- PEGASUS_ASSERT(removed);
- }
- PEG_METHOD_EXIT();
- 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
- // while requests remain outstanding.
- if (response == 0)
- {
- response = request->buildResponse();
- response->cimException = PEGASUS_CIM_EXCEPTION(
- CIM_ERR_FAILED,
- MessageLoaderParms(
- "ProviderManager.OOPProviderManagerRouter."
- "CIMPROVAGT_CONNECTION_LOST",
- "Lost connection with cimprovagt \"$0\".",
- _moduleOrGroupName));
- }
}
catch (CIMException& e)
{
"Caught unknown exception");
response = request->buildResponse();
response->cimException = PEGASUS_CIM_EXCEPTION(
- CIM_ERR_FAILED, String::EMPTY);
+ CIM_ERR_FAILED, String());
}
response->messageId = originalMessageId;
PEG_METHOD_EXIT();
}
+void ProviderAgentContainer::cleanDisconnectedClientRequests()
+{
+ PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
+ "ProviderAgentContainer::cleanDisconnectedClientRequests");
+
+ // Array to store the keys which need to be remvoed.
+ Array<String> keys;
+
+ AutoMutex tableLock(_outstandingRequestTableMutex);
+ for (OutstandingRequestTable::Iterator i = _outstandingRequestTable.start();
+ i != 0; i++)
+ {
+ if(!_isClientActive(i.value()->requestMessage))
+ {
+ // create empty response and set isComplete to true.
+ AutoPtr<CIMResponseMessage> response;
+ SharedPtr<OutstandingRequestEntry> entry = i.value();
+ response.reset(i.value()->requestMessage->buildResponse());
+ response->setComplete(true);
+ response->messageId = i.value()->originalMessageId;
+ _asyncResponseCallback(
+ i.value()->requestMessage,
+ response.release());
+ keys.append(i.key());
+ }
+ }
+
+ for(Uint32 j=0; j<keys.size();j++)
+ {
+ _outstandingRequestTable.remove(keys[j]);
+ }
+ PEG_METHOD_EXIT();
+}
+
void ProviderAgentContainer::_processGetSCMOClassRequest(
ProvAgtGetScmoClassRequestMessage* request)
{
return;
}
+Boolean ProviderAgentContainer::_isClientActive(CIMRequestMessage *request_)
+{
+ MessageQueue *connectionMQ = MessageQueue::lookup(request_->queueIds[0]);
+ return connectionMQ->isActive();
+}
+
+// Note: This method should not throw an exception. It is used as a thread
+// entry point, and any exceptions thrown are ignored.
+ThreadReturnType PEGASUS_THREAD_CDECL
+ProviderAgentContainer::_retryRequestHandler(void* arg)
+{
+ PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
+ "ProviderAgentContainer::_retryRequestHandler");
+
+ PEGASUS_ASSERT(arg != 0);
+ RetryThreadParam *threadParams=
+ reinterpret_cast<RetryThreadParam *>(arg);
+ Array<CIMRequestMessage *> retryRequests = threadParams->retryRequestArray;
+
+ try
+ {
+ for(Uint32 i=0; i<retryRequests.size(); i++)
+ {
+ threadParams->pac->processMessage(retryRequests[i]);
+ }
+ }
+ catch(Exception &e)
+ {
+ PEG_TRACE((TRC_DISCARDED_DATA, Tracer::LEVEL1,
+ "Unexpected exception in _retryRequestHandler: %s",
+ (const char*)e.getMessage().getCString()));
+ }
+ catch (...)
+ {
+ PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
+ "Unexpected exception in _retryRequestHandler.");
+ }
+ PEG_METHOD_EXIT();
+
+ return ThreadReturnType(0);
+}
+
+
void ProviderAgentContainer::_processResponses()
{
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
response = dynamic_cast<CIMResponseMessage*>(message);
PEGASUS_ASSERT(response != 0);
+ Boolean foundEntry = false;
// Get the OutstandingRequestEntry for this response chunk
- OutstandingRequestEntry* _outstandingRequestEntry = 0;
+ SharedPtr<OutstandingRequestEntry> _outstandingRequestEntry;
{
AutoMutex tableLock(_outstandingRequestTableMutex);
- Boolean foundEntry = _outstandingRequestTable.lookup(
+ 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);
+ if(foundEntry)
+ {
+ // Put the original message ID into the response
+ response->messageId =
+ _outstandingRequestEntry->originalMessageId;
+
+ // Call the response chunk callback to process the chunk
+ // if the client connection is active.
+ // No need to acquire _agentMutex since this a chunk
+ // response callback. The request object will not be
+ // deleted here.
+ _responseChunkCallback(
+ _outstandingRequestEntry->requestMessage, response);
+ }
}
else
{
// Process a completed response
-
CIMResponseMessage* response;
response = dynamic_cast<CIMResponseMessage*>(message);
PEGASUS_ASSERT(response != 0);
+ Boolean foundEntry = false;
// Give the response to the waiting OutstandingRequestEntry
- OutstandingRequestEntry* _outstandingRequestEntry = 0;
+ SharedPtr<OutstandingRequestEntry> _outstandingRequestEntry;
{
AutoMutex tableLock(_outstandingRequestTableMutex);
- Boolean foundEntry = _outstandingRequestTable.lookup(
+ foundEntry = _outstandingRequestTable.lookup(
response->messageId, _outstandingRequestEntry);
- PEGASUS_ASSERT(foundEntry);
- // Remove the completed request from the table
- Boolean removed =
- _outstandingRequestTable.remove(response->messageId);
- PEGASUS_ASSERT(removed);
+ if(foundEntry)
+ {
+ // Remove the completed request from the table
+ Boolean removed = _outstandingRequestTable.remove( \
+ response->messageId);
+ PEGASUS_ASSERT(removed);
+ }
+
}
- _outstandingRequestEntry->responseMessage = response;
- _outstandingRequestEntry->responseReady->signal();
+ if(foundEntry)
+ {
+ if(_outstandingRequestEntry->respAggregator == NULL)
+ {
+ response->messageId =
+ _outstandingRequestEntry->originalMessageId;
+
+ _sendResponse(_outstandingRequestEntry->requestMessage,
+ response);
+ }
+ else
+ {
+ if(_outstandingRequestEntry->respAggregator-> \
+ isComplete(response->cimException))
+ {
+ response->messageId =
+ _outstandingRequestEntry->originalMessageId;
+
+ _sendResponse(
+ _outstandingRequestEntry->requestMessage,
+ response);
+
+ // delete respAggregator pointer now
+ delete _outstandingRequestEntry->respAggregator;
+ }
+ else
+ {
+ // this is not the last response for this request.
+ // Its job is done and it can be deleted now.
+ delete response;
+ }
+ }
+ }
+ else
+ {
+ PEG_TRACE((TRC_DISCARDED_DATA,Tracer::LEVEL4,
+ "The response for message id %s arrived after the " \
+ "client disconnected.",
+ (const char *)response->messageId.getCString()));
+ }
}
}
catch (Exception& e)
}
}
+void ProviderAgentContainer::_sendResponse(CIMRequestMessage *request,
+ CIMResponseMessage *response)
+{
+ response->syncAttributes(request);
+ {
+ // acquire the _agentMutex to make sure that
+ // _processMessage thread has finished
+ // processing the request.
+ AutoMutex agentLock(_agentMutex);
+ }
+
+ // Call the asyncResponseCallback to process
+ // the completed response.
+ _asyncResponseCallback(
+ request,
+ response);
+}
+
ThreadReturnType PEGASUS_THREAD_CDECL
ProviderAgentContainer::_responseProcessor(void* arg)
{
ProviderRegistrationManager *providerRegistrationManager,
PEGASUS_INDICATION_CALLBACK_T indicationCallback,
PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
- PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T providerModuleFailCallback)
+ PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T providerModuleFailCallback,
+ PEGASUS_ASYNC_RESPONSE_CALLBACK_T asyncResponseCallback)
{
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
"OOPProviderManagerRouter::OOPProviderManagerRouter");
_indicationCallback = indicationCallback;
_responseChunkCallback = responseChunkCallback;
_providerModuleFailCallback = providerModuleFailCallback;
+ _asyncResponseCallback = asyncResponseCallback;
_subscriptionInitComplete = false;
_providerRegistrationManager = providerRegistrationManager;
+ _threadPool =
+ new ThreadPool(0, "OOPProviderManagerRouter", 0, 0, deallocateWait);;
PEG_METHOD_EXIT();
}
{
delete i.value();
}
+
+ delete _threadPool;
}
catch (...) {}
Array<ProviderAgentContainer*> paArray =
_lookupProviderAgents(groupNameWithType);
+ Array<ProviderAgentContainer*> paInit;
+
for (Uint32 i=0; i<paArray.size(); i++)
{
//
//
if (paArray[i]->isInitialized())
{
- //
+ paInit.append(paArray[i]);
+ }
+ }
+
+ if(paInit.size() > 0)
+ {
+ RespAggCounter *respAggregator =
+ new RespAggCounter(paInit.size());
+
+ for (Uint32 i=0; i<paInit.size(); i++)
+ {
// Forward the request to the provider agent
//
- response.reset(paArray[i]->processMessage(request));
+ response.reset(
+ paInit[i]->processMessage(request,respAggregator));
// 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 j=0; j < dmResponse->operationalStatus.size(); j++)
- {
- if (dmResponse->operationalStatus[j] ==
- 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;
- }
}
}
Array<ProviderAgentContainer*> paArray =
_lookupProviderAgents(groupNameWithType);
+ // Create an array of initialized provider agents.
+ Array<ProviderAgentContainer*> paInit;
+
+ // create an array of initialized provider agents.
for (Uint32 i=0; i<paArray.size(); i++)
{
- //
- // Do not start up an agent process just to enable the module
- //
- if (paArray[i]->isInitialized())
+ if (paArray[i]->isInitialized())
+ {
+ paInit.append(paArray[i]);
+ }
+ }
+
+ if(paInit.size() > 0 )
+ {
+ RespAggCounter *respAggregator =
+ new RespAggCounter(paInit.size());
+
+ for (Uint32 i=0; i<paInit.size(); i++)
{
//
// 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 j=0; j < emResponse->operationalStatus.size(); j++)
- {
- if (emResponse->operationalStatus[j] ==
- 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;
- }
+ response.reset(
+ paInit[i]->processMessage(request,respAggregator));
}
}
groupNameWithType, userName, userContext,
_indicationCallback, _responseChunkCallback,
_providerModuleFailCallback,
- _subscriptionInitComplete);
+ _asyncResponseCallback,
+ _subscriptionInitComplete,
+ _threadPool);
_providerAgentTable.insert(key, pa);
}
for (ProviderAgentTable::Iterator i = _providerAgentTable.start();
i != 0; i++)
{
- paContainerArray.append(i.value());
+ if(i.value()->isInitialized())
+ {
+ paContainerArray.append(i.value());
+ }
}
}
- CIMException responseException;
-
- // Forward the request to each of the initialized provider agents
- for (Uint32 j = 0; j < paContainerArray.size(); j++)
+ Boolean responsePending = false;
+ CIMResponseMessage *response = request->buildResponse();
+
+ if(paContainerArray.size() > 0 )
{
- ProviderAgentContainer* pa = paContainerArray[j];
- if (pa->isInitialized())
+ RespAggCounter *respAggregator =
+ new RespAggCounter(paContainerArray.size());
+
+ // Forward the request to each of the initialized provider agents
+ for (Uint32 j = 0; j < paContainerArray.size(); j++)
{
+ ProviderAgentContainer* pa = paContainerArray[j];
+
// Note: The ProviderAgentContainer could become uninitialized
// before _ProviderAgentContainer::processMessage() processes
// this request. In this case, the Provider Agent process will
// (unfortunately) be started to process this message.
AutoPtr<CIMResponseMessage> response;
- response.reset(pa->processMessage(request));
- if (response.get() != 0)
- {
- // If the operation failed, save the exception data
- if ((response->cimException.getCode() != CIM_ERR_SUCCESS) &&
- (responseException.getCode() == CIM_ERR_SUCCESS))
- {
- responseException = response->cimException;
- }
- }
+ response.reset(pa->processMessage(request,respAggregator));
+ responsePending = true;
}
- }
- CIMResponseMessage* response = request->buildResponse();
- response->cimException = responseException;
+ response->isAsyncResponsePending = responsePending;
+ }
PEG_METHOD_EXIT();
return response;
}
-void OOPProviderManagerRouter::unloadIdleProviders()
+void OOPProviderManagerRouter::idleTimeCleanup()
{
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
- "OOPProviderManagerRouter::unloadIdleProviders");
+ "OOPProviderManagerRouter::idleTimeCleanup");
// Get a list of the ProviderAgentContainers. We need our own array copy
// because we cannot hold the _providerAgentTableMutex while calling
- // ProviderAgentContainer::unloadIdleProviders().
+ // ProviderAgentContainer::unloadIdleProviders() &
+ // ProviderAgentContainer::cleanDisconnectedClientRequests().
Array<ProviderAgentContainer*> paContainerArray;
{
AutoMutex tableLock(_providerAgentTableMutex);
paContainerArray[j]->unloadIdleProviders();
}
+ // Iterate through the _providerAgentTable cleaning up disconnected clients.
+ for (Uint32 k = 0; k < paContainerArray.size(); k++)
+ {
+ paContainerArray[k]->cleanDisconnectedClientRequests();
+ }
+
PEG_METHOD_EXIT();
}
typedef void (*PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T)(const String &,
const String &, Uint16);
+typedef void (*PEGASUS_ASYNC_RESPONSE_CALLBACK_T)(
+ CIMRequestMessage* request, CIMResponseMessage* response);
+
class ProviderAgentContainer;
typedef HashTable<String, ProviderAgentContainer*, EqualFunc<String>,
ProviderRegistrationManager *providerRegistrationManager,
PEGASUS_INDICATION_CALLBACK_T indicationCallback,
PEGASUS_RESPONSE_CHUNK_CALLBACK_T responseChunkCallback,
- PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T providerModuleFailCallback);
+ PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T providerModuleFailCallback,
+ PEGASUS_ASYNC_RESPONSE_CALLBACK_T asyncResponseCallback);
virtual ~OOPProviderManagerRouter();
virtual Message* processMessage(Message* message);
- virtual void unloadIdleProviders();
+ virtual void idleTimeCleanup();
static ProviderRegistrationManager* getProviderRegistrationManager();
*/
PEGASUS_PROVIDERMODULEFAIL_CALLBACK_T _providerModuleFailCallback;
+ /**
+ Callback function to be called for all async responses.
+ */
+ PEGASUS_ASYNC_RESPONSE_CALLBACK_T _asyncResponseCallback;
+
/**
The _providerAgentTable contains a ProviderAgentContainer entry for
each of the Provider Agent processes for which a request has been
static ProviderRegistrationManager *_providerRegistrationManager;
+ /**
+ Pointer to the MessageQueueService thread pool.
+ */
+ ThreadPool *_threadPool;
+
};
PEGASUS_NAMESPACE_END
#include <Pegasus/Common/Signal.h>
#include <Pegasus/Common/Array.h>
#include <Pegasus/Common/AutoPtr.h>
+#include <Pegasus/Common/AtomicInt.h>
#include <Pegasus/Common/CIMMessageSerializer.h>
#include <Pegasus/Common/CIMMessageDeserializer.h>
#include <Pegasus/Common/Tracer.h>
PEGASUS_NAMESPACE_BEGIN
+// threadCreationFailureLogged will indicate if the thread limit related
+// msg has been logged already. This will help avoid flooding the syslog/audit
+// log with thread limit reached errors.
+static AtomicInt threadCreationFailureLogged(0);
+
/////////////////////////////////////////////////////////////////////////////
//
// ProviderAgentRequest
ProviderAgent::_processRequestAndWriteResponse)) !=
PEGASUS_THREAD_OK)
{
- if (rtn == PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
+ // Yield only for the following request.
+ // CIM_INITIALIZE_PROVIDER_AGENT_REQUEST_MESSAGE,
+ // CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE,
+ // CIM_DISABLE_MODULE_REQUEST_MESSAGE,
+ // CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE,
+ // CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE,
+ // CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE,
+ // CIM_EXPORT_INDICATION_REQUEST_MESSAGE
+ // All the above have already been handled differently
+ // except for CIM_EXPORT_INDICATION_REQUEST_MESSAGE.
+ if (rtn == PEGASUS_THREAD_INSUFFICIENT_RESOURCES &&
+ request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE)
{
Threads::yield();
}
{
PEG_TRACE_CSTRING(TRC_PROVIDERAGENT, Tracer::LEVEL1,
"Could not allocate thread to process agent request.");
+ MessageLoaderParms msgLoaderPrms(
+ "ProviderManager.ProviderAgent.ProviderAgent."
+ "THREAD_ALLOCATION_FAILED",
+ "Failed to allocate a thread in cimprovagt \"$0\".",
+ _agentId);
AutoPtr<CIMResponseMessage> response(request->buildResponse());
response->cimException = PEGASUS_CIM_EXCEPTION_L(
- CIM_ERR_FAILED,
- MessageLoaderParms(
- "ProviderManager.ProviderAgent.ProviderAgent."
- "THREAD_ALLOCATION_FAILED",
- "Failed to allocate a thread in cimprovagt \"$0\".",
- _agentId));
+ CIM_ERR_FAILED,msgLoaderPrms);
// Return response to CIM Server
_writeResponse(response.get());
+ // make an entry in syslog for this behaviour.
+ if(threadCreationFailureLogged.get() == 0)
+ {
+ threadCreationFailureLogged.inc();
+ Logger::put_l(Logger::STANDARD_LOG,
+ System::CIMSERVER,Logger::WARNING,msgLoaderPrms);
+ }
+
delete agentRequest;
delete request;
- break;
+ PEG_METHOD_EXIT();
+ return true;
}
}
+
+ // Control will reach here only if the thread creation was successful.
+ // Hence this is the right place to reset threadCreationFailureLogged
+ // to that if the thread limit is reached again it is logged.
+ if(threadCreationFailureLogged.get() == 1)
+ {
+ threadCreationFailureLogged.dec();
+ }
}
PEG_METHOD_EXIT();
try
{
- myself->_providerManagerRouter.unloadIdleProviders();
+ myself->_providerManagerRouter.idleTimeCleanup();
}
catch (...)
{
virtual Message* processMessage(Message* message) = 0;
/**
- Unload idle providers in all active ProviderManagers.
+ Cleanup idle providers and disconnected client requests in all
+ active ProviderManagers.
Note: This operation may take a long time to complete and should
be called on a non-critical thread.
*/
- virtual void unloadIdleProviders() = 0;
+ virtual void idleTimeCleanup() = 0;
/**
Sets the SubscriptionInitComplete flag indicating whether the Indication
#include <Pegasus/ProviderManager2/ProviderManagerzOS_inline.h>
#endif
-
PEGASUS_NAMESPACE_BEGIN
const String PG_PROVMODULE_GROUPNAME_CIMSERVER = "CIMServer";
_providerRegistrationManager = providerRegistrationManager;
- _unloadIdleProvidersBusy = 0;
+ _idleTimeCleanupBusy = 0;
_forceProviderProcesses = ConfigManager::parseBooleanValue(
ConfigManager::getInstance()->getCurrentValue(
providerRegistrationManager,
indicationCallback,
responseChunkCallback,
- providerModuleFailureCallback);
+ providerModuleFailureCallback,
+ asyncResponseCallback);
_basicProviderManagerRouter = new BasicProviderManagerRouter(
indicationCallback,
PEGASUS_ASSERT(request->getType() == ASYNC_ASYNC_LEGACY_OP_START);
Message* legacy =
- static_cast<AsyncLegacyOperationStart *>(request)->get_action();
-
- AutoPtr<Message> xmessage(legacy);
+ static_cast<AsyncLegacyOperationStart *>(request)->get_action();
+ static_cast<AsyncLegacyOperationStart *>(request)->put_action(legacy);
// Set the client's requested language into this service thread.
// This will allow functions in this service to return messages
// ATTN: Use CIMEnableModuleResponseMessage operationalStatus?
CIMEnableModuleResponseMessage * emResp =
dynamic_cast<CIMEnableModuleResponseMessage*>(response.get());
- if (emResp->cimException.getCode() == CIM_ERR_SUCCESS)
+ // If the provider is not loaded then update the provider status in
+ // this thread or else the response thread will call
+ // asyncResponseCallback which will update the provider status.
+ if(!emResp->isAsyncResponsePending)
{
- //
- // On a successful enable, remove Stopped status and
- // append OK status
- //
- Array<Uint16> removeStatus;
- Array<Uint16> appendStatus;
- removeStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPED);
- appendStatus.append (CIM_MSE_OPSTATUS_VALUE_OK);
- _updateProviderModuleStatus(
- providerModule, removeStatus, appendStatus);
+ _updateModuleStatusToEnabled(emResp, providerModule);
}
}
else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
// Forward the request to the ProviderManager
response.reset(_processMessage(request));
- // Update provider module status based on success or failure
- if (updateModuleStatus)
+ // If the provider is not initialized then update the status of the
+ // provider in this thread since there will be no response from
+ // any provider.
+ CIMDisableModuleResponseMessage * dmResp =
+ dynamic_cast<CIMDisableModuleResponseMessage*>(response.get());
+ if(!dmResp->isAsyncResponsePending)
{
- CIMDisableModuleResponseMessage * dmResp =
- dynamic_cast<CIMDisableModuleResponseMessage*>(
- response.get());
- if (dmResp->cimException.getCode() != CIM_ERR_SUCCESS)
+ if (updateModuleStatus)
{
- //
- // On an unsuccessful disable, remove Stopping status
- //
- Array<Uint16> removeStatus;
- Array<Uint16> appendStatus;
- removeStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPING);
- _updateProviderModuleStatus(
- providerModule, removeStatus, appendStatus);
- }
- else
- {
- // Disable may or may not have been successful,
- // depending on whether there are outstanding requests.
- // Remove Stopping status
- // Append status, if any, from disable module response
- Array<Uint16> removeStatus;
- Array<Uint16> appendStatus;
- removeStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPING);
- if (dmResp->operationalStatus.size() > 0)
- {
- //
- // On a successful disable, remove an OK or a Degraded
- // status, if present
- //
- if (dmResp->operationalStatus[
- dmResp->operationalStatus.size()-1] ==
- CIM_MSE_OPSTATUS_VALUE_STOPPED)
- {
- removeStatus.append (CIM_MSE_OPSTATUS_VALUE_OK);
- removeStatus.append
- (CIM_MSE_OPSTATUS_VALUE_DEGRADED);
- }
- appendStatus.append (dmResp->operationalStatus[
- dmResp->operationalStatus.size()-1]);
- }
- _updateProviderModuleStatus(
- providerModule, removeStatus, appendStatus);
+ _updateModuleStatusToDisabled(dmResp,providerModule);
}
}
}
response.reset(cimResponse);
}
- AsyncLegacyOperationResult * async_result =
- new AsyncLegacyOperationResult(
- op,
- response.release());
+ // all responses will be handled by the asyncResponseCallback
+ // Certain requests like disable and enable module will be processed
+ // in this thread if the module is not loaded yet.
+ CIMResponseMessage *cimResponse = dynamic_cast<CIMResponseMessage*>(
+ response.get());
- _complete_op_node(op);
+ if(!cimResponse->isAsyncResponsePending)
+ {
+ AsyncLegacyOperationResult * async_result =
+ new AsyncLegacyOperationResult(
+ op,
+ response.release());
+
+ _complete_op_node(op);
+ }
PEG_METHOD_EXIT();
}
PEG_METHOD_EXIT();
}
+
+void ProviderManagerService::asyncResponseCallback(
+ CIMRequestMessage* request,
+ CIMResponseMessage* response)
+{
+ PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
+ "ProviderManagerService::asyncResponseCallback");
+
+ AsyncLegacyOperationStart *requestAsync =
+ dynamic_cast<AsyncLegacyOperationStart *>(request->get_async());
+ request->put_async(requestAsync);
+ PEGASUS_ASSERT(requestAsync);
+
+ AsyncOpNode *op = requestAsync->op;
+ PEGASUS_ASSERT(op);
+
+ try
+ {
+ // Only complete responses for async responses are handled
+ // here.
+ PEGASUS_ASSERT(response->isComplete() == true);
+
+ if(request->operationContext.contains(
+ AcceptLanguageListContainer::NAME))
+ {
+ Thread::setLanguages(
+ ((AcceptLanguageListContainer)request->operationContext.get(
+ AcceptLanguageListContainer::NAME)).getLanguages());
+ }
+ else
+ {
+ Thread::setLanguages(AcceptLanguageList());
+ }
+
+ if(request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE)
+ {
+ _allProvidersStopped = true;
+ }
+ else if(request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
+ {
+ // Handle CIMEnableModuleRequestMessage
+ CIMEnableModuleRequestMessage * emReq =
+ dynamic_cast<CIMEnableModuleRequestMessage*>(request);
+
+ CIMInstance providerModule = emReq->providerModule;
+
+ // If successful, update provider module status to OK
+ // ATTN: Use CIMEnableModuleResponseMessage operationalStatus?
+ CIMEnableModuleResponseMessage * emResp =
+ dynamic_cast<CIMEnableModuleResponseMessage*>(response);
+ providerManagerService->_updateModuleStatusToEnabled(
+ emResp,providerModule);
+ }
+ else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
+ {
+ // Handle CIMDisableModuleRequestMessage
+ CIMDisableModuleRequestMessage * dmReq =
+ dynamic_cast<CIMDisableModuleRequestMessage*>(request);
+
+ CIMInstance providerModule = dmReq->providerModule;
+ Boolean updateModuleStatus = !dmReq->disableProviderOnly;
+
+ // Update provider module status based on success or failure
+ if (updateModuleStatus)
+ {
+ CIMDisableModuleResponseMessage * dmResp =
+ dynamic_cast<CIMDisableModuleResponseMessage*>(
+ response);
+ providerManagerService->_updateModuleStatusToDisabled(
+ dmResp,providerModule);
+ }
+ }
+ }
+ catch (Exception &e)
+ {
+ response->cimException =
+ CIMException(CIM_ERR_FAILED, e.getMessage());
+ }
+ catch (PEGASUS_STD(exception)& e)
+ {
+ response->cimException = CIMException(CIM_ERR_FAILED, e.what());
+ }
+ catch (...)
+ {
+ response->cimException = CIMException(CIM_ERR_FAILED, String());
+ }
+
+ AsyncLegacyOperationResult * async_result =
+ new AsyncLegacyOperationResult(
+ op,
+ response);
+
+ providerManagerService->_complete_op_node(op);
+
+ PEG_METHOD_EXIT();
+}
+
Message* ProviderManagerService::_processMessage(CIMRequestMessage* request)
{
Message* response = 0;
response = _oopProviderManagerRouter->processMessage(request);
}
-
- if (request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE)
- {
- _allProvidersStopped = true;
- }
}
else
{
return response;
}
-void ProviderManagerService::unloadIdleProviders()
+void ProviderManagerService::idleTimeCleanup()
{
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
- "ProviderManagerService::unloadIdleProviders");
+ "ProviderManagerService::idleTimeCleanup");
- // Ensure that only one _unloadIdleProvidersHandler thread runs at a time
- _unloadIdleProvidersBusy++;
- if (_unloadIdleProvidersBusy.get() != 1)
+ // Ensure that only one _idleTimeCleanupHandler thread runs at a time
+ _idleTimeCleanupBusy++;
+ if (_idleTimeCleanupBusy.get() != 1)
{
- _unloadIdleProvidersBusy--;
+ _idleTimeCleanupBusy--;
PEG_METHOD_EXIT();
return;
}
//
- // Start an idle provider unload thread
+ // Start an idle time cleanup thread.
//
if (_thread_pool->allocate_and_awaken((void*)this,
- ProviderManagerService::_unloadIdleProvidersHandler) !=
+ ProviderManagerService::_idleTimeCleanupHandler) !=
PEGASUS_THREAD_OK)
{
PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL1,
- "Could not allocate thread for %s to unload idle providers.",
+ "Could not allocate thread for %s to cleanup idle providers \
+ and request.",
getQueueName()));
// If we fail to allocate a thread, don't retry now.
- _unloadIdleProvidersBusy--;
+ _idleTimeCleanupBusy--;
PEG_METHOD_EXIT();
return;
}
- // Note: _unloadIdleProvidersBusy is decremented in
- // _unloadIdleProvidersHandler
+ // Note: _idleTimeCleanupBusy is decremented in
+ // _idleTimeCleanupHandler
PEG_METHOD_EXIT();
}
ThreadReturnType PEGASUS_THREAD_CDECL
-ProviderManagerService::_unloadIdleProvidersHandler(void* arg) throw()
+ProviderManagerService::_idleTimeCleanupHandler(void* arg) throw()
{
ProviderManagerService* myself =
reinterpret_cast<ProviderManagerService*>(arg);
try
{
PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
- "ProviderManagerService::_unloadIdleProvidersHandler");
+ "ProviderManagerService::_idleTimeCleanupHandler");
if (myself->_basicProviderManagerRouter)
{
try
{
- myself->_basicProviderManagerRouter->unloadIdleProviders();
+ myself->_basicProviderManagerRouter->idleTimeCleanup();
}
catch (...)
{
// Ignore errors
PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
"Unexpected exception from "
- "BasicProviderManagerRouter::_unloadIdleProviders");
+ "BasicProviderManagerRouter::idleTimeCleanup");
}
}
{
try
{
- myself->_oopProviderManagerRouter->unloadIdleProviders();
+ myself->_oopProviderManagerRouter->idleTimeCleanup();
}
catch (...)
{
// Ignore errors
PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
"Unexpected exception from "
- "OOPProviderManagerRouter::_unloadIdleProviders");
+ "OOPProviderManagerRouter::idleTimeCleanup");
}
}
- myself->_unloadIdleProvidersBusy--;
+ myself->_idleTimeCleanupBusy--;
PEG_METHOD_EXIT();
}
catch (...)
{
// Ignore errors
PEG_TRACE_CSTRING(TRC_PROVIDERMANAGER, Tracer::LEVEL2,
- "Unexpected exception in _unloadIdleProvidersHandler");
+ "Unexpected exception in _idleTimeCleanupHandler");
- myself->_unloadIdleProvidersBusy--;
+ myself->_idleTimeCleanupBusy--;
}
return ThreadReturnType(0);
}
+void ProviderManagerService::_updateModuleStatusToEnabled(
+ CIMEnableModuleResponseMessage *emResp,
+ CIMInstance &providerModule)
+{
+ if (emResp->cimException.getCode() == CIM_ERR_SUCCESS)
+ {
+ //
+ // On a successful enable, remove Stopped status and
+ // append OK status
+ //
+ Array<Uint16> removeStatus;
+ Array<Uint16> appendStatus;
+ removeStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPED);
+ appendStatus.append (CIM_MSE_OPSTATUS_VALUE_OK);
+ _updateProviderModuleStatus(
+ providerModule, removeStatus, appendStatus);
+ }
+}
+
+void ProviderManagerService::_updateModuleStatusToDisabled(
+ CIMDisableModuleResponseMessage *dmResp,
+ CIMInstance &providerModule)
+{
+ // Update provider module status based on success or failure
+ if (dmResp->cimException.getCode() != CIM_ERR_SUCCESS)
+ {
+ //
+ // On an unsuccessful disable, remove Stopping status
+ //
+ Array<Uint16> removeStatus;
+ Array<Uint16> appendStatus;
+ removeStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPING);
+ _updateProviderModuleStatus(
+ providerModule, removeStatus, appendStatus);
+ }
+ else
+ {
+ // Disable may or may not have been successful,
+ // depending on whether there are outstanding requests.
+ // Remove Stopping status
+ // Append status, if any, from disable module response
+ Array<Uint16> removeStatus;
+ Array<Uint16> appendStatus;
+ removeStatus.append (CIM_MSE_OPSTATUS_VALUE_STOPPING);
+ if (dmResp->operationalStatus.size() > 0)
+ {
+ //
+ // On a successful disable, remove an OK or
+ // a Degraded status, if present
+ //
+ if (dmResp->operationalStatus[
+ dmResp->operationalStatus.size()-1] ==
+ CIM_MSE_OPSTATUS_VALUE_STOPPED)
+ {
+ removeStatus.append (CIM_MSE_OPSTATUS_VALUE_OK);
+ removeStatus.append
+ (CIM_MSE_OPSTATUS_VALUE_DEGRADED);
+ }
+ appendStatus.append (dmResp->operationalStatus[
+ dmResp->operationalStatus.size()-1]);
+ }
+ _updateProviderModuleStatus(
+ providerModule, removeStatus, appendStatus);
+ }
+}
+
// Updates the providerModule instance and the ProviderRegistrationManager
//
// This method is used to update the provider module status when the module is
virtual ~ProviderManagerService();
- void unloadIdleProviders();
+ void idleTimeCleanup();
static void indicationCallback(CIMProcessIndicationRequestMessage* request);
static void responseChunkCallback(
CIMRequestMessage* request, CIMResponseMessage* response);
+ static void asyncResponseCallback(
+ CIMRequestMessage* request, CIMResponseMessage* response);
/**
Callback function to be called upon detection of failure of a
Message* _processMessage(CIMRequestMessage* request);
static ThreadReturnType PEGASUS_THREAD_CDECL
- _unloadIdleProvidersHandler(void* arg) throw();
+ _idleTimeCleanupHandler(void* arg) throw();
+
+ void _updateModuleStatusToEnabled(
+ CIMEnableModuleResponseMessage *emResp,
+ CIMInstance &providerModule);
+
+ void _updateModuleStatusToDisabled(
+ CIMDisableModuleResponseMessage *dmResp,
+ CIMInstance &providerModule);
void _updateProviderModuleStatus(
CIMInstance& providerModule,
static Uint32 _indicationServiceQueueId;
/**
- Indicates the number of threads currently attempting to unload idle
- providers. This value is used to prevent multiple threads from
- unloading idle providers at the same time.
+ Indicates the number of threads currently attempting to cleanup idle
+ providers and clean disconnected client requests. This value is used
+ to prevent multiple threads from initiating cleanup the same time.
*/
- AtomicInt _unloadIdleProvidersBusy;
+ AtomicInt _idleTimeCleanupBusy;
};
PEGASUS_NAMESPACE_END
try
{
- _providerManager->unloadIdleProviders();
+ _providerManager->idleTimeCleanup();
MessageQueueService::get_thread_pool()->cleanupIdleThreads();
#ifdef PEGASUS_ENABLE_PROTOCOL_WSMAN
_wsmProcessor->cleanupExpiredContexts();
#endif
-
}
catch (...)
{
*/
ProviderManager.OOPProviderManagerRouter.OOP_PROVIDER_MODULE_FAILURE_DETECTED:string {"PGS13606: A failure was detected in provider module {0}. The generation of indications by providers in this module may be affected. To ensure these providers are serving active subscriptions, disable and then re-enable this module using the cimprovider command."}
+ /**
+ * @note PGS13607
+ * Substitution {0} is the provider module group name.
+ */
+ ProviderManager.OOPProviderManagerRouter.REQUEST_RETRY_THREAD_ALLOCATION_FAILED:string {"PGS13607: Failed to allocate a thread to retry a request in \"{0}\"."}
+
// ==========================================================
// Messages for ProviderManager.ProviderAgent.cimprovagt
--- /dev/null
+#//%LICENSE////////////////////////////////////////////////////////////////
+#//
+#// Licensed to The Open Group (TOG) under one or more contributor license
+#// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+#// this work for additional information regarding copyright ownership.
+#// Each contributor licenses this file to you under the OpenPegasus Open
+#// Source License; you may not use this file except in compliance with the
+#// License.
+#//
+#// 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.
+#//
+#//////////////////////////////////////////////////////////////////////////
+ROOT = ../../../..
+
+DIR = Providers/TestProviders/FaultyInstanceProvider
+
+include $(ROOT)/mak/config.mak
+
+LIBRARY = TestFaultyProvider
+
+LIBRARIES = \
+ pegprovider \
+ pegclient \
+ pegcommon
+
+SOURCES = \
+ TestFaultyProviderMain.cpp \
+ TestFaultyInstanceProvider.cpp \
+ TestGoodIndicationProvider.cpp
+
+include $(ROOT)/mak/dynamic-library.mak
+
+tests:
+
--- /dev/null
+//%LICENSE////////////////////////////////////////////////////////////////
+//
+// Licensed to The Open Group (TOG) under one or more contributor license
+// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+// this work for additional information regarding copyright ownership.
+// Each contributor licenses this file to you under the OpenPegasus Open
+// Source License; you may not use this file except in compliance with the
+// License.
+//
+// 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 <cstring>
+#include <Pegasus/Common/Config.h>
+#include <Pegasus/Provider/CIMInstanceProvider.h>
+
+#include <Pegasus/Common/CIMDateTime.h>
+#include <Pegasus/Common/Threads.h>
+
+#include "TestFaultyInstanceProvider.h"
+
+PEGASUS_USING_STD;
+PEGASUS_NAMESPACE_BEGIN
+
+#define CIMSERVER_CLEANUP_TIME 600
+#define CONN_TIME_OUT 70
+#define DEFAULT_CLIENT_TIMEOUT 20 // default timeout
+
+TestFaultyInstanceProvider::TestFaultyInstanceProvider()
+{
+}
+
+TestFaultyInstanceProvider::~TestFaultyInstanceProvider()
+{
+}
+
+void TestFaultyInstanceProvider::initialize(CIMOMHandle& cimom)
+{
+ // save cimom handle
+ //_cimom = cimom;
+
+ char namebuf[20];
+ char pathbuf[45];
+ memset(namebuf, 0x00, sizeof(namebuf));
+ memset(pathbuf, 0x00, sizeof(pathbuf));
+
+ // create default instances
+ for (Uint32 i = 1; i <= 2; i++)
+ {
+ sprintf(namebuf, "%u", i);
+ sprintf(pathbuf, "TST_FaultyInstanceInstance.Name=\"%u\"", i);
+ {
+ CIMInstance instance("TST_FaultyInstanceInstance");
+
+ instance.addProperty(CIMProperty("name", String(namebuf)));
+ instance.addProperty(CIMProperty("s", String("specified")));
+ instance.addProperty(CIMProperty("n", Uint64(i)));
+ instance.addProperty(CIMProperty("f", Real64(Real64(i)+0.001)));
+ instance.addProperty(
+ CIMProperty("d", CIMDateTime::getCurrentDateTime()));
+
+ instance.setPath(CIMObjectPath(pathbuf));
+
+ _instances.append(instance);
+ }
+ }
+}
+
+void TestFaultyInstanceProvider::terminate()
+{
+ delete this;
+}
+
+void TestFaultyInstanceProvider::getInstance(
+ const OperationContext& context,
+ const CIMObjectPath& instanceReference,
+ const Boolean includeQualifiers,
+ const Boolean includeClassOrigin,
+ const CIMPropertyList& propertyList,
+ InstanceResponseHandler& handler)
+{
+ throw CIMException(CIM_ERR_NOT_SUPPORTED);
+}
+
+void TestFaultyInstanceProvider::enumerateInstances(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ const Boolean includeQualifiers,
+ const Boolean includeClassOrigin,
+ const CIMPropertyList& propertyList,
+ InstanceResponseHandler& handler)
+{
+ throw CIMException(CIM_ERR_NOT_SUPPORTED);
+}
+
+void TestFaultyInstanceProvider::enumerateInstanceNames(
+ const OperationContext& context,
+ const CIMObjectPath& classReference,
+ ObjectPathResponseHandler& handler)
+{
+ _requestCount.inc();
+
+ Uint32 sleepDuration=0;
+ if(_requestCount.get() % 2)
+ {
+ //few requets will respond after cimserver cleanup time.
+ sleepDuration = CIMSERVER_CLEANUP_TIME * 1000 ;
+ }
+ else if(_requestCount.get() % 16)
+ {
+ // respond correctly.
+ }
+ else
+ {
+ //few requests will respond after client connections have timed out
+ //but before cimserver cleanup time.
+ sleepDuration = CONN_TIME_OUT *1000;
+ }
+
+ handler.processing();
+
+ Threads::sleep(sleepDuration);
+
+ for (Uint32 i = 0, n = _instances.size(); i < n; i++)
+ {
+ try
+ {
+ handler.deliver(_instances[i].getPath());
+ }
+ catch (CIMException&)
+ {
+ // suppress error
+ }
+ }
+
+ handler.complete();
+}
+
+void TestFaultyInstanceProvider::modifyInstance(
+ const OperationContext& context,
+ const CIMObjectPath& instanceReference,
+ const CIMInstance& instanceObject,
+ const Boolean includeQualifiers,
+ const CIMPropertyList& propertyList,
+ ResponseHandler& handler)
+{
+ throw CIMException(CIM_ERR_NOT_SUPPORTED);
+}
+
+void TestFaultyInstanceProvider::createInstance(
+ const OperationContext& context,
+ const CIMObjectPath& instanceReference,
+ const CIMInstance& instanceObject,
+ ObjectPathResponseHandler& handler)
+{
+ throw CIMException(CIM_ERR_NOT_SUPPORTED);
+}
+
+void TestFaultyInstanceProvider::deleteInstance(
+ const OperationContext& context,
+ const CIMObjectPath& instanceReference,
+ ResponseHandler& handler)
+{
+ throw CIMException(CIM_ERR_NOT_SUPPORTED);
+}
+
+PEGASUS_NAMESPACE_END
--- /dev/null
+//%LICENSE////////////////////////////////////////////////////////////////
+//
+// Licensed to The Open Group (TOG) under one or more contributor license
+// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+// this work for additional information regarding copyright ownership.
+// Each contributor licenses this file to you under the OpenPegasus Open
+// Source License; you may not use this file except in compliance with the
+// License.
+//
+// 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.
+//
+//////////////////////////////////////////////////////////////////////////
+//
+//%///////////////////////////////////////////////////////////////////////
+
+#ifndef Pegasus_TestFaultyInstanceProvider_h
+#define Pegasus_TestFaultyInstanceProvider_h
+
+#include <Pegasus/Common/Config.h>
+#include <Pegasus/Common/AtomicInt.h>
+#include <Pegasus/Provider/CIMInstanceProvider.h>
+
+PEGASUS_NAMESPACE_BEGIN
+
+class TestFaultyInstanceProvider :
+ public CIMInstanceProvider
+{
+public:
+ TestFaultyInstanceProvider();
+ virtual ~TestFaultyInstanceProvider();
+
+ // CIMProvider interface
+ virtual void initialize(CIMOMHandle& cimom);
+ virtual void terminate();
+
+ // CIMInstanceProvider interface
+ virtual void getInstance(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ const Boolean includeQualifiers,
+ const Boolean includeClassOrigin,
+ const CIMPropertyList& propertyList,
+ InstanceResponseHandler& handler);
+
+ virtual void enumerateInstances(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ const Boolean includeQualifiers,
+ const Boolean includeClassOrigin,
+ const CIMPropertyList& propertyList,
+ InstanceResponseHandler& handler);
+
+ virtual void enumerateInstanceNames(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ ObjectPathResponseHandler& handler);
+
+ virtual void modifyInstance(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ const CIMInstance& obj,
+ const Boolean includeQualifiers,
+ const CIMPropertyList& propertyList,
+ ResponseHandler& handler);
+
+ virtual void createInstance(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ const CIMInstance& obj,
+ ObjectPathResponseHandler& handler);
+
+ virtual void deleteInstance(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ ResponseHandler& handler);
+
+protected:
+ Array<CIMInstance> _instances;
+ AtomicInt _requestCount;
+};
+
+PEGASUS_NAMESPACE_END
+
+#endif
--- /dev/null
+//%LICENSE////////////////////////////////////////////////////////////////
+//
+// Licensed to The Open Group (TOG) under one or more contributor license
+// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+// this work for additional information regarding copyright ownership.
+// Each contributor licenses this file to you under the OpenPegasus Open
+// Source License; you may not use this file except in compliance with the
+// License.
+//
+// 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/Config.h>
+
+#include "TestFaultyInstanceProvider.h"
+#include "TestGoodIndicationProvider.h"
+
+PEGASUS_NAMESPACE_BEGIN
+
+extern "C"
+PEGASUS_EXPORT CIMProvider* PegasusCreateProvider(const String& providerName)
+{
+ if (String::equalNoCase(providerName, "TestFaultyInstanceProvider"))
+ {
+ return new TestFaultyInstanceProvider();
+ }
+ if (String::equalNoCase(providerName, "TestGoodIndicationProvider"))
+ {
+ return new TestGoodIndicationProvider();
+ }
+
+ return 0;
+}
+
+PEGASUS_NAMESPACE_END
--- /dev/null
+//%LICENSE////////////////////////////////////////////////////////////////
+//
+// Licensed to The Open Group (TOG) under one or more contributor license
+// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+// this work for additional information regarding copyright ownership.
+// Each contributor licenses this file to you under the OpenPegasus Open
+// Source License; you may not use this file except in compliance with the
+// License.
+//
+// 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/PegasusAssert.h>
+
+#include "TestGoodIndicationProvider.h"
+
+PEGASUS_USING_STD;
+
+PEGASUS_USING_PEGASUS;
+
+TestGoodIndicationProvider::TestGoodIndicationProvider() throw ()
+{
+}
+
+TestGoodIndicationProvider::~TestGoodIndicationProvider() throw ()
+{
+}
+
+void TestGoodIndicationProvider::initialize(CIMOMHandle& cimom)
+{
+ _cimom = cimom;
+}
+
+void TestGoodIndicationProvider::terminate()
+{
+ delete this;
+}
+
+void TestGoodIndicationProvider::enableIndications(
+ IndicationResponseHandler& handler)
+{
+}
+
+void TestGoodIndicationProvider::disableIndications()
+{
+}
+
+void TestGoodIndicationProvider::createSubscription(
+ const OperationContext& context,
+ const CIMObjectPath& subscriptionName,
+ const Array <CIMObjectPath>& classNames,
+ const CIMPropertyList& propertyList,
+ const Uint16 repeatNotificationPolicy)
+{
+ // do nothing
+}
+
+void TestGoodIndicationProvider::modifySubscription(
+ const OperationContext& context,
+ const CIMObjectPath& subscriptionName,
+ const Array <CIMObjectPath>& classNames,
+ const CIMPropertyList& propertyList,
+ const Uint16 repeatNotificationPolicy)
+{
+ throw CIMException(CIM_ERR_NOT_SUPPORTED);
+}
+
+void TestGoodIndicationProvider::deleteSubscription(
+ const OperationContext& context,
+ const CIMObjectPath& subscriptionName,
+ const Array <CIMObjectPath>& classNames)
+{
+}
--- /dev/null
+//%LICENSE////////////////////////////////////////////////////////////////
+//
+// Licensed to The Open Group (TOG) under one or more contributor license
+// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+// this work for additional information regarding copyright ownership.
+// Each contributor licenses this file to you under the OpenPegasus Open
+// Source License; you may not use this file except in compliance with the
+// License.
+//
+// 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.
+//
+//////////////////////////////////////////////////////////////////////////
+//
+//%///////////////////////////////////////////////////////////////////////
+
+#ifndef Pegasus_TestGoodIndicationProvider_h
+#define Pegasus_TestGoodIndicationProvider_h
+
+#include <Pegasus/Common/Config.h>
+#include <Pegasus/Provider/CIMIndicationProvider.h>
+#include <Pegasus/Provider/CIMMethodProvider.h>
+
+PEGASUS_USING_PEGASUS;
+
+class TestGoodIndicationProvider:
+ public CIMIndicationProvider
+{
+public:
+ TestGoodIndicationProvider() throw();
+ virtual ~TestGoodIndicationProvider() throw();
+
+ // CIMProvider interface
+ virtual void initialize(CIMOMHandle& cimom);
+ virtual void terminate();
+
+ // CIMIndicationProvider interface
+ virtual void enableIndications(IndicationResponseHandler& handler);
+ virtual void disableIndications();
+
+ virtual void createSubscription(
+ const OperationContext& context,
+ const CIMObjectPath& subscriptionName,
+ const Array <CIMObjectPath>& classNames,
+ const CIMPropertyList& propertyList,
+ const Uint16 repeatNotificationPolicy);
+
+ virtual void modifySubscription(
+ const OperationContext& context,
+ const CIMObjectPath& subscriptionName,
+ const Array <CIMObjectPath>& classNames,
+ const CIMPropertyList& propertyList,
+ const Uint16 repeatNotificationPolicy);
+
+ virtual void deleteSubscription(
+ const OperationContext& context,
+ const CIMObjectPath& subscriptionName,
+ const Array <CIMObjectPath>& classNames);
+
+private:
+
+ CIMOMHandle _cimom;
+
+};
+
+#endif
--- /dev/null
+#//%LICENSE////////////////////////////////////////////////////////////////
+#//
+#// Licensed to The Open Group (TOG) under one or more contributor license
+#// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+#// this work for additional information regarding copyright ownership.
+#// Each contributor licenses this file to you under the OpenPegasus Open
+#// Source License; you may not use this file except in compliance with the
+#// License.
+#//
+#// 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.
+#//
+#//////////////////////////////////////////////////////////////////////////
+ROOT = ../../../../..
+
+PEGASUS_ZOS_PROGRAM_OBJECT = yes
+
+DIR = Providers/TestProviders/FaultyInstanceProvider/testclient
+
+include $(ROOT)/mak/config.mak
+
+LIBRARIES = \
+ pegclient \
+ peggeneral \
+ pegcommon
+
+EXTRA_INCLUDES = $(SYS_INCLUDES)
+
+LOCAL_DEFINES = -DPEGASUS_INTERNALONLY
+
+PROGRAM = TestFaultyInstanceProviderClient
+
+SOURCES = TestFaultyInstanceProviderClient.cpp
+
+include $(ROOT)/mak/program.mak
+
+include $(ROOT)/mak/test.mak
+
+tests:
+
+poststarttests:
+
+runAvailabilityTest:
+# When tests are run through valgrind the client timeout
+# is disabled hence no point running these tests, since
+# the client will never timeout.
+ifndef PEGASUS_TEST_VALGRIND_LOG_DIR
+ @cimprovider -dm TestFaultyProviderModule
+ @cimprovider -em TestFaultyProviderModule
+ @cimprovider -dm TestGoodInstanceProviderModule
+ @cimprovider -em TestGoodInstanceProviderModule
+ $(PROGRAM)
+endif
--- /dev/null
+//%LICENSE////////////////////////////////////////////////////////////////
+//
+// Licensed to The Open Group (TOG) under one or more contributor license
+// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+// this work for additional information regarding copyright ownership.
+// Each contributor licenses this file to you under the OpenPegasus Open
+// Source License; you may not use this file except in compliance with the
+// License.
+//
+// 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 <cstdio>
+
+#include <Pegasus/Common/Thread.h>
+#include <Pegasus/Common/Config.h>
+#include <Pegasus/Common/Constants.h>
+#include <Pegasus/Common/Exception.h>
+#include <Pegasus/Common/ArrayInternal.h>
+#include <Pegasus/Common/AutoPtr.h>
+#include <Pegasus/Common/AtomicInt.h>
+#include <Pegasus/Common/PegasusAssert.h>
+#include <Pegasus/General/Stopwatch.h>
+#include <Pegasus/Common/System.h>
+#include <Pegasus/Common/Exception.h>
+#include <Pegasus/Client/CIMClient.h>
+#if defined(PEGASUS_OS_TYPE_UNIX)
+# include <unistd.h>
+# include <errno.h>
+# include <limits.h>
+#endif
+
+
+PEGASUS_USING_PEGASUS;
+PEGASUS_USING_STD;
+
+
+/*
+ * Here we test the availability of cimserver even after it crosses
+ * its socket fd limit(max client connections) or a faulty provider crosses
+ * its thread limit.
+ *
+ * 1. The setup has a provider module with 1 faulty instance provider and one
+ * indication provider. The faulty provider does not respond correctly
+ * or respond after connection timeout or responds after the idle cleanup thread
+ * has been run by the cimserver. There is also a good instance provider which
+ * serves the same class hierarchy as the faulty instance provider. The test
+ * client inundates the cimserver with huge number of CIM requests for the
+ * faulty provider and good provider on multiple connections causing the
+ * cimserver to reach its thread/fd limit whichever is lower.
+ * 2. The test client detects that cimserver crossed fd limit if it recieved
+ * CannotConnectException after few requests .
+ * OR
+ * 3. The test client detects that cimserver crossed thread limit if it
+ * received CIMException after few requests.Then the test client runs a test
+ * on sample instance provider which should succeed.
+ * 4. Then the test client waits for cimserver cleanup interval for cimserver to
+ * release the held resources (fds/threads) after which it executes a test on
+ * a sample provider which should succeed.
+ * 5. The indication provider is exercised at the same time when a request is
+ * sent to the faulty instance provider.
+ * 6. The above tests should run through CHO and should pass the leak test.
+ */
+#define DEFAULT_MAX_CIM_REQUESTS 2000
+#define MAX_CONNECTIONS 100
+#define CONN_TIMEOUT 3
+#define EXPECTED_INSTANCENAMES 2
+#define CIMSERVER_CLEANUP_TIME 600
+
+static char * verbose = 0;
+static CIMException expectedNICIMException(CIM_ERR_FAILED);
+
+static AtomicInt recievedNICIMExceptionCount(0);
+static AtomicInt recievedNIConnTimeoutExceptionCount(0);
+static AtomicInt recievedNICannotConnectExceptionCount(0);
+
+static const String NAMESPACE("test/TestProvider");
+static const String FAULTY_CLASSNAME("TST_FaultyInstance");
+static const String WELLBEHAVED_CLASSNAME("TST_Instance1");
+
+class T_Parms{
+public:
+ CIMClient* client;
+ long requestCount;
+ Uint32 uniqueID;
+};
+
+Thread * _runTestThreads(
+ CIMClient* client,
+ ThreadReturnType (PEGASUS_THREAD_CDECL *_executeFn)(void *),
+ Uint32 uniqueID,
+ long requestCount)
+{
+ // package parameters, create thread and run...
+ AutoPtr<T_Parms> parms(new T_Parms());
+
+ parms->client = client;
+ parms->uniqueID = uniqueID;
+ parms->requestCount = requestCount;
+ AutoPtr<Thread> t(new Thread(_executeFn, (void*)parms.release(), false));
+ // zzzzz... (1 second) zzzzz...
+ Threads::sleep(100);
+ t->run();
+ return t.release();
+}
+
+void _executeRequest(Array<CIMClient *>& clientConnections,
+ ThreadReturnType (PEGASUS_THREAD_CDECL *_executeFn)(void *),
+ long requests)
+{
+ // run tests
+ Array<Thread *> clientThreads;
+ Uint32 thdIndex = 0;
+
+ //lets split the cim requests equally among client connections
+ long requestCount = (requests/clientConnections.size());
+
+ // start enumerateInstanceNames threads
+ for(Uint32 i = 0; i < clientConnections.size(); i++, thdIndex++)
+ {
+ clientThreads.append(
+ _runTestThreads(clientConnections[thdIndex],
+ _executeFn,
+ thdIndex,
+ requestCount));
+ }
+
+ // wait for threads to terminate
+ for(Uint32 i=0; i< clientThreads.size(); i++)
+ {
+ clientThreads[i]->join();
+ }
+
+ // clean up threads
+ for(Uint32 i=0; i < clientThreads.size(); i++)
+ {
+ delete clientThreads[i];
+ }
+}
+
+bool TestWellbehavedInstanceProvider()
+{
+ bool result = false;
+
+ try
+ {
+ CIMClient client;
+ client.connectLocal();
+
+ Array<CIMObjectPath> cimInstanceNames =
+ client.enumerateInstanceNames(
+ NAMESPACE,
+ WELLBEHAVED_CLASSNAME);
+ if(cimInstanceNames.size() > 0)
+ {
+ result = true;
+ }
+ }
+ catch (Exception& e)
+ {
+ cout << "---- caught exception from test instance provider : "
+ << e.getMessage()<<endl;
+ result = false;
+ }
+
+ return result;
+}
+
+ThreadReturnType PEGASUS_THREAD_CDECL _createSubFunc(void *parm)
+{
+ // client for creating subscription on the good
+ // provider which is part of the FaultyProviderModule.
+ CIMClient client;
+ client.connectLocal();
+
+ // create filter and handler
+ String queryFaulty01("SELECT * FROM CIM_AlertIndication");
+
+ String filterFaulty01("FilterFaulty01");
+
+ CIMInstance filterInstance (PEGASUS_CLASSNAME_INDFILTER);
+ filterInstance.addProperty (CIMProperty (CIMName
+ ("SystemCreationClassName"), System::getSystemCreationClassName ()));
+ filterInstance.addProperty (CIMProperty (CIMName ("SystemName"),
+ System::getFullyQualifiedHostName ()));
+ filterInstance.addProperty (CIMProperty (CIMName ("CreationClassName"),
+ PEGASUS_CLASSNAME_INDFILTER.getString ()));
+ filterInstance.addProperty (CIMProperty (CIMName ("Name"), filterFaulty01));
+ filterInstance.addProperty (CIMProperty (CIMName ("Query"), queryFaulty01));
+ filterInstance.addProperty (CIMProperty (CIMName ("QueryLanguage"),
+ String ("WQL")));
+ filterInstance.addProperty (CIMProperty (CIMName ("SourceNamespace"),
+ String(NAMESPACE)));
+
+ CIMObjectPath filterObjectPath;
+ try
+ {
+ filterObjectPath = client.createInstance(
+ NAMESPACE,
+ filterInstance);
+ }
+ catch(Exception& e)
+ {
+ cerr << "----- Error: Filter Instance Not Created: " <<
+ e.getMessage() << endl;
+ PEGASUS_TEST_ASSERT(false);
+ }
+
+ String handlerFaulty01("Handlerfaulty01");
+ String destination =String("http//localhost");
+
+ CIMInstance handlerInstance (PEGASUS_CLASSNAME_INDHANDLER_CIMXML);
+ handlerInstance.addProperty (CIMProperty (CIMName
+ ("SystemCreationClassName"), System::getSystemCreationClassName ()));
+ handlerInstance.addProperty (CIMProperty (CIMName ("SystemName"),
+ System::getFullyQualifiedHostName ()));
+ handlerInstance.addProperty (CIMProperty (CIMName ("CreationClassName"),
+ PEGASUS_CLASSNAME_INDHANDLER_CIMXML.getString ()));
+ handlerInstance.addProperty (CIMProperty (CIMName ("Name"),
+ handlerFaulty01));
+ handlerInstance.addProperty (CIMProperty (CIMName ("Destination"),
+ destination));
+
+ CIMObjectPath handlerObjPath;
+ try
+ {
+ handlerObjPath = client.createInstance(
+ NAMESPACE,
+ handlerInstance);
+ }
+ catch(Exception& e)
+ {
+ cerr << "----- Error: Handler Instance Not Created: " <<
+ e.getMessage() << endl;
+ PEGASUS_TEST_ASSERT(false);
+ }
+
+ // Thread 1 : subscription creation
+ CIMInstance subscriptionInstance (PEGASUS_CLASSNAME_INDSUBSCRIPTION);
+ subscriptionInstance.addProperty (CIMProperty (CIMName ("Filter"),
+ filterObjectPath, 0, PEGASUS_CLASSNAME_INDFILTER));
+ subscriptionInstance.addProperty (CIMProperty (CIMName ("Handler"),
+ handlerObjPath, 0, PEGASUS_CLASSNAME_INDHANDLER_CIMXML));
+ subscriptionInstance.addProperty (CIMProperty
+ (CIMName ("SubscriptionState"), CIMValue ((Uint16) 2)));
+
+ CIMObjectPath subscriptionObjPath;
+ try
+ {
+ subscriptionObjPath = client.createInstance(
+ NAMESPACE,
+ subscriptionInstance);
+ }
+ catch(Exception& e)
+ {
+ cerr << "----- Error: Subscription Instance Not Created: " <<
+ e.getMessage() << endl;
+ PEGASUS_TEST_ASSERT(false);
+ }
+ cout << "Successfully created subscription instance" << endl;
+
+ // delete subscription
+ try
+ {
+ client.deleteInstance(NAMESPACE,subscriptionObjPath);
+ client.deleteInstance(NAMESPACE,filterObjectPath);
+ client.deleteInstance(NAMESPACE,handlerObjPath);
+ }
+ catch(Exception& e)
+ {
+ cerr << "----- Error: Subscription deletion failed : " <<
+ e.getMessage() << endl;
+ PEGASUS_TEST_ASSERT(false);
+ }
+
+ return ThreadReturnType(0);
+}
+
+ThreadReturnType PEGASUS_THREAD_CDECL _enumInstanceNamesFunc(void *parm)
+{
+ // client for enumerateInstanceNames request on the faulty
+ // provider.
+ CIMClient client;
+ client.connectLocal();
+
+ // Thread 2 : enumerate instance request to faulty provider.
+ try
+ {
+ Array<CIMObjectPath> objs = client.enumerateInstanceNames(NAMESPACE,
+ FAULTY_CLASSNAME);
+ }
+ catch(Exception &e)
+ {
+ cout << "Caught exception while enumerating class " <<
+ FAULTY_CLASSNAME << ": " << e.getMessage() << endl;
+ return ThreadReturnType(0);
+ }
+
+ return ThreadReturnType(0);
+}
+
+bool TestIndicationProviderAndFaultyProvider()
+{
+ Thread t1(_createSubFunc, 0, false);
+ Thread t2(_enumInstanceNamesFunc, 0, false);
+
+ t1.run();
+
+ t2.run();
+
+ t1.join();
+ t2.join();
+
+ return true;
+}
+
+ThreadReturnType PEGASUS_THREAD_CDECL _executeNIonFaultyProvider(void *parm)
+{
+ Thread *my_thread = (Thread *)parm;
+ T_Parms *parms = (T_Parms *)my_thread->get_parm();
+ CIMClient *client = parms->client;
+ Uint32 uniqueID = parms->uniqueID;
+ long requestCount = parms->requestCount;
+ bool connectionAlreadyRefused=false;
+
+ long i=0;
+ for(i=0;i<requestCount;i++)
+ {
+ try
+ {
+ Array<CIMObjectPath> cimInstanceNames =
+ client->enumerateInstanceNames(NAMESPACE, FAULTY_CLASSNAME);
+
+ if(verbose)
+ cout<<"Request " << i << ": Faulty provider responded..!"<<endl;
+ }
+ catch (CIMException& e)
+ {
+ if(e.getCode() == expectedNICIMException.getCode())
+ {
+ recievedNICIMExceptionCount.inc();
+ }
+ else
+ {
+ cout << "---- NI thread " << uniqueID
+ <<" caught unexpected CIM exception: "<< e.getMessage()
+ << endl;
+ break;
+ }
+ }
+
+ catch (ConnectionTimeoutException& e)
+ {
+ recievedNIConnTimeoutExceptionCount.inc();
+ }
+ catch (CannotConnectException& e)
+ {
+ //While testing its observed that because of huge number of
+ //requests and responses cimserver could be busy and unable to
+ //accept a aconnection and hence ignoring the exception once.
+ if(!connectionAlreadyRefused)
+ {
+ i--;
+ connectionAlreadyRefused=true;
+ Threads::sleep(1 * 1000);
+ }
+ else
+ {
+ recievedNICannotConnectExceptionCount.inc();
+ if(verbose )
+ cout << "---- NI thread " << uniqueID
+ << " caught exception: "<< e.getMessage() << endl;
+ break;
+ }
+ }
+ catch(CIMClientMalformedHTTPException& e)
+ {
+ // This is the exception thrown on HP-UX if connection cannot be
+ // established.
+ if(!connectionAlreadyRefused)
+ {
+ i--;
+ connectionAlreadyRefused=true;
+ Threads::sleep(1 * 1000);
+ }
+ else
+ {
+ recievedNICannotConnectExceptionCount.inc();
+ if(verbose )
+ cout << "---- NI thread " << uniqueID
+ << " caught exception: "<< e.getMessage() << endl;
+ break;
+ }
+ }
+
+ catch (Exception& e)
+ {
+ cout << "---- NI thread " << uniqueID
+ << " caught unexpected exception: "<< e.getMessage() << endl;
+
+ break;
+ }
+ }
+
+ if(verbose && (i >= requestCount))
+ cout<<"---- NI thread " << uniqueID
+ << " successfully completed"<<endl;
+
+ delete parms;
+ return ThreadReturnType(0);
+}
+
+void TestCimserverAvailability()
+{
+ //runn a test on a test instance provider
+ bool resultWellbehavedProvider = TestWellbehavedInstanceProvider();
+ PEGASUS_TEST_ASSERT(resultWellbehavedProvider);
+
+ TestIndicationProviderAndFaultyProvider();
+
+ Array<CIMClient *> clientConnections;
+
+ // declare the clients
+ CIMClient * tmpClient;
+
+ // Calculate the thread limit on the OS.
+ long maxThread(-1);
+ #if defined(PEGASUS_OS_TYPE_UNIX)
+ maxThread = sysconf(_SC_THREAD_THREADS_MAX);
+ #endif
+
+ // The maximum requests to be sent are derived from the maximum
+ // thread limit on the OS. The Faulty provider responds properly
+ // to some requests. Hence for the cimprovagt to reach its
+ // thread limit we have to inundate it with maxThread*2 requests.
+ long maxRequests;
+ maxThread == -1 ?
+ maxRequests = DEFAULT_MAX_CIM_REQUESTS:
+ maxRequests = maxThread * 2;
+
+ for(Uint32 i = 0; i < MAX_CONNECTIONS; i++)
+ {
+ tmpClient = new CIMClient();
+ tmpClient->setTimeout(CONN_TIMEOUT * 1000);
+ tmpClient->connectLocal();
+ clientConnections.append(tmpClient);
+ }
+
+ //initialize
+ recievedNICIMExceptionCount = 0;
+ recievedNIConnTimeoutExceptionCount = 0;
+ recievedNICannotConnectExceptionCount = 0;
+
+ // run tests
+ cout <<"Executing " << maxRequests
+ <<" NI requests for faulty provider on " <<MAX_CONNECTIONS
+ <<" client connections for "
+ << (maxRequests/MAX_CONNECTIONS)*CONN_TIMEOUT
+ <<" sec."<<endl;
+
+ _executeRequest(clientConnections,
+ _executeNIonFaultyProvider,
+ maxRequests);
+
+ // clean up connections
+ for(Uint32 i=0; i< clientConnections.size(); i++)
+ {
+ delete clientConnections[i];
+ }
+
+ if(verbose)
+ cout<<"received CIM exceptions = "
+ <<recievedNICIMExceptionCount.get()<<endl
+ <<"received Connection Timeout exceptions = "
+ <<recievedNIConnTimeoutExceptionCount.get()<<endl
+ <<"received CannotConnect exceptions = "
+ <<recievedNICannotConnectExceptionCount.get()<<endl;
+
+ //we should have recieved either CIM exception(for crossing thread limit) or
+ //cannot connect exceptions(for crossing fd limit) AND not both/none.
+ if(!(recievedNICIMExceptionCount.get() > 0) ^
+ (recievedNICannotConnectExceptionCount.get() > 0))
+ {
+ cout << "The test could have failed due to two reasons : " << endl
+ << "Reason 1 : The code did not behave as expected. " << endl
+ << "Reason 2 : The number of requests used to inundate the "
+ << "cimserver is insufficient." << endl;
+ }
+
+ PEGASUS_TEST_ASSERT((recievedNICIMExceptionCount.get() > 0) ^
+ (recievedNICannotConnectExceptionCount.get() > 0));
+
+ //if cimserver reached its thread limit for the faulty provider
+ //before fd limit..then evaluate the results.
+ if(recievedNIConnTimeoutExceptionCount.get() == 0)
+ {
+ throw Exception(
+ "did not receive any conn timeout exceptions "
+ "for NI requests on faulty provider. ");
+ }
+ else
+ if(recievedNICIMExceptionCount.get() > 0)
+ {
+ cout<<"Faulty provider agent has reached its threadpool limit."<<endl;
+
+ //run a test on test instance provider
+ resultWellbehavedProvider = TestWellbehavedInstanceProvider();
+ PEGASUS_TEST_ASSERT(resultWellbehavedProvider);
+ }
+ else if(recievedNICannotConnectExceptionCount.get() > 0)
+ {
+ cout<<"cimserver may have reached its fd limit"
+ " before the thread limit"<<endl;
+ }
+ else
+ {
+ PEGASUS_TEST_ASSERT(false);
+ }
+
+ // wait for cim server to clean up disconnected clients' resources(threads
+ // and fds).
+ cout<<"Waiting for clean up routine to initiate cleanup for " <<
+ CIMSERVER_CLEANUP_TIME<<" sec."<<endl;
+ Threads::sleep(CIMSERVER_CLEANUP_TIME * 1000);
+
+ //run a test on test instance provider
+ resultWellbehavedProvider = TestWellbehavedInstanceProvider();
+
+ if(resultWellbehavedProvider == false)
+ {
+ throw Exception(
+ "A cim request on well behaved test instance provider failed"
+ " after cimserver crossed its fd/thread limit");
+ }
+
+}
+
+int main(int argc, char** argv)
+{
+ verbose = getenv("PEGASUS_TEST_VERBOSE");
+
+ try
+ {
+ TestCimserverAvailability();
+ }
+ catch(const CIMException & e)
+ {
+ cout << "CIMException: " << e.getCode() << " "
+ << e.getMessage() << endl;
+ return(-1);
+ }
+ catch(const Exception & e)
+ {
+ cout << "Exception: " << e.getMessage() << endl;
+ return(-1);
+ }
+ catch(...)
+ {
+ cout << "unknown exception" << endl;
+ return(-1);
+ }
+
+ cout << argv[0] << " +++++ passed all tests" << endl;
+
+ return(0);
+}
+
+
@ cimmofl "-R$(REPOSITORY_DIR)" "-N$(REPOSITORY_NAME)" "-M$(REPOSITORY_MODE)" "-n$(TESTPROVIDERNS)" TestChunkingStressProviderSchema.mof
@ $(ECHO) +++++ Loading IndicationStressTest class definitions into $(TESTPROVIDERNS) namespace ...
@ cimmofl "-R$(REPOSITORY_DIR)" "-N$(REPOSITORY_NAME)" "-M$(REPOSITORY_MODE)" "-n$(TESTPROVIDERNS)" IndicationStressTestProviderSchema.mof
+ @ $(ECHO) +++++ Loading TestFaultyProvider class definitions into $(TESTPROVIDERNS) namespace ...
+ @ cimmofl "-R$(REPOSITORY_DIR)" "-N$(REPOSITORY_NAME)" "-M$(REPOSITORY_MODE)" "-n$(TESTPROVIDERNS)" TestFaultyProviderSchema.mof
@ $(ECHO) +++++ Registering TestInstanceProvider ...
@ cimmofl "-R$(REPOSITORY_DIR)" "-N$(REPOSITORY_NAME)" "-M$(REPOSITORY_MODE)" "-n$(INTEROPNS)" TestInstanceProviderRegistration.mof
@ cimmofl "-R$(REPOSITORY_DIR)" "-N$(REPOSITORY_NAME)" "-M$(REPOSITORY_MODE)" "-n$(INTEROPNS)" IndicationStressTestProviderR.mof
@ $(ECHO) +++++ Registering IndicationStressTestConsumer Provider ...
@ cimmofl "-R$(REPOSITORY_DIR)" "-N$(REPOSITORY_NAME)" "-M$(REPOSITORY_MODE)" "-n$(INTEROPNS)" IndicationStressTestConsumerR.mof
+ @ $(ECHO) +++++ Registering TestFaultyProvider ...
+ @ cimmofl "-R$(REPOSITORY_DIR)" "-N$(REPOSITORY_NAME)" "-M$(REPOSITORY_MODE)" "-n$(INTEROPNS)" TestFaultyProviderRegistration.mof
+ @ $(ECHO) +++++ Registering TestGoodInstanceProvider ...
+ @ cimmofl "-R$(REPOSITORY_DIR)" "-N$(REPOSITORY_NAME)" "-M$(REPOSITORY_MODE)" "-n$(INTEROPNS)" TestGoodInstanceProviderRegistration.mof
@ $(ECHO) +++++ Loading IndicationTestProvider class definitions into $(TESTPROVIDERNS) namespace ...
@ cimmofl "-R$(REPOSITORY_DIR)" "-N$(REPOSITORY_NAME)" "-M$(REPOSITORY_MODE)" "-n$(TESTPROVIDERNS)" IndicationTestProvider.mof
--- /dev/null
+//%LICENSE////////////////////////////////////////////////////////////////
+//
+// Licensed to The Open Group (TOG) under one or more contributor license
+// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+// this work for additional information regarding copyright ownership.
+// Each contributor licenses this file to you under the OpenPegasus Open
+// Source License; you may not use this file except in compliance with the
+// License.
+//
+// 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.
+//
+//////////////////////////////////////////////////////////////////////////
+#pragma locale("en_US")
+
+instance of PG_ProviderModule
+{
+ Description = "A test provider to test cimom availability in the event of outstanding requests exceeding cimserver thread limit.";
+ Caption = "Pegasus thread limit test Provider Module";
+ Name = "TestFaultyProviderModule";
+ ModuleGroupName = "Faulty";
+ Vendor = "OpenPegasus";
+ Version = "2.5.0";
+ InterfaceType = "C++Default";
+ InterfaceVersion = "2.5.0";
+ Location = "TestFaultyProvider";
+};
+
+instance of PG_Provider
+{
+ ProviderModuleName = "TestFaultyProviderModule";
+ Name = "TestFaultyInstanceProvider";
+};
+
+instance of PG_ProviderCapabilities
+{
+ ProviderModuleName = "TestFaultyProviderModule";
+ ProviderName = "TestFaultyInstanceProvider";
+ CapabilityID = "001";
+ ClassName = "TST_FaultyInstance";
+ Namespaces = { "test/TestProvider" };
+ ProviderType = { 2 };
+ SupportedProperties = NULL;
+ SupportedMethods = NULL;
+};
+
+instance of PG_Provider
+{
+ ProviderModuleName = "TestFaultyProviderModule";
+ Name = "TestGoodIndicationProvider";
+};
+
+instance of PG_ProviderCapabilities
+{
+ ProviderModuleName = "TestFaultyProviderModule";
+ ProviderName = "TestGoodIndicationProvider";
+ CapabilityID = "002";
+ ClassName = "CIM_AlertIndication";
+ Namespaces = { "test/TestProvider" };
+ ProviderType = { 4 }; // Incication
+ SupportedProperties = NULL;
+ SupportedMethods = NULL;
+};
--- /dev/null
+//%LICENSE////////////////////////////////////////////////////////////////
+//
+// Licensed to The Open Group (TOG) under one or more contributor license
+// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+// this work for additional information regarding copyright ownership.
+// Each contributor licenses this file to you under the OpenPegasus Open
+// Source License; you may not use this file except in compliance with the
+// License.
+//
+// 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.
+//
+//////////////////////////////////////////////////////////////////////////
+#pragma locale("en_US")
+
+class TST_FaultyInstance
+{
+ [key]
+ string Name;
+
+ string s = "Faulty Instance Class";
+ uint64 n;
+ real64 f;
+ datetime d;
+
+};
+
+class TST_FaultyInstanceSub : TST_FaultyInstance
+{
+ uint64 sub;
+};
+
+
--- /dev/null
+//%LICENSE////////////////////////////////////////////////////////////////
+//
+// Licensed to The Open Group (TOG) under one or more contributor license
+// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+// this work for additional information regarding copyright ownership.
+// Each contributor licenses this file to you under the OpenPegasus Open
+// Source License; you may not use this file except in compliance with the
+// License.
+//
+// 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.
+//
+//////////////////////////////////////////////////////////////////////////
+#pragma locale("en_US")
+
+instance of PG_ProviderModule
+{
+ Description = "A test provider used to test the cimserver availibility along with TestFaultyInstanceProvider";
+ Caption = "Pegasus Good Instance Provider Module";
+ Name = "TestGoodInstanceProviderModule";
+ Vendor = "OpenPegasus";
+ Version = "2.5.0";
+ InterfaceType = "C++Default";
+ InterfaceVersion = "2.5.0";
+ Location = "TestGoodInstanceProvider";
+};
+
+instance of PG_Provider
+{
+ ProviderModuleName = "TestGoodInstanceProviderModule";
+ Name = "TestGoodInstanceProvider";
+};
+
+instance of PG_ProviderCapabilities
+{
+ ProviderModuleName = "TestGoodInstanceProviderModule";
+ ProviderName = "TestGoodInstanceProvider";
+ CapabilityID = "001";
+ ClassName = "TST_FaultyInstanceSub";
+ Namespaces = { "test/TestProvider" };
+ ProviderType = { 2 }; // Instance
+ SupportedProperties = NULL;
+ SupportedMethods = NULL;
+};
+
+
+
PerformanceTests \
EmbeddedInstanceProvider \
EmbeddedInstanceProvider/testClient \
- TestModuleGrouping
+ TestModuleGrouping \
+ FaultyInstanceProvider \
+ FaultyInstanceProvider/testclient \
+ TestGoodInstanceProvider
+
ifeq ($(PEGASUS_ENABLE_INTEROP_PROVIDER),true)
TEST_DIRS += \
--- /dev/null
+#//%LICENSE////////////////////////////////////////////////////////////////
+#//
+#// Licensed to The Open Group (TOG) under one or more contributor license
+#// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+#// this work for additional information regarding copyright ownership.
+#// Each contributor licenses this file to you under the OpenPegasus Open
+#// Source License; you may not use this file except in compliance with the
+#// License.
+#//
+#// 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.
+#//
+#//////////////////////////////////////////////////////////////////////////
+ROOT = ../../../..
+
+DIR = Providers/TestProviders/TestGoodInstanceProvider
+
+include $(ROOT)/mak/config.mak
+
+LIBRARY = TestGoodInstanceProvider
+
+LIBRARIES = \
+ pegprovider \
+ pegclient \
+ pegcommon
+
+SOURCES = \
+ TestGoodInstanceProviderMain.cpp \
+ TestGoodInstanceProvider.cpp
+
+include $(ROOT)/mak/dynamic-library.mak
+
+tests:
+
--- /dev/null
+//%LICENSE////////////////////////////////////////////////////////////////
+//
+// Licensed to The Open Group (TOG) under one or more contributor license
+// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+// this work for additional information regarding copyright ownership.
+// Each contributor licenses this file to you under the OpenPegasus Open
+// Source License; you may not use this file except in compliance with the
+// License.
+//
+// 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 <cstring>
+#include <Pegasus/Common/Config.h>
+#include <Pegasus/Provider/CIMInstanceProvider.h>
+
+#include "TestGoodInstanceProvider.h"
+
+PEGASUS_USING_STD;
+PEGASUS_NAMESPACE_BEGIN
+
+TestGoodInstanceProvider::TestGoodInstanceProvider()
+{
+}
+
+TestGoodInstanceProvider::~TestGoodInstanceProvider()
+{
+}
+
+void TestGoodInstanceProvider::initialize(CIMOMHandle& cimom)
+{
+ // save cimom handle
+ //_cimom = cimom;
+
+ char namebuf[20];
+ char pathbuf[45];
+ memset(namebuf, 0x00, sizeof(namebuf));
+ memset(pathbuf, 0x00, sizeof(pathbuf));
+
+ // create default instances
+ for (Uint32 i = 1; i <= 2; i++)
+ {
+ sprintf(namebuf, "%u", i);
+ sprintf(pathbuf, "TST_FaultyInstanceInstance.Name=\"%u\"", i);
+ {
+ CIMInstance instance("TST_FaultyInstanceInstance");
+
+ instance.addProperty(CIMProperty("name", String(namebuf)));
+ instance.addProperty(CIMProperty("s", String("specified")));
+ instance.addProperty(CIMProperty("n", Uint64(i)));
+ instance.addProperty(CIMProperty("f", Real64(Real64(i)+0.001)));
+ instance.addProperty(
+ CIMProperty("d", CIMDateTime::getCurrentDateTime()));
+ instance.addProperty(CIMProperty("sub", Uint64(i)));
+
+ instance.setPath(CIMObjectPath(pathbuf));
+
+ _instances.append(instance);
+ }
+ }
+}
+
+void TestGoodInstanceProvider::terminate()
+{
+ delete this;
+}
+
+void TestGoodInstanceProvider::getInstance(
+ const OperationContext& context,
+ const CIMObjectPath& instanceReference,
+ const Boolean includeQualifiers,
+ const Boolean includeClassOrigin,
+ const CIMPropertyList& propertyList,
+ InstanceResponseHandler& handler)
+{
+ throw CIMException(CIM_ERR_NOT_SUPPORTED);
+}
+
+void TestGoodInstanceProvider::enumerateInstances(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ const Boolean includeQualifiers,
+ const Boolean includeClassOrigin,
+ const CIMPropertyList& propertyList,
+ InstanceResponseHandler& handler)
+{
+ throw CIMException(CIM_ERR_NOT_SUPPORTED);
+}
+
+void TestGoodInstanceProvider::enumerateInstanceNames(
+ const OperationContext& context,
+ const CIMObjectPath& classReference,
+ ObjectPathResponseHandler& handler)
+{
+ handler.processing();
+
+ for (Uint32 i = 0, n = _instances.size(); i < n; i++)
+ {
+ try
+ {
+ handler.deliver(_instances[i].getPath());
+ }
+ catch (CIMException&)
+ {
+ // suppress error
+ }
+ }
+
+ handler.complete();
+}
+
+void TestGoodInstanceProvider::modifyInstance(
+ const OperationContext& context,
+ const CIMObjectPath& instanceReference,
+ const CIMInstance& instanceObject,
+ const Boolean includeQualifiers,
+ const CIMPropertyList& propertyList,
+ ResponseHandler& handler)
+{
+ throw CIMException(CIM_ERR_NOT_SUPPORTED);
+}
+
+void TestGoodInstanceProvider::createInstance(
+ const OperationContext& context,
+ const CIMObjectPath& instanceReference,
+ const CIMInstance& instanceObject,
+ ObjectPathResponseHandler& handler)
+{
+ throw CIMException(CIM_ERR_NOT_SUPPORTED);
+}
+
+void TestGoodInstanceProvider::deleteInstance(
+ const OperationContext& context,
+ const CIMObjectPath& instanceReference,
+ ResponseHandler& handler)
+{
+ throw CIMException(CIM_ERR_NOT_SUPPORTED);
+}
+
+PEGASUS_NAMESPACE_END
--- /dev/null
+//%LICENSE////////////////////////////////////////////////////////////////
+//
+// Licensed to The Open Group (TOG) under one or more contributor license
+// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+// this work for additional information regarding copyright ownership.
+// Each contributor licenses this file to you under the OpenPegasus Open
+// Source License; you may not use this file except in compliance with the
+// License.
+//
+// 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.
+//
+//////////////////////////////////////////////////////////////////////////
+//
+//%///////////////////////////////////////////////////////////////////////
+
+#ifndef Pegasus_TestGoodInstanceProvider_h
+#define Pegasus_TestGoodInstanceProvider_h
+
+#include <Pegasus/Common/Config.h>
+#include <Pegasus/Common/AtomicInt.h>
+#include <Pegasus/Provider/CIMInstanceProvider.h>
+
+PEGASUS_NAMESPACE_BEGIN
+
+class TestGoodInstanceProvider :
+ public CIMInstanceProvider
+{
+public:
+ TestGoodInstanceProvider();
+ virtual ~TestGoodInstanceProvider();
+
+ // CIMProvider interface
+ virtual void initialize(CIMOMHandle& cimom);
+ virtual void terminate();
+
+ // CIMInstanceProvider interface
+ virtual void getInstance(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ const Boolean includeQualifiers,
+ const Boolean includeClassOrigin,
+ const CIMPropertyList& propertyList,
+ InstanceResponseHandler& handler);
+
+ virtual void enumerateInstances(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ const Boolean includeQualifiers,
+ const Boolean includeClassOrigin,
+ const CIMPropertyList& propertyList,
+ InstanceResponseHandler& handler);
+
+ virtual void enumerateInstanceNames(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ ObjectPathResponseHandler& handler);
+
+ virtual void modifyInstance(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ const CIMInstance& obj,
+ const Boolean includeQualifiers,
+ const CIMPropertyList& propertyList,
+ ResponseHandler& handler);
+
+ virtual void createInstance(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ const CIMInstance& obj,
+ ObjectPathResponseHandler& handler);
+
+ virtual void deleteInstance(
+ const OperationContext& context,
+ const CIMObjectPath& ref,
+ ResponseHandler& handler);
+
+protected:
+ Array<CIMInstance> _instances;
+};
+
+PEGASUS_NAMESPACE_END
+
+#endif
--- /dev/null
+//%LICENSE////////////////////////////////////////////////////////////////
+//
+// Licensed to The Open Group (TOG) under one or more contributor license
+// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
+// this work for additional information regarding copyright ownership.
+// Each contributor licenses this file to you under the OpenPegasus Open
+// Source License; you may not use this file except in compliance with the
+// License.
+//
+// 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/Config.h>
+
+#include "TestGoodInstanceProvider.h"
+
+PEGASUS_NAMESPACE_BEGIN
+
+extern "C"
+PEGASUS_EXPORT CIMProvider* PegasusCreateProvider(const String& providerName)
+{
+ if (String::equalNoCase(providerName, "TestGoodInstanceProvider"))
+ {
+ return new TestGoodInstanceProvider();
+ }
+
+ return 0;
+}
+
+PEGASUS_NAMESPACE_END
-e "Test_IndicationProviderClass" \
-e "idle connection" \
-e "The repository throws the following exception: TestCMPI_Instance" \
+ -e "HTTPAcceptor: accept() failed. errno: 24" \
+ -e "Socket write failed with error: Broken pipe (error code 32)" \
+ -e "arrived after the client disconnected." \
-e "^$" \
$traceFile > $PEGASUS_HOME/trace/trace.out