ATLAS Offline Software
Loading...
Searching...
No Matches
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
virtual::StatusCode doManagerStep (Detail::ManagerData &data) const override
 do whatever needs to be done for the given submission step

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 69 of file SubmitDirManager.cxx.

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

◆ 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 61 of file SubmitDirManager.cxx.

63 {
64 return std::make_pair (ManagerOrder::SUBMIT_DIR, "");
65 }
@ SUBMIT_DIR
the basic operations for the submission directory

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