//++ ------------------------------------------------------------------------------------ // Details: Having previously had the potential command validated and found valid now // get the command executed. // If the Functionalityity returns MIstatus::failure call GetErrorDescription(). // This function is used by the application's main thread. // Type: Method. // Args: vCmd - (RW) Command object. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmdInvoker::CmdExecute( CMICmdBase & vCmd ) { bool bOk = CmdAdd( vCmd ); if( bOk && !vCmd.ParseArgs() ) { // Report command execution failed const SMICmdData cmdData( vCmd.GetCmdData() ); CmdStdout( cmdData ); CmdDelete( cmdData.id ); // Proceed to wait or execute next command return MIstatus::success; } if( bOk && !vCmd.Execute() ) { // Report command execution failed const SMICmdData cmdData( vCmd.GetCmdData() ); CmdStdout( cmdData ); CmdDelete( cmdData.id ); // Proceed to wait or execute next command return MIstatus::success; } bOk = CmdExecuteFinished( vCmd ); return bOk; }
//++ ------------------------------------------------------------------------------------ // Details: Create a command given the specified MI command name. The command data object // contains the options for the command. // Type: Method. // Args: vMiCmd - (R) Command's name, the MI command. // vCmdData - (RW) Command's metadata status/information/result object. // vpNewCmd - (W) New command instance. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmdFactory::CmdCreate( const CMIUtilString & vMiCmd, const SMICmdData & vCmdData, CMICmdBase *& vpNewCmd ) { bool bOk = MIstatus::success; vpNewCmd = nullptr; if( !IsValid( vMiCmd ) ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_INVALID_CMD_NAME ), vMiCmd.c_str() ) ); return MIstatus::failure; } if( !HaveAlready( vMiCmd ) ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED ), vMiCmd.c_str() ) ); return MIstatus::failure; } const MapMiCmdToCmdCreatorFn_t::const_iterator it = m_mapMiCmdToCmdCreatorFn.find( vMiCmd ); const CMIUtilString & rMiCmd( (*it).first ); MIunused( rMiCmd ); CmdCreatorFnPtr pFn = (*it).second; CMICmdBase * pCmd = (*pFn)(); SMICmdData cmdData( vCmdData ); cmdData.id = pCmd->GetGUID(); bOk = pCmd->SetCmdData( cmdData ); if( bOk ) vpNewCmd = pCmd; return bOk; }
//++ ------------------------------------------------------------------------------------ // Details: Empty the map of invoked commands doing work. Command objects are deleted too. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- void CMICmdInvoker::CmdDeleteAll( void ) { CMICmdMgr & rMgr = CMICmdMgr::Instance(); MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.begin(); while( it != m_mapCmdIdToCmd.end() ) { const MIuint cmdId( (*it).first ); MIunused( cmdId ); CMICmdBase * pCmd = (*it).second; const CMIUtilString & rCmdName( pCmd->GetCmdData().strMiCmd ); MIunused( rCmdName ); rMgr.CmdDelete( pCmd->GetCmdData() ); // Next ++it; } m_mapCmdIdToCmd.clear(); }
//++ //------------------------------------------------------------------------------------ // Details: If the MI Driver is not operating via a client i.e. Eclipse check // the command // on failure suggests the application exits. A command can be such // that a // failure cannot the allow the application to continue operating. // Args: vCmd - (R) Command object. // Return: None. // Return: None. // Throws: None. //-- void CMICmdInvoker::CmdCauseAppExit(const CMICmdBase &vCmd) const { if (vCmd.GetExitAppOnCommandFailure()) { CMIDriver &rDriver(CMIDriver::Instance()); if (rDriver.IsDriverDebuggingArgExecutable()) { rDriver.SetExitApplicationFlag(true); } } }
//++ ------------------------------------------------------------------------------------ // Details: Called when a command has finished its Execution() work either synchronously // because the command executed was the type a non event type or asynchronoulsy // via the command's callback (because of an SB Listener event). Needs to be called // so that *this invoker call do some house keeping and then proceed to call // the command's Acknowledge() function. // Type: Method. // Args: vCmd - (R) Command object. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmdInvoker::CmdExecuteFinished( CMICmdBase & vCmd ) { // Command finished now get the command to gather it's information and form the MI // Result record if( !vCmd.Acknowledge() ) { // Report command acknowledge functionality failed const SMICmdData cmdData( vCmd.GetCmdData() ); CmdStdout( cmdData ); CmdDelete( cmdData.id ); // Proceed to wait or execute next command return MIstatus::success; } // Retrieve the command's latest data/information. Needed for commands of the event type so have // a record of commands pending finishing execution. const CMIUtilString & rMIResultRecord( vCmd.GetMIResultRecord() ); SMICmdData cmdData( vCmd.GetCmdData() ); // Make a copy as the command will be deleted soon cmdData.strMiCmdResultRecord = rMIResultRecord; // Precautionary copy as the command might forget to do this if( vCmd.HasMIResultRecordExtra() ) { cmdData.bHasResultRecordExtra = true; const CMIUtilString & rMIExtra( vCmd.GetMIResultRecordExtra() ); cmdData.strMiCmdResultRecordExtra = rMIExtra; // Precautionary copy as the command might forget to do this } // Send command's MI response to the client bool bOk = CmdStdout( cmdData ); // Delete the command object as do not require anymore bOk = bOk && CmdDelete( vCmd.GetCmdData().id ); return bOk; }
//++ //------------------------------------------------------------------------------------ // Details: Remove from the map of invoked commands doing work a command that // has finished // its work. The command object is deleted too. // Type: Method. // Args: vId - (R) Command object's unique ID. // vbYesDeleteCmd - (R) True = Delete command object, false = delete // via the Command Manager. // Return: None. // Throws: None. //-- bool CMICmdInvoker::CmdDelete(const MIuint vId, const bool vbYesDeleteCmd /*= false*/) { CMICmdMgr &rMgr = CMICmdMgr::Instance(); MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find(vId); if (it != m_mapCmdIdToCmd.end()) { CMICmdBase *pCmd = (*it).second; if (vbYesDeleteCmd) { // Via registered interest command manager callback *this object to delete // the command m_mapCmdIdToCmd.erase(it); delete pCmd; } else // Notify other interested object of this command's pending deletion rMgr.CmdDelete(pCmd->GetCmdData()); } if (m_mapCmdIdToCmd.empty()) rMgr.CmdUnregisterForDeleteNotification(*this); return MIstatus::success; }
//++ //------------------------------------------------------------------------------------ // Details: Add to the map of invoked commands doing work a command that is // about to // start to do work. // Type: Method. // Args: vCmd - (R) Command object. // Return: None. // Throws: None. //-- bool CMICmdInvoker::CmdAdd(const CMICmdBase &vCmd) { if (m_mapCmdIdToCmd.empty()) { CMICmdMgr &rMgr = CMICmdMgr::Instance(); rMgr.CmdRegisterForDeleteNotification(*this); } const MIuint &cmdId(vCmd.GetCmdData().id); MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find(cmdId); if (it != m_mapCmdIdToCmd.end()) return MIstatus::success; MapPairCmdIdToCmd_t pr(cmdId, const_cast<CMICmdBase *>(&vCmd)); m_mapCmdIdToCmd.insert(pr); return MIstatus::success; }