00001
00002
00003
00004
00005
00006
00007
00008
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
00047
00048
00049 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(&eDest, Config);
00050
00051
00052
00053
00054
00055 const char *XrdPssSys::ConfigFN;
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
00088
00089
00090 int XrdPssSys::Configure(const char *cfn)
00091 {
00092
00093
00094
00095
00096
00097
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
00112
00113 if (getenv("XRDDEBUG")) XrdPosixXrootd::setDebug(1);
00114 myHost = getenv("XRDHOST");
00115 myName = XrdOucUtils::InstName(1);
00116
00117
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
00127
00128 if ((NoGo = ConfigProc(cfn))) return NoGo;
00129
00130
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
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
00146
00147 urlPlen = sprintf(theRdr, hdrData, "", "", "", "", "", "", "", "");
00148 urlPlain= strdup(theRdr);
00149
00150
00151
00152
00153
00154 if (!(eP = getenv("XRDEXPORTS")) || *eP != '/') xP = "/tmp";
00155 else if ((xP = rindex(eP, ' '))) xP++;
00156 else xP = eP;
00157
00158
00159
00160
00161 strcpy(&theRdr[urlPlen], xP);
00162
00163 XrdFfsMisc_refresh_url_cache(theRdr);
00164 XrdFfsDent_cache_init();
00165 XrdFfsWcache_init();
00166 XrdFfsQueue_create_workers(Workers);
00167
00168
00169
00170
00171 Xroot = new XrdPosixXrootd(-32768, 16384);
00172 return 0;
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182 int XrdPssSys::buildHdr()
00183 {
00184 XrdOucTList *tp = ManList;
00185 char buff[maxHLen], *pb;
00186 int n, bleft = sizeof(buff);
00187
00188
00189
00190 strcpy(buff, "root://"); pb = buff+strlen(buff); bleft -= strlen(buff);
00191
00192
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
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
00224
00225 if (!Cfn || !*Cfn)
00226 {eDest.Emsg("Config", "pss configuration file not specified.");
00227 return 1;
00228 }
00229
00230
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
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
00246
00247 if ((retc = Config.LastError()))
00248 NoGo = eDest.Emsg("Config", retc, "read config file", Cfn);
00249 Config.Close();
00250
00251
00252
00253 return NoGo;
00254 }
00255
00256
00257
00258
00259
00260 int XrdPssSys::ConfigXeq(char *var, XrdOucStream &Config)
00261 {
00262
00263
00264
00265 TS_Xeq("config", xconf);
00266 TS_Xeq("origin", xorig);
00267 TS_Xeq("setopt", xsopt);
00268 TS_Xeq("trace", xtrac);
00269
00270
00271
00272 eDest.Say("Config warning: ignoring unknown directive '",var,"'.");
00273 Config.Echo();
00274 return 0;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
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
00327
00328
00329
00330
00331
00332
00333
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
00343
00344 if (!(val = Config.GetWord()))
00345 {errp->Emsg("Config","origin host name not specified"); return 1;}
00346 else mval = strdup(val);
00347
00348
00349
00350 if (!(val = index(mval,':'))) val = Config.GetWord();
00351 else {*val = '\0'; val++;}
00352
00353
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
00367
00368 if (!port) {free(mval); return 1;}
00369
00370
00371
00372 if ((i = strlen(mval)) > 1 && mval[i-1] == '+') mval[i-1] = 0;
00373
00374
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
00382
00383 free(mval);
00384 return tp != 0;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
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
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
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 }