(file) Return to client.cpp CVS log (file) (dir) Up to [OMI] / omi / omiclient

File: [OMI] / omi / omiclient / client.cpp (download)
Revision: 1.1.1.1 (vendor branch), Wed May 30 21:47:49 2012 UTC (12 years ago) by mike
Branch: TOG
CVS Tags: OMI_1_0_2_Branch, OMI_1_0_2, OMI_1_0_1_PRE, OMI_1_0_1, OMI_1_0_0
Changes since 1.1: +0 -0 lines
Initial Import

/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
** 
** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
** use this file except in compliance with the License. You may obtain a copy 
** of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
** MERCHANTABLITY OR NON-INFRINGEMENT. 
**
** See the Apache 2 License for the specific language governing permissions 
** and limitations under the License.
**
**==============================================================================
*/

#include "client.h"
#include <base/packing.h>
#include <protocol/protocol.h>
#include <base/time.h>
#include <base/paths.h>
#include "thread.h"

#define TRACE printf("TRACE: %s(%u)\n", __FILE__, __LINE__)

#if 0
# define D(X) X
#else
# define D(X) /* empty */
#endif

MI_BEGIN_NAMESPACE

//==============================================================================
//
// Local definitions.
//
//==============================================================================

Uint64 _NextMsgID()
{
    static Mutex mutex;
    mutex.Lock();
    static Uint64 _msgID = 10000;
    Uint64 x = _msgID++;
    mutex.Unlock();

    return x;
}

static char* _StringToStr(const String& str)
{
    Uint32 n = str.GetSize();
    char* r = new char[n + 1];

    if (!r)
        return NULL;

    for (Uint32 i = 0; i < n; i++)
    {
        r[i] = char(str[i]);
    }

    r[n] = '\0';

    return r;
}

//==============================================================================
//
// class EnvelopeHandler
//
//==============================================================================

class EnvelopeHandler : public Handler
{
public:

    EnvelopeHandler(Handler* handler) : m_handler(handler)
    {
    }

    virtual void HandleConnect()
    {
        if (m_handler)
            m_handler->HandleConnect();
    }

    virtual void HandleConnectFailed()
    {
        if (m_handler)
            m_handler->HandleConnectFailed();
    }

    virtual void HandleDisconnect()
    {
        if (m_handler)
            m_handler->HandleDisconnect();
    }

    virtual void HandleNoOp(Uint64 msgID)
    {
        if (m_handler)
            m_handler->HandleNoOp(msgID);
    }

    virtual void HandleInstance(Uint64 msgID, const DInstance& instance)
    {
        if (m_handler)
            m_handler->HandleInstance(msgID, instance);
    }

    virtual void HandleResult(Uint64 msgID, MI_Result result)
    {
        if (m_handler)
            m_handler->HandleResult(msgID, result);
    }

private:
    Handler* m_handler;
};

//==============================================================================
//
// class NoOpHandler
//
//==============================================================================

class NoOpHandler : public EnvelopeHandler
{
public:

    enum State { START, DONE, FAILED };

    NoOpHandler(Handler* handler, Uint64 msgID) : 
        EnvelopeHandler(handler), m_state(START), m_msgID(msgID)
    {
    }

    virtual void HandleNoOp(Uint64 msgID)
    {
        if (msgID != m_msgID)
        {
            EnvelopeHandler::HandleNoOp(msgID);
            return;
        }

        if (m_state != START)
        {
            m_state = FAILED;
            return;
        }

        m_state = DONE;
    }

    State m_state;
    Uint64 m_msgID;
};

//==============================================================================
//
// class ResultHandler
//
//==============================================================================

class ResultHandler : public EnvelopeHandler
{
public:

    enum State { START, DONE, FAILED };

    ResultHandler(Handler* handler, Uint64 msgID) : 
        EnvelopeHandler(handler),
        m_state(START),
        m_msgID(msgID),
        m_result(MI_RESULT_OK)
    {
    }

    virtual void HandleResult(Uint64 msgID, Result result)
    {
        if (msgID != m_msgID)
        {
            EnvelopeHandler::HandleResult(msgID, result);
            return;
        }

        if (m_state != START)
        {
            m_state = FAILED;
            return;
        }

        m_result = result;
        m_state = DONE;
    }

    State m_state;
    Uint64 m_msgID;
    Result m_result;
};

//==============================================================================
//
// class InstanceHandler
//
//==============================================================================

class InstanceHandler : public EnvelopeHandler
{
public:

    enum State { INSTANCE, RESULT, DONE, FAILED };

    InstanceHandler(
        Handler* handler, 
        Uint64 msgID,
        DInstance& instance) 
        : 
        EnvelopeHandler(handler),
        m_state(INSTANCE),
        m_msgID(msgID),
        m_instance(instance),
        m_result(MI_RESULT_OK)
    {
    }

