XrdCmsClientConfig.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                 X r d C m s C l i e n t 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: XrdCmsClientConfig.cc 35287 2010-09-14 21:19:35Z ganis $
00012 
00013 const char *XrdCmsClientConfigCVSID = "$Id: XrdCmsClientConfig.cc 35287 2010-09-14 21:19:35Z ganis $";
00014 
00015 // Based on: XrdCmsClientConfig.cc,v 1.24 2007/07/31 02:24:52 abh
00016 
00017 #include <unistd.h>
00018 #include <ctype.h>
00019 #include <strings.h>
00020 #include <stdio.h>
00021 #include <sys/param.h>
00022 #include <sys/socket.h>
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <sys/un.h>
00026 #include <fcntl.h>
00027 
00028 #include "XrdCms/XrdCmsClientConfig.hh"
00029 #include "XrdCms/XrdCmsClientMsg.hh"
00030 #include "XrdCms/XrdCmsSecurity.hh"
00031 #include "XrdCms/XrdCmsTrace.hh"
00032 
00033 #include "XrdSys/XrdSysHeaders.hh"
00034 #include "XrdOuc/XrdOuca2x.hh"
00035 #include "XrdOuc/XrdOucEnv.hh"
00036 #include "XrdOuc/XrdOucStream.hh"
00037 #include "XrdOuc/XrdOucTList.hh"
00038 #include "XrdOuc/XrdOucUtils.hh"
00039 #include "XrdNet/XrdNetDNS.hh"
00040 
00041 using namespace XrdCms;
00042 
00043 /******************************************************************************/
00044 /*                               d e f i n e s                                */
00045 /******************************************************************************/
00046 
00047 #define TS_Xeq(x,m)    if (!strcmp(x,var)) return m(Config);
00048   
00049 /******************************************************************************/
00050 /*                            D e s t r u c t o r                             */
00051 /******************************************************************************/
00052   
00053 XrdCmsClientConfig::~XrdCmsClientConfig()
00054 {
00055   XrdOucTList *tp, *tpp;
00056 
00057   tpp = ManList;
00058   while((tp = tpp)) {tpp = tp->next; delete tp;}
00059   tpp = PanList;
00060   while((tp = tpp)) {tpp = tp->next; delete tp;}
00061 }
00062 
00063 /******************************************************************************/
00064 /*                             C o n f i g u r e                              */
00065 /******************************************************************************/
00066   
00067 int XrdCmsClientConfig::Configure(char *cfn, configWhat What, configHow How)
00068 {
00069 /*
00070   Function: Establish configuration at start up time.
00071 
00072   Input:    None.
00073 
00074   Output:   0 upon success or !0 otherwise.
00075 */
00076    EPNAME("Configure");
00077    static const char *mySid = 0;
00078    XrdOucTList *tpe, *tpl;
00079    int i, NoGo = 0;
00080    const char *eText = 0;
00081    char buff[256], *slash, *temp, *bP, sfx;
00082 
00083 // Preset some values
00084 //
00085    myHost = getenv("XRDHOST");
00086    myName = XrdOucUtils::InstName(1);
00087    CMSPath= strdup("/tmp/");
00088    isMeta = How & configMeta;
00089    isMan  = What& configMan;
00090 
00091 // Process the configuration file
00092 //
00093    if (!(NoGo = ConfigProc(cfn)) && isMan)
00094       {if (How & configProxy) eText = (PanList ? 0 : "Proxy manager");
00095           else if (!ManList)
00096                   eText = (How & configMeta ? "Meta manager" : "Manager");
00097        if (eText) {Say.Emsg("Config", eText, "not specified."); NoGo=1;}
00098       }
00099 
00100 // Reset tracing options
00101 //
00102    if (getenv("XRDDEBUG")) Trace.What = TRACE_ALL;
00103 
00104 // Set proper local socket path
00105 //
00106    temp=XrdOucUtils::genPath(CMSPath, XrdOucUtils::InstName(-1), ".olb");
00107    free(CMSPath); CMSPath = temp;
00108    XrdOucEnv::Export("XRDCMSPATH", temp);
00109    XrdOucEnv::Export("XRDOLBPATH", temp); //Compatability
00110 
00111 // Generate the system ID for this configuration.
00112 //
00113    tpl = (How & configProxy ? PanList : ManList);
00114    if (!mySid)
00115       {     if (What & configServer) sfx = 's';
00116        else if (What & configSuper)  sfx = 'u';
00117        else                          sfx = 'm';
00118        if (!(mySid = XrdCmsSecurity::setSystemID(tpl, myName, myHost, sfx)))
00119           {Say.Emsg("xrootd","Unable to generate system ID; too many managers.");
00120            NoGo = 1;
00121           } else {DEBUG("Global System Identification: " <<mySid);}
00122       }
00123 
00124 // Export the manager list
00125 //
00126    if (tpl)
00127       {i = 0; tpe = tpl;
00128        while(tpe) {i += strlen(tpe->text) + 9; tpe = tpe->next;}
00129        bP = temp = (char *)malloc(i);
00130        while(tpl)
00131             {bP += sprintf(bP, "%s:%d ", tpl->text, tpl->val);
00132              tpl = tpl->next;
00133             }
00134        *(bP-1) = '\0';
00135        XrdOucEnv::Export("XRDCMSMAN", temp); free(temp);
00136       }
00137 
00138 // Construct proper communications path for a supervisor node
00139 //
00140    i = strlen(CMSPath);
00141    if (What & configSuper)
00142       {while((tpl = ManList)) {ManList = tpl->next; delete tpl;}
00143        slash = (CMSPath[i-1] == '/' ? (char *)"" : (char *)"/");
00144        sprintf(buff, "%s%solbd.super", CMSPath, slash);
00145        ManList = new XrdOucTList(buff, -1, 0);
00146        SMode = SModeP = FailOver;
00147       }
00148 
00149 // Construct proper old communication path for a target node
00150 //
00151    temp = (What & (configMan|configSuper) ? (char *)"nimda" : (char *)"admin");
00152    slash = (CMSPath[i-1] == '/' ? (char *)"" : (char *)"/");
00153    sprintf(buff, "%s%solbd.%s", CMSPath, slash, temp);
00154    free(CMSPath); CMSPath = strdup(buff);
00155 
00156    RepWaitMS = RepWait * 1000;
00157 
00158 // Initialize the msg queue
00159 //
00160    if (XrdCmsClientMsg::Init())
00161       {Say.Emsg("Config", ENOMEM, "allocate initial msg objects");
00162        NoGo = 1;
00163       }
00164 
00165    return NoGo;
00166 }
00167 
00168 /******************************************************************************/
00169 /*                     P r i v a t e   F u n c t i o n s                      */
00170 /******************************************************************************/
00171 /******************************************************************************/
00172 /*                            C o n f i g P r o c                             */
00173 /******************************************************************************/
00174   
00175 int XrdCmsClientConfig::ConfigProc(char *ConfigFN)
00176 {
00177   static int DoneOnce = 0;
00178   char *var;
00179   int  cfgFD, retc, NoGo = 0;
00180   XrdOucEnv myEnv;
00181   XrdOucStream Config((DoneOnce ? 0 : &Say), getenv("XRDINSTANCE"),
00182                       &myEnv, "=====> ");
00183 
00184 // Make sure we have a config file
00185 //
00186    if (!ConfigFN || !*ConfigFN)
00187       {Say.Emsg("Config", "cms configuration file not specified.");
00188        return 1;
00189       }
00190 
00191 // Try to open the configuration file.
00192 //
00193    if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
00194       {Say.Emsg("Config", errno, "open config file", ConfigFN);
00195        return 1;
00196       }
00197    Config.Attach(cfgFD);
00198 
00199 // Now start reading records until eof.
00200 //
00201    while((var = Config.GetMyFirstWord()))
00202         {if (!strncmp(var, "cms.", 4)
00203          ||  !strncmp(var, "odc.", 4)      // Compatability
00204          ||  !strcmp(var, "all.manager")
00205          ||  !strcmp(var, "all.adminpath")
00206          ||  !strcmp(var, "olb.adminpath"))
00207             if (ConfigXeq(var+4, Config)) {Config.Echo(); NoGo = 1;}
00208         }
00209 
00210 // Now check if any errors occured during file i/o
00211 //
00212    if ((retc = Config.LastError()))
00213       NoGo = Say.Emsg("Config", retc, "read config file", ConfigFN);
00214    Config.Close();
00215 
00216 // Return final return code
00217 //
00218    DoneOnce = 1;
00219    return NoGo;
00220 }
00221 
00222 /******************************************************************************/
00223 /*                             C o n f i g X e q                              */
00224 /******************************************************************************/
00225 
00226 int XrdCmsClientConfig::ConfigXeq(char *var, XrdOucStream &Config)
00227 {
00228 
00229    // Process items. for either a local or a remote configuration
00230    //
00231    TS_Xeq("conwait",       xconw);
00232    TS_Xeq("manager",       xmang);
00233    TS_Xeq("adminpath",     xapath);
00234    TS_Xeq("request",       xreqs);
00235    TS_Xeq("trace",         xtrac);
00236    return 0;
00237 }
00238 
00239 /******************************************************************************/
00240 /*                                x a p a t h                                 */
00241 /******************************************************************************/
00242 
00243 /* Function: xapath
00244 
00245    Purpose:  To parse the directive: adminpath <path> [ group ]
00246 
00247              <path>    the path of the named socket to use for admin requests.
00248                        Only the path may be specified, not the filename.
00249              group     allow group access to the path.
00250 
00251    Type: Manager only, non-dynamic.
00252 
00253    Output: 0 upon success or !0 upon failure.
00254 */
00255   
00256 int XrdCmsClientConfig::xapath(XrdOucStream &Config)
00257 {
00258     struct sockaddr_un USock;
00259     char *pval;
00260 
00261 // Get the path
00262 //
00263    pval = Config.GetWord();
00264    if (!pval || !pval[0])
00265       {Say.Emsg("Config", "cms admin path not specified"); return 1;}
00266 
00267 // Make sure it's an absolute path
00268 //
00269    if (*pval != '/')
00270       {Say.Emsg("Config", "cms admin path not absolute"); return 1;}
00271 
00272 // Make sure path is not too long (account for "/olbd.admin")
00273 //                                              12345678901
00274    if (strlen(pval) > sizeof(USock.sun_path) - 11)
00275       {Say.Emsg("Config", "cms admin path is too long.");
00276        return 1;
00277       }
00278 
00279 // Record the path
00280 //
00281    if (CMSPath) free(CMSPath);
00282    CMSPath = strdup(pval);
00283    return 0;
00284 }
00285 
00286 /******************************************************************************/
00287 /*                                 x c o n w                                  */
00288 /******************************************************************************/
00289 
00290 /* Function: xconw
00291 
00292    Purpose:  To parse the directive: conwait <sec>
00293 
00294              <sec>   number of seconds to wait for a manager connection
00295 
00296    Type: Remote server only, dynamic.
00297 
00298    Output: 0 upon success or !0 upon failure.
00299 */
00300 
00301 int XrdCmsClientConfig::xconw(XrdOucStream &Config)
00302 {
00303     char *val;
00304     int cw;
00305 
00306     if (!(val = Config.GetWord()))
00307        {Say.Emsg("Config", "conwait value not specified."); return 1;}
00308 
00309     if (XrdOuca2x::a2tm(Say,"conwait value",val,&cw,1)) return 1;
00310 
00311     ConWait = cw;
00312     return 0;
00313 }
00314   
00315 /******************************************************************************/
00316 /*                                 x m a n g                                  */
00317 /******************************************************************************/
00318 
00319 /* Function: xmang
00320 
00321    Purpose:  Parse: manager [meta | peer | proxy] [all|any]
00322                             <host>[+][:<port>|<port>] [if ...]
00323 
00324              meta   For cmsd:   Specifies the manager when running as a manager
00325                     For xrootd: Specifies the manager when running as a meta
00326              peer   For cmsd:   Specifies the manager when running as a peer
00327                     For xrootd: The directive is ignored.
00328              proxy  For cmsd:   This directive is ignored.
00329                     For xrootd: Specifies the cms-proxy service manager
00330              all    Distribute requests across all managers.
00331              any    Choose different manager only when necessary (default).
00332              <host> The dns name of the host that is the cache manager.
00333                     If the host name ends with a plus, all addresses that are
00334                     associated with the host are treated as managers.
00335              <port> The port number to use for this host.
00336              if     Apply the manager directive if "if" is true. See
00337                     XrdOucUtils:doIf() for "if" syntax.
00338 
00339    Notes:   Any number of manager directives can be given. When niether peer nor
00340             proxy is specified, then regardless of role the following occurs:
00341             cmsd:   Subscribes to each manager whens role is not peer.
00342             xrootd: Logins in as a redirector to each manager when role is not 
00343                     proxy or server.
00344 
00345    Type: Remote server only, non-dynamic.
00346 
00347    Output: 0 upon success or !0 upon failure.
00348 */
00349 
00350 int XrdCmsClientConfig::xmang(XrdOucStream &Config)
00351 {
00352     struct sockaddr InetAddr[8];
00353     XrdOucTList *tp = 0, *tpp = 0, *tpnew;
00354     char *val, *bval = 0, *mval = 0;
00355     int rc, i, j, port, xMeta = 0, isProxy = 0, smode = FailOver;
00356 
00357 //  Process the optional "peer" or "proxy"
00358 //
00359     if ((val = Config.GetWord()))
00360        {if (!strcmp("peer", val)) return Config.noEcho();
00361         if ((isProxy = !strcmp("proxy", val))) val = Config.GetWord();
00362            else if ((xMeta = !strcmp("meta", val)))
00363                    if (isMeta || isMan) val = Config.GetWord();
00364                       else return Config.noEcho();
00365                    else if (isMeta) return Config.noEcho();
00366        }
00367 
00368 //  We can accept this manager. Skip the optional "all" or "any"
00369 //
00370     if (val)
00371        {     if (!strcmp("any", val)) smode = FailOver;
00372         else if (!strcmp("all", val)) smode = RoundRob;
00373         else                          smode = 0;
00374         if (smode)
00375            {if (isProxy) SModeP = smode;
00376                else      SMode  = smode;
00377             val = Config.GetWord();
00378            }
00379        }
00380 
00381 //  Get the actual manager
00382 //
00383     if (!val)
00384        {Say.Emsg("Config","manager host name not specified"); return 1;}
00385        else mval = strdup(val);
00386 
00387     if (!(val = index(mval,':'))) val = Config.GetWord();
00388        else {*val = '\0'; val++;}
00389 
00390     if (val)
00391        {if (isdigit(*val))
00392            {if (XrdOuca2x::a2i(Say,"manager port",val,&port,1,65535))
00393                port = 0;
00394            }
00395            else if (!(port = XrdNetDNS::getPort(val, "tcp")))
00396                    {Say.Emsg("Config", "unable to find tcp service", val);
00397                     port = 0;
00398                    }
00399        } else Say.Emsg("Config","manager port not specified for",mval);
00400 
00401     if (!port) {free(mval); return 1;}
00402 
00403     if (myHost && (val = Config.GetWord()) && !strcmp("if", val))
00404        if ((rc = XrdOucUtils::doIf(&Say,Config,"role directive",myHost, myName,
00405                                    getenv("XRDPROG"))) <= 0)
00406           {free(mval);
00407            return (rc < 0);
00408           }
00409 
00410     i = strlen(mval);
00411     if (mval[i-1] != '+')
00412        {i = 0; val = mval; mval = XrdNetDNS::getHostName(mval); free(val);}
00413         else {bval = strdup(mval); mval[i-1] = '\0';
00414               if (!(i = XrdNetDNS::getHostAddr(mval, InetAddr, 8)))
00415                  {Say.Emsg("Config","Manager host", mval, "not found");
00416                   free(bval); free(mval); return 1;
00417                  }
00418              }
00419 
00420     if (xMeta && !isMeta) 
00421        {haveMeta = 1; free(bval); free(mval); return 0;}
00422 
00423     do {if (i)
00424            {i--; free(mval);
00425             mval = XrdNetDNS::getHostName(InetAddr[i]);
00426             Say.Emsg("Config", bval, "-> all.manager", mval);
00427            }
00428         tp = (isProxy ? PanList : ManList); tpp = 0; j = 1;
00429         while(tp) 
00430              if ((j = strcmp(tp->text, mval)) < 0 || tp->val != port)
00431                 {tpp = tp; tp = tp->next;}
00432                 else {if (!j) Say.Emsg("Config","Duplicate manager",mval);
00433                       break;
00434                      }
00435         if (j) {tpnew = new XrdOucTList(mval, port, tp);
00436                 if (tpp) tpp->next = tpnew;
00437                    else if (isProxy) PanList = tpnew;
00438                            else      ManList = tpnew;
00439                }
00440        } while(i);
00441 
00442     if (bval) free(bval);
00443     free(mval);
00444     return 0;
00445 }
00446   
00447 /******************************************************************************/
00448 /*                                 x r e q s                                  */
00449 /******************************************************************************/
00450 
00451 /* Function: xreqs
00452 
00453    Purpose:  To parse the directive: request [repwait <sec1>] [delay <sec2>]
00454                                              [noresp <cnt>] [prep <ms>]
00455 
00456              <sec1>  number of seconds to wait for a locate reply
00457              <sec2>  number of seconds to delay a retry upon failure
00458              <cnt>   number of no-responses before cms fault declared.
00459              <ms>    milliseconds between prepare requests
00460 
00461    Type: Remote server only, dynamic.
00462 
00463    Output: 0 upon success or !0 upon failure.
00464 */
00465 
00466 int XrdCmsClientConfig::xreqs(XrdOucStream &Config)
00467 {
00468     char *val;
00469     static struct reqsopts {const char *opname; int istime; int *oploc;}
00470            rqopts[] =
00471        {
00472         {"delay",    1, &RepDelay},
00473         {"noresp",   0, &RepNone},
00474         {"prep",     1, &PrepWait},
00475         {"repwait",  1, &RepWait}
00476        };
00477     int i, ppp, numopts = sizeof(rqopts)/sizeof(struct reqsopts);
00478 
00479     if (!(val = Config.GetWord()))
00480        {Say.Emsg("Config", "request arguments not specified"); return 1;}
00481 
00482     while (val)
00483     do {for (i = 0; i < numopts; i++)
00484             if (!strcmp(val, rqopts[i].opname))
00485                { if (!(val = Config.GetWord()))
00486                   {Say.Emsg("Config","request argument value not specified");
00487                    return 1;}
00488                    if (rqopts[i].istime ?
00489                        XrdOuca2x::a2tm(Say,"request value",val,&ppp,1) :
00490                        XrdOuca2x::a2i( Say,"request value",val,&ppp,1))
00491                       return 1;
00492                       else *rqopts[i].oploc = ppp;
00493                 break;
00494                }
00495         if (i >= numopts) Say.Say("Config warning: ignoring invalid request option '",val,"'.");
00496        } while((val = Config.GetWord()));
00497      return 0;
00498 }
00499   
00500 /******************************************************************************/
00501 /*                                x t r a c e                                 */
00502 /******************************************************************************/
00503 
00504 /* Function: xtrace
00505 
00506    Purpose:  To parse the directive: trace <events>
00507 
00508              <events> the blank separated list of events to trace. Trace
00509                       directives are cummalative.
00510 
00511    Output: retc upon success or -EINVAL upon failure.
00512 */
00513 
00514 int XrdCmsClientConfig::xtrac(XrdOucStream &Config)
00515 {
00516     char  *val;
00517     static struct traceopts {const char *opname; int opval;} tropts[] =
00518        {
00519         {"all",      TRACE_ALL},
00520         {"debug",    TRACE_Debug},
00521         {"forward",  TRACE_Forward},
00522         {"redirect", TRACE_Redirect},
00523         {"defer",    TRACE_Defer},
00524         {"stage",    TRACE_Stage}
00525        };
00526     int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
00527 
00528     if (!(val = Config.GetWord()))
00529        {Say.Emsg("config", "trace option not specified"); return 1;}
00530     while (val)
00531          {if (!strcmp(val, "off")) trval = 0;
00532              else {if ((neg = (val[0] == '-' && val[1]))) val++;
00533                    for (i = 0; i < numopts; i++)
00534                        {if (!strcmp(val, tropts[i].opname))
00535                            {if (neg) trval &= ~tropts[i].opval;
00536                                else  trval |=  tropts[i].opval;
00537                             break;
00538                            }
00539                        }
00540                    if (i >= numopts)
00541                       Say.Say("Config warning: ignoring invalid trace option '",val,"'.");
00542                   }
00543           val = Config.GetWord();
00544          }
00545     Trace.What = trval;
00546     return 0;
00547 }

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