21 #include "RConfigure.h"
29 #include "Xrd/XrdScheduler.hh"
30 #include "XrdOuc/XrdOucStream.hh"
40 XrdROOT::XrdROOT(
const char *dir,
const char *tag,
const char *bindir,
41 const char *incdir,
const char *libdir,
const char *datadir)
43 XPDLOC(SMGR,
"XrdROOT")
55 if (!dir || strlen(dir) <= 0)
57 if (tag && strlen(tag) > 0) {
59 fExport +=
" "; fExport += dir;
63 if (CheckDir(dir) != 0)
return;
68 if (!incdir || strlen(incdir) <= 0) {
70 fIncDir +=
"/include";
72 if (CheckDir(fIncDir.c_str()) != 0)
return;
75 if (ParseROOTVersionInfo() == -1) {
76 TRACE(XERR,
"unable to extract ROOT version information from path "<<fIncDir);
81 fTag = (!tag || strlen(tag) <= 0) ? fRelease : tag;
85 if (!libdir || strlen(libdir) <= 0) {
89 if (CheckDir(fLibDir.c_str()) != 0)
return;
93 if (!bindir || strlen(bindir) <= 0) {
97 if (CheckDir(fBinDir.c_str()) != 0)
return;
101 if (!datadir || strlen(datadir) <= 0) {
104 if (CheckDir(fDataDir.c_str()) != 0)
return;
108 fPrgmSrv +=
"/proofserv";
112 fExport +=
" "; fExport += fRelease;
113 fExport +=
" "; fExport += dir;
123 int XrdROOT::CheckDir(
const char *dir)
125 XPDLOC(SMGR,
"CheckDir")
127 if (dir && strlen(dir) > 0) {
130 if (stat(dir, &st) == -1) {
131 TRACE(XERR,
"unable to stat path "<<dir);
135 if (!S_ISDIR(st.st_mode)) {
136 TRACE(XERR,
"path "<<dir<<
" is not a directory");
142 TRACE(XERR,
"path is undefined");
149 void XrdROOT::SetValid(kXR_int16 vers)
155 if (fSrvProtVers > 0) {
156 XrdOucString vs(
" ");
158 fExport.replace(vs,XrdOucString(
""));
164 fExport += (int)fSrvProtVers;
171 int XrdROOT::ParseROOTVersionInfo()
173 XPDLOC(SMGR,
"ParseROOTVersionInfo")
177 XrdOucString versfile = fIncDir;
178 versfile += "/RVersion.h";
181 FILE *fv = fopen(versfile.c_str(), "r");
183 TRACE(XERR,
"unable to open "<<versfile);
197 XrdOucString tkn, sline;
199 while (fgets(line,
sizeof(line), fv)) {
200 if (fRelease.length() <= 0 && (pv = (
char *) strstr(line,
"ROOT_RELEASE"))) {
201 if (line[strlen(line)-1] ==
'\n')
202 line[strlen(line)-1] = 0;
203 pv += strlen(
"ROOT_RELEASE") + 1;
205 fRelease.replace(
"\"",
"");
206 }
else if (fGitCommit.length() <= 0 && (pv = (
char *) strstr(line,
"ROOT_GIT_COMMIT"))) {
207 if (line[strlen(line)-1] ==
'\n')
208 line[strlen(line)-1] = 0;
209 pv += strlen(
"ROOT_GIT_COMMIT") + 1;
211 fGitCommit.replace(
"\"",
"");
212 }
else if ((pv = (
char *) strstr(line,
"ROOT_VERSION_CODE"))) {
213 if (line[strlen(line)-1] ==
'\n') line[strlen(line)-1] = 0;
214 pv += strlen(
"ROOT_VERSION_CODE");
215 while (pv[0] ==
' ') pv++;
216 fVersionCode = atoi(pv);
224 if (fVersionCode < 0) {
225 TRACE(XERR,
"incomplete info found in "<<versfile<<
": version code missing or bad: "<<fVersionCode);
230 if (fRelease.length() <= 0 ||
231 XrdROOT::ParseReleaseString(fRelease.c_str(), fVrsMajor, fVrsMinor, fVrsPatch) < 0) {
232 TRACE(XERR,
"incomplete info found in "<<versfile<<
": release tag missing or bad: "<<fRelease);
237 if (fGitCommit.length() <= 0) {
239 XrdOucString gitcommit = fIncDir;
240 gitcommit +=
"/RGitCommit.h";
243 if ((fv = fopen(gitcommit.c_str(),
"r"))) {
247 while (fgets(line,
sizeof(line), fv)) {
248 if (fGitCommit.length() <= 0 && (pv = (
char *) strstr(line,
"ROOT_GIT_COMMIT"))) {
249 if (line[strlen(line)-1] ==
'\n')
250 line[strlen(line)-1] = 0;
251 pv += strlen(
"ROOT_GIT_COMMIT") + 1;
253 fGitCommit.replace(
"\"",
"");
254 if (fGitCommit.length() > 0)
break;
262 TRACE(REQ,
"file "<<gitcommit<<
" not found");
275 int XrdROOT::GetVersionCode(
const char *release)
278 if (XrdROOT::ParseReleaseString(release, maj, min, patch) < 0)
return -1;
279 return XrdROOT::GetVersionCode(maj, min, patch);
286 int XrdROOT::GetVersionCode(
int maj,
int min,
int patch)
288 return ((maj << 16) + (min << 8) + patch);
296 int XrdROOT::ParseReleaseString(
const char *release,
297 int &maj,
int &min,
int &patch)
299 if (!release || strlen(release) <= 0)
return -1;
301 XrdOucString rel(release, 7), tkn;
303 if ((from = rel.tokenize(tkn, from,
'.')) == -1)
return -1;
304 maj = atoi(tkn.c_str());
305 if ((from = rel.tokenize(tkn, from,
'/')) == -1)
return -1;
306 min = atoi(tkn.c_str());
307 if ((from = rel.tokenize(tkn, from,
' ')) == -1)
return -1;
308 patch = atoi(tkn.c_str());
319 XrdROOTMgr::XrdROOTMgr(XrdProofdManager *mgr,
320 XrdProtocol_Config *pi, XrdSysError *e)
321 : XrdProofdConfig(pi->ConfigFN, e)
324 fLogger = pi->eDest->logger();
328 RegisterDirectives();
334 void XrdROOTMgr::SetLogDir(
const char *dir)
336 XPDLOC(SMGR,
"ROOTMgr::SetLogDir")
338 if (fMgr && dir && strlen(dir)) {
340 XPDFORM(fLogDir,
"%s/rootsysvalidation", dir);
342 XrdProofdAux::GetUserInfo(fMgr->EffectiveUser(), ui);
343 if (XrdProofdAux::AssertDir(fLogDir.c_str(), ui, fMgr->ChangeOwn()) != 0) {
344 XPDERR(
"unable to assert the rootsys log validation path: "<<fLogDir);
347 TRACE(ALL,
"rootsys log validation path: "<<fLogDir);
356 int XrdROOTMgr::Config(
bool rcf)
358 XPDLOC(SMGR,
"ROOTMgr::Config")
361 if (XrdProofdConfig::Config(rcf) != 0) {
362 TRACE(XERR,
"problems parsing file ");
367 msg = (rcf) ?
"re-configuring" :
"configuring";
373 std::list<XrdROOT *>::iterator tri;
374 if (fROOT.size() > 0) {
375 for (tri = fROOT.begin(); tri != fROOT.end();) {
376 if ((*tri)->IsParked()) {
378 tri = fROOT.erase(tri);
386 if (fROOT.size() <= 0) {
387 XrdOucString dir, bd, ld, id, dd;
388 #ifdef R__HAVE_CONFIG
389 if (getenv(
"ROOTIGNOREPREFIX"))
391 dir = getenv(
"ROOTSYS");
392 #ifdef R__HAVE_CONFIG
402 if (dir.length() > 0) {
403 XrdROOT *rootc =
new XrdROOT(dir.c_str(),
"",
404 bd.c_str(),
id.c_str(), ld.c_str(), dd.c_str());
405 if (Validate(rootc, fMgr->Sched()) == 0) {
406 XPDFORM(msg,
"ROOT dist: '%s' validated", rootc->Export());
407 fROOT.push_back(rootc);
410 XPDFORM(mnp,
"ROOT version details: git: '%s', code: %d, {mnp} = {%d,%d,%d}",
411 rootc->GitCommit(), rootc->VersionCode(), rootc->VrsMajor(),
412 rootc->VrsMinor(), rootc->VrsPatch());
415 XPDFORM(msg,
"ROOT dist: '%s' could not be validated", rootc->Export());
419 if (fROOT.size() <= 0) {
420 TRACE(XERR,
"no ROOT dir defined; ROOTSYS location missing - unloading");
433 void XrdROOTMgr::RegisterDirectives()
435 Register(
"rootsys",
new XrdProofdDirective(
"rootsys",
this, &DoDirectiveClass));
441 int XrdROOTMgr::DoDirective(XrdProofdDirective *d,
442 char *val, XrdOucStream *cfg,
bool rcf)
444 XPDLOC(SMGR,
"ROOTMgr::DoDirective")
450 if (d->fName == "rootsys") {
451 return DoDirectiveRootSys(val, cfg, rcf);
453 TRACE(XERR,
"unknown directive: "<<d->fName);
460 int XrdROOTMgr::DoDirectiveRootSys(
char *val, XrdOucStream *cfg,
bool)
462 XPDLOC(SMGR,
"ROOTMgr::DoDirectiveRootSys")
469 XrdOucString dir = val;
470 val = cfg->GetWord();
471 XrdOucString tag = val;
477 ok = (XrdProofdAux::CheckIf(cfg, fMgr->Host()) > 0) ? 1 : 0;
483 if (tag.length() > 0) {
484 while ((val = cfg->GetWord())) { a[i++] = val; }
486 XrdROOT *rootc =
new XrdROOT(dir.c_str(), tag.c_str(), a[0].c_str(),
487 a[1].c_str(), a[2].c_str(), a[3].c_str());
489 std::list<XrdROOT *>::iterator ori;
490 for (ori = fROOT.begin(); ori != fROOT.end(); ++ori) {
491 if ((*ori)->Match(rootc->Dir(), rootc->Tag())) {
492 if ((*ori)->IsParked()) {
501 if (Validate(rootc, fMgr->Sched()) == 0) {
502 TRACE(REQ,
"validation OK for: "<<rootc->Export());
504 XPDFORM(mnp,
"version details: git: '%s', code: %d, {mnp} = {%d,%d,%d}",
505 rootc->GitCommit(), rootc->VersionCode(), rootc->VrsMajor(),
506 rootc->VrsMinor(), rootc->VrsPatch());
509 fROOT.push_back(rootc);
511 TRACE(XERR,
"could not validate "<<rootc->Export());
524 int XrdROOTMgr::Validate(XrdROOT *r, XrdScheduler *sched)
526 XPDLOC(SMGR,
"ROOTMgr::Validate")
528 TRACE(REQ, "forking test and protocol retrieval");
530 if (r->IsInvalid()) {
532 TRACE(XERR,
"invalid instance - cannot be validated");
537 if (!r->PrgmSrv() || strlen(r->PrgmSrv()) <= 0) {
538 TRACE(XERR,
"path to PROOF server application undefined - exit");
544 TRACE(XERR,
"scheduler undefined - exit");
551 TRACE(XERR,
"PROOT protocol number communication");
557 if (TRACING(DBG)) debug = 1;
560 XrdOucString logfile, rootrc;
561 if (fLogDir.length() > 0) {
562 XrdOucString tag(r->Tag());
563 tag.replace(
"/",
"-");
564 XPDFORM(logfile,
"%s/root.%s.log", fLogDir.c_str(), tag.c_str());
566 XPDFORM(rootrc,
"%s/root.%s.rootrc", fLogDir.c_str(), tag.c_str());
571 TRACE(FORK,
"XrdROOTMgr::Validate: forking external proofsrv");
573 if (!(pid = sched->Fork(
"proofsrv"))) {
575 if (logfile.length() > 0 && fLogger) {
577 fLogger->Bind(logfile.c_str());
579 size_t len = strlen(
"ROOTPROOFLOGFILE=") + logfile.length() + 2;
580 char *ev =
new char[len];
581 snprintf(ev, len,
"ROOTPROOFLOGFILE=%s", logfile.c_str());
583 if (debug && rootrc.length() > 0) {
585 FILE *frc = fopen(rootrc.c_str(),
"w");
587 fprintf(frc,
"Proof.DebugLevel: 1\n");
591 len = strlen(
"ROOTRCFILE=") + rootrc.length() + 2;
593 snprintf(ev, len,
"ROOTRCFILE=%s", rootrc.c_str());
598 char *argvv[6] = {0};
601 argvv[0] = (
char *)r->PrgmSrv();
602 argvv[1] = (
char *)
"proofserv";
603 argvv[2] = (
char *)
"xpd";
604 argvv[3] = (
char *)
"test";
606 argvv[4] = (
char *)
"1";
614 if (XrdProofdProofServMgr::SetProofServEnv(fMgr, r) != 0) {
615 TRACE(XERR,
" SetProofServEnv did not return OK - EXIT");
620 char *ev =
new char[25];
621 snprintf(ev, 25,
"ROOTOPENSOCK=%d", fp[1]);
628 if (XrdProofdAux::GetUserInfo(geteuid(), ui) != 0) {
629 TRACE(XERR,
"could not get info for user-id: "<<geteuid());
634 if (XrdSysPriv::ChangePerm((uid_t)ui.fUid, (gid_t)ui.fGid) != 0) {
635 TRACE(XERR,
"can't acquire "<<ui.fUser <<
" identity");
642 execv(r->PrgmSrv(), argvv);
645 TRACE(XERR,
"returned from execv: bad, bad sign !!!");
651 TRACE(XERR,
"forking failed - exit");
658 TRACE(FORK,
"test server launched: wait for protocol ");
664 fds_r.events = POLLIN;
669 while (pollRet == 0 && ntry--) {
670 while ((pollRet = poll(&fds_r, 1, 2000)) < 0 &&
671 (errno == EINTR)) { }
673 TRACE(DBG,
"receiving PROOF server protocol number: waiting 2 s ...");
676 if (read(fp[0], &proto,
sizeof(proto)) !=
sizeof(proto)) {
677 TRACE(XERR,
"problems receiving PROOF server protocol number");
682 TRACE(XERR,
"timed-out receiving PROOF server protocol number");
684 TRACE(XERR,
"failed to receive PROOF server protocol number");
690 r->SetValid((kXR_int16) ntohl(proto));
693 if (logfile.length() > 0 && !debug) {
694 if (unlink(logfile.c_str()) != 0) {
695 TRACE(XERR,
"problems unlinking "<<logfile<<
"; errno: "<<errno);
698 if (debug && rootrc.length() > 0 && unlink(rootrc.c_str()) != 0) {
699 TRACE(XERR,
"problems unlinking "<<rootrc<<
"; errno: "<<errno);
714 XrdOucString XrdROOTMgr::ExportVersions(XrdROOT *def)
719 std::list<XrdROOT *>::iterator ip;
720 for (ip = fROOT.begin(); ip != fROOT.end(); ++ip) {
726 out += (*ip)->Export();
738 XrdROOT *XrdROOTMgr::GetVersion(
const char *tag)
742 std::list<XrdROOT *>::iterator ip;
743 for (ip = fROOT.begin(); ip != fROOT.end(); ++ip) {
744 if ((*ip)->MatchTag(tag)) {