votca 2026-dev
Loading...
Searching...
No Matches
progressobserver.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2020 The VOTCA Development Team
3 * (http://www.votca.org)
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License")
6 *
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
21
22// Standard includes
23#include <fstream>
24#include <unistd.h>
25
26// Third party includes
27#include <boost/algorithm/string/replace.hpp>
28#include <boost/date_time/posix_time/posix_time.hpp>
29#include <boost/format.hpp>
30#include <sys/types.h>
31
32// Local VOTCA includes
33#include "votca/xtp/job.h"
35#include "votca/xtp/qmthread.h"
36
37using boost::format;
38
39namespace votca {
40namespace xtp {
41
42template <typename JobContainer>
45
46 lockThread_.Lock();
47 Job *jobToProc = nullptr;
48
49 XTP_LOG(Log::error, thread.getLogger())
50 << "Requesting next job" << std::flush;
52 // NEED NEW CHUNK?
53 if (nextjit_ == jobsToProc_.end() && moreJobsAvailable_) {
56 if (nextjit_ == jobsToProc_.end()) {
57 moreJobsAvailable_ = false;
58 XTP_LOG(Log::error, thread.getLogger())
59 << "Sync did not yield any new jobs." << std::flush;
60 }
61 }
62
63 // JOBS EATEN ALL UP?
64 if (nextjit_ == jobsToProc_.end()) {
65 if (maxJobs_ == startJobsCount_) {
67 << "Next job: ID = - (reached maximum for this process)"
68 << std::flush;
69 } else {
71 << "Next job: ID = - (none available)" << std::flush;
72 }
73 }
74 // TAKE A BITE
75 else {
76 jobToProc = *nextjit_;
77 ++nextjit_;
78 XTP_LOG(Log::error, thread.getLogger())
79 << "Next job: ID = " << jobToProc->getId() << std::flush;
80 }
81
82 if (!thread.isMaverick() && jobToProc != nullptr) {
83 Index idx = jobToProc->getId();
84 Index frac = (jobs_.size() >= 10) ? 10 : jobs_.size();
85 Index rounded = Index(double(jobs_.size()) / double(frac)) * frac;
86 Index tenth = rounded / frac;
87 if (idx % tenth == 0) {
88 double percent = double(idx) / double(rounded) * 100 + 0.5;
89 std::cout << (format("=> [%1$2.0f%%] ") % percent).str() << std::flush;
90 }
91 }
92
93 lockThread_.Unlock();
94 return jobToProc;
95}
96
97template <typename JobContainer>
99 QMThread &thread) {
100 lockThread_.Lock();
101 XTP_LOG(Log::error, thread.getLogger())
102 << "Reporting job results" << std::flush;
103 // RESULTS, TIME, HOST
104 job.UpdateFromResult(res);
105 job.setTime(GenerateTime());
106 job.setHost(GenerateHost());
107 // PRINT PROGRESS BAR
108 jobsReported_ += 1;
109 if (!thread.isMaverick()) {
110 std::cout << std::endl << thread.getLogger() << std::flush;
111 }
112 lockThread_.Unlock();
113 return;
114}
115
116template <typename JobContainer>
118 char host[128];
119 (void)gethostname(host, sizeof host);
120 pid_t pid = getpid();
121 return (format("%1$s:%2$d") % host % pid).str();
122}
123
124template <typename JobContainer>
126 boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
127 return (format("%1$s") % now.time_of_day()).str();
128}
129
130template <typename JobContainer>
132
133 // INTERPROCESS FILE LOCKING (THREAD LOCK IN ::RequestNextJob)
134 this->LockProgFile(thread);
135
136 std::string progFile = progFile_;
137 std::string progBackFile = progFile_ + "~";
138
139 // LOAD EXTERNAL JOBS FROM SHARED XML & UPDATE INTERNAL JOBS
140 XTP_LOG(Log::info, thread.getLogger())
141 << "Update internal structures from job file" << std::flush;
142 JobContainer jobs_ext = LOAD_JOBS(progFile);
143 UPDATE_JOBS(jobs_ext, jobs_, GenerateHost());
144
145 // GENERATE BACK-UP FOR SHARED XML
146 XTP_LOG(Log::info, thread.getLogger())
147 << "Create job-file back-up" << std::flush;
148 WRITE_JOBS(jobs_, progBackFile);
149
150 // ASSIGN NEW JOBS IF AVAILABLE
151 XTP_LOG(Log::error, thread.getLogger())
152 << "Assign jobs from stack" << std::flush;
153 jobsToProc_.clear();
154
155 Index cacheSize = cacheSize_;
156 while (int(jobsToProc_.size()) < cacheSize) {
157 if (metajit_ == jobs_.end() || startJobsCount_ == maxJobs_) {
158 break;
159 }
160
161 bool startJob = false;
162
163 // Start if job available or restart patterns matched
164 if ((metajit_->isAvailable()) ||
165 (restartMode_ && restart_stats_.count(metajit_->getStatusStr())) ||
166 (restartMode_ && restart_hosts_.count(metajit_->getHost()))) {
167 startJob = true;
168 }
169
170 if (startJob) {
171 metajit_->Reset();
172 metajit_->setStatus("ASSIGNED");
173 metajit_->setHost(GenerateHost());
174 metajit_->setTime(GenerateTime());
175 jobsToProc_.push_back(&*metajit_);
176 startJobsCount_ += 1;
177 }
178
179 ++metajit_;
180 }
181
182 // UPDATE PROGRESS STATUS FILE
183 WRITE_JOBS(jobs_, progFile);
184
185 // RELEASE PROGRESS STATUS FILE
186 this->ReleaseProgFile(thread);
187 return;
188}
189
190template <typename JobContainer>
192 flock_ = std::unique_ptr<boost::interprocess::file_lock>(
193 new boost::interprocess::file_lock(lockFile_.c_str()));
194 flock_->lock_sharable();
195 XTP_LOG(Log::warning, thread.getLogger())
196 << "Imposed lock on " << lockFile_ << std::flush;
197 XTP_LOG(Log::warning, thread.getLogger())
198 << "Sleep ... " << lockFile_ << std::flush;
199 XTP_LOG(Log::warning, thread.getLogger())
200 << "Wake up ... " << lockFile_ << std::flush;
201}
202
203template <typename JobContainer>
205 flock_->unlock_sharable();
206 XTP_LOG(Log::warning, thread.getLogger())
207 << "Releasing " << lockFile_ << ". " << std::flush;
208}
209
210template <typename JobContainer>
212 const boost::program_options::variables_map &optsMap) {
213
214 lockFile_ = optsMap["file"].as<std::string>();
215 cacheSize_ = optsMap["cache"].as<Index>();
216 maxJobs_ = optsMap["maxjobs"].as<Index>();
217 std::string restartPattern = optsMap["restart"].as<std::string>();
218
219 // restartPattern = e.g. host(pckr124:1234) stat(FAILED)
220 boost::algorithm::replace_all(restartPattern, " ", "");
221 if (restartPattern == "") {
222 restartMode_ = false;
223 } else {
224 restartMode_ = true;
225 }
226
227 std::vector<std::string> patterns =
228 tools::Tokenizer(restartPattern, "(,)").ToVector();
229
230 std::string category = "";
231 for (const std::string &pattern : patterns) {
232
233 if (pattern == "host" || pattern == "stat") {
234 category = pattern;
235
236 } else if (category == "host") {
237 restart_hosts_[pattern] = true;
238 } else if (category == "stat") {
239 if (pattern == "ASSIGNED" || pattern == "COMPLETE") {
240 std::cout << "Restart if status == " << pattern
241 << "? Not necessarily a good idea." << std::endl;
242 }
243 restart_stats_[pattern] = true;
244 }
245
246 else {
247 throw std::runtime_error(
248 "Restart pattern ill-defined, format is"
249 "[host([HOSTNAME:PID])] [stat([STATUS])]");
250 }
251 }
252 return;
253}
254
255template <typename JobContainer>
257 QMThread &thread) {
258
259 progFile_ = progFile;
260 jobsReported_ = 0;
261
262 XTP_LOG(Log::error, thread.getLogger())
263 << "Job file = '" << progFile_ << "', ";
264 XTP_LOG(Log::info, thread.getLogger())
265 << "lock file = '" << lockFile_ << "', ";
266 XTP_LOG(Log::error, thread.getLogger())
267 << "cache size = " << cacheSize_ << std::flush;
268
269 XTP_LOG(Log::error, thread.getLogger())
270 << "Initialize jobs from " << progFile << std::flush;
271 XTP_LOG(Log::info, thread.getLogger()) << "Lock & load " << std::flush;
272
273 // LOCK, READ INTO XML
274 this->LockProgFile(thread);
275
276 // ... Clear container
277 jobs_.clear();
278
279 // ... Load new, set availability bool
280 jobs_ = LOAD_JOBS(progFile);
281 metajit_ = jobs_.begin();
282 WRITE_JOBS(jobs_, progFile + "~");
283 XTP_LOG(Log::error, thread.getLogger())
284 << "Registered " << jobs_.size() << " jobs." << std::flush;
285 if (jobs_.size() > 0) {
286 moreJobsAvailable_ = true;
287 } else {
288 moreJobsAvailable_ = false;
289 }
290
291 // SUMMARIZE OBSERVER VARIABLES: RESTART PATTERN, CACHE, LOCK FILE
292 if (restartMode_ && restart_hosts_.size()) {
293 std::string infostr = "Restart if host == ";
294 for (const std::pair<const std::string, bool> &host : restart_hosts_) {
295 infostr += host.first + " ";
296 }
297 XTP_LOG(Log::error, thread.getLogger()) << infostr << std::flush;
298 }
299 if (restartMode_ && restart_stats_.size()) {
300 std::string infostr = "Restart if stat == ";
301 for (const std::pair<const std::string, bool> &host : restart_hosts_) {
302 infostr += host.first + " ";
303 }
304 XTP_LOG(Log::error, thread.getLogger()) << infostr << std::flush;
305 }
306
307 // RELEASE PROGRESS FILE
308 this->ReleaseProgFile(thread);
309 return;
310}
311
312// REGISTER
313template class ProgObserver<std::vector<Job> >;
314
315} // namespace xtp
316} // namespace votca
break string into words
Definition tokenizer.h:72
std::vector< T > ToVector()
store all words in a vector of type T, does type conversion.
Definition tokenizer.h:109
void LockProgFile(QMThread &thread)
typename JobContainer::value_type Job
void InitFromProgFile(std::string progFile, QMThread &thread)
void ReportJobDone(Job &job, Result &res, QMThread &thread)
ProgObserver::Job * RequestNextJob(QMThread &thread)
typename Job::JobResult Result
std::map< std::string, bool > restart_stats_
std::map< std::string, bool > restart_hosts_
void ReleaseProgFile(QMThread &thread)
void SyncWithProgFile(QMThread &thread)
void InitCmdLineOpts(const boost::program_options::variables_map &optsMap)
std::unique_ptr< boost::interprocess::file_lock > flock_
Logger & getLogger()
Definition qmthread.h:55
#define XTP_LOG(level, log)
Definition logger.h:40
Charge transport classes.
Definition ERIs.h:28
void WRITE_JOBS(const std::vector< Job > &jobs, const std::string &job_file)
Definition job.cc:201
void UPDATE_JOBS(const std::vector< Job > &from, std::vector< Job > &to, const std::string &thisHost)
Definition job.cc:217
std::vector< Job > LOAD_JOBS(const std::string &xml_file)
Definition job.cc:186
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26