9#include <boost/python/def.hpp>
10#include <boost/python/overloads.hpp>
11#include <boost/python/docstring_options.hpp>
12#include <boost/python/list.hpp>
13#include <boost/python/dict.hpp>
14#include <boost/python/extract.hpp>
15#include <boost/python/return_value_policy.hpp>
16#include <boost/python/manage_new_object.hpp>
17#include <boost/python/raw_function.hpp>
18#include <boost/algorithm/string.hpp>
20#include <framework/database/Database.h>
22#include <framework/dataobjects/EventMetaData.h>
23#include <framework/logging/Logger.h>
24#include <framework/database/DBStore.h>
26#include <framework/database/PayloadProvider.h>
27#include <framework/database/MetadataProvider.h>
28#include <framework/database/LocalMetadataProvider.h>
29#include <framework/database/CentralMetadataProvider.h>
30#include <framework/database/Configuration.h>
52 conf.setInitialized(
false);
74 std::vector<DBQuery> query{
DBQuery{name,
true}};
76 entry.
updatePayload(query[0].revision, query[0].iov, query[0].filename, query[0].checksum, query[0].globaltag, event);
86 const size_t testingPayloads = std::count_if(query.begin(), query.end(), [
this, &event](
auto & payload) {
88 payload.filename =
"";
91 for (auto& tmp : m_testingPayloads) {
92 if (tmp.get(event, payload)) return true;
97 if (testingPayloads == query.size())
return true;
100 m_metadataProvider->getPayloads(event.getExperiment(), event.getRun(), query);
101 }
catch (std::exception&) {
103 B2WARNING(
"Conditions data: Problem with payload metadata provider, trying to fall back to next provider..."
104 <<
LogVar(
"provider", m_currentProvider));
105 nextMetadataProvider();
106 return getData(event, query);
109 const size_t payloadsLocated = std::count_if(query.begin(), query.end(), [
this](
auto & payload) {
111 if (!payload.filename.empty()) return true;
115 if (payload.revision == 0) return not payload.required;
117 if (not m_payloadProvider->find(payload)) {
121 auto loglevel = payload.required ? LogConfig::c_Error : LogConfig::c_Warning;
122 B2LOG(loglevel, 0,
"Conditions data: Could not find file for payload"
123 << LogVar(
"name", payload.name) << LogVar(
"revision", payload.revision)
124 << LogVar(
"checksum", payload.checksum) << LogVar(
"globaltag", payload.globaltag));
125 return not payload.required;
130 return payloadsLocated == query.size();
133 bool Database::storeData(std::list<DBImportQuery>& query)
135 return std::all_of(query.begin(), query.end(), [
this](
const auto &
import) {
136 return storeData(import.name, import.object, import.iov);
142 if (!m_payloadCreation) initialize();
143 auto result = m_payloadCreation->storeData(name, obj, iov);
146 for (
auto& testing : m_testingPayloads) {
153 std::string Database::getGlobalTags()
155 return boost::algorithm::join(m_globalTags,
",");
158 void Database::nextMetadataProvider()
160 if (m_metadataConfigurations.empty()) {
161 B2FATAL(
"Conditions data: No more metadata providers available");
163 m_currentProvider = m_metadataConfigurations.back();
164 m_metadataConfigurations.pop_back();
166 if (
auto pos = m_currentProvider.find(
"://"); pos != std::string::npos) {
168 auto protocol = m_currentProvider.substr(0, pos);
169 boost::algorithm::to_lower(protocol);
170 if (protocol ==
"file") {
171 m_currentProvider = m_currentProvider.substr(pos + 3);
172 }
else if (protocol ==
"http" or protocol ==
"https") {
175 B2FATAL(
"Conditions data: Unknown metadata protocol, only supported protocols for payload metadata are file, http, https"
176 <<
LogVar(
"protocol", protocol));
181 m_metadataProvider = std::make_unique<Conditions::CentralMetadataProvider>(m_currentProvider, m_usableTagStates);
183 m_metadataProvider = std::make_unique<Conditions::LocalMetadataProvider>(m_currentProvider, m_usableTagStates);
185 }
catch (std::exception& e) {
186 B2WARNING(
"Conditions data: Metadata provider not usable, trying next one ..."
187 <<
LogVar(
"provider", m_currentProvider) <<
LogVar(
"error", e.what()));
188 return nextMetadataProvider();
191 if (!m_metadataProvider->setTags(m_globalTags)) {
192 B2FATAL(
"Conditions data: Problems with globaltag configuration, cannot continue");
198 if (m_configState >= target)
return;
199 auto conf = Conditions::Configuration::getInstance();
201 if (m_configState == c_PreInit) {
205 conf.setInitialized(
true);
206 m_globalTags = conf.getFinalListOfTags();
209 std::transform(m_globalTags.begin(), m_globalTags.end(), m_globalTags.begin(),
210 [](
const auto & tag) {
211 return boost::algorithm::trim_copy(tag);
214 std::set<std::string> seen;
215 m_globalTags.erase(std::remove_if(m_globalTags.begin(), m_globalTags.end(),
216 [&seen](
const auto & tag) {
217 return not seen.insert(tag).second;
218 }), m_globalTags.end());
220 m_usableTagStates = conf.getUsableTagStates();
221 m_metadataConfigurations = conf.getMetadataProviders();
223 std::reverse(m_metadataConfigurations.begin(), m_metadataConfigurations.end());
224 m_currentProvider =
"";
225 m_configState = c_InitGlobaltagList;
228 if (m_configState >= target)
return;
229 if (m_configState == c_InitGlobaltagList) {
231 if (m_metadataConfigurations.empty()) {
232 m_metadataProvider = std::make_unique<Conditions::NullMetadataProvider>();
234 nextMetadataProvider();
237 if (!m_globalTags.empty()) {
239 if (m_globalTags.size() == 1) {
240 B2INFO(
"Conditions data: configured globaltag is " << m_globalTags[0]);
242 B2INFO(
"Conditions data: configured globaltags (highest priority first) are " << boost::algorithm::join(m_globalTags,
", "));
246 m_payloadProvider = std::make_unique<Conditions::PayloadProvider>(
247 conf.getPayloadLocations(),
248 conf.getDownloadCacheDirectory(),
249 conf.getDownloadLockTimeout()
252 m_payloadCreation = std::make_unique<Conditions::TestingPayloadStorage>(conf.getNewPayloadLocation());
254 m_testingPayloads.clear();
255 for (
const auto& path : conf.getTestingPayloadLocations()) {
256 B2INFO(
"Conditions data: configured to use testing payloads" <<
LogVar(
"location", path));
257 m_testingPayloads.emplace_back(path);
260 if (not m_testingPayloads.empty()) {
261 B2WARNING(R
"(Conditions data: configured to look for temporary testing payloads from one or more local folders.
263 This will lead to non-reproducible results and is strictly only for testing purposes.
264 It is NOT ALLOWED for official productions or data analysis and any results obtained like this WILL NOT BE PUBLISHED.
267 m_configState = c_Ready;
271 void Database::exposePythonAPI()
274 namespace py = boost::python;
277 Database::Instance();
280 py::docstring_options options(
true,
true,
false);
283 Conditions::Configuration::exposePythonAPI();
static Configuration & getInstance()
Get a reference to the instance which will be used when the Database is initialized.
ScopeGuard ensureSession()
Make sure there's an active session and return a ScopeGuard object that closes the session on destruc...
static Downloader & getDefaultInstance()
Return the default instance.
Class to hold one entry from the ConditionsDB in the DBStore.
@ c_Object
A ROOT file containing a object with the name of the DBStoreEntry.
TObject * releaseObject()
Return the pointer to the current object and release ownership: The caller is responsible to clean up...
Singleton base class for the low-level interface to the database.
std::unique_ptr< Conditions::MetadataProvider > m_metadataProvider
Currently active metadata provider.
EDatabaseState m_configState
Current configuration state of the database.
EDatabaseState
State of the database.
@ c_PreInit
Before any initialization.
std::unique_ptr< Conditions::TestingPayloadStorage > m_payloadCreation
testing payload storage to create new payloads
std::vector< Conditions::TestingPayloadStorage > m_testingPayloads
optional list of testing payload storages to look for existing payloads
A class that describes the interval of experiments/runs for which an object in the database is valid.
Simple ScopeGuard to execute a function at the end of the object lifetime.
Class to store variables with their name which were sent to the logging service.
void reset(bool keepEntries=false)
Invalidate all payloads.
void initialize(const EDatabaseState target=c_Ready)
Initialize the database connection settings on first use.
~Database()
Hidden destructor, as it is a singleton.
std::pair< TObject *, IntervalOfValidity > getData(const EventMetaData &event, const std::string &name)
Request an object from the database.
static Database & Instance()
Instance of a singleton Database.
static DBStore & Instance()
Instance of a singleton DBStore.
static void reset(bool keepConfig=false)
Reset the database instance.
ScopeGuard createScopedUpdateSession()
Make sure we have efficient http pipelinging during initialize/beginRun but don't keep session alive ...
void updatePayload(unsigned int revision, const IntervalOfValidity &iov, const std::string &filename, const std::string &checksum, const std::string &globaltag, const EventMetaData &event)
Update the payload information for this entry and if appropriate open the new file and extract the ob...
Abstract base class for different kinds of events.