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