XRootD
XrdPfcFPurgeState.cc
Go to the documentation of this file.
1 #include "XrdPfcFPurgeState.hh"
2 #include "XrdPfcFsTraversal.hh"
3 #include "XrdPfcInfo.hh"
4 #include "XrdPfc.hh"
5 #include "XrdPfcTrace.hh"
6 
7 #include "XrdOuc/XrdOucEnv.hh"
8 #include "XrdOuc/XrdOucUtils.hh"
9 #include "XrdOss/XrdOss.hh"
10 #include "XrdOss/XrdOssAt.hh"
11 
12 // Temporary, extensive purge tracing
13 // #define TRACE_PURGE(x) TRACE(Debug, x)
14 // #define TRACE_PURGE(x) std::cout << "PURGE " << x << "\n"
15 #define TRACE_PURGE(x)
16 
17 using namespace XrdPfc;
18 
19 const char *FPurgeState::m_traceID = "Purge";
20 
21 //----------------------------------------------------------------------------
23 //----------------------------------------------------------------------------
24 FPurgeState::FPurgeState(long long iNBytesReq, XrdOss &oss) :
25  m_oss(oss),
26  m_nStBlocksReq((iNBytesReq >> 9) + 1ll), m_nStBlocksAccum(0), m_nStBlocksTotal(0),
27  m_tMinTimeStamp(0), m_tMinUVKeepTimeStamp(0)
28 {
29 
30 }
31 
32 //----------------------------------------------------------------------------
35 //----------------------------------------------------------------------------
37 {
38  for (list_i i = m_flist.begin(); i != m_flist.end(); ++i)
39  {
40  m_fmap.insert(std::make_pair(i->time, *i));
41  }
42  m_flist.clear();
43 }
44 
45 //----------------------------------------------------------------------------
52 //----------------------------------------------------------------------------
53 void FPurgeState::CheckFile(const FsTraversal &fst, const char *fname, time_t atime, struct stat &fstat)
54 {
55  long long nblocks = fstat.st_blocks;
56  // TRACE(Dump, trc_pfx << "FPurgeState::CheckFile checking " << fname << " accessTime " << atime);
57 
58  m_nStBlocksTotal += nblocks;
59 
60  // Could remove aged-out / uv-keep-failed files here ... or in the calling function that
61  // can aggreagate info for all files in the directory.
62 
63  // For now keep using 0 time as this is used in the purge loop to make sure we continue even if enough
64  // disk-space has been freed.
65 
66  if (m_tMinTimeStamp > 0 && atime < m_tMinTimeStamp)
67  {
68  m_flist.push_back(PurgeCandidate(fst.m_current_path, fname, nblocks, 0));
69  m_nStBlocksAccum += nblocks;
70  }
71  else if (m_nStBlocksAccum < m_nStBlocksReq || (!m_fmap.empty() && atime < m_fmap.rbegin()->first))
72  {
73  m_fmap.insert(std::make_pair(atime, PurgeCandidate(fst.m_current_path, fname, nblocks, atime)));
74  m_nStBlocksAccum += nblocks;
75 
76  // remove newest files from map if necessary
77  while (!m_fmap.empty() && m_nStBlocksAccum - m_fmap.rbegin()->second.nStBlocks >= m_nStBlocksReq)
78  {
79  m_nStBlocksAccum -= m_fmap.rbegin()->second.nStBlocks;
80  m_fmap.erase(--(m_fmap.rbegin().base()));
81  }
82  }
83 }
84 
86 {
87  for (auto it = fst.m_current_files.begin(); it != fst.m_current_files.end(); ++it)
88  {
89  // Check if the file is currently opened / purge-protected is done before unlinking of the file.
90  const std::string &f_name = it->first;
91  const std::string i_name = f_name + Info::s_infoExtension;
92 
93  // XXX Note, the initial scan now uses stat information only!
94 
95  if (! it->second.has_both()) {
96  // cinfo or data file is missing. What do we do? Erase?
97  // Should really be checked in some other "consistency" traversal.
98  continue;
99  }
100 
101  time_t atime = it->second.stat_cinfo.st_mtime;
102  CheckFile(fst, i_name.c_str(), atime, it->second.stat_data);
103 
104  // Protected top-directories are skipped.
105  }
106 
107  std::vector<std::string> dirs;
108  dirs.swap(fst.m_current_dirs);
109  for (auto &dname : dirs)
110  {
111  if (fst.cd_down(dname))
112  {
114  fst.cd_up();
115  }
116  }
117 }
118 
119 bool FPurgeState::TraverseNamespace(const char *root_path)
120 {
121  bool success_p = true;
122 
123  FsTraversal fst(m_oss);
124  fst.m_protected_top_dirs.insert("pfc-stats"); // XXXX This should come from config. Also: N2N?
125  // Also ... this onoly applies to /, not any root_path
126  if (fst.begin_traversal(root_path))
127  {
129  }
130  else
131  {
132  // Fail startup, can't open /.
133  success_p = false;
134  }
135  fst.end_traversal();
136 
137  return success_p;
138 }
139 
140 /*
141 void FPurgeState::UnlinkInfoAndData(const char *fname, long long nblocks, XrdOssDF *iOssDF)
142 {
143  fname[fname_len - m_info_ext_len] = 0;
144  if (nblocks > 0)
145  {
146  if ( ! Cache.GetInstance().IsFileActiveOrPurgeProtected(dataPath))
147  {
148  m_n_purged++;
149  m_bytes_purged += nblocks;
150  } else
151  {
152  m_n_purge_protected++;
153  m_bytes_purge_protected += nblocks;
154  m_dir_state->add_usage_purged(nblocks);
155  // XXXX should also tweak other stuff?
156  fname[fname_len - m_info_ext_len] = '.';
157  return;
158  }
159  }
160  m_oss_at.Unlink(*iOssDF, fname);
161  fname[fname_len - m_info_ext_len] = '.';
162  m_oss_at.Unlink(*iOssDF, fname);
163 }
164 */
int stat(const char *path, struct stat *buf)
int fstat(int fildes, struct stat *buf)
void CheckFile(const FsTraversal &fst, const char *fname, time_t atime, struct stat &fstat)
void ProcessDirAndRecurse(FsTraversal &fst)
FPurgeState(long long iNBytesReq, XrdOss &oss)
Constructor.
bool TraverseNamespace(const char *root_path)
list_t::iterator list_i
std::vector< std::string > m_current_dirs
bool begin_traversal(DirState *root, const char *root_path)
std::set< std::string > m_protected_top_dirs
bool cd_down(const std::string &dir_name)
std::map< std::string, FilePairStat > m_current_files
static const char * s_infoExtension
Definition: XrdPfcInfo.hh:309
Definition: XrdPfc.hh:41