Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Detectors/MUON/Common/src/dcs-ccdb.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ void makeCCDBEntryForDCS(const std::string ccdbUrl, uint64_t timestamp)
DPID dpidtmp;
for (const auto& a : aliases) {
auto legitName = o2::muon::replaceDotByUnderscore(a);
DPID::FILL(dpidtmp, legitName, o2::dcs::DeliveryType::RAW_DOUBLE);
DPID::FILL(dpidtmp, legitName, o2::dcs::DeliveryType::DPVAL_DOUBLE);
dpid2DataDesc[dpidtmp] = fmt::format("{}DATAPOINTS", o2::muon ::subsysname());
}

Expand All @@ -120,7 +120,10 @@ void makeCCDBEntryForDCS(const std::string ccdbUrl, uint64_t timestamp)
<< o2::muon::subsysname() << " data points to "
<< CcdbDpConfName() << "\n";

api.storeAsTFileAny(&dpid2DataDesc, CcdbDpConfName(), md, timestamp);
uint64_t endOfValidity = 99999999999999;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like my yesterday comment was lost by the github...
Why do you need infinite end validity? This will make every new object to overlap with all previous, which, afaik, leads to overhead. Is not it enough to add e.g. 1-2 days margin to start-time?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @shahor02 ,
I allow myself to jump in :-) I also think I replied to you this morning... Weird.
Anyway, this is the configuration entry, where they define which DPs to process, it is not expected to change often (if ever).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok, thanks for pointing this out.


api.storeAsTFileAny(&dpid2DataDesc, CcdbDpConfName(), md, timestamp,
endOfValidity);
}