    virtual void HandleInstance(Uint64 msgID, const DInstance& instance)
    {
        if (msgID != m_msgID)
        {
            EnvelopeHandler::HandleInstance(msgID, instance);
            return;
        }

        if (m_state != INSTANCE)
        {
            m_state = FAILED;
            return;
        }

        m_instance = instance;
        m_state = RESULT;
    }

    virtual void HandleResult(Uint64 msgID, Result result)
    {
        if (msgID != m_msgID)
        {
            EnvelopeHandler::HandleResult(msgID, result);
            return;
        }

        if (m_state != INSTANCE && m_state != RESULT)
        {
            m_state = FAILED;
            return;
        }

        m_result = result;
        m_state = DONE;
    }

    State m_state;
    Uint64 m_msgID;
    DInstance& m_instance;
    Result m_result;
};

//==============================================================================
//
// class InstancesHandler
//
//==============================================================================

class InstancesHandler : public EnvelopeHandler
{
public:

    enum State { INSTANCES, RESULT, DONE, FAILED };

    InstancesHandler(
        Handler* handler, 
        Uint64 msgID,
        Array<DInstance>& instances) 
        : 
        EnvelopeHandler(handler),
        m_state(INSTANCES),
        m_msgID(msgID),
        m_instances(instances),
        m_result(MI_RESULT_OK)
    {
    }

    virtual void HandleInstance(Uint64 msgID, const DInstance& instance)
    {
        if (msgID != m_msgID)
        {
            EnvelopeHandler::HandleInstance(msgID, instance);
            return;
        }

        if (m_state != INSTANCES)
        {
            m_state = FAILED;
            return;
        }

        m_instances.PushBack(instance);
    }

    virtual void HandleResult(Uint64 msgID, Result result)
    {
        if (msgID != m_msgID)
        {
            EnvelopeHandler::HandleResult(msgID, result);
            return;
        }

        if (m_state != INSTANCES)
        {
            m_state = FAILED;
            return;
        }

        m_result = result;
        m_state = DONE;
    }

    State m_state;
    Uint64 m_msgID;
    Array<DInstance>& m_instances;
    Result m_result;
};

//==============================================================================
//
// class ClientRep
//
//==============================================================================

class ClientRep
{
public:
    enum ConnectState
    {
        CONNECTSTATE_PENDING,
        CONNECTSTATE_FAILED,
        CONNECTSTATE_CONNECTED,
        CONNECTSTATE_DISCONNECTED
    };

    Protocol* protocol;
    Handler* handler;
    ConnectState connectState;

    static void EventCallback(
        Protocol* protocol,
        ProtocolEvent event,
        void* data);

    static MI_Boolean MessageCallback(
        Protocol* protocol,
        Message* msg,
        void* data);

    bool NoOpAsync(
        Uint64 msgID);

    bool GetInstanceAsync(
        const String& nameSpace,
        const DInstance& instanceName,
        Uint64 msgID);

    bool CreateInstanceAsync(
        const String& nameSpace,
        const DInstance& instance,
        Uint64 msgID);

    bool ModifyInstanceAsync(
        const String& nameSpace,
        const DInstance& instance,
        Uint64 msgID);

    bool DeleteInstanceAsync(
        const String& nameSpace,
        const DInstance& instanceName,
        Uint64 msgID);

    bool EnumerateInstancesAsync(
        const String& nameSpace,
        const String& className,
        bool deepInheritance,
        const String& queryLanguage,
        const String& queryExpression,
        Uint64 msgID);

    bool InvokeAsync(
        const String& nameSpace,
        const DInstance& instanceName,
        const String& methodName,
        const DInstance& inParameters,
        DInstance& outParameters,
        Uint64 msgID);

    bool AssociatorInstancesAsync(
        const String& nameSpace,
        const DInstance& instanceName,
        const String& assocClass,
        const String& resultClass,
        const String& role,
        const String& resultRole,
        Uint64& msgID);

    bool ReferenceInstancesAsync(
        const String& nameSpace,
        const DInstance& instanceName,
        const String& assocClass,
        const String& role,
        Uint64& msgID);
};

void ClientRep::EventCallback(
    Protocol* protocol,
    ProtocolEvent event,
    void* data)
{
    ClientRep* clientRep = (ClientRep*)data;
    Handler* handler = clientRep->handler;

    D( printf("==== ClientRep::EventCallback()\n"); )


    if (event == PROTOCOLEVENT_CONNECT)
    {
        D( printf("==== EventCallback() PROTOCOLEVENT_CONNECT\n"); )
        clientRep->connectState = ClientRep::CONNECTSTATE_CONNECTED;
        if (handler)
            handler->HandleConnect();
        return;
    }

    if (event == PROTOCOLEVENT_CONNECT_FAILED)
    {
        D( printf("==== EventCallback() PROTOCOLEVENT_CONNECT_FAILED\n"); )
        if (handler)
            handler->HandleConnectFailed();
        clientRep->connectState = ClientRep::CONNECTSTATE_FAILED;
        return;
    }

    if (event == PROTOCOLEVENT_DISCONNECT)
    {
        D( printf("==== EventCallback() PROTOCOLEVENT_DISCONNECT\n"); )
        if (handler)
            handler->HandleDisconnect();
        clientRep->connectState = ClientRep::CONNECTSTATE_DISCONNECTED;
        return;
    }
}

