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())
112 {
113 // TODO: add some error info/handling when failing
114 mMetaData = metaData;
115 return getForTimeStamp<T>(path, timestamp);
116 }
117
119 template <typename T>
120 T* getSpecificForRun(std::string const& path, int runNumber, MD metaData = MD());
121
124
126 template <typename T>
127 T* get(std::string const& path)
128 {
129 return getForTimeStamp<T>(path, mTimestamp);
130 }
131
132 bool isHostReachable() const { return mCCDBAccessor.isHostReachable(); }
133
135 void clearCache() { mCache.clear(); }
136
138 void clearCache(std::string const& path) { mCache.erase(path); }
139
141 bool isCachingEnabled() const { return mCachingEnabled; }
142
144 void setCaching(bool v)
145 {
146 mCachingEnabled = v;
147 if (!v) {
148 clearCache();
149 }
150 }
151
153 bool isCachedObjectValid(std::string const& path, long timestamp)
154 {
155 if (!isCachingEnabled()) {
156 return false;
157 }
158 return (mCheckObjValidityEnabled && mCache[path].isValid(timestamp)) || mCache[path].isCacheValid(timestamp); // use stricter check
159 }
160
162 bool isLocalObjectValidityCheckingEnabled() const { return mCheckObjValidityEnabled; }
163
165 void setLocalObjectValidityChecking(bool v = true) { mCheckObjValidityEnabled = v; }
166
168 void setCreatedNotAfter(long v) { mCreatedNotAfter = v; }
169
171 long getCreatedNotAfter() const { return mCreatedNotAfter; }
172
174 void resetCreatedNotAfter() { mCreatedNotAfter = 0; }
175
177 void setCreatedNotBefore(long v) { mCreatedNotBefore = v; }
178
180 long getCreatedNotBefore() const { return mCreatedNotBefore; }
181
183 void resetCreatedNotBefore() { mCreatedNotBefore = 0; }
184
186 bool getFatalWhenNull() const { return mFatalWhenNull; }
188 void setFatalWhenNull(bool b) { mFatalWhenNull = b; }
189
195 std::pair<int64_t, int64_t> getRunDuration(int runnumber, bool fatal = true);
196 static std::pair<int64_t, int64_t> getRunDuration(o2::ccdb::CcdbApi const& api, int runnumber, bool fatal = true);
197 static std::pair<int64_t, int64_t> getRunDuration(const MD& headers);
198 std::string getSummaryString() const;
199
200 size_t getFetchedSize() const { return mFetchedSize; }
201
202 void report(bool longrep = false);
203
204 void endOfStream();
205
206 private:
207 // method to print (fatal) error
208 void reportFatal(std::string_view s);
209 // we access the CCDB via the CURL based C++ API
210 o2::ccdb::CcdbApi mCCDBAccessor;
211 std::unordered_map<std::string, CachedObject> mCache;
212 MD mMetaData; // some dummy object needed to talk to CCDB API
213 MD mHeaders; // headers to retrieve tags
214 long mTimestamp{o2::ccdb::getCurrentTimestamp()}; // timestamp to be used for query (by default "now")
215 bool mCanDefault = false; // whether default is ok --> useful for testing purposes done standalone/isolation
216 bool mCachingEnabled = true; // whether caching is enabled
217 bool mCheckObjValidityEnabled = false; // wether the validity of cached object is checked before proceeding to a CCDB API query
218 bool mFatalWhenNull = true; // if nullptr blob replies should be treated as fatal (can be set by user)
219 long mCreatedNotAfter = 0; // upper limit for object creation timestamp (TimeMachine mode) - If-Not-After HTTP header
220 long mCreatedNotBefore = 0; // lower limit for object creation timestamp (TimeMachine mode) - If-Not-Before HTTP header
221 long mTimerMS = 0; // timer for queries
222 size_t mFetchedSize = 0; // total fetched size
223 int mQueries = 0; // total number of object queries
224 int mFetches = 0; // total number of succesful fetches from CCDB
225 int mFailures = 0; // total number of failed fetches
226 o2::framework::DeploymentMode mDeplMode; // O2 deployment mode
227 ClassDefNV(CCDBManagerInstance, 1);
228};
229
230template <typename T>
231T* CCDBManagerInstance::getForTimeStamp(std::string const& path, long timestamp)
232{
233 T* ptr = nullptr;
234 mQueries++;
235 auto start = std::chrono::system_clock::now();
236 if (!isCachingEnabled()) {
237 ptr = mCCDBAccessor.retrieveFromTFileAny<T>(path, mMetaData, timestamp, nullptr, "",
238 mCreatedNotAfter ? std::to_string(mCreatedNotAfter) : "",
239 mCreatedNotBefore ? std::to_string(mCreatedNotBefore) : "");
240 if (!ptr) {
241 if (mFatalWhenNull) {
242 reportFatal(std::string("Got nullptr from CCDB for path ") + path + std::string(" and timestamp ") + std::to_string(timestamp));
243 }
244 mFailures++;
245 } else {
246 mFetches++;
247 auto sh = mHeaders.find("fileSize");
248 if (sh != mHeaders.end()) {
249 size_t s = atol(sh->second.c_str());
250 mFetchedSize += s;
251 }
252 }
253 } else {
254 auto& cached = mCache[path];
255 cached.queries++;
256 if ((!isOnline() && cached.isCacheValid(timestamp)) || (mCheckObjValidityEnabled && cached.isValid(timestamp))) {
257 return reinterpret_cast<T*>(cached.noCleanupPtr ? cached.noCleanupPtr : cached.objPtr.get());
258 }
259 ptr = mCCDBAccessor.retrieveFromTFileAny<T>(path, mMetaData, timestamp, &mHeaders, cached.uuid,
260 mCreatedNotAfter ? std::to_string(mCreatedNotAfter) : "",
261 mCreatedNotBefore ? std::to_string(mCreatedNotBefore) : "");
262 if (ptr) { // new object was shipped, old one (if any) is not valid anymore
263 cached.fetches++;
264 mFetches++;
265 if constexpr (std::is_same<TGeoManager, T>::value || std::is_base_of<o2::conf::ConfigurableParam, T>::value) {
266 // some special objects cannot be cached to shared_ptr since root may delete their raw global pointer
267 cached.noCleanupPtr = ptr;
268 } else {
269 cached.objPtr.reset(ptr);
270 }
271 cached.uuid = mHeaders["ETag"];
272
273 try {
274 if (mHeaders.find("Valid-From") != mHeaders.end()) {
275 cached.startvalidity = std::stol(mHeaders["Valid-From"]);
276 } else {
277 // if meta-information missing assume infinit validity
278 // (should happen only for locally created objects)
279 cached.startvalidity = 0;
280 }
281 if (mHeaders.find("Valid-Until") != mHeaders.end()) {
282 cached.endvalidity = std::stol(mHeaders["Valid-Until"]);
283 } else {
284 cached.endvalidity = std::numeric_limits<long>::max();
285 }
286 cached.cacheValidFrom = timestamp;
287 } catch (std::exception const& e) {
288 reportFatal("Failed to read validity from CCDB response (Valid-From : " + mHeaders["Valid-From"] + std::string(" Valid-Until: ") + mHeaders["Valid-Until"] + std::string(")"));
289 }
290 auto sh = mHeaders.find("fileSize");
291 if (sh != mHeaders.end()) {
292 size_t s = atol(sh->second.c_str());
293 mFetchedSize += s;
294 cached.minSize = std::min(s, cached.minSize);
295 cached.maxSize = std::max(s, cached.minSize);
296 }
297 } else if (mHeaders.count("Error")) { // in case of errors the pointer is 0 and headers["Error"] should be set
298 cached.failures++;
299 cached.clear(); // in case of any error clear cache for this object
300 }
301 // the old object is valid, fetch cache end of validity
302 ptr = reinterpret_cast<T*>(cached.noCleanupPtr ? cached.noCleanupPtr : cached.objPtr.get());
303 if (mHeaders.find("Cache-Valid-Until") != mHeaders.end()) {
304 cached.cacheValidUntil = std::stol(mHeaders["Cache-Valid-Until"]);
305 } else {
306 cached.cacheValidUntil = -1;
307 }
308 mHeaders.clear();
309 mMetaData.clear();
310 if (!ptr) {
311 if (mFatalWhenNull) {
312 reportFatal(std::string("Got nullptr from CCDB for path ") + path + std::string(" and timestamp ") + std::to_string(timestamp));
313 }
314 mFailures++;
315 }
316 }
317 auto end = std::chrono::system_clock::now();
318 mTimerMS += std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
319 return ptr;
320}
321
322template <typename T>
323T* CCDBManagerInstance::getForRun(std::string const& path, int runNumber, bool setRunMetadata)
324{
325 auto metaData = setRunMetadata ? MD{{"runNumber", std::to_string(runNumber)}} : MD{};
326 mMetaData = metaData;
327 return getSpecificForRun<T>(path, runNumber, metaData);
328}
329
330template <typename T>
331T* CCDBManagerInstance::getSpecificForRun(std::string const& path, int runNumber, MD metaData)
332{
333 auto [start, stop] = getRunDuration(runNumber);
334 if (start < 0 || stop < 0) {
335 if (mFatalWhenNull) {
336 reportFatal(std::string("Failed to get run duration for run ") + std::to_string(runNumber));
337 }
338 return nullptr;
339 }
340 return getSpecific<T>(path, start / 2 + stop / 2, metaData);
341}
342
344{
345 public:
347 {
348 const std::string ccdbUrl{o2::base::NameConf::getCCDBServer()};
349 static BasicCCDBManager inst{ccdbUrl};
350 return inst;
351 }
352
353 private:
355 BasicCCDBManager(std::string const& url) : CCDBManagerInstance(url)
356 {
357 const char* t = getenv("ALICEO2_CCDB_CONDITION_NOT_AFTER");
358 if (t) {
359 auto timeaslong = strtol(t, nullptr, 10);
360 if (timeaslong != 0L) {
361 LOG(info) << "CCDB Time-machine constrained detected. Setting condition-not-after constrained to timestamp " << timeaslong;
362 setCreatedNotAfter(timeaslong);
363 }
364 }
365 }
366};
367
368} // namespace o2::ccdb
369
370#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()
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
T * getSpecificForRun(std::string const &path, int runNumber, MD metaData=MD())
retrieve an object of type T from CCDB as stored under path and using the timestamp in the middle of ...
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
T * getSpecific(std::string const &path, long timestamp=-1, MD metaData=MD())
retrieve an object of type T from CCDB as stored under path, timestamp and metaData
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
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:1301
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
static DeploymentMode deploymentMode()
std::string ccdbUrl
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
vec clear()