XRootD
Loading...
Searching...
No Matches
XrdPfcDirState.cc
Go to the documentation of this file.
1#include "XrdPfcDirState.hh"
3
4#include <string>
5#include <cassert>
6
7using namespace XrdPfc;
8
9//----------------------------------------------------------------------------
11//----------------------------------------------------------------------------
14
15//----------------------------------------------------------------------------
18//----------------------------------------------------------------------------
23
24//----------------------------------------------------------------------------
28//----------------------------------------------------------------------------
29DirState::DirState(DirState *parent, const std::string &dname) :
30 DirStateBase(dname),
33{}
34
35//----------------------------------------------------------------------------
38//----------------------------------------------------------------------------
39DirState *DirState::create_child(const std::string &dir)
40{
41 std::pair<DsMap_i, bool> ir = m_subdirs.insert(std::make_pair(dir, DirState(this, dir)));
42 return &ir.first->second;
43}
44
45//----------------------------------------------------------------------------
48//----------------------------------------------------------------------------
49DirState *DirState::find_path_tok(PathTokenizer &pt, int pos, bool create_subdirs,
50 DirState **last_existing_dir)
51{
52 if (pos == pt.get_n_dirs())
53 return this;
54
55 DirState *ds = nullptr;
56
57 DsMap_i i = m_subdirs.find(pt.m_dirs[pos]);
58
59 if (i != m_subdirs.end())
60 {
61 ds = &i->second;
62 if (last_existing_dir)
63 *last_existing_dir = ds;
64 }
65 else if (create_subdirs)
66 {
67 ds = create_child(pt.m_dirs[pos]);
68 }
69
70 if (ds)
71 return ds->find_path_tok(pt, pos + 1, create_subdirs, last_existing_dir);
72
73 return nullptr;
74}
75
76//----------------------------------------------------------------------------
82DirState *DirState::find_path(const std::string &path, int max_depth, bool parse_as_lfn,
83 bool create_subdirs, DirState **last_existing_dir)
84{
85 PathTokenizer pt(path, max_depth, parse_as_lfn);
86
87 if (last_existing_dir)
88 *last_existing_dir = this;
89
90 return find_path_tok(pt, 0, create_subdirs, last_existing_dir);
91}
92
93//----------------------------------------------------------------------------
98DirState *DirState::find_dir(const std::string &dir,
99 bool create_subdirs)
100{
101 DsMap_i i = m_subdirs.find(dir);
102
103 if (i != m_subdirs.end())
104 return &i->second;
105
106 if (create_subdirs)
107 return create_child(dir);
108
109 return nullptr;
110}
111
112//----------------------------------------------------------------------------
116int DirState::generate_dir_path(std::string &result)
117{
118 int n_chars = 0;
119 if (m_parent) {
120 n_chars += m_parent->generate_dir_path(result) + 1 + m_dir_name.length();
121 result += '/';
122 result += m_dir_name;
123 }
124 return n_chars;
125}
126
127//----------------------------------------------------------------------------
130//----------------------------------------------------------------------------
132{
133 DirUsage &here = m_here_usage;
135
136 for (auto & [name, daughter] : m_subdirs)
137 {
138 daughter.upward_propagate_initial_scan_usages();
139
140 DirUsage &dhere = daughter.m_here_usage;
141 DirUsage &dsubdirs = daughter.m_recursive_subdir_usage;
142
143 here.m_NDirectories += 1;
144
145 subdirs.m_StBlocks += dhere.m_StBlocks + dsubdirs.m_StBlocks;
146 subdirs.m_NFiles += dhere.m_NFiles + dsubdirs.m_NFiles;
147 subdirs.m_NDirectories += dhere.m_NDirectories + dsubdirs.m_NDirectories;
148 }
149}
150
151//----------------------------------------------------------------------------
157
158void DirState::update_stats_and_usages(bool purge_empty_dirs, unlink_func unlink_foo)
159{
160 // Hmmh.
161 DsMap_i i = m_subdirs.begin();
162 while (i != m_subdirs.end())
163 {
164 DirState &sub_ds = i->second;
165
166 sub_ds.update_stats_and_usages(purge_empty_dirs, unlink_foo);
167
170 // nothing to do for m_here_stats.
171
172 // Join timestamps from daugters and their sub-daugter trees.
173 m_recursive_subdir_usage.update_last_times(sub_ds.m_recursive_subdir_usage);
174 m_recursive_subdir_usage.update_last_times(sub_ds.m_here_usage);
175
176 // Clean empty leaf directories. Only do one level at a time.
177 // Note that root will never get purged.
178 bool increment_iter = true;
179 if (purge_empty_dirs && sub_ds.m_here_stats.m_NDirectoriesRemoved == 0 &&
180 sub_ds.m_here_usage.m_NDirectories == 0 && sub_ds.m_here_usage.m_NFiles == 0)
181 {
182 assert(sub_ds.m_subdirs.empty());
183
184 std::string dir_path;
185 dir_path.reserve(1024);
186 sub_ds.generate_dir_path(dir_path);
187
188 if (unlink_foo(dir_path) == 0) {
189 DsMap_i j = i++;
190 m_subdirs.erase(j);
191 ++m_here_stats.m_NDirectoriesRemoved;
192 increment_iter = false;
193 }
194 }
195 if (increment_iter)
196 ++i;
197 }
198
199 // Apply current deltas to sshot_stats (and, if eventually needed, purge_stats).
202
203 // Apply deltas / stats to usages.
204 m_here_usage.update_from_stats(m_here_stats);
206
207 // Once we have m_report_stats and m_purge_stats, update them here.
208}
209
210//----------------------------------------------------------------------------
213//----------------------------------------------------------------------------
215{
216 for (DsMap_i i = m_subdirs.begin(); i != m_subdirs.end(); ++i)
217 {
218 i->second.reset_stats();
219 }
220 m_here_stats.Reset();
222}
223
225{
226 for (DsMap_i i = m_subdirs.begin(); i != m_subdirs.end(); ++i)
227 {
228 i->second.reset_sshot_stats();
229 }
230 m_sshot_stats.Reset();
231}
232
233int DirState::count_dirs_to_level(int max_depth) const
234{
235 int n_dirs = 1;
236 if (m_depth < max_depth)
237 {
238 for (auto & [name, ds] : m_subdirs)
239 {
240 n_dirs += ds.count_dirs_to_level(max_depth);
241 }
242 }
243 return n_dirs;
244}
245
246//----------------------------------------------------------------------------
249//----------------------------------------------------------------------------
250void DirState::dump_recursively(const char *name, int max_depth) const
251{
252 printf("%*d %s usage_here=%lld usage_sub=%lld usage_total=%lld num_ios=%d duration=%d b_hit=%lld b_miss=%lld b_byps=%lld b_wrtn=%lld\n",
253 2 + 2 * m_depth, m_depth, name,
254 512 * m_here_usage.m_StBlocks, 512 * m_recursive_subdir_usage.m_StBlocks,
255 512 * (m_here_usage.m_StBlocks + m_recursive_subdir_usage.m_StBlocks),
256 // XXXXX here_stats or sum up? or both?
257 m_here_stats.m_NumIos, m_here_stats.m_Duration,
258 m_here_stats.m_BytesHit, m_here_stats.m_BytesMissed, m_here_stats.m_BytesBypassed,
259 m_here_stats.m_BytesWritten);
260
261 if (m_depth < max_depth)
262 {
263 for (auto & [name, ds] : m_subdirs)
264 {
265 ds.dump_recursively(name.c_str(), max_depth);
266 }
267 }
268}
269
270
271//==============================================================================
272// DataFsState
273//==============================================================================
274
275void DataFsState::update_stats_and_usages(time_t last_update, bool purge_empty_dirs, unlink_func unlink_foo)
276{
277 m_root.update_stats_and_usages(purge_empty_dirs, unlink_foo);
278 m_usage_update_time = last_update;
279}
280
281void DataFsState::reset_stats(time_t last_update)
282{
283 m_root.reset_stats();
284 m_stats_reset_time = last_update;
285}
286
287void DataFsState::reset_sshot_stats(time_t last_update)
288{
289 m_root.reset_sshot_stats();
290 m_sshot_stats_reset_time = last_update;
291}
292
293void DataFsState::dump_recursively(int max_depth) const
294{
295 if (max_depth < 0)
296 max_depth = 4096;
297
298 printf("DataFsState::dump_recursively delta_t = %lld, max_dump_depth = %d\n",
299 (long long)(m_usage_update_time - m_stats_reset_time), max_depth);
300
301 m_root.dump_recursively("root", max_depth);
302}
static void parent()
std::function< int(const std::string &)> unlink_func
void reset_stats(time_t last_update)
void dump_recursively(int max_depth) const
void update_stats_and_usages(time_t last_update, bool purge_empty_dirs, unlink_func unlink_foo)
void reset_sshot_stats(time_t last_update)
DirUsage m_recursive_subdir_usage
DsMap_t::iterator DsMap_i
int count_dirs_to_level(int max_depth) const
DirState * create_child(const std::string &dir)
DirStats m_recursive_subdir_stats
DirState * find_dir(const std::string &dir, bool create_subdirs)
int generate_dir_path(std::string &result)
DirState()
Constructor.
DirState * find_path_tok(PathTokenizer &pt, int pos, bool create_subdirs, DirState **last_existing_dir=nullptr)
DirState * find_path(const std::string &path, int max_depth, bool parse_as_lfn, bool create_subdirs, DirState **last_existing_dir=nullptr)
void dump_recursively(const char *name, int max_depth) const
void upward_propagate_initial_scan_usages()
void update_stats_and_usages(bool purge_empty_dirs, unlink_func unlink_foo)
std::vector< const char * > m_dirs