XrdCnsConfig.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                       X r d C n s C o n f i g . c c                        */
00004 /*                                                                            */
00005 /* (c) 2007 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //         $Id: XrdCnsConfig.cc 35287 2010-09-14 21:19:35Z ganis $
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 /*           G l o b a l   C o n f i g u r a t i o n   O b j e c t            */
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 /*            E x t e r n a l   T h r e a d   I n t e r f a c e s             */
00068 /******************************************************************************/
00069   
00070 namespace XrdCns
00071 {
00072 void *CnsEvents(void *parg)
00073 {
00074    XrdOucStream fifoEvents;    // FIFO fed events
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 // Just blab out the midnight herald
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 /*                             C o n f i g u r e                              */
00099 /******************************************************************************/
00100 
00101 int XrdCnsConfig::Configure(int argc, char **argv, char *argt)
00102 {
00103 /*
00104   Function: Establish configuration at start up time via arglist.
00105 
00106   Input:    None.
00107 
00108   Output:   1 upon success or 0 otherwise.
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 // Setup the logger
00120 //
00121    if (argt) Spec.Set(argt);
00122       else   Spec.Set(argc-1, argv+1);
00123 
00124 // Parse the options
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 // The recreate option is only valid if we are not running under an xrootd
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 // Handle config
00208 //
00209    if (!cPath) cPath = getenv("XRDCONFIGFN");
00210    cPath = (cPath ? strdup(cPath) : (char *)"");
00211 
00212 // Handle the backup directory now. If there is one then we will create a
00213 // thread that periodically closes and backs up the log files.
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 // Get the destination for the name space and log files. In the process if we
00246 // create a client who will not be archiving but archive-only mode is in
00247 // effect; then delete that newly created client. Yes, Amelia, this is an odd
00248 // way of doing this but is much less complicated given the logic choices.
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 // Chain in backup host if we have not done so
00280 //
00281    if (bDest && !haveArk) {bDest->next = Dest; Dest = bDest;}
00282 
00283 // All done here
00284 //
00285    return !NoGo;
00286 }
00287 
00288 /******************************************************************************/
00289 
00290 int XrdCnsConfig::Configure()
00291 {
00292 /*
00293   Function: Establish configuration at start up time.
00294 
00295   Input:    None.
00296 
00297   Output:   1 upon success or 0 otherwise.
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 // Put out the herald
00309 //
00310    if (!(Opts & optRecr)) MLog.Emsg("Config", "Cns initialization started.");
00311 
00312 // Set current working directory for core files
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 // Do some XrdClient specific optimizations
00320 //
00321    EnvPutInt(NAME_DATASERVERCONN_TTL, 2147483647); // Prevent timeouts
00322 
00323 // Get the directory where the meta information is to go
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 // Create the admin path if it is not there
00333 //
00334    if ((retc = XrdOucUtils::makePath(aPath,0770)))
00335       {MLog.Emsg("Config", retc, "create admin directory", aPath);
00336        NoGo = 1;
00337       }
00338 
00339 // Establish the event directory path
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 // Create the event path if it is not there (forget it for 1-time recreates)
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 // Handle the name2name library
00357 //
00358    NoGo |= ConfigN2N();
00359 
00360 // Handle the exports list
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 // Check if we have any exported paths
00375 //
00376    if (!Exports)
00377       {MLog.Emsg("Config", "No paths have been exported!");
00378        NoGo = 1;
00379       }
00380 
00381 // Get the destination for the name space
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 // If we have an archiver, create a thread that periodically closes and 
00400 // backs up the log files.
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 // Check if we should continue
00412 //
00413    if (NoGo)
00414       {MLog.Emsg("Config", "Cns initialization failed.");
00415        return 0;
00416       }
00417 
00418 // Initialize event handling and return for 1-time recreates
00419 //
00420    XrdCnsLog = new XrdCnsLogServer();
00421    NoGo = !XrdCnsLog->Init(Dest);
00422    if (Opts & optRecr) exit(NoGo ? 4 : 0);
00423 
00424 // Create our notification path (r/w for us and our group) and start it
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 // All done
00436 //
00437    MLog.Emsg("Config", "Cns initialization",(NoGo ? "failed.":"completed."));
00438    return !NoGo;
00439 }
00440 
00441 /******************************************************************************/
00442 /* Private:                    C o n f i g N 2 N                              */
00443 /******************************************************************************/
00444 
00445 int XrdCnsConfig::ConfigN2N()
00446 {
00447    XrdSysPlugin    *myLib;
00448    XrdOucName2Name *(*ep)(XrdOucgetName2NameArgs);
00449    char *N2NLib, *N2NParms = 0;
00450 
00451 // Get local root
00452 //
00453    if ((LCLRoot = getenv("XRDLCLROOT")) && !*LCLRoot) LCLRoot = 0;
00454 
00455 // If we have no library path then use the default method (this will always
00456 // succeed).
00457 //
00458    if (!(N2NLib = getenv("XRDN2NLIB")) || !*N2NLib)
00459       {if (LCLRoot) N2N = XrdOucgetName2Name(&MLog, 0, "", LCLRoot, 0);
00460        return 0;
00461       }
00462 
00463 // Get the N2N parameters
00464 //
00465    if ((N2NParms = getenv("XRDN2NPARMS"))) N2NParms = strdup(N2NParms);
00466 
00467 // Create a pluin object (we will throw this away without deletion because
00468 // the library must stay open but we never want to reference it again).
00469 //
00470    if (!(myLib = new XrdSysPlugin(&MLog, N2NLib))) return 1;
00471 
00472 // Now get the entry point of the object creator
00473 //
00474    ep = (XrdOucName2Name *(*)(XrdOucgetName2NameArgs))(myLib->getPlugin("XrdOucgetName2Name"));
00475    if (!ep) return 1;
00476 
00477 // Get the Object now
00478 //
00479    N2N = ep(&MLog, cPath,(N2NParms ? N2NParms:""),LCLRoot,0);
00480    if (N2NParms) free(N2NParms);
00481    return N2N == 0;
00482 }
00483 
00484 /******************************************************************************/
00485 /* Public:                     L o c a l P a t h                              */
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 /* Public:                     L o g i c P a t h                              */
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 /* Public:                     M o u n t P a t h                              */
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 // Find the export path for this incomming path
00528 //
00529    while(xP)
00530         {if (n >= xP->val && !strncmp(xP->text, lfnP, xP->val)) break;
00531          xP = xP->next;
00532         }
00533 
00534 // Enter the mount path
00535 //
00536    if (!xP)
00537       {strcpy(newp, LCLRoot ? LCLRoot : "/");
00538        return 0;
00539       }
00540 
00541 // Convert export to a physical path and use that
00542 //
00543    Config.LocalPath(xP->text, newp, newpsz);
00544    return 1;
00545 }
00546 
00547 /******************************************************************************/
00548 /* Private:                       N A P a t h                                 */
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 }

Generated on Tue Jul 5 14:46:32 2011 for ROOT_528-00b_version by  doxygen 1.5.1