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 }