Bdb packages | Design docs | Source docs | Guidelines | Recent releases

Search | Site Map .

Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

/BdbPud/pud_Config.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                          p u d _ C o n f i g . C                           */
00004 /*                                                                            */
00005 /* (C) 2001 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-AC03-76-SFO0515 with the Deprtment of Energy              */
00009 /******************************************************************************/
00010 
00011 #include <unistd.h>
00012 #include <ctype.h>
00013 #include <errno.h>
00014 #include <iostream.h>
00015 #include <limits.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <strings.h>
00019 #include <stdio.h>
00020 #include <time.h>
00021 #include <sys/param.h>
00022 #include <sys/time.h>
00023 #include <sys/types.h>
00024 
00025 #include "pud_Config.h"
00026 #include "pud_Debug.h"
00027 #include "pud_Emsg.h"
00028 #include "pud_Network.h"
00029 
00030 /******************************************************************************/
00031 /*                               d e f i n e s                                */
00032 /******************************************************************************/
00033 
00034 #define Duplicate(x,y) if (y) free(y); y = strdup(x)
00035 
00036 #define TS_Xeq(x,m)    if (!strcmp(x,var)) return m(Config);
00037 
00038 #define TS_String(x,m) if (!strcmp(x,var)) {free(m); m = strdup(val); return 0;}
00039 
00040 #define TS_List(x,m,v) if (!strcmp(x,var)) \
00041                           {m.Insert(new oouc_PList(val, v); return 0;}
00042 
00043 #define TS_Char(x,m)   if (!strcmp(x,var)) {m = val[0]; return 0;}
00044 
00045 #define TS_Add(x,m,v)  if (!strcmp(x,var)) {m |= v; return 0;}
00046 
00047 #define TS_Set(x,m,v)  if (!strcmp(x,var)) {m = v; return 0;}
00048 
00049 #define max(a,b)       (a < b ? b : a)
00050 
00051 #define CVT pud_Config
00052 
00053 /******************************************************************************/
00054 /*                        G l o b a l   O b j e c t s                         */
00055 /******************************************************************************/
00056 
00057        pud_Debug   pud_Debug;
00058 
00059 extern pud_Network pud_Net;
00060 
00061 /******************************************************************************/
00062 /*                      C o p y   C o n s t r u c t o r                       */
00063 /******************************************************************************/
00064 
00065 pud_Config::pud_Config(pud_Config &rv)
00066 {
00067    int i, j;
00068    pud_Host *php=0, *chp;
00069 
00070 // Copy all constants
00071 //
00072    CT_num   = rv.CT_num;
00073    CT_minw  = rv.CT_minw;
00074    CT_maxw  = rv.CT_maxw;
00075    CT_randw = rv.CT_randw;
00076    XT_num   = rv.XT_num;
00077    XT_minw  = rv.XT_minw;
00078    XT_maxw  = rv.XT_maxw;
00079    XT_randw = rv.XT_randw;
00080    HostVnum = rv.HostVnum;
00081    Sport    = rv.Sport;
00082    if (rv.ServName) ServName = strdup(rv.ServName);
00083    if (rv.AutheTyp) AutheTyp = strdup(rv.AutheTyp);
00084    if (rv.AutheCmd) AutheCmd = strdup(rv.AutheCmd);
00085 
00086 // Now copy the host list
00087 //
00088    for (i = 0; i < HostVnum; i++)
00089        {chp = rv.HostVec[i];
00090         while(chp)
00091              { php = new pud_Host(php);
00092               *php = *chp;
00093                chp = chp->next;
00094              }
00095         HostVec[i] = php;
00096        }
00097 }
00098 
00099 /******************************************************************************/
00100 /*                                  a 2 x x                                   */
00101 /******************************************************************************/
00102 
00103 int pud_Config::a2sz(const char *etxt, char *item, long &result,
00104                       long minv, long maxv)
00105 {   int i = strlen(item)-1; char cmult = item[i];
00106     long val, qmult = 1;
00107          if (cmult == 'k' || cmult == 'K') qmult = 1024;
00108     else if (cmult == 'm' || cmult == 'M') qmult = 1024*1024;
00109     else if (cmult == 'g' || cmult == 'G') qmult = 1024*1024*1024;
00110     if (qmult > 1) item[i] = '\0';
00111     errno = 0;
00112     val  = strtol(item, (char **)NULL, 10) * qmult;
00113     if (qmult > 1) item[i] = cmult;
00114     if (errno || (maxv != -1 && (val > maxv || val < 1)) || val < minv)
00115        return pud_Fmsg("Config", "Invalid", (char *)etxt, (char *)" - ",item);
00116     result = val;
00117     return 0;
00118 }
00119 
00120 int pud_Config::a2l(const char *etxt, char *item, long &result,
00121                      long minv, long maxv)
00122 {   long val;
00123     errno = 0;
00124     val  = strtol(item, (char **)NULL, 10);
00125     if (errno || (maxv != -1 && val > maxv) || val  < minv)
00126        return pud_Fmsg("Config", "Invalid", (char *)etxt, (char *)" - ", item);
00127     result = val;
00128     return 0;
00129 }
00130 
00131 int pud_Config::a2i(const char *etxt, char *item, int &result,
00132                      int minv, int maxv)
00133 {   int val;
00134     errno = 0;
00135     val  = (int)strtol(item, (char **)NULL, 10);
00136     if (errno || (maxv != -1 && val > maxv) || val  < minv)
00137        return pud_Fmsg("Config", "Invalid", (char *)etxt, (char *)" - ", item);
00138     result = val;
00139     return 0;
00140 }
00141 
00142 int pud_Config::a2o(const char *etxt, char *item, long &result, 
00143                      long minv, long maxv)
00144 {   long val;
00145     errno = 0;
00146     val  = strtol(item, (char **)NULL, 8);
00147     if (errno || (maxv != -1 && val > maxv) || val < minv)
00148        return pud_Fmsg("Config", "Invalid", (char *)etxt, (char *)" - ", item);
00149     result = val;
00150     return 0;
00151 }
00152 
00153 /******************************************************************************/
00154 /*                                   n 2 a                                    */
00155 /******************************************************************************/
00156 
00157 char *pud_Config::n2a(int  val, char *buff, const char *fmt)
00158       {return buff + sprintf(buff, fmt, val);}
00159 
00160 char *pud_Config::n2a(long val, char *buff, const char *fmt)
00161       {return buff + sprintf(buff, fmt, val);}
00162 
00163 /******************************************************************************/
00164 /*                          H o s t A n d   P o r t                           */
00165 /******************************************************************************/
00166   
00167 int pud_Config::HostAndPort(const char *what, char *path, char *buff, int bsz)
00168 {   int hlen, pnum = 0;
00169     char *hn = path;
00170 
00171  // Extract the host name from the path
00172  //
00173     while (*hn && *hn != ':') hn++;
00174     if (!(hlen = hn - path))
00175        {pud_Fmsg("Config", what, (char *)"host not specified in", path); 
00176         return -1;
00177        }
00178     if (hlen >= bsz)
00179        {pud_Fmsg("Config", what, (char *)"hostname too long in", path);
00180         return -1;
00181        }
00182     if (path != buff) strncpy(buff, path, hlen);
00183 
00184  // Extract the port number from the path
00185  //
00186     if (*hn == ':' && hn++ && *hn)
00187        {errno = 0;
00188         pnum = strtol((const char *)hn, (char **)NULL, 10);
00189         if ((!pnum && errno || pnum > 65535)
00190         && ((pnum = pud_Net.findPort(hn)) <= 0))
00191            {pud_Fmsg("Config",what,(char *)"port invalid -", hn); return -1;}
00192        }
00193 
00194 // All done.
00195 //
00196     buff[hlen] = '\0';
00197     return pnum;
00198 }
00199 
00200 /******************************************************************************/
00201 /*                             C o n f i g X e q                              */
00202 /******************************************************************************/
00203 
00204 int pud_Config::ConfigXeq(char *var, pud_Stream *Config)
00205 {
00206     char  buff[2048], *bp, *val;
00207     int vlen, blen;
00208 
00209    TS_Xeq("authe",         xauthe);
00210    TS_Xeq("ctries",        xctries);
00211    TS_Xeq("eom",           xeom);
00212    TS_Xeq("port",          xport);
00213    TS_Xeq("shost",         xshost);
00214    TS_Xeq("xtries",        xxtries);
00215 
00216    // At this point, make sure we have a value
00217    //
00218    if (!(val = Config->GetWord()))
00219       {pud_Fmsg("config", "no value for", var); return 1;}
00220 
00221    // Now assign the appropriate global variable
00222    //
00223    TS_String("sname",      ServName);
00224 
00225    // No match found, simply ignore it
00226    //
00227    return 0;
00228 }
00229   
00230 /******************************************************************************/
00231 /*                           s e t D e f a u l t s                            */
00232 /******************************************************************************/
00233 
00234 void pud_Config::setDefaults()
00235 {
00236    if (InitDone) Reset();
00237 
00238    AutheTyp = 0;
00239    AutheCmd = 0;
00240 
00241    memset((void *)HostVec, 0, sizeof(HostVec));
00242    HostVnum = 0;
00243    Sport    = 0;
00244 
00245    CT_num   = pud_CT_NUM;
00246    CT_minw  = pud_CT_MINW;
00247    CT_maxw  = pud_CT_MAXW;
00248    CT_randw = pud_CT_RANDW;
00249 
00250    Resp_eom = pud_EOM;
00251 
00252    ServName = strdup(pud_SERVNAME);
00253 
00254    XT_num   = pud_XT_NUM;
00255    XT_minw  = pud_XT_MINW;
00256    XT_maxw  = pud_XT_MAXW;
00257    XT_randw = pud_XT_RANDW;
00258 }
00259 
00260 /******************************************************************************/
00261 /*                       P r i v a t e   M e t h o d s                        */
00262 /******************************************************************************/
00263 /******************************************************************************/
00264 /*                                x a u t h e                                 */
00265 /******************************************************************************/
00266 
00267 /* Function: xauthe
00268 
00269    Purpose:  To parse the directive:  authe type cmd [ parms ]
00270 
00271              The authe directive specifies how authentication infor-
00272              mation is to be encoded. The receiver must have a
00273              matching authd directive to be able to successfully
00274              decode the authentication information.  If you use the
00275              sample authentication method (i.e., Kerberos version 4)
00276              then you would use the katix command to encode the
00277              credentials. Parameters are:
00278 
00279              type   - the type of authentication that cmd provides.
00280                       Examples are K4, K5, PGP, etc. In fact, type
00281                       can be aything as long as it matches an authd
00282                       type in the server's configuration file.
00283              cmd    - is the command to invoke to encode the authen-
00284                       tication informtion to be sent to the server.
00285                       The information returned must be a hexa-
00286                       decimal ASCII string and must be returned via
00287                       standard out.
00288 */
00289 int pud_Config::xauthe(pud_Stream *Config)
00290 {
00291     char *atype, *val, buff[2048], *bp = buff;
00292     int blen = sizeof(buff);
00293 
00294     if (!(atype = Config->GetWord()))
00295        {pud_Fmsg("config", "authe type not specified"); return 1;}
00296     if (strlen(atype) > 4)
00297        {pud_Fmsg("config", "authe type too long -", atype); return 1;}
00298 
00299     *buff = '\0';
00300 
00301     while((blen > 0) && (val = Config->GetWord()))
00302          {if (bp != buff) {*bp = ' '; bp++; blen--;}
00303           do {*bp = *val; bp++; val++; blen--;} while(*val && blen > 0);
00304          }
00305 
00306     if (!*buff)
00307        {pud_Fmsg("config", "authe command not specified"); return 1;}
00308     if (blen <= 0)
00309        {pud_Fmsg("config", "authe command too long"); return 1;}
00310 
00311     if (AutheTyp) free(AutheTyp);
00312     AutheTyp = strdup(atype);
00313     if (AutheCmd) free(AutheCmd);
00314     AutheCmd = strdup(buff);
00315 
00316     return 0;
00317 }
00318   
00319 /******************************************************************************/
00320 /*                               x c t r i e s                                */
00321 /******************************************************************************/
00322 
00323 /* Function: xctries
00324 
00325    Purpose:  To parse the directive: ctries num minw maxw randw
00326 
00327              num   is the maximum number of times to try a connec-
00328                    tion. The # actual number is num times the number
00329                    of shosts since pudc tries to connect to each
00330                    possible host before failing.  The default is
00331                    nine (9).
00332              minw  is the minimum number of seconds to wait between
00333                    connection failures. The wait is imposed after
00334                    all possible hosts are tried.  The default is 60.
00335              maxw  the maximum number of seconds to wait between
00336                    connection failures. The default is 180.
00337              randw is the number of seconds to stretch the maximum
00338                    wait time on each successive failure. After each
00339                    failure, pudc waits
00340                          rand(maxw-minw+randw*(try-1))+minw seconds.
00341                    This allows multiple clients to retry at dif-
00342                    ferent times.  The default is 30.
00343 
00344    Output: 0 upon success or !0 upon failure.
00345 */
00346 
00347 int pud_Config::xctries(pud_Stream *Config)
00348 {
00349     char *val;
00350     int num, minw, maxw, randw;
00351 
00352     if (!(val = Config->GetWord()))
00353        {pud_Fmsg("config", "ctries num not specified"); return 1;}
00354     if (a2i("invalid ctries num", val, num, 1)) return 1;
00355 
00356     if (!(val = Config->GetWord()))
00357        {pud_Fmsg("config", "ctries minw not specified"); return 1;}
00358     if (a2i("invalid ctries minw", val, minw, 1)) return 1;
00359 
00360     if (!(val = Config->GetWord()))
00361        {pud_Fmsg("config", "ctries maxw not specified"); return 1;}
00362     if (a2i("invalid ctries maxw", val, maxw, minw)) return 1;
00363 
00364     if (!(val = Config->GetWord()))
00365        {pud_Fmsg("config", "ctries randw not specified"); return 1;}
00366     if (a2i("invalid ctries randw", val, randw, 1)) return 1;
00367 
00368     CT_num   = num;
00369     CT_minw  = minw;
00370     CT_maxw  = maxw;
00371     CT_randw = randw;
00372     return 0;
00373 }
00374 
00375 /******************************************************************************/
00376 /*                                  x e o m                                   */
00377 /******************************************************************************/
00378 
00379 /* Function: xeom
00380 
00381    Purpose:  To parse the directive: eom <char>
00382 
00383              <char>   the character the indicates end of line.
00384 
00385    Output: 0 upon success or !0 upon failure.
00386 */
00387 
00388 int pud_Config::xeom(pud_Stream *Config)
00389 {
00390     char *val;
00391 
00392     if (!(val = Config->GetWord()))
00393        {pud_Fmsg("config", "eom character not specified"); return 1;}
00394 
00395     if (strlen(val) == 1) {Resp_eom = *val; return 0;}
00396 
00397     if (*val == '\\')
00398        switch(val[1])
00399              {case '0': Resp_eom = '\0'; return 0;
00400               case 'b': Resp_eom = '\b'; return 0;
00401               case 'f': Resp_eom = '\f'; return 0;
00402               case 'n': Resp_eom = '\n'; return 0;
00403               case 'r': Resp_eom = '\r'; return 0;
00404               case 's': Resp_eom = ' ' ; return 0;
00405               case 't': Resp_eom = '\t'; return 0;
00406               default:  break;
00407              }
00408 
00409      pud_Fmsg("config", "invalid eom character - ", val);
00410      return 1;
00411 }
00412 
00413 /******************************************************************************/
00414 /*                                x p o r t                                   */
00415 /******************************************************************************/
00416 
00417 /* Function: xport
00418 
00419    Purpose:  To parse the directive: port <num>
00420 
00421              <num>     the port number to connect to.
00422 
00423    Output: 0 upon success or !0 upon failure.
00424 */
00425 int pud_Config::xport(pud_Stream *Config)
00426 {   int pnum;
00427     char *val;
00428 
00429     if (!(val = Config->GetWord()))
00430        {pud_Fmsg("config", "port not specified"); return 1;}
00431     if (a2i("invalid port", val, pnum, 0)) return 1;
00432     Sport = pnum;
00433     return 0;
00434 }
00435 
00436 /******************************************************************************/
00437 /*                               x s h o s t                                  */
00438 /******************************************************************************/
00439 
00440 /* Function: xshost
00441 
00442    Purpose:  To parse the directive: shost hostlist [ | hostlist [...]]
00443              is the list one one or more blank-separated hosts
00444              that provide the pud service. It is assumed that
00445              each host provides exactly the same service and
00446              that any of them can be used interchangeably.  In
00447              fact, pudc attempts connections to a random ord-
00448              You can prioritize host selection by partitioning
00449              the host list using an "or" (|). In a partitioned
00450              list, only after all hosts are randomly tried in
00451              the first partition does random selection proceed
00452              to the next partition.  A strict ordering is
00453              imposed if each sublist has only one member.  For
00454              example, while
00455                     shost host1 host2 | host3 host4
00456              would try host1 and host2, in some order, fol-
00457              lowed by host3 and host4, in some order;
00458                     shost host1 | host2 | host3 | host4
00459              would try the hosts in the exact order that they
00460              were specified.
00461 
00462    Output: 0 upon success or !0 upon failure.
00463 */
00464 
00465 int pud_Config::xshost(pud_Stream *Config)
00466 {
00467     char *val, *vp, vx;
00468     char *shlist[pud_MAXSHOST];
00469     int   svnow = 0;
00470 
00471 // Start parsing the shost parameters
00472 //
00473    while (val = Config->GetWord())
00474          {if (*val == '|' && !svnow)
00475              {pud_Fmsg("config", "Invalid shost -", val); return 1;}
00476 
00477           do {vp = val;
00478               while(*vp && *vp != '|') vp++;
00479               vx = *vp; *vp = '\0';
00480               if (svnow == pud_MAXSHOST)
00481                 {pud_Fmsg("config", "maximum shost limit exceeded."); return 1;}
00482               shlist[svnow++] = strdup(val);
00483               if (vx)
00484                  {while(*val) {*val = ' '; val++;}
00485                   *val = ' ';
00486                   Config->RetToken();
00487                  }
00488                  else break;
00489               } while(val && !vx);
00490           if (Order(shlist, svnow)) return 1;
00491           svnow = 0;
00492          }
00493 
00494 // Check if we really have any hosts
00495 //
00496    if (!HostVec[0])
00497       {pud_Fmsg("config", "No shosts specified."); return 1;}
00498    return 0;
00499 }
00500 
00501 
00502 /******************************************************************************/
00503 /*                               x x t r i e s                                */
00504 /******************************************************************************/
00505 
00506 /* Function: xctries
00507 
00508    Purpose:  To parse the directive: xtries num minw maxw randw
00509 
00510              num   is the maximum number of times to retry a
00511                    request. The # actual number is num times
00512                    the number of shosts since pudc tries to
00513                    send the failing request to each possible
00514                    host before failing itself.  The default is
00515                    nine (2).
00516              minw  is the minimum number of seconds to wait
00517                    between request failures. The wait is
00518                    imposed after all possible hosts are tried.
00519                    The default is 30.
00520              maxw  the maximum number of seconds to wait
00521                    between request failures. The default is 90.
00522              randw is the number of seconds to stretch the max-
00523                    imum wait time on each successive failure.
00524                    After each failure, pudc waits
00525                          rand(maxw-minw+randw*(try-1))+minw
00526                    seconds. This allows multiple clients to
00527                    retry at different times.  The default is
00528                    15.
00529 
00530    Output: 0 upon success or !0 upon failure.
00531 */
00532 
00533 int pud_Config::xxtries(pud_Stream *Config)
00534 {
00535     char *val;
00536     int num, minw, maxw, randw;
00537 
00538     if (!(val = Config->GetWord()))
00539        {pud_Fmsg("config", "xtries num not specified"); return 1;}
00540     if (a2i("invalid xtries num", val, num, 1)) return 1;
00541 
00542     if (!(val = Config->GetWord()))
00543        {pud_Fmsg("config", "xtries minw not specified"); return 1;}
00544     if (a2i("invalid xtries minw", val, minw, 1)) return 1;
00545 
00546     if (!(val = Config->GetWord()))
00547        {pud_Fmsg("config", "xtries maxw not specified"); return 1;}
00548     if (a2i("invalid xtries maxw", val, maxw, minw)) return 1;
00549 
00550     if (!(val = Config->GetWord()))
00551        {pud_Fmsg("config", "xtries randw not specified"); return 1;}
00552     if (a2i("invalid xtries randw", val, randw, 1)) return 1;
00553 
00554     XT_num   = num;
00555     XT_minw  = minw;
00556     XT_maxw  = maxw;
00557     XT_randw = randw;
00558     return 0;
00559 }
00560 
00561 /******************************************************************************/
00562 /*                             U t i l i t i e s                              */
00563 /******************************************************************************/
00564 /******************************************************************************/
00565 /*                                 O r d e r                                  */
00566 /******************************************************************************/
00567 
00568 int pud_Config::Order(char **shlist, int shend)
00569 {
00570    int i, shnow, shcnt = shend;
00571    pud_Host *php;
00572 
00573 // Make sure shost level wasn't exceeded
00574 //
00575    if (HostVnum >= pud_MAXSHOST)
00576       {pud_Fmsg("config", "maximum shost level limit exceeded."); return 1;}
00577 
00578 // Get the random starting point
00579 //
00580    if (shend == 1) shnow = 0;
00581       {srand((unsigned int)time(0));
00582        shnow = random();
00583       }
00584 
00585 // Resolve each host in the vector
00586 //
00587    while (shcnt--)
00588          {i = shnow++ % shend;
00589           if (shlist[i])
00590              {php = new pud_Host(HostVec[HostVnum], shlist[i]);
00591               HostVec[HostVnum] = php;
00592              }
00593          }
00594 
00595 // All done;
00596 //
00597    HostVnum++;
00598    return 0;
00599 }
00600 
00601 /******************************************************************************/
00602 /*                                 R e s e t                                  */
00603 /******************************************************************************/
00604 
00605 void pud_Config::Reset()
00606 {
00607    int i = 0;
00608    pud_Host *php, *nhp;
00609 
00610    while ((i < HostVnum) && (nhp = HostVec[i++]))
00611          while (php=nhp) {nhp = php->next; delete php;}
00612 
00613    if (ServName) free(ServName);
00614    if (AutheTyp) free(AutheTyp);
00615    if (AutheCmd) free(AutheCmd);
00616 }

 


BaBar Public Site | SLAC | News | Links | Who's Who | Contact Us

Page Owner: Jacek Becla
Last Update: October 04, 2002