ATLAS Offline Software
Loading...
Searching...
No Matches
SH::ScanDir Struct Reference

the class used for scanning local directories and file servers for samples More...

#include <ScanDir.h>

Collaboration diagram for SH::ScanDir:

Public Member Functions

 ScanDir ()
 standard constructor
const ScanDirscan (SampleHandler &sh, const std::string &dir) const
 scan the given directory and put the created samples into the sample handler
const ScanDirscanEOS (SampleHandler &sh, const std::string &eosDir) const
 scan the given directory in EOS and put the created samples into the sample handler
const ScanDirscan (SampleHandler &sh, DiskList &list) const
 scan the given directory and put the created samples into the sample handler
ScanDirsampleDepth (int val_sampleDepth)
 the index of the file hierarchy at which we gather the sample name.
ScanDirabsSampleDepth (int val_absSampleDepth)
 the index of the file hierarchy at which we gather the sample name.
ScanDirsampleName (const std::string &val_sampleName)
 a single sample name into which all found files should be placed.
ScanDirminDepth (std::size_t val_minDepth)
 the minimum depth for files to make it into the sample
ScanDirmaxDepth (std::size_t val_maxDepth)
 the maximum depth for files to make it into the sample
ScanDirfilePattern (const std::string &val_filePattern)
 the pattern for files to be accepted
ScanDirfileRegex (const std::string &val_fileRegex)
 the regular expression for files to be accepted
ScanDirdirectoryPattern (const std::string &val_directoryPattern)
 the pattern for directories to be visited
ScanDirdirectoryRegex (const std::string &val_directoryRegex)
 the regular expression for directories to be visited
ScanDirsamplePattern (const std::string &val_samplePattern)
 the pattern for samples to be accepted
ScanDirsamplePostfix (const std::string &val_samplePostfix)
 the pattern for the postfix to be stripped from the sampleName
ScanDirsampleRename (const std::string &pattern, const std::string &name)
 rename any sample matching pattern to name
ScanDirextraNameComponent (int val_relSampleDepth)
 attach an extra name component to the sample based on a second component of the path

Private Types

using SampleRenameIter = std::vector<std::pair<std::regex,std::string> >::const_iterator
 the list of entries from sampleRename

Private Member Functions

void recurse (std::map< std::string, std::shared_ptr< Sample > > &samples, DiskList &list, const std::vector< std::string > &hierarchy) const
 perform the recursive scanning of the directory tree
void addSampleFile (std::map< std::string, std::shared_ptr< Sample > > &samples, const std::vector< std::string > &hierarchy, const std::string &path) const
 add the given file to the sample based on the hierarchy, creating the sample if necessary
std::string findPathComponent (const std::vector< std::string > &hierarchy, int absSampleDepth, int relSampleDepth) const
 find the path component at the given depth

Private Attributes

int m_relSampleDepth
 if this is negative it is the depth at which we take the sample name, counting from the end
int m_absSampleDepth
 if m_relSampleDepth is not negative, it is the depth at which we take the sample name, counting from the first directory scanned
std::string m_sampleName
 the value set by sampleName
std::size_t m_minDepth
 the value set by minDepth
std::size_t m_maxDepth
 the value set by maxDepth
std::regex m_filePattern
 the value set by filePattern, converted to a regular expression
std::regex m_directoryPattern
 the value set by directoryPattern, converted to a regular expression
std::regex m_samplePattern
 the value set by samplePattern, converted to a regular expression
std::regex m_samplePostfix
 the value set by samplePostfix, converted to a regular expression
bool m_samplePostfixEmpty
 whether samplePostfix has been set to the empty string
std::vector< std::pair< std::regex, std::string > > m_sampleRename
int m_extraNameComponent
 the depth set with extraNameComponent, or 0 otherwise

Detailed Description

the class used for scanning local directories and file servers for samples

Originally these was a series of stand-alone function calls, but people kept asking for more and more options, making it unwieldy to call and to maintain. Instead we now have a single class containing all the possible parameters, which makes it easier to configure and extend.

The member functions all return *this, so that usage like this is possible:

.filePattern ("*.root*")
.scan (sh, "/data");
ScanDir()
standard constructor
Definition ScanDir.cxx:33

Definition at line 38 of file ScanDir.h.

Member Typedef Documentation

◆ SampleRenameIter

using SH::ScanDir::SampleRenameIter = std::vector<std::pair<std::regex,std::string> >::const_iterator
private

the list of entries from sampleRename

Definition at line 211 of file ScanDir.h.

Constructor & Destructor Documentation

