Project
Loading...
Searching...
No Matches
PluginManager.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.
12#include "Framework/Logger.h"
13#include <uv.h>
14#include <functional>
15#include <vector>
16
17namespace o2::framework
18{
19std::vector<LoadablePlugin> PluginManager::parsePluginSpecString(char const* str)
20{
21 std::vector<LoadablePlugin> loadablePlugins;
22 enum struct ParserState : int {
23 IN_LIBRARY,
24 IN_NAME,
25 IN_END,
27 };
28 const char* cur = str;
29 const char* next = cur;
30 ParserState state = ParserState::IN_LIBRARY;
31 std::string_view library;
32 std::string_view name;
33 while (cur && *cur != '\0') {
34 ParserState previousState = state;
35 state = ParserState::IN_ERROR;
36 switch (previousState) {
37 case ParserState::IN_LIBRARY:
38 next = strchr(cur, ':');
39 if (next != nullptr) {
40 state = ParserState::IN_NAME;
41 library = std::string_view(cur, next - cur);
42 }
43 break;
44 case ParserState::IN_NAME:
45 next = strchr(cur, ',');
46 if (next == nullptr) {
47 state = ParserState::IN_END;
48 name = std::string_view(cur, strlen(cur));
49 } else {
50 name = std::string_view(cur, next - cur);
51 state = ParserState::IN_LIBRARY;
52 }
53 loadablePlugins.push_back({std::string(name), std::string(library)});
54 break;
55 case ParserState::IN_END:
56 break;
57 case ParserState::IN_ERROR:
58 LOG(error) << "Error while parsing DPL_LOAD_SERVICES";
59 break;
60 }
61 if (!next) {
62 break;
63 }
64 cur = next + 1;
65 };
66 return loadablePlugins;
67}
68
69void PluginManager::load(std::vector<PluginInfo>& libs, const char* dso, std::function<void(DPLPluginHandle*)>& onSuccess)
70{
71 auto plugin = std::find_if(libs.begin(), libs.end(), [dso](PluginInfo& info) { return info.name == dso; });
72 if (plugin != libs.end()) {
73 return onSuccess(plugin->instance);
74 }
75 auto* supportLib = (uv_lib_t*)malloc(sizeof(uv_lib_t));
76 int result = 0;
77#ifdef __APPLE__
78 char const* extension = "dylib";
79#else
80 char const* extension = "so";
81#endif
82 std::string filename = fmt::format("lib{}.{}", dso, extension);
83 result = uv_dlopen(filename.c_str(), supportLib);
84 if (result == -1) {
85 LOG(fatal) << uv_dlerror(supportLib);
86 return;
87 }
88 DPLPluginHandle* (*dpl_plugin_callback)(DPLPluginHandle*);
89
90 result = uv_dlsym(supportLib, "dpl_plugin_callback", (void**)&dpl_plugin_callback);
91 if (result == -1) {
92 LOG(fatal) << uv_dlerror(supportLib);
93 return;
94 }
95 if (dpl_plugin_callback == nullptr) {
96 LOGP(fatal, "Could not find the {} plugin.", dso);
97 return;
98 }
99 DPLPluginHandle* pluginInstance = dpl_plugin_callback(nullptr);
100 libs.push_back({supportLib, dso});
101 onSuccess(pluginInstance);
102}
103
104auto PluginManager::loadAlgorithmFromPlugin(std::string library, std::string plugin, ConfigContext const& context) -> AlgorithmSpec
105{
106 std::shared_ptr<AlgorithmSpec> algorithm{nullptr};
107 return AlgorithmSpec{[algorithm, library, plugin, &context](InitContext& ic) mutable -> AlgorithmSpec::ProcessCallback {
108 if (algorithm.get()) {
109 return algorithm->onInit(ic);
110 }
111
112 uv_lib_t supportLib;
113 std::string libName = "lib" + library;
114#ifdef __APPLE__
115 libName += ".dylib";
116#else
117 libName += ".so";
118#endif
119 int result = uv_dlopen(libName.c_str(), &supportLib);
120 if (result == -1) {
121 LOG(fatal) << uv_dlerror(&supportLib);
122 }
123 DPLPluginHandle* (*dpl_plugin_callback)(DPLPluginHandle*);
124
125 result = uv_dlsym(&supportLib, "dpl_plugin_callback", (void**)&dpl_plugin_callback);
126 if (result == -1) {
127 LOG(fatal) << uv_dlerror(&supportLib);
128 }
129 if (dpl_plugin_callback == nullptr) {
130 LOGP(fatal, "Could not find the {} plugin in {}.", plugin, libName);
131 }
132 DPLPluginHandle* pluginInstance = dpl_plugin_callback(nullptr);
133 auto* creator = PluginManager::getByName<AlgorithmPlugin>(pluginInstance, plugin.c_str());
134 if (!creator) {
135 LOGP(fatal, "Could not find the {} plugin in {}.", plugin, libName);
136 }
137 algorithm = std::make_shared<AlgorithmSpec>(creator->create(context));
138 return algorithm->onInit(ic);
139 }};
140};
141
143{
144 return AlgorithmSpec{[spec, wrapper = std::move(wrapper)](InitContext& ic) mutable -> AlgorithmSpec::ProcessCallback {
145 // We either use provided onInit to create the ProcessCallback, or we
146 // call directly the one provided
147 auto old = spec.onInit ? spec.onInit(ic) : spec.onProcess;
148 return [old, wrapper = std::move(wrapper)](ProcessingContext& pc) mutable {
149 // Make sure the wrapper calls the old callback at some point.
150 wrapper(old, pc);
151 };
152 }};
153}
154} // namespace o2::framework
benchmark::State & state
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint const GLchar * name
Definition glcorearb.h:781
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::string filename()
std::function< void(ProcessingContext &)> ProcessCallback
static std::vector< LoadablePlugin > parsePluginSpecString(char const *str)
Parse a comma separated list of <library>:<plugin-name> plugin declarations.
static auto loadAlgorithmFromPlugin(std::string library, std::string plugin, ConfigContext const &context) -> AlgorithmSpec
static void load(std::vector< PluginInfo > &infos, const char *dso, std::function< void(DPLPluginHandle *)> &onSuccess)
static auto wrapAlgorithm(AlgorithmSpec const &spec, WrapperProcessCallback &&wrapper) -> AlgorithmSpec
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
const std::string str