16 #include "XrdVersion.hh"
35 m_allow_xrdpfc_command(false),
36 m_data_space(
"public"),
37 m_meta_space(
"public"),
41 m_fileUsageBaseline(-1),
42 m_fileUsageNominal(-1),
45 m_purgeColdFilesAge(-1),
46 m_purgeAgeBasedPeriod(10),
48 m_dirStatsMaxDepth(-1),
49 m_dirStatsStoreDepth(0),
50 m_bufferSize(128*1024),
52 m_RamKeepStdBlocks(0),
55 m_prefetch_max_blocks(10),
56 m_hdfsbsize(128*1024*1024),
61 m_onlyIfCachedMinSize(1024*1024),
62 m_onlyIfCachedMinFrac(1.0)
66 bool Cache::cfg2bytes(
const std::string &str,
long long &store,
long long totalSpace,
const char *name)
69 snprintf(errStr, 1024,
"ConfigParameters() Error parsing parameter %s", name);
71 if (::isalpha(*(str.rbegin())))
82 double frac = strtod(str.c_str(), &eP);
83 if (errno || eP == str.c_str())
85 m_log.
Emsg(errStr, str.c_str());
89 store =
static_cast<long long>(totalSpace * frac + 0.5);
92 if (store < 0 || store > totalSpace)
94 snprintf(errStr, 1024,
"ConfigParameters() Error: parameter %s should be between 0 and total available disk space (%lld) - it is %lld (given as %s)",
95 name, totalSpace, store, str.c_str());
96 m_log.
Emsg(errStr,
"");
124 const char *val, *val2;
125 struct cschkopts {
const char *opname;
int opval;} csopts[] =
132 int i, numopts =
sizeof(csopts)/
sizeof(
struct cschkopts);
135 if (! (val =
Config.GetWord()))
136 {m_log.
Emsg(
"Config",
"cschk parameter not specified");
return false; }
140 if ((
isNo = strncmp(val,
"no", 2) == 0))
144 for (i = 0; i < numopts; i++)
146 if (!strcmp(val2, csopts[i].opname))
149 m_configuration.
m_cs_Chk &= ~csopts[i].opval;
150 else if (csopts[i].opval)
151 m_configuration.
m_cs_Chk |= csopts[i].opval;
153 m_configuration.
m_cs_Chk = csopts[i].opval;
159 if (strcmp(val,
"uvkeep"))
161 m_log.
Emsg(
"Config",
"invalid cschk option -", val);
164 if (!(val =
Config.GetWord()))
166 m_log.
Emsg(
"Config",
"cschk uvkeep value not specified");
169 if (!strcmp(val,
"lru"))
182 m_configuration.m_cs_ChkTLS = m_configuration.m_cs_Chk &
CSChk_TLS;
185 m_env->Put(
"psx.CSNet", m_configuration.is_cschk_net() ? (m_configuration.m_cs_ChkTLS ?
"2" :
"1") :
"0");
206 if (! (val =
Config.GetWord()) || ! val[0])
208 TRACE(
Info,
" Cache::Config() decisionlib not specified; always caching files");
218 Config.GetRest(params, 4096);
227 if (! ep) {myLib->
Unload(
true);
return false; }
232 TRACE(
Error,
"Config() decisionlib was not able to create a decision object");
238 m_decisionpoints.push_back(d);
257 if (! (val =
Config.GetWord()) || ! val[0])
259 TRACE(
Info,
" Cache::Config() purgelib not specified; will use LRU for purging files");
269 Config.GetRest(params, 4096);
278 if (! ep) {myLib->
Unload(
true);
return false; }
283 TRACE(
Error,
"Config() purgelib was not able to create a Purge Plugin object?");
303 static struct traceopts {
const char *opname;
int opval; } tropts[] =
313 int numopts =
sizeof(tropts)/
sizeof(
struct traceopts);
315 if (! (val =
Config.GetWord()))
316 {m_log.
Emsg(
"Config",
"trace option not specified");
return 1; }
318 for (
int i = 0; i < numopts; i++)
320 if (! strcmp(val, tropts[i].opname))
322 m_trace->
What = tropts[i].opval;
326 m_log.
Emsg(
"Config",
"invalid trace option -", val);
331 bool Cache::test_oss_basics_and_features()
333 static const char *epfx =
"test_oss_basics_and_features()";
335 const auto &conf = m_configuration;
339 auto check_space = [&](
const char *space,
bool &has_xattr)
341 std::string fname(
"__prerun_test_pfc_");
344 env.
Put(
"oss.cgroup", space);
348 m_log.
Emsg(epfx,
"Can not create a file on space", space);
352 res = oss_file->
Open(fname.c_str(), O_RDWR, 0600, env);
354 m_log.
Emsg(epfx,
"Can not open a file on space", space);
357 res = oss_file->
Write(fname.data(), 0, fname.length());
358 if (res != (
int) fname.length()) {
359 m_log.
Emsg(epfx,
"Can not write into a file on space", space);
364 long long fsize = fname.length();
367 m_log.
Emsg(epfx,
"Can not write xattr to a file on space", space);
375 m_oss->
Lfn2Pfn(fname.c_str(), pfn, 4096);
378 if (res !=
sizeof(
long long) || fsize != (
long long) fname.length())
380 m_log.
Emsg(epfx,
"Can not read xattr from a file on space", space);
385 res = m_oss->
Unlink(fname.c_str());
387 m_log.
Emsg(epfx,
"Can not unlink a file on space", space);
395 aOK &= check_space(conf.m_data_space.c_str(), m_dataXattr);
396 aOK &= check_space(conf.m_meta_space.c_str(), m_metaXattr);
410 const char *theINS = getenv(
"XRDINSTANCE");
411 m_isClient = (theINS != 0 && strncmp(
"*client ", theINS, 8) == 0);
419 if (! config_filename || ! *config_filename)
421 TRACE(
Error,
"Config() configuration file not specified.");
426 if ( (fd =
open(config_filename, O_RDONLY, 0)) < 0)
428 TRACE(
Error,
"Config() can't open configuration file " << config_filename);
433 static const char *cvec[] = {
"*** pfc plugin config:", 0 };
439 if (! ofsCfg)
return false;
455 bool retval =
true, aOK =
true;
457 while ((var =
Config.GetMyFirstWord()))
459 if (! strcmp(var,
"pfc.osslib"))
463 else if (! strcmp(var,
"pfc.cschk"))
467 else if (! strcmp(var,
"pfc.decisionlib"))
471 else if (! strcmp(var,
"pfc.purgelib"))
475 else if (! strcmp(var,
"pfc.trace"))
479 else if (! strcmp(var,
"pfc.allow_xrdpfc_command"))
483 else if (! strncmp(var,
"pfc.", 4))
485 retval = ConfigParameters(std::string(var+4),
Config, tmpc);
498 myEnv.
Put(
"oss.runmode",
"pfc");
502 if (snprintf(csi_conf, 128,
"space=%s nofill", m_configuration.
m_meta_space.c_str()) < 128)
506 TRACE(
Error,
"Config() buffer too small for libXrdOssCsi params.");
516 TRACE(
Error,
"Config() Unable to create an OSS object");
521 aOK &= test_oss_basics_and_features();
529 m_log.
Emsg(
"ConfigParameters()",
"error obtaining stat info for meta space ", m_configuration.
m_meta_space.c_str());
534 m_log.
Emsg(
"ConfigParameters()",
"available data space is less than 10 MB (can be due to a mistake in oss.localroot directive) for space ",
540 m_log.
Emsg(
"ConfigParameters()",
"error obtaining stat info for data space ", m_configuration.
m_data_space.c_str());
543 if (sP.
Total < 10ll << 20)
545 m_log.
Emsg(
"ConfigParameters()",
"available data space is less than 10 MB (can be due to a mistake in oss.localroot directive) for space ",
556 m_log.
Emsg(
"ConfigParameters()",
"pfc.diskusage should have lowWatermark < highWatermark.");
572 m_log.
Emsg(
"ConfigParameters()",
"pfc.diskusage files should have baseline < nominal < max.");
579 m_log.
Emsg(
"ConfigParameters()",
"pfc.diskusage files values must be below lowWatermark");
613 m_configuration.
m_RamAbsAvailable = m_isClient ? 256ll * 1024 * 1024 : 1024ll * 1024 * 1024;
615 snprintf(buff,
sizeof(buff),
"RAM usage pfc.ram is not specified. Default value %s is used.", m_isClient ?
"256m" :
"1g");
616 m_log.
Say(
"Config info: ", buff);
622 char* cenv = getenv(
"XRDDEBUG");
623 if (cenv && ! strcmp(cenv,
"1") && m_trace->
What < 4) m_trace->
What = 4;
629 const char *csc[] = {
"off",
"cache nonet",
"nocache net notls",
633 "off",
"cache nonet",
"nocache net tls",
636 char buff[8192], uvk[32];
640 sprintf(uvk,
"%lld", (
long long) m_configuration.
m_cs_UVKeep);
642 loff = snprintf(buff,
sizeof(buff),
"Config effective %s pfc configuration:\n"
643 " pfc.cschk %s uvkeep %s\n"
644 " pfc.blocksize %lld\n"
647 " pfc.writequeue %d %d\n"
648 " # Total available disk: %lld\n"
649 " pfc.diskusage %lld %lld files %lld %lld %lld purgeinterval %d purgecoldfiles %d\n"
650 " pfc.spaces %s %s\n"
653 " pfc.acchistorysize %d\n"
654 " pfc.onlyIfCachedMinBytes %lld\n"
655 " pfc.onlyIfCachedMinFrac %.2f\n",
657 csc[
int(m_configuration.
m_cs_Chk)], uvk,
676 loff += snprintf(buff + loff,
sizeof(buff) - loff,
677 " pfc.dirstats maxdepth %d ((internal: store_depth %d, size_of_dirlist %d, size_of_globlist %d))\n",
680 loff += snprintf(buff + loff,
sizeof(buff) - loff,
" dirlist:\n");
682 loff += snprintf(buff + loff,
sizeof(buff) - loff,
" %s\n", i->c_str());
683 loff += snprintf(buff + loff,
sizeof(buff) - loff,
" globlist:\n");
685 loff += snprintf(buff + loff,
sizeof(buff) - loff,
" %s/*\n", i->c_str());
690 loff += snprintf(buff + loff,
sizeof(buff) - loff,
" pfc.hdfsmode hdfsbsize %lld\n", m_configuration.
m_hdfsbsize);
701 loff += snprintf(buff + loff,
sizeof(buff) - loff,
" pfc.user %s\n", m_configuration.
m_username.c_str());
706 m_env->
Put(
"XRDPFC.SEGSIZE", std::to_string(m_configuration.
m_bufferSize).c_str());
715 m_log.
Say(
" pfc g-stream has", m_gstream ?
"" :
" NOT",
" been configured via xrootd.monitor directive\n");
724 m_log.
Say(
"=====> Proxy file cache configuration parsing ", aOK ?
"completed" :
"failed");
726 if (ofsCfg)
delete ofsCfg;
730 #ifdef XRDPFC_CKSUM_TEST
736 Info::TestCksumStuff();
750 struct ConfWordGetter
755 ConfWordGetter(
XrdOucStream& c) : m_config(c), m_last_word((char*)1) {}
757 const char* GetWord() {
if (HasLast()) m_last_word = m_config.
GetWord();
return HasLast() ? m_last_word :
""; }
758 bool HasLast() {
return (m_last_word != 0); }
761 ConfWordGetter cwg(config);
764 if ( part ==
"user" )
767 if ( ! cwg.HasLast())
769 m_log.
Emsg(
"Config",
"Error: pfc.user requires a parameter.");
773 else if ( part ==
"diskusage" )
780 m_log.
Emsg(
"Config",
"Error: pfc.diskusage parameter requires at least two arguments.");
785 while ((p = cwg.GetWord()) && cwg.HasLast())
787 if (strcmp(p,
"files") == 0)
793 if ( ! cwg.HasLast())
795 m_log.
Emsg(
"Config",
"Error: pfc.diskusage files directive requires three arguments.");
799 else if (strcmp(p,
"sleep") == 0 || strcmp(p,
"purgeinterval") == 0)
801 if (strcmp(p,
"sleep") == 0) m_log.
Emsg(
"Config",
"warning sleep directive is deprecated in pfc.diskusage. Please use purgeinterval instead.");
808 else if (strcmp(p,
"purgecoldfiles") == 0)
821 m_log.
Emsg(
"Config",
"Error: diskusage stanza contains unknown directive", p);
825 else if ( part ==
"acchistorysize" )
832 else if ( part ==
"dirstats" )
835 while ((p = cwg.GetWord()) && cwg.HasLast())
837 if (strcmp(p,
"maxdepth") == 0)
845 else if (strcmp(p,
"dir") == 0)
848 if (p && p[0] ==
'/')
852 char d[1024]; d[0] = 0;
860 if (*(pd - 1) ==
'/')
872 if (*pd ==
'/' && pd != d) *pd = 0;
875 if (ld >= 2 && d[ld-1] ==
'*' && d[ld-2] ==
'/')
880 printf(
"Glob %s -> %s -- depth = %d\n", p, d, depth);
885 printf(
"Dir %s -> %s -- depth = %d\n", p, d, depth);
892 m_log.
Emsg(
"Config",
"Error: dirstats dir parameter requires a directory argument starting with a '/'.");
898 m_log.
Emsg(
"Config",
"Error: dirstats stanza contains unknown directive '", p,
"'");
903 else if ( part ==
"blocksize" )
905 long long minBSize = 4 * 1024;
906 long long maxBSize = 512 * 1024 * 1024;
915 m_log.
Emsg(
"Config",
"pfc.blocksize must be a multiple of 4 kB. Rounded up.");
918 else if ( part ==
"prefetch" || part ==
"nramprefetch" )
920 if (part ==
"nramprefetch")
922 m_log.
Emsg(
"Config",
"pfc.nramprefetch is deprecated, please use pfc.prefetch instead. Replacing the directive internally.");
931 else if ( part ==
"nramread" )
933 m_log.
Emsg(
"Config",
"pfc.nramread is deprecated, please use pfc.ram instead. Ignoring this directive.");
936 else if ( part ==
"ram" )
938 long long minRAM = m_isClient ? 256 * 1024 * 1024 : 1024 * 1024 * 1024;
939 long long maxRAM = 256 * minRAM;
945 else if ( part ==
"writequeue")
956 else if ( part ==
"spaces" )
960 if ( ! cwg.HasLast())
962 m_log.
Emsg(
"Config",
"spacenames requires two parameters: <data-space> <metadata-space>.");
966 else if ( part ==
"hdfsmode" )
968 m_log.
Emsg(
"Config",
"pfc.hdfsmode is currently unsupported.");
973 const char* params = cwg.GetWord();
976 if (! strncmp(
"hdfsbsize", params, 9))
978 long long minBlSize = 32 * 1024;
979 long long maxBlSize = 128 * 1024 * 1024;
980 if (
XrdOuca2x::a2sz(m_log,
"Error getting file fragment size", cwg.GetWord(), &m_configuration.
m_hdfsbsize, minBlSize, maxBlSize))
987 m_log.
Emsg(
"Config",
"Error setting the fragment size parameter name");
992 else if ( part ==
"flush" )
995 if ( ! cwg.HasLast())
997 m_log.
Emsg(
"Config",
"Error: pfc.flush requires a parameter.");
1001 else if ( part ==
"onlyifcached" )
1004 while ((p = cwg.GetWord()) && cwg.HasLast())
1006 if (strcmp(p,
"minsize") == 0)
1008 std::string minBytes = cwg.GetWord();
1009 long long minBytesTop = 1024 * 1024 * 1024;
1010 if (::isalpha(*(minBytes.rbegin())))
1025 if (strcmp(p,
"minfrac") == 0)
1027 std::string minFrac = cwg.GetWord();
1030 double frac = strtod(minFrac.c_str(), &eP);
1031 if (errno || eP == minFrac.c_str())
1033 m_log.
Emsg(
"Config",
"Error setting fraction for only-if-cached directive");
1040 m_log.
Emsg(
"Config",
"Error: onlyifcached stanza contains unknown directive", p);
1046 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
Base class for reguesting directory space to obtain.
virtual bool ConfigPurgePin(const char *params)
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