Project
Loading...
Searching...
No Matches
Plugin.cxx
Go to the documentation of this file.
1// Copyright 2019-2024 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"
15#include "Framework/Logger.h"
17#include "Framework/Signpost.h"
20#include <TBufferFile.h>
21#include <TDirectory.h>
22#include <TDirectoryFile.h>
23#include <TClass.h>
24#include <arrow/dataset/file_base.h>
25#include <arrow/filesystem/filesystem.h>
26#include <cstddef>
27#include <memory>
28#include <string_view>
29
31namespace o2::framework
32{
33auto lookForAodFile = [](ConfigParamRegistry& registry, int argc, char** argv) -> bool {
34 O2_SIGNPOST_ID_GENERATE(sid, capabilities);
35 if (registry.hasOption("aod-file") && registry.isSet("aod-file")) {
36 for (size_t i = 0; i < argc; i++) {
37 std::string_view arg = argv[i];
38 if (arg.starts_with("--aod-metadata-")) {
39 return false;
40 }
41 }
42 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverMetadataInAODCapability", "Metadata not found in arguments. Checking in AOD file.");
43 return true;
44 }
45 return false;
46};
47
48auto lookForCommandLineOptions = [](ConfigParamRegistry& registry, int argc, char** argv) -> bool {
49 O2_SIGNPOST_ID_GENERATE(sid, capabilities);
50 for (size_t i = 0; i < argc; i++) {
51 std::string_view arg = argv[i];
52 if (arg.starts_with("--aod-metadata-")) {
53 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverMetadataInCommandLineCapability", "Metadata found in arguments. Populating from them.");
54 return true;
55 }
56 }
57 return false;
58};
59
60auto lookForCommandLineAODOptions = [](ConfigParamRegistry& registry, int argc, char** argv) -> bool {
61 O2_SIGNPOST_ID_GENERATE(sid, capabilities);
62 // If one of the options for aod-writer is specified, we should allow configuring compression.
63 for (size_t i = 0; i < argc; i++) {
64 std::string_view arg = argv[i];
65 if (arg.starts_with("--aod-writer-")) {
66 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverAODOptionsInCommandLineCapability", "AOD options found in arguments. Populating from them.");
67 return true;
68 }
69 if (arg.starts_with("--aod-parent-")) {
70 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverAODOptionsInCommandLineCapability", "AOD options found in arguments. Populating from them.");
71 return true;
72 }
73 if (arg.starts_with("--aod-origin-")) {
74 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverAODOptionsInCommandLineCapability", "AOD options found in arguments. Populating from them.");
75 return true;
76 }
77 }
78 return false;
79};
80
81struct DiscoverMetadataInAODCapability : o2::framework::CapabilityPlugin {
82 Capability* create() override
83 {
84 return new Capability{
85 .name = "DiscoverMetadataInAODCapability",
86 .checkIfNeeded = lookForAodFile,
87 .requiredPlugin = "O2FrameworkAnalysisSupport:DiscoverMetadataInAOD"};
88 }
89};
90
91// Trigger discovery of metadata from command line, if needed.
92struct DiscoverMetadataInCommandLineCapability : o2::framework::CapabilityPlugin {
93 Capability* create() override
94 {
95 return new Capability{
96 .name = "DiscoverMetadataInCommandLineCapability",
97 .checkIfNeeded = lookForCommandLineOptions,
98 .requiredPlugin = "O2Framework:DiscoverMetadataInCommandLine"};
99 }
100};
101
102struct DiscoverAODOptionsInCommandLineCapability : o2::framework::CapabilityPlugin {
103 Capability* create() override
104 {
105 return new Capability{
106 .name = "DiscoverAODOptionsInCommandLineCapability",
107 .checkIfNeeded = lookForCommandLineAODOptions,
108 .requiredPlugin = "O2Framework:DiscoverAODOptionsInCommandLine"};
109 }
110};
111
112struct DiscoverMetadataInCommandLine : o2::framework::ConfigDiscoveryPlugin {
113 ConfigDiscovery* create() override
114 {
115 return new ConfigDiscovery{
116 .init = []() {},
117 .discover = [](ConfigParamRegistry& registry, int argc, char** argv) -> std::vector<ConfigParamSpec> {
118 O2_SIGNPOST_ID_GENERATE(sid, capabilities);
119 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverMetadataInCommandLine",
120 "Discovering metadata for analysis from well known environment variables.");
121 std::vector<ConfigParamSpec> results;
122 for (size_t i = 0; i < argc; i++) {
123 std::string_view arg = argv[i];
124 if (!arg.starts_with("--aod-metadata")) {
125 continue;
126 }
127 std::string key = arg.data() + 2;
128 std::string value = argv[i + 1];
129 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverMetadataInCommandLine",
130 "Found %{public}s with value %{public}s.", key.c_str(), value.c_str());
131 if (key == "aod-metadata-tables") {
132 std::stringstream is(value);
133 auto arrayValue = VariantJSONHelpers::read<VariantType::ArrayString>(is);
134 results.push_back(ConfigParamSpec{key, VariantType::ArrayString, arrayValue, {"Metadata in command line"}});
135 } else {
136 results.push_back(ConfigParamSpec{key, VariantType::String, value, {"Metadata in command line"}});
137 }
138 }
139 return results;
140 }};
141 }
142};
143
144struct DiscoverAODOptionsInCommandLine : o2::framework::ConfigDiscoveryPlugin {
145 ConfigDiscovery* create() override
146 {
147 return new ConfigDiscovery{
148 .init = []() {},
149 .discover = [](ConfigParamRegistry& registry, int argc, char** argv) -> std::vector<ConfigParamSpec> {
150 O2_SIGNPOST_ID_GENERATE(sid, capabilities);
151 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverAODOptionsInCommandLine",
152 "Discovering AOD handling related options in commandline arguments.");
153 std::vector<ConfigParamSpec> results;
154 bool injectOption = true;
155 for (size_t i = 0; i < argc; i++) {
156 std::string_view arg = argv[i];
157 if (!arg.starts_with("--aod-writer-") && !arg.starts_with("--aod-parent-") && !arg.starts_with("--aod-origin-")) {
158 continue;
159 }
160 std::string key = arg.data() + 2;
161 std::string value = argv[i + 1];
162 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverAODOptionsInCommandLine",
163 "Found %{public}s with value %{public}s.", key.c_str(), value.c_str());
164 if (key == "aod-writer-compression") {
165 int numericValue = std::stoi(value);
166 results.push_back(ConfigParamSpec{"aod-writer-compression", VariantType::Int, numericValue, {"AOD Compression options"}});
167 injectOption = false;
168 }
169 if (key == "aod-parent-base-path-replacement") {
170 results.push_back(ConfigParamSpec{"aod-parent-base-path-replacement", VariantType::String, value, {R"(Replace base path of parent files. Syntax: FROM;TO. E.g. "alien:///path/in/alien;/local/path". Enclose in "" on the command line.)"}});
171 }
172 if (key == "aod-parent-access-level") {
173 results.push_back(ConfigParamSpec{"aod-parent-access-level", VariantType::String, value, {"Allow parent file access up to specified level. Default: no (0)"}});
174 }
175 if (key == "aod-origin-level-mapping") {
176 results.push_back(ConfigParamSpec{"aod-origin-level-mapping", VariantType::String, value, {"Map origin to parent level for AOD reading. Syntax: ORIGIN:LEVEL[,ORIGIN2:LEVEL2,...]. E.g. \"DYN:1\"."}});
177 }
178 }
179 if (injectOption) {
180 results.push_back(ConfigParamSpec{"aod-writer-compression", VariantType::Int, 505, {"AOD Compression options"}});
181 }
182 return results;
183 }};
184 }
185};
186
187struct ImplementationContext {
188 std::vector<RootArrowFactory> implementations;
189};
190
191std::function<void*(std::shared_ptr<arrow::fs::FileSystem>, std::string const&)> getHandleByClass(char const* classname)
192{
193 return [c = TClass::GetClass(classname)](std::shared_ptr<arrow::fs::FileSystem> fs, std::string const& path) -> void* {
194 if (auto tfileFS = std::dynamic_pointer_cast<TFileFileSystem>(fs)) {
195 return tfileFS->GetFile()->GetObjectChecked(path.c_str(), c);
196 } else if (auto tbufferFS = std::dynamic_pointer_cast<TBufferFileFS>(fs)) {
197 tbufferFS->GetBuffer()->Reset();
198 return tbufferFS->GetBuffer()->ReadObjectAny(c);
199 }
200 return nullptr;
201 };
202}
203
204std::function<bool(char const*)> matchClassByName(std::string_view classname)
205{
206 return [c = classname](char const* attempt) -> bool {
207 return c == attempt;
208 };
209}
210
211void lazyLoadFactory(std::vector<RootArrowFactory>& implementations, char const* specs)
212{
213 // Lazy loading of the plugin so that we do not bring in RNTuple / TTree if not needed
214 if (implementations.empty()) {
215 std::vector<LoadablePlugin> plugins;
216 auto morePlugins = PluginManager::parsePluginSpecString(specs);
217 for (auto& extra : morePlugins) {
218 plugins.push_back(extra);
219 }
220 PluginManager::loadFromPlugin<RootArrowFactory, RootArrowFactoryPlugin>(plugins, implementations);
221 if (implementations.empty()) {
222 return;
223 }
224 }
225}
226
227struct RNTupleObjectReadingCapability : o2::framework::RootObjectReadingCapabilityPlugin {
229 {
230 auto context = new ImplementationContext;
231
233 {
234 .name = "rntuple",
235 .lfn2objectPath = [](std::string s) -> std::string {
236 std::replace(s.begin()+1, s.end(), '/', '-');
237#if __has_include(<ROOT/RFieldBase.hxx>)
238 if (s.starts_with("/")) {
239 return std::string(s.begin() + 1, s.end());
240 } else {
241 return s;
242 } },
243#else
244 if (s.starts_with("/")) {
245 return s;
246 } else {
247 return "/" + s;
248 } },
249#endif
250#if __has_include(<ROOT/RFieldBase.hxx>)
251 .getHandle = getHandleByClass("ROOT::RNTuple"),
252 .checkSupport = matchClassByName("ROOT::RNTuple"),
253#else
254 .getHandle = getHandleByClass("ROOT::Experimental::RNTuple"),
255 .checkSupport = matchClassByName("ROOT::Experimental::RNTuple"),
256#endif
257 .factory = [context]() -> RootArrowFactory& {
258 lazyLoadFactory(context->implementations, "O2FrameworkAnalysisRNTupleSupport:RNTupleObjectReadingImplementation");
259 return context->implementations.back();
260 }
261 };
262 }
263};
264
265struct TTreeObjectReadingCapability : o2::framework::RootObjectReadingCapabilityPlugin {
267 {
268 auto context = new ImplementationContext;
269
271 .name = "ttree",
272 .lfn2objectPath = [](std::string s) { return s; },
273 .getHandle = getHandleByClass("TTree"),
274 .checkSupport = matchClassByName("TTree"),
275 .factory = [context]() -> RootArrowFactory& {
276 lazyLoadFactory(context->implementations, "O2FrameworkAnalysisTTreeSupport:TTreeObjectReadingImplementation");
277 return context->implementations.back();
278 }};
279 }
280};
281
283DEFINE_DPL_PLUGIN_INSTANCE(DiscoverMetadataInAODCapability, Capability);
284DEFINE_DPL_PLUGIN_INSTANCE(DiscoverMetadataInCommandLineCapability, Capability);
285DEFINE_DPL_PLUGIN_INSTANCE(DiscoverAODOptionsInCommandLineCapability, Capability);
286DEFINE_DPL_PLUGIN_INSTANCE(DiscoverMetadataInCommandLine, ConfigDiscovery);
287DEFINE_DPL_PLUGIN_INSTANCE(DiscoverAODOptionsInCommandLine, ConfigDiscovery);
288DEFINE_DPL_PLUGIN_INSTANCE(RNTupleObjectReadingCapability, RootObjectReadingCapability);
289DEFINE_DPL_PLUGIN_INSTANCE(TTreeObjectReadingCapability, RootObjectReadingCapability);
291} // namespace o2::framework
int32_t i
#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
uint32_t c
Definition RawData.h:2
#define O2_DECLARE_DYNAMIC_LOG(name)
Definition Signpost.h:490
#define O2_SIGNPOST_ID_GENERATE(name, log)
Definition Signpost.h:507
#define O2_SIGNPOST_EVENT_EMIT(log, id, name, format,...)
Definition Signpost.h:523
StringRef key
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
ConcreteParserVariants< PageSize, BOUNDS_CHECKS > create(T const *buffer, size_t size)
create a raw parser depending on version of RAWDataHeader found at beginning of data
Definition RawParser.h:378
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
static std::vector< LoadablePlugin > parsePluginSpecString(char const *str)
Parse a comma separated list of <library>:<plugin-name> plugin declarations.
virtual RootObjectReadingCapability * create()=0