DABC (Data Acquisition Backbone Core)  2.9.9
ConfigBase.cxx
Go to the documentation of this file.
1 // $Id: ConfigBase.cxx 4722 2021-03-13 13:56:03Z 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/ConfigBase.h"
17 
18 #include <fnmatch.h>
19 #include <cstdlib>
20 #include <cstring>
21 #include <string>
22 
23 #include "dabc/logging.h"
24 
25 namespace dabc {
26 
27  const char* xmlRootNode = "dabc";
28  const char* xmlVersionAttr = "version";
29  const char* xmlContext = "Context";
30  const char* xmlApplication = "Application";
31  const char* xmlAppDfltName = "App";
32  const char* xmlVariablesNode = "Variables";
33  const char* xmlNameAttr = "name";
34  const char* xmlHostAttr = "host";
35  const char* xmlPortAttr = "port";
36  const char* xmlClassAttr = "class";
37  const char* xmlDeviceAttr = "device";
38  const char* xmlThreadAttr = "thread";
39  const char* xmlUseacknAttr = "useackn";
40  const char* xmlOptionalAttr = "optional";
41  const char* xmlPoolAttr = "pool";
42  const char* xmlTimeoutAttr = "timeout";
43  const char* xmlAutoAttr = "auto";
44  const char* xmlReconnectAttr = "reconnect";
45  const char* xmlNumReconnAttr = "numreconn";
46  const char* xmlValueAttr = "value";
47  const char* xmlRunNode = "Run";
48  const char* xmlUserNode = "User";
49  const char* xmlSshUser = "ssh_user";
50  const char* xmlSshPort = "ssh_port";
51  const char* xmlSshInit = "ssh_init";
52  const char* xmlSshTest = "ssh_test";
53  const char* xmlSshTimeout = "ssh_timeout";
54  const char* xmlDABCSYS = "DABCSYS";
55  const char* xmlDABCUSERDIR = "DABCUSERDIR";
56  const char* xmlDABCWORKDIR = "DABCWORKDIR";
57  const char* xmlDABCNODEID = "DABCNODEID";
58  const char* xmlDABCNUMNODES = "DABCNUMNODES";
59  const char* xmlActive = "active";
60  const char* xmlCopyCfg = "copycfg";
61  const char* xmlStdOut = "stdout";
62  const char* xmlErrOut = "errout";
63  const char* xmlNullOut = "nullout";
64  const char* xmlDebugger = "debugger";
65  const char* xmlWorkDir = "workdir";
66  const char* xmlDebuglevel = "debuglevel";
67  const char* xmlNoDebugPrefix = "nodebugprefix";
68  const char* xmlLogfile = "logfile";
69  const char* xmlLoglimit = "loglimit";
70  const char* xmlLoglevel = "loglevel";
71  const char* xmlSysloglevel = "sysloglevel";
72  const char* xmlSyslog = "syslog";
73  const char* xmlRunTime = "runtime";
74  const char* xmlHaltTime = "halttime";
75  const char* xmlThrdStopTime = "thrdstoptime";
76  const char* xmlNormalMainThrd = "normalmainthrd";
77  const char* xmlAffinity = "affinity";
78  const char* xmlThreadsLayout = "threads_layout";
79  const char* xmlTaskset = "taskset";
80  const char* xmlLDPATH = "LD_LIBRARY_PATH";
81  const char* xmlUserLib = "lib";
82  const char* xmlInitFunc = "func";
83  const char* xmlRunFunc = "runfunc";
84  const char* xmlCpuInfo = "cpuinfo";
85  const char* xmlSocketHost = "sockethost";
86  const char* xmlUseControl = "control";
87  const char* xmlMasterProcess = "master";
88  const char* xmlPublisher = "publisher";
89 
90  const char* xmlTrueValue = "true";
91  const char* xmlFalseValue = "false";
92 }
93 
94 dabc::ConfigBase::ConfigBase(const char* fname) :
95  fDoc(nullptr),
96  fVersion(-1),
97  fCmdVariables(nullptr),
98  fVariables(nullptr),
99  envDABCSYS(),
100  envDABCUSERDIR(),
101  envDABCNODEID(),
102  envContext()
103 {
104  if (!fname) return;
105 
106  fDoc = Xml::ParseFile(fname, true);
107  if (!fDoc) return;
108 
110 
111  if (IsNodeName(rootnode, xmlRootNode)) {
112  fVersion = GetIntAttr(rootnode, xmlVersionAttr, 2);
113  } else {
114  EOUT("Xml file %s not in dabc format", fname);
116  fDoc = nullptr;
117  fVersion = -1;
118  }
119 }
120 
122 {
123  Xml::FreeDoc(fDoc);
124  fDoc = nullptr;
125 
126  Xml::FreeNode(fCmdVariables);
127  fCmdVariables = nullptr;
128 
129 }
130 
132 {
133  if (!fDoc || fVariables) return fVariables;
134 
135  fVariables = nullptr;
136  XMLNodePointer_t rootnode = Xml::DocGetRootElement(fDoc);
137  if (!rootnode) return nullptr;
138 
139  XMLNodePointer_t node = Xml::GetChild(rootnode);
140  while (node!=nullptr) {
141  if (IsNodeName(node, xmlVariablesNode)) {
142  fVariables = node;
143  break;
144  }
145  node = Xml::GetNext(node);
146  }
147 
148  return fVariables;
149 }
150 
151 void dabc::ConfigBase::AddCmdVariable(const char* name, const char* value)
152 {
153  if (!fCmdVariables) fCmdVariables = Xml::NewChild(nullptr, nullptr, "CmdVariables", nullptr);
154 
155  XMLNodePointer_t node = Xml::NewChild(fCmdVariables, nullptr, name, nullptr);
156  Xml::NewAttr(node, nullptr, xmlValueAttr, value);
157 }
158 
159 
160 bool dabc::ConfigBase::IsNodeName(XMLNodePointer_t node, const char* name)
161 {
162  if (!node || !name) return false;
163 
164  const char *n = Xml::GetNodeName(node);
165 
166  return !n ? false : strcmp(n,name) == 0;
167 }
168 
169 const char* dabc::ConfigBase::GetAttr(XMLNodePointer_t node, const char* attr, const char* defvalue)
170 {
171  const char* res = Xml::GetAttr(node, attr);
172  return res ? res : defvalue;
173 }
174 
175 int dabc::ConfigBase::GetIntAttr(XMLNodePointer_t node, const char* attr, int defvalue)
176 {
177  const char* res = GetAttr(node, attr, 0);
178  return res ? std::stoi(res) : defvalue;
179 }
180 
182 {
183  if (!node) return nullptr;
184  XMLNodePointer_t child = Xml::GetChild(node);
185  while (child!=nullptr) {
186  if (IsNodeName(child, name)) return child;
187  child = Xml::GetNext(child);
188  }
189  return nullptr;
190 }
191 
193  XMLNodePointer_t node,
194  const char* sub1,
195  const char* sub2,
196  const char* sub3)
197 {
198  if (sub1==0) return 0;
199 
200  XMLNodePointer_t subnode = Xml::GetChild(node);
201  while (subnode!=0) {
202  if (IsNodeName(subnode, sub1)) {
203  if (sub2==0) {
204  if (lastmatch==0) return subnode;
205  if (lastmatch==subnode) lastmatch = 0;
206  } else {
207  XMLNodePointer_t res = FindItemMatch(lastmatch, subnode, sub2, sub3, 0);
208  if (res!=0) return res;
209  }
210  }
211 
212  subnode = Xml::GetNext(subnode);
213  }
214 
215  return 0;
216 }
217 
219 {
220  if ((node==0) || (mask==0)) return false;
221 
222  if (!IsNodeName(node, Xml::GetNodeName(mask))) return false;
223 
224  // this code compares attributes of two nodes and verify that they are matching
225  XMLAttrPointer_t xmlattr = Xml::GetFirstAttr(node);
226 
227  bool isanyattr(xmlattr!=0), isanywildcard(false);
228 
229  while (xmlattr!=0) {
230 
231  const char* attrname = Xml::GetAttrName(xmlattr);
232 
233  const char* value = Xml::GetAttr(node, attrname);
234 
235  const char* maskvalue = Xml::GetAttr(mask, attrname);
236 
237  if (IsWildcard(maskvalue)) isanywildcard = true;
238 
239  if ((value!=0) && (maskvalue!=0))
240  if (fnmatch(maskvalue, value, FNM_NOESCAPE)!=0) return false;
241 
242  xmlattr = Xml::GetNextAttr(xmlattr);
243  }
244 
245  // it is required that matching nodes should contain at least one attribute with wildcard,
246  // otherwise we will enter main node itself again and again
247  if (isanyattr && !isanywildcard) return false;
248 
249  return true;
250 }
251 
252 
254  XMLNodePointer_t node,
255  const char* sub1,
256  const char* sub2,
257  const char* sub3)
258 {
259  if (!node) return nullptr;
260 
261  // first of all, check if node has specified subitem
262 
263  XMLNodePointer_t nextmatch = FindItemMatch(lastmatch, node, sub1, sub2, sub3);
264 
265  if (nextmatch!=0) return nextmatch;
266 
267 
268  XMLNodePointer_t subfolder = Xml::GetChild(RootNode());
269 
270  while (subfolder!=0) {
271  if (NodeMaskMatch(node, subfolder)) {
272 
273  nextmatch = FindItemMatch(lastmatch, subfolder, sub1, sub2, sub3);
274 
275  if (nextmatch!=0) return nextmatch;
276  }
277 
278  subfolder = Xml::GetNext(subfolder);
279  }
280 
281  return 0;
282 }
283 
285 {
286  if (node==0) return std::string();
287  const char* value = Xml::GetAttr(node, xmlValueAttr);
288  if (value==0) value = Xml::GetNodeContent(node);
289  return ResolveEnv(value ? value : "");
290 }
291 
292 std::string dabc::ConfigBase::GetAttrValue(XMLNodePointer_t node, const char* name)
293 {
294  const char* res = Xml::GetAttr(node, name);
295  if (res==0) return std::string();
296  return ResolveEnv(res);
297 }
298 
299 
305  const std::string &dflt,
306  const char* sub1,
307  const char* sub2,
308  const char* sub3)
309 {
310  XMLNodePointer_t res = FindMatch(0, node, sub1, sub2, sub3);
311  if (res==0) {
312  if (sub2!=0) {
313  XMLNodePointer_t child = FindChild(node, sub1);
314  if (child) return Find1(child, dflt, sub2, sub3);
315  }
316  return dflt;
317  }
318  std::string cont = GetNodeValue(res);
319  return cont.empty() ? dflt : cont;
320 }
321 
323  XMLNodePointer_t& prev,
324  const char* sub1,
325  const char* sub2,
326  const char* sub3)
327 {
328  XMLNodePointer_t res = FindMatch(prev, node, sub1, sub2, sub3);
329  prev = res;
330  if (res==0) return std::string();
331  return GetNodeValue(res);
332 }
333 
335 {
336  if (!IsOk()) return 0;
337 
338  XMLNodePointer_t rootnode = Xml::DocGetRootElement(fDoc);
339  if (rootnode==0) return 0;
340  XMLNodePointer_t node = Xml::GetChild(rootnode);
341  unsigned cnt = 0;
342  while (node!=0) {
343  if (IsContextNode(node)) cnt++;
344  node = Xml::GetNext(node);
345  }
346  return cnt;
347 }
348 
349 std::string dabc::ConfigBase::NodeName(unsigned id)
350 {
351  XMLNodePointer_t contnode = FindContext(id);
352  if (contnode == 0) return std::string("");
353  const char* host = Xml::GetAttr(contnode, xmlHostAttr);
354  if (host == 0) return std::string("");
355  return ResolveEnv(host);
356 }
357 
359 {
360  XMLNodePointer_t contnode = FindContext(id);
361  if (contnode == 0) return 0;
362  const char* sbuf = Xml::GetAttr(contnode, xmlPortAttr);
363  if (sbuf == 0) return 0;
364  std::string s = ResolveEnv(sbuf);
365  if (s.empty()) return 0;
366  int res = 0;
367  if (!dabc::str_to_int(s.c_str(), &res)) res = 0;
368  return res;
369 }
370 
372 {
373  XMLNodePointer_t contnode = FindContext(id);
374  if (contnode == 0) return false;
375 
376  return Find1(contnode, "", xmlRunNode, xmlActive) != xmlFalseValue;
377 }
378 
379 std::string dabc::ConfigBase::ContextName(unsigned id)
380 {
381  XMLNodePointer_t contnode = FindContext(id);
382  std::string oldhost = envHost;
383  envHost = NodeName(id);
384  const char* name = Xml::GetAttr(contnode, xmlNameAttr);
385  std::string res = name ? ResolveEnv(name) : "";
386  if (res.empty()) res = envHost;
387  envHost = oldhost;
388  return res;
389 }
390 
391 bool dabc::ConfigBase::IsWildcard(const char* str)
392 {
393  if (str==0) return false;
394 
395  return (strchr(str,'*')!=0) || (strchr(str,'?')!=0);
396 }
397 
399 {
400  if (fDoc==0) return 0;
401  return Xml::DocGetRootElement(fDoc);
402 }
403 
405 {
406  if (node==0) return false;
407 
408  if (!IsNodeName(node, xmlContext)) return false;
409 
410  const char* host = Xml::GetAttr(node, xmlHostAttr);
411  if (IsWildcard(host)) return false;
412 
413  const char* name = Xml::GetAttr(node, xmlNameAttr);
414 
415  if (IsWildcard(name)) return false;
416 
417  return true;
418 }
419 
420 
422 {
423  if (!fDoc) return nullptr;
424  XMLNodePointer_t rootnode = Xml::DocGetRootElement(fDoc);
425  if (!rootnode) return nullptr;
426  XMLNodePointer_t node = Xml::GetChild(rootnode);
427  unsigned cnt = 0;
428 
429  while (node!=nullptr) {
430  if (IsContextNode(node)) {
431  if (cnt++ == id) return node;
432  }
433  node = Xml::GetNext(node);
434  }
435 
436  return nullptr;
437 }
438 
439 
440 std::string dabc::ConfigBase::ResolveEnv(const std::string &arg, int id)
441 {
442  if (arg.empty()) return arg;
443 
444  std::string name = arg;
445 
446  XMLNodePointer_t vars = Variables();
447 
448  size_t pos1, pos2;
449 
450  while ((pos1 = name.find("${")) != std::string::npos) {
451 
452  pos2 = name.find("}", pos1);
453 
454  if (pos2==std::string::npos) {
455  EOUT("Wrong variable parenthesis %s", arg.c_str());
456  return arg;
457  }
458 
459  std::string var(name, pos1+2, pos2-pos1-2);
460 
461  name.erase(pos1, pos2-pos1+1);
462 
463  if (var.length()>0) {
464  std::string value;
465 
466  XMLNodePointer_t node = FindChild(fCmdVariables, var.c_str());
467  if (node==0) node = FindChild(vars, var.c_str());
468  if (node!=0) value = GetNodeValue(node);
469 
470  if (value.empty()){
471  if (var==xmlDABCSYS) value = envDABCSYS; else
472  if (var==xmlDABCUSERDIR) value = envDABCUSERDIR; else
473  if (var==xmlDABCWORKDIR) value = envDABCWORKDIR; else
474  if (var==xmlDABCNODEID) value = envDABCNODEID; else
475  if (var==xmlDABCNUMNODES) value = envDABCNUMNODES; else
476  if (var==xmlHostAttr) value = envHost; else
477  if (var==xmlContext) value = envContext;
478  }
479  if (value.empty()) value = GetEnv(var.c_str());
480 
481  // allow #${} to get number of entries from variable (if not array - 1)
482  if ((pos1>0) && (name[pos1-1] == '#')) {
483  if (value.empty()) value = "0"; else
484  if ((value[0]!='[') || (value[value.length()-1]!=']')) value = "1"; else {
485  int cnt = 1;
486  for (size_t i=1;i<value.length()-1;++i)
487  if (value[i]==',') cnt++;
488  value = dabc::format("%d", cnt);
489  }
490  name.erase(--pos1, 1);
491  } else
492  if ((id>=0) && (pos1 < name.length()) && (name[pos1] == '#') && !value.empty()) {
493  name.erase(pos1, 1);
494  // extract element of array
495  if ((value[0]!='[') || (value[value.length()-1]!=']')) {
496  if (id!=0) value.clear();
497  } else {
498  int cnt = 0;
499  size_t prev = 1;
500  for (size_t i=1;i<value.length();++i) {
501  if ((value[i]==',') || (i==value.length()-1)) {
502  if (cnt == id) {
503  value = value.substr(prev, i-prev);
504  prev = 0; // just mark
505  break;
506  }
507  prev = i+1;
508  cnt++;
509  }
510  }
511  if (prev!=0) value.clear();
512  }
513 
514  }
515 
516  if (!value.empty()) name.insert(pos1, value);
517  }
518  }
519 
520  return name;
521 }
522 
523 std::string dabc::ConfigBase::GetEnv(const char* name)
524 {
525  const char* env = getenv(name);
526  return std::string(env ? env : "");
527 }
528 
529 std::string dabc::ConfigBase::SshArgs(unsigned id, const char* skind, const char* topcfgfile, const char* topworkdir)
530 {
531  if (skind==0) skind = "test";
532 
533  int kind = -1;
534  if (strcmp(skind, "kill")==0) kind = kindKill; else
535  if (strcmp(skind, "copycfg")==0) kind = kindCopy; else
536  if (strcmp(skind, "start")==0) kind = kindStart; else
537  if (strcmp(skind, "stop")==0) kind = kindStop; else
538  if (strcmp(skind, "test")==0) kind = kindTest; else
539  if (strcmp(skind, "run")==0) kind = kindRun; else
540  if (strcmp(skind, "getlog")==0) kind = kindGetlog; else
541  if (strcmp(skind, "dellog")==0) kind = kindDellog; else
542 
543  if (kind<0) return std::string("");
544 
545  std::string res;
546  XMLNodePointer_t contnode = FindContext(id);
547  if (contnode == 0) return std::string("");
548 
549  envDABCNODEID = dabc::format("%u", id);
550  envDABCNUMNODES = dabc::format("%u", NumNodes());
551 
552  envHost = NodeName(id);
553  envContext = ContextName(id);
554 
555  envDABCSYS = Find1(contnode, "", xmlRunNode, xmlDABCSYS);
556  envDABCUSERDIR = Find1(contnode, "", xmlRunNode, xmlDABCUSERDIR);
557  envDABCWORKDIR = Find1(contnode, "", xmlRunNode, xmlWorkDir);
558 
559  std::string hostname = envHost;
560  if (hostname.empty()) hostname = "localhost";
561 
562  std::string username = Find1(contnode, "", xmlRunNode, xmlSshUser);
563  std::string portid = Find1(contnode, "", xmlRunNode, xmlSshPort);
564  std::string timeout = Find1(contnode, "", xmlRunNode, xmlSshTimeout);
565  std::string initcmd = Find1(contnode, "", xmlRunNode, xmlSshInit);
566  std::string testcmd = Find1(contnode, "", xmlRunNode, xmlSshTest);
567 
568  std::string debugger = Find1(contnode, "", xmlRunNode, xmlDebugger);
569  std::string ldpath = Find1(contnode, "", xmlRunNode, xmlLDPATH);
570  bool copycfg = (Find1(contnode, "", xmlRunNode, xmlCopyCfg) == xmlTrueValue);
571  std::string dabc_stdout = Find1(contnode, "", xmlRunNode, xmlStdOut);
572  std::string dabc_errout = Find1(contnode, "", xmlRunNode, xmlErrOut);
573  bool nullout = (Find1(contnode, "", xmlRunNode, xmlNullOut) == xmlTrueValue);
574  std::string tasksetargs = Find1(contnode, "", xmlRunNode, xmlTaskset);
575  std::string logfile = Find1(contnode, "", xmlRunNode, xmlLogfile);
576 
577  std::string workdir = envDABCWORKDIR;
578  std::string dabcsys = envDABCSYS;
579  std::string userdir = envDABCUSERDIR;
580 
581  std::string envdabcsys = GetEnv("DABCSYS");
582 
583  if (topcfgfile==0) {
584  EOUT("Config file not defined");
585  return std::string("");
586  }
587 
588  if (workdir.empty()) workdir = topworkdir;
589 
590  std::string workcfgfile = topcfgfile;
591  if (copycfg)
592  workcfgfile = dabc::format("node%03u_%s", id, topcfgfile);
593 
594  std::string copycmd, logcmd;
595 
596  bool backgr(false), addcopycmd(false);
597 
598  if (copycfg) {
599  copycmd = "scp -q ";
600  if (!portid.empty())
601  copycmd += dabc::format("-P %s ", portid.c_str());
602 
603  copycmd += dabc::format("%s ", topcfgfile);
604 
605  if (!username.empty()) {
606  copycmd += username;
607  copycmd += "@";
608  }
609 
610  copycmd += hostname;
611  copycmd += ":";
612 
613  if (!workdir.empty()) {
614  copycmd += workdir;
615  if (workdir[workdir.length()-1] != '/') copycmd += "/";
616  }
617 
618  copycmd += workcfgfile;
619  }
620 
621  logcmd = "ssh -x ";
622 
623  if (!portid.empty()) {
624  logcmd += "-p ";
625  logcmd += portid;
626  logcmd += " ";
627  }
628 
629  if (!timeout.empty()) {
630  logcmd += "-o ConnectTimeout=";
631  logcmd += timeout;
632  logcmd += " ";
633  }
634 
635  if (!username.empty()) {
636  logcmd += username;
637  logcmd += "@";
638  }
639 
640  logcmd += hostname;
641 
642  if (kind == kindTest) {
643  // this is a way to get test arguments
644 
645  if (!initcmd.empty()) res += dabc::format("%s; ", initcmd.c_str());
646 
647  if (!testcmd.empty()) res += dabc::format("%s; ", testcmd.c_str());
648 
649  if (!dabcsys.empty())
650  res += dabc::format("if [[ ! -d %s ]] ; then echo DABCSYS = %s missed; exit 11; fi; ", dabcsys.c_str(), dabcsys.c_str());
651  else
652  if (!envdabcsys.empty())
653  res += dabc::format("if [[ (( \\${#DABCSYS}==0 )) && (! -d %s) ]] ; then echo DABCSYS = %s missed; exit 11; fi; ", envdabcsys.c_str(), envdabcsys.c_str());
654  else
655  res += "if (( \\${#DABCSYS}==0 )) ; then echo DABCSYS not specified; exit 7; fi; ";
656 
657  if (!workdir.empty())
658  res += dabc::format(" if [[ ! -d %s ]] ; then echo workdir = %s missed; exit 12; fi; ", workdir.c_str(), workdir.c_str());
659 
660  if (!copycfg && !workcfgfile.empty()) {
661  if (!workdir.empty()) res += dabc::format(" cd %s;", workdir.c_str());
662  res += dabc::format(" if [[ ! -f %s ]] ; then echo cfgfile = %s missed; exit 12; fi; ", workcfgfile.c_str(), workcfgfile.c_str());
663  }
664 
665  res += dabc::format(" echo Test on node %s done;", hostname.c_str());
666 
667  } else
668 
669  if (kind == kindCopy) {
670  // copy in extra config file
671 
672  if (copycmd.empty()) logcmd = "echo noop";
673  else logcmd = copycmd;
674 
675  } else
676 
677  if ((kind == kindStart) || (kind == kindRun)) {
678 
679  // add config copy command at the very beginning
680 
681  if (copycfg && !copycmd.empty()) addcopycmd = true;
682 
683  // this is main run arguments
684 
685  if (!initcmd.empty()) res += dabc::format("%s; ", initcmd.c_str());
686 
687  std::string ld;
688  if (!ldpath.empty()) ld += ldpath;
689  if (!userdir.empty()) { if (!ld.empty()) ld += ":"; ld += userdir; }
690 
691  if (!dabcsys.empty()) {
692  res += dabc::format("export DABCSYS=%s;", dabcsys.c_str());
693  res += " export LD_LIBRARY_PATH=";
694  if (!ld.empty()) { res += ld; res += ":"; }
695  res += "\\$DABCSYS/lib:\\$LD_LIBRARY_PATH;";
696  } else
697  if (!envdabcsys.empty()) {
698  res += dabc::format( "if [[ (( \\${#DABCSYS}==0 )) && -d %s ]] ; then export DABCSYS=%s;", envdabcsys.c_str(), envdabcsys.c_str());
699  res += " export LD_LIBRARY_PATH=";
700  if (!ld.empty()) { res += ld; res += ":"; }
701  res += "\\$DABCSYS/lib:\\$LD_LIBRARY_PATH; fi;";
702  } else
703  if (!ld.empty()) {
704  res += " if (( \\${#DABCSYS}==0 )) ; then echo DABCSYS not specified; exit 7; fi;";
705  res += dabc::format(" export LD_LIBRARY_PATH=%s:\\$LD_LIBRARY_PATH;", ld.c_str());
706  }
707 
708  if (!workdir.empty()) res += dabc::format(" cd %s;", workdir.c_str());
709 
710  if (!tasksetargs.empty() && (tasksetargs!=xmlFalseValue)) {
711  res += " taskset ";
712  res += tasksetargs;
713  }
714 
715  if (!debugger.empty() && (debugger!=xmlFalseValue)) {
716  if (debugger == xmlTrueValue)
717  res += " gdb -q -x \\$DABCSYS/base/run/gdbcmd.txt --args";
718  else {
719  res += " ";
720  res += debugger;
721  }
722  }
723 
724  res += dabc::format(" \\$DABCSYS/bin/dabc_exe %s -nodeid %u -numnodes %u",
725  workcfgfile.c_str(), id, NumNodes());
726 
727  if (kind == kindRun) res += " -run";
728 
729  if (nullout) {
730  res += " >/dev/null 2>/dev/null";
731  } else {
732  if (!dabc_stdout.empty()) { res += " >"; res+=dabc_stdout; }
733  if (!dabc_errout.empty()) { res += " 2>"; res+=dabc_errout; }
734  }
735 
736  backgr = true;
737 
738  } else
739 
740  if ((kind == kindKill) || (kind == kindStop)) {
741  if (copycfg && !workcfgfile.empty()) {
742  if (!workdir.empty()) res += dabc::format(" cd %s;", workdir.c_str());
743  res += dabc::format(" rm -f %s;", workcfgfile.c_str());
744  }
745 
746  if (kind == kindKill)
747  res += dabc::format(" killall --quiet dabc_exe; echo Kill on node %s done;", hostname.c_str());
748  else
749  res += dabc::format(" pkill -SIGINT dabc_exe; echo Stop on node %s done;", hostname.c_str());
750  } else
751 
752  if (kind == kindGetlog) {
753 
754  if (logfile.empty())
755  logcmd = dabc::format("echo no logfile on node id %u host %u", id, hostname.c_str());
756  else {
757 
758  addcopycmd = true;
759  copycmd = dabc::format("echo Copy logfile %s from node %s", logfile.c_str(), hostname.c_str());
760 
761  logcmd = "scp -q ";
762  if (!portid.empty())
763  logcmd += dabc::format("-P %s ", portid.c_str());
764 
765  if (!username.empty()) {
766  logcmd += username;
767  logcmd += "@";
768  }
769 
770  logcmd += hostname;
771  logcmd += ":";
772 
773  // add path to workdir if logfile defined whithout absolute path
774  if (!workdir.empty() && (logfile[0]!='/')) {
775  logcmd += workdir;
776  if (workdir[workdir.length()-1] != '/') logcmd += "/";
777  }
778 
779  logcmd += logfile;
780 
781  logcmd += " .";
782  }
783  } else
784 
785  if (kind == kindDellog) {
786 
787  if (!workdir.empty()) res += dabc::format(" cd %s;", workdir.c_str());
788 
789  if (logfile.empty())
790  res += dabc::format(" echo no logfile on node %s;", hostname.c_str());
791  else
792  res += dabc::format(" rm -f %s; echo Del logfile %s on node %s", logfile.c_str(), logfile.c_str(), hostname.c_str());
793  }
794 
795  if (!res.empty())
796  logcmd = logcmd + " " + res;
797 
798  if (backgr)
799  logcmd = std::string("&") + logcmd;
800 
801  // when many commands, use bash format ([0]="arg1" [1]="arg2")
802  if (addcopycmd)
803  logcmd = std::string("([0]=\"") + copycmd + "\" [1]=\"" + logcmd + "\")";
804  else
805  logcmd = std::string("\"") + logcmd + "\"";
806 
807  return logcmd;
808 }
809 
XMLNodePointer_t Variables()
Definition: ConfigBase.cxx:131
void AddCmdVariable(const char *name, const char *value)
Add variable from command line.
Definition: ConfigBase.cxx:151
std::string GetAttrValue(XMLNodePointer_t node, const char *name)
Definition: ConfigBase.cxx:292
std::string SshArgs(unsigned id=0, const char *skind="run", const char *topcfgfile=0, const char *topworkdir=0)
method used by run.sh script to produce command line
Definition: ConfigBase.cxx:529
int GetIntAttr(XMLNodePointer_t node, const char *attr, int defvalue=0)
Definition: ConfigBase.cxx:175
std::string NodeName(unsigned id)
returns nodename of specified context
Definition: ConfigBase.cxx:349
bool NodeMaskMatch(XMLNodePointer_t node, XMLNodePointer_t mask)
Definition: ConfigBase.cxx:218
XMLNodePointer_t FindItemMatch(XMLNodePointer_t &lastmatch, XMLNodePointer_t node, const char *sub1=0, const char *sub2=0, const char *sub3=0)
Definition: ConfigBase.cxx:192
XMLNodePointer_t RootNode()
Definition: ConfigBase.cxx:398
std::string GetEnv(const char *name)
Definition: ConfigBase.cxx:523
XMLNodePointer_t FindContext(unsigned id)
Definition: ConfigBase.cxx:421
int NodePort(unsigned id)
returns communication port of specified context
Definition: ConfigBase.cxx:358
std::string Find1(XMLNodePointer_t node, const std::string &dflt, const char *sub1, const char *sub2=0, const char *sub3=0)
Search first entry for item sub1/sub2/sub3 in specified node First tries full path,...
Definition: ConfigBase.cxx:304
static bool IsWildcard(const char *str)
Definition: ConfigBase.cxx:391
std::string FindN(XMLNodePointer_t node, XMLNodePointer_t &prev, const char *sub1, const char *sub2=0, const char *sub3=0)
Definition: ConfigBase.cxx:322
std::string GetNodeValue(XMLNodePointer_t node)
Definition: ConfigBase.cxx:284
XMLNodePointer_t FindChild(XMLNodePointer_t node, const char *name)
Definition: ConfigBase.cxx:181
XMLNodePointer_t FindMatch(XMLNodePointer_t lastmatch, XMLNodePointer_t node, const char *sub1=0, const char *sub2=0, const char *sub3=0)
Definition: ConfigBase.cxx:253
const char * GetAttr(XMLNodePointer_t node, const char *attr, const char *defvalue=0)
Definition: ConfigBase.cxx:169
ConfigBase(const char *fname=0)
Definition: ConfigBase.cxx:94
std::string ContextName(unsigned id)
returns name of specified context
Definition: ConfigBase.cxx:379
bool NodeActive(unsigned id)
returns configured (initial) state of the node
Definition: ConfigBase.cxx:371
XMLDocPointer_t fDoc
Definition: ConfigBase.h:111
static bool IsContextNode(XMLNodePointer_t node)
Identifies, if node can be identified as valid context - no any wildcards in names.
Definition: ConfigBase.cxx:404
unsigned NumNodes()
returns number of nodes in xml file
Definition: ConfigBase.cxx:334
static bool IsNodeName(XMLNodePointer_t node, const char *name)
Definition: ConfigBase.cxx:160
std::string ResolveEnv(const std::string &arg, int id=-1)
Replaces entries like ${name} be variable value.
Definition: ConfigBase.cxx:440
#define EOUT(args ...)
Definition: logging.h:150
XMLDocPointer_t ParseFile(const char *filename, bool showerr=true)
Definition: XmlEngine.cxx:1078
XMLAttrPointer_t GetFirstAttr(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:518
XMLNodePointer_t DocGetRootElement(XMLDocPointer_t xmldoc)
Definition: XmlEngine.cxx:1062
XMLNodePointer_t GetNext(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:925
const char * GetAttr(XMLNodePointer_t xmlnode, const char *name)
Definition: XmlEngine.cxx:411
void FreeNode(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:847
XMLAttrPointer_t NewAttr(XMLNodePointer_t xmlnode, XMLNsPointer_t, const char *name, const char *value)
Definition: XmlEngine.cxx:438
const char * GetNodeName(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:885
XMLNodePointer_t GetChild(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:906
const char * GetNodeContent(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:893
XMLNodePointer_t NewChild(XMLNodePointer_t parent, XMLNsPointer_t ns, const char *name, const char *content=nullptr)
Definition: XmlEngine.cxx:564
void FreeDoc(XMLDocPointer_t xmldoc)
Definition: XmlEngine.cxx:1013
const char * GetAttrName(XMLAttrPointer_t xmlattr)
Definition: XmlEngine.cxx:542
XMLAttrPointer_t GetNextAttr(XMLAttrPointer_t xmlattr)
Definition: XmlEngine.cxx:532
Event manipulation API.
Definition: api.h:23
const char * xmlWorkDir
Definition: ConfigBase.cxx:65
const char * xmlDABCNUMNODES
Definition: ConfigBase.cxx:58
void * XMLAttrPointer_t
Definition: XmlEngine.h:27
const char * xmlThrdStopTime
Definition: ConfigBase.cxx:75
const char * xmlNoDebugPrefix
Definition: ConfigBase.cxx:67
const char * xmlValueAttr
Definition: ConfigBase.cxx:46
const char * xmlDebugger
Definition: ConfigBase.cxx:64
const char * xmlLoglimit
Definition: ConfigBase.cxx:69
const char * xmlInitFunc
Definition: ConfigBase.cxx:82
const char * xmlVersionAttr
Definition: ConfigBase.cxx:28
void * XMLNodePointer_t
Definition: XmlEngine.h:25
const char * xmlTimeoutAttr
Definition: ConfigBase.cxx:42
const char * xmlLDPATH
Definition: ConfigBase.cxx:80
const char * xmlCpuInfo
Definition: ConfigBase.cxx:84
const char * xmlPoolAttr
Definition: ConfigBase.cxx:41
const char * xmlMasterProcess
Definition: ConfigBase.cxx:87
const char * xmlUseacknAttr
Definition: ConfigBase.cxx:39
const char * xmlCopyCfg
Definition: ConfigBase.cxx:60
const char * xmlDeviceAttr
Definition: ConfigBase.cxx:37
const char * xmlSshTimeout
Definition: ConfigBase.cxx:53
const char * xmlUserNode
Definition: ConfigBase.cxx:48
std::string format(const char *fmt,...)
Definition: string.cxx:49
const char * xmlThreadsLayout
Definition: ConfigBase.cxx:78
const char * xmlAppDfltName
Definition: ConfigBase.cxx:31
const char * xmlAutoAttr
Definition: ConfigBase.cxx:43
const char * xmlApplication
Definition: ConfigBase.cxx:30
const char * xmlOptionalAttr
Definition: ConfigBase.cxx:40
const char * xmlNumReconnAttr
Definition: ConfigBase.cxx:45
const char * xmlDebuglevel
Definition: ConfigBase.cxx:66
const char * xmlLogfile
Definition: ConfigBase.cxx:68
const char * xmlSshUser
Definition: ConfigBase.cxx:49
const char * xmlRunTime
Definition: ConfigBase.cxx:73
const char * xmlReconnectAttr
Definition: ConfigBase.cxx:44
const char * xmlRunNode
Definition: ConfigBase.cxx:47
const char * xmlDABCUSERDIR
Definition: ConfigBase.cxx:55
const char * xmlVariablesNode
Definition: ConfigBase.cxx:32
const char * xmlNullOut
Definition: ConfigBase.cxx:63
const char * xmlSshTest
Definition: ConfigBase.cxx:52
const char * xmlHaltTime
Definition: ConfigBase.cxx:74
const char * xmlThreadAttr
Definition: ConfigBase.cxx:38
const char * xmlErrOut
Definition: ConfigBase.cxx:62
const char * xmlLoglevel
Definition: ConfigBase.cxx:70
const char * xmlDABCSYS
Definition: ConfigBase.cxx:54
const char * xmlTrueValue
Definition: ConfigBase.cxx:90
const char * xmlContext
Definition: ConfigBase.cxx:29
const char * xmlRootNode
Definition: ConfigBase.cxx:27
const char * xmlSyslog
Definition: ConfigBase.cxx:72
const char * xmlSocketHost
Definition: ConfigBase.cxx:85
const char * xmlPublisher
Definition: ConfigBase.cxx:88
const char * xmlActive
Definition: ConfigBase.cxx:59
const char * xmlUseControl
Definition: ConfigBase.cxx:86
const char * xmlFalseValue
Definition: ConfigBase.cxx:91
const char * xmlClassAttr
Definition: ConfigBase.cxx:36
const char * xmlAffinity
Definition: ConfigBase.cxx:77
const char * xmlStdOut
Definition: ConfigBase.cxx:61
const char * xmlDABCWORKDIR
Definition: ConfigBase.cxx:56
const char * xmlDABCNODEID
Definition: ConfigBase.cxx:57
const char * xmlNameAttr
Definition: ConfigBase.cxx:33
const char * xmlRunFunc
Definition: ConfigBase.cxx:83
const char * xmlPortAttr
Definition: ConfigBase.cxx:35
const char * xmlTaskset
Definition: ConfigBase.cxx:79
const char * xmlSysloglevel
Definition: ConfigBase.cxx:71
const char * xmlNormalMainThrd
Definition: ConfigBase.cxx:76
const char * xmlSshPort
Definition: ConfigBase.cxx:50
const char * xmlHostAttr
Definition: ConfigBase.cxx:34
bool str_to_int(const char *val, int *res)
Convert string to integer value.
Definition: string.cxx:142
const char * xmlUserLib
Definition: ConfigBase.cxx:81
const char * xmlSshInit
Definition: ConfigBase.cxx:51