XrdPssConfig.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                       X r d P s 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 #include <unistd.h>
00012 #include <ctype.h>
00013 #include <stdio.h>
00014 #include <string.h>
00015 #include <strings.h>
00016 #include <sys/param.h>
00017 #include <sys/socket.h>
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 #include <sys/un.h>
00021 #include <fcntl.h>
00022 
00023 #include "XrdFfs/XrdFfsDent.hh"
00024 #include "XrdFfs/XrdFfsMisc.hh"
00025 #include "XrdFfs/XrdFfsWcache.hh"
00026 #include "XrdFfs/XrdFfsQueue.hh"
00027 
00028 #include "XrdPss/XrdPss.hh"
00029 
00030 #include "XrdOuc/XrdOuca2x.hh"
00031 #include "XrdOuc/XrdOucEnv.hh"
00032 
00033 #include "XrdSys/XrdSysError.hh"
00034 #include "XrdSys/XrdSysHeaders.hh"
00035 #include "XrdSys/XrdSysPlatform.hh"
00036 
00037 #include "XrdOuc/XrdOucStream.hh"
00038 #include "XrdOuc/XrdOucTList.hh"
00039 #include "XrdOuc/XrdOucUtils.hh"
00040 
00041 #include "XrdNet/XrdNetDNS.hh"
00042 
00043 #include "XrdPosix/XrdPosixXrootd.hh"
00044 
00045 /******************************************************************************/
00046 /*                               d e f i n e s                                */
00047 /******************************************************************************/
00048 
00049 #define TS_Xeq(x,m)    if (!strcmp(x,var)) return m(&eDest, Config);
00050 
00051 /******************************************************************************/
00052 /*                               G l o b a l s                                */
00053 /******************************************************************************/
00054 
00055 const char  *XrdPssSys::ConfigFN;       // -> Pointer to the config file name
00056 const char  *XrdPssSys::myHost;
00057 const char  *XrdPssSys::myName;
00058 uid_t        XrdPssSys::myUid     =  geteuid();
00059 gid_t        XrdPssSys::myGid     =  getegid();
00060 
00061 XrdOucTList *XrdPssSys::ManList   =  0;
00062 const char  *XrdPssSys::urlPlain  =  0;
00063 int          XrdPssSys::urlPlen   =  0;
00064 int          XrdPssSys::hdrLen    =  0;
00065 const char  *XrdPssSys::hdrData   =  0;
00066 int          XrdPssSys::Workers   = 16;
00067 
00068 char         XrdPssSys::allChmod  =  0;
00069 char         XrdPssSys::allMkdir  =  0;
00070 char         XrdPssSys::allMv     =  0;
00071 char         XrdPssSys::allRm     =  0;
00072 char         XrdPssSys::allRmdir  =  0;
00073 char         XrdPssSys::allTrunc  =  0;
00074 
00075 namespace XrdProxy
00076 {
00077 static XrdPosixXrootd  *Xroot;
00078   
00079 extern XrdSysError      eDest;
00080 
00081 static const int maxHLen = 1024;
00082 }
00083 
00084 using namespace XrdProxy;
00085 
00086 /******************************************************************************/
00087 /*                             C o n f i g u r e                              */
00088 /******************************************************************************/
00089   
00090 int XrdPssSys::Configure(const char *cfn)
00091 {
00092 /*
00093   Function: Establish configuration at start up time.
00094 
00095   Input:    None.
00096 
00097   Output:   0 upon success or !0 otherwise.
00098 */
00099    struct {const char *Typ; char *Loc;} Fwd[] = {{" ch", &allChmod},
00100                                                  {" mk", &allMkdir},
00101                                                  {" mv", &allMv   },
00102                                                  {" rd", &allRmdir},
00103                                                  {" rm", &allRm   },
00104                                                  {" tr", &allTrunc},
00105                                                  {0,     0        }
00106                                                 };
00107    const char *xP;
00108    char *eP, theRdr[maxHLen+1024];
00109    int i, NoGo = 0;
00110 
00111 // Preset tracing options
00112 //
00113    if (getenv("XRDDEBUG")) XrdPosixXrootd::setDebug(1);
00114    myHost = getenv("XRDHOST");
00115    myName = XrdOucUtils::InstName(1);
00116 
00117 // Set the default values for the client
00118 //
00119    XrdPosixXrootd::setEnv("ReadAheadSize",           1024*1024);
00120    XrdPosixXrootd::setEnv("ReadCacheSize",       512*1024*1024);
00121    XrdPosixXrootd::setEnv("ParStreamsPerPhyConn",            2);
00122    XrdPosixXrootd::setEnv("PurgeWrittenBlocks",              1);
00123    XrdPosixXrootd::setEnv("DataServerConn_ttl",          20*60);
00124    XrdPosixXrootd::setEnv("LBServerConn_ttl",            60*60);
00125 
00126 // Process the configuration file
00127 //
00128    if ((NoGo = ConfigProc(cfn))) return NoGo;
00129 
00130 // Build the URL header
00131 //
00132    if (!ManList)
00133       {eDest.Emsg("Config", "Origin for proxy service not specified.");
00134        return 1;
00135       }
00136    if (buildHdr()) return 1;
00137 
00138 // Copy out the forwarding that might be happening via the ofs
00139 //
00140    i = 0;
00141    if ((eP = getenv("XRDOFS_FWD")))
00142       while(Fwd[i].Typ)
00143            {if (!strstr(eP, Fwd[i].Typ)) *(Fwd[i].Loc) = 1; i++;}
00144 
00145 // Create a plain url for future use
00146 //
00147    urlPlen = sprintf(theRdr, hdrData, "", "", "", "", "", "", "", "");
00148    urlPlain= strdup(theRdr);
00149 
00150 // We would really like that the Ffs interface use the generic method of
00151 // keeping track of data servers. It does not and it even can't handle more
00152 // than one export (really). But it does mean we need to give it a valid one.
00153 //
00154    if (!(eP = getenv("XRDEXPORTS")) || *eP != '/') xP = "/tmp";
00155       else if ((xP = rindex(eP, ' '))) xP++;
00156               else xP = eP;
00157 
00158 // Initialize the Ffs (we don't use xrd_init() as it messes up the settings
00159 // We also do not initialize secsss as we don't know how to effectively use it.
00160 //
00161    strcpy(&theRdr[urlPlen], xP);
00162 // XrdFfsMisc_xrd_secsss_init();
00163    XrdFfsMisc_refresh_url_cache(theRdr);
00164    XrdFfsDent_cache_init();
00165    XrdFfsWcache_init();
00166    XrdFfsQueue_create_workers(Workers);
00167 
00168 // Allocate an Xroot proxy object (only one needed here). Tell it to not
00169 // shadow open files with real file descriptors (we will be honest).
00170 //
00171    Xroot = new XrdPosixXrootd(-32768, 16384);
00172    return 0;
00173 }
00174 
00175 /******************************************************************************/
00176 /*                     P r i v a t e   F u n c t i o n s                      */
00177 /******************************************************************************/
00178 /******************************************************************************/
00179 /*                              b u i l d H d r                               */
00180 /******************************************************************************/
00181   
00182 int XrdPssSys::buildHdr()
00183 {
00184    XrdOucTList *tp = ManList;
00185    char buff[maxHLen], *pb;
00186    int n, bleft = sizeof(buff);
00187 
00188 // Fill in start of header
00189 //
00190    strcpy(buff, "root://"); pb = buff+strlen(buff); bleft -= strlen(buff);
00191 
00192 // The redirector list must fit into 1K bytes (along with header)
00193 //
00194    while(tp)
00195         {n = snprintf(pb, bleft, "%%s%s:%d%c", tp->text, tp->val,
00196                                               (tp->next ? ',':'/'));
00197          if (n >= bleft) break;
00198          pb += n; bleft -= n;
00199          tp = tp->next;
00200         }
00201 
00202    if (tp)
00203       {eDest.Emsg("Config", "Too many proxy service managers specified.");
00204        return 1;
00205       }
00206 
00207    hdrData = strdup(buff);
00208    hdrLen  = strlen(buff);
00209    return 0;
00210 }
00211 
00212 /******************************************************************************/
00213 /*                            C o n f i g P r o c                             */
00214 /******************************************************************************/
00215   
00216 int XrdPssSys::ConfigProc(const char *Cfn)
00217 {
00218   char *var;
00219   int  cfgFD, retc, NoGo = 0;
00220   XrdOucEnv myEnv;
00221   XrdOucStream Config(&eDest, getenv("XRDINSTANCE"), &myEnv, "=====> ");
00222 
00223 // Make sure we have a config file
00224 //
00225    if (!Cfn || !*Cfn)
00226       {eDest.Emsg("Config", "pss configuration file not specified.");
00227        return 1;
00228       }
00229 
00230 // Try to open the configuration file.
00231 //
00232    if ( (cfgFD = open(Cfn, O_RDONLY, 0)) < 0)
00233       {eDest.Emsg("Config", errno, "open config file", Cfn);
00234        return 1;
00235       }
00236    Config.Attach(cfgFD);
00237 
00238 // Now start reading records until eof.
00239 //
00240    while((var = Config.GetMyFirstWord()))
00241         {if (!strncmp(var, "pss.", 4))
00242             if (ConfigXeq(var+4, Config)) {Config.Echo(); NoGo = 1;}
00243         }
00244 
00245 // Now check if any errors occured during file i/o
00246 //
00247    if ((retc = Config.LastError()))
00248       NoGo = eDest.Emsg("Config", retc, "read config file", Cfn);
00249    Config.Close();
00250 
00251 // Return final return code
00252 //
00253    return NoGo;
00254 }
00255 
00256 /******************************************************************************/
00257 /*                             C o n f i g X e q                              */
00258 /******************************************************************************/
00259 
00260 int XrdPssSys::ConfigXeq(char *var, XrdOucStream &Config)
00261 {
00262 
00263    // Process items. for either a local or a remote configuration
00264    //
00265    TS_Xeq("config",        xconf);
00266    TS_Xeq("origin",        xorig);
00267    TS_Xeq("setopt",        xsopt);
00268    TS_Xeq("trace",         xtrac);
00269 
00270    // No match found, complain.
00271    //
00272    eDest.Say("Config warning: ignoring unknown directive '",var,"'.");
00273    Config.Echo();
00274    return 0;
00275 }
00276   
00277 /******************************************************************************/
00278 /*                                 x c o n f                                  */
00279 /******************************************************************************/
00280 
00281 /* Function: xconf
00282 
00283    Purpose:  To parse the directive: config <keyword> <value>
00284 
00285              <keyword> is one of the following:
00286              workers   number of queue workers > 0
00287 
00288    Output: 0 upon success or 1 upon failure.
00289 */
00290 
00291 int XrdPssSys::xconf(XrdSysError *Eroute, XrdOucStream &Config)
00292 {
00293    char  *val, *kvp;
00294    int    kval;
00295    struct Xtab {const char *Key; int *Val;} Xopts[] =
00296                {{"workers", &Workers}};
00297    int i, numopts = sizeof(Xopts)/sizeof(struct Xtab);
00298 
00299    if (!(val = Config.GetWord()))
00300       {Eroute->Emsg("Config", "options argument not specified."); return 1;}
00301 
00302 do{for (i = 0; i < numopts; i++) if (!strcmp(Xopts[i].Key, val)) break;
00303 
00304    if (i > numopts)
00305       Eroute->Say("Config warning: ignoring unknown config option '",val,"'.");
00306       else {if (!(val = Config.GetWord()))
00307                {Eroute->Emsg("Config", "config", val, "value not specified.");
00308                 return 1;
00309                }
00310 
00311             kval = strtol(val, &kvp, 10);
00312             if (*kvp || !kval)
00313                {Eroute->Emsg("Config", Xopts[i].Key, 
00314                              "config value is invalid -", val);
00315                 return 1;
00316                }
00317             *(Xopts[i].Val) = kval;
00318            }
00319    val = Config.GetWord();
00320   } while(val && *val);
00321 
00322    return 0;
00323 }
00324   
00325 /******************************************************************************/
00326 /*                                 x o r i g                                  */
00327 /******************************************************************************/
00328 
00329 /* Function: xorig
00330 
00331    Purpose:  Parse: origin <host>[+][:<port>|<port>]
00332 
00333    Output: 0 upon success or !0 upon failure.
00334 */
00335 
00336 int XrdPssSys::xorig(XrdSysError *errp, XrdOucStream &Config)
00337 {
00338     XrdOucTList *tp = 0;
00339     char *val, *mval = 0;
00340     int  i, port;
00341 
00342 //  We are looking for regular managers. These are our points of contact
00343 //
00344     if (!(val = Config.GetWord()))
00345        {errp->Emsg("Config","origin host name not specified"); return 1;}
00346        else mval = strdup(val);
00347 
00348 // Check if there is a port number. This could be as ':port' or ' port'.
00349 //
00350     if (!(val = index(mval,':'))) val = Config.GetWord();
00351        else {*val = '\0'; val++;}
00352 
00353 // Validate the port number
00354 //
00355     if (val)
00356        {if (isdigit(*val))
00357             {if (XrdOuca2x::a2i(*errp,"origin port",val,&port,1,65535))
00358                 port = 0;
00359             }
00360             else if (!(port = XrdNetDNS::getPort(val, "tcp")))
00361                     {errp->Emsg("Config", "unable to find tcp service", val);
00362                      port = 0;
00363                     }
00364        } else errp->Emsg("Config","origin port not specified for",mval);
00365 
00366 // If port is invalid or missing, fail this
00367 //
00368     if (!port) {free(mval); return 1;}
00369 
00370 // For proxies we need not expand 'host+' spec but need to supress the plus
00371 //
00372     if ((i = strlen(mval)) > 1 && mval[i-1] == '+') mval[i-1] = 0;
00373 
00374 // Check if this is a duplicate, if its new, add to the list
00375 //
00376    tp = ManList;
00377    while(tp && (strcmp(tp->text, mval) || tp->val != port)) tp = tp->next;
00378    if (tp) errp->Emsg("Config","Duplicate origin",mval);
00379       else ManList = new XrdOucTList(mval, port, ManList);
00380 
00381 // All done
00382 //
00383    free(mval);
00384    return tp != 0;
00385 }
00386   
00387 /******************************************************************************/
00388 /*                                 x s o p t                                  */
00389 /******************************************************************************/
00390 
00391 /* Function: xsopt
00392 
00393    Purpose:  To parse the directive: setopt <keyword> <value>
00394 
00395              <keyword> is an XrdClient option keyword.
00396              <value>   is the value the option is to have.
00397 
00398    Output: 0 upon success or !0 upon failure.
00399 */
00400 
00401 int XrdPssSys::xsopt(XrdSysError *Eroute, XrdOucStream &Config)
00402 {
00403     char  kword[256], *val, *kvp;
00404     long  kval;
00405     static const char *Sopts[] =
00406        {
00407          "ConnectTimeout",
00408          "DataServerConn_ttl",
00409          "DebugLevel",
00410          "DfltTcpWindowSize",
00411          "LBServerConn_ttl",
00412          "ParStreamsPerPhyConn",
00413          "ParStreamsPerPhyConn",
00414          "RedirCntTimeout",
00415          "ReadAheadSize",
00416          "ReadAheadStrategy",
00417          "ReadCacheBlkRemPolicy",
00418          "ReadCacheSize",
00419          "ReadTrimBlockSize",
00420          "ReconnectWait",
00421          "RemoveUsedCacheBlocks",
00422          "RequestTimeout",
00423          "TransactionTimeout"
00424        };
00425     int i, numopts = sizeof(Sopts)/sizeof(const char *);
00426 
00427     if (!(val = Config.GetWord()))
00428        {Eroute->Emsg("Config", "setopt keyword not specified"); return 1;}
00429     strlcpy(kword, val, sizeof(kword));
00430     if (!(val = Config.GetWord()))
00431        {Eroute->Emsg("Config", "setopt", kword, "value not specified");
00432         return 1;
00433        }
00434 
00435     kval = strtol(val, &kvp, 10);
00436     if (*kvp)
00437        {Eroute->Emsg("Config", kword, "setopt keyword value is invalid -", val);
00438         return 1;
00439        }
00440 
00441     for (i = 0; i < numopts; i++)
00442         if (!strcmp(Sopts[i], kword))
00443            {XrdPosixXrootd::setEnv(kword, kval);
00444             return 0;
00445            }
00446 
00447     Eroute->Say("Config warning: ignoring unknown setopt '",kword,"'.");
00448     return 0;
00449 }
00450   
00451 /******************************************************************************/
00452 /*                                x t r a c e                                 */
00453 /******************************************************************************/
00454 
00455 /* Function: xtrace
00456 
00457    Purpose:  To parse the directive: trace <events>
00458 
00459              <events> the blank separated list of events to trace. Trace
00460                       directives are cummalative.
00461 
00462    Output: retc upon success or -EINVAL upon failure.
00463 */
00464 
00465 int XrdPssSys::xtrac(XrdSysError *Eroute, XrdOucStream &Config)
00466 {
00467     char  *val;
00468     static struct traceopts {const char *opname; int opval;} tropts[] =
00469        {
00470         {"all",      3},
00471         {"debug",    2},
00472         {"on",       1}
00473        };
00474     int i, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
00475 
00476     if (!(val = Config.GetWord()))
00477        {Eroute->Emsg("Config", "trace option not specified"); return 1;}
00478     while (val)
00479          {if (!strcmp(val, "off")) trval = 0;
00480              else {for (i = 0; i < numopts; i++)
00481                        {if (!strcmp(val, tropts[i].opname))
00482                            {trval |=  tropts[i].opval;
00483                             break;
00484                            }
00485                        }
00486                    if (i >= numopts)
00487                       Eroute->Say("Config warning: ignoring invalid trace option '",val,"'.");
00488                   }
00489           val = Config.GetWord();
00490          }
00491     XrdPosixXrootd::setDebug(trval);
00492     return 0;
00493 }

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