-
Notifications
You must be signed in to change notification settings - Fork 494
Merge multiple HBFs into STF #384
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
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| .\" Manpage for SubframeBuilderDevice. | ||
| .TH AliceO2 1 "12 May 2017" "1.0" "SubframeBuilderDevice man page" | ||
|
|
||
| .SH NAME | ||
|
|
||
| SubframeBuilderDevice - aggregate HBF in input as a single STF | ||
|
|
||
| .SH SYNOPSIS | ||
|
|
||
| SubframeBuilderDevice [options] | ||
|
|
||
| .SH DESCRIPTION | ||
|
|
||
| SubframeBuilderDevice will take in input a number of HeartBeat Frames | ||
| (HBF) and merge them in a single STF, with a policy defined by the | ||
| passed options. | ||
|
|
||
| .SH OPTIONS | ||
|
|
||
| --self-triggered Time frame duration | ||
|
|
||
| .TP 5 | ||
|
|
||
| --in-chan-name [NAME] Name of the input channel | ||
|
|
||
| .TP 5 | ||
|
|
||
| --out-chan-name [NAME] Name of the output channel | ||
|
|
||
| .TP 5 | ||
|
|
||
| --detector-name [NAME] Name of detector as data source | ||
|
|
||
| .TP 5 | ||
|
|
||
| --flp-id arg [NAME] ID of the FLP used as data source | ||
|
|
||
| .TP 5 | ||
|
|
||
| --strip-hbf Strip HeartBeatHeader (HBH) & HeartBeatTrailer (HBT) from each HBF | ||
|
|
||
| .SH SEE ALSO | ||
|
|
||
| FLPSenderDEvice(1), EPNReceiverDevice(1), HeartbeatSampler(1), TimeframeValidator(1) | ||
|
|
||
| .SH BUGS | ||
|
|
||
| Lots of bugs |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| // 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 https://alice-o2.web.cern.ch/ 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 PAYLOAD_MERGER_H | ||
| #define PAYLOAD_MERGER_H | ||
|
|
||
| #include <map> | ||
| #include <cstdint> | ||
| #include <vector> | ||
| #include <functional> | ||
| #include <cstring> | ||
|
|
||
| #include <fairmq/FairMQMessage.h> | ||
|
|
||
| namespace o2 { namespace dataflow { | ||
| /// Helper class that given a set of FairMQMessage, merges (part of) their | ||
| /// payload into a separate memory area. | ||
| /// | ||
| /// - Append multiple messages via the aggregate method | ||
| /// - Finalise buffer creation with the finalise call. | ||
| template <typename ID> | ||
| class PayloadMerger { | ||
| public: | ||
| using MergeableId = ID; | ||
| using MessageMap = std::multimap<MergeableId, std::unique_ptr<FairMQMessage>>; | ||
| using PayloadExtractor = std::function<size_t(char **, char *, size_t)>; | ||
| using IdExtractor = std::function<MergeableId(std::unique_ptr<FairMQMessage>&)>; | ||
| using MergeCompletionCheker = std::function<bool(MergeableId, MessageMap &)>; | ||
|
|
||
| /// Helper class to merge FairMQMessages sharing a user defined class of equivalence, | ||
| /// specified by @makeId. Completeness of the class of equivalence can be asserted by | ||
| /// the @checkIfComplete policy. It's also possible to specify a user defined way of | ||
| /// extracting the parts of the payload to be merged via the extractPayload method. | ||
| PayloadMerger(IdExtractor makeId, | ||
| MergeCompletionCheker checkIfComplete, | ||
| PayloadExtractor extractPayload = fullPayloadExtractor) | ||
| : | ||
| mMakeId{makeId}, | ||
| mCheckIfComplete{checkIfComplete}, | ||
| mExtractPayload{extractPayload} | ||
| { | ||
| } | ||
|
|
||
| /// Aggregates @payload to all the ones with the same id. | ||
| /// @return the id extracted from the payload via the constructor | ||
| /// specified id policy (mMakeId callback). | ||
| MergeableId aggregate(std::unique_ptr<FairMQMessage> &payload) { | ||
| auto id = mMakeId(payload); | ||
| mPartsMap.emplace(std::make_pair(id, std::move(payload))); | ||
| return id; | ||
| } | ||
|
|
||
| /// This merges a set of messages sharing the same id @id to a unique buffer | ||
| /// @out, so that it can be either consumed or sent as a message itself. | ||
| /// The decision on whether the merge must happen is done by the constructor | ||
| /// specified policy mCheckIfComplete which can, for example, decide | ||
| /// to merge when a certain number of subparts are reached. | ||
| /// Merging at the moment requires an extra copy, but in principle this could | ||
| /// be easily extended to support scatter - gather. | ||
| size_t finalise(char **out, MergeableId &id) { | ||
| *out = nullptr; | ||
| if (mCheckIfComplete(id, mPartsMap) == false) { | ||
| return 0; | ||
| } | ||
| // If we are here, it means we can send the messages that belong | ||
| // to some predefined class of equivalence, identified by the MERGEABLE_ID, | ||
| // to the receiver. This is done by the following process: | ||
| // | ||
| // - Extract what we actually want to send (this might be data embedded inside the message itself) | ||
| // - Calculate the aggregate size of all the payloads. | ||
| // - Copy all the parts into a final payload | ||
| // - Create the header part | ||
| // - Create the payload part | ||
| // - Send | ||
| std::vector<std::pair<char *, size_t>> parts; | ||
|
|
||
| size_t sum = 0; | ||
| auto range = mPartsMap.equal_range(id); | ||
| for (auto hi = range.first, he = range.second; hi != he; ++hi) { | ||
| std::unique_ptr<FairMQMessage> &payload = hi->second; | ||
| std::pair<char *, size_t> part; | ||
| part.second = mExtractPayload(&part.first, reinterpret_cast<char *>(payload->GetData()), payload->GetSize()); | ||
| parts.push_back(part); | ||
| sum += part.second; | ||
| } | ||
|
|
||
| auto *payload = new char[sum](); | ||
| size_t offset = 0; | ||
| for (auto &part : parts) { | ||
| // Right now this does a copy. In principle this could be done with some sort of | ||
| // vectorized I/O | ||
| memcpy(payload + offset, part.first, part.second); | ||
| offset += part.second; | ||
| } | ||
|
|
||
| mPartsMap.erase(id); | ||
| *out = payload; | ||
| return sum; | ||
| } | ||
|
|
||
| // Helper method which leaves the payload untouched | ||
| static int64_t fullPayloadExtractor(char **payload, | ||
| char *buffer, | ||
| size_t bufferSize) { | ||
| *payload = buffer; | ||
| return bufferSize; | ||
| } | ||
| private: | ||
| IdExtractor mMakeId; | ||
| MergeCompletionCheker mCheckIfComplete; | ||
| PayloadExtractor mExtractPayload; | ||
|
|
||
| MessageMap mPartsMap; | ||
| }; | ||
| } /* dataflow */ | ||
| } /* o2 */ | ||
|
|
||
| #endif // PAYLOAD_MERGER_H | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| // 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 https://alice-o2.web.cern.ch/ 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 DATAFLOW_SUBFRAMEUTILS_H | ||
| #define DATAFLOW_SUBFRAMEUTILS_H | ||
|
|
||
| #include <tuple> | ||
| #include <cstddef> | ||
| #include "Headers/HeartbeatFrame.h" | ||
|
|
||
| namespace o2 { namespace dataflow { | ||
|
|
||
| int64_t extractDetectorPayloadStrip(char **payload, char *buffer, size_t bufferSize) { | ||
| *payload = buffer + sizeof(o2::Header::HeartbeatHeader); | ||
| return bufferSize - sizeof(o2::Header::HeartbeatHeader) - sizeof(o2::Header::HeartbeatTrailer); | ||
| } | ||
|
|
||
|
|
||
| struct SubframeId { | ||
| size_t timeframeId; | ||
| size_t socketId; | ||
|
|
||
| // operator needed for the equal_range algorithm/ multimap method | ||
| bool operator<(const SubframeId& rhs) const { | ||
| return std::tie(timeframeId, socketId) < std::tie(rhs.timeframeId, rhs.socketId); | ||
| } | ||
| }; | ||
|
|
||
| SubframeId makeIdFromHeartbeatHeader(const Header::HeartbeatHeader &header, size_t socketId, size_t orbitsPerTimeframe) { | ||
| SubframeId id = { | ||
| .timeframeId = header.orbit / orbitsPerTimeframe, | ||
| .socketId = socketId | ||
| }; | ||
| return id; | ||
| } | ||
|
|
||
| } /* namespace dataflow */ } /* namespace o2 */ | ||
|
|
||
| #endif // DATAFLOW_SUBFRAMEUTILS_H |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At least for the new files we should start adding the correct public link with http instead https.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for the record: we agreed to postpone this for the moment because it would break the PR code check.