XRootD
XrdPfcFsTraversal.cc
Go to the documentation of this file.
1 #include "XrdPfcFsTraversal.hh"
2 #include "XrdPfcDirState.hh"
3 #include "XrdPfc.hh"
4 #include "XrdPfcTrace.hh"
5 
6 #include "XrdOuc/XrdOucEnv.hh"
7 #include "XrdOss/XrdOssApi.hh"
8 
9 // #define TRACE_PURGE(x) std::cout << "PURGE " << x << "\n"
10 #define TRACE_PURGE(x)
11 
12 using namespace XrdPfc;
13 
14 namespace
15 {
16  XrdSysTrace* GetTrace() { return Cache::GetInstance().GetTrace(); }
17 }
18 
19 const char *FsTraversal::m_traceID = "FsTraversal";
20 
21 //----------------------------------------------------------------------------
22 
24  m_oss(oss), m_oss_at(oss)
25 {}
26 
28 {}
29 
31 {
32  int ret = 0;
33  if (ossDF) {
34  ret = ossDF->Close();
35  delete ossDF;
36  }
37  ossDF = nullptr;
38  return ret;
39 }
40 
41 //----------------------------------------------------------------------------
42 
43 bool FsTraversal::begin_traversal(DirState *root, const char *root_path)
44 {
45  m_maintain_dirstate = true;
47 
48  bool ret = begin_traversal(root_path);
49 
50  return ret;
51 }
52 
53 bool FsTraversal::begin_traversal(const char *root_path)
54 {
55  static const char *trc_pfx = "FsTraversal::begin_traversal ";
56 
57  assert(root_path && strlen(root_path) > 0 && root_path[0] == '/');
58 
59  m_rel_dir_level = 0;
60  m_current_path = root_path;
61 
62  XrdOssDF* dhp = m_oss.newDir("PfcFsTraversal");
63  if (dhp->Opendir(root_path, m_env) != XrdOssOK) {
64  delete dhp;
65  TRACE(Error, trc_pfx << "could not opendir [" << root_path << "], " << XrdSysE2T(errno));
66  return false;
67  }
68  m_dir_handle_stack.push_back(dhp);
69 
70  TRACE_PURGE("FPurgeState::begin_traversal cur_path '" << m_current_path << "', rel_level=" << m_rel_dir_level);
71 
73  return true;
74 }
75 
77 {
78  TRACE_PURGE("FPurgeState::end_traversal reporting for '" << m_current_path << "', re_level=" << m_rel_dir_level);
79 
80  for (auto &dhp : m_dir_handle_stack) {
81  dhp->Close();
82  delete dhp;
83  }
84  m_dir_handle_stack.clear();
85  m_current_path.clear();
86  m_current_dirs.clear();
87  m_current_files.clear();
88 
89  m_rel_dir_level = -1;
90  m_root_dir_state = m_dir_state = nullptr;
91  m_maintain_dirstate = false;
92 }
93 
94 //----------------------------------------------------------------------------
95 
96 bool FsTraversal::cd_down(const std::string &dir_name)
97 {
98  static const char *trc_pfx = "FsTraversal::cd_down ";
99 
100  XrdOssDF *dhp = 0;
101  if (m_oss_at.Opendir(*m_dir_handle_stack.back(), dir_name.c_str(), m_env, dhp) != XrdOssOK) {
102  delete dhp;
103  TRACE(Error, trc_pfx << "could not opendir [" << m_current_path << dir_name << "], " << XrdSysE2T(errno));
104  return false;
105  }
106  m_dir_handle_stack.push_back(dhp);
107 
108  ++m_rel_dir_level;
109  m_current_path.append(dir_name);
110  m_current_path.append("/");
111 
113  m_dir_state = m_dir_state->find_dir(dir_name, true);
114 
116  return true;
117 }
118 
120 {
121  m_current_dirs.clear();
122  m_current_files.clear();
123 
124  m_dir_handle_stack.back()->Close();
125  delete m_dir_handle_stack.back();
126  m_dir_handle_stack.pop_back();
127 
130 
131  m_current_path.erase(m_current_path.find_last_of('/', m_current_path.size() - 2) + 1);
132  --m_rel_dir_level;
133 }
134 
135 //----------------------------------------------------------------------------
136 
138 {
139  static const char *trc_pfx = "FsTraversal::slurp_current_dir ";
140 
141  XrdOssDF &dh = *m_dir_handle_stack.back();
142  slurp_dir_ll(dh, m_rel_dir_level, m_current_path.c_str(), trc_pfx);
143 }
144 
145 //----------------------------------------------------------------------------
146 
147 void FsTraversal::slurp_dir_ll(XrdOssDF &dh, int dir_level, const char *path, const char *trc_pfx)
148 {
149  // Low-level implementation of slurp dir.
150 
151  char fname[256];
152  struct stat fstat;
153 
154  dh.StatRet(&fstat);
155 
156  const char *info_ext = Info::s_infoExtension;
157  const size_t info_ext_len = Info::s_infoExtensionLen;
158 
159  m_current_dirs.clear();
160  m_current_files.clear();
161 
162  while (true)
163  {
164  int rc = dh.Readdir(fname, 256);
165 
166  if (rc == -ENOENT)
167  {
168  TRACE_PURGE(" Skipping ENOENT dir entry [" << fname << "].");
169  continue;
170  }
171  if (rc != XrdOssOK)
172  {
173  TRACE(Error, trc_pfx << "Readdir error at " << path << ", err " << XrdSysE2T(-rc) << ".");
174  break;
175  }
176 
177  TRACE_PURGE(" Readdir [" << fname << "]");
178 
179  if (fname[0] == 0)
180  {
181  TRACE_PURGE(" Finished reading dir [" << path << "]. Break loop.");
182  break;
183  }
184  if (fname[0] == '.' && (fname[1] == 0 || (fname[1] == '.' && fname[2] == 0)))
185  {
186  TRACE_PURGE(" Skipping here or parent dir [" << fname << "]. Continue loop.");
187  continue;
188  }
189 
190  if (S_ISDIR(fstat.st_mode))
191  {
192  if (dir_level == 0 && m_protected_top_dirs.find(fname) != m_protected_top_dirs.end())
193  {
194  // Skip protected top-directories.
195  continue;
196  }
197  m_current_dirs.push_back(fname);
198  }
199  else
200  {
201  size_t fname_len = strlen(fname);
202 
203  if (fname_len > info_ext_len && strncmp(&fname[fname_len - info_ext_len], info_ext, info_ext_len) == 0)
204  {
205  // truncate ".cinfo" away
206  fname[fname_len - info_ext_len] = 0;
207  m_current_files[fname].set_cinfo(fstat);
208  }
209  else
210  {
211  m_current_files[fname].set_data(fstat);
212  }
213  }
214  }
215 }
#define XrdOssOK
Definition: XrdOss.hh:50
#define TRACE_PURGE(x)
int stat(const char *path, struct stat *buf)
int fstat(int fildes, struct stat *buf)
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
#define TRACE(act, x)
Definition: XrdTrace.hh:63
int Opendir(XrdOssDF &atDir, const char *path, XrdOucEnv &env, XrdOssDF *&ossDF)
Definition: XrdOssAt.cc:96
virtual int StatRet(struct stat *buff)
Definition: XrdOss.hh:107
virtual int Opendir(const char *path, XrdOucEnv &env)
Definition: XrdOss.hh:79
virtual int Readdir(char *buff, int blen)
Definition: XrdOss.hh:92
virtual int Close(long long *retsz=0)=0
virtual XrdOssDF * newDir(const char *tident)=0
XrdSysTrace * GetTrace()
Definition: XrdPfc.hh:283
static Cache & GetInstance()
Singleton access.
Definition: XrdPfc.cc:132
std::vector< std::string > m_current_dirs
std::vector< XrdOssDF * > m_dir_handle_stack
int close_delete(XrdOssDF *&ossDF)
void slurp_dir_ll(XrdOssDF &dh, int dir_level, const char *path, const char *trc_pfx)
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 * m_traceID
static const char * s_infoExtension
Definition: XrdPfcInfo.hh:309
static const size_t s_infoExtensionLen
Definition: XrdPfcInfo.hh:310
Definition: XrdPfc.hh:41
DirState * get_parent()
DirState * find_dir(const std::string &dir, bool create_subdirs)