13 #include "XrdVersion.hh"
32 m_allow_xrdpfc_command(false),
33 m_data_space(
"public"),
34 m_meta_space(
"public"),
38 m_fileUsageBaseline(-1),
39 m_fileUsageNominal(-1),
42 m_purgeColdFilesAge(-1),
43 m_purgeAgeBasedPeriod(10),
45 m_dirStatsMaxDepth(-1),
46 m_dirStatsStoreDepth(0),
47 m_bufferSize(128*1024),
49 m_RamKeepStdBlocks(0),
52 m_prefetch_max_blocks(10),
53 m_hdfsbsize(128*1024*1024),
58 m_onlyIfCachedMinSize(1024*1024),
59 m_onlyIfCachedMinFrac(1.0)
63 bool Cache::cfg2bytes(
const std::string &str,
long long &store,
long long totalSpace,
const char *name)
66 snprintf(errStr, 1024,
"ConfigParameters() Error parsing parameter %s", name);
68 if (::isalpha(*(str.rbegin())))
79 double frac = strtod(str.c_str(), &eP);
80 if (errno || eP == str.c_str())
82 m_log.
Emsg(errStr, str.c_str());
86 store =
static_cast<long long>(totalSpace * frac + 0.5);
89 if (store < 0 || store > totalSpace)
91 snprintf(errStr, 1024,
"ConfigParameters() Error: parameter %s should be between 0 and total available disk space (%lld) - it is %lld (given as %s)",
92 name, totalSpace, store, str.c_str());
93 m_log.
Emsg(errStr,
"");
121 const char *val, *val2;
122 struct cschkopts {
const char *opname;
int opval;} csopts[] =
129 int i, numopts =
sizeof(csopts)/
sizeof(
struct cschkopts);
132 if (! (val =
Config.GetWord()))
133 {m_log.
Emsg(
"Config",
"cschk parameter not specified");
return false; }
137 if ((
isNo = strncmp(val,
"no", 2) == 0))
141 for (i = 0; i < numopts; i++)
143 if (!strcmp(val2, csopts[i].opname))
146 m_configuration.
m_cs_Chk &= ~csopts[i].opval;
147 else if (csopts[i].opval)
148 m_configuration.
m_cs_Chk |= csopts[i].opval;
150 m_configuration.
m_cs_Chk = csopts[i].opval;
156 if (strcmp(val,
"uvkeep"))
158 m_log.
Emsg(
"Config",
"invalid cschk option -", val);
161 if (!(val =
Config.GetWord()))
163 m_log.
Emsg(
"Config",
"cschk uvkeep value not specified");
166 if (!strcmp(val,
"lru"))
179 m_configuration.m_cs_ChkTLS = m_configuration.m_cs_Chk &
CSChk_TLS;
182 m_env->Put(
"psx.CSNet", m_configuration.is_cschk_net() ? (m_configuration.m_cs_ChkTLS ?
"2" :
"1") :
"0");
203 if (! (val =
Config.GetWord()) || ! val[0])
205 TRACE(
Info,
" Cache::Config() decisionlib not specified; always caching files");
215 Config.GetRest(params, 4096);
224 if (! ep) {myLib->
Unload(
true);
return false; }
229 TRACE(
Error,
"Config() decisionlib was not able to create a decision object");
235 m_decisionpoints.push_back(d);
247 static struct traceopts {
const char *opname;
int opval; } tropts[] =
257 int numopts =
sizeof(tropts)/
sizeof(
struct traceopts);
259 if (! (val =
Config.GetWord()))
260 {m_log.
Emsg(
"Config",
"trace option not specified");
return 1; }
262 for (
int i = 0; i < numopts; i++)
264 if (! strcmp(val, tropts[i].opname))
266 m_trace->
What = tropts[i].opval;
270 m_log.
Emsg(
"Config",
"invalid trace option -", val);
275 bool Cache::test_oss_basics_and_features()
277 static const char *epfx =
"test_oss_basics_and_features()";
279 const auto &conf = m_configuration;
283 auto check_space = [&](
const char *space,
bool &has_xattr)
285 std::string fname(
"__prerun_test_pfc_");
288 env.
Put(
"oss.cgroup", space);
292 m_log.
Emsg(epfx,
"Can not create a file on space", space);
296 res = oss_file->
Open(fname.c_str(), O_RDWR, 0600, env);
298 m_log.
Emsg(epfx,
"Can not open a file on space", space);
301 res = oss_file->
Write(fname.data(), 0, fname.length());
302 if (res != (
int) fname.length()) {
303 m_log.
Emsg(epfx,
"Can not write into a file on space", space);
308 long long fsize = fname.length();
311 m_log.
Emsg(epfx,
"Can not write xattr to a file on space", space);
319 m_oss->
Lfn2Pfn(fname.c_str(), pfn, 4096);
322 if (res !=
sizeof(
long long) || fsize != (
long long) fname.length())
324 m_log.
Emsg(epfx,
"Can not read xattr from a file on space", space);
329 res = m_oss->
Unlink(fname.c_str());
331 m_log.
Emsg(epfx,
"Can not unlink a file on space", space);
339 aOK &= check_space(conf.m_data_space.c_str(), m_dataXattr);
340 aOK &= check_space(conf.m_meta_space.c_str(), m_metaXattr);
354 const char *theINS = getenv(
"XRDINSTANCE");
355 m_isClient = (theINS != 0 && strncmp(
"*client ", theINS, 8) == 0);
363 if (! config_filename || ! *config_filename)
365 TRACE(
Error,
"Config() configuration file not specified.");
370 if ( (fd =
open(config_filename, O_RDONLY, 0)) < 0)
372 TRACE(
Error,
"Config() can't open configuration file " << config_filename);
377 static const char *cvec[] = {
"*** pfc plugin config:", 0 };
383 if (! ofsCfg)
return false;
399 bool retval =
true, aOK =
true;
401 while ((var =
Config.GetMyFirstWord()))
403 if (! strcmp(var,
"pfc.osslib"))
407 else if (! strcmp(var,
"pfc.cschk"))
411 else if (! strcmp(var,
"pfc.decisionlib"))
415 else if (! strcmp(var,
"pfc.trace"))
419 else if (! strcmp(var,
"pfc.allow_xrdpfc_command"))
423 else if (! strncmp(var,
"pfc.", 4))
425 retval = ConfigParameters(std::string(var+4),
Config, tmpc);
438 myEnv.
Put(
"oss.runmode",
"pfc");
442 if (snprintf(csi_conf, 128,
"space=%s nofill", m_configuration.
m_meta_space.c_str()) < 128)
446 TRACE(
Error,
"Config() buffer too small for libXrdOssCsi params.");
456 TRACE(
Error,
"Config() Unable to create an OSS object");
461 aOK &= test_oss_basics_and_features();
468 m_log.
Emsg(
"ConfigParameters()",
"error obtaining stat info for data space ", m_configuration.
m_data_space.c_str());
471 if (sP.
Total < 10ll << 20)
473 m_log.
Emsg(
"ConfigParameters()",
"available data space is less than 10 MB (can be due to a mistake in oss.localroot directive) for space ",
484 m_log.
Emsg(
"ConfigParameters()",
"pfc.diskusage should have lowWatermark < highWatermark.");
500 m_log.
Emsg(
"ConfigParameters()",
"pfc.diskusage files should have baseline < nominal < max.");
534 m_configuration.
m_RamAbsAvailable = m_isClient ? 256ll * 1024 * 1024 : 1024ll * 1024 * 1024;
536 snprintf(buff,
sizeof(buff),
"RAM usage pfc.ram is not specified. Default value %s is used.", m_isClient ?
"256m" :
"1g");
537 m_log.
Say(
"Config info: ", buff);
543 char* cenv = getenv(
"XRDDEBUG");
544 if (cenv && ! strcmp(cenv,
"1") && m_trace->
What < 4) m_trace->
What = 4;
550 const char *csc[] = {
"off",
"cache nonet",
"nocache net notls",
554 "off",
"cache nonet",
"nocache net tls",
557 char buff[8192], uvk[32];
561 sprintf(uvk,
"%lld", (
long long) m_configuration.
m_cs_UVKeep);
563 loff = snprintf(buff,
sizeof(buff),
"Config effective %s pfc configuration:\n"
564 " pfc.cschk %s uvkeep %s\n"
565 " pfc.blocksize %lld\n"
568 " pfc.writequeue %d %d\n"
569 " # Total available disk: %lld\n"
570 " pfc.diskusage %lld %lld files %lld %lld %lld purgeinterval %d purgecoldfiles %d\n"
571 " pfc.spaces %s %s\n"
574 " pfc.acchistorysize %d\n"
575 " pfc.onlyIfCachedMinBytes %lld\n"
576 " pfc.onlyIfCachedMinFrac %.2f\n",
578 csc[
int(m_configuration.
m_cs_Chk)], uvk,
597 loff += snprintf(buff + loff,
sizeof(buff) - loff,
598 " pfc.dirstats maxdepth %d ((internal: store_depth %d, size_of_dirlist %d, size_of_globlist %d))\n",
601 loff += snprintf(buff + loff,
sizeof(buff) - loff,
" dirlist:\n");
603 loff += snprintf(buff + loff,
sizeof(buff) - loff,
" %s\n", i->c_str());
604 loff += snprintf(buff + loff,
sizeof(buff) - loff,
" globlist:\n");
606 loff += snprintf(buff + loff,
sizeof(buff) - loff,
" %s/*\n", i->c_str());
611 loff += snprintf(buff + loff,
sizeof(buff) - loff,
" pfc.hdfsmode hdfsbsize %lld\n", m_configuration.
m_hdfsbsize);
622 loff += snprintf(buff + loff,
sizeof(buff) - loff,
" pfc.user %s\n", m_configuration.
m_username.c_str());
627 m_env->
Put(
"XRDPFC.SEGSIZE", std::to_string(m_configuration.
m_bufferSize).c_str());
636 m_log.
Say(
"Config Proxy File Cache g-stream has", m_gstream ?
"" :
" NOT",
" been configured via xrootd.monitor directive");
638 m_log.
Say(
"------ Proxy File Cache configuration parsing ", aOK ?
"completed" :
"failed");
640 if (ofsCfg)
delete ofsCfg;
644 #ifdef XRDPFC_CKSUM_TEST
650 Info::TestCksumStuff();
664 struct ConfWordGetter
669 ConfWordGetter(
XrdOucStream& c) : m_config(c), m_last_word((char*)1) {}
671 const char* GetWord() {
if (HasLast()) m_last_word = m_config.
GetWord();
return HasLast() ? m_last_word :
""; }
672 bool HasLast() {
return (m_last_word != 0); }
675 ConfWordGetter cwg(config);
678 if ( part ==
"user" )
681 if ( ! cwg.HasLast())
683 m_log.
Emsg(
"Config",
"Error: pfc.user requires a parameter.");
687 else if ( part ==
"diskusage" )
694 m_log.
Emsg(
"Config",
"Error: pfc.diskusage parameter requires at least two arguments.");
699 while ((p = cwg.GetWord()) && cwg.HasLast())
701 if (strcmp(p,
"files") == 0)
707 if ( ! cwg.HasLast())
709 m_log.
Emsg(
"Config",
"Error: pfc.diskusage files directive requires three arguments.");
713 else if (strcmp(p,
"sleep") == 0 || strcmp(p,
"purgeinterval") == 0)
715 if (strcmp(p,
"sleep") == 0) m_log.
Emsg(
"Config",
"warning sleep directive is deprecated in pfc.diskusage. Please use purgeinterval instead.");
722 else if (strcmp(p,
"purgecoldfiles") == 0)
735 m_log.
Emsg(
"Config",
"Error: diskusage stanza contains unknown directive", p);
739 else if ( part ==
"acchistorysize" )
746 else if ( part ==
"dirstats" )
749 while ((p = cwg.GetWord()) && cwg.HasLast())
751 if (strcmp(p,
"maxdepth") == 0)
759 else if (strcmp(p,
"dir") == 0)
762 if (p && p[0] ==
'/')
766 char d[1024]; d[0] = 0;
774 if (*(pd - 1) ==
'/')
786 if (*pd ==
'/' && pd != d) *pd = 0;
789 if (ld >= 2 && d[ld-1] ==
'*' && d[ld-2] ==
'/')
794 printf(
"Glob %s -> %s -- depth = %d\n", p, d, depth);
799 printf(
"Dir %s -> %s -- depth = %d\n", p, d, depth);
806 m_log.
Emsg(
"Config",
"Error: dirstats dir parameter requires a directory argument starting with a '/'.");
812 m_log.
Emsg(
"Config",
"Error: dirstats stanza contains unknown directive '", p,
"'");
817 else if ( part ==
"blocksize" )
819 long long minBSize = 4 * 1024;
820 long long maxBSize = 512 * 1024 * 1024;
829 m_log.
Emsg(
"Config",
"pfc.blocksize must be a multiple of 4 kB. Rounded up.");
832 else if ( part ==
"prefetch" || part ==
"nramprefetch" )
834 if (part ==
"nramprefetch")
836 m_log.
Emsg(
"Config",
"pfc.nramprefetch is deprecated, please use pfc.prefetch instead. Replacing the directive internally.");
845 else if ( part ==
"nramread" )
847 m_log.
Emsg(
"Config",
"pfc.nramread is deprecated, please use pfc.ram instead. Ignoring this directive.");
850 else if ( part ==
"ram" )
852 long long minRAM = m_isClient ? 256 * 1024 * 1024 : 1024 * 1024 * 1024;
853 long long maxRAM = 256 * minRAM;
859 else if ( part ==
"writequeue")
870 else if ( part ==
"spaces" )
874 if ( ! cwg.HasLast())
876 m_log.
Emsg(
"Config",
"spacenames requires two parameters: <data-space> <metadata-space>.");
880 else if ( part ==
"hdfsmode" )
882 m_log.
Emsg(
"Config",
"pfc.hdfsmode is currently unsupported.");
887 const char* params = cwg.GetWord();
890 if (! strncmp(
"hdfsbsize", params, 9))
892 long long minBlSize = 32 * 1024;
893 long long maxBlSize = 128 * 1024 * 1024;
894 if (
XrdOuca2x::a2sz(m_log,
"Error getting file fragment size", cwg.GetWord(), &m_configuration.
m_hdfsbsize, minBlSize, maxBlSize))
901 m_log.
Emsg(
"Config",
"Error setting the fragment size parameter name");
906 else if ( part ==
"flush" )
909 if ( ! cwg.HasLast())
911 m_log.
Emsg(
"Config",
"Error: pfc.flush requires a parameter.");
915 else if ( part ==
"onlyifcached" )
918 while ((p = cwg.GetWord()) && cwg.HasLast())
920 if (strcmp(p,
"minsize") == 0)
922 std::string minBytes = cwg.GetWord();
923 long long minBytesTop = 1024 * 1024 * 1024;
924 if (::isalpha(*(minBytes.rbegin())))
939 if (strcmp(p,
"minfrac") == 0)
941 std::string minFrac = cwg.GetWord();
944 double frac = strtod(minFrac.c_str(), &eP);
945 if (errno || eP == minFrac.c_str())
947 m_log.
Emsg(
"Config",
"Error setting fraction for only-if-cached directive");
954 m_log.
Emsg(
"Config",
"Error: onlyifcached stanza contains unknown directive", p);
960 m_log.
Emsg(
"ConfigParameters() unmatched pfc parameter", part.c_str());
XrdSysXAttr * XrdSysXAttrActive
XrdVERSIONINFO(XrdOucGetCache, XrdPfc)
XrdOucCache * XrdOucGetCache(XrdSysLogger *logger, const char *config_filename, const char *parameters, XrdOucEnv *env)
int open(const char *path, int oflag,...)
int isNo(int dflt, const char *Msg1, const char *Msg2, const char *Msg3)
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)
virtual int Close(long long *retsz=0)=0
virtual int Open(const char *path, int Oflag, mode_t Mode, XrdOucEnv &env)
virtual ssize_t Write(const void *buffer, off_t offset, size_t size)
virtual int Create(const char *tid, const char *path, mode_t mode, XrdOucEnv &env, int opts=0)=0
virtual int Lfn2Pfn(const char *Path, char *buff, int blen)
virtual int StatVS(XrdOssVSInfo *vsP, const char *sname=0, int updt=0)
virtual XrdOssDF * newFile(const char *tident)=0
virtual int Unlink(const char *path, int Opts=0, XrdOucEnv *envP=0)=0
static int Export(const char *Var, const char *Val)
void * GetPtr(const char *varname)
void Put(const char *varname, const char *value)
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)
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
static int a2ll(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
bool Config(const char *config_filename, const char *parameters)
Parse configuration file.
Base class for selecting which files should be cached.
virtual bool ConfigDecision(const char *params)
Status of cached file. Can be read from and written into a binary file.
static size_t s_maxNumAccess
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
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[]
long long m_hdfsbsize
used with m_hdfsmode, default 128MB
long long m_RamAbsAvailable
available from configuration
long long m_flushCnt
nuber of unsynced blcoks on disk before flush is called
int m_accHistorySize
max number of entries in access history part of cinfo file
int m_wqueue_threads
number of threads writing blocks to disk
long long m_diskTotalSpace
total disk space on configured partition or oss space
long long m_fileUsageMax
cache purge - files usage maximum
long long m_fileUsageBaseline
cache purge - files usage baseline
int m_dirStatsStoreDepth
depth to which statistics should be collected
bool m_allow_xrdpfc_command
flag for enabling access to /xrdpfc-command/ functionality.
long long m_diskUsageHWM
cache purge - disk usage high water mark
bool is_cschk_cache() const
std::set< std::string > m_dirStatsDirGlobs
directory globs for which stat reporting was requested
int m_prefetch_max_blocks
maximum number of blocks to prefetch per file
bool m_cs_ChkTLS
Allow TLS.
long long m_fileUsageNominal
cache purge - files usage nominal
int m_cs_Chk
Checksum check.
int m_purgeAgeBasedPeriod
peform cold file / uvkeep purge every this many purge cycles
bool m_hdfsmode
flag for enabling block-level operation
int m_purgeColdFilesAge
purge files older than this age
std::string m_data_space
oss space for data files
std::set< std::string > m_dirStatsDirs
directories for which stat reporting was requested
long long m_diskUsageLWM
cache purge - disk usage low water mark
int m_RamKeepStdBlocks
number of standard-sized blocks kept after release
long long m_bufferSize
prefetch buffer size, default 1MB
std::string m_meta_space
oss space for metadata files (cinfo)
int m_wqueue_blocks
maximum number of blocks written per write-queue loop
std::string m_username
username passed to oss plugin
bool is_cschk_net() const
double m_onlyIfCachedMinFrac
minimum fraction of downloaded file, used by only-if-cached CGI option
time_t m_cs_UVKeep
unverified checksum cache keep
int m_dirStatsMaxDepth
maximum depth for statistics write out
int m_purgeInterval
sleep interval between cache purges
long long m_onlyIfCachedMinSize
minumum size of downloaded file, used by only-if-cached CGI option
bool is_dir_stat_reporting_on() const
std::string m_diskUsageLWM
std::string m_diskUsageHWM
std::string m_fileUsageBaseline
std::string m_fileUsageNominal
std::string m_fileUsageMax