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"
23#include <string>
24#include <chrono>
25#include <map>
26#include <string_view>
27#include <unordered_map>
28#include <memory>
29#include <cstdlib>
30
31class TGeoManager; // we need to forward-declare those classes which should not be cleaned up
32
33namespace o2::ccdb
34{
35
45
47{
48 struct CachedObject {
49 std::shared_ptr<void> objPtr;
50 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)
51 std::string uuid;
52 long startvalidity = 0;
53 long endvalidity = -1;
54 long cacheValidFrom = 0; // time for which the object was cached
55 long cacheValidUntil = -1; // object is guaranteed to be valid till this time (modulo new updates)
56 size_t minSize = -1ULL;
57 size_t maxSize = 0;
58 int queries = 0;
59 int fetches = 0;
60 int failures = 0;
61 std::map<std::string, std::string> cacheOfHeaders;
62 bool isValid(long ts) { return ts < endvalidity && ts >= startvalidity; }
63 bool isCacheValid(long ts)
64 {
65 LOGP(debug, "isCacheValid : {} : {} : {} --> {}", cacheValidFrom, ts, cacheValidUntil, ts < cacheValidUntil && ts >= cacheValidFrom);
66 return ts < cacheValidUntil && ts >= cacheValidFrom;
67 }
68 void clear()
69 {
70 noCleanupPtr = nullptr;
71 objPtr.reset();
72 uuid = "";
73 startvalidity = 0;
74 endvalidity = -1;
75 cacheOfHeaders.clear();
76 }
77 };
78
79 public:
80 using MD = std::map<std::string, std::string>;
81
82 CCDBManagerInstance(std::string const& path) : mCCDBAccessor{}
83 {
84 mCCDBAccessor.init(path);
86 }
88 void setURL(const std::string& url);
89
91 void setTimestamp(long t)
92 {
93 if (t >= 0) {
94 mTimestamp = t;
95 }
96 }
97
99 std::string const& getURL() const { return mCCDBAccessor.getURL(); }
100
102 long getTimestamp() const { return mTimestamp; }
103
105 template <typename T>
106 T* getForTimeStamp(std::string const& path, long timestamp, std::map<std::string, std::string>* headers = nullptr);
107
109 template <typename T>
110 T* getForRun(std::string const& path, int runNumber, bool setRunMetadata = false);
111
113 template <typename T>
114 T* getSpecific(std::string const& path, long timestamp = -1, MD metaData = MD(), std::map<std::string, std::string>* headers = nullptr)
115 {
116 // TODO: add some error info/handling when failing
117 mMetaData = metaData;
118 auto obj = getForTimeStamp<T>(path, timestamp, headers);
119 return obj;
120 }
121
123 template <typename T>
124 T* getSpecificForRun(std::string const& path, int runNumber, MD const& metaData = MD());
125
128
130 template <typename T>
131 T* get(std::string const& path)
132 {
133 return getForTimeStamp<T>(path, mTimestamp);
134 }
135
136 // gain access to underlaying CCDB layer (to allow for more complex queries without need to reinit another API)
137 CcdbApi& getCCDBAccessor() { return mCCDBAccessor; }
138
139 bool isHostReachable() const { return mCCDBAccessor.isHostReachable(); }
140
142 void clearCache() { mCache.clear(); }
143
145 void clearCache(std::string const& path) { mCache.erase(path); }
146
148 bool isCachingEnabled() const { return mCachingEnabled; }
149
151 void setCaching(bool v)
152 {
153 mCachingEnabled = v;
154 if (!v) {
155 clearCache();
156 }
157 }
158
160 bool isCachedObjectValid(std::string const& path, long timestamp)
161 {
162 if (!isCachingEnabled()) {
163 return false;
164 }
165 return (mCheckObjValidityEnabled && mCache[path].isValid(timestamp)) || mCache[path].isCacheValid(timestamp); // use stricter check
166 }
167
169 bool isLocalObjectValidityCheckingEnabled() const { return mCheckObjValidityEnabled; }
170
172 void setLocalObjectValidityChecking(bool v = true) { mCheckObjValidityEnabled = v; }
173
175 void setCreatedNotAfter(long v) { mCreatedNotAfter = v; }
176
178 long getCreatedNotAfter() const { return mCreatedNotAfter; }
179
181 void resetCreatedNotAfter() { mCreatedNotAfter = 0; }
182
184 void setCreatedNotBefore(long v) { mCreatedNotBefore = v; }
185
187 long getCreatedNotBefore() const { return mCreatedNotBefore; }
188
190 void resetCreatedNotBefore() { mCreatedNotBefore = 0; }
191
193 bool getFatalWhenNull() const { return mFatalWhenNull; }
195 void setFatalWhenNull(bool b) { mFatalWhenNull = b; }
196
202 std::pair<int64_t, int64_t> getRunDuration(int runnumber, bool fatal = true);
203 static std::pair<int64_t, int64_t> getRunDuration(o2::ccdb::CcdbApi const& api, int runnumber, bool fatal = true);
204 static std::pair<int64_t, int64_t> getRunDuration(const MD& headers);
205 std::string getSummaryString() const;
206
207 size_t getFetchedSize() const { return mFetchedSize; }
208
209 void report(bool longrep = false);
210
211 void endOfStream();
212
213 private:
214 // method to print (fatal) error
215 void reportFatal(std::string_view s);
216 // we access the CCDB via the CURL based C++ API
217 o2::ccdb::CcdbApi mCCDBAccessor;
218 std::unordered_map<std::string, CachedObject> mCache;
219 MD mMetaData; // some dummy object needed to talk to CCDB API
220 MD mHeaders; // headers to retrieve tags
221 long mTimestamp{o2::ccdb::getCurrentTimestamp()}; // timestamp to be used for query (by default "now")
222 bool mCanDefault = false; // whether default is ok --> useful for testing purposes done standalone/isolation
223 bool mCachingEnabled = true; // whether caching is enabled
224 bool mCheckObjValidityEnabled = false; // wether the validity of cached object is checked before proceeding to a CCDB API query
225 bool mFatalWhenNull = true; // if nullptr blob replies should be treated as fatal (can be set by user)
226 long mCreatedNotAfter = 0; // upper limit for object creation timestamp (TimeMachine mode) - If-Not-After HTTP header
227 long mCreatedNotBefore = 0; // lower limit for object creation timestamp (TimeMachine mode) - If-Not-Before HTTP header
228 long mTimerMS = 0; // timer for queries
229 size_t mFetchedSize = 0; // total fetched size
230 int mQueries = 0; // total number of object queries
231 int mFetches = 0; // total number of succesful fetches from CCDB
232 int mFailures = 0; // total number of failed fetches
233 o2::framework::DeploymentMode mDeplMode; // O2 deployment mode
234 ClassDefNV(CCDBManagerInstance, 1);
235};
236
237template <typename T>
238T* CCDBManagerInstance::getForTimeStamp(std::string const& path, long timestamp, std::map<std::string, std::string>* headers)
239{
240 mHeaders.clear(); // we clear at the beginning; to allow to retrieve the header information in a subsequent call
241 T* ptr = nullptr;
242 mQueries++;
243 auto start = std::chrono::system_clock::now();
244 if (!isCachingEnabled()) {
245 ptr = mCCDBAccessor.retrieveFromTFileAny<T>(path, mMetaData, timestamp, &mHeaders, "",
246 mCreatedNotAfter ? std::to_string(mCreatedNotAfter) : "",
247 mCreatedNotBefore ? std::to_string(mCreatedNotBefore) : "");
248 if (!ptr) {
249 if (mFatalWhenNull) {
250 reportFatal(std::string("Got nullptr from CCDB for path ") + path + std::string(" and timestamp ") + std::to_string(timestamp));
251 }
252 mFailures++;
253 } else {
254 mFetches++;
255 auto sh = mHeaders.find("fileSize");
256 if (sh != mHeaders.end()) {
257 size_t s = atol(sh->second.c_str());
258 mFetchedSize += s;
259 }
260 }
261
262 if (headers) {
263 *headers = mHeaders;
264 }
265 } else {
266 auto& cached = mCache[path];
267 cached.queries++;
268 if ((!isOnline() && cached.isCacheValid(timestamp)) || (mCheckObjValidityEnabled && cached.isValid(timestamp))) {
269 // Give back the cached/saved headers
270 if (headers) {
271 *headers = cached.cacheOfHeaders;
272 }
273 return reinterpret_cast<T*>(cached.noCleanupPtr ? cached.noCleanupPtr : cached.objPtr.get());
274 }
275 ptr = mCCDBAccessor.retrieveFromTFileAny<T>(path, mMetaData, timestamp, &mHeaders, cached.uuid,
276 mCreatedNotAfter ? std::to_string(mCreatedNotAfter) : "",
277 mCreatedNotBefore ? std::to_string(mCreatedNotBefore) : "");
278 // update the cached headers
279 for (auto const& h : mHeaders) {
280 cached.cacheOfHeaders[h.first] = h.second;
281 }
282 // return the cached headers
283 if (headers) {
284 *headers = cached.cacheOfHeaders;
285 }
286
287 if (ptr) { // new object was shipped, old one (if any) is not valid anymore
288 cached.fetches++;
289 mFetches++;
290 if constexpr (std::is_same<TGeoManager, T>::value || std::is_base_of<o2::conf::ConfigurableParam, T>::value) {
291 // some special objects cannot be cached to shared_ptr since root may delete their raw global pointer
292 cached.noCleanupPtr = ptr;
293 } else {
294 cached.objPtr.reset(ptr);
295 }
296 cached.uuid = mHeaders["ETag"];
297
298 try {
299 if (mHeaders.find("Valid-From") != mHeaders.end()) {
300 cached.startvalidity = std::stol(mHeaders["Valid-From"]);
301 } else {
302 // if meta-information missing assume infinit validity
303 // (should happen only for locally created objects)
304 cached.startvalidity = 0;
305 }
306 if (mHeaders.find("Valid-Until") != mHeaders.end()) {
307 cached.endvalidity = std::stol(mHeaders["Valid-Until"]);
308 } else {
309 cached.endvalidity = std::numeric_limits<long>::max();
310 }
311 cached.cacheValidFrom = timestamp;
312 } catch (std::exception const& e) {
313 reportFatal("Failed to read validity from CCDB response (Valid-From : " + mHeaders["Valid-From"] + std::string(" Valid-Until: ") + mHeaders["Valid-Until"] + std::string(")"));
314 }
315 auto sh = mHeaders.find("fileSize");
316 if (sh != mHeaders.end()) {
317 size_t s = atol(sh->second.c_str());
318 mFetchedSize += s;
319 cached.minSize = std::min(s, cached.minSize);
320 cached.maxSize = std::max(s, cached.minSize);
321 }
322 } else if (mHeaders.count("Error")) { // in case of errors the pointer is 0 and headers["Error"] should be set
323 cached.failures++;
324 cached.clear(); // in case of any error clear cache for this object
325 }
326 // the old object is valid, fetch cache end of validity
327 ptr = reinterpret_cast<T*>(cached.noCleanupPtr ? cached.noCleanupPtr : cached.objPtr.get());
328 if (mHeaders.find("Cache-Valid-Until") != mHeaders.end()) {
329 cached.cacheValidUntil = std::stol(mHeaders["Cache-Valid-Until"]);
330 } else {
331 cached.cacheValidUntil = -1;
332 }
333 mMetaData.clear();
334 if (!ptr) {
335 if (mFatalWhenNull) {
336 reportFatal(std::string("Got nullptr from CCDB for path ") + path + std::string(" and timestamp ") + std::to_string(timestamp));
337 }
338 mFailures++;
339 }
340 }
341 auto end = std::chrono::system_clock::now();
342 mTimerMS += std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
343 return ptr;
344}
345
346template <typename T>
347T* CCDBManagerInstance::getForRun(std::string const& path, int runNumber, bool setRunMetadata)
348{
349 auto metaData = setRunMetadata ? MD{{"runNumber", std::to_string(runNumber)}} : MD{};
350 mMetaData = metaData;
351 return getSpecificForRun<T>(path, runNumber, metaData);
352}
353
354template <typename T>
355T* CCDBManagerInstance::getSpecificForRun(std::string const& path, int runNumber, MD const& metaData)
356{
357 auto [start, stop] = getRunDuration(runNumber, mFatalWhenNull);
358 if (start < 0 || stop < 0) {
359 if (mFatalWhenNull) {
360 reportFatal(std::string("Failed to get run duration for run ") + std::to_string(runNumber) + std::string(" from CCDB"));
361 }
362 return nullptr;
363 }
364 return getSpecific<T>(path, start / 2 + stop / 2, metaData);
365}
366
368{
369 public:
371 {
372 const std::string ccdbUrl{o2::base::NameConf::getCCDBServer()};
373 static BasicCCDBManager inst{ccdbUrl};
374 return inst;
375 }
376
377 private:
379 BasicCCDBManager(std::string const& url) : CCDBManagerInstance(url)
380 {
381 const char* t = getenv("ALICEO2_CCDB_CONDITION_NOT_AFTER");
382 if (t) {
383 auto timeaslong = strtol(t, nullptr, 10);
384 if (timeaslong != 0L) {
385 LOG(info) << "CCDB Time-machine constrained detected. Setting condition-not-after constrained to timestamp " << timeaslong;
386 setCreatedNotAfter(timeaslong);
387 }
388 }
389 }
390};
391
392} // namespace o2::ccdb
393
394#endif //O2_BASICCCDBMANAGER_H
size_t minSize
size_t maxSize
size_t cacheValidUntil
std::string url
Definition of the Names Generator class.
TBranch * ptr
std::ostringstream debug
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:166
std::string const & getURL() const
Definition CcdbApi.h:87
bool isHostReachable() const
Definition CcdbApi.cxx:1326
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
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)
static DeploymentMode deploymentMode()
std::string ccdbUrl
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
vec clear()