Project
Loading...
Searching...
No Matches
DataRefUtils.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include <span>
13#include <typeinfo>
14#include <cstring>
17#include "Framework/Logger.h"
18#include <TMemFile.h>
19#include <TTree.h>
20#include <TH1.h>
21#include <TError.h>
22#include <algorithm>
23
24namespace o2::framework
25{
26
27namespace
28{
29void* extractFromTFile(TFile& file, TClass const* cl, const char* what)
30{
31 if (!cl) {
32 return nullptr;
33 }
34 auto object = file.GetObjectChecked(what, cl);
35 if (!object) {
36 // it could be that object was stored with previous convention
37 // where the classname was taken as key
38 std::string objectName(cl->GetName());
39 objectName.erase(std::find_if(objectName.rbegin(), objectName.rend(), [](unsigned char ch) {
40 return !std::isspace(ch);
41 }).base(),
42 objectName.end());
43 objectName.erase(objectName.begin(), std::find_if(objectName.begin(), objectName.end(), [](unsigned char ch) {
44 return !std::isspace(ch);
45 }));
46
47 object = file.GetObjectChecked(objectName.c_str(), cl);
48 LOG(warn) << "Did not find object under expected name " << what;
49 if (!object) {
50 return nullptr;
51 }
52 LOG(warn) << "Found object under deprecated name " << cl->GetName();
53 }
54 auto result = object;
55 // We need to handle some specific cases as ROOT ties them deeply
56 // to the file they are contained in
57 if (cl->InheritsFrom("TObject")) {
58 // make a clone
59 // detach from the file
60 auto tree = dynamic_cast<TTree*>((TObject*)object);
61 if (tree) {
62 tree->LoadBaskets(0x1L << 32); // make tree memory based
63 tree->SetDirectory(nullptr);
64 result = tree;
65 } else {
66 auto h = dynamic_cast<TH1*>((TObject*)object);
67 if (h) {
68 h->SetDirectory(nullptr);
69 result = h;
70 }
71 }
72 }
73 return result;
74}
75} // namespace
76// Adapted from CcdbApi private method interpretAsTMemFileAndExtract
77// If the former is moved to public, throws on error and could be changed to
78// not require a mutex we could use it.
79void* DataRefUtils::decodeCCDB(DataRef const& ref, std::type_info const& tinfo)
80{
81 void* result = nullptr;
82 Int_t previousErrorLevel = gErrorIgnoreLevel;
83 gErrorIgnoreLevel = kFatal;
84 auto* dh = o2::header::get<o2::header::DataHeader*>(ref.header);
85 const char* buff = const_cast<char*>(ref.payload);
86 size_t flSize = dh->payloadSize;
87 // does it have a flattened headers map attached in the end?
88 constexpr char FlatHeaderAnnot[] = "$HEADER$";
89 constexpr int Offset = sizeof(int) + sizeof(FlatHeaderAnnot);
90 int headerSize = 0;
91 LOGP(debug, "DHPayloadSize={}>{} Ref:{}/{} Cmp {}:{}", dh->payloadSize, Offset, dh->dataOrigin.as<std::string>(), dh->dataDescription.as<std::string>(), std::string{buff + dh->payloadSize - sizeof(FlatHeaderAnnot)}, std::string{FlatHeaderAnnot});
92
93 if (dh->payloadSize >= Offset &&
94 !std::strncmp(buff + dh->payloadSize - sizeof(FlatHeaderAnnot), FlatHeaderAnnot, sizeof(FlatHeaderAnnot))) {
95 headerSize = *reinterpret_cast<const int*>(buff + dh->payloadSize - Offset);
96 }
97 if (headerSize < 0) {
98 LOGP(fatal, "Anomalous flattened header size {} extracted for CCDB object {}/{}", headerSize, dh->dataOrigin.as<std::string>(), dh->dataDescription.as<std::string>());
99 }
100 TMemFile memFile("name", const_cast<char*>(ref.payload), dh->payloadSize - headerSize, "READ");
101 gErrorIgnoreLevel = previousErrorLevel;
102 if (memFile.IsZombie()) {
103 return nullptr;
104 }
105
106 TClass* tcl = TClass::GetClass(tinfo);
107 result = extractFromTFile(memFile, tcl, "ccdb_object");
108 if (!result) {
109 throw runtime_error_f("Couldn't retrieve object corresponding to %s from TFile", tcl->GetName());
110 }
111 memFile.Close();
112 return result;
113}
114
115std::map<std::string, std::string> DataRefUtils::extractCCDBHeaders(DataRef const& ref)
116{
117 auto* dh = o2::header::get<o2::header::DataHeader*>(ref.header);
118 const char* buff = const_cast<char*>(ref.payload);
119 // does it have a flattened headers map attached in the end?
120 constexpr char FlatHeaderAnnot[] = "$HEADER$";
121 constexpr int Offset = sizeof(int) + sizeof(FlatHeaderAnnot);
122 int headerSize = 0, ss0 = 0;
123 std::map<std::string, std::string> res;
124 if (dh->payloadSize >= Offset && !std::strncmp(buff + dh->payloadSize - sizeof(FlatHeaderAnnot), FlatHeaderAnnot, sizeof(FlatHeaderAnnot))) {
125 headerSize = *reinterpret_cast<const int*>(buff + dh->payloadSize - Offset);
126 } else { // header was not added
127 LOGP(warn, "CCDB headers were not added to condition object blob, returning dummy header map");
128 return res;
129 }
130
131 if (headerSize < 0) {
132 LOGP(fatal, "Anomalous flattened header size {} extracted for CCDB object {}/{}", headerSize, dh->dataOrigin.as<std::string>(), dh->dataDescription.as<std::string>());
133 }
134
135 buff += dh->payloadSize - headerSize; // jump to the start of flattened header
136 headerSize -= Offset;
137 const char* str0 = &buff[ss0++];
138 while (ss0 < headerSize) {
139 if (buff[ss0++] == 0) {
140 if (!str0) {
141 str0 = &buff[ss0]; // new key string is found
142 } else {
143 res.emplace(std::string(str0), std::string(&buff[ss0])); // new value string found, add key value to the map
144 LOGP(debug, "Header{} {}:{}", res.size(), std::string(str0), std::string(&buff[ss0]));
145 str0 = nullptr;
146 }
147 }
148 }
149 return res;
150}
151
152std::span<const char> DataRefUtils::getCCDBPayloadBlob(DataRef const& ref)
153{
154 auto* dh = o2::header::get<o2::header::DataHeader*>(ref.header);
155 const char* buff = ref.payload;
156 size_t payloadSize = dh->payloadSize;
157 constexpr char FlatHeaderAnnot[] = "$HEADER$";
158 constexpr size_t Offset = sizeof(int) + sizeof(FlatHeaderAnnot);
159 int headerSize = 0;
160 if (payloadSize >= Offset &&
161 !std::strncmp(buff + payloadSize - sizeof(FlatHeaderAnnot), FlatHeaderAnnot, sizeof(FlatHeaderAnnot))) {
162 headerSize = *reinterpret_cast<const int*>(buff + payloadSize - Offset);
163 }
164 return {buff, payloadSize - headerSize};
165}
166
167} // namespace o2::framework
std::ostringstream debug
uint32_t res
Definition RawData.h:0
Class for time synchronization of RawReader instances.
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint object
Definition glcorearb.h:4041
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
RuntimeErrorRef runtime_error_f(const char *,...)
int32_t const char * file
static std::map< std::string, std::string > extractCCDBHeaders(DataRef const &ref)
static void * decodeCCDB(DataRef const &ref, std::type_info const &info)
static std::span< const char > getCCDBPayloadBlob(DataRef const &ref)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))