◆ ScanDir()

SH::ScanDir::ScanDir ( )

standard constructor

Guarantee
strong
Failures
out of memory I

Definition at line 32 of file ScanDir.cxx.

35 m_minDepth (0), m_maxDepth (-1),
42 {}
std::string glob_to_regexp(std::string_view glob)
returns: a string that is the regular expression equivalent of the given glob expression guarantee: s...
std::regex m_directoryPattern
the value set by directoryPattern, converted to a regular expression
Definition ScanDir.h:192
bool m_samplePostfixEmpty
whether samplePostfix has been set to the empty string
Definition ScanDir.h:207
std::regex m_filePattern
the value set by filePattern, converted to a regular expression
Definition ScanDir.h:187
int m_relSampleDepth
if this is negative it is the depth at which we take the sample name, counting from the end
Definition ScanDir.h:164
int m_extraNameComponent
the depth set with extraNameComponent, or 0 otherwise
Definition ScanDir.h:216
int m_absSampleDepth
if m_relSampleDepth is not negative, it is the depth at which we take the sample name,...
Definition ScanDir.h:170
std::size_t m_maxDepth
the value set by maxDepth
Definition ScanDir.h:182
std::regex m_samplePattern
the value set by samplePattern, converted to a regular expression
Definition ScanDir.h:197
std::size_t m_minDepth
the value set by minDepth
Definition ScanDir.h:178
std::regex m_samplePostfix
the value set by samplePostfix, converted to a regular expression
Definition ScanDir.h:202

Member Function Documentation

◆ absSampleDepth()

ScanDir & SH::ScanDir::absSampleDepth ( int val_absSampleDepth)

the index of the file hierarchy at which we gather the sample name.

this differs from sampleDepth in that negative numbers count up in the directory hierarchy from the top of where we scan, while sampleDepth starts counting from the back if the number is negative.

Definition at line 56 of file ScanDir.cxx.

58 {
60 m_absSampleDepth = val_absSampleDepth;
61 return *this;
62 }

◆ addSampleFile()

void SH::ScanDir::addSampleFile ( std::map< std::string, std::shared_ptr< Sample > > & samples,
const std::vector< std::string > & hierarchy,
const std::string & path ) const
private

add the given file to the sample based on the hierarchy, creating the sample if necessary

Guarantee
basic
Failures
out of memory II

Definition at line 259 of file ScanDir.cxx.

263 {
264 std::string sampleName;
265
266 if (!m_sampleName.empty())
267 {
269 } else
270 {
273 if (sampleName.empty())
274 return;
275
277 {
278 bool done = false;
279 for (std::size_t iter = 0, end = sampleName.size();
280 iter != end && !done; ++ iter)
281 {
282 if (RCU::match_expr (m_samplePostfix, sampleName.substr (iter)))
283 {
284 if (iter == 0)
285 throw std::runtime_error ("sample name matches entire postfix pattern: \"" + sampleName + "\"");
286 sampleName.resize (iter);
287 done = true;
288 }
289 }
290 }
291
292 if (m_extraNameComponent != 0)
293 {
294 std::string component = findPathComponent
296 if (component.empty())
297 return;
298 sampleName += "_" + component;
299 }
300
302 return;
303
304 {
305 bool done = false;
306 for (SampleRenameIter iter = m_sampleRename.begin(),
307 end = m_sampleRename.end(); !done && iter != end; ++ iter)
308 {
309 if (RCU::match_expr (iter->first, sampleName))
310 {
311 sampleName = iter->second;
312 done = true;
313 }
314 }
315 }
316 }
317
318 auto iter = samples.find (sampleName);
319 if (iter == samples.end())
320 {
321 auto sample = std::make_shared<SampleLocal> (sampleName);
322 samples[sampleName] = sample;
323 iter = samples.find (sampleName);
324 }
325 SampleLocal *sample = dynamic_cast<SampleLocal*>(iter->second.get());
326 RCU_ASSERT (sample != 0);
327 sample->add (path);
328 }
#define RCU_ASSERT(x)
Definition Assert.h:210
bool match_expr(const std::regex &expr, std::string_view str)
returns: whether we can match the entire string with the regular expression guarantee: strong failure...
std::vector< std::pair< std::regex, std::string > >::const_iterator SampleRenameIter
the list of entries from sampleRename
Definition ScanDir.h:211
ScanDir & sampleName(const std::string &val_sampleName)
a single sample name into which all found files should be placed.
Definition ScanDir.cxx:67
std::string m_sampleName
the value set by sampleName
Definition ScanDir.h:174
std::string findPathComponent(const std::vector< std::string > &hierarchy, int absSampleDepth, int relSampleDepth) const
find the path component at the given depth
Definition ScanDir.cxx:333
std::vector< std::pair< std::regex, std::string > > m_sampleRename
Definition ScanDir.h:212

