DABC (Data Acquisition Backbone Core)  2.9.9
Command.cxx
Go to the documentation of this file.
1 // $Id: Command.cxx 4748 2021-03-23 14:57:34Z linev $
2 
3 /************************************************************
4  * The Data Acquisition Backbone Core (DABC) *
5  ************************************************************
6  * Copyright (C) 2009 - *
7  * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
8  * Planckstr. 1, 64291 Darmstadt, Germany *
9  * Contact: http://dabc.gsi.de *
10  ************************************************************
11  * This software can be used under the GPL license *
12  * agreements as stated in LICENSE.txt file *
13  * which is part of the distribution. *
14  ************************************************************/
15 
16 #include "dabc/Command.h"
17 
18 #include <cstdlib>
19 
20 #include "dabc/Manager.h"
21 
22 dabc::CommandContainer::CommandContainer(const std::string &name) :
23  RecordContainer(name),
24  fCallers(),
25  fTimeout(),
26  fCanceled(false)
27 {
28  // object will be destroy as long no references are existing
29  SetFlag(flAutoDestroy, true);
30 
31  DOUT4("CMD:%p name %s created", this, GetName());
32 
33 #ifdef DABC_EXTRA_CHECKS
34  DebugObject("Command", this, 1);
35 #endif
36 
37 }
38 
39 
41 {
42 
43  if (fCallers.size()>0) {
44  EOUT("Non empty callers list in cmd %s destructor", GetName());
45  fCallers.clear();
46  }
47 
48  DOUT4("CMD:%p name %s deleted", this, GetName());
49 
50 #ifdef DABC_EXTRA_CHECKS
51  DebugObject("Command", this, -1);
52 #endif
53 
54 }
55 
56 dabc::Command::Command(const std::string &name) throw()
57 {
58  if (!name.empty())
59  SetObject(new dabc::CommandContainer(name.c_str()));
60 }
61 
62 void dabc::Command::ChangeName(const std::string &name)
63 {
64  CommandContainer* cont = static_cast<CommandContainer*> (GetObject());
65  if (cont) cont->SetNameDirect(name.c_str());
66 }
67 
68 void dabc::Command::AddCaller(Worker* worker, bool* exe_ready)
69 {
70  CommandContainer* cont = (CommandContainer*) GetObject();
71  if (cont==0) return;
72 
73  LockGuard lock(ObjectMutex());
74 
75  cont->fCallers.push_back(CommandContainer::CallerRec(worker, exe_ready));
76 }
77 
78 void dabc::Command::RemoveCaller(Worker* worker, bool* exe_ready)
79 {
80  CommandContainer* cont = (CommandContainer*) GetObject();
81  if (cont==0) return;
82 
83  LockGuard lock(ObjectMutex());
84 
85  auto iter = cont->fCallers.begin();
86 
87  while (iter != cont->fCallers.end()) {
88 
89  if ((iter->worker == worker) && ((exe_ready==0) || (iter->exe_ready==exe_ready)))
90  cont->fCallers.erase(iter++);
91  else
92  iter++;
93  }
94 }
95 
97 {
98  CommandContainer* cont = (CommandContainer*) GetObject();
99  if (cont==0) return false;
100 
101  LockGuard lock(ObjectMutex());
102 
103  if ((cont->fCallers.size()==0)) return false;
104 
105  return cont->fCallers.back().exe_ready != 0;
106 }
107 
109 {
110  CommandContainer* cont = (CommandContainer*) GetObject();
111  if (cont!=0) {
112  LockGuard lock(ObjectMutex());
113  if (tm<=0.) {
114  cont->fTimeout.Reset();
115  } else {
116  cont->fTimeout.GetNow();
117  cont->fTimeout += tm;
118  }
119  }
120 
121  return *this;
122 }
123 
125 {
126  CommandContainer* cont = (CommandContainer*) GetObject();
127  if (cont==0) return false;
128  LockGuard lock(ObjectMutex());
129  return !cont->fTimeout.null();
130 }
131 
132 double dabc::Command::TimeTillTimeout(double extra) const
133 {
134  CommandContainer* cont = (CommandContainer*) GetObject();
135  if (cont==0) return -1.;
136 
137  LockGuard lock(ObjectMutex());
138  if (cont->fTimeout.null()) return -1.;
139 
140  double now = TimeStamp::Now().AsDouble();
141  double ref = cont->fTimeout.AsDouble() + extra;
142 
143  return (now > ref) ? 0. : (ref - now);
144 }
145 
147 {
148  return GetInt(PriorityParName(), Worker::priorityDefault);
149 }
150 
151 void dabc::Command::SetPtr(const std::string &name, void* p)
152 {
153  char buf[100];
154  snprintf(buf, sizeof(buf), "%p", p);
155  SetStr(name, buf);
156 }
157 
158 void* dabc::Command::GetPtr(const std::string &name, void* deflt) const
159 {
160  std::string val = GetStr(name);
161  if (val.empty()) return deflt;
162 
163  void* p = nullptr;
164  int res = sscanf(val.c_str(),"%p", &p);
165  return res>0 ? p : deflt;
166 }
167 
168 bool dabc::Command::SetRef(const std::string &name, Reference ref)
169 {
170  std::string field = dabc::format("#%s", name.c_str());
171 
172  return SetField(field, ref);
173 }
174 
175 dabc::Reference dabc::Command::GetRef(const std::string &name)
176 {
177  std::string field = dabc::format("#%s", name.c_str());
178 
179  dabc::Reference ref = GetField(field).AsReference();
180 
181  RemoveField(field);
182 
183  return ref;
184 }
185 
186 
187 void dabc::Command::AddValuesFrom(const dabc::Command& cmd, bool canoverwrite)
188 {
189  if (!null() && !cmd.null())
190  GetObject()->Fields().CopyFrom(cmd.GetObject()->Fields(), canoverwrite);
191 }
192 
193 void dabc::Command::Print(int lvl, const char* from) const
194 {
195  Record::Print(lvl, from);
196 }
197 
199 {
201 }
202 
204 {
205  CommandContainer* cont = (CommandContainer*) GetObject();
206  if (cont!=0) {
207  LockGuard lock(ObjectMutex());
208  cont->fCanceled = true;
209  }
210 
212 }
213 
215 {
216  CommandContainer* cont = (CommandContainer*) GetObject();
217  if (cont!=0) {
218  LockGuard lock(ObjectMutex());
219  return cont->fCanceled;
220  }
221 
222  return false;
223 }
224 
225 void dabc::Command::Reply(int res)
226 {
227  if (null()) return;
228 
229  if (res>=0) SetResult(res);
230 
231  while (!null()) {
232 
233  CommandContainer* cont = (CommandContainer*) GetObject();
234 
236 
237  {
238  LockGuard lock(ObjectMutex());
239 
240  if (cont->fCallers.size()==0) break;
241 
242  DOUT5("Cmd %s Finalize callers %u", cont->GetName(), cont->fCallers.size());
243 
244  rec = cont->fCallers.back();
245  cont->fCallers.pop_back();
246  }
247 
248  if (rec.worker==0) continue;
249 
250  if (rec.worker->GetCommandReply(*this, rec.exe_ready)) break;
251 
252  if (!HasField("#no_warnings"))
253  EOUT("AAAAAAAAAAAAAAAAAAAAAAAA Problem with cmd %s worker %p", GetName(), rec.worker);
254  }
255 
256  // in any case release reference at the end
257  Release();
258 }
259 
260 
261 size_t find_symbol(const std::string &str, size_t pos, char symb)
262 {
263  bool quote = false;
264 
265  while (pos < str.length()) {
266 
267  if (str[pos]=='\"') quote = !quote;
268 
269  if (!quote && (str[pos] == symb)) return pos;
270 
271  pos++;
272  }
273 
274  return str.length();
275 }
276 
277 bool remove_quotes(std::string& str)
278 {
279  size_t len = str.length();
280 
281  if (len < 2) return true;
282 
283  if (str[0] != str[len-1]) return true;
284 
285  if (str[0]=='\"') {
286  str.erase(len-1, 1);
287  str.erase(0,1);
288  }
289  return true;
290 }
291 
292 bool dabc::Command::ReadFromCmdString(const std::string &str)
293 {
294  Release();
295 
296  size_t pos = 0;
297  int narg = 0;
298 
299  while (pos<str.length()) {
300  if (str[pos] == ' ') { pos++; continue; }
301 
302  size_t next = find_symbol(str, pos, ' ');
303  std::string part = str.substr(pos, next-pos);
304  pos = next;
305 
306  if (null()) {
307  SetObject(new dabc::CommandContainer(part));
308  continue;
309  }
310 
311  size_t separ = find_symbol(part, 0, '=');
312 
313  if (separ == part.length()) {
314  SetStr(dabc::format("Arg%d", narg++), part);
315  } else
316  if (separ==0) {
317  EOUT("Wrong position of '=' symbol");
318  Release();
319  return false;
320  } else {
321  std::string argname = part.substr(0, separ-1);
322  std::string argvalue = part.substr(separ+1);
323  remove_quotes(argvalue);
324  SetStr(argname, argvalue);
325  }
326  }
327 
328  if (narg>0) SetInt("NumArg", narg);
329 
330  return true;
331 }
332 
333 
335 {
336  return SetField("#RawData", rawdata);
337 }
338 
339 
340 bool dabc::Command::SetStrRawData(const std::string &str)
341 {
342  dabc::Buffer raw = dabc::Buffer::CreateBuffer(str.c_str(), str.length(), false, true);
343  return SetRawData(raw);
344 }
345 
346 
348 {
349  dabc::Buffer buf = GetField("#RawData").AsBuffer();
350  RemoveField("#RawData");
351  return buf;
352 }
size_t find_symbol(const std::string &str, size_t pos, char symb)
Definition: Command.cxx:261
bool remove_quotes(std::string &str)
Definition: Command.cxx:277
Reference on memory from memory pool.
Definition: Buffer.h:135
static Buffer CreateBuffer(BufferSize_t sz)
This static method create independent buffer for any other memory pools Therefore it can be used in s...
Definition: Buffer.cxx:419
Container object for command which should not been seen to normal user.
Definition: Command.h:56
bool fCanceled
indicate if command was canceled ant not need to be executed further
Definition: Command.h:79
std::list< CallerRec > fCallers
list of callers
Definition: Command.h:77
virtual ~CommandContainer()
Definition: Command.cxx:40
TimeStamp fTimeout
absolute time when timeout will be expired
Definition: Command.h:78
CommandContainer(const std::string &name="Command")
Definition: Command.cxx:22
Represents command with its arguments.
Definition: Command.h:99
double TimeTillTimeout(double extra=0.) const
Returns time which remains until command should be timed out.
Definition: Command.cxx:132
bool ReadFromCmdString(const std::string &str)
Read command from string, which is typed in std output.
Definition: Command.cxx:292
bool IsLastCallerSync()
Definition: Command.cxx:96
void SetPtr(const std::string &name, void *p)
Set pointer argument for the command.
Definition: Command.cxx:151
void AddCaller(Worker *worker, bool *exe_ready=nullptr)
Definition: Command.cxx:68
bool SetStrRawData(const std::string &str)
Set raw data with string content.
Definition: Command.cxx:340
void Cancel()
Call this method to cancel command execution.
Definition: Command.cxx:203
bool SetRawData(Buffer rawdata)
Set raw data to the command, which can be transported also between nodes.
Definition: Command.cxx:334
Command & SetTimeout(double tm)
Set maximum time which can be used for command execution.
Definition: Command.cxx:108
bool IsTimeoutSet() const
Return true if timeout was specified.
Definition: Command.cxx:124
void Release()
Method used to clean command - all internal data will be cleaned, command container will be released.
Definition: Command.cxx:198
void AddValuesFrom(const Command &cmd, bool canoverwrite=true)
Definition: Command.cxx:187
Reference GetRef(const std::string &name)
Returns reference from the command, can be called only once.
Definition: Command.cxx:175
void Print(int lvl=0, const char *from=nullptr) const
Show on debug output content of command.
Definition: Command.cxx:193
bool IsCanceled()
Return true if command was canceled.
Definition: Command.cxx:214
Buffer GetRawData()
Returns reference on raw data Can be called only once - raw data reference will be cleaned.
Definition: Command.cxx:347
void Reply(int res=cmd_noresult)
Replied on the command.
Definition: Command.cxx:225
void ChangeName(const std::string &name)
Change command name, should not be used for remote commands.
Definition: Command.cxx:62
bool SetRef(const std::string &name, Reference ref)
Set reference to the command.
Definition: Command.cxx:168
void RemoveCaller(Worker *worker, bool *exe_ready=nullptr)
Definition: Command.cxx:78
int GetPriority() const
Returns command priority.
Definition: Command.cxx:146
void * GetPtr(const std::string &name, void *deflt=0) const
Get pointer argument from the command.
Definition: Command.cxx:158
Lock guard for posix mutex.
Definition: threads.h:127
void SetFlag(unsigned fl, bool on=true)
Change value of selected flag, not thread safe
Definition: Object.h:187
void SetNameDirect(const char *name)
Changes object name disregard of existing references.
Definition: Object.cxx:884
const char * GetName() const
Returns name of the object, thread safe
Definition: Object.h:295
@ flAutoDestroy
object will be automatically destroyed when no references exists, normally set in constructor,...
Definition: Object.h:167
Container for records fields.
Definition: Record.h:440
Reference on the arbitrary object
Definition: Reference.h:73
void Release()
Releases reference on the object.
Definition: Reference.cxx:138
Object * GetObject() const
Return pointer on the object.
Definition: Reference.h:129
friend class Command
Definition: Reference.h:76
void Print(int lvl=0, const char *from=0) const
Show on debug output content of reference.
Definition: Reference.cxx:229
bool null() const
Returns true if reference contains nullptr.
Definition: Reference.h:151
Active object, which is working inside dabc::Thread.
Definition: Worker.h:116
@ priorityDefault
Definition: Worker.h:209
bool GetCommandReply(dabc::Command &cmd, bool *exe_ready)
Definition: Worker.cxx:996
#define DOUT5(args ...)
Definition: logging.h:188
#define EOUT(args ...)
Definition: logging.h:150
#define DOUT4(args ...)
Definition: logging.h:182
std::string format(const char *fmt,...)
Definition: string.cxx:49
bool * exe_ready
pointer on worker, do not use reference while worker will care about correct cleanup
Definition: Command.h:64
bool null() const
Returns true if time stamp is not initialized or its value less than 0.
Definition: timing.h:131
void Reset()
Set time stamp value to null.
Definition: timing.h:134
static TimeStamp Now()
Method returns TimeStamp instance with current time stamp value, measured either by fast TSC (if it i...
Definition: timing.h:176
void GetNow()
Method to acquire current time stamp.
Definition: timing.h:137
double AsDouble() const
Return time stamp in form of double (in seconds)
Definition: timing.h:120