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 <unordered_map>
27#include <memory>
28#include <cstdlib>
29
30class TGeoManager; // we need to forward-declare those classes which should not be cleaned up
31
32namespace o2::ccdb
33{
34
44
46{
47 struct CachedObject {
48 std::shared_ptr<void> objPtr;
49 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)
50 std::string uuid;
51 long startvalidity = 0;
52 long endvalidity = -1;
53 long cacheValidFrom = 0; // time for which the object was cached
54 long cacheValidUntil = -1; // object is guaranteed to be valid till this time (modulo new updates)
55 size_t minSize = -1ULL;
56 size_t maxSize = 0;
57 int queries = 0;
58 int fetches = 0;
59 int failures = 0;
60 bool isValid(long ts) { return ts < endvalidity && ts >= startvalidity; }
61 bool isCacheValid(long ts)
62 {
63 LOGP(debug, "isCacheValid : {} : {} : {} --> {}", cacheValidFrom, ts, cacheValidUntil, ts < cacheValidUntil && ts >= cacheValidFrom);
64 return ts < cacheValidUntil && ts >= cacheValidFrom;
65 }
66 void clear()
67 {
68 noCleanupPtr = nullptr;
69 objPtr.reset();
70 uuid = "";
71 startvalidity = 0;
72 endvalidity = -1;
73 }
74 };
75
76 public:
77 using MD = std::map<std::string, std::string>;
78
79 CCDBManagerInstance(std::string const& path) : mCCDBAccessor{}
80 {
81 mCCDBAccessor.init(path);
83 }
85 void setURL(const std::string& url);
86
88 void setTimestamp(long t)
89 {
90 if (t >= 0) {
91 mTimestamp = t;
92 }
93 }
94
96 std::string const& getURL() const { return mCCDBAccessor.getURL(); }
97
99 long getTimestamp() const { return mTimestamp; }
100
102 template <typename T>
103 T* getForTimeStamp(std::string const& path, long timestamp);
104
106 template <typename T>
107 T* getForRun(std::string const& path, int runNumber, bool setRunMetadata = false);
108
110 template <typename T>
111 T* getSpecific(std::string const& path, long timestamp = -1, MD metaData = MD(), std::map<std::string, std::string>* headers = nullptr)
112 {
113 // TODO: add some error info/handling when failing
114 mMetaData = metaData;
115 auto obj = getForTimeStamp<T>(path, timestamp);
116 if (headers) {
117 *headers = mHeaders;
118 }
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)
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 } else {
262 auto& cached = mCache[path];
263 cached.queries++;
264 if ((!isOnline() && cached.isCacheValid(timestamp)) || (mCheckObjValidityEnabled && cached.isValid(timestamp))) {
265 return reinterpret_cast<T*>(cached.noCleanupPtr ? cached.noCleanupPtr : cached.objPtr.get());
266 }
267 ptr = mCCDBAccessor.retrieveFromTFileAny<T>(path, mMetaData, timestamp, &mHeaders, cached.uuid,
268 mCreatedNotAfter ? std::to_string(mCreatedNotAfter) : "",
269 mCreatedNotBefore ? std::to_string(mCreatedNotBefore) : "");
270 if (ptr) { // new object was shipped, old one (if any) is not valid anymore
271 cached.fetches++;
272 mFetches++;
273 if constexpr (std::is_same<TGeoManager, T>::value || std::is_base_of<o2::conf::ConfigurableParam, T>::value) {
274 // some special objects cannot be cached to shared_ptr since root may delete their raw global pointer
275 cached.noCleanupPtr = ptr;
276 } else {
277 cached.objPtr.reset(ptr);
278 }
279 cached.uuid = mHeaders["ETag"];
280
281 try {
282 if (mHeaders.find("Valid-From") != mHeaders.end()) {
283 cached.startvalidity = std::stol(mHeaders["Valid-From"]);
284 } else {
285 // if meta-information missing assume infinit validity
286 // (should happen only for locally created objects)
287 cached.startvalidity = 0;
288 }
289 if (mHeaders.find("Valid-Until") != mHeaders.end()) {
290 cached.endvalidity = std::stol(mHeaders["Valid-Until"]);
291 } else {
292 cached.endvalidity = std::numeric_limits<long>::max();
293 }
294 cached.cacheValidFrom = timestamp;
295 } catch (std::exception const& e) {
296 reportFatal("Failed to read validity from CCDB response (Valid-From : " + mHeaders["Valid-From"] + std::string(" Valid-Until: ") + mHeaders["Valid-Until"] + std::string(")"));
297 }
298 auto sh = mHeaders.find("fileSize");
299 if (sh != mHeaders.end()) {
300 size_t s = atol(sh->second.c_str());
301 mFetchedSize += s;
302 cached.minSize = std::min(s, cached.minSize);
303 cached.maxSize = std::max(s, cached.minSize);
304 }
305 } else if (mHeaders.count("Error")) { // in case of errors the pointer is 0 and headers["Error"] should be set
306 cached.failures++;
307 cached.clear(); // in case of any error clear cache for this object
308 }
309 // the old object is valid, fetch cache end of validity
310 ptr = reinterpret_cast<T*>(cached.noCleanupPtr ? cached.noCleanupPtr : cached.objPtr.get());
311 if (mHeaders.find("Cache-Valid-Until") != mHeaders.end()) {
312 cached.cacheValidUntil = std::stol(mHeaders["Cache-Valid-Until"]);
313 } else {
314 cached.cacheValidUntil = -1;
315 }
316 mMetaData.clear();
317 if (!ptr) {
318 if (mFatalWhenNull) {
319 reportFatal(std::string("Got nullptr from CCDB for path ") + path + std::string(" and timestamp ") + std::to_string(timestamp));
320 }
321 mFailures++;
322 }
323 }
324 auto end = std::chrono::system_clock::now();
325 mTimerMS += std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
326 return ptr;
327}
328
329template <typename T>
330T* CCDBManagerInstance::getForRun(std::string const& path, int runNumber, bool setRunMetadata)
331{
332 auto metaData = setRunMetadata ? MD{{"runNumber", std::to_string(runNumber)}} : MD{};
333 mMetaData = metaData;
334 return getSpecificForRun<T>(path, runNumber, metaData);
335}
336
337template <typename T>
338T* CCDBManagerInstance::getSpecificForRun(std::string const& path, int runNumber, MD const& metaData)
339{
340 auto [start, stop] = getRunDuration(runNumber, mFatalWhenNull);
341 if (start < 0 || stop < 0) {
342 if (mFatalWhenNull) {
343 reportFatal(std::string("Failed to get run duration for run ") + std::to_string(runNumber) + std::string(" from CCDB"));
344 }
345 return nullptr;
346 }
347 return getSpecific<T>(path, start / 2 + stop / 2, metaData);
348}
349
351{
352 public:
354 {
355 const std::string ccdbUrl{o2::base::NameConf::getCCDBServer()};
356 static BasicCCDBManager inst{ccdbUrl};
357 return inst;
358 }
359
360 private:
362 BasicCCDBManager(std::string const& url) : CCDBManagerInstance(url)
363 {
364 const char* t = getenv("ALICEO2_CCDB_CONDITION_NOT_AFTER");
365 if (t) {
366 auto timeaslong = strtol(t, nullptr, 10);
367 if (timeaslong != 0L) {
368 LOG(info) << "CCDB Time-machine constrained detected. Setting condition-not-after constrained to timestamp " << timeaslong;
369 setCreatedNotAfter(timeaslong);
370 }
371 }
372 }
373};
374
375} // namespace o2::ccdb
376
377#endif //O2_BASICCCDBMANAGER_H
Definition of the Names Generator class.
TBranch * ptr
std::ostringstream debug
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)
T * getForTimeStamp(std::string const &path, long timestamp)
retrieve an object of type T from CCDB as stored under path and timestamp
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
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:165
std::string const & getURL() const
Definition CcdbApi.h:87
bool isHostReachable() const
Definition CcdbApi.cxx:1318
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:660
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()