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