XRootD
XrdCmsConfig.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d C m s C o n f i g . c c */
4 /* */
5 /* (c) 2011 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 /*
32  The methods in this file handle cmsd() initialization.
33 */
34 
35 #include <string>
36 #include <unistd.h>
37 #include <cctype>
38 #include <fcntl.h>
39 #include <strings.h>
40 #include <cstdio>
41 #include <sys/param.h>
42 #include <sys/resource.h>
43 #include <sys/stat.h>
44 #include <sys/types.h>
45 #include <dirent.h>
46 
47 #include "XrdVersion.hh"
48 #include "Xrd/XrdProtocol.hh"
49 #include "Xrd/XrdScheduler.hh"
50 #include "Xrd/XrdSendQ.hh"
51 
52 #include "XrdCms/XrdCmsAdmin.hh"
53 #include "XrdCms/XrdCmsBaseFS.hh"
55 #include "XrdCms/XrdCmsCache.hh"
56 #include "XrdCms/XrdCmsCluster.hh"
57 #include "XrdCms/XrdCmsConfig.hh"
58 #include "XrdCms/XrdCmsManager.hh"
59 #include "XrdCms/XrdCmsMeter.hh"
60 #include "XrdCms/XrdCmsNode.hh"
61 #include "XrdCms/XrdCmsPrepare.hh"
62 #include "XrdCms/XrdCmsPrepArgs.hh"
63 #include "XrdCms/XrdCmsProtocol.hh"
64 #include "XrdCms/XrdCmsRole.hh"
65 #include "XrdCms/XrdCmsRRQ.hh"
66 #include "XrdCms/XrdCmsSecurity.hh"
67 #include "XrdCms/XrdCmsSelect.hh"
68 #include "XrdCms/XrdCmsState.hh"
70 #include "XrdCms/XrdCmsTrace.hh"
71 #include "XrdCms/XrdCmsUtils.hh"
72 
73 #include "XrdNet/XrdNetOpts.hh"
74 #include "XrdNet/XrdNetUtils.hh"
75 #include "XrdNet/XrdNetSecurity.hh"
76 #include "XrdNet/XrdNetSocket.hh"
77 
78 #include "XrdOss/XrdOss.hh"
79 
80 #include "XrdOuc/XrdOuca2x.hh"
81 #include "XrdOuc/XrdOucEnv.hh"
82 #include "XrdOuc/XrdOucExport.hh"
84 #include "XrdOuc/XrdOucProg.hh"
85 #include "XrdOuc/XrdOucStream.hh"
86 #include "XrdOuc/XrdOucUtils.hh"
87 
88 #include "XrdSys/XrdSysError.hh"
89 #include "XrdSys/XrdSysHeaders.hh"
90 #include "XrdSys/XrdSysPlatform.hh"
91 #include "XrdSys/XrdSysPthread.hh"
92 #include "XrdSys/XrdSysTimer.hh"
93 
94 using namespace XrdCms;
95 
96 /******************************************************************************/
97 /* G l o b a l O b j e c t s */
98 /******************************************************************************/
99 
100 namespace XrdCms
101 {
103 
105 
107 
109 
110  XrdSysError Say(0, "");
111 
112  XrdSysTrace Trace("cms");
113 
115 };
116 
117 /******************************************************************************/
118 /* S e c u r i t y S y m b o l T i e - I n */
119 /******************************************************************************/
120 
121 // The following is a bit of a kludge. The client side will use the xrootd
122 // security infrastructure if it exists. This is tipped off by the presence
123 // of the following symbol being non-zero. On the server side, we have no
124 // such symbol and need to provide one initialized to zero.
125 //
126  XrdSecProtocol *(*XrdXrootdSecGetProtocol)
127  (const char *hostname,
128  const struct sockaddr &netaddr,
129  const XrdSecParameters &parms,
130  XrdOucErrInfo *einfo)=0;
131 
132 /******************************************************************************/
133 /* E x t e r n a l T h r e a d I n t e r f a c e s */
134 /******************************************************************************/
135 
136 void *XrdCmsStartMonPerf(void *carg) { return Cluster.MonPerf(); }
137 
138 void *XrdCmsStartMonRefs(void *carg) { return Cluster.MonRefs(); }
139 
140 void *XrdCmsStartMonStat(void *carg) { return CmsState.Monitor(); }
141 
142 void *XrdCmsStartAdmin(void *carg)
143  {return XrdCms::Admin.Start((XrdNetSocket *)carg);
144  }
145 
146 void *XrdCmsStartAnote(void *carg)
147  {XrdCmsAdmin Anote;
148  return Anote.Notes((XrdNetSocket *)carg);
149  }
150 
151 void *XrdCmsStartPreparing(void *carg)
153  return (void *)0;
154  }
155 
156 void *XrdCmsStartSupervising(void *carg)
158  return (void *)0;
159  }
160 
161 /******************************************************************************/
162 /* P i n g C l o c k H a n d l e r */
163 /******************************************************************************/
164 
165 namespace XrdCms
166 {
167 
169 {
170 public:
171 
172  void DoIt() {Config.PingTick++;
173  Sched->Schedule((XrdJob *)this,time(0)+Config.AskPing);
174  }
175 
176 static void Start() {static PingClock selfie;}
177 
178  PingClock() : XrdJob(".ping clock") {DoIt();}
180 private:
181 };
182 };
183 
184 /******************************************************************************/
185 /* d e f i n e s */
186 /******************************************************************************/
187 
188 #define TS_Lib(x, y, z) if (!strcmp(x, var)) \
189  return (XrdOucUtils::parseLib(*eDest, CFile, x, y, z) ? 0 : 1);
190 
191 #define TS_String(x,m) if (!strcmp(x,var)) {free(m); m = strdup(val); return 0;}
192 
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);
195 
196 #define TS_Set(x,v) if (!strcmp(x,var)) {v=1; CFile.Echo(true); return 0;}
197 
198 #define TS_unSet(x,v) if (!strcmp(x,var)) {v=0; CFile.Echo(true); return 0;}
199 
200 /******************************************************************************/
201 /* C o n f i g u r e 0 */
202 /******************************************************************************/
203 
205 {
206 
207 // Initialize the error message handler and get starting values
208 //
209  Say.logger(pi->eDest->logger(0));
210  Trace.SetLogger(pi->eDest->logger(0));
211  myName = strdup(pi->myName);
212  PortTCP = (pi->Port < 0 ? 0 : pi->Port);
213  myInsName = strdup(pi->myInst);
214  myProg = strdup(pi->myProg);
215  Sched = pi->Sched;
216  if (pi->AdmPath) AdminPath = strdup(pi->AdmPath);
217  else AdminPath = XrdOucUtils::genPath("/tmp/",
218  XrdOucUtils::InstName(myInsName,0));
219  AdminMode = pi->AdmMode;
220  if (pi->DebugON) Trace.What = TRACE_ALL;
221  xrdEnv = pi->theEnv;
222 
223 // Create an xrootd compatabile environment
224 //
225  theEnv.PutPtr("XrdScheduler*", Sched);
226  if (pi->theEnv) theEnv.PutPtr("xrdEnv*", pi->theEnv);
227 
228 // All done
229 //
230  return 0;
231 }
232 
233 /******************************************************************************/
234 /* C o n f i g u r e 1 */
235 /******************************************************************************/
236 
237 int XrdCmsConfig::Configure1(int argc, char **argv, char *cfn)
238 {
239 /*
240  Function: Establish phase 1 configuration at start up time.
241 
242  Input: argc - argument count
243  argv - argument vector
244  cfn - optional configuration file name
245 
246  Output: 0 upon success or !0 otherwise.
247 */
248  int NoGo = 0, immed = 0;
249  char c, buff[512];
250  extern int opterr, optopt;
251 
252 // Process the options
253 //
254  opterr = 0; optind = 1;
255  if (argc > 1 && '-' == *argv[1])
256  while ((c=getopt(argc,argv,"iw")) && ((unsigned char)c != 0xff))
257  { switch(c)
258  {
259  case 'i': immed = 1;
260  break;
261  case 'w': immed = -1; // Backward compatibility only
262  break;
263  default: buff[0] = '-'; buff[1] = optopt; buff[2] = '\0';
264  Say.Say("Config warning: unrecognized option, ",buff,", ignored.");
265  }
266  }
267 
268 // Accept a single parameter defining the overiding major role
269 //
270  if (optind < argc)
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.");
276  }
277 
278 // Bail if no configuration file specified
279 //
280  inArgv = argv; inArgc = argc;
281  if ((!(ConfigFN = cfn) && !(ConfigFN = getenv("XrdCmsCONFIGFN")))
282  || !*ConfigFN)
283  {Say.Emsg("Config", "Required config file not specified.");
284  Usage(1);
285  }
286 
287 // Establish my instance name
288 //
289  sprintf(buff, "%s@%s", XrdOucUtils::InstName(myInsName), myName);
290  myInstance = strdup(buff);
291 
292 // This is somewhat poor but we need to establish the default non-blocking
293 // message queue limit for the cms (this being 30) which can be overriden.
294 //
295  XrdSendQ::SetQM(30);
296 
297 // Print herald
298 //
299  Say.Say("++++++ ", myInstance, " phase 1 initialization started.");
300 
301 // If we don't know our role yet then we must find out before processing the
302 // config file. This means a double scan, sigh.
303 //
304  if (!(isManager || isServer))
305  if (!(NoGo |= ConfigProc(1)) && !(isManager || isServer))
306  {Say.Say("Config warning: role not specified; manager role assumed.");
307  isManager = -1;
308  }
309 
310 // Process the configuration file
311 //
312  if (!NoGo) NoGo |= ConfigProc();
313 
314 // Override the trace option
315 //
316  if (getenv("XRDDEBUG")) Trace.What = TRACE_ALL;
317 
318 // Override the wait/nowait from the command line
319 //
320  if (immed) doWait = (immed > 0 ? 0 : 1);
321 
322 // Determine the role
323 //
324  if (isManager < 0) isManager = 1;
325  if (isPeer < 0) isPeer = 1;
326  if (isProxy < 0) isProxy = 1;
327  if (isServer < 0) isServer = 1;
328 
329 // Create a text description of our role for use in messages
330 //
331  if (!myRole)
333  if (isMeta) rid = XrdCmsRole::MetaManager;
334  else if (isPeer) rid = XrdCmsRole::Peer;
335  else if (isProxy)
336  {if (isManager) rid = (isServer ? XrdCmsRole::ProxySuper
338  else rid = XrdCmsRole::ProxyServer;
339  }
340  else if (isManager)
341  {if (isManager) rid = (isServer ? XrdCmsRole::Supervisor
343  }
344  else rid = XrdCmsRole::Server;
345  strcpy(myRType, XrdCmsRole::Type(rid));
346  myRole = strdup(XrdCmsRole::Name(rid));
347  myRoleID = static_cast<int>(rid);
348  }
349 
350 // Export the role IN basic form and expanded form
351 //
352  XrdOucEnv::Export("XRDROLE", myRole);
353  XrdOucEnv::Export("XRDROLETYPE", myRType);
354 
355 // For managers, make sure that we have a well designated port.
356 // For servers or supervisors, force an ephemeral port to be used.
357 //
358  if (!NoGo)
359  {if ((isManager && !isServer) || isPeer)
360  {if (PortTCP <= 0)
361  {Say.Emsg("Config","port for this", myRole, "not specified.");
362  NoGo = 1;
363  }
364  }
365  else if ((isManager && isServer)) PortTCP = PortSUP;
366  else PortTCP = 0;
367  }
368 
369 // If we are configured in proxy mode then we are running a shared filesystem
370 //
372  (baseFS.Local() ? XrdCmsBaseFS::Cntrl : 0), 0, 0);
373 
374 // If we are a server and some scheduling parameters were specified but
375 // nothing to feed them, give a warning.
376 //
377  if (isServer)
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!");
382  } else {
383  if ( prfLib || perfpgm)
384  Say.Say("Config warning: metrics supplier specified without "
385  "any scheduling metrics!");
386  }
387  }
388 
389 // Determine how we ended and return status
390 //
391  sprintf(buff, " phase 1 %s initialization %s.", myRole,
392  (NoGo ? "failed" : "completed"));
393  Say.Say("------ ", myInstance, buff);
394  return NoGo;
395 }
396 
397 /******************************************************************************/
398 /* C o n f i g u r e 2 */
399 /******************************************************************************/
400 
402 {
403 /*
404  Function: Establish phase 2 configuration at start up time.
405 
406  Input: None.
407 
408  Output: 0 upon success or !0 otherwise.
409 */
410  int Who, NoGo = 0;
411  char *p, buff[512];
412  std::string envData;
413 
414 // Add our host name to the env
415 //
416  envData += "myHN=";
417  envData += myName;
418  const char *override_hn = getenv("OVERRIDEXRDHOST");
419  if (override_hn)
420  {envData += "&ovHN=";
421  envData += override_hn;
422  }
423 
424 // Print herald
425 //
426  sprintf(buff, " phase 2 %s initialization started.", myRole);
427  Say.Say("++++++ ", myInstance, buff);
428 
429 // Fix up the QryMinum (we hard code 64 as the max) and P_gshr values.
430 // The QryMinum only applies to a metamanager and is set as 1 minus the min.
431 //
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;
437 
438 // Determine who we are. If we are a manager or supervisor start the file
439 // location cache scrubber.
440 //
441  if (QryDelay < 0) QryDelay = LUPDelay;
442  if (isManager)
443  NoGo = !Cache.Init(cachelife,LUPDelay,QryDelay,baseFS.isDFS(),emptylife);
444 
445 // Issue warning if the adminpath resides in /tmp
446 //
447  if (!strncmp(AdminPath, "/tmp/", 5))
448  Say.Say("Config warning: adminpath resides in /tmp and may be unstable!");
449 
450 
451 // Establish the path to be used for admin functions. It has already been
452 // qualified by the instance name.
453 //
454  p = XrdOucUtils::genPath(AdminPath, (const char *)0, ".olb");
455  free(AdminPath);
456  AdminPath = p;
457 
458 // Setup the admin path (used in all roles)
459 //
460  if (!NoGo) NoGo = !(AdminSock = XrdNetSocket::Create(&Say, AdminPath,
461  (isManager|isPeer ? "olbd.nimda":"olbd.admin"),AdminMode));
462 
463 // Develop a stable unique identifier for this cmsd independent of the port
464 //
465  if (!NoGo)
466  {if (!(mySID = setupSid())) NoGo = 1;
467  else {if (QTRACE(Debug))
468  Say.Say("Config ", "Global System Identification: ", mySID);
469  if (Config.mySite)
470  {envData += "&site=";
471  envData += mySite;
472  }
473  }
474  }
475 
476 // Create envCGI string for logins
477 //
478  envCGI = (envData.length() > 0 ? strdup(envData.c_str()) : 0);
479 
480 // If we need a name library, load it now
481 //
482  if ((LocalRoot || RemotRoot || N2N_Lib) && ConfigN2N()) NoGo = 1;
483 
484 // Configure the OSS, the base filesystem, and initialize the prep queue
485 //
486  if (!NoGo) NoGo = ConfigOSS();
487  if (!NoGo) baseFS.Start();
488  if (!NoGo) PrepQ.Init();
489 
490 // Setup manager or server, as needed
491 //
492  if (!NoGo && isManager) NoGo = setupManager();
493  if (!NoGo && (isServer || ManList)) NoGo = setupServer();
494 
495 // If we are a solo peer then we have no servers and a lot of space and
496 // connections don't matter. Only one connection matters for a meta-manager.
497 // Servers, supervisors, and managers who have a meta manager must wait for
498 // for the local data server to connect so port mapping occurs. Otherwise,
499 // we indicate that it doesn't matter as the local server won't connect.
500 //
501  if (isPeer && isSolo)
502  {SUPCount = SUPLevel = 0; Meter.setVirtual(XrdCmsMeter::peerFS);}
503  else if (isManager)
505  if (isMeta) {SUPCount = 1; SUPLevel = 0;}
506  if (!ManList) CmsState.Update(XrdCmsState::FrontEnd, 1);
507  }
508  if (isManager) Who = (isServer ? -1 : 1);
509  else Who = 0;
510  CmsState.Set(SUPCount, Who, AdminPath);
511 
512 // At this point we will add to the existing manifest file
513 //
514  if (!NoGo) NoGo |= Manifest();
515 
516 // All done, check for success or failure
517 //
518  sprintf(buff, " phase 2 %s initialization %s.", myRole,
519  (NoGo ? "failed" : "completed"));
520  Say.Say("------ ", myInstance, buff);
521 
522 // The remainder of the configuration needs to be run in a separate thread
523 //
524  if (!NoGo) Sched->Schedule((XrdJob *)this);
525 
526 // All done
527 //
528  return NoGo;
529 }
530 
531 /******************************************************************************/
532 /* C o n f i g X e q */
533 /******************************************************************************/
534 
536 {
537  int dynamic;
538 
539  // Determine whether is is dynamic or not
540  //
541  if (eDest) dynamic = 1;
542  else {dynamic = 0; eDest = &Say;}
543 
544  // Process items
545  //
546  TS_Xeq("delay", xdelay); // Manager, dynamic
547  TS_Xeq("fxhold", xfxhld); // Manager, dynamic
548  TS_Xeq("ping", xping); // Manager, dynamic
549  TS_Xeq("sched", xsched); // Any, dynamic
550  TS_Xeq("space", xspace); // Any, dynamic
551  TS_Xeq("trace", xtrace); // Any, dynamic
552 
553  if (!dynamic)
554  {
555  TS_Xeq("adminpath", xapath); // Any, non-dynamic
556  TS_Xeq("allow", xallow); // Manager, non-dynamic
557  TS_Xeq("altds", xaltds); // Server, non-dynamic
558  TS_Xeq("blacklist", xblk); // Manager, non-dynamic
559  TS_Xeq("cidtag", xcid); // Any, non-dynamic
560  TS_Xeq("defaults", xdefs); // Server, non-dynamic
561  TS_Xeq("dfs", xdfs); // Any, non-dynamic
562  TS_Xeq("export", xexpo); // Any, non-dynamic
563  TS_Xeq("fsxeq", xfsxq); // Server, non-dynamic
564  TS_Xeq("localroot", xlclrt); // Any, non-dynamic
565  TS_Xeq("manager", xmang); // Server, non-dynamic
566  TS_Xeq("mode", xmode); // Manager, non-dynamic
567  TS_Lib("namelib", N2N_Lib, &N2N_Parms);
568  TS_Xeq("nbsendq", xnbsq); // Any non-dynamic
569  TS_Lib("osslib", ossLib, &ossParms);
570  TS_Xeq("perf", xperf); // Server, non-dynamic
571  TS_Xeq("prep", xprep); // Any, non-dynamic
572  TS_Xeq("prepmsg", xprepm); // Any, non-dynamic
573  TS_Xeq("remoteroot", xrmtrt); // Any, non-dynamic
574  TS_Xeq("repstats", xreps); // Any, non-dynamic
575  TS_Xeq("role", xrole); // Server, non-dynamic
576  TS_Xeq("seclib", xsecl); // Server, non-dynamic
577  TS_Xeq("subcluster", xsubc); // Manager, non-dynamic
578  TS_Xeq("superport", xsupp); // Super, non-dynamic
579  TS_Xeq("vnid", xvnid); // Server, non-dynamic
580  TS_Set("wait", doWait); // Server, non-dynamic (backward compat)
581  TS_unSet("nowait", doWait); // Server, non-dynamic
582  TS_Xer("whitelist", xblk,true);//Manager, non-dynamic
583  }
584 
585  // The following are client directives that we will ignore
586  //
587  if (!strcmp(var, "conwait")
588  || !strcmp(var, "request")) return 0;
589 
590  // No match found, complain.
591  //
592  if (!strcmp(var, "pidpath"))
593  {Say.Say("Config warning: 'cms.pidpath' no longer "
594  "supported; use 'all.pidpath'.");
595  } else {
596  Say.Say("Config warning: ignoring unknown directive '", var, "'.");
597  }
598  CFile.Echo(false);
599  return 0;
600 }
601 
602 /******************************************************************************/
603 /* D o I t */
604 /******************************************************************************/
605 
607 {
608  XrdSysSemaphore SyncUp(0);
609  pthread_t tid;
610  time_t eTime = time(0);
611  int wTime;
612 
613 // Set doWait correctly. We only wait if we have to provide a data path. This
614 // include server, supervisors, and managers who have a meta-manager, only.
615 // Why? Because we never get a primary login if we are a mere manager.
616 //
617  if (isManager && !isServer && !ManList) doWait = 0;
618  else if (isServer && adsMon) doWait = 1;
619 
620 // Start the notification thread if we need to
621 //
622  if (AnoteSock)
623  if (XrdSysThread::Run(&tid, XrdCmsStartAnote, (void *)AnoteSock,
624  0, "Notification handler"))
625  Say.Emsg("cmsd", errno, "start notification handler");
626 
627 // Start the prepare handler
628 //
630  (void *)0, 0, "Prep handler"))
631  Say.Emsg("cmsd", errno, "start prep handler");
632 
633 // Start the supervisor subsystem
634 //
637  (void *)0, 0, "supervisor"))
638  {Say.Emsg("cmsd", errno, "start", myRole);
639  return;
640  }
641  }
642 
643 // Start the ping clock if we are a manager of any kind
644 //
645  if (isManager) PingClock::Start();
646 
647 // Start the admin thread if we need to, we will not continue until told
648 // to do so by the admin interface.
649 //
650  if (AdminSock)
651  {XrdCmsAdmin::setSync(&SyncUp);
652  if (XrdSysThread::Run(&tid, XrdCmsStartAdmin, (void *)AdminSock,
653  0, "Admin traffic"))
654  Say.Emsg("cmsd", errno, "start admin handler");
655  SyncUp.Wait();
656  }
657 
658 // Start the manager subsystem.
659 //
660  if (isManager || isServer || isPeer) XrdCmsManager::Start(ManList);
661 
662 // Start state monitoring thread
663 //
664  if (XrdSysThread::Run(&tid, XrdCmsStartMonStat, (void *)0,
665  0, "State monitor"))
666  {Say.Emsg("Config", errno, "create state monitor thread");
667  return;
668  }
669 
670 // If we are a manager then we must do a service enable after a service delay
671 //
672  if ((isManager || isPeer) && SRVDelay)
673  {wTime = SRVDelay - static_cast<int>((time(0) - eTime));
674  if (wTime > 0) XrdSysTimer::Wait(wTime*1000);
675  }
676 
677 // All done
678 //
679  if (!SUPCount) CmsState.Update(XrdCmsState::Counts, 0, 0);
680  CmsState.Enable();
681  Say.Emsg("Config", myRole, "service enabled.");
682 }
683 
684 /******************************************************************************/
685 /* G e n L o c a l P a t h */
686 /******************************************************************************/
687 
688 /* GenLocalPath() generates the path that a file will have in the local file
689  system. The decision is made based on the user-given path (typically what
690  the user thinks is the local file system path). The output buffer where the
691  new path is placed must be at least XrdCmsMAX_PATH_LEN bytes long.
692 */
693 int XrdCmsConfig::GenLocalPath(const char *oldp, char *newp)
694 {
695  if (lcl_N2N) return -(lcl_N2N->lfn2pfn(oldp, newp, XrdCmsMAX_PATH_LEN));
696  if (strlen(oldp) >= XrdCmsMAX_PATH_LEN) return -ENAMETOOLONG;
697  strcpy(newp, oldp);
698  return 0;
699 }
700 
701 /******************************************************************************/
702 /* P r i v a t e F u n c t i o n s */
703 /******************************************************************************/
704 /******************************************************************************/
705 /* C o n f i g D e f a u l t s */
706 /******************************************************************************/
707 
708 void XrdCmsConfig::ConfigDefaults(void)
709 {
710  static XrdVERSIONINFODEF(myVer, cmsd, XrdVNUMBER, XrdVERSION);
711  int myTZ, isEast = 0;
712 
713 // Preset all variables with common defaults
714 //
715  myName = (char *)"localhost"; // Correctly set in Configure()
716  myDomain = 0;
717  LUPDelay = 5;
718  QryDelay =-1;
719  QryMinum = 0;
720  LUPHold = 178;
721  DELDelay = 960; // 15 minutes
722  DRPDelay = 10*60;
723  PSDelay = 0;
724  RWDelay = 2;
725  SRVDelay = 90;
726  SUPCount = 1;
727  SUPLevel = 80;
728  SUPDelay = 15;
729  SUSDelay = 30;
730  MaxLoad = 0x7fffffff;
731  MaxRetries= 0x7fffffff;
732  MsgTTL = 7;
733  MultiSrc = 1;
734  PortTCP = 0;
735  PortSUP = 0;
736  P_cpu = 0;
737  P_fuzz = 20;
738  P_gsdf = 0;
739  P_gshr = 0;
740  P_io = 0;
741  P_load = 0;
742  P_mem = 0;
743  P_pag = 0;
744  AskPerf = 10; // Every 10 pings
745  AskPing = 60; // Every 1 minute
746  PingTick = 0;
747  DoMWChk = 1;
748  DoHnTry = 1;
749  MaxDelay = -1;
750  LogPerf = 10; // Every 10 usage requests
751  DiskMin = 10240; // 10GB*1024 (Min partition space) in MB
752  DiskHWM = 11264; // 11GB*1024 (High Water Mark SUO) in MB
753  DiskMinP = 2;
754  DiskHWMP = 5;
755  DiskAsk = 12; // 15 Seconds between space calibrations.
756  DiskWT = 0; // Do not defer when out of space
757  DiskSS = false; // Not a staging server
758  DiskOK = false; // Does not have any disk
759  forceRO = false; // Allow redirects for writing
760  myPaths = (char *)""; // Default is 'r /'
761  ConfigFN = 0;
762  sched_RR = sched_Pack = sched_AffPC = sched_Level = sched_LoadR = 0; sched_Force = 1;
763  isManager= 0;
764  isMeta = 0;
765  isPeer = 0;
766  isSolo = 0;
767  isProxy = 0;
768  isServer = 0;
769  VNID_Lib = 0;
770  VNID_Parms=0;
771  N2N_Lib = 0;
772  N2N_Parms= 0;
773  lcl_N2N = 0;
774  xeq_N2N = 0;
775  LocalRoot= 0;
776  RemotRoot= 0;
777  myInsName= 0;
778  RepStats = 0;
779  myRole =0;
780  myRType[0]=0;
781  myRoleID = XrdCmsRole::noRole;
782  ManList =0;
783  NanList =0;
784  SanList =0;
785  myVNID = 0;
786  mySID = 0;
787  mySite = 0;
788  envCGI = 0;
789  cidTag = 0;
790  ifList =0;
791  perfint = 3*60;
792  perfpgm = 0;
793  xrdEnv = 0;
794  AdminPath= 0;
795  AdminMode= 0700;
796  AdminSock= 0;
797  AnoteSock= 0;
798  RedirSock= 0;
799  Police = 0;
800  cachelife= 8*60*60;
801  emptylife= 0;
802  pendplife= 60*60*24*7;
803  DiskLinger=0;
804  ProgCH = 0;
805  ProgMD = 0;
806  ProgMV = 0;
807  ProgRD = 0;
808  ProgRM = 0;
809  doWait = 1;
810  RefReset = 60*60;
811  RefTurn = 3*STMax*(DiskLinger+1);
812  DirFlags = 0;
813  blkList = 0;
814  blkChk = 0;
815  SecLib = 0;
816  ossLib = 0;
817  ossParms = 0;
818  prfLib = 0;
819  prfParms = 0;
820  ossFS = 0;
821  myVInfo = &myVer;
822  adsPort = 0;
823  adsMon = 0;
824  adsProt = 0;
825  nbSQ = 1;
826 
827  mrRdrHost = 0;
828  mrRdrHLen = 0;
829  mrRdrPort = 0;
830  msRdrHost = 0;
831  msRdrHLen = 0;
832  msRdrPort = 0;
833 
834 // Compute the time zone we are in
835 //
836  myTZ = XrdSysTimer::TimeZone();
837  if (myTZ <= 0) {isEast = 0x10; myTZ = -myTZ;}
838  if (myTZ > 12) myTZ = 12;
839  TimeZone = (myTZ | isEast);
840 }
841 
842 /******************************************************************************/
843 /* C o n f i g N 2 N */
844 /******************************************************************************/
845 
846 int XrdCmsConfig::ConfigN2N()
847 {
848  XrdOucN2NLoader n2nLoader(&Say, ConfigFN, N2N_Parms, LocalRoot, RemotRoot);
849 
850 // Get the plugin
851 //
852  if (!(xeq_N2N = n2nLoader.Load(N2N_Lib, *myVInfo, &theEnv))) return 1;
853 
854 // Optimize the local case
855 //
856  if (N2N_Lib || LocalRoot) lcl_N2N = xeq_N2N;
857 
858 // All done
859 //
860  PrepQ.setParms(lcl_N2N);
861  return 0;
862 }
863 
864 /******************************************************************************/
865 /* C o n f i g O S S */
866 /******************************************************************************/
867 
868 int XrdCmsConfig::ConfigOSS()
869 {
870  extern XrdOss *XrdOssGetSS(XrdSysLogger *, const char *, const char *,
871  const char *, XrdOucEnv *, XrdVersionInfo &);
872  void *arFunc;
873 
874 // Set up environment for the OSS to keep it relevant for cmsd
875 //
876  XrdOucEnv::Export("XRDREDIRECT", "Q");
877  XrdOucEnv::Export("XRDOSSTYPE", "cms");
878  XrdOucEnv::Export("XRDOSSCSCAN", "off");
879 
880 // If no osslib was specified but we are a proxy, then we must load the
881 // the proxy osslib.
882 //
883  if (!ossLib && isProxy) ossLib = strdup("libXrdPss.so");
884 
885 // Load and return result
886 //
887  ossFS=XrdOssGetSS(Say.logger(),ConfigFN,ossLib,ossParms,&theEnv,*myVInfo);
888  if (!ossFS) return 1;
889 
890 // Check if we should elay add/remove events to the statinfo function
891 //
892  if (!isManager && isServer && (arFunc = theEnv.GetPtr("XrdOssStatInfo2*")))
893  return (XrdCmsAdmin::InitAREvents(arFunc) ? 0 : 1);
894  return 0;
895 }
896 
897 /******************************************************************************/
898 /* C o n f i g P r o c */
899 /******************************************************************************/
900 
901 int XrdCmsConfig::ConfigProc(int getrole)
902 {
903  char *var;
904  int cfgFD, retc, NoGo = 0;
905  XrdOucEnv myEnv;
906  XrdOucStream CFile(&Say, getenv("XRDINSTANCE"), &myEnv, "=====> ");
907 
908 // Try to open the configuration file.
909 //
910  if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
911  {Say.Emsg("Config", errno, "open config file", ConfigFN);
912  return 1;
913  }
914  CFile.Attach(cfgFD);
915 
916 // Turn off echoing if we are doing a pre-scan
917 //
918  if (getrole) CFile.SetEroute(0);
919 
920 // Now start reading records until eof.
921 //
922  while((var = CFile.GetMyFirstWord()))
923  if (getrole)
924  {if (!strcmp("all.role", var) || !strcmp("olb.role", var))
925  if (xrole(&Say, CFile))
926  {CFile.SetEroute(&Say); CFile.Echo(); NoGo = 1;
927  CFile.SetEroute(0);
928  }
929  }
930  else if (!strncmp(var, "cms.", 4)
931  || !strncmp(var, "olb.", 4) // Backward compatibility
932  || !strcmp(var, "ofs.osslib")
933  || !strcmp(var, "oss.defaults")
934  || !strcmp(var, "oss.localroot")
935  || !strcmp(var, "oss.remoteroot")
936  || !strcmp(var, "oss.namelib")
937  || !strcmp(var, "all.export")
938  || !strcmp(var, "all.manager")
939  || !strcmp(var, "all.role")
940  || !strcmp(var, "all.seclib")
941  || !strcmp(var, "all.subcluster"))
942  {if (ConfigXeq(var+4, CFile, 0)) {CFile.Echo(); NoGo = 1;}}
943  else if (!strcmp(var, "oss.stagecmd")) DiskSS = true;
944 
945 // Now check if any errors occurred during file i/o
946 //
947  if ((retc = CFile.LastError()))
948  NoGo = Say.Emsg("Config", retc, "read config file", ConfigFN);
949  CFile.Close();
950 
951 // Merge Paths as needed
952 //
953  if (!getrole && (ManList || SanList)) NoGo |= MergeP();
954 
955 // Return final return code
956 //
957  return NoGo;
958 }
959 
960 /******************************************************************************/
961 /* i s E x e c */
962 /******************************************************************************/
963 
964 int XrdCmsConfig::isExec(XrdSysError *eDest, const char *ptype, char *prog)
965 {
966  char buff[512], pp, *mp = prog;
967 
968 // Isolate the program name
969 //
970  while(*mp && *mp != ' ') mp++;
971  pp = *mp; *mp ='\0';
972 
973 // Make sure the program is executable by us
974 //
975  if (access(prog, X_OK))
976  {sprintf(buff, "find %s executable", ptype);
977  eDest->Emsg("Config", errno, buff, prog);
978  *mp = pp;
979  return 0;
980  }
981 
982 // All is well
983 //
984  *mp = pp;
985  return 1;
986 }
987 
988 /******************************************************************************/
989 /* M a n i f e s t */
990 /******************************************************************************/
991 
992 int XrdCmsConfig::Manifest()
993 {
994  int xfd;
995  const char *clID, *xop = 0;
996  char *envFN;
997 
998 // Get the exiting manifest file from he environment. If none, return.
999 //
1000  if (!xrdEnv || !(envFN = xrdEnv->Get("envFile"))) return 0;
1001 
1002  if ((clID = index(mySID, ' '))) clID++;
1003  else clID = mySID;
1004 
1005  if ((xfd = open(envFN, O_WRONLY|O_APPEND)) < 0) xop = "open";
1006  else {bool bad = false;
1007  if (LocalRoot)
1008  bad = write(xfd,(void *)"&pfx=",5) < 0
1009  || write(xfd,(void *)LocalRoot,strlen(LocalRoot)) < 0;
1010  if (!bad && AdminPath)
1011  bad = write(xfd,(void *)"&ap=", 4) < 0
1012  || write(xfd,(void *)AdminPath,strlen(AdminPath)) < 0;
1013  if (!bad) bad = write(xfd,(void *)"&cn=", 4) < 0
1014  || write(xfd,(void *)clID, strlen(clID)) < 0;
1015  if (bad) xop = "append to";
1016  close(xfd);
1017  }
1018 
1019  if (xop) Say.Emsg("Config", errno, xop, envFN);
1020 
1021  return xop != 0;
1022 }
1023 
1024 /******************************************************************************/
1025 /* M e r g e P */
1026 /******************************************************************************/
1027 
1028 int XrdCmsConfig::MergeP()
1029 {
1030  static const unsigned long long stage4MM = XRDEXP_STAGEMM & ~XRDEXP_STAGE;
1031  static const unsigned long long stageAny = XRDEXP_PFCACHE | XRDEXP_STAGE;
1032  static const unsigned long long readOnly = XRDEXP_PFCACHE | XRDEXP_NOTRW;
1033 
1034  XrdOucPList *plp = PexpList.First();
1035  XrdCmsPList *pp;
1036  XrdCmsPInfo opinfo, npinfo;
1037  const char *ptype;
1038  char *pbP;
1039  unsigned long long Opts;
1040  int pbLen = 0, NoGo = 0, export2MM = isManager && !isServer;
1041  npinfo.rovec = 1;
1042 
1043 // For each path in the export list merge it into the path list
1044 //
1045  while(plp)
1046  {Opts = plp->Flag();
1047  if (!(Opts & XRDEXP_LOCAL))
1048  {npinfo.rwvec = (Opts & (XRDEXP_GLBLRO | readOnly) ? 0 : 1);
1049  if (export2MM) npinfo.ssvec = (Opts & stage4MM ? 1 : 0);
1050  else npinfo.ssvec = (Opts & stageAny ? 1 : 0);
1051  if (!PathList.Add(plp->Path(), &npinfo))
1052  Say.Emsg("Config","Ignoring duplicate export path",plp->Path());
1053  else if (npinfo.ssvec) DiskSS = true;
1054  }
1055  plp = plp->Next();
1056  }
1057 
1058 // Document what we will be declaring as available
1059 //
1060  if (!NoGo)
1061  {const char *Who;
1062  if (isManager)
1063  {if (SanList) Who = "subcluster manager:";
1064  else Who = (isServer ? "manager:" : "meta-manager:");
1065  } else Who = "redirector:";
1066  Say.Say("The following paths are available to the ", Who);
1067  if (!(pp = PathList.First())) Say.Say("r /");
1068  else while(pp)
1069  {ptype = pp->PType();
1070  Say.Say(ptype, (strlen(ptype) > 1 ? " " : " "), pp->Path());
1071  pbLen += strlen(pp->Path())+8; pp = pp->Next();
1072  }
1073  Say.Say(" ");
1074  }
1075 
1076 // Now allocate a buffer and place all of the paths into that buffer to be
1077 // sent during the login phase.
1078 //
1079  if (pbLen != 0 && (pp = PathList.First()))
1080  {pbP = myPaths = (char *)malloc(pbLen);
1081  while(pp)
1082  {pbP += sprintf(pbP, "\n%s %s", pp->PType(), pp->Path());
1083  pp = pp->Next();
1084  }
1085  myPaths++;
1086  }
1087 
1088 // All done update the staging status (it's nostage by default)
1089 //
1090  if (DiskSS) CmsState.Update(XrdCmsState::Counts, 0, 1);
1091  return NoGo;
1092 }
1093 
1094 /******************************************************************************/
1095 /* s e t u p M a n a g e r */
1096 /******************************************************************************/
1097 
1098 int XrdCmsConfig::setupManager()
1099 {
1100  pthread_t tid;
1101  int rc;
1102 
1103 // If we are a subcluster then we need to replace the manager list with the
1104 // one specified on the subcluster directive.
1105 //
1106  if (SanList)
1107  {XrdOucTList *nP, *tP = ManList;
1108  const char *urDom, *myDom = index(myName, '.');
1109  bool isBad = false;
1110  while(tP) {nP = tP; tP = tP->next; delete nP;}
1111  ManList = tP = SanList;
1112  if (myDom) while(tP)
1113  {if ((urDom = index(tP->text, '.')) && strcmp(urDom, myDom))
1114  {Say.Emsg("Config", "Subcluster's manager", tP->text,
1115  "is in a different domain.");
1116  isBad = true;
1117  }
1118  tP = tP->next;
1119  }
1120  if (isBad) {Say.Emsg("Config","Cross domain subclusters disallowed!");
1121  return 1;
1122  }
1123  }
1124 
1125 // Setup supervisor mode if we are also a server
1126 //
1127  if (isServer && !XrdCmsSupervisor::Init(AdminPath, AdminMode)) return 1;
1128 
1129 // Compute the scheduling policy
1130 //
1131  sched_RR = (100 == P_fuzz) || !AskPerf
1132  || !(P_cpu || P_io || P_load || P_mem || P_pag);
1133  if (sched_RR)
1134  {Say.Say("Config round robin scheduling in effect.");
1135  sched_Level = 0;
1136  }
1137 
1138 // Create statistical monitoring thread
1139 //
1140  if ((rc = XrdSysThread::Run(&tid, XrdCmsStartMonPerf, (void *)0,
1141  0, "Performance monitor")))
1142  {Say.Emsg("Config", rc, "create perf monitor thread");
1143  return 1;
1144  }
1145 
1146 // Create reference monitoring thread
1147 //
1148  RefTurn = 3*STMax*(DiskLinger+1);
1149  if (RefReset)
1150  {if ((rc = XrdSysThread::Run(&tid, XrdCmsStartMonRefs, (void *)0,
1151  0, "Refcount monitor")))
1152  {Say.Emsg("Config", rc, "create refcount monitor thread");
1153  return 1;
1154  }
1155  }
1156 
1157 // Initialize the fast redirect queue
1158 //
1159  RRQ.Init(LUPHold, LUPDelay);
1160 
1161 // Initialize the security interface
1162 //
1163  if (SecLib && !XrdCmsSecurity::Configure(SecLib, ConfigFN)) return 1;
1164 
1165 // Initialize the black list
1166 //
1167  if (!isServer && blkChk)
1168  XrdCmsBlackList::Init(Sched, &Cluster, blkList, blkChk);
1169 
1170 // All done
1171 //
1172  return 0;
1173 }
1174 
1175 /******************************************************************************/
1176 /* s e t u p S e r v e r */
1177 /******************************************************************************/
1178 
1179 int XrdCmsConfig::setupServer()
1180 {
1181  XrdOucTList *tp;
1182  int n = 0;
1183 
1184 // Make sure we have enough info to be a server
1185 //
1186  if (!ManList)
1187  {Say.Emsg("Config", "Manager node not specified for", myRole, "role");
1188  return 1;
1189  }
1190 
1191 // Count the number of managers. Make sure there are not too many.
1192 //
1193  tp = ManList;
1194  while(tp) {n++; tp = tp->next;}
1195  if (n > XrdCmsManager::MTMax)
1196  {Say.Emsg("Config", "Too many managers have been specified"); return 1;}
1197 
1198 // Calculate overload delay time
1199 //
1200  if (MaxDelay < 0) MaxDelay = AskPerf*AskPing+30;
1201  if (DiskWT < 0) DiskWT = AskPerf*AskPing+30;
1202 
1203 // Setup notification path
1204 //
1205  if (!(AnoteSock = XrdNetSocket::Create(&Say, AdminPath,
1206  (isManager|isPeer ? "olbd.seton":"olbd.notes"),
1207  AdminMode, XRDNET_UDPSOCKET))) return 1;
1208 
1209 // We have data only if we are a pure data server (the default is noData)
1210 // If we have no data, then we are done (the rest is for pure servers)
1211 //
1212  if (isManager || isPeer) return 0;
1213  SUPCount = 0; SUPLevel = 0;
1214  if (isProxy) return 0;
1215  DiskOK = true;
1216 
1217 // If this is a staging server then set up the Prepq object
1218 //
1219  if (DiskSS) PrepQ.Reset(myInsName, AdminPath, AdminMode);
1220 
1221 // Setup file system metering (skip it for peers)
1222 //
1223  Meter.Init();
1224  if (perfpgm && Meter.Monitor(perfpgm, perfint))
1225  Say.Say("Config warning: load based scheduling disabled.");
1226 
1227 // All done
1228 //
1229  return 0;
1230 }
1231 
1232 /******************************************************************************/
1233 /* s e t u p S i d */
1234 /******************************************************************************/
1235 
1236 char *XrdCmsConfig::setupSid()
1237 {
1238  XrdOucTList *tp = (NanList ? NanList : ManList);
1239  char *sidVal, sfx;
1240 
1241 // Grab the interfaces. This is normally set as an envar. If present then
1242 // we will copy it because we must use it permanently.
1243 //
1244  if (getenv("XRDIFADDRS")) ifList = strdup(getenv("XRDIFADDRS"));
1245 
1246 // Grab the site name
1247 //
1248  if ((mySite = getenv("XRDSITE")) && *mySite) mySite = strdup(mySite);
1249  else mySite = 0;
1250 
1251 // Determine what type of role we are playing
1252 //
1253  if (isManager && isServer) sfx = 'u';
1254  else sfx = (isManager ? 'm' : 's');
1255  if (isProxy) sfx = toupper(sfx);
1256 
1257 // Get the node ID if we need to
1258 //
1259  if (VNID_Lib)
1260  {myVNID = XrdCmsSecurity::getVnId(Say,ConfigFN,VNID_Lib,VNID_Parms,sfx);
1261  if (!myVNID) return 0;
1262  }
1263 
1264 // Generate the system ID and set the cluster ID
1265 //
1266  sidVal = XrdCmsSecurity::setSystemID(tp, myVNID, cidTag, sfx);
1267  if (!sidVal || *sidVal == '!')
1268  {const char *msg;
1269  if (!sidVal) msg = "too many managers.";
1270  else msg = sidVal+1;
1271  Say.Emsg("cmsd","Unable to generate system ID; ", msg);
1272  return 0;
1273  }
1274  return sidVal;
1275 }
1276 
1277 /******************************************************************************/
1278 /* U s a g e */
1279 /******************************************************************************/
1280 
1281 void XrdCmsConfig::Usage(int rc)
1282 {
1283 std::cerr <<"\nUsage: cmsd [xrdopts] [-i] [-m] [-s] -c <cfile>" <<std::endl;
1284 exit(rc);
1285 }
1286 
1287 /******************************************************************************/
1288 /* x a l l o w */
1289 /******************************************************************************/
1290 
1291 /* Function: xallow
1292 
1293  Purpose: To parse the directive: allow {host | netgroup} <name>
1294 
1295  <name> The dns name of the host that is allowed to connect or the
1296  netgroup name the host must be a member of. For DNS names,
1297  a single asterisk may be specified anywhere in the name.
1298 
1299  Type: Manager only, non-dynamic.
1300 
1301  Output: 0 upon success or !0 upon failure.
1302 */
1303 
1304 int XrdCmsConfig::xallow(XrdSysError *eDest, XrdOucStream &CFile)
1305 {
1306  char *val;
1307  int ishost;
1308 
1309  if (!isManager) return CFile.noEcho();
1310 
1311  if (!(val = CFile.GetWord()))
1312  {eDest->Emsg("Config", "allow type not specified"); return 1;}
1313 
1314  if (!strcmp(val, "host")) ishost = 1;
1315  else if (!strcmp(val, "netgroup")) ishost = 0;
1316  else {eDest->Emsg("Config", "invalid allow type -", val);
1317  return 1;
1318  }
1319 
1320  if (!(val = CFile.GetWord()))
1321  {eDest->Emsg("Config", "allow target name not specified"); return 1;}
1322 
1323  if (!Police) Police = new XrdNetSecurity();
1324  if (ishost) Police->AddHost(val);
1325  else Police->AddNetGroup(val);
1326 
1327  return 0;
1328 }
1329 
1330 /******************************************************************************/
1331 /* x a l t d s */
1332 /******************************************************************************/
1333 
1334 /* Function: xaltds
1335 
1336  Purpose: To parse the directive: altds xroot <port> [[no]monitor]
1337 
1338  xroot The protocol used by the alternate data server.
1339  <port> The port being used by the alternate data server.
1340  mon Actively monitor alternate data server by connecting to it.
1341  This is the default.
1342  nomon Do not monitor the alternate data server.
1343  it and if <sec> is greater than zero, send "ping" requests
1344  every <sec> seconds. Zero merely connects.
1345 
1346  Type: Manager only, non-dynamic.
1347 
1348  Output: 0 upon success or !0 upon failure.
1349 */
1350 
1351 int XrdCmsConfig::xaltds(XrdSysError *eDest, XrdOucStream &CFile)
1352 {
1353  char *val;
1354 
1355  if (isManager) return CFile.noEcho();
1356 
1357  if (!(val = CFile.GetWord()))
1358  {eDest->Emsg("Config", "protocol not specified"); return 1;}
1359 
1360  if (strcmp(val, "xroot"))
1361  {eDest->Emsg("Config", "unsupported protocol, '", val, "'."); return 1;}
1362  if (adsProt) free(adsProt);
1363  adsProt = strdup(val);
1364 
1365  if (!(val = CFile.GetWord()))
1366  {eDest->Emsg("Config", "data server port not specified"); return 1;}
1367 
1368  if (isdigit(*val))
1369  {if (XrdOuca2x::a2i(*eDest,"data server port",val,&adsPort,1,65535))
1370  return 1;
1371  }
1372  else if (!(adsPort = XrdNetUtils::ServPort(val, "tcp")))
1373  {eDest->Emsg("Config", "Unable to find tcp service '",val,"'.");
1374  return 1;
1375  }
1376 
1377  if (!(val = CFile.GetWord()) || !strcmp(val, "monitor")) adsMon = 1;
1378  else if (!strcmp(val, "nomonitor")) adsMon = 0;
1379  else {eDest->Emsg("Config", "invalid option, '", val, "'.");
1380  return 1;
1381  }
1382 
1383  return 0;
1384 }
1385 
1386 /******************************************************************************/
1387 /* x a p a t h */
1388 /******************************************************************************/
1389 
1390 /* Function: xapath
1391 
1392  Purpose: To parse the directive: adminpath <path>
1393 
1394  <path> the path of the named socket to use for admin requests.
1395 
1396  Type: Manager and Server, non-dynamic.
1397 
1398  Output: 0 upon success or !0 upon failure.
1399 */
1400 
1401 int XrdCmsConfig::xapath(XrdSysError *eDest, XrdOucStream &CFile)
1402 {
1403  char *pval, *val;
1404  mode_t mode = S_IRWXU;
1405 
1406 // Get the path
1407 //
1408  pval = CFile.GetWord();
1409  if (!pval || !pval[0])
1410  {eDest->Emsg("Config", "adminpath not specified"); return 1;}
1411 
1412 // Make sure it's an absolute path
1413 //
1414  if (*pval != '/')
1415  {eDest->Emsg("Config", "adminpath not absolute"); return 1;}
1416  pval = strdup(pval);
1417 
1418 // Get the optional access rights
1419 //
1420  if ((val = CFile.GetWord()) && val[0])
1421  {if (!strcmp("group", val)) mode |= S_IRWXG;
1422  else {eDest->Emsg("Config", "invalid admin path modifier -", val);
1423  free(pval); return 1;
1424  }
1425  }
1426 
1427 // Record the path
1428 //
1429  if (AdminPath) free(AdminPath);
1430  AdminPath = XrdOucUtils::genPath(pval,XrdOucUtils::InstName(myInsName,0));
1431  free(pval);
1432  AdminMode = mode;
1433  return 0;
1434 }
1435 
1436 /******************************************************************************/
1437 /* x b l k */
1438 /******************************************************************************/
1439 
1440 /* Function: xblk
1441 
1442  Purpose: To parse the directive: blacklist [check <time>] [<path>]
1443 
1444  <time> how often to check for black list changes.
1445  <path> the path to the blacklist file
1446 
1447  Output: 0 upon success or !0 upon failure.
1448 */
1449 
1450 int XrdCmsConfig::xblk(XrdSysError *eDest, XrdOucStream &CFile, bool iswl)
1451 {
1452  const char *fType = (iswl ? "whitelist" : "blacklist");
1453  char *val = CFile.GetWord();
1454 
1455 // We only support this for managers
1456 //
1457  if (!isManager || isServer) return CFile.noEcho();
1458 
1459 // Indicate blacklisting is active and free up any current blacklist path
1460 //
1461  blkChk = 600;
1462  if (blkList) {free(blkList); blkList = 0;}
1463 
1464 // Avoid echoing limitation in the stream object
1465 //
1466  if (!val || !val[0])
1467  {eDest->Say("=====> cms.", fType);
1468  return 0;
1469  }
1470 
1471 // Process any options
1472 //
1473  do { if (!strcmp(val, "check"))
1474  {if (!(val = CFile.GetWord()) || !val[0])
1475  {eDest->Emsg("Config",fType,"check interval not specified");
1476  return 1;
1477  }
1478  if (XrdOuca2x::a2tm(*eDest, "check value", val, &blkChk, 60)) return 1;
1479  }
1480  else break;
1481  } while((val = CFile.GetWord()));
1482 
1483 // Handle the invert option
1484 //
1485  if (iswl) blkChk = -blkChk;
1486 
1487 // Verify the path, if any. is absolute
1488 //
1489  if (!val || !val[0]) return 0;
1490  if (*val != '/')
1491  {eDest->Emsg("Config", "blacklist path not absolute"); return 1;}
1492 
1493 // Record the path
1494 //
1495  blkList = strdup(val);
1496  return 0;
1497 }
1498 
1499 /******************************************************************************/
1500 /* x c i d */
1501 /******************************************************************************/
1502 
1503 /* Function: xcid
1504 
1505  Purpose: To parse the directive: cidtag <tag>
1506 
1507  <tag> a 1- to 16-character cluster ID tag.
1508 
1509  Output: 0 upon success or !0 upon failure.
1510 */
1511 
1512 int XrdCmsConfig::xcid(XrdSysError *eDest, XrdOucStream &CFile)
1513 {
1514  char *val;
1515 
1516 // Get the path
1517 //
1518  if (!(val = CFile.GetWord()) || !val[0])
1519  {eDest->Emsg("Config", "tag not specified"); return 1;}
1520 
1521 // Make sure it is not too long
1522 //
1523  if ((int)strlen(val) > 16)
1524  {eDest->Emsg("Config", "tag is > 16 characters"); return 1;}
1525 
1526 // Record the tag
1527 //
1528  if (cidTag) free(cidTag);
1529  cidTag = strdup(val);
1530  return 0;
1531 }
1532 
1533 /******************************************************************************/
1534 /* x d e l a y */
1535 /******************************************************************************/
1536 
1537 /* Function: xdelay
1538 
1539  Purpose: To parse the directive: delay [lookup <sec>] [overload <sec>]
1540  [startup <sec>] [servers <cnt>[%]]
1541  [full <sec>] [discard <cnt>]
1542  [suspend <sec>] [drop <sec>]
1543  [service <sec>] [hold <msec>]
1544  [peer <sec>] [rw <lvl>] [qdl <sec>]
1545  [qdn <cnt>] [delnode <sec>]
1546  [nostage <cnt>]
1547 
1548  delnode <sec> maximum seconds to wait to be able to delete a node.
1549  discard <cnt> maximum number a message may be forwarded.
1550  drop <sec> seconds to delay a drop of an offline server.
1551  full <sec> seconds to delay client when no servers have space.
1552  hold <msec> millseconds to optimistically hold requests.
1553  lookup <sec> seconds to delay client when finding a file.
1554  nostage <cnt> Maximum number of staging reselections allowed.
1555  overload <sec> seconds to delay client when all servers overloaded.
1556  peer <sec> maximum seconds client may be delayed before peer
1557  selection is triggered.
1558  qdl <sec> the query response deadline.
1559  qdn <cnt> Min number of servers that must respond to satisfy qdl.
1560  rw <lvl> how to delay r/w lookups (one of three levels):
1561  0 - always use fast redirect when possible
1562  1 - delay update requests only
1563  2 - delay all rw requests (the default)
1564  servers <cnt> minimum number of servers we need.
1565  service <sec> seconds to delay client when waiting for servers.
1566  startup <sec> seconds to delay enabling our service
1567  suspend <sec> seconds to delay client when all servers suspended.
1568 
1569  Type: Manager only, dynamic.
1570 
1571  Output: 0 upon success or !0 upon failure.
1572 */
1573 int XrdCmsConfig::xdelay(XrdSysError *eDest, XrdOucStream &CFile)
1574 { char *val;
1575  const char *etxt = "invalid delay option";
1576  int i, ppp, minV = 1, ispercent = 0, noStage = 0;
1577  static struct delayopts {const char *opname; int *oploc; int istime;}
1578  dyopts[] =
1579  {
1580  {"delnode", &DELDelay, 1},
1581  {"discard", &MsgTTL, 0},
1582  {"drop", &DRPDelay, 1},
1583  {"full", &DiskWT, -1},
1584  {"hold", &LUPHold, 0},
1585  {"lookup", &LUPDelay, 1},
1586  {"nostage", &noStage, 01},
1587  {"overload", &MaxDelay,-1},
1588  {"peer", &PSDelay, 1},
1589  {"qdl", &QryDelay, 1},
1590  {"qdn", &QryMinum, 0},
1591  {"rw", &RWDelay, 0},
1592  {"servers", &SUPCount, 0},
1593  {"service", &SUPDelay, 1},
1594  {"startup", &SRVDelay, 1},
1595  {"suspend", &SUSDelay, 1}
1596  };
1597  int numopts = sizeof(dyopts)/sizeof(struct delayopts);
1598 
1599  if (!isManager && !isPeer) return CFile.noEcho();
1600 
1601  if (!(val = CFile.GetWord()))
1602  {eDest->Emsg("Config", "delay arguments not specified"); return 1;}
1603 
1604  while (val)
1605  {for (i = 0; i < numopts; i++)
1606  if (!strcmp(val, dyopts[i].opname))
1607  {if (!(val = CFile.GetWord()))
1608  {eDest->Emsg("Config", "delay ", dyopts[i].opname,
1609  " argument not specified.");
1610  return 1;
1611  }
1612  if (dyopts[i].istime < 0 && !strcmp(val, "*")) ppp = -1;
1613  else if (dyopts[i].istime)
1614  {if (XrdOuca2x::a2tm(*eDest,etxt,val,&ppp,1))
1615  return 1;
1616  } else
1617  if (*dyopts[i].opname == 'r')
1618  {if (XrdOuca2x::a2i( *eDest,etxt,val,&ppp,0,2))
1619  return 1;
1620  } else {
1621  if (*dyopts[i].opname == 's')
1622  {ppp = strlen(val); SUPLevel = 0; minV = 0;
1623  if (val[ppp-1] == '%')
1624  {ispercent = 1; val[ppp-1] = '\0';}
1625  } else minV = 1;
1626  if (XrdOuca2x::a2i( *eDest,etxt,val,&ppp,minV))
1627  return 1;
1628  }
1629  if (!ispercent) *dyopts[i].oploc = ppp;
1630  else {ispercent = 0; SUPCount = 1; SUPLevel = ppp;}
1631  break;
1632  }
1633  if (i >= numopts)
1634  eDest->Say("Config warning: ignoring invalid delay option '",val,"'.");
1635  val = CFile.GetWord();
1636  }
1637 
1638 // Set the nostage option here
1639 //
1640  if (noStage) baseFS.SetTries(false, noStage);
1641  return 0;
1642 }
1643 
1644 /******************************************************************************/
1645 /* x d e f s */
1646 /******************************************************************************/
1647 
1648 /* Function: xdefs
1649 
1650  Purpose: Parse: oss.defaults <default options>
1651 
1652  Notes: See the oss configuration manual for the meaning of each option.
1653  The actual implementation is defined in XrdOucExport.
1654 
1655  Output: 0 upon success or !0 upon failure.
1656 */
1657 
1658 int XrdCmsConfig::xdefs(XrdSysError *eDest, XrdOucStream &CFile)
1659 {
1660  DirFlags = XrdOucExport::ParseDefs(CFile, *eDest, DirFlags);
1661  return 0;
1662 }
1663 
1664 /******************************************************************************/
1665 /* x d f s */
1666 /******************************************************************************/
1667 
1668 /* Function: xdfs
1669 
1670  Purpose: To parse the directive: dfs <opts>
1671 
1672  <opts>: limit [central] [=]<n>
1673  central - apply limit on manager node. Otherwise, limit
1674  is applied where lookups occur.
1675  [=]<n> - the limit value as transactions per second. If
1676  an equals is given before the limit, then
1677  requests are paced at the specified rate.
1678  Otherwise, a predictive algorithm is used.
1679  Zero (default) turns limit off.
1680 
1681  lookup {central | distrib}
1682  central - perform file lookups on the manager.
1683  distrib - distribute file lookups to servers (default).
1684 
1685  mdhold <n> - remember missing directories for n seconds
1686  Zero (default) turns this off.
1687 
1688  qmax <n> - maximum number of requests that may be queued.
1689  One is the minimum. The default qmax is 2.5
1690  the limit value.
1691 
1692  redirect {immed | verify}
1693  immed - do not verify file existence prior to
1694  redirecting a client. This is the
1695  default for proxy configurations.
1696  verify - verify file existence prior to
1697  redirecting a client. This is the
1698  default for non-proxy configurations. top
1699 
1700  retries <n> Maximum number of select retries.
1701 
1702  Type: Any, non-dynamic.
1703 
1704  Output: 0 upon success or !0 upon failure.
1705 */
1706 
1707 int XrdCmsConfig::xdfs(XrdSysError *eDest, XrdOucStream &CFile)
1708 {
1709  int Opts = XrdCmsBaseFS::DFSys | (isProxy ? XrdCmsBaseFS::Immed : 0)
1710  | (!isManager && isServer ? XrdCmsBaseFS::Servr: 0);
1711  int Hold = 0, limCent = 0, limFix = 0, limV = 0, qMax = 0, rTry = -1;
1712  char *val;
1713 
1714 // If we are a meta-manager or a peer, ignore this option
1715 //
1716  if (isMeta || isPeer) return CFile.noEcho();
1717 
1718 // Get first option. We need one but they can come in any order
1719 //
1720  if (!(val = CFile.GetWord()))
1721  {eDest->Emsg("Config", "dfs option not specified"); return 1;}
1722 
1723 // Now parse each option
1724 //
1725 do{ if (!strcmp("mdhold", val))
1726  {if (!(val = CFile.GetWord()))
1727  {eDest->Emsg("Config","mdhold value not specified."); return 1;}
1728  if (XrdOuca2x::a2tm(*eDest, "hold value", val, &Hold, 0)) return 1;
1729  }
1730  else if (!strcmp("limit", val))
1731  {if (!(val = CFile.GetWord()))
1732  {eDest->Emsg("Config","limit value not specified."); return 1;}
1733  if ((limCent = !strcmp("central",val)) && !(val = CFile.GetWord()))
1734  {eDest->Emsg("Config","limit value not specified."); return 1;}
1735  if ((limFix = (*val == '=')) && *(val+1)) val++;
1736  if (XrdOuca2x::a2i(*eDest, "limit value", val, &limV, 0)) return 1;
1737  }
1738  else if (!strcmp("lookup", val))
1739  {if (!(val = CFile.GetWord()))
1740  {eDest->Emsg("Config","lookup value not specified."); return 1;}
1741  if (!strcmp("central", val)) Opts |= XrdCmsBaseFS::Cntrl;
1742  else if (!strcmp("distrib", val)) Opts &= ~XrdCmsBaseFS::Cntrl;
1743  else {eDest->Emsg("Config","invalid lookup value '", val, "'.");
1744  return 1;
1745  }
1746  }
1747  else if (!strcmp("qmax", val))
1748  {if (!(val = CFile.GetWord()))
1749  {eDest->Emsg("Config","qmax value not specified."); return 1;}
1750  if (XrdOuca2x::a2i(*eDest, "qmax value", val, &qMax, 1)) return 1;
1751  }
1752  else if (!strcmp("redirect",val))
1753  {if (!(val = CFile.GetWord()))
1754  {eDest->Emsg("Config","redirect value not specified.");return 1;}
1755  if (!strcmp("immed", val)) Opts |= XrdCmsBaseFS::Immed;
1756  else if (!strcmp("verify", val)) Opts &= ~XrdCmsBaseFS::Immed;
1757  else {eDest->Emsg("Config","invalid redirect value -", val);
1758  return 1;
1759  }
1760  }
1761  else if (!strcmp("retries", val))
1762  {if (!(val = CFile.GetWord()))
1763  {eDest->Emsg("Config","retries value not specified."); return 1;}
1764  if (XrdOuca2x::a2i(*eDest, "retries value", val, &rTry, 0)) return 1;
1765  }
1766  else {eDest->Emsg("Config", "invalid dfs option '",val,"'."); return 1;}
1767  } while((val = CFile.GetWord()));
1768 
1769 // Supervisors are special beasts so we need to make transparent. One of these
1770 // days we'll allow lookups to go down to the supervisor level.
1771 //
1772  if (isManager && isServer)
1773  {limV = 0;
1774  Opts &= ~XrdCmsBaseFS::Cntrl;
1775  }
1776 
1777 // Adjust the limit value and option as needed
1778 //
1779  if (limV)
1780  {if (limFix) limV = -limV;
1781  if (limCent || Opts & XrdCmsBaseFS::Cntrl) {if (isServer) limV = 0;}
1782  else if (isManager) limV = 0;
1783  }
1784 
1785 // If we are a manager but not doing local lookups, then hold does not apply
1786 //
1787  if (isManager && !(Opts & XrdCmsBaseFS::Cntrl)) Hold = 0;
1788 
1789 // All done, simply set the values
1790 //
1791  baseFS.SetTries(true, rTry);
1792  baseFS.Limit(limV, qMax);
1793  baseFS.Init(Opts, Hold, Hold*10);
1794  return 0;
1795 }
1796 
1797 /******************************************************************************/
1798 /* x e x p o */
1799 /******************************************************************************/
1800 
1801 /* Function: xexpo
1802 
1803  Purpose: To parse the directive: all.export <path> [<options>]
1804 
1805  <path> the full path that resides in a remote system.
1806  <options> a blank separated list of options (see XrdOucExport)
1807 
1808  Output: 0 upon success or !0 upon failure.
1809 */
1810 
1811 int XrdCmsConfig::xexpo(XrdSysError *eDest, XrdOucStream &CFile)
1812 {
1813 
1814 // Parse the arguments
1815 //
1816  return (XrdOucExport::ParsePath(CFile, *eDest, PexpList, DirFlags) ? 0 : 1);
1817 }
1818 
1819 /******************************************************************************/
1820 /* x f s x q */
1821 /******************************************************************************/
1822 
1823 /* Function: xfsxq
1824 
1825  Purpose: To parse the directive: fsxeq <types> <prog>
1826 
1827  <types> what operations the program performs (one or more of):
1828  chmod mkdir mkpath mv rm rmdir
1829  <prog> the program to execute when doing a forwarded fs op.
1830 
1831  Type: Server only, non-dynamic.
1832 
1833  Output: 0 upon success or !0 upon failure.
1834 */
1835 
1836 int XrdCmsConfig::xfsxq(XrdSysError *eDest, XrdOucStream &CFile)
1837 {
1838  struct xeqopts {const char *opname; int doset; XrdOucProg **pgm;} xqopts[] =
1839  {
1840  {"chmod", 0, &ProgCH},
1841  {"mkdir", 0, &ProgMD},
1842  {"mkpath", 0, &ProgMP},
1843  {"mv", 0, &ProgMV},
1844  {"rm", 0, &ProgRM},
1845  {"rmdir", 0, &ProgRD},
1846  {"trunc", 0, &ProgTR}
1847  };
1848  int i, xtval = 0, numopts = sizeof(xqopts)/sizeof(struct xeqopts);
1849  char *val;
1850 
1851 // If we are a manager, ignore this option
1852 //
1853  if (!isServer) return CFile.noEcho();
1854 
1855 // Get the operation types
1856 //
1857  val = CFile.GetWord();
1858  while (val && *val != '/')
1859  {for (i = 0; i < numopts; i++)
1860  if (!strcmp(val, xqopts[i].opname))
1861  {xqopts[i].doset = 1;
1862  xtval = 1;
1863  break;
1864  }
1865  if (i >= numopts)
1866  eDest->Say("Config warning: ignoring invalid fsxeq type option '",val,"'.");
1867  val = CFile.GetWord();
1868  }
1869 
1870 // Make sure some type was specified
1871 //
1872  if (!xtval)
1873  {eDest->Emsg("Config", "fsxeq type option not specified"); return 1;}
1874 
1875 // Make sure a program was specified
1876 //
1877  if (!val)
1878  {eDest->Emsg("Config", "fsxeq program not specified"); return 1;}
1879 
1880 // Get the program
1881 //
1882  CFile.RetToken();
1883 
1884 // Set the program for each type
1885 //
1886  for (i = 0; i < numopts; i++)
1887  if (xqopts[i].doset)
1888  {if (!*xqopts[i].pgm) *(xqopts[i].pgm) = new XrdOucProg(0);
1889  if ((*(xqopts[i].pgm))->Setup(val, eDest)) return 1;
1890  }
1891 
1892 // All done
1893 //
1894  return 0;
1895 }
1896 
1897 /******************************************************************************/
1898 /* x f x h l d */
1899 /******************************************************************************/
1900 
1901 /* Function: xfxhld
1902 
1903  Purpose: To parse the directive: fxhold [noloc <nls>] <sec>
1904 
1905  <nls> number of seconds (or M, H, etc) to cache file non-existence
1906  <sec> number of seconds (or M, H, etc) to cache file existence
1907 
1908  Type: Manager only, dynamic.
1909 
1910  Output: 0 upon success or !0 upon failure.
1911 */
1912 
1913 int XrdCmsConfig::xfxhld(XrdSysError *eDest, XrdOucStream &CFile)
1914 {
1915  char *val;
1916  int ct;
1917 
1918  if (!isManager) return CFile.noEcho();
1919 
1920  if (!(val = CFile.GetWord()))
1921  {eDest->Emsg("Config", "fxhold value not specified."); return 1;}
1922 
1923  if (!strcmp(val, "noloc"))
1924  {if (!(val = CFile.GetWord()))
1925  {eDest->Emsg("Config","fxhold noloc value not specified."); return 1;}
1926  if (XrdOuca2x::a2tm(*eDest, "fxhold noloc value", val, &ct,
1927  XrdCmsCache:: min_nxTime)) return 1;
1928  emptylife = ct;
1929  if (!(val = CFile.GetWord())) return 0;
1930  }
1931 
1932  if (XrdOuca2x::a2tm(*eDest, "fxhold value", val, &ct, 60)) return 1;
1933 
1934  cachelife = ct;
1935  return 0;
1936 }
1937 
1938 /******************************************************************************/
1939 /* x l c l r t */
1940 /******************************************************************************/
1941 
1942 /* Function: xlclrt
1943 
1944  Purpose: To parse the directive: localroot <path>
1945 
1946  <path> the path that the server will prefix to all local paths.
1947 
1948  Type: Server only, non-dynamic.
1949 
1950  Output: 0 upon success or !0 upon failure.
1951 */
1952 
1953 int XrdCmsConfig::xlclrt(XrdSysError *eDest, XrdOucStream &CFile)
1954 {
1955  char *val;
1956  int i;
1957 
1958 // If we are a manager, ignore this option
1959 //
1960  if (!isServer) return CFile.noEcho();
1961 
1962 // Get path type
1963 //
1964  val = CFile.GetWord();
1965  if (!val || !val[0])
1966  {eDest->Emsg("Config", "localroot path not specified"); return 1;}
1967  if (*val != '/')
1968  {eDest->Emsg("Config", "localroot path not absolute"); return 1;}
1969 
1970 // Cleanup the path
1971 //
1972  i = strlen(val)-1;
1973  while (i && val[i] == '/') val[i--] = '\0';
1974 
1975 // Assign new path prefix
1976 //
1977  if (i)
1978  {if (LocalRoot) free(LocalRoot);
1979  LocalRoot = strdup(val);
1980  }
1981  return 0;
1982 }
1983 
1984 /******************************************************************************/
1985 /* x m a n g */
1986 /******************************************************************************/
1987 
1988 /* Function: xmang
1989 
1990  Purpose: Parse: manager [meta | peer | proxy] [all|any]
1991  <host>[+][:<port>|<port>] [if ...]
1992 
1993  meta For cmsd: Specified the manager when running as a manager
1994  For xrootd: The directive is ignored.
1995  peer For cmsd: Specified the manager when running as a peer
1996  For xrootd: The directive is ignored.
1997  proxy For cmsd: This directive is ignored.
1998  For xrootd: Specifies the cmsd-proxy service manager
1999  all Ignored (useful only to the cmsd client)
2000  any Ignored (useful only to the cmsd client)
2001  <host> The dns name of the host that is the cache manager.
2002  If the host name ends with a plus, all addresses that are
2003  associated with the host are treated as managers.
2004  <port> The port number to use for this host.
2005  if Apply the manager directive if "if" is true. See
2006  XrdOucUtils:doIf() for "if" syntax.
2007 
2008  Notes: Any number of manager directives can be given.
2009 
2010  Type: Remote server only, non-dynamic.
2011 
2012  Output: 0 upon success or !0 upon failure.
2013 */
2014 
2015 int XrdCmsConfig::xmang(XrdSysError *eDest, XrdOucStream &CFile)
2016 {
2017  class StorageHelper
2018  {public:
2019  StorageHelper(char **v1, char **v2) : val1(v1), val2(v2) {}
2020  ~StorageHelper() {if (*val1) free(*val1);
2021  if (*val2) free(*val2);
2022  }
2023  char **val1, **val2;
2024  };
2025 
2026  XrdOucTList **theList = &ManList;
2027  char *val, *hSpec = 0, *hPort = 0;
2028  StorageHelper SHelp(&hSpec, &hPort);
2029  int rc, xMeta = 0, xPeer = 0, xProxy = 0, *myPort = 0;
2030 
2031 // Process the optional "meta", "peer" or "proxy"
2032 //
2033  if ((val = CFile.GetWord()))
2034  {if ((xMeta = !strcmp("meta", val))
2035  || (xPeer = !strcmp("peer", val))
2036  || (xProxy = !strcmp("proxy", val)))
2037  {if ((xMeta && (isServer || isPeer))
2038  || (xPeer && !isPeer)
2039  || (xProxy && !isProxy)) return CFile.noEcho();
2040  val = CFile.GetWord();
2041  } else if (isPeer) return CFile.noEcho();
2042  }
2043 
2044 // We can accept this manager. Skip the optional "all" or "any"
2045 //
2046  if (val)
2047  if (!strcmp("any", val) || !strcmp("all", val)) val = CFile.GetWord();
2048 
2049 // Get the actual host name and copy it
2050 //
2051  if (!val)
2052  {eDest->Emsg("Config","manager host name not specified"); return 1;}
2053  hSpec = strdup(val);
2054 
2055 // Grab the port number (either in hostname or following token)
2056 //
2057  if (!(hPort = XrdCmsUtils::ParseManPort(eDest, CFile, hSpec))) return 1;
2058 
2059 // Check if this statement is gaurded by and "if" and process it
2060 //
2061  if ((val = CFile.GetWord()))
2062  {if (strcmp(val, "if"))
2063  {eDest->Emsg("Config","expecting manager 'if' but",val,"found");
2064  return 1;
2065  }
2066  if ((rc = XrdOucUtils::doIf(eDest,CFile,"manager directive",
2067  myName,myInsName,myProg))<=0)
2068  {if (!rc) CFile.noEcho(); return rc < 0;}
2069  }
2070 
2071 // Calculate the correct queue and port number to update
2072 //
2073  if (isManager && !isServer)
2074 // {if (((xMeta && isMeta) || (!xMeta && !isMeta)) && PortTCP < 1)
2075  {if (((xMeta && isMeta) || (!xMeta && !isMeta)))
2076  myPort = &PortTCP;
2077  if (isMeta) theList = 0;
2078  else theList = (xMeta ? &ManList : &NanList);
2079  }
2080 
2081 // Parse the specification and return
2082 //
2083  return (XrdCmsUtils::ParseMan(eDest, theList, hSpec, hPort, myPort) ? 0 : 1);
2084 }
2085 
2086 /******************************************************************************/
2087 /* x m o d e */
2088 /******************************************************************************/
2089 
2090 /* Function: xmode
2091 
2092  Purpose: To parse the directive: mode {r/o | readonly | r/w | readwrite}
2093 
2094  r/o Only allows read operations, readonly is a synonym.
2095  r/w Allows read and write operations, readwrite is a synonym.
2096  This mode is the default.
2097 
2098  Type: Manager only, non-dynamic.
2099 
2100  Output: 0 upon success or !0 upon failure.
2101 */
2102 
2103 int XrdCmsConfig::xmode(XrdSysError *eDest, XrdOucStream &CFile)
2104 {
2105  char *val;
2106 
2107  if (!isManager) return CFile.noEcho();
2108 
2109  if (!(val = CFile.GetWord()))
2110  {eDest->Emsg("Config", "mode type not specified"); return 1;}
2111 
2112  if (!strcmp(val, "r/o") || !strcmp(val, "readonly")) forceRO = true;
2113  else if (!strcmp(val,"r/w") || !strcmp(val,"readwrite")) forceRO = false;
2114  else {eDest->Emsg("Config", "invalid mode type -", val);
2115  return 1;
2116  }
2117 
2118  return 0;
2119 }
2120 
2121 /******************************************************************************/
2122 /* x n b s q */
2123 /******************************************************************************/
2124 
2125 /* Function: xnbsq
2126 
2127  Purpose: To parse the directive: nbsendq [<opt>] [warn <nw>] [maxq <mq>]
2128 
2129  <opt> One of: all | off | remote
2130  <nw> Warning will be issued at a <nw> backlog.
2131  <mq> Message will be discarded at a <mq> backlog (<mq> may
2132  also be the word "none").
2133 
2134  Defaults: remote warn 3 maxq 30
2135 
2136  Output: 0 upon success or !0 upon failure.
2137 */
2138 
2139 int XrdCmsConfig::xnbsq(XrdSysError *eDest, XrdOucStream &CFile)
2140 {
2141  char *val, xopt[16];
2142  int ival;
2143  bool xAll = false, xOff = false, xRmt = false;
2144 
2145 // Process the optional "all", "off" or "remote"
2146 //
2147  if ((val = CFile.GetWord()))
2148  {if ((xAll = !strcmp("all", val))
2149  || (xOff = !strcmp("off", val))
2150  || (xRmt = !strcmp("remote", val)))
2151  { if (xAll) nbSQ = 2;
2152  else if (xRmt) nbSQ = 1;
2153  else nbSQ = 0;
2154  val = CFile.GetWord();
2155  }
2156  } else {eDest->Emsg("Config","nbsendq option not specified"); return 1;}
2157 
2158 // Now scan for the other options
2159 //
2160  while(val && *val)
2161  {size_t size = sizeof(xopt)-1;
2162  strncpy(xopt, val, size);
2163  xopt[size] = '\0';
2164  if (!(val= CFile.GetWord()) || *val == 0)
2165  {eDest->Emsg("Config","nbsendq ", xopt, " argument not specified");
2166  return 1;
2167  }
2168  if (!strcmp(xopt, "maxq"))
2169  {if (!strcmp("val", "none")) ival = -1;
2170  else if (XrdOuca2x::a2i(*eDest,"nbsendq maxq",val,&ival,0))
2171  return 1;
2172  XrdSendQ::SetQM(ival);
2173  }
2174  else if (!strcmp(xopt, "warn"))
2175  {if (XrdOuca2x::a2i(*eDest,"nbsendq warn",val,&ival,0)) return 1;
2176  XrdSendQ::SetQW(ival);
2177  }
2178  else eDest->Say("Config warning: ignoring invalid nbsendq option '",xopt,"'.");
2179  val = CFile.GetWord();
2180  }
2181  return 0;
2182 }
2183 
2184 /******************************************************************************/
2185 /* x p e r f */
2186 /******************************************************************************/
2187 
2188 /* Function: xperf
2189 
2190  Purpose: To parse the directive: perf [xrootd] [int <sec>]
2191  [lib <lib> [<parms>] | pgm <pgm>]
2192 
2193  int <time> estimated time (seconds, M, H) between reports by <pgm>
2194  lib <lib> the shared library holding the XrdCmsPerf object that
2195  reports perf values. It must be the last option.
2196  pgm <pgm> program to start that will write perf values to standard
2197  out. It must be the last option.
2198  xrootd This directive only applies to the cms xrootd plugin.
2199 
2200  Type: Server only, non-dynamic.
2201 
2202  Output: 0 upon success or !0 upon failure. Ignored by manager.
2203 */
2204 int XrdCmsConfig::xperf(XrdSysError *eDest, XrdOucStream &CFile)
2205 { char *pgm=0, *val, rest[2048];
2206 
2207  if (!isServer) return CFile.noEcho();
2208 
2209  if (!(val = CFile.GetWord()))
2210  {eDest->Emsg("Config", "perf options not specified"); return 1;}
2211 
2212  if (!strcmp("xrootd", val)) return CFile.noEcho();
2213  perfint = 3*60;
2214 
2215  do { if (!strcmp("int", val))
2216  {if (!(val = CFile.GetWord()))
2217  {eDest->Emsg("Config", "perf int value not specified");
2218  return 1;
2219  }
2220  if (XrdOuca2x::a2tm(*eDest,"perf int",val,&perfint,0)) return 1;
2221  }
2222  else if (!strcmp("lib", val))
2223  {if (perfpgm) {free(perfpgm); perfpgm = 0;}
2224  return (XrdOucUtils::parseLib(*eDest,CFile,"perf lib",
2225  prfLib, &prfParms) ? 0 : 1);
2226  break;
2227  }
2228  else if (!strcmp("pgm", val))
2229  {if (!CFile.GetRest(rest, sizeof(rest)))
2230  {eDest->Emsg("Config", "perf pgm parameters too long");
2231  return 1;
2232  }
2233  if (!*rest)
2234  {eDest->Emsg("Config", "perf pgm value not specified");
2235  return 1;
2236  }
2237  pgm = rest;
2238  break;
2239  }
2240  else eDest->Say("Config warning: ignoring invalid perf option '",val,"'.");
2241  } while((val = CFile.GetWord()));
2242 
2243 // Make sure that the perf program is here
2244 //
2245  if (perfpgm) {free(perfpgm); perfpgm = 0;}
2246  if (prfLib) {free(prfLib); prfLib = 0;}
2247  if (prfParms){free(prfParms);prfParms = 0;}
2248  if (pgm) {if (!isExec(eDest, "perf", pgm)) return 1;
2249  else perfpgm = strdup(pgm);
2250  }
2251 
2252 // All done.
2253 //
2254  return 0;
2255 }
2256 
2257 /******************************************************************************/
2258 /* x p i n g */
2259 /******************************************************************************/
2260 
2261 /* Function: xping
2262 
2263  Purpose: To parse the directive: ping <ptm> [log <num>] [usage <cnt>]
2264 
2265  <ptm> Time (seconds, M, H. etc) between keepalive pings.
2266  The default is 60 seconds.
2267  log values are logged to the log every <num> usage
2268  requests (default 10). Zero, suppresses logging.
2269  usage The number of pings between resource usage requests.
2270  The default is 10. Zero suppresses usage requests.
2271 
2272  Note: The defaults will log usage 100 minutes (little less than 2 hours).
2273 
2274  Type: Server for ping value and Manager for all values, dynamic.
2275 
2276  Output: 0 upon success or !0 upon failure.
2277 */
2278 int XrdCmsConfig::xping(XrdSysError *eDest, XrdOucStream &CFile)
2279 { int pnum = AskPerf, lnum = LogPerf, ping;
2280  char *val;
2281 
2282  if (!(val = CFile.GetWord()))
2283  {eDest->Emsg("Config", "ping value not specified"); return 1;}
2284  if (XrdOuca2x::a2tm(*eDest, "ping interval",val,&ping,0)) return 1;
2285  if (ping < 3) ping = 3;
2286 
2287  while((val = CFile.GetWord()))
2288  { if (!strcmp("log", val))
2289  {if (!(val = CFile.GetWord()))
2290  {eDest->Emsg("Config", "ping log value not specified");
2291  return 1;
2292  }
2293  if (XrdOuca2x::a2i(*eDest,"ping log",val,&lnum,0)) return 1;
2294  }
2295  else if (!strcmp("usage", val))
2296  {if (!(val = CFile.GetWord()))
2297  {eDest->Emsg("Config", "ping usage value not specified");
2298  return 1;
2299  }
2300  if (XrdOuca2x::a2i(*eDest,"ping usage",val,&pnum,1)) return 1;
2301  }
2302  }
2303  AskPerf = pnum;
2304  AskPing = ping;
2305  LogPerf = lnum;
2306  return 0;
2307 }
2308 
2309 /******************************************************************************/
2310 /* x p r e p */
2311 /******************************************************************************/
2312 
2313 /* Function: xprep
2314 
2315  Purpose: To parse the directive: prep [echo]
2316  [reset <cnt>] [scrub <sec>]
2317  [ifpgm <pgm>]
2318 
2319  echo display list of pending prepares during resets.
2320  reset <cnt> number of scrubs after which a full reset is done.
2321  scrub <sec> time (seconds, M, H) between pendq scrubs.
2322  ifpgm <pgm> program that adds, deletes, and lists prepare queue
2323  entries. If specified, t must be specified as the last
2324  option on the line. If not specified, then the built-in
2325  frm_xfragent program is used.
2326 
2327  Type: Any, non-dynamic. Note that the Manager only need the "batch" option
2328  while slacves need the remaining options.
2329 
2330  Output: 0 upon success or !0 upon failure. Ignored by manager.
2331 */
2332 int XrdCmsConfig::xprep(XrdSysError *eDest, XrdOucStream &CFile)
2333 { int reset=0, scrub=0, echo = 0, doset = 0;
2334  char *prepif=0, *val, rest[2048];
2335 
2336  if (!isServer) return CFile.noEcho();
2337 
2338  if (!(val = CFile.GetWord())) {PrepQ.setParms(""); return 0;}
2339 
2340  do { if (!strcmp("echo", val)) doset = echo = 1;
2341  else if (!strcmp("reset", val))
2342  {if (!(val = CFile.GetWord()))
2343  {eDest->Emsg("Config", "prep reset value not specified");
2344  return 1;
2345  }
2346  if (XrdOuca2x::a2i(*eDest,"prep reset int",val,&reset,1)) return 1;
2347  doset = 1;
2348  }
2349  else if (!strcmp("scrub", val))
2350  {if (!(val = CFile.GetWord()))
2351  {eDest->Emsg("Config", "prep scrub value not specified");
2352  return 1;
2353  }
2354  if (XrdOuca2x::a2tm(*eDest,"prep scrub",val,&scrub,0)) return 1;
2355  doset = 1;
2356  }
2357  else if (!strcmp("ifpgm", val))
2358  {if (!CFile.GetRest(rest, sizeof(rest)))
2359  {eDest->Emsg("Config", "prep ifpgm parameters too long"); return 1;}
2360  if (!*rest)
2361  {eDest->Emsg("Config", "prep ifpgm value not specified");
2362  return 1;
2363  }
2364  prepif = rest;
2365  break;
2366  }
2367  else eDest->Say("Config warning: ignoring invalid prep option '",val,"'.");
2368  } while((val = CFile.GetWord()));
2369 
2370 
2371 
2372 // Set the values
2373 //
2374  if (scrub) pendplife = scrub;
2375  if (doset) PrepQ.setParms(reset, scrub, echo);
2376  if (prepif) {if (!isExec(eDest, "prep", prepif)) return 1;
2377  else return PrepQ.setParms(prepif);
2378  } else PrepQ.setParms("");
2379  return 0;
2380 }
2381 
2382 /******************************************************************************/
2383 /* x p r e p m */
2384 /******************************************************************************/
2385 
2386 /* Function: xprepm
2387 
2388  Purpose: To parse the directive: prepmsg <msg>
2389 
2390  <msg> the message to be sent to the prep ifpgm (see prep).
2391 
2392  Type: Manager only, non-dynamic.
2393 
2394  Output: 0 upon success or !0 upon failure.
2395 */
2396 
2397 int XrdCmsConfig::xprepm(XrdSysError *eDest, XrdOucStream &CFile)
2398 {
2399  char *val, buff[2048];
2400  XrdOucEnv *myEnv = CFile.SetEnv(0);
2401 
2402  // At this point, make sure we have a value
2403  //
2404  if (!(val = CFile.GetWord()))
2405  {eDest->Emsg("Config", "no value for prepmsg directive");
2406  CFile.SetEnv(myEnv);
2407  return 1;
2408  }
2409 
2410  // We need to suck all the tokens to the end of the line for remaining
2411  // options. Do so, until we run out of space in the buffer.
2412  //
2413  CFile.RetToken();
2414  if (!CFile.GetRest(buff, sizeof(buff)))
2415  {eDest->Emsg("Config", "prepmsg arguments too long");
2416  CFile.SetEnv(myEnv);
2417  return 1;
2418  }
2419 
2420  // Restore substitutions and parse the message
2421  //
2422  CFile.SetEnv(myEnv);
2423  return PrepQ.setParms(0, buff);
2424 }
2425 
2426 /******************************************************************************/
2427 /* x r e p s */
2428 /******************************************************************************/
2429 
2430 /* Function: xreps
2431 
2432  Purpose: To parse the directive: repstats <options>
2433 
2434  Type: Manager or Server, dynamic.
2435 
2436  Output: 0 upon success or !0 upon failure.
2437 */
2438 
2439 int XrdCmsConfig::xreps(XrdSysError *eDest, XrdOucStream &CFile)
2440 {
2441  char *val;
2442  static struct repsopts {const char *opname; int opval;} rsopts[] =
2443  {
2444  {"all", RepStat_All},
2445  {"frq", RepStat_frq},
2446  {"shr", RepStat_shr}
2447  };
2448  int i, neg, rsval = 0, numopts = sizeof(rsopts)/sizeof(struct repsopts);
2449 
2450  if (!(val = CFile.GetWord()))
2451  {eDest->Emsg("config", "repstats option not specified"); return 1;}
2452  while (val)
2453  {if (!strcmp(val, "off")) rsval = 0;
2454  else {if ((neg = (val[0] == '-' && val[1]))) val++;
2455  for (i = 0; i < numopts; i++)
2456  {if (!strcmp(val, rsopts[i].opname))
2457  {if (neg) rsval &= ~rsopts[i].opval;
2458  else rsval |= rsopts[i].opval;
2459  break;
2460  }
2461  }
2462  if (i >= numopts)
2463  eDest->Say("Config warning: ignoring invalid repstats option '",val,"'.");
2464  }
2465  val = CFile.GetWord();
2466  }
2467 
2468  RepStats = rsval;
2469  return 0;
2470 }
2471 
2472 /******************************************************************************/
2473 /* x r m t r t */
2474 /******************************************************************************/
2475 
2476 /* Function: xrmtrt
2477 
2478  Purpose: To parse the directive: remoteroot <path>
2479 
2480  <path> the path that the server will prefix to all remote paths.
2481 
2482  Type: Manager only, non-dynamic.
2483 
2484  Output: 0 upon success or !0 upon failure.
2485 */
2486 
2487 int XrdCmsConfig::xrmtrt(XrdSysError *eDest, XrdOucStream &CFile)
2488 {
2489  char *val, *colon, *slash;
2490  int i;
2491 
2492 // If we are a manager, ignore this option
2493 //
2494  if (isManager) return CFile.noEcho();
2495 
2496 // Get path type
2497 //
2498  val = CFile.GetWord();
2499  if (!val || !val[0])
2500  {eDest->Emsg("Config", "remoteroot path not specified"); return 1;}
2501 
2502 // For remote roots we allow a url-type specification o/w path must be absolute
2503 //
2504  if (*val != '/')
2505  {colon = index(val, ':'); slash = index(val, '/');
2506  if ((colon+1) != slash)
2507  {eDest->Emsg("Config", "remoteroot path not absolute"); return 1;}
2508  }
2509 
2510 // Cleanup the path
2511 //
2512  i = strlen(val)-1;
2513  while (i && val[i] == '/') val[i--] = '\0';
2514 
2515 // Assign new path prefix
2516 //
2517  if (i)
2518  {if (RemotRoot) free(RemotRoot);
2519  RemotRoot = strdup(val);
2520  }
2521  return 0;
2522 }
2523 
2524 /******************************************************************************/
2525 /* x r o l e */
2526 /******************************************************************************/
2527 
2528 /* Function: xrole
2529  Purpose: Parse: role { {[meta] | [peer] [proxy]} manager
2530  | peer | proxy | [proxy] server
2531  | [proxy] supervisor
2532  } [if ...]
2533 
2534  manager xrootd: act as a manager (redirecting server). Prefixes:
2535  meta - connect only to manager meta's
2536  peer - ignored
2537  proxy - ignored
2538  cmsd: accept server subscribes and redirectors. Prefix
2539  modifiers do the following:
2540  meta - No other managers apply
2541  peer - subscribe to other managers as a peer
2542  proxy - manage a cluster of proxy servers
2543 
2544  peer xrootd: same as "peer manager"
2545  cmsd: same as "peer manager" but no server subscribers
2546  are required to function (i.e., run stand-alone).
2547 
2548  proxy xrootd: act as a server but supply data from another
2549  server. No local cmsd is present or required.
2550  cmsd: Generates an error as this makes no sense.
2551 
2552  server xrootd: act as a server (supply local data). Prefix
2553  modifications do the following:
2554  proxy - server is part of a cluster. A local
2555  cmsd is required.
2556  cmsd: subscribe to a manager, possibly as a proxy.
2557 
2558  supervisor xrootd: equivalent to manager.
2559  cmsd: equivalent to manager but also subscribe to a
2560  manager. When proxy is specified, subscribe as
2561  a proxy and only accept proxy servers.
2562 
2563 
2564  if Apply the manager directive if "if" is true. See
2565  XrdOucUtils:doIf() for "if" syntax.
2566 
2567 
2568  Type: Server only, non-dynamic.
2569 
2570  Output: 0 upon success or !0 upon failure.
2571 */
2572 
2573 int XrdCmsConfig::xrole(XrdSysError *eDest, XrdOucStream &CFile)
2574 {
2575  XrdCmsRole::RoleID roleID;
2576  char *val, *Tok1, *Tok2;
2577  int rc, xMeta=0, xPeer=0, xProxy=0, xServ=0, xMan=0, xSolo=0;
2578 
2579 // Get the first token
2580 //
2581  if (!(val = CFile.GetWord()) || !strcmp(val, "if"))
2582  {eDest->Emsg("Config", "role not specified"); return 1;}
2583  Tok1 = strdup(val);
2584 
2585 // Get second token which might be an "if"
2586 //
2587  if ((val = CFile.GetWord()) && strcmp(val, "if"))
2588  {Tok2 = strdup(val);
2589  val = CFile.GetWord();
2590  } else Tok2 = 0;
2591 
2592 // Process the if at this point
2593 //
2594  if (val && !strcmp("if", val))
2595  if ((rc = XrdOucUtils::doIf(eDest,CFile,"role directive",
2596  myName,myInsName,myProg)) <= 0)
2597  {free(Tok1); if (Tok2) free(Tok2);
2598  if (!rc) CFile.noEcho();
2599  return (rc < 0);
2600  }
2601 
2602 // Convert the role names to a role ID, if possible
2603 //
2604  roleID = XrdCmsRole::Convert(Tok1, Tok2);
2605 
2606 // Set markers based on the role we have
2607 //
2608  rc = 0;
2609  switch(roleID)
2610  {case XrdCmsRole::MetaManager: xMeta = xMan = -1; break;
2611  case XrdCmsRole::Manager: xMan = -1; break;
2612  case XrdCmsRole::Supervisor: xMan = xServ = -1; break;
2613  case XrdCmsRole::Server: xServ = -1; break;
2614  case XrdCmsRole::ProxyManager: xProxy = xMan = -1; break;
2615  case XrdCmsRole::ProxySuper: xProxy = xMan = xServ = -1; break;
2616  case XrdCmsRole::ProxyServer: xProxy = xServ = -1; break;
2617  case XrdCmsRole::PeerManager: xPeer = xMan = -1; break;
2618  case XrdCmsRole::Peer: xPeer = xSolo = xServ -1; break;
2619  default: eDest->Emsg("Config", "invalid role -", Tok1, Tok2); rc = 1;
2620  }
2621 
2622 // Release storage and return if an error occurred
2623 //
2624  free(Tok1);
2625  if (Tok2) free(Tok2);
2626  if (rc) return rc;
2627 
2628 // If the role was specified on the command line, issue warning and ignore this
2629 //
2630  if (isServer > 0 || isManager > 0 || isProxy > 0 || isPeer > 0)
2631  {eDest->Say("Config warning: role directive over-ridden by command line.");
2632  return 0;
2633  }
2634 
2635 // Fill out information
2636 //
2637  isServer = xServ; isManager = xMan; isProxy = xProxy;
2638  isPeer = xPeer; isSolo = xSolo; isMeta = xMeta;
2639  if (myRole) free(myRole);
2640  myRole = strdup(XrdCmsRole::Name(roleID));
2641  myRoleID = static_cast<int>(roleID);
2642  strcpy(myRType, XrdCmsRole::Type(roleID));
2643  return 0;
2644 }
2645 
2646 /******************************************************************************/
2647 /* x s c h e d */
2648 /******************************************************************************/
2649 
2650 /* Function: xsched
2651 
2652  Purpose: To parse directive: sched [cpu <p>] [gsdflt <p>] [gshr <p>]
2653  [io <p>] [runq <p>]
2654  [mem <p>] [pag <p>] [space <p>]
2655  [fuzz <p>] [maxload <p>] [refreset <sec>]
2656  [maxretries <n>[@<host>:<port>]]
2657  [nomultisrc[@<host>:<port>]]
2658  [affinity [default] {none | weak | strong | strict}]
2659  [affpath {all | first m | last n}]
2660 
2661  <p> is the percentage to include in the load as a value
2662  between 0 and 100. For fuzz this is the largest
2663  difference two load values may have to be treated equal.
2664  maxload is the largest load allowed before server is
2665  not selected. refreset is the minimum number of seconds
2666  between reference counter resets. gshr is the percentage
2667  share of requests that should be redirected here via the
2668  metamanager (i.e. global share). The gsdflt is the
2669  default to be used by the metamanager.
2670 
2671  Type: Any, dynamic.
2672 
2673  Output: retc upon success or -EINVAL upon failure.
2674 */
2675 
2676 int XrdCmsConfig::xsched(XrdSysError *eDest, XrdOucStream &CFile)
2677 {
2678  char *val;
2679  int i, ppp, V_hntry = -1;
2680  static struct schedopts {const char *opname; int maxv; int *oploc;}
2681  scopts[] =
2682  {
2683  {"cpu", 100, &P_cpu},
2684  {"fuzz", 100, &P_fuzz},
2685  {"gsdflt", 100, &P_gsdf},
2686  {"gshr", 100, &P_gshr},
2687  {"io", 100, &P_io},
2688  {"runq", 100, &P_load}, // Actually load, runq to avoid confusion
2689  {"mem", 100, &P_mem},
2690  {"pag", 100, &P_pag},
2691  {"space", 100, &P_dsk},
2692  {"maxload", 100, &MaxLoad},
2693  {"refreset", -1, &RefReset},
2694  {"affinity", -2, 0},
2695  {"affpath", -3, 0},
2696  {"tryhname", 1, &V_hntry}
2697  };
2698  int numopts = sizeof(scopts)/sizeof(struct schedopts);
2699 
2700  if (!(val = CFile.GetWord()))
2701  {eDest->Emsg("Config", "sched option not specified"); return 1;}
2702 
2703  while (val)
2704  {for (i = 0; i < numopts; i++)
2705  if (!strcmp(val, scopts[i].opname))
2706  {if (!(val = CFile.GetWord()))
2707  {eDest->Emsg("Config", "sched ", scopts[i].opname,
2708  "argument not specified.");
2709  return 1;
2710  }
2711  if (scopts[i].maxv == -2)
2712  {if (!xschedm(val, eDest, CFile)) return 1;
2713  break;
2714  }
2715  if (scopts[i].maxv == -3)
2716  {if (!xschedp(val, eDest, CFile)) return 1;
2717  break;
2718  }
2719  if (scopts[i].maxv < 0)
2720  {if (XrdOuca2x::a2tm(*eDest,"sched value", val, &ppp, 0))
2721  return 1;
2722  }
2723  else if (XrdOuca2x::a2i(*eDest,"sched value", val, &ppp,
2724  0, scopts[i].maxv)) return 1;
2725  *scopts[i].oploc = ppp;
2726  break;
2727  }
2728  if (i >= numopts)
2729  {int rc = xschedx(val, eDest, CFile);
2730  if (rc < 0) return 1;
2731  if (rc > 0) eDest->Say("Config warning: "
2732  "ignoring invalid sched option '",val,"'.");
2733  }
2734  val = CFile.GetWord();
2735  }
2736 
2737 // Handle non-int settings
2738 //
2739  if (V_hntry >= 0) DoHnTry = static_cast<char>(V_hntry);
2740 
2741  return 0;
2742 }
2743 
2744 /******************************************************************************/
2745 
2746 int XrdCmsConfig::xschedm(char *val, XrdSysError *eDest, XrdOucStream &CFile)
2747 {
2748 
2749  if (!strcmp(val, "default"))
2750  {sched_Force = 0;
2751  if (!(val = CFile.GetWord()))
2752  {eDest->Emsg("Config", "sched affinity not specified"); return 0;}
2753  } else sched_Force = 1;
2754 
2755  if (!strcmp(val, "none"))
2756  {sched_Pack = sched_Level = 0;
2757  return 1;
2758  }
2759 
2760  sched_Pack = sched_Level = 1;
2761 
2762  if (!strcmp(val, "weak")) return 1;
2763 
2764  sched_Pack = 2;
2765 
2766  if (!strcmp(val, "strong")) return 1;
2767 
2768  if (!strcmp(val, "strict"))
2769  {sched_Level = 0;
2770  return 1;
2771  }
2772 
2773  if (!strcmp(val, "randomized"))
2774  {sched_LoadR = 1;
2775  return 1;
2776  }
2777 
2778  eDest->Emsg("Config", "Invalid sched affinity -", val);
2779  return 0;
2780 }
2781 
2782 /******************************************************************************/
2783 
2784 int XrdCmsConfig::xschedp(char *val, XrdSysError *eDest, XrdOucStream &CFile)
2785 {
2786  int afpsign, afpval;
2787 
2788  if (!strcmp(val, "all"))
2789  {sched_AffPC = 0;
2790  return 1;
2791  }
2792 
2793  if (!strcmp(val, "first")) afpsign = 1;
2794  else if (!strcmp(val, "last")) afpsign = -1;
2795  else {eDest->Emsg("Config", "sched affpath option invalid -", val);
2796  return 0;
2797  }
2798 
2799  if (!(val = CFile.GetWord()))
2800  {eDest->Emsg("Config", "sched affpath argument not specified"); return 0;}
2801 
2802  if (XrdOuca2x::a2i(*eDest,"sched affpath value", val, &afpval, 1, 255))
2803  return 0;
2804 
2805  sched_AffPC = static_cast<char>(afpval*afpsign);
2806  return 1;
2807 }
2808 
2809 /******************************************************************************/
2810 
2811 int XrdCmsConfig::xschedx(char *val, XrdSysError *eDest, XrdOucStream &CFile)
2812 {
2813 
2814 // Check for maxretries
2815 //
2816  if (!strcmp(val, "maxretries"))
2817  {if (!(val = CFile.GetWord()))
2818  {eDest->Emsg("Config","sched ","maxretries argument not specified.");
2819  return -1;
2820  }
2821  if (!xschedy(val, eDest, mrRdrHost, mrRdrHLen, mrRdrPort)) return -1;
2822  if (XrdOuca2x::a2i(*eDest,"sched value",val,&MaxRetries,0)) return -1;
2823  return 0;
2824  }
2825 
2826 // Check for unqualified nomultisrc
2827 //
2828  if (!strcmp(val, "nomultisrc"))
2829  {MultiSrc = 0;
2830  if (msRdrHost)
2831  {free(msRdrHost);
2832  msRdrHost = 0;
2833  msRdrHLen = 0;
2834  }
2835  return 0;
2836  }
2837 
2838 // Check for qualified nomultisrc
2839 // 12345678901
2840  if (!strncmp(val, "nomultisrc@", 11))
2841  {if (!xschedy(val, eDest, msRdrHost, msRdrHLen, msRdrPort)) return -1;
2842  MultiSrc = 0;
2843  return 0;
2844  }
2845 
2846  return 1;
2847 }
2848 
2849 /******************************************************************************/
2850 
2851 bool XrdCmsConfig::xschedy(char *val, XrdSysError *eDest, char *&host,
2852  int &hlen, int &port)
2853 {
2854  const char *badTarget = "Invalid sched redirect target '%s'%s";
2855  XrdNetAddr netAddr;
2856  char *at, hName[XrdCmsSelect::SelDSZ];
2857  const char *eText = "not a redirect target";
2858 
2859 // Free the host name if present
2860 //
2861  if (host) {free(host); host = 0; hlen = port = 0;}
2862 
2863 // Check if we have an at sign
2864 //
2865  if (!(at = index(val, '@'))) return true;
2866  if (!*(at+1))
2867  {snprintf(hName, sizeof(hName),
2868  "Missing sched redirect target after '%s'.", val);
2869  eDest->Emsg("Config", hName);
2870  return false;
2871  }
2872  *at = 0; val = at + 1;
2873 
2874 // Make sure this is not a named pipe
2875 //
2876  if (*val == '/')
2877  {snprintf(hName, sizeof(hName), badTarget, val, ".");
2878  eDest->Emsg("Config", hName);
2879  return false;
2880  }
2881 
2882 // Parse the host and port
2883 //
2884  if ((eText = netAddr.Set(val)))
2885  {snprintf(hName, sizeof(hName), badTarget, val, ";");
2886  eDest->Emsg("Config", hName, eText);
2887  return false;
2888  }
2889 
2890 // Now get the host name and port
2891 //
2892  if (!netAddr.Format(hName, sizeof(hName), XrdNetAddrInfo::fmtAuto,
2894  {snprintf(hName, sizeof(hName), badTarget, val, ".");
2895  eDest->Emsg("Config", hName);
2896  return false;
2897  }
2898 
2899 // Set values and return
2900 //
2901  host = strdup(hName);
2902  hlen = strlen(hName)+1;
2903  port = netAddr.Port();
2904  return true;
2905 }
2906 
2907 /******************************************************************************/
2908 /* x s e c l */
2909 /******************************************************************************/
2910 
2911 /* Function: xsecl
2912 
2913  Purpose: To parse the directive: seclib <path>
2914 
2915  <path> the location of the security library.
2916 
2917  Type: Server only, non-dynamic.
2918 
2919  Output: 0 upon success or !0 upon failure.
2920 */
2921 
2922 int XrdCmsConfig::xsecl(XrdSysError *eDest, XrdOucStream &CFile)
2923 {
2924 
2925 // If we are a server, ignore this option
2926 //
2927  if (!isManager) return CFile.noEcho();
2928 
2929 // Return parse result
2930 //
2931  return (XrdOucUtils::parseLib(*eDest,CFile,"seclib",SecLib,0) ? 0 : 1);
2932 }
2933 
2934 /******************************************************************************/
2935 /* x s p a c e */
2936 /******************************************************************************/
2937 
2938 /* Function: xspace
2939 
2940  Purpose: To parse the directive: space [linger <num>] [recalc <sec>]
2941 
2942  [[min] {<mnp> [<min>] | <min>} [[<hwp>] <hwm>]]
2943 
2944  [mwfiles]
2945 
2946  <num> Maximum number of times a server may be reselected without
2947  a break. The default is 0.
2948 
2949  <mnp> Min free space needed as percentage of the largest partition.
2950 
2951  <min> Min free space needed in bytes (or K, M, G) in a partition.
2952  The default is 10G.
2953 
2954  <hwp> Percentage of free space needed to requalify.
2955 
2956  <hwm> Bytes (or K, M,G) of free space needed when bytes falls below
2957  <min> to requalify a server for selection.
2958  The default is 11G.
2959 
2960  <sec> Number of seconds that must elapse before a disk free space
2961  calculation will occur.
2962 
2963  mwfiles
2964  space supports multiple writable file copies. This suppresses
2965  multiple file check when open a file in write mode.
2966 
2967  Notes: This is used by the manager and the server.
2968 
2969  Type: All, dynamic.
2970 
2971  Output: 0 upon success or !0 upon failure.
2972 */
2973 
2974 int XrdCmsConfig::xspace(XrdSysError *eDest, XrdOucStream &CFile)
2975 {
2976  char *val;
2977  int i, alinger = -1, arecalc = -1, minfP = -1, hwmP = -1;
2978  long long minf = -1, hwm = -1;
2979  bool haveopt = false;
2980 
2981  while((val = CFile.GetWord()))
2982  { if (!strcmp("linger", val))
2983  {if (!(val = CFile.GetWord()))
2984  {eDest->Emsg("Config", "linger value not specified"); return 1;}
2985  if (XrdOuca2x::a2i(*eDest,"linger",val,&alinger,0)) return 1;
2986  }
2987  else if (!strcmp("recalc", val))
2988  {if (!(val = CFile.GetWord()))
2989  {eDest->Emsg("Config", "recalc value not specified"); return 1;}
2990  if (XrdOuca2x::a2i(*eDest,"recalc",val,&arecalc,1)) return 1;
2991  }
2992  else if (!strcmp("min", val))
2993  {if (!(val = CFile.GetWord()) || !isdigit(*val))
2994  {eDest->Emsg("Config", "space min value not specified"); return 1;}
2995  break;
2996  }
2997  else if (!strcmp("mwfiles", val)) {DoMWChk = 0; haveopt = true;}
2998  else if (isdigit(*val)) break;
2999  else {eDest->Emsg("Config", "invalid space parameters"); return 1;}
3000  }
3001 
3002  if (val && isdigit(*val))
3003  {i = strlen(val);
3004  if (val[i-1] == '%')
3005  {val[i-1] = '\0';
3006  if (XrdOuca2x::a2i(*eDest,"space % minfree",val,&minfP,1,99)) return 1;
3007  val = CFile.GetWord();
3008  }
3009  }
3010 
3011  if (val && isdigit(*val))
3012  {i = strlen(val);
3013  if (val[i-1] != '%')
3014  {if (XrdOuca2x::a2sz(*eDest,"space minfree",val,&minf,0)) return 1;
3015  val = CFile.GetWord();
3016  }
3017  }
3018 
3019  if (minfP >= 0 && minf < 0)
3020  {eDest->Emsg("Config", "absolute min value not specified"); return 1;}
3021 
3022  if (val && isdigit(*val))
3023  {i = strlen(val);
3024  if (val[i-1] == '%')
3025  {val[i-1] = '\0';
3026  if (XrdOuca2x::a2i(*eDest,"space % high watermark",val,&hwmP,1,99)) return 1;
3027  val = CFile.GetWord();
3028  }
3029  }
3030 
3031  if (val && isdigit(*val))
3032  {i = strlen(val);
3033  if (val[i-1] != '%')
3034  {if (XrdOuca2x::a2sz(*eDest,"space high watermark",val,&hwm,0)) return 1;
3035  val = CFile.GetWord();
3036  }
3037  }
3038 
3039  if (hwmP >= 0 && hwm < 0)
3040  {eDest->Emsg("Config", "absolute high watermark value not specified"); return 1;}
3041 
3042  if (val) {eDest->Emsg("Config", "invalid space parameter -", val); return 1;}
3043 
3044  if (!haveopt && alinger < 0 && arecalc < 0 && minf < 0)
3045  {eDest->Emsg("Config", "no space values specified"); return 1;}
3046 
3047  if (alinger >= 0) DiskLinger = alinger;
3048  if (arecalc >= 0) DiskAsk = arecalc;
3049 
3050  if (minfP > 0)
3051  {if (hwmP < minfP) hwmP = minfP + 1;
3052  DiskMinP = minfP; DiskHWMP = hwmP;
3053  } else DiskMinP = DiskHWMP = 0;
3054 
3055  if (minf >= 0)
3056  {if (hwm < minf) hwm = minf+1073741824; // Minimum + 1GB
3057  minf = minf >> 20LL; hwm = hwm >> 20LL; // Now Megabytes
3058  if (minf >> 31LL) {minf = 0x7fefffff; hwm = 0x7fffffff;}
3059  else if (hwm >> 31LL) minf = 0x7fffffff;
3060  DiskMin = static_cast<int>(minf);
3061  DiskHWM = static_cast<int>(hwm);
3062  }
3063  return 0;
3064 }
3065 
3066 /******************************************************************************/
3067 /* x s u b c */
3068 /******************************************************************************/
3069 
3070 /* Function: subc
3071 
3072  Purpose: To parse the directive: subcluster of <host>[+][:<port>|<port>]
3073 
3074  Type: Manager only, non-dynamic.
3075 
3076  Output: 0 upon success or !0 upon failure.
3077 */
3078 
3079 int XrdCmsConfig::xsubc(XrdSysError *eDest, XrdOucStream &CFile)
3080 {
3081  class StorageHelper
3082  {public:
3083  StorageHelper(char **v1, char **v2) : val1(v1), val2(v2) {}
3084  ~StorageHelper() {if (*val1) free(*val1);
3085  if (*val2) free(*val2);
3086  }
3087  char **val1, **val2;
3088  };
3089 
3090  char *val, *hSpec = 0, *hPort = 0;
3091  StorageHelper SHelp(&hSpec, &hPort);
3092 
3093 // Ignore this call if we are not a simple manager
3094 //
3095  if (isMeta || isServer || isPeer || isProxy) return CFile.noEcho();
3096 
3097 // Skip the optional "of" keyword
3098 //
3099  val = CFile.GetWord();
3100  if (val && !strcmp("of", val)) val = CFile.GetWord();
3101 
3102 // Get the actual host name and copy it
3103 //
3104  if (!val)
3105  {eDest->Emsg("Config","cluster manager host name not specified");
3106  return 1;
3107  }
3108  hSpec = strdup(val);
3109 
3110 // Grab the port number (either in hostname or following token)
3111 //
3112  if (!(hPort = XrdCmsUtils::ParseManPort(eDest, CFile, hSpec))) return 1;
3113 
3114 // Parse the specification and return
3115 //
3116  return (XrdCmsUtils::ParseMan(eDest, &SanList, hSpec, hPort) ? 0 : 1);
3117 }
3118 
3119 /******************************************************************************/
3120 /* x s u p p */
3121 /******************************************************************************/
3122 
3123 /* Function: xsupp
3124 
3125  Purpose: To parse the directive: superport <tcpnum>
3126  [if [<hlst>] [named <nlst>]]
3127 
3128  <tcpnum> number of the tcp port for incoming requests
3129  <hlst> list of applicable host patterns
3130  <nlst> list of applicable instance names.
3131 
3132  Output: 0 upon success or !0 upon failure.
3133 */
3134 int XrdCmsConfig::xsupp(XrdSysError *eDest, XrdOucStream &CFile)
3135 { const char *invp = "superport port";
3136  char *val, cport[32];
3137  int rc, pnum;
3138 
3139  if (!(val = CFile.GetWord()))
3140  {eDest->Emsg("Config", "tcp port not specified"); return 1;}
3141 
3142  strncpy(cport, val, sizeof(cport)-1); cport[sizeof(cport)-1] = '\0';
3143 
3144  if ((val = CFile.GetWord()) && !strcmp("if", val))
3145  if ((rc = XrdOucUtils::doIf(eDest,CFile,"superport directive",
3146  myName,myInsName,myProg))<=0)
3147  {if (!rc) CFile.noEcho(); return rc < 0;}
3148 
3149  if (!strcmp(cport, "any")) pnum = 0;
3150  else if (!strcmp(cport, "-p")) pnum = PortTCP;
3151  else if (isdigit(*cport))
3152  {if (XrdOuca2x::a2i(*eDest,invp,cport,&pnum,1,65535)) return 0;}
3153  else if (!(pnum = XrdNetUtils::ServPort(cport)))
3154  {eDest->Emsg("Config", "Unable to find superport", cport);
3155  return 1;
3156  }
3157 
3158  PortSUP = pnum;
3159 
3160  return 0;
3161 }
3162 
3163 /******************************************************************************/
3164 /* x t r a c e */
3165 /******************************************************************************/
3166 
3167 /* Function: xtrace
3168 
3169  Purpose: To parse the directive: trace <options>
3170 
3171  Type: Manager or Server, dynamic.
3172 
3173  Output: 0 upon success or !0 upon failure.
3174 */
3175 
3176 int XrdCmsConfig::xtrace(XrdSysError *eDest, XrdOucStream &CFile)
3177 {
3178  char *val;
3179  static struct traceopts {const char *opname; int opval;} tropts[] =
3180  {
3181  {"all", TRACE_ALL},
3182  {"debug", TRACE_Debug},
3183  {"defer", TRACE_Defer},
3184  {"files", TRACE_Files},
3185  {"forward", TRACE_Forward},
3186  {"redirect", TRACE_Redirect},
3187  {"space", TRACE_Space},
3188  {"stage", TRACE_Stage}
3189  };
3190  int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
3191 
3192  if (!(val = CFile.GetWord()))
3193  {eDest->Emsg("config", "trace option not specified"); return 1;}
3194  while (val)
3195  {if (!strcmp(val, "off")) trval = 0;
3196  else {if ((neg = (val[0] == '-' && val[1]))) val++;
3197  for (i = 0; i < numopts; i++)
3198  {if (!strcmp(val, tropts[i].opname))
3199  {if (neg) trval &= ~tropts[i].opval;
3200  else trval |= tropts[i].opval;
3201  break;
3202  }
3203  }
3204  if (i >= numopts)
3205  eDest->Say("Config warning: ignoring invalid trace option '",val,"'.");
3206  }
3207  val = CFile.GetWord();
3208  }
3209 
3210  Trace.What = trval;
3211  return 0;
3212 }
3213 
3214 /******************************************************************************/
3215 /* x v n i d */
3216 /******************************************************************************/
3217 
3218 /* Function: xvnid
3219 
3220  Purpose: To parse the directive: vnid {=|<|@}<vnarg> [<parms>]
3221 
3222  <vnarg> = - the actual vnid value
3223  < - the path of the file to be read for the vnid.
3224  @ - the path of the plugin library to be used.
3225  <parms> optional parms to be passed
3226 
3227  Output: 0 upon success or !0 upon failure.
3228 */
3229 
3230 int XrdCmsConfig::xvnid(XrdSysError *eDest, XrdOucStream &CFile)
3231 {
3232  char *val, parms[1024];
3233 
3234 // Get the argument
3235 //
3236  if (!(val = CFile.GetWord()) || !val[0])
3237  {eDest->Emsg("Config", "vnid not specified"); return 1;}
3238 
3239 // Record the path
3240 //
3241  if (VNID_Lib) free(VNID_Lib);
3242  VNID_Lib = strdup(val);
3243 
3244 // Record any parms (only if it starts with an @)
3245 //
3246  if (VNID_Parms) {free(VNID_Parms); VNID_Parms = 0;}
3247  if (*VNID_Lib == '@')
3248  {if (!CFile.GetRest(parms, sizeof(parms)))
3249  {eDest->Emsg("Config", "vnid plug-in parameters too long"); return 1;}
3250  if (*parms) VNID_Parms = strdup(parms);
3251  }
3252  return 0;
3253 }
void Usage(const char *msg)
Definition: XrdAccTest.cc:105
#define TS_Set(x, v)
void * XrdCmsStartAdmin(void *carg)
void * XrdCmsStartMonPerf(void *carg)
void * XrdCmsStartMonStat(void *carg)
void * XrdCmsStartAnote(void *carg)
void * XrdCmsStartMonRefs(void *carg)
#define TS_Xeq(x, m)
void * XrdCmsStartSupervising(void *carg)
#define TS_Lib(x, y, z)
void * XrdCmsStartPreparing(void *carg)
#define TS_Xer(x, m, v)
#define TS_unSet(x, v)
#define TRACE_Stage
Definition: XrdCmsTrace.hh:38
#define TRACE_Space
Definition: XrdCmsTrace.hh:43
#define TRACE_Debug
Definition: XrdCmsTrace.hh:37
#define TRACE_Files
Definition: XrdCmsTrace.hh:42
#define TRACE_Redirect
Definition: XrdCmsTrace.hh:41
#define QTRACE(act)
Definition: XrdCmsTrace.hh:49
#define TRACE_Forward
Definition: XrdCmsTrace.hh:40
#define TRACE_Defer
Definition: XrdCmsTrace.hh:39
#define STMax
Definition: XrdCmsTypes.hh:39
#define XrdCmsMAX_PATH_LEN
Definition: XrdCmsTypes.hh:46
static XrdSysError eDest(0,"crypto_")
int optopt
int optind
#define XRDNET_UDPSOCKET
Definition: XrdNetOpts.hh:79
XrdOss * XrdOssGetSS(XrdSysLogger *Logger, const char *config_fn, const char *OssLib, const char *OssParms, XrdOucEnv *envP, XrdVersionInfo &urVer)
Definition: XrdOssApi.cc:98
#define XRDEXP_NOTRW
Definition: XrdOucExport.hh:45
#define XRDEXP_PFCACHE
Definition: XrdOucExport.hh:70
#define XRDEXP_STAGEMM
Definition: XrdOucExport.hh:76
#define XRDEXP_GLBLRO
Definition: XrdOucExport.hh:74
#define XRDEXP_STAGE
Definition: XrdOucExport.hh:52
#define XRDEXP_LOCAL
Definition: XrdOucExport.hh:72
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)
#define close(a)
Definition: XrdPosix.hh:43
#define TRACE_ALL
Definition: XrdTrace.hh:35
static bool InitAREvents(void *arFunc)
Definition: XrdCmsAdmin.cc:176
void * Start(XrdNetSocket *AdminSock)
Definition: XrdCmsAdmin.cc:451
static void setSync(XrdSysSemaphore *sync)
Definition: XrdCmsAdmin.hh:55
void * Notes(XrdNetSocket *AdminSock)
Definition: XrdCmsAdmin.cc:301
void SetTries(bool xdfs, int tcnt)
static const int Immed
static const int Servr
void Init(int Opts, int DMlife, int DPLife)
static const int Cntrl
static const int DFSys
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)
Definition: XrdCmsCache.cc:380
static const int min_nxTime
Definition: XrdCmsCache.hh:81
void * MonPerf()
void * MonRefs()
int GenLocalPath(const char *oldp, char *newp)
const char * mySite
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)
static const int MTMax
int Monitor(char *pgm, int itv)
Definition: XrdCmsMeter.cc:258
void setVirtual(vType vVal)
Definition: XrdCmsMeter.hh:76
static void do_StateDFS(XrdCmsBaseFR *rP, int rc)
SMask_t ssvec
Definition: XrdCmsPList.hh:49
SMask_t rovec
Definition: XrdCmsPList.hh:47
SMask_t rwvec
Definition: XrdCmsPList.hh:48
char * Path()
Definition: XrdCmsPList.hh:76
XrdCmsPList * Next()
Definition: XrdCmsPList.hh:75
const char * PType()
Definition: XrdCmsPList.cc:212
static void Process()
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)
Definition: XrdCmsRRQ.cc:125
static const char * Name(RoleID rid)
Definition: XrdCmsRole.hh:63
static RoleID Convert(const char *Tok1, const char *Tok2)
Definition: XrdCmsRole.hh:47
static const char * Type(RoleID rid)
Definition: XrdCmsRole.hh:78
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)
static const int SelDSZ
Definition: XrdCmsSelect.hh:87
void * Monitor()
Definition: XrdCmsState.cc:111
void Update(StateType StateT, int ActivVal, int StageVal=0)
Definition: XrdCmsState.cc:258
void Set(int ncount)
Definition: XrdCmsState.cc:182
void Enable()
Definition: XrdCmsState.cc:85
static void Start()
static int Init(const char *AdminPath, int AdminMode)
static char * ParseManPort(XrdSysError *eDest, XrdOucStream &CFile, char *hSpec)
Definition: XrdCmsUtils.cc:249
static bool ParseMan(XrdSysError *eDest, XrdOucTList **oldMans, char *hSpec, char *hPort, int *sPort=0, bool hush=false)
Definition: XrdCmsUtils.cc:123
static void Start()
Definition: XrdJob.hh:43
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.
int Port(int pNum=-1)
Definition: XrdNetAddr.cc:156
const char * Set(const char *hSpec, int pNum=PortInSpec)
Definition: XrdNetAddr.cc:216
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)
Definition: XrdNetUtils.cc:839
static int Export(const char *Var, const char *Val)
Definition: XrdOucEnv.cc:188
void * GetPtr(const char *varname)
Definition: XrdOucEnv.cc:281
void PutPtr(const char *varname, void *value)
Definition: XrdOucEnv.cc:316
static unsigned long long ParseDefs(XrdOucStream &Config, XrdSysError &Eroute, unsigned long long Flags)
Definition: XrdOucExport.cc:60
static XrdOucPList * ParsePath(XrdOucStream &Config, XrdSysError &Eroute, XrdOucPListAnchor &Export, unsigned long long Defopts)
XrdOucPList * Next()
Definition: XrdOucPList.hh:44
char * Path()
Definition: XrdOucPList.hh:45
unsigned long long Flag()
Definition: XrdOucPList.hh:42
char * GetWord(int lowcase=0)
XrdOucEnv * SetEnv(XrdOucEnv *newEnv)
int GetRest(char *theBuf, int Blen, int lowcase=0)
XrdOucTList * next
Definition: XrdOucTList.hh:45
char * text
Definition: XrdOucTList.hh:46
static char * genPath(const char *path, const char *inst, const char *psfx=0)
Definition: XrdOucUtils.cc:417
static bool parseLib(XrdSysError &eDest, XrdOucStream &Config, const char *libName, char *&path, char **libparm)
Definition: XrdOucUtils.cc:989
static const char * InstName(int TranOpt=0)
Definition: XrdOucUtils.cc:732
static int doIf(XrdSysError *eDest, XrdOucStream &Config, const char *what, const char *hname, const char *nname, const char *pname)
Definition: XrdOucUtils.cc:231
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:45
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
Definition: XrdOuca2x.cc:257
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:288
const char * myName
Definition: XrdProtocol.hh:82
XrdScheduler * Sched
Definition: XrdProtocol.hh:64
const char * AdmPath
Definition: XrdProtocol.hh:76
XrdSysError * eDest
Definition: XrdProtocol.hh:61
XrdOucEnv * theEnv
Definition: XrdProtocol.hh:66
const char * myProg
Definition: XrdProtocol.hh:83
const char * myInst
Definition: XrdProtocol.hh:81
void Schedule(XrdJob *jp)
static void SetQW(unsigned int qwVal)
Definition: XrdSendQ.hh:58
static void SetQM(unsigned int qmVal)
Definition: XrdSendQ.hh:56
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
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)
Definition: XrdSysError.cc:141
XrdSysLogger * logger(XrdSysLogger *lp=0)
Definition: XrdSysError.hh:141
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)
static int TimeZone()
Definition: XrdSysTimer.cc:210
static void Wait(int milliseconds)
Definition: XrdSysTimer.cc:227
void SetLogger(XrdSysLogger *logp)
Definition: XrdSysTrace.cc:65
XrdCmsMeter Meter
Definition: XrdCmsMeter.hh:131
XrdCmsRRQ RRQ
Definition: XrdCmsRRQ.cc:55
XrdCmsCache Cache
Definition: XrdPfcFile.hh:204
XrdCmsAdmin Admin
XrdVERSIONINFODEF(myVersion, cmsclient, XrdVNUMBER, XrdVERSION)
XrdScheduler * Sched
XrdCmsCluster Cluster
XrdCmsBaseFS baseFS
XrdSysError Say
XrdSysTrace Trace("cms")
XrdCmsState CmsState
Definition: XrdCmsState.cc:55
XrdCmsPrepare PrepQ
XrdCmsConfig Config
XrdOucEnv theEnv
int Opts
Definition: XrdMpxStats.cc:58
const char * myDomain
Generic structure to pass security information back and forth.