MI_Boolean ClientRep::MessageCallback(
    Protocol* protocol,
    Message* msg,
    void* data)
{
    ClientRep* clientRep = (ClientRep*)data;
    Handler* handler = clientRep->handler;

    DEBUG_ASSERT(msg != 0);

    switch (msg->tag)
    {
        case NoOpRspTag:
        {
            D( printf("ClientRep::MessageCallback(): NoOpRspTag\n"); )
            NoOpRsp* rsp = (NoOpRsp*)msg;
            MI_UNUSED(rsp);
            if (handler)
                handler->HandleNoOp(rsp->base.msgID);
            break;
        }
        case PostInstanceMsgTag:
        {
            D( printf("ClientRep::MessageCallback(): PostInstanceMsgTag\n"); )
            PostInstanceMsg* rsp = (PostInstanceMsg*)msg;

            if (rsp->instance)
            {
                DInstance di(rsp->instance, DInstance::CLONE);
                if (handler)
                    handler->HandleInstance(rsp->base.msgID, di);
            }

            break;
        }
        case SubscribeResTag:
        {
            D( printf("ClientRep::MessageCallback(): SubscribeResTag\n"); )
            SubscribeRes* rsp = (SubscribeRes*)msg;
            MI_UNUSED(rsp);
            break;
        }
        case PostResultMsgTag:
        {
            D( printf("ClientRep::MessageCallback(): PostResultMsgTag\n"); )
            PostResultMsg* rsp = (PostResultMsg*)msg;
            if (handler)
                handler->HandleResult(rsp->base.msgID, rsp->result);
            break;
        }
        default:
        {
            D( printf("ClientRep::MessageCallback(): default\n"); )
            break;
        }
    }
    return MI_TRUE;
}

