00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "RConfigure.h"
00022
00023 #include "XrdProofdPlatform.h"
00024
00025 #include "XrdROOT.h"
00026 #include "XrdProofdManager.h"
00027 #include "XrdProofdProtocol.h"
00028 #include "XrdProofdProofServMgr.h"
00029 #include "Xrd/XrdScheduler.hh"
00030 #include "XrdOuc/XrdOucStream.hh"
00031 #include "XrdSys/XrdSysPriv.hh"
00032 #include "XrdSys/XrdSysLogger.hh"
00033
00034
00035 #include "XrdProofdTrace.h"
00036
00037
00038 XrdROOT::XrdROOT(const char *dir, const char *tag, const char *bindir,
00039 const char *incdir, const char *libdir, const char *datadir)
00040 {
00041
00042 XPDLOC(SMGR, "XrdROOT")
00043
00044 fStatus = -1;
00045 fSrvProtVers = -1;
00046
00047
00048 if (!dir || strlen(dir) <= 0)
00049 return;
00050 if (tag && strlen(tag) > 0) {
00051 fExport = tag;
00052 fExport += " "; fExport += dir;
00053 } else
00054 fExport += dir;
00055
00056 if (CheckDir(dir) != 0) return;
00057 fDir = dir;
00058
00059
00060 fIncDir = incdir;
00061 if (!incdir || strlen(incdir) <= 0) {
00062 fIncDir = fDir;
00063 fIncDir += "/include";
00064 }
00065 if (CheckDir(fIncDir.c_str()) != 0) return;
00066
00067
00068 fRelease = "";
00069 fSvnRevision = -1;
00070 fVersionCode = -1;
00071 fVrsMajor = -1;
00072 fVrsMinor = -1;
00073 fVrsPatch = -1;
00074 if (ParseROOTVersionInfo() == -1) {
00075 TRACE(XERR, "unable to extract ROOT version information from path "<<fIncDir);
00076 return;
00077 }
00078
00079
00080 fTag = (!tag || strlen(tag) <= 0) ? fRelease : tag;
00081
00082
00083 fLibDir = libdir;
00084 if (!libdir || strlen(libdir) <= 0) {
00085 fLibDir = fDir;
00086 fLibDir += "/lib";
00087 }
00088 if (CheckDir(fLibDir.c_str()) != 0) return;
00089
00090
00091 fBinDir = bindir;
00092 if (!bindir || strlen(bindir) <= 0) {
00093 fBinDir = fDir;
00094 fBinDir += "/bin";
00095 }
00096 if (CheckDir(fBinDir.c_str()) != 0) return;
00097
00098
00099 fDataDir = datadir;
00100 if (!datadir || strlen(datadir) <= 0) {
00101 fDataDir = fDir;
00102 }
00103 if (CheckDir(fDataDir.c_str()) != 0) return;
00104
00105
00106 fPrgmSrv = fBinDir;
00107 fPrgmSrv += "/proofserv";
00108
00109
00110 fExport = fTag;
00111 fExport += " "; fExport += fRelease;
00112 fExport += " "; fExport += dir;
00113
00114
00115 fStatus = 0;
00116 }
00117
00118
00119 int XrdROOT::CheckDir(const char *dir)
00120 {
00121
00122
00123 XPDLOC(SMGR, "CheckDir")
00124
00125 if (dir && strlen(dir) > 0) {
00126
00127 struct stat st;
00128 if (stat(dir, &st) == -1) {
00129 TRACE(XERR, "unable to stat path "<<dir);
00130 return -1;
00131 }
00132
00133 if (!S_ISDIR(st.st_mode)) {
00134 TRACE(XERR, "path "<<dir<<" is not a directory");
00135 return -1;
00136 }
00137
00138 return 0;
00139 }
00140 TRACE(XERR, "path is undefined");
00141 return -1;
00142 }
00143
00144
00145 void XrdROOT::SetValid(kXR_int16 vers)
00146 {
00147
00148
00149 fStatus = 1;
00150
00151 if (vers > 0) {
00152
00153 if (fSrvProtVers > 0) {
00154 XrdOucString vs(" ");
00155 vs += fSrvProtVers;
00156 fExport.replace(vs,XrdOucString(""));
00157 }
00158 fSrvProtVers = vers;
00159
00160
00161 fExport += " ";
00162 fExport += (int)fSrvProtVers;
00163 }
00164 }
00165
00166
00167 int XrdROOT::ParseROOTVersionInfo()
00168 {
00169
00170 XPDLOC(SMGR, "ParseROOTVersionInfo")
00171
00172 int rc = -1;
00173
00174 XrdOucString versfile = fIncDir;
00175 versfile += "/RVersion.h";
00176
00177
00178 FILE *fv = fopen(versfile.c_str(), "r");
00179 if (!fv) {
00180 TRACE(XERR, "unable to open "<<versfile);
00181 return rc;
00182 }
00183
00184
00185 fRelease = "";
00186 fSvnRevision = -1;
00187 fVersionCode = -1;
00188 fVrsMajor = -1;
00189 fVrsMinor = -1;
00190 fVrsPatch = -1;
00191
00192
00193 char *pv = 0;
00194 XrdOucString tkn;
00195 char line[1024];
00196 while (fgets(line, sizeof(line), fv)) {
00197 if (fRelease.length() <= 0 && (pv = (char *) strstr(line, "ROOT_RELEASE"))) {
00198 if (line[strlen(line)-1] == '\n')
00199 line[strlen(line)-1] = 0;
00200 pv += strlen("ROOT_RELEASE") + 1;
00201 fRelease = pv;
00202 fRelease.replace("\"","");
00203 } else if ((pv = (char *) strstr(line, "ROOT_SVN_REVISION"))) {
00204 if (line[strlen(line)-1] == '\n')
00205 line[strlen(line)-1] = 0;
00206 sscanf(pv, "ROOT_SVN_REVISION %d", &fSvnRevision);
00207 } else if ((pv = (char *) strstr(line, "ROOT_VERSION_CODE"))) {
00208 if (line[strlen(line)-1] == '\n')
00209 line[strlen(line)-1] = 0;
00210 sscanf(pv, "ROOT_VERSION_CODE %d", &fVersionCode);
00211 }
00212 }
00213
00214
00215 fclose(fv);
00216
00217
00218 if (fVersionCode < 0) {
00219 TRACE(XERR, "incomplete info found in "<<versfile<<": version code missing or bad: "<<fVersionCode);
00220 return rc;
00221 }
00222
00223
00224 if (fRelease.length() <= 0 ||
00225 XrdROOT::ParseReleaseString(fRelease.c_str(), fVrsMajor, fVrsMinor, fVrsPatch) < 0) {
00226 TRACE(XERR, "incomplete info found in "<<versfile<<": release tag missing or bad: "<<fRelease);
00227 return rc;
00228 }
00229
00230
00231 return 0;
00232 }
00233
00234
00235 int XrdROOT::GetVersionCode(const char *release)
00236 {
00237
00238
00239
00240
00241 int maj, min, patch;
00242 if (XrdROOT::ParseReleaseString(release, maj, min, patch) < 0) return -1;
00243 return XrdROOT::GetVersionCode(maj, min, patch);
00244 }
00245
00246
00247 int XrdROOT::GetVersionCode(int maj, int min, int patch)
00248 {
00249
00250
00251
00252 return ((maj << 16) + (min << 8) + patch);
00253 }
00254
00255
00256 int XrdROOT::ParseReleaseString(const char *release,
00257 int &maj, int &min, int &patch)
00258 {
00259
00260
00261
00262
00263 if (!release || strlen(release) <= 0) return -1;
00264
00265 XrdOucString rel(release, 7);
00266 rel.replace(".", " ");
00267 rel.replace("/", " ");
00268
00269 sscanf(rel.c_str(), "%d %d %d", &maj, &min, &patch);
00270 return 0;
00271 }
00272
00273
00274
00275
00276
00277 XrdROOTMgr::XrdROOTMgr(XrdProofdManager *mgr,
00278 XrdProtocol_Config *pi, XrdSysError *e)
00279 : XrdProofdConfig(pi->ConfigFN, e)
00280 {
00281
00282 fMgr = mgr;
00283 fLogger = pi->eDest->logger();
00284 fROOT.clear();
00285
00286
00287 RegisterDirectives();
00288 }
00289
00290
00291 void XrdROOTMgr::SetLogDir(const char *dir)
00292 {
00293
00294 XPDLOC(SMGR, "ROOTMgr::SetLogDir")
00295
00296 if (fMgr && dir && strlen(dir)) {
00297
00298 XPDFORM(fLogDir, "%s/rootsysvalidation", dir);
00299 XrdProofUI ui;
00300 XrdProofdAux::GetUserInfo(fMgr->EffectiveUser(), ui);
00301 if (XrdProofdAux::AssertDir(fLogDir.c_str(), ui, fMgr->ChangeOwn()) != 0) {
00302 XPDERR("unable to assert the rootsys log validation path: "<<fLogDir);
00303 fLogDir = "";
00304 } else {
00305 TRACE(ALL,"rootsys log validation path: "<<fLogDir);
00306 }
00307 }
00308 }
00309
00310
00311 int XrdROOTMgr::Config(bool rcf)
00312 {
00313
00314
00315 XPDLOC(SMGR, "ROOTMgr::Config")
00316
00317
00318 if (XrdProofdConfig::Config(rcf) != 0) {
00319 TRACE(XERR, "problems parsing file ");
00320 return -1;
00321 }
00322
00323 XrdOucString msg;
00324 msg = (rcf) ? "re-configuring" : "configuring";
00325 TRACE(ALL, msg);
00326
00327
00328 if (rcf) {
00329
00330 std::list<XrdROOT *>::iterator tri;
00331 if (fROOT.size() > 0) {
00332 for (tri = fROOT.begin(); tri != fROOT.end();) {
00333 if ((*tri)->IsParked()) {
00334 delete (*tri);
00335 tri = fROOT.erase(tri);
00336 } else {
00337 tri++;
00338 }
00339 }
00340 }
00341 } else {
00342
00343 if (fROOT.size() <= 0) {
00344 #ifdef R__HAVE_CONFIG
00345 XrdOucString dir(ROOTPREFIX), bd(ROOTBINDIR), ld(ROOTLIBDIR),
00346 id(ROOTINCDIR), dd(ROOTDATADIR);
00347 #else
00348 XrdOucString dir(getenv("ROOTSYS")), bd, ld, id, dd;
00349 #endif
00350
00351 if (dir.length() > 0) {
00352 XrdROOT *rootc = new XrdROOT(dir.c_str(), "",
00353 bd.c_str(), id.c_str(), ld.c_str(), dd.c_str());
00354 if (Validate(rootc, fMgr->Sched()) == 0) {
00355 XPDFORM(msg, "ROOT dist: '%s' validated", rootc->Export());
00356 fROOT.push_back(rootc);
00357 TRACE(ALL, msg);
00358 XrdOucString mnp;
00359 XPDFORM(mnp, "ROOT version details: svn: %d, code: %d, {mnp} = {%d,%d,%d}",
00360 rootc->SvnRevision(), rootc->VersionCode(), rootc->VrsMajor(),
00361 rootc->VrsMinor(), rootc->VrsPatch());
00362 TRACE(ALL, mnp);
00363 } else {
00364 XPDFORM(msg, "ROOT dist: '%s' could not be validated", rootc->Export());
00365 TRACE(XERR, msg);
00366 }
00367 }
00368 if (fROOT.size() <= 0) {
00369 TRACE(XERR, "no ROOT dir defined; ROOTSYS location missing - unloading");
00370 return -1;
00371 }
00372 }
00373 }
00374
00375
00376 return 0;
00377 }
00378
00379
00380 void XrdROOTMgr::RegisterDirectives()
00381 {
00382
00383
00384 Register("rootsys", new XrdProofdDirective("rootsys", this, &DoDirectiveClass));
00385 }
00386
00387
00388 int XrdROOTMgr::DoDirective(XrdProofdDirective *d,
00389 char *val, XrdOucStream *cfg, bool rcf)
00390 {
00391
00392 XPDLOC(SMGR, "ROOTMgr::DoDirective")
00393
00394 if (!d)
00395
00396 return -1;
00397
00398 if (d->fName == "rootsys") {
00399 return DoDirectiveRootSys(val, cfg, rcf);
00400 }
00401 TRACE(XERR, "unknown directive: "<<d->fName);
00402 return -1;
00403 }
00404
00405
00406 int XrdROOTMgr::DoDirectiveRootSys(char *val, XrdOucStream *cfg, bool)
00407 {
00408
00409 XPDLOC(SMGR, "ROOTMgr::DoDirectiveRootSys")
00410
00411 if (!val || !cfg)
00412
00413 return -1;
00414
00415
00416 XrdOucString dir = val;
00417 val = cfg->GetWord();
00418 XrdOucString tag = val;
00419 bool ok = 1;
00420 if (tag == "if") {
00421 tag = "";
00422
00423 cfg->RetToken();
00424 ok = (XrdProofdAux::CheckIf(cfg, fMgr->Host()) > 0) ? 1 : 0;
00425 }
00426 if (ok) {
00427
00428 XrdOucString a[4];
00429 int i = 0;
00430 if (tag.length() > 0) {
00431 while ((val = cfg->GetWord())) { a[i++] = val; }
00432 }
00433 XrdROOT *rootc = new XrdROOT(dir.c_str(), tag.c_str(), a[0].c_str(),
00434 a[1].c_str(), a[2].c_str(), a[3].c_str());
00435
00436 std::list<XrdROOT *>::iterator ori;
00437 for (ori = fROOT.begin(); ori != fROOT.end(); ori++) {
00438 if ((*ori)->Match(rootc->Dir(), rootc->Tag())) {
00439 if ((*ori)->IsParked()) {
00440 (*ori)->SetValid();
00441 SafeDelete(rootc);
00442 break;
00443 }
00444 }
00445 }
00446
00447 if (rootc) {
00448 if (Validate(rootc, fMgr->Sched()) == 0) {
00449 TRACE(REQ, "validation OK for: "<<rootc->Export());
00450 XrdOucString mnp;
00451 XPDFORM(mnp, "version details: svn: %d, code: %d, {mnp} = {%d,%d,%d}",
00452 rootc->SvnRevision(), rootc->VersionCode(), rootc->VrsMajor(),
00453 rootc->VrsMinor(), rootc->VrsPatch());
00454 TRACE(REQ, mnp);
00455
00456 fROOT.push_back(rootc);
00457 } else {
00458 TRACE(XERR, "could not validate "<<rootc->Export());
00459 SafeDelete(rootc);
00460 }
00461 }
00462 }
00463 return 0;
00464 }
00465
00466
00467 int XrdROOTMgr::Validate(XrdROOT *r, XrdScheduler *sched)
00468 {
00469
00470
00471
00472 XPDLOC(SMGR, "ROOTMgr::Validate")
00473
00474 TRACE(REQ, "forking test and protocol retrieval");
00475
00476 if (r->IsInvalid()) {
00477
00478 TRACE(XERR, "invalid instance - cannot be validated");
00479 return -1;
00480 }
00481
00482
00483 if (!r->PrgmSrv() || strlen(r->PrgmSrv()) <= 0) {
00484 TRACE(XERR, "path to PROOF server application undefined - exit");
00485 return -1;
00486 }
00487
00488
00489 if (!sched) {
00490 TRACE(XERR, "scheduler undefined - exit");
00491 return -1;
00492 }
00493
00494
00495 int fp[2];
00496 if (pipe(fp) != 0) {
00497 TRACE(XERR, "PROOT protocol number communication");
00498 return -1;
00499 }
00500
00501
00502 bool debug = 0;
00503 if (TRACING(DBG)) debug = 1;
00504
00505
00506 XrdOucString logfile, rootrc;
00507 if (fLogDir.length() > 0) {
00508 XrdOucString tag(r->Tag());
00509 tag.replace("/","-");
00510 XPDFORM(logfile, "%s/root.%s.log", fLogDir.c_str(), tag.c_str());
00511 if (debug) {
00512 XPDFORM(rootrc, "%s/root.%s.rootrc", fLogDir.c_str(), tag.c_str());
00513 }
00514 }
00515
00516
00517 TRACE(FORK,"XrdROOTMgr::Validate: forking external proofsrv");
00518 int pid = -1;
00519 if (!(pid = sched->Fork("proofsrv"))) {
00520
00521 if (logfile.length() > 0 && fLogger) {
00522
00523 fLogger->Bind(logfile.c_str());
00524
00525 char *ev = new char[strlen("ROOTPROOFLOGFILE=") + logfile.length() + 2];
00526 sprintf(ev, "ROOTPROOFLOGFILE=%s", logfile.c_str());
00527 putenv(ev);
00528 if (debug && rootrc.length() > 0) {
00529
00530 FILE *frc = fopen(rootrc.c_str(),"w");
00531 if (frc) {
00532 fprintf(frc, "Proof.DebugLevel: 1\n");
00533 fclose(frc);
00534 }
00535
00536 ev = new char[strlen("ROOTRCFILE=") + rootrc.length() + 2];
00537 sprintf(ev, "ROOTRCFILE=%s", rootrc.c_str());
00538 putenv(ev);
00539 }
00540 }
00541
00542 char *argvv[6] = {0};
00543
00544
00545 argvv[0] = (char *)r->PrgmSrv();
00546 argvv[1] = (char *)"proofserv";
00547 argvv[2] = (char *)"xpd";
00548 argvv[3] = (char *)"test";
00549 if (debug) {
00550 argvv[4] = (char *)"1";
00551 argvv[5] = 0;
00552 } else {
00553 argvv[4] = 0;
00554 argvv[5] = 0;
00555 }
00556
00557
00558 if (XrdProofdProofServMgr::SetProofServEnv(fMgr, r) != 0) {
00559 TRACE(XERR, " SetProofServEnv did not return OK - EXIT");
00560 exit(1);
00561 }
00562
00563
00564 char *ev = new char[25];
00565 sprintf(ev, "ROOTOPENSOCK=%d", fp[1]);
00566 putenv(ev);
00567
00568
00569
00570 if (!getuid()) {
00571 XrdProofUI ui;
00572 if (XrdProofdAux::GetUserInfo(geteuid(), ui) != 0) {
00573 TRACE(XERR, "could not get info for user-id: "<<geteuid());
00574 exit(1);
00575 }
00576
00577
00578 if (XrdSysPriv::ChangePerm((uid_t)ui.fUid, (gid_t)ui.fGid) != 0) {
00579 TRACE(XERR, "can't acquire "<<ui.fUser <<" identity");
00580 exit(1);
00581 }
00582
00583 }
00584
00585
00586 execv(r->PrgmSrv(), argvv);
00587
00588
00589 TRACE(XERR, "returned from execv: bad, bad sign !!!");
00590 exit(1);
00591 }
00592
00593
00594 if (pid < 0) {
00595 TRACE(XERR, "forking failed - exit");
00596 close(fp[0]);
00597 close(fp[1]);
00598 return -1;
00599 }
00600
00601
00602 TRACE(FORK, "test server launched: wait for protocol ");
00603
00604
00605 int proto = -1;
00606 struct pollfd fds_r;
00607 fds_r.fd = fp[0];
00608 fds_r.events = POLLIN;
00609 int pollRet = 0;
00610
00611
00612 int ntry = 30;
00613 while (pollRet == 0 && ntry--) {
00614 while ((pollRet = poll(&fds_r, 1, 2000)) < 0 &&
00615 (errno == EINTR)) { }
00616 if (pollRet == 0)
00617 TRACE(DBG, "receiving PROOF server protocol number: waiting 2 s ...");
00618 }
00619 if (pollRet > 0) {
00620 if (read(fp[0], &proto, sizeof(proto)) != sizeof(proto)) {
00621 TRACE(XERR, "problems receiving PROOF server protocol number");
00622 return -1;
00623 }
00624 } else {
00625 if (pollRet == 0) {
00626 TRACE(XERR, "timed-out receiving PROOF server protocol number");
00627 } else {
00628 TRACE(XERR, "failed to receive PROOF server protocol number");
00629 }
00630 return -1;
00631 }
00632
00633
00634 r->SetValid((kXR_int16) ntohl(proto));
00635
00636
00637 if (logfile.length() > 0 && !debug) {
00638 if (unlink(logfile.c_str()) != 0) {
00639 TRACE(XERR, "problems unlinking "<<logfile<<"; errno: "<<errno);
00640 }
00641 }
00642 if (debug && rootrc.length() > 0 && unlink(rootrc.c_str()) != 0) {
00643 TRACE(XERR, "problems unlinking "<<rootrc<<"; errno: "<<errno);
00644 }
00645
00646
00647 close(fp[0]);
00648 close(fp[1]);
00649
00650
00651 return 0;
00652 }
00653
00654
00655 XrdOucString XrdROOTMgr::ExportVersions(XrdROOT *def)
00656 {
00657
00658
00659
00660 XrdOucString out;
00661
00662
00663 std::list<XrdROOT *>::iterator ip;
00664 for (ip = fROOT.begin(); ip != fROOT.end(); ++ip) {
00665
00666 if (def == *ip)
00667 out += " * ";
00668 else
00669 out += " ";
00670 out += (*ip)->Export();
00671 out += "\n";
00672 }
00673
00674
00675 return out;
00676 }
00677
00678
00679 XrdROOT *XrdROOTMgr::GetVersion(const char *tag)
00680 {
00681
00682
00683
00684 XrdROOT *r = 0;
00685
00686 std::list<XrdROOT *>::iterator ip;
00687 for (ip = fROOT.begin(); ip != fROOT.end(); ++ip) {
00688 if ((*ip)->MatchTag(tag)) {
00689 r = (*ip);
00690 break;
00691 }
00692 }
00693
00694
00695 return r;
00696 }