Skip to content

Commit b20df41

Browse files
knopers8Barthelemy
authored andcommitted
DPL integration (AliceO2Group#7)
QC-47 * Added dependency on O2 (alidist will need to be updated as well - i will create PR shortly) * Created TaskDataProcessor class, which executes user modules similarly to TaskDevice, but using DPL and O2 Data Model. * Created TaskDataProcessorFactory, which generates DataProcessorSpec of QC task. * Created TaskInterfaceDPL, similar to TaskInterface, to be inherited by user modules. * Moved Activity class to separate file, because it is used by two different classes from now on. * Moved implementation of TaskFactory.create to header and made it a template - now it can be used to get both TaskInterface or TaskInterfaceDPL children. * Created TaskDPL - exemplary workflow using QC/DPL Task * Created SkeletonDPL - exemplary user module
1 parent 15c4ad4 commit b20df41

27 files changed

Lines changed: 1195 additions & 158 deletions

Framework/CMakeLists.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ set(SRCS
6464
src/MonitorObject.cxx
6565
src/Quality.cxx
6666
src/ObjectsManager.cxx
67-
src/TaskFactory.cxx
6867
src/Checker.cxx
6968
src/CheckInterface.cxx
7069
src/DatabaseFactory.cxx
@@ -76,6 +75,9 @@ set(SRCS
7675
src/CcdbDatabase.cxx
7776
src/InformationService.cxx
7877
src/InformationServiceDump.cxx
78+
src/TaskDataProcessor.cxx
79+
src/TaskDataProcessorFactory.cxx
80+
src/TaskInterfaceDPL.cxx
7981
)
8082

8183
set(HEADERS # needed for the dictionary generation
@@ -85,6 +87,8 @@ set(HEADERS # needed for the dictionary generation
8587
include/QualityControl/SpyMainFrame.h
8688
include/QualityControl/DatabaseInterface.h
8789
include/QualityControl/CcdbDatabase.h
90+
include/QualityControl/TaskDataProcessor.h
91+
include/QualityControl/TaskDataProcessorFactory.h
8892
)
8993

9094
if(MYSQL_FOUND)
@@ -150,6 +154,14 @@ O2_GENERATE_EXECUTABLE(
150154
BUCKET_NAME ${BUCKET_NAME}
151155
)
152156

157+
O2_GENERATE_EXECUTABLE(
158+
EXE_NAME taskDPL
159+
SOURCES src/TaskDPL.cxx
160+
MODULE_LIBRARY_NAME ${LIBRARY_NAME}
161+
BUCKET_NAME ${BUCKET_NAME}
162+
)
163+
Install(FILES qcTaskDplConfig.ini DESTINATION etc/)
164+
153165
if (FAIRROOT_FOUND)
154166
O2_GENERATE_EXECUTABLE(
155167
EXE_NAME alfaTestReceiver

Framework/apmon.cfg

Lines changed: 0 additions & 17 deletions
This file was deleted.

Framework/example-default.ini

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -77,32 +77,4 @@ broadcastAddress=tcp://*:5600
7777
id=0
7878

7979
[Checks]
80-
checkMeanIsAbove/threshold=1
81-
82-
;===============================
83-
; Monitoring
84-
;-------------------------------
85-
86-
[ApMon]
87-
enable=0
88-
pathToConfig=apmon.cfg
89-
90-
[InfluxDB]
91-
enableUDP=1
92-
enableHTTP=0
93-
hostname=aido2mon-gpn
94-
port=8087
95-
db=qc
96-
97-
[InfoLoggerBackend]
98-
enable=1
99-
100-
[ProcessMonitor]
101-
enable=1
102-
interval=10
103-
104-
[DerivedMetrics]
105-
maxCacheSize=1000
106-
107-
[Flume]
108-
enable=0
80+
checkMeanIsAbove/threshold=1
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
///
2+
/// \file Activity.h
3+
/// \author Barthelemy von Haller
4+
///
5+
6+
#ifndef QUALITYCONTROL_CORE_ACTIVITY_H
7+
#define QUALITYCONTROL_CORE_ACTIVITY_H
8+
9+
namespace o2 {
10+
namespace quality_control {
11+
namespace core {
12+
13+
/// \brief Dummy class that should be removed when there is the official one.
14+
/// This corresponds to a Run1/2 "run".
15+
/// \author Barthelemy von Haller
16+
class Activity
17+
{
18+
public:
19+
Activity() = default;
20+
Activity(int id, int type) : mId(id), mType(type)
21+
{}
22+
/// Copy constructor
23+
Activity (const Activity& other) = default;
24+
/// Move constructor
25+
Activity (Activity&& other) noexcept = default;
26+
/// Copy assignment operator
27+
Activity& operator= (const Activity& other) = default;
28+
/// Move assignment operator
29+
Activity& operator= (Activity&& other) noexcept = default;
30+
31+
virtual ~Activity() = default;
32+
33+
int mId{0};
34+
int mType{0};
35+
};
36+
37+
} // namespace core
38+
} // namespace QualityControl
39+
} // namespace o2
40+
41+
#endif // QUALITYCONTROL_CORE_ACTIVITY_H
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
///
2+
/// \file TaskDataProcessor.h
3+
/// \author Piotr Konopka
4+
///
5+
6+
#ifndef TASKDATAPROCESSOR_H
7+
#define TASKDATAPROCESSOR_H
8+
9+
#include <thread>
10+
#include <mutex>
11+
// boost (should be first but then it makes errors in fairmq)
12+
#include <boost/serialization/array_wrapper.hpp>
13+
#include <boost/accumulators/accumulators.hpp>
14+
#include <boost/accumulators/statistics.hpp>
15+
#include <boost/asio.hpp>
16+
// O2
17+
#include "Common/Timer.h"
18+
#include "Configuration/ConfigurationInterface.h"
19+
#include "Framework/DataProcessorSpec.h"
20+
#include "Monitoring/MonitoringFactory.h"
21+
// QC
22+
#include "QualityControl/TaskInterfaceDPL.h"
23+
#include "QualityControl/TaskConfig.h"
24+
25+
namespace ba = boost::accumulators;
26+
27+
namespace o2 {
28+
namespace quality_control {
29+
namespace core {
30+
31+
using namespace o2::framework;
32+
using namespace std::chrono;
33+
34+
/// \brief A class driving the execution of a QC task inside DPL.
35+
///
36+
/// TaskDataProcessor is a port of TaskDevice class, adapted for usage inside Data Processing Layer.
37+
/// It is responsible for retrieving details about the task via the Configuration system and the Task (indirectly).
38+
/// It then steers the execution of the task and provides it with O2 Data Model data, provided by framework.
39+
/// It finally publishes the MonitorObjects owned and filled by the QC task and managed by the ObjectsManager.
40+
/// Usage:
41+
/// \code{.cxx}
42+
/// auto qcTask = std::make_shared<TaskDataProcessor>(taskName, configurationSource);
43+
/// DataProcessorSpec newTask{
44+
/// taskName,
45+
/// qcTask->getInputsSpecs(),
46+
/// Outputs{ qcTask->getOutputSpec() },
47+
/// AlgorithmSpec{
48+
/// (AlgorithmSpec::InitCallback) [qcTask = std::move(qcTask)](InitContext& initContext) {
49+
///
50+
/// qcTask->initCallback(initContext);
51+
///
52+
/// return (AlgorithmSpec::ProcessCallback) [qcTask = std::move(qcTask)] (ProcessingContext &processingContext) {
53+
/// qcTask->processCallback(processingContext);
54+
/// };
55+
/// }
56+
/// }
57+
/// };
58+
/// \endcode
59+
///
60+
/// \author Piotr Konopka
61+
/// \author Barthelemy von Haller
62+
class TaskDataProcessor {
63+
public:
64+
TaskDataProcessor(std::string taskName, std::string configurationSource);
65+
~TaskDataProcessor();
66+
67+
/// \brief To be invoked during initialization of Data Processor
68+
void initCallback(InitContext& iCtx);
69+
/// \brief To be invoked inside Data Processor's main ProcessCallback
70+
void processCallback(ProcessingContext& pCtx);
71+
/// \brief To be invoked inside Data Processor's TimerCallback
72+
void timerCallback(ProcessingContext& pCtx);
73+
74+
const Inputs& getInputsSpecs() { return mInputSpecs; };
75+
const OutputSpec getOutputSpec() { return mMonitorObjectsSpec; };
76+
77+
private:
78+
void populateConfig(std::string taskName);
79+
void startOfActivity();
80+
void endOfActivity();
81+
void finishCycle(DataAllocator& outputs);
82+
unsigned long publish(DataAllocator& outputs);
83+
static void CustomCleanupTMessage(void* data, void* object);
84+
85+
private:
86+
std::string mTaskName;
87+
TaskConfig mTaskConfig;
88+
std::shared_ptr<o2::configuration::ConfigurationInterface> mConfigFile; // used in init only
89+
std::shared_ptr<o2::monitoring::Monitoring> mCollector;
90+
TaskInterfaceDPL* mTask;
91+
std::shared_ptr<ObjectsManager> mObjectsManager;
92+
std::recursive_mutex mTaskMutex; // \todo should be plain mutex, when timer callback is implemented in dpl
93+
94+
// consider moving these two to TaskConfig
95+
Inputs mInputSpecs;
96+
OutputSpec mMonitorObjectsSpec;
97+
98+
int mNumberBlocks;
99+
int mLastNumberObjects;
100+
bool mCycleOn;
101+
int mCycleNumber;
102+
103+
// stats
104+
AliceO2::Common::Timer mStatsTimer;
105+
int mTotalNumberObjectsPublished;
106+
AliceO2::Common::Timer mTimerTotalDurationActivity;
107+
ba::accumulator_set<double, ba::features<ba::tag::mean, ba::tag::variance>> mPCpus;
108+
ba::accumulator_set<double, ba::features<ba::tag::mean, ba::tag::variance>> mPMems;
109+
};
110+
111+
}
112+
}
113+
}
114+
115+
#endif // TASKDATAPROCESSOR_H
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
///
2+
/// \file TaskDataProcessorFactory.h
3+
/// \author Piotr Konopka
4+
///
5+
6+
#ifndef PROJECT_TASKDATAPROCESSORFACTORY_H
7+
#define PROJECT_TASKDATAPROCESSORFACTORY_H
8+
9+
#include "Framework/DataProcessorSpec.h"
10+
11+
namespace o2 {
12+
namespace quality_control {
13+
namespace core {
14+
15+
/// \brief Factory in charge of creating DataProcessorSpec of QC task
16+
class TaskDataProcessorFactory
17+
{
18+
public:
19+
TaskDataProcessorFactory();
20+
virtual ~TaskDataProcessorFactory();
21+
22+
o2::framework::DataProcessorSpec create(std::string taskName, std::string configurationSource);
23+
};
24+
25+
} // namespace core
26+
} // namespace QualityControl
27+
} // namespace o2
28+
29+
#endif //PROJECT_TASKDATAPROCESSORFACTORY_H

Framework/include/QualityControl/TaskFactory.h

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@
88

99
#include <iostream>
1010
#include <memory>
11+
// ROOT
12+
#include <TSystem.h>
13+
#include <TClass.h>
14+
#include <TROOT.h>
1115
// O2
1216
#include <Common/Exceptions.h>
1317
#include "QualityControl/TaskConfig.h"
1418
#include "QualityControl/TaskDevice.h"
19+
#include "QualityControl/QcInfoLogger.h"
1520

1621
namespace o2 {
1722
namespace quality_control {
@@ -27,15 +32,51 @@ class ObjectsManager;
2732
/// The class loaded in the library must inherit from TaskInterface.
2833
class TaskFactory
2934
{
30-
public:
31-
TaskFactory();
32-
virtual ~TaskFactory();
33-
34-
/// \brief Create a new instance of a TaskInterface.
35-
/// The TaskInterface actual class is decided based on the parameters passed.
36-
/// \todo make it static ?
37-
/// \author Barthelemy von Haller
38-
TaskInterface *create(TaskConfig &taskConfig, std::shared_ptr<ObjectsManager> objectsManager);
35+
public:
36+
TaskFactory() {};
37+
virtual ~TaskFactory() {};
38+
39+
using FatalException = AliceO2::Common::FatalException;
40+
using errinfo_details = AliceO2::Common::errinfo_details;
41+
/// \brief Create a new instance of a TaskInterface.
42+
/// The TaskInterface actual class is decided based on the parameters passed.
43+
/// \todo make it static ?
44+
/// \author Barthelemy von Haller
45+
template <class T>
46+
T* create(TaskConfig& taskConfig, std::shared_ptr <ObjectsManager> objectsManager)
47+
{
48+
T* result = nullptr;
49+
QcInfoLogger& logger = QcInfoLogger::GetInstance();
50+
51+
// Load the library
52+
std::string library = "lib" + taskConfig.moduleName + ".so";
53+
logger << "Loading library " << library << AliceO2::InfoLogger::InfoLogger::endm;
54+
if (gSystem->Load(library.c_str())) {
55+
BOOST_THROW_EXCEPTION(FatalException() << errinfo_details("Failed to load Detector Publisher Library"));
56+
}
57+
58+
// Get the class and instantiate
59+
logger << "Loading class " << taskConfig.className << AliceO2::InfoLogger::InfoLogger::endm;
60+
TClass* cl = TClass::GetClass(taskConfig.className.c_str());
61+
std::string tempString("Failed to instantiate Quality Control Module");
62+
if (!cl) {
63+
tempString += " because no dictionary for class named \"";
64+
tempString += taskConfig.className;
65+
tempString += "\" could be retrieved";
66+
BOOST_THROW_EXCEPTION(FatalException() << errinfo_details(tempString));
67+
}
68+
logger << "Instantiating class " << taskConfig.className << " (" << cl << ")"
69+
<< AliceO2::InfoLogger::InfoLogger::endm;
70+
result = static_cast<T*>(cl->New());
71+
if (!result) {
72+
BOOST_THROW_EXCEPTION(FatalException() << errinfo_details(tempString));
73+
}
74+
result->setName(taskConfig.taskName);
75+
result->setObjectsManager(objectsManager);
76+
logger << "QualityControl Module " << taskConfig.moduleName << " loaded " << AliceO2::InfoLogger::InfoLogger::endm;
77+
78+
return result;
79+
}
3980
};
4081

4182
} // namespace core

Framework/include/QualityControl/TaskInterface.h

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,13 @@
99
#include <memory>
1010

1111
#include "QualityControl/ObjectsManager.h"
12+
#include "QualityControl/Activity.h"
1213
#include <Common/DataSet.h>
1314

1415
namespace o2 {
1516
namespace quality_control {
1617
namespace core {
1718

18-
/// \brief Dummy class that should be removed when there is the official one.
19-
/// This corresponds to a Run1/2 "run".
20-
/// \author Barthelemy von Haller
21-
class Activity
22-
{
23-
public:
24-
Activity() = default;
25-
Activity(int id, int type) : mId(id), mType(type)
26-
{}
27-
/// Copy constructor
28-
Activity (const Activity& other) = default;
29-
/// Move constructor
30-
Activity (Activity&& other) noexcept = default;
31-
/// Copy assignment operator
32-
Activity& operator= (const Activity& other) = default;
33-
/// Move assignment operator
34-
Activity& operator= (Activity&& other) noexcept = default;
35-
36-
virtual ~Activity() = default;
37-
38-
int mId{0};
39-
int mType{0};
40-
};
41-
4219
/// \brief Skeleton of a QC task.
4320
///
4421
/// Purely abstract class defining the skeleton and the common interface of a QC task.

0 commit comments

Comments
 (0)