Skip to content

Commit a4dcbc9

Browse files
mkrzewicmatthiasrichter
authored andcommitted
Implement most O2Device functionality as free functions
- Remove O2Device::AddMessage(...), move functionality to o2::Base::AddDataBlock(..), a free function in header O2Device/Utilities.h - Make ForEach a free function in O2Device/Utilities.h - Remove the ForEach(...) that took a member function pointer, that was an ugly idea.
1 parent da8ed32 commit a4dcbc9

File tree

7 files changed

+67
-99
lines changed

7 files changed

+67
-99
lines changed

Utilities/DataFlow/src/HeartbeatSampler.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ bool o2::DataFlow::HeartbeatSampler::ConditionalRun()
4848
O2Message outgoing;
4949

5050
// build multipart message from header and payload
51-
AddMessage(outgoing, {dh, specificHeader}, NewSimpleMessage(hbfPayload));
51+
o2::Base::AddDataBlock(outgoing, { dh, specificHeader }, NewSimpleMessage(hbfPayload));
5252

5353
// send message
5454
Send(outgoing, mOutputChannelName.c_str());

Utilities/DataFlow/src/SubframeBuilderDevice.cxx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,12 @@ bool o2::DataFlow::SubframeBuilderDevice::BuildAndSendFrame(FairMQParts &inParts
116116
// Add the metadata about the merged subtimeframes
117117
// FIXME: do we really need this?
118118
O2Message outgoing;
119-
AddMessage(outgoing, dh, NewSimpleMessage(md));
119+
o2::Base::AddDataBlock(outgoing, dh, NewSimpleMessage(md));
120120

121121
// Add the actual merged payload.
122-
AddMessage(outgoing, payloadheader,
123-
NewMessage(*outBuffer, outSize,
124-
[](void* data, void* hint) { delete[] reinterpret_cast<char *>(hint); }, *outBuffer));
122+
o2::Base::AddDataBlock(outgoing, payloadheader,
123+
NewMessage(*outBuffer, outSize,
124+
[](void* data, void* hint) { delete[] reinterpret_cast<char*>(hint); }, *outBuffer));
125125
// send message
126126
Send(outgoing, mOutputChannelName.c_str());
127127
// FIXME: do we actually need this? outgoing should go out of scope

Utilities/O2Device/include/O2Device/O2Device.h

Lines changed: 2 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,9 @@
3030

3131
#include <FairMQDevice.h>
3232
#include <options/FairMQProgOptions.h>
33-
#include "Headers/DataHeader.h"
33+
#include "O2Device/Utilities.h"
3434
#include "Monitoring/MonitoringFactory.h"
3535
#include <stdexcept>
36-
#include <gsl/gsl>
37-
#include "O2Device/Utilities.h"
3836

3937
namespace o2
4038
{
@@ -47,6 +45,7 @@ class O2Device : public FairMQDevice
4745
{
4846
public:
4947
using FairMQDevice::FairMQDevice;
48+
5049
~O2Device() override = default;
5150

5251
/// Monitoring instance
@@ -66,82 +65,7 @@ class O2Device : public FairMQDevice
6665
}
6766
}
6867

69-
/// Here is how to add an annotated data part (with header);
70-
/// @param[in,out] parts is a reference to the message;
71-
/// @param[] inputHeaderStack header block must be MOVED in (rvalue ref)
72-
/// @param[] inputDataMessage the data message must be MOVED in (unique_ptr by value)
73-
bool AddMessage(O2Message& parts, o2::header::Stack&& inputHeaderStack, FairMQMessagePtr inputDataMessage)
74-
{
75-
76-
// we have to move the incoming data
77-
using std::move;
78-
o2::header::Stack headerStack{ move(inputHeaderStack) };
79-
FairMQMessagePtr dataMessage{ move(inputDataMessage) };
80-
81-
FairMQMessagePtr headerMessage =
82-
o2::memoryResources::getMessage(move(inputHeaderStack));
83-
84-
parts.AddPart(move(headerMessage));
85-
parts.AddPart(move(dataMessage));
86-
return true;
87-
}
88-
89-
// this executes user code (e.g. a lambda) on each data block (header-payload pair)
90-
template <typename F>
91-
bool ForEach(O2Message& parts, F function)
92-
{
93-
if ((parts.Size() % 2) != 0) {
94-
throw std::invalid_argument(
95-
"number of parts in message not even (n%2 != 0), cannot be considered an O2 compliant message");
96-
}
97-
98-
return ForEach(parts.begin(), parts.end(), function);
99-
}
100-
101-
// this executes user code (a member function) on a data block (header-payload pair)
102-
// at some point should de DEPRECATED in favor of the lambda version
103-
template <typename T, typename std::enable_if<std::is_base_of<O2Device, T>::value, int>::type = 0>
104-
bool ForEach(O2Message& parts, bool (T::*memberFunction)(const byte* headerBuffer, size_t headerBufferSize,
105-
const byte* dataBuffer, size_t dataBufferSize))
106-
{
107-
if ((parts.Size() % 2) != 0) {
108-
throw std::invalid_argument(
109-
"number of parts in message not even (n%2 != 0), cannot be considered an O2 compliant message");
110-
}
111-
112-
return ForEach(parts.fParts.begin(), parts.fParts.end(),
113-
[&](gsl::span<const byte> headerBuffer, gsl::span<const byte> dataBuffer) {
114-
(static_cast<T*>(this)->*memberFunction)(headerBuffer.data(), headerBuffer.size(),
115-
dataBuffer.data(), dataBuffer.size());
116-
});
117-
}
118-
11968
private:
120-
template <typename I, typename F>
121-
bool ForEach(I begin, I end, F function)
122-
{
123-
using span = gsl::span<const byte>;
124-
using gsl::narrow_cast;
125-
for (auto it = begin; it != end; ++it) {
126-
byte* headerBuffer{ nullptr };
127-
span::index_type headerBufferSize{ 0 };
128-
if (*it != nullptr) {
129-
headerBuffer = reinterpret_cast<byte*>((*it)->GetData());
130-
headerBufferSize = narrow_cast<span::index_type>((*it)->GetSize());
131-
}
132-
++it;
133-
byte* dataBuffer{ nullptr };
134-
span::index_type dataBufferSize{ 0 };
135-
if (*it != nullptr) {
136-
dataBuffer = reinterpret_cast<byte*>((*it)->GetData());
137-
dataBufferSize = narrow_cast<span::index_type>((*it)->GetSize());
138-
}
139-
140-
// call the user provided function
141-
function(span{ headerBuffer, headerBufferSize }, span{ dataBuffer, dataBufferSize });
142-
}
143-
return true;
144-
}
14569
};
14670
}
14771
}

