1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
|
#include "DQMServices/Core/interface/DQMStore.h"
#include "DQMServices/Core/interface/LegacyIOHelper.h"
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/LuminosityBlock.h"
#include "FWCore/Framework/interface/Run.h"
#include "FWCore/MessageLogger/interface/JobReport.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/ServiceRegistry/interface/Service.h"
#include "FWCore/Version/interface/GetReleaseVersion.h"
#include "Utilities/OpenSSL/interface/openssl_init.h"
#include "DQMFileSaverOnline.h"
#include <TString.h>
#include <TSystem.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
#include <filesystem>
#include <boost/iostreams/device/mapped_file.hpp>
using namespace dqm;
DQMFileSaverOnline::DQMFileSaverOnline(const edm::ParameterSet& ps) : DQMFileSaverBase(ps) {
backupLumiCount_ = ps.getUntrackedParameter<int>("backupLumiCount", 1);
keepBackupLumi_ = ps.getUntrackedParameter<bool>("keepBackupLumi", false);
}
DQMFileSaverOnline::~DQMFileSaverOnline() = default;
void DQMFileSaverOnline::saveLumi(const FileParameters& fp) const {
if (backupLumiCount_ > 0) {
if (fp.lumi_ % backupLumiCount_ == 0) {
// actual saving is done here
makeSnapshot(fp, false);
}
}
}
void DQMFileSaverOnline::saveRun(const FileParameters& fp) const { makeSnapshot(fp, true); }
void DQMFileSaverOnline::makeSnapshot(const FileParameters& fp, bool final) const {
int pid = getpid();
char hostname[64];
gethostname(hostname, 64);
hostname[63] = 0;
char suffix[128];
if (!final) {
snprintf(suffix, 127, ".ls%08ld_host%s_pid%08d", fp.lumi_, hostname, pid);
} else {
suffix[0] = 0;
}
std::string prefix = filename(fp, false);
std::string root_fp = prefix + ".root" + suffix;
std::string meta_fp = prefix + ".root.origin" + suffix;
std::string tmp_root_fp = root_fp + ".tmp";
std::string tmp_meta_fp = meta_fp + ".tmp";
// run_ and lumi_ are ignored if dqmstore is not in multithread mode
edm::Service<DQMStore> store;
logFileAction("Writing DQM Root file: ", root_fp);
// logFileAction("Writing DQM Origin file: ", meta_fp);
//char rewrite[128];
//snprintf(rewrite, 128, "\\1Run %ld/\\2/Run summary", fp.run_);
//store->save(tmp_root_fp, /* filename */
// "", /* path */
// "^(Reference/)?([^/]+)", /* pattern */
// rewrite, /* rewrite */
// store->mtEnabled() ? fp.run_ : 0, /* run */
// 0, /* lumi */
// fp.saveReference_, /* ref */
// fp.saveReferenceQMin_, /* ref minStatus */
// "RECREATE"); /* fileupdate */
// TODO: some parameters prepared here are now unused, and the code should
// eventually be removed.
LegacyIOHelper h(&*store);
h.save(tmp_root_fp, "", fp.run_, /* saveall */ true, "RECREATE");
// write metadata
// format.origin: md5:d566a34b27f48d507150a332b189398b 294835
// /home/dqmprolocal/output/DQM_V0001_FED_R000194224.root
std::ofstream meta_fd(tmp_meta_fp);
meta_fd << fillOrigin(tmp_root_fp, root_fp);
meta_fd.close();
checkError("Rename failed: ", root_fp, ::rename(tmp_root_fp.c_str(), root_fp.c_str()));
checkError("Rename failed: ", meta_fp, ::rename(tmp_meta_fp.c_str(), meta_fp.c_str()));
SnapshotFiles files = {root_fp, meta_fp};
if (final) {
// final will never be cleared
appendSnapshot(SnapshotFiles{});
saveJobReport(root_fp);
} else {
appendSnapshot(SnapshotFiles{root_fp, meta_fp});
}
}
void DQMFileSaverOnline::appendSnapshot(SnapshotFiles f) const {
std::lock_guard<std::mutex> lock(snapshots_lock_);
if (!keepBackupLumi_) {
while (!snapshots_.empty()) {
SnapshotFiles& x = snapshots_.front();
// logFileAction("Deleting old snapshot (origin): ", x.meta);
checkError("Unlink failed: ", x.meta, ::unlink(x.meta.c_str()));
logFileAction("Deleting old snapshot (root): ", x.data);
checkError("Unlink failed: ", x.data, ::unlink(x.data.c_str()));
snapshots_.pop_front();
}
}
if (!f.data.empty()) {
snapshots_.push_back(f);
}
}
void DQMFileSaverOnline::checkError(const char* msg, const std::string& file, int status) const {
if (status != 0) {
std::string actual_msg = msg;
actual_msg += std::strerror(status);
logFileAction(actual_msg, file);
}
}
const std::string DQMFileSaverOnline::fillOrigin(const std::string& filename, const std::string& final_filename) {
// format.origin (one line):
// md5:d566a34b27f48d507150a332b189398b 294835 final_filename.root
cms::openssl_init();
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
const EVP_MD* md = EVP_get_digestbyname("MD5");
unsigned int md_len = 0;
unsigned char md5[EVP_MAX_MD_SIZE];
boost::iostreams::mapped_file_source fp(filename);
EVP_DigestInit_ex(mdctx, md, nullptr);
EVP_DigestUpdate(mdctx, (unsigned char*)fp.data(), fp.size());
EVP_DigestFinal_ex(mdctx, md5, &md_len);
EVP_MD_CTX_free(mdctx);
std::ostringstream hash;
for (unsigned int i = 0; i < md_len; i++) {
hash << std::hex << std::setfill('0') << std::setw(2) << (int)md5[i];
}
std::ostringstream out;
out << "md5:" << hash.str() << " " << fp.size() << " " << final_filename;
return out.str();
}
void DQMFileSaverOnline::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
desc.setComment("Saves histograms from DQM store, online workflow.");
desc.addUntracked<int>("backupLumiCount", 10)
->setComment(
"How often the backup file will be generated, in lumisections (-1 "
"disables).");
desc.addUntracked<bool>("keepBackupLumi", false)
->setComment(
"Usually the backup old backup is deleted once the new file is "
"available. Setting this to true ensures that no backup files are "
"ever deleted. Useful for ML applications, which use backups as a "
"'history' of what happened during the run.");
DQMFileSaverBase::fillDescription(desc);
// Changed to use addDefault instead of add here because previously
// DQMFileSaverOnline and DQMFileSaverPB both used the module label
// "saver" which caused conflicting cfi filenames to be generated.
// add could be used if unique module labels were given.
descriptions.addDefault(desc);
}
#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE(DQMFileSaverOnline);
|