◆ directoryPattern()

ScanDir & SH::ScanDir::directoryPattern ( const std::string & val_directoryPattern)

the pattern for directories to be visited

See also
directoryPatternRegex

Definition at line 111 of file ScanDir.cxx.

113 {
114 m_directoryPattern = RCU::glob_to_regexp (val_directoryPattern);
115 return *this;
116 }

◆ directoryRegex()

ScanDir & SH::ScanDir::directoryRegex ( const std::string & val_directoryRegex)

the regular expression for directories to be visited

See also
directoryPattern

Definition at line 120 of file ScanDir.cxx.

122 {
123 m_directoryPattern = val_directoryRegex;
124 return *this;
125 }

◆ extraNameComponent()

ScanDir & SH::ScanDir::extraNameComponent ( int val_relSampleDepth)

attach an extra name component to the sample based on a second component of the path

Precondition
val_relSampleDepth != 0

Definition at line 157 of file ScanDir.cxx.

159 {
160 RCU_REQUIRE (val_relSampleDepth != 0);
161 m_extraNameComponent = val_relSampleDepth;
162 return *this;
163 }
#define RCU_REQUIRE(x)
Definition Assert.h:196

◆ filePattern()

ScanDir & SH::ScanDir::filePattern ( const std::string & val_filePattern)

the pattern for files to be accepted

See also
filePatternRegex

Definition at line 93 of file ScanDir.cxx.

95 {
96 m_filePattern = RCU::glob_to_regexp (val_filePattern);
97 return *this;
98 }

◆ fileRegex()

ScanDir & SH::ScanDir::fileRegex ( const std::string & val_fileRegex)

the regular expression for files to be accepted

See also
filePattern

Definition at line 102 of file ScanDir.cxx.

104 {
105 m_filePattern = val_fileRegex;
106 return *this;
107 }

◆ findPathComponent()

std::string SH::ScanDir::findPathComponent ( const std::vector< std::string > & hierarchy,
int absSampleDepth,
int relSampleDepth ) const
private

find the path component at the given depth

Returns
the path componenent, or NULL if it doesn't exist
Guarantee
strong
Failures
out of memory II

Definition at line 332 of file ScanDir.cxx.

336 {
337 std::string sampleName;
338
339 int myindex = absSampleDepth+1;
340 if (relSampleDepth < 0)
341 myindex = relSampleDepth + hierarchy.size();
342 // rationale: only apply the upper-bound check for a non-negative
343 // index; a negative index (e.g. absSampleDepth <= -2) is meant to
344 // climb up the hierarchy in the else branch below, and converting
345 // it to std::size_t here would wrap to SIZE_MAX and drop every
346 // file.
347 if (myindex >= 0 && std::size_t (myindex) >= hierarchy.size())
348 return sampleName;
349 if (myindex > 0)
350 {
351 sampleName = hierarchy[myindex];
352 } else
353 {
354 sampleName = hierarchy[0];
355 while (sampleName.empty() ||
356 sampleName[sampleName.size()-1] == '/' ||
357 myindex < 0)
358 {
359 while (!sampleName.empty() && sampleName[sampleName.size()-1] == '/')
360 sampleName.pop_back();
361 if (sampleName.empty())
362 return sampleName;
363 if (myindex < 0)
364 {
365 std::string::size_type split = sampleName.rfind ('/');
366 if (split == std::string::npos)
367 {
368 sampleName.clear ();
369 return sampleName;
370 }
371 sampleName.resize (split);
372 ++ myindex;
373 }
374 if (sampleName.empty())
375 return sampleName;
376 }
377 std::string::size_type split = sampleName.rfind ('/');
378 if (split != std::string::npos)
379 sampleName = sampleName.substr (split + 1);
380 }
381 return sampleName;
382 }
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179
ScanDir & absSampleDepth(int val_absSampleDepth)
the index of the file hierarchy at which we gather the sample name.
Definition ScanDir.cxx:57

◆ maxDepth()

ScanDir & SH::ScanDir::maxDepth ( std::size_t val_maxDepth)

the maximum depth for files to make it into the sample

Definition at line 84 of file ScanDir.cxx.

86 {
87 m_maxDepth = val_maxDepth;
88 return *this;
89 }

◆ minDepth()

