82 std::filesystem::remove_all(path);
84 catch (std::exception &ex)
86 Oks::error_msg(
"OksKernel::~OksKernel") <<
"cannot remove user repository \"" << path <<
"\"" << ex.what() << std::endl;
118 return std::string(strerror_r(
error, buffer, 1024));
125 "cannot set group ID " <<
id <<
" for the file \'" << file <<
"\': chown() failed with code " << code <<
" , reason = \'" << why <<
'\'',
135 "Found unresolved reference(s):\n" << which,
142 "class \"" << name <<
"\" is defined in files \"" << f1 <<
"\" and \"" << f2 <<
"\"",
151 "internal error: " << text,
156 CanNotOpenFile::fill(
const char * prefix,
const std::string& name,
const std::string& reason)
noexcept
158 std::string result(prefix);
161 if(name.empty())
return (result +
"file name is empty");
163 result +=
"cannot load file \'" + name +
'\'' ;
165 if(!reason.empty()) {
166 result +=
" because:\n" + reason;
173 FailedLoadFile::fill(
const std::string& what,
const std::string& name,
const std::string& reason)
noexcept
175 return (std::string(
"Failed to load ") + what +
" \"" + name +
"\" because:\n" + reason);
181 return (std::string(
"Failed to re-load file(s) ") + names +
" because:\n" + reason);
187 return (std::string(
"Failed to ") + op +
" file(s) because:\n" + reason);
191 CanNotCreateFile::fill(
const char * prefix,
const char * what,
const std::string& name,
const std::string& reason)
noexcept
193 return std::string(prefix) +
"(): failed to create new " + what +
" \'" + name +
"\' because:\n" +
reason;
199 return std::string(prefix) +
"(): failed to create user repository dir, mkdtemp(\'" + name +
"\') failed: " +
strerror(errno);
203 CanNotWriteToFile::fill(
const char * prefix,
const char * item,
const std::string& name,
const std::string& reason)
noexcept
205 return (std::string(prefix) +
"(): failed to write " + item +
" to \'" + name +
"\' because:\n" + reason);
211 return (std::string(
"Failed to make a backup file of \'") + name +
"\' because:\n" + reason);
217 return (std::string(
"Failed to set active ") + item +
" file \'" + name +
"\' because:\n" + reason);
221 CanNotSetFile::fill(
const OksClass * c,
const OksObject * o,
const OksFile& file,
const std::string& reason)
noexcept
223 std::ostringstream
s;
224 s <<
"Failed to move ";
225 if(c)
s <<
"class " <<
c->get_name();
226 else s <<
"object " << o;
227 s <<
" to file \'" <<
file.get_full_file_name() <<
"\' because:\n" <<
reason;
234 return (std::string(
"Cannot add class \'") +
c.get_name() +
"\' because:\n" + reason);
240 std::ostringstream text;
241 text <<
"realpath(\'" << path <<
"\') has failed with code " << error_code <<
": \'" <<
strerror(error_code) <<
'\'';
246 static const std::string&
249 static std::string s_dir;
250 static std::once_flag flag;
252 std::call_once(flag, []()
256 if (!getenv(
"OKS_GIT_NO_VAR_DIR"))
260 s_dir =
"/var/run/user/";
261 s_dir.append(std::to_string(myself.
identity()));
263 if (std::filesystem::is_directory(s_dir) ==
false)
265 TLOG_DEBUG(1) <<
"directory " << s_dir <<
" does not exist";
270 const std::filesystem::space_info si = std::filesystem::space(s_dir);
271 const double available =
static_cast<double>(si.available) /
static_cast<double>(si.capacity);
275 TLOG_DEBUG(1) <<
"usage of " << s_dir <<
" is " <<
static_cast<int>((1.0 - available) * 100.0) <<
"%, will use standard temporary path";
282 s_dir = std::filesystem::temp_directory_path().string();
284 catch (std::exception& ex)
286 Oks::error_msg(
"OksKernel::OksKernel") <<
"cannot get temporary directory path: " << ex.what() << std::endl;
299 return "862f2957270";
306 static std::once_flag flag;
308 std::call_once(flag, []()
310 if (
const char * s = getenv(
"TDAQ_DB_REPOSITORY"))
314 if (!std::all_of(rep.begin(), rep.end(), [](
char c) { return std::isspace(c); }))
316 const char * p = getenv(
"OKS_GIT_PROTOCOL");
328 if (token.find(p) == 0)
340 Oks::error_msg(
"OksKernel::OksKernel") <<
"cannot find OKS_GIT_PROTOCOL=\"" << p <<
"\" in TDAQ_DB_REPOSITORY=\"" << rep <<
'\"' << std::endl;
352 static std::once_flag flag;
354 std::call_once(flag, []()
356 if (
const char * s = getenv(
"OKS_REPOSITORY_MAPPING_DIR"))
376 if(
const char * s = getenv(
"TDAQ_DB_USER_REPOSITORY")) {
392 TLOG_DEBUG( 1) <<
"Failed to set user-repository-root:\n\tcaused by: repository-root is not set" ;
409 TLOG_DEBUG( 1) <<
"Failed to set user-repository-root = \'" << s <<
"\':\n\tcaused by: " << ex.
what() ;
412 for(std::string::size_type idx = s.size()-1; idx > 0 && s[idx] ==
'/' ; idx--) {
431 static std::string s_host_name;
432 static std::once_flag flag;
434 std::call_once(flag, []()
438 if (s_host_name.empty())
439 s_host_name =
"unknown.host";
449 static std::string s_domain_name;
450 static std::once_flag flag;
452 std::call_once(flag, []()
456 if (idx != std::string::npos)
459 if (s_domain_name.empty())
460 s_domain_name =
"unknown.domain";
464 return s_domain_name;
470 static std::string s_user_name;
471 static std::once_flag flag;
473 std::call_once(flag, []()
478 if (s_user_name.empty())
479 s_user_name =
"unknown.user";
492 long file_length = 0;
496 f.seekg(0, std::ios::end);
499 file_length =
static_cast<std::streamoff
>(f.tellg());
501 file_length = f.tellg();
504 f.seekg(0, std::ios::beg);
512make_fname(
const char * f,
size_t f_len,
const std::string& file,
bool * p,
const OksFile *
const * fh)
514 const char _prefix [] =
"OksKernel::";
515 std::string fname(_prefix, (
sizeof(_prefix)-1));
517 fname.append(f, f_len);
519 const char _x1 [] =
"(file \'";
520 fname.append(_x1, (
sizeof(_x1)-1));
522 fname.push_back(
'\'');
528 const char _true_str [] =
", true";
529 fname.append(_true_str, (
sizeof(_true_str)-1));
532 const char _false_str [] =
", false";
533 fname.append(_false_str, (
sizeof(_false_str)-1));
540 const char _x2 [] =
", included by file \'";
541 fname.append(_x2, (
sizeof(_x2)-1));
542 fname.append((*fh)->get_full_file_name());
543 fname.push_back(
'\'');
546 fname.push_back(
')');
558 std::cerr <<
"ERROR [" << msg <<
"]:\n";
return std::cerr;
565 std::cerr <<
"WARNING [" << msg <<
"]:\n";
return std::cerr;
572 std::string::size_type pos = 0;
573 std::string::size_type p_start = 0;
574 std::string::size_type p_end = 0;
577 ((p_start = s.find(
"$(", pos)) != std::string::npos) &&
578 ((p_end = s.find(
")", p_start + 2)) != std::string::npos)
580 std::string var(s, p_start + 2, p_end - p_start - 2);
582 char * env = getenv(var.c_str());
585 s.replace(p_start, p_end - p_start + 1, env);
596 char resolved_name[PATH_MAX];
598 if(realpath(path.c_str(), resolved_name) != 0) {
599 path = resolved_name;
604 TLOG_DEBUG( 3) <<
"realpath(\'" << path <<
"\') has failed with code " << errno <<
": \'" <<
strerror(errno) <<
'\'' ;
616 "abcdefghijklmnoprstuvwxyz"
617 "ABCDEFGHIJKLMNOPRSTUVWXYZ";
623 static const size_t slen(
sizeof(
symbols)-1);
624 static const size_t slen2(slen*slen);
626 char b[16], *buf = b;
632 if((
size_t)
count >= slen) {
635 if((
size_t)
count >= slen2) {
669 std::ostringstream s;
671 while(j++ < 1000000) {
677 std::ofstream f(s2.c_str(), std::ios::in);
682 std::string s3(file);
696 long size = pathconf(
".", _PC_PATH_MAX);
699 Oks::error_msg(
"OksKernel::OksKernel") <<
"pathconf(\".\", _PC_PATH_MAX) has failed with code " << errno <<
": \'" <<
strerror(errno) <<
'\'' << std::endl;
710 Oks::error_msg(
"OksKernel::OksKernel") <<
"getcwd() has failed with code " << errno <<
": \'" <<
strerror(errno) <<
'\'' << std::endl;
737 p_allow_repository (allow_repository),
738 p_allow_duplicated_classes (true),
739 p_allow_duplicated_objects (false),
740 p_test_duplicated_objects_via_inheritance (false),
741 p_user_repository_root_inited (false),
742 p_user_repository_root_created (false),
743 p_active_schema (nullptr),
744 p_active_data (nullptr),
747 p_create_object_notify_fn (nullptr),
748 p_create_object_notify_param (nullptr),
749 p_change_object_notify_fn (nullptr),
750 p_change_object_notify_param (nullptr),
751 p_delete_object_notify_fn (nullptr),
752 p_delete_object_notify_param (nullptr)
754 OSK_VERBOSE_REPORT(
"Enter OksKernel::OksKernel(" << sm <<
", " << vm <<
", " << tm <<
')')
756 struct __InitFromEnv__ {
770 for(
unsigned int i = 0; i <
sizeof(vars) /
sizeof(__InitFromEnv__); ++i) {
771 if(
char * s = getenv(vars[i].name)) {
772 vars[i].value = (strcmp(s,
"no")) ?
true :
false;
777 const char * oks_db_root = getenv(
"OKS_DB_ROOT");
779 if (oks_db_root ==
nullptr || *oks_db_root == 0)
780 oks_db_root = getenv(
"DUNEDAQ_DB_PATH");
784 OSK_VERBOSE_REPORT(
"database root = \'" << oks_db_root <<
"\' (as defined by the OKS_DB_ROOT or DUNEDAQ_DB_PATH)");
789 if (oks_db_root ==
nullptr)
798 while (t.
next(token))
818 static std::once_flag flag;
820 std::call_once(flag, []()
822 if (
char * s = getenv(
"OKS_KERNEL_THREADS_POOL_SIZE"))
838 Oks::error_msg(
"OksKernel::OksKernel()") <<
" sysconf(_SC_NPROCESSORS_ONLN) has failed with code " << errno <<
": \'" <<
strerror(errno) <<
'\'' << std::endl;
858 std::string param, val;
861 version = getenv(
"TDAQ_DB_VERSION");
867 if(
const char * value = strchr(
version,
':'))
873 Oks::error_msg(
"OksKernel::OksKernel") <<
"bad version value \"" <<
version <<
"\" expecting parameter:value format (check TDAQ_DB_VERSION variable)" << std::endl;
885 if (branch_name.empty())
886 if (
const char *var = getenv(
"TDAQ_DB_BRANCH"))
893 Oks::error_msg(
"OksKernel::OksKernel") <<
"cannot check out user repository: " << ex.
what() << std::endl;
907 Oks::error_msg(
"OksKernel::OksKernel") <<
"cannot read user repository version: " << ex.
what() << std::endl;
920 p_silence (src.p_silence),
921 p_verbose (src.p_verbose),
922 p_profiling (src.p_profiling),
923 p_allow_repository (src.p_allow_repository),
924 p_allow_duplicated_classes (src.p_allow_duplicated_classes),
925 p_allow_duplicated_objects (src.p_allow_duplicated_objects),
926 p_test_duplicated_objects_via_inheritance (src.p_test_duplicated_objects_via_inheritance),
927 p_user_repository_root (src.p_user_repository_root),
928 p_user_repository_root_inited (src.p_user_repository_root_inited),
929 p_user_repository_root_created (false),
930 p_repository_version (src.p_repository_version),
931 p_repository_checkout_ts (src.p_repository_checkout_ts),
932 p_repository_update_ts (src.p_repository_update_ts),
933 p_active_schema (nullptr),
934 p_active_data (nullptr),
937 p_create_object_notify_fn (nullptr),
938 p_create_object_notify_param (nullptr),
939 p_change_object_notify_fn (nullptr),
940 p_change_object_notify_param (nullptr),
941 p_delete_object_notify_fn (nullptr),
942 p_delete_object_notify_param (nullptr)
962 Oks::error_msg(
"OksKernel::OksKernel") <<
"cannot copy user repository: " << ex.
what() << std::endl;
978 const OksFile::Map * src_files[2] = { &src.p_schema_files, &src.p_data_files };
979 OksFile::Map * dst_files[2] = { &p_schema_files, &p_data_files };
981 for (
int i = 0; i < 2; ++i)
983 for (
const auto& j : *src_files[i])
987 (*dst_files[i])[&f->p_full_name] = f;
998 for(
const auto& i : src.p_classes) {
1000 OksClass * c =
new OksClass (src_c.p_name, src_c.p_description, src_c.p_abstract,
nullptr, src_c.p_transient);
1003 p_classes[c->get_name().c_str()] = c;
1005 const_cast<OksClass&
>(src_c).p_id = idx++;
1006 c->p_id = src_c.p_id;
1007 c_table[c->p_id] = c;
1009 c->p_abstract = src_c.p_abstract;
1010 c->p_to_be_deleted = src_c.p_to_be_deleted;
1011 c->p_instance_size = src_c.p_instance_size;
1012 c->p_file = (*p_schema_files.find(&src_c.p_file->p_full_name)).second;
1013 c->p_objects = (src_c.p_objects ?
new OksObject::Map() : nullptr);
1017 if (
const std::list<std::string *> * scls = src_c.p_super_classes)
1019 c->p_super_classes = new std::list<std::string *>();
1021 for (const auto& j : *scls)
1022 c->p_super_classes->push_back(new std::string(*j));
1027 if (
const std::list<OksAttribute *> * attrs = src_c.p_attributes)
1029 c->p_attributes = new std::list<OksAttribute *>();
1031 for (const auto& j : *attrs)
1033 OksAttribute * a = new OksAttribute(j->p_name, c);
1035 a->p_range = j->p_range;
1036 a->p_data_type = j->p_data_type;
1037 a->p_multi_values = j->p_multi_values;
1038 a->p_no_null = j->p_no_null;
1039 a->p_init_value = j->p_init_value;
1040 a->p_init_data = j->p_init_data;
1041 a->p_format = j->p_format;
1042 a->p_description = j->p_description;
1044 if (j->p_enumerators)
1045 a->p_enumerators = new std::vector<std::string>(*j->p_enumerators);
1047 c->p_attributes->push_back(a);
1053 if (
const std::list<OksRelationship *> * rels = src_c.p_relationships)
1055 c->p_relationships =
new std::list<OksRelationship *>();
1057 for (
const auto& j : *rels)
1059 OksRelationship * r =
new OksRelationship(j->p_name, c);
1061 r->p_rclass = j->p_rclass;
1062 r->p_low_cc = j->p_low_cc;
1063 r->p_high_cc = j->p_high_cc;
1064 r->p_composite = j->p_composite;
1065 r->p_exclusive = j->p_exclusive;
1066 r->p_dependent = j->p_dependent;
1067 r->p_description = j->p_description;
1069 c->p_relationships->push_back(r);
1075 if (
const std::list<OksMethod *> * mets = src_c.p_methods)
1077 c->p_methods =
new std::list<OksMethod *>();
1079 for (
const auto& j : *mets)
1081 OksMethod *
m =
new OksMethod(j->p_name, j->p_description, c);
1083 if (
const std::list<OksMethodImplementation *> * impls = j->p_implementations)
1085 m->p_implementations =
new std::list<OksMethodImplementation *>();
1087 for (
const auto& x : *impls)
1088 m->p_implementations->push_back(
new OksMethodImplementation(x->get_language(), x->get_prototype(), x->get_body(), m));
1091 c->p_methods->push_back(m);
1099 for (
const auto& i : src.p_classes)
1101 OksClass *
c = c_table[i.second->p_id];
1104 if (
const std::list<OksRelationship *> * rels = i.second->p_relationships)
1106 for (
const auto& j : *rels)
1107 c->find_relationship(j->get_name())->p_class_type = (j->p_class_type ? c_table[j->p_class_type->p_id] :
nullptr);
1111 if (
const OksClass::FList * spcls = i.second->p_all_super_classes)
1113 c->p_all_super_classes =
new OksClass::FList();
1115 for (
const auto& j : *spcls)
1116 c->p_all_super_classes->push_back(c_table[j->p_id]);
1119 if (
const OksClass::FList * sbcls = i.second->p_all_sub_classes)
1121 c->p_all_sub_classes =
new OksClass::FList();
1123 for (
const auto& j : *sbcls)
1124 c->p_all_sub_classes->push_back(c_table[j->p_id]);
1128 c->p_data_info =
new OksDataInfo::Map();
1129 size_t instance_size = 0;
1132 if (
const std::list<OksAttribute *> * attrs = i.second->p_all_attributes)
1134 c->p_all_attributes =
new std::list<OksAttribute *>();
1136 for (
const auto& j : *attrs)
1138 OksAttribute * a = (c_table[j->p_class->p_id])->find_direct_attribute(j->get_name());
1139 c->p_all_attributes->push_back(a);
1140 (*
c->p_data_info)[a->get_name()] =
new OksDataInfo(instance_size++, a);
1145 if (
const std::list<OksRelationship *> * rels = i.second->p_all_relationships)
1147 c->p_all_relationships =
new std::list<OksRelationship *>();
1149 for (
const auto& j : *rels)
1151 OksRelationship *
r = (c_table[j->p_class->p_id])->find_direct_relationship(j->get_name());
1152 c->p_all_relationships->push_back(r);
1153 (*
c->p_data_info)[
r->get_name()] =
new OksDataInfo(instance_size++, r);
1158 if (
const std::list<OksMethod *> * mets = i.second->p_all_methods)
1160 c->p_all_methods =
new std::list<OksMethod *>();
1162 for (
const auto& j : *mets)
1163 c->p_all_methods->push_back((c_table[j->p_class->p_id])->find_direct_method(j->get_name()));
1167 if (
const std::vector<OksClass *> * ih = i.second->p_inheritance_hierarchy)
1169 c->p_inheritance_hierarchy =
new std::vector<OksClass *>();
1170 c->p_inheritance_hierarchy->reserve(ih->size());
1172 for (
const auto& j : *ih)
1173 c->p_inheritance_hierarchy->push_back(c_table[j->p_id]);
1180 if(!src.p_objects.empty()) {
1185 OksObject ** o_table =
new OksObject * [src.p_objects.size()];
1190 for(OksObject::Set::const_iterator i = src.p_objects.begin(); i != src.p_objects.end(); ++i, ++idx) {
1191 OksObject * src_o(*i);
1192 src_o->p_user_data =
reinterpret_cast<void *
>(idx);
1194 OksClass *
c = c_table[src_o->uid.class_id->p_id];
1196 OksObject * o =
new OksObject(
1198 src_o->uid.object_id,
1201 src_o->p_duplicated_object_id_idx,
1202 (*p_data_files.find(&src_o->file->p_full_name)).second
1206 (*
c->p_objects)[&o->uid.object_id] = o;
1207 p_objects.insert(o);
1209 if(
size_t num_of_attrs =
c->number_of_all_attributes()) {
1210 const OksData * src_data = src_o->data;
1211 OksData * dst_data = o->data;
1213 std::list<OksAttribute *>::const_iterator ia_dst =
c->all_attributes()->begin();
1214 std::list<OksAttribute *>::const_iterator ia_src = src_o->uid.class_id->all_attributes()->begin();
1216 for(
size_t j = 0; j < num_of_attrs; ++j) {
1217 *dst_data = *src_data;
1219 OksAttribute * a_dst(*ia_dst);
1223 if(a_dst->get_data_type() == OksData::class_type) {
1224 if(a_dst->get_is_multi_values() ==
false) {
1225 dst_data->data.CLASS = c_table[src_data->data.CLASS->p_id];
1228 OksData::List::iterator li_dst = dst_data->data.LIST->begin();
1229 OksData::List::iterator li_src = src_data->data.LIST->begin();
1231 while(li_dst != dst_data->data.LIST->end()) {
1232 (*li_dst)->data.CLASS = c_table[(*li_src)->data.CLASS->p_id];
1241 else if(a_dst->get_data_type() == OksData::enum_type) {
1242 OksAttribute * a_src(*ia_src);
1243 const std::string * p_enumerators_first(&((*(a_src->p_enumerators))[0]));
1245 if(a_dst->get_is_multi_values() ==
false) {
1246 unsigned long dx = src_data->data.ENUMERATION - p_enumerators_first;
1247 dst_data->data.ENUMERATION = &((*(a_dst->p_enumerators))[dx]);
1250 OksData::List::iterator li_dst = dst_data->data.LIST->begin();
1251 OksData::List::iterator li_src = src_data->data.LIST->begin();
1253 while(li_dst != dst_data->data.LIST->end()) {
1254 unsigned long dx = (*li_src)->data.ENUMERATION - p_enumerators_first;
1255 (*li_dst)->data.ENUMERATION = &((*(a_dst->p_enumerators))[dx]);
1274 for(
const auto& src_o : src.p_objects) {
1275 OksClass *
c = c_table[src_o->uid.class_id->p_id];
1276 OksObject * o(o_table[
reinterpret_cast<unsigned long>(src_o->p_user_data)]);
1278 if(
size_t num_of_rels =
c->number_of_all_relationships()) {
1279 const OksData * src_data(src_o->data +
c->number_of_all_attributes());
1280 OksData * dst_data(o->data +
c->number_of_all_attributes());
1282 for(
size_t j = 0; j < num_of_rels; ++j) {
1283 dst_data->type = src_data->type;
1284 switch(src_data->type) {
1285 case OksData::list_type:
1286 dst_data->data.LIST =
new OksData::List();
1287 for(
const auto& x : *src_data->data.LIST) {
1288 OksData *
d =
new OksData();
1290 if(x->type == OksData::object_type)
1292 if(
const OksObject * o2 = x->data.OBJECT)
1294 d->Set(o_table[
reinterpret_cast<unsigned long>(o2->p_user_data)]);
1298 d->Set((OksObject *)
nullptr);
1301 else if(x->type == OksData::uid_type)
1303 d->Set(c_table[x->data.UID.class_id->p_id], *x->data.UID.object_id);
1305 else if(x->type == OksData::uid2_type)
1307 d->Set(*x->data.UID2.class_id, *x->data.UID2.object_id);
1311 ers::error(kernel::InternalError(
ERS_HERE,
"unexpected data type in relationship list"));
1314 dst_data->data.LIST->push_back(d);
1318 case OksData::object_type:
1319 if(
const OksObject * o2 = src_data->data.OBJECT) {
1320 dst_data->data.OBJECT = o_table[
reinterpret_cast<unsigned long>(o2->p_user_data)];
1323 dst_data->data.OBJECT = 0;
1327 case OksData::uid_type:
1328 dst_data->data.UID.class_id = c_table[src_data->data.UID.class_id->p_id];
1329 dst_data->data.UID.object_id =
new OksString(*src_data->data.UID.object_id);
1332 case OksData::uid2_type:
1333 dst_data->data.UID2.class_id =
new OksString(*src_data->data.UID2.class_id);
1334 dst_data->data.UID2.object_id =
new OksString(*src_data->data.UID2.object_id);
1347 if (
const std::list<OksRCR *> * src_rcrs = src_o->p_rcr)
1349 o->p_rcr =
new std::list<OksRCR *>();
1351 for (
const auto& j : *src_rcrs)
1352 o->p_rcr->push_back(
1354 o_table[
reinterpret_cast<unsigned long>(j->obj->p_user_data)],
1355 (c_table[j->relationship->p_class->p_id])->find_direct_relationship(j->relationship->get_name())
1371 if (copy_repository && p_user_repository_root_inited)
1373 OksFile::Map * files_map[2] = { &p_schema_files, &p_data_files };
1375 for (
int i = 0; i < 2; ++i)
1377 std::vector<OksFile *> files;
1379 for (
auto& f : *files_map[i])
1380 files.push_back(
f.second);
1382 files_map[i]->clear();
1384 for (
auto& f : files)
1386 std::string name = p_user_repository_root;
1387 name.push_back(
'/');
1388 name.append(
f->get_repository_name());
1390 (*files_map[i])[&
f->p_full_name] = f;
1398OksKernel::insert_repository_dir(
const std::string& dir,
bool push_back)
1400 std::unique_lock lock(p_kernel_mutex);
1403 Oks::substitute_variables(s);
1406 Oks::real_path(s,
false);
1408 if(std::find(p_repository_dirs.begin(), p_repository_dirs.end(), s) == p_repository_dirs.end()) {
1409 if(push_back) p_repository_dirs.push_back(s);
else p_repository_dirs.push_front(s);
1411 std::cout <<
" * push " << (push_back ?
"back" :
"front") <<
" repository search directory \'" << s <<
"\'\n";
1417 TLOG_DEBUG( 1) <<
"Cannot insert repository dir \'" << dir <<
"\':\n\tcaused by: " << ex ;
1424OksKernel::remove_repository_dir(
const std::string& dir)
1426 std::unique_lock lock(p_kernel_mutex);
1428 std::list<std::string>::iterator i = std::find(p_repository_dirs.begin(), p_repository_dirs.end(), dir);
1429 if(i != p_repository_dirs.end()) {
1431 std::cout <<
" * remove repository search directory \'" << dir <<
"\'\n";
1433 p_repository_dirs.erase(i);
1439OksKernel::set_profiling_mode(
const bool b)
1441 if(p_profiling == b)
return;
1446 if(p_profiling ==
true) {
1459OksKernel::~OksKernel()
1468 std::unique_lock lock(p_kernel_mutex);
1470 p_classes.erase(p_classes.begin(), p_classes.end());
1480 remove_user_repository_dir();
1484 if(p_profiling) std::cout << *profiler << std::endl;
1496 s <<
"OKS KERNEL DUMP:\n" <<
"OKS VERSION: " << k.
GetVersion() << std::endl;
1500 s <<
" Loaded schema:\n";
1503 s <<
" " << i.second->get_full_file_name() << std::endl;
1507 s <<
" Loaded data:\n";
1510 s <<
" " << j.second->get_full_file_name() << std::endl;
1513 s <<
" No loaded data files\n";
1517 s <<
" The classes:\n";
1524 s <<
" No loaded schema files\n";
1526 s <<
"END OF OKS KERNEL DUMP.\n";
1534 static std::string suffix;
1535 static std::once_flag flag;
1537 std::call_once(flag, []()
1539 std::ostringstream s;
1540 s <<
'-' << get_user_name() <<
':' << get_host_name() <<
':' << getpid() << std::ends;
1549 static std::mutex p_check_read_only_mutex;
1550 std::lock_guard scoped_lock(p_check_read_only_mutex);
1553 std::ofstream f(s.c_str(), std::ios::out);
1568OksKernel::create_file_info(
const std::string& short_path,
const std::string& full_path)
1573 std::shared_ptr<std::ifstream> f(
new std::ifstream(full_path.c_str()));
1577 file_h =
new OksFile(xmls, short_path, full_path,
this);
1584 check_read_only(file_h);
1599 bool file_exists =
false;
1603 if(stat(file_name.c_str(), &buf) == 0) {
1605 Oks::warning_msg(fname) <<
" File \"" << file_name <<
"\" already exists\n";
1615 std::ofstream f(file_name.c_str());
1620 throw std::runtime_error(
"cannot open file in write mode");
1623 throw std::runtime_error(
"cannot create file");
1630 std::cout <<
"Creating new " << msg <<
" file \"" << file_name <<
"\"..." << std::endl;
1637 const char _s1_str[] =
" - \'";
1638 const char _s2_str[] =
"\' tested as ";
1640 return ((std::string(_s1_str,
sizeof(_s1_str)-1) + name).append(_s2_str,
sizeof(_s2_str)-1)).append(test, test_len);
1644#define TEST_PATH_TOKEN(path, file, msg) \
1645std::string token(path); \
1646token.push_back('/'); \
1647token.append(file); \
1648Oks::substitute_variables(token); \
1649if(Oks::real_path(token, true)) { \
1650 TLOG_DEBUG(2) << fname << " returns \'" << token << "\' (filename relative to " << msg << " database repository directory)"; \
1654 const char _test_name[] = "relative to database repository directory"; \
1655 tested_files.push_back(mk_name_and_test(token, _test_name, sizeof(_test_name)-1)); \
1660OksKernel::get_file_path(
const std::string& s,
const OksFile * file_h,
bool strict_paths)
const
1662 strict_paths &= p_use_strict_repository_paths;
1664 const char _fname[] =
"get_file_path";
1669 std::list<std::string> tested_files;
1672 bool is_absolute_path =
false;
1675 Oks::substitute_variables(s2);
1676 fname =
make_fname(_fname,
sizeof(_fname) - 1, s2,
nullptr, &file_h);
1680 is_absolute_path =
true;
1683 if (is_absolute_path || file_h == 0)
1685 if (!is_absolute_path && s_cwd && *s_cwd)
1687 std::string s3 = s_cwd;
1692 if (Oks::real_path(s2,
true))
1694 if (!get_user_repository_root().empty() && strict_paths)
1696 if (!get_repository_mapping_dir().empty() && s2.find(get_repository_mapping_dir()) == 0)
1698 s2.erase(0, get_repository_mapping_dir().
size()+1);
1701 else if (s2.find(get_user_repository_root()) == 0)
1704 TLOG_DEBUG(2) << fname <<
" returns external \'" << s2 <<
"\' (an absolute filename or relative to CWD=\'" << s_cwd <<
"\')";
1708 std::ostringstream text;
1709 text << fname <<
" file does not belong to oks git repository\n"
1710 "provide file repository name, or unset TDAQ_DB_REPOSITORY and try again with the DUNEDAQ_DB_PATH environment variable";
1711 throw std::runtime_error(text.str().c_str());
1715 TLOG_DEBUG(2) << fname <<
" returns \'" << s2 <<
"\' (an absolute filename or relative to CWD=\'" << s_cwd <<
"\')";
1721 if (is_absolute_path)
1723 const char _test_name[] =
"an absolute file name";
1724 tested_files.push_back(
mk_name_and_test(s2, _test_name,
sizeof(_test_name) - 1));
1728 const char _test_name[] =
"relative to current working directory";
1729 tested_files.push_back(
mk_name_and_test(s2, _test_name,
sizeof(_test_name) - 1));
1734 if( !get_user_repository_root().empty())
1739 if(get_user_repository_root().empty() || !p_use_strict_repository_paths)
1742 if (!is_absolute_path)
1743 for (
auto & i : p_repository_dirs)
1749 if (file_h && !is_absolute_path)
1752 std::string::size_type pos = s2.find_last_of(
'/');
1754 if (pos != std::string::npos)
1758 Oks::substitute_variables(s2);
1760 if (Oks::real_path(s2,
true))
1762 TLOG_DEBUG(2) << fname <<
" returns \'" << s2 <<
"\' (filename relative to parent file)";
1767 const char _test_name[] =
"relative to parent file";
1768 tested_files.push_back(
mk_name_and_test(s2, _test_name,
sizeof(_test_name) - 1));
1774 TLOG_DEBUG(2) << fname <<
" throw exception (file was not found)";
1776 std::ostringstream text;
1777 text << fname <<
" found no readable file among " << tested_files.size() <<
" tested:\n";
1778 for (
auto & i : tested_files)
1779 text << i << std::endl;
1781 throw std::runtime_error(text.str().c_str());
1788OksKernel::load_file(
const std::string& short_file_name,
bool bind)
1790 std::unique_lock lock(p_kernel_mutex);
1791 return k_load_file(short_file_name, bind, 0, 0);
1798OksKernel::k_load_file(
const std::string& short_file_name,
bool bind,
const OksFile * parent_h,
OksPipeline * pipeline)
1800 const char _fname[] =
"k_load_file";
1801 std::string fname =
make_fname(_fname,
sizeof(_fname)-1, short_file_name, &bind, &parent_h);
1805 std::string full_file_name;
1808 full_file_name = get_file_path(short_file_name, parent_h);
1810 catch (std::exception & e) {
1818 OksFile::Map::const_iterator i = p_schema_files.find(&full_file_name);
1819 if(i != p_schema_files.end())
return i->second->check_parent(parent_h);
1821 i = p_data_files.find(&full_file_name);
1822 if(i != p_data_files.end())
return i->second->check_parent(parent_h);
1824 std::shared_ptr<std::ifstream> f(
new std::ifstream(full_file_name.c_str()));
1830 throw std::runtime_error(
"k_load_file(): file is empty");
1837 OksFile * file_h =
new OksFile(xmls, short_file_name, full_file_name,
this);
1840 k_load_schema(file_h, xmls, parent_h);
1853 throw std::runtime_error(
"k_load_file(): failed to parse header");
1856 k_load_data(file_h, format, xmls, file_length, bind, parent_h, pipeline);
1864 throw std::runtime_error(
"k_load_file(): cannot open file");
1870 catch (std::exception & e) {
1874 throw FailedLoadFile(
"file", full_file_name,
"caught unknown exception");
1882 for(std::list<std::string>::const_iterator i = f.p_list_of_include_files.begin(); i != f.p_list_of_include_files.end(); ++i) {
1885 if(!get_user_repository_root().empty()) {
1886 if((*i)[0] ==
'/') {
1887 throw FailedLoadFile(
"include", *i,
"inclusion of files with absolute pathname (like \"/foo/bar\") is not allowed by repository files; include files relative to repository root (like \"foo/bar\")");
1889 else if((*i)[0] ==
'.') {
1890 throw FailedLoadFile(
"include", *i,
"inclusion of files with file-related relative pathnames (like \"../foo/bar\" or \"./bar\") is not supported by repository files; include files relative to repository root (like \"foo/bar\")");
1892 else if((*i).find(
'/') == std::string::npos) {
1893 throw FailedLoadFile(
"include", *i,
"inclusion of files with file-related local pathnames (like \"bar\") is not supported by repository files; include files relative to repository root (like \"foo/bar\")");
1898 k_load_file(*i,
false, &f, pipeline);
1903 catch (std::exception & e) {
1914OksKernel::get_includes(
const std::string& file_name, std::set< std::string >& includes,
bool use_repository_name)
1917 std::shared_ptr<std::ifstream> f(
new std::ifstream(file_name.c_str()));
1920 throw std::runtime_error(
"get_includes(): cannot open file");
1924 OksFile fp(xmls, file_name, file_name,
this);
1928 includes.insert(use_repository_name ? get_file_path(*i, &fp).substr(get_user_repository_root().
size()+1) : get_file_path(*i, &fp));
1937 catch (std::exception & e) {
1943OksKernel::test_parent(
OksFile * file, OksFile::IMap::iterator& i)
1948 if(includes.find(file) != includes.end()) {
1949 if(file->p_included_by != parent) {
1951 file->p_included_by = parent;
1961OksKernel::k_close_dangling_includes()
1967 for(OksFile::Map::iterator i = p_schema_files.begin(); i != p_schema_files.end(); ++i) {
1968 for(std::list<std::string>::const_iterator x = i->second->p_list_of_include_files.begin(); x != i->second->p_list_of_include_files.end(); ++x) {
1969 std::string f = get_file_path(*x, i->second);
1970 OksFile::Map::const_iterator it = p_schema_files.find(&f);
1971 if(it != p_schema_files.end()) {
1972 igraph[i->second].insert(it->second);
1975 std::cerr <<
"cannot find schema " << *x <<
" included by " << i->second->get_full_file_name() << std::endl;
1980 for(OksFile::Map::iterator i = p_data_files.begin(); i != p_data_files.end(); ++i) {
1981 for(std::list<std::string>::const_iterator x = i->second->p_list_of_include_files.begin(); x != i->second->p_list_of_include_files.end(); ++x) {
1982 std::string f = get_file_path(*x, i->second);
1983 OksFile::Map::const_iterator it = p_data_files.find(&f);
1984 if(it != p_data_files.end()) {
1985 igraph[i->second].insert(it->second);
1988 it = p_schema_files.find(&f);
1990 if(it != p_schema_files.end()) {
1991 igraph[i->second].insert(it->second);
1994 std::cerr <<
"cannot find file " << *x <<
" included by " << i->second->get_full_file_name() << std::endl;
2001 const size_t num_of_schema_files(schema_files().
size());
2007 std::list<OksFile *> schema_files, data_files;
2009 OksFile::Map * files[2] = {&p_schema_files, &p_data_files};
2010 std::list<OksFile *> to_be_closed[2];
2012 for(
int c = 0; c < 2; ++c) {
2013 for(OksFile::Map::iterator i = files[c]->begin(); i != files[c]->end(); ++i) {
2014 if(
OksFile * p =
const_cast<OksFile *
>(i->second->p_included_by)) {
2015 bool found_parent =
false;
2019 if(igraph.find(p) != igraph.end()) {
2020 OksFile::IMap::iterator j = igraph.find(p);
2021 if(test_parent(i->second, j)) {
2026 TLOG_DEBUG( 1 ) <<
"the parent of file " << i->second->get_full_file_name() <<
" is not valid" ;
2031 for(OksFile::IMap::iterator j = igraph.begin(); j != igraph.end(); ++j) {
2032 if(test_parent(i->second, j)) {
2033 found_parent =
true;
2038 if(found_parent ==
false) {
2039 TLOG_DEBUG( 1 ) <<
"the file " << i->second->get_full_file_name() <<
" is not included by any other file and will be closed" ;
2040 to_be_closed[c].push_back(i->second);
2048 for(std::list<OksFile *>::const_iterator i = to_be_closed[1].begin(); i != to_be_closed[1].end(); ++i) {
2049 num += (*i)->p_list_of_include_files.size();
2050 k_close_data(*i,
true);
2054 for(std::list<OksFile *>::const_iterator i = to_be_closed[0].begin(); i != to_be_closed[0].end(); ++i) {
2055 num += (*i)->p_list_of_include_files.size();
2061 TLOG_DEBUG( 1 ) <<
"go into recursive call, number of potentially closed includes is " << num ;
2069 if(num_of_schema_files != schema_files().
size()) {
2070 TLOG_DEBUG( 1 ) <<
"rebuild classes since number of schema files has been changed from " << num_of_schema_files <<
" to " << schema_files().size() ;
2071 registrate_all_classes();
2077OksKernel::k_preload_includes(
OksFile * fp, std::set<OksFile *>& new_files_h,
bool allow_schema_extension)
2079 bool found_include_changes(
false);
2082 std::shared_ptr<std::ifstream> file(
new std::ifstream(fp->
get_full_file_name().c_str()));
2085 throw std::runtime_error(std::string(
"k_preload_includes(): cannot open file \"") + fp->
get_full_file_name() +
'\"');
2090 std::set<std::string> included;
2094 included.insert(*i);
2100 file->seekg(0, std::ios::end);
2102 long file_length =
static_cast<std::streamoff
>(file->tellg());
2104 if(file_length == 0) {
2105 throw std::runtime_error(std::string(
"k_preload_includes(): file \"") + fp->
get_full_file_name() +
"\" is empty");
2108 file->seekg(0, std::ios::beg);
2115 p_preload_file_info[fp] =
new OksFile(*fp);
2119 throw std::runtime_error(std::string(
"k_preload_includes(): failed to read header of file \"") + fp->
get_full_file_name() +
'\"');
2126 throw std::runtime_error(std::string(
"k_preload_includes(): file \"") + fp->
get_full_file_name() +
"\" is not valid oks file");
2136 std::set<std::string>::const_iterator x = included.find(*i);
2137 if(x != included.end()) {
2138 TLOG_DEBUG(3) <<
"include \'" << *i <<
"\' already exists, skip...";
2143 found_include_changes =
true;
2145 std::string full_file_name;
2148 full_file_name = get_file_path(*i, fp);
2150 catch (std::exception & e) {
2154 OksFile::Map::const_iterator j = p_schema_files.find(&full_file_name);
2155 if(j != p_schema_files.end()) {
2156 TLOG_DEBUG(3) <<
"the include \'" << *i <<
"\' is already loaded schema file \'" << j->first <<
'\'';
2160 j = p_data_files.find(&full_file_name);
2161 if(j != p_data_files.end()) {
2162 TLOG_DEBUG(3) <<
"the include \'" << *i <<
"\' is already loaded data file \'" << j->first <<
'\'';
2166 if(
OksFile * f = create_file_info(*i, full_file_name)) {
2167 if(f->p_oks_format ==
"schema") {
2168 std::string new_schema_full_file_name = f->get_full_file_name();
2170 if(p_schema_files.find(&new_schema_full_file_name) != p_schema_files.end()) {
2171 TLOG_DEBUG(3) <<
"the include \'" << *i <<
"\' is a schema file, that was already loaded";
2175 if(allow_schema_extension) {
2176 TLOG_DEBUG(3) <<
"the include \'" << *i <<
"\' is new schema file, loading...";
2177 k_load_schema(*i, fp);
2181 std::ostringstream text;
2182 text <<
"k_preload_includes(): include of new schema file (\'" << *i <<
"\') is not allowed on data reload";
2183 throw std::runtime_error(text.str().c_str());
2187 else if(f->p_oks_format ==
"data" || f->p_oks_format ==
"extended" || f->p_oks_format ==
"compact") {
2188 TLOG_DEBUG(3) <<
"the include \'" << *i <<
"\' is new data file, pre-loading...";
2190 p_preload_added_files.push_back(f);
2191 new_files_h.insert(f);
2192 f->p_list_of_include_files.clear();
2193 if(k_preload_includes(f, new_files_h, allow_schema_extension)) found_include_changes =
true;
2194 f->p_included_by = fp;
2195 f->update_status_of_file();
2199 std::ostringstream text;
2200 text <<
"k_preload_includes(): failed to parse header of included \'" << full_file_name <<
"\' file";
2201 throw std::runtime_error(text.str().c_str());
2205 throw std::runtime_error(
"k_load_file(): cannot open file");
2214 catch (std::exception & e) {
2218 return found_include_changes;
2225OksKernel::create_user_repository_dir()
2227 if (
const char * path = getenv(
"TDAQ_DB_USER_REPOSITORY_PATH"))
2231 std::string user_repo;
2233 if (
const char * user_repo_base = getenv(
"TDAQ_DB_USER_REPOSITORY_ROOT"))
2234 user_repo = user_repo_base;
2236 user_repo = get_temporary_dir();
2238 user_repo.push_back(
'/');
2239 if (
const char * user_repo_pattern = getenv(
"TDAQ_DB_USER_REPOSITORY_PATTERN"))
2240 user_repo.append(user_repo_pattern);
2242 user_repo.append(
"oks.XXXXXX");
2244 std::unique_ptr<char[]> dir_template(
new char[user_repo.size() + 1]);
2245 strcpy(dir_template.get(), user_repo.c_str());
2247 if (
char * tmp_dirname = mkdtemp(dir_template.get()))
2260 std::string at = get_file_path(s,
nullptr);
2261 OksFile::Map::const_iterator i = files.find(&at);
2262 if(i != files.end())
return (*i).second;
2269 for(
const auto& f : files)
2271 if (s == f.second->get_short_file_name())
2281OksKernel::find_schema_file(
const std::string &s)
const
2283 return find_file(s, p_schema_files);
2287OksKernel::find_data_file(
const std::string &s)
const
2289 return find_file(s, p_data_files);
2297OksKernel::load_schema(
const std::string& short_file_name,
const OksFile * parent_h)
2299 std::unique_lock lock(p_kernel_mutex);
2300 return k_load_schema(short_file_name, parent_h);
2306OksKernel::k_load_schema(
const std::string& short_file_name,
const OksFile * parent_h)
2308 const char _fname[] =
"k_load_schema";
2309 std::string fname =
make_fname(_fname,
sizeof(_fname)-1, short_file_name,
nullptr, &parent_h);
2313 std::string full_file_name;
2316 full_file_name = get_file_path(short_file_name, parent_h);
2318 catch (std::exception & e) {
2319 throw CanNotOpenFile(
"k_load_schema", short_file_name, e.what());
2323 OksFile * fp = find_schema_file(full_file_name);
2327 std::lock_guard lock(p_parallel_out_mutex);
2328 Oks::warning_msg(fname) <<
" The file was already loaded\n";
2334 std::shared_ptr<std::ifstream> f(
new std::ifstream(full_file_name.c_str()));
2337 throw std::runtime_error(
"k_load_schema(): cannot open file");
2342 fp =
new OksFile(xmls, short_file_name, full_file_name,
this);
2345 throw std::runtime_error(
"k_load_schema(): failed to read header of file");
2348 throw std::runtime_error(
"k_load_schema(): file is not oks schema file");
2351 k_load_schema(fp, xmls, parent_h);
2364 catch (std::exception & e) {
2368 throw FailedLoadFile(
"schema file", full_file_name,
"caught unknown exception");
2374OksKernel::k_load_schema(
OksFile * fp, std::shared_ptr<OksXmlInputStream> xmls,
const OksFile * parent_h)
2379 check_read_only(fp);
2383 std::lock_guard lock(p_parallel_out_mutex);
2386 std::cout <<
"(non-fully-qualified filename was \"" << fp->
get_short_file_name() <<
"\")\n";
2390 k_load_includes(*fp, 0);
2392 add_schema_file(fp);
2394 std::list<OksClass *> set;
2407 if(c->get_name().empty()) {
2408 throw std::runtime_error(
"k_load_schema(): failed to read a class");
2411 OksClass::Map::const_iterator ic = p_classes.find(c->get_name().c_str());
2412 if(ic != p_classes.end()) {
2413 bool are_different = (*ic->second != *c);
2415 c->p_transient =
true;
2418 if(p_allow_duplicated_classes && !are_different) {
2419 static bool ers_report = (getenv(
"OKS_KERNEL_ERS_REPORT_DUPLICATED_CLASSES") !=
nullptr);
2424 const char _fname[] =
"k_load_schema";
2425 std::lock_guard lock(p_parallel_out_mutex);
2427 <<
" Class \"" << c->get_name() <<
"\" was already loaded from file \'" << c->get_file()->get_full_file_name() <<
"\'\n";
2431 std::stringstream text;
2432 text << (are_different ?
"different " :
"") <<
"class \"" << c->get_name() <<
"\" was already loaded from file \'" << c->get_file()->get_full_file_name() <<
'\'';
2433 throw std::runtime_error(text.str().c_str());
2438 std::unique_lock lock(p_schema_mutex);
2439 p_classes[c->get_name().c_str()] = c;
2442 if(OksClass::create_notify_fn) set.push_back(c);
2446 fp->
p_size = xmls->get_position();
2448 registrate_all_classes(
true);
2450 if(OksClass::create_notify_fn)
2451 for(std::list<OksClass *>::iterator i2 = set.begin(); i2 != set.end(); ++i2)
2452 (*OksClass::create_notify_fn)(*i2);
2454 if(OksClass::change_notify_fn) {
2455 std::set<OksClass *> set2;
2457 for(std::list<OksClass *>::iterator i2 = set.begin(); i2 != set.end(); ++i2) {
2459 if(c->p_all_sub_classes && !c->p_all_sub_classes->empty()) {
2460 for(OksClass::FList::iterator i3 = c->p_all_sub_classes->begin(); i3 != c->p_all_sub_classes->end(); ++i3) {
2461 if(set2.find(*i3) == set2.end()) {
2462 (*OksClass::change_notify_fn)(*i3, OksClass::ChangeSuperClassesList, (
const void *)(&(c->p_name)));
2475 catch (std::exception & e) {
2485OksKernel::new_schema(
const std::string& s)
2487 const char _fname[] =
"new_schema";
2488 std::string fname =
make_fname(_fname,
sizeof(_fname)-1, s,
nullptr,
nullptr);
2495 std::string file_name(s);
2499 Oks::substitute_variables(file_name);
2503 file_name = get_file_path(s,
nullptr,
false);
2505 std::unique_lock lock(p_kernel_mutex);
2507 if(find_schema_file(file_name) != 0) {
2508 throw std::runtime_error(
"the file is already loaded");
2511 OksFile * file_h =
new OksFile(file_name,
"",
"",
"schema",
this);
2515 k_set_active_schema(file_h);
2517 add_schema_file(p_active_schema);
2519 registrate_all_classes(
true);
2522 catch (std::exception & e) {
2526 throw CanNotCreateFile(
"new_schema",
"schema file", file_name,
"caught unknown exception");
2531 return p_active_schema;
2540 std::shared_lock lock(p_kernel_mutex);
2541 k_save_schema(pf, force, fh);
2548 std::shared_lock lock(p_kernel_mutex);
2549 k_save_schema(file_h, force, 0, &classes);
2554OksKernel::backup_schema(
OksFile * pf,
const char * suffix)
2556 std::shared_lock lock(p_kernel_mutex);
2572 std::cout <<
"Making backup of schema file \"" << pf->
p_full_name <<
"\"...\n";
2575 bool silence = p_silence;
2580 k_save_schema(&f,
true, pf);
2583 p_silence = silence;
2587 p_silence = silence;
2595 const char _fname[] =
"k_save_schema";
2601 std::string tmp_file_name;
2616 size_t numberOfClasses = 0;
2619 numberOfClasses = classes->size();
2621 else if(!p_classes.empty()) {
2622 for(OksClass::Map::iterator i = p_classes.begin(); i != p_classes.end(); ++i) {
2623 if(i->second->p_file == fh) numberOfClasses++;
2633 std::ofstream f(tmp_file_name.c_str());
2634 f.exceptions ( std::ostream::failbit | std::ostream::badbit );
2637 std::ostringstream text;
2638 text <<
"cannot create temporal file \'" << tmp_file_name <<
"\' to save schema";
2639 throw std::runtime_error(text.str().c_str());
2643 std::cout <<
"Saving " << numberOfClasses <<
" classes to schema file \"" << pf->
p_full_name <<
"\"...\n";
2660 std::ostringstream errors;
2661 bool found_errors =
false;
2665 for (
auto & i : *classes)
2667 found_errors |= i.second->check_relationships(errors,
false);
2668 i.second->save(xmls);
2673 for (
auto & i : p_classes)
2675 if (i.second->p_file == fh)
2677 found_errors |= i.second->check_relationships(errors,
false);
2678 i.second->save(xmls);
2685 kernel::BindError ex(
ERS_HERE, errors.str());
2689 throw std::runtime_error(ex.what());
2691 else if(p_silence ==
false)
2699 xmls.
put_last_tag(
"oks-schema",
sizeof(
"oks-schema")-1);
2707 if(rename(tmp_file_name.c_str(), pf->
p_full_name.c_str())) {
2708 std::ostringstream text;
2709 text <<
"cannot rename \'" << tmp_file_name <<
"\' to \'" << pf->
p_full_name <<
'\'';
2710 throw std::runtime_error(text.str().c_str());
2713 tmp_file_name.erase(0);
2715 if(pf != p_active_schema) {
2720 throw std::runtime_error(ex.
what());
2728 if(pf != p_active_schema) {
try { pf->
unlock();}
catch(...) {} }
2729 if(!tmp_file_name.empty()) { unlink(tmp_file_name.c_str()); }
2732 catch (std::exception & ex) {
2733 if(pf != p_active_schema) {
try { pf->
unlock();}
catch(...) {} }
2734 if(!tmp_file_name.empty()) { unlink(tmp_file_name.c_str()); }
2746OksKernel::k_rename_schema(
OksFile * pf,
const std::string& short_name,
const std::string& long_name)
2748 remove_schema_file(pf);
2749 pf->
rename(short_name, long_name);
2750 add_schema_file(pf);
2755OksKernel::save_as_schema(
const std::string& new_name,
OksFile * pf)
2757 const char _fname[] =
"save_as_schema";
2758 std::string fname =
make_fname(_fname,
sizeof(_fname)-1, new_name,
nullptr, &pf);
2763 if(!new_name.length()) {
2764 throw std::runtime_error(
"the new filename is empty");
2770 std::unique_lock lock(p_kernel_mutex);
2772 k_rename_schema(pf, new_name, new_name);
2778 k_rename_schema(pf, old_short_name, old_full_name);
2786 catch (std::exception & ex) {
2794OksKernel::save_all_schema()
2799 std::shared_lock lock(p_kernel_mutex);
2801 for(OksFile::Map::iterator i = p_schema_files.begin(); i != p_schema_files.end(); ++i) {
2802 if(check_read_only(i->second) ==
false) {
2803 k_save_schema(i->second);
2806 TLOG_DEBUG(2) <<
"skip read-only schema file \'" << *(i->first) <<
'\'';
2822 std::unique_lock lock(p_kernel_mutex);
2841 if(p_active_schema == pf) p_active_schema = 0;
2847 Oks::error_msg(
"OksKernel::k_close_schema()") << ex.
what() << std::endl;
2851 std::cout << (pf->
p_included_by ?
" * c" :
"C") <<
"lose OKS schema \"" << pf->
p_full_name <<
"\"..." << std::endl;
2853 if(!p_classes.empty()) {
2863 std::set<OksClass *> sorted;
2865 for(OksClass::Map::iterator i = p_classes.begin(); i != p_classes.end(); ++i) {
2867 if(pf == c->p_file) sorted.insert(c);
2868 c->p_to_be_deleted =
true;
2871 for(std::set<OksClass *>::iterator j = sorted.begin(); j != sorted.end(); ++j) {
2876 remove_schema_file(pf);
2879 TLOG_DEBUG(4) <<
"exit for file " << (
void *)pf;
2883OksKernel::close_all_schema()
2888 std::unique_lock lock(p_kernel_mutex);
2890 for(OksClass::Map::iterator i = p_classes.begin(); i != p_classes.end(); ++i) {
2891 i->second->p_to_be_deleted =
true;
2894 while(!p_schema_files.empty()) {
2895 k_close_schema(p_schema_files.begin()->second);
2905 std::unique_lock lock(p_kernel_mutex);
2906 k_set_active_schema(f);
2912 TLOG_DEBUG(4) <<
"enter for file " << (
void *)f;
2916 if(p_active_schema == f)
return;
2921 if(p_active_schema && p_active_schema->is_updated() ==
false) {
2923 p_active_schema->unlock();
2934 p_active_schema = 0;
2940 p_active_schema = f;
2946 TLOG_DEBUG(4) <<
"exit for file " << (
void *)f;
2949std::list<OksClass *> *
2950OksKernel::create_list_of_schema_classes(
OksFile * pf)
const
2952 std::string fname(
"OksKernel::create_list_of_schema_classes(");
2954 fname.push_back(
'\'');
2956 OSK_PROFILING(OksProfiler::KernelCreateSchemaClassList,
this)
2959 std::list<OksClass *> * clist =
nullptr;
2961 if(!p_classes.empty()) {
2962 for(OksClass::Map::const_iterator i = p_classes.begin(); i != p_classes.end(); ++i) {
2963 if(pf == i->second->p_file) {
2964 if(!clist && !(clist =
new std::list<OksClass *>())) {
2968 clist->push_back(i->second);
2986 for(OksFile::Map::const_iterator i = files.begin(); i != files.end(); ++i) {
2990 if(*ufs == 0) { *ufs =
new std::list<OksFile *>(); }
2991 (*ufs)->push_back(i->second);
2993 else if(fs == wr ) {
2994 if(*rfs == 0) { *rfs =
new std::list<OksFile *>(); }
2995 (*rfs)->push_back(i->second);
3001OksKernel::create_lists_of_updated_schema_files(std::list<OksFile *> ** ufs, std::list<OksFile *> ** rfs)
const
3003 std::shared_lock lock(p_kernel_mutex);
3009OksKernel::create_lists_of_updated_data_files(std::list<OksFile *> ** ufs, std::list<OksFile *> ** rfs)
const
3011 std::shared_lock lock(p_kernel_mutex);
3017OksKernel::get_modified_files(std::set<OksFile *>& mfs, std::set<OksFile *>& rfs,
const std::string&
version)
3019 std::list<OksFile *> * files[] =
3020 {
nullptr,
nullptr,
nullptr,
nullptr };
3022 std::set<OksFile *> * sets[] =
3025 create_lists_of_updated_data_files(&files[0], &files[1]);
3026 create_lists_of_updated_schema_files(&files[2], &files[3]);
3028 for (
int i = 0; i < 4; ++i)
3029 if (std::list<OksFile *> * f = files[i])
3033 sets[i % 2]->insert(f->front());
3039 if (!get_user_repository_root().empty() && !
version.empty())
3040 for (
const auto& file_name : get_repository_versions_diff(get_repository_version(),
version))
3042 if (
OksFile * f = find_data_file(file_name))
3044 else if (
OksFile * f = find_schema_file(file_name))
3052 void LoadErrors::add_parents(std::string& text,
const OksFile * file, std::set<const OksFile *>& parents)
3055 if(parents.insert(file).second ==
false) {
3056 text +=
"(ignoring circular dependency between included files...)\n";
3059 add_parents(text, file->get_parent(), parents);
3061 text += file->get_full_file_name();
3062 text +=
"\' includes:\n";
3067 void LoadErrors::add_error(
const OksFile& file, std::exception& ex)
3070 std::set<const OksFile *> parents;
3071 add_parents(text, file.get_parent(), parents);
3073 bool has_no_parents(text.empty());
3076 text += file.get_full_file_name();
3077 text += (has_no_parents ?
"\' has problem:\n" :
"\' that has problem:\n");
3080 std::lock_guard lock(p_mutex);
3081 m_errors.push_back(text);
3084 std::string LoadErrors::get_text()
3086 std::lock_guard lock(p_mutex);
3089 std::ostringstream s;
3091 if(m_errors.size() == 1) {
3092 s <<
"Found 1 error parsing OKS data:\n" << *m_errors.begin();
3095 s <<
"Found " << m_errors.size() <<
" errors parsing OKS data:";
3097 for(std::list<std::string>::const_iterator i = m_errors.begin(); i != m_errors.end(); ++i) {
3098 s <<
"\nERROR [" << j++ <<
"] ***: " << *i;
3102 m_error_string = s.str();
3105 return m_error_string;
3115 : m_kernel (kernel),
3126 ReadFileParams read_params( m_fp, *m_xmls, ((m_format ==
'X') ? 0 : &alias_table), m_kernel, m_format, 0 );
3128 m_fp->p_number_of_items = 0;
3131 while(OksObject::read(read_params)) {
3132 m_fp->p_number_of_items++;
3136 m_kernel->p_load_errors.add_error(*m_fp, ex);
3140 m_fp->p_size = m_xmls->get_position();
3142 catch (std::exception& ex) {
3143 m_kernel->p_load_errors.add_error(*m_fp, ex);
3169 for(OksFile::Map::const_iterator i = files.begin(); i != files.end(); ++i) {
3170 if(i->second == f)
return true;
3180 (*c)[o->
GetId()] = o;
3184ReloadObjects::pop(
const OksClass* c,
const std::string&
id)
3186 std::map< const OksClass *, map_str_t<OksObject *> * >::iterator i = data.find(c);
3187 if(i != data.end()) {
3189 if(j != i->second->end()) {
3191 i->second->erase(j);
3192 if(i->second->empty()) {
3203ReloadObjects::~ReloadObjects()
3211OksKernel::reload_data(std::set<OksFile *>& files_h,
bool allow_schema_extension)
3213 std::map<OksFile *, std::vector<std::string> > included;
3215 std::set<OksFile *>::const_iterator i;
3217 bool check_includes(
false);
3218 bool found_schema_files(
false);
3219 std::string file_names;
3221 std::unique_lock lock(p_kernel_mutex);
3223 for(std::set<OksFile *>::const_iterator fi = files_h.begin(); fi != files_h.end();) {
3225 found_schema_files =
true;
3228 Oks::error_msg(
"OksKernel::reload_data") <<
"file " << (
void *)(*fi) <<
" is not OKS data or schema file, skip..." << std::endl;
3229 files_h.erase(fi++);
3233 if(fi != files_h.begin()) file_names.append(
", ");
3234 file_names.push_back(
'\"');
3235 file_names.append((*fi)->get_full_file_name());
3236 file_names.push_back(
'\"');
3244 if(found_schema_files) {
3245 throw std::runtime_error(
"Reload of modified schema files is not supported");
3250 if(files_h.empty())
return;
3258 for(i = files_h.begin(); i != files_h.end(); ++i) {
3259 if((*i)->is_locked()) {
3260 if(p_active_data == (*i)) { p_active_data = 0; }
3264 for(OksObject::Set::const_iterator oi = p_objects.begin(); oi != p_objects.end(); ++oi) {
3265 if((*oi)->file == *i) reload_objects.
put(*oi);
3273 std::set<OksFile *> new_files;
3275 for(i = files_h.begin(); i != files_h.end(); ++i) {
3277 check_includes |= k_preload_includes(*i, new_files, allow_schema_extension);
3280 restore_preload_file_info();
3285 clear_preload_file_info();
3287 if(!new_files.empty()) {
3288 TLOG_DEBUG(2) << new_files.size() <<
" new files will be loaded";
3291 for(i = new_files.begin(); i != new_files.end(); ++i) {
3300 std::set<OksFile *> files_to_be_closed;
3302 if(check_includes) {
3303 size_t num_of_closing_files = 0;
3310 std::map<std::string, OksFile *> good_files;
3312 for(OksFile::Map::iterator j = p_data_files.begin(); j != p_data_files.end(); ++j) {
3313 if(files_to_be_closed.find(j->second) == files_to_be_closed.end()) {
3314 for(std::list<std::string>::iterator l = j->second->p_list_of_include_files.begin(); l != j->second->p_list_of_include_files.end(); ++l) {
3316 good_files[get_file_path(*l, j->second)] = j->second;
3324 for(OksFile::Map::iterator i = p_data_files.begin(); i != p_data_files.end(); ) {
3325 if(i->second->p_included_by && files_to_be_closed.find(i->second) == files_to_be_closed.end()) {
3326 TLOG_DEBUG(3) <<
"check the file \'" << i->second->get_full_file_name() <<
"\' is included";
3327 const std::string& s = i->second->get_full_file_name();
3335 std::map<std::string, OksFile *>::const_iterator j = good_files.find(s);
3337 if(j != good_files.end()) {
3341 files_to_be_closed.insert(f2);
3343 for(OksObject::Set::const_iterator oi = p_objects.begin(); oi != p_objects.end(); ++oi) {
3344 if((*oi)->file == f2) {
3345 reload_objects.
put(*oi);
3349 if (files_h.erase(f2)) {
3361 if(num_of_closing_files == files_to_be_closed.size()) {
3365 num_of_closing_files = files_to_be_closed.size();
3370 TLOG_DEBUG(2) <<
"no changes in the list of includes";
3378 if(c->p_all_relationships && !c->p_all_relationships->empty()) {
3379 const unsigned int atts_num(c->number_of_all_attributes());
3382 OksData * d(obj->data + atts_num);
3384 for(std::list<OksRelationship *>::iterator i = c->p_all_relationships->begin(); i != c->p_all_relationships->end(); ++i, ++d) {
3386 if(r->get_is_composite() && r->get_is_exclusive()) {
3387 if(d->type == OksData::object_type && d->data.OBJECT) {
3388 if(!is_dangling(d->data.OBJECT)) {
3389 d->data.OBJECT->remove_RCR(obj, r);
3392 else if(d->type == OksData::list_type && d->data.LIST) {
3393 for(OksData::List::iterator i2 = d->data.LIST->begin(); i2 != d->data.LIST->end(); ++i2) {
3411 bool duplicated_objs_mode = get_test_duplicated_objects_via_inheritance_mode();
3412 set_test_duplicated_objects_via_inheritance_mode(
false);
3417 for(i = files_h.begin(); i != files_h.end(); ++i) {
3418 std::shared_ptr<std::ifstream> f(
new std::ifstream((*i)->get_full_file_name().c_str()));
3422 OksFile fp(xmls, (*i)->get_short_file_name(), (*i)->get_full_file_name(),
this);
3426 std::lock_guard lock(p_parallel_out_mutex);
3427 std::cout <<
" * reading data file \"" << (*i)->get_full_file_name() <<
"\"..." << std::endl;
3432 ReadFileParams read_params( *i, *xmls, ((format ==
'X') ? 0 : &alias_table),
this, format, &reload_objects );
3435 while(OksObject::read(read_params)) { ; }
3438 set_test_duplicated_objects_via_inheritance_mode(duplicated_objs_mode);
3443 (*i)->update_status_of_file();
3444 (*i)->p_is_updated =
false;
3447 set_test_duplicated_objects_via_inheritance_mode(duplicated_objs_mode);
3457 oset.insert(ox->second);
3463 std::ostringstream text;
3464 text <<
"there are " << oset.size() <<
" removed objects:\n";
3466 for(OksObject::FSet::iterator x = oset.begin(); x != oset.end(); ++x) {
3467 text <<
" - object " << *x << std::endl;
3475 unbind_all_rels(oset, refs);
3476 if(p_change_object_notify_fn) {
3477 for(OksObject::FSet::const_iterator x2 = refs.begin(); x2 != refs.end(); ++x2) {
3478 TLOG_DEBUG(3) <<
"*** add object " << *x2 <<
" to the list of updated *** ";
3479 (*p_change_object_notify_fn)(*x2, p_change_object_notify_param);
3485 for(OksObject::FSet::iterator ox = oset.begin(); ox != oset.end(); ++ox) {
3488 if(is_dangling(o)) {
3489 TLOG_DEBUG(4) <<
"skip dangling object " << (
void *)o;
3493 TLOG_DEBUG(3) <<
"*** remove non-reloaded object " << o <<
" => " << (
void *)o <<
" ***";
3499 for(std::set<OksFile *>::const_iterator x = files_to_be_closed.begin(); x != files_to_be_closed.end(); ++x) {
3500 k_close_data(*x,
true);
3508 if (duplicated_objs_mode ==
true)
3510 for (
auto& o : reload_objects.
created)
3519 catch (std::exception & e) {
3525OksKernel::clear_preload_file_info()
3527 for(std::map<const OksFile *, OksFile *>::iterator i = p_preload_file_info.begin(); i != p_preload_file_info.end(); ++i) {
3531 p_preload_file_info.clear();
3532 p_preload_added_files.clear();
3536OksKernel::restore_preload_file_info()
3538 for(std::vector<OksFile *>::iterator j = p_preload_added_files.begin(); j != p_preload_added_files.end(); ++j) {
3539 TLOG_DEBUG( 1 ) <<
"remove file " << (*j)->get_full_file_name() ;
3540 remove_data_file(*j);
3544 for(OksFile::Map::iterator i = p_data_files.begin(); i != p_data_files.end(); ++i) {
3545 std::map<const OksFile *, OksFile *>::iterator j = p_preload_file_info.find(i->second);
3546 if(j != p_preload_file_info.end()) {
3547 TLOG_DEBUG( 1 ) <<
"restore file " << i->second->get_full_file_name() ;
3548 (*i->second) = (*j->second);
3552 clear_preload_file_info();
3559OksKernel::load_data(
const std::string& short_file_name,
bool bind)
3561 std::unique_lock lock(p_kernel_mutex);
3562 return k_load_data(short_file_name, bind, 0, 0);
3569OksKernel::k_load_data(
const std::string& short_file_name,
bool bind,
const OksFile * parent_h,
OksPipeline * pipeline)
3571 const char _fname[] =
"k_load_data";
3572 std::string fname =
make_fname(_fname,
sizeof(_fname)-1, short_file_name, &bind, &parent_h);
3576 std::string full_file_name;
3579 full_file_name = get_file_path(short_file_name, parent_h);
3581 catch (std::exception & e) {
3587 OksFile *fp = find_data_file(full_file_name);
3591 std::lock_guard lock(p_parallel_out_mutex);
3592 Oks::warning_msg(fname) <<
" The file \'" << full_file_name <<
"\' was already loaded";
3598 std::shared_ptr<std::ifstream> f(
new std::ifstream(full_file_name.c_str()));
3601 throw std::runtime_error(
"k_load_data(): cannot open file");
3607 throw std::runtime_error(
"k_load_data(): file is empty");
3612 fp =
new OksFile(xmls, short_file_name, full_file_name,
this);
3615 throw std::runtime_error(
"k_load_data(): failed to read header of file");
3627 throw std::runtime_error(
"k_load_data(): file is not an oks data file");
3630 k_load_data(fp, format, xmls, file_length, bind, parent_h, pipeline);
3643 catch (std::exception & e) {
3650OksKernel::k_load_data(
OksFile * fp,
char format, std::shared_ptr<OksXmlInputStream> xmls,
long file_length,
bool bind,
const OksFile * parent_h,
OksPipeline * pipeline)
3655 check_read_only(fp);
3659 std::lock_guard lock(p_parallel_out_mutex);
3660 std::cout << (parent_h ?
" * r" :
"R") <<
"eading data file \"" << fp->
get_full_file_name()
3661 <<
"\" in " << (format ==
'n' ?
"normal" : (format ==
'X' ?
"extended" :
"compact")) <<
" format (" << file_length <<
" bytes)...\n";
3663 std::cout <<
"(non-fully-qualified filename was \"" << fp->
get_short_file_name() <<
"\")\n";
3671 std::unique_ptr<OksPipeline> pipeline_guard(pipeline ? 0 :
new OksPipeline(p_threads_pool_size));
3676 m_pipeline = pipeline;
3679 m_pipeline = pipeline_guard.get();
3680 p_load_errors.clear();
3683 k_load_includes(*fp, m_pipeline);
3686 if(p_threads_pool_size > 1) {
3696 if(!p_load_errors.is_empty()) {
3711 catch (std::exception& e) {
3718OksKernel::new_data(
const std::string& s,
const std::string& logical_name,
const std::string& type)
3720 const char _fname[] =
"new_data";
3721 std::string fname =
make_fname(_fname,
sizeof(_fname)-1, s,
nullptr,
nullptr);
3728 std::string file_name(s);
3732 Oks::substitute_variables(file_name);
3736 file_name = get_file_path(s,
nullptr,
false);
3738 std::unique_lock lock(p_kernel_mutex);
3740 if(find_data_file(file_name) != 0) {
3741 throw std::runtime_error(
"the file is already loaded");
3744 OksFile * file_h =
new OksFile(file_name, logical_name, type,
"data",
this);
3748 k_set_active_data(file_h);
3750 add_data_file(p_active_data);
3756 catch (std::exception & e) {
3762 return p_active_data;
3769 p_data_files[&f->p_full_name] = f;
3775 p_schema_files[&f->p_full_name] = f;
3781 p_data_files.erase(&f->p_full_name);
3787 p_schema_files.erase(&f->p_full_name);
3794OksKernel::save_data(
OksFile * pf,
bool ignoreBadObjects,
OksFile * true_file_h,
bool force_defaults)
3796 std::shared_lock lock(p_kernel_mutex);
3797 k_save_data(pf, ignoreBadObjects, true_file_h,
nullptr, force_defaults);
3803 std::shared_lock lock(p_kernel_mutex);
3804 k_save_data(file_h,
false, 0, &objects);
3808OksKernel::backup_data(
OksFile * pf,
const char * suffix)
3810 std::shared_lock lock(p_kernel_mutex);
3826 std::lock_guard lock(p_parallel_out_mutex);
3827 std::cout <<
"Making backup of data file \"" << pf->
p_full_name <<
"\"...\n";
3830 bool silence = p_silence;
3835 k_save_data(&f,
true, pf);
3838 p_silence = silence;
3842 p_silence = silence;
3851 const char _fname[] =
"k_save_data";
3857 std::string tmp_file_name;
3865 size_t numberOfObjects = 0;
3868 numberOfObjects = objects->size();
3870 if(!ignoreBadObjects) {
3873 for(OksObject::FSet::const_iterator i = objects->begin(); i != objects->end(); ++i) {
3874 errors += (*i)->report_dangling_references();
3877 if(!errors.empty()) {
3878 std::ostringstream text;
3879 text <<
"the file contains objects with dangling references:\n" << errors;
3880 throw std::runtime_error(text.str().c_str());
3887 std::set<OksFile *> includes;
3892 bool found_bad_object =
false;
3894 for(OksObject::Set::iterator i = p_objects.begin(); i != p_objects.end(); ++i) {
3895 if((*i)->file == fh) {
3897 if(!ignoreBadObjects || !p_silence) {
3898 if((*i)->is_consistent(includes,
"WARNING") ==
false) {
3899 found_bad_object =
true;
3901 if((*i)->is_duplicated() ==
true) {
3903 Oks::error_msg(fname) <<
" The file contains duplicated object " << *i << std::endl;
3905 found_bad_object =
true;
3911 if(found_bad_object && ignoreBadObjects ==
false) {
3912 throw std::runtime_error(
"the file contains inconsistent/duplicated objects or misses includes");
3929 std::fstream f(pf->
p_full_name.c_str(), std::ios::in);
3935 std::fstream f2(pf->
p_full_name.c_str(), std::ios::out);
3938 std::ostringstream text;
3939 text <<
"cannot open file \'" << pf->
p_full_name <<
"\' for writing";
3940 throw std::runtime_error(text.str().c_str());
3951 std::ofstream f(tmp_file_name.c_str());
3953 f.exceptions ( std::ostream::failbit | std::ostream::badbit );
3956 std::ostringstream text;
3957 text <<
"cannot create temporal file \'" << tmp_file_name <<
"\' to save data";
3958 throw std::runtime_error(text.str().c_str());
3962 std::lock_guard lock(p_parallel_out_mutex);
3963 std::cout <<
"Saving " << numberOfObjects <<
" objects " << (force_defaults ?
"with enforced default values " :
"") <<
"to data file \"" << pf->
p_full_name <<
"\"...\n";
3977 if(!p_objects.empty()) {
3978 for(OksClass::Map::const_iterator i = p_classes.begin(); i != p_classes.end() && f.good(); ++i) {
3981 for(OksObject::Map::const_iterator j = i->second->p_objects->begin(); j != i->second->p_objects->end(); ++j) {
3982 if(j->second->file == fh || (objects && (objects->find(j->second) != objects->end()))) {
3983 sorted[j->first] = j->second;
3987 for(OksObject::SMap::iterator j = sorted.begin(); j != sorted.end(); ++j) {
3988 j->second->put(xmls, force_defaults);
3995 file_len = f.tellp();
4005 long written_len = 0;
4007 std::shared_ptr<std::ifstream> f(
new std::ifstream(tmp_file_name.c_str()));
4010 f->seekg(0, std::ios::end);
4011 written_len =
static_cast<std::streamoff
>(f->tellg());
4014 if(written_len != file_len) {
4015 unlink(tmp_file_name.c_str());
4016 std::ostringstream text;
4017 text <<
"write error in file \'" << tmp_file_name <<
"\': " << written_len <<
" bytes been written instead of " << file_len;
4018 throw std::runtime_error(text.str().c_str());
4026 if(
int code = stat(pf->
p_full_name.c_str(), &buf)) {
4027 std::ostringstream text;
4028 text <<
"cannot get information about file \'" << pf->
p_full_name <<
"\': stat() failed with code " << code <<
", reason = \'" <<
strerror(errno) <<
'\'';
4029 throw std::runtime_error(text.str().c_str());
4035 if(
int code = rename(tmp_file_name.c_str(), pf->
p_full_name.c_str())) {
4036 std::ostringstream text;
4037 text <<
"cannot rename file \'" << tmp_file_name <<
"\' to \'" << pf->
p_full_name <<
"\': rename() failed with code " << code <<
", reason = \'" <<
strerror(errno) <<
'\'';
4038 throw std::runtime_error(text.str().c_str());
4041 tmp_file_name.erase(0);
4044 if(pf != p_active_data) {
4049 throw std::runtime_error(ex.
what());
4059 if(
int code = stat(pf->
p_full_name.c_str(), &buf2)) {
4060 std::ostringstream text;
4061 text <<
"cannot get information about file \'" << pf->
p_full_name <<
"\': stat() failed with code " << code <<
", reason = \'" <<
strerror(errno) <<
'\'';
4062 throw std::runtime_error(text.str().c_str());
4068 if(buf.st_mode != buf2.st_mode) {
4069 if(
int code = chmod(pf->
p_full_name.c_str(), buf.st_mode) != 0) {
4070 std::ostringstream text;
4071 text <<
"cannot set protection mode for file \'" << pf->
p_full_name <<
"\': chmod() failed with code " << code <<
", reason = \'" <<
strerror(errno) <<
'\'';
4072 throw std::runtime_error(text.str().c_str());
4078 if(buf.st_gid != buf2.st_gid) {
4079 if(
int code = chown(pf->
p_full_name.c_str(), (gid_t)(-1), buf.st_gid) != 0) {
4087 if(pf != p_active_data) {
try { pf->
unlock();}
catch(...) {} }
4088 if(!tmp_file_name.empty()) { unlink(tmp_file_name.c_str()); }
4091 catch (std::exception & e) {
4092 if(pf != p_active_data) {
try { pf->
unlock();}
catch(...) {} }
4093 if(!tmp_file_name.empty()) { unlink(tmp_file_name.c_str()); }
4097 if(pf != p_active_data) {
try { pf->
unlock();}
catch(...) {} }
4098 if(!tmp_file_name.empty()) { unlink(tmp_file_name.c_str()); }
4110OksKernel::k_rename_data(
OksFile * pf,
const std::string& short_name,
const std::string& long_name)
4112 remove_data_file(pf);
4113 pf->
rename(short_name, long_name);
4118OksKernel::save_as_data(
const std::string& new_name,
OksFile * pf)
4120 const char _fname[] =
"save_as_data";
4121 std::string fname =
make_fname(_fname,
sizeof(_fname)-1, new_name,
nullptr, &pf);
4126 if(!new_name.length()) {
4127 throw std::runtime_error(
"the new filename is empty");
4130 std::unique_lock lock(p_kernel_mutex);
4136 k_rename_data(pf, new_name, new_name);
4142 k_rename_data(pf, old_short_name, old_full_name);
4151 catch (std::exception & ex) {
4160OksKernel::save_all_data(
bool force_defaults)
4165 std::shared_lock lock(p_kernel_mutex);
4167 for(OksFile::Map::iterator i = p_data_files.begin(); i != p_data_files.end(); ++i) {
4168 if(check_read_only(i->second) ==
false) {
4169 k_save_data(i->second,
false,
nullptr,
nullptr, force_defaults);
4172 TLOG_DEBUG(2) <<
"skip read-only data file \'" << *(i->first) <<
'\'';
4185 std::unique_lock lock(p_kernel_mutex);
4186 k_close_data(fp, unbind);
4194 const char _fname[] =
"k_close_data";
4204 Oks::error_msg(fname) << ex.
what() << std::endl;
4208 std::lock_guard lock(p_parallel_out_mutex);
4213 for(OksObject::Set::const_iterator i = p_objects.begin(); i != p_objects.end(); ++i) {
4219 if(p_close_all ==
false) {
4220 std::list<OksObject *> * olist = create_list_of_data_objects(fp);
4223 while(!olist->empty()) {
4226 if(!is_dangling(o))
delete o;
4233 remove_data_file(fp);
4236 if(p_active_data == fp) p_active_data = 0;
4243OksKernel::close_all_data()
4248 std::unique_lock lock(p_kernel_mutex);
4252 while(!p_data_files.empty()) {
4253 k_close_data(p_data_files.begin()->second,
false);
4256 if(!p_objects.empty()) {
4257 for(OksObject::Set::iterator i = p_objects.begin(); i != p_objects.end(); ++i) {
4263 for(OksClass::Map::const_iterator i = p_classes.begin(); i != p_classes.end(); ++i) {
4264 if(i->second->p_objects) {
4265 delete i->second->p_objects;
4266 i->second->p_objects = 0;
4271 p_close_all =
false;
4280 std::unique_lock lock(p_kernel_mutex);
4281 k_set_active_data(fp);
4287 TLOG_DEBUG(4) <<
"enter for file " << (
void *)fp;
4292 if(p_active_data == fp)
return;
4297 if(p_active_data && p_active_data->is_updated() ==
false) {
4299 p_active_data->unlock();
4322 TLOG_DEBUG(4) <<
"leave for file " << (
void *)fp;
4326std::list<OksObject *> *
4327OksKernel::create_list_of_data_objects(
OksFile * fp)
const
4329 const char _fname[] =
"create_list_of_data_objects";
4332 OSK_PROFILING(OksProfiler::KernelCreateDataObjectList,
this)
4336 std::list<OksObject *> * olist =
new std::list<OksObject *>();
4338 if(!p_objects.empty()) {
4339 for(OksObject::Set::const_iterator i = p_objects.begin(); i != p_objects.end(); ++i) {
4340 if((*i)->file == fp) olist->push_back(*i);
4344 if(olist->empty()) {
4361OksKernel::bind_objects()
4363 std::unique_lock lock(p_kernel_mutex);
4368OksKernel::k_bind_objects()
4372 p_bind_objects_status.clear();
4374 if(!p_objects.empty()) {
4375 for(OksObject::Set::iterator i = p_objects.begin(); i != p_objects.end(); ++i) {
4377 (*i)->bind_objects();
4384 const std::string error_text(strchr(ex.
what(),
'\n')+1);
4385 if(!p_bind_objects_status.empty()) p_bind_objects_status.push_back(
'\n');
4386 p_bind_objects_status.append(error_text);
4394 if(!p_silence && !p_bind_objects_status.empty()) {
4398 TLOG_DEBUG(4) <<
"exit with status:\n" << p_bind_objects_status;
4407 for(OksClass::Map::const_iterator i = all_classes.begin(); i != all_classes.end(); ++i) {
4410 for(OksObject::Map::const_iterator j = objs->begin(); j != objs->end(); ++j) {
4412 unsigned short l1 = c->number_of_all_attributes();
4413 unsigned short l2 = l1 + c->number_of_all_relationships();
4419 if(d->type == OksData::object_type) {
4420 if(rm_objs.find(d->data.OBJECT) != rm_objs.end()) {
4422 const OksClass * __c(d->data.OBJECT->GetClass());
4423 const OksString& __id(d->data.OBJECT->GetId());
4425 TLOG_DEBUG(5) <<
"set relationship of " << o <<
": " << *d;
4428 else if(d->type == OksData::list_type) {
4429 for(OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
4431 if(lid->
type == OksData::object_type) {
4432 if(rm_objs.find(lid->
data.
OBJECT) != rm_objs.end()) {
4437 TLOG_DEBUG(5) <<
"set relationship of " << o <<
": " << *d;
4451OksKernel::find_class(
const char * name)
const
4453 OksClass::Map::const_iterator i = p_classes.find(name);
4454 return (i != p_classes.end() ? i->second : 0);
4461 TLOG_DEBUG(4) <<
"enter for class \"" << c->get_name() <<
'\"';
4463 if(p_active_schema == 0) {
4467 if(p_classes.find(c->get_name().c_str()) != p_classes.end()) {
4472 c->p_file = p_active_schema;
4473 c->p_file->p_is_updated =
true;
4475 p_classes[c->get_name().c_str()] = c;
4478 registrate_all_classes(
false);
4484 if(OksClass::create_notify_fn) (*OksClass::create_notify_fn)(c);
4490 TLOG_DEBUG(4) <<
"enter for class \"" << c->get_name() <<
'\"';
4492 if(OksClass::delete_notify_fn) (*OksClass::delete_notify_fn)(c);
4494 p_classes.erase(c->get_name().c_str());
4499OksKernel::registrate_all_classes(
bool skip_registered)
4501 std::unique_lock lock(p_schema_mutex);
4503 if(
size_t num_of_classes = p_classes.size()) {
4505 size_t array_size = num_of_classes *
sizeof(
OksClass*) /
sizeof(
wchar_t);
4507 OksClass::Map::iterator i = p_classes.begin();
4508 unsigned long idx(0);
4510 for(; i != p_classes.end(); ++i) i->second->registrate_class(skip_registered);
4514 for(i = p_classes.begin(); i != p_classes.end(); ++i) {
4517 if(!c->p_all_sub_classes) c->p_all_sub_classes =
new OksClass::FList();
4518 else c->p_all_sub_classes->clear();
4523 for(i = p_classes.begin(); i != p_classes.end(); ++i) {
4526 for(OksClass::FList::const_iterator j = scl->begin(); j != scl->end(); ++j) {
4527 (*j)->p_all_sub_classes->push_back(c);
4532 if(get_test_duplicated_objects_via_inheritance_mode() && !get_allow_duplicated_objects_mode()) {
4533 for(i = p_classes.begin(); i != p_classes.end(); ++i) {
4535 if(!c->get_is_abstract()) {
4538 wmemset(
reinterpret_cast<wchar_t *
>(table), 0, array_size);
4539 for(OksClass::FList::const_iterator j1 = spc->begin(); j1 != spc->end(); ++j1) {
4541 for(OksClass::FList::const_iterator j2 = sbc->begin(); j2 != sbc->end(); ++j2) {
4544 table[c2->
p_id] = c2;
4550 unsigned int count(0);
4551 for(
unsigned int x = 0; x < num_of_classes; ++x) {
4552 if(table[x]) count++;
4556 std::vector<OksClass *> * cih;
4557 if(!c->p_inheritance_hierarchy) {
4558 cih = c->p_inheritance_hierarchy =
new std::vector<OksClass *>();
4561 cih = c->p_inheritance_hierarchy;
4565 cih->reserve(count);
4567 for(
unsigned int x = 0; x < num_of_classes; ++x) {
4568 if(table[x]) cih->push_back(table[x]);
4578 std::ostringstream s;
4580 for(i = p_classes.begin(); i != p_classes.end(); ++i) {
4581 if(std::vector<OksClass *> * cis = i->second->p_inheritance_hierarchy) {
4582 s <<
" - class \'" << i->second->get_name() <<
"\' shares IDs with " << cis->size() <<
" classes: ";
4584 for(std::vector<OksClass *>::const_iterator j = cis->begin(); j != cis->end(); ++j) {
4587 for(OksClass::Set::const_iterator j = sorted.begin(); j != sorted.end(); ++j) {
4588 if(j != sorted.begin()) s <<
", ";
4589 s <<
'\'' << (*j)->get_name() <<
'\'';
4595 TLOG_DEBUG(2) <<
"Schema inheritance hierarchy used to test objects with equal IDs:\n" << s.str();
4602 k_check_bind_classes_status();
4615 std::lock_guard lock(p_objects_mutex);
4616 not_found = (p_objects.find(o) == p_objects.end());
4620 std::string fname(
"OksKernel::is_dangling(");
4623 fname +=
"?object?) returns true";
4626 fname += o->
GetId();
4627 fname +=
"\") returns false";
4643 bool not_found =
true;
4646 if(!p_classes.empty()) {
4647 for(OksClass::Map::const_iterator i = p_classes.begin(); i != p_classes.end(); ++i) {
4648 if(i->second == c) {
4657 std::string fname(
"OksKernel::is_dangling(");
4660 fname +=
"?class?) returns true";
4663 fname += c->get_name();
4664 fname +=
"\") returns false";
4675OksKernel::get_all_classes(
const std::vector<std::string>& names_in,
ClassSet& classes_out)
const
4677 for(std::vector<std::string>::const_iterator i = names_in.begin(); i != names_in.end(); ++i) {
4679 if(c != 0 && classes_out.find(c) == classes_out.end()) {
4680 classes_out.insert(c);
4682 for(OksClass::FList::const_iterator j = sc->begin(); j != sc->end(); ++j) {
4683 classes_out.insert(*j);
4709std::mutex ReposDirs::p_mutex;
4712ReposDirs::ReposDirs(
const char * op,
const char * cwd,
OksKernel * kernel)
4714 p_repository_root = OksKernel::get_repository_root().c_str();
4715 if(OksKernel::get_repository_root().empty()) {
4719 p_repos_dir_len = strlen(p_repository_root);
4723 if(!*p_user_repository_root) {
4724 throw RepositoryOperationFailed(op,
"the user-repository-root is not set (check environment variable TDAQ_DB_USER_REPOSITORY)");
4727 p_user_dir_len = strlen(p_user_repository_root);
4732 if(strcmp(cwd, p_user_repository_root)) {
4733 if(
int result = chdir(p_user_repository_root)) {
4735 std::ostringstream text;
4736 text <<
"chdir (\'" << p_user_repository_root <<
"\') failed with code " << result <<
": " <<
strerror(errno);
4740 TLOG_DEBUG( 2 ) <<
"change cwd: \"" << p_user_repository_root <<
'\"' ;
4744 TLOG_DEBUG( 2 ) <<
"cwd: \"" << p_user_repository_root <<
"\" is equal to target dir" ;
4748ReposDirs::~ReposDirs()
4751 if(
int result = chdir(p_dir)) {
4752 Oks::error_msg(
"ReposDirs::~ReposDirs()")
4753 <<
"chdir (\'" << p_dir <<
"\') failed with code " << result <<
": " <<
strerror(errno) << std::endl;
4755 TLOG_DEBUG( 2 ) <<
"restore cwd: \"" << p_dir <<
'\"' ;
4771 std::string cat2str()
const;
4772 std::string last_str()
const;
4774 void check_command_status(
int status);
4782CommandOutput::CommandOutput(
const char *command_name,
const OksKernel *k, std::string &cmd) :
4783p_command(cmd), p_command_name(command_name)
4785 p_file_name = get_temporary_dir() +
'/' + command_name +
'.' + std::to_string(getpid()) +
':' + std::to_string(
reinterpret_cast<std::uintptr_t
>(k)) +
".txt";
4803 std::filebuf * buf = f.rdbuf();
4805 char c = buf->sbumpc();
4818 std::string lastline;
4822 f.seekg(-1, std::ios_base::end);
4823 if (f.peek() ==
'\n')
4825 f.seekg(-1, std::ios_base::cur);
4826 for (
int i = f.tellg(); i >= 0; i--)
4828 if (f.peek() ==
'\n')
4833 f.seekg(i, std::ios_base::beg);
4837 getline(f, lastline);
4848 std::ostringstream text;
4852 else if (
int error_code = WEXITSTATUS(status))
4854 std::ostringstream text;
4855 text <<
p_command.substr(0,
p_command.find_first_of(
' ')) <<
" exit with error code " << error_code <<
", output:\n" <<
cat2str();
4867 file_h->
rename(new_name);
4873 file_h->
rename(new_name);
4887 std::string cmd(
"oks-checkout.sh");
4899 cmd.push_back(
'\"');
4901 cmd.push_back(
'\"');
4904 if (!branch_name.empty())
4907 cmd.append(branch_name);
4910 auto start_usage = std::chrono::steady_clock::now();
4915 log_timestamp() <<
"[OKS checkout] => " << cmd << std::endl;
4926 std::cout << cmd_out.
cat2str();
4927 log_timestamp() <<
"[OKS checkout] => done in " << std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()-start_usage).count() / 1000. <<
" ms" << std::endl;
4930 static std::string version_prefix(
"checkout oks version ");
4932 std::string::size_type pos =
version.find(version_prefix);
4961 std::string cmd(
"oks-copy.sh");
4970 cmd.append(destination);
4975 auto start_usage = std::chrono::steady_clock::now();
4987 std::cout << cmd_out.
cat2str();
4988 log_timestamp() <<
"[OKS copy] => done in " << std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()-start_usage).count() / 1000. <<
" ms" << std::endl;
4999 throw RepositoryOperationFailed(
"update",
"the repository-root is not set (check environment variable TDAQ_DB_REPOSITORY)");
5002 throw RepositoryOperationFailed(
"update",
"the user-repository-root is not set (check environment variable TDAQ_DB_USER_REPOSITORY)");
5004 std::string cmd(
"oks-update.sh");
5013 cmd.append(
" --force");
5015 cmd.append(
" --merge");
5022 cmd.push_back(
'\"');
5024 cmd.push_back(
'\"');
5027 auto start_usage = std::chrono::steady_clock::now();
5039 static std::string version_prefix(
"update oks version ");
5041 std::string::size_type pos =
version.find(version_prefix);
5051 std::cout << cmd_out.
cat2str();
5052 log_timestamp() <<
"[OKS update] => done in " << std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()-start_usage).count() / 1000. <<
" ms" << std::endl;
5062 throw RepositoryOperationFailed(
"commit",
"the repository-root is not set (check environment variable TDAQ_DB_REPOSITORY)");
5065 throw RepositoryOperationFailed(
"commit",
"the user-repository-root is not set (check environment variable TDAQ_DB_USER_REPOSITORY)");
5067 std::string cmd(
"oks-commit.sh");
5075 if(comments.empty() || std::all_of(comments.begin(), comments.end(), [](
char c) { return std::isspace(c); }))
5078 const std::string log_file_name(get_temporary_dir() +
'/' +
"oks-commit-msg." + std::to_string(getpid()) +
':' + std::to_string(
reinterpret_cast<std::uintptr_t
>(
this)) +
".txt");
5082 std::ofstream f(log_file_name);
5084 f.exceptions(std::ostream::failbit | std::ostream::badbit);
5087 throw std::runtime_error(
"create message file failed");
5092 catch (
const std::exception& ex)
5094 std::ostringstream ss;
5095 ss <<
"cannot write to file \'" << log_file_name <<
"\' to save commit message: " << ex.what();
5099 cmd.append(
" -f \'");
5100 cmd.append(log_file_name);
5101 cmd.push_back(
'\'');
5163 auto start_usage = std::chrono::steady_clock::now();
5173 int status = system(cmd.c_str());
5175 unlink(log_file_name.c_str());
5177 if (!credentials.empty())
5178 unsetenv(
"OKS_COMMIT_USER");
5187 std::cout << cmd_out.
cat2str();
5188 log_timestamp() <<
"[OKS commit] => done in " << std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()-start_usage).count() / 1000. <<
" ms" << std::endl;
5191 static std::string version_prefix(
"commit oks version ");
5193 std::string::size_type pos =
version.find(version_prefix);
5207 throw RepositoryOperationFailed(
"tag",
"the repository-root is not set (check environment variable TDAQ_DB_REPOSITORY)");
5210 throw RepositoryOperationFailed(
"tag",
"the user-repository-root is not set (check environment variable TDAQ_DB_USER_REPOSITORY)");
5212 std::string cmd(
"oks-tag.sh");
5220 if(tag.empty() || std::all_of(tag.begin(), tag.end(), [](
char c) { return std::isspace(c); }))
5223 cmd.append(
" -t \'");
5225 cmd.append(
"\' -c \'");
5227 cmd.push_back(
'\'');
5229 auto start_usage = std::chrono::steady_clock::now();
5243 std::cout << cmd_out.
cat2str();
5244 log_timestamp() <<
"[OKS tag] => done in " << std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()-start_usage).count() / 1000. <<
" ms" << std::endl;
5248std::list<std::string>
5254 throw RepositoryOperationFailed(
"diff",
"the repository-root is not set (check environment variable TDAQ_DB_REPOSITORY)");
5257 throw RepositoryOperationFailed(
"diff",
"the user-repository-root is not set (check environment variable TDAQ_DB_USER_REPOSITORY)");
5259 std::string cmd(
"oks-diff.sh");
5267 if(!sha1.empty() && !sha2.empty())
5269 cmd.append(
" --sha ");
5276 cmd.append(
" --unmerged");
5282 std::string output = cmd_out.
cat2str();
5286 std::cout << output <<
"[OKS get_diff] => done" << std::endl;
5289 std::istringstream s(output);
5294 const char * diff_pattern =
"git diff --name-only ";
5296 while (std::getline(s, line))
5297 if (line.find(diff_pattern) == 0)
5305 std::ostringstream text;
5306 text <<
"cannot find \"" << diff_pattern <<
"\" pattern in output of oks-diff.sh:\n" << output;
5310 std::list<std::string> result;
5312 while (std::getline(s, line))
5313 result.push_back(line);
5321 for (
const auto& x : ver.
m_files)
5322 if (loaded_files.find(x) != loaded_files.end())
5328std::vector<OksRepositoryVersion>
5331 std::string cmd(
"oks-log.sh");
5339 cmd.append(command_line);
5344 std::string output = cmd_out.
cat2str();
5346 std::istringstream s(output);
5351 while (std::getline(s, line))
5352 if (line.find(
"git log ") == 0)
5360 std::ostringstream text;
5361 text <<
"cannot find \"git log\" pattern in output of oks-log.sh:\n" << output;
5365 std::set<std::string> loaded_files;
5367 if (skip_irrelevant)
5372 loaded_files.emplace(x.first->substr(len));
5375 loaded_files.emplace(x.first->substr(len));
5378 std::vector<OksRepositoryVersion> vec;
5383 while (std::getline(s, line))
5389 std::string::size_type idx1 = 0;
5390 std::string::size_type idx2 = line.find(
'|');
5392 if (idx2 != std::string::npos)
5396 idx2 = line.find(
'|', idx1);
5398 if (idx2 != std::string::npos)
5400 ver.
m_user = line.substr(idx1, idx2-idx1);
5402 idx2 = line.find(
'|', idx1);
5404 if (idx2 != std::string::npos)
5406 ver.
m_date = std::stol(line.substr(idx1, idx2-idx1));
5417 std::ostringstream text;
5418 text <<
"unexpected line \"" << line <<
"\" in output of oks-log.sh:\n" << output;
5428 if (skip_irrelevant &&
check_relevant(loaded_files, ver) ==
false)
5431 vec.emplace_back(ver);
5442 if (skip_irrelevant ==
false ||
check_relevant(loaded_files, ver))
5443 vec.emplace_back(ver);
5449std::vector<OksRepositoryVersion>
5452 std::string command_line;
5454 if(!since.empty() && !until.empty())
5456 command_line.push_back(
' ');
5457 command_line.append(since);
5458 command_line.append(
"..");
5459 command_line.append(until);
5461 else if(!since.empty())
5463 command_line.push_back(
' ');
5464 command_line.append(since);
5465 command_line.append(
"..origin/master");
5467 else if(!until.empty())
5469 command_line.append(
" ..");
5470 command_line.append(until);
5479 std::string
out(in);
5480 std::replace(
out.begin(),
out.end(),
' ',
'T');
5485std::vector<OksRepositoryVersion>
5488 std::string command_line;
5492 command_line.append(
" --since ");
5498 command_line.append(
" --until ");
5502 command_line.append(
" origin/master");
5514 throw RepositoryOperationFailed(
"status",
"the repository-root is not set (check environment variable TDAQ_DB_REPOSITORY)");
5517 throw RepositoryOperationFailed(
"status",
"the user-repository-root is not set (check environment variable TDAQ_DB_USER_REPOSITORY)");
5519 std::string cmd(
"oks-version.sh");
5527 std::string output = cmd_out.
cat2str();
5529 static std::string version_prefix(
"oks version ");
5531 std::string::size_type pos =
version.find(version_prefix);
5537 std::ostringstream text;
5538 text <<
"cannot read oks version from oks-version.sh output: \"" << output <<
'\"';
5551 throw RepositoryOperationFailed(
"status",
"the repository-root is not set (check environment variable TDAQ_DB_REPOSITORY)");
5554 throw RepositoryOperationFailed(
"status",
"the user-repository-root is not set (check environment variable TDAQ_DB_USER_REPOSITORY)");
5556 std::string cmd(
"oks-status.sh");
5564 std::string output = cmd_out.
cat2str();
5568 std::cout << output <<
"[OKS get_status] => done" << std::endl;
5571 std::istringstream s(output);
5576 const char * diff_pattern =
"git status --porcelain";
5578 while (std::getline(s, line))
5579 if (line.find(diff_pattern) == 0)
5587 std::ostringstream text;
5588 text <<
"cannot find \"" << diff_pattern <<
"\" pattern in output of oks-status.sh:\n" << output;
5592 std::list<std::string> result;
5594 while (std::getline(s, line))
5596 if (line.find(
" D ") == 0)
5597 removed.insert(line.substr(3));
5598 else if (line.find(
" M ") == 0)
5599 updated.insert(line.substr(3));
5600 else if (line.find(
"?? ") == 0)
5601 added.insert(line.substr(3));
5604 std::ostringstream text;
5605 text <<
"unexpected output \"" << line <<
"\" in output of oks-status.sh:\n" << output;
5712 std::ostringstream
out;
5715 c.second->check_relationships(
out,
true);
5724 auto now(std::chrono::system_clock::now());
5725 auto time_since_epoch(
now.time_since_epoch());
5726 auto seconds_since_epoch(std::chrono::duration_cast<std::chrono::seconds>(time_since_epoch));
5728 std::time_t now_t(std::chrono::system_clock::to_time_t(std::chrono::system_clock::time_point(seconds_since_epoch)));
5731 std::size_t len = std::strftime(buff, 128 - 16,
"%Y-%b-%d %H:%M:%S.", std::localtime(&now_t));
5732 sprintf(buff+len,
"%03d ", (
int)(std::chrono::duration_cast<std::chrono::milliseconds>(time_since_epoch).count() - seconds_since_epoch.count()*1000));
5734 std::ostream& s (severity <=
Warning ? std::cerr : std::cout);
5736 s << buff << (severity ==
Error ?
"ERROR " : severity ==
Warning ?
"WARNING " : severity ==
Debug ?
"DEBUG " :
"");
std::ostream & operator<<(std::ostream &stream, const OksSystem::File &file)
#define ERS_DECLARE_ISSUE(namespace_name, class_name, message, attributes)
static const std::string & full_local_name()
fully qualified local host name
static const LocalHost * instance()
pointer to the singleton local host
uid_t identity() const
user-id
const std::string & name_safe() const
username - no exception
static std::string fill(const std::string &name, const std::string &reason) noexcept
static std::string fill(const char *prefix, const char *item, const std::string &name, const std::string &reason) noexcept
static std::string fill(const char *prefix, const std::string &name) noexcept
static std::string fill(const char *prefix, const std::string &name, const std::string &reason) noexcept
Failed to set active file.
static std::string fill(const char *item, const std::string &name, const std::string &reason) noexcept
static std::string fill(const OksClass *c, const OksObject *o, const OksFile &file, const std::string &reason) noexcept
static std::string fill(const char *prefix, const char *item, const std::string &name, const std::string &reason) noexcept
static std::string fill(const OksClass &c, const std::string &reason) noexcept
static std::string fill(const std::string &path, int error_code) noexcept
static std::string fill(const std::string &item, const std::string &name, const std::string &reason) noexcept
static std::string fill(const std::string &names, const std::string &reason) noexcept
static void remove(const std::string &path)
void erase(const std::string &path)
std::set< std::string > s_git_folders
void insert(const std::string &path)
std::mutex s_git_folders_mutex
bool get_is_abstract() const noexcept
std::set< OksClass *, SortByName > Set
static NotifyFN create_notify_fn
static NotifyFN delete_notify_fn
static ChangeNotifyFN change_notify_fn
std::list< OksClass *, boost::fast_pool_allocator< OksClass * > > FList
std::map< const char *, OksClass *, SortStr > Map
Provides interface to the OKS XML schema and data files.
std::unordered_map< OksFile *, Set, oks::hash_file_ptr, oks::equal_file_ptr > IMap
const std::string & get_logical_name() const
void unlock()
Unlock OKS file.
void get_all_include_files(const OksKernel *kernel, std::set< OksFile * > &out)
Get all include files.
void lock()
Lock OKS file.
void write(OksXmlOutputStream &)
std::unordered_set< OksFile *, oks::hash_file_ptr, oks::equal_file_ptr > Set
bool is_locked() const
Return lock status of OKS file.
const std::string & get_type() const
const std::string & get_short_file_name() const
std::list< std::string > p_list_of_include_files
boost::posix_time::ptime p_creation_time
void update_status_of_file(bool update_local=true, bool update_repository=true)
Update status of file.
const std::string & get_oks_format() const
OksFile * check_parent(const OksFile *parent_h)
Set given parent, if this file is not yet included.
const OksFile * p_included_by
const std::string & get_full_file_name() const
void rename(const std::string &short_name, const std::string &full_name)
std::map< const std::string *, OksFile *, SortByName > Map
Provides interface to the OKS kernel.
bool p_allow_duplicated_classes
static const std::string & get_repository_mapping_dir()
Get OKS repository name.
const std::string & get_user_repository_root() const
Get user OKS repository root.
static std::string & get_host_name()
Get hostname of given process.
static std::string & get_user_name()
Get username of given process.
std::list< std::string > get_repository_versions_diff(const std::string &sha1, const std::string &sha2)
bool p_allow_duplicated_objects
void k_rename_repository_file(OksFile *file_h, const std::string &new_name)
static bool p_use_strict_repository_paths
void update_repository(const std::string &hash_val, RepositoryUpdateType update_type)
Update user repository files from origin by hash.
static std::mutex p_parallel_out_mutex
std::string p_repository_version
void k_check_bind_classes_status() const noexcept
static std::string p_repository_root
std::time_t p_repository_checkout_ts
std::map< std::string, T > map_str_t
void set_user_repository_root(const std::string &path, const std::string &version="")
Set user OKS repository root.
void add_data_file(OksFile *)
OksFile::Map p_schema_files
bool get_verbose_mode() const
Get status of verbose mode. The method returns true, if the verbose mode is switched 'On'.
std::string create_user_repository_dir()
OksKernel(bool silence_mode=false, bool verbose_mode=false, bool profiling_mode=false, bool allow_repository=true, const char *version=nullptr, std::string branch_name="")
Constructor to build OksKernel object.
std::list< std::string > p_repository_dirs
void remove_user_repository_dir()
std::vector< OksRepositoryVersion > get_repository_versions(bool skip_irrelevant, const std::string &command_line)
Return repository versions.
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.
static std::string p_repository_mapping_dir
std::time_t p_repository_update_ts
static int p_threads_pool_size
bool p_user_repository_root_created
void tag_repository(const std::string &tag)
Tag current state of repository.
void remove_schema_file(OksFile *)
void get_updated_repository_files(std::set< std::string > &updated, std::set< std::string > &added, std::set< std::string > &removed)
Get repository modified schema files.
void unset_repository_created()
Set repository created flag to false to avoid created repository removal in destructor;.
void k_copy_repository(const std::string &source, const std::string &destination)
std::string p_bind_classes_status
static unsigned long p_count
std::string read_repository_version()
Read and return current repository version.
std::string p_user_repository_root
static bool p_skip_string_range
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()
static std::string get_tmp_file(const std::string &file_name)
Generates temporal file name.
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.
std::shared_mutex p_kernel_mutex
bool p_test_duplicated_objects_via_inheritance
void add_schema_file(OksFile *)
static const char * GetVersion()
Get OKS version. The method returns string containing CVS tag and date of OKS build.
void remove_data_file(OksFile *)
static std::string & get_domain_name()
Get domain name of host.
std::string insert_repository_dir(const std::string &dir, bool push_back=true)
Insert repository search directory.
void k_checkout_repository(const std::string ¶m, const std::string &val, const std::string &branch)
Check out repository files into local user directory.
OksFile::Map p_data_files
bool p_user_repository_root_inited
OksObject describes instance of OksClass.
struct dunedaq::oks::OksObject::OksUid uid
std::unordered_map< const std::string *, OksObject *, oks::hash_str, oks::equal_str > Map
OksData * GetRelationshipValue(const std::string &) const
Get value of relationship by name.
std::unordered_set< OksObject *, oks::hash_obj_ptr, oks::equal_obj_ptr > FSet
std::map< const std::string *, OksObject *, SortById > SMap
void unbind_file(const OksFile *)
const OksClass * GetClass() const
void remove_RCR(OksObject *, const OksRelationship *) noexcept
const std::string & GetId() const
void put_last_tag(const char *, size_t len)
static void substitute_variables(std::string &)
static std::ostream & warning_msg(const char *)
static bool real_path(std::string &, bool ignore_errors)
static std::ostream & error_msg(const char *)
Cannot commit, checkout or release files.
static std::string fill(const char *op, const std::string &reason) noexcept
virtual const char * what() const noexcept
#define OSK_VERBOSE_REPORT(MSG)
#define OSK_PROFILING(FID, K)
#define TEST_PATH_TOKEN(path, file, msg)
#define TLOG_DEBUG(lvl,...)
std::string const reason(ers::Issue const &)
bool cmp_str8n(const char *s1, const char s2[9])
const std::string strerror(int error)
Convert C error number to string.
static void create_updated_lists(const OksFile::Map &files, std::list< OksFile * > **ufs, std::list< OksFile * > **rfs, OksFile::FileStatus wu, OksFile::FileStatus wr)
bool cmp_str7n(const char *s1, const char s2[8])
std::string make_fname(const char *f, size_t f_len, const std::string &file, bool *p, const OksFile *const *fh)
static std::mutex s_get_cwd_mutex
static bool check_relevant(const std::set< std::string > &loaded_files, const OksRepositoryVersion &ver)
std::ostream & log_timestamp(__LogSeverity__ severity=Log)
static std::string replace_datetime_spaces(const std::string &in)
static GitFoldersHolder s_git_folders
static long get_file_length(std::ifstream &f)
std::unordered_set< const OksClass *, oks::hash_class_ptr, oks::equal_class_ptr > ClassSet
static void test_file_existence(const std::string &file_name, bool silence, const std::string &fname, const char *msg)
std::string mk_name_and_test(const std::string &name, const char *test, size_t test_len)
static bool _find_file(const OksFile::Map &files, const OksFile *f)
bool cmp_str6n(const char *s1, const char s2[6])
bool cmp_str4n(const char *s1, const char s2[4])
FELIX Initialization std::string initerror FELIX queue timed out
FELIX Initialization std::string initerror FELIX queue timed std::string queuename Unexpected chunk size
void warning(const Issue &issue)
void error(const Issue &issue)
void check_command_status(int status)
std::string last_str() const
const char * p_command_name
std::string cat2str() const
const std::string & file_name() const
The struct OksAliasTable is used to support aliases.
Struct OKS data information.
the structure to pass common parameters to various read() methods of OksData and OksObject class
union dunedaq::oks::OksData::Data data
enum dunedaq::oks::OksData::Type type
std::shared_ptr< OksXmlInputStream > m_xmls
OksLoadObjectsJob(OksKernel *kernel, OksFile *fp, std::shared_ptr< OksXmlInputStream > xmls, char format)
OksLoadObjectsJob(const OksLoadObjectsJob &)
OksLoadObjectsJob & operator=(const OksLoadObjectsJob &)
std::string m_commit_hash
std::vector< std::string > m_files
std::map< std::string, T > map_str_t
std::vector< OksObject * > created
std::map< const OksClass *, map_str_t< OksObject * > * > data
const char * p_user_repository_root
const char * p_repository_root
static std::mutex p_mutex
Factory couldn t std::string alg_name Invalid configuration error