XRootD
Loading...
Searching...
No Matches
XrdOssArcConfig.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d O s s A r c C o n f i g . c c */
4/* */
5/* (c) 2023 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Deprtment of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30/******************************************************************************/
31/* i n c l u d e s */
32/******************************************************************************/
33
34#include <set>
35#include <string>
36#include <vector>
37
38#include <string.h>
39#include <unistd.h>
40#include <sys/param.h>
41#include <sys/stat.h>
42#include <sys/types.h>
43
44#include "Xrd/XrdScheduler.hh"
45
46#include "XrdOss/XrdOss.hh"
47
54
55#include "XrdOuc/XrdOuca2x.hh"
56#include "XrdOuc/XrdOucECMsg.hh"
57#include "XrdOuc/XrdOucEnv.hh"
59#include "XrdOuc/XrdOucProg.hh"
61#include "XrdOuc/XrdOucUtils.hh"
62
63#include "XrdSys/XrdSysError.hh"
65
66/******************************************************************************/
67/* G l o b a l O b j e c t s */
68/******************************************************************************/
69
70namespace XrdOssArcGlobals
71{
72extern XrdOss* ossP;
73
74extern XrdScheduler* schedP;
75
76extern XrdSysError Elog;
77
78extern XrdSysTrace ArcTrace;
79
81
82 thread_local XrdOucECMsg ecMsg("[ossArc]");
83}
84using namespace XrdOssArcGlobals;
85
86/******************************************************************************/
87/* L o c a l O b j e c t s */
88/******************************************************************************/
89
90namespace
91{
92std::set<std::string> bkpScopes;
93}
94
95/******************************************************************************/
96/* C o n s t r u c t o r */
97/******************************************************************************/
98
100{
101// Establish the defaults
102//
103 BkpUtilPath = strdup("XrdOssArc_BkpUtils");
105
106 PrepArcPath = 0;
107 PrepArcName = 0;
108
109 PostArcPath = 0;
110 PostArcName = 0;
111
112 ArchiverPath= strdup("XrdOssArc_Archiver");
114 ArchiverSave= 0;
115
116 MssComPath = strdup("XrdOssArc_MssCom");
118 MssComCmd = 0;
119 MssComRoot = 0;
120
121 arcvPathLFN = strdup("/archive/");
122 arcvPathLEN = strlen(arcvPathLFN);
123 bkupPathLFN = strdup("/backup/");
124 bkupPathLEN = strlen(bkupPathLFN);
125 dsetPathLFN = strdup("/dataset/");
126 dsetRepoPFN = 0;
127
128 const char*atmp;
129 if ((atmp = getenv("XRDADMINPATH")))
130 {std::string as = atmp;
131 if (as.back() != '/') as.append("/");
132 as.append("OssArc/");
133 admnPath = strdup(as.c_str());
134 }
135 stopPath = 0;
136
137 srcData = strdup("");
138 stagePath = strdup("/tmp/stage");
139 tapePath = strdup("/TapeBuffer");
140 tapePathLEN = strlen(tapePath);
141 utilsPath = strdup("/usr/local/etc");
142
143 stopMon = 0;
144
145 metaBKP = "arcBackup";
146 metaIDX = "arcIndex";
147 doneBKP = 0;
148 needBKP = 0;
149 dstRSE = 0;
150 srcRSE = 0;
151 manCKS = strdup("adler32");
152
153 bkpMinF = -20;
154 bkpMax = 2;
155 bkpPoll = 15*60;
156 bkpFSt = -1; // Eventual default is bkpPoll/3
157 maxStage = 30;
158 wtpStage = 30;
159 r_maxItems = 1000;
160 arFName = strdup("Archive.zip");
161 arfSfx = strdup(".zip");
162 arfSfxLen = 4;
163 stopChk = 10;
164 bkpLocal = true;
165
166 arcSZ_Skip = false;
167 arcSZ_Want = 0; // The XrdOssArc_BkpUtils defines the default
168 arcSZ_MinV = 0;
169 arcSZ_MaxV = 0;
170
171 if (getenv("XRDOSSARC_DEBUG") || getenv("XRDDEBUG"))
172 ArcTrace.What |= TRACE_Debug;
173}
174
175/******************************************************************************/
176/* Private: B u i l d P a t h */
177/******************************************************************************/
178
179bool XrdOssArcConfig::BuildPath(const char* what, const char* baseP,
180 const char* addP, char*& destP, int mode)
181{
182 char lclPath[MAXPATHLEN];
183 int rc;
184
185// Get the local path to the base directory
186//
187 if ((rc = GenLocalPath(baseP, lclPath, sizeof(lclPath))))
188 {Elog.Emsg("Config", rc, "configure", what);
189 return false;
190 }
191
192// Copy the path for further modification
193//
194 std::string tmpStr(lclPath);
195
196// Trimp off trailing slashes
197//
198 while(tmpStr.back() == '/') tmpStr.pop_back();
199
200// Add any additional element
201//
202 if (addP) tmpStr.append(addP);
203
204// Create modifiable copy
205//
206 char* modStr = strdup(tmpStr.c_str());
207
208// Check if we need to create the full path
209//
210 if (mode)
211 {int rc = XrdOucUtils::makePath(modStr, mode);
212 if (rc)
213 {std::string msgT("create ");
214 msgT.append(what);
215 Elog.Emsg("Config", rc, msgT.c_str(), tmpStr.c_str());
216 free(modStr);
217 return false;
218 }
219 }
220
221// Set destination and return success
222//
223 destP = modStr;
224 return true;
225}
226
227/******************************************************************************/
228/* C o n f i g u r e */
229/******************************************************************************/
230
231bool XrdOssArcConfig::Configure(const char* cfn, const char* parms,
232 XrdOucEnv* envP)
233{
234 TraceInfo("Configure", 0);
235 bool NoGo = false;
236
237// Read and process the config file
238//
239 if (!ConfigXeq(cfn, parms, envP)) return false;
240
241// Set the external debug flag as needed
242//
243 if (ArcTrace.What & (TRACE_Debug | TRACE_Save))
244 XrdOucEnv::Export("XRDOSSARC_DEBUG",ArcTrace.What & TRACE_Save ? "2":"1");
245
246// Make sure that the rse declarations have been specified
247//
248 if (dstRSE && srcRSE)
249 {std::string tmp;
250 XrdOucEnv::Export("XRDOSSARC_DSTRSE", dstRSE);
251 DEBUG("exporting XRDOSSARC_DSTRSE="<<dstRSE);
252 XrdOucEnv::Export("XRDOSSARC_SRCRSE", srcRSE);
253 DEBUG("exporting XRDOSSARC_SRCRSE="<<srcRSE);
254
255 tmp = dstRSE;
256 tmp += ":need";
257 needBKP = strdup(tmp.c_str());
258 tmp = dstRSE;
259 tmp += ":done";
260 doneBKP = strdup(tmp.c_str());
261 } else {
262 Elog.Say("Config mistake: required 'rsedcl' directive not specified!");
263 NoGo = true;
264 }
265
266// Export values needed by the metadata script
267//
268 XrdOucEnv::Export("XRDOSSARC_MAXITEMS", r_maxItems);
269
270// Export manifest checksum, unless none wanted
271//
272 if (strcmp(manCKS, "none")) XrdOucEnv::Export("XRDOSSARC_CKSUM", manCKS);
273
274// Export archive size parameters if specified
275//
276 if (arcSZ_Want)
277 {char buff[1024];
278 snprintf(buff, sizeof(buff), "%lld %lld %lld %d", arcSZ_Want,
280 XrdOucEnv::Export("XRDOSSARC_SIZE", buff);
281 }
282
283// Handle the admin path
284//
285 if (admnPath)
286 {int rc = XrdOucUtils::makePath(admnPath, S_IRWXU | S_IRGRP);
287 if (rc) {Elog.Emsg("Config", rc, "create admin path", admnPath);
288 NoGo = true;
289 }
290 else if (!Usable(admnPath, "admin path", false)) NoGo = true;
291 }
292
293// Handle the stop file path
294//
295 if (!stopPath) stopPath = admnPath;
296 else {std::string ss = stopPath;
297 if (ss.back() != '/')
298 {ss.append("/");
299 free(stopPath);
300 stopPath = strdup(ss.c_str());
301 }
302 }
303
304// Create the stop monitor
305//
306 if (!stopPath)
307 {Elog.Emsg("Config", "Unable to determine the stopfile path!");
308 NoGo = true;
309 } else {
310 if (!Usable(stopPath, "stopfile path", false)) NoGo = true;
311 else if (!NoGo)
312 {bool uOK;
314 if (!uOK)
315 {NoGo = true;
316 delete stopMon;
317 stopMon = 0;
318 }
319 }
320 }
321
322// Verify that the tape buffer is usable
323//
324 if (!Usable(tapePath, "tape buffer path", false)) NoGo = true;
325 tapePathLEN = strlen(tapePath);
326
327// Initialize the tape buffer resourse monitor
328//
329 if (bkpFSt < 0)
330 {bkpFSt = bkpPoll/3;
331 if (bkpFSt < 30) bkpFSt = 30;
332 }
333 if (!fsMon.Init(tapePath, bkpMinF, bkpFSt)) NoGo = true;
334
335// Verify that the data source mount point is usable
336//
337 if (*srcData)
338 {struct stat Stat;
339 if (stat(srcData, &Stat))
340 {Elog.Emsg("Config", errno, "use srcdata path", srcData);
341 NoGo = true;
342 }
343 }
344
345// Create the backup staging path
346//
347 if (!BuildPath("dataset backup arena", dsetPathLFN, "/4bkp/",
348 dsetRepoPFN, S_IRWXU|S_IRGRP|S_IXGRP))
349 NoGo = true;
350
351// Create the program that returns the datasets that need to be backed up.
352// It also is the one that manipulates the backup status of a dataset.
353//
355 ConfigPath(&BkpUtilPath, utilsPath);
356 if (BkpUtilProg->Setup(BkpUtilPath)) NoGo = true;
357 else {const char* rslash = rindex(BkpUtilPath, '/');
358 BkpUtilName = (rslash ? rslash+1 : BkpUtilPath);
359 }
360
361// Create program to communicate with the MSS
362//
363 MssComProg = new XrdOucProg(&Elog);
364 ConfigPath(&MssComPath, utilsPath);
365 if (MssComProg->Setup(MssComPath)) NoGo = true;
366 else {const char* rslash = rindex(MssComPath, '/');
367 MssComName = (rslash ? rslash+1 : MssComPath);
368 }
369
370// Export envars that the programs needs
371//
372 if (MssComCmd)
373 {XrdOucEnv::Export("XRDOSSARC_MSSCMD", MssComCmd);
374 DEBUG("Exporting XRDOSSARC_MSSCMD="<<MssComCmd);
375 }
376 if (MssComRoot)
377 {XrdOucEnv::Export("XRDOSSARC_MSSROOT", MssComRoot);
378 DEBUG("exporting XRDOSSARC_MSSROOT="<<MssComRoot);
379 } else MssComRoot = strdup("");
380
381// Create the pre archiver program if it has been specified
382//
383 if (PrepArcPath)
384 {PrepArcProg = new XrdOucProg(&Elog);
385 ConfigPath(&PrepArcPath, utilsPath);
386 if (PrepArcProg->Setup(PrepArcPath)) NoGo = true;
387 else {const char* rslash = rindex(PrepArcPath, '/');
388 PrepArcName = (rslash ? rslash+1 : PrepArcPath);
389 }
390 } else PrepArcProg = 0;
391
392// Create the post archiver program if it has been specified
393//
394 if (PostArcPath)
395 {PostArcProg = new XrdOucProg(&Elog);
396 ConfigPath(&PostArcPath, utilsPath);
397 if (PostArcProg->Setup(PostArcPath)) NoGo = true;
398 else {const char* rslash = rindex(PostArcPath, '/');
399 PostArcName = (rslash ? rslash+1 : PostArcPath);
400 }
401 } else {
402 PostArcProg = 0;
403 PostArcName = PostArcPath = strdup("");
404 }
405
406// Create the program to be used to create the archive
407//
409 ConfigPath(&ArchiverPath, utilsPath);
410 if (ArchiverProg->Setup(ArchiverPath)) NoGo = true;
411 else {const char* rslash = rindex(ArchiverPath, '/');
412 ArchiverName = (rslash ? rslash+1 : ArchiverPath);
413 }
414
415// Setup the remote copy command the archiver should use for backups
416//
417 if (bkpLocal)
418 {if (ArchiverSave) free(ArchiverSave);
419 ArchiverSave = strdup("");
420 } else {
422 else ConfigPath(&ArchiverSave, utilsPath);
423 DEBUG("Archiver remote copycmd="<<ArchiverSave);
424 }
425
426// Make sure all the required metadata keys have been defined
427//
428 DEBUG("Running "<<BkpUtilName<<" addkey "<<metaBKP<<' '<<metaIDX);
429 if (BkpUtilProg->Run("addkey", metaBKP, metaIDX))
430 Elog.Emsg("Config","Unable to create/verify metadata keys; continuing...");
431
432// Start the backup process.
433//
434 std::vector<XrdOssArcBackup*> bkpVec;
435 XrdOssArcBackup* bkpP;
436 if (bkpScopes.empty())
437 {Elog.Emsg("Config", "No backup scopes specified!"); NoGo = true;
438 } else {
439 bool isOK;
440 for (auto it = bkpScopes.begin(); it != bkpScopes.end(); ++it)
441 {bkpP = new XrdOssArcBackup(it->c_str(), isOK);
442 if (!isOK)
443 {NoGo = true;
444 Elog.Emsg("Config", "Unable to start backing up scope",
445 it->c_str());
446 delete bkpP;
447 } else bkpVec.push_back(bkpP);
448 }
449 }
450
451// Start the configured number of backup workers The workers will wait for
452// backup tasks which will come shortly as we will start them once we have
453// dispatched workers. However, if we failed in any way, nothing is started.
454//
455 if (!NoGo)
457 for (auto it = bkpVec.begin(); it != bkpVec.end(); it++)
458 {Elog.Say("Config process: scheduling backup for scope ",
459 (*it)->theScope());
460 schedP->Schedule(*it, time(0)+3);
461 }
462 }
463
464// All done
465//
466 return !NoGo;
467}
468
469/******************************************************************************/
470/* Private: C o n f i g P a t h */
471/******************************************************************************/
472
473void XrdOssArcConfig::ConfigPath(char** pDest, const char* pRoot)
474{
475// If pDest starts with a slash then we use it as is; otherwise qualify it
476//
477 if ((*pDest)[0] != '/')
478 {std::string tmp(pRoot);
479 if (tmp.back() != '/') tmp += '/';
480 tmp += *pDest;
481 free(*pDest);
482 *pDest = strdup(tmp.c_str());
483 }
484}
485
486/******************************************************************************/
487/* Private: C o n f i g P r o c */
488/******************************************************************************/
489
490bool XrdOssArcConfig::ConfigProc(const char* drctv)
491{
492
493// Process each directive
494//
495 if (!strcmp(drctv, "arcsize")) return xqArcsz();
496 else if (!strcmp(drctv, "backup")) return xqBkup();
497 else if (!strcmp(drctv, "manifest"))return xqManf();
498 else if (!strcmp(drctv, "msscmd"))
499 return xqGrab("msscmd", MssComCmd, Conf->LastLine());
500 else if (!strcmp(drctv, "paths")) return xqPaths();
501 else if (!strcmp(drctv, "rsedcl")) return xqRse();
502 else if (!strcmp(drctv, "rucio")) return xqRucio();
503 else if (!strcmp(drctv, "stage")) return xqStage();
504 else if (!strcmp(drctv, "trace")) return xqTrace();
505 else if (!strcmp(drctv, "utils")) return xqUtils();
506 else Conf->MsgfW("ignoring unknown directive '%s'", drctv);
507
508 return true;
509}
510
511/******************************************************************************/
512/* Private: C o n f i g X e q */
513/******************************************************************************/
514
515
516bool XrdOssArcConfig::ConfigXeq(const char* cfName, const char* parms,
517 XrdOucEnv* envP)
518{
519 XrdOucGatherConf Cfile("ossarc.", &Elog);
520 char *token;
521 int rc;
522 bool NoGo = false;
523
524// Get all relevant config options. Ignore the parms.
525//
526 if ((rc = Cfile.Gather(cfName, XrdOucGatherConf::full_lines)) <= 0)
527 return (rc < 0 ? false : true);
528
529 Cfile.Tabs(0);
530
531// We point to the tokenizer to avod passing it around everywhere
532//
533 Conf = &Cfile;
534
535// Process each directive
536//
537 while(Cfile.GetLine())
538 {if ((token = Cfile.GetToken()))
539 {if (!strncmp(token, "ossarc.", 7)) token += 7;
540 NoGo |= !ConfigProc(token);
541 }
542 }
543
544// All done
545//
546 return !NoGo;
547}
548
549/******************************************************************************/
550/* Private: G e n L o c a l P a t h */
551/******************************************************************************/
552
553int XrdOssArcConfig::GenLocalPath(const char* dsn, char* buff, int bSZ)
554{
555 int rc;
556
557// Generate the pfn treating the dsn as the lfn
558//
559 if ((rc = ossP->Lfn2Pfn(dsn, buff, bSZ)))
560 {Elog.Emsg("Archive", rc, "generate local path for", dsn);
561 return rc;
562 }
563 return 0;
564}
565
566/******************************************************************************/
567/* Private: M i s s A r g */
568/******************************************************************************/
569
570bool XrdOssArcConfig::MissArg(const char* what)
571{
572 Conf->MsgfE("%s not specified.", what);
573 return false;
574}
575
576/******************************************************************************/
577/* U s a b l e */
578/******************************************************************************/
579
580bool XrdOssArcConfig::Usable(const char* path, const char* what, bool useOss)
581{
582 struct stat Stat;
583 int rc;
584
585 if (useOss) rc = ossP->Stat(path, &Stat);
586 else if ((rc = stat(path, &Stat))) rc = errno;
587
588 if (rc)
589 {char buff[256];
590 snprintf(buff, sizeof(buff), "use %s", what);
591 Elog.Emsg("Config", rc, buff, path);
592 return false;
593 }
594
595// Verify that it is a directory
596//
597 if (!S_ISDIR(Stat.st_mode))
598 {Elog.Emsg("Config", what, path, "is not a directory!");
599 return false;
600 }
601
602// Verify that it is writable
603//
604 if ( ((Stat.st_mode & S_IWOTH) == 0)
605 && ((Stat.st_mode & S_IWUSR) != 0 && (Stat.st_uid != geteuid()))
606 && ((Stat.st_mode & S_IWGRP) != 0 && (Stat.st_uid != getegid())))
607 {Elog.Emsg("Config", what, path, "is not writable!");
608 rc = 1;
609 }
610
611// Verify that it is searchable
612//
613 if ( ( (Stat.st_mode & S_IXOTH) == 0)
614 && ( (Stat.st_mode & S_IXUSR) != 0 && (Stat.st_uid != geteuid()))
615 && ( (Stat.st_mode & S_IXGRP) != 0 && (Stat.st_uid != getegid())))
616 {Elog.Emsg("Config", what, path, "is not searchable!");
617 rc = 1;
618 }
619
620// All done
621//
622 return rc == 0;
623}
624
625/******************************************************************************/
626/* Private: x q A r c s z */
627/******************************************************************************/
628/*
629 arcsize <target> [range <min> <max>] [skip]
630*/
631
632namespace
633{
634bool getVal(XrdOucGatherConf* Conf, const char* what, long long& theval,
635 long long minV, long long maxV)
636{
637 char* token;
638
639// Get next token
640//
641 if (!(token = Conf->GetToken()))
642 {Conf->MsgE(what, "value not specified!"); return false;}
643
644// Convert it
645//
646 if (XrdOuca2x::a2sz(Elog,what, token, &theval, minV, maxV))
647 {Conf-> EchoLine();
648 return false;
649 }
650
651// All done, success
652//
653 return true;
654}
655}
656
657bool XrdOssArcConfig::xqArcsz()
658{
659 static const long long MinV = 104857600LL; // minimum value 100 MB
660 static const long long MaxV = 500*1073741824LL; // maximum value 500 GB
661
662 char* token;
663 long long tVal, minVal = 0, maxVal = 0;
664
665// Get first value which is the target size
666//
667 if (!getVal(Conf, "arcsize target", tVal, MinV, MaxV)) return false;
668
669// Get optional arguments
670//
671 while((token = Conf->GetToken()))
672 {if (!strcmp(token, "range"))
673 {if (!getVal(Conf, "arcsize range minimum", minVal, MinV, MaxV))
674 return false;
675 if (!getVal(Conf, "arcsize range maximum", maxVal, MinV, MaxV))
676 return false;
677 if (minVal > maxVal)
678 {Conf->MsgE("arcsize range minimum is greater than maximum!");
679 return false;
680 }
681 if (tVal < minVal || tVal > maxVal)
682 {Conf->MsgE("arcsize target value out of specified range!");
683 return false;
684 }
685 } else if (!strcmp(token, "skip"))
686 {arcSZ_Skip = true;
687 } else {
688 Conf->MsgE("Invalid arcsize option -", token);
689 return false;
690 }
691 }
692
693// If no range has been specified, provide one
694//
695 if (!minVal)
696 {minVal = tVal/2;
697 maxVal = tVal*2;
698 }
699
700// Set the values in common area
701//
702 arcSZ_Want = tVal;
703 arcSZ_MinV = minVal;
704 arcSZ_MaxV = maxVal;
705
706// Return success
707//
708 return true;
709}
710
711/******************************************************************************/
712/* Private: x q B k u p */
713/******************************************************************************/
714/*
715 backup [fscan <sec>] [max <num>] [mode {local|remote}] [poll <sec>]
716 [stopchk <sec>] [minfree <n>[%|k|m|g]] [scope <name> [<name [...]]]
717*/
718
719bool XrdOssArcConfig::xqBkup()
720{
721 static const int isN = 0; // Argument is int
722 static const int isT = 1; // Argument is time
723 static const int isPS = 2; // Atgument is size value or percentage
724 static const int isM = 3; // Atgument is mode
725
726 struct bkpopts {const char *opname; int* oploc; int minv; int isX;}
727 bkpopt[] =
728 {
729 {"check", &stopChk, 5, isT},
730 {"fscan", &bkpFSt, 30, isT},
731 {"max", &bkpMax, 1, isN},
732 {"minfree", 0, 1, isPS},
733 {"mode", 0, 0, isM},
734 {"poll", &bkpPoll, 60, isT},
735 {"scope", 0, -1, isN}
736 };
737 int numopts = sizeof(bkpopt)/sizeof(struct bkpopts);
738 int i;
739 char* token, *tval;
740
741// Get the first token, there must be one
742//
743 if (!(token = Conf->GetToken()))
744 {Conf->MsgfE("no backup arguments specified!"); return false;}
745
746// Process all options
747//
748do{for (i = 0; i < numopts; i++)
749 {if (!strcmp(token, bkpopt[i].opname))
750 {if (bkpopt[i].minv == -1) return xqBkupScope();
751 int* val = bkpopt[i].oploc;
752 int minv = bkpopt[i].minv;
753
754 if (!(tval = Conf->GetToken()) || !(*tval))
755 {Conf->MsgE("backup", token, "value not specified!");
756 return false;
757 }
758
759 if (bkpopt[i].isX == isM)
760 { if (!strcmp("remote", tval)) bkpLocal = false;
761 else if (!strcmp("local", tval)) bkpLocal = true;
762 else {Conf->MsgfE("Invalid backup mode '%s'.", token);
763 return false;
764 }
765 break;
766 }
767
768 if (bkpopt[i].isX == isPS)
769 {if (!xqBkupPS(tval)) return false;
770 break;
771 }
772
773 if (bkpopt[i].isX == isT)
774 {if (XrdOuca2x::a2tm(Elog,bkpopt[i].opname,tval,val,minv))
775 {Conf-> EchoLine();
776 return false;
777 }
778 break;
779 }
780
781 if (XrdOuca2x::a2i(Elog,bkpopt[i].opname,tval,val,minv))
782 {Conf-> EchoLine();
783 return false;
784 }
785 break;
786 }
787 }
788 if (i >= numopts)
789 {Conf->MsgfE("Unknown backup option '%s'.", token); return false;}
790
791 } while((token = Conf->GetToken()));
792
793// All done
794//
795 return true;
796}
797
798/******************************************************************************/
799/* Private: x q B k u p P S */
800/******************************************************************************/
801
802bool XrdOssArcConfig::xqBkupPS(char* tval)
803{
804 int n = strlen(tval);
805
806// Check for percentage or actual size
807//
808 if (tval[n-1] == '%')
809 {if (XrdOuca2x::a2sp(Elog,"backup minfree",tval,&bkpMinF,1,99))
810 {Conf-> EchoLine();
811 return false;
812 }
813 bkpMinF = -bkpMinF;
814 } else {
815 if (XrdOuca2x::a2sz(Elog,"backup minfree",tval,&bkpMinF,1))
816 {Conf-> EchoLine();
817 return false;
818 }
819 }
820
821// All done
822//
823 return true;
824}
825
826/******************************************************************************/
827/* Private: x q B k u p S c o p e */
828/******************************************************************************/
829
830bool XrdOssArcConfig::xqBkupScope()
831{
832 char* scope = Conf->GetToken();
833
834 if (!scope || !(*scope))
835 {Conf->MsgfE("backup scope not specified!"); return false;}
836
837do{auto rslt = bkpScopes.insert(std::string(scope));
838 if (!rslt.second)
839 Conf->MsgW("backup scope", scope, "previously specified.");
840 scope = Conf->GetToken();
841 } while(scope && *scope);
842
843 return true;
844}
845
846/******************************************************************************/
847/* Private: x q G r a b */
848/******************************************************************************/
849
850bool XrdOssArcConfig::xqGrab(const char* what, char*& theDest,
851 const char* theLine)
852{
853 const char* tP;
854
855// Get all text after the direcive keyword in the last line
856//
857 if ((tP = index(theLine, ' '))) while(*tP == ' ') tP++;
858 if (!tP || !(*tP))
859 {Conf->MsgfE("%s argument not specified!", what);
860 return false;
861 }
862
863// Replace the new argument with the old one
864//
865 if (theDest) free(theDest);
866 theDest = strdup(tP);
867 return true;
868}
869
870/******************************************************************************/
871/* Private: x q M a n f */
872/******************************************************************************/
873/*
874 manifest cksum <ckalg>
875*/
876
877bool XrdOssArcConfig::xqManf()
878{
879 char** tDest = 0;
880 char *token, *targ;
881
882 if (!(token = Conf->GetToken()))
883 {Conf->MsgfE("No manifest parameters specified!");
884 return false;
885 }
886
887// Process all options
888//
889 do { if (!strcmp("cksum", token)) tDest = &manCKS;
890 else {Conf->MsgfE("Unknown manifest parameter '%s'; ignored.", token);
891 return false;
892 }
893 if (!(targ = Conf->GetToken()))
894 {Conf->MsgfE("%s argument not specified!", token);
895 return false;
896 }
897 if (*tDest) free(*tDest);
898 *tDest = strdup(targ);
899 } while((token = Conf->GetToken()));
900
901// All done
902//
903 return true;
904}
905
906/******************************************************************************/
907/* Private: x q P a t h s */
908/******************************************************************************/
909/*
910 paths [backing <path>] [{mssfs|mssroot} <path>] [srcdata <path>]
911 [staging <path>] [utils <path>]
912*/
913
914bool XrdOssArcConfig::xqPaths()
915{
916 char** pDest = 0;
917 char *token, *ploc;
918
919// Process all options
920//
921 while((token = Conf->GetToken()))
922 { if (!strcmp("backing", token)) pDest = &tapePath;
923 else if (!strcmp("mssfs", token)) pDest = &MssComRoot;
924 else if (!strcmp("mssroot", token)) pDest = &MssComRoot;
925 else if (!strcmp("srcdata", token)) pDest = &srcData;
926 else if (!strcmp("staging", token)) pDest = &stagePath;
927 else if (!strcmp("stopfile", token)) pDest = &stopPath;
928 else if (!strcmp("utils", token)) pDest = &utilsPath;
929 else {Conf->MsgfE("Unknown path type '%s'; ignored.", token);
930 if (!Conf->GetToken()) break;
931 continue;
932 }
933 if (!(ploc = Conf->GetToken()))
934 {Conf->MsgfE("%s path not specified!", token);
935 return false;
936 }
937
938 // Make sure path starts with a slash
939 //
940 if (*ploc != '/')
941 {Conf->MsgfE("%s path is not absolute!", token);
942 return false;
943 }
944
945 if (*pDest) free(*pDest);
946 *pDest = strdup(ploc);
947 }
948
949// Make sure we have at least one argument
950//
951 if (!pDest) {Conf->MsgfE("no 'path' arguments specified!"); return false;}
952
953// All done
954//
955 return true;
956}
957
958/******************************************************************************/
959/* Private: x q R s e */
960/******************************************************************************/
961/*
962 rsedcl <srcrse_name> <dstrse_name>
963*/
964bool XrdOssArcConfig::xqRse()
965{
966 char* token;
967
968// Get the first token, there must be one
969//
970 if (!(token = Conf->GetToken()))
971 {Conf->MsgfE("source rse name not specified!"); return false;}
972
973// Copy it over
974//
975 if (srcRSE) free(srcRSE);
976 srcRSE = strdup(token);
977
978// Get the next token, there must be one
979//
980 if (!(token = Conf->GetToken()))
981 {Conf->MsgfE("destination rse name not specified!"); return false;}
982
983// Copy it over
984//
985 if (dstRSE) free(dstRSE);
986 dstRSE = strdup(token);
987 return true;
988}
989
990/******************************************************************************/
991/* Private: x q R u c i o */
992/******************************************************************************/
993/*
994Note: the maxitems value should match what is specified in the schema.py file
995 that is used to describe the Rucio schema.
996
997 maxitems <items>
998*/
999bool XrdOssArcConfig::xqRucio()
1000{
1001 char* token, *val;
1002 int num;
1003
1004// Get the first token, there must be one
1005//
1006 if (!(token = Conf->GetToken()))
1007 {Conf->MsgfE("rucio parameter not specified!"); return false;}
1008
1009// Process the attribute
1010//
1011do{if (!strcmp(token, "maxitems"))
1012 {if (!(val = Conf->GetToken())
1013 || XrdOuca2x::a2i(Elog, "rucio maxitems value", val, &num, 1)) break;
1014 r_maxItems = num;
1015 } else {
1016 Conf->MsgfE("Invalid rucio parameter, '%s'!", token);
1017 return false;
1018 }
1019 } while((token = Conf->GetToken()));
1020
1021// Check ending
1022//
1023 if (token)
1024 {if (val) Conf->EchoLine();
1025 else Conf->MsgfE("rucio %s parameter value not specified.", token);
1026 return false;
1027 }
1028
1029// All done
1030//
1031 return true;
1032}
1033
1034/******************************************************************************/
1035/* Private: x q S t a g e */
1036/******************************************************************************/
1037/*
1038 stage [max <num>] [poll <sec>]
1039*/
1040
1041bool XrdOssArcConfig::xqStage()
1042{
1043 static const int minStg = 1, maxStg = 100, minPoll = 5, maxPoll = 100;
1044 char* val;
1045 int num, rc;
1046
1047// Get the first token (there must be at least one)
1048//
1049 if (!(val = Conf->GetToken()))
1050 {Conf->MsgfE("No stage parameters specified");
1051 return false;
1052 }
1053
1054// Now process all of them
1055//
1056 while(val)
1057 { if (!strcmp(val, "max"))
1058 {if (!(val = Conf->GetToken())) return MissArg("'max' value");
1059 rc = XrdOuca2x::a2i(Elog, "stage max value", val, &num,
1060 minStg, maxStg);
1061 if (rc) {Conf->EchoLine(); return false;}
1062 maxStage = num;
1063 }
1064 else if (!strcmp(val, "poll"))
1065 {if (!(val = Conf->GetToken())) return MissArg("'poll' value");
1066 rc = XrdOuca2x::a2tm(Elog, "stage poll value", val, &num,
1067 minPoll, maxPoll);
1068 if (rc) {Conf->EchoLine(); return false;}
1069 wtpStage = num;
1070 }
1071 else {Conf->MsgE("unknown option -", val);
1072 return false;
1073 }
1074 } while((val = Conf->GetToken()));
1075
1076// All done
1077//
1078 return true;
1079}
1080
1081/******************************************************************************/
1082/* Private: x q T r a c e */
1083/******************************************************************************/
1084
1085bool XrdOssArcConfig::xqTrace()
1086{
1087 char *val;
1088 struct traceopts {const char *opname; unsigned int opval;} tropts[] =
1089 {
1090 {"all", TRACE_All},
1091 {"off", TRACE_None},
1092 {"none", TRACE_None},
1093 {"save", TRACE_Save},
1094 {"debug", TRACE_Debug}
1095 };
1096 int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
1097
1098 if (!(val = Conf->GetToken()))
1099 {Conf->MsgE("no trace options specified");
1100 return false;
1101 }
1102 while (val)
1103 {if (!strcmp(val, "off")) trval = 0;
1104 else {if ((neg = (val[0] == '-' && val[1]))) val++;
1105 for (i = 0; i < numopts; i++)
1106 {if (!strcmp(val, tropts[i].opname))
1107 {if (neg)
1108 if (tropts[i].opval) trval &= ~tropts[i].opval;
1109 else trval = TRACE_All;
1110 else if (tropts[i].opval) trval |= tropts[i].opval;
1111 else trval = TRACE_None;
1112 break;
1113 }
1114 }
1115 if (i >= numopts)
1116 Conf->MsgfW("ignoring invalid trace option '%s'", val);
1117 }
1118 val = Conf->GetToken();
1119 }
1120 ArcTrace.What = trval;
1121 return true;
1122}
1123
1124/******************************************************************************/
1125/* Private: x q U t i l s */
1126/******************************************************************************/
1127/*
1128 utils [archiver <path>] [bkputils <path>] [disparc <path>] [msscom <path>]
1129 [preparc <path>]
1130*/
1131
1132bool XrdOssArcConfig::xqUtils()
1133{
1134 char** uDest = 0;
1135 char *token, *uloc;
1136
1137// Process all options
1138//
1139 while((token = Conf->GetToken()))
1140 { if (!strcmp("archiver", token)) uDest = &ArchiverPath;
1141 else if (!strcmp("bkputils", token)) uDest = &BkpUtilPath;
1142 else if (!strcmp("msscom", token)) uDest = &MssComPath;
1143 else if (!strcmp("postarc", token)) uDest = &PostArcPath;
1144 else if (!strcmp("preparc", token)) uDest = &PrepArcPath;
1145 else if (!strcmp("saver", token)) uDest = &ArchiverSave;
1146 else {Conf->MsgfW("Unknown util '%s'; ignored.", token);
1147 if (!Conf->GetToken()) break;
1148 continue;
1149 }
1150 if (!(uloc = Conf->GetToken()))
1151 {Conf->MsgfE("utils %s value not specified!", token);
1152 return false;
1153 }
1154 if (*uDest) free(*uDest);
1155 *uDest = strdup(uloc);
1156 }
1157
1158// Make sure we have at least one argument
1159//
1160 if (!uDest) {Conf->MsgE("no 'utils' arguments specified!"); return false;}
1161
1162// All done
1163//
1164 return true;
1165}
#define DEBUG(x)
struct stat Stat
Definition XrdCks.cc:49
#define TRACE_Debug
#define TRACE_All
#define TraceInfo(x, y)
#define TRACE_Save
#define TRACE_None
#define stat(a, b)
Definition XrdPosix.hh:101
static void StartWorkers(int maxw)
const char * PostArcName
XrdOucProg * MssComProg
const char * metaBKP
const char * metaIDX
bool BuildPath(const char *what, const char *baseP, const char *addP, char *&destP, int mode=0)
XrdOssArcStopMon * stopMon
XrdOucProg * ArchiverProg
const char * ArchiverName
const char * MssComName
const char * PrepArcName
bool Configure(const char *cfn, const char *parms, XrdOucEnv *envP)
const char * BkpUtilName
XrdOucProg * PrepArcProg
XrdOucProg * PostArcProg
XrdOucProg * BkpUtilProg
virtual int Lfn2Pfn(const char *Path, char *buff, int blen)
Definition XrdOss.hh:954
virtual int Stat(const char *path, struct stat *buff, int opts=0, XrdOucEnv *envP=0)=0
static int Export(const char *Var, const char *Val)
Definition XrdOucEnv.cc:170
char * GetToken(char **rest=0, int lowcase=0)
void MsgE(const char *txt1, const char *txt2=0, const char *txt3=0, const char *txt4=0, const char *txt5=0, const char *txt6=0)
@ full_lines
Complete lines.
static int makePath(char *path, mode_t mode, bool reset=false)
static int a2sp(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
Definition XrdOuca2x.cc:213
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
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
XrdSysTrace ArcTrace("OssArc")
XrdScheduler * schedP
Definition XrdOssArc.cc:66
XrdOssArcFSMon fsMon
XrdSysError Elog(0, "OssArc_")