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