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