void CIMOperationResponseEncoder::enqueue(Message* message)
{
    try
    {
        handleEnqueue(message);
    }
    catch(PEGASUS_STD(bad_alloc)&)
    {
        MessageLoaderParms parms(
            "Server.CIMOperationResponseEncoder.OUT_OF_MEMORY",
            "A System error has occurred. Please retry the CIM Operation "
                "at a later time.");

        Logger::put_l(
            Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE, parms);

        CIMResponseMessage* response =
            dynamic_cast<CIMResponseMessage*>(message);
        Uint32 queueId = response->queueIds.top();
        MessageQueue* queue = MessageQueue::lookup(queueId);
        HTTPConnection* httpQueue = dynamic_cast<HTTPConnection*>(queue);
        PEGASUS_ASSERT(httpQueue);

        // Handle internal error on this connection.
        httpQueue->handleInternalServerError(
            response->getIndex(), response->isComplete());

        delete message;
    }
}
void CIMOperationResponseEncoder::handleEnqueue(Message* message)
{
    PEG_METHOD_ENTER(TRC_DISPATCHER,
        "CIMOperationResponseEncoder::handleEnqueue()");

    if (!message)
    {
        PEG_METHOD_EXIT();
        return;
    }

    CIMResponseMessage* response = dynamic_cast<CIMResponseMessage*>(message);
    PEGASUS_ASSERT(response);

    response->updateThreadLanguages();

    PEG_TRACE((
        TRC_HTTP,
        Tracer::LEVEL4,
        "CIMOperationResponseEncoder::handleEnque()- "
            "message->getCloseConnect() returned %d",
        message->getCloseConnect()));

    // Handle binary messages up front:
    {
        CIMResponseMessage* msg = dynamic_cast<CIMResponseMessage*>(message);

        if (msg && msg->binaryResponse)
        {
            if (msg->cimException.getCode() == CIM_ERR_SUCCESS)
            {
                Buffer body;
                CIMName name;

                if (BinaryCodec::encodeResponseBody(body, msg, name))
                {
                    sendResponse(msg, name.getString(), true, &body);
                    delete msg;
                    PEG_METHOD_EXIT();
                    return;
                }
            }
        }
    }

    switch (message->getType())
    {
        case CIM_GET_CLASS_RESPONSE_MESSAGE:
            encodeGetClassResponse(
                (CIMGetClassResponseMessage*)message);
            break;

        case CIM_GET_INSTANCE_RESPONSE_MESSAGE:
            encodeGetInstanceResponse(
                (CIMGetInstanceResponseMessage*)message);
            break;

        case CIM_DELETE_CLASS_RESPONSE_MESSAGE:
            encodeDeleteClassResponse(
                (CIMDeleteClassResponseMessage*)message);
            break;

        case CIM_DELETE_INSTANCE_RESPONSE_MESSAGE:
            encodeDeleteInstanceResponse(
                (CIMDeleteInstanceResponseMessage*)message);
            break;

        case CIM_CREATE_CLASS_RESPONSE_MESSAGE:
            encodeCreateClassResponse(
                (CIMCreateClassResponseMessage*)message);
            break;

        case CIM_CREATE_INSTANCE_RESPONSE_MESSAGE:
            encodeCreateInstanceResponse(
                (CIMCreateInstanceResponseMessage*)message);
            break;

        case CIM_MODIFY_CLASS_RESPONSE_MESSAGE:
            encodeModifyClassResponse(
                (CIMModifyClassResponseMessage*)message);
            break;

        case CIM_MODIFY_INSTANCE_RESPONSE_MESSAGE:
            encodeModifyInstanceResponse(
                (CIMModifyInstanceResponseMessage*)message);
            break;

        case CIM_ENUMERATE_CLASSES_RESPONSE_MESSAGE:
            encodeEnumerateClassesResponse(
                (CIMEnumerateClassesResponseMessage*)message);
            break;

        case CIM_ENUMERATE_CLASS_NAMES_RESPONSE_MESSAGE:
            encodeEnumerateClassNamesResponse(
                (CIMEnumerateClassNamesResponseMessage*)message);
            break;

        case CIM_ENUMERATE_INSTANCES_RESPONSE_MESSAGE:
            encodeEnumerateInstancesResponse(
                (CIMEnumerateInstancesResponseMessage*)message);
            break;

        case CIM_ENUMERATE_INSTANCE_NAMES_RESPONSE_MESSAGE:
            encodeEnumerateInstanceNamesResponse(
                (CIMEnumerateInstanceNamesResponseMessage*)message);
            break;

        case CIM_EXEC_QUERY_RESPONSE_MESSAGE:
            encodeExecQueryResponse(
                (CIMExecQueryResponseMessage*)message);
            break;

        case CIM_ASSOCIATORS_RESPONSE_MESSAGE:
            encodeAssociatorsResponse(
                (CIMAssociatorsResponseMessage*)message);
            break;

        case CIM_ASSOCIATOR_NAMES_RESPONSE_MESSAGE:
            encodeAssociatorNamesResponse(
                (CIMAssociatorNamesResponseMessage*)message);
            break;

        case CIM_REFERENCES_RESPONSE_MESSAGE:
            encodeReferencesResponse(
                (CIMReferencesResponseMessage*)message);
            break;

        case CIM_REFERENCE_NAMES_RESPONSE_MESSAGE:
            encodeReferenceNamesResponse(
                (CIMReferenceNamesResponseMessage*)message);
            break;

        case CIM_GET_PROPERTY_RESPONSE_MESSAGE:
            encodeGetPropertyResponse(
                (CIMGetPropertyResponseMessage*)message);
            break;

        case CIM_SET_PROPERTY_RESPONSE_MESSAGE:
            encodeSetPropertyResponse(
                (CIMSetPropertyResponseMessage*)message);
            break;

        case CIM_GET_QUALIFIER_RESPONSE_MESSAGE:
            encodeGetQualifierResponse(
                (CIMGetQualifierResponseMessage*)message);
            break;

        case CIM_SET_QUALIFIER_RESPONSE_MESSAGE:
            encodeSetQualifierResponse(
                (CIMSetQualifierResponseMessage*)message);
            break;

        case CIM_DELETE_QUALIFIER_RESPONSE_MESSAGE:
            encodeDeleteQualifierResponse(
                (CIMDeleteQualifierResponseMessage*)message);
            break;

        case CIM_ENUMERATE_QUALIFIERS_RESPONSE_MESSAGE:
            encodeEnumerateQualifiersResponse(
                (CIMEnumerateQualifiersResponseMessage*)message);
            break;

        case CIM_INVOKE_METHOD_RESPONSE_MESSAGE:
            encodeInvokeMethodResponse(
                (CIMInvokeMethodResponseMessage*)message);
            break;
//EXP_PULL_BEGIN
        case CIM_OPEN_ENUMERATE_INSTANCES_RESPONSE_MESSAGE:
            encodeOpenEnumerateInstancesResponse(
                (CIMOpenEnumerateInstancesResponseMessage*)message);
            break;

        case CIM_OPEN_ENUMERATE_INSTANCE_PATHS_RESPONSE_MESSAGE:
            encodeOpenEnumerateInstancePathsResponse(
                (CIMOpenEnumerateInstancePathsResponseMessage*)message);
            break;

        case CIM_OPEN_REFERENCE_INSTANCES_RESPONSE_MESSAGE:
            encodeOpenReferenceInstancesResponse(
                (CIMOpenReferenceInstancesResponseMessage*)message);
            break;

        case CIM_OPEN_REFERENCE_INSTANCE_PATHS_RESPONSE_MESSAGE:
            encodeOpenReferenceInstancePathsResponse(
                (CIMOpenReferenceInstancePathsResponseMessage*)message);
            break;

        case CIM_OPEN_ASSOCIATOR_INSTANCES_RESPONSE_MESSAGE:
            encodeOpenAssociatorInstancesResponse(
                (CIMOpenAssociatorInstancesResponseMessage*)message);
            break;

        case CIM_OPEN_ASSOCIATOR_INSTANCE_PATHS_RESPONSE_MESSAGE:
            encodeOpenAssociatorInstancePathsResponse(
                (CIMOpenAssociatorInstancePathsResponseMessage*)message);
            break;

        case CIM_PULL_INSTANCE_PATHS_RESPONSE_MESSAGE:
            encodePullInstancePathsResponse(
                (CIMPullInstancePathsResponseMessage*)message);
            break;

        case CIM_PULL_INSTANCES_WITH_PATH_RESPONSE_MESSAGE:
            encodePullInstancesWithPathResponse(
                (CIMPullInstancesWithPathResponseMessage*)message);
            break;

        case CIM_PULL_INSTANCES_RESPONSE_MESSAGE:
            encodePullInstancesResponse(
                (CIMPullInstancesResponseMessage*)message);
            break;

        case CIM_CLOSE_ENUMERATION_RESPONSE_MESSAGE:
            encodeCloseEnumerationResponse(
                (CIMCloseEnumerationResponseMessage*)message);
            break;

        case CIM_ENUMERATION_COUNT_RESPONSE_MESSAGE:
            encodeEnumerationCountResponse(
                (CIMEnumerationCountResponseMessage*)message);
            break;

        case CIM_OPEN_QUERY_INSTANCES_RESPONSE_MESSAGE:
            encodeOpenQueryInstancesResponse(
                (CIMOpenQueryInstancesResponseMessage*)message);
            break;
//EXP_PULL_END
        default:
            // Unexpected message type
            PEGASUS_UNREACHABLE(PEGASUS_ASSERT(0);)
            break;
    }
Esempio n. 3
0
Message* CIMClientRep::_doRequest(
    AutoPtr<CIMRequestMessage>& request,
    const Uint32 expectedResponseMessageType
)
{
    if (!_connected)
    {
        request.reset();
        throw NotConnectedException();
    }

    String messageId = XmlWriter::getNextMessageId();
    const_cast<String &>(request->messageId) = messageId;

    _authenticator.setRequestMessage(0);

    // ATTN-RK-P2-20020416: We should probably clear out the queue first.
    PEGASUS_ASSERT(getCount() == 0);  // Shouldn't be any messages in our queue

    //
    //  Set HTTP method in request to POST
    //
    //Bug 478/418 - Change this to do post call, not mpost
    request->setHttpMethod (HTTP_METHOD__POST);

// l10n
    // Set the Accept-Languages and Content-Languages into
    // the request message

    request->operationContext.set(AcceptLanguageListContainer(requestAcceptLanguages));
    request->operationContext.set(ContentLanguageListContainer(requestContentLanguages));


    //gathering statistical information about client operation
    ClientPerfDataStore* perfDataStore = ClientPerfDataStore::Instance();
    perfDataStore->reset();
    perfDataStore->setOperationType(request->getType());
    perfDataStore->setMessageID(request->messageId);


    // Sending a new request, so clear out the response Content-Languages
    responseContentLanguages = ContentLanguages::EMPTY;

    _requestEncoder->enqueue(request.get());
    request.release();

    Uint64 startMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
    Uint64 nowMilliseconds = startMilliseconds;
    Uint64 stopMilliseconds = nowMilliseconds + _timeoutMilliseconds;

    while (nowMilliseconds < stopMilliseconds)
    {
        //
        // Wait until the timeout expires or an event occurs:
        //
        _monitor->run(Uint32(stopMilliseconds - nowMilliseconds));

        //
        // Check to see if incoming queue has a message
        //

        Message* response = dequeue();

        if (response)
        {
            // Shouldn't be any more messages in our queue
            PEGASUS_ASSERT(getCount() == 0);

            //
            // Reconnect to reset the connection
            // if Server response contained a Connection: Close Header
            //
            if (response->getCloseConnect() == true) {
                _reconnect();
                response->setCloseConnect(false);
            }

            //
            //  Future:  If M-POST is used and HTTP response is 501 Not
            //  Implemented or 510 Not Extended, retry with POST method
            //

            if (response->getType() == CLIENT_EXCEPTION_MESSAGE)
            {

                Exception* clientException =
                    ((ClientExceptionMessage*)response)->clientException;
                delete response;

                AutoPtr<Exception> d(clientException);

                // Make the ContentLanguage of the exception available through
                // the CIMClient API (its also available in the exception).
                responseContentLanguages = clientException->getContentLanguages();

                //
                // Determine and throw the specific class of client exception
                //

                CIMClientMalformedHTTPException* malformedHTTPException =
                    dynamic_cast<CIMClientMalformedHTTPException*>(
                        clientException);
                if (malformedHTTPException)
                {
                    throw *malformedHTTPException;
                }

                CIMClientHTTPErrorException* httpErrorException =
                    dynamic_cast<CIMClientHTTPErrorException*>(
                        clientException);
                if (httpErrorException)
                {
                    throw *httpErrorException;
                }

                CIMClientXmlException* xmlException =
                    dynamic_cast<CIMClientXmlException*>(clientException);
                if (xmlException)
                {
                    throw *xmlException;
                }

                CIMClientResponseException* responseException =
                    dynamic_cast<CIMClientResponseException*>(clientException);
                if (responseException)
                {
                    throw *responseException;
                }

                CIMException* cimException =
                    dynamic_cast<CIMException*>(clientException);
                if (cimException)
                {
                    throw *cimException;
                }

                throw *clientException;
            }
            else if (response->getType() == expectedResponseMessageType)
            {
                CIMResponseMessage* cimResponse = (CIMResponseMessage*)response;

                if (cimResponse->messageId != messageId)
                {
                    // l10n

                    // CIMClientResponseException responseException(
                    //   String("Mismatched response message ID:  Got \"") +
                    //    cimResponse->messageId + "\", expected \"" +
                    //    messageId + "\".");

                    MessageLoaderParms mlParms(
                        "Client.CIMClient.MISMATCHED_RESPONSE",
                        "Mismatched response message ID:  Got \"$0\", "
                        "expected \"$1\".",
                        cimResponse->messageId, messageId);
                    String mlString(MessageLoader::getMessage(mlParms));

                    CIMClientResponseException responseException(mlString);

                    delete response;
                    throw responseException;
                }

                // l10n
                // Get the Content-Languages from the response's operationContext
                // and make available through the CIMClient API
                responseContentLanguages =
                    ((ContentLanguageListContainer)cimResponse->operationContext.get
                     (ContentLanguageListContainer::NAME)).getLanguages();

                if (cimResponse->cimException.getCode() != CIM_ERR_SUCCESS)
                {
                    CIMException cimException(
                        cimResponse->cimException.getCode(),
                        cimResponse->cimException.getMessage());
                    cimException.setContentLanguages(responseContentLanguages);
                    delete response;
                    throw cimException;
                }

                /* if excicution gets here everytihng is working correctly and a proper response
                was generated and recived */

                //check that client side statistics are valid before handing them to the
                // client application via a call back
                Boolean re_check = perfDataStore->checkMessageIDandType(cimResponse->messageId,
                                   cimResponse->getType());

                if (re_check && !perfDataStore->getStatError() && perfDataStore->isClassRegistered())
                {
                    //if callback method throws an exception it will be seen by the client
                    //no try/catch block is used here intentionaly - becasue exceptions
                    //come from the client application so client app. should handle them
                    ClientOpPerformanceData item = perfDataStore->createPerfDataStruct();
                    perfDataStore->handler_prt->handleClientOpPerformanceData(item);

                }//end of if statmet that call the callback method
                return response;
            }
            else if (dynamic_cast<CIMRequestMessage*>(response) != 0)
            {
                // Respond to an authentication challenge
                _requestEncoder->enqueue(response);
                nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
                stopMilliseconds = nowMilliseconds + _timeoutMilliseconds;
                continue;
            }
            else
            {
                // l10n

                // CIMClientResponseException responseException(
                //   "Mismatched response message type.");
                MessageLoaderParms mlParms(
                    "Client.CIMOperationResponseDecoder.MISMATCHED_RESPONSE_TYPE",
                    "Mismatched response message type.");
                String mlString(MessageLoader::getMessage(mlParms));

                CIMClientResponseException responseException(mlString);

                delete response;
                throw responseException;
            }
        }

        nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
        pegasus_yield();
    }

    //
    // Reconnect to reset the connection (disregard late response)
    //
    try
    {
        _reconnect();
    }
    catch (...)
    {
    }

    //
    // Throw timed out exception:
    //
    throw ConnectionTimeoutException();
}
// This is only called from SimpleResponseHandler.deliver() but lives in this
// class because all asyncronous response must have a "response" pointer
// to go through. Only operation classes have a response pointer
void OperationResponseHandler::send(Boolean isComplete)
{
    // It is possible to instantiate this class directly (not a derived
    // class, which would also inherit from SimpleResponseHandler).
    // The caller would do this only if the operation does not have any
    // data to be returned.

    SimpleResponseHandler* simpleP =
        dynamic_cast<SimpleResponseHandler*>(this);
    if (simpleP == 0)
    {
        // if there is no data to be returned, then the message should NEVER be
        // incomplete (even on an error)
        PEGASUS_ASSERT(isComplete);
        return;
    }

    // some handlers do not send async because their callers cannot handle
    // partial responses. If this is the case, stop here.

    if (!isAsync())
    {
        // preserve traditional behavior
        if (isComplete)
        {
            if (_response != 0)
            {
                _response->operationContext.set(
                    ContentLanguageListContainer(simpleP->getLanguages()));
            }
            transfer();
        }

        return;
    }

    SimpleResponseHandler& simple = *simpleP;
    PEGASUS_ASSERT(_response);
    Uint32 objectCount = simple.size();

    // have not reached threshold yet
    if ((isComplete == false) && (objectCount < _responseObjectThreshold))
    {
        return;
    }

    CIMResponseMessage* response = _response;

    // for complete responses, just use the one handed down from caller
    // otherwise, create our own that the caller never sees but is
    // utilized for async responses underneath

    if (isComplete == false)
    {
        _response = _request->buildResponse();
    }

    _response->setComplete(isComplete);
    _responseObjectTotal += objectCount;

    // since we are reusing response for every chunk, keep track of original
    // count
    _response->setIndex(_responseMessageTotal++);

    // set the originally allocated response to one more than the current.
    // The reason for doing this is proactive in case of an exception. This
    // allows the last response to be set as it may not re-enter this code.

    if (isComplete == false)
    {
        response->setIndex(_responseMessageTotal);
    }

    validate();

    if (_response->cimException.getCode() != CIM_ERR_SUCCESS)
    {
        simple.clear();
    }

    PEG_TRACE((
        TRC_PROVIDERMANAGER,
        Tracer::LEVEL4,
        "%s::transfer",
        (const char*) getClass().getCString()));

    transfer();
    simple.clear();

    _response->operationContext.set(
        ContentLanguageListContainer(simple.getLanguages()));

    // call thru ProviderManager to get externally declared entry point

    if (isComplete == false)
    {
        _responseChunkCallback(_request, _response);
    }

    // put caller's allocated response back in place. Note that _response
    // is INVALID after sending because it has been deleted externally

    _response = response;
}
// This is only called from SimpleResponseHandler.deliver() but lives in this
// class because all asyncronous response must have a "response" pointer
// to go through. Only operation classes have a response pointer
void OperationResponseHandler::send(Boolean isComplete)
{
	// some handlers do not send async because their callers cannot handle
	// partial responses. If this is the case, stop here.

	if (isAsync() == false)
	{
		// preserve tradional behavior
		if (isComplete == true)
        {
            transfer();
        }

        return;
	}

	SimpleResponseHandler *simpleP = dynamic_cast<SimpleResponseHandler*>(this);

	// It is possible to instantiate this class directly (not derived)
	// The caller would do this only if the operation does not have any data to
	// be returned

	if (! simpleP)
	{
		// if there is no data to be returned, then the message should NEVER be
		// incomplete (even on an error)
		if (isComplete == false)
        {
            PEGASUS_ASSERT(false);
        }

        return;
	}

	SimpleResponseHandler &simple = *simpleP;
	PEGASUS_ASSERT(_response);
	Uint32 objectCount = simple.size();

	// have not reached threshold yet
	if ((isComplete == false) && (objectCount < _responseObjectThreshold))
    {
        return;
    }

	CIMResponseMessage *response = _response;

	// for complete responses, just use the one handed down from caller
	// otherwise, create our own that the caller never sees but is
	// utilized for async responses underneath

	if (isComplete == false)
    {
        _response = _request->buildResponse();
    }

	_response->setComplete(isComplete);
	_responseObjectTotal += objectCount;

	// since we are reusing response for every chunk,keep track of original count
	_response->setIndex(_responseMessageTotal++);

	// set the originally allocated response to one more than the current.
	// The reason for doing this is proactive in case of an exception. This
	// allows the last response to be set as it may not re-enter this code.

	if (isComplete == false)
    {
        response->setIndex(_responseMessageTotal);
    }

	validate();

	if (_response->cimException.getCode() != CIM_ERR_SUCCESS)
    {
        simple.clear();
    }

	String function = getClass() + "::" + "transfer";
	Logger::put(
        Logger::STANDARD_LOG,
        System::CIMSERVER,
        Logger::TRACE,
        function);

	transfer();
	simple.clear();

	// l10n
	_response->operationContext.set(ContentLanguageListContainer(simple.getLanguages()));

	// call thru ProviderManager to get externally declared entry point

	if (isComplete == false)
	{
		ProviderManagerService::handleCimResponse(*_request, *_response);
	}

	// put caller's allocated response back in place. Note that _response
	// is INVALID after sending because it has been deleted externally

	_response = response;
}