Project
Loading...
Searching...
No Matches
BasicCCDBManager.h
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// Created by Sandro Wenzel on 2019-08-14.
13//
14
15#ifndef O2_BASICCDBMANAGER_H
16#define O2_BASICCDBMANAGER_H
17
18#include "CCDB/CcdbApi.h"
25#include <string>
26#include <chrono>
27#include <map>
28#include <string_view>
29#include <unordered_map>
30#include <memory>
31#include <cstdlib>
32
33class TGeoManager; // we need to forward-declare those classes which should not be cleaned up
34
35namespace o2::ccdb
36{
37
47
49{
50 struct CachedObject {
51 std::shared_ptr<void> objPtr;
52 void* noCleanupPtr = nullptr; // if assigned instead of objPtr, no cleanup will be done on exit (for global objects cleaned up by the root, e.g. gGeoManager)
53 std::string uuid;
54 long startvalidity = 0;
55 long endvalidity = -1;
56 long cacheValidFrom = 0; // time for which the object was cached
57 long cacheValidUntil = -1; // object is guaranteed to be valid till this time (modulo new updates)
58 size_t minSize = -1ULL;
59 size_t maxSize = 0;
60 int queries = 0;
61 int fetches = 0;
62 int failures = 0;
63 std::map<std::string, std::string> cacheOfHeaders;
64 bool isValid(long ts) { return ts < endvalidity && ts >= startvalidity; }
65 bool isCacheValid(long ts)
66 {
67 LOGP(debug, "isCacheValid : {} : {} : {} --> {}", cacheValidFrom, ts, cacheValidUntil, ts < cacheValidUntil && ts >= cacheValidFrom);
68 return ts < cacheValidUntil && ts >= cacheValidFrom;
69 }
70 void clear()
71 {
72 noCleanupPtr = nullptr;
73 objPtr.reset();
74 uuid = "";
75 startvalidity = 0;
76 endvalidity = -1;
77 cacheOfHeaders.clear();
78 }
79 };
80
81 public:
82 using MD = std::map<std::string, std::string>;
83
84 CCDBManagerInstance(std::string const& path) : mCCDBAccessor{}
85 {
86 mCCDBAccessor.init(path);
88 }
90 void setURL(const std::string& url);
91
93 void setTimestamp(long t)
94 {
95 if (t >= 0) {
96 mTimestamp = t;
97 }
98 }
99
101 std::string const& getURL() const { return mCCDBAccessor.getURL(); }
102
104 long getTimestamp() const { return mTimestamp; }
105
107 template <typename T>
108 T* getForTimeStamp(std::string const& path, long timestamp, std::map<std::string, std::string>* headers = nullptr);
109
111 template <typename T>
112 T* getForRun(std::string const& path, int runNumber, bool setRunMetadata = false);
113
115 template <typename T>
116 T* getSpecific(std::string const& path, long timestamp = -1, MD metaData = MD(), std::map<std::string, std::string>* headers = nullptr)
117 {
118 // TODO: add some error info/handling when failing
119 mMetaData = metaData;
120 auto obj = getForTimeStamp<T>(path, timestamp, headers);
121 return obj;
122 }
123
125 template <typename T>
126 T* getSpecificForRun(std::string const& path, int runNumber, MD const& metaData = MD());
127
130
132 template <typename T>
133 T* get(std::string const& path)
134 {
135 return getForTimeStamp<T>(path, mTimestamp);
136 }
137
138 // gain access to underlaying CCDB layer (to allow for more complex queries without need to reinit another API)
139 CcdbApi& getCCDBAccessor() { return mCCDBAccessor; }
140
141 bool isHostReachable() const { return mCCDBAccessor.isHostReachable(); }
142
144 void clearCache() { mCache.clear(); }
145
147 void clearCache(std::string const& path) { mCache.erase(path); }
148
150 bool isCachingEnabled() const { return mCachingEnabled; }
151
153 void setCaching(bool v)
154 {
155 mCachingEnabled = v;
156 if (!v) {
157 clearCache();
158 }
159 }
160
162 bool isCachedObjectValid(std::string const& path, long timestamp)
163 {
164 if (!isCachingEnabled()) {
165 return false;
166 }
167 return (mCheckObjValidityEnabled && mCache[path].isValid(timestamp)) || mCache[path].isCacheValid(timestamp); // use stricter check
168 }
169
171 bool isLocalObjectValidityCheckingEnabled() const { return mCheckObjValidityEnabled; }
172
174 void setLocalObjectValidityChecking(bool v = true) { mCheckObjValidityEnabled = v; }
175
177 void setCreatedNotAfter(long v) { mCreatedNotAfter = v; }
178
180 long getCreatedNotAfter() const { return mCreatedNotAfter; }
181
183 void resetCreatedNotAfter() { mCreatedNotAfter = 0; }
184
186 void setCreatedNotBefore(long v) { mCreatedNotBefore = v; }
187
189 long getCreatedNotBefore() const { return mCreatedNotBefore; }
190
192 void resetCreatedNotBefore() { mCreatedNotBefore = 0; }
193
195 bool getFatalWhenNull() const { return mFatalWhenNull; }
197 void setFatalWhenNull(bool b) { mFatalWhenNull = b; }
198
204 std::pair<int64_t, int64_t> getRunDuration(int runnumber, bool fatal = true);
205 static std::pair<int64_t, int64_t> getRunDuration(o2::ccdb::CcdbApi const& api, int runnumber, bool fatal = true);
206 static std::pair<int64_t, int64_t> getRunDuration(const MD& headers);
207 std::string getSummaryString() const;
208
209 size_t getFetchedSize() const { return mFetchedSize; }
210
211 void report(bool longrep = false);
212
213 void endOfStream();
214
215 private:
216 // method to print (fatal) error
217 void reportFatal(std::string_view s);
218 // we access the CCDB via the CURL based C++ API
219 o2::ccdb::CcdbApi mCCDBAccessor;
220 std::unordered_map<std::string, CachedObject> mCache;
221 MD mMetaData; // some dummy object needed to talk to CCDB API
222 MD mHeaders; // headers to retrieve tags
223 long mTimestamp{o2::ccdb::getCurrentTimestamp()}; // timestamp to be used for query (by default "now")
224 bool mCanDefault = false; // whether default is ok --> useful for testing purposes done standalone/isolation
225 bool mCachingEnabled = true; // whether caching is enabled
226 bool mCheckObjValidityEnabled = false; // wether the validity of cached object is checked before proceeding to a CCDB API query
227 bool mFatalWhenNull = true; // if nullptr blob replies should be treated as fatal (can be set by user)
228 long mCreatedNotAfter = 0; // upper limit for object creation timestamp (TimeMachine mode) - If-Not-After HTTP header
229 long mCreatedNotBefore = 0; // lower limit for object creation timestamp (TimeMachine mode) - If-Not-Before HTTP header
230 long mTimerMS = 0; // timer for queries
231 size_t mFetchedSize = 0; // total fetched size
232 int mQueries = 0; // total number of object queries
233 int mFetches = 0; // total number of succesful fetches from CCDB
234 int mFailures = 0; // total number of failed fetches
235 o2::framework::DeploymentMode mDeplMode; // O2 deployment mode
236 ClassDefNV(CCDBManagerInstance, 1);
237};
238
239template <typename T>
240T* CCDBManagerInstance::getForTimeStamp(std::string const& path, long timestamp, std::map<std::string, std::string>* headers)
241{
242 mHeaders.clear(); // we clear at the beginning; to allow to retrieve the header information in a subsequent call
243 T* ptr = nullptr;
244 mQueries++;
245 auto start = std::chrono::system_clock::now();
246 if (!isCachingEnabled()) {
247 ptr = mCCDBAccessor.retrieveFromTFileAny<T>(path, mMetaData, timestamp, &mHeaders, "",
248 mCreatedNotAfter ? std::to_string(mCreatedNotAfter) : "",
249 mCreatedNotBefore ? std::to_string(mCreatedNotBefore) : "");
250 if (!ptr) {
251 if (mFatalWhenNull) {
252 reportFatal(std::string("Got nullptr from CCDB for path ") + path + std::string(" and timestamp ") + std::to_string(timestamp));
253 }
254 mFailures++;
255 } else {
256 mFetches++;
257 auto sh = mHeaders.find("fileSize");
258 if (sh != mHeaders.end()) {
259 size_t s = atol(sh->second.c_str());
260 mFetchedSize += s;
261 }
262 }
263
264 if (headers) {
265 *headers = mHeaders;
266 }
267 } else {
268 auto& cached = mCache[path];
269 cached.queries++;
270 if ((!isOnline() && cached.isCacheValid(timestamp)) || (mCheckObjValidityEnabled && cached.isValid(timestamp))) {
271 // Give back the cached/saved headers
272 if (headers) {
273 *headers = cached.cacheOfHeaders;
274 }
275 return reinterpret_cast<T*>(cached.noCleanupPtr ? cached.noCleanupPtr : cached.objPtr.get());
276 }
277 ptr = mCCDBAccessor.retrieveFromTFileAny<T>(path, mMetaData, timestamp, &mHeaders, cached.uuid,
278 mCreatedNotAfter ? std::to_string(mCreatedNotAfter) : "",
279 mCreatedNotBefore ? std::to_string(mCreatedNotBefore) : "");
280 // update the cached headers
281 for (auto const& h : mHeaders) {
282 cached.cacheOfHeaders[h.first] = h.second;
283 }
284 // return the cached headers
285 if (headers) {
286 *headers = cached.cacheOfHeaders;
287 }
288
289 if (ptr) { // new object was shipped, old one (if any) is not valid anymore
290 cached.fetches++;
291 mFetches++;
292 if constexpr (std::is_same<TGeoManager, T>::value || std::is_base_of<o2::conf::ConfigurableParam, T>::value) {
293 // some special objects cannot be cached to shared_ptr since root may delete their raw global pointer
294 cached.noCleanupPtr = ptr;
295 } else {
296 cached.objPtr.reset(ptr);
297 }
298 cached.uuid = mHeaders["ETag"];
299
300 try {
301 if (mHeaders.find("Valid-From") != mHeaders.end()) {
302 cached.startvalidity = std::stol(mHeaders["Valid-From"]);
303 } else {
304 // if meta-information missing assume infinit validity
305 // (should happen only for locally created objects)
306 cached.startvalidity = 0;
307 }
308 if (mHeaders.find("Valid-Until") != mHeaders.end()) {
309 cached.endvalidity = std::stol(mHeaders["Valid-Until"]);
310 } else {
311 cached.endvalidity = std::numeric_limits<long>::max();
312 }
313 cached.cacheValidFrom = timestamp;
314 } catch (std::exception const& e) {
315 reportFatal("Failed to read validity from CCDB response (Valid-From : " + mHeaders["Valid-From"] + std::string(" Valid-Until: ") + mHeaders["Valid-Until"] + std::string(")"));
316 }
317 auto sh = mHeaders.find("fileSize");
318 if (sh != mHeaders.end()) {
319 size_t s = atol(sh->second.c_str());
320 mFetchedSize += s;
321 cached.minSize = std::min(s, cached.minSize);
322 cached.maxSize = std::max(s, cached.minSize);
323 }
324 } else if (mHeaders.count("Error")) { // in case of errors the pointer is 0 and headers["Error"] should be set
325 cached.failures++;
326 cached.clear(); // in case of any error clear cache for this object
327 }
328 // the old object is valid, fetch cache end of validity
329 ptr = reinterpret_cast<T*>(cached.noCleanupPtr ? cached.noCleanupPtr : cached.objPtr.get());
330 if (mHeaders.find("Cache-Valid-Until") != mHeaders.end()) {
331 cached.cacheValidUntil = std::stol(mHeaders["Cache-Valid-Until"]);
332 } else {
333 cached.cacheValidUntil = -1;
334 }
335 mMetaData.clear();
336 if (!ptr) {
337 if (mFatalWhenNull) {
338 reportFatal(std::string("Got nullptr from CCDB for path ") + path + std::string(" and timestamp ") + std::to_string(timestamp));
339 }
340 mFailures++;
341 }
342 }
343 auto end = std::chrono::system_clock::now();
344 mTimerMS += std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
346 if (ref && ref->active<framework::DataProcessingStats>()) {
347 auto& stats = ref->get<o2::framework::DataProcessingStats>();
348 stats.updateStats({(int)o2::framework::ProcessingStatsId::CCDB_CACHE_HIT, o2::framework::DataProcessingStats::Op::Set, (int64_t)mQueries - mFailures - mFetches});
351 }
352 return ptr;
353}
354
355template <typename T>
356T* CCDBManagerInstance::getForRun(std::string const& path, int runNumber, bool setRunMetadata)
357{
358 auto metaData = setRunMetadata ? MD{{"runNumber", std::to_string(runNumber)}} : MD{};
359 mMetaData = metaData;
360 return getSpecificForRun<T>(path, runNumber, metaData);
361}
362
363template <typename T>
364T* CCDBManagerInstance::getSpecificForRun(std::string const& path, int runNumber, MD const& metaData)
365{
366 auto [start, stop] = getRunDuration(runNumber, mFatalWhenNull);
367 if (start < 0 || stop < 0) {
368 if (mFatalWhenNull) {
369 reportFatal(std::string("Failed to get run duration for run ") + std::to_string(runNumber) + std::string(" from CCDB"));
370 }
371 return nullptr;
372 }
373 return getSpecific<T>(path, start / 2 + stop / 2, metaData);
374}
375
377{
378 public:
380 {
381 const std::string ccdbUrl{o2::base::NameConf::getCCDBServer()};
382 static BasicCCDBManager inst{ccdbUrl};
383 return inst;
384 }
385
386 private:
388 BasicCCDBManager(std::string const& url) : CCDBManagerInstance(url)
389 {
390 const char* t = getenv("ALICEO2_CCDB_CONDITION_NOT_AFTER");
391 if (t) {
392 auto timeaslong = strtol(t, nullptr, 10);
393 if (timeaslong != 0L) {
394 LOG(info) << "CCDB Time-machine constrained detected. Setting condition-not-after constrained to timestamp " << timeaslong;
395 setCreatedNotAfter(timeaslong);
396 }
397 }
398 }
399};
400
401} // namespace o2::ccdb
402
403#endif // O2_BASICCCDBMANAGER_H
size_t minSize
size_t maxSize
size_t cacheValidUntil
std::string url
std::ostringstream debug
Definition of the Names Generator class.
TBranch * ptr
Class for time synchronization of RawReader instances.
static std::string getCCDBServer()
Definition NameConf.cxx:110
static BasicCCDBManager & instance()
T * getSpecificForRun(std::string const &path, int runNumber, MD const &metaData=MD())
retrieve an object of type T from CCDB as stored under path and using the timestamp in the middle of ...
long getTimestamp() const
query timestamp
CCDBManagerInstance(std::string const &path)
void report(bool longrep=false)
void resetCreatedNotBefore()
reset the object upper validity limit
void setCaching(bool v)
disable or enable caching
void clearCache()
clear all entries in the cache
void setTimestamp(long t)
set timestamp cache for all queries
bool isCachedObjectValid(std::string const &path, long timestamp)
Check if an object in cache is valid.
bool isCachingEnabled() const
check if caching is enabled
void setCreatedNotBefore(long v)
set the object upper validity limit
void setCreatedNotAfter(long v)
set the object upper validity limit
void resetCreatedNotAfter()
reset the object upper validity limit
void setLocalObjectValidityChecking(bool v=true)
set the flag to check object validity before CCDB query
bool isOnline() const
detect online processing modes (i.e. CCDB objects may be updated in the lifetime of the manager)
std::map< std::string, std::string > MD
std::pair< int64_t, int64_t > getRunDuration(int runnumber, bool fatal=true)
T * getForRun(std::string const &path, int runNumber, bool setRunMetadata=false)
retrieve an object of type T from CCDB as stored under path and using the timestamp in the middle of ...
long getCreatedNotAfter() const
get the object upper validity limit
bool getFatalWhenNull() const
get the fatalWhenNull state
static std::pair< int64_t, int64_t > getRunDuration(const MD &headers)
std::string const & getURL() const
query current URL
void setURL(const std::string &url)
set a URL to query from
T * getSpecific(std::string const &path, long timestamp=-1, MD metaData=MD(), std::map< std::string, std::string > *headers=nullptr)
retrieve an object of type T from CCDB as stored under path, timestamp and metaData
void clearCache(std::string const &path)
clear particular entry in the cache
T * get(std::string const &path)
retrieve an object of type T from CCDB as stored under path; will use the timestamp member
T * getForTimeStamp(std::string const &path, long timestamp, std::map< std::string, std::string > *headers=nullptr)
retrieve an object of type T from CCDB as stored under path and timestamp. Optional to get the header...
void setFatalWhenNull(bool b)
set the fatal property (when false; nullptr object responses will not abort)
long getCreatedNotBefore() const
get the object upper validity limit
bool isLocalObjectValidityCheckingEnabled() const
check if checks of object validity before CCDB query is enabled
void init(std::string const &hosts)
Definition CcdbApi.cxx:160
std::string const & getURL() const
Definition CcdbApi.h:87
bool isHostReachable() const
Definition CcdbApi.cxx:1330
std::enable_if<!std::is_base_of< o2::conf::ConfigurableParam, T >::value, T * >::type retrieveFromTFileAny(std::string const &path, std::map< std::string, std::string > const &metadata, long timestamp=-1, std::map< std::string, std::string > *headers=nullptr, std::string const &etag="", const std::string &createdNotAfter="", const std::string &createdNotBefore="") const
Definition CcdbApi.h:657
static ServiceRegistryRef * globalDeviceRef(ServiceRegistryRef *ref=nullptr)
GLuint GLuint end
Definition glcorearb.h:469
const GLdouble * v
Definition glcorearb.h:832
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLuint start
Definition glcorearb.h:469
information complementary to a CCDB object (path, metadata, startTimeValidity, endTimeValidity etc)
long getCurrentTimestamp()
returns the timestamp in long corresponding to "now"
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
bool isValid(std::string alias)
Helper struct to hold statistics about the data processing happening.
static DeploymentMode deploymentMode()
std::string ccdbUrl
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
vec clear()