32{
33 void LocalDriver ::
34 testInvariant () const
35 {}
36
37
38
39 LocalDriver ::
40 LocalDriver ()
41 {
43 }
44
45
46
47 ::StatusCode LocalDriver ::
48 doManagerStep (Detail::ManagerData& data) const
49 {
51 using namespace msgEventLoop;
52 ANA_CHECK (BatchDriver::doManagerStep (data));
54 {
55 case Detail::ManagerStep::batchScriptVar:
56 {
57 data.batchSkipReleaseSetup =
true;
58 }
59 break;
60
61 case Detail::ManagerStep::submitJob:
62 case Detail::ManagerStep::doResubmit:
63 {
64
65
66 const std::string dockerImage {
67 data.options.castString(Job::optDockerImage)};
68 const std::string dockerOptions {
69 data.options.castString(Job::optDockerOptions)};
70 int numParallelProcs
71 =
data.options.castDouble (Job::optNumParallelProcs, 1);
72 if (numParallelProcs < 0)
73 {
74 ANA_MSG_ERROR (
"invalid number of parallel processes: " << numParallelProcs);
75 return StatusCode::FAILURE;
76 }
77
78 std::ostringstream basedirName;
79 basedirName <<
data.submitDir <<
"/tmp";
81 {
82 if (gSystem->MakeDirectory (basedirName.str().c_str()) != 0)
83 {
84 ANA_MSG_ERROR (
"failed to create directory " << basedirName.str());
85 return StatusCode::FAILURE;
86 }
87 }
88 auto submitSingle = [&] (std::size_t
index)
noexcept -> StatusCode
89 {
90 try
91 {
94 if (gSystem->MakeDirectory (
dirName.str().c_str()) != 0)
95 {
97 return StatusCode::FAILURE;
98 }
99
100 std::ostringstream
cmd;
102 if (!dockerImage.empty())
106 } catch (std::exception& e)
107 {
109 return StatusCode::FAILURE;
110 }
111 return StatusCode::SUCCESS;
112 };
113 if (numParallelProcs == 1)
114 {
115 for (std::size_t
index :
data.batchJobIndices)
116 {
117 if (submitSingle (
index).isFailure())
118 return StatusCode::FAILURE;
119 }
120 } else
121 {
122 if (numParallelProcs == 0)
123 numParallelProcs = std::thread::hardware_concurrency();
124
125
126 if (numParallelProcs < 1)
127 numParallelProcs = 1;
128 if (numParallelProcs >
int (
data.batchJobIndices.size()))
129 numParallelProcs =
data.batchJobIndices.size();
130 std::vector<std::thread>
threads;
132 auto indexIter =
data.batchJobIndices.begin();
133 bool abort = false;
135 {
136 threads.emplace_back ([&] ()
noexcept
137 {
138 std::unique_lock<std::mutex>
lock (
mutex);
139 while (indexIter !=
data.batchJobIndices.end() && !abort)
140 {
141 auto myindex = *indexIter;
142 ++ indexIter;
144 if (submitSingle (myindex).isFailure())
145 {
146 abort = true;
147 return;
148 }
150 }
151 });
152 }
153 for (auto& thread : threads)
154 thread.join();
155 if (abort)
156 return StatusCode::FAILURE;
157 }
158 data.submitted =
true;
159 }
160 break;
161
162 default:
163 break;
164 }
165 return ::StatusCode::SUCCESS;
166 }
167}
#define RCU_NEW_INVARIANT(x)
#define RCU_READ_INVARIANT(x)
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
void exec(const std::string &cmd)
effects: execute the given command guarantee: strong failures: out of memory II failures: system fail...
std::string quote(const std::string &name)
effects: quote the given name to protect it from the shell returns: the quoted name guarantee: strong...