XrdOssConfig.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                       X r d O s s C o n f i g . c c                        */
00004 /*                                                                            */
00005 /*                                                                            */
00006 /* (C) 2003 by the Board of Trustees of the Leland Stanford, Jr., University  */
00007 /*                            All Rights Reserved                             */
00008 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00009 /*                DE-AC03-76-SFO0515 with the Deprtment of Energy             */
00010 /******************************************************************************/
00011 
00012 //         $Id: XrdOssConfig.cc 38011 2011-02-08 18:35:57Z ganis $
00013 
00014 const char *XrdOssConfigCVSID = "$Id: XrdOssConfig.cc 38011 2011-02-08 18:35:57Z ganis $";
00015 
00016 /*
00017    The routines in this file handle initialization. They get the
00018    configuration values either from configuration file or XrdOssconfig.h (in that
00019    order of precedence).
00020 
00021    These routines are thread-safe if compiled with:
00022    AIX: -D_THREAD_SAFE
00023    SUN: -D_REENTRANT
00024 */
00025   
00026 #include <unistd.h>
00027 #include <ctype.h>
00028 #include <dirent.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 
00037 #include "XrdFrm/XrdFrmProxy.hh"
00038 #include "XrdOss/XrdOssApi.hh"
00039 #include "XrdOss/XrdOssCache.hh"
00040 #include "XrdOss/XrdOssConfig.hh"
00041 #include "XrdOss/XrdOssError.hh"
00042 #include "XrdOss/XrdOssMio.hh"
00043 #include "XrdOss/XrdOssOpaque.hh"
00044 #include "XrdOss/XrdOssSpace.hh"
00045 #include "XrdOss/XrdOssTrace.hh"
00046 #include "XrdOuc/XrdOuca2x.hh"
00047 #include "XrdOuc/XrdOucEnv.hh"
00048 #include "XrdSys/XrdSysError.hh"
00049 #include "XrdOuc/XrdOucExport.hh"
00050 #include "XrdOuc/XrdOucMsubs.hh"
00051 #include "XrdOuc/XrdOucName2Name.hh"
00052 #include "XrdOuc/XrdOucProg.hh"
00053 #include "XrdOuc/XrdOucStream.hh"
00054 #include "XrdOuc/XrdOucUtils.hh"
00055 #include "XrdSys/XrdSysHeaders.hh"
00056 #include "XrdSys/XrdSysPlugin.hh"
00057 #include "XrdSys/XrdSysPthread.hh"
00058 #include "XrdSys/XrdSysPlatform.hh"
00059 
00060 /******************************************************************************/
00061 /*                 S t o r a g e   S y s t e m   O b j e c t                  */
00062 /******************************************************************************/
00063   
00064 extern XrdOssSys   *XrdOssSS;
00065 
00066 extern XrdOucTrace  OssTrace;
00067 
00068 XrdOucPListAnchor  *XrdOssRPList;
00069 
00070 /******************************************************************************/
00071 /*                            E r r o r   T e x t                             */
00072 /******************************************************************************/
00073   
00074 const char *XrdOssErrorText[] =
00075       {XRDOSS_T8001,
00076        XRDOSS_T8002,
00077        XRDOSS_T8003,
00078        XRDOSS_T8004,
00079        XRDOSS_T8005,
00080        XRDOSS_T8006,
00081        XRDOSS_T8007,
00082        XRDOSS_T8008,
00083        XRDOSS_T8009,
00084        XRDOSS_T8010,
00085        XRDOSS_T8011,
00086        XRDOSS_T8012,
00087        XRDOSS_T8013,
00088        XRDOSS_T8014,
00089        XRDOSS_T8015,
00090        XRDOSS_T8016,
00091        XRDOSS_T8017,
00092        XRDOSS_T8018,
00093        XRDOSS_T8019,
00094        XRDOSS_T8020,
00095        XRDOSS_T8021,
00096        XRDOSS_T8022,
00097        XRDOSS_T8023,
00098        XRDOSS_T8024,
00099        XRDOSS_T8025,
00100        XRDOSS_T8026
00101       };
00102 
00103 /******************************************************************************/
00104 /*                               d e f i n e s                                */
00105 /******************************************************************************/
00106 
00107 #define Duplicate(x,y) if (y) free(y); y = strdup(x)
00108 
00109 #define TS_Xeq(x,m)    if (!strcmp(x,var)) return m(Config, Eroute);
00110 
00111 #define TS_String(x,m) if (!strcmp(x,var)) {Duplicate(val,m); return 0;}
00112 
00113 #define TS_List(x,m,v) if (!strcmp(x,var)) \
00114                           {m.Insert(new XrdOucPList(val, v); return 0;}
00115 
00116 #define TS_Char(x,m)   if (!strcmp(x,var)) {m = val[0]; return 0;}
00117 
00118 #define TS_Add(x,m,v,s) if (!strcmp(x,var)) {m |= (v|s); return 0;}
00119 #define TS_Ade(x,m,v,s) if (!strcmp(x,var)) {m |= (v|s); Config.Echo(); return 0;}
00120 #define TS_Rem(x,m,v,s) if (!strcmp(x,var)) {m = (m & ~v) | s; return 0;}
00121 
00122 #define TS_Set(x,m,v)  if (!strcmp(x,var)) {m = v; Config.Echo(); return 0;}
00123 
00124 #define xrdmax(a,b)       (a < b ? b : a)
00125 
00126 // Set the following value to establish the ulimit for FD numbers. Zero
00127 // sets it to whatever the current hard limit is. Negative leaves it alone.
00128 //
00129 #define XrdOssFDLIMIT     -1
00130 #define XrdOssFDMINLIM    64
00131 
00132 /******************************************************************************/
00133 /*            E x t e r n a l   T h r e a d   I n t e r f a c e s             */
00134 /******************************************************************************/
00135   
00136 void *XrdOssxfr(void *carg)       {return XrdOssSS->Stage_In(carg);}
00137 
00138 void *XrdOssCacheScan(void *carg) {return XrdOssCache::Scan(*((int *)carg));}
00139 
00140 /******************************************************************************/
00141 /*                           C o n s t r u c t o r                            */
00142 /******************************************************************************/
00143 
00144 XrdOssSys::XrdOssSys()
00145 {
00146    xfrtcount     = 0;
00147    pndbytes      = 0;
00148    stgbytes      = 0;
00149    totbytes      = 0;
00150    totreqs       = 0;
00151    badreqs       = 0;
00152    CompSuffix    = 0;
00153    CompSuflen    = 0;
00154    MaxTwiddle    = 3;
00155    tryMmap       = 0;
00156    chkMmap       = 0;
00157    lcl_N2N = rmt_N2N = the_N2N = 0; 
00158    N2N_Lib = N2N_Parms         = 0;
00159    StageCmd      = 0;
00160    StageMsg      = 0; 
00161    StageSnd      = 0;
00162    StageFrm      = 0;
00163    StageRealTime = 1;
00164    StageAsync    = 0;
00165    StageCreate   = 0;
00166    StageEvents   = (char *)"-";
00167    StageEvSize   = 1;
00168    StageAction   = (char *)"wq "; 
00169    StageActLen   = 3;
00170    RSSCmd        = 0;
00171    isMSSC        = 0;
00172    RSSTout       =15*1000;
00173    DirFlags      = 0; 
00174    OptFlags      = 0;
00175    LocalRoot     = 0;
00176    RemoteRoot    = 0;
00177    cscanint      = 600;
00178    FDFence       = -1;
00179    FDLimit       = XrdOssFDLIMIT;
00180    MaxSize       = 0;
00181    minalloc      = 0;
00182    ovhalloc      = 0;
00183    fuzalloc      = 0;
00184    xfrspeed      = 9*1024*1024;
00185    xfrovhd       = 30;
00186    xfrhold       =  3*60*60;
00187    xfrkeep       = 20*60;
00188    xfrthreads    = 1;
00189    ConfigFN      = 0;
00190    QFile         = 0;
00191    UDir          = 0;
00192    Solitary      = 0;
00193    DPList        = 0;
00194    lenDP         = 0;
00195    numCG = numDP = 0;
00196 }
00197   
00198 /******************************************************************************/
00199 /*                             C o n f i g u r e                              */
00200 /******************************************************************************/
00201   
00202 int XrdOssSys::Configure(const char *configfn, XrdSysError &Eroute)
00203 {
00204 /*
00205   Function: Establish default values using a configuration file.
00206 
00207   Input:    None.
00208 
00209   Output:   0 upon success or !0 otherwise.
00210 */
00211    XrdSysError_Table *ETab = new XrdSysError_Table(XRDOSS_EBASE, XRDOSS_ELAST,
00212                                                    XrdOssErrorText);
00213    char *val;
00214    int  retc, NoGo = XrdOssOK;
00215    pthread_t tid;
00216 
00217 // Do the herald thing
00218 //
00219    Eroute.Say("++++++ Storage system initialization started.");
00220    Eroute.addTable(ETab);
00221    if (getenv("XRDDEBUG")) OssTrace.What = TRACE_ALL;
00222 
00223 // Preset all variables with common defaults
00224 //
00225    ConfigFN = (configfn && *configfn ? strdup(configfn) : 0);
00226 
00227 // Process the configuration file
00228 //
00229    NoGo = ConfigProc(Eroute);
00230 
00231 // Establish the FD limit
00232 //
00233    {struct rlimit rlim;
00234     if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
00235        Eroute.Emsg("Config", errno, "get resource limits");
00236        else Hard_FD_Limit = rlim.rlim_max;
00237 
00238     if (FDLimit <= 0) FDLimit = rlim.rlim_cur;
00239        else {rlim.rlim_cur = FDLimit;
00240             if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
00241                NoGo = Eroute.Emsg("Config", errno,"set FD limit");
00242             }
00243     if (FDFence < 0 || FDFence >= FDLimit) FDFence = FDLimit >> 1;
00244    }
00245 
00246 // Establish usage tracking and quotas, if need be. Note that if we are not
00247 // a true data server, those services will be initialized but then disabled.
00248 //
00249    Solitary = ((val = getenv("XRDREDIRECT")) && !strcmp(val, "Q"));
00250    if (Solitary) Eroute.Say("++++++ Configuring standalone mode . . .");
00251    NoGo |= XrdOssCache::Init(UDir, QFile, Solitary)
00252           |XrdOssCache::Init(minalloc, ovhalloc, fuzalloc);
00253 
00254 // Configure the MSS interface including staging
00255 //
00256    if (!NoGo) NoGo = ConfigStage(Eroute);
00257 
00258 // Configure async I/O
00259 //
00260    if (!NoGo) NoGo = !AioInit();
00261 
00262 // Initialize memory mapping setting to speed execution
00263 //
00264    if (!NoGo) ConfigMio(Eroute);
00265 
00266 // Establish the actual default path settings (modified by the above)
00267 //
00268    RPList.Set(DirFlags);
00269 
00270 // Configure space (final pass)
00271 //
00272    ConfigSpace();
00273 
00274 // Configure statiscal reporting
00275 //
00276    if (!NoGo) ConfigStats(Eroute);
00277 
00278 // Start up the cache scan thread unless specifically told not to. Some programs
00279 // like the cmsd manually handle space updates.
00280 //
00281    if (!(val = getenv("XRDOSSCSCAN")) || strcmp(val, "off"))
00282       {if ((retc = XrdSysThread::Run(&tid, XrdOssCacheScan,
00283                                     (void *)&cscanint, 0, "cache scan")))
00284           Eroute.Emsg("Config", retc, "create cache scan thread");
00285       }
00286 
00287 // Display the final config if we can continue
00288 //
00289    if (!NoGo) Config_Display(Eroute);
00290 
00291 // Export the real path list (for frm et. al.)
00292 //
00293    XrdOssRPList = &RPList;
00294 
00295 // All done, close the stream and return the return code.
00296 //
00297    val = (NoGo ? (char *)"failed." : (char *)"completed.");
00298    Eroute.Say("------ Storage system initialization ", val);
00299    return NoGo;
00300 }
00301   
00302 /******************************************************************************/
00303 /*                   o o s s _ C o n f i g _ D i s p l a y                    */
00304 /******************************************************************************/
00305   
00306 #define XrdOssConfig_Val(base, opt) \
00307              (Have ## base  ? "       oss." #opt " " : ""), \
00308              (Have ## base  ? base     : ""), \
00309              (Have ## base  ? "\n"     : "")
00310   
00311 #define XrdOssConfig_Vop(base, opt, optchk0, opt1, opt2, optchk1, opt3, opt4) \
00312              (Have ## base  ? "       oss." #opt " " : ""), \
00313              (Have ## base  ? (optchk0 ? opt1 : opt2) : ""), \
00314              (Have ## base  ? (optchk1 ? opt3 : opt4) : ""), \
00315              (Have ## base  ? base     : ""), \
00316              (Have ## base  ? "\n"     : "")
00317 
00318 void XrdOssSys::Config_Display(XrdSysError &Eroute)
00319 {
00320      char buff[4096], *cloc;
00321      XrdOucPList *fp;
00322 
00323      // Preset some tests
00324      //
00325      int HaveRSSCmd     = (RSSCmd     && RSSCmd[0]);
00326      int HaveStageCmd   = (StageCmd   && StageCmd[0]);
00327      int HaveRemoteRoot = (RemoteRoot && RemoteRoot[0]);
00328      int HaveLocalRoot  = (LocalRoot  && LocalRoot[0]);
00329      int HaveStageMsg   = (StageMsg   && StageMsg[0]);
00330      int HaveN2N_Lib    = (N2N_Lib != 0);
00331 
00332      if (!ConfigFN || !ConfigFN[0]) cloc = (char *)"Default";
00333         else cloc = ConfigFN;
00334 
00335      snprintf(buff, sizeof(buff), "Config effective %s oss configuration:\n"
00336                                   "       oss.alloc        %lld %d %d\n"
00337                                   "       oss.cachescan    %d\n"
00338                                   "       oss.compdetect   %s\n"
00339                                   "       oss.fdlimit      %d %d\n"
00340                                   "       oss.maxsize      %lld\n"
00341                                   "%s%s%s"
00342                                   "%s%s%s"
00343                                   "%s%s%s"
00344                                   "%s%s%s%s%s"
00345                                   "%s%s%s"
00346                                   "%s%s%s"
00347                                   "       oss.trace        %x\n"
00348                                   "       oss.xfr          %d %d %d %d",
00349              cloc,
00350              minalloc, ovhalloc, fuzalloc,
00351              cscanint,
00352              (CompSuffix ? CompSuffix : "*"),
00353              FDFence, FDLimit, MaxSize,
00354              XrdOssConfig_Val(N2N_Lib,    namelib),
00355              XrdOssConfig_Val(LocalRoot,  localroot),
00356              XrdOssConfig_Val(RemoteRoot, remoteroot),
00357              XrdOssConfig_Vop(StageCmd,   stagecmd, StageAsync,  "async ","sync ",
00358                                                     StageCreate, "creates ", ""),
00359              XrdOssConfig_Val(StageMsg,   stagemsg),
00360              XrdOssConfig_Val(RSSCmd,     rsscmd),
00361              OssTrace.What,
00362              xfrthreads, xfrspeed, xfrovhd, xfrhold);
00363 
00364      Eroute.Say(buff);
00365 
00366      XrdOssMio::Display(Eroute);
00367 
00368      XrdOssCache::List("       oss.space", Eroute);
00369            List_Path("       oss.defaults ", "", DirFlags, Eroute);
00370      fp = RPList.First();
00371      while(fp)
00372           {List_Path("       oss.path ", fp->Path(), fp->Flag(), Eroute);
00373            fp = fp->Next();
00374           }
00375 }
00376 
00377 /******************************************************************************/
00378 /*                     P r i v a t e   F u n c t i o n s                      */
00379 /******************************************************************************/
00380 /******************************************************************************/
00381 /*                             C o n f i g M i o                              */
00382 /******************************************************************************/
00383   
00384 void XrdOssSys::ConfigMio(XrdSysError &Eroute)
00385 {
00386      XrdOucPList *fp;
00387      unsigned long long flags = 0;
00388      int setoff = 0;
00389 
00390 // Initialize memory mapping setting to speed execution
00391 //
00392    if (!(tryMmap = XrdOssMio::isOn())) return;
00393    chkMmap = XrdOssMio::isAuto();
00394 
00395 // Run through all the paths and get the composite flags
00396 //
00397    fp = RPList.First();
00398    while(fp)
00399         {flags |= fp->Flag();
00400          fp = fp->Next();
00401         }
00402 
00403 // Handle default settings
00404 //
00405    if (DirFlags & XRDEXP_MEMAP && !(DirFlags & XRDEXP_NOTRW))
00406       DirFlags |= XRDEXP_FORCERO;
00407    flags |= DirFlags;
00408    if (DirFlags & (XRDEXP_MLOK | XRDEXP_MKEEP)) DirFlags |= XRDEXP_MMAP;
00409 
00410 // Produce warnings if unsupported features have been selected
00411 //
00412 #if !defined(_POSIX_MAPPED_FILES)
00413    if (flags & XRDEXP_MEMAP)
00414       {Eroute.Say("Config warning: memory mapped files not supported; "
00415                              "feature disabled.");
00416        setoff = 1;
00417        fp = RPList.First();
00418        while(fp)
00419             {fp->Set(fp->Flag() & ~XRDEXP_MEMAP);
00420              fp = fp->Next();
00421             }
00422        DirFlags = DirFlags & ~XRDEXP_MEMAP;
00423       }
00424 #elif !defined(_POSIX_MEMLOCK)
00425    if (flags & XRDEXP_MLOK)
00426       {Eroute.Say("Config warning: memory locked files not supported; "
00427                              "feature disabled.");
00428        fp = RPList.First();
00429        while(fp)
00430             {fp->Set(fp->Flag() & ~XRDEXP_MLOK);
00431              fp = fp->Next();
00432             }
00433        DirFlags = DirFlags & ~XRDEXP_MLOK;
00434       }
00435 #endif
00436 
00437 // If no memory flags are set, turn off memory mapped files
00438 //
00439    if (!(flags & XRDEXP_MEMAP) || setoff)
00440      {XrdOssMio::Set(0, 0, 0, 0, 0);
00441       tryMmap = 0; chkMmap = 0;
00442      }
00443 }
00444   
00445 /******************************************************************************/
00446 /*                             C o n f i g N 2 N                              */
00447 /******************************************************************************/
00448 
00449 int XrdOssSys::ConfigN2N(XrdSysError &Eroute)
00450 {
00451    XrdSysPlugin    *myLib;
00452    XrdOucName2Name *(*ep)(XrdOucgetName2NameArgs);
00453 
00454 // If we have no library path then use the default method (this will always
00455 // succeed).
00456 //
00457    if (!N2N_Lib)
00458       {the_N2N = XrdOucgetName2Name(&Eroute, ConfigFN, "", LocalRoot, RemoteRoot);
00459        if (LocalRoot) {lcl_N2N = the_N2N;
00460                        XrdOucEnv::Export("XRDLCLROOT", LocalRoot);
00461                       }
00462        if (RemoteRoot){rmt_N2N = the_N2N;
00463                        XrdOucEnv::Export("XRDRMTROOT",RemoteRoot);
00464                       }
00465        return 0;
00466       }
00467 
00468 // Export name lib information
00469 //
00470    XrdOucEnv::Export("XRDN2NLIB", N2N_Lib);
00471    if (N2N_Parms) XrdOucEnv::Export("XRDN2NPARMS", N2N_Parms);
00472 
00473 // Create a pluin object (we will throw this away without deletion because
00474 // the library must stay open but we never want to reference it again).
00475 //
00476    if (!(myLib = new XrdSysPlugin(&Eroute, N2N_Lib))) return 1;
00477 
00478 // Now get the entry point of the object creator
00479 //
00480    ep = (XrdOucName2Name *(*)(XrdOucgetName2NameArgs))(myLib->getPlugin("XrdOucgetName2Name"));
00481    if (!ep) return 1;
00482 
00483 
00484 // Get the Object now
00485 //
00486    lcl_N2N = rmt_N2N = the_N2N = ep(&Eroute, ConfigFN, 
00487                                    (N2N_Parms ? N2N_Parms : ""),
00488                                    LocalRoot, RemoteRoot);
00489    return lcl_N2N == 0;
00490 }
00491   
00492 /******************************************************************************/
00493 /*                            C o n f i g P r o c                             */
00494 /******************************************************************************/
00495   
00496 int XrdOssSys::ConfigProc(XrdSysError &Eroute)
00497 {
00498   char *var;
00499   int  cfgFD, retc, NoGo = XrdOssOK;
00500   XrdOucEnv myEnv;
00501   XrdOucStream Config(&Eroute, getenv("XRDINSTANCE"), &myEnv, "=====> ");
00502 
00503 // If there is no config file, return with the defaults sets.
00504 //
00505    if( !ConfigFN || !*ConfigFN)
00506      {Eroute.Say("Config warning: config file not specified; defaults assumed.");
00507       return XrdOssOK;
00508      }
00509 
00510 // Try to open the configuration file.
00511 //
00512    if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
00513       {Eroute.Emsg("Config", errno, "open config file", ConfigFN);
00514        return 1;
00515       }
00516    Config.Attach(cfgFD);
00517 
00518 // Now start reading records until eof.
00519 //
00520    while((var = Config.GetMyFirstWord()))
00521         {if (!strncmp(var, "oss.", 4))
00522             {if (ConfigXeq(var+4, Config, Eroute)) {Config.Echo(); NoGo = 1;}}
00523             else if (!strcmp(var,"all.export")
00524                  &&  xpath(Config, Eroute)) {Config.Echo(); NoGo = 1;}
00525         }
00526 
00527 // All done scanning the file, set dependent parameters.
00528 //
00529    if (N2N_Lib || LocalRoot || RemoteRoot) NoGo |= ConfigN2N(Eroute);
00530 
00531 // Now check if any errors occured during file i/o
00532 //
00533    if ((retc = Config.LastError()))
00534       NoGo = Eroute.Emsg("Config", retc, "read config file", ConfigFN);
00535    Config.Close();
00536 
00537 // Return final return code
00538 //
00539    return NoGo;
00540 }
00541 
00542 /******************************************************************************/
00543 /*                           C o n f i g S p a c e                            */
00544 /******************************************************************************/
00545 
00546 void XrdOssSys::ConfigSpace()
00547 {
00548    XrdOucPList *fp = RPList.First();
00549    int noCacheFS = !(OptFlags & XrdOss_CacheFS);
00550 
00551 // Configure space for each non-cached exported path. We only keep track of
00552 // space that can actually be modified in some way.
00553 //
00554    while(fp)
00555         {if ((noCacheFS || (fp->Flag() & XRDEXP_INPLACE))
00556          &&  ((fp->Flag() & (XRDEXP_STAGE | XRDEXP_PURGE))
00557          ||  !(fp->Flag() & XRDEXP_NOTRW)))
00558             ConfigSpace(fp->Path());
00559          fp = fp->Next();
00560         }
00561 }
00562 
00563 /******************************************************************************/
00564 
00565 void XrdOssSys::ConfigSpace(const char *Lfn)
00566 {
00567    struct stat statbuff;
00568    char Pfn[MAXPATHLEN+1+8], *Slash;
00569 
00570 // Get local path for this lfn
00571 //
00572    if (GenLocalPath(Lfn, Pfn)) return;
00573 
00574 // Now try to find the actual existing base path
00575 //
00576    while(stat(Pfn, &statbuff))
00577         {if (!(Slash = rindex(Pfn, '/')) || Slash == Pfn) return;
00578          *Slash = '\0';
00579         }
00580 
00581 // Add this path to the file system data. We need to do this to track space
00582 //
00583    XrdOssCache_FS::Add(Pfn);
00584 }
00585   
00586 /******************************************************************************/
00587 /*                           C o n f i g S p a t h                            */
00588 /******************************************************************************/
00589 
00590 void XrdOssSys::ConfigSpath(XrdSysError &Eroute, const char *Path,
00591                            unsigned long long &flags, int noMSS)
00592 {
00593 
00594 // Apply defaults for anything not actually specified in the flags
00595 //
00596    flags = flags | (DirFlags & (~(flags >> XRDEXP_MASKSHIFT)));
00597 
00598 // mig+r/w -> check unless nocheck was specified
00599 //
00600    if ((flags & XRDEXP_MIG) && !(flags & XRDEXP_NOTRW)
00601    && !((flags | DirFlags) & XRDEXP_CHECK_X )) flags &= ~XRDEXP_NOCHECK;
00602 
00603 // mig| (purge+r/w) -> lock file creation
00604 //
00605    if ((flags & XRDEXP_MIG)
00606    || ((flags & XRDEXP_PURGE) && !(flags & XRDEXP_NOTRW)))
00607            flags |=  XRDEXP_MAKELF;
00608       else flags &= ~XRDEXP_MAKELF;
00609 
00610 // If there is no mss then turn off all mss related optionss, otherwise check
00611 // if the options may leave the system in an inconsistent state
00612 //
00613    if (noMSS) flags=(flags & ~XRDEXP_RCREATE)|XRDEXP_NOCHECK|XRDEXP_NODREAD;
00614       else if ((flags & XRDEXP_MIG)   &&  (flags & XRDEXP_NOCHECK)
00615            && !(flags & XRDEXP_NOTRW))
00616               Eroute.Say("Config warning: 'all.export ", Path,
00617                           " nocheck mig r/w' allows file inconsistentcy!");
00618 }
00619   
00620 /******************************************************************************/
00621 /*                           C o n f i g S t a g e                            */
00622 /******************************************************************************/
00623 
00624 int XrdOssSys::ConfigStage(XrdSysError &Eroute)
00625 {
00626    const char *What;
00627    char *tp, *stgp = 0;
00628    unsigned long long flags;
00629    int noMSS, needRSS = 0, NoGo = 0;
00630    XrdOucPList *fp;
00631 
00632 // Determine if we are a manager/supervisor. These never stage files so we
00633 // really don't need (nor want) a stagecmd or an msscmd.
00634 //
00635    noMSS = ((tp = getenv("XRDREDIRECT"))
00636             && (!strcmp(tp, "R") || !strcmp(tp, "M"))) | Solitary;
00637 
00638 // A rsscmd implies check+dread. Note that nostage is now always the default.
00639 //
00640    flags = (RSSCmd ? 0 : XRDEXP_NOCHECK | XRDEXP_NODREAD);
00641    DirFlags = DirFlags | (flags & (~(DirFlags >> XRDEXP_MASKSHIFT)));
00642 
00643 // Indicate whether lock files are to be created. We create them for migratable
00644 // space and purgeable space that is writable.
00645 //
00646    if ((DirFlags & XRDEXP_MIG)
00647    || ((DirFlags & XRDEXP_PURGE) && !(DirFlags & XRDEXP_NOTRW)))
00648       DirFlags |= XRDEXP_MAKELF;
00649    RPList.Default(DirFlags);
00650 
00651 // Reprocess the paths to set correct defaults
00652 //
00653    fp = RPList.First();
00654    while(fp) 
00655         {flags = fp->Flag(); ConfigSpath(Eroute, fp->Path(), flags, noMSS);
00656 
00657          // Record the fact that we have a stageable path
00658          //
00659          if (flags & XRDEXP_STAGE) stgp = fp->Path();
00660 
00661          // Check if path requires rsscmd and complain if we don't have one
00662          //
00663               if (!(flags & XRDEXP_NOCHECK)) What = "has check";
00664          else if (!(flags & XRDEXP_NODREAD)) What = "has dread";
00665          else if   (flags & XRDEXP_RCREATE)  What = "has recreate";
00666          else                                What = 0;
00667          if (!noMSS && !RSSCmd && What)
00668             {Eroute.Emsg("Config", fp->Path(), What,
00669                          " export attribute but rsscmd not specified.");
00670              NoGo  = 1;
00671             } else if (What) needRSS = 1;
00672 
00673          // Update flags and proceed to next path
00674          //
00675          fp->Set(flags); fp = fp->Next();
00676         }
00677 
00678 // If we are a manager/supervisor, short circuit MSS initialization
00679 //
00680    if (noMSS)
00681       {if (RSSCmd)   {free(RSSCmd);   RSSCmd   = 0;}
00682        if (StageCmd) {free(StageCmd); StageCmd = 0;}
00683        RSSProg = 0; StageCreate = 0;
00684        return NoGo;
00685       }
00686 
00687 // Check if we don't need the stagecmd but one was specified
00688 //
00689    if (StageCmd && !stgp)
00690       {Eroute.Say("Config warning: 'stagecmd' ignored; no stageable paths present.");
00691        free(StageCmd); StageCmd = 0;
00692       }
00693 
00694 // Check if we don't need a remote storage service but one was specified
00695 //
00696    if (RSSCmd && !needRSS)
00697       {Eroute.Say("Config warning: 'rsscmd' ignored; no path exported with "
00698                                            "check, dread, or rcreate.");
00699        free(RSSCmd); RSSCmd = 0;
00700       }
00701 
00702 // If we have any errors at this point, just return failure
00703 //
00704    if (NoGo) return 1;
00705    if (!RSSCmd && !StageCmd && !stgp) return 0;
00706    Eroute.Say("++++++ Remote Storage System interface initialization started.");
00707 
00708 // Allocate a pr0gram object for the gateway command
00709 //
00710    if (RSSCmd)
00711       {RSSProg = new XrdOucProg(&Eroute);
00712        if (RSSProg->Setup(RSSCmd)) NoGo = 1;
00713       }
00714 
00715 // Initialize staging if we need to
00716 //
00717    if (!NoGo && (StageCmd || stgp))
00718       {const int AMode = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH; // 775
00719        if (StageCmd && *StageCmd) NoGo = ConfigStageC(Eroute);
00720           else {StageFrm = new XrdFrmProxy(Eroute.logger(),
00721                            XrdOucUtils::InstName(),OssTrace.What & TRACE_Debug);
00722                 NoGo = !StageFrm->Init(XrdFrmProxy::opStg,
00723                                        getenv("XRDADMINPATH"), AMode);
00724                 StageRealTime = 0; StageAsync = 1;
00725                }
00726 
00727       // Set up the event path
00728       //
00729          StageAction = (char *)"wfn "; StageActLen = 4;
00730          if ((tp = getenv("XRDOFSEVENTS")))
00731             {char sebuff[MAXPATHLEN+8];
00732              StageEvSize = sprintf(sebuff, "file:///%s", tp);
00733              StageEvents = strdup(sebuff);
00734             } else {StageEvents = (char *)"-"; StageEvSize = 1;}
00735       }
00736 
00737 // All done
00738 //
00739    tp = (NoGo ? (char *)"failed." : (char *)"completed.");
00740    Eroute.Say("------ Remote Storage System interface initialization ", tp);
00741    return NoGo;
00742 }
00743   
00744 /******************************************************************************/
00745 /*                          C o n f i g S t a g e C                           */
00746 /******************************************************************************/
00747 
00748 int XrdOssSys::ConfigStageC(XrdSysError &Eroute)
00749 {
00750    pthread_t tid;
00751    char *sp, *tp;
00752    int numt, retc, NoGo = 0;
00753 
00754 // The stage command is interactive if it starts with an | (i.e., pipe in)
00755 //
00756    tp = StageCmd;
00757    while(*tp && *tp == ' ') tp++;
00758    if (*tp == '|') {StageRealTime = 0;
00759                     do {tp++;} while(*tp == ' ');
00760                    }
00761    StageCmd = tp;
00762 
00763 // This is a bit of hackery to get the traceid sent over to the
00764 // new file residency manager (frm). Keeps the config simple.
00765 //
00766    if ((sp = index(StageCmd, ' '))) *sp = '\0';
00767    if (!(tp = rindex (StageCmd, '/'))) tp = StageCmd;
00768       else tp++;
00769    if (!strncmp("frm_", tp, 4)) StageFormat = 1;
00770    if (sp) *sp = ' ';
00771 
00772 // Set up a program object for the command
00773 //
00774    StageProg = new XrdOucProg(&Eroute);
00775    if (StageProg->Setup(StageCmd)) NoGo = 1;
00776 
00777 // For old-style real-time staging, create threads to handle the staging
00778 // For queue-style staging, start the program that handles the queue
00779 //
00780    if (!NoGo)
00781       {if (StageRealTime)
00782           {if ((numt = xfrthreads - xfrtcount) > 0) while(numt--)
00783                if ((retc = XrdSysThread::Run(&tid,XrdOssxfr,(void *)0,0,"staging")))
00784                   Eroute.Emsg("Config", retc, "create staging thread");
00785                   else xfrtcount++;
00786           } else NoGo = StageProg->Start();
00787       }
00788 
00789 // Setup the additional stage information vector. Variable substitution:
00790 // <data>$var;<data>.... (max of MaxArgs substitutions). This is only relevant
00791 // when using an actual stagecmd.
00792 //
00793    if (!NoGo && !StageRealTime && StageMsg)
00794       {XrdOucMsubs *msubs = new XrdOucMsubs(&Eroute);
00795        if (msubs->Parse("stagemsg", StageMsg)) StageSnd = msubs;
00796           else NoGo = 1;  // We will exit no need to delete msubs
00797       }
00798 
00799 // All done
00800 //
00801    return NoGo;
00802 }
00803 
00804   
00805 /******************************************************************************/
00806 /*                           C o n f i g S t a t s                            */
00807 /******************************************************************************/
00808 
00809 void XrdOssSys::ConfigStats(XrdSysError &Eroute)
00810 {
00811    struct StatsDev
00812          {StatsDev *Next;
00813           dev_t     st_dev;
00814           StatsDev(StatsDev *dP, dev_t dn) : Next(dP), st_dev(dn) {}
00815          };
00816 
00817    XrdOssCache_Group  *fsg = XrdOssCache_Group::fsgroups;
00818    XrdOucPList        *fP = RPList.First();
00819    StatsDev           *dP1st = 0, *dP, *dPp;
00820    struct stat         Stat;
00821    char LPath[MAXPATHLEN+1], PPath[MAXPATHLEN+1], *cP;
00822 
00823 // Count actual cache groups
00824 //
00825    while(fsg) {numCG++; fsg = fsg->next;}
00826 
00827 // Develop the list of paths that we will report on
00828 //
00829    if (fP) do
00830       {strcpy(LPath, fP->Path());
00831        if (GenLocalPath(LPath, PPath)) continue;
00832        if (stat(PPath, &Stat) && (cP = rindex(LPath, '/')))
00833           {*cP = '\0';
00834            if (GenLocalPath(LPath, PPath) || stat(PPath, &Stat)) continue;
00835           }
00836        dP = dP1st;
00837        while(dP && dP->st_dev != Stat.st_dev) dP = dP->Next;
00838        if (dP) continue;
00839        ConfigStats(Stat.st_dev, LPath);
00840        if (GenLocalPath(LPath, PPath)) continue;
00841        DPList = new OssDPath(DPList, strdup(LPath), strdup(PPath));
00842        lenDP += strlen(LPath) + strlen(PPath); numDP++;
00843        dP1st  = new StatsDev(dP1st, Stat.st_dev);
00844       } while ((fP = fP->Next()));
00845 
00846 // If we have no exported paths then create a simple /tmp object
00847 //
00848    if (!numDP)
00849       {DPList = new OssDPath(0, strdup("/tmp"), strdup("/tmp"));
00850        lenDP = 4; numDP = 1;
00851       }
00852 
00853 // Now delete all of the device objects
00854 //
00855    dP = dP1st;
00856    while(dP) {dPp = dP; dP = dP->Next; delete dPp;}
00857 }
00858   
00859 /******************************************************************************/
00860 
00861 void XrdOssSys::ConfigStats(dev_t Devnum, char *lP)
00862 {
00863    struct stat Stat;
00864    char *Slash, pP[MAXPATHLEN+1];
00865 
00866 // Minimize the path
00867 //
00868    while((Slash = rindex(lP+1, '/')))
00869         {*Slash = '\0';
00870          if (GenLocalPath(lP, pP) || stat(pP, &Stat) || Stat.st_dev != Devnum)
00871             break;
00872         }
00873 
00874 // Extend path if need be and return
00875 //
00876    if (Slash) *Slash = '/';
00877 }
00878   
00879 /******************************************************************************/
00880 /*                             C o n f i g X e q                              */
00881 /******************************************************************************/
00882 
00883 int XrdOssSys::ConfigXeq(char *var, XrdOucStream &Config, XrdSysError &Eroute)
00884 {
00885     char  myVar[80], buff[2048], *val;
00886     int nosubs;
00887     XrdOucEnv *myEnv = 0;
00888 
00889    TS_Ade("userprty",      OptFlags, XrdOss_USRPRTY, 0);
00890 
00891    TS_Xeq("alloc",         xalloc);
00892    TS_Xeq("cache",         xcache);
00893    TS_Xeq("cachescan",     xcachescan);
00894    TS_Xeq("compdetect",    xcompdct);
00895    TS_Xeq("defaults",      xdefault);
00896    TS_Xeq("fdlimit",       xfdlimit);
00897    TS_Xeq("maxsize",       xmaxsz);
00898    TS_Xeq("memfile",       xmemf);
00899    TS_Xeq("namelib",       xnml);
00900    TS_Xeq("path",          xpath);
00901    TS_Xeq("space",         xspace);
00902    TS_Xeq("stagecmd",      xstg);
00903    TS_Xeq("trace",         xtrace);
00904    TS_Xeq("usage",         xusage);
00905    TS_Xeq("xfr",           xxfr);
00906 
00907    // Check if var substitutions are prohibited (e.g., stagemsg). Note that
00908    // TS_String() returns upon success so be careful when adding new opts.
00909    //
00910    if ((nosubs = !strcmp(var, "stagemsg"))) myEnv = Config.SetEnv(0);
00911 
00912    // Copy the variable name as this may change because it points to an
00913    // internal buffer in Config. The vagaries of effeciency.
00914    //
00915    strlcpy(myVar, var, sizeof(myVar));
00916    var = myVar;
00917 
00918    // We need to suck all the tokens to the end of the line for remaining
00919    // options. Do so, until we run out of space in the buffer.
00920    //
00921    if (!Config.GetRest(buff, sizeof(buff)))
00922       {Eroute.Emsg("Config", "arguments too long for", var);
00923        if (nosubs) Config.SetEnv(myEnv);
00924        return 1;
00925       }
00926    val = buff;
00927 
00928    // Restore substititions at this point if need be
00929    //
00930    if (nosubs) Config.SetEnv(myEnv);
00931 
00932    // At this point, make sure we have a value
00933    //
00934    if (!(*val))
00935       {Eroute.Emsg("Config", "no value for directive", var);
00936        return 1;
00937       }
00938 
00939    // Check for tokens taking a variable number of parameters
00940    //
00941    TS_String("localroot",  LocalRoot);
00942    TS_String("remoteroot", RemoteRoot);
00943    TS_String("stagemsg",   StageMsg);
00944 
00945    // The following differentiates between a deprecated and a preferred command
00946    //
00947    if (!strcmp("msscmd", var)) {isMSSC = 1; Duplicate(val, RSSCmd); return 0;}
00948    if (!strcmp("rsscmd", var)) {isMSSC = 0; Duplicate(val, RSSCmd); return 0;}
00949 
00950    // No match found, complain.
00951    //
00952    Eroute.Say("Config warning: ignoring unknown directive '",var,"'.");
00953    Config.Echo();
00954    return 0;
00955 }
00956 
00957 /******************************************************************************/
00958 /*                                x a l l o c                                 */
00959 /******************************************************************************/
00960 
00961 /* Function: aalloc
00962 
00963    Purpose:  To parse the directive: alloc <min> [<headroom> [<fuzz>]]
00964 
00965              <min>       minimum amount of free space needed in a partition.
00966                          (asterisk uses default).
00967              <headroom>  percentage of requested space to be added to the
00968                          free space amount (asterisk uses default).
00969              <fuzz>      the percentage difference between two free space
00970                          quantities that may be ignored when selecting a cache
00971                            0 - reduces to finding the largest free space
00972                          100 - reduces to simple round-robin allocation
00973 
00974    Output: 0 upon success or !0 upon failure.
00975 */
00976 
00977 int XrdOssSys::xalloc(XrdOucStream &Config, XrdSysError &Eroute)
00978 {
00979     char *val;
00980     long long mina = 0;
00981     int       fuzz = 0;
00982     int       hdrm = 0;
00983 
00984     if (!(val = Config.GetWord()))
00985        {Eroute.Emsg("Config", "alloc minfree not specified"); return 1;}
00986     if (strcmp(val, "*") &&
00987         XrdOuca2x::a2sz(Eroute, "alloc minfree", val, &mina, 0)) return 1;
00988 
00989     if ((val = Config.GetWord()))
00990        {if (strcmp(val, "*") &&
00991             XrdOuca2x::a2i(Eroute,"alloc headroom",val,&hdrm,0,100)) return 1;
00992 
00993         if ((val = Config.GetWord()))
00994            {if (strcmp(val, "*") &&
00995             XrdOuca2x::a2i(Eroute, "alloc fuzz", val, &fuzz, 0, 100)) return 1;
00996            }
00997        }
00998 
00999     minalloc = mina;
01000     ovhalloc = hdrm;
01001     fuzalloc = fuzz;
01002     return 0;
01003 }
01004 
01005 /******************************************************************************/
01006 /*                                x c a c h e                                 */
01007 /******************************************************************************/
01008 
01009 /* Function: xcache
01010 
01011    Purpose:  To parse the directive: cache <group> <path> [xa]
01012 
01013              <group>  logical group name for the cache filesystem.
01014              <path>   path to the cache.
01015              xa       support extended attributes
01016 
01017    Output: 0 upon success or !0 upon failure.
01018 */
01019 
01020 int XrdOssSys::xcache(XrdOucStream &Config, XrdSysError &Eroute)
01021 {
01022    int rc, isXA = 0;
01023 
01024 // Skip out to process this entry and upon success indicate that it is
01025 // deprecated and "space" should be used instead if an XA-style space defined.
01026 //
01027    if (!(rc = xspace(Config, Eroute, &isXA)) && isXA)
01028       Eroute.Say("Config warning: 'oss.cache' is deprecated; "
01029                                  "use 'oss.space' instead!");
01030     return rc;
01031 }
01032 
01033 /******************************************************************************/
01034 /*                              x c o m p d c t                               */
01035 /******************************************************************************/
01036 
01037 /* Function: xcompdct
01038 
01039    Purpose:  To parse the directive: compdetect { * | <sfx>}
01040 
01041              *        perform autodetect for compression
01042              <sfx>    path suffix to indicate that file is compressed
01043 
01044    Output: 0 upon success or !0 upon failure.
01045 */
01046 
01047 int XrdOssSys::xcompdct(XrdOucStream &Config, XrdSysError &Eroute)
01048 {
01049     char *val;
01050 
01051     if (!(val = Config.GetWord()))
01052        {Eroute.Emsg("Config", "compdetect suffix not specified"); return 1;}
01053 
01054     if (CompSuffix) free(CompSuffix);
01055     CompSuffix = 0; CompSuflen = 0;
01056 
01057     if (!strcmp("*", val))
01058        {CompSuffix = strdup(val); CompSuflen = strlen(val);}
01059 
01060     return 0;
01061 }
01062 
01063 /******************************************************************************/
01064 /*                            x c a c h e s c a n                             */
01065 /******************************************************************************/
01066 
01067 /* Function: xcachescan
01068 
01069    Purpose:  To parse the directive: cachescan <num>
01070 
01071              <num>     number of seconds between cache scans.
01072 
01073    Output: 0 upon success or !0 upon failure.
01074 */
01075 int XrdOssSys::xcachescan(XrdOucStream &Config, XrdSysError &Eroute)
01076 {   int cscan = 0;
01077     char *val;
01078 
01079     if (!(val = Config.GetWord()))
01080        {Eroute.Emsg("Config", "cachescan not specified"); return 1;}
01081     if (XrdOuca2x::a2tm(Eroute, "cachescan", val, &cscan, 30)) return 1;
01082     cscanint = cscan;
01083     return 0;
01084 }
01085 
01086 /******************************************************************************/
01087 /*                              x d e f a u l t                               */
01088 /******************************************************************************/
01089 
01090 /* Function: xdefault
01091 
01092    Purpose:  Parse: defaults <default options>
01093                               
01094    Notes: See the oss configuration manual for the meaning of each option.
01095           The actual implementation is defined in XrdOucExport.
01096 
01097    Output: 0 upon success or !0 upon failure.
01098 */
01099 
01100 int XrdOssSys::xdefault(XrdOucStream &Config, XrdSysError &Eroute)
01101 {
01102    DirFlags = XrdOucExport::ParseDefs(Config, Eroute, DirFlags);
01103    return 0;
01104 }
01105   
01106 /******************************************************************************/
01107 /*                              x f d l i m i t                               */
01108 /******************************************************************************/
01109 
01110 /* Function: xfdlimit
01111 
01112    Purpose:  To parse the directive: fdlimit <fence> [ <max> ]
01113 
01114              <fence>  lowest number to use for file fd's (0 -> max). If
01115                       specified as * then max/2 is used.
01116              <max>    highest number that can be used. The soft rlimit is set
01117                       to this value. If not supplied, the limit is not changed.
01118                       If supplied as 'max' then the hard limit is used.
01119 
01120    Output: 0 upon success or !0 upon failure.
01121 */
01122 
01123 int XrdOssSys::xfdlimit(XrdOucStream &Config, XrdSysError &Eroute)
01124 {
01125     char *val;
01126     int fence = 0, fdmax = XrdOssFDLIMIT;
01127 
01128       if (!(val = Config.GetWord()))
01129          {Eroute.Emsg("Config", "fdlimit fence not specified"); return 1;}
01130 
01131       if (!strcmp(val, "*")) fence = -1;
01132          else if (XrdOuca2x::a2i(Eroute,"fdlimit fence",val,&fence,0)) return 1;
01133 
01134       if (!(val = Config.GetWord())) fdmax = -1;
01135          else if (!strcmp(val, "max")) fdmax = Hard_FD_Limit;
01136                  else if (XrdOuca2x::a2i(Eroute, "fdlimit value", val, &fdmax,
01137                               xrdmax(fence,XrdOssFDMINLIM))) return -EINVAL;
01138                          else if (fdmax > Hard_FD_Limit)
01139                                  {fdmax = Hard_FD_Limit;
01140                                   Eroute.Say("Config warning: ",
01141                                               "'fdlimit' forced to hard max");
01142                                  }
01143       FDFence = fence;
01144       FDLimit = fdmax;
01145       return 0;
01146 }
01147   
01148 /******************************************************************************/
01149 /*                                x m a x s z                                 */
01150 /******************************************************************************/
01151 
01152 /* Function: xmaxsz
01153 
01154    Purpose:  Parse the directive:  maxsize <num>
01155 
01156              <num> Maximum number of bytes in a file.
01157 
01158    Output: 0 upon success or !0 upon failure.
01159 */
01160 
01161 int XrdOssSys::xmaxsz(XrdOucStream &Config, XrdSysError &Eroute)
01162 {   long long msz;
01163     char *val;
01164 
01165     if (!(val = Config.GetWord()))
01166        {Eroute.Emsg("Config", "maxsize value not specified"); return 1;}
01167     if (XrdOuca2x::a2sz(Eroute, "maxsize", val, &msz, 1024*1024)) return 1;
01168     MaxSize = msz;
01169     return 0;
01170 }
01171 
01172 /******************************************************************************/
01173 /*                                 x m e m f                                  */
01174 /******************************************************************************/
01175   
01176 /* Function: xmemf
01177 
01178    Purpose:  Parse the directive: memfile [off] [max <msz>]
01179                                           [check {keep | lock | map}] [preload]
01180 
01181              check keep Maps files that have ".mkeep" shadow file, premanently.
01182              check lock Maps and locks files that have ".mlock" shadow file.
01183              check map  Maps files that have ".mmap" shadow file.
01184              all        Preloads the complete file into memory.
01185              off        Disables memory mapping regardless of other options.
01186              on         Enables memory mapping
01187              preload    Preloads the file after every opn reference.
01188              <msz>      Maximum amount of memory to use (can be n% or real mem).
01189 
01190    Output: 0 upon success or !0 upon failure.
01191 */
01192 
01193 int XrdOssSys::xmemf(XrdOucStream &Config, XrdSysError &Eroute)
01194 {
01195     char *val;
01196     int i, j, V_autolok=-1, V_automap=-1, V_autokeep=-1, V_preld = -1, V_on=-1;
01197     long long V_max = 0;
01198 
01199     static struct mmapopts {const char *opname; int otyp;
01200                             const char *opmsg;} mmopts[] =
01201        {
01202         {"off",        0, ""},
01203         {"preload",    1, "memfile preload"},
01204         {"check",      2, "memfile check"},
01205         {"max",        3, "memfile max"}};
01206     int numopts = sizeof(mmopts)/sizeof(struct mmapopts);
01207 
01208     if (!(val = Config.GetWord()))
01209        {Eroute.Emsg("Config", "memfile option not specified"); return 1;}
01210 
01211     while (val)
01212          {for (i = 0; i < numopts; i++)
01213               if (!strcmp(val, mmopts[i].opname)) break;
01214           if (i >= numopts)
01215              Eroute.Say("Config warning: ignoring invalid memfile option '",val,"'.");
01216              else {if (mmopts[i].otyp >  1 && !(val = Config.GetWord()))
01217                       {Eroute.Emsg("Config","memfile",mmopts[i].opname,
01218                                    "value not specified");
01219                        return 1;
01220                       }
01221                    switch(mmopts[i].otyp)
01222                          {case 1: V_preld = 1;
01223                                   break;
01224                           case 2:     if (!strcmp("lock", val)) V_autolok=1;
01225                                  else if (!strcmp("map",  val)) V_automap=1;
01226                                  else if (!strcmp("keep", val)) V_autokeep=1;
01227                                  else {Eroute.Emsg("Config",
01228                                        "mmap auto neither keep, lock, nor map");
01229                                        return 1;
01230                                       }
01231                                   break;
01232                           case 3: j = strlen(val);
01233                                   if (val[j-1] == '%')
01234                                      {val[j-1] = '\0';
01235                                       if (XrdOuca2x::a2i(Eroute,mmopts[i].opmsg,
01236                                                      val, &j, 1, 1000)) return 1;
01237                                       V_max = -j;
01238                                      } else if (XrdOuca2x::a2sz(Eroute,
01239                                                 mmopts[i].opmsg, val, &V_max,
01240                                                 10*1024*1024)) return 1;
01241                                   break;
01242                           default: V_on = 0; break;
01243                          }
01244                   val = Config.GetWord();
01245                  }
01246          }
01247 
01248 // Set the values
01249 //
01250    XrdOssMio::Set(V_on, V_preld, V_autolok, V_automap, V_autokeep);
01251    XrdOssMio::Set(V_max);
01252    return 0;
01253 }
01254 
01255 /******************************************************************************/
01256 /*                                  x n m l                                   */
01257 /******************************************************************************/
01258 
01259 /* Function: xnml
01260 
01261    Purpose:  To parse the directive: namelib <path> [<parms>]
01262 
01263              <path>    the path of the filesystem library to be used.
01264              <parms>   optional parms to be passed
01265 
01266   Output: 0 upon success or !0 upon failure.
01267 */
01268 
01269 int XrdOssSys::xnml(XrdOucStream &Config, XrdSysError &Eroute)
01270 {
01271     char *val, parms[1040];
01272 
01273 // Get the path
01274 //
01275    if (!(val = Config.GetWord()) || !val[0])
01276       {Eroute.Emsg("Config", "namelib not specified"); return 1;}
01277 
01278 // Record the path
01279 //
01280    if (N2N_Lib) free(N2N_Lib);
01281    N2N_Lib = strdup(val);
01282 
01283 // Record any parms
01284 //
01285    if (!Config.GetRest(parms, sizeof(parms)))
01286       {Eroute.Emsg("Config", "namelib parameters too long"); return 1;}
01287    if (N2N_Parms) free(N2N_Parms);
01288    N2N_Parms = (*parms ? strdup(parms) : 0);
01289    return 0;
01290 }
01291 
01292 /******************************************************************************/
01293 /*                                 x p a t h                                  */
01294 /******************************************************************************/
01295 
01296 /* Function: xpath
01297 
01298    Purpose:  To parse the directive: {export | path} <path> [<options>]
01299 
01300              <path>    the full path that resides in a remote system.
01301              <options> a blank separated list of options (see XrdOucExport)
01302 
01303    Output: 0 upon success or !0 upon failure.
01304 */
01305 
01306 int XrdOssSys::xpath(XrdOucStream &Config, XrdSysError &Eroute)
01307 {
01308     XrdOucPList *plp, *olp;
01309     unsigned long long Opts;
01310 
01311 // Parse the arguments
01312 //
01313    if (!(plp = XrdOucExport::ParsePath(Config, Eroute, DirFlags))) return 1;
01314 
01315 // Check if this path is being modified or added. For modifications, turn off
01316 // all bitsin the old path specified in the new path and then set the new bits.
01317 //
01318    if (!(olp = RPList.Match(plp->Path()))) RPList.Insert(plp);
01319       else {Opts = plp->Flag() >> XRDEXP_MASKSHIFT;
01320             Opts = olp->Flag() & ~Opts;
01321             olp->Set(Opts | plp->Flag());
01322             delete plp;
01323            }
01324    return 0;
01325 }
01326 
01327 /******************************************************************************/
01328 /*                                x s p a c e                                 */
01329 /******************************************************************************/
01330 
01331 /* Function: xspace
01332 
01333    Purpose:  To parse the directive: space <name> <path>
01334 
01335              <name>   logical name for the filesystem.
01336              <path>   path to the filesystem.
01337 
01338    Output: 0 upon success or !0 upon failure.
01339 
01340    Note: This is the new and prefered way to say "cache <group> <path> xa".
01341 */
01342 
01343 int XrdOssSys::xspace(XrdOucStream &Config, XrdSysError &Eroute, int *isCD)
01344 {
01345    char *val, *pfxdir, *sfxdir;
01346    char grp[XrdOssSpace::minSNbsz], dn[XrdOssSpace::minSNbsz];
01347    char fn[MAXPATHLEN+1];
01348    int i, k, rc, pfxln, isxa = 0, cnum = 0;
01349    struct dirent *dp;
01350    struct stat buff;
01351    DIR *DFD;
01352 
01353 // Get the space name
01354 //
01355    if (!(val = Config.GetWord()))
01356       {Eroute.Emsg("Config", "space name not specified"); return 1;}
01357    if ((int)strlen(val) > XrdOssSpace::maxSNlen)
01358       {Eroute.Emsg("Config","excessively long space name - ",val); return 1;}
01359    strcpy(grp, val);
01360 
01361 // Get the path to the space
01362 //
01363    if (!(val = Config.GetWord()))
01364       {Eroute.Emsg("Config", "space path not specified"); return 1;}
01365 
01366    k = strlen(val);
01367    if (k >= (int)(sizeof(fn)-1) || val[0] != '/' || k < 2)
01368       {Eroute.Emsg("Config", "invalid space path - ", val); return 1;}
01369    strcpy(fn, val);
01370 
01371 // Additional options (for now) are only available to the old-style cache
01372 // directive. So, ignore any unless we entered via the directive.
01373 //
01374    if (isCD)
01375       {if ((val = Config.GetWord()))
01376           {if (strcmp("xa", val))
01377               {Eroute.Emsg("Config","invalid cache option - ",val); return 1;}
01378               else *isCD = isxa = 1;
01379           } else   *isCD = 0;
01380       } else isxa = 1;
01381 
01382 // Check if any directory in the parent can be used for space
01383 //
01384    if (fn[k-1] != '*')
01385       {for (i = k-1; i; i--) if (fn[i] != '/') break;
01386        fn[i+1] = '/'; fn[i+2] = '\0';
01387        return !xspaceBuild(grp, fn, isxa, Eroute);
01388       }
01389 
01390 // We now need to build a space for each directory
01391 //
01392    for (i = k-1; i; i--) if (fn[i] == '/') break;
01393    i++; strcpy(dn, &fn[i]); fn[i] = '\0';
01394    sfxdir = &fn[i]; pfxdir = dn; pfxln = strlen(dn)-1;
01395    if (!(DFD = opendir(fn)))
01396       {Eroute.Emsg("Config", errno, "open space directory", fn); return 1;}
01397 
01398    errno = 0;
01399    while((dp = readdir(DFD)))
01400         {if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")
01401          || (pfxln && strncmp(dp->d_name, pfxdir, pfxln)))
01402             continue;
01403          strcpy(sfxdir, dp->d_name);
01404          if (stat(fn, &buff)) break;
01405          if ((buff.st_mode & S_IFMT) == S_IFDIR)
01406             {val = sfxdir + strlen(sfxdir) - 1;
01407             if (*val++ != '/') {*val++ = '/'; *val = '\0';}
01408             if (xspaceBuild(grp, fn, isxa, Eroute)) cnum++;
01409                else {closedir(DFD); return 1;}
01410             }
01411          errno = 0;
01412         }
01413 
01414 // Make sure we built all space successfully and have at least one space
01415 //
01416    if ((rc = errno))
01417       Eroute.Emsg("Config", errno, "process space directory", fn);
01418       else if (!cnum) Eroute.Say("Config warning: no space directories found in ",val);
01419 
01420    closedir(DFD);
01421    return rc != 0;
01422 }
01423 
01424 int XrdOssSys::xspaceBuild(char *grp, char *fn, int isxa, XrdSysError &Eroute)
01425 {
01426     XrdOssCache_FS::FSOpts fopts = (isxa ? XrdOssCache_FS::isXA
01427                                          : XrdOssCache_FS::None);
01428     XrdOssCache_FS *fsp;
01429     int rc = 0;
01430     if (!(fsp = new XrdOssCache_FS(rc, grp, fn, fopts))) rc = ENOMEM;
01431     if (rc)
01432        {Eroute.Emsg("Config", rc, "create space", fn);
01433         if (fsp) delete fsp;
01434         return 0;
01435        }
01436     OptFlags |= XrdOss_CacheFS;
01437     return 1;
01438 }
01439 
01440 /******************************************************************************/
01441 /*                                  x s t g                                   */
01442 /******************************************************************************/
01443 
01444 /* Function: xstg
01445 
01446    Purpose:  To parse the directive: 
01447                 stagecmd [async | sync] [creates] [|]<cmd>
01448 
01449              async     Client is to be notified when <cmd> sends an event
01450              sync      Client is to poll for <cmd> completion.
01451              creates   Route file creation requests to <cmd>.
01452              <cmd>     The command and args to stage in the file. If the
01453                        <cmd> is prefixed ny '|' then pipe in the requests.
01454 
01455   Output: 0 upon success or !0 upon failure.
01456 */
01457 
01458 int XrdOssSys::xstg(XrdOucStream &Config, XrdSysError &Eroute)
01459 {
01460     char *val, buff[2048], *bp = buff;
01461     int vlen, blen = sizeof(buff)-1, isAsync = 0, isCreate = 0;
01462 
01463 // Get the aync or async option
01464 //
01465    if ((val = Config.GetWord()))
01466        if ((isAsync = !strcmp(val, "async")) || !strcmp(val, "sync"))
01467           val = Config.GetWord();
01468 
01469 // Get the create option
01470 //
01471    if (val)
01472        if ((isCreate = !strcmp(val, "creates"))) val = Config.GetWord();
01473 
01474 // Get the command
01475 //
01476    if (!val) {Eroute.Emsg("Config", "stagecmd not specified"); return 1;}
01477 
01478 // Copy the command and all of it's arguments
01479 //
01480    do {if ((vlen = strlen(val)) >= blen)
01481           {Eroute.Emsg("Config", "stagecmd arguments too long"); break;}
01482        *bp = ' '; bp++; strcpy(bp, val); bp += vlen; blen -= vlen;
01483       } while((val = Config.GetWord()));
01484 
01485     if (val) return 1;
01486     *bp = '\0'; val = buff+1;
01487 
01488 // Record the command and operating mode
01489 //
01490    StageAsync = (isAsync ? 1 : 0);
01491    StageCreate= isCreate;
01492    if (StageCmd) free(StageCmd);
01493    StageCmd = strdup(val);
01494    return 0;
01495 }
01496 
01497   
01498 /******************************************************************************/
01499 /*                                x t r a c e                                 */
01500 /******************************************************************************/
01501 
01502 /* Function: xtrace
01503 
01504    Purpose:  To parse the directive: trace <events>
01505 
01506              <events> the blank separated list of events to trace. Trace
01507                       directives are cummalative.
01508 
01509    Output: retc upon success or -EINVAL upon failure.
01510 */
01511 
01512 int XrdOssSys::xtrace(XrdOucStream &Config, XrdSysError &Eroute)
01513 {
01514     char *val;
01515     static struct traceopts {const char *opname; int opval;} tropts[] =
01516        {
01517         {"all",      TRACE_ALL},
01518         {"debug",    TRACE_Debug},
01519         {"open",     TRACE_Open},
01520         {"opendir",  TRACE_Opendir}
01521        };
01522     int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
01523 
01524     if (!(val = Config.GetWord()))
01525        {Eroute.Emsg("Config", "trace option not specified"); return 1;}
01526     while (val)
01527          {if (!strcmp(val, "off")) trval = 0;
01528              else {if ((neg = (val[0] == '-' && val[1]))) val++;
01529                    for (i = 0; i < numopts; i++)
01530                        {if (!strcmp(val, tropts[i].opname))
01531                            {if (neg) trval &= ~tropts[i].opval;
01532                                else  trval |=  tropts[i].opval;
01533                             break;
01534                            }
01535                        }
01536                    if (i >= numopts)
01537                       Eroute.Say("Config warning: ignoring invalid trace option '",val,"'.");
01538                   }
01539           val = Config.GetWord();
01540          }
01541     OssTrace.What = trval;
01542     return 0;
01543 }
01544 
01545 /******************************************************************************/
01546 /*                                x u s a g e                                 */
01547 /******************************************************************************/
01548 
01549 /* Function: xusage
01550 
01551    Purpose:  To parse the directive: usage <parms>
01552 
01553              <parms>: [nolog | log <path>] [noquotafile | quotafile <qfile>]
01554 
01555              nolog    does not save usage info across restarts
01556              log      saves usages information in the <path> directory
01557              qfile    where the quota file resides.
01558 
01559    Output: 0 upon success or !0 upon failure.
01560 */
01561 
01562 int XrdOssSys::xusage(XrdOucStream &Config, XrdSysError &Eroute)
01563 {
01564     char *val;
01565 
01566     if (!(val = Config.GetWord()))
01567        {Eroute.Emsg("Config", "usage option not specified"); return 1;}
01568 
01569     while(val)
01570          {     if (!strcmp("nolog", val))
01571                   {if (UDir)  {free(UDir);  UDir = 0;}}
01572           else if (!strcmp("log"  , val))
01573                   {if (UDir)  {free(UDir);  UDir = 0;}
01574                    if (!(val = Config.GetWord()))
01575                       {Eroute.Emsg("Config", "usage log path not specified");
01576                        return 1;
01577                       }
01578                    if (*val != '/')
01579                       {Eroute.Emsg("Config", "usage log path not absolute");
01580                        return 1;
01581                       }
01582                    UDir = strdup(val);
01583                   }
01584           else if (!strcmp("noquotafile",val))
01585                   {if (QFile) {free(QFile); QFile= 0;}}
01586           else if (!strcmp("quotafile",val))
01587                   {if (QFile) {free(QFile); QFile= 0;}
01588                    if (!(val = Config.GetWord()))
01589                       {Eroute.Emsg("Config", "quota file not specified");
01590                        return 1;
01591                       }
01592                    QFile = strdup(val);
01593                   }
01594           else {Eroute.Emsg("Config", "invalid usage option -",val); return 1;}
01595 
01596           val = Config.GetWord();
01597          }
01598     return 0;
01599 }
01600 
01601 /******************************************************************************/
01602 /*                                  x x f r                                   */
01603 /******************************************************************************/
01604   
01605 /* Function: xxfr
01606 
01607    Purpose:  To parse the directive: xfr [deny <sec>] [keep <sec>] [up]
01608                                          [<threads> [<speed> [<ovhd> [<hold>]]]]
01609 
01610              keep      number of seconds to keep queued requests
01611              <threads> number of threads for staging (* uses default).
01612 
01613 The following are deprecated and allowed for backward compatability:
01614 
01615              <speed>   average speed in bytes/second (* uses default).
01616              <ovhd>    minimum seconds of overhead (* uses default).
01617              <hold>    seconds to hold failing requests (* uses default).
01618 
01619    Output: 0 upon success or !0 upon failure.
01620 */
01621 
01622 int XrdOssSys::xxfr(XrdOucStream &Config, XrdSysError &Eroute)
01623 {
01624     char *val;
01625     int       thrds = 1;
01626     long long speed = 9*1024*1024;
01627     int       ovhd  = 30;
01628     int       htime = 3*60*60;
01629     int       ktime;
01630     int       haveparm = 0;
01631     int       upon = 0;
01632 
01633     while((val = Config.GetWord()))        // deny | keep
01634          {     if (!strcmp("deny", val))
01635                   {if ((val = Config.GetWord()))     // keep time
01636                       {if (XrdOuca2x::a2tm(Eroute,"xfr deny",val,&htime,0))
01637                           return 1;
01638                        haveparm=1;
01639                       }
01640                   }
01641           else if (!strcmp("keep", val))
01642                   {if ((val = Config.GetWord()))     // keep time
01643                       {if (XrdOuca2x::a2tm(Eroute,"xfr keep",val,&ktime,0))
01644                           return 1;
01645                        xfrkeep=ktime; haveparm=1;
01646                       }
01647                   }
01648           else if (!strcmp("up", val)) {upon = 1; haveparm = 1;}
01649           else break;
01650          };
01651 
01652     if (!val) {if (haveparm) return 0;
01653                   else {Eroute.Emsg("Config", "xfr parameter not specified");
01654                         return 1;
01655                        }
01656               }
01657 
01658       if (strcmp(val, "*") && XrdOuca2x::a2i(Eroute,"xfr threads",val,&thrds,1))
01659          return 1;
01660 
01661       if ((val = Config.GetWord()))         // <speed>
01662          {if (strcmp(val, "*") && 
01663               XrdOuca2x::a2sz(Eroute,"xfr speed",val,&speed,1024)) return 1;
01664 
01665           if ((val = Config.GetWord()))     // <ovhd>
01666              {if (strcmp(val, "*") && 
01667                   XrdOuca2x::a2tm(Eroute,"xfr overhead",val,&ovhd,0)) return 1;
01668 
01669               if ((val = Config.GetWord())) // <hold>
01670                  if (strcmp(val, "*") && 
01671                     XrdOuca2x::a2tm(Eroute,"xfr hold",val,&htime,0)) return 1;
01672              }
01673          }
01674 
01675       xfrthreads = thrds;
01676       xfrspeed   = speed;
01677       xfrovhd    = ovhd;
01678       xfrhold    = htime;
01679       if (upon) OptFlags |= XrdOss_USRPRTY;
01680       return 0;
01681 }
01682 
01683 /******************************************************************************/
01684 /*                            L i s t _ P a t h                               */
01685 /******************************************************************************/
01686   
01687 void XrdOssSys::List_Path(const char *pfx, const char *pname,
01688                           unsigned long long flags, XrdSysError &Eroute)
01689 {
01690      char buff[4096], *rwmode;
01691 
01692      if (flags & XRDEXP_FORCERO) rwmode = (char *)" forcero";
01693         else if (flags & XRDEXP_READONLY) rwmode = (char *)" r/o ";
01694                 else rwmode = (char *)" r/w ";
01695                                  // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
01696      snprintf(buff, sizeof(buff), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
01697               pfx, pname,                                           // 0
01698               (flags & XRDEXP_COMPCHK  ?  " compchk" : ""),         // 1
01699               rwmode,                                               // 2
01700               (flags & XRDEXP_INPLACE  ? " inplace" : ""),          // 3
01701               (flags & XRDEXP_LOCAL    ? " local"   : ""),          // 4
01702               (flags & XRDEXP_GLBLRO   ? " globalro": ""),          // 5
01703               (flags & XRDEXP_NOCHECK  ? " nocheck" : " check"),    // 6
01704               (flags & XRDEXP_NODREAD  ? " nodread" : " dread"),    // 7
01705               (flags & XRDEXP_MIG      ? " mig"     : " nomig"),    // 8
01706      (!(flags & XRDEXP_MMAP)           ? ""         :               // 9
01707               (flags & XRDEXP_MKEEP    ? " mkeep"   : " nomkeep")),
01708      (!(flags & XRDEXP_MMAP)           ? ""         :               // 10
01709               (flags & XRDEXP_MLOK     ? " mlock"   : " nomlock")),
01710               (flags & XRDEXP_MMAP     ? " mmap"    : ""),          // 11
01711               (flags & XRDEXP_RCREATE  ? " rcreate" : " norcreate"),// 12
01712               (flags & XRDEXP_PURGE    ? " purge"   : " nopurge"),  // 13
01713               (flags & XRDEXP_STAGE    ? " stage"   : " nostage")   // 14
01714               );
01715      Eroute.Say(buff); 
01716 }

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