bool match(const std::vector<std::string>& queries, const char* pattern)
Expand Down
138 changes: 84 additions & 54 deletions Detectors/MUON/Common/src/dcs-processor-workflow.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "aliasFixer.h"
#include "subsysname.h"
#include <array>
#include <chrono>
#include <gsl/span>
#include <iostream>
#include <unordered_map>
Expand Down Expand Up @@ -80,7 +81,57 @@ std::array<o2::ccdb::CcdbObjectInfo, NOBJECTS> info{createDefaultInfo("MID/Calib

std::array<DPMAP, NOBJECTS> dataPoints;

int t0{-1};
uint64_t t0{0};

/*
* Return the data point values with min and max timestamps
*/
std::pair<DPVAL, DPVAL> computeTimeRange(const DPMAP& dpmap)
{
DPVAL dmin, dmax;
uint64_t minTime{std::numeric_limits<uint64_t>::max()};
uint64_t maxTime{0};

for (auto did : dpmap) {
for (auto d : did.second) {
const auto ts = d.get_epoch_time();
if (ts < minTime) {
dmin = d;
minTime = ts;
}
if (ts > maxTime) {
dmax = d;
maxTime = ts;
}
}
}
return std::make_pair(dmin, dmax);
}

/*
* Compute the (approximate) size (in KB) of a dpmap.
*/
size_t computeSize(const DPMAP& dpmap)
{
constexpr int itemSize = 64; // DataPointIdentifier or DataPointValue have the same size = 64 bytes
constexpr float byte2KB = 1.0 / 1024;

size_t nofItems = 0;
for (auto did : dpmap) {
nofItems++; // +1 for the DataPointIdentifier itself
nofItems += did.second.size(); // +number of DataPointValues
}
return static_cast<size_t>(std::floor(nofItems * itemSize * byte2KB));
}

/*
* Compute the duration (in seconds) span by the datapoints in the dpmap.
*/
int computeDuration(const DPMAP& dpmap)
{
auto range = computeTimeRange(dpmap);
return static_cast<int>((range.second.get_epoch_time() - range.first.get_epoch_time()) / 1000);
}

/*
* Send a DPMAP to the output.
Expand All @@ -91,15 +142,39 @@ int t0{-1};
* @param reason (optional, can be empty) a string description why the dpmap
* was ready to be shipped (e.g. big enough, long enough, end of process, etc...)
*/
void sendOutput(const DPMAP& dpmap, o2::framework::DataAllocator& output, o2::ccdb::CcdbObjectInfo info, const std::string& reason)
void sendOutput(const DPMAP& dpmap,
o2::framework::DataAllocator& output,
o2::ccdb::CcdbObjectInfo info,
const std::string& reason,
uint64_t startOfValidity)
{
if (dpmap.empty()) {
// we do _not_ write empty objects
return;
}

auto duration = computeDuration(dpmap);
if (duration < 10) {
// we do _not_ write objects with a duration below 10 seconds
return;
}
//info.setStartValidityTimestamp(startOfValidity);
auto range = computeTimeRange(dpmap);
info.setStartValidityTimestamp(range.first.get_epoch_time());
info.setEndValidityTimestamp(range.second.get_epoch_time());

auto md = info.getMetaData();
md["upload reason"] = reason;
md["upload-reason"] = reason;
md["nof-datapoints"] = fmt::format("{}", dpmap.size());
size_t nofValues = 0;
for (auto did : dpmap) {
nofValues += did.second.size();
}
md["nof-datapoint-values"] = fmt::format("{}", nofValues);
md["datapoint-value-first-time"] = range.first.get_timestamp()->c_str();
md["datapoint-value-last-time"] = range.second.get_timestamp()->c_str();
info.setMetaData(md);

auto image = o2::ccdb::CcdbApi::createObjectImage(&dpmap, &info);
LOG(info) << "Sending object " << info.getPath() << "/"
<< info.getFileName() << " of size " << image->size()
Expand All @@ -119,41 +194,8 @@ void endOfStream(o2::framework::EndOfStreamContext& eosc)
{
LOG(debug) << "This is the end. Must write what we have left ?\n";
for (auto i = 0; i < NOBJECTS; i++) {
sendOutput(dataPoints[i], eosc.outputs(), info[i], "end of stream");
}
}

/*
* Compute the (approximate) size (in KB) of a dpmap.
*/
size_t computeSize(const DPMAP& dpmap)
{
constexpr int itemSize = 64; // DataPointIdentifier or DataPointValue have the same size = 64 bytes
constexpr float byte2KB = 1.0 / 1024;

size_t nofItems = 0;
for (auto did : dpmap) {
nofItems++; // +1 for the DataPointIdentifier itself
nofItems += did.second.size(); // +number of DataPointValues
sendOutput(dataPoints[i], eosc.outputs(), info[i], "end of stream", t0);
}
return static_cast<size_t>(std::floor(nofItems * itemSize * byte2KB));
}

/*
* Compute the duration (in seconds) span by the datapoints in the dpmap.
*/
int computeDuration(const DPMAP& dpmap)
{
uint64_t minTime{std::numeric_limits<uint64_t>::max()};
uint64_t maxTime{0};

for (auto did : dpmap) {
for (auto d : did.second) {
minTime = std::min(minTime, d.get_epoch_time());
maxTime = std::max(maxTime, d.get_epoch_time());
}
}
return static_cast<int>((maxTime - minTime) / 1000);
}

/*
Expand Down Expand Up @@ -195,17 +237,6 @@ std::tuple<bool, std::string> needOutput(const DPMAP& dpmap, int maxSize, int ma
return {complete && (bigEnough || longEnough), reason};
}

o2::ccdb::CcdbObjectInfo addTFInfo(o2::ccdb::CcdbObjectInfo inf,
uint64_t t0, uint64_t t1)
{
auto md = inf.getMetaData();
md["tf range"] = fmt::format("{}-{}", t0, t1);
inf.setMetaData(md);
inf.setStartValidityTimestamp(t0);
//inf.setEndValidityTimestamp(t1);
return inf;
}

/*
* Process the datapoints received.
*
Expand All @@ -229,9 +260,9 @@ void processDataPoints(o2::framework::ProcessingContext& pc,
std::array<int, NOBJECTS> maxDuration)
{

auto tfid = o2::header::get<o2::framework::DataProcessingHeader*>(pc.inputs().get("input").header)->startTime;
if (t0 < 0) {
t0 = tfid;
auto creationTime = o2::header::get<o2::framework::DataProcessingHeader*>(pc.inputs().get("input").header)->creation;
if (t0 <= 0) {
t0 = creationTime;
}
auto dps = pc.inputs().get<gsl::span<o2::dcs::DataPointCompositeObject>>("input");
for (auto dp : dps) {
Expand All @@ -245,9 +276,8 @@ void processDataPoints(o2::framework::ProcessingContext& pc,
for (auto i = 0; i < NOBJECTS; i++) {
auto [shouldOutput, reason] = needOutput(dataPoints[i], maxSize[i], maxDuration[i]);
if (shouldOutput) {
auto inf = addTFInfo(info[i], t0, tfid);
sendOutput(dataPoints[i], pc.outputs(), inf, reason);
t0 = tfid;
sendOutput(dataPoints[i], pc.outputs(), info[i], reason, t0);
t0 = creationTime;
dataPoints[i].clear(); //FIXME: here the clear should be more clever and keep at least one value per dp ?
}
}
Expand Down