00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 const char *XrdCmsConfigCVSID = "$Id: XrdCmsConfig.cc 35287 2010-09-14 21:19:35Z ganis $";
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <unistd.h>
00028 #include <ctype.h>
00029 #include <fcntl.h>
00030 #include <strings.h>
00031 #include <stdio.h>
00032 #include <sys/param.h>
00033 #include <sys/resource.h>
00034 #include <sys/stat.h>
00035 #include <sys/types.h>
00036 #include <sys/un.h>
00037 #include <dirent.h>
00038
00039 #include "../XrdVersion.hh"
00040 #include "Xrd/XrdScheduler.hh"
00041
00042 #include "XrdCms/XrdCmsAdmin.hh"
00043 #include "XrdCms/XrdCmsCache.hh"
00044 #include "XrdCms/XrdCmsCluster.hh"
00045 #include "XrdCms/XrdCmsConfig.hh"
00046 #include "XrdCms/XrdCmsManager.hh"
00047 #include "XrdCms/XrdCmsManTree.hh"
00048 #include "XrdCms/XrdCmsMeter.hh"
00049 #include "XrdCms/XrdCmsNode.hh"
00050 #include "XrdCms/XrdCmsPrepare.hh"
00051 #include "XrdCms/XrdCmsPrepArgs.hh"
00052 #include "XrdCms/XrdCmsProtocol.hh"
00053 #include "XrdCms/XrdCmsRRQ.hh"
00054 #include "XrdCms/XrdCmsSecurity.hh"
00055 #include "XrdCms/XrdCmsState.hh"
00056 #include "XrdCms/XrdCmsSupervisor.hh"
00057 #include "XrdCms/XrdCmsTrace.hh"
00058 #include "XrdCms/XrdCmsXmi.hh"
00059 #include "XrdCms/XrdCmsXmiReq.hh"
00060
00061 #include "XrdNet/XrdNetDNS.hh"
00062 #include "XrdNet/XrdNetOpts.hh"
00063 #include "XrdNet/XrdNetSecurity.hh"
00064 #include "XrdNet/XrdNetSocket.hh"
00065
00066 #include "XrdOss/XrdOss.hh"
00067
00068 #include "XrdOuc/XrdOuca2x.hh"
00069 #include "XrdOuc/XrdOucEnv.hh"
00070 #include "XrdSys/XrdSysError.hh"
00071 #include "XrdOuc/XrdOucExport.hh"
00072 #include "XrdOuc/XrdOucName2Name.hh"
00073 #include "XrdOuc/XrdOucProg.hh"
00074 #include "XrdOuc/XrdOucUtils.hh"
00075
00076 #include "XrdSys/XrdSysHeaders.hh"
00077 #include "XrdSys/XrdSysPlatform.hh"
00078 #include "XrdSys/XrdSysPlugin.hh"
00079 #include "XrdSys/XrdSysPthread.hh"
00080 #include "XrdOuc/XrdOucStream.hh"
00081 #include "XrdSys/XrdSysTimer.hh"
00082
00083 using namespace XrdCms;
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 XrdCmsAdmin XrdCms::Admin;
00108
00109 XrdCmsConfig XrdCms::Config;
00110
00111 XrdSysError XrdCms::Say(0, "");
00112
00113 XrdOucTrace XrdCms::Trace(&Say);
00114
00115 XrdScheduler *XrdCms::Sched = 0;
00116
00117 XrdCmsXmi *XrdCms::Xmi_Chmod = 0;
00118 XrdCmsXmi *XrdCms::Xmi_Load = 0;
00119 XrdCmsXmi *XrdCms::Xmi_Mkdir = 0;
00120 XrdCmsXmi *XrdCms::Xmi_Mkpath = 0;
00121 XrdCmsXmi *XrdCms::Xmi_Prep = 0;
00122 XrdCmsXmi *XrdCms::Xmi_Rename = 0;
00123 XrdCmsXmi *XrdCms::Xmi_Remdir = 0;
00124 XrdCmsXmi *XrdCms::Xmi_Remove = 0;
00125 XrdCmsXmi *XrdCms::Xmi_Select = 0;
00126 XrdCmsXmi *XrdCms::Xmi_Space = 0;
00127 XrdCmsXmi *XrdCms::Xmi_Stat = 0;
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 XrdSecProtocol *(*XrdXrootdSecGetProtocol)
00139 (const char *hostname,
00140 const struct sockaddr &netaddr,
00141 const XrdSecParameters &parms,
00142 XrdOucErrInfo *einfo)=0;
00143
00144
00145
00146
00147
00148 void *XrdCmsStartMonPerf(void *carg) { return Cluster.MonPerf(); }
00149
00150 void *XrdCmsStartMonRefs(void *carg) { return Cluster.MonRefs(); }
00151
00152 void *XrdCmsStartMonStat(void *carg) { return CmsState.Monitor(); }
00153
00154 void *XrdCmsStartAdmin(void *carg)
00155 {return XrdCms::Admin.Start((XrdNetSocket *)carg);
00156 }
00157
00158 void *XrdCmsStartAnote(void *carg)
00159 {XrdCmsAdmin Anote;
00160 return Anote.Notes((XrdNetSocket *)carg);
00161 }
00162
00163 void *XrdCmsStartPreparing(void *carg)
00164 {XrdCmsPrepArgs::Process();
00165 return (void *)0;
00166 }
00167
00168 void *XrdCmsStartSupervising(void *carg)
00169 {XrdCmsSupervisor::Start();
00170 return (void *)0;
00171 }
00172
00173
00174
00175
00176
00177 #define TS_String(x,m) if (!strcmp(x,var)) {free(m); m = strdup(val); return 0;}
00178
00179 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(eDest, CFile);
00180
00181 #define TS_Set(x,v) if (!strcmp(x,var)) {v=1; CFile.Echo(); return 0;}
00182
00183 #define TS_unSet(x,v) if (!strcmp(x,var)) {v=0; CFile.Echo(); return 0;}
00184
00185
00186
00187
00188
00189 int XrdCmsConfig::Configure1(int argc, char **argv, char *cfn)
00190 {
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 int NoGo = 0, immed = 0;
00201 char c, buff[512];
00202 extern int opterr, optopt;
00203
00204
00205
00206 if (geteuid() == 0)
00207 {Say.Emsg("Config", "Security reasons prohibit cmsd running as "
00208 "superuser; cmsd is terminating.");
00209 _exit(8);
00210 }
00211
00212
00213
00214 opterr = 0; optind = 1;
00215 if (argc > 1 && '-' == *argv[1])
00216 while ((c=getopt(argc,argv,"imsw")) && ((unsigned char)c != 0xff))
00217 { switch(c)
00218 {
00219 case 'i': immed = 1;
00220 break;
00221 case 'm': isManager = 1;
00222 break;
00223 case 's': isServer = 1;
00224 break;
00225 case 'w': immed = -1;
00226 break;
00227 default: buff[0] = '-'; buff[1] = optopt; buff[2] = '\0';
00228 Say.Say("Config warning: unrecognized option,",buff,", ignored.");
00229 }
00230 }
00231
00232
00233
00234 inArgv = argv; inArgc = argc;
00235 if ((!(ConfigFN = cfn) && !(ConfigFN = getenv("XrdCmsCONFIGFN")))
00236 || !*ConfigFN)
00237 {Say.Emsg("Config", "Required config file not specified.");
00238 Usage(1);
00239 }
00240
00241
00242
00243 sprintf(buff, "%s@%s", XrdOucUtils::InstName(myInsName), myName);
00244 myInstance = strdup(buff);
00245
00246
00247
00248 Say.Say("++++++ ", myInstance, " phase 1 initialization started.");
00249
00250
00251
00252
00253 if (!(isManager || isServer))
00254 if (!(NoGo |= ConfigProc(1)) && !(isManager || isServer))
00255 {Say.Say("Config warning: role not specified; manager role assumed.");
00256 isManager = -1;
00257 }
00258
00259
00260
00261 if (!NoGo) NoGo |= ConfigProc();
00262
00263
00264
00265 if (immed) doWait = (immed > 0 ? 0 : 1);
00266
00267
00268
00269 if (isManager < 0) isManager = 1;
00270 if (isPeer < 0) isPeer = 1;
00271 if (isProxy < 0) isProxy = 1;
00272 if (isServer < 0) isServer = 1;
00273
00274
00275
00276 if (!myRole)
00277 { if (isPeer) myRole = strdup("peer");
00278 else if (isProxy) myRole = strdup("proxy");
00279 else if (isManager && isServer) myRole = strdup("Supervisor");
00280 else if (isManager) myRole = strdup("manager");
00281 else myRole = strdup("server");
00282 }
00283
00284
00285
00286
00287 if (!NoGo)
00288 {if ((isManager && !isServer) || isPeer)
00289 {if (PortTCP <= 0)
00290 {Say.Emsg("Config","port for this", myRole, "not specified.");
00291 NoGo = 1;
00292 }
00293 }
00294 else PortTCP = 0;
00295 }
00296
00297
00298
00299 sprintf(buff, " phase 1 %s initialization %s.", myRole,
00300 (NoGo ? "failed" : "completed"));
00301 Say.Say("------ ", myInstance, buff);
00302 return NoGo;
00303 }
00304
00305
00306
00307
00308
00309 int XrdCmsConfig::Configure2()
00310 {
00311
00312
00313
00314
00315
00316
00317
00318 EPNAME("Configure2");
00319 int Who, NoGo = 0;
00320 char *p, buff[512];
00321
00322
00323
00324 sprintf(buff, " phase 2 %s initialization started.", myRole);
00325 Say.Say("++++++ ", myInstance, buff);
00326
00327
00328
00329
00330 if (isManager) NoGo = !Cache.Init(cachelife, LUPDelay);
00331
00332
00333
00334 if (!strncmp(AdminPath, "/tmp/", 5))
00335 Say.Say("Config warning: adminpath resides in /tmp and may be unstable!");
00336
00337
00338
00339
00340 p = XrdOucUtils::genPath(AdminPath,XrdOucUtils::InstName(myInsName,0),".olb");
00341 free(AdminPath);
00342 AdminPath = p;
00343
00344
00345
00346 if (!NoGo) NoGo = !(AdminSock = XrdNetSocket::Create(&Say, AdminPath,
00347 (isManager|isPeer ? "olbd.nimda":"olbd.admin"),AdminMode));
00348
00349
00350
00351 if (!NoGo && !(mySID = setupSid()))
00352 {Say.Emsg("cmsd", "Unable to generate system ID; too many managers.");
00353 NoGo = 1;
00354 } else {DEBUG("Global System Identification: " <<mySID);}
00355
00356
00357
00358 if ((LocalRoot || RemotRoot) && ConfigN2N()) NoGo = 1;
00359
00360
00361
00362 if (!NoGo) NoGo = ConfigOSS();
00363
00364
00365
00366 if (!NoGo && isManager) NoGo = setupManager();
00367 if (!NoGo && (isServer || ManList)) NoGo = setupServer();
00368
00369
00370
00371
00372
00373
00374
00375 if (isPeer && isSolo)
00376 {SUPCount = SUPLevel = 0; Meter.setVirtual(XrdCmsMeter::peerFS);}
00377 else if (isManager)
00378 {Meter.setVirtual(XrdCmsMeter::manFS);
00379 if (isMeta) {SUPCount = 1; SUPLevel = 0;}
00380 if (!ManList) CmsState.Update(XrdCmsState::FrontEnd, 1);
00381 }
00382 if (isManager) Who = (isServer ? -1 : 1);
00383 else Who = 0;
00384 CmsState.Set(SUPCount, Who, AdminPath);
00385
00386
00387
00388 if (!NoGo) NoGo |= PidFile();
00389
00390
00391
00392 if (!NoGo && XmiPath) NoGo = setupXmi();
00393
00394
00395
00396 Sched->setParms(8, 200, 40, -1, 1);
00397
00398
00399
00400 sprintf(buff, " phase 2 %s initialization %s.", myRole,
00401 (NoGo ? "failed" : "completed"));
00402 Say.Say("------ ", myInstance, buff);
00403
00404
00405
00406 if (!NoGo) Sched->Schedule((XrdJob *)this);
00407
00408
00409
00410 return NoGo;
00411 }
00412
00413
00414
00415
00416
00417 int XrdCmsConfig::ConfigXeq(char *var, XrdOucStream &CFile, XrdSysError *eDest)
00418 {
00419 int dynamic;
00420
00421
00422
00423 if (eDest) dynamic = 1;
00424 else {dynamic = 0; eDest = &Say;}
00425
00426
00427
00428 TS_Xeq("delay", xdelay);
00429 TS_Xeq("fxhold", xfxhld);
00430 TS_Xeq("ping", xping);
00431 TS_Xeq("sched", xsched);
00432 TS_Xeq("space", xspace);
00433 TS_Xeq("trace", xtrace);
00434
00435 if (!dynamic)
00436 {
00437 TS_Xeq("adminpath", xapath);
00438 TS_Xeq("allow", xallow);
00439 TS_Xeq("defaults", xdefs);
00440 TS_Xeq("export", xexpo);
00441 TS_Xeq("fsxeq", xfsxq);
00442 TS_Xeq("localroot", xlclrt);
00443 TS_Xeq("manager", xmang);
00444 TS_Xeq("namelib", xnml);
00445 TS_Xeq("osslib", xolib);
00446 TS_Xeq("perf", xperf);
00447 TS_Xeq("pidpath", xpidf);
00448 TS_Xeq("prep", xprep);
00449 TS_Xeq("prepmsg", xprepm);
00450 TS_Xeq("remoteroot", xrmtrt);
00451 TS_Xeq("role", xrole);
00452 TS_Xeq("seclib", xsecl);
00453 TS_Set("wait", doWait);
00454 TS_unSet("nowait", doWait);
00455 TS_Xeq("xmilib", xxmi);
00456 }
00457
00458
00459
00460 if (!strcmp(var, "conwait")
00461 || !strcmp(var, "request")) return 0;
00462
00463
00464
00465 eDest->Say("Config warning: ignoring unknown directive '", var, "'.");
00466 CFile.Echo();
00467 return 0;
00468 }
00469
00470
00471
00472
00473
00474 void XrdCmsConfig::DoIt()
00475 {
00476 XrdSysSemaphore SyncUp(0);
00477 XrdCmsProtocol *pP;
00478 XrdOucTList *tp;
00479 pthread_t tid;
00480 time_t eTime = time(0);
00481 int wTime;
00482
00483
00484
00485
00486
00487 if (isManager && !isServer && !ManList) doWait = 0;
00488
00489
00490
00491 if (AnoteSock)
00492 if (XrdSysThread::Run(&tid, XrdCmsStartAnote, (void *)AnoteSock,
00493 0, "Notification handler"))
00494 Say.Emsg("cmsd", errno, "start notification handler");
00495
00496
00497
00498 if (XrdSysThread::Run(&tid,XrdCmsStartPreparing,
00499 (void *)0, 0, "Prep handler"))
00500 Say.Emsg("cmsd", errno, "start prep handler");
00501
00502
00503
00504 if (XrdCmsSupervisor::superOK)
00505 {if (XrdSysThread::Run(&tid,XrdCmsStartSupervising,
00506 (void *)0, 0, "supervisor"))
00507 {Say.Emsg("cmsd", errno, "start", myRole);
00508 return;
00509 }
00510 }
00511
00512
00513
00514
00515 if (AdminSock)
00516 {XrdCmsAdmin::setSync(&SyncUp);
00517 if (XrdSysThread::Run(&tid, XrdCmsStartAdmin, (void *)AdminSock,
00518 0, "Admin traffic"))
00519 Say.Emsg("cmsd", errno, "start admin handler");
00520 SyncUp.Wait();
00521 }
00522
00523
00524
00525
00526
00527
00528 if (isManager || isServer || isPeer)
00529 {tp = ManList;
00530 while(tp)
00531 {if (strcmp(tp->text, myName) || tp->val != PortTCP)
00532 {pP = XrdCmsProtocol::Alloc(myRole, tp->text, tp->val);
00533 Sched->Schedule((XrdJob *)pP);
00534 } else {
00535 char buff[512];
00536 sprintf(buff, "%s:%d", tp->text, tp->val);
00537 Say.Emsg("Config", "Circular connection to", buff, "ignored.");
00538 }
00539 tp = tp->next;
00540 }
00541 }
00542
00543
00544
00545 if (XrdSysThread::Run(&tid, XrdCmsStartMonStat, (void *)0,
00546 0, "State monitor"))
00547 {Say.Emsg("Config", errno, "create state monitor thread");
00548 return;
00549 }
00550
00551
00552
00553 if ((isManager || isPeer) && SRVDelay)
00554 {wTime = SRVDelay - static_cast<int>((time(0) - eTime));
00555 if (wTime > 0) XrdSysTimer::Wait(wTime*1000);
00556 }
00557
00558
00559
00560 if (!SUPCount) CmsState.Update(XrdCmsState::Counts, 0, 0);
00561 CmsState.Enable();
00562 Say.Emsg("Config", myRole, "service enabled.");
00563 }
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574 int XrdCmsConfig::GenLocalPath(const char *oldp, char *newp)
00575 {
00576 if (lcl_N2N) return -(lcl_N2N->lfn2pfn(oldp, newp, XrdCmsMAX_PATH_LEN));
00577 if (strlen(oldp) >= XrdCmsMAX_PATH_LEN) return -ENAMETOOLONG;
00578 strcpy(newp, oldp);
00579 return 0;
00580 }
00581
00582
00583
00584
00585
00586
00587
00588
00589 void XrdCmsConfig::ConfigDefaults(void)
00590 {
00591
00592
00593
00594 myName = (char *)"localhost";
00595 myDomain = 0;
00596 LUPDelay = 5;
00597 LUPHold = 178;
00598 DRPDelay = 10*60;
00599 PSDelay = 0;
00600 RWDelay = 2;
00601 SRVDelay = 90;
00602 SUPCount = 1;
00603 SUPLevel = 80;
00604 SUPDelay = 15;
00605 SUSDelay = 30;
00606 MaxLoad = 0x7fffffff;
00607 MsgTTL = 7;
00608 PortTCP = 0;
00609 P_cpu = 0;
00610 P_fuzz = 20;
00611 P_io = 0;
00612 P_load = 0;
00613 P_mem = 0;
00614 P_pag = 0;
00615 AskPerf = 10;
00616 AskPing = 60;
00617 MaxDelay = -1;
00618 LogPerf = 10;
00619 DiskMin = 10240;
00620 DiskHWM = 11264;
00621 DiskMinP = 2;
00622 DiskHWMP = 5;
00623 DiskAsk = 12;
00624 DiskWT = 0;
00625 DiskSS = 0;
00626 DiskOK = 0;
00627 myPaths = (char *)"";
00628 ConfigFN = 0;
00629 sched_RR = 0;
00630 isManager= 0;
00631 isMeta = 0;
00632 isPeer = 0;
00633 isSolo = 0;
00634 isProxy = 0;
00635 isServer = 0;
00636 N2N_Lib = 0;
00637 N2N_Parms= 0;
00638 lcl_N2N = 0;
00639 xeq_N2N = 0;
00640 LocalRoot= 0;
00641 RemotRoot= 0;
00642 myInsName= 0;
00643 myRole =0;
00644 ManList =0;
00645 NanList =0;
00646 mySID = 0;
00647 perfint = 3*60;
00648 perfpgm = 0;
00649 AdminPath= strdup("/tmp/");
00650 AdminMode= 0700;
00651 AdminSock= 0;
00652 AnoteSock= 0;
00653 RedirSock= 0;
00654 pidPath = strdup("/tmp");
00655 Police = 0;
00656 cachelife= 8*60*60;
00657 pendplife= 60*60*24*7;
00658 DiskLinger=0;
00659 ProgCH = 0;
00660 ProgMD = 0;
00661 ProgMV = 0;
00662 ProgRD = 0;
00663 ProgRM = 0;
00664 doWait = 1;
00665 RefReset = 60*60;
00666 RefTurn = 3*STMax*(DiskLinger+1);
00667 XmiPath = 0;
00668 XmiParms = 0;
00669 DirFlags = 0;
00670 SecLib = 0;
00671 ossLib = 0;
00672 ossFS = 0;
00673 }
00674
00675
00676
00677
00678
00679 int XrdCmsConfig::ConfigN2N()
00680 {
00681 XrdSysPlugin *myLib;
00682 XrdOucName2Name *(*ep)(XrdOucgetName2NameArgs);
00683
00684
00685
00686
00687 if (!N2N_Lib)
00688 {if (LocalRoot || (RemotRoot && XmiPath))
00689 {xeq_N2N = XrdOucgetName2Name(&Say,ConfigFN,"",LocalRoot,RemotRoot);
00690 if (LocalRoot) lcl_N2N = xeq_N2N;
00691 }
00692 PrepQ.setParms(xeq_N2N);
00693 return 0;
00694 }
00695
00696
00697
00698
00699 if (!(myLib = new XrdSysPlugin(&Say, N2N_Lib))) return 1;
00700
00701
00702
00703 ep = (XrdOucName2Name *(*)(XrdOucgetName2NameArgs))(myLib->getPlugin("XrdOucgetName2Name"));
00704 if (!ep) return 1;
00705
00706
00707
00708 lcl_N2N = ep(&Say,ConfigFN,(N2N_Parms ? N2N_Parms : ""),LocalRoot,RemotRoot);
00709 PrepQ.setParms(lcl_N2N);
00710 return lcl_N2N == 0;
00711 }
00712
00713
00714
00715
00716
00717 int XrdCmsConfig::ConfigOSS()
00718 {
00719 extern XrdOss *XrdOssGetSS(XrdSysLogger *, const char *, const char *);
00720
00721
00722
00723 XrdOucEnv::Export("XRDREDIRECT", "Q");
00724 XrdOucEnv::Export("XRDOSSTYPE", "cms");
00725 XrdOucEnv::Export("XRDOSSCSCAN", "off");
00726
00727
00728
00729 return !(ossFS=XrdOssGetSS(Say.logger(),ConfigFN,ossLib));
00730 }
00731
00732
00733
00734
00735
00736 int XrdCmsConfig::ConfigProc(int getrole)
00737 {
00738 char *var;
00739 int cfgFD, retc, NoGo = 0;
00740 XrdOucEnv myEnv;
00741 XrdOucStream CFile(&Say, getenv("XRDINSTANCE"), &myEnv, "=====> ");
00742
00743
00744
00745 if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
00746 {Say.Emsg("Config", errno, "open config file", ConfigFN);
00747 return 1;
00748 }
00749 CFile.Attach(cfgFD);
00750
00751
00752
00753 if (getrole) CFile.SetEroute(0);
00754
00755
00756
00757 while((var = CFile.GetMyFirstWord()))
00758 if (getrole)
00759 {if (!strcmp("all.role", var) || !strcmp("olb.role", var))
00760 if (xrole(&Say, CFile))
00761 {CFile.SetEroute(&Say); CFile.Echo(); NoGo = 1;
00762 CFile.SetEroute(0);
00763 }
00764 }
00765 else if (!strncmp(var, "cms.", 4)
00766 || !strncmp(var, "olb.", 4)
00767 || !strcmp(var, "ofs.osslib")
00768 || !strcmp(var, "oss.defaults")
00769 || !strcmp(var, "oss.localroot")
00770 || !strcmp(var, "oss.remoteroot")
00771 || !strcmp(var, "oss.namelib")
00772 || !strcmp(var, "all.adminpath")
00773 || !strcmp(var, "all.export")
00774 || !strcmp(var, "all.manager")
00775 || !strcmp(var, "all.pidpath")
00776 || !strcmp(var, "all.role")
00777 || !strcmp(var, "all.seclib"))
00778 {if (ConfigXeq(var+4, CFile, 0)) {CFile.Echo(); NoGo = 1;}}
00779 else if (!strcmp(var, "oss.stagecmd")) DiskSS = 1;
00780
00781
00782
00783 if ((retc = CFile.LastError()))
00784 NoGo = Say.Emsg("Config", retc, "read config file", ConfigFN);
00785 CFile.Close();
00786
00787
00788
00789 if (!getrole && ManList) NoGo |= MergeP();
00790
00791
00792
00793 return NoGo;
00794 }
00795
00796
00797
00798
00799
00800 int XrdCmsConfig::isExec(XrdSysError *eDest, const char *ptype, char *prog)
00801 {
00802 char buff[512], pp, *mp = prog;
00803
00804
00805
00806 while(*mp && *mp != ' ') mp++;
00807 pp = *mp; *mp ='\0';
00808
00809
00810
00811 if (access(prog, X_OK))
00812 {sprintf(buff, "find %s execuatble", ptype);
00813 eDest->Emsg("Config", errno, buff, prog);
00814 *mp = pp;
00815 return 0;
00816 }
00817
00818
00819
00820 *mp = pp;
00821 return 1;
00822 }
00823
00824
00825
00826
00827
00828 int XrdCmsConfig::MergeP()
00829 {
00830 XrdOucPList *plp = PexpList.First();
00831 XrdCmsPList *pp;
00832 XrdCmsPInfo opinfo, npinfo;
00833 const char *ptype;
00834 char *pbP;
00835 unsigned long long Opts;
00836 int pbLen = 0, NoGo = 0;
00837 npinfo.rovec = 1;
00838
00839
00840
00841 while(plp)
00842 {Opts = plp->Flag();
00843 if (!(Opts & XRDEXP_LOCAL))
00844 {npinfo.rwvec = (Opts & (XRDEXP_GLBLRO | XRDEXP_NOTRW) ? 0 : 1);
00845 npinfo.ssvec = (Opts & XRDEXP_STAGE ? 1 : 0);
00846 if (!PathList.Add(plp->Path(), &npinfo))
00847 Say.Emsg("Config","Ignoring duplicate export path",plp->Path());
00848 else if (npinfo.ssvec) DiskSS = 1;
00849 }
00850 plp = plp->Next();
00851 }
00852
00853
00854
00855 if (!NoGo)
00856 {const char *Who = (isManager ? (isServer ? "manager:" : "meta-manager:")
00857 : "redirector:");
00858 Say.Say("The following paths are available to the ", Who);
00859 if (!(pp = PathList.First())) Say.Say("r /");
00860 else while(pp)
00861 {ptype = pp->PType();
00862 Say.Say(ptype, (strlen(ptype) > 1 ? " " : " "), pp->Path());
00863 pbLen += strlen(pp->Path())+8; pp = pp->Next();
00864 }
00865 Say.Say(" ");
00866 }
00867
00868
00869
00870
00871 if (pbLen != 0 && (pp = PathList.First()))
00872 {pbP = myPaths = (char *)malloc(pbLen);
00873 while(pp)
00874 {pbP += sprintf(pbP, "\n%s %s", pp->PType(), pp->Path());
00875 pp = pp->Next();
00876 }
00877 myPaths++;
00878 }
00879
00880
00881
00882 if (DiskSS) CmsState.Update(XrdCmsState::Counts, 0, 1);
00883 return NoGo;
00884 }
00885
00886
00887
00888
00889
00890 int XrdCmsConfig::PidFile()
00891 {
00892 int rc, xfd;
00893 const char *clID;
00894 char buff[1024];
00895 char pidFN[1200], *ppath=XrdOucUtils::genPath(pidPath,
00896 XrdOucUtils::InstName(myInsName,0));
00897 const char *xop = 0;
00898
00899 if ((rc = XrdOucUtils::makePath(ppath, XrdOucUtils::pathMode)))
00900 {Say.Emsg("Config", rc, "create pid file path", ppath);
00901 free(ppath);
00902 return 1;
00903 }
00904
00905 if ((clID = index(mySID, ' '))) clID++;
00906 else clID = mySID;
00907
00908 if (isManager && isServer)
00909 snprintf(pidFN, sizeof(pidFN), "%s/cmsd.super.pid", ppath);
00910 else if (isServer)
00911 snprintf(pidFN, sizeof(pidFN), "%s/cmsd.pid", ppath);
00912 else snprintf(pidFN, sizeof(pidFN), "%s/cmsd.mangr.pid", ppath);
00913
00914 if ((xfd = open(pidFN, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0) xop = "open";
00915 else {if ((write(xfd,buff,snprintf(buff,sizeof(buff),"%d",
00916 static_cast<int>(getpid()))) < 0)
00917 || (LocalRoot &&
00918 (write(xfd,(void *)"\n&pfx=",6) < 0 ||
00919 write(xfd,(void *)LocalRoot,strlen(LocalRoot)) < 0
00920 ) )
00921 || (AdminPath &&
00922 (write(xfd,(void *)"\n&ap=", 5) < 0 ||
00923 write(xfd,(void *)AdminPath,strlen(AdminPath)) < 0
00924 ) )
00925 || write(xfd,(void *)"\n&cn=", 5) < 0
00926 || write(xfd,(void *)clID, strlen(clID)) < 0
00927 ) xop = "write";
00928 close(xfd);
00929 }
00930
00931 if (xop) Say.Emsg("Config", errno, xop, pidFN);
00932 else XrdOucEnv::Export("XRDCMSPIDFN", pidFN);
00933
00934 free(ppath);
00935 return xop != 0;
00936 }
00937
00938
00939
00940
00941
00942 int XrdCmsConfig::setupManager()
00943 {
00944 pthread_t tid;
00945 int rc;
00946
00947
00948
00949 if (isServer && !XrdCmsSupervisor::Init(AdminPath, AdminMode)) return 1;
00950
00951
00952
00953 sched_RR = (100 == P_fuzz) || !AskPerf
00954 || !(P_cpu || P_io || P_load || P_mem || P_pag);
00955 if (sched_RR)
00956 Say.Say("Config round robin scheduling in effect.");
00957
00958
00959
00960 if ((rc = XrdSysThread::Run(&tid, XrdCmsStartMonPerf, (void *)0,
00961 0, "Performance monitor")))
00962 {Say.Emsg("Config", rc, "create perf monitor thread");
00963 return 1;
00964 }
00965
00966
00967
00968 RefTurn = 3*STMax*(DiskLinger+1);
00969 if (RefReset)
00970 {if ((rc = XrdSysThread::Run(&tid, XrdCmsStartMonRefs, (void *)0,
00971 0, "Refcount monitor")))
00972 {Say.Emsg("Config", rc, "create refcount monitor thread");
00973 return 1;
00974 }
00975 }
00976
00977
00978
00979 RRQ.Init(LUPHold, LUPDelay);
00980
00981
00982
00983 if (SecLib && !XrdCmsSecurity::Configure(SecLib, ConfigFN)) return 1;
00984
00985
00986
00987 return 0;
00988 }
00989
00990
00991
00992
00993
00994 int XrdCmsConfig::setupServer()
00995 {
00996 XrdOucTList *tp;
00997 int n = 0;
00998
00999
01000
01001 if (!ManList)
01002 {Say.Emsg("Config", "Manager node not specified for", myRole, "role");
01003 return 1;
01004 }
01005
01006
01007
01008 tp = ManList;
01009 while(tp) {n++; tp = tp->next;}
01010 if (n > XrdCmsManager::MTMax)
01011 {Say.Emsg("Config", "Too many managers have been specified"); return 1;}
01012 ManTree.setMaxCon(n);
01013
01014
01015
01016 if (MaxDelay < 0) MaxDelay = AskPerf*AskPing+30;
01017 if (DiskWT < 0) DiskWT = AskPerf*AskPing+30;
01018
01019
01020
01021 if (!(AnoteSock = XrdNetSocket::Create(&Say, AdminPath,
01022 (isManager|isPeer ? "olbd.seton":"olbd.notes"),
01023 AdminMode, XRDNET_UDPSOCKET))) return 1;
01024
01025
01026
01027
01028 if (isManager || isPeer || isProxy) return 0;
01029 DiskOK = 1; SUPCount = 0; SUPLevel = 0;
01030
01031
01032
01033 if (DiskSS) PrepQ.Reset(myInsName, AdminPath, AdminMode);
01034
01035
01036
01037 Meter.Init();
01038 if (perfpgm && Meter.Monitor(perfpgm, perfint))
01039 Say.Say("Config warning: load based scheduling disabled.");
01040
01041
01042
01043 return 0;
01044 }
01045
01046
01047
01048
01049
01050 char *XrdCmsConfig::setupSid()
01051 {
01052 XrdOucTList *tp = (NanList ? NanList : ManList);
01053 char sfx;
01054
01055
01056
01057 if (isManager && isServer) sfx = 'u';
01058 else sfx = (isManager ? 'm' : 's');
01059
01060
01061
01062 return XrdCmsSecurity::setSystemID(tp, myInsName, myName, sfx);
01063 }
01064
01065
01066
01067
01068
01069 int XrdCmsConfig::setupXmi()
01070 {
01071 EPNAME("setupXmi");
01072 static XrdCmsXmiEnv XmiEnv;
01073 XrdSysPlugin *xmiLib;
01074 XrdCmsXmi *(*ep)(int, char **, XrdCmsXmiEnv *);
01075 unsigned int isNormal, isDirect;
01076 XrdCmsXmi *XMI, *myXMI;
01077 const char *theMode;
01078 int i;
01079
01080 struct {unsigned int theMask;
01081 XrdCmsXmi **theAddr;
01082 const char *theName;} XmiTab[] =
01083 {{XMI_CHMOD, &Xmi_Chmod, "chmod"},
01084 {XMI_LOAD, &Xmi_Load, "load"},
01085 {XMI_MKDIR, &Xmi_Mkdir, "mkdir"},
01086 {XMI_MKPATH, &Xmi_Mkpath, "mkpath"},
01087 {XMI_PREP, &Xmi_Prep, "prep"},
01088 {XMI_RENAME, &Xmi_Rename, "rename"},
01089 {XMI_REMDIR, &Xmi_Remdir, "remdir"},
01090 {XMI_REMOVE, &Xmi_Remove, "remove"},
01091 {XMI_SELECT, &Xmi_Select, "select"},
01092 {XMI_SPACE, &Xmi_Space, "space"},
01093 {XMI_STAT, &Xmi_Stat, "stat"}};
01094 int numintab = sizeof(XmiTab)/sizeof(XmiTab[0]);
01095
01096
01097
01098 XmiEnv.Role = myRole;
01099 XmiEnv.ConfigFN = ConfigFN;
01100 XmiEnv.Parms = XmiParms;
01101 XmiEnv.eDest = &Say;
01102 XmiEnv.iNet = NetTCP;
01103 XmiEnv.Sched = Sched;
01104 XmiEnv.Trace = &Trace;
01105 XmiEnv.Name2Name= xeq_N2N;
01106
01107
01108
01109
01110 if (!(xmiLib = new XrdSysPlugin(&Say, XmiPath))) return 1;
01111
01112
01113
01114 ep = (XrdCmsXmi *(*)(int, char **, XrdCmsXmiEnv *))(xmiLib->getPlugin("XrdCmsgetXmi"));
01115 if (!ep) return 1;
01116
01117
01118
01119 if (!(XMI = ep(inArgc, inArgv, &XmiEnv))) return 1;
01120 DEBUG("xmi library loaded; path=" <<XmiPath);
01121
01122
01123
01124 XMI->XeqMode(isNormal, isDirect);
01125
01126
01127
01128 if ((isDirect & XMI_ALL) == XMI_ALL) myXMI = 0;
01129 else myXMI = (XrdCmsXmi *)new XrdCmsXmiReq(XMI);
01130
01131
01132
01133 for (i = 0; i < numintab; i++)
01134 {if (!(isNormal & XmiTab[i].theMask))
01135 if (isDirect & XmiTab[i].theMask)
01136 {*XmiTab[i].theAddr = XMI; theMode = "direct";}
01137 else {*XmiTab[i].theAddr = myXMI; theMode = "queued";}
01138 else theMode = "normal";
01139 DEBUG(XmiTab[i].theName <<" is " <<theMode);
01140 }
01141 return 0;
01142 }
01143
01144
01145
01146
01147
01148 void XrdCmsConfig::Usage(int rc)
01149 {
01150 cerr <<"\nUsage: cmsd [xrdopts] [-i] [-m] [-s] -c <cfile>" <<endl;
01151 exit(rc);
01152 }
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171 int XrdCmsConfig::xallow(XrdSysError *eDest, XrdOucStream &CFile)
01172 {
01173 char *val;
01174 int ishost;
01175
01176 if (!isManager) return CFile.noEcho();
01177
01178 if (!(val = CFile.GetWord()))
01179 {eDest->Emsg("Config", "allow type not specified"); return 1;}
01180
01181 if (!strcmp(val, "host")) ishost = 1;
01182 else if (!strcmp(val, "netgroup")) ishost = 0;
01183 else {eDest->Emsg("Config", "invalid allow type -", val);
01184 return 1;
01185 }
01186
01187 if (!(val = CFile.GetWord()))
01188 {eDest->Emsg("Config", "allow target name not specified"); return 1;}
01189
01190 if (!Police) Police = new XrdNetSecurity();
01191 if (ishost) Police->AddHost(val);
01192 else Police->AddNetGroup(val);
01193
01194 return 0;
01195 }
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212 int XrdCmsConfig::xapath(XrdSysError *eDest, XrdOucStream &CFile)
01213 {
01214 char *pval, *val;
01215 mode_t mode = S_IRWXU;
01216 struct sockaddr_un USock;
01217
01218
01219
01220 pval = CFile.GetWord();
01221 if (!pval || !pval[0])
01222 {eDest->Emsg("Config", "adminpath not specified"); return 1;}
01223
01224
01225
01226 if (*pval != '/')
01227 {eDest->Emsg("Config", "adminpath not absolute"); return 1;}
01228
01229
01230
01231 if (strlen(pval) > sizeof(USock.sun_path) - 11)
01232 {eDest->Emsg("Config", "admin path", pval, "is too long");
01233 return 1;
01234 }
01235 pval = strdup(pval);
01236
01237
01238
01239 if ((val = CFile.GetWord()) && val[0])
01240 {if (!strcmp("group", val)) mode |= S_IRWXG;
01241 else {eDest->Emsg("Config", "invalid admin path modifier -", val);
01242 free(pval); return 1;
01243 }
01244 }
01245
01246
01247
01248 if (AdminPath) free(AdminPath);
01249 AdminPath = pval;
01250 AdminMode = mode;
01251 return 0;
01252 }
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288 int XrdCmsConfig::xdelay(XrdSysError *eDest, XrdOucStream &CFile)
01289 { char *val;
01290 const char *etxt = "invalid delay option";
01291 int i, ppp, minV = 1, ispercent = 0;
01292 static struct delayopts {const char *opname; int *oploc; int istime;}
01293 dyopts[] =
01294 {
01295 {"discard", &MsgTTL, 0},
01296 {"drop", &DRPDelay, 1},
01297 {"full", &DiskWT, -1},
01298 {"hold", &LUPHold, 0},
01299 {"lookup", &LUPDelay, 1},
01300 {"overload", &MaxDelay,-1},
01301 {"peer", &PSDelay, 1},
01302 {"rw", &RWDelay, 0},
01303 {"servers", &SUPCount, 0},
01304 {"service", &SUPDelay, 1},
01305 {"startup", &SRVDelay, 1},
01306 {"suspend", &SUSDelay, 1}
01307 };
01308 int numopts = sizeof(dyopts)/sizeof(struct delayopts);
01309
01310 if (!isManager && !isPeer) return CFile.noEcho();
01311
01312 if (!(val = CFile.GetWord()))
01313 {eDest->Emsg("Config", "delay arguments not specified"); return 1;}
01314
01315 while (val)
01316 {for (i = 0; i < numopts; i++)
01317 if (!strcmp(val, dyopts[i].opname))
01318 {if (!(val = CFile.GetWord()))
01319 {eDest->Emsg("Config", "delay ", dyopts[i].opname,
01320 " argument not specified.");
01321 return 1;
01322 }
01323 if (dyopts[i].istime < 0 && !strcmp(val, "*")) ppp = -1;
01324 else if (dyopts[i].istime)
01325 {if (XrdOuca2x::a2tm(*eDest,etxt,val,&ppp,1))
01326 return 1;
01327 } else
01328 if (*dyopts[i].opname == 'r')
01329 {if (XrdOuca2x::a2i( *eDest,etxt,val,&ppp,0,2))
01330 return 1;
01331 } else {
01332 if (*dyopts[i].opname == 's')
01333 {ppp = strlen(val); SUPLevel = 0; minV = 0;
01334 if (val[ppp-1] == '%')
01335 {ispercent = 1; val[ppp-1] = '\0';}
01336 } else minV = 1;
01337 if (XrdOuca2x::a2i( *eDest,etxt,val,&ppp,minV))
01338 return 1;
01339 }
01340 if (!ispercent) *dyopts[i].oploc = ppp;
01341 else {ispercent = 0; SUPCount = 1; SUPLevel = ppp;}
01342 break;
01343 }
01344 if (i >= numopts)
01345 eDest->Say("Config warning: ignoring invalid delay option '",val,"'.");
01346 val = CFile.GetWord();
01347 }
01348 return 0;
01349 }
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365 int XrdCmsConfig::xdefs(XrdSysError *eDest, XrdOucStream &CFile)
01366 {
01367 if (!isServer) return CFile.noEcho();
01368 DirFlags = XrdOucExport::ParseDefs(CFile, *eDest, DirFlags);
01369 return 0;
01370 }
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386 int XrdCmsConfig::xexpo(XrdSysError *eDest, XrdOucStream &CFile)
01387 {
01388 XrdOucPList *plp, *olp;
01389 unsigned long long Opts = DirFlags & XRDEXP_SETTINGS;
01390
01391
01392
01393 if (!(plp = XrdOucExport::ParsePath(CFile, *eDest, Opts))) return 1;
01394
01395
01396
01397
01398 if (!(olp = PexpList.Match(plp->Path()))) PexpList.Insert(plp);
01399 else {Opts = plp->Flag() >> XRDEXP_MASKSHIFT;
01400 Opts = olp->Flag() & ~Opts;
01401 olp->Set(Opts | plp->Flag());
01402 delete plp;
01403 }
01404 return 0;
01405 }
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424 int XrdCmsConfig::xfsxq(XrdSysError *eDest, XrdOucStream &CFile)
01425 {
01426 struct xeqopts {const char *opname; int doset; XrdOucProg **pgm;} xqopts[] =
01427 {
01428 {"chmod", 0, &ProgCH},
01429 {"mkdir", 0, &ProgMD},
01430 {"mkpath", 0, &ProgMP},
01431 {"mv", 0, &ProgMV},
01432 {"rm", 0, &ProgRM},
01433 {"rmdir", 0, &ProgRD},
01434 {"trunc", 0, &ProgTR}
01435 };
01436 int i, xtval = 0, numopts = sizeof(xqopts)/sizeof(struct xeqopts);
01437 char *val;
01438
01439
01440
01441 if (!isServer) return CFile.noEcho();
01442
01443
01444
01445 val = CFile.GetWord();
01446 while (val && *val != '/')
01447 {for (i = 0; i < numopts; i++)
01448 if (!strcmp(val, xqopts[i].opname))
01449 {xqopts[i].doset = 1;
01450 xtval = 1;
01451 break;
01452 }
01453 if (i >= numopts)
01454 eDest->Say("Config warning: ignoring invalid fsxeq type option '",val,"'.");
01455 val = CFile.GetWord();
01456 }
01457
01458
01459
01460 if (!xtval)
01461 {eDest->Emsg("Config", "fsxeq type option not specified"); return 1;}
01462
01463
01464
01465 if (!val)
01466 {eDest->Emsg("Config", "fsxeq program not specified"); return 1;}
01467
01468
01469
01470 CFile.RetToken();
01471
01472
01473
01474 for (i = 0; i < numopts; i++)
01475 if (xqopts[i].doset)
01476 {if (!*xqopts[i].pgm) *(xqopts[i].pgm) = new XrdOucProg(0);
01477 if ((*(xqopts[i].pgm))->Setup(val, eDest)) return 1;
01478 }
01479
01480
01481
01482 return 0;
01483 }
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500 int XrdCmsConfig::xfxhld(XrdSysError *eDest, XrdOucStream &CFile)
01501 {
01502 char *val;
01503 int ct;
01504
01505 if (!isManager) return CFile.noEcho();
01506
01507 if (!(val = CFile.GetWord()))
01508 {eDest->Emsg("Config", "fxhold value not specified."); return 1;}
01509
01510 if (XrdOuca2x::a2tm(*eDest, "fxhold value", val, &ct, 60)) return 1;
01511
01512 cachelife = ct;
01513 return 0;
01514 }
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531 int XrdCmsConfig::xlclrt(XrdSysError *eDest, XrdOucStream &CFile)
01532 {
01533 char *val;
01534 int i;
01535
01536
01537
01538 if (!isServer) return CFile.noEcho();
01539
01540
01541
01542 val = CFile.GetWord();
01543 if (!val || !val[0])
01544 {eDest->Emsg("Config", "localroot path not specified"); return 1;}
01545 if (*val != '/')
01546 {eDest->Emsg("Config", "localroot path not absolute"); return 1;}
01547
01548
01549
01550 i = strlen(val)-1;
01551 while (i && val[i] == '/') val[i--] = '\0';
01552
01553
01554
01555 if (i)
01556 {if (LocalRoot) free(LocalRoot);
01557 LocalRoot = strdup(val);
01558 }
01559 return 0;
01560 }
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593 int XrdCmsConfig::xmang(XrdSysError *eDest, XrdOucStream &CFile)
01594 {
01595 class StorageHelper
01596 {public:
01597 StorageHelper(char **v1, char **v2) : val1(v1), val2(v2) {}
01598 ~StorageHelper() {if (*val1) free(*val1);
01599 if (*val2) free(*val2);
01600 }
01601 char **val1, **val2;
01602 };
01603
01604 static const int sockALen = sizeof(struct sockaddr);
01605 struct sockaddr InetAddr[8];
01606 XrdOucTList *tp = 0, *tpp = 0, *tpnew;
01607 char *val, *bval = 0, *mval = 0;
01608 StorageHelper SHelp(&bval, &mval);
01609 int j, i, multi = 0, port = 0, xMeta = 0, xPeer = 0, xProxy = 0, Prt = 1;
01610
01611
01612
01613 if ((val = CFile.GetWord()))
01614 {if ((xMeta = !strcmp("meta", val))
01615 || (xPeer = !strcmp("peer", val))
01616 || (xProxy = !strcmp("proxy", val)))
01617 {if (xMeta && (isServer || isPeer || isProxy)) return CFile.noEcho();
01618 if (xProxy || (xPeer && !isPeer)) return CFile.noEcho();
01619 val = CFile.GetWord();
01620 } else if (isPeer) return CFile.noEcho();
01621 }
01622
01623
01624
01625 if (val)
01626 if (!strcmp("any", val) || !strcmp("all", val)) val = CFile.GetWord();
01627
01628
01629
01630 if (!val)
01631 {eDest->Emsg("Config","manager host name not specified"); return 1;}
01632 mval = strdup(val);
01633
01634
01635
01636 if ((val = index(mval, ':'))) {*val = '\0'; val++;}
01637 else val = CFile.GetWord();
01638
01639 if (val)
01640 {if (isdigit(*val))
01641 {if (XrdOuca2x::a2i(*eDest,"manager port",val,&port,1,65535))
01642 port = 0;
01643 }
01644 else if (!(port = XrdNetDNS::getPort(val, "tcp")))
01645 {eDest->Emsg("Config", "Unable to find tcp service '",val,"'.");
01646 port = 0;
01647 }
01648 }
01649 else if (!(port = PortTCP))
01650 eDest->Emsg("Config","manager port not specified for",mval);
01651
01652 if (!port) return 1;
01653
01654 if ((val = CFile.GetWord()))
01655 {if (strcmp(val, "if"))
01656 {eDest->Emsg("Config","expecting manager 'if' but",val,"found");
01657 return 1;
01658 }
01659 if ((i=XrdOucUtils::doIf(eDest,CFile,"manager directive",
01660 myName,myInsName,myProg))<=0) return i < 0;
01661 }
01662
01663 i = strlen(mval);
01664 if (mval[i-1] != '+')
01665 {i = 1;
01666 if (!XrdNetDNS::getHostAddr(mval, InetAddr))
01667 {eDest->Emsg("CFile","Manager host", mval, "not found");
01668 return 1;
01669 }
01670 free(mval); mval = XrdNetDNS::getHostName(InetAddr[0]);
01671 }
01672 else {bval = strdup(mval); mval[i-1] = '\0'; multi = 1;
01673 if (!(i = XrdNetDNS::getHostAddr(mval, InetAddr, 8)))
01674 {eDest->Emsg("CFile","Manager host", mval, "not found");
01675 return 1;
01676 }
01677 }
01678
01679
01680
01681 if (isManager && !isServer)
01682 {if ((xMeta && isMeta) || (!xMeta && !isMeta))
01683 for (j = 0; j < i; j++)
01684 if (!memcmp(&InetAddr[j], &myAddr, sockALen))
01685 {PortTCP = port; break;}
01686 if (isMeta) return (xMeta ? 0: CFile.noEcho());
01687 if (!xMeta) Prt = 0;
01688 }
01689
01690
01691
01692 do {if (multi)
01693 {free(mval);
01694 char mvBuff[1024];
01695 if (Prt) sprintf(mvBuff, "%s -> all.manager ", bval);
01696 mval = XrdNetDNS::getHostName(InetAddr[i-1]);
01697 if (Prt) eDest->Say("Config ", mvBuff, mval);
01698 }
01699 tp = (Prt ? ManList : NanList); tpp = 0; j = 1;
01700 while(tp)
01701 if ((j = strcmp(tp->text, mval)) < 0 || tp->val != port)
01702 {tpp = tp; tp = tp->next;}
01703 else {if (Prt && !j)
01704 eDest->Say("Config warning: duplicate manager ",mval);
01705 break;
01706 }
01707 if (j) {tpnew = new XrdOucTList(mval, port, tp);
01708 if (tpp) tpp->next = tpnew;
01709 else if (Prt) ManList = tpnew;
01710 else NanList = tpnew;
01711 }
01712 } while(--i);
01713
01714 return 0;
01715 }
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731 int XrdCmsConfig::xnml(XrdSysError *eDest, XrdOucStream &CFile)
01732 {
01733 char *val, parms[1024];
01734
01735
01736
01737 if (!(val = CFile.GetWord()) || !val[0])
01738 {eDest->Emsg("Config", "namelib not specified"); return 1;}
01739
01740
01741
01742 if (N2N_Lib) free(N2N_Lib);
01743 N2N_Lib = strdup(val);
01744
01745
01746
01747 if (!CFile.GetRest(parms, sizeof(parms)))
01748 {eDest->Emsg("Config", "namelib parameters too long"); return 1;}
01749 if (N2N_Parms) free(N2N_Parms);
01750 N2N_Parms = (*parms ? strdup(parms) : 0);
01751 return 0;
01752 }
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767 int XrdCmsConfig::xolib(XrdSysError *eDest, XrdOucStream &CFile)
01768 {
01769 char *val, parms[1024];
01770
01771
01772
01773 if (!(val = CFile.GetWord()) || !val[0])
01774 {eDest->Emsg("Config", "osslib not specified"); return 1;}
01775 if (ossLib) free(ossLib);
01776 ossLib = strdup(val);
01777
01778
01779
01780 if (!CFile.GetRest(parms, sizeof(parms)))
01781 {eDest->Emsg("Config", "namelib parameters too long"); return 1;}
01782 if (ossParms) free(ossParms);
01783 ossParms = (*parms ? strdup(parms) : 0);
01784 return 0;
01785 }
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804 int XrdCmsConfig::xperf(XrdSysError *eDest, XrdOucStream &CFile)
01805 { int ival = 3*60;
01806 char *pgm=0, *val, rest[2048];
01807
01808 if (!isServer) return CFile.noEcho();
01809
01810 if (!(val = CFile.GetWord()))
01811 {eDest->Emsg("Config", "perf options not specified"); return 1;}
01812
01813 do { if (!strcmp("int", val))
01814 {if (!(val = CFile.GetWord()))
01815 {eDest->Emsg("Config", "perf int value not specified");
01816 return 1;
01817 }
01818 if (XrdOuca2x::a2tm(*eDest,"perf int",val,&ival,0)) return 1;
01819 }
01820 else if (!strcmp("pgm", val))
01821 {if (!CFile.GetRest(rest, sizeof(rest)))
01822 {eDest->Emsg("Config", "perf pgm parameters too long"); return 1;}
01823 if (!*rest)
01824 {eDest->Emsg("Config", "perf prog value not specified");
01825 return 1;
01826 }
01827 pgm = rest;
01828 break;
01829 }
01830 else eDest->Say("Config warning: ignoring invalid perf option '",val,"'.");
01831 } while((val = CFile.GetWord()));
01832
01833
01834
01835 if (perfpgm) {free(perfpgm); perfpgm = 0;}
01836 if (pgm) {if (!isExec(eDest, "perf", pgm)) return 1;
01837 else perfpgm = strdup(pgm);
01838 }
01839
01840
01841
01842 perfint = ival;
01843 return 0;
01844 }
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860 int XrdCmsConfig::xpidf(XrdSysError *eDest, XrdOucStream &CFile)
01861 {
01862 char *val;
01863
01864
01865
01866 val = CFile.GetWord();
01867 if (!val || !val[0])
01868 {eDest->Emsg("Config", "pidpath not specified"); return 1;}
01869
01870
01871
01872 if (pidPath) free(pidPath);
01873 pidPath = strdup(val);
01874 return 0;
01875 }
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898 int XrdCmsConfig::xping(XrdSysError *eDest, XrdOucStream &CFile)
01899 { int pnum = AskPerf, lnum = LogPerf, ping;
01900 char *val;
01901
01902 if (!(val = CFile.GetWord()))
01903 {eDest->Emsg("Config", "ping value not specified"); return 1;}
01904 if (XrdOuca2x::a2tm(*eDest, "ping interval",val,&ping,0)) return 1;
01905
01906
01907 while((val = CFile.GetWord()))
01908 { if (!strcmp("log", val))
01909 {if (!(val = CFile.GetWord()))
01910 {eDest->Emsg("Config", "ping log value not specified");
01911 return 1;
01912 }
01913 if (XrdOuca2x::a2i(*eDest,"ping log",val,&lnum,0)) return 1;
01914 }
01915 else if (!strcmp("usage", val))
01916 {if (!(val = CFile.GetWord()))
01917 {eDest->Emsg("Config", "ping usage value not specified");
01918 return 1;
01919 }
01920 if (XrdOuca2x::a2i(*eDest,"ping usage",val,&pnum,1)) return 1;
01921 }
01922 }
01923 AskPerf = pnum;
01924 AskPing = ping;
01925 LogPerf = lnum;
01926 return 0;
01927 }
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952 int XrdCmsConfig::xprep(XrdSysError *eDest, XrdOucStream &CFile)
01953 { int reset=0, scrub=0, echo = 0, doset = 0;
01954 char *prepif=0, *val, rest[2048];
01955
01956 if (!isServer) return CFile.noEcho();
01957
01958 if (!(val = CFile.GetWord())) {PrepQ.setParms(""); return 0;}
01959
01960 do { if (!strcmp("echo", val)) doset = echo = 1;
01961 else if (!strcmp("reset", val))
01962 {if (!(val = CFile.GetWord()))
01963 {eDest->Emsg("Config", "prep reset value not specified");
01964 return 1;
01965 }
01966 if (XrdOuca2x::a2i(*eDest,"prep reset int",val,&reset,1)) return 1;
01967 doset = 1;
01968 }
01969 else if (!strcmp("scrub", val))
01970 {if (!(val = CFile.GetWord()))
01971 {eDest->Emsg("Config", "prep scrub value not specified");
01972 return 1;
01973 }
01974 if (XrdOuca2x::a2tm(*eDest,"prep scrub",val,&scrub,0)) return 1;
01975 doset = 1;
01976 }
01977 else if (!strcmp("ifpgm", val))
01978 {if (!CFile.GetRest(rest, sizeof(rest)))
01979 {eDest->Emsg("Config", "prep ifpgm parameters too long"); return 1;}
01980 if (!*rest)
01981 {eDest->Emsg("Config", "prep ifpgm value not specified");
01982 return 1;
01983 }
01984 prepif = rest;
01985 break;
01986 }
01987 else eDest->Say("Config warning: ignoring invalid prep option '",val,"'.");
01988 } while((val = CFile.GetWord()));
01989
01990
01991
01992
01993
01994 if (scrub) pendplife = scrub;
01995 if (doset) PrepQ.setParms(reset, scrub, echo);
01996 if (prepif) {if (!isExec(eDest, "prep", prepif)) return 1;
01997 else return PrepQ.setParms(prepif);
01998 } else PrepQ.setParms("");
01999 return 0;
02000 }
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017 int XrdCmsConfig::xprepm(XrdSysError *eDest, XrdOucStream &CFile)
02018 {
02019 char *val, buff[2048];
02020 XrdOucEnv *myEnv = CFile.SetEnv(0);
02021
02022
02023
02024 if (!(val = CFile.GetWord()))
02025 {eDest->Emsg("Config", "no value for prepmsg directive");
02026 CFile.SetEnv(myEnv);
02027 return 1;
02028 }
02029
02030
02031
02032
02033 CFile.RetToken();
02034 if (!CFile.GetRest(buff, sizeof(buff)))
02035 {eDest->Emsg("Config", "prepmsg arguments too long");
02036 CFile.SetEnv(myEnv);
02037 return 1;
02038 }
02039
02040
02041
02042 CFile.SetEnv(myEnv);
02043 return PrepQ.setParms(0, buff);
02044 }
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061 int XrdCmsConfig::xrmtrt(XrdSysError *eDest, XrdOucStream &CFile)
02062 {
02063 char *val, *colon, *slash;
02064 int i;
02065
02066
02067
02068 if (isManager) return CFile.noEcho();
02069
02070
02071
02072 val = CFile.GetWord();
02073 if (!val || !val[0])
02074 {eDest->Emsg("Config", "remoteroot path not specified"); return 1;}
02075
02076
02077
02078 if (*val != '/')
02079 {colon = index(val, ':'); slash = index(val, '/');
02080 if ((colon+1) != slash)
02081 {eDest->Emsg("Config", "remoteroot path not absolute"); return 1;}
02082 }
02083
02084
02085
02086 i = strlen(val)-1;
02087 while (i && val[i] == '/') val[i--] = '\0';
02088
02089
02090
02091 if (i)
02092 {if (RemotRoot) free(RemotRoot);
02093 RemotRoot = strdup(val);
02094 }
02095 return 0;
02096 }
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147 int XrdCmsConfig::xrole(XrdSysError *eDest, XrdOucStream &CFile)
02148 {
02149 char *val, role[64];
02150 int rc, xMeta=0, xPeer=0, xProxy=0, xServ=0, xMan=0, xSolo=0, xSup=0;
02151
02152 *role = '\0';
02153 if (!(val = CFile.GetWord()))
02154 {eDest->Emsg("Config", "role not specified"); return 1;}
02155
02156
02157
02158 if (!strcmp("meta", val))
02159 {xMeta = -1; strcpy(role, val); val = CFile.GetWord();}
02160 else {if (!strcmp("peer", val))
02161 {xPeer = -1; strcpy(role, val);
02162 val = CFile.GetWord();
02163 }
02164 if (val && !strcmp("proxy", val))
02165 {xProxy = -1; if (xPeer) strcat(role, " "); strcat(role, val);
02166 val = CFile.GetWord();
02167 }
02168 }
02169
02170
02171
02172 if (val && strcmp("if", val))
02173 { if (!strcmp("manager", val)) {xMan = -1;}
02174 else if (!strcmp("server", val)) { xServ = -1;}
02175 else if (!strcmp("supervisor", val)) {xMan = -1; xServ = -1; xSup = -1;}
02176 else {eDest->Emsg("Config", "invalid role -", val); return 1;}
02177
02178 if (xMeta || xPeer || xProxy) strcat(role, " ");
02179 strcat(role, val);
02180 val = CFile.GetWord();
02181 }
02182
02183
02184
02185 if (((xPeer && xProxy) && !(xMan || xServ))
02186 || (xPeer && xServ)
02187 || (xPeer && xSup)
02188 || (xMeta &&!xMan))
02189 {eDest->Emsg("Config", "invalid role -", role); return 1;}
02190 if (!(xMan || xServ) && xProxy)
02191 {eDest->Emsg("Config", "pure proxy role is not supported"); return 1;}
02192
02193
02194
02195 if (!(xPeer || xProxy || xServ || xMan))
02196 {eDest->Emsg("Config", "role not specified"); return 1;}
02197
02198
02199
02200 if (xPeer) if (!xMan) {xSolo = 1; xServ = -1;}
02201
02202
02203
02204 if (val && !strcmp("if", val))
02205 if ((rc = XrdOucUtils::doIf(eDest,CFile,"role directive",
02206 myName,myInsName,myProg)) <= 0) return (rc < 0);
02207
02208 if (isServer > 0 || isManager > 0 || isProxy > 0 || isPeer > 0)
02209 eDest->Say("Config warning: role directive over-ridden by command line options.");
02210 else {isServer = xServ; isManager = xMan; isProxy = xProxy;
02211 isPeer = xPeer; isSolo = xSolo; isMeta = xMeta;
02212 if (myRole) free(myRole); myRole = strdup(role);
02213 }
02214 return 0;
02215 }
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239 int XrdCmsConfig::xsched(XrdSysError *eDest, XrdOucStream &CFile)
02240 {
02241 char *val;
02242 int i, ppp;
02243 static struct schedopts {const char *opname; int maxv; int *oploc;}
02244 scopts[] =
02245 {
02246 {"cpu", 100, &P_cpu},
02247 {"fuzz", 100, &P_fuzz},
02248 {"io", 100, &P_io},
02249 {"runq", 100, &P_load},
02250 {"mem", 100, &P_mem},
02251 {"pag", 100, &P_pag},
02252 {"space", 100, &P_dsk},
02253 {"maxload", 100, &MaxLoad},
02254 {"refreset", -1, &RefReset}
02255 };
02256 int numopts = sizeof(scopts)/sizeof(struct schedopts);
02257
02258 if (!(val = CFile.GetWord()))
02259 {eDest->Emsg("Config", "sched option not specified"); return 1;}
02260
02261 while (val)
02262 {for (i = 0; i < numopts; i++)
02263 if (!strcmp(val, scopts[i].opname))
02264 {if (!(val = CFile.GetWord()))
02265 {eDest->Emsg("Config", "sched ", scopts[i].opname,
02266 "argument not specified.");
02267 return 1;
02268 }
02269 if (scopts[i].maxv < 0)
02270 {if (XrdOuca2x::a2tm(*eDest,"sched value", val, &ppp, 0))
02271 return 1;
02272 }
02273 else if (XrdOuca2x::a2i(*eDest,"sched value", val, &ppp,
02274 0, scopts[i].maxv)) return 1;
02275 *scopts[i].oploc = ppp;
02276 break;
02277 }
02278 if (i >= numopts)
02279 eDest->Say("Config warning: ignoring invalid sched option '",val,"'.");
02280 val = CFile.GetWord();
02281 }
02282
02283 return 0;
02284 }
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301 int XrdCmsConfig::xsecl(XrdSysError *eDest, XrdOucStream &CFile)
02302 {
02303 char *val;
02304
02305
02306
02307 if (!isManager) return CFile.noEcho();
02308
02309
02310
02311 val = CFile.GetWord();
02312 if (!val || !val[0])
02313 {eDest->Emsg("Config", "seclib path not specified"); return 1;}
02314
02315
02316
02317 if (SecLib) free(SecLib);
02318 SecLib = strdup(val);
02319 return 0;
02320 }
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356 int XrdCmsConfig::xspace(XrdSysError *eDest, XrdOucStream &CFile)
02357 {
02358 char *val;
02359 int i, alinger = -1, arecalc = -1, minfP = 0, hwmP = 0;
02360 long long minf = -1, hwm = -1;
02361
02362 while((val = CFile.GetWord()))
02363 { if (!strcmp("linger", val))
02364 {if (!(val = CFile.GetWord()))
02365 {eDest->Emsg("Config", "linger value not specified"); return 1;}
02366 if (XrdOuca2x::a2i(*eDest,"linger",val,&alinger,0)) return 1;
02367 }
02368 else if (!strcmp("recalc", val))
02369 {if (!(val = CFile.GetWord()))
02370 {eDest->Emsg("Config", "recalc value not specified"); return 1;}
02371 if (XrdOuca2x::a2i(*eDest,"recalc",val,&arecalc,1)) return 1;
02372 }
02373 else if (!strcmp("min", val))
02374 {if (!(val = CFile.GetWord()) || !isdigit(*val))
02375 {eDest->Emsg("Config", "space min value not specified"); return 1;}
02376 break;
02377 }
02378 else if (isdigit(*val)) break;
02379 else {eDest->Emsg("Config", "invalid space parameters"); return 1;}
02380 }
02381
02382 if (val && isdigit(*val))
02383 {i = strlen(val);
02384 if (val[i-1] == '%')
02385 {val[i-1] = '\0';
02386 if (XrdOuca2x::a2i(*eDest,"space % minfree",val,&minfP,1,99)) return 1;
02387 val = CFile.GetWord(); minf = 10240LL<<20LL; hwm = 11264LL<<20LL;
02388 }
02389 }
02390
02391 if (val && isdigit(*val))
02392 {i = strlen(val);
02393 if (val[i-1] != '%')
02394 {if (XrdOuca2x::a2sz(*eDest,"space minfree",val,&minf,0)) return 1;
02395 val = CFile.GetWord();
02396 }
02397 }
02398
02399 if (val && isdigit(*val))
02400 {i = strlen(val);
02401 if (val[i-1] == '%')
02402 {val[i-1] = '\0';
02403 if (XrdOuca2x::a2i(*eDest,"space % high watermark",val,&hwmP,1,99)) return 1;
02404 val = CFile.GetWord();
02405 }
02406 }
02407
02408 if (val && isdigit(*val))
02409 {i = strlen(val);
02410 if (val[i-1] != '%')
02411 {if (XrdOuca2x::a2sz(*eDest,"space high watermark",val,&hwm,0)) return 1;
02412 val = CFile.GetWord();
02413 }
02414 }
02415
02416 if (val) {eDest->Emsg("Config", "invalid space parameter -", val); return 1;}
02417
02418 if (alinger < 0 && arecalc < 0 && minf < 0 && minfP)
02419 {eDest->Emsg("Config", "no space values specified"); return 1;}
02420
02421 if (alinger >= 0) DiskLinger = alinger;
02422 if (arecalc >= 0) DiskAsk = arecalc;
02423
02424 if (minfP)
02425 {if (hwmP < minfP) hwmP = minfP + 1;
02426 DiskMinP = minfP; DiskHWMP = hwmP;
02427 }
02428
02429 if (minf >= 0)
02430 {if (hwm < minf) hwm = minf+1073741824;
02431 minf = minf >> 20LL; hwm = hwm >> 20LL;
02432 if (minf >> 31LL) {minf = 0x7fefffff; hwm = 0x7fffffff;}
02433 else if (hwm >> 31LL) minf = 0x7fffffff;
02434 DiskMin = static_cast<int>(minf);
02435 DiskHWM = static_cast<int>(hwm);
02436 }
02437 return 0;
02438 }
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453 int XrdCmsConfig::xtrace(XrdSysError *eDest, XrdOucStream &CFile)
02454 {
02455 char *val;
02456 static struct traceopts {const char *opname; int opval;} tropts[] =
02457 {
02458 {"all", TRACE_ALL},
02459 {"debug", TRACE_Debug},
02460 {"defer", TRACE_Defer},
02461 {"files", TRACE_Files},
02462 {"forward", TRACE_Forward},
02463 {"redirect", TRACE_Redirect},
02464 {"stage", TRACE_Stage}
02465 };
02466 int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
02467
02468 if (!(val = CFile.GetWord()))
02469 {eDest->Emsg("config", "trace option not specified"); return 1;}
02470 while (val)
02471 {if (!strcmp(val, "off")) trval = 0;
02472 else {if ((neg = (val[0] == '-' && val[1]))) val++;
02473 for (i = 0; i < numopts; i++)
02474 {if (!strcmp(val, tropts[i].opname))
02475 {if (neg) trval &= ~tropts[i].opval;
02476 else trval |= tropts[i].opval;
02477 break;
02478 }
02479 }
02480 if (i >= numopts)
02481 eDest->Say("Config warning: ignoring invalid trace option '",val,"'.");
02482 }
02483 val = CFile.GetWord();
02484 }
02485
02486 Trace.What = trval;
02487 return 0;
02488 }
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504 int XrdCmsConfig::xxmi(XrdSysError *eDest, XrdOucStream &CFile)
02505 {
02506 char *val, parms[1024];
02507
02508
02509
02510 if (!(val = CFile.GetWord()) || !val[0])
02511 {eDest->Emsg("Config", "xmilib path not specified"); return 1;}
02512
02513
02514
02515 if (XmiPath) free(XmiPath);
02516 XmiPath = strdup(val);
02517
02518
02519
02520 if (!CFile.GetRest(parms, sizeof(parms)))
02521 {eDest->Emsg("Config", "xmilib parameters too long"); return 1;}
02522 if (XmiParms) free(XmiParms);
02523 XmiParms = (*parms ? strdup(parms) : 0);
02524
02525 return 0;
02526 }