41 #include <sys/param.h>
42 #include <sys/resource.h>
44 #include <sys/types.h>
47 #include "XrdVersion.hh"
127 (
const char *hostname,
128 const struct sockaddr &netaddr,
188 #define TS_Lib(x, y, z) if (!strcmp(x, var)) \
189 return (XrdOucUtils::parseLib(*eDest, CFile, x, y, z) ? 0 : 1);
191 #define TS_String(x,m) if (!strcmp(x,var)) {free(m); m = strdup(val); return 0;}
193 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(eDest, CFile);
194 #define TS_Xer(x,m,v) if (!strcmp(x,var)) return m(eDest, CFile, v);
196 #define TS_Set(x,v) if (!strcmp(x,var)) {v=1; CFile.Echo(true); return 0;}
198 #define TS_unSet(x,v) if (!strcmp(x,var)) {v=0; CFile.Echo(true); return 0;}
211 myName = strdup(pi->
myName);
212 PortTCP = (pi->
Port < 0 ? 0 : pi->
Port);
213 myInsName = strdup(pi->
myInst);
214 myProg = strdup(pi->
myProg);
248 int NoGo = 0, immed = 0;
250 extern int opterr,
optopt;
255 if (argc > 1 &&
'-' == *argv[1])
256 while ((c=getopt(argc,argv,
"iw")) && ((
unsigned char)c != 0xff))
261 case 'w': immed = -1;
263 default: buff[0] =
'-'; buff[1] =
optopt; buff[2] =
'\0';
264 Say.
Say(
"Config warning: unrecognized option, ",buff,
", ignored.");
271 {
if (!strcmp(argv[
optind],
"manager")) isManager = 1;
272 else if (!strcmp(argv[
optind],
"server" )) isServer = 1;
273 else if (!strcmp(argv[
optind],
"super" )) isServer = isManager = 1;
274 else Say.
Say(
"Config warning: unrecognized parameter, ",
275 argv[
optind],
", ignored.");
280 inArgv = argv; inArgc = argc;
281 if ((!(ConfigFN = cfn) && !(ConfigFN = getenv(
"XrdCmsCONFIGFN")))
283 {
Say.
Emsg(
"Config",
"Required config file not specified.");
290 myInstance = strdup(buff);
299 Say.
Say(
"++++++ ", myInstance,
" phase 1 initialization started.");
304 if (!(isManager || isServer))
305 if (!(NoGo |= ConfigProc(1)) && !(isManager || isServer))
306 {
Say.
Say(
"Config warning: role not specified; manager role assumed.");
312 if (!NoGo) NoGo |= ConfigProc();
320 if (immed) doWait = (immed > 0 ? 0 : 1);
324 if (isManager < 0) isManager = 1;
325 if (isPeer < 0) isPeer = 1;
326 if (isProxy < 0) isProxy = 1;
327 if (isServer < 0) isServer = 1;
347 myRoleID =
static_cast<int>(rid);
359 {
if ((isManager && !isServer) || isPeer)
361 {
Say.
Emsg(
"Config",
"port for this", myRole,
"not specified.");
365 else if ((isManager && isServer)) PortTCP = PortSUP;
378 {
if (P_cpu|P_io|P_load|P_mem|P_pag)
379 {
if (!prfLib && !perfpgm)
380 Say.
Say(
"Config warning: metric scheduling requested without a "
381 "metrics supplier!");
383 if ( prfLib || perfpgm)
384 Say.
Say(
"Config warning: metrics supplier specified without "
385 "any scheduling metrics!");
391 sprintf(buff,
" phase 1 %s initialization %s.", myRole,
392 (NoGo ?
"failed" :
"completed"));
393 Say.
Say(
"------ ", myInstance, buff);
418 const char *override_hn = getenv(
"OVERRIDEXRDHOST");
420 {envData +=
"&ovHN=";
421 envData += override_hn;
426 sprintf(buff,
" phase 2 %s initialization started.", myRole);
427 Say.
Say(
"++++++ ", myInstance, buff);
432 if (!isMeta) QryMinum = 0;
433 else if (QryMinum < 2) QryMinum = 0;
434 else if (QryMinum > 64) QryMinum = 64;
435 if (P_gshr < 0) P_gshr = 0;
436 else if (P_gshr > 100) P_gshr = 100;
441 if (QryDelay < 0) QryDelay = LUPDelay;
447 if (!strncmp(AdminPath,
"/tmp/", 5))
448 Say.
Say(
"Config warning: adminpath resides in /tmp and may be unstable!");
461 (isManager|isPeer ?
"olbd.nimda":
"olbd.admin"),AdminMode));
466 {
if (!(
mySID = setupSid())) NoGo = 1;
468 Say.
Say(
"Config ",
"Global System Identification: ",
mySID);
470 {envData +=
"&site=";
478 envCGI = (envData.length() > 0 ? strdup(envData.c_str()) : 0);
482 if ((LocalRoot || RemotRoot || N2N_Lib) && ConfigN2N()) NoGo = 1;
486 if (!NoGo) NoGo = ConfigOSS();
492 if (!NoGo && isManager) NoGo = setupManager();
493 if (!NoGo && (isServer || ManList)) NoGo = setupServer();
501 if (isPeer && isSolo)
505 if (isMeta) {SUPCount = 1; SUPLevel = 0;}
508 if (isManager) Who = (isServer ? -1 : 1);
514 if (!NoGo) NoGo |= Manifest();
518 sprintf(buff,
" phase 2 %s initialization %s.", myRole,
519 (NoGo ?
"failed" :
"completed"));
520 Say.
Say(
"------ ", myInstance, buff);
541 if (
eDest) dynamic = 1;
555 TS_Xeq(
"adminpath", xapath);
558 TS_Xeq(
"blacklist", xblk);
560 TS_Xeq(
"defaults", xdefs);
564 TS_Xeq(
"localroot", xlclrt);
566 TS_Lib(
"namelib", N2N_Lib, &N2N_Parms);
568 TS_Lib(
"osslib", ossLib, &ossParms);
571 TS_Xeq(
"prepmsg", xprepm);
572 TS_Xeq(
"remoteroot", xrmtrt);
573 TS_Xeq(
"repstats", xreps);
576 TS_Xeq(
"subcluster", xsubc);
577 TS_Xeq(
"superport", xsupp);
581 TS_Xer(
"whitelist", xblk,
true);
586 if (!strcmp(var,
"conwait")
587 || !strcmp(var,
"request"))
return 0;
591 if (!strcmp(var,
"pidpath"))
592 {
Say.
Say(
"Config warning: 'cms.pidpath' no longer "
593 "supported; use 'all.pidpath'.");
595 Say.
Say(
"Config warning: ignoring unknown directive '", var,
"'.");
609 time_t eTime = time(0);
616 if (isManager && !isServer && !ManList) doWait = 0;
617 else if (isServer && adsMon) doWait = 1;
623 0,
"Notification handler"))
624 Say.
Emsg(
"cmsd", errno,
"start notification handler");
629 (
void *)0, 0,
"Prep handler"))
630 Say.
Emsg(
"cmsd", errno,
"start prep handler");
636 (
void *)0, 0,
"supervisor"))
637 {
Say.
Emsg(
"cmsd", errno,
"start", myRole);
653 Say.
Emsg(
"cmsd", errno,
"start admin handler");
665 {
Say.
Emsg(
"Config", errno,
"create state monitor thread");
671 if ((isManager || isPeer) && SRVDelay)
672 {wTime = SRVDelay -
static_cast<int>((time(0) - eTime));
680 Say.
Emsg(
"Config", myRole,
"service enabled.");
707 void XrdCmsConfig::ConfigDefaults(
void)
710 int myTZ, isEast = 0;
714 myName = (
char *)
"localhost";
729 MaxLoad = 0x7fffffff;
730 MaxRetries= 0x7fffffff;
758 myPaths = (
char *)
"";
760 sched_RR = sched_Pack = sched_AffPC = sched_Level = sched_LoadR = 0; sched_Force = 1;
800 pendplife= 60*60*24*7;
809 RefTurn = 3*
STMax*(DiskLinger+1);
835 if (myTZ <= 0) {isEast = 0x10; myTZ = -myTZ;}
836 if (myTZ > 12) myTZ = 12;
837 TimeZone = (myTZ | isEast);
844 int XrdCmsConfig::ConfigN2N()
850 if (!(xeq_N2N = n2nLoader.Load(N2N_Lib, *myVInfo, &
theEnv)))
return 1;
854 if (N2N_Lib || LocalRoot) lcl_N2N = xeq_N2N;
866 int XrdCmsConfig::ConfigOSS()
869 const char *,
XrdOucEnv *, XrdVersionInfo &);
881 if (!ossLib && isProxy) ossLib = strdup(
"libXrdPss.so");
886 if (!ossFS)
return 1;
890 if (!isManager && isServer && (arFunc =
theEnv.
GetPtr(
"XrdOssStatInfo2*")))
899 int XrdCmsConfig::ConfigProc(
int getrole)
902 int cfgFD, retc, NoGo = 0;
908 if ( (cfgFD =
open(ConfigFN, O_RDONLY, 0)) < 0)
909 {
Say.
Emsg(
"Config", errno,
"open config file", ConfigFN);
916 if (getrole) CFile.SetEroute(0);
920 while((var = CFile.GetMyFirstWord()))
922 {
if (!strcmp(
"all.role", var) || !strcmp(
"olb.role", var))
923 if (xrole(&
Say, CFile))
924 {CFile.SetEroute(&
Say); CFile.Echo(); NoGo = 1;
928 else if (!strncmp(var,
"cms.", 4)
929 || !strncmp(var,
"olb.", 4)
930 || !strcmp(var,
"ofs.osslib")
931 || !strcmp(var,
"oss.defaults")
932 || !strcmp(var,
"oss.localroot")
933 || !strcmp(var,
"oss.remoteroot")
934 || !strcmp(var,
"oss.namelib")
935 || !strcmp(var,
"all.export")
936 || !strcmp(var,
"all.manager")
937 || !strcmp(var,
"all.role")
938 || !strcmp(var,
"all.seclib")
939 || !strcmp(var,
"all.subcluster"))
940 {
if (ConfigXeq(var+4, CFile, 0)) {CFile.Echo(); NoGo = 1;}}
941 else if (!strcmp(var,
"oss.stagecmd")) DiskSS =
true;
945 if ((retc = CFile.LastError()))
946 NoGo =
Say.
Emsg(
"Config", retc,
"read config file", ConfigFN);
951 if (!getrole && (ManList || SanList)) NoGo |= MergeP();
964 char buff[512], pp, *mp = prog;
968 while(*mp && *mp !=
' ') mp++;
974 {sprintf(buff,
"find %s executable", ptype);
975 eDest->
Emsg(
"Config", errno, buff, prog);
990 int XrdCmsConfig::Manifest()
993 const char *clID, *xop = 0;
998 if (!xrdEnv || !(envFN = xrdEnv->Get(
"envFile")))
return 0;
1000 if ((clID = index(
mySID,
' '))) clID++;
1003 if ((xfd =
open(envFN, O_WRONLY|O_APPEND)) < 0) xop =
"open";
1004 else {
bool bad =
false;
1006 bad =
write(xfd,(
void *)
"&pfx=",5) < 0
1007 ||
write(xfd,(
void *)LocalRoot,strlen(LocalRoot)) < 0;
1008 if (!bad && AdminPath)
1009 bad =
write(xfd,(
void *)
"&ap=", 4) < 0
1010 ||
write(xfd,(
void *)AdminPath,strlen(AdminPath)) < 0;
1011 if (!bad) bad =
write(xfd,(
void *)
"&cn=", 4) < 0
1012 ||
write(xfd,(
void *)clID, strlen(clID)) < 0;
1013 if (bad) xop =
"append to";
1017 if (xop)
Say.
Emsg(
"Config", errno, xop, envFN);
1026 int XrdCmsConfig::MergeP()
1037 unsigned long long Opts;
1038 int pbLen = 0, NoGo = 0, export2MM = isManager && !isServer;
1047 if (export2MM) npinfo.
ssvec = (
Opts & stage4MM ? 1 : 0);
1048 else npinfo.
ssvec = (
Opts & stageAny ? 1 : 0);
1049 if (!PathList.Add(plp->
Path(), &npinfo))
1050 Say.
Emsg(
"Config",
"Ignoring duplicate export path",plp->
Path());
1051 else if (npinfo.
ssvec) DiskSS =
true;
1061 {
if (SanList) Who =
"subcluster manager:";
1062 else Who = (isServer ?
"manager:" :
"meta-manager:");
1063 }
else Who =
"redirector:";
1064 Say.
Say(
"The following paths are available to the ", Who);
1065 if (!(pp = PathList.First()))
Say.
Say(
"r /");
1067 {ptype = pp->
PType();
1068 Say.
Say(ptype, (strlen(ptype) > 1 ?
" " :
" "), pp->
Path());
1069 pbLen += strlen(pp->
Path())+8; pp = pp->
Next();
1077 if (pbLen != 0 && (pp = PathList.First()))
1078 {pbP = myPaths = (
char *)malloc(pbLen);
1080 {pbP += sprintf(pbP,
"\n%s %s", pp->
PType(), pp->
Path());
1096 int XrdCmsConfig::setupManager()
1106 const char *urDom, *myDom = index(myName,
'.');
1108 while(tP) {nP = tP; tP = tP->
next;
delete nP;}
1109 ManList = tP = SanList;
1110 if (myDom)
while(tP)
1111 {
if ((urDom = index(tP->
text,
'.')) && strcmp(urDom, myDom))
1112 {
Say.
Emsg(
"Config",
"Subcluster's manager", tP->
text,
1113 "is in a different domain.");
1118 if (isBad) {
Say.
Emsg(
"Config",
"Cross domain subclusters disallowed!");
1129 sched_RR = (100 == P_fuzz) || !AskPerf
1130 || !(P_cpu || P_io || P_load || P_mem || P_pag);
1132 {
Say.
Say(
"Config round robin scheduling in effect.");
1139 0,
"Performance monitor")))
1140 {
Say.
Emsg(
"Config", rc,
"create perf monitor thread");
1146 RefTurn = 3*
STMax*(DiskLinger+1);
1149 0,
"Refcount monitor")))
1150 {
Say.
Emsg(
"Config", rc,
"create refcount monitor thread");
1165 if (!isServer && blkChk)
1177 int XrdCmsConfig::setupServer()
1185 {
Say.
Emsg(
"Config",
"Manager node not specified for", myRole,
"role");
1192 while(tp) {n++; tp = tp->
next;}
1194 {
Say.
Emsg(
"Config",
"Too many managers have been specified");
return 1;}
1198 if (MaxDelay < 0) MaxDelay = AskPerf*AskPing+30;
1199 if (DiskWT < 0) DiskWT = AskPerf*AskPing+30;
1204 (isManager|isPeer ?
"olbd.seton":
"olbd.notes"),
1210 if (isManager || isPeer)
return 0;
1211 SUPCount = 0; SUPLevel = 0;
1212 if (isProxy)
return 0;
1217 if (DiskSS)
PrepQ.
Reset(myInsName, AdminPath, AdminMode);
1223 Say.
Say(
"Config warning: load based scheduling disabled.");
1234 char *XrdCmsConfig::setupSid()
1242 if (getenv(
"XRDIFADDRS")) ifList = strdup(getenv(
"XRDIFADDRS"));
1246 if ((mySite = getenv(
"XRDSITE")) && *mySite) mySite = strdup(mySite);
1251 if (isManager && isServer) sfx =
'u';
1252 else sfx = (isManager ?
'm' :
's');
1253 if (isProxy) sfx = toupper(sfx);
1259 if (!myVNID)
return 0;
1265 if (!sidVal || *sidVal ==
'!')
1267 if (!sidVal) msg =
"too many managers.";
1268 else msg = sidVal+1;
1269 Say.
Emsg(
"cmsd",
"Unable to generate system ID; ", msg);
1279 void XrdCmsConfig::Usage(
int rc)
1281 std::cerr <<
"\nUsage: cmsd [xrdopts] [-i] [-m] [-s] -c <cfile>" <<std::endl;
1307 if (!isManager)
return CFile.
noEcho();
1310 {
eDest->
Emsg(
"Config",
"allow type not specified");
return 1;}
1312 if (!strcmp(val,
"host")) ishost = 1;
1313 else if (!strcmp(val,
"netgroup")) ishost = 0;
1314 else {
eDest->
Emsg(
"Config",
"invalid allow type -", val);
1319 {
eDest->
Emsg(
"Config",
"allow target name not specified");
return 1;}
1322 if (ishost) Police->AddHost(val);
1323 else Police->AddNetGroup(val);
1353 if (isManager)
return CFile.
noEcho();
1356 {
eDest->
Emsg(
"Config",
"protocol not specified");
return 1;}
1358 if (strcmp(val,
"xroot"))
1359 {
eDest->
Emsg(
"Config",
"unsupported protocol, '", val,
"'.");
return 1;}
1360 if (adsProt) free(adsProt);
1361 adsProt = strdup(val);
1364 {
eDest->
Emsg(
"Config",
"data server port not specified");
return 1;}
1371 {
eDest->
Emsg(
"Config",
"Unable to find tcp service '",val,
"'.");
1375 if (!(val = CFile.
GetWord()) || !strcmp(val,
"monitor")) adsMon = 1;
1376 else if (!strcmp(val,
"nomonitor")) adsMon = 0;
1377 else {
eDest->
Emsg(
"Config",
"invalid option, '", val,
"'.");
1402 mode_t mode = S_IRWXU;
1407 if (!pval || !pval[0])
1408 {
eDest->
Emsg(
"Config",
"adminpath not specified");
return 1;}
1413 {
eDest->
Emsg(
"Config",
"adminpath not absolute");
return 1;}
1414 pval = strdup(pval);
1418 if ((val = CFile.
GetWord()) && val[0])
1419 {
if (!strcmp(
"group", val)) mode |= S_IRWXG;
1420 else {
eDest->
Emsg(
"Config",
"invalid admin path modifier -", val);
1421 free(pval);
return 1;
1427 if (AdminPath) free(AdminPath);
1450 const char *fType = (iswl ?
"whitelist" :
"blacklist");
1455 if (!isManager || isServer)
return CFile.
noEcho();
1460 if (blkList) {free(blkList); blkList = 0;}
1464 if (!val || !val[0])
1471 do {
if (!strcmp(val,
"check"))
1472 {
if (!(val = CFile.
GetWord()) || !val[0])
1473 {
eDest->
Emsg(
"Config",fType,
"check interval not specified");
1479 }
while((val = CFile.
GetWord()));
1483 if (iswl) blkChk = -blkChk;
1487 if (!val || !val[0])
return 0;
1489 {
eDest->
Emsg(
"Config",
"blacklist path not absolute");
return 1;}
1493 blkList = strdup(val);
1516 if (!(val = CFile.
GetWord()) || !val[0])
1517 {
eDest->
Emsg(
"Config",
"tag not specified");
return 1;}
1521 if ((
int)strlen(val) > 16)
1522 {
eDest->
Emsg(
"Config",
"tag is > 16 characters");
return 1;}
1526 if (cidTag) free(cidTag);
1527 cidTag = strdup(val);
1573 const char *etxt =
"invalid delay option";
1574 int i, ppp, minV = 1, ispercent = 0, noStage = 0;
1575 static struct delayopts {
const char *opname;
int *oploc;
int istime;}
1578 {
"delnode", &DELDelay, 1},
1579 {
"discard", &MsgTTL, 0},
1580 {
"drop", &DRPDelay, 1},
1581 {
"full", &DiskWT, -1},
1582 {
"hold", &LUPHold, 0},
1583 {
"lookup", &LUPDelay, 1},
1584 {
"nostage", &noStage, 01},
1585 {
"overload", &MaxDelay,-1},
1586 {
"peer", &PSDelay, 1},
1587 {
"qdl", &QryDelay, 1},
1588 {
"qdn", &QryMinum, 0},
1589 {
"rw", &RWDelay, 0},
1590 {
"servers", &SUPCount, 0},
1591 {
"service", &SUPDelay, 1},
1592 {
"startup", &SRVDelay, 1},
1593 {
"suspend", &SUSDelay, 1}
1595 int numopts =
sizeof(dyopts)/
sizeof(
struct delayopts);
1597 if (!isManager && !isPeer)
return CFile.
noEcho();
1600 {
eDest->
Emsg(
"Config",
"delay arguments not specified");
return 1;}
1603 {
for (i = 0; i < numopts; i++)
1604 if (!strcmp(val, dyopts[i].opname))
1605 {
if (!(val = CFile.
GetWord()))
1606 {
eDest->
Emsg(
"Config",
"delay ", dyopts[i].opname,
1607 " argument not specified.");
1610 if (dyopts[i].istime < 0 && !strcmp(val,
"*")) ppp = -1;
1611 else if (dyopts[i].istime)
1615 if (*dyopts[i].opname ==
'r')
1619 if (*dyopts[i].opname ==
's')
1620 {ppp = strlen(val); SUPLevel = 0; minV = 0;
1621 if (val[ppp-1] ==
'%')
1622 {ispercent = 1; val[ppp-1] =
'\0';}
1627 if (!ispercent) *dyopts[i].oploc = ppp;
1628 else {ispercent = 0; SUPCount = 1; SUPLevel = ppp;}
1632 eDest->
Say(
"Config warning: ignoring invalid delay option '",val,
"'.");
1709 int Hold = 0, limCent = 0, limFix = 0, limV = 0, qMax = 0, rTry = -1;
1714 if (isMeta || isPeer)
return CFile.
noEcho();
1719 {
eDest->
Emsg(
"Config",
"dfs option not specified");
return 1;}
1723 do{
if (!strcmp(
"mdhold", val))
1724 {
if (!(val = CFile.
GetWord()))
1725 {
eDest->
Emsg(
"Config",
"mdhold value not specified.");
return 1;}
1728 else if (!strcmp(
"limit", val))
1729 {
if (!(val = CFile.
GetWord()))
1730 {
eDest->
Emsg(
"Config",
"limit value not specified.");
return 1;}
1731 if ((limCent = !strcmp(
"central",val)) && !(val = CFile.
GetWord()))
1732 {
eDest->
Emsg(
"Config",
"limit value not specified.");
return 1;}
1733 if ((limFix = (*val ==
'=')) && *(val+1)) val++;
1736 else if (!strcmp(
"lookup", val))
1737 {
if (!(val = CFile.
GetWord()))
1738 {
eDest->
Emsg(
"Config",
"lookup value not specified.");
return 1;}
1741 else {
eDest->
Emsg(
"Config",
"invalid lookup value '", val,
"'.");
1745 else if (!strcmp(
"qmax", val))
1746 {
if (!(val = CFile.
GetWord()))
1747 {
eDest->
Emsg(
"Config",
"qmax value not specified.");
return 1;}
1750 else if (!strcmp(
"redirect",val))
1751 {
if (!(val = CFile.
GetWord()))
1752 {
eDest->
Emsg(
"Config",
"redirect value not specified.");
return 1;}
1755 else {
eDest->
Emsg(
"Config",
"invalid redirect value -", val);
1759 else if (!strcmp(
"retries", val))
1760 {
if (!(val = CFile.
GetWord()))
1761 {
eDest->
Emsg(
"Config",
"retries value not specified.");
return 1;}
1764 else {
eDest->
Emsg(
"Config",
"invalid dfs option '",val,
"'.");
return 1;}
1765 }
while((val = CFile.
GetWord()));
1770 if (isManager && isServer)
1778 {
if (limFix) limV = -limV;
1780 else if (isManager) limV = 0;
1836 struct xeqopts {
const char *opname;
int doset;
XrdOucProg **pgm;} xqopts[] =
1838 {
"chmod", 0, &ProgCH},
1839 {
"mkdir", 0, &ProgMD},
1840 {
"mkpath", 0, &ProgMP},
1843 {
"rmdir", 0, &ProgRD},
1844 {
"trunc", 0, &ProgTR}
1846 int i, xtval = 0, numopts =
sizeof(xqopts)/
sizeof(
struct xeqopts);
1851 if (!isServer)
return CFile.
noEcho();
1856 while (val && *val !=
'/')
1857 {
for (i = 0; i < numopts; i++)
1858 if (!strcmp(val, xqopts[i].opname))
1859 {xqopts[i].doset = 1;
1864 eDest->
Say(
"Config warning: ignoring invalid fsxeq type option '",val,
"'.");
1871 {
eDest->
Emsg(
"Config",
"fsxeq type option not specified");
return 1;}
1876 {
eDest->
Emsg(
"Config",
"fsxeq program not specified");
return 1;}
1884 for (i = 0; i < numopts; i++)
1885 if (xqopts[i].doset)
1886 {
if (!*xqopts[i].pgm) *(xqopts[i].pgm) =
new XrdOucProg(0);
1887 if ((*(xqopts[i].pgm))->Setup(val,
eDest))
return 1;
1916 if (!isManager)
return CFile.
noEcho();
1919 {
eDest->
Emsg(
"Config",
"fxhold value not specified.");
return 1;}
1921 if (!strcmp(val,
"noloc"))
1922 {
if (!(val = CFile.
GetWord()))
1923 {
eDest->
Emsg(
"Config",
"fxhold noloc value not specified.");
return 1;}
1927 if (!(val = CFile.
GetWord()))
return 0;
1958 if (!isServer)
return CFile.
noEcho();
1963 if (!val || !val[0])
1964 {
eDest->
Emsg(
"Config",
"localroot path not specified");
return 1;}
1966 {
eDest->
Emsg(
"Config",
"localroot path not absolute");
return 1;}
1971 while (i && val[i] ==
'/') val[i--] =
'\0';
1976 {
if (LocalRoot) free(LocalRoot);
1977 LocalRoot = strdup(val);
2017 StorageHelper(
char **v1,
char **v2) : val1(v1), val2(v2) {}
2018 ~StorageHelper() {
if (*val1) free(*val1);
2019 if (*val2) free(*val2);
2021 char **val1, **val2;
2025 char *val, *hSpec = 0, *hPort = 0;
2026 StorageHelper SHelp(&hSpec, &hPort);
2027 int rc, xMeta = 0, xPeer = 0, xProxy = 0, *myPort = 0;
2032 {
if ((xMeta = !strcmp(
"meta", val))
2033 || (xPeer = !strcmp(
"peer", val))
2034 || (xProxy = !strcmp(
"proxy", val)))
2035 {
if ((xMeta && (isServer || isPeer))
2036 || (xPeer && !isPeer)
2037 || (xProxy && !isProxy))
return CFile.
noEcho();
2039 }
else if (isPeer)
return CFile.
noEcho();
2045 if (!strcmp(
"any", val) || !strcmp(
"all", val)) val = CFile.
GetWord();
2050 {
eDest->
Emsg(
"Config",
"manager host name not specified");
return 1;}
2051 hSpec = strdup(val);
2060 {
if (strcmp(val,
"if"))
2061 {
eDest->
Emsg(
"Config",
"expecting manager 'if' but",val,
"found");
2065 myName,myInsName,myProg))<=0)
2066 {
if (!rc) CFile.
noEcho();
return rc < 0;}
2071 if (isManager && !isServer)
2073 {
if (((xMeta && isMeta) || (!xMeta && !isMeta)))
2075 if (isMeta) theList = 0;
2076 else theList = (xMeta ? &ManList : &NanList);
2104 char *val, xopt[16];
2106 bool xAll =
false, xOff =
false, xRmt =
false;
2111 {
if ((xAll = !strcmp(
"all", val))
2112 || (xOff = !strcmp(
"off", val))
2113 || (xRmt = !strcmp(
"remote", val)))
2114 {
if (xAll) nbSQ = 2;
2115 else if (xRmt) nbSQ = 1;
2119 }
else {
eDest->
Emsg(
"Config",
"nbsendq option not specified");
return 1;}
2124 {
size_t size =
sizeof(xopt)-1;
2125 strncpy(xopt, val, size);
2127 if (!(val= CFile.
GetWord()) || *val == 0)
2128 {
eDest->
Emsg(
"Config",
"nbsendq ", xopt,
" argument not specified");
2131 if (!strcmp(xopt,
"maxq"))
2132 {
if (!strcmp(
"val",
"none")) ival = -1;
2137 else if (!strcmp(xopt,
"warn"))
2141 else eDest->
Say(
"Config warning: ignoring invalid nbsendq option '",xopt,
"'.");
2168 {
char *pgm=0, *val, rest[2048];
2170 if (!isServer)
return CFile.
noEcho();
2173 {
eDest->
Emsg(
"Config",
"perf options not specified");
return 1;}
2175 if (!strcmp(
"xrootd", val))
return CFile.
noEcho();
2178 do {
if (!strcmp(
"int", val))
2179 {
if (!(val = CFile.
GetWord()))
2180 {
eDest->
Emsg(
"Config",
"perf int value not specified");
2185 else if (!strcmp(
"lib", val))
2186 {
if (perfpgm) {free(perfpgm); perfpgm = 0;}
2188 prfLib, &prfParms) ? 0 : 1);
2191 else if (!strcmp(
"pgm", val))
2192 {
if (!CFile.
GetRest(rest,
sizeof(rest)))
2193 {
eDest->
Emsg(
"Config",
"perf pgm parameters too long");
2197 {
eDest->
Emsg(
"Config",
"perf pgm value not specified");
2203 else eDest->
Say(
"Config warning: ignoring invalid perf option '",val,
"'.");
2204 }
while((val = CFile.
GetWord()));
2208 if (perfpgm) {free(perfpgm); perfpgm = 0;}
2209 if (prfLib) {free(prfLib); prfLib = 0;}
2210 if (prfParms){free(prfParms);prfParms = 0;}
2211 if (pgm) {
if (!isExec(
eDest,
"perf", pgm))
return 1;
2212 else perfpgm = strdup(pgm);
2242 {
int pnum = AskPerf, lnum = LogPerf, ping;
2246 {
eDest->
Emsg(
"Config",
"ping value not specified");
return 1;}
2248 if (ping < 3) ping = 3;
2250 while((val = CFile.
GetWord()))
2251 {
if (!strcmp(
"log", val))
2252 {
if (!(val = CFile.
GetWord()))
2253 {
eDest->
Emsg(
"Config",
"ping log value not specified");
2258 else if (!strcmp(
"usage", val))
2259 {
if (!(val = CFile.
GetWord()))
2260 {
eDest->
Emsg(
"Config",
"ping usage value not specified");
2296 {
int reset=0, scrub=0, echo = 0, doset = 0;
2297 char *prepif=0, *val, rest[2048];
2299 if (!isServer)
return CFile.
noEcho();
2303 do {
if (!strcmp(
"echo", val)) doset = echo = 1;
2304 else if (!strcmp(
"reset", val))
2305 {
if (!(val = CFile.
GetWord()))
2306 {
eDest->
Emsg(
"Config",
"prep reset value not specified");
2312 else if (!strcmp(
"scrub", val))
2313 {
if (!(val = CFile.
GetWord()))
2314 {
eDest->
Emsg(
"Config",
"prep scrub value not specified");
2320 else if (!strcmp(
"ifpgm", val))
2321 {
if (!CFile.
GetRest(rest,
sizeof(rest)))
2322 {
eDest->
Emsg(
"Config",
"prep ifpgm parameters too long");
return 1;}
2324 {
eDest->
Emsg(
"Config",
"prep ifpgm value not specified");
2330 else eDest->
Say(
"Config warning: ignoring invalid prep option '",val,
"'.");
2331 }
while((val = CFile.
GetWord()));
2337 if (scrub) pendplife = scrub;
2339 if (prepif) {
if (!isExec(
eDest,
"prep", prepif))
return 1;
2362 char *val, buff[2048];
2368 {
eDest->
Emsg(
"Config",
"no value for prepmsg directive");
2377 if (!CFile.
GetRest(buff,
sizeof(buff)))
2378 {
eDest->
Emsg(
"Config",
"prepmsg arguments too long");
2405 static struct repsopts {
const char *opname;
int opval;} rsopts[] =
2407 {
"all", RepStat_All},
2408 {
"frq", RepStat_frq},
2409 {
"shr", RepStat_shr}
2411 int i, neg, rsval = 0, numopts =
sizeof(rsopts)/
sizeof(
struct repsopts);
2414 {
eDest->
Emsg(
"config",
"repstats option not specified");
return 1;}
2416 {
if (!strcmp(val,
"off")) rsval = 0;
2417 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
2418 for (i = 0; i < numopts; i++)
2419 {
if (!strcmp(val, rsopts[i].opname))
2420 {
if (neg) rsval &= ~rsopts[i].opval;
2421 else rsval |= rsopts[i].opval;
2426 eDest->
Say(
"Config warning: ignoring invalid repstats option '",val,
"'.");
2452 char *val, *colon, *slash;
2457 if (isManager)
return CFile.
noEcho();
2462 if (!val || !val[0])
2463 {
eDest->
Emsg(
"Config",
"remoteroot path not specified");
return 1;}
2468 {colon = index(val,
':'); slash = index(val,
'/');
2469 if ((colon+1) != slash)
2470 {
eDest->
Emsg(
"Config",
"remoteroot path not absolute");
return 1;}
2476 while (i && val[i] ==
'/') val[i--] =
'\0';
2481 {
if (RemotRoot) free(RemotRoot);
2482 RemotRoot = strdup(val);
2539 char *val, *Tok1, *Tok2;
2540 int rc, xMeta=0, xPeer=0, xProxy=0, xServ=0, xMan=0, xSolo=0;
2544 if (!(val = CFile.
GetWord()) || !strcmp(val,
"if"))
2545 {
eDest->
Emsg(
"Config",
"role not specified");
return 1;}
2550 if ((val = CFile.
GetWord()) && strcmp(val,
"if"))
2551 {Tok2 = strdup(val);
2557 if (val && !strcmp(
"if", val))
2559 myName,myInsName,myProg)) <= 0)
2560 {free(Tok1);
if (Tok2) free(Tok2);
2582 default:
eDest->
Emsg(
"Config",
"invalid role -", Tok1, Tok2); rc = 1;
2588 if (Tok2) free(Tok2);
2593 if (isServer > 0 || isManager > 0 || isProxy > 0 || isPeer > 0)
2594 {
eDest->
Say(
"Config warning: role directive over-ridden by command line.");
2600 isServer = xServ; isManager = xMan; isProxy = xProxy;
2601 isPeer = xPeer; isSolo = xSolo; isMeta = xMeta;
2602 if (myRole) free(myRole);
2604 myRoleID =
static_cast<int>(roleID);
2642 int i, ppp, V_hntry = -1;
2643 static struct schedopts {
const char *opname;
int maxv;
int *oploc;}
2646 {
"cpu", 100, &P_cpu},
2647 {
"fuzz", 100, &P_fuzz},
2648 {
"gsdflt", 100, &P_gsdf},
2649 {
"gshr", 100, &P_gshr},
2651 {
"runq", 100, &P_load},
2652 {
"mem", 100, &P_mem},
2653 {
"pag", 100, &P_pag},
2654 {
"space", 100, &P_dsk},
2655 {
"maxload", 100, &MaxLoad},
2656 {
"refreset", -1, &RefReset},
2657 {
"affinity", -2, 0},
2659 {
"tryhname", 1, &V_hntry}
2661 int numopts =
sizeof(scopts)/
sizeof(
struct schedopts);
2664 {
eDest->
Emsg(
"Config",
"sched option not specified");
return 1;}
2667 {
for (i = 0; i < numopts; i++)
2668 if (!strcmp(val, scopts[i].opname))
2669 {
if (!(val = CFile.
GetWord()))
2670 {
eDest->
Emsg(
"Config",
"sched ", scopts[i].opname,
2671 "argument not specified.");
2674 if (scopts[i].maxv == -2)
2675 {
if (!xschedm(val,
eDest, CFile))
return 1;
2678 if (scopts[i].maxv == -3)
2679 {
if (!xschedp(val,
eDest, CFile))
return 1;
2682 if (scopts[i].maxv < 0)
2687 0, scopts[i].maxv))
return 1;
2688 *scopts[i].oploc = ppp;
2692 {
int rc = xschedx(val,
eDest, CFile);
2693 if (rc < 0)
return 1;
2694 if (rc > 0)
eDest->
Say(
"Config warning: "
2695 "ignoring invalid sched option '",val,
"'.");
2702 if (V_hntry >= 0) DoHnTry =
static_cast<char>(V_hntry);
2712 if (!strcmp(val,
"default"))
2715 {
eDest->
Emsg(
"Config",
"sched affinity not specified");
return 0;}
2716 }
else sched_Force = 1;
2718 if (!strcmp(val,
"none"))
2719 {sched_Pack = sched_Level = 0;
2723 sched_Pack = sched_Level = 1;
2725 if (!strcmp(val,
"weak"))
return 1;
2729 if (!strcmp(val,
"strong"))
return 1;
2731 if (!strcmp(val,
"strict"))
2736 if (!strcmp(val,
"randomized"))
2741 eDest->
Emsg(
"Config",
"Invalid sched affinity -", val);
2749 int afpsign, afpval;
2751 if (!strcmp(val,
"all"))
2756 if (!strcmp(val,
"first")) afpsign = 1;
2757 else if (!strcmp(val,
"last")) afpsign = -1;
2758 else {
eDest->
Emsg(
"Config",
"sched affpath option invalid -", val);
2763 {
eDest->
Emsg(
"Config",
"sched affpath argument not specified");
return 0;}
2768 sched_AffPC =
static_cast<char>(afpval*afpsign);
2779 if (!strcmp(val,
"maxretries"))
2780 {
if (!(val = CFile.
GetWord()))
2781 {
eDest->
Emsg(
"Config",
"sched ",
"maxretries argument not specified.");
2784 if (!xschedy(val,
eDest, mrRdrHost, mrRdrHLen, mrRdrPort))
return -1;
2791 if (!strcmp(val,
"nomultisrc"))
2803 if (!strncmp(val,
"nomultisrc@", 11))
2804 {
if (!xschedy(val,
eDest, msRdrHost, msRdrHLen, msRdrPort))
return -1;
2815 int &hlen,
int &port)
2817 const char *badTarget =
"Invalid sched redirect target '%s'%s";
2820 const char *eText =
"not a redirect target";
2824 if (host) {free(host); host = 0; hlen = port = 0;}
2828 if (!(at = index(val,
'@')))
return true;
2830 {snprintf(hName,
sizeof(hName),
2831 "Missing sched redirect target after '%s'.", val);
2835 *at = 0; val = at + 1;
2840 {snprintf(hName,
sizeof(hName), badTarget, val,
".");
2847 if ((eText = netAddr.
Set(val)))
2848 {snprintf(hName,
sizeof(hName), badTarget, val,
";");
2857 {snprintf(hName,
sizeof(hName), badTarget, val,
".");
2864 host = strdup(hName);
2865 hlen = strlen(hName)+1;
2866 port = netAddr.
Port();
2890 if (!isManager)
return CFile.
noEcho();
2940 int i, alinger = -1, arecalc = -1, minfP = -1, hwmP = -1;
2941 long long minf = -1, hwm = -1;
2942 bool haveopt =
false;
2944 while((val = CFile.
GetWord()))
2945 {
if (!strcmp(
"linger", val))
2946 {
if (!(val = CFile.
GetWord()))
2947 {
eDest->
Emsg(
"Config",
"linger value not specified");
return 1;}
2950 else if (!strcmp(
"recalc", val))
2951 {
if (!(val = CFile.
GetWord()))
2952 {
eDest->
Emsg(
"Config",
"recalc value not specified");
return 1;}
2955 else if (!strcmp(
"min", val))
2956 {
if (!(val = CFile.
GetWord()) || !isdigit(*val))
2957 {
eDest->
Emsg(
"Config",
"space min value not specified");
return 1;}
2960 else if (!strcmp(
"mwfiles", val)) {DoMWChk = 0; haveopt =
true;}
2961 else if (isdigit(*val))
break;
2962 else {
eDest->
Emsg(
"Config",
"invalid space parameters");
return 1;}
2965 if (val && isdigit(*val))
2967 if (val[i-1] ==
'%')
2974 if (val && isdigit(*val))
2976 if (val[i-1] !=
'%')
2982 if (minfP >= 0 && minf < 0)
2983 {
eDest->
Emsg(
"Config",
"absolute min value not specified");
return 1;}
2985 if (val && isdigit(*val))
2987 if (val[i-1] ==
'%')
2994 if (val && isdigit(*val))
2996 if (val[i-1] !=
'%')
3002 if (hwmP >= 0 && hwm < 0)
3003 {
eDest->
Emsg(
"Config",
"absolute high watermark value not specified");
return 1;}
3005 if (val) {
eDest->
Emsg(
"Config",
"invalid space parameter -", val);
return 1;}
3007 if (!haveopt && alinger < 0 && arecalc < 0 && minf < 0)
3008 {
eDest->
Emsg(
"Config",
"no space values specified");
return 1;}
3010 if (alinger >= 0) DiskLinger = alinger;
3011 if (arecalc >= 0) DiskAsk = arecalc;
3014 {
if (hwmP < minfP) hwmP = minfP + 1;
3015 DiskMinP = minfP; DiskHWMP = hwmP;
3016 }
else DiskMinP = DiskHWMP = 0;
3019 {
if (hwm < minf) hwm = minf+1073741824;
3020 minf = minf >> 20LL; hwm = hwm >> 20LL;
3021 if (minf >> 31LL) {minf = 0x7fefffff; hwm = 0x7fffffff;}
3022 else if (hwm >> 31LL) minf = 0x7fffffff;
3023 DiskMin =
static_cast<int>(minf);
3024 DiskHWM =
static_cast<int>(hwm);
3046 StorageHelper(
char **v1,
char **v2) : val1(v1), val2(v2) {}
3047 ~StorageHelper() {
if (*val1) free(*val1);
3048 if (*val2) free(*val2);
3050 char **val1, **val2;
3053 char *val, *hSpec = 0, *hPort = 0;
3054 StorageHelper SHelp(&hSpec, &hPort);
3058 if (isMeta || isServer || isPeer || isProxy)
return CFile.
noEcho();
3063 if (val && !strcmp(
"of", val)) val = CFile.
GetWord();
3068 {
eDest->
Emsg(
"Config",
"cluster manager host name not specified");
3071 hSpec = strdup(val);
3098 {
const char *invp =
"superport port";
3099 char *val, cport[32];
3103 {
eDest->
Emsg(
"Config",
"tcp port not specified");
return 1;}
3105 strncpy(cport, val,
sizeof(cport)-1); cport[
sizeof(cport)-1] =
'\0';
3107 if ((val = CFile.
GetWord()) && !strcmp(
"if", val))
3109 myName,myInsName,myProg))<=0)
3110 {
if (!rc) CFile.
noEcho();
return rc < 0;}
3112 if (!strcmp(cport,
"any")) pnum = 0;
3113 else if (!strcmp(cport,
"-p")) pnum = PortTCP;
3114 else if (isdigit(*cport))
3117 {
eDest->
Emsg(
"Config",
"Unable to find superport", cport);
3142 static struct traceopts {
const char *opname;
int opval;} tropts[] =
3153 int i, neg, trval = 0, numopts =
sizeof(tropts)/
sizeof(
struct traceopts);
3156 {
eDest->
Emsg(
"config",
"trace option not specified");
return 1;}
3158 {
if (!strcmp(val,
"off")) trval = 0;
3159 else {
if ((neg = (val[0] ==
'-' && val[1]))) val++;
3160 for (i = 0; i < numopts; i++)
3161 {
if (!strcmp(val, tropts[i].opname))
3162 {
if (neg) trval &= ~tropts[i].opval;
3163 else trval |= tropts[i].opval;
3168 eDest->
Say(
"Config warning: ignoring invalid trace option '",val,
"'.");
3195 char *val, parms[1024];
3199 if (!(val = CFile.
GetWord()) || !val[0])
3200 {
eDest->
Emsg(
"Config",
"vnid not specified");
return 1;}
3204 if (VNID_Lib) free(VNID_Lib);
3205 VNID_Lib = strdup(val);
3209 if (VNID_Parms) {free(VNID_Parms); VNID_Parms = 0;}
3210 if (*VNID_Lib ==
'@')
3211 {
if (!CFile.
GetRest(parms,
sizeof(parms)))
3212 {
eDest->
Emsg(
"Config",
"vnid plug-in parameters too long");
return 1;}
3213 if (*parms) VNID_Parms = strdup(parms);
void Usage(const char *msg)
void * XrdCmsStartAdmin(void *carg)
void * XrdCmsStartMonPerf(void *carg)
void * XrdCmsStartMonStat(void *carg)
void * XrdCmsStartAnote(void *carg)
void * XrdCmsStartMonRefs(void *carg)
void * XrdCmsStartSupervising(void *carg)
void * XrdCmsStartPreparing(void *carg)
#define XrdCmsMAX_PATH_LEN
static XrdSysError eDest(0,"crypto_")
XrdOss * XrdOssGetSS(XrdSysLogger *Logger, const char *config_fn, const char *OssLib, const char *OssParms, XrdOucEnv *envP, XrdVersionInfo &urVer)
int open(const char *path, int oflag,...)
ssize_t write(int fildes, const void *buf, size_t nbyte)
int access(const char *path, int amode)
static bool InitAREvents(void *arFunc)
void * Start(XrdNetSocket *AdminSock)
static void setSync(XrdSysSemaphore *sync)
void * Notes(XrdNetSocket *AdminSock)
void SetTries(bool xdfs, int tcnt)
void Init(int Opts, int DMlife, int DPLife)
static void Init(XrdScheduler *sP, XrdCmsCluster *cP, const char *blfn, int chkt=600)
int Init(int fxHold, int fxDelay, int fxQuery, int seFS, int nxHold)
static const int min_nxTime
int GenLocalPath(const char *oldp, char *newp)
int Configure1(int argc, char **argv, char *cfn)
int ConfigXeq(char *var, XrdOucStream &CFile, XrdSysError *eDest)
int Configure0(XrdProtocol_Config *pi)
static bool Start(const XrdOucTList *mL)
int Monitor(char *pgm, int itv)
void setVirtual(vType vVal)
static void do_StateDFS(XrdCmsBaseFR *rP, int rc)
int setParms(int rcnt, int stime, int deco=0)
void Reset(const char *iName, const char *aPath, int aMode)
int Init(int Tint=0, int Tdly=0)
static const char * Name(RoleID rid)
static RoleID Convert(const char *Tok1, const char *Tok2)
static const char * Type(RoleID rid)
static char * getVnId(XrdSysError &eDest, const char *cfgFN, const char *nidlib, const char *nidparm, char nidType)
static char * setSystemID(XrdOucTList *tp, const char *iVNID, const char *iTag, char iType)
static int Configure(const char *Lib, const char *Cfn=0)
void Update(StateType StateT, int ActivVal, int StageVal=0)
static int Init(const char *AdminPath, int AdminMode)
static char * ParseManPort(XrdSysError *eDest, XrdOucStream &CFile, char *hSpec)
static bool ParseMan(XrdSysError *eDest, XrdOucTList **oldMans, char *hSpec, char *hPort, int *sPort=0, bool hush=false)
static const int noPort
Do not add port number.
int Format(char *bAddr, int bLen, fmtUse fmtType=fmtAuto, int fmtOpts=0)
@ fmtAuto
Hostname if already resolved o/w use fmtAddr.
const char * Set(const char *hSpec, int pNum=PortInSpec)
static XrdNetSocket * Create(XrdSysError *Say, const char *path, const char *fn, mode_t mode, int isudp=0)
static int ServPort(const char *sName, bool isUDP=false, const char **eText=0)
static int Export(const char *Var, const char *Val)
void * GetPtr(const char *varname)
void PutPtr(const char *varname, void *value)
static unsigned long long ParseDefs(XrdOucStream &Config, XrdSysError &Eroute, unsigned long long Flags)
static XrdOucPList * ParsePath(XrdOucStream &Config, XrdSysError &Eroute, XrdOucPListAnchor &Export, unsigned long long Defopts)
unsigned long long Flag()
char * GetWord(int lowcase=0)
XrdOucEnv * SetEnv(XrdOucEnv *newEnv)
int GetRest(char *theBuf, int Blen, int lowcase=0)
static char * genPath(const char *path, const char *inst, const char *psfx=0)
static bool parseLib(XrdSysError &eDest, XrdOucStream &Config, const char *libName, char *&path, char **libparm)
static const char * InstName(int TranOpt=0)
static int doIf(XrdSysError *eDest, XrdOucStream &Config, const char *what, const char *hname, const char *nname, const char *pname)
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
void Schedule(XrdJob *jp)
static void SetQW(unsigned int qwVal)
static void SetQM(unsigned int qmVal)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
XrdSysLogger * logger(XrdSysLogger *lp=0)
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)
static void Wait(int milliseconds)
void SetLogger(XrdSysLogger *logp)
XrdVERSIONINFODEF(myVersion, cmsclient, XrdVNUMBER, XrdVERSION)
Generic structure to pass security information back and forth.