Project
Loading...
Searching...
No Matches
Plugin.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11#include "Framework/Plugins.h"
17#include "Framework/Signpost.h"
19#include "AODWriterHelpers.h"
20#include <TFile.h>
21#include <TMap.h>
22#include <TGrid.h>
23#include <TObjString.h>
24#include <TString.h>
25#include <fmt/format.h>
26#include <memory>
27
28O2_DECLARE_DYNAMIC_LOG(analysis_support);
29
36
43
50
51using namespace o2::framework;
54 {
56 .name = "analysis-run-summary",
57 .init = [](ServiceRegistryRef ref, DeviceState&, fair::mq::ProgOptions&) -> ServiceHandle {
58 return ServiceHandle{TypeIdHelpers::uniqueId<RunSummary>(), nullptr, ServiceKind::Serial, "analysis-run-summary"};
59 },
60 .summaryHandling = [](ServiceMetricsInfo const& info) {
61 LOGP(info, "## Analysis Run Summary ##");
63 for (size_t mi = 0; mi < info.deviceMetricsInfos.size(); ++mi) {
64 DeviceMetricsInfo &metrics = info.deviceMetricsInfos[mi];
65 for (size_t li = 0; li < metrics.metricLabels.size(); ++li) {
66 MetricLabel const&label = metrics.metricLabels[li];
67 if (strcmp(label.label, "aod-file-read-info") != 0) {
68 continue;
69 }
70 MetricInfo const&metric = metrics.metrics[li];
71 auto &files = metrics.stringMetrics[metric.storeIdx];
72 if (metric.filledMetrics) {
73 LOGP(info, "### Files read stats ###");
74 }
75 for (size_t fi = 0; fi < metric.filledMetrics; ++fi) {
76 LOGP(info, "{}", files[fi % files.size()].data);
77 }
78 }
79 } },
80 .kind = ServiceKind::Serial};
81 }
82};
83
84std::vector<std::string> getListOfTables(std::unique_ptr<TFile>& f)
85{
86 std::vector<std::string> r;
87 TList* keyList = f->GetListOfKeys();
88 // We should handle two cases, one where the list of tables in a TDirectory,
89 // the other one where the dataframe number is just a prefix
90 std::string first = "";
91
92 for (auto key : *keyList) {
93 if (!std::string_view(key->GetName()).starts_with("DF_") && !std::string_view(key->GetName()).starts_with("/DF_")) {
94 continue;
95 }
96 auto* d = (TDirectory*)f->GetObjectChecked(key->GetName(), TClass::GetClass("TDirectory"));
97 // Objects are in a folder, list it.
98 if (d) {
99 TList* branchList = d->GetListOfKeys();
100 for (auto b : *branchList) {
101 r.emplace_back(b->GetName());
102 }
103 break;
104 }
105
106 void* v = f->GetObjectChecked(key->GetName(), TClass::GetClass("ROOT::Experimental::RNTuple"));
107 if (v) {
108 std::string s = key->GetName();
109 size_t pos = s.find('-');
110 // Check if '-' is found
111 // Skip metaData and parentFiles
112 if (pos == std::string::npos) {
113 continue;
114 }
115 std::string t = s.substr(pos + 1);
116 // If we find a duplicate table name, it means we are in the next DF and we can stop.
117 if (t == first) {
118 break;
119 }
120 if (first.empty()) {
121 first = t;
122 }
123 // Create a new string starting after the '-'
124 r.emplace_back(t);
125 }
126 }
127 return r;
128}
129
130auto readMetadata(std::unique_ptr<TFile>& currentFile) -> std::vector<ConfigParamSpec>
131{
132 // Get the metadata, if any
133 auto m = (TMap*)currentFile->Get("metaData");
134 if (!m) {
135 return {};
136 }
137 std::vector<ConfigParamSpec> results;
138 auto it = m->MakeIterator();
139
140 // Serialise metadata into a ; separated string with : separating key and value
141 bool first = true;
142 while (auto obj = it->Next()) {
143 if (first) {
144 LOGP(info, "Metadata for file \"{}\":", currentFile->GetName());
145 first = false;
146 }
147 auto objString = (TObjString*)m->GetValue(obj);
148 LOGP(info, "- {}: {}", obj->GetName(), objString->String().Data());
149 std::string key = "aod-metadata-" + std::string(obj->GetName());
150 char const* value = strdup(objString->String());
151 results.push_back(ConfigParamSpec{key, VariantType::String, value, {"Metadata in AOD"}});
152 }
153
154 return results;
155}
156
159 {
160 return new ConfigDiscovery{
161 .init = []() {},
162 .discover = [](ConfigParamRegistry& registry, int argc, char** argv) -> std::vector<ConfigParamSpec> {
163 auto filename = registry.get<std::string>("aod-file");
164 if (filename.empty()) {
165 return {};
166 }
167 if (filename.at(0) == '@') {
168 filename.erase(0, 1);
169 // read the text file and set filename to the contents of the first line
170 std::ifstream file(filename);
171 if (!file.is_open()) {
172 LOGP(fatal, "Couldn't open file \"{}\"!", filename);
173 }
174 std::getline(file, filename);
175 file.close();
176 }
177 if (filename.rfind("alien://", 0) == 0) {
178 TGrid::Connect("alien://");
179 }
180 LOGP(info, "Loading metadata from file {} in PID {}", filename, getpid());
181 std::unique_ptr<TFile> currentFile{TFile::Open(filename.c_str())};
182 if (currentFile.get() == nullptr) {
183 LOGP(fatal, "Couldn't open file \"{}\"!", filename);
184 }
185 std::vector<ConfigParamSpec> results = readMetadata(currentFile);
186 const bool metaDataEmpty = results.empty();
187 auto tables = getListOfTables(currentFile);
188 if (tables.empty() == false) {
189 results.push_back(ConfigParamSpec{"aod-metadata-tables", VariantType::ArrayString, tables, {"Tables in first AOD"}});
190 }
191
192 // Found metadata already in the main file.
193 if (!metaDataEmpty) {
194 results.push_back(ConfigParamSpec{"aod-metadata-source", VariantType::String, filename, {"File from which the metadata was extracted."}});
195 return results;
196 }
197
198 if (!registry.isSet("aod-parent-access-level") || registry.get<int>("aod-parent-access-level") == 0) {
199 LOGP(info, "No metadata found in file \"{}\" and parent level 0 prevents further lookup.", filename);
200 results.push_back(ConfigParamSpec{"aod-metadata-disable", VariantType::String, "1", {"Metadata not found in AOD"}});
201 return results;
202 }
203
204 // Lets try in parent file.
205 auto parentFiles = (TMap*)currentFile->Get("parentFiles");
206 if (!parentFiles) {
207 LOGP(info, "No metadata found in file \"{}\"", filename);
208 results.push_back(ConfigParamSpec{"aod-metadata-disable", VariantType::String, "1", {"Metadata not found in AOD"}});
209 return results;
210 }
211 LOGP(info, "No metadata found in file \"{}\", checking in its parents.", filename);
212 for (auto* p : *parentFiles) {
213 std::string parentFilename = ((TPair*)p)->Value()->GetName();
214 // Do the replacement. Notice this will require changing aod-parent-base-path-replacement to be
215 // a workflow option (because the metadata itself is potentially changing the topology).
216 if (registry.isSet("aod-parent-base-path-replacement")) {
217 auto parentFileReplacement = registry.get<std::string>("aod-parent-base-path-replacement");
218 auto pos = parentFileReplacement.find(';');
219 if (pos == std::string::npos) {
220 throw std::runtime_error(fmt::format("Invalid syntax in aod-parent-base-path-replacement: \"{}\"", parentFileReplacement.c_str()));
221 }
222 auto from = parentFileReplacement.substr(0, pos);
223 auto to = parentFileReplacement.substr(pos + 1);
224 pos = parentFilename.find(from);
225 if (pos != std::string::npos) {
226 parentFilename.replace(pos, from.length(), to);
227 }
228 }
229
230 if (parentFilename.starts_with("alien://")) {
231 TGrid::Connect("alien://");
232 }
233
234 std::unique_ptr<TFile> parentFile{TFile::Open(parentFilename.c_str())};
235 if (parentFile.get() == nullptr) {
236 LOGP(fatal, "Couldn't open derived file \"{}\"!", parentFilename);
237 }
238 results = readMetadata(parentFile);
239 // Found metadata already in the main file.
240 if (!results.empty()) {
241 auto tables = getListOfTables(parentFile);
242 if (tables.empty() == false) {
243 results.push_back(ConfigParamSpec{"aod-metadata-tables", VariantType::ArrayString, tables, {"Tables in first AOD"}});
244 }
245 results.push_back(ConfigParamSpec{"aod-metadata-source", VariantType::String, filename, {"File from which the metadata was extracted."}});
246 return results;
247 }
248 LOGP(info, "No metadata found in file \"{}\" nor in its parent file \"{}\"", filename, parentFilename);
249 break;
250 }
251 results.push_back(ConfigParamSpec{"aod-metadata-disable", VariantType::String, "1", {"Metadata not found in AOD"}});
252 return results;
253 }};
254 }
255};
256
std::vector< std::string > getListOfTables(std::unique_ptr< TFile > &f)
Definition Plugin.cxx:84
auto readMetadata(std::unique_ptr< TFile > &currentFile) -> std::vector< ConfigParamSpec >
Definition Plugin.cxx:130
#define DEFINE_DPL_PLUGIN_INSTANCE(NAME, KIND)
Definition Plugins.h:112
#define DEFINE_DPL_PLUGINS_END
Definition Plugins.h:115
#define DEFINE_DPL_PLUGINS_BEGIN
Definition Plugins.h:107
uint16_t pos
Definition RawData.h:3
#define O2_DECLARE_DYNAMIC_LOG(name)
Definition Signpost.h:483
StringRef key
const GLfloat * m
Definition glcorearb.h:4066
const GLdouble * v
Definition glcorearb.h:832
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
Definition glcorearb.h:5500
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLboolean r
Definition glcorearb.h:1233
GLint ref
Definition glcorearb.h:291
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::string filename()
ConfigDiscovery * create() override
Definition Plugin.cxx:158
o2::framework::AlgorithmSpec create(o2::framework::ConfigContext const &config) override
Definition Plugin.cxx:31
o2::framework::AlgorithmSpec create(o2::framework::ConfigContext const &config) override
Definition Plugin.cxx:38
o2::framework::AlgorithmSpec create(o2::framework::ConfigContext const &config) override
Definition Plugin.cxx:45
o2::framework::ServiceSpec * create() final
Definition Plugin.cxx:53
Helper class for an algorithm which is loaded as a plugin.
Running state information of a given device.
Definition DeviceState.h:34
std::string name
Name of the service.
static AlgorithmSpec rootFileReaderCallback(ConfigContext const &context)
static AlgorithmSpec getOutputObjHistWriter(ConfigContext const &context)
static AlgorithmSpec getOutputTTreeWriter(ConfigContext const &context)