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>
25#include <framework/database/PayloadFile.h>
27#include <framework/database/PayloadProvider.h>
28#include <framework/database/MetadataProvider.h>
29#include <framework/database/LocalMetadataProvider.h>
30#include <framework/database/CentralMetadataProvider.h>
31#include <framework/database/Configuration.h>
53 conf.setInitialized(
false);
75 std::vector<DBQuery> query{
DBQuery{name,
true}};
77 entry.
updatePayload(query[0].revision, query[0].iov, query[0].filename, query[0].checksum, query[0].globaltag, event);
87 const size_t testingPayloads = std::count_if(query.begin(), query.end(), [
this, &event](
auto & payload) {
89 payload.filename =
"";
92 for (auto& tmp : m_testingPayloads) {
93 if (tmp.get(event, payload)) return true;
98 if (testingPayloads == query.size())
return true;
101 m_metadataProvider->getPayloads(event.getExperiment(), event.getRun(), query);
102 }
catch (std::exception&) {
104 B2WARNING(
"Conditions data: Problem with payload metadata provider, trying to fall back to next provider..."
105 <<
LogVar(
"provider", m_currentProvider));
106 nextMetadataProvider();
107 return getData(event, query);
110 const size_t payloadsLocated = std::count_if(query.begin(), query.end(), [
this](
auto & payload) {
112 if (!payload.filename.empty()) return true;
116 if (payload.revision == 0) return not payload.required;
118 if (not m_payloadProvider->find(payload)) {
122 auto loglevel = payload.required ? LogConfig::c_Error : LogConfig::c_Warning;
123 B2LOG(loglevel, 0,
"Conditions data: Could not find file for payload"
124 << LogVar(
"name", payload.name) << LogVar(
"revision", payload.revision)
125 << LogVar(
"checksum", payload.checksum) << LogVar(
"globaltag", payload.globaltag));
126 return not payload.required;
131 return payloadsLocated == query.size();
134 bool Database::storeData(std::list<DBImportQuery>& query)
136 return std::all_of(query.begin(), query.end(), [
this](
const auto &
import) {
137 return storeData(import.name, import.object, import.iov);
143 if (!m_payloadCreation) initialize();
144 auto result = m_payloadCreation->storeData(name, obj, iov);
147 for (
auto& testing : m_testingPayloads) {
154 std::string Database::getGlobalTags()
156 return boost::algorithm::join(m_globalTags,
",");
159 void Database::nextMetadataProvider()
161 if (m_metadataConfigurations.empty()) {
162 B2FATAL(
"Conditions data: No more metadata providers available");
164 m_currentProvider = m_metadataConfigurations.back();
165 m_metadataConfigurations.pop_back();
167 if (
auto pos = m_currentProvider.find(
"://"); pos != std::string::npos) {
169 auto protocol = m_currentProvider.substr(0, pos);
170 boost::algorithm::to_lower(protocol);
171 if (protocol ==
"file") {
172 m_currentProvider = m_currentProvider.substr(pos + 3);
173 }
else if (protocol ==
"http" or protocol ==
"https") {
176 B2FATAL(
"Conditions data: Unknown metadata protocol, only supported protocols for payload metadata are file, http, https"
177 <<
LogVar(
"protocol", protocol));
182 m_metadataProvider = std::make_unique<Conditions::CentralMetadataProvider>(m_currentProvider, m_usableTagStates);
184 m_metadataProvider = std::make_unique<Conditions::LocalMetadataProvider>(m_currentProvider, m_usableTagStates);
186 }
catch (std::exception& e) {
187 B2WARNING(
"Conditions data: Metadata provider not usable, trying next one ..."
188 <<
LogVar(
"provider", m_currentProvider) <<
LogVar(
"error", e.what()));
189 return nextMetadataProvider();
192 if (!m_metadataProvider->setTags(m_globalTags)) {
193 B2FATAL(
"Conditions data: Problems with globaltag configuration, cannot continue");
199 if (m_configState >= target)
return;
200 auto conf = Conditions::Configuration::getInstance();
202 if (m_configState == c_PreInit) {
206 conf.setInitialized(
true);
207 m_globalTags = conf.getFinalListOfTags();
210 std::transform(m_globalTags.begin(), m_globalTags.end(), m_globalTags.begin(),
211 [](
const auto & tag) {
212 return boost::algorithm::trim_copy(tag);
215 std::set<std::string> seen;
216 m_globalTags.erase(std::remove_if(m_globalTags.begin(), m_globalTags.end(),
217 [&seen](
const auto & tag) {
218 return not seen.insert(tag).second;
219 }), m_globalTags.end());
221 m_usableTagStates = conf.getUsableTagStates();
222 m_metadataConfigurations = conf.getMetadataProviders();
224 std::reverse(m_metadataConfigurations.begin(), m_metadataConfigurations.end());
225 m_currentProvider =
"";
226 m_configState = c_InitGlobaltagList;
229 if (m_configState >= target)
return;
230 if (m_configState == c_InitGlobaltagList) {
232 if (m_metadataConfigurations.empty()) {
233 m_metadataProvider = std::make_unique<Conditions::NullMetadataProvider>();
235 nextMetadataProvider();
238 if (!m_globalTags.empty()) {
240 if (m_globalTags.size() == 1) {
241 B2INFO(
"Conditions data: configured globaltag is " << m_globalTags[0]);
243 B2INFO(
"Conditions data: configured globaltags (highest priority first) are " << boost::algorithm::join(m_globalTags,
", "));
247 m_payloadProvider = std::make_unique<Conditions::PayloadProvider>(
248 conf.getPayloadLocations(),
249 conf.getDownloadCacheDirectory(),
250 conf.getDownloadLockTimeout()
253 m_payloadCreation = std::make_unique<Conditions::TestingPayloadStorage>(conf.getNewPayloadLocation());
255 m_testingPayloads.clear();
256 for (
const auto& path : conf.getTestingPayloadLocations()) {
257 B2INFO(
"Conditions data: configured to use testing payloads" <<
LogVar(
"location", path));
258 m_testingPayloads.emplace_back(path);
261 if (not m_testingPayloads.empty()) {
262 B2WARNING(R
"(Conditions data: configured to look for temporary testing payloads from one or more local folders.
264 This will lead to non-reproducible results and is strictly only for testing purposes.
265 It is NOT ALLOWED for official productions or data analysis and any results obtained like this WILL NOT BE PUBLISHED.
268 m_configState = c_Ready;
272 void Database::exposePythonAPI()
275 namespace py = boost::python;
278 Database::Instance();
281 py::docstring_options options(
true,
true,
false);
284 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.