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 }
74 return false;
75};
76
77struct DiscoverMetadataInAODCapability : o2::framework::CapabilityPlugin {
78 Capability* create() override
79 {
80 return new Capability{
81 .name = "DiscoverMetadataInAODCapability",
82 .checkIfNeeded = lookForAodFile,
83 .requiredPlugin = "O2FrameworkAnalysisSupport:DiscoverMetadataInAOD"};
84 }
85};
86
87// Trigger discovery of metadata from command line, if needed.
88struct DiscoverMetadataInCommandLineCapability : o2::framework::CapabilityPlugin {
89 Capability* create() override
90 {
91 return new Capability{
92 .name = "DiscoverMetadataInCommandLineCapability",
93 .checkIfNeeded = lookForCommandLineOptions,
94 .requiredPlugin = "O2Framework:DiscoverMetadataInCommandLine"};
95 }
96};
97
98struct DiscoverAODOptionsInCommandLineCapability : o2::framework::CapabilityPlugin {
99 Capability* create() override
100 {
101 return new Capability{
102 .name = "DiscoverAODOptionsInCommandLineCapability",
103 .checkIfNeeded = lookForCommandLineAODOptions,
104 .requiredPlugin = "O2Framework:DiscoverAODOptionsInCommandLine"};
105 }
106};
107
108struct DiscoverMetadataInCommandLine : o2::framework::ConfigDiscoveryPlugin {
109 ConfigDiscovery* create() override
110 {
111 return new ConfigDiscovery{
112 .init = []() {},
113 .discover = [](ConfigParamRegistry& registry, int argc, char** argv) -> std::vector<ConfigParamSpec> {
114 O2_SIGNPOST_ID_GENERATE(sid, capabilities);
115 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverMetadataInCommandLine",
116 "Discovering metadata for analysis from well known environment variables.");
117 std::vector<ConfigParamSpec> results;
118 for (size_t i = 0; i < argc; i++) {
119 std::string_view arg = argv[i];
120 if (!arg.starts_with("--aod-metadata")) {
121 continue;
122 }
123 std::string key = arg.data() + 2;
124 std::string value = argv[i + 1];
125 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverMetadataInCommandLine",
126 "Found %{public}s with value %{public}s.", key.c_str(), value.c_str());
127 if (key == "aod-metadata-tables") {
128 std::stringstream is(value);
129 auto arrayValue = VariantJSONHelpers::read<VariantType::ArrayString>(is);
130 results.push_back(ConfigParamSpec{key, VariantType::ArrayString, arrayValue, {"Metadata in command line"}});
131 } else {
132 results.push_back(ConfigParamSpec{key, VariantType::String, value, {"Metadata in command line"}});
133 }
134 }
135 return results;
136 }};
137 }
138};
139
140struct DiscoverAODOptionsInCommandLine : o2::framework::ConfigDiscoveryPlugin {
141 ConfigDiscovery* create() override
142 {
143 return new ConfigDiscovery{
144 .init = []() {},
145 .discover = [](ConfigParamRegistry& registry, int argc, char** argv) -> std::vector<ConfigParamSpec> {
146 O2_SIGNPOST_ID_GENERATE(sid, capabilities);
147 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverAODOptionsInCommandLine",
148 "Discovering AOD handling related options in commandline arguments.");
149 std::vector<ConfigParamSpec> results;
150 bool injectOption = true;
151 for (size_t i = 0; i < argc; i++) {
152 std::string_view arg = argv[i];
153 if (!arg.starts_with("--aod-writer-") && !arg.starts_with("--aod-parent-")) {
154 continue;
155 }
156 std::string key = arg.data() + 2;
157 std::string value = argv[i + 1];
158 O2_SIGNPOST_EVENT_EMIT(capabilities, sid, "DiscoverAODOptionsInCommandLine",
159 "Found %{public}s with value %{public}s.", key.c_str(), value.c_str());
160 if (key == "aod-writer-compression") {
161 int numericValue = std::stoi(value);
162 results.push_back(ConfigParamSpec{"aod-writer-compression", VariantType::Int, numericValue, {"AOD Compression options"}});
163 injectOption = false;
164 }
165 if (key == "aod-parent-base-path-replacement") {
166 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.)"}});
167 }
168 if (key == "aod-parent-access-level") {
169 results.push_back(ConfigParamSpec{"aod-parent-access-level", VariantType::String, value, {"Allow parent file access up to specified level. Default: no (0)"}});
170 }
171 }
172 if (injectOption) {
173 results.push_back(ConfigParamSpec{"aod-writer-compression", VariantType::Int, 505, {"AOD Compression options"}});
174 }
175 return results;
176 }};
177 }
178};
179
180struct ImplementationContext {
181 std::vector<RootArrowFactory> implementations;
182};
183
184std::function<void*(std::shared_ptr<arrow::fs::FileSystem>, std::string const&)> getHandleByClass(char const* classname)
185{
186 return [c = TClass::GetClass(classname)](std::shared_ptr<arrow::fs::FileSystem> fs, std::string const& path) -> void* {
187 if (auto tfileFS = std::dynamic_pointer_cast<TFileFileSystem>(fs)) {
188 return tfileFS->GetFile()->GetObjectChecked(path.c_str(), c);
189 } else if (auto tbufferFS = std::dynamic_pointer_cast<TBufferFileFS>(fs)) {
190 tbufferFS->GetBuffer()->Reset();
191 return tbufferFS->GetBuffer()->ReadObjectAny(c);
192 }
193 return nullptr;
194 };
195}
196
197std::function<bool(char const*)> matchClassByName(std::string_view classname)
198{
199 return [c = classname](char const* attempt) -> bool {
200 return c == attempt;
201 };
202}
203
204void lazyLoadFactory(std::vector<RootArrowFactory>& implementations, char const* specs)
205{
206 // Lazy loading of the plugin so that we do not bring in RNTuple / TTree if not needed
207 if (implementations.empty()) {
208 std::vector<LoadablePlugin> plugins;
209 auto morePlugins = PluginManager::parsePluginSpecString(specs);
210 for (auto& extra : morePlugins) {
211 plugins.push_back(extra);
212 }
213 PluginManager::loadFromPlugin<RootArrowFactory, RootArrowFactoryPlugin>(plugins, implementations);
214 if (implementations.empty()) {
215 return;
216 }
217 }
218}
219
220struct RNTupleObjectReadingCapability : o2::framework::RootObjectReadingCapabilityPlugin {
222 {
223 auto context = new ImplementationContext;
224
226 .name = "rntuple",
227 .lfn2objectPath = [](std::string s) {
228 std::replace(s.begin()+1, s.end(), '/', '-');
229 if (s.starts_with("/")) {
230 return s;
231 } else {
232 return "/" + s;
233 } },
234 .getHandle = getHandleByClass("ROOT::Experimental::RNTuple"),
235 .checkSupport = matchClassByName("ROOT::Experimental::RNTuple"),
236 .factory = [context]() -> RootArrowFactory& {
237 lazyLoadFactory(context->implementations, "O2FrameworkAnalysisRNTupleSupport:RNTupleObjectReadingImplementation");
238 return context->implementations.back();
239 }};
240 }
241};
242
243struct TTreeObjectReadingCapability : o2::framework::RootObjectReadingCapabilityPlugin {
245 {
246 auto context = new ImplementationContext;
247
249 .name = "ttree",
250 .lfn2objectPath = [](std::string s) { return s; },
251 .getHandle = getHandleByClass("TTree"),
252 .checkSupport = matchClassByName("TTree"),
253 .factory = [context]() -> RootArrowFactory& {
254 lazyLoadFactory(context->implementations, "O2FrameworkAnalysisTTreeSupport:TTreeObjectReadingImplementation");
255 return context->implementations.back();
256 }};
257 }
258};
259
261DEFINE_DPL_PLUGIN_INSTANCE(DiscoverMetadataInAODCapability, Capability);
262DEFINE_DPL_PLUGIN_INSTANCE(DiscoverMetadataInCommandLineCapability, Capability);
263DEFINE_DPL_PLUGIN_INSTANCE(DiscoverAODOptionsInCommandLineCapability, Capability);
264DEFINE_DPL_PLUGIN_INSTANCE(DiscoverMetadataInCommandLine, ConfigDiscovery);
265DEFINE_DPL_PLUGIN_INSTANCE(DiscoverAODOptionsInCommandLine, ConfigDiscovery);
266DEFINE_DPL_PLUGIN_INSTANCE(RNTupleObjectReadingCapability, RootObjectReadingCapability);
267DEFINE_DPL_PLUGIN_INSTANCE(TTreeObjectReadingCapability, RootObjectReadingCapability);
269} // 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:473
#define O2_SIGNPOST_ID_GENERATE(name, log)
Definition Signpost.h:490
#define O2_SIGNPOST_EVENT_EMIT(log, id, name, format,...)
Definition Signpost.h:495
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 PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
static std::vector< LoadablePlugin > parsePluginSpecString(char const *str)
Parse a comma separated list of <library>:<plugin-name> plugin declarations.