Utilities/O2Device/include/O2Device/Utilities.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "MemoryResources/MemoryResources.h"
3131
#include "Headers/DataHeader.h"
3232
#include <utility>
33+
#include <gsl/gsl>
3334

3435
namespace o2
3536
{
@@ -56,6 +57,12 @@ template <typename ContainerT, typename std::enable_if<std::is_same<ContainerT,
5657
bool AddDataBlock(O2Message& parts, o2::header::Stack&& inputStack, ContainerT&& dataMessage, o2::memoryResources::FairMQMemoryResource* targetResource = nullptr)
5758
{
5859
using std::move;
60+
61+
//make sure the payload size in DataHeader corresponds to message size
62+
using o2::header::DataHeader;
63+
DataHeader* dataHeader = const_cast<DataHeader*>(o2::header::get<DataHeader*>(inputStack.data()));
64+
dataHeader->payloadSize = dataMessage->GetSize();
65+
5966
auto headerMessage = getMessage(move(inputStack), targetResource);
6067

6168
parts.AddPart(move(headerMessage));
@@ -64,6 +71,49 @@ bool AddDataBlock(O2Message& parts, o2::header::Stack&& inputStack, ContainerT&&
6471
return true;
6572
}
6673

74+
namespace internal
75+
{
76+
77+
template <typename I, typename F>
78+
auto ForEach(I begin, I end, F function)
79+
{
80+
using span = gsl::span<const byte>;
81+
using gsl::narrow_cast;
82+
for (auto it = begin; it != end; ++it) {
83+
byte* headerBuffer{ nullptr };
84+
span::index_type headerBufferSize{ 0 };
85+
if (*it != nullptr) {
86+
headerBuffer = reinterpret_cast<byte*>((*it)->GetData());
87+
headerBufferSize = narrow_cast<span::index_type>((*it)->GetSize());
88+
}
89+
++it;
90+
byte* dataBuffer{ nullptr };
91+
span::index_type dataBufferSize{ 0 };
92+
if (*it != nullptr) {
93+
dataBuffer = reinterpret_cast<byte*>((*it)->GetData());
94+
dataBufferSize = narrow_cast<span::index_type>((*it)->GetSize());
95+
}
96+
97+
// call the user provided function
98+
function(span{ headerBuffer, headerBufferSize }, span{ dataBuffer, dataBufferSize });
99+
}
100+
return std::move(function);
101+
}
102+
}; //namespace internal
103+
104+
/// Execute user code (e.g. a lambda) on each data block (header-payload pair)
105+
/// returns the function (same as std::for_each)
106+
template <typename F>
107+
auto ForEach(O2Message& parts, F function)
108+
{
109+
if ((parts.Size() % 2) != 0) {
110+
throw std::invalid_argument(
111+
"number of parts in message not even (n%2 != 0), cannot be considered an O2 compliant message");
112+
}
113+
114+
return internal::ForEach(parts.begin(), parts.end(), function);
115+
}
116+
67117
}; //namespace o2
68118
}; //namespace Base
69119

Utilities/O2MessageMonitor/include/O2MessageMonitor/O2MessageMonitor.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
#ifndef O2MESSAGEMONITOR_H_
2929
#define O2MESSAGEMONITOR_H_
3030

31-
#include "Headers/DataHeader.h"
3231
#include "O2Device/O2Device.h"
3332