ScanDir & SH::ScanDir::minDepth ( std::size_t val_minDepth)

the minimum depth for files to make it into the sample

Definition at line 75 of file ScanDir.cxx.

77 {
78 m_minDepth = val_minDepth;
79 return *this;
80 }

◆ recurse()

void SH::ScanDir::recurse ( std::map< std::string, std::shared_ptr< Sample > > & samples,
DiskList & list,
const std::vector< std::string > & hierarchy ) const
private

perform the recursive scanning of the directory tree

Guarantee
basic
Failures
out of memory III
i/o errors

Definition at line 207 of file ScanDir.cxx.

211 {
212 using namespace msgScanDir;
213
214 ANA_MSG_DEBUG ("scanning directory: " << list.dirname());
215 while (list.next())
216 {
217 std::unique_ptr<DiskList> sublist (list.openDirUnique());
218
219 if (sublist.get() != 0)
220 {
221 if (!RCU::match_expr (m_directoryPattern, list.fileName()))
222 {
223 ANA_MSG_DEBUG ("directory does not match pattern, skipping directory " << list.path());
224 } else if (hierarchy.size() > m_maxDepth)
225 {
226 ANA_MSG_DEBUG ("maxDepth exceeded, skipping directory " << list.path());
227 } else if (hierarchy.size() >= 100)
228 {
229 // rationale: a hard sanity cap so that a directory symlink
230 // loop (or a link to an ancestor) does not recurse forever
231 // when the user has not set an explicit maxDepth.
232 ANA_MSG_WARNING ("directory nesting exceeds 100 levels, not descending further (possible symlink loop): " << list.path());
233 } else
234 {
235 ANA_MSG_DEBUG ("descending into directory " << list.path());
236 std::vector<std::string> subhierarchy = hierarchy;
237 subhierarchy.push_back (list.fileName());
238 recurse (samples, *sublist, subhierarchy);
239 }
240 } else
241 {
242 if (hierarchy.size() > m_minDepth &&
243 RCU::match_expr (m_filePattern, list.fileName()))
244 {
245 ANA_MSG_DEBUG ("adding file " << list.path());
246 std::vector<std::string> subhierarchy = hierarchy;
247 subhierarchy.push_back (list.fileName());
248 addSampleFile (samples, subhierarchy, list.path());
249 } else
250 {
251 ANA_MSG_DEBUG ("skipping file " << list.path());
252 }
253 }
254 }
255 }
#define ANA_MSG_WARNING(xmsg)
Macro printing warning messages.
#define ANA_MSG_DEBUG(xmsg)
Macro printing debug messages.
list(name, path='/')
Definition histSizes.py:38
void recurse(std::map< std::string, std::shared_ptr< Sample > > &samples, DiskList &list, const std::vector< std::string > &hierarchy) const
perform the recursive scanning of the directory tree
Definition ScanDir.cxx:208
void addSampleFile(std::map< std::string, std::shared_ptr< Sample > > &samples, const std::vector< std::string > &hierarchy, const std::string &path) const
add the given file to the sample based on the hierarchy, creating the sample if necessary
Definition ScanDir.cxx:260

◆ sampleDepth()

ScanDir & SH::ScanDir::sampleDepth ( int val_sampleDepth)

the index of the file hierarchy at which we gather the sample name.

this is positive when it starts counting from the top, and negative when it starts from the back, i.e. -1 uses the file name, 0 denotes the directory inside the top level directory

Definition at line 46 of file ScanDir.cxx.

48 {
49 m_relSampleDepth = val_sampleDepth;
50 m_absSampleDepth = val_sampleDepth;
51 return *this;
52 }

◆ sampleName()

ScanDir & SH::ScanDir::sampleName ( const std::string & val_sampleName)

a single sample name into which all found files should be placed.

if set, this overrides all other naming methods.

Definition at line 66 of file ScanDir.cxx.

68 {
69 m_sampleName = val_sampleName;
70 return *this;
71 }

◆ samplePattern()

ScanDir & SH::ScanDir::samplePattern ( const std::string & val_samplePattern)

the pattern for samples to be accepted

Definition at line 129 of file ScanDir.cxx.

131 {
132 m_samplePattern = RCU::glob_to_regexp (val_samplePattern);
133 return *this;
134 }

◆ samplePostfix()

ScanDir & SH::ScanDir::samplePostfix ( const std::string & val_samplePostfix)

the pattern for the postfix to be stripped from the sampleName

Definition at line 138 of file ScanDir.cxx.

