![]() |
|
|
Bdb packages | Design docs | Source docs | Guidelines | Recent releases |
|
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