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