3433
/// This is a simple FairMQ monitoring class
@@ -47,7 +46,6 @@ class O2MessageMonitor : public o2::Base::O2Device
4746
protected:
4847
void Run() override;
4948
void InitTask() override;
50-
bool HandleData(o2::Base::O2Message& parts, int index);
5149

5250
private:
5351
std::string mPayload{ "I am the info payload" };

Utilities/O2MessageMonitor/src/O2MessageMonitor.cxx

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,12 @@
3030

3131
#include <FairMQLogger.h>
3232
#include <options/FairMQProgOptions.h>
33-
#include "Headers/DataHeader.h"
34-
#include "Headers/NameHeader.h"
3533
#include "O2MessageMonitor/O2MessageMonitor.h"
3634

3735
using namespace std;
3836
using namespace o2::header;
3937
using namespace o2::Base;
4038

41-
using NameHeader48 = NameHeader<48>; // header holding 16 characters
42-
4339
//__________________________________________________________________________________________________
4440
void O2MessageMonitor::InitTask()
4541
{
@@ -57,12 +53,12 @@ void O2MessageMonitor::Run()
5753
{
5854
// check socket type of data channel
5955
std::string type;
60-
std::vector<FairMQChannel> subChannels = fChannels["data"];
56+
std::vector<FairMQChannel>& subChannels = fChannels["data"];
6157
if (subChannels.size() > 0) {
6258
type = subChannels[0].GetType();
6359
}
6460

65-
o2::memoryResources::ChannelResource dataResource(subChannels[0].Transport());
61+
auto dataResource = o2::memoryResources::getTransportAllocator(subChannels[0].Transport());
6662

6763
while (CheckCurrentState(RUNNING) && (--mIterations) != 0) {
6864
this_thread::sleep_for(chrono::milliseconds(mDelay));
@@ -71,7 +67,7 @@ void O2MessageMonitor::Run()
7167

7268
// maybe send a request
7369
if (type == "req") {
74-
AddDataBlock(message, { &dataResource, DataHeader{ gDataDescriptionInfo, gDataOriginAny, DataHeader::SubSpecificationType{ 0 }, 0 } },
70+
AddDataBlock(message, { dataResource, DataHeader{ gDataDescriptionInfo, gDataOriginAny, DataHeader::SubSpecificationType{ 0 }, 0 } },
7571
NewSimpleMessageFor("data", 0, mPayload));
7672
Send(message, "data");
7773
message.fParts.clear();
@@ -80,17 +76,17 @@ void O2MessageMonitor::Run()
8076
// message in;
8177
Receive(message, "data");
8278
LOG(INFO) << "== New message=============================";
83-
ForEach(message, [&](auto header, auto data) {
79+
o2::Base::ForEach(message, [&](auto header, auto data) {
8480
hexDump("headerBuffer", header.data(), header.size());
8581
hexDump("dataBuffer", data.data(), data.size(), mLimitOutputCharacters);
8682
});
8783
message.fParts.clear();
8884

8985
// maybe a reply message
9086
if (type == "rep") {
91-
AddMessage(message,
92-
{ &dataResource, DataHeader{ gDataDescriptionInfo, gDataOriginAny, DataHeader::SubSpecificationType{ 0 }, 0 } },
93-
NewSimpleMessageFor("data", 0, "I am a reply"));
87+
o2::Base::AddDataBlock(message,
88+
{ dataResource, DataHeader{ gDataDescriptionInfo, gDataOriginAny, DataHeader::SubSpecificationType{ 0 }, 0 } },
89+
NewSimpleMessageFor("data", 0, ""));
9490
Send(message, "data");
9591
}
9692
}

Utilities/Publishers/src/DataPublisherDevice.cxx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ void DataPublisherDevice::InitTask()
122122

123123
bool DataPublisherDevice::HandleData(FairMQParts& msgParts, int index)
124124
{
125-
ForEach(msgParts, &DataPublisherDevice::HandleO2LogicalBlock);
125+
o2::Base::ForEach(msgParts, [&](auto header, auto payload) { this->HandleO2LogicalBlock(header.data(), header.size(), payload.data(), payload.size()); });
126126

127127
return true;
128128
}
@@ -191,8 +191,8 @@ bool DataPublisherDevice::HandleO2LogicalBlock(const byte* headerBuffer,
191191
// TODO: fix payload size in dh
192192
auto *buffer = new char[mFileBuffer.size()];
193193
memcpy(buffer, mFileBuffer.data(), mFileBuffer.size());
194-
AddMessage(outgoing, dh, NewMessage(buffer, mFileBuffer.size(),
195-
[](void* data, void* hint) { delete[] reinterpret_cast<char *>(data); }, nullptr));
194+
o2::Base::AddDataBlock(outgoing, dh, NewMessage(buffer, mFileBuffer.size(),
195+
[](void* data, void* hint) { delete[] reinterpret_cast<char*>(data); }, nullptr));
196196

197197
// send message
198198
Send(outgoing, mOutputChannelName.c_str());

0 commit comments

Comments
 (0)