ATLAS Offline Software
Public Member Functions | List of all members
EL::Detail::SubmitDirManager Class Referencefinal

a Manager to handle the submission directory itself More...

#include <SubmitDirManager.h>

Inheritance diagram for EL::Detail::SubmitDirManager:
Collaboration diagram for EL::Detail::SubmitDirManager:

Public Member Functions

virtual std::pair< Detail::ManagerOrder, std::string > getManagerOrder () const noexcept override
 get the order/name of this manager More...
 
virtual ::StatusCode doManagerStep (Detail::ManagerData &data) const override
 do whatever needs to be done for the given submission step More...
 

Detailed Description

a Manager to handle the submission directory itself

Definition at line 22 of file SubmitDirManager.h.

Member Function Documentation

◆ doManagerStep()

StatusCode EL::Detail::SubmitDirManager::doManagerStep ( Detail::ManagerData data) const
overridevirtual

do whatever needs to be done for the given submission step

Guarantee
basic
Failures
job configuration errors
driver errors

Implements EL::Detail::Manager.

Definition at line 68 of file SubmitDirManager.cxx.

70  {
71  switch (data.step)
72  {
74  {
75  std::smatch match;
76 
77  // make sure directory is absolute
78  if (data.submitDir[0] != '/')
79  data.submitDir = gSystem->WorkingDirectory () + ("/" + data.submitDir);
80 
81  // make sure we don't end in "/", "/." or "/.."
82  const std::regex identityEndExpr {"(/$)|(/\\.$)"};
83  while (std::regex_search (data.submitDir, match, identityEndExpr))
84  data.submitDir.replace (match.position(0), match.length(0), "");
85  const std::regex relativeEndExpr {"/\\.\\.$"};
86  if (std::regex_search (data.submitDir, match, relativeEndExpr))
87  {
88  ANA_MSG_ERROR ("submit directory can not end in \"..\": " + data.submitDir);
89  return ::StatusCode::FAILURE;
90  }
91 
92  // make sure we don't include any '..' in our path. this is
93  // mainly relevant for Ganga Tasks which may crash
94  // otherwise. this specifically doesn't use any of the
95  // "normal" regularization functions because those resolve
96  // symlinks as well, and depending on the driver we may not
97  // want that to happen.
98  const std::regex identityExpr {"(/\\./)|(//)|(^/\\.\\./)"};
99  while (std::regex_search (data.submitDir, match, identityExpr))
100  data.submitDir.replace (match.position(0), match.length(0), "/");
101  const std::regex relativeExpr {"/[^/]+/\\.\\./"};
102  while (std::regex_search (data.submitDir, match, relativeExpr))
103  data.submitDir.replace (match.position(0), match.length(0), "/");
104 
105  if (data.submitDir.find ("/pnfs/") == 0)
106  {
107  ANA_MSG_ERROR ("can not place submit directory on pnfs: " + data.submitDir);
108  return ::StatusCode::FAILURE;
109  }
110 
111  ANA_MSG_DEBUG ("changed submit-dir to " << data.submitDir);
112  }
113  break;
114 
116  {
117  std::string mode = data.options.castString (Job::optSubmitDirMode);
118  if (!mode.empty())
119  {
120  if (mode == "no-clobber")
121  data.submitDirMode = SubmitDirMode::NO_CLOBBER;
122  else if (mode == "overwrite")
123  data.submitDirMode = SubmitDirMode::OVERWRITE;
124  else if (mode == "unique")
125  data.submitDirMode = SubmitDirMode::UNIQUE;
126  else if (mode == "unique-link")
127  data.submitDirMode = SubmitDirMode::UNIQUE_LINK;
128  else
129  {
130  ANA_MSG_ERROR ("unknown submit-dir mode: " << mode);
131  ANA_MSG_ERROR ("known modes: no-clobber, overwrite, unique, unique-link");
132  return ::StatusCode::FAILURE;
133  }
134  }
135 
136  if (data.options.castBool (Job::optRemoveSubmitDir, false))
137  {
138  if (!mode.empty())
139  {
140  ANA_MSG_ERROR ("can't specify both an explicit submit-dir mode and optRemoveSubmitDir");
141  return ::StatusCode::FAILURE;
142  }
143  data.submitDirMode = SubmitDirMode::OVERWRITE;
144  }
145  }
146  break;
147 
149  {
150  ANA_MSG_DEBUG ("using submit-dir mode: " << unsigned (data.submitDirMode));
151 
152  bool success {false};
153  unsigned tries {0};
154  std::string submitDir;
155  std::size_t hash {0};
156  while (success == false && tries < 10)
157  {
158  tries += 1;
159 
160  switch (data.submitDirMode)
161  {
164  submitDir = data.submitDir;
165  break;
166 
169  {
170  timeval tv;
171  tm tvSplit;
172  if (gettimeofday (&tv, nullptr) == -1 ||
173  localtime_r (&tv.tv_sec, &tvSplit) == nullptr)
174  {
175  reportErrno ();
176  ANA_MSG_ERROR ("failed to get time of day???");
177  return ::StatusCode::FAILURE;
178  }
179  const std::string uniqueDateFormat {
180  data.options.castString (Job::optUniqueDateFormat,
181  "-%Y-%m-%d-%H%M-")};
182  char timeString [160];
183  strftime (timeString, sizeof (timeString),
184  uniqueDateFormat.c_str(), &tvSplit);
185 
186  // make a hash value and reduce it to 16 bits
187  boost::hash_combine (hash, std::hash<pid_t>() (getpid()));
188  boost::hash_combine (hash, std::hash<suseconds_t>() (tv.tv_usec));
189  std::size_t hash16 {hash};
190  while (hash16 > 0xffff)
191  hash16 = (hash16&0xffff) ^ (hash16 >> 16);
192 
193  // we are appending both a date and a unique hash
194  // here, in most cases the date should be sufficient
195  // to make it unique, but for unit tests a lot of jobs
196  // may be submitted in rapid succcession, so having
197  // some random suffix should help avoid clashes. the
198  // date is purposely put first because in some cases
199  // that can provide a useful ordering of output
200  // directories, i.e. the latest results will be listed
201  // last.
202  submitDir = data.submitDir + timeString +
203  std::format("{:04x}", hash16);
204  ANA_MSG_DEBUG ("unique submit-dir: " << submitDir);
205  }
206  break;
207  }
208 
209  if (::mkdir (submitDir.c_str(), 0777) == 0)
210  {
211  success = true;
212  } else
213  {
214  const int myerrno {errno};
215  if (myerrno == EEXIST)
216  {
217  switch (data.submitDirMode)
218  {
220  ANA_MSG_ERROR ("cowardly refusing to overwrite " << submitDir);
221  ANA_MSG_ERROR ("change the name or remove file/directory already there");
222  return ::StatusCode::FAILURE;
224  if (tries > 1)
225  {
226  ANA_MSG_ERROR ("failed to remove directory " << submitDir);
227  ANA_MSG_ERROR ("please try to remove it manually");
228  return ::StatusCode::FAILURE;
229  }
230  ANA_MSG_DEBUG ("removing directory " << submitDir);
231  gSystem->Exec (("rm -rf " + submitDir).c_str());
232  break;
235  // just pass through, try again with a new directory
236  // name next time
237  break;
238  }
239  } else
240  {
241  reportErrno (myerrno);
242  ANA_MSG_ERROR ("failed to create directory: " << submitDir);
243  return ::StatusCode::FAILURE;
244  }
245  }
246  }
247 
248  if (success)
249  {
250  ANA_MSG_INFO ("created submission directory " + submitDir);
251  switch (data.submitDirMode)
252  {
256  // no-op
257  break;
258 
260  {
261  if (unlink (data.submitDir.c_str()) == -1 && errno != ENOENT)
262  {
263  reportErrno ();
264  ANA_MSG_ERROR ("failed to remove: " << data.submitDir);
265  return ::StatusCode::FAILURE;
266  }
267 
268  std::string file = submitDir.substr (submitDir.rfind ('/')+1);
269  if (symlink (file.c_str(), data.submitDir.c_str()) == -1)
270  {
271  reportErrno ();
272  ANA_MSG_ERROR ("failed to create symlink at: " << data.submitDir);
273  return ::StatusCode::FAILURE;
274  }
275  ANA_MSG_INFO ("created sym-link at: " << data.submitDir);
276  }
277  break;
278  }
279  data.submitDir = submitDir;
280  } else
281  {
282  ANA_MSG_ERROR ("tried " << tries << " times to create directory and failed: " << data.submitDir);
283  ANA_MSG_ERROR ("try removing existing directory manually");
284  return ::StatusCode::FAILURE;
285  }
286  }
287  break;
288 
289  default:
290  // no-op
291  break;
292  }
293  return ::StatusCode::SUCCESS;
294  }

