XRootD
Loading...
Searching...
No Matches
XrdPfcConfiguration.cc
Go to the documentation of this file.
1#include "XrdPfc.hh"
2#include "XrdPfcTrace.hh"
3#include "XrdPfcInfo.hh"
4
6#include "XrdPfcPurgePin.hh"
7
8#include "XrdOss/XrdOss.hh"
9
10#include "XrdOuc/XrdOucEnv.hh"
11#include "XrdOuc/XrdOucUtils.hh"
14#include "XrdOuc/XrdOuca2x.hh"
15
16#include "XrdVersion.hh"
18#include "XrdSys/XrdSysXAttr.hh"
19
20#include <fcntl.h>
21
23
24namespace XrdPfc
25{
26 const char *trace_what_strings[] = {"","error ","warning ","info ","debug ","dump "};
27}
28
29using namespace XrdPfc;
30
32
65
66
67bool Cache::cfg2bytes(const std::string &str, long long &store, long long totalSpace, const char *name) const
68{
69 char errStr[1024];
70 snprintf(errStr, 1024, "ConfigParameters() Error parsing parameter %s", name);
71
72 if (::isalpha(*(str.rbegin())))
73 {
74 if (XrdOuca2x::a2sz(m_log, errStr, str.c_str(), &store, 0, totalSpace))
75 {
76 return false;
77 }
78 }
79 else
80 {
81 char *eP;
82 errno = 0;
83 double frac = strtod(str.c_str(), &eP);
84 if (errno || eP == str.c_str())
85 {
86 m_log.Emsg(errStr, str.c_str());
87 return false;
88 }
89
90 store = static_cast<long long>(totalSpace * frac + 0.5);
91 }
92
93 if (store < 0 || store > totalSpace)
94 {
95 snprintf(errStr, 1024, "ConfigParameters() Error: parameter %s should be between 0 and total available disk space (%lld) - it is %lld (given as %s)",
96 name, totalSpace, store, str.c_str());
97 m_log.Emsg(errStr, "");
98 return false;
99 }
100
101 return true;
102}
103
104bool Cache::blocksize_str2value(const char *from, const char *str,
105 long long &val, long long min, long long max) const
106{
107 if (XrdOuca2x::a2sz(m_log, "Error parsing block-size", str, &val, min, max))
108 return false;
109
110 if (val & 0xFFF) {
111 val &= ~0x0FFF;
112 val += 0x1000;
113 m_log.Emsg(from, "blocksize must be a multiple of 4 kB. Rounded up.");
114 }
115
116 return true;
117}
118
119bool Cache::prefetch_str2value(const char *from, const char *str,
120 int &val, int min, int max) const
121{
122 if (XrdOuca2x::a2i(m_log, "Error parsing prefetch block count", str, &val, min, max))
123 return false;
124
125 return true;
126}
127
128/* Function: xcschk
129
130 Purpose: To parse the directive: cschk <parms>
131
132 parms: [[no]net] [[no]tls] [[no]cache] [uvkeep <arg>]
133
134 all Checksum check on cache & net transfers.
135 cache Checksum check on cache only, 'no' turns it off.
136 net Checksum check on net transfers 'no' turns it off.
137 tls use TLS if server doesn't support checksums 'no' turns it off.
138 uvkeep Maximum amount of time a cached file make be kept if it
139 contains unverified checksums as n[d|h|m|s], where 'n'
140 is a non-negative integer. A value of 0 prohibits disk
141 caching unless the checksum can be verified. You can
142 also specify "lru" which means the standard purge policy
143 is to be used.
144
145 Output: true upon success or false upon failure.
146 */
147bool Cache::xcschk(XrdOucStream &Config)
148{
149 const char *val, *val2;
150 struct cschkopts {const char *opname; int opval;} csopts[] =
151 {
152 {"off", CSChk_None},
153 {"cache", CSChk_Cache},
154 {"net", CSChk_Net},
155 {"tls", CSChk_TLS}
156 };
157 int i, numopts = sizeof(csopts)/sizeof(struct cschkopts);
158 bool isNo;
159
160 if (! (val = Config.GetWord()))
161 {m_log.Emsg("Config", "cschk parameter not specified"); return false; }
162
163 while(val)
164 {
165 if ((isNo = strncmp(val, "no", 2) == 0))
166 val2 = val + 2;
167 else
168 val2 = val;
169 for (i = 0; i < numopts; i++)
170 {
171 if (!strcmp(val2, csopts[i].opname))
172 {
173 if (isNo)
174 m_configuration.m_cs_Chk &= ~csopts[i].opval;
175 else if (csopts[i].opval)
176 m_configuration.m_cs_Chk |= csopts[i].opval;
177 else
178 m_configuration.m_cs_Chk = csopts[i].opval;
179 break;
180 }
181 }
182 if (i >= numopts)
183 {
184 if (strcmp(val, "uvkeep"))
185 {
186 m_log.Emsg("Config", "invalid cschk option -", val);
187 return false;
188 }
189 if (!(val = Config.GetWord()))
190 {
191 m_log.Emsg("Config", "cschk uvkeep value not specified");
192 return false;
193 }
194 if (!strcmp(val, "lru"))
195 m_configuration.m_cs_UVKeep = -1;
196 else
197 {
198 int uvkeep;
199 if (XrdOuca2x::a2tm(m_log, "uvkeep time", val, &uvkeep, 0))
200 return false;
201 m_configuration.m_cs_UVKeep = uvkeep;
202 }
203 }
204 val = Config.GetWord();
205 }
206 // Decompose into separate TLS state, it is only passed on to psx
207 m_configuration.m_cs_ChkTLS = m_configuration.m_cs_Chk & CSChk_TLS;
208 m_configuration.m_cs_Chk &= ~CSChk_TLS;
209
210 m_env->Put("psx.CSNet", m_configuration.is_cschk_net() ? (m_configuration.m_cs_ChkTLS ? "2" : "1") : "0");
211
212 return true;
213}
214
215
216/* Function: xdlib
217
218 Purpose: To parse the directive: decisionlib <path> [<parms>]
219
220 <path> the path of the decision library to be used.
221 <parms> optional parameters to be passed.
222
223
224 Output: true upon success or false upon failure.
225 */
226bool Cache::xdlib(XrdOucStream &Config)
227{
228 const char* val;
229
230 std::string libp;
231 if (! (val = Config.GetWord()) || ! val[0])
232 {
233 TRACE(Info," Cache::Config() decisionlib not specified; always caching files");
234 return true;
235 }
236 else
237 {
238 libp = val;
239 }
240
241 char params[4096];
242 if (val[0])
243 Config.GetRest(params, 4096);
244 else
245 params[0] = 0;
246
247 XrdOucPinLoader* myLib = new XrdOucPinLoader(&m_log, 0, "decisionlib",
248 libp.c_str());
249
250 Decision *(*ep)(XrdSysError&);
251 ep = (Decision *(*)(XrdSysError&))myLib->Resolve("XrdPfcGetDecision");
252 if (! ep) {myLib->Unload(true); return false; }
253
254 Decision * d = ep(m_log);
255 if (! d)
256 {
257 TRACE(Error, "Config() decisionlib was not able to create a decision object");
258 return false;
259 }
260 if (params[0])
261 d->ConfigDecision(params);
262
263 m_decisionpoints.push_back(d);
264 return true;
265}
266
267/* Function: xplib
268
269 Purpose: To parse the directive: purgelib <path> [<parms>]
270
271 <path> the path of the decision library to be used.
272 <parms> optional parameters to be passed.
273
274
275 Output: true upon success or false upon failure.
276 */
277bool Cache::xplib(XrdOucStream &Config)
278{
279 const char* val;
280
281 std::string libp;
282 if (! (val = Config.GetWord()) || ! val[0])
283 {
284 TRACE(Info," Cache::Config() purgelib not specified; will use LRU for purging files");
285 return true;
286 }
287 else
288 {
289 libp = val;
290 }
291
292 char params[4096];
293 if (val[0])
294 Config.GetRest(params, 4096);
295 else
296 params[0] = 0;
297
298 XrdOucPinLoader* myLib = new XrdOucPinLoader(&m_log, 0, "purgelib",
299 libp.c_str());
300
301 PurgePin *(*ep)(XrdSysError&);
302 ep = (PurgePin *(*)(XrdSysError&))myLib->Resolve("XrdPfcGetPurgePin");
303 if (! ep) {myLib->Unload(true); return false; }
304
305 PurgePin * dp = ep(m_log);
306 if (! dp)
307 {
308 TRACE(Error, "Config() purgelib was not able to create a Purge Plugin object?");
309 return false;
310 }
311 m_purge_pin = dp;
312
313 if (params[0])
314 m_purge_pin->ConfigPurgePin(params);
315
316
317 return true;
318}
319
320/* Function: xtrace
321
322 Purpose: To parse the directive: trace <level>
323 Output: true upon success or false upon failure.
324 */
325bool Cache::xtrace(XrdOucStream &Config)
326{
327 char *val;
328 static struct traceopts {const char *opname; int opval; } tropts[] =
329 {
330 {"none", 0},
331 {"error", 1},
332 {"warning", 2},
333 {"info", 3},
334 {"debug", 4},
335 {"dump", 5},
336 {"dumpxl", 6}
337 };
338 int numopts = sizeof(tropts)/sizeof(struct traceopts);
339
340 if (! (val = Config.GetWord()))
341 {m_log.Emsg("Config", "trace option not specified"); return 1; }
342
343 for (int i = 0; i < numopts; i++)
344 {
345 if (! strcmp(val, tropts[i].opname))
346 {
347 m_trace->What = tropts[i].opval;
348 return true;
349 }
350 }
351 m_log.Emsg("Config", "invalid trace option -", val);
352 return false;
353}
354
355// Determine if oss spaces are operational and if they support xattrs.
356bool Cache::test_oss_basics_and_features()
357{
358 static const char *epfx = "test_oss_basics_and_features()";
359
360 const auto &conf = m_configuration;
361 const char *user = conf.m_username.c_str();
362 XrdOucEnv env;
363
364 auto check_space = [&](const char *space, bool &has_xattr)
365 {
366 std::string fname("__prerun_test_pfc_");
367 fname += space;
368 fname += "_space__";
369 env.Put("oss.cgroup", space);
370
371 int res = m_oss->Create(user, fname.c_str(), 0600, env, XRDOSS_mkpath);
372 if (res != XrdOssOK) {
373 m_log.Emsg(epfx, "Can not create a file on space", space);
374 return false;
375 }
376 XrdOssDF *oss_file = m_oss->newFile(user);
377 res = oss_file->Open(fname.c_str(), O_RDWR, 0600, env);
378 if (res != XrdOssOK) {
379 m_log.Emsg(epfx, "Can not open a file on space", space);
380 return false;
381 }
382 res = oss_file->Write(fname.data(), 0, fname.length());
383 if (res != (int) fname.length()) {
384 m_log.Emsg(epfx, "Can not write into a file on space", space);
385 return false;
386 }
387
388 has_xattr = true;
389 long long fsize = fname.length();
390 res = XrdSysXAttrActive->Set("pfc.fsize", &fsize, sizeof(long long), 0, oss_file->getFD(), 0);
391 if (res != 0) {
392 m_log.Emsg(epfx, "Can not write xattr to a file on space", space);
393 has_xattr = false;
394 }
395
396 oss_file->Close();
397
398 if (has_xattr) {
399 char pfn[4096];
400 m_oss->Lfn2Pfn(fname.c_str(), pfn, 4096);
401 fsize = -1ll;
402 res = XrdSysXAttrActive->Get("pfc.fsize", &fsize, sizeof(long long), pfn);
403 if (res != sizeof(long long) || fsize != (long long) fname.length())
404 {
405 m_log.Emsg(epfx, "Can not read xattr from a file on space", space);
406 has_xattr = false;
407 }
408 }
409
410 res = m_oss->Unlink(fname.c_str());
411 if (res != XrdOssOK) {
412 m_log.Emsg(epfx, "Can not unlink a file on space", space);
413 return false;
414 }
415
416 return true;
417 };
418
419 bool aOK = true;
420 aOK &= check_space(conf.m_data_space.c_str(), m_dataXattr);
421 aOK &= check_space(conf.m_meta_space.c_str(), m_metaXattr);
422
423 return aOK;
424}
425
426//______________________________________________________________________________
427/* Function: Config
428
429 Purpose: To parse configuration file and configure Cache instance.
430 Output: true upon success or false upon failure.
431 */
432bool Cache::Config(const char *config_filename, const char *parameters, XrdOucEnv *env)
433{
434 // Indicate whether or not we are a client instance
435 const char *theINS = getenv("XRDINSTANCE");
436 m_isClient = (theINS != 0 && strncmp("*client ", theINS, 8) == 0);
437
438 // Tell everyone else we are a caching proxy
439 XrdOucEnv::Export("XRDPFC", 1);
440
441 XrdOucEnv emptyEnv;
442 XrdOucEnv *myEnv = env ? env : &emptyEnv;
443
444 XrdOucStream Config(&m_log, theINS, myEnv, "=====> ");
445
446 if (! config_filename || ! *config_filename)
447 {
448 TRACE(Error, "Config() configuration file not specified.");
449 return false;
450 }
451
452 int fd;
453 if ( (fd = open(config_filename, O_RDONLY, 0)) < 0)
454 {
455 TRACE( Error, "Config() can't open configuration file " << config_filename);
456 return false;
457 }
458
459 Config.Attach(fd);
460 static const char *cvec[] = { "*** pfc plugin config:", 0 };
461 Config.Capture(cvec);
462
463 // Obtain OFS configurator for OSS plugin.
464 XrdOfsConfigPI *ofsCfg = XrdOfsConfigPI::New(config_filename,&Config,&m_log,
465 &XrdVERSIONINFOVAR(XrdOucGetCache));
466 if (! ofsCfg) return false;
467
468 TmpConfiguration tmpc;
469
470 Configuration &CFG = m_configuration;
471
472 // Adjust default parameters for client/serverless caching
473 if (m_isClient)
474 {
475 m_configuration.m_bufferSize = 128 * 1024; // same as normal.
476 m_configuration.m_wqueue_blocks = 8;
477 m_configuration.m_wqueue_threads = 1;
478 }
479
480 // If network checksum processing is the default, indicate so.
481 if (m_configuration.is_cschk_net()) m_env->Put("psx.CSNet", m_configuration.m_cs_ChkTLS ? "2" : "1");
482
483 // Actual parsing of the config file.
484 bool retval = true, aOK = true;
485 char *var;
486 while ((var = Config.GetMyFirstWord()))
487 {
488 if (! strcmp(var,"pfc.osslib"))
489 {
490 retval = ofsCfg->Parse(XrdOfsConfigPI::theOssLib);
491 }
492 else if (! strcmp(var,"pfc.cschk"))
493 {
494 retval = xcschk(Config);
495 }
496 else if (! strcmp(var,"pfc.decisionlib"))
497 {
498 retval = xdlib(Config);
499 }
500 else if (! strcmp(var,"pfc.purgelib"))
501 {
502 retval = xplib(Config);
503 }
504 else if (! strcmp(var,"pfc.trace"))
505 {
506 retval = xtrace(Config);
507 }
508 else if (! strcmp(var,"pfc.allow_xrdpfc_command"))
509 {
510 m_configuration.m_allow_xrdpfc_command = true;
511 }
512 else if (! strncmp(var,"pfc.", 4))
513 {
514 retval = ConfigParameters(std::string(var+4), Config, tmpc);
515 }
516
517 if ( ! retval)
518 {
519 TRACE(Error, "Config() error in parsing");
520 aOK = false;
521 }
522 }
523
524 Config.Close();
525
526 // Load OSS plugin.
527 auto orig_runmode = myEnv->Get("oss.runmode");
528 myEnv->Put("oss.runmode", "pfc");
529 if (m_configuration.is_cschk_cache())
530 {
531 char csi_conf[128];
532 if (snprintf(csi_conf, 128, "space=%s nofill", m_configuration.m_meta_space.c_str()) < 128)
533 {
534 ofsCfg->Push(XrdOfsConfigPI::theOssLib, "libXrdOssCsi.so", csi_conf);
535 } else {
536 TRACE(Error, "Config() buffer too small for libXrdOssCsi params.");
537 return false;
538 }
539 }
540 if (ofsCfg->Load(XrdOfsConfigPI::theOssLib, myEnv))
541 {
542 ofsCfg->Plugin(m_oss);
543 }
544 else
545 {
546 TRACE(Error, "Config() Unable to create an OSS object");
547 return false;
548 }
549 if (orig_runmode) myEnv->Put("oss.runmode", orig_runmode);
550 else myEnv->Put("oss.runmode", "");
551
552 // Test if OSS is operational, determine optional features.
553 aOK &= test_oss_basics_and_features();
554
555 // sets default value for disk usage
556 XrdOssVSInfo sP;
557 {
558 if (m_configuration.m_meta_space != m_configuration.m_data_space &&
559 m_oss->StatVS(&sP, m_configuration.m_meta_space.c_str(), 1) < 0)
560 {
561 m_log.Emsg("ConfigParameters()", "error obtaining stat info for meta space ", m_configuration.m_meta_space.c_str());
562 return false;
563 }
564 if (m_configuration.m_meta_space != m_configuration.m_data_space && sP.Total < 10ll << 20)
565 {
566 m_log.Emsg("ConfigParameters()", "available data space is less than 10 MB (can be due to a mistake in oss.localroot directive) for space ",
567 m_configuration.m_meta_space.c_str());
568 return false;
569 }
570 if (m_oss->StatVS(&sP, m_configuration.m_data_space.c_str(), 1) < 0)
571 {
572 m_log.Emsg("ConfigParameters()", "error obtaining stat info for data space ", m_configuration.m_data_space.c_str());
573 return false;
574 }
575 if (sP.Total < 10ll << 20)
576 {
577 m_log.Emsg("ConfigParameters()", "available data space is less than 10 MB (can be due to a mistake in oss.localroot directive) for space ",
578 m_configuration.m_data_space.c_str());
579 return false;
580 }
581
582 m_configuration.m_diskTotalSpace = sP.Total;
583
584 if (cfg2bytes(tmpc.m_diskUsageLWM, m_configuration.m_diskUsageLWM, sP.Total, "lowWatermark") &&
585 cfg2bytes(tmpc.m_diskUsageHWM, m_configuration.m_diskUsageHWM, sP.Total, "highWatermark"))
586 {
587 if (m_configuration.m_diskUsageLWM >= m_configuration.m_diskUsageHWM) {
588 m_log.Emsg("ConfigParameters()", "pfc.diskusage should have lowWatermark < highWatermark.");
589 aOK = false;
590 }
591 }
592 else aOK = false;
593
594 if ( ! tmpc.m_fileUsageMax.empty())
595 {
596 if (cfg2bytes(tmpc.m_fileUsageBaseline, m_configuration.m_fileUsageBaseline, sP.Total, "files baseline") &&
597 cfg2bytes(tmpc.m_fileUsageNominal, m_configuration.m_fileUsageNominal, sP.Total, "files nominal") &&
598 cfg2bytes(tmpc.m_fileUsageMax, m_configuration.m_fileUsageMax, sP.Total, "files max"))
599 {
600 if (m_configuration.m_fileUsageBaseline >= m_configuration.m_fileUsageNominal ||
601 m_configuration.m_fileUsageBaseline >= m_configuration.m_fileUsageMax ||
602 m_configuration.m_fileUsageNominal >= m_configuration.m_fileUsageMax)
603 {
604 m_log.Emsg("ConfigParameters()", "pfc.diskusage files should have baseline < nominal < max.");
605 aOK = false;
606 }
607
608
609 if (aOK && m_configuration.m_fileUsageMax >= m_configuration.m_diskUsageLWM)
610 {
611 m_log.Emsg("ConfigParameters()", "pfc.diskusage files values must be below lowWatermark");
612 aOK = false;
613 }
614 }
615 else aOK = false;
616 }
617 }
618
619 // sets flush frequency
620 if ( ! tmpc.m_flushRaw.empty())
621 {
622 if (::isalpha(*(tmpc.m_flushRaw.rbegin())))
623 {
624 if (XrdOuca2x::a2sz(m_log, "Error getting number of bytes written before flush", tmpc.m_flushRaw.c_str(),
625 &m_configuration.m_flushCnt,
626 100 * m_configuration.m_bufferSize , 100000 * m_configuration.m_bufferSize))
627 {
628 return false;
629 }
630 m_configuration.m_flushCnt /= m_configuration.m_bufferSize;
631 }
632 else
633 {
634 if (XrdOuca2x::a2ll(m_log, "Error getting number of blocks written before flush", tmpc.m_flushRaw.c_str(),
635 &m_configuration.m_flushCnt, 100, 100000))
636 {
637 return false;
638 }
639 }
640 }
641
642 // set the write mode
643 if ( ! tmpc.m_writemodeRaw.empty())
644 {
645 if (tmpc.m_writemodeRaw == "writethrough")
646 {
647 m_configuration.m_write_through = true;
648 }
649 else if (tmpc.m_writemodeRaw != "off")
650 {
651 m_log.Emsg("ConfigParameters()", "Unknown value for pfc.writemode (valid values are `writethrough` or `off`): %s",
652 tmpc.m_writemodeRaw.c_str());
653 return false;
654 }
655 }
656
657 // get number of available RAM blocks after process configuration
658 if (m_configuration.m_RamAbsAvailable == 0)
659 {
660 m_configuration.m_RamAbsAvailable = m_isClient ? 256ll * 1024 * 1024 : 1024ll * 1024 * 1024;
661 char buff[1024];
662 snprintf(buff, sizeof(buff), "RAM usage pfc.ram is not specified. Default value %s is used.", m_isClient ? "256m" : "1g");
663 m_log.Say("Config info: ", buff);
664 }
665 // Setup number of standard-size blocks not released back to the system to 5% of total RAM.
666 m_configuration.m_RamKeepStdBlocks = (m_configuration.m_RamAbsAvailable / m_configuration.m_bufferSize + 1) * 5 / 100;
667
668 // Set tracing to debug if this is set in environment
669 char* cenv = getenv("XRDDEBUG");
670 if (cenv && ! strcmp(cenv,"1") && m_trace->What < 4) m_trace->What = 4;
671
672 if (aOK)
673 {
674// 000 001 010
675 const char *csc[] = {"off", "cache nonet", "nocache net notls",
676// 011
677 "cache net notls",
678// 100 101 110
679 "off", "cache nonet", "nocache net tls",
680// 111
681 "cache net tls"};
682 char uvk[32];
683 if (m_configuration.m_cs_UVKeep < 0)
684 strcpy(uvk, "lru");
685 else
686 sprintf(uvk, "%lld", (long long) m_configuration.m_cs_UVKeep);
687 float ram_gb = (m_configuration.m_RamAbsAvailable) / float(1024*1024*1024);
688
689 char urlcgi_blks[64] = "ignore", urlcgi_npref[32] = "ignore";
691 snprintf(urlcgi_blks, sizeof(urlcgi_blks), "%lldk %lldk",
692 CFG.m_cgi_min_bufferSize >> 10, CFG.m_cgi_max_bufferSize >> 10);
694 snprintf(urlcgi_npref, sizeof(urlcgi_npref), "%d %d",
696
697 char buff[8192];
698 int loff = 0;
699 loff = snprintf(buff, sizeof(buff), "Config effective %s pfc configuration:\n"
700 " pfc.cschk %s uvkeep %s\n"
701 " pfc.blocksize %lldk\n"
702 " pfc.prefetch %d\n"
703 " pfc.urlcgi blocksize %s prefetch %s\n"
704 " pfc.ram %.fg\n"
705 " pfc.writequeue %d %d\n"
706 " # Total available disk: %lld\n"
707 " pfc.diskusage %lld %lld files %lld %lld %lld purgeinterval %d purgecoldfiles %d\n"
708 " pfc.spaces %s %s\n"
709 " pfc.trace %d\n"
710 " pfc.flush %lld\n"
711 " pfc.acchistorysize %d\n"
712 " pfc.onlyIfCachedMinBytes %lld\n"
713 " pfc.onlyIfCachedMinFrac %.2f\n",
714 config_filename,
715 csc[int(m_configuration.m_cs_Chk)], uvk,
716 m_configuration.m_bufferSize >> 10,
717 m_configuration.m_prefetch_max_blocks,
718 urlcgi_blks, urlcgi_npref,
719 ram_gb,
720 m_configuration.m_wqueue_blocks, m_configuration.m_wqueue_threads,
721 sP.Total,
722 m_configuration.m_diskUsageLWM, m_configuration.m_diskUsageHWM,
723 m_configuration.m_fileUsageBaseline, m_configuration.m_fileUsageNominal, m_configuration.m_fileUsageMax,
724 m_configuration.m_purgeInterval, m_configuration.m_purgeColdFilesAge,
725 m_configuration.m_data_space.c_str(),
726 m_configuration.m_meta_space.c_str(),
727 m_trace->What,
728 m_configuration.m_flushCnt,
729 m_configuration.m_accHistorySize,
730 m_configuration.m_onlyIfCachedMinSize,
731 m_configuration.m_onlyIfCachedMinFrac);
732
733 if (m_configuration.is_dir_stat_reporting_on())
734 {
735 loff += snprintf(buff + loff, sizeof(buff) - loff,
736 " pfc.dirstats interval %d maxdepth %d (internal: size_of_dirlist %d, size_of_globlist %d)\n",
737 m_configuration.m_dirStatsInterval, m_configuration.m_dirStatsStoreDepth,
738 (int) m_configuration.m_dirStatsDirs.size(), (int) m_configuration.m_dirStatsDirGlobs.size());
739 loff += snprintf(buff + loff, sizeof(buff) - loff, " dirlist:\n");
740 for (std::set<std::string>::iterator i = m_configuration.m_dirStatsDirs.begin(); i != m_configuration.m_dirStatsDirs.end(); ++i)
741 loff += snprintf(buff + loff, sizeof(buff) - loff, " %s\n", i->c_str());
742 loff += snprintf(buff + loff, sizeof(buff) - loff, " globlist:\n");
743 for (std::set<std::string>::iterator i = m_configuration.m_dirStatsDirGlobs.begin(); i != m_configuration.m_dirStatsDirGlobs.end(); ++i)
744 loff += snprintf(buff + loff, sizeof(buff) - loff, " %s/*\n", i->c_str());
745 }
746
747 if (m_configuration.m_hdfsmode)
748 {
749 loff += snprintf(buff + loff, sizeof(buff) - loff, " pfc.hdfsmode hdfsbsize %lld\n", m_configuration.m_hdfsbsize);
750 }
751 loff += snprintf(buff + loff, sizeof(buff) - loff, " pfc.writemode %s\n", m_configuration.m_write_through ? "writethrough" : "off");
752
753 if (m_configuration.m_username.empty())
754 {
755 char unameBuff[256];
756 XrdOucUtils::UserName(getuid(), unameBuff, sizeof(unameBuff));
757 m_configuration.m_username = unameBuff;
758 }
759 else
760 {
761 loff += snprintf(buff + loff, sizeof(buff) - loff, " pfc.user %s\n", m_configuration.m_username.c_str());
762 }
763
764 m_log.Say(buff);
765
766 m_env->Put("XRDPFC.SEGSIZE", std::to_string(m_configuration.m_bufferSize).c_str());
767 }
768
769 // Derived settings
770 m_prefetch_enabled = CFG.m_prefetch_max_blocks > 0 || CFG.m_cgi_max_prefetch_max_blocks > 0;
772
773 m_gstream = (XrdXrootdGStream*) m_env->GetPtr("pfc.gStream*");
774
775 m_log.Say(" pfc g-stream has", m_gstream ? "" : " NOT", " been configured via xrootd.monitor directive\n");
776
777 // Create the ResourceMonitor and get it ready for starting the main thread function.
778 if (aOK)
779 {
780 m_res_mon = new ResourceMonitor(*m_oss);
781 m_res_mon->init_before_main();
782 }
783
784 m_log.Say("=====> Proxy file cache configuration parsing ", aOK ? "completed" : "failed");
785
786 if (ofsCfg) delete ofsCfg;
787
788 // XXXX-CKSUM Testing. To be removed after OssPgi is also merged and valildated.
789 // Building of xrdpfc_print fails when this is enabled.
790#ifdef XRDPFC_CKSUM_TEST
791 {
792 int xxx = m_configuration.m_cs_Chk;
793
794 for (m_configuration.m_cs_Chk = CSChk_None; m_configuration.m_cs_Chk <= CSChk_Both; ++m_configuration.m_cs_Chk)
795 {
796 Info::TestCksumStuff();
797 }
798
799 m_configuration.m_cs_Chk = xxx;
800 }
801#endif
802
803 return aOK;
804}
805
806//------------------------------------------------------------------------------
807
808bool Cache::ConfigParameters(std::string part, XrdOucStream& config, TmpConfiguration &tmpc)
809{
810 struct ConfWordGetter
811 {
812 XrdOucStream &m_config;
813 char *m_last_word;
814
815 ConfWordGetter(XrdOucStream& c) : m_config(c), m_last_word((char*)1) {}
816
817 const char* GetWord() { if (HasLast()) m_last_word = m_config.GetWord(); return HasLast() ? m_last_word : ""; }
818 bool HasLast() { return (m_last_word != 0); }
819 };
820
821 ConfWordGetter cwg(config);
822
823 Configuration &CFG = m_configuration;
824
825 if ( part == "user" )
826 {
827 m_configuration.m_username = cwg.GetWord();
828 if ( ! cwg.HasLast())
829 {
830 m_log.Emsg("Config", "Error: pfc.user requires a parameter.");
831 return false;
832 }
833 }
834 else if ( part == "diskusage" )
835 {
836 tmpc.m_diskUsageLWM = cwg.GetWord();
837 tmpc.m_diskUsageHWM = cwg.GetWord();
838
839 if (tmpc.m_diskUsageHWM.empty())
840 {
841 m_log.Emsg("Config", "Error: pfc.diskusage parameter requires at least two arguments.");
842 return false;
843 }
844
845 const char *p = 0;
846 while ((p = cwg.GetWord()) && cwg.HasLast())
847 {
848 if (strcmp(p, "files") == 0)
849 {
850 tmpc.m_fileUsageBaseline = cwg.GetWord();
851 tmpc.m_fileUsageNominal = cwg.GetWord();
852 tmpc.m_fileUsageMax = cwg.GetWord();
853
854 if ( ! cwg.HasLast())
855 {
856 m_log.Emsg("Config", "Error: pfc.diskusage files directive requires three arguments.");
857 return false;
858 }
859 }
860 else if (strcmp(p, "sleep") == 0 || strcmp(p, "purgeinterval") == 0)
861 {
862 if (strcmp(p, "sleep") == 0) m_log.Emsg("Config", "warning sleep directive is deprecated in pfc.diskusage. Please use purgeinterval instead.");
863
864 if (XrdOuca2x::a2tm(m_log, "Error getting purgeinterval", cwg.GetWord(), &m_configuration.m_purgeInterval, 60, 3600))
865 {
866 return false;
867 }
868 }
869 else if (strcmp(p, "purgecoldfiles") == 0)
870 {
871 if (XrdOuca2x::a2tm(m_log, "Error getting purgecoldfiles age", cwg.GetWord(), &m_configuration.m_purgeColdFilesAge, 3600, 3600*24*360))
872 {
873 return false;
874 }
875 if (XrdOuca2x::a2i(m_log, "Error getting purgecoldfiles period", cwg.GetWord(), &m_configuration.m_purgeAgeBasedPeriod, 1, 1000))
876 {
877 return false;
878 }
879 }
880 else
881 {
882 m_log.Emsg("Config", "Error: diskusage stanza contains unknown directive", p);
883 }
884 }
885 }
886 else if ( part == "acchistorysize" )
887 {
888 if ( XrdOuca2x::a2i(m_log, "Error getting access-history-size", cwg.GetWord(), &m_configuration.m_accHistorySize, 20, 200))
889 {
890 return false;
891 }
892 }
893 else if ( part == "dirstats" )
894 {
895 const char *p = 0;
896 while ((p = cwg.GetWord()) && cwg.HasLast())
897 {
898 if (strcmp(p, "interval") == 0)
899 {
900 int validIntervals[] = {60, 120, 300, 600, 900, 1200, 1800, 3600};
901 int size = sizeof(validIntervals) / sizeof(int);
902
903 if (XrdOuca2x::a2tm(m_log, "Error getting dirstsat interval", cwg.GetWord(),
904 &m_configuration.m_dirStatsInterval, validIntervals[0], validIntervals[size - 1]))
905 {
906 return false;
907 }
908 bool match = false, round_down = false;
909 for (int i = 0; i < size; i++) {
910 if (validIntervals[i] == m_configuration.m_dirStatsInterval) {
911 match = true;
912 break;
913 }
914 if (i > 0 && m_configuration.m_dirStatsInterval < validIntervals[i]) {
915 m_configuration.m_dirStatsInterval = validIntervals[i - 1];
916 round_down = true;
917 break;
918 }
919 }
920 if ( ! match && ! round_down) {
921 m_log.Emsg("Config", "Error: dirstat interval parsing failed.");
922 return false;
923 }
924 if (round_down) {
925 m_log.Emsg("Config", "Info: dirstat interval was rounded down to the nearest valid value.");
926 }
927
928 }
929 else if (strcmp(p, "maxdepth") == 0)
930 {
931 if (XrdOuca2x::a2i(m_log, "Error getting maxdepth value", cwg.GetWord(),
932 &m_configuration.m_dirStatsStoreDepth, 0, 16))
933 {
934 return false;
935 }
936 }
937 else if (strcmp(p, "dir") == 0)
938 {
939 p = cwg.GetWord();
940 if (p && p[0] == '/')
941 {
942 // XXX -- should we just store them as sets of PathTokenizer objects, not strings?
943
944 char d[1024]; d[0] = 0;
945 int depth = 0;
946 { // Compress multiple slashes and "measure" depth
947 const char *pp = p;
948 char *pd = d;
949 *(pd++) = *(pp++);
950 while (*pp != 0)
951 {
952 if (*(pd - 1) == '/')
953 {
954 if (*pp == '/')
955 {
956 ++pp; continue;
957 }
958 ++depth;
959 }
960 *(pd++) = *(pp++);
961 }
962 *(pd--) = 0;
963 // remove trailing but but not leading /
964 if (*pd == '/' && pd != d) *pd = 0;
965 }
966 int ld = strlen(d);
967 if (ld >= 2 && d[ld-1] == '*' && d[ld-2] == '/')
968 {
969 d[ld-2] = 0;
970 ld -= 2;
971 m_configuration.m_dirStatsDirGlobs.insert(d);
972 printf("Glob %s -> %s -- depth = %d\n", p, d, depth);
973 }
974 else
975 {
976 m_configuration.m_dirStatsDirs.insert(d);
977 printf("Dir %s -> %s -- depth = %d\n", p, d, depth);
978 }
979
980 m_configuration.m_dirStatsStoreDepth = std::max(m_configuration.m_dirStatsStoreDepth, depth);
981 }
982 else
983 {
984 m_log.Emsg("Config", "Error: dirstats dir parameter requires a directory argument starting with a '/'.");
985 return false;
986 }
987 }
988 else
989 {
990 m_log.Emsg("Config", "Error: dirstats stanza contains unknown directive '", p, "'");
991 return false;
992 }
993 }
994 }
995 else if ( part == "blocksize" )
996 {
997 if ( ! blocksize_str2value("Config", cwg.GetWord(), CFG.m_bufferSize,
999 return false;
1000 }
1001 else if ( part == "prefetch" || part == "nramprefetch" )
1002 {
1003 if (part == "nramprefetch")
1004 {
1005 m_log.Emsg("Config", "pfc.nramprefetch is deprecated, please use pfc.prefetch instead. Replacing the directive internally.");
1006 }
1007
1008 if ( ! prefetch_str2value("Config", cwg.GetWord(), CFG.m_prefetch_max_blocks,
1010 return false;
1011 }
1012 else if ( part == "urlcgi" )
1013 {
1014 // pfc.urlcgi [blocksize {ignore | min max}] [prefetch {ignore | min max}]
1015 const char *p = 0;
1016 while ((p = cwg.GetWord()) && cwg.HasLast())
1017 {
1018 if (strcmp(p, "blocksize") == 0)
1019 {
1020 std::string bmin = cwg.GetWord();
1021 if (bmin == "ignore")
1022 continue;
1023 std::string bmax = cwg.GetWord();
1024 if ( ! cwg.HasLast()) {
1025 m_log.Emsg("Config", "Error: pfc.urlcgi blocksize parameter requires two arguments.");
1026 return false;
1027 }
1028 if ( ! blocksize_str2value("Config::urlcgi", bmin.c_str(), CFG.m_cgi_min_bufferSize,
1030 return false;
1031 if ( ! blocksize_str2value("Config::urlcgi", bmax.c_str(), CFG.m_cgi_max_bufferSize,
1033 return false;
1035 m_log.Emsg("Config", "Error: pfc.urlcgi blocksize second argument must be larger or equal to the first one.");
1036 return false;
1037 }
1038 CFG.m_cgi_blocksize_allowed = true;
1039 }
1040 else if (strcmp(p, "prefetch") == 0)
1041 {
1042 std::string bmin = cwg.GetWord();
1043 if (bmin == "ignore")
1044 continue;
1045 std::string bmax = cwg.GetWord();
1046 if ( ! cwg.HasLast()) {
1047 m_log.Emsg("Config", "Error: pfc.urlcgi blocksize parameter requires two arguments.");
1048 return false;
1049 }
1050 if ( ! prefetch_str2value("Config::urlcgi", bmin.c_str(), CFG.m_cgi_min_prefetch_max_blocks,
1052 return false;
1053 if ( ! prefetch_str2value("Config::urlcgi", bmax.c_str(), CFG.m_cgi_max_prefetch_max_blocks,
1055 return false;
1057 m_log.Emsg("Config", "Error: pfc.urlcgi prefetch second argument must be larger or equal to the first one.");
1058 return false;
1059 }
1060 CFG.m_cgi_prefetch_allowed = true;
1061 }
1062 else
1063 {
1064 m_log.Emsg("Config", "Error: urlcgi stanza contains unknown directive '", p, "'");
1065 return false;
1066 }
1067 } // while get next pfc.urlcgi word
1068 }
1069 else if ( part == "nramread" )
1070 {
1071 m_log.Emsg("Config", "pfc.nramread is deprecated, please use pfc.ram instead. Ignoring this directive.");
1072 cwg.GetWord(); // Ignoring argument.
1073 }
1074 else if ( part == "ram" )
1075 {
1076 long long minRAM = m_isClient ? 256 * 1024 * 1024 : 1024 * 1024 * 1024;
1077 long long maxRAM = 256 * minRAM;
1078 if ( XrdOuca2x::a2sz(m_log, "get RAM available", cwg.GetWord(), &m_configuration.m_RamAbsAvailable, minRAM, maxRAM))
1079 {
1080 return false;
1081 }
1082 }
1083 else if ( part == "writequeue")
1084 {
1085 if (XrdOuca2x::a2i(m_log, "Error getting pfc.writequeue num-blocks", cwg.GetWord(), &m_configuration.m_wqueue_blocks, 1, 1024))
1086 {
1087 return false;
1088 }
1089 if (XrdOuca2x::a2i(m_log, "Error getting pfc.writequeue num-threads", cwg.GetWord(), &m_configuration.m_wqueue_threads, 1, 64))
1090 {
1091 return false;
1092 }
1093 }
1094 else if ( part == "spaces" )
1095 {
1096 m_configuration.m_data_space = cwg.GetWord();
1097 m_configuration.m_meta_space = cwg.GetWord();
1098 if ( ! cwg.HasLast())
1099 {
1100 m_log.Emsg("Config", "spacenames requires two parameters: <data-space> <metadata-space>.");
1101 return false;
1102 }
1103 }
1104 else if ( part == "hdfsmode" )
1105 {
1106 m_log.Emsg("Config", "pfc.hdfsmode is currently unsupported.");
1107 return false;
1108
1109 m_configuration.m_hdfsmode = true;
1110
1111 const char* params = cwg.GetWord();
1112 if (params)
1113 {
1114 if (! strncmp("hdfsbsize", params, 9))
1115 {
1116 long long minBlSize = 32 * 1024;
1117 long long maxBlSize = 128 * 1024 * 1024;
1118 if ( XrdOuca2x::a2sz(m_log, "Error getting file fragment size", cwg.GetWord(), &m_configuration.m_hdfsbsize, minBlSize, maxBlSize))
1119 {
1120 return false;
1121 }
1122 }
1123 else
1124 {
1125 m_log.Emsg("Config", "Error setting the fragment size parameter name");
1126 return false;
1127 }
1128 }
1129 }
1130 else if ( part == "writemode" )
1131 {
1132 tmpc.m_writemodeRaw = cwg.GetWord();
1133 if ( ! cwg.HasLast())
1134 {
1135 m_log.Emsg("Config", "Error: pfc.writemode requires a parameter.");
1136 return false;
1137 }
1138 }
1139 else if ( part == "flush" )
1140 {
1141 tmpc.m_flushRaw = cwg.GetWord();
1142 if ( ! cwg.HasLast())
1143 {
1144 m_log.Emsg("Config", "Error: pfc.flush requires a parameter.");
1145 return false;
1146 }
1147 }
1148 else if ( part == "onlyifcached" )
1149 {
1150 const char *p = 0;
1151 while ((p = cwg.GetWord()) && cwg.HasLast())
1152 {
1153 if (strcmp(p, "minsize") == 0)
1154 {
1155 std::string minBytes = cwg.GetWord();
1156 long long minBytesTop = 1024 * 1024 * 1024;
1157 if (::isalpha(*(minBytes.rbegin())))
1158 {
1159 if (XrdOuca2x::a2sz(m_log, "Error in parsing minsize value for onlyifcached parameter", minBytes.c_str(), &m_configuration.m_onlyIfCachedMinSize, 0, minBytesTop))
1160 {
1161 return false;
1162 }
1163 }
1164 else
1165 {
1166 if (XrdOuca2x::a2ll(m_log, "Error in parsing numeric minsize value for onlyifcached parameter", minBytes.c_str(),&m_configuration.m_onlyIfCachedMinSize, 0, minBytesTop))
1167 {
1168 return false;
1169 }
1170 }
1171 }
1172 if (strcmp(p, "minfrac") == 0)
1173 {
1174 std::string minFrac = cwg.GetWord();
1175 char *eP;
1176 errno = 0;
1177 double frac = strtod(minFrac.c_str(), &eP);
1178 if (errno || eP == minFrac.c_str())
1179 {
1180 m_log.Emsg("Config", "Error setting fraction for only-if-cached directive");
1181 return false;
1182 }
1183 m_configuration.m_onlyIfCachedMinFrac = frac;
1184 }
1185 else
1186 {
1187 m_log.Emsg("Config", "Error: onlyifcached stanza contains unknown directive", p);
1188 }
1189 }
1190 }
1191 else
1192 {
1193 m_log.Emsg("ConfigParameters() unmatched pfc parameter", part.c_str());
1194 return false;
1195 }
1196
1197 return true;
1198}
#define XrdOssOK
Definition XrdOss.hh:50
#define XRDOSS_mkpath
Definition XrdOss.hh:466
XrdVERSIONINFO(XrdOucGetCache, XrdPfc)
XrdSysXAttr * XrdSysXAttrActive
XrdOucCache * XrdOucGetCache(XrdSysLogger *logger, const char *config_filename, const char *parameters, XrdOucEnv *env)
Definition XrdPfc.cc:76
#define open
Definition XrdPosix.hh:76
int isNo(int dflt, const char *Msg1, const char *Msg2, const char *Msg3)
#define TRACE(act, x)
Definition XrdTrace.hh:63
bool Parse(TheLib what)
bool Plugin(XrdAccAuthorize *&piP)
Get Authorization plugin.
static XrdOfsConfigPI * New(const char *cfn, XrdOucStream *cfgP, XrdSysError *errP, XrdVersionInfo *verP=0, XrdSfsFileSystem *sfsP=0)
bool Load(int what, XrdOucEnv *envP=0)
bool Push(TheLib what, const char *plugP, const char *parmP=0)
@ theOssLib
Oss plugin.
virtual int Close(long long *retsz=0)=0
virtual int getFD()
Definition XrdOss.hh:426
virtual int Open(const char *path, int Oflag, mode_t Mode, XrdOucEnv &env)
Definition XrdOss.hh:200
virtual ssize_t Write(const void *buffer, off_t offset, size_t size)
Definition XrdOss.hh:345
long long Total
Definition XrdOssVS.hh:90
char * Get(const char *varname)
Definition XrdOucEnv.hh:69
static int Export(const char *Var, const char *Val)
Definition XrdOucEnv.cc:188
void Put(const char *varname, const char *value)
Definition XrdOucEnv.hh:85
void * Resolve(const char *symbl, int mcnt=1)
void Unload(bool dodel=false)
char * GetWord(int lowcase=0)
static int UserName(uid_t uID, char *uName, int uNsz)
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 a2ll(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
Definition XrdOuca2x.cc:70
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition XrdOuca2x.cc:288
bool blocksize_str2value(const char *from, const char *str, long long &val, long long min, long long max) const
bool Config(const char *config_filename, const char *parameters, XrdOucEnv *env)
Parse configuration file.
bool prefetch_str2value(const char *from, const char *str, int &val, int min, int max) const
virtual bool ConfigDecision(const char *params)
static size_t s_maxNumAccess
virtual bool ConfigPurgePin(const char *params)
virtual int Get(const char *Aname, void *Aval, int Avsz, const char *Path, int fd=-1)=0
virtual int Set(const char *Aname, const void *Aval, int Avsz, const char *Path, int fd=-1, int isNew=0)=0
const char * trace_what_strings[]
@ CSChk_Cache
Contains parameters configurable from the xrootd config file.
Definition XrdPfc.hh:64
long long m_hdfsbsize
used with m_hdfsmode, default 128MB
Definition XrdPfc.hh:122
long long m_RamAbsAvailable
available from configuration
Definition XrdPfc.hh:109
long long m_flushCnt
nuber of unsynced blcoks on disk before flush is called
Definition XrdPfc.hh:123
long long m_cgi_max_bufferSize
max buffer size allowed in pfc.blocksize
Definition XrdPfc.hh:116
int m_accHistorySize
max number of entries in access history part of cinfo file
Definition XrdPfc.hh:101
int m_cgi_min_prefetch_max_blocks
min prefetch block count allowed in pfc.prefetch
Definition XrdPfc.hh:117
bool m_cgi_prefetch_allowed
allow cgi setting of prefetch
Definition XrdPfc.hh:120
int m_wqueue_threads
number of threads writing blocks to disk
Definition XrdPfc.hh:112
bool m_write_through
flag indicating write-through mode is enabled
Definition XrdPfc.hh:84
long long m_diskTotalSpace
total disk space on configured partition or oss space
Definition XrdPfc.hh:92
long long m_fileUsageMax
cache purge - files usage maximum
Definition XrdPfc.hh:97
long long m_fileUsageBaseline
cache purge - files usage baseline
Definition XrdPfc.hh:95
int m_dirStatsStoreDepth
maximum depth for statistics write out
Definition XrdPfc.hh:106
bool m_allow_xrdpfc_command
flag for enabling access to /xrdpfc-command/ functionality.
Definition XrdPfc.hh:86
long long m_diskUsageHWM
cache purge - disk usage high water mark
Definition XrdPfc.hh:94
static constexpr long long s_min_bufferSize
Definition XrdPfc.hh:132
static constexpr long long s_max_bufferSize
Definition XrdPfc.hh:133
int m_prefetch_max_blocks
default maximum number of blocks to prefetch per file
Definition XrdPfc.hh:113
bool m_cs_ChkTLS
Allow TLS.
Definition XrdPfc.hh:127
long long m_fileUsageNominal
cache purge - files usage nominal
Definition XrdPfc.hh:96
int m_cs_Chk
Checksum check.
Definition XrdPfc.hh:126
int m_purgeAgeBasedPeriod
peform cold file / uvkeep purge every this many purge cycles
Definition XrdPfc.hh:100
bool m_hdfsmode
flag for enabling block-level operation
Definition XrdPfc.hh:85
int m_purgeColdFilesAge
purge files older than this age
Definition XrdPfc.hh:99
std::string m_data_space
oss space for data files
Definition XrdPfc.hh:89
long long m_diskUsageLWM
cache purge - disk usage low water mark
Definition XrdPfc.hh:93
int m_RamKeepStdBlocks
number of standard-sized blocks kept after release
Definition XrdPfc.hh:110
long long m_bufferSize
cache block size, default 128 kB
Definition XrdPfc.hh:108
long long m_cgi_min_bufferSize
min buffer size allowed in pfc.blocksize
Definition XrdPfc.hh:115
int m_dirStatsInterval
time between resource monitor statistics dump in seconds
Definition XrdPfc.hh:105
std::string m_meta_space
oss space for metadata files (cinfo)
Definition XrdPfc.hh:90
int m_wqueue_blocks
maximum number of blocks written per write-queue loop
Definition XrdPfc.hh:111
int m_cgi_max_prefetch_max_blocks
max prefetch block count allowed in pfc.prefetch
Definition XrdPfc.hh:118
static constexpr int s_max_prefetch_max_blocks
Definition XrdPfc.hh:135
bool m_cgi_blocksize_allowed
allow cgi setting of blocksize
Definition XrdPfc.hh:119
double m_onlyIfCachedMinFrac
minimum fraction of downloaded file, used by only-if-cached CGI option
Definition XrdPfc.hh:130
time_t m_cs_UVKeep
unverified checksum cache keep
Definition XrdPfc.hh:125
int m_purgeInterval
sleep interval between cache purges
Definition XrdPfc.hh:98
long long m_onlyIfCachedMinSize
minumum size of downloaded file, used by only-if-cached CGI option
Definition XrdPfc.hh:129
std::string m_writemodeRaw
Definition XrdPfc.hh:148
std::string m_diskUsageLWM
Definition XrdPfc.hh:142
std::string m_diskUsageHWM
Definition XrdPfc.hh:143
std::string m_fileUsageBaseline
Definition XrdPfc.hh:144
std::string m_fileUsageNominal
Definition XrdPfc.hh:145
std::string m_flushRaw
Definition XrdPfc.hh:147
std::string m_fileUsageMax
Definition XrdPfc.hh:146