97 fCmdVariables(nullptr),
114 EOUT(
"Xml file %s not in dabc format", fname);
127 fCmdVariables =
nullptr;
133 if (!fDoc || fVariables)
return fVariables;
135 fVariables =
nullptr;
137 if (!rootnode)
return nullptr;
140 while (node!=
nullptr) {
153 if (!fCmdVariables) fCmdVariables =
Xml::NewChild(
nullptr,
nullptr,
"CmdVariables",
nullptr);
162 if (!node || !name)
return false;
166 return !n ? false : strcmp(n,name) == 0;
172 return res ? res : defvalue;
177 const char* res =
GetAttr(node, attr, 0);
178 return res ? std::stoi(res) : defvalue;
183 if (!node)
return nullptr;
185 while (child!=
nullptr) {
186 if (IsNodeName(child, name))
return child;
198 if (sub1==0)
return 0;
202 if (IsNodeName(subnode, sub1)) {
204 if (lastmatch==0)
return subnode;
205 if (lastmatch==subnode) lastmatch = 0;
208 if (res!=0)
return res;
220 if ((node==0) || (mask==0))
return false;
227 bool isanyattr(xmlattr!=0), isanywildcard(
false);
237 if (IsWildcard(maskvalue)) isanywildcard =
true;
239 if ((value!=0) && (maskvalue!=0))
240 if (fnmatch(maskvalue, value, FNM_NOESCAPE)!=0)
return false;
247 if (isanyattr && !isanywildcard)
return false;
259 if (!node)
return nullptr;
263 XMLNodePointer_t nextmatch = FindItemMatch(lastmatch, node, sub1, sub2, sub3);
265 if (nextmatch!=0)
return nextmatch;
270 while (subfolder!=0) {
271 if (NodeMaskMatch(node, subfolder)) {
273 nextmatch = FindItemMatch(lastmatch, subfolder, sub1, sub2, sub3);
275 if (nextmatch!=0)
return nextmatch;
286 if (node==0)
return std::string();
289 return ResolveEnv(value ? value :
"");
295 if (res==0)
return std::string();
296 return ResolveEnv(res);
305 const std::string &dflt,
314 if (child)
return Find1(child, dflt, sub2, sub3);
318 std::string cont = GetNodeValue(res);
319 return cont.empty() ? dflt : cont;
330 if (res==0)
return std::string();
331 return GetNodeValue(res);
336 if (!IsOk())
return 0;
339 if (rootnode==0)
return 0;
343 if (IsContextNode(node)) cnt++;
352 if (contnode == 0)
return std::string(
"");
354 if (host == 0)
return std::string(
"");
355 return ResolveEnv(host);
361 if (contnode == 0)
return 0;
363 if (sbuf == 0)
return 0;
364 std::string s = ResolveEnv(sbuf);
365 if (s.empty())
return 0;
374 if (contnode == 0)
return false;
382 std::string oldhost = envHost;
383 envHost = NodeName(
id);
385 std::string res = name ? ResolveEnv(name) :
"";
386 if (res.empty()) res = envHost;
393 if (str==0)
return false;
395 return (strchr(str,
'*')!=0) || (strchr(str,
'?')!=0);
400 if (fDoc==0)
return 0;
406 if (node==0)
return false;
408 if (!IsNodeName(node,
xmlContext))
return false;
411 if (IsWildcard(host))
return false;
415 if (IsWildcard(name))
return false;
423 if (!fDoc)
return nullptr;
425 if (!rootnode)
return nullptr;
429 while (node!=
nullptr) {
430 if (IsContextNode(node)) {
431 if (cnt++ ==
id)
return node;
442 if (arg.empty())
return arg;
444 std::string name = arg;
450 while ((pos1 = name.find(
"${")) != std::string::npos) {
452 pos2 = name.find(
"}", pos1);
454 if (pos2==std::string::npos) {
455 EOUT(
"Wrong variable parenthesis %s", arg.c_str());
459 std::string var(name, pos1+2, pos2-pos1-2);
461 name.erase(pos1, pos2-pos1+1);
463 if (var.length()>0) {
467 if (node==0) node = FindChild(vars, var.c_str());
468 if (node!=0) value = GetNodeValue(node);
479 if (value.empty()) value = GetEnv(var.c_str());
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 {
486 for (
size_t i=1;i<value.length()-1;++i)
487 if (value[i]==
',') cnt++;
490 name.erase(--pos1, 1);
492 if ((
id>=0) && (pos1 < name.length()) && (name[pos1] ==
'#') && !value.empty()) {
495 if ((value[0]!=
'[') || (value[value.length()-1]!=
']')) {
496 if (
id!=0) value.clear();
500 for (
size_t i=1;i<value.length();++i) {
501 if ((value[i]==
',') || (i==value.length()-1)) {
503 value = value.substr(prev, i-prev);
511 if (prev!=0) value.clear();
516 if (!value.empty()) name.insert(pos1, value);
525 const char* env = getenv(name);
526 return std::string(env ? env :
"");
531 if (skind==0) skind =
"test";
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
543 if (kind<0)
return std::string(
"");
547 if (contnode == 0)
return std::string(
"");
552 envHost = NodeName(
id);
553 envContext = ContextName(
id);
559 std::string hostname = envHost;
560 if (hostname.empty()) hostname =
"localhost";
577 std::string workdir = envDABCWORKDIR;
578 std::string dabcsys = envDABCSYS;
579 std::string userdir = envDABCUSERDIR;
581 std::string envdabcsys = GetEnv(
"DABCSYS");
584 EOUT(
"Config file not defined");
585 return std::string(
"");
588 if (workdir.empty()) workdir = topworkdir;
590 std::string workcfgfile = topcfgfile;
592 workcfgfile =
dabc::format(
"node%03u_%s",
id, topcfgfile);
594 std::string copycmd, logcmd;
596 bool backgr(
false), addcopycmd(
false);
605 if (!username.empty()) {
613 if (!workdir.empty()) {
615 if (workdir[workdir.length()-1] !=
'/') copycmd +=
"/";
618 copycmd += workcfgfile;
623 if (!portid.empty()) {
629 if (!timeout.empty()) {
630 logcmd +=
"-o ConnectTimeout=";
635 if (!username.empty()) {
642 if (kind == kindTest) {
645 if (!initcmd.empty()) res +=
dabc::format(
"%s; ", initcmd.c_str());
647 if (!testcmd.empty()) res +=
dabc::format(
"%s; ", testcmd.c_str());
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());
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());
655 res +=
"if (( \\${#DABCSYS}==0 )) ; then echo DABCSYS not specified; exit 7; fi; ";
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());
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());
665 res +=
dabc::format(
" echo Test on node %s done;", hostname.c_str());
669 if (kind == kindCopy) {
672 if (copycmd.empty()) logcmd =
"echo noop";
673 else logcmd = copycmd;
677 if ((kind == kindStart) || (kind == kindRun)) {
681 if (copycfg && !copycmd.empty()) addcopycmd =
true;
685 if (!initcmd.empty()) res +=
dabc::format(
"%s; ", initcmd.c_str());
688 if (!ldpath.empty()) ld += ldpath;
689 if (!userdir.empty()) {
if (!ld.empty()) ld +=
":"; ld += userdir; }
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;";
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;";
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());
708 if (!workdir.empty()) res +=
dabc::format(
" cd %s;", workdir.c_str());
717 res +=
" gdb -q -x \\$DABCSYS/base/run/gdbcmd.txt --args";
724 res +=
dabc::format(
" \\$DABCSYS/bin/dabc_exe %s -nodeid %u -numnodes %u",
725 workcfgfile.c_str(),
id, NumNodes());
727 if (kind == kindRun) res +=
" -run";
730 res +=
" >/dev/null 2>/dev/null";
732 if (!dabc_stdout.empty()) { res +=
" >"; res+=dabc_stdout; }
733 if (!dabc_errout.empty()) { res +=
" 2>"; res+=dabc_errout; }
740 if ((kind == kindKill) || (kind == kindStop)) {
741 if (copycfg && !workcfgfile.empty()) {
742 if (!workdir.empty()) res +=
dabc::format(
" cd %s;", workdir.c_str());
746 if (kind == kindKill)
747 res +=
dabc::format(
" killall --quiet dabc_exe; echo Kill on node %s done;", hostname.c_str());
749 res +=
dabc::format(
" pkill -SIGINT dabc_exe; echo Stop on node %s done;", hostname.c_str());
752 if (kind == kindGetlog) {
755 logcmd =
dabc::format(
"echo no logfile on node id %u host %u",
id, hostname.c_str());
759 copycmd =
dabc::format(
"echo Copy logfile %s from node %s", logfile.c_str(), hostname.c_str());
765 if (!username.empty()) {
774 if (!workdir.empty() && (logfile[0]!=
'/')) {
776 if (workdir[workdir.length()-1] !=
'/') logcmd +=
"/";
785 if (kind == kindDellog) {
787 if (!workdir.empty()) res +=
dabc::format(
" cd %s;", workdir.c_str());
790 res +=
dabc::format(
" echo no logfile on node %s;", hostname.c_str());
792 res +=
dabc::format(
" rm -f %s; echo Del logfile %s on node %s", logfile.c_str(), logfile.c_str(), hostname.c_str());
796 logcmd = logcmd +
" " + res;
799 logcmd = std::string(
"&") + logcmd;
803 logcmd = std::string(
"([0]=\"") + copycmd +
"\" [1]=\"" + logcmd +
"\")";
805 logcmd = std::string(
"\"") + logcmd +
"\"";
XMLNodePointer_t Variables()
void AddCmdVariable(const char *name, const char *value)
Add variable from command line.
std::string GetAttrValue(XMLNodePointer_t node, const char *name)
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
int GetIntAttr(XMLNodePointer_t node, const char *attr, int defvalue=0)
std::string NodeName(unsigned id)
returns nodename of specified context
bool NodeMaskMatch(XMLNodePointer_t node, XMLNodePointer_t mask)
XMLNodePointer_t FindItemMatch(XMLNodePointer_t &lastmatch, XMLNodePointer_t node, const char *sub1=0, const char *sub2=0, const char *sub3=0)
XMLNodePointer_t RootNode()
std::string GetEnv(const char *name)
XMLNodePointer_t FindContext(unsigned id)
int NodePort(unsigned id)
returns communication port of specified context
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,...
static bool IsWildcard(const char *str)
std::string FindN(XMLNodePointer_t node, XMLNodePointer_t &prev, const char *sub1, const char *sub2=0, const char *sub3=0)
std::string GetNodeValue(XMLNodePointer_t node)
XMLNodePointer_t FindChild(XMLNodePointer_t node, const char *name)
XMLNodePointer_t FindMatch(XMLNodePointer_t lastmatch, XMLNodePointer_t node, const char *sub1=0, const char *sub2=0, const char *sub3=0)
const char * GetAttr(XMLNodePointer_t node, const char *attr, const char *defvalue=0)
ConfigBase(const char *fname=0)
std::string ContextName(unsigned id)
returns name of specified context
bool NodeActive(unsigned id)
returns configured (initial) state of the node
static bool IsContextNode(XMLNodePointer_t node)
Identifies, if node can be identified as valid context - no any wildcards in names.
unsigned NumNodes()
returns number of nodes in xml file
static bool IsNodeName(XMLNodePointer_t node, const char *name)
std::string ResolveEnv(const std::string &arg, int id=-1)
Replaces entries like ${name} be variable value.
XMLDocPointer_t ParseFile(const char *filename, bool showerr=true)
XMLAttrPointer_t GetFirstAttr(XMLNodePointer_t xmlnode)
XMLNodePointer_t DocGetRootElement(XMLDocPointer_t xmldoc)
XMLNodePointer_t GetNext(XMLNodePointer_t xmlnode)
const char * GetAttr(XMLNodePointer_t xmlnode, const char *name)
void FreeNode(XMLNodePointer_t xmlnode)
XMLAttrPointer_t NewAttr(XMLNodePointer_t xmlnode, XMLNsPointer_t, const char *name, const char *value)
const char * GetNodeName(XMLNodePointer_t xmlnode)
XMLNodePointer_t GetChild(XMLNodePointer_t xmlnode)
const char * GetNodeContent(XMLNodePointer_t xmlnode)
XMLNodePointer_t NewChild(XMLNodePointer_t parent, XMLNsPointer_t ns, const char *name, const char *content=nullptr)
void FreeDoc(XMLDocPointer_t xmldoc)
const char * GetAttrName(XMLAttrPointer_t xmlattr)
XMLAttrPointer_t GetNextAttr(XMLAttrPointer_t xmlattr)
const char * xmlDABCNUMNODES
const char * xmlThrdStopTime
const char * xmlNoDebugPrefix
const char * xmlValueAttr
const char * xmlVersionAttr
const char * xmlTimeoutAttr
const char * xmlMasterProcess
const char * xmlUseacknAttr
const char * xmlDeviceAttr
const char * xmlSshTimeout
std::string format(const char *fmt,...)
const char * xmlThreadsLayout
const char * xmlAppDfltName
const char * xmlApplication
const char * xmlOptionalAttr
const char * xmlNumReconnAttr
const char * xmlDebuglevel
const char * xmlReconnectAttr
const char * xmlDABCUSERDIR
const char * xmlVariablesNode
const char * xmlThreadAttr
const char * xmlTrueValue
const char * xmlSocketHost
const char * xmlPublisher
const char * xmlUseControl
const char * xmlFalseValue
const char * xmlClassAttr
const char * xmlDABCWORKDIR
const char * xmlDABCNODEID
const char * xmlSysloglevel
const char * xmlNormalMainThrd
bool str_to_int(const char *val, int *res)
Convert string to integer value.