blob: ea7116dd688b566b5ac99c756719e3d3b24a7c5c [file] [log] [blame]
Deepak Panickal6f9c4682014-05-16 10:51:01 +00001//===-- MICmdInvoker.cpp ----------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Deepak Panickal6f9c4682014-05-16 10:51:01 +000010// In-house headers:
11#include "MICmdInvoker.h"
12#include "MICmdBase.h"
13#include "MICmdMgr.h"
14#include "MICmnLog.h"
15#include "MICmnStreamStdout.h"
Deepak Panickald2499282014-08-08 16:47:42 +000016#include "MIDriver.h"
Deepak Panickal6f9c4682014-05-16 10:51:01 +000017
Kate Stoneb9c1b512016-09-06 20:57:50 +000018//++
19//------------------------------------------------------------------------------------
Zachary Turner1d6af022014-11-17 18:06:21 +000020// Details: CMICmdInvoker constructor.
21// Type: Method.
22// Args: None.
23// Return: None.
24// Throws: None.
Deepak Panickal6f9c4682014-05-16 10:51:01 +000025//--
Kate Stoneb9c1b512016-09-06 20:57:50 +000026CMICmdInvoker::CMICmdInvoker() : m_rStreamOut(CMICmnStreamStdout::Instance()) {}
Deepak Panickal6f9c4682014-05-16 10:51:01 +000027
Kate Stoneb9c1b512016-09-06 20:57:50 +000028//++
29//------------------------------------------------------------------------------------
Zachary Turner1d6af022014-11-17 18:06:21 +000030// Details: CMICmdInvoker destructor.
31// Type: Overridable.
32// Args: None.
33// Return: None.
34// Throws: None.
Deepak Panickal6f9c4682014-05-16 10:51:01 +000035//--
Kate Stoneb9c1b512016-09-06 20:57:50 +000036CMICmdInvoker::~CMICmdInvoker() { Shutdown(); }
Deepak Panickal6f9c4682014-05-16 10:51:01 +000037
Kate Stoneb9c1b512016-09-06 20:57:50 +000038//++
39//------------------------------------------------------------------------------------
Zachary Turner1d6af022014-11-17 18:06:21 +000040// Details: Initialize resources for *this Command Invoker.
41// Type: Method.
42// Args: None.
43// Return: MIstatus::success - Functional succeeded.
44// MIstatus::failure - Functional failed.
45// Throws: None.
Deepak Panickal6f9c4682014-05-16 10:51:01 +000046//--
Kate Stoneb9c1b512016-09-06 20:57:50 +000047bool CMICmdInvoker::Initialize() {
48 m_clientUsageRefCnt++;
Deepak Panickal6f9c4682014-05-16 10:51:01 +000049
Kate Stoneb9c1b512016-09-06 20:57:50 +000050 if (m_bInitialized)
Zachary Turner1d6af022014-11-17 18:06:21 +000051 return MIstatus::success;
Kate Stoneb9c1b512016-09-06 20:57:50 +000052
53 m_bInitialized = true;
54
55 return MIstatus::success;
Deepak Panickal6f9c4682014-05-16 10:51:01 +000056}
57
Kate Stoneb9c1b512016-09-06 20:57:50 +000058//++
59//------------------------------------------------------------------------------------
Zachary Turner1d6af022014-11-17 18:06:21 +000060// Details: Release resources for *this Stdin stream.
61// Type: Method.
62// Args: None.
63// Return: MIstatus::success - Functional succeeded.
64// MIstatus::failure - Functional failed.
65// Throws: None.
Deepak Panickal6f9c4682014-05-16 10:51:01 +000066//--
Kate Stoneb9c1b512016-09-06 20:57:50 +000067bool CMICmdInvoker::Shutdown() {
68 if (--m_clientUsageRefCnt > 0)
Zachary Turner1d6af022014-11-17 18:06:21 +000069 return MIstatus::success;
Kate Stoneb9c1b512016-09-06 20:57:50 +000070
71 if (!m_bInitialized)
72 return MIstatus::success;
73
74 CmdDeleteAll();
75
76 m_bInitialized = false;
77
78 return MIstatus::success;
Deepak Panickal6f9c4682014-05-16 10:51:01 +000079}
80
Kate Stoneb9c1b512016-09-06 20:57:50 +000081//++
82//------------------------------------------------------------------------------------
83// Details: Empty the map of invoked commands doing work. Command objects are
84// deleted too.
Zachary Turner1d6af022014-11-17 18:06:21 +000085// Type: Method.
86// Args: None.
87// Return: None.
88// Throws: None.
Deepak Panickal6f9c4682014-05-16 10:51:01 +000089//--
Kate Stoneb9c1b512016-09-06 20:57:50 +000090void CMICmdInvoker::CmdDeleteAll() {
91 CMICmdMgr &rMgr = CMICmdMgr::Instance();
92 MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.begin();
93 while (it != m_mapCmdIdToCmd.end()) {
94 const MIuint cmdId((*it).first);
95 MIunused(cmdId);
96 CMICmdBase *pCmd = (*it).second;
97 const CMIUtilString &rCmdName(pCmd->GetCmdData().strMiCmd);
98 MIunused(rCmdName);
99 rMgr.CmdDelete(pCmd->GetCmdData());
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000100
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101 // Next
102 ++it;
103 }
104 m_mapCmdIdToCmd.clear();
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000105}
106
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107//++
108//------------------------------------------------------------------------------------
109// Details: Remove from the map of invoked commands doing work a command that
110// has finished
Zachary Turner1d6af022014-11-17 18:06:21 +0000111// its work. The command object is deleted too.
112// Type: Method.
113// Args: vId - (R) Command object's unique ID.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000114// vbYesDeleteCmd - (R) True = Delete command object, false = delete
115// via the Command Manager.
Zachary Turner1d6af022014-11-17 18:06:21 +0000116// Return: None.
117// Throws: None.
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000118//--
Kate Stoneb9c1b512016-09-06 20:57:50 +0000119bool CMICmdInvoker::CmdDelete(const MIuint vId,
120 const bool vbYesDeleteCmd /*= false*/) {
121 CMICmdMgr &rMgr = CMICmdMgr::Instance();
122 MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find(vId);
123 if (it != m_mapCmdIdToCmd.end()) {
124 CMICmdBase *pCmd = (*it).second;
125 if (vbYesDeleteCmd) {
126 // Via registered interest command manager callback *this object to delete
127 // the command
128 m_mapCmdIdToCmd.erase(it);
129 delete pCmd;
130 } else
131 // Notify other interested object of this command's pending deletion
132 rMgr.CmdDelete(pCmd->GetCmdData());
133 }
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000134
Kate Stoneb9c1b512016-09-06 20:57:50 +0000135 if (m_mapCmdIdToCmd.empty())
136 rMgr.CmdUnregisterForDeleteNotification(*this);
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000137
Kate Stoneb9c1b512016-09-06 20:57:50 +0000138 return MIstatus::success;
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000139}
140
Kate Stoneb9c1b512016-09-06 20:57:50 +0000141//++
142//------------------------------------------------------------------------------------
143// Details: Add to the map of invoked commands doing work a command that is
144// about to
Zachary Turner1d6af022014-11-17 18:06:21 +0000145// start to do work.
146// Type: Method.
147// Args: vCmd - (R) Command object.
148// Return: None.
149// Throws: None.
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000150//--
Kate Stoneb9c1b512016-09-06 20:57:50 +0000151bool CMICmdInvoker::CmdAdd(const CMICmdBase &vCmd) {
152 if (m_mapCmdIdToCmd.empty()) {
153 CMICmdMgr &rMgr = CMICmdMgr::Instance();
154 rMgr.CmdRegisterForDeleteNotification(*this);
155 }
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000156
Kate Stoneb9c1b512016-09-06 20:57:50 +0000157 const MIuint &cmdId(vCmd.GetCmdData().id);
158 MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find(cmdId);
159 if (it != m_mapCmdIdToCmd.end())
Zachary Turner1d6af022014-11-17 18:06:21 +0000160 return MIstatus::success;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000161
162 MapPairCmdIdToCmd_t pr(cmdId, const_cast<CMICmdBase *>(&vCmd));
163 m_mapCmdIdToCmd.insert(pr);
164
165 return MIstatus::success;
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000166}
167
Kate Stoneb9c1b512016-09-06 20:57:50 +0000168//++
169//------------------------------------------------------------------------------------
170// Details: Having previously had the potential command validated and found
171// valid now
Zachary Turner1d6af022014-11-17 18:06:21 +0000172// get the command executed.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173// If the Functionality returns MIstatus::failure call
174// GetErrorDescription().
Zachary Turner1d6af022014-11-17 18:06:21 +0000175// This function is used by the application's main thread.
176// Type: Method.
177// Args: vCmd - (RW) Command object.
178// Return: MIstatus::success - Functionality succeeded.
179// MIstatus::failure - Functionality failed.
180// Throws: None.
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000181//--
Kate Stoneb9c1b512016-09-06 20:57:50 +0000182bool CMICmdInvoker::CmdExecute(CMICmdBase &vCmd) {
183 bool bOk = CmdAdd(vCmd);
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000184
Kate Stoneb9c1b512016-09-06 20:57:50 +0000185 if (bOk) {
186 vCmd.AddCommonArgs();
187 if (!vCmd.ParseArgs()) {
188 // Report command execution failed
189 const SMICmdData cmdData(vCmd.GetCmdData());
190 CmdStdout(cmdData);
191 CmdCauseAppExit(vCmd);
192 CmdDelete(cmdData.id);
Zachary Turner1d6af022014-11-17 18:06:21 +0000193
Kate Stoneb9c1b512016-09-06 20:57:50 +0000194 // Proceed to wait or execute next command
195 return MIstatus::success;
Zachary Turner1d6af022014-11-17 18:06:21 +0000196 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000197 }
Zachary Turner1d6af022014-11-17 18:06:21 +0000198
Kate Stoneb9c1b512016-09-06 20:57:50 +0000199 if (bOk && !vCmd.Execute()) {
200 // Report command execution failed
201 const SMICmdData cmdData(vCmd.GetCmdData());
202 CmdStdout(cmdData);
203 CmdCauseAppExit(vCmd);
204 CmdDelete(cmdData.id);
Zachary Turner1d6af022014-11-17 18:06:21 +0000205
Kate Stoneb9c1b512016-09-06 20:57:50 +0000206 // Proceed to wait or execute next command
207 return MIstatus::success;
208 }
Zachary Turner1d6af022014-11-17 18:06:21 +0000209
Kate Stoneb9c1b512016-09-06 20:57:50 +0000210 bOk = CmdExecuteFinished(vCmd);
Zachary Turner1d6af022014-11-17 18:06:21 +0000211
Kate Stoneb9c1b512016-09-06 20:57:50 +0000212 return bOk;
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000213}
214
Kate Stoneb9c1b512016-09-06 20:57:50 +0000215//++
216//------------------------------------------------------------------------------------
217// Details: Called when a command has finished its Execution() work either
218// synchronously
219// because the command executed was the type a non event type or
220// asynchronously
221// via the command's callback (because of an SB Listener event). Needs
222// to be called
223// so that *this invoker call do some house keeping and then proceed to
224// call
Zachary Turner1d6af022014-11-17 18:06:21 +0000225// the command's Acknowledge() function.
226// Type: Method.
227// Args: vCmd - (R) Command object.
228// Return: MIstatus::success - Functionality succeeded.
229// MIstatus::failure - Functionality failed.
230// Throws: None.
Deepak Panickald2499282014-08-08 16:47:42 +0000231//--
Kate Stoneb9c1b512016-09-06 20:57:50 +0000232bool CMICmdInvoker::CmdExecuteFinished(CMICmdBase &vCmd) {
233 // Command finished now get the command to gather it's information and form
234 // the MI
235 // Result record
236 if (!vCmd.Acknowledge()) {
237 // Report command acknowledge functionality failed
238 const SMICmdData cmdData(vCmd.GetCmdData());
239 CmdStdout(cmdData);
240 CmdCauseAppExit(vCmd);
241 CmdDelete(cmdData.id);
Zachary Turner1d6af022014-11-17 18:06:21 +0000242
Kate Stoneb9c1b512016-09-06 20:57:50 +0000243 // Proceed to wait or execute next command
244 return MIstatus::success;
245 }
Zachary Turner1d6af022014-11-17 18:06:21 +0000246
Kate Stoneb9c1b512016-09-06 20:57:50 +0000247 // Retrieve the command's latest data/information. Needed for commands of the
248 // event type so have
249 // a record of commands pending finishing execution.
250 const CMIUtilString &rMIResultRecord(vCmd.GetMIResultRecord());
251 SMICmdData cmdData(
252 vCmd.GetCmdData()); // Make a copy as the command will be deleted soon
253 cmdData.strMiCmdResultRecord = rMIResultRecord; // Precautionary copy as the
254 // command might forget to do
255 // this
256 if (vCmd.HasMIResultRecordExtra()) {
257 cmdData.bHasResultRecordExtra = true;
258 const CMIUtilString &rMIExtra(vCmd.GetMIResultRecordExtra());
259 cmdData.strMiCmdResultRecordExtra =
260 rMIExtra; // Precautionary copy as the command might forget to do this
261 }
Zachary Turner1d6af022014-11-17 18:06:21 +0000262
Kate Stoneb9c1b512016-09-06 20:57:50 +0000263 // Send command's MI response to the client
264 bool bOk = CmdStdout(cmdData);
Zachary Turner1d6af022014-11-17 18:06:21 +0000265
Kate Stoneb9c1b512016-09-06 20:57:50 +0000266 // Delete the command object as do not require anymore
267 bOk = bOk && CmdDelete(vCmd.GetCmdData().id);
Zachary Turner1d6af022014-11-17 18:06:21 +0000268
Kate Stoneb9c1b512016-09-06 20:57:50 +0000269 return bOk;
Deepak Panickald2499282014-08-08 16:47:42 +0000270}
271
Kate Stoneb9c1b512016-09-06 20:57:50 +0000272//++
273//------------------------------------------------------------------------------------
274// Details: If the MI Driver is not operating via a client i.e. Eclipse check
275// the command
276// on failure suggests the application exits. A command can be such
277// that a
Zachary Turner1d6af022014-11-17 18:06:21 +0000278// failure cannot the allow the application to continue operating.
279// Args: vCmd - (R) Command object.
280// Return: None.
281// Return: None.
282// Throws: None.
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000283//--
Kate Stoneb9c1b512016-09-06 20:57:50 +0000284void CMICmdInvoker::CmdCauseAppExit(const CMICmdBase &vCmd) const {
285 if (vCmd.GetExitAppOnCommandFailure()) {
286 CMIDriver &rDriver(CMIDriver::Instance());
287 if (rDriver.IsDriverDebuggingArgExecutable()) {
288 rDriver.SetExitApplicationFlag(true);
Zachary Turner1d6af022014-11-17 18:06:21 +0000289 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000290 }
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000291}
292
Kate Stoneb9c1b512016-09-06 20:57:50 +0000293//++
294//------------------------------------------------------------------------------------
Zachary Turner1d6af022014-11-17 18:06:21 +0000295// Details: Write to stdout and the Log file the command's MI formatted result.
296// Type: vCmdData - (R) A command's information.
297// Return: MIstatus::success - Functionality succeeded.
298// MIstatus::failure - Functionality failed.
299// Return: None.
300// Throws: None.
Deepak Panickal6f9c4682014-05-16 10:51:01 +0000301//--
Kate Stoneb9c1b512016-09-06 20:57:50 +0000302bool CMICmdInvoker::CmdStdout(const SMICmdData &vCmdData) const {
303 bool bOk = m_pLog->WriteLog(vCmdData.strMiCmdAll);
304 const bool bLock = bOk && m_rStreamOut.Lock();
305 bOk = bOk && bLock &&
306 m_rStreamOut.WriteMIResponse(vCmdData.strMiCmdResultRecord);
307 if (bOk && vCmdData.bHasResultRecordExtra) {
308 bOk = m_rStreamOut.WriteMIResponse(vCmdData.strMiCmdResultRecordExtra);
309 }
310 bOk = bLock && m_rStreamOut.Unlock();
Zachary Turner1d6af022014-11-17 18:06:21 +0000311
Kate Stoneb9c1b512016-09-06 20:57:50 +0000312 return bOk;
Zachary Turner1d6af022014-11-17 18:06:21 +0000313}
314
Kate Stoneb9c1b512016-09-06 20:57:50 +0000315//++
316//------------------------------------------------------------------------------------
317// Details: Required by the CMICmdMgr::ICmdDeleteCallback. *this object is
318// registered
319// with the Command Manager to receive callbacks when a command is
320// being deleted.
321// An object, *this invoker, does not delete a command object itself
322// but calls
323// the Command Manager to delete a command object. This function is the
324// Invoker's
Zachary Turner1d6af022014-11-17 18:06:21 +0000325// called.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000326// The Invoker owns the command objects and so can delete them but must
327// do it
Zachary Turner1d6af022014-11-17 18:06:21 +0000328// via the manager so other objects can be notified of the deletion.
329// Type: Method.
330// Args: vCmd - (RW) Command.
331// Return: None.
332// Throws: None.
333//--
Kate Stoneb9c1b512016-09-06 20:57:50 +0000334void CMICmdInvoker::Delete(SMICmdData &vCmd) { CmdDelete(vCmd.id, true); }