37 if(!spec.empty()) { impl->open_db(spec); }
38 return impl.release();
40 catch(dunedaq::conffwk::Exception & ex) {
57 TLOG_DEBUG( 3 ) <<
"Call destructor of OksConfigurationCheckDB object" ;
78 if (getenv(
"OKSCONFLIBS_NO_RELOAD_ABORT") !=
nullptr)
91 TLOG_DEBUG( 4 ) <<
"Destroy OksConfigurationCheckDB object = " << (
void *)
this ;
110 bool is_absolute_path = (s[0] ==
'/');
112 if (!is_absolute_path)
121 static std::string user_repo_dir;
122 static std::once_flag flag;
124 std::call_once(flag, []()
126 if (
const char * s = getenv(
"TDAQ_DB_USER_REPOSITORY"))
136 TLOG_DEBUG( 0) <<
"Failed to read TDAQ_DB_USER_REPOSITORY = \'" << s <<
"\':\n\tcaused by: " << ex.
what() ;
142 if (!user_repo_dir.empty() && s.find(user_repo_dir) == 0)
159 std::string::size_type idx = spec_params.find_first_of(
'&');
161 std::string data, params;
163 if (idx == std::string::npos)
169 data = spec_params.substr(0, idx);
170 params = spec_params.substr(idx + 1);
180 while (!(token = t.
next()).empty())
195 while (!(token = t.
next()).empty())
197 if(token ==
"norepo")
207 while(!(token = t.
next()).empty()) {
212 std::ostringstream text;
213 text <<
"cannot load file \'" << token <<
"\':\n" << e.
what();
218 std::ostringstream text;
219 text <<
"cannot load file \'" << token <<
'\'';
249 catch(oksconflibs::Exception& ex) {
252 catch(std::exception& ex) {
280 for(std::list<std::string>::const_iterator i = includes.begin(); i != includes.end(); ++i) {
285 std::ostringstream text;
286 text <<
"cannot add and load include file \'" << *i <<
"\' to \'" << db_name <<
"\':\n" << e.
what();
291 std::ostringstream text;
292 text <<
"cannot add and load include file \'" << *i <<
"\' to \'" << db_name <<
'\'';
302 std::ostringstream text;
303 text <<
"cannot create new data file \'" << db_name <<
"\': " << ex.
what();
308 std::ostringstream text;
309 text <<
"cannot create new data file \'" << db_name <<
"\'";
314 std::ostringstream text;
315 text <<
"cannot create new data file \'" << db_name <<
'\'';
323 std::ostringstream text;
324 text <<
"cannot find file \'" << db <<
'\'';
331 std::ostringstream text;
332 text <<
"cannot add and load include file \'" << include <<
"\' to \'" << db <<
'\'';
334 text <<
":\n" <<
error;
344 if (i.second->is_updated())
345 dbs.push_back(i.second->get_full_file_name());
359 std::ostringstream text;
360 text <<
"cannot " << action <<
" file \'" << file_h->
get_full_file_name() <<
"\' since " << reason;
377 unsigned int count(0);
394 if (!commit2repo && !log_message.empty())
403 std::ostringstream text;
404 text <<
"cannot save updated data file \'" << *(i.first) <<
"\':\n" << ex.
what();
410 if (commit2repo && count)
426 namespace oksconflibs{
469 const std::string file_name(i->get_full_file_name());
471 TLOG_DEBUG(1) <<
"destroy created file \'" << file_name <<
"\')" ;
474 if (
int result = unlink(file_name.c_str()))
476 std::ostringstream text;
477 text <<
"abort changes failed since cannot erase created file \'" << file_name <<
"\'; unlink failed with code " << result <<
": " <<
dunedaq::oks::strerror(errno);
487 std::set<OksFile *> updated;
491 if (i.second->is_updated())
493 updated.insert(i.second);
494 TLOG_DEBUG(2) <<
"file \'" << i.second->get_full_file_name() <<
"\' was updated, to be reloaded..." ;
500 std::set<OksFile *> mfs, rfs;
507 std::ostringstream text;
513 if (!updated.empty())
534static std::vector<dunedaq::conffwk::Version>
537 std::vector<dunedaq::conffwk::Version>
out;
538 out.reserve(in.size());
541 out.emplace_back(x.m_commit_hash, x.m_user, x.m_date, x.m_comment, x.m_files);
546std::vector<dunedaq::conffwk::Version>
562 std::vector<dunedaq::conffwk::Version>
out;
564 std::set<OksFile *> oks_files;
567 if (!oks_files.empty())
569 std::vector<std::string> files;
571 for(
const auto& x : oks_files)
572 files.push_back(x->get_well_formed_name());
574 out.emplace_back(
"",
"", 0,
"", files);
582std::vector<dunedaq::conffwk::Version>
607 return insert_object<dunedaq::oksconflibs::OksConfigObject>(obj, obj->GetId(), obj->GetClass()->get_name());
625 for (OksClass::FList::const_iterator it = subclasses->begin(); it != subclasses->end(); ++it)
627 if ((*it)->get_object(name))
639 if (
OksClass * cl = m_kernel->find_class(class_name))
647 for (
const auto& it : *subclasses)
649 obj = it->get_object(name);
656 const std::string id(name +
'@' + class_name);
661 object = new_object(obj);
670OksConfiguration::get(
const std::string& class_name, std::vector<conffwk::ConfigObject>& objects,
const std::string& query,
unsigned long ,
const std::vector<std::string> * )
678 objs = cl->create_list_of_all_objects();
682 std::unique_ptr<OksQuery> qe(
new OksQuery(cl, query.c_str()));
683 if(qe->good() ==
false) {
684 std::ostringstream text;
685 text <<
"bad query syntax \"" << query <<
"\" in scope of class \"" << class_name <<
'\"';
688 objs = cl->execute_query(qe.get());
691 std::ostringstream text;
692 text <<
"failed to execute query:\n" << ex.
what();
698 for(OksObject::List::iterator i = objs->begin(); i != objs->end(); ++i) {
721 for(OksObject::List::iterator i = objs->begin(); i != objs->end(); ++i) {
728 std::ostringstream text;
729 text <<
"bad path-query \"" << query <<
"\" to object " << o;
747 if(
const std::list<std::string *> * classes = c->direct_super_classes()) {
748 for(
const auto& i : *classes) {
749 const_cast< std::vector<std::string>&
>(d->p_superclasses).push_back(*i);
755 for(
const auto& i : *classes) {
756 const_cast< std::vector<std::string>&
>(d->p_superclasses).push_back(i->get_name());
762 for(
const auto& i : *subclasses) {
763 if(direct_only ==
false || i->has_direct_super_class(c->get_name()) ==
true) {
764 const_cast< std::vector<std::string>&
>(d->p_subclasses).push_back(i->get_name());
769 if(
const std::list<OksAttribute *> * attrs = (direct_only ? c->direct_attributes() : c->all_attributes())) {
770 for(
const auto& i : *attrs) {
774 const_cast< std::vector<dunedaq::conffwk::attribute_t>&
>(d->p_attributes).push_back(
805 i->get_is_multi_values(),
814 if(
const std::list<OksRelationship *> * rels = (direct_only ? c->direct_relationships() : c->all_relationships())) {
815 for(
const auto& i : *rels) {
816 const_cast< std::vector<dunedaq::conffwk::relationship_t>&
>(d->p_relationships).push_back(
822 i->get_is_composite(),
845 const std::string* name = &conffwk::DalFactory::instance().get_known_class_name_ref(i->second->get_name());
847 auto& subclasses = schema[name];
850 subclasses.reserve(scl->size() * 3);
851 for(OksClass::FList::const_iterator j = scl->begin(); j != scl->end(); ++j) {
852 subclasses.insert(&conffwk::DalFactory::instance().get_known_class_name_ref((*j)->get_name()));
873 std::ostringstream text;
874 text <<
"cannot find class \"" << class_name <<
'\"';
877 else if(
id.empty() ==
false) {
878 if(
OksObject * obj = c->get_object(
id)) {
879 std::ostringstream text;
880 text <<
"object \"" <<
id <<
'@' << class_name <<
"\" already exists in file \"" << obj->get_file()->get_full_file_name() <<
'\"';
903 if(at.empty() ==
true) {
908 return create(h, class_name,
id,
object);
911 std::ostringstream text;
912 text <<
"file \"" << at <<
"\" is not loaded";
938 reinterpret_cast<OksConfiguration *
>(p)->m_removed[o->GetClass()->get_name()].insert(o->GetId());
954 for (OksClass::Map::const_iterator i = kernel.
classes().begin(); i != kernel.
classes().end(); ++i)
957 std::set<std::string> &data(m_data[i->second->get_name()]);
958 for (
const auto &j : *slist)
959 data.insert(j->get_name());
974check(std::vector<conffwk::ConfigurationChange *>& changes,
976 const std::set<std::string>& class_names,
978 const std::string& obj_class,
979 const std::string& obj_id,
983 bool any = (class_names.empty() && objects.empty());
991 OksConfiguration::SMap::const_iterator omi = objects.end();
994 omi = objects.find(obj_class);
995 if(omi != objects.end()) {
996 std::set<std::string>::const_iterator i = omi->second.find(obj_id);
998 if(i != omi->second.end()) {
1007 if(action ==
'+' || omi == objects.end()) {
1008 if(any || class_names.find(obj_class) != class_names.end()) {
1016 OksConfiguration::SMap::const_iterator it = inheritance.
data().find(obj_class);
1017 if(it != inheritance.
data().end()) {
1018 for(std::set<std::string>::const_iterator j = it->second.begin(); j != it->second.end(); ++j) {
1019 omi = (action !=
'+' ? objects.find(*j) : objects.end());
1028 omi == objects.end() &&
1029 class_names.find(*j) != class_names.end()
1032 omi != objects.end() &&
1033 omi->second.find(obj_id) != omi->second.end()
1050 m_kernel.subscribe_delete_object(0, 0);
1095 std::vector<conffwk::ConfigurationChange *> changes;
1098 for(std::set<std::string>::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
1103 if(!changes.empty()) {
1126 catch (
const std::exception& ex)
1128 std::ostringstream text;
1129 text <<
"cannot check access status of file \'" << db_name <<
"\': " << ex.what();
1142 std::ostringstream text;
1143 text <<
"cannot remove include file \'" << include <<
"\' from \'" << db <<
'\'';
1145 text <<
":\n" <<
error;
1154 h->add_include_file(include);
1182 h->remove_include_file(include);
1198 std::vector<conffwk::ConfigurationChange *> changes;
1201 for(std::set<std::string>::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
1206 if(!changes.empty()) {
1216 if (db_name.empty())
1220 if(i.second->get_parent() ==
nullptr)
1221 includes.push_back(*i.first);
1228 for (
auto& i : h->get_include_files())
1230 includes.push_back(i);
1244 static const std::string
version(
"origin/master");
1248 std::set<OksFile *> ufs, rfs;
1257 std::ostringstream text;
1263 std::ostringstream text;
1264 text <<
"cannot get modified files: " << ex.
what();
1268 for (
const auto& x : ufs)
1270 if (x->get_oks_format() ==
"schema")
1272 std::ostringstream text;
1273 text <<
"reload of schema files is not supported (\'" << x->get_well_formed_name() <<
"\')";
1278 if (ufs.empty() ==
false)
1299 std::ostringstream text;
1300 text <<
"failed to reload updated files:\n" << ex.
what();
1315 std::vector<conffwk::ConfigurationChange *> changes;
1322 std::set<OksObject *>::iterator j =
m_modified.find(i);
1325 TLOG_DEBUG(1) <<
"created object " << i <<
" appears in \'modified\' set, removing..." ;
1336 TLOG_DEBUG(1) <<
"object " << (
void *)(i) <<
" is dangling, ignore..." ;
1348 for (
auto& j : i.second)
1355 if (!changes.empty())
1357 (*m_fn)(changes,
m_conf);
1380 ConfigurationImpl::notify cb,
1381 ConfigurationImpl::pre_notify pre_cb)
1397 TLOG_DEBUG( 2) <<
"starting CheckDB thread ..." ;
1412 TLOG_DEBUG( 2) <<
"stopping CheckDB thread ..." ;
1418 TLOG_DEBUG( 2) <<
"the CheckDB thread has been terminated" ;
1427 "OksConfiguration profiler report:\n"
#define ERS_DECLARE_ISSUE(namespace_name, class_name, message, attributes)
static void throw_update_exception(const OksFile *file_h, const char *action, const char *reason)
conffwk::ConfigurationImpl * _oksconflibs_creator_(const std::string &spec)
static std::string mk_no_file_error_text(const std::string &db)
static void check(std::vector< conffwk::ConfigurationChange * > &changes, const InheritanceData &inheritance, const std::set< std::string > &class_names, const OksConfiguration::SMap &objects, const std::string &obj_class, const std::string &obj_id, const char action)
bool is_repo_name(const std::string &name)
static std::string mk_add_include_error_text(const std::string &db, const std::string &include, const char *error=nullptr)
static std::string mk_rm_include_error_text(const std::string &db, const std::string &include, const char *error=0)
DestroyGuard1(OksKernel &kernel)
DestroyGuard2(OksConfiguration::SMap &removed)
OksConfiguration::SMap & m_removed
Represents database objects.
bool is_null() const noexcept
Check if object's implementation points to null.
const ConfigObjectImpl * implementation() const noexcept
Returns pointer on implementation.
static void clear(std::vector< ConfigurationChange * > &changes)
Helper method to clear vector of changes (pointers).
static void add(std::vector< ConfigurationChange * > &changes, const std::string &class_name, const std::string &obj_id, const char action)
Helper method to add object to the vector of existing changes.
Provides pure virtual interface used by the Configuration class.
void clean() noexcept
clean cache (e.g. to be used by destructor)
Configuration * m_conf
Configuration pointer is needed for notification on changes, e.g. in case of subscription or an objec...
void update_cache(std::vector< ConfigurationChange * > &changes) noexcept
System function invoked in case of modifications.
Generic configuration exception.
Try to access non-existent object or class.
const FList * all_sub_classes() const noexcept
OksObject * get_object(const std::string &id) const noexcept
Get object by ID.
std::list< OksClass *, boost::fast_pool_allocator< OksClass * > > FList
Provides interface to the OKS XML schema and data files.
void add_include_file(const std::string &name)
Add include file.
void add_comment(const std::string &text, const std::string &author)
Add new comment to file.
bool is_updated() const
Return update status of OKS file.
const std::string & get_full_file_name() const
FileStatus get_status_of_file() const
Return update status of file.
Provides interface to the OKS kernel.
static const std::string & get_repository_mapping_dir()
Get OKS repository name.
void subscribe_change_object(OksObject::notify_obj, void *)
Subscribe on object changing.
const std::string & get_user_repository_root() const
Get user OKS repository root.
void subscribe_delete_object(OksObject::notify_obj, void *)
Subscribe on object deleting.
OksFile * load_file(const std::string &name, bool bind=true)
Load OKS database file.
static std::string & get_user_name()
Get username of given process.
bool is_dangling(OksClass *class_ptr) const
Check pointer on oks class.
static bool check_read_only(OksFile *f)
Check if the OKS file is read-only.
void update_repository(const std::string &hash_val, RepositoryUpdateType update_type)
Update user repository files from origin by hash.
void get_modified_files(std::set< OksFile * > &mfs, std::set< OksFile * > &rfs, const std::string &version)
Get modified data files.
const OksFile::Map & data_files() const
Get all data files.
OksFile * new_data(const std::string &name, const std::string &logical_name="", const std::string &type="")
Create OKS data file.
OksFile * find_data_file(const std::string &s) const
Finds OKS data file.
bool is_user_repository_created() const
void registrate_all_classes(bool skip_registered=false)
The method rebuilds all classes taking into account inheritance.
const OksObject::Set & objects() const
Get objects.
bool get_test_duplicated_objects_via_inheritance_mode() const
Get status of test inherited duplicated objects mode. The method returns true, if the mode is switche...
void reload_data(std::set< OksFile * > &files, bool allow_schema_extension=true)
Reload OKS data files.
const OksClass::Map & classes() const
Get classes.
std::vector< OksRepositoryVersion > get_repository_versions_by_date(bool skip_irrelevant=true, const std::string &since="", const std::string &until="")
Return repository versions between timestamps.
void subscribe_create_object(OksObject::notify_obj cb_f, void *parameter)
Subscribe on object creation.
void close_all_data()
Close all OKS data files.
void save_data(OksFile *file_h, bool ignore_bad_objects=false, OksFile *true_file_h=nullptr, bool force_defaults=false)
Save OKS data file.
void set_test_duplicated_objects_via_inheritance_mode(const bool b)
Set status of test inherited duplicated objects mode. To switch 'On'/'Off' use the method's parameter...
void bind_objects()
Bind oks objects.
static const std::string & get_repository_root()
Get OKS repository root.
void commit_repository(const std::string &comments, const std::string &credentials="")
Commit user modifications into repository.
const std::string & get_repository_version()
void close_data(OksFile *file_h, bool unbind_objects=true)
Close OKS data file.
static const char * get_cwd()
std::vector< OksRepositoryVersion > get_repository_versions_by_hash(bool skip_irrelevant=true, const std::string &sha1="", const std::string &sha2="")
Return repository versions between hash keys.
OksClass * find_class(const std::string &class_name) const
Find class by name (C++ string).
void close_all_schema()
Close all OKS schema files.
void set_active_data(OksFile *file_h)
Set active OKS data file.
const OksFile::Map & schema_files() const
Get all schema files.
OksObject describes instance of OksClass.
static void destroy(OksObject *obj, bool fast=false)
Destroy OKS object.
std::list< OksObject * > List
OksObject::List * find_path(const oks::QueryPath &query) const
static void substitute_variables(std::string &)
static bool real_path(std::string &, bool ignore_errors)
Cannot commit, checkout or release files.
virtual const char * what() const noexcept
virtual bool test_object(const std::string &class_name, const std::string &name, unsigned long rlevel, const std::vector< std::string > *rclasses)
Test object existence (used by Python binding)
conffwk::ConfigurationImpl::pre_notify m_pre_fn
static void change_notify(oks::OksObject *, void *) noexcept
oks::OksKernel * m_kernel
virtual void open_db(const std::string &db_name)
Open database implementation in accordance with given name.
std::thread * m_check_db_thread
static void delete_notify(oks::OksObject *, void *) noexcept
std::set< std::string > m_class_names
virtual void subscribe(const std::set< std::string > &class_names, const SMap &objs, ConfigurationImpl::notify cb, ConfigurationImpl::pre_notify pre_cb)
virtual void print_profiling_info() noexcept
Print implementation specific profiling information.
virtual void get_includes(const std::string &db_name, std::list< std::string > &includes) const
Get included files.
virtual void destroy(conffwk::ConfigObject &object)
Destroy object of class by id.
static void create_notify(oks::OksObject *, void *) noexcept
std::list< oks::OksObject * > m_created
virtual void remove_include(const std::string &db_name, const std::string &include)
Remove include file.
std::set< oks::OksFile * > m_created_files
OksConfigObject * new_object(oks::OksObject *obj) noexcept
virtual void get_updated_dbs(std::list< std::string > &dbs) const
Get uncommitted files.
OksConfigurationCheckDB * m_check_db_obj
virtual void close_db()
Close database implementation.
bool m_oks_kernel_no_repo
std::map< std::string, std::set< std::string > > m_removed
std::map< std::string, std::set< std::string > > SMap
virtual void set_commit_credentials(const std::string &user, const std::string &password)
Set commit credentials.
virtual std::vector< dunedaq::conffwk::Version > get_versions(const std::string &since, const std::string &until, dunedaq::conffwk::Version::QueryType type, bool skip_irrelevant)
Get archived versions.
unsigned int m_repo_error_count
friend struct OksConfigurationCheckDB
virtual void unsubscribe()
Remove subscription on database changes.
virtual void add_include(const std::string &db_name, const std::string &include)
Add include file.
virtual std::vector< dunedaq::conffwk::Version > get_changes()
Get newly available versions.
virtual void create(const std::string &at, const std::string &class_name, const std::string &id, conffwk::ConfigObject &object)
Create object of class by id at given file.
virtual void abort()
Abort database changes.
virtual void get_superclasses(conffwk::fmap< conffwk::fset > &schema)
Get inheritance hierarchy.
std::set< oks::OksObject * > m_modified
virtual bool is_writable(const std::string &db_name)
Return write access status.
bool m_oks_kernel_silence
virtual void get(const std::string &class_name, const std::string &name, conffwk::ConfigObject &object, unsigned long rlevel, const std::vector< std::string > *rclasses)
Get object of class by id.
virtual void commit(const std::string &why)
Commit database changes.
void close_database(bool unsubscribe)
conffwk::ConfigurationImpl::notify m_fn
ResubscribeGuard(OksConfiguration &db)
#define TLOG_DEBUG(lvl,...)
const std::string strerror(int error)
Convert C error number to string.
static std::vector< dunedaq::conffwk::Version > oks2config(const std::vector< OksRepositoryVersion > &in)
bool is_writable(const oks::OksFile &file, const std::string &user=oks::OksKernel::get_user_name())
FELIX Initialization std::string initerror FELIX queue timed out
FELIX Initialization std::string initerror FELIX queue timed std::string queuename Unexpected chunk size
void fatal(const Issue &issue)
void error(const Issue &issue)
InheritanceData(const OksKernel &)
const OksConfiguration::SMap & data() const
OksConfiguration::SMap m_data
~OksConfigurationCheckDB()
OksConfigurationCheckDB(OksConfiguration *db)
Factory couldn t std::string alg_name Invalid configuration error