Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DPL: initial support for plugin based algorithms #5071

Merged
merged 2 commits into from
Dec 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions Framework/AnalysisSupport/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright CERN and copyright holders of ALICE O2. This software is distributed
# under the terms of the GNU General Public License v3 (GPL Version 3), copied
# verbatim in the file "COPYING".
#
# See http://alice-o2.web.cern.ch/license for full licensing information.
#
# In applying this license CERN does not waive the privileges and immunities
# granted to it by virtue of its status as an Intergovernmental Organization or
# submit itself to any jurisdiction.

# Given GCC 7.3 does not provide std::filesystem we use Boost instead
# Drop this once we move to GCC 8.2+
o2_add_library(FrameworkAnalysisSupport
SOURCES src/Plugin.cxx
PRIVATE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/src
PUBLIC_LINK_LIBRARIES O2::Framework)
21 changes: 21 additions & 0 deletions Framework/AnalysisSupport/src/Plugin.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright CERN and copyright holders of ALICE O2. This software is
// distributed under the terms of the GNU General Public License v3 (GPL
// Version 3), copied verbatim in the file "COPYING".
//
// See http://alice-o2.web.cern.ch/license for full licensing information.
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
#include "Framework/Plugins.h"
#include "Framework/AlgorithmSpec.h"
#include "Framework/AODReaderHelpers.h"

struct ROOTFileReader : o2::framework::AlgorithmPlugin {
o2::framework::AlgorithmSpec create() override
{
return o2::framework::readers::AODReaderHelpers::rootFileReaderCallback();
}
};

DEFINE_DPL_PLUGIN(ROOTFileReader, CustomAlgorithm);
2 changes: 2 additions & 0 deletions Framework/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ add_subdirectory(Core)

add_subdirectory(Utils)

add_subdirectory(AnalysisSupport)

add_subdirectory(TestWorkflows)
12 changes: 7 additions & 5 deletions Framework/Core/include/Framework/AlgorithmSpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@

#include <functional>

namespace o2
{
namespace framework
namespace o2::framework
{

/// This is the class holding the actual algorithm to be used. Notice that the
Expand Down Expand Up @@ -88,6 +86,11 @@ struct AlgorithmSpec {
ErrorCallback onError = nullptr;
};

/// Helper class for an algorithm which is loaded as a plugin.
struct AlgorithmPlugin {
virtual AlgorithmSpec create() = 0;
};

template <typename T>
struct ContextElementTraits {
static decltype(auto) get(ProcessingContext& ctx)
Expand Down Expand Up @@ -180,7 +183,6 @@ AlgorithmSpec::InitCallback adaptStateful(LAMBDA l)
return adaptStatefulF(FFL(l));
}

} // namespace framework
} // namespace o2
} // namespace o2::framework

#endif // FRAMEWORK_ALGORITHMSPEC_H
61 changes: 61 additions & 0 deletions Framework/Core/include/Framework/Plugins.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright CERN and copyright holders of ALICE O2. This software is
// distributed under the terms of the GNU General Public License v3 (GPL
// Version 3), copied verbatim in the file "COPYING".
//
// See http://alice-o2.web.cern.ch/license for full licensing information.
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
#ifndef O2_FRAMEWORK_PLUGINS_H_
#define O2_FRAMEWORK_PLUGINS_H_

#include "Framework/AlgorithmSpec.h"
#include <cstring>

namespace o2::framework
{

enum struct DplPluginKind : int {
// A plugin which can customise the workflow. Needs to return
// an object of kind o2::framework::WorkflowCustomizationService
CustomAlgorithm
};

} // namespace o2::framework

/// An handle for a generic DPL plugin.
/// The handle is returned by the dpl_plugin_callback()
struct DPLPluginHandle {
void* instance;
char const* name;
enum o2::framework::DplPluginKind kind;
DPLPluginHandle* previous;
};

#define DEFINE_DPL_PLUGIN(NAME, KIND) \
extern "C" { \
DPLPluginHandle* dpl_plugin_callback(DPLPluginHandle* previous) \
{ \
return new DPLPluginHandle{new NAME{}, strdup(#NAME), o2::framework::DplPluginKind::KIND, previous}; \
} \
}

namespace o2::framework
{
struct PluginManager {
template <typename T>
static T* getByName(DPLPluginHandle* handle, char const* name)
{
while (handle != nullptr) {
if (strncmp(handle->name, name, strlen(name)) == 0) {
return reinterpret_cast<T*>(handle->instance);
}
handle = handle->previous;
}
return nullptr;
}
};
} // namespace o2::framework

#endif // O2_FRAMEWORK_PLUGINS_H_
24 changes: 23 additions & 1 deletion Framework/Core/src/WorkflowHelpers.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "Framework/RawDeviceService.h"
#include "Framework/StringHelpers.h"
#include "Framework/CommonMessageBackends.h"
#include "Framework/ExternalFairMQDeviceProxy.h"
#include "Framework/Plugins.h"

#include "Headers/DataHeader.h"
#include <algorithm>
Expand Down Expand Up @@ -258,7 +260,7 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext
static_cast<DataAllocator::SubSpecificationType>(compile_time_hash("internal-dpl-aod-reader")),
aodLifetime}},
{},
readers::AODReaderHelpers::rootFileReaderCallback(),
AlgorithmSpec::dummyAlgorithm(),
{ConfigParamSpec{"aod-file", VariantType::String, {"Input AOD file"}},
ConfigParamSpec{"aod-reader-json", VariantType::String, {"json configuration file"}},
ConfigParamSpec{"time-limit", VariantType::Int64, 0ll, {"Maximum run time limit in seconds"}},
Expand Down Expand Up @@ -417,6 +419,26 @@ void WorkflowHelpers::injectServiceDevices(WorkflowSpec& workflow, ConfigContext

// add the reader
if (aodReader.outputs.empty() == false) {
uv_lib_t supportLib;
int result = 0;
#ifdef __APPLE__
result = uv_dlopen("libO2FrameworkAnalysisSupport.dylib", &supportLib);
#else
result = uv_dlopen("libO2FrameworkAnalysisSupport.so", &supportLib);
#endif
if (result == -1) {
LOG(ERROR) << uv_dlerror(&supportLib);
}
void* callback = nullptr;
DPLPluginHandle* (*dpl_plugin_callback)(DPLPluginHandle*);

result = uv_dlsym(&supportLib, "dpl_plugin_callback", (void**)&dpl_plugin_callback);
if (result == -1) {
LOG(ERROR) << uv_dlerror(&supportLib);
}
DPLPluginHandle* pluginInstance = dpl_plugin_callback(nullptr);
AlgorithmPlugin* creator = PluginManager::getByName<AlgorithmPlugin>(pluginInstance, "ROOTFileReader");
aodReader.algorithm = creator->create();
aodReader.outputs.emplace_back(OutputSpec{"TFN", "TFNumber"});
extraSpecs.push_back(timePipeline(aodReader, ctx.options().get<int64_t>("readers")));
auto concrete = DataSpecUtils::asConcreteDataMatcher(aodReader.inputs[0]);
Expand Down