diff --git a/CCDB/include/CCDB/BasicCCDBManager.h b/CCDB/include/CCDB/BasicCCDBManager.h index b7bf6920a5c7c..9668097c39473 100644 --- a/CCDB/include/CCDB/BasicCCDBManager.h +++ b/CCDB/include/CCDB/BasicCCDBManager.h @@ -108,16 +108,20 @@ class CCDBManagerInstance /// retrieve an object of type T from CCDB as stored under path, timestamp and metaData template - T* getSpecific(std::string const& path, long timestamp = -1, MD metaData = MD()) + T* getSpecific(std::string const& path, long timestamp = -1, MD metaData = MD(), std::map* headers = nullptr) { // TODO: add some error info/handling when failing mMetaData = metaData; - return getForTimeStamp(path, timestamp); + auto obj = getForTimeStamp(path, timestamp); + if (headers) { + *headers = mHeaders; + } + return obj; } /// retrieve an object of type T from CCDB as stored under path and using the timestamp in the middle of the run + metadata. The run number is provided separately to conform to typical analysis use (in which case metadata does not include runNumber) template - T* getSpecificForRun(std::string const& path, int runNumber, MD metaData = MD()); + T* getSpecificForRun(std::string const& path, int runNumber, MD const& metaData = MD()); /// detect online processing modes (i.e. CCDB objects may be updated in the lifetime of the manager) bool isOnline() const { return mDeplMode == o2::framework::DeploymentMode::OnlineAUX || mDeplMode == o2::framework::DeploymentMode::OnlineDDS || mDeplMode == o2::framework::DeploymentMode::OnlineECS; } @@ -129,6 +133,9 @@ class CCDBManagerInstance return getForTimeStamp(path, mTimestamp); } + // gain access to underlaying CCDB layer (to allow for more complex queries without need to reinit another API) + CcdbApi& getCCDBAccessor() { return mCCDBAccessor; } + bool isHostReachable() const { return mCCDBAccessor.isHostReachable(); } /// clear all entries in the cache @@ -230,11 +237,12 @@ class CCDBManagerInstance template T* CCDBManagerInstance::getForTimeStamp(std::string const& path, long timestamp) { + mHeaders.clear(); // we clear at the beginning; to allow to retrieve the header information in a subsequent call T* ptr = nullptr; mQueries++; auto start = std::chrono::system_clock::now(); if (!isCachingEnabled()) { - ptr = mCCDBAccessor.retrieveFromTFileAny(path, mMetaData, timestamp, nullptr, "", + ptr = mCCDBAccessor.retrieveFromTFileAny(path, mMetaData, timestamp, &mHeaders, "", mCreatedNotAfter ? std::to_string(mCreatedNotAfter) : "", mCreatedNotBefore ? std::to_string(mCreatedNotBefore) : ""); if (!ptr) { @@ -305,7 +313,6 @@ T* CCDBManagerInstance::getForTimeStamp(std::string const& path, long timestamp) } else { cached.cacheValidUntil = -1; } - mHeaders.clear(); mMetaData.clear(); if (!ptr) { if (mFatalWhenNull) { @@ -328,7 +335,7 @@ T* CCDBManagerInstance::getForRun(std::string const& path, int runNumber, bool s } template -T* CCDBManagerInstance::getSpecificForRun(std::string const& path, int runNumber, MD metaData) +T* CCDBManagerInstance::getSpecificForRun(std::string const& path, int runNumber, MD const& metaData) { auto [start, stop] = getRunDuration(runNumber, mFatalWhenNull); if (start < 0 || stop < 0) { diff --git a/DataFormats/Parameters/include/DataFormatsParameters/AggregatedRunInfo.h b/DataFormats/Parameters/include/DataFormatsParameters/AggregatedRunInfo.h index e509be97a14fa..865169118faf7 100644 --- a/DataFormats/Parameters/include/DataFormatsParameters/AggregatedRunInfo.h +++ b/DataFormats/Parameters/include/DataFormatsParameters/AggregatedRunInfo.h @@ -32,7 +32,7 @@ struct AggregatedRunInfo { int runNumber = 0; // run number int64_t sor = 0; // best known timestamp for the start of run int64_t eor = 0; // best known timestamp for end of run - int64_t orbitsPerTF = 0; // number of orbits per TF + int64_t orbitsPerTF = 0; // number of orbits per TF (takes precedence over that in GRPECS) int64_t orbitReset = 0; // timestamp of orbit reset before run int64_t orbitSOR = 0; // orbit when run starts after orbit reset int64_t orbitEOR = 0; // orbit when run ends after orbit reset @@ -43,6 +43,19 @@ struct AggregatedRunInfo { // fills and returns AggregatedRunInfo for a given run number. static AggregatedRunInfo buildAggregatedRunInfo(o2::ccdb::CCDBManagerInstance& ccdb, int runnumber); static AggregatedRunInfo buildAggregatedRunInfo(int runnumber, long sorMS, long eorMS, long orbitResetMUS, const o2::parameters::GRPECSObject* grpecs, const std::vector* ctfFirstRunOrbitVec); + + // Special method for MC becayse MC may use extra settings or different values. + // The idea is to rely on a composite RunInfo object that a MC production uploaded to CCDB. + // This may depend: + // - on the runnumber + // - the lpm_prod_tag as a unique specifier of a MC GRID campaign + // - maybe username -> to allow for analysis of user-generated AO2D. The username determines the base-path where to look for CCDB objects + // The return value is a pointer to AggregatedRunInfo if such object exists or nullptr otherwise + static AggregatedRunInfo const* lookupAggregatedRunInfo_MC(o2::ccdb::CCDBManagerInstance& ccdb, int run_number, std::string const& lpm_prod_tag, std::string const& username = "aliprod"); + + static void publishToCCDB_MC(AggregatedRunInfo const& info, o2::ccdb::CCDBManagerInstance& ccdb, int run_number, std::string const& lpm_prod_tag, std::string const& username); + + ClassDefNV(AggregatedRunInfo, 1); }; } // namespace o2::parameters diff --git a/DataFormats/Parameters/src/AggregatedRunInfo.cxx b/DataFormats/Parameters/src/AggregatedRunInfo.cxx index 22ce362b5d85a..ad3be46252a8c 100644 --- a/DataFormats/Parameters/src/AggregatedRunInfo.cxx +++ b/DataFormats/Parameters/src/AggregatedRunInfo.cxx @@ -83,3 +83,53 @@ o2::parameters::AggregatedRunInfo AggregatedRunInfo::buildAggregatedRunInfo(int } return AggregatedRunInfo{runnumber, sorMS, eorMS, nOrbitsPerTF, orbitResetMUS, orbitSOR, orbitEOR, grpecs}; } + +namespace +{ + +std::string getFullPath_MC(std::string username) +{ + // construct the path where to lookup + std::string path = "/Users/" + std::string(1, username[0]) + "/" + username; + std::string fullpath = path + "/" + "MCAggregatedRunInfo"; + return fullpath; +} + +} // namespace + +o2::parameters::AggregatedRunInfo const* AggregatedRunInfo::lookupAggregatedRunInfo_MC(o2::ccdb::CCDBManagerInstance& ccdb, int run_number, std::string const& lpm_prod_tag, std::string const& username) +{ + // we simply look if we find a prebuild AggregatedRunInfo, stored from an MC production, under the expected location + + std::map headers; + std::map metaDataFilter; + metaDataFilter["lpm_prod_tag"] = lpm_prod_tag; + + bool oldFatalState = ccdb.getFatalWhenNull(); + ccdb.setFatalWhenNull(false); + auto obj = ccdb.getSpecific(getFullPath_MC(username), run_number, metaDataFilter, &headers); + ccdb.setFatalWhenNull(oldFatalState); + return obj; +} + +void o2::parameters::AggregatedRunInfo::publishToCCDB_MC(AggregatedRunInfo const& info, o2::ccdb::CCDBManagerInstance& ccdb, int run_number, std::string const& lpm_prod_tag, std::string const& username) +{ + // we upload the info to the MC path on CCDB - but we check first of all of this is already there + auto path = getFullPath_MC(username); + std::map meta; + meta["lpm_prod_tag"] = lpm_prod_tag; + + auto cl = TClass::GetClass(typeid(AggregatedRunInfo)); + auto ti = cl->GetTypeInfo(); + + auto& api = ccdb.getCCDBAccessor(); + + auto headers = api.retrieveHeaders(path, meta, run_number); + if (headers.find("lpm_prod_tag") != headers.end()) { + LOG(info) << "AggregatedRunInfo Object already present on CCDB for this production tag and user. Not doing anything"; + // already uploaded + return; + } + + api.storeAsTFile_impl(&info, *ti, path, meta, run_number, run_number + 1); +} \ No newline at end of file