◆ getManagerOrder()

std::pair< Detail::ManagerOrder, std::string > EL::Detail::SubmitDirManager::getManagerOrder ( ) const
overridevirtualnoexcept

get the order/name of this manager

This is both used to identify the manager we are looking at, and to make sure they get executed in the right order. It is a mistake to load two managers that report the same order.

This is a pair of an enum that defines the absolute order of managers, and a string that identifies the stream that this manager belongs to. If this manager is not specific to a stream this should be the empty stream.

Guarantee
no-fail

Implements EL::Detail::Manager.

Definition at line 60 of file SubmitDirManager.cxx.

62  {
63  return std::make_pair (ManagerOrder::SUBMIT_DIR, "");
64  }

The documentation for this class was generated from the following files:
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
vtune_athena.format
format
Definition: vtune_athena.py:14
plot_material.mkdir
def mkdir(path, recursive=True)
Definition: plot_material.py:16
EL::Detail::SubmitDirMode::UNIQUE_LINK
@ UNIQUE_LINK
append a unique suffix to the directory name and place a symbolic link in place of the originally req...
EL::Job::optRemoveSubmitDir
static const std::string optRemoveSubmitDir
description: the name of the option for overwriting the submission directory.
Definition: Job.h:189
ANA_MSG_ERROR
#define ANA_MSG_ERROR(xmsg)
Macro printing error messages.
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:294
PrepareReferenceFile.regex
regex
Definition: PrepareReferenceFile.py:43
EL::Detail::ManagerOrder::SUBMIT_DIR
@ SUBMIT_DIR
the basic operations for the submission directory
EL::Detail::ManagerStep::createSubmitDir
@ createSubmitDir
create the submission directory
EL::Detail::ManagerStep::extractOptions
@ extractOptions
extract any options into ManagerData for which it is appropriate
FullCPAlgorithmsTest_eljob.submitDir
submitDir
Definition: FullCPAlgorithmsTest_eljob.py:160
ANA_MSG_INFO
#define ANA_MSG_INFO(xmsg)
Macro printing info messages.
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:290
file
TFile * file
Definition: tile_monitor.h:29
Preparation.mode
mode
Definition: Preparation.py:94
EL::Detail::SubmitDirMode::UNIQUE
@ UNIQUE
append a unique suffix to the directory name
EL::Detail::SubmitDirMode::OVERWRITE
@ OVERWRITE
create the directory as is, removing existing directories if needed
EL::Detail::ManagerStep::updateSubmitDir
@ updateSubmitDir
update the submitDir variable to be an absolute path
python.AtlCoolLib.timeString
def timeString(iovkey)
Definition: AtlCoolLib.py:120
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:109
EL::Detail::SubmitDirMode::NO_CLOBBER
@ NO_CLOBBER
create the directory as is, raise an error if it already exists
EL::Job::optSubmitDirMode
static const std::string optSubmitDirMode
the submit-dir mode (allowed values: "no-clobber", "overwrite", "unique", "unique-link")
Definition: Job.h:195
EL::Job::optUniqueDateFormat
static const std::string optUniqueDateFormat
the date-format to use when generating unique submission directory names
Definition: Job.h:200
match
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition: hcg.cxx:356
ANA_MSG_DEBUG
#define ANA_MSG_DEBUG(xmsg)
Macro printing debug messages.
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:288