140 {
141 m_samplePostfix = RCU::glob_to_regexp (val_samplePostfix);
142 m_samplePostfixEmpty = val_samplePostfix.empty();
143 return *this;
144 }

◆ sampleRename()

ScanDir & SH::ScanDir::sampleRename ( const std::string & pattern,
const std::string & name )

rename any sample matching pattern to name

Definition at line 148 of file ScanDir.cxx.

150 {
151 m_sampleRename.push_back (std::pair<std::regex,std::string> (std::regex (RCU::glob_to_regexp (pattern)), name));
152 return *this;
153 }

◆ scan() [1/2]

const ScanDir & SH::ScanDir::scan ( SampleHandler & sh,
const std::string & dir ) const

scan the given directory and put the created samples into the sample handler

Returns
*this
Guarantee
basic
Failures
out of memory III
i/o errors
duplicate samples

Definition at line 167 of file ScanDir.cxx.

169 {
170 DiskListLocal list (dir);
171 scan (sh, list);
172 return *this;
173 }
const ScanDir & scan(SampleHandler &sh, const std::string &dir) const
scan the given directory and put the created samples into the sample handler
Definition ScanDir.cxx:168

◆ scan() [2/2]

const ScanDir & SH::ScanDir::scan ( SampleHandler & sh,
DiskList & list ) const

scan the given directory and put the created samples into the sample handler

Returns
*this
Guarantee
basic
Failures
out of memory III
i/o errors
duplicate samples

Definition at line 187 of file ScanDir.cxx.

189 {
190 std::vector<std::string> hierarchy;
191 hierarchy.push_back (list.dirname());
192
193 std::map<std::string,std::shared_ptr<Sample>> samples;
194 recurse (samples, list, hierarchy);
195 for (const auto& sample : samples)
196 {
197 if (sample.second != nullptr)
198 {
199 sh.add (sample.second);
200 }
201 }
202 return *this;
203 }

◆ scanEOS()

const ScanDir & SH::ScanDir::scanEOS ( SampleHandler & sh,
const std::string & eosDir ) const

scan the given directory in EOS and put the created samples into the sample handler

Returns
*this
Guarantee
basic
Failures
out of memory III
i/o errors
duplicate samples

Definition at line 177 of file ScanDir.cxx.

179 {
180 DiskListEOS list (eosDir);
181 scan (sh, list);
182 return *this;
183 }

Member Data Documentation

◆ m_absSampleDepth

int SH::ScanDir::m_absSampleDepth
private

if m_relSampleDepth is not negative, it is the depth at which we take the sample name, counting from the first directory scanned

Definition at line 170 of file ScanDir.h.

◆ m_directoryPattern

std::regex SH::ScanDir::m_directoryPattern
private

the value set by directoryPattern, converted to a regular expression

Definition at line 192 of file ScanDir.h.

◆ m_extraNameComponent

int SH::ScanDir::m_extraNameComponent
private

the depth set with extraNameComponent, or 0 otherwise

Definition at line 216 of file ScanDir.h.

◆ m_filePattern

std::regex SH::ScanDir::m_filePattern
private

the value set by filePattern, converted to a regular expression

Definition at line 187 of file ScanDir.h.

◆ m_maxDepth

std::size_t SH::ScanDir::m_maxDepth
private

the value set by maxDepth

Definition at line 182 of file ScanDir.h.

◆ m_minDepth

std::size_t SH::ScanDir::m_minDepth
private

the value set by minDepth

Definition at line 178 of file ScanDir.h.

◆ m_relSampleDepth

int SH::ScanDir::m_relSampleDepth
private

if this is negative it is the depth at which we take the sample name, counting from the end

Definition at line 164 of file ScanDir.h.

◆ m_sampleName

std::string SH::ScanDir::m_sampleName
private

the value set by sampleName

Definition at line 174 of file ScanDir.h.

◆ m_samplePattern

std::regex SH::ScanDir::m_samplePattern
private

the value set by samplePattern, converted to a regular expression

Definition at line 197 of file ScanDir.h.

◆ m_samplePostfix

std::regex SH::ScanDir::m_samplePostfix
private

the value set by samplePostfix, converted to a regular expression

Definition at line 202 of file ScanDir.h.

◆ m_samplePostfixEmpty

bool SH::ScanDir::m_samplePostfixEmpty
private

whether samplePostfix has been set to the empty string

Definition at line 207 of file ScanDir.h.

◆ m_sampleRename

std::vector<std::pair<std::regex,std::string> > SH::ScanDir::m_sampleRename
private

Definition at line 212 of file ScanDir.h.


The documentation for this struct was generated from the following files: