00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdCnsConfigCVSID = "$Id: XrdCnsConfig.cc 35287 2010-09-14 21:19:35Z ganis $";
00014
00015 #include <unistd.h>
00016 #include <string.h>
00017 #include <stdio.h>
00018 #include <sys/types.h>
00019
00020 #include "Xrd/XrdTrace.hh"
00021
00022 #include "XrdClient/XrdClientConst.hh"
00023 #include "XrdClient/XrdClientEnv.hh"
00024
00025 #include "XrdNet/XrdNetDNS.hh"
00026 #include "XrdNet/XrdNetOpts.hh"
00027 #include "XrdNet/XrdNetSocket.hh"
00028
00029 #include "XrdOuc/XrdOuca2x.hh"
00030 #include "XrdOuc/XrdOucArgs.hh"
00031 #include "XrdOuc/XrdOucName2Name.hh"
00032 #include "XrdOuc/XrdOucStream.hh"
00033 #include "XrdOuc/XrdOucTList.hh"
00034 #include "XrdOuc/XrdOucTokenizer.hh"
00035 #include "XrdOuc/XrdOucUtils.hh"
00036
00037 #include "XrdSys/XrdSysError.hh"
00038 #include "XrdSys/XrdSysHeaders.hh"
00039 #include "XrdSys/XrdSysLogger.hh"
00040 #include "XrdSys/XrdSysPlugin.hh"
00041 #include "XrdSys/XrdSysTimer.hh"
00042
00043 #include "XrdCns/XrdCnsConfig.hh"
00044 #include "XrdCns/XrdCnsDaemon.hh"
00045 #include "XrdCns/XrdCnsLogRec.hh"
00046 #include "XrdCns/XrdCnsLogServer.hh"
00047 #include "XrdCns/XrdCnsXref.hh"
00048
00049
00050
00051
00052
00053 namespace XrdCns
00054 {
00055 XrdCnsConfig Config;
00056
00057 extern XrdCnsDaemon XrdCnsd;
00058
00059 extern XrdSysError MLog;
00060
00061 extern XrdOucTrace XrdTrace;
00062 }
00063
00064 using namespace XrdCns;
00065
00066
00067
00068
00069
00070 namespace XrdCns
00071 {
00072 void *CnsEvents(void *parg)
00073 {
00074 XrdOucStream fifoEvents;
00075 int eFD = *static_cast<int *>(parg);
00076 fifoEvents.Attach(eFD, 32*1024);
00077 XrdCnsd.getEvents(fifoEvents, "fifo");
00078 return (void *)0;
00079 }
00080
00081 void *CnsInt(void *parg)
00082 {
00083 XrdCnsLogRec *lrP;
00084
00085
00086
00087 while(1)
00088 {XrdSysTimer::Snooze(Config.cInt);
00089 lrP = XrdCnsLogRec::Alloc();
00090 lrP->setType('\0');
00091 lrP->Queue();
00092 }
00093 return (void *)0;
00094 }
00095 }
00096
00097
00098
00099
00100
00101 int XrdCnsConfig::Configure(int argc, char **argv, char *argt)
00102 {
00103
00104
00105
00106
00107
00108
00109
00110
00111 const char *TraceID = "Config";
00112 XrdOucArgs Spec(&MLog,(argt ? "Cns_Config: ":"XrdCnsd: "),
00113 "a:b:B:c:dD:e:E:i:I:l:L:N:p:q:R:");
00114 char buff[2048], *dP, *tP, *dnsEtxt = 0, *n2n = 0, *lroot = 0, *xpl = 0;
00115 char theOpt, *theArg;
00116 long long llval;
00117 int n, bPort = 0, haveArk = 0, NoGo = 0;
00118
00119
00120
00121 if (argt) Spec.Set(argt);
00122 else Spec.Set(argc-1, argv+1);
00123
00124
00125
00126 while((theOpt = Spec.getopt()) != -1)
00127 {switch(theOpt)
00128 {
00129 case 'a': if (*aPath == '/') aPath = Spec.argval;
00130 else NoGo = NAPath("'-a'", Spec.argval);
00131 break;
00132 case 'B': Opts |= optNoCns;
00133 case 'b': bPath = Spec.argval;
00134 break;
00135 case 'c': cPath = Spec.argval;
00136 break;
00137 case 'D': NoGo |= XrdOuca2x::a2i(MLog,"-D value",Spec.argval,&n,0,4);
00138 if (!NoGo) EnvPutInt("DebugLevel", n);
00139 break;
00140 case 'd': XrdTrace.What = TRACE_ALL;
00141 XrdSysThread::setDebug(&MLog);
00142 break;
00143 case 'e': if (*ePath == '/') ePath = Spec.argval;
00144 else NoGo = NAPath("'-e'", Spec.argval);
00145 break;
00146 case 'k': n = strlen(Spec.argval)-1;
00147 NoGo |= (isalpha(Spec.argval[n])
00148 ? XrdOuca2x::a2sz(MLog,"keep size", Spec.argval,&llval)
00149 : XrdOuca2x::a2ll(MLog,"keep count",Spec.argval,&llval));
00150 if (!isalpha(Spec.argval[n])) llval = -llval;
00151 logKeep = static_cast<int>(llval);
00152 break;
00153 case 'i': NoGo |= XrdOuca2x::a2tm(MLog,"-i value",Spec.argval,&cInt,1);
00154 break;
00155 case 'I': NoGo |= XrdOuca2x::a2tm(MLog,"-I value",Spec.argval,&mInt,1);
00156 break;
00157 case 'l': logfn = Spec.argval;
00158 break;
00159 case 'L': lroot = Spec.argval;
00160 break;
00161 case 'N': n2n = Spec.argval;
00162 break;
00163 case 'p': NoGo |= XrdOuca2x::a2i(MLog,"-p value",Spec.argval,&Port,1,65535);
00164 bPort = Port;
00165 break;
00166 case 'q': NoGo |= XrdOuca2x::a2i(MLog,"-q value",Spec.argval,&qLim,1,1024);
00167 break;
00168 case 'R': Opts |= optRecr;
00169 xpl = Spec.argval;
00170 break;
00171 default: NoGo = 1;
00172 }
00173 }
00174
00175
00176
00177 if (Opts & optRecr)
00178 {if (getenv("XRDINSTANCE") || getenv("XRDPROG"))
00179 {MLog.Emsg("Config","'-R' is valid only for a stand-alone command.");
00180 return 0;
00181 }
00182 if (bPath) {free(bPath); bPath = 0;}
00183 if (lroot)
00184 {sprintf(buff, "XRDLCLROOT=%s", lroot); putenv(strdup(buff));}
00185 if (n2n)
00186 {if ((tP=index(n2n, ' '))) {*tP++ = '\0'; while(*tP == ' ') tP++;}
00187 sprintf(buff, "XRDN2NLIB=%s", n2n); putenv(strdup(buff));
00188 if (tP && *tP)
00189 {sprintf(buff, "XRDN2NPARMS=%s", tP); putenv(strdup(buff));}
00190 }
00191 if (xpl && *xpl)
00192 {char *Colon = xpl;
00193 while((Colon = index(Colon, ':'))) *Colon++ = ' ';
00194 sprintf(buff, "XRDEXPORTS=%s", xpl); putenv(strdup(buff));
00195 } else {MLog.Emsg("Config","'-R' requires exports to be specified.");
00196 return 0;
00197 }
00198 Space = new XrdCnsXref("public",0);
00199 } else {
00200 *buff = '\0'; tP = buff;
00201 if (lroot) {*tP++ = ' '; *tP++ = '-'; *tP++ = 'L';}
00202 if (n2n) {*tP++ = ' '; *tP++ = '-'; *tP++ = 'N';}
00203 if (*buff)
00204 MLog.Emsg("Config", buff+1, "options ignored; valid only with -R.");
00205 }
00206
00207
00208
00209 if (!cPath) cPath = getenv("XRDCONFIGFN");
00210 cPath = (cPath ? strdup(cPath) : (char *)"");
00211
00212
00213
00214
00215 if (bPath)
00216 {char *bHost = 0;
00217 if (!bPort) bPort = Port;
00218 if (*bPath == '/') strcpy(buff, bPath);
00219 else if (!(dP = index(bPath, '/')) || *(dP-1) != ':') *buff = 0;
00220 else {char hBuff[1024], *cP = dP-1;
00221 strncpy(hBuff+1, bPath, cP-bPath); hBuff[cP-bPath+1] = '\0';
00222 if ((cP = index(hBuff+1, ':'))
00223 && XrdOuca2x::a2i(MLog,"-b port",cP+1,&bPort,1,65535)) *buff = 0;
00224 if (cP) *cP = '\0';
00225 bHost = XrdNetDNS::getHostName(hBuff+1, &dnsEtxt);
00226 if (dnsEtxt)
00227 {*hBuff = '\''; strcat(hBuff+1, "\'"); *buff = 0;
00228 MLog.Emsg("Config", hBuff, dnsEtxt);
00229 } else strcpy(buff, dP);
00230 }
00231 if (!*buff)
00232 {MLog.Emsg("Config","Backup path cannot be determined."); NoGo=1;}
00233 else {if (buff[strlen(buff)-1] == '/') strcat(buff, "cns/");
00234 else strcat(buff, "/cns/");
00235 bPath = strdup(buff);
00236 if (bHost)
00237 {sprintf(buff, "%s:%d", bHost, bPort); free(bHost);
00238 bDest = new XrdOucTList(buff, -bPort);
00239 TRACE(DEBUG, "Bkp host =" <<bDest->text);
00240 }
00241 TRACE(DEBUG, "Bkp path =" <<bPath);
00242 }
00243 }
00244
00245
00246
00247
00248
00249
00250 while((theArg = Spec.getarg()))
00251 {strcpy(buff, theArg);
00252 if (!strncmp("xroot://", buff, 8)) dP = buff+8;
00253 else if (!strncmp( "root://", buff, 7)) dP = buff+7;
00254 else dP = buff;
00255 if ( (tP = index(dP, '/'))) *tP = '\0';
00256 if (!(tP = index(dP, ':'))) n = Port;
00257 else if ((n = atoi(tP+1)) <= 0)
00258 {MLog.Emsg("Config", "Invalid port number in", dP);
00259 NoGo = 1; continue;
00260 } else *tP = '\0';
00261 dnsEtxt = 0;
00262 tP = XrdNetDNS::getHostName(dP, &dnsEtxt);
00263 if (dnsEtxt)
00264 {buff[0] = '\''; buff[1] = ' '; strcpy(buff+2, dnsEtxt);
00265 MLog.Emsg("Config", "'", dP, buff);
00266 NoGo = 1; delete tP; continue;
00267 }
00268 sprintf(buff, "%s:%d", tP, n); delete tP;
00269 if (!bDest) Dest = new XrdOucTList(buff, (bPath ? -n : n), Dest);
00270 else if (haveArk) Dest = new XrdOucTList(buff, n, Dest);
00271 else if (strcmp(buff, bDest->text))
00272 Dest = new XrdOucTList(buff, n, Dest);
00273 else {bDest->next = Dest; Dest = bDest; haveArk = 1;}
00274
00275 if (Opts & optNoCns && Dest->val >= 0)
00276 {XrdOucTList *xP = Dest; Dest = xP->next; delete xP;}
00277 }
00278
00279
00280
00281 if (bDest && !haveArk) {bDest->next = Dest; Dest = bDest;}
00282
00283
00284
00285 return !NoGo;
00286 }
00287
00288
00289
00290 int XrdCnsConfig::Configure()
00291 {
00292
00293
00294
00295
00296
00297
00298
00299 const char *TraceID = "Config";
00300 static int eFD;
00301 XrdOucTokenizer mToks(0);
00302 XrdNetSocket *EventSock;
00303 pthread_t tid;
00304 int n, retc, NoGo = 0;
00305 const char *iP;
00306 char buff[2048], *dP, *tP, *eVar;
00307
00308
00309
00310 if (!(Opts & optRecr)) MLog.Emsg("Config", "Cns initialization started.");
00311
00312
00313
00314 if ((iP = XrdOucUtils::InstName(-1))) {strcpy(buff,"./"); strcat(buff, iP);}
00315 else strcpy(buff, ".");
00316 strcat(buff, "/cns/");
00317 if (!XrdOucUtils::makePath(buff,0770) && chdir(buff)) {}
00318
00319
00320
00321 EnvPutInt(NAME_DATASERVERCONN_TTL, 2147483647);
00322
00323
00324
00325 if (!aPath && !(aPath = getenv("XRDADMINPATH"))) aPath = (char *)"/tmp/";
00326 strcpy(buff, aPath);
00327 if (buff[strlen(buff)-1] == '/') strcat(buff, "cns/");
00328 else strcat(buff, "/cns/");
00329 aPath = strdup(buff);
00330 TRACE(DEBUG, "Admin path=" <<aPath);
00331
00332
00333
00334 if ((retc = XrdOucUtils::makePath(aPath,0770)))
00335 {MLog.Emsg("Config", retc, "create admin directory", aPath);
00336 NoGo = 1;
00337 }
00338
00339
00340
00341 if (!ePath) ePath = aPath;
00342 else {strcpy(buff, ePath);
00343 if (buff[strlen(buff)-1] != '/') strcat(buff, "/");
00344 ePath = strdup(buff);
00345 }
00346 TRACE(DEBUG, "Event path=" <<ePath);
00347
00348
00349
00350 if (!(Opts & optRecr))
00351 if (aPath != ePath && (retc = XrdOucUtils::makePath(ePath,0770)))
00352 {MLog.Emsg("Config", retc, "create event directory", ePath);
00353 NoGo = 1;
00354 }
00355
00356
00357
00358 NoGo |= ConfigN2N();
00359
00360
00361
00362 if ((eVar = getenv("XRDEXPORTS")) && *eVar)
00363 {eVar = strdup(eVar); mToks.Attach(eVar); mToks.GetLine();
00364 n = 9999;
00365 while((dP = mToks.GetToken()))
00366 {if (!LocalPath(dP, buff, sizeof(buff))) NoGo = 1;
00367 else {Exports = new XrdOucTList(buff, strlen(buff), Exports);
00368 TRACE(DEBUG, "Exported physical path=" <<buff);
00369 }
00370 }
00371 free(eVar);
00372 }
00373
00374
00375
00376 if (!Exports)
00377 {MLog.Emsg("Config", "No paths have been exported!");
00378 NoGo = 1;
00379 }
00380
00381
00382
00383 if (!Dest)
00384 {if ((eVar = getenv("XRDCMSMAN")) && *eVar)
00385 {eVar = strdup(eVar); mToks.Attach(eVar); mToks.GetLine();
00386 while((dP = mToks.GetToken()))
00387 {if ((tP = index(dP, ':'))) *tP = '\0';
00388 sprintf(buff, "%s:%d", tP, Port);
00389 if (*tP) *tP = ':';
00390 Dest = new XrdOucTList(dP, Port, Dest);
00391 TRACE(DEBUG, "CNS dest=" <<dP <<':' <<Port);
00392 }
00393 free(eVar);
00394 }
00395 if (!Dest)
00396 {MLog.Emsg("Config","Name space routing not specified."); NoGo=1;}
00397 }
00398
00399
00400
00401
00402 if (bPath)
00403 {if ((retc = XrdSysThread::Run(&tid,CnsInt,0,XRDSYSTHREAD_BIND,
00404 "Interval logging")))
00405 {MLog.Emsg("Config",retc,"create interval logging thread"); NoGo=1;}
00406 } else {
00407 if (!(Opts & optRecr))
00408 MLog.Emsg("Config","Backup path not specified; inventory disabled!");
00409 }
00410
00411
00412
00413 if (NoGo)
00414 {MLog.Emsg("Config", "Cns initialization failed.");
00415 return 0;
00416 }
00417
00418
00419
00420 XrdCnsLog = new XrdCnsLogServer();
00421 NoGo = !XrdCnsLog->Init(Dest);
00422 if (Opts & optRecr) exit(NoGo ? 4 : 0);
00423
00424
00425
00426 if ((EventSock = XrdNetSocket::Create(&MLog, aPath, "XrdCnsd.events",
00427 0660, XRDNET_FIFO)))
00428 {eFD = EventSock->Detach();
00429 delete EventSock;
00430 if ((retc = XrdSysThread::Run(&tid, CnsEvents, (void *)&eFD,
00431 XRDSYSTHREAD_BIND, "FIFO event handler")))
00432 {MLog.Emsg("Config", retc, "create FIFO event thread"); NoGo = 1;}
00433 } else NoGo = 1;
00434
00435
00436
00437 MLog.Emsg("Config", "Cns initialization",(NoGo ? "failed.":"completed."));
00438 return !NoGo;
00439 }
00440
00441
00442
00443
00444
00445 int XrdCnsConfig::ConfigN2N()
00446 {
00447 XrdSysPlugin *myLib;
00448 XrdOucName2Name *(*ep)(XrdOucgetName2NameArgs);
00449 char *N2NLib, *N2NParms = 0;
00450
00451
00452
00453 if ((LCLRoot = getenv("XRDLCLROOT")) && !*LCLRoot) LCLRoot = 0;
00454
00455
00456
00457
00458 if (!(N2NLib = getenv("XRDN2NLIB")) || !*N2NLib)
00459 {if (LCLRoot) N2N = XrdOucgetName2Name(&MLog, 0, "", LCLRoot, 0);
00460 return 0;
00461 }
00462
00463
00464
00465 if ((N2NParms = getenv("XRDN2NPARMS"))) N2NParms = strdup(N2NParms);
00466
00467
00468
00469
00470 if (!(myLib = new XrdSysPlugin(&MLog, N2NLib))) return 1;
00471
00472
00473
00474 ep = (XrdOucName2Name *(*)(XrdOucgetName2NameArgs))(myLib->getPlugin("XrdOucgetName2Name"));
00475 if (!ep) return 1;
00476
00477
00478
00479 N2N = ep(&MLog, cPath,(N2NParms ? N2NParms:""),LCLRoot,0);
00480 if (N2NParms) free(N2NParms);
00481 return N2N == 0;
00482 }
00483
00484
00485
00486
00487
00488 int XrdCnsConfig::LocalPath(const char *oldp, char *newp, int newpsz)
00489 {
00490 int rc = 0;
00491
00492 if (N2N) rc = N2N->lfn2pfn(oldp, newp, newpsz);
00493 else if (((int)strlen(oldp)) >= newpsz) rc = ENAMETOOLONG;
00494 else strcpy(newp, oldp);
00495 if (rc) {MLog.Emsg("Config", rc, "generate local path from", oldp);
00496 return 0;
00497 }
00498 return 1;
00499 }
00500
00501
00502
00503
00504
00505 int XrdCnsConfig::LogicPath(const char *oldp, char *newp, int newpsz)
00506 {
00507 int rc = 0;
00508
00509 if (N2N) rc = N2N->pfn2lfn(oldp, newp, newpsz);
00510 else if (((int)strlen(oldp)) >= newpsz) rc = ENAMETOOLONG;
00511 else strcpy(newp, oldp);
00512 if (rc) {MLog.Emsg("Config", rc, "generate logical path from", oldp);
00513 return 0;
00514 }
00515 return 1;
00516 }
00517
00518
00519
00520
00521
00522 int XrdCnsConfig::MountPath(const char *lfnP, char *newp, int newpsz)
00523 {
00524 XrdOucTList *xP = Exports;
00525 int n = strlen(lfnP);
00526
00527
00528
00529 while(xP)
00530 {if (n >= xP->val && !strncmp(xP->text, lfnP, xP->val)) break;
00531 xP = xP->next;
00532 }
00533
00534
00535
00536 if (!xP)
00537 {strcpy(newp, LCLRoot ? LCLRoot : "/");
00538 return 0;
00539 }
00540
00541
00542
00543 Config.LocalPath(xP->text, newp, newpsz);
00544 return 1;
00545 }
00546
00547
00548
00549
00550
00551 int XrdCnsConfig::NAPath(const char *What, const char *Path)
00552 {
00553 MLog.Emsg("Config", "Absolute path required in", What, Path);
00554 return 1;
00555 }