/* **============================================================================== ** ** 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 #include #include #include #include #include #if 0 # define D(X) X #else # define D(X) /* empty */ #endif STRAND_DEBUGNAME(OmiClient); MI_BEGIN_NAMESPACE //============================================================================== // // Local definitions. // //============================================================================== PAL_Uint64 _NextOperationId() { static volatile ptrdiff_t _operationId = 10000; PAL_Uint64 x = Atomic_Inc(&_operationId); 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; } static String _StrToString(const char* str) { String r; while (str) { MI_Char c = *str++; r.Append(&c, 1); } 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 operationId) { if (m_handler) m_handler->HandleNoOp(operationId); } virtual void HandleInstance(Uint64 operationId, const DInstance& instance) { if (m_handler) m_handler->HandleInstance(operationId, instance); } virtual void HandleResult(Uint64 operationId, MI_Result result) { if (m_handler) m_handler->HandleResult(operationId, result); } virtual void HandleResult(Uint64 operationId, MI_Result result, const MI_Char *error, const DInstance* cimError) { if (m_handler) m_handler->HandleResult(operationId, result, error, cimError); } private: Handler* m_handler; }; //============================================================================== // // class NoOpHandler // //============================================================================== class NoOpHandler : public EnvelopeHandler { public: enum State { START, DONE, FAILED }; NoOpHandler(Handler* handler, Uint64 operationId) : EnvelopeHandler(handler), m_state(START), m_operationId(operationId) { } virtual void HandleNoOp(Uint64 operationId) { if (operationId != m_operationId) { EnvelopeHandler::HandleNoOp(operationId); return; } if (m_state != START) { m_state = FAILED; return; } m_state = DONE; } State m_state; Uint64 m_operationId; }; //============================================================================== // // class ResultHandler // //============================================================================== class ResultHandler : public EnvelopeHandler { public: enum State { START, DONE, FAILED }; ResultHandler(Handler* handler, Uint64 operationId) : EnvelopeHandler(handler), m_state(START), m_operationId(operationId), m_result(MI_RESULT_OK), m_cimerror(NULL), m_errorMessage(NULL) { } virtual void HandleResult(Uint64 operationId, Result result) { if (operationId != m_operationId) { EnvelopeHandler::HandleResult(operationId, result); return; } if (m_state != START) { m_state = FAILED; return; } m_result = result; m_state = DONE; } virtual void HandleResult(Uint64 operationId, MI_Result result, const MI_Char *error, const DInstance* cimError) { if (operationId != m_operationId) { EnvelopeHandler::HandleResult(operationId, result, error, cimError); return; } if (m_state != START) { m_state = FAILED; return; } m_result = result; m_cimerror = cimError; m_errorMessage = error; m_state = DONE; } State m_state; Uint64 m_operationId; Result m_result; const DInstance* m_cimerror; const MI_Char *m_errorMessage; }; //============================================================================== // // class InstanceHandler // //============================================================================== class InstanceHandler : public EnvelopeHandler { public: enum State { INSTANCE, RESULT, DONE, FAILED }; InstanceHandler( Handler* handler, Uint64 operationId, DInstance& instance) : EnvelopeHandler(handler), m_state(INSTANCE), m_operationId(operationId), m_instance(instance), m_result(MI_RESULT_OK), m_errorMessage(NULL), m_cimerror(NULL) { } virtual void HandleInstance(Uint64 operationId, const DInstance& instance) { if (operationId != m_operationId) { EnvelopeHandler::HandleInstance(operationId, instance); return; } if (m_state != INSTANCE) { m_state = FAILED; return; } m_instance = instance; m_state = RESULT; } virtual void HandleResult(Uint64 operationId, Result result) { if (operationId != m_operationId) { EnvelopeHandler::HandleResult(operationId, result); return; } if (m_state != INSTANCE && m_state != RESULT) { m_state = FAILED; return; } m_result = result; m_state = DONE; } virtual void HandleResult(Uint64 operationId, MI_Result result, const MI_Char *error, const DInstance* cimError) { if (operationId != m_operationId) { EnvelopeHandler::HandleResult(operationId, result, error, cimError); return; } if (m_state != INSTANCE && m_state != RESULT) { m_state = FAILED; return; } m_result = result; m_cimerror = cimError; m_errorMessage = error; m_state = DONE; } State m_state; Uint64 m_operationId; DInstance& m_instance; Result m_result; const MI_Char *m_errorMessage; const DInstance* m_cimerror; }; //============================================================================== // // class InstancesHandler // //============================================================================== class InstancesHandler : public EnvelopeHandler { public: enum State { INSTANCES, RESULT, DONE, FAILED }; InstancesHandler( Handler* handler, Uint64 operationId, Array& instances) : EnvelopeHandler(handler), m_state(INSTANCES), m_operationId(operationId), m_instances(instances), m_result(MI_RESULT_OK) { } virtual void HandleInstance(Uint64 operationId, const DInstance& instance) { if (operationId != m_operationId) { EnvelopeHandler::HandleInstance(operationId, instance); return; } if (m_state != INSTANCES) { m_state = FAILED; return; } m_instances.PushBack(instance); } virtual void HandleResult(Uint64 operationId, Result result) { if (operationId != m_operationId) { EnvelopeHandler::HandleResult(operationId, result); return; } if (m_state != INSTANCES) { m_state = FAILED; return; } m_result = result; m_state = DONE; } virtual void HandleResult(Uint64 operationId, Result result, const MI_Char *error, const DInstance* cimError) { if (operationId != m_operationId) { EnvelopeHandler::HandleResult(operationId, result); return; } if (m_state != INSTANCES) { m_state = FAILED; return; } m_result = result; m_state = DONE; } State m_state; Uint64 m_operationId; Array& m_instances; Result m_result; }; //============================================================================== // // class ClientRep // //============================================================================== class ClientRep { public: enum ConnectState { CONNECTSTATE_PENDING, CONNECTSTATE_FAILED, CONNECTSTATE_CONNECTED, CONNECTSTATE_DISCONNECTED }; ProtocolSocketAndBase* protocol; Strand strand; // To manage interaction with ProtocolSocket Handler* handler; ConnectState connectState; static void MessageCallback( ClientRep * rep, Message* msg); bool NoOpAsync( Uint64 operationId); bool GetInstanceAsync( const String& nameSpace, const DInstance& instanceName, Uint64 operationId); bool CreateInstanceAsync( const String& nameSpace, const DInstance& instance, Uint64 operationId); bool ModifyInstanceAsync( const String& nameSpace, const DInstance& instance, Uint64 operationId); bool DeleteInstanceAsync( const String& nameSpace, const DInstance& instanceName, Uint64 operationId); bool EnumerateInstancesAsync( const String& nameSpace, const String& className, bool deepInheritance, const String& queryLanguage, const String& queryExpression, Uint64 operationId); bool InvokeAsync( const String& nameSpace, const DInstance& instanceName, const String& methodName, const DInstance& inParameters, DInstance& outParameters, Uint64 operationId); bool AssociatorInstancesAsync( const String& nameSpace, const DInstance& instanceName, const String& assocClass, const String& resultClass, const String& role, const String& resultRole, Uint64& operationId); bool ReferenceInstancesAsync( const String& nameSpace, const DInstance& instanceName, const String& resultClass, const String& role, Uint64& operationId); }; void ClientRep::MessageCallback( ClientRep * clientRep, Message* msg) { 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.operationId); 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.operationId, di); } break; } case PostResultMsgTag: { D( printf("ClientRep::MessageCallback(): PostResultMsgTag\n"); ) PostResultMsg* rsp = (PostResultMsg*)msg; if (handler) { if (rsp->cimError) { DInstance di((MI_Instance*)(rsp->cimError), DInstance::CLONE); handler->HandleResult(rsp->base.operationId, rsp->result, rsp->errorMessage, &di); } else { handler->HandleResult(rsp->base.operationId, rsp->result, rsp->errorMessage, NULL); } } break; } default: { D( printf("ClientRep::MessageCallback(): default\n"); ) break; } } } bool ClientRep::NoOpAsync( Uint64 operationId) { NoOpReq* req = 0; bool result = true; // Fail if not connected: if( !protocol || !strand.info.opened ) { result = false; goto done; } // Create request message: { req = NoOpReq_New(operationId); if (!req) { result = false; goto done; } } // Send the message: { Strand_SchedulePost(&strand,&req->base.base); } done: if (req) NoOpReq_Release(req); return result; } bool ClientRep::GetInstanceAsync( const String& nameSpace, const DInstance& instanceName, Uint64 operationId) { GetInstanceReq* req = 0; bool result = true; // Fail if not connected. if( !protocol || !strand.info.opened ) { result = false; goto done; } // Create the request message: { req = GetInstanceReq_New(operationId, BinaryProtocolFlag); if (!req) { result = false; goto done; } } // Set nameSpace: req->nameSpace = Batch_Tcsdup(req->base.base.batch, nameSpace.Str()); if (!req->nameSpace) { result = false; goto done; } // Pack the instance name into the message's batch. { Result r = InstanceToBatch( instanceName.m_self, NULL, NULL, req->base.base.batch, &req->packedInstanceNamePtr, &req->packedInstanceNameSize); if (r != MI_RESULT_OK) { result = false; goto done; } } // Send the messages: { Strand_SchedulePost(&strand,&req->base.base); } done: if (req) GetInstanceReq_Release(req); return result; } bool ClientRep::CreateInstanceAsync( const String& nameSpace, const DInstance& instance, Uint64 operationId) { CreateInstanceReq* req = 0; bool result = true; // Fail if not connected. if( !protocol || !strand.info.opened ) { result = false; goto done; } // Create the request message: { req = CreateInstanceReq_New(operationId, BinaryProtocolFlag); if (!req) { result = false; goto done; } } // Set nameSpace: req->nameSpace = Batch_Tcsdup(req->base.base.batch, nameSpace.Str()); if (!req->nameSpace) { result = false; goto done; } // Pack the instance name into the message's batch. { Result r = InstanceToBatch( instance.m_self, NULL, NULL, req->base.base.batch, &req->packedInstancePtr, &req->packedInstanceSize); if (r != MI_RESULT_OK) { result = false; goto done; } } // Send the messages: { Strand_SchedulePost(&strand,&req->base.base); } done: if (req) CreateInstanceReq_Release(req); return result; } bool ClientRep::ModifyInstanceAsync( const String& nameSpace, const DInstance& instance, Uint64 operationId) { ModifyInstanceReq* req = 0; bool result = true; // Fail if not connected. if( !protocol || !strand.info.opened ) { result = false; goto done; } // Create the request message: { req = ModifyInstanceReq_New(operationId, BinaryProtocolFlag); if (!req) { result = false; goto done; } } // Set nameSpace: req->nameSpace = Batch_Tcsdup(req->base.base.batch, nameSpace.Str()); if (!req->nameSpace) { result = false; goto done; } // Pack the instance name into the message's batch. { Result r = InstanceToBatch( instance.m_self, NULL, NULL, req->base.base.batch, &req->packedInstancePtr, &req->packedInstanceSize); if (r != MI_RESULT_OK) { result = false; goto done; } } // Send the messages: Strand_SchedulePost(&strand,&req->base.base); done: if (req) ModifyInstanceReq_Release(req); return result; } bool ClientRep::DeleteInstanceAsync( const String& nameSpace, const DInstance& instanceName, Uint64 operationId) { DeleteInstanceReq* req = 0; bool result = true; // Fail if not connected. if( !protocol || !strand.info.opened ) { result = false; goto done; } // Create the request message: { req = DeleteInstanceReq_New(operationId, BinaryProtocolFlag); if (!req) { result = false; goto done; } } // Set nameSpace: req->nameSpace = Batch_Tcsdup(req->base.base.batch, nameSpace.Str()); if (!req->nameSpace) { result = false; goto done; } // Pack the instance name into the message's batch. { Result r = InstanceToBatch( instanceName.m_self, NULL, NULL, req->base.base.batch, &req->packedInstanceNamePtr, &req->packedInstanceNameSize); if (r != MI_RESULT_OK) { result = false; goto done; } } // Send the messages: Strand_SchedulePost(&strand,&req->base.base); 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 operationId) { EnumerateInstancesReq* req = 0; bool result = true; // Fail if not connected. if( !protocol || !strand.info.opened ) { result = false; goto done; } // Create the request message: { req = EnumerateInstancesReq_New(operationId, BinaryProtocolFlag); if (!req) { result = false; goto done; } } // Populate the fields of the request message: { req->nameSpace = Batch_Tcsdup(req->base.base.batch, nameSpace.Str()); req->className = Batch_Tcsdup(req->base.base.batch, className.Str()); if (!req->nameSpace || !req->className) { result = false; goto done; } if (queryLanguage.GetSize()) { req->queryLanguage = Batch_Tcsdup(req->base.base.batch, queryLanguage.Str()); if (!req->queryLanguage) { result = false; goto done; } } if (queryExpression.GetSize()) { req->queryExpression = Batch_Tcsdup(req->base.base.batch, queryExpression.Str()); if (!req->queryExpression) { result = false; goto done; } } req->deepInheritance = deepInheritance; } // Send the messages: Strand_SchedulePost(&strand,&req->base.base); 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 operationId) { InvokeReq* req = 0; bool result = true; // Fail if not connected. if( !protocol || !strand.info.opened ) { result = false; goto done; } // Create the request message: { req = InvokeReq_New(operationId, BinaryProtocolFlag); if (!req) { result = false; goto done; } } // Set nameSpace: req->nameSpace = Batch_Tcsdup(req->base.base.batch, nameSpace.Str()); if (!req->nameSpace) { result = false; goto done; } // Set className: req->className = Batch_Tcsdup(req->base.base.batch, instanceName.GetClassName().Str()); if (!req->className) { result = false; goto done; } // Set methodName: req->function = Batch_Tcsdup(req->base.base.batch, methodName.Str()); if (!req->function) { result = false; goto done; } // Pack instanceName: if (instanceName.Count()) { Result r = InstanceToBatch( instanceName.m_self, NULL, NULL, req->base.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.base.batch, &req->packedInstanceParamsPtr, &req->packedInstanceParamsSize); if (r != MI_RESULT_OK) { result = false; goto done; } } // Send the messages: Strand_SchedulePost(&strand,&req->base.base); 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& operationId) { AssociationsOfReq* req = 0; bool result = true; // Fail if not connected. if( !protocol || !strand.info.opened ) { result = false; goto done; } // Create the request message: { req = AssociationsOfReq_New(operationId, BinaryProtocolFlag, AssociatorsOfReqTag); if (!req) { result = false; goto done; } } // Set nameSpace: req->nameSpace = Batch_Tcsdup(req->base.base.batch, nameSpace.Str()); if (!req->nameSpace) { result = false; goto done; } // Set assocClass: if (assocClass.GetSize()) { req->assocClass = Batch_Tcsdup(req->base.base.batch, assocClass.Str()); if (!req->assocClass) { result = false; goto done; } } // Set resultClass: if (resultClass.GetSize()) { req->resultClass = Batch_Tcsdup(req->base.base.batch,resultClass.Str()); if (!req->resultClass) { result = false; goto done; } } // Set role: if (role.GetSize()) { req->role = Batch_Tcsdup(req->base.base.batch, role.Str()); if (!req->role) { result = false; goto done; } } // Set resultRole: if (resultRole.GetSize()) { req->resultRole = Batch_Tcsdup(req->base.base.batch, resultRole.Str()); if (!req->resultRole) { result = false; goto done; } } // Pack the instance name into the message's batch. { Result r = InstanceToBatch( instanceName.m_self, NULL, NULL, req->base.base.batch, &req->packedInstancePtr, &req->packedInstanceSize); if (r != MI_RESULT_OK) { result = false; goto done; } } // Send the messages: Strand_SchedulePost(&strand,&req->base.base); done: if (req) { AssociationsOfReq_Release(req); } return result; } bool ClientRep::ReferenceInstancesAsync( const String& nameSpace, const DInstance& instanceName, const String& resultClass, const String& role, Uint64& operationId) { AssociationsOfReq* req = 0; bool result = true; // Fail if not connected. if( !protocol || !strand.info.opened ) { result = false; goto done; } // Create the request message: { req = AssociationsOfReq_New(operationId, BinaryProtocolFlag, ReferencesOfReqTag); if (!req) { result = false; goto done; } } // Set nameSpace: req->nameSpace = Batch_Tcsdup(req->base.base.batch, nameSpace.Str()); if (!req->nameSpace) { result = false; goto done; } // Set assocClass: if (resultClass.GetSize()) { req->resultClass = Batch_Tcsdup(req->base.base.batch, resultClass.Str()); if (!req->resultClass) { result = false; goto done; } } // Set role: if (role.GetSize()) { req->role = Batch_Tcsdup(req->base.base.batch, role.Str()); if (!req->role) { result = false; goto done; } } // Pack the instance name into the message's batch. { Result r = InstanceToBatch( instanceName.m_self, NULL, NULL, req->base.base.batch, &req->packedInstancePtr, &req->packedInstanceSize); if (r != MI_RESULT_OK) { result = false; goto done; } } // Send the messages: Strand_SchedulePost(&strand,&req->base.base); done: if (req) AssociationsOfReq_Release(req); return result; } //============================================================================== MI_EXTERN_C void _Client_Post( _In_ Strand* self_, _In_ Message* msg) { ClientRep* rep = FromOffset(ClientRep,strand,self_); trace_Client_Post( msg, msg->tag, MessageName(msg->tag), msg->operationId ); ClientRep::MessageCallback( rep, msg ); Strand_Ack(self_); // return an Ack to protocol } MI_EXTERN_C void _Client_PostControl( _In_ Strand* self_, _In_ Message* msg) { ClientRep* rep = FromOffset(ClientRep,strand,self_); ProtocolEventConnect* eventMsg = (ProtocolEventConnect*)msg; Handler* handler = rep->handler; DEBUG_ASSERT( ProtocolEventConnectTag == msg->tag ); if( eventMsg->success ) { D( printf("==== EventCallback() PROTOCOLEVENT_CONNECT\n"); ) rep->connectState = ClientRep::CONNECTSTATE_CONNECTED; if (handler) handler->HandleConnect(); } else { D( printf("==== EventCallback() PROTOCOLEVENT_CONNECT_FAILED\n"); ) if (handler) handler->HandleConnectFailed(); rep->connectState = ClientRep::CONNECTSTATE_FAILED; } } MI_EXTERN_C void _Client_Ack( _In_ Strand* self ) { trace_Client_Ack(); // We are not streaming any results, so no need to manage flow control on Ack } MI_EXTERN_C void _Client_Cancel( _In_ Strand* self ) { DEBUG_ASSERT( MI_FALSE ); // not used yet } MI_EXTERN_C void _Client_Close( _In_ Strand* self_ ) { ClientRep* rep = FromOffset(ClientRep,strand,self_); Handler* handler = rep->handler; trace_Client_Close(); // most management done by strand implementation if (handler) handler->HandleDisconnect(); rep->connectState = ClientRep::CONNECTSTATE_DISCONNECTED; } MI_EXTERN_C void _Client_Finish( _In_ Strand* self_ ) { trace_Client_Finish(); // nothing to do here, (class take care of deleting itself) } /* Object that implements the C++ client endpoint. It opens an interaction to the binary protocol below to communicate on a TCP Socket. Behavior: - Post just passed the operation to tries to ClientRep::MessageCallback if that fails it sends the Ack immediately - Post control is used to notify connected state (connect succeeded/failed) - Ack does not do anything at this point (as there are no secondary messages) - Cancel is not used - Puts it on disconnected state if not there already - Shutdown: The Client objects are shutdown/deleted thru the normal Strand logic (once the interaction is closed). */ StrandFT _Client_InteractionFT = { _Client_Post, _Client_PostControl, _Client_Ack, _Client_Cancel, _Client_Close, _Client_Finish, NULL, NULL, NULL, NULL, NULL, NULL }; //============================================================================== // // class Client // //============================================================================== Client::Client(Handler* handler) { m_rep = new ClientRep; m_rep->protocol = 0; m_rep->connectState = ClientRep::CONNECTSTATE_DISCONNECTED; m_rep->handler = handler; //Log_OpenStdErr(); //Log_SetLevel(LOG_DEBUG); Strand_Init( STRAND_DEBUG(OmiClient) &m_rep->strand, &_Client_InteractionFT, STRAND_FLAG_ENTERSTRAND, NULL ); // this is the one that Opens the interaction (not the one that receives the open) } 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 = _StrToString(OMI_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: { InteractionOpenParams params; ProtocolSocketAndBase* protocol = NULL; Strand_OpenPrepare(&m_rep->strand,¶ms,NULL,NULL,MI_TRUE); r = ProtocolSocketAndBase_New_Connector( &protocol, NULL, locator_, ¶ms, 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 (PAL_Time(&now) != PAL_TRUE) return false; endTime = now + timeOutUsec; // Wait for connection establishment or timeout. for (;endTime >= now;) { Protocol_Run(&m_rep->protocol->internalProtocolBase, SELECT_BASE_TIMEOUT_MSEC * 1000); if (m_rep->connectState != ClientRep::CONNECTSTATE_PENDING) break; if (PAL_Time(&now) != PAL_TRUE) 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 || !m_rep->strand.info.opened ) { result = false; goto done; } if ( m_rep->strand.info.opened ) { Strand_ScheduleClose( &m_rep->strand ); Protocol_Run(&m_rep->protocol->internalProtocolBase, SELECT_BASE_TIMEOUT_MSEC * 1000); } // Delete the protocol object. { ProtocolSocketAndBase_ReadyToFinish(m_rep->protocol); m_rep->protocol = 0; } m_rep->connectState = ClientRep::CONNECTSTATE_DISCONNECTED; done: return result; } bool Client::Connected() const { return m_rep->protocol && m_rep->strand.info.opened ? true : false; } bool Client::Run(Uint64 timeOutUsec) { bool result = true; // Fail if not connected. if (!m_rep->protocol || !m_rep->strand.info.opened) { result = false; goto done; } // Process events. // ATTN: what can this return? Protocol_Run(&m_rep->protocol->internalProtocolBase, timeOutUsec); done: return result; } bool Client::NoOpAsync( Uint64& operationId) { operationId = _NextOperationId(); return m_rep->NoOpAsync(operationId); } bool Client::GetInstanceAsync( const String& nameSpace, const DInstance& instanceName, Uint64& operationId) { operationId = _NextOperationId(); return m_rep->GetInstanceAsync(nameSpace, instanceName, operationId); } bool Client::CreateInstanceAsync( const String& nameSpace, const DInstance& instance, Uint64& operationId) { operationId = _NextOperationId(); return m_rep->CreateInstanceAsync(nameSpace, instance, operationId); } bool Client::ModifyInstanceAsync( const String& nameSpace, const DInstance& instance, Uint64& operationId) { operationId = _NextOperationId(); return m_rep->ModifyInstanceAsync(nameSpace, instance, operationId); } bool Client::DeleteInstanceAsync( const String& nameSpace, const DInstance& instanceName, Uint64& operationId) { operationId = _NextOperationId(); return m_rep->DeleteInstanceAsync(nameSpace, instanceName, operationId); } bool Client::EnumerateInstancesAsync( const String& nameSpace, const String& className, bool deepInheritance, const String& queryLanguage, const String& queryExpression, Uint64& operationId) { operationId = _NextOperationId(); return m_rep->EnumerateInstancesAsync(nameSpace, className, deepInheritance, queryLanguage, queryExpression, operationId); } bool Client::InvokeAsync( const String& nameSpace, const DInstance& instanceName, const String& methodName, const DInstance& inParameters, DInstance& outParameters, Uint64 operationId) { operationId = _NextOperationId(); return m_rep->InvokeAsync(nameSpace, instanceName, methodName, inParameters, outParameters, operationId); } bool Client::AssociatorInstancesAsync( const String& nameSpace, const DInstance& instanceName, const String& assocClass, const String& resultClass, const String& role, const String& resultRole, Uint64& operationId) { operationId = _NextOperationId(); return m_rep->AssociatorInstancesAsync(nameSpace, instanceName, assocClass, resultClass, role, resultRole, operationId); } bool Client::ReferenceInstancesAsync( const String& nameSpace, const DInstance& instanceName, const String& assocClass, const String& role, Uint64& operationId) { operationId = _NextOperationId(); return m_rep->ReferenceInstancesAsync(nameSpace, instanceName, assocClass, role, operationId); } bool Client::GetInstance( const String& nameSpace, const DInstance& instanceName, Uint64 timeOutUsec, DInstance& instance, Result& result) { Handler* oldHandler = m_rep->handler; Uint64 operationId = _NextOperationId(); InstanceHandler handler(oldHandler, operationId, instance); m_rep->handler = &handler; bool flag = true; if (!m_rep->GetInstanceAsync(nameSpace, instanceName, operationId)) { flag = false; goto done; } Uint64 endTime, now; if (PAL_Time(&now) != PAL_TRUE) return false; endTime = now + timeOutUsec; for (;endTime >= now;) { Protocol_Run(&m_rep->protocol->internalProtocolBase, SELECT_BASE_TIMEOUT_MSEC * 1000); if (handler.m_state == InstanceHandler::FAILED || handler.m_state == InstanceHandler::DONE) { break; } if (PAL_Time(&now) != PAL_TRUE) 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 operationId = _NextOperationId(); InstanceHandler handler(oldHandler, operationId, instanceName); m_rep->handler = &handler; bool flag = true; if (!m_rep->CreateInstanceAsync(nameSpace, instance, operationId)) { flag = false; goto done; } Uint64 endTime, now; if (PAL_Time(&now) != PAL_TRUE) return false; endTime = now + timeOutUsec; for (;endTime >= now;) { Protocol_Run(&m_rep->protocol->internalProtocolBase, SELECT_BASE_TIMEOUT_MSEC * 1000); if (handler.m_state == InstanceHandler::FAILED || handler.m_state == InstanceHandler::DONE) { break; } if (PAL_Time(&now) != PAL_TRUE) 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 operationId = _NextOperationId(); ResultHandler handler(oldHandler, operationId); m_rep->handler = &handler; bool flag = true; if (!m_rep->ModifyInstanceAsync(nameSpace, instance, operationId)) { flag = false; goto done; } Uint64 endTime, now; if (PAL_Time(&now) != PAL_TRUE) return false; endTime = now + timeOutUsec; for (;endTime >= now;) { Protocol_Run(&m_rep->protocol->internalProtocolBase, SELECT_BASE_TIMEOUT_MSEC * 1000); if (handler.m_state == ResultHandler::FAILED || handler.m_state == ResultHandler::DONE) { break; } if (PAL_Time(&now) != PAL_TRUE) 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 operationId = _NextOperationId(); ResultHandler handler(oldHandler, operationId); m_rep->handler = &handler; bool flag = true; if (!m_rep->DeleteInstanceAsync(nameSpace, instanceName, operationId)) { flag = false; goto done; } Uint64 endTime, now; if (PAL_Time(&now) != PAL_TRUE) return false; endTime = now + timeOutUsec; for (;endTime >= now;) { Protocol_Run(&m_rep->protocol->internalProtocolBase, SELECT_BASE_TIMEOUT_MSEC * 1000); if (handler.m_state == ResultHandler::FAILED || handler.m_state == ResultHandler::DONE) { break; } if (PAL_Time(&now) != PAL_TRUE) 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 operationId = _NextOperationId(); NoOpHandler handler(oldHandler, operationId); m_rep->handler = &handler; bool flag = true; if (!m_rep->NoOpAsync(operationId)) { flag = false; goto done; } Uint64 endTime, now; if (PAL_Time(&now) != PAL_TRUE) return false; endTime = now + timeOutUsec; for (;endTime >= now;) { Protocol_Run(&m_rep->protocol->internalProtocolBase, SELECT_BASE_TIMEOUT_MSEC * 1000); if (handler.m_state == NoOpHandler::FAILED || handler.m_state == NoOpHandler::DONE) { break; } if (PAL_Time(&now) != PAL_TRUE) 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& instances, const String& queryLanguage, const String& queryExpression, Result& result) { Handler* oldHandler = m_rep->handler; Uint64 operationId = _NextOperationId(); InstancesHandler handler(oldHandler, operationId, instances); m_rep->handler = &handler; bool flag = true; if (!m_rep->EnumerateInstancesAsync(nameSpace, className, deepInheritance, queryLanguage, queryExpression, operationId)) { flag = false; goto done; } Uint64 endTime, now; if (PAL_Time(&now) != PAL_TRUE) return false; endTime = now + timeOutUsec; for (;endTime >= now;) { Protocol_Run(&m_rep->protocol->internalProtocolBase, SELECT_BASE_TIMEOUT_MSEC * 1000); if (handler.m_state == InstancesHandler::FAILED || handler.m_state == InstancesHandler::DONE) { break; } if (PAL_Time(&now) != PAL_TRUE) 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 operationId = _NextOperationId(); InstanceHandler handler(oldHandler, operationId, outParameters); m_rep->handler = &handler; bool flag = true; if (!m_rep->InvokeAsync(nameSpace, instanceName, methodName, inParameters, outParameters, operationId)) { flag = false; goto done; } Uint64 endTime, now; if (PAL_Time(&now) != PAL_TRUE) return false; endTime = now + timeOutUsec; for (;endTime >= now;) { Protocol_Run(&m_rep->protocol->internalProtocolBase, SELECT_BASE_TIMEOUT_MSEC * 1000); if (handler.m_state == InstanceHandler::FAILED || handler.m_state == InstanceHandler::DONE) { break; } if (PAL_Time(&now) != PAL_TRUE) 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& instances, Result& result) { Handler* oldHandler = m_rep->handler; Uint64 operationId = _NextOperationId(); InstancesHandler handler(oldHandler, operationId, instances); m_rep->handler = &handler; bool flag = true; if (!m_rep->AssociatorInstancesAsync(nameSpace, instanceName, assocClass, resultClass, role, resultRole, operationId)) { flag = false; goto done; } Uint64 endTime, now; if (PAL_Time(&now) != PAL_TRUE) return false; endTime = now + timeOutUsec; for (;endTime >= now;) { Protocol_Run(&m_rep->protocol->internalProtocolBase, SELECT_BASE_TIMEOUT_MSEC * 1000); if (handler.m_state == InstancesHandler::FAILED || handler.m_state == InstancesHandler::DONE) { break; } if (PAL_Time(&now) != PAL_TRUE) 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& instances, Result& result) { Handler* oldHandler = m_rep->handler; Uint64 operationId = _NextOperationId(); InstancesHandler handler(oldHandler, operationId, instances); m_rep->handler = &handler; bool flag = true; if (!m_rep->ReferenceInstancesAsync(nameSpace, instanceName, assocClass, role, operationId)) { flag = false; goto done; } Uint64 endTime, now; if (PAL_Time(&now) != PAL_TRUE) return false; endTime = now + timeOutUsec; for (;endTime >= now;) { Protocol_Run(&m_rep->protocol->internalProtocolBase, SELECT_BASE_TIMEOUT_MSEC * 1000); if (handler.m_state == InstancesHandler::FAILED || handler.m_state == InstancesHandler::DONE) { break; } if (PAL_Time(&now) != PAL_TRUE) break; } if (handler.m_state == InstancesHandler::DONE) result = handler.m_result; else flag = false; done: m_rep->handler = oldHandler; return flag; } MI_END_NAMESPACE