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