bool ClientRep::NoOpAsync(
    Uint64 msgID)
{
    NoOpReq* req = 0;
    bool result = true;

    // Fail if not connected:
    if (!protocol)
    {
        result = false;
        goto done;
    }

    // Create request message:
    {
        req = NoOpReq_New(msgID);

        if (!req)
        {
            result = false;
            goto done;
        }
    }

    // Send the message:
    {
        Result r = Protocol_Send(protocol, &req->base);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

done:

    if (req)
        NoOpReq_Release(req);

    return result;
}

bool ClientRep::GetInstanceAsync(
    const String& nameSpace,
    const DInstance& instanceName,
    Uint64 msgID)
{
    GetInstanceReq* req = 0;
    bool result = true;

    // Fail if not connected.
    if (!protocol)
    {
        result = false;
        goto done;
    }

    // Create the request message:
    {
        req = GetInstanceReq_New(msgID, BinaryProtocolFlag);

        if (!req)
        {
            result = false;
            goto done;
        }
    }

    // Set nameSpace:
    req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());

    // Pack the instance name into the message's batch.
    {
        Result r = InstanceToBatch(
            instanceName.m_self, 
            NULL,
            NULL,
            req->base.batch,
            &req->packedInstanceNamePtr, 
            &req->packedInstanceNameSize);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

    // Send the messages:
    {
        Result r = Protocol_Send(protocol, &req->base);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

done:
    if (req)
        GetInstanceReq_Release(req);

    return result;
}

bool ClientRep::CreateInstanceAsync(
    const String& nameSpace,
    const DInstance& instance,
    Uint64 msgID)
{
    CreateInstanceReq* req = 0;
    bool result = true;

    // Fail if not connected.
    if (!protocol)
    {
        result = false;
        goto done;
    }

    // Create the request message:
    {
        req = CreateInstanceReq_New(msgID, BinaryProtocolFlag);

        if (!req)
        {
            result = false;
            goto done;
        }
    }

    // Set nameSpace:
    req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());

    // Pack the instance name into the message's batch.
    {
        Result r = InstanceToBatch(
            instance.m_self, 
            NULL,
            NULL,
            req->base.batch,
            &req->packedInstancePtr, 
            &req->packedInstanceSize);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

    // Send the messages:
    {
        Result r = Protocol_Send(protocol, &req->base);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

done:
    if (req)
        CreateInstanceReq_Release(req);

    return result;
}

bool ClientRep::ModifyInstanceAsync(
    const String& nameSpace,
    const DInstance& instance,
    Uint64 msgID)
{
    ModifyInstanceReq* req = 0;
    bool result = true;

    // Fail if not connected.
    if (!protocol)
    {
        result = false;
        goto done;
    }

    // Create the request message:
    {
        req = ModifyInstanceReq_New(msgID, BinaryProtocolFlag);

        if (!req)
        {
            result = false;
            goto done;
        }
    }

    // Set nameSpace:
    req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());

    // Pack the instance name into the message's batch.
    {
        Result r = InstanceToBatch(
            instance.m_self, 
            NULL,
            NULL,
            req->base.batch,
            &req->packedInstancePtr, 
            &req->packedInstanceSize);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

    // Send the messages:
    {
        Result r = Protocol_Send(protocol, &req->base);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

done:
    if (req)
        ModifyInstanceReq_Release(req);

    return result;
}

bool ClientRep::DeleteInstanceAsync(
    const String& nameSpace,
    const DInstance& instanceName,
    Uint64 msgID)
{
    DeleteInstanceReq* req = 0;
    bool result = true;

    // Fail if not connected.
    if (!protocol)
    {
        result = false;
        goto done;
    }

    // Create the request message:
    {
        req = DeleteInstanceReq_New(msgID, BinaryProtocolFlag);

        if (!req)
        {
            result = false;
            goto done;
        }
    }

    // Set nameSpace:
    req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());

    // Pack the instance name into the message's batch.
    {
        Result r = InstanceToBatch(
            instanceName.m_self, 
            NULL,
            NULL,
            req->base.batch,
            &req->packedInstanceNamePtr, 
            &req->packedInstanceNameSize);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

    // Send the messages:
    {
        Result r = Protocol_Send(protocol, &req->base);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

done:
    if (req)
        DeleteInstanceReq_Release(req);

    return result;
}

bool ClientRep::EnumerateInstancesAsync(
    const String& nameSpace,
    const String& className,
    bool deepInheritance,
    const String& queryLanguage,
    const String& queryExpression,
    Uint64 msgID)
{
    EnumerateInstancesReq* req = 0;
    bool result = true;

    // Fail if not connected.
    if (!protocol)
    {
        result = false;
        goto done;
    }

    // Create the request message:
    {
        req = EnumerateInstancesReq_New(msgID, BinaryProtocolFlag);

        if (!req)
        {
            result = false;
            goto done;
        }
    }

    // Populate the fields of the request message:
    {
        req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());
        req->className = Batch_Zdup(req->base.batch, className.Str());

        if (queryLanguage.GetSize())
        {
            req->queryLanguage = 
                Batch_Zdup(req->base.batch, queryLanguage.Str());
        }

        if (queryExpression.GetSize())
        {
            req->queryExpression = 
                Batch_Zdup(req->base.batch, queryExpression.Str());
        }

        req->deepInheritance = deepInheritance;
    }

    // Send the messages:
    {
        Result r = Protocol_Send(protocol, &req->base);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

done:
    if (req)
        EnumerateInstancesReq_Release(req);

    return result;
}

bool ClientRep::InvokeAsync(
    const String& nameSpace,
    const DInstance& instanceName,
    const String& methodName,
    const DInstance& inParameters,
    DInstance& outParameters,
    Uint64 msgID)
{
    InvokeReq* req = 0;
    bool result = true;

    // Fail if not connected.
    if (!protocol)
    {
        result = false;
        goto done;
    }

    // Create the request message:
    {
        req = InvokeReq_New(msgID, BinaryProtocolFlag);

        if (!req)
        {
            result = false;
            goto done;
        }
    }

    // Set nameSpace:
    req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());

    // Set className:
    req->className = Batch_Zdup(req->base.batch, 
        instanceName.GetClassName().Str());

    // Set methodName:
    req->function = Batch_Zdup(req->base.batch, methodName.Str());

    // Pack instanceName:
    if (instanceName.Count())
    {
        Result r = InstanceToBatch(
            instanceName.m_self, 
            NULL, 
            NULL,
            req->base.batch, 
            &req->packedInstancePtr, 
            &req->packedInstanceSize);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

    // Pack inParameters:
    {
        Result r = InstanceToBatch(
            inParameters.m_self, 
            NULL, 
            NULL,
            req->base.batch,
            &req->packedInstanceParamsPtr, 
            &req->packedInstanceParamsSize);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

    // Send the messages:
    {
        Result r = Protocol_Send(protocol, &req->base);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

done:
    if (req)
        InvokeReq_Release(req);

    return result;
}

bool ClientRep::AssociatorInstancesAsync(
    const String& nameSpace,
    const DInstance& instanceName,
    const String& assocClass,
    const String& resultClass,
    const String& role,
    const String& resultRole,
    Uint64& msgID)
{
    AssociatorsOfReq* req = 0;
    bool result = true;

    // Fail if not connected.
    if (!protocol)
    {
        result = false;
        goto done;
    }

    // Create the request message:
    {
        req = AssociatorsOfReq_New(msgID, BinaryProtocolFlag);

        if (!req)
        {
            result = false;
            goto done;
        }
    }

    // Set nameSpace:
    req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());

    // Set assocClass:
    if (assocClass.GetSize())
        req->assocClass = Batch_Zdup(req->base.batch, assocClass.Str());

    // Set resultClass:
    if (resultClass.GetSize())
        req->resultClass = Batch_Zdup(req->base.batch,resultClass.Str());

    // Set role:
    if (role.GetSize())
        req->role = Batch_Zdup(req->base.batch, role.Str());

    // Set resultRole:
    if (resultRole.GetSize())
        req->resultRole = Batch_Zdup(req->base.batch, resultRole.Str());

    // Pack the instance name into the message's batch.
    {
        Result r = InstanceToBatch(
            instanceName.m_self, 
            NULL,
            NULL,
            req->base.batch,
            &req->packedInstancePtr, 
            &req->packedInstanceSize);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

    // Send the messages:
    {
        Result r = Protocol_Send(protocol, &req->base);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

done:
    if (req)
    {
        AssociatorsOfReq_Release(req);
    }

    return result;
}

bool ClientRep::ReferenceInstancesAsync(
    const String& nameSpace,
    const DInstance& instanceName,
    const String& assocClass,
    const String& role,
    Uint64& msgID)
{
    ReferencesOfReq* req = 0;
    bool result = true;

    // Fail if not connected.
    if (!protocol)
    {
        result = false;
        goto done;
    }

    // Create the request message:
    {
        req = ReferencesOfReq_New(msgID, BinaryProtocolFlag);

        if (!req)
        {
            result = false;
            goto done;
        }
    }

    // Set nameSpace:
    req->nameSpace = Batch_Zdup(req->base.batch, nameSpace.Str());

    // Set assocClass:
    if (assocClass.GetSize())
        req->assocClass = Batch_Zdup(req->base.batch, assocClass.Str());

    // Set role:
    if (role.GetSize())
        req->role = Batch_Zdup(req->base.batch, role.Str());

    // Pack the instance name into the message's batch.
    {
        Result r = InstanceToBatch(
            instanceName.m_self, 
            NULL,
            NULL,
            req->base.batch,
            &req->packedInstancePtr, 
            &req->packedInstanceSize);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

    // Send the messages:
    {
        Result r = Protocol_Send(protocol, &req->base);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }
    }

done:
    if (req)
        ReferencesOfReq_Release(req);

    return result;
}

//==============================================================================
//
// class Client
//
//==============================================================================

Client::Client(Handler* handler)
{
    m_rep = new ClientRep;
    m_rep->protocol = 0;
    m_rep->connectState = ClientRep::CONNECTSTATE_DISCONNECTED;
    m_rep->handler = handler;
}

Client::~Client()
{
    Disconnect();
    delete m_rep->handler;
    delete m_rep;
}

bool Client::ConnectAsync(
    const String& locatorIn,
    const String& user,
    const String& password)
{
    Result r;
    bool result = true;
    String locator = locatorIn;
    char* locator_ = NULL;
    char* user_ = NULL;
    char* password_ = NULL;

    // Fail if already connected:
    if (m_rep->protocol)
    {
        result = false;
        goto done;
    }

    // Locator defaults to SOCKETFILE:
    if (locator.GetSize() == 0)
    {
#ifdef CONFIG_POSIX
        locator = GetPath(ID_SOCKETFILE);
#else
        locator = MI_T("localhost:7777");
#endif
    }

    // Convert host to 'char' type:
    locator_ = _StringToStr(locator);
    if (!locator_)
    {
        goto done;
    }
    user_ = _StringToStr(user);
    if (!user_)
    {
        goto done;
    }
    password_ = _StringToStr(password);
    if (!password_)
    {
        goto done;
    }

    // Set connection state to pending.
    m_rep->connectState = ClientRep::CONNECTSTATE_PENDING;

    // Establish connection with server:
    {
        Protocol* protocol = NULL;
        r = Protocol_New_Connector(
            &protocol, 
            NULL,
            locator_,
            (ProtocolCallback)ClientRep::MessageCallback, 
            m_rep,
            (ProtocolEventCallback)ClientRep::EventCallback, 
            m_rep,
            user_,
            password_);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }

        m_rep->protocol = protocol;
    }

done:

    if (locator_)
        delete [] locator_;
    if (user_)
        delete [] user_;
    if (password_)
        delete [] password_;
    return result;
}

bool Client::Connect(
    const String& locator, 
    const String& user,
    const String& password,
    Uint64 timeOutUsec)
{
    m_rep->connectState = ClientRep::CONNECTSTATE_PENDING;

    if (!ConnectAsync(locator, user, password))
        return false;

    Uint64 endTime, now;

    if (Time_Now(&now) != MI_RESULT_OK)
        return false;

    endTime = now + timeOutUsec;

    // Wait for connection establishment or timeout.
    for (;endTime >= now;)
    {
        Protocol_Run(m_rep->protocol, 1000);

        if (m_rep->connectState != ClientRep::CONNECTSTATE_PENDING)
            break;

        if (Time_Now(&now) != MI_RESULT_OK)
            break;
    }

    if (m_rep->connectState != ClientRep::CONNECTSTATE_CONNECTED)
        return false;

    return true;
}

bool Client::Disconnect()
{
    bool result = true;

    // Fail if not connected:
    if (!m_rep->protocol)
    {
        result = false;
        goto done;
    }

    // Delete the protocol object.
    {
        Result r = Protocol_Delete(m_rep->protocol);

        if (r != MI_RESULT_OK)
        {
            result = false;
            goto done;
        }

        m_rep->protocol = 0;
    }

    m_rep->connectState = ClientRep::CONNECTSTATE_DISCONNECTED;

done:
    return result;
}

bool Client::Connected() const
{
    return m_rep->protocol ? true : false;
}

bool Client::Run(Uint64 timeOutUsec)
{
    bool result = true;

    // Fail if not connected.
    if (!m_rep->protocol)
    {
        result = false;
        goto done;
    }

    // Process events.
    // ATTN: what can this return?
    Protocol_Run(m_rep->protocol, timeOutUsec);

done:
    return result;
}

bool Client::NoOpAsync(
    Uint64& msgID)
{
    msgID = _NextMsgID();
    return m_rep->NoOpAsync(msgID);
}

bool Client::GetInstanceAsync(
    const String& nameSpace,
    const DInstance& instanceName,
    Uint64& msgID)
{
    msgID = _NextMsgID();
    return m_rep->GetInstanceAsync(nameSpace, instanceName, msgID);
}

bool Client::CreateInstanceAsync(
    const String& nameSpace,
    const DInstance& instance,
    Uint64& msgID)
{
    msgID = _NextMsgID();
    return m_rep->CreateInstanceAsync(nameSpace, instance, msgID);
}

bool Client::ModifyInstanceAsync(
    const String& nameSpace,
    const DInstance& instance,
    Uint64& msgID)
{
    msgID = _NextMsgID();
    return m_rep->ModifyInstanceAsync(nameSpace, instance, msgID);
}

bool Client::DeleteInstanceAsync(
    const String& nameSpace,
    const DInstance& instanceName,
    Uint64& msgID)
{
    msgID = _NextMsgID();
    return m_rep->DeleteInstanceAsync(nameSpace, instanceName, msgID);
}

bool Client::EnumerateInstancesAsync(
    const String& nameSpace,
    const String& className,
    bool deepInheritance,
    const String& queryLanguage,
    const String& queryExpression,
    Uint64& msgID)
{
    msgID = _NextMsgID();
    return m_rep->EnumerateInstancesAsync(nameSpace, className, 
        deepInheritance, queryLanguage, queryExpression, msgID);
}

bool Client::InvokeAsync(
    const String& nameSpace,
    const DInstance& instanceName,
    const String& methodName,
    const DInstance& inParameters,
    DInstance& outParameters,
    Uint64 msgID)
{
    msgID = _NextMsgID();
    return m_rep->InvokeAsync(nameSpace, instanceName, methodName, inParameters,
        outParameters, msgID);
}

bool Client::AssociatorInstancesAsync(
    const String& nameSpace,
    const DInstance& instanceName,
    const String& assocClass,
    const String& resultClass,
    const String& role,
    const String& resultRole,
    Uint64& msgID)
{
    msgID = _NextMsgID();
    return m_rep->AssociatorInstancesAsync(nameSpace, instanceName, assocClass,
        resultClass, role, resultRole, msgID);
}

bool Client::ReferenceInstancesAsync(
    const String& nameSpace,
    const DInstance& instanceName,
    const String& assocClass,
    const String& role,
    Uint64& msgID)
{
    msgID = _NextMsgID();
    return m_rep->ReferenceInstancesAsync(nameSpace, instanceName, assocClass,
        role, msgID);
}

bool Client::GetInstance(
    const String& nameSpace,
    const DInstance& instanceName,
    Uint64 timeOutUsec,
    DInstance& instance,
    Result& result)
{
    Handler* oldHandler = m_rep->handler;
    Uint64 msgID = _NextMsgID();
    InstanceHandler handler(oldHandler, msgID, instance);
    m_rep->handler = &handler;
    bool flag = true;

    if (!m_rep->GetInstanceAsync(nameSpace, instanceName, msgID))
    {
        flag = false;
        goto done;
    }

    Uint64 endTime, now;

    if (Time_Now(&now) != MI_RESULT_OK)
        return false;

    endTime = now + timeOutUsec;

    for (;endTime >= now;)
    {
        Protocol_Run(m_rep->protocol, 1000);

        if (handler.m_state == InstanceHandler::FAILED ||
            handler.m_state == InstanceHandler::DONE)
        {
            break;
        }

        if (Time_Now(&now) != MI_RESULT_OK)
            break;
    }

    if (handler.m_state == InstanceHandler::DONE)
        result = handler.m_result;
    else
        flag = false;

done:
    m_rep->handler = oldHandler;
    return flag;
}

bool Client::CreateInstance(
    const String& nameSpace,
    const DInstance& instance,
    Uint64 timeOutUsec,
    DInstance& instanceName,
    Result& result)
{
    Handler* oldHandler = m_rep->handler;
    Uint64 msgID = _NextMsgID();
    InstanceHandler handler(oldHandler, msgID, instanceName);
    m_rep->handler = &handler;
    bool flag = true;

    if (!m_rep->CreateInstanceAsync(nameSpace, instance, msgID))
    {
        flag = false;
        goto done;
    }

    Uint64 endTime, now;

    if (Time_Now(&now) != MI_RESULT_OK)
        return false;

    endTime = now + timeOutUsec;

    for (;endTime >= now;)
    {
        Protocol_Run(m_rep->protocol, 1000);

        if (handler.m_state == InstanceHandler::FAILED ||
            handler.m_state == InstanceHandler::DONE)
        {
            break;
        }

        if (Time_Now(&now) != MI_RESULT_OK)
            break;
    }

    if (handler.m_state == InstanceHandler::DONE)
        result = handler.m_result;
    else
        flag = false;

done:
    m_rep->handler = oldHandler;
    return flag;
}

bool Client::ModifyInstance(
    const String& nameSpace,
    const DInstance& instance,
    Uint64 timeOutUsec,
    Result& result)
{
    Handler* oldHandler = m_rep->handler;
    Uint64 msgID = _NextMsgID();
    ResultHandler handler(oldHandler, msgID);
    m_rep->handler = &handler;
    bool flag = true;

    if (!m_rep->ModifyInstanceAsync(nameSpace, instance, msgID))
    {
        flag = false;
        goto done;
    }

    Uint64 endTime, now;

    if (Time_Now(&now) != MI_RESULT_OK)
        return false;

    endTime = now + timeOutUsec;

    for (;endTime >= now;)
    {
        Protocol_Run(m_rep->protocol, 1000);

        if (handler.m_state == ResultHandler::FAILED ||
            handler.m_state == ResultHandler::DONE)
        {
            break;
        }

        if (Time_Now(&now) != MI_RESULT_OK)
            break;
    }

    if (handler.m_state == ResultHandler::DONE)
        result = handler.m_result;
    else
        flag = false;

done:
    m_rep->handler = oldHandler;
    return flag;
}

bool Client::DeleteInstance(
    const String& nameSpace,
    const DInstance& instanceName,
    Uint64 timeOutUsec,
    Result& result)
{
    Handler* oldHandler = m_rep->handler;
    Uint64 msgID = _NextMsgID();
    ResultHandler handler(oldHandler, msgID);
    m_rep->handler = &handler;
    bool flag = true;

    if (!m_rep->DeleteInstanceAsync(nameSpace, instanceName, msgID))
    {
        flag = false;
        goto done;
    }

    Uint64 endTime, now;

    if (Time_Now(&now) != MI_RESULT_OK)
        return false;

    endTime = now + timeOutUsec;

    for (;endTime >= now;)
    {
        Protocol_Run(m_rep->protocol, 1000);

        if (handler.m_state == ResultHandler::FAILED ||
            handler.m_state == ResultHandler::DONE)
        {
            break;
        }

        if (Time_Now(&now) != MI_RESULT_OK)
            break;
    }

    if (handler.m_state == ResultHandler::DONE)
        result = handler.m_result;
    else
        flag = false;

done:
    m_rep->handler = oldHandler;
    return flag;
}

bool Client::NoOp(Uint64 timeOutUsec)
{
    Handler* oldHandler = m_rep->handler;
    Uint64 msgID = _NextMsgID();
    NoOpHandler handler(oldHandler, msgID);
    m_rep->handler = &handler;
    bool flag = true;

    if (!m_rep->NoOpAsync(msgID))
    {
        flag = false;
        goto done;
    }

    Uint64 endTime, now;

    if (Time_Now(&now) != MI_RESULT_OK)
        return false;

    endTime = now + timeOutUsec;

    for (;endTime >= now;)
    {
        Protocol_Run(m_rep->protocol, 1000);

        if (handler.m_state == NoOpHandler::FAILED ||
            handler.m_state == NoOpHandler::DONE)
        {
            break;
        }

        if (Time_Now(&now) != MI_RESULT_OK)
            break;
    }

    if (handler.m_state != NoOpHandler::DONE)
        flag = false;

done:
    m_rep->handler = oldHandler;
    return flag;
}

bool Client::EnumerateInstances(
    const String& nameSpace,
    const String& className,
    bool deepInheritance,
    Uint64 timeOutUsec,
    Array<DInstance>& instances,
    const String& queryLanguage,
    const String& queryExpression,
    Result& result)
{
    Handler* oldHandler = m_rep->handler;
    Uint64 msgID = _NextMsgID();
    InstancesHandler handler(oldHandler, msgID, instances);
    m_rep->handler = &handler;
    bool flag = true;

    if (!m_rep->EnumerateInstancesAsync(nameSpace, className, deepInheritance,
        queryLanguage, queryExpression, msgID))
    {
        flag = false;
        goto done;
    }

    Uint64 endTime, now;

    if (Time_Now(&now) != MI_RESULT_OK)
        return false;

    endTime = now + timeOutUsec;

    for (;endTime >= now;)
    {
        Protocol_Run(m_rep->protocol, 1000);

        if (handler.m_state == InstancesHandler::FAILED ||
            handler.m_state == InstancesHandler::DONE)
        {
            break;
        }

        if (Time_Now(&now) != MI_RESULT_OK)
            break;
    }

    if (handler.m_state == InstancesHandler::DONE)
        result = handler.m_result;
    else
        flag = false;

done:
    m_rep->handler = oldHandler;
    return flag;
}

bool Client::Invoke(
    const String& nameSpace,
    const DInstance& instanceName,
    const String& methodName,
    const DInstance& inParameters,
    Uint64 timeOutUsec,
    DInstance& outParameters,
    Result& result)
{
    Handler* oldHandler = m_rep->handler;
    Uint64 msgID = _NextMsgID();
    InstanceHandler handler(oldHandler, msgID, outParameters);
    m_rep->handler = &handler;
    bool flag = true;

    if (!m_rep->InvokeAsync(nameSpace, instanceName, methodName, inParameters,
        outParameters, msgID))
    {
        flag = false;
        goto done;
    }

    Uint64 endTime, now;

    if (Time_Now(&now) != MI_RESULT_OK)
        return false;

    endTime = now + timeOutUsec;

    for (;endTime >= now;)
    {
        Protocol_Run(m_rep->protocol, 1000);

        if (handler.m_state == InstanceHandler::FAILED ||
            handler.m_state == InstanceHandler::DONE)
        {
            break;
        }

        if (Time_Now(&now) != MI_RESULT_OK)
            break;
    }

    if (handler.m_state == InstanceHandler::DONE)
        result = handler.m_result;
    else
        flag = false;

done:
    m_rep->handler = oldHandler;
    return flag;
}

bool Client::AssociatorInstances(
    const String& nameSpace,
    const DInstance& instanceName,
    const String& assocClass,
    const String& resultClass,
    const String& role,
    const String& resultRole,
    Uint64 timeOutUsec,
    Array<DInstance>& instances,
    Result& result)
{
    Handler* oldHandler = m_rep->handler;
    Uint64 msgID = _NextMsgID();
    InstancesHandler handler(oldHandler, msgID, instances);
    m_rep->handler = &handler;
    bool flag = true;

    if (!m_rep->AssociatorInstancesAsync(nameSpace, instanceName, assocClass,
        resultClass, role, resultRole, msgID))
    {
        flag = false;
        goto done;
    }

    Uint64 endTime, now;

    if (Time_Now(&now) != MI_RESULT_OK)
        return false;

    endTime = now + timeOutUsec;

    for (;endTime >= now;)
    {
        Protocol_Run(m_rep->protocol, 1000);

        if (handler.m_state == InstancesHandler::FAILED ||
            handler.m_state == InstancesHandler::DONE)
        {
            break;
        }

        if (Time_Now(&now) != MI_RESULT_OK)
            break;
    }

    if (handler.m_state == InstancesHandler::DONE)
        result = handler.m_result;
    else
        flag = false;

done:
    m_rep->handler = oldHandler;
    return flag;
}

bool Client::ReferenceInstances(
    const String& nameSpace,
    const DInstance& instanceName,
    const String& assocClass,
    const String& role,
    Uint64 timeOutUsec,
    Array<DInstance>& instances,
    Result& result)
{
    Handler* oldHandler = m_rep->handler;
    Uint64 msgID = _NextMsgID();
    InstancesHandler handler(oldHandler, msgID, instances);
    m_rep->handler = &handler;
    bool flag = true;

    if (!m_rep->ReferenceInstancesAsync(nameSpace, instanceName, assocClass,
        role, msgID))
    {
        flag = false;
        goto done;
    }

    Uint64 endTime, now;

    if (Time_Now(&now) != MI_RESULT_OK)
        return false;

    endTime = now + timeOutUsec;

    for (;endTime >= now;)
    {
        Protocol_Run(m_rep->protocol, 1000);

        if (handler.m_state == InstancesHandler::FAILED ||
            handler.m_state == InstancesHandler::DONE)
        {
            break;
        }

        if (Time_Now(&now) != MI_RESULT_OK)
            break;
    }

    if (handler.m_state == InstancesHandler::DONE)
        result = handler.m_result;
    else
        flag = false;

done:
    m_rep->handler = oldHandler;
    return flag;
}

MI_END_NAMESPACE

ViewCVS 0.9.2