DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
dunedaq::oks::OksObject Class Reference

OksObject describes instance of OksClass. More...

#include <object.hpp>

Collaboration diagram for dunedaq::oks::OksObject:
[legend]

Classes

struct  SortById
struct  OksUid
struct  BindInfo

Public Types

typedef void(*) notify_obj(OksObject *, void *)
typedef std::map< const std::string *, OksObject *, SortById > SMap
typedef std::unordered_map< const std::string *, OksObject *, oks::hash_str, oks::equal_str > Map
typedef std::unordered_set< OksObject *, oks::hash_obj_ptr, oks::equal_obj_ptr > FSet
typedef std::set< OksObject *, std::less< OksObject * > > Set
typedef std::list< OksObject * > List
typedef std::list< OksObject *, boost::fast_pool_allocator< OksObject * > > FList

Public Member Functions

 OksObject (const OksClass *oks_class, const char *object_id=0, bool skip_init=false)
 OKS object constructor.
 OksObject (const OksObject &parent_object, const char *object_id=0)
 OKS object copy constructor.
bool operator== (const OksObject &) const
 The equality operator.
bool operator!= (const OksObject &) const =delete
void * operator new (size_t)
void operator delete (void *ptr)
const OksClass * GetClass () const
const std::string & GetId () const
void set_id (const std::string &id)
 Set object ID.
OksFile * get_file () const
void set_file (OksFile *file, bool update_owner=true)
 Move object to different file.
OksData * GetAttributeValue (const std::string &name) const
 Get value of attribute by name.
OksData * GetAttributeValue (const OksDataInfo *i) const noexcept
 Get value of attribute by offset.
OksData * GetRelationshipValue (const std::string &) const
 Get value of relationship by name.
OksData * GetRelationshipValue (const OksDataInfo *i) const noexcept
 Get value of relationship by offset.
void SetAttributeValue (const std::string &name, OksData *data)
 Set value of attribute by name.
void SetAttributeValue (const OksDataInfo *data_info, OksData *data)
 Set value of attribute by offset.
void SetRelationshipValue (const std::string &name, OksData *data, bool skip_non_null_check=false)
 Set value of relationship by name.
void SetRelationshipValue (const OksDataInfo *data_info, OksData *data, bool skip_non_null_check=false)
 Set value of relationship by offset.
void SetRelationshipValue (const std::string &name, OksObject *object)
 Set value of single-value relationship by name.
void SetRelationshipValue (const OksDataInfo *data_info, OksObject *object)
 Set value of single-value relationship by offset.
void AddRelationshipValue (const std::string &name, OksObject *object)
 Add object value to multi-value relationship by name.
void AddRelationshipValue (const OksDataInfo *data_info, OksObject *object)
 Add object value to multi-value relationship by offset.
void RemoveRelationshipValue (const std::string &name, OksObject *object)
 Remove object value from multi-value relationship by name.
void RemoveRelationshipValue (const OksDataInfo *data_info, OksObject *object)
 Remove object value from multi-value relationship by offset.
void SetRelationshipValue (const std::string &rel_name, const std::string &class_name, const std::string &object_id)
 Set class-name and object-id value of single-value relationship by name.
void AddRelationshipValue (const std::string &rel_name, const std::string &class_name, const std::string &object_i)
 Add class-name and object-id value to multi-value relationship by name.
void RemoveRelationshipValue (const std::string &rel_name, const std::string &class_name, const std::string &object_i)
 Remove class-name and object-id value from multi-value relationship by name.
const std::list< OksRCR * > * reverse_composite_rels () const
 Return information about composite parents. The method returns list of the OKS object's reverse composite relationships.
FList * get_all_rels (const std::string &name="*") const
 Return objects referencing this one via relationship with given name.
void SetTransientData (void *d) const
 Set transient user data associated with given object. Such data are not stored on file and only exist while OksKernel object is not destroyed.
void * GetTransientData () const
 Get transient user data associated with given object. Return data set using SetTransientData() method.
void set_int32_id (int32_t object_id)
 Set object id is used to assign an object unique integer number. Such data are not stored on file and only exist while OksKernel object is not destroyed.
int32_t get_int32_id () const
 Get object id associated with given object. Return integer number set using set_int32_id() method.
bool SatisfiesQueryExpression (OksQueryExpression *query_exp) const
 Check if object satisfies query expression.
bool satisfies (const OksObject *goal, const oks::QueryPathExpression &expresssion, OksObject::List &path) const
OksObject::List * find_path (const oks::QueryPath &query) const
bool is_consistent (const std::set< OksFile * > &, const char *msg) const
std::string report_dangling_references () const
void references (OksObject::FSet &refs, unsigned long recursion_depth, bool add_self=false, oks::ClassSet *classes=0) const
bool is_duplicated () const
void add_RCR (OksObject *, const OksRelationship *)
void remove_RCR (OksObject *, const OksRelationship *) noexcept

Static Public Member Functions

static void destroy (OksObject *obj, bool fast=false)
 Destroy OKS object.
static bool are_equal_fast (const OksObject *o1, const OksObject *o2)
 The fast equal method.

Private Member Functions

 ~OksObject ()
void __report_type_cvt_warning (const oks::ReadFileParams &, const OksAttribute &, const OksData &, const OksData::Type, int32_t) const
void __report_cardinality_cvt_warning (const oks::ReadFileParams &, const OksRelationship &) const
int32_t __get_num (const oks::ReadFileParams &params)
void read_body (const oks::ReadFileParams &, bool)
 OksObject (const oks::ReadFileParams &, OksClass *, const std::string &)
 OksObject (size_t, const OksData *)
 OksObject (OksClass *c, const std::string &id, void *user_data, int32_t object_id, int32_t duplicated_object_id_idx, OksFile *f)
OksObject & operator= (const OksObject &)
void init1 (const OksFile *=0)
void init2 (bool skip_init=false)
void init3 ()
void init3 (OksClass *c)
void check_ids ()
void notify ()
void check_class_type (const OksRelationship *, const OksClass *)
void check_class_type (const OksRelationship *r, const OksObject *o)
void check_non_null (const OksRelationship *, const OksObject *)
void check_file_lock (const OksAttribute *, const OksRelationship *)
void set_unique_id ()
void put (OksXmlOutputStream &, bool force_defaults) const
void bind_objects ()
void unbind_file (const OksFile *)
bool check_links_and_report (const OksObject *, const std::set< OksFile * > &, const std::string &, const char *) const
notify_obj get_change_notify () const
void create_notify ()
void change_notify ()
void delete_notify ()

Static Private Member Functions

static OksObject * read (const oks::ReadFileParams &)
static void put_object_attributes (OksXmlOutputStream &, const OksData &)
static void bind (OksData *, const BindInfo &)

Private Attributes

struct dunedaq::oks::OksObject::OksUid uid
OksData * data
std::list< OksRCR * > * p_rcr
void * p_user_data
int32_t p_int32_id
int32_t p_duplicated_object_id_idx
OksFile * file

Static Private Attributes

static const char obj_xml_tag [] = "obj"
static const char obj2_xml_tag [] = "o"
static const char attribute_xml_tag [] = "attr"
static const char relationship_xml_tag [] = "rel"
static const char class_xml_attribute [] = "class"
static const char class2_xml_attribute [] = "c"
static const char id_xml_attribute [] = "id"
static const char id2_xml_attribute [] = "i"
static const char name_xml_attribute [] = "name"
static const char type_xml_attribute [] = "type"
static const char num_xml_attribute [] = "num"
static const char value_xml_attribute [] = "val"
static const char data_xml_tag [] = "data"
static const char ref_xml_tag [] = "ref"

Friends

class OksClass
struct OksData
class OksKernel
class OksIndex
class OksObjectSortBy
struct OksLoadObjectsJob
struct oks::ReadFileParams
struct oks::ReloadObjects
std::ostream & operator<< (std::ostream &out, const OksObject &obj)
 Detailed stream operator.
std::ostream & operator<< (std::ostream &s, const OksObject *o)
 Short stream operator.

Detailed Description

OksObject describes instance of OksClass.

This class implements OKS object that is an instance of OKS class. Each object has unique ID string in a scope of class and its derived sub-classes. The properties of object are described by values of its attributes (i.e. values of primitive types like strings, integers, floats, see also OksAttribute) and relationships (i.e. references on others OKS objects, see also OksRelationship).

Definition at line 1143 of file object.hpp.

Member Typedef Documentation

◆ FList

typedef std::list<OksObject*, boost::fast_pool_allocator<OksObject*> > dunedaq::oks::OksObject::FList

Definition at line 1181 of file object.hpp.

◆ FSet

Definition at line 1171 of file object.hpp.

◆ List

List of pointers to OksObject

Definition at line 1179 of file object.hpp.

◆ Map

typedef std::unordered_map<const std::string*, OksObject*, oks::hash_str, oks::equal_str> dunedaq::oks::OksObject::Map

Map of pointers to OksObject (unsorted)

Definition at line 1170 of file object.hpp.

◆ notify_obj

typedef void(*) dunedaq::oks::OksObject::notify_obj(OksObject *, void *)

Definition at line 1155 of file object.hpp.

◆ Set

typedef std::set<OksObject*, std::less<OksObject*> > dunedaq::oks::OksObject::Set

Set of pointers to OksObject

Definition at line 1175 of file object.hpp.

◆ SMap

typedef std::map<const std::string*, OksObject*, SortById> dunedaq::oks::OksObject::SMap

Map of pointers to OksObject sorted by object Id

Definition at line 1166 of file object.hpp.

Constructor & Destructor Documentation

◆ OksObject() [1/5]

dunedaq::oks::OksObject::OksObject ( const OksClass * oks_class,
const char * object_id = 0,
bool skip_init = false )

OKS object constructor.

Create new OKS object providing class and object ID. If the object ID is not set, the OKS creates new object with random unique ID. To create a new object the OKS kernel active data file has to be set.

In case of problems the error message is printed and the uid.class_id is set to 0 to flag the error.

The parameters are:

Parameters
oks_classpointer to OKS class
object_idoptional object unique ID
skip_initif true, skip initialization of OKS data

Definition at line 1151 of file object.cpp.

1152 : data(nullptr)
1154{
1156
1157 if (!c->p_kernel->get_active_data()) {
1158 Oks::error_msg("OksObject::OksObject(const OksClass*, const char *)")
1159 << " Can not create new object since there is no active data file\n";
1160 return;
1161 }
1162
1163 uid.class_id = c;
1164 uid.object_id = (object_id ? object_id : "");
1165
1166 try {
1167 init1();
1168 } catch (oks::exception& ex) {
1169 uid.class_id = nullptr;
1170 throw;
1171 }
1172
1173 init2(skip_init);
1174 init3();
1175
1176 file->set_updated();
1177}
struct dunedaq::oks::OksObject::OksUid uid
void init1(const OksFile *=0)
Definition object.cpp:193
void init2(bool skip_init=false)
Definition object.cpp:275
int32_t p_duplicated_object_id_idx
Definition object.hpp:1689
static std::ostream & error_msg(const char *)
Definition kernel.cpp:511
#define OSK_PROFILING(FID, K)
Definition defs.hpp:96

◆ OksObject() [2/5]

dunedaq::oks::OksObject::OksObject ( const OksObject & parent_object,
const char * object_id = 0 )

OKS object copy constructor.

Create new OKS object as copy of parent. If the object ID is not set, the OKS creates new object with random unique ID. To create a new object the OKS kernel active data file has to be set.

In case of problems the error message is printed and the uid.class_id is set to 0 to flag the error.

The parameters are:

Parameters
parent_objectpointer to OKS class
object_idoptional object unique ID

Definition at line 1179 of file object.cpp.

1180 : data(nullptr)
1182{
1183 OSK_PROFILING(OksProfiler::ObjectCopyConstructor, parentObj.uid.class_id->p_kernel)
1184
1185 if (!parentObj.uid.class_id->p_kernel->get_active_data()) {
1186 Oks::error_msg("OksObject::OksObject(const OksObject&, const char *)")
1187 << " Can not create new object since there is no active data file\n";
1188 return;
1189 }
1190
1191 const OksClass* c = uid.class_id = parentObj.uid.class_id;
1192
1193 uid.object_id = (object_id ? object_id : "");
1194
1195 try {
1196 init1();
1197 } catch (oks::exception& ex) {
1198 uid.class_id = nullptr;
1199 throw;
1200 }
1201
1202 int count = c->p_instance_size;
1203 int num_of_attr = c->p_all_attributes->size();
1204 int j = 0;
1205
1206 while (j < num_of_attr) {
1207 data[j] = parentObj.data[j];
1208 j++;
1209 }
1210
1211 try {
1212 std::list<OksRelationship*>::iterator i = c->p_all_relationships->begin();
1213
1214 while (j < count) {
1215 const OksRelationship* r = *i;
1216 const char* relationshipName = r->get_name().c_str();
1217
1218 if (parentObj.data[j].type == OksData::list_type) {
1219 data[j].Set(new OksData::List());
1220
1221 if (parentObj.data[j].data.LIST) {
1222 for (const auto& i2 : *parentObj.data[j].data.LIST) {
1223 if (i2->type == OksData::object_type)
1224 AddRelationshipValue(relationshipName, i2->data.OBJECT);
1225 else {
1226 OksData* uid_d = new OksData();
1227 uid_d = i2;
1228 data[j].data.LIST->push_back(uid_d);
1229 }
1230 }
1231 }
1232 } else {
1233 if (parentObj.data[j].type == OksData::object_type) {
1234 data[j].Set((OksObject*)0);
1235 SetRelationshipValue(relationshipName, parentObj.data[j].data.OBJECT);
1236 } else
1237 data[j] = parentObj.data[j];
1238 }
1239 ++j;
1240 ++i;
1241 }
1242 } catch (oks::exception& ex) {
1243 uid.class_id = nullptr;
1244 throw;
1245 }
1246
1247 init3();
1248
1249 file->set_updated();
1250}
friend class OksClass
Definition object.hpp:1145
void AddRelationshipValue(const std::string &name, OksObject *object)
Add object value to multi-value relationship by name.
Definition object.cpp:2266
friend struct OksData
Definition object.hpp:1146
void SetRelationshipValue(const std::string &name, OksData *data, bool skip_non_null_check=false)
Set value of relationship by name.
Definition object.cpp:2125
OksObject(const OksClass *oks_class, const char *object_id=0, bool skip_init=false)
OKS object constructor.
Definition object.cpp:1151
void Set(int8_t c)
Definition object.hpp:711
union dunedaq::oks::OksData::Data data
std::list< OksData *, boost::fast_pool_allocator< OksData * > > List
Definition object.hpp:515

◆ ~OksObject()

dunedaq::oks::OksObject::~OksObject ( )
private

Definition at line 1348 of file object.cpp.

1349{
1350 OksClass* c = const_cast<OksClass*>(uid.class_id);
1351
1352 if (!c) {
1353 if (data) {
1354 delete[] data;
1355 }
1356 } else {
1357 OksKernel* k = c->p_kernel;
1358
1360
1361 TLOG_DEBUG(4) << "destroy object " << this;
1362
1363 static std::mutex s_mutex;
1364 static std::set<OksObject*, std::less<OksObject*>> oset;
1365
1366 if (k->p_close_all == false) {
1367 k->undefine(this);
1368 std::lock_guard lock(s_mutex);
1369 oset.insert(this);
1370 }
1371
1372 delete_notify();
1373
1374 if (data) {
1375 if (c->p_all_relationships && !c->p_all_relationships->empty()) {
1376 OksData* di = data + c->number_of_all_attributes();
1377
1378 for (std::list<OksRelationship*>::iterator i = c->p_all_relationships->begin();
1379 i != c->p_all_relationships->end();
1380 ++i, ++di) {
1381 OksRelationship* r = *i;
1382
1383 if (r->get_is_composite() == false || k->p_close_all == true)
1384 continue;
1385
1386 OksData* d = di;
1387
1388 if (d->type == OksData::object_type && d->data.OBJECT) {
1389 OksObject* o = d->data.OBJECT;
1390
1391 if (!k->is_dangling(o)) {
1392 o->remove_RCR(this, r);
1393
1394 bool delete_obj(r->get_is_dependent() && !o->p_rcr);
1395
1396 if (delete_obj) {
1397 std::lock_guard lock(s_mutex);
1398 delete_obj = (oset.find(o) == oset.end());
1399 }
1400
1401 if (delete_obj) {
1402 delete o;
1403 d->data.OBJECT = nullptr;
1404 }
1405 }
1406 } else if (d->type == OksData::list_type && d->data.LIST) {
1407 for (const auto& i2 : *d->data.LIST) {
1408 if (i2->type == OksData::object_type && i2->data.OBJECT) {
1409 OksObject* o = i2->data.OBJECT;
1410
1411 if (!k->is_dangling(o)) {
1412 o->remove_RCR(this, r);
1413
1414 bool delete_obj(r->get_is_dependent() && !o->p_rcr);
1415
1416 if (delete_obj) {
1417 std::lock_guard lock(s_mutex);
1418 delete_obj = (oset.find(o) == oset.end());
1419 }
1420
1421 if (delete_obj) {
1422 delete o;
1423 i2->data.OBJECT = nullptr;
1424 }
1425 }
1426 }
1427 }
1428 }
1429 }
1430 }
1431
1432 if (c->p_indices) {
1433 for (const auto& i : *c->p_indices)
1434 i.second->remove_obj(this);
1435 }
1436
1437 int count = c->p_instance_size;
1438 while (count--)
1439 data[count].Clear();
1440
1441 delete[] data;
1442
1443 if (k->p_close_all == false) {
1444 try {
1445 c->remove(this);
1446 } catch (oks::exception& ex) {
1447 Oks::error_msg("OksObject::~OksObject()") << ex.what() << std::endl;
1448 }
1449 }
1450 }
1451
1452 if (p_rcr) {
1453 for (std::list<OksRCR*>::const_iterator i = p_rcr->begin(); i != p_rcr->end(); ++i) {
1454 delete *i;
1455 }
1456
1457 delete p_rcr;
1458 }
1459
1460 if (k->p_close_all == false) {
1461 std::lock_guard lock(s_mutex);
1462 oset.erase(this);
1463 }
1464 }
1465}
friend class OksKernel
Definition object.hpp:1147
std::list< OksRCR * > * p_rcr
Definition object.hpp:1686
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:116

◆ OksObject() [3/5]

dunedaq::oks::OksObject::OksObject ( const oks::ReadFileParams & read_params,
OksClass * c,
const std::string & id )
private

Construct OKS object from input stream.

Exceptions
oks::exceptionis thrown in case of errors.

Definition at line 1127 of file object.cpp.

1128 : data(nullptr)
1130{
1131 if (c) {
1133 }
1134
1135 uid.object_id = id;
1136 uid.class_id = c;
1137
1138 std::shared_lock lock(read_params.oks_kernel->p_schema_mutex); // protect schema and all objects from changes
1139
1140 if (c) {
1141 init1(read_params.f); // can throw exception; to be caught by caller (i.e. OksKernel)
1142 }
1143
1144 read_body(read_params, false);
1145
1146 if (c) {
1147 init3(c);
1148 }
1149}
void read_body(const oks::ReadFileParams &, bool)
Definition object.cpp:542

◆ OksObject() [4/5]

dunedaq::oks::OksObject::OksObject ( size_t offset,
const OksData * d )
private

Definition at line 1252 of file object.cpp.

1253 : data(nullptr)
1255{
1256 uid.class_id = nullptr;
1257 data = new OksData[offset + 1];
1258 memcpy(static_cast<void*>(&data[offset]), static_cast<const void*>(d), sizeof(OksData));
1259}
double offset

◆ OksObject() [5/5]

dunedaq::oks::OksObject::OksObject ( OksClass * c,
const std::string & id,
void * user_data,
int32_t object_id,
int32_t duplicated_object_id_idx,
OksFile * f )
private

Definition at line 1261 of file object.cpp.

1267 : data(new OksData[c->p_instance_size])
1268 , p_user_data(user_data)
1269 , p_int32_id(int32_id)
1270 , p_duplicated_object_id_idx(duplicated_object_id_idx)
1271 , file(f)
1272
1273{
1274 uid.class_id = c;
1275 uid.object_id = id;
1276
1277 // set OksData type to unknown
1278 if (size_t data_size = c->p_instance_size * sizeof(OksData*)) {
1279 bzero(data, data_size);
1280 }
1281}

Member Function Documentation

◆ __get_num()

int32_t dunedaq::oks::OksObject::__get_num ( const oks::ReadFileParams & params)
private

Definition at line 530 of file object.cpp.

531{
532 char* __sanity;
533 params.s.get_num_token('\"');
534 int32_t num = static_cast<int32_t>(strtol(params.s.m_cvt_char->m_buf, &__sanity, 0));
535 if (*__sanity != 0 || errno == ERANGE)
537 "strtol", __sanity, params.s.m_cvt_char->m_buf, params.s.get_line_no(), params.s.get_line_pos());
538 return num;
539}
static void __throw_strto(const char *f, const char *where, const char *what, unsigned long line_no, unsigned long line_pos)
Definition xml.cpp:651

◆ __report_cardinality_cvt_warning()

void dunedaq::oks::OksObject::__report_cardinality_cvt_warning ( const oks::ReadFileParams & params,
const OksRelationship & r ) const
private

Definition at line 510 of file object.cpp.

511{
512 std::lock_guard lock(OksKernel::p_parallel_out_mutex);
513 Oks::warning_msg(std::string("Read object \"") + GetId() + '@' + GetClass()->get_name() + '\"')
514 << " file: \"" << params.f->get_full_file_name() << "\" (line: " << params.s.get_line_no()
515 << ", pos: " << params.s.get_line_pos()
516 << ")\n"
517 " mismatch between relationship \""
518 << r.get_name() << "\" cardinality and its value (save data file with new schema)." << std::endl;
519}
static std::mutex p_parallel_out_mutex
Definition kernel.hpp:1969
const OksClass * GetClass() const
Definition object.hpp:1286
const std::string & GetId() const
Definition object.hpp:1290
static std::ostream & warning_msg(const char *)
Definition kernel.cpp:518

◆ __report_type_cvt_warning()

void dunedaq::oks::OksObject::__report_type_cvt_warning ( const oks::ReadFileParams & params,
const OksAttribute & a,
const OksData & d,
const OksData::Type type,
int32_t num ) const
private

Definition at line 436 of file object.cpp.

441{
442 const char* type_str;
443
444 switch (type) {
446 type_str = OksAttribute::s8_int_type;
447 break;
449 type_str = OksAttribute::u8_int_type;
450 break;
453 break;
456 break;
459 break;
462 break;
465 break;
468 break;
470 type_str = OksAttribute::float_type;
471 break;
473 type_str = OksAttribute::double_type;
474 break;
476 type_str = OksAttribute::bool_type;
477 break;
479 type_str = OksAttribute::class_type;
480 break;
482 type_str = OksAttribute::date_type;
483 break;
485 type_str = OksAttribute::time_type;
486 break;
488 type_str = OksAttribute::string_type;
489 break;
491 type_str = OksAttribute::enum_type;
492 break;
493 default:
494 type_str = "unknown";
495 }
496
497 std::lock_guard lock(OksKernel::p_parallel_out_mutex);
498 Oks::warning_msg(std::string("Read object \"") + GetId() + '@' + GetClass()->get_name() + '\"')
499 << " file: \"" << params.f->get_full_file_name() << "\" (line: " << params.s.get_line_no()
500 << ", pos: " << params.s.get_line_pos()
501 << ")\n"
502 " convert value from wrong type \""
503 << (num == -1 ? "single" : "multi") << "-value " << type_str << "\" to \""
504 << (a.get_is_multi_values() ? "multi" : "single") << "-value " << a.get_type() << "\" as required for attribute \""
505 << a.get_name() << "\"\n"
506 << " converted value: " << d << std::endl;
507}
static const char * s8_int_type
static const char * u32_int_type
static const char * u8_int_type
static const char * time_type
static const char * s64_int_type
static const char * bool_type
static const char * class_type
static const char * string_type
static const char * enum_type
static const char * s32_int_type
static const char * s16_int_type
static const char * u64_int_type
static const char * double_type
static const char * u16_int_type
static const char * date_type
static const char * float_type

◆ add_RCR()

void dunedaq::oks::OksObject::add_RCR ( OksObject * o,
const OksRelationship * r )

Definition at line 2500 of file object.cpp.

2501{
2502 if (r->get_is_composite() == false)
2503 return;
2504
2505 TLOG_DEBUG(4) << "object " << this << " adds RCR to object " << o << " throught relationship \"" << r->get_name()
2506 << '\"';
2507
2508 if (!p_rcr) {
2509 p_rcr = new std::list<OksRCR*>();
2510 } else {
2511 for (const auto& i : *p_rcr) {
2512 if (i->relationship == r) {
2513 if (i->obj == o) {
2514 TLOG_DEBUG(4) << "[this=" << this << ", o=" << o << ", r=\"" << r->get_name()
2515 << "\"]: such RCR was already set.";
2516 return;
2517 } else if (r->get_is_exclusive()) {
2518 throw oks::AddRcrError(this, r->get_name(), o, i->obj);
2519 }
2520 }
2521 }
2522 }
2523
2524 p_rcr->push_back(new OksRCR(o, r));
2525}
OksRCR(OksObject *o, const OksRelationship *r)
Definition object.hpp:1082

◆ AddRelationshipValue() [1/3]

void dunedaq::oks::OksObject::AddRelationshipValue ( const OksDataInfo * data_info,
OksObject * object )

Add object value to multi-value relationship by offset.

In case of problems (e.g. wrong class type, relationship is single-value or RCR cannot be set) the oks::exception is thrown.

The parameters are:

Parameters
data_infodescribes offset of relationship's value for given OKS class
objectthe object to be added
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 2235 of file object.cpp.

2236{
2237 const OksRelationship* r = odi->relationship;
2238 size_t offset = odi->offset;
2239
2240 if (!object) {
2241 throw oks::ObjectSetError(this, true, r->get_name(), "the (null) value is not allowed");
2242 }
2243
2244 check_class_type(r, object);
2245
2246 if (r->get_high_cardinality_constraint() != OksRelationship::Many) {
2247 std::ostringstream text;
2248 text << "cannot add value " << object << " since the relationship has no \'many\' high cardinality constraint";
2249 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2250 }
2251
2252 try {
2253 object->add_RCR(this, r);
2254 } catch (oks::exception& ex) {
2255 throw oks::ObjectSetError(this, true, r->get_name(), ex);
2256 }
2257
2258 check_file_lock(0, r);
2259
2260 data[offset].data.LIST->push_back(new OksData(object));
2261
2262 notify();
2263}
void check_file_lock(const OksAttribute *, const OksRelationship *)
Definition object.cpp:3125
void check_class_type(const OksRelationship *, const OksClass *)
Definition object.cpp:1970

◆ AddRelationshipValue() [2/3]

void dunedaq::oks::OksObject::AddRelationshipValue ( const std::string & name,
OksObject * object )

Add object value to multi-value relationship by name.

In case of problems (e.g. no relationship with such name, wrong class type, relationship is single-value or RCR cannot be set) the oks::exception is thrown.

The parameters are:

Parameters
namename of relationship
objectthe object to be added
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 2266 of file object.cpp.

2267{
2268 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2269
2270 if (i == uid.class_id->p_data_info->end()) {
2271 std::ostringstream text;
2272 text << "object " << this << " has no relationship \"" << name << '\"';
2273 throw oks::ObjectSetError(this, true, name, text.str());
2274 }
2275
2276 AddRelationshipValue(i->second, object);
2277}
OksDataInfo::Map * p_data_info
Definition class.hpp:904

◆ AddRelationshipValue() [3/3]

void dunedaq::oks::OksObject::AddRelationshipValue ( const std::string & rel_name,
const std::string & class_name,
const std::string & object_i )

Add class-name and object-id value to multi-value relationship by name.

In case of problems (e.g. no relationship with such name, unknown class) the oks::exception is thrown.

The parameters are:

Parameters
rel_namename of relationship
class_nameclass name of the referenced object
object_idID of the referenced object
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 2400 of file object.cpp.

2401{
2402 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2403
2404 if (i == uid.class_id->p_data_info->end()) {
2405 std::ostringstream text;
2406 text << "object " << this << " has no relationship \"" << name << '\"';
2407 throw oks::ObjectSetError(this, true, name, text.str());
2408 }
2409
2410 OksDataInfo* odi = i->second;
2411 const OksRelationship* r = odi->relationship;
2412
2413 if (class_id.empty() || object_id.empty()) {
2414 throw oks::ObjectSetError(this, true, r->get_name(), "cannot add (null) object");
2415 }
2416
2417 const std::string& r_class_type = r->get_type();
2418 size_t offset = odi->offset;
2419
2420 OksClass* c = uid.class_id->p_kernel->find_class(class_id);
2421
2422 if (c) {
2423 check_class_type(r, c);
2424 } else if (r_class_type != class_id) {
2425 std::ostringstream text;
2426 text << "cannot add value \"" << object_id << '@' << class_id << "\" since the class \"" << class_id
2427 << "\" is not defined and it is impossible to check its validity for given type of relationship";
2428 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2429 }
2430
2431 if (r->get_high_cardinality_constraint() != OksRelationship::Many) {
2432 std::ostringstream text;
2433 text << "cannot add object \"" << object_id << '@' << class_id
2434 << "\" since the relationship has no \'many\' high cardinality constraint";
2435 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2436 }
2437
2438 OksObject* o = nullptr;
2439
2440 if (c)
2441 o = c->get_object(object_id);
2442
2443 if (o) {
2444 AddRelationshipValue(odi, o);
2445 } else {
2446 check_file_lock(0, r);
2447 data[offset].data.LIST->push_back(new OksData(class_id, object_id));
2448 notify();
2449 }
2450}
OksKernel * p_kernel
Definition class.hpp:900
OksClass * find_class(const std::string &class_name) const
Find class by name (C++ string).
Definition kernel.hpp:1754

◆ are_equal_fast()

bool dunedaq::oks::OksObject::are_equal_fast ( const OksObject * o1,
const OksObject * o2 )
static

The fast equal method.

This method replaces operator!= used by OKS library in the past, since the operator causes problems starting from gcc62 assuming &reference != nullptr

The method returns false, if comparing objects belong to classes with different names or their IDs are not equal.

Definition at line 1578 of file object.cpp.

1579{
1580 if (o1 == o2)
1581 return true;
1582
1583 if (o1 == nullptr || o2 == nullptr)
1584 return false;
1585
1586 return (o1->uid.class_id->get_name() == o2->uid.class_id->get_name() && o1->uid.object_id == o2->uid.object_id);
1587}

◆ bind()

void dunedaq::oks::OksObject::bind ( OksData * d,
const BindInfo & info )
staticprivate

Definition at line 2552 of file object.cpp.

2553{
2554 const OksClass* c(0);
2555 OksObject* o(0);
2556
2557 if (d->type == OksData::uid_type) {
2558 if (d->data.UID.class_id && !d->data.UID.object_id->empty()) {
2559 c = d->data.UID.class_id;
2560 o = c->get_object(d->data.UID.object_id);
2561 } else {
2562 d->Set((OksObject*)0);
2563 return;
2564 }
2565 } else {
2566 if (d->data.UID2.class_id->empty() || d->data.UID2.object_id->empty()) {
2567 d->Set((OksObject*)0);
2568 return;
2569 }
2570
2571 c = info.k->find_class(*d->data.UID2.class_id);
2572
2573 if (c) {
2574 o = c->get_object(d->data.UID2.object_id);
2575 } else {
2576 std::ostringstream text;
2577 text << "Class of object " << *d << " is not defined";
2578 throw oks::ObjectBindError(info.o, d, info.r, true, text.str(), "");
2579 }
2580 }
2581
2582 if (c != info.r->p_class_type) {
2583 if (const OksClass::FList* slist = c->all_super_classes()) {
2584 for (OksClass::FList::const_iterator i = slist->begin(); i != slist->end(); ++i) {
2585 if (info.r->p_class_type == *i) {
2586 goto check_passed;
2587 }
2588 }
2589 }
2590
2591 {
2592 std::ostringstream text;
2593 text << "The relationship has class type \"" << info.r->get_type() << "\" and the referenced object " << *d
2594 << " is not of that class or derived one";
2595 throw oks::ObjectBindError(info.o, d, info.r, true, text.str(), "");
2596 }
2597
2598 check_passed:;
2599 }
2600
2601 if (!o) {
2602 std::ostringstream text;
2603 text << "Cannot find object " << *d;
2604 throw oks::ObjectBindError(info.o, d, info.r, false, text.str(), "");
2605 }
2606
2607 try {
2608 d->Set(o);
2609 o->add_RCR(info.o, info.r);
2610 } catch (oks::exception& ex) {
2611 std::ostringstream text;
2612 text << "Failed to set relationship value " << o;
2613 throw oks::ObjectBindError(info.o, d, info.r, true, text.str(), ex);
2614 }
2615}
std::list< OksClass *, boost::fast_pool_allocator< OksClass * > > FList
Definition class.hpp:254

◆ bind_objects()

void dunedaq::oks::OksObject::bind_objects ( )
private

Binds objects and returns true on success

Definition at line 2660 of file object.cpp.

2661{
2662 const OksClass* c = uid.class_id;
2663
2664 if (c->p_all_relationships->empty())
2665 return; // if class has no relationships then nothing to do
2666
2667 BindInfo info;
2668 info.k = c->p_kernel;
2669 info.o = this;
2670
2671 OksData* d(data + c->number_of_all_attributes());
2672
2673 BindWarning warnings;
2674
2675 for (auto& i : (*c->p_all_relationships)) {
2676 info.r = i;
2677
2678 if (d->type == OksData::object_type) {
2679 if (i->get_low_cardinality_constraint() == OksRelationship::One && d->data.OBJECT == nullptr) {
2680 warnings.add(i);
2681 }
2682 } else if (d->type == OksData::uid_type) {
2683 if (d->data.UID.object_id == nullptr) {
2684 if (i->get_low_cardinality_constraint() == OksRelationship::One) {
2685 warnings.add(i);
2686 }
2687 }
2688
2689 try {
2690 bind(d, info);
2691 } catch (oks::ObjectBindError& ex) {
2692 if (ex.p_is_error) {
2693 throw;
2694 } else {
2695 warnings.add(*ex.p_data, ex.p_rel);
2696 }
2697 }
2698 } else if (d->type == OksData::list_type) {
2699 if (d->data.LIST->empty()) {
2700 if (i->get_low_cardinality_constraint() == OksRelationship::One) {
2701 warnings.add(i);
2702 }
2703 } else {
2704 for (const auto& i2 : *d->data.LIST) {
2705 if (i2->type == OksData::uid_type || i2->type == OksData::uid2_type) {
2706 try {
2707 bind(i2, info);
2708 } catch (oks::ObjectBindError& ex) {
2709 if (ex.p_is_error) {
2710 throw;
2711 } else {
2712 warnings.add(*ex.p_data, ex.p_rel);
2713 }
2714 }
2715 }
2716 }
2717 }
2718 } else if (d->type == OksData::uid2_type) {
2719 if (i->get_low_cardinality_constraint() == OksRelationship::One && d->data.UID2.object_id == nullptr) {
2720 warnings.add(i);
2721 }
2722 try {
2723 bind(d, info);
2724 } catch (oks::ObjectBindError& ex) {
2725 if (ex.p_is_error) {
2726 throw;
2727 } else {
2728 warnings.add(*ex.p_data, ex.p_rel);
2729 }
2730 }
2731 }
2732
2733 d++;
2734 }
2735
2736 if (warnings.p_warnings_count) {
2737 std::ostringstream text;
2738 const char* s1(warnings.p_warnings_count == 1 ? "is" : "are");
2739 const char* s2(warnings.p_warnings_count == 1 ? "" : "s");
2740 text << "There " << s1 << " " << warnings.p_warnings_count << " unresolved reference" << s2 << " from object "
2741 << this << '\n'
2742 << warnings.p_warnings->str();
2743 throw oks::ObjectBindError(this, 0, 0, false, text.str(), "");
2744 }
2745}
static void bind(OksData *, const BindInfo &)
Definition object.cpp:2552

◆ change_notify()

void dunedaq::oks::OksObject::change_notify ( )
private

Invoke change object notification.

Definition at line 2817 of file object.cpp.

2818{
2820 if (k->p_change_object_notify_fn) {
2821 (*k->p_change_object_notify_fn)(this, k->p_change_object_notify_param);
2822 }
2823}

◆ check_class_type() [1/2]

void dunedaq::oks::OksObject::check_class_type ( const OksRelationship * r,
const OksClass * class_type )
private

Definition at line 1970 of file object.cpp.

1971{
1972 if (!class_type)
1973 return;
1974
1975 const OksClass* rel_class_type = r->p_class_type;
1976
1977 if (class_type != rel_class_type) {
1978 OksClass::FList* super_classes = class_type->p_all_super_classes;
1979
1980 if (super_classes && !super_classes->empty()) {
1981 for (const auto& i : *super_classes) {
1982 if (rel_class_type == i)
1983 return;
1984 }
1985 }
1986
1987 std::ostringstream text;
1988 text << "set to an object of class \"" << class_type->get_name()
1989 << "\" is not allowed since the relationship's class type is \"" << r->get_type() << "\" and the class \""
1990 << class_type->get_name() << "\" has no such superclass";
1991 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
1992 }
1993}

◆ check_class_type() [2/2]

void dunedaq::oks::OksObject::check_class_type ( const OksRelationship * r,
const OksObject * o )
inlineprivate

Definition at line 1761 of file object.hpp.

1762 {
1763 if (o) {
1764 check_class_type(r, o->GetClass());
1765 }
1766 }

◆ check_file_lock()

void dunedaq::oks::OksObject::check_file_lock ( const OksAttribute * a,
const OksRelationship * r )
private

Definition at line 3125 of file object.cpp.

3126{
3127 try {
3128 file->lock();
3129 } catch (oks::exception& ex) {
3130 throw oks::ObjectSetError(this, (a == nullptr), (a ? a->get_name() : r->get_name()), ex);
3131 }
3132}
void lock()
Lock OKS file.
Definition file.cpp:1004

◆ check_ids()

void dunedaq::oks::OksObject::check_ids ( )
private

Definition at line 172 of file object.cpp.

173{
174 if (std::vector<OksClass*>* cs = uid.class_id->p_inheritance_hierarchy) {
175 for (std::vector<OksClass*>::const_iterator j = cs->begin(); j != cs->end(); ++j) {
176 OksObject* o = (*j)->get_object(uid.object_id);
177 if (__builtin_expect((o != nullptr), 0)) {
178 std::stringstream e;
179 e << "the object " << o << " from file \'" << o->get_file()->get_full_file_name()
180 << "\' "
181 "has ID equal with \'"
182 << uid.object_id << '@' << uid.class_id->get_name()
183 << "\' object and their classes belong to the same inheritance hierarchy "
184 "(the OKS kernel is configured in the \"test-duplicated-objects-within-inheritance-hierarchy\" mode for "
185 "compatibility with config and DAL tools)";
186 throw oks::FailedCreateObject(this, e.str());
187 }
188 }
189 }
190}
const std::string & get_name() const noexcept
Definition class.hpp:374
std::vector< OksClass * > * p_inheritance_hierarchy
Definition class.hpp:896

◆ check_links_and_report()

bool dunedaq::oks::OksObject::check_links_and_report ( const OksObject * o2,
const std::set< OksFile * > & includes,
const std::string & name,
const char * msg ) const
private

Definition at line 2840 of file object.cpp.

2844{
2845 if (get_file() != o2->get_file()) {
2846 if (includes.find(o2->get_file()) == includes.end()) {
2847 if (GetClass()->get_kernel()->get_silence_mode() == false) {
2848 std::cerr << msg
2849 << ": no files inclusion path between referenced objects:\n"
2850 " object "
2851 << this << " from file \"" << get_file()->get_full_file_name() << "\" via relationship \"" << name
2852 << "\"\n"
2853 " has reference to object "
2854 << o2 << " from file \"" << o2->get_file()->get_full_file_name()
2855 << "\";\n"
2856 " file \""
2857 << get_file()->get_full_file_name() << "\" includes " << includes.size() << " files:\n";
2858
2859 for (std::set<OksFile*>::const_iterator j = includes.begin(); j != includes.end(); ++j) {
2860 std::cerr << " * \'" << (*j)->get_full_file_name() << "\'\n";
2861 }
2862 }
2863
2864 return false;
2865 }
2866 }
2867
2868 return true;
2869}
const std::string & get_full_file_name() const
Definition file.hpp:528
OksFile * get_file() const
Definition object.hpp:1306

◆ check_non_null()

void dunedaq::oks::OksObject::check_non_null ( const OksRelationship * r,
const OksObject * o )
private

Definition at line 1958 of file object.cpp.

1959{
1960 if (!o && r->get_low_cardinality_constraint() != OksRelationship::Zero) {
1961 throw oks::ObjectSetError(
1962 this,
1963 true,
1964 r->get_name(),
1965 "set to (null) is not allowed since the relationship has non-zero low cardinality constraint");
1966 }
1967}

◆ create_notify()

void dunedaq::oks::OksObject::create_notify ( )
private

Invoke create object notification.

Definition at line 2803 of file object.cpp.

2804{
2806
2807 if (k->p_create_object_notify_fn) {
2808 (*k->p_create_object_notify_fn)(this, k->p_create_object_notify_param);
2809 }
2810}

◆ delete_notify()

void dunedaq::oks::OksObject::delete_notify ( )
private

Invoke delete object notification.

Definition at line 2830 of file object.cpp.

2831{
2833
2834 if (k->p_delete_object_notify_fn) {
2835 (*k->p_delete_object_notify_fn)(this, k->p_delete_object_notify_param);
2836 }
2837}

◆ destroy()

void dunedaq::oks::OksObject::destroy ( OksObject * obj,
bool fast = false )
static

Destroy OKS object.

This the the only way available to user to destroy OKS object since ~OksObject() is private.

When an object is destroyed, it shall not be referenced by other objects.

In case of problems the oks::exception is thrown.

The parameters are:

Parameters
objthe object to be destroyed
fastif true, skip extra protection checks

Definition at line 1284 of file object.cpp.

1285{
1286 if (!o->uid.class_id || fast) {
1287 delete o;
1288 return;
1289 }
1290
1291 // check lack of references on object
1292
1293 std::unique_ptr<std::ostringstream> error_text;
1294
1295 const OksClass::Map& classes = o->uid.class_id->p_kernel->classes();
1296
1297 for (OksClass::Map::const_iterator i = classes.begin(); i != classes.end(); ++i) {
1298 OksClass* c(i->second);
1299 if (c->p_all_relationships == nullptr || c->p_all_relationships->empty())
1300 continue;
1301
1302 if (const OksObject::Map* objects = c->objects()) {
1303 for (OksObject::Map::const_iterator j = objects->begin(); j != objects->end(); ++j) {
1304 size_t offset = c->number_of_all_attributes();
1305 for (std::list<OksRelationship*>::iterator k = c->p_all_relationships->begin();
1306 k != c->p_all_relationships->end();
1307 ++k, ++offset) {
1308 OksData* d = j->second->data + offset;
1309 OksObject* ref = nullptr;
1310
1311 if (d->type == OksData::object_type && d->data.OBJECT == o) {
1312 ref = j->second;
1313 } else if (d->type == OksData::list_type && d->data.LIST != nullptr) {
1314 for (const auto& l : *d->data.LIST) {
1315 if (l->type == OksData::object_type && l->data.OBJECT == o) {
1316 ref = j->second;
1317 break;
1318 }
1319 }
1320 }
1321
1322 if (ref) {
1323 if (!error_text.get()) {
1324 error_text.reset(new std::ostringstream());
1325 *error_text << "since it is referenced by:";
1326 }
1327 *error_text << "\n * object " << ref << " via relationship \"" << (*k)->get_name() << '\"';
1328 }
1329 }
1330 }
1331 }
1332 }
1333
1334 if (error_text.get()) {
1335 throw oks::FailedDestoyObject(o, error_text->str().c_str());
1336 }
1337
1338 try {
1339 o->file->lock();
1340 o->file->set_updated();
1341 } catch (oks::exception& ex) {
1342 throw oks::FailedDestoyObject(o, ex);
1343 }
1344
1345 delete o;
1346}
std::map< const char *, OksClass *, SortStr > Map
Definition class.hpp:252
std::unordered_map< const std::string *, OksObject *, oks::hash_str, oks::equal_str > Map
Definition object.hpp:1170

◆ find_path()

OksObject::List * dunedaq::oks::OksObject::find_path ( const oks::QueryPath & query) const

Definition at line 923 of file query.cpp.

924{
925 OksObject::List* path = new OksObject::List();
926
927 if (satisfies(query.get_goal_object(), *query.get_start_expression(), *path) == false) {
928 delete path;
929 path = 0;
930 }
931
932 return path;
933}
std::list< OksObject * > List
Definition object.hpp:1179
bool satisfies(const OksObject *goal, const oks::QueryPathExpression &expresssion, OksObject::List &path) const
Definition query.cpp:936

◆ get_all_rels()

OksObject::FList * dunedaq::oks::OksObject::get_all_rels ( const std::string & name = "*") const

Return objects referencing this one via relationship with given name.

The method returns list of objects which have a reference on given one. If the relationship name is set to "*", then the method takes into account all relationships of all objects. The method performs full scan of all OKS objects and it is not recommended at large scale to build complete graph of relations between all database object; if only composite parents are needed, them the reverse_composite_rels() method has to be used.

The parameters are:

Parameters
namethe name of relationship used to reference given object (by default ANY relationship)
Returns
the list of objects referencing this one (can be null, if there are no such objects); the user is responsible to destroy the returned list (but not the objects it contains)

Definition at line 3062 of file object.cpp.

3063{
3064 bool any_name = (name == "*");
3065
3066 OksObject::FList* result = nullptr;
3067
3068 const OksClass::Map& all_classes(GetClass()->get_kernel()->classes());
3069
3070 for (OksClass::Map::const_iterator i = all_classes.begin(); i != all_classes.end(); ++i) {
3071 OksClass* c(i->second);
3072 if (any_name || c->find_relationship(name) != nullptr) {
3073 if (const OksObject::Map* objs = i->second->objects()) {
3074 for (OksObject::Map::const_iterator j = objs->begin(); j != objs->end(); ++j) {
3075 OksObject* o(j->second);
3076 unsigned short l1, l2;
3077
3078 if (any_name) {
3079 l1 = c->number_of_all_attributes();
3080 l2 = l1 + c->number_of_all_relationships();
3081 } else {
3082 l1 = c->data_info(name)->offset;
3083 l2 = l1 + 1;
3084 }
3085
3086 while (l1 < l2) {
3087 OksDataInfo odi(l1, (OksRelationship*)0);
3088 OksData* d(o->GetRelationshipValue(&odi));
3089
3090 if (d->type == OksData::object_type) {
3091 if (this == d->data.OBJECT) {
3092 if (!result)
3093 result = new OksObject::FList();
3094 result->push_back(o);
3095 break;
3096 }
3097 } else if (d->type == OksData::list_type) {
3098 bool found = false;
3099 for (OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
3100 OksData* lid(*li);
3101 if (lid->type == OksData::object_type) {
3102 if (this == lid->data.OBJECT) {
3103 if (!result)
3104 result = new OksObject::FList();
3105 result->push_back(o);
3106 found = true;
3107 break; // exit given relationship value iterator
3108 }
3109 }
3110 }
3111 if (found)
3112 break; // exit relationships iterator for given object
3113 }
3114 ++l1;
3115 }
3116 }
3117 }
3118 }
3119 }
3120
3121 return result;
3122}
std::list< OksObject *, boost::fast_pool_allocator< OksObject * > > FList
Definition object.hpp:1181

◆ get_change_notify()

OksObject::notify_obj dunedaq::oks::OksObject::get_change_notify ( ) const
private

Definition at line 2793 of file object.cpp.

2794{
2796}
OksObject::notify_obj p_change_object_notify_fn
Definition kernel.hpp:2098

◆ get_file()

OksFile * dunedaq::oks::OksObject::get_file ( ) const
inline

Get file of object.

Definition at line 1306 of file object.hpp.

1306{ return file; }

◆ get_int32_id()

int32_t dunedaq::oks::OksObject::get_int32_id ( ) const
inline

Get object id associated with given object. Return integer number set using set_int32_id() method.

Definition at line 1635 of file object.hpp.

1635{ return p_int32_id; }

◆ GetAttributeValue() [1/2]

OksData * dunedaq::oks::OksObject::GetAttributeValue ( const OksDataInfo * i) const
inlinenoexcept

Get value of attribute by offset.

The method returns pointer on OksData value for given attribute offset. The method is optimised for performance and does not check validity of offset.

The parameter is:

Parameters
data_infodescribes offset of attribute's value for given OKS class
Returns
the OKS data value for given attribute

Definition at line 1352 of file object.hpp.

1352{ return &(data[i->offset]); }

◆ GetAttributeValue() [2/2]

OksData * dunedaq::oks::OksObject::GetAttributeValue ( const std::string & name) const

Get value of attribute by name.

The method returns pointer on OksData value for given attribute.

In case of problems (e.g. no attribute with such name) the oks::exception is thrown.

The parameter is:

Parameters
namename of attribute
Returns
the OKS data value for given attribute
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 1852 of file object.cpp.

1853{
1854 OksDataInfo::Map::const_iterator i = uid.class_id->p_data_info->find(name);
1855
1856 if (i == uid.class_id->p_data_info->end()) {
1857 std::ostringstream text;
1858 text << "object " << this << " has no attribute \"" << name << '\"';
1859 throw oks::ObjectGetError(this, false, name, text.str());
1860 }
1861
1862 return GetAttributeValue(i->second);
1863}
OksData * GetAttributeValue(const std::string &name) const
Get value of attribute by name.
Definition object.cpp:1852

◆ GetClass()

const OksClass * dunedaq::oks::OksObject::GetClass ( ) const
inline

Get class of object.

Definition at line 1286 of file object.hpp.

1286{ return uid.class_id; }

◆ GetId()

const std::string & dunedaq::oks::OksObject::GetId ( ) const
inline

Get object ID.

Definition at line 1290 of file object.hpp.

1290{ return uid.object_id; }

◆ GetRelationshipValue() [1/2]

OksData * dunedaq::oks::OksObject::GetRelationshipValue ( const OksDataInfo * i) const
inlinenoexcept

Get value of relationship by offset.

The method returns pointer on OksData value for given relationship offset. The method is optimised for performance and does not check validity of offset.

The parameter is:

Parameters
data_infodescribes offset of relationship's value for given OKS class
Returns
the OKS data value for given relationship

Definition at line 1383 of file object.hpp.

1383{ return &(data[i->offset]); }

◆ GetRelationshipValue() [2/2]

OksData * dunedaq::oks::OksObject::GetRelationshipValue ( const std::string & name) const

Get value of relationship by name.

The method returns pointer on OksData value for given relationship.

In case of problems (e.g. no relationship with such name) the oks::exception is thrown.

The parameter is:

Parameters
namename of relationship
Returns
the OKS data value for given relationship
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 1944 of file object.cpp.

1945{
1946 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
1947
1948 if (i == uid.class_id->p_data_info->end()) {
1949 std::ostringstream text;
1950 text << "object " << this << " has no relationship \"" << name << '\"';
1951 throw oks::ObjectGetError(this, false, name, text.str());
1952 }
1953
1954 return GetRelationshipValue(i->second);
1955}
OksData * GetRelationshipValue(const std::string &) const
Get value of relationship by name.
Definition object.cpp:1944

◆ GetTransientData()

void * dunedaq::oks::OksObject::GetTransientData ( ) const
inline

Get transient user data associated with given object. Return data set using SetTransientData() method.

Definition at line 1621 of file object.hpp.

1621{ return p_user_data; }

◆ init1()

void dunedaq::oks::OksObject::init1 ( const OksFile * fp = 0)
private

Definition at line 193 of file object.cpp.

194{
195 const OksClass* c = uid.class_id;
196 const std::string& object_id = uid.object_id;
197 const OksKernel* kernel(c->get_kernel());
198
199 // do not allow to create an object of ABSTRACT class
200
201 if (__builtin_expect((c->get_is_abstract()), 0)) {
202 std::ostringstream text;
203 text << "the class \'" << c->get_name() << "\' is abstract";
204 throw oks::FailedCreateObject(this, text.str());
205 }
206
207 // do not allow two objects with equal ID in the same class
208
209 if (__builtin_expect((!object_id.empty()), 1)) {
210 if (kernel->get_test_duplicated_objects_via_inheritance_mode() && !kernel->get_allow_duplicated_objects_mode()) {
211 check_ids();
212 }
213
214 OksObject* o = c->get_object(object_id);
215
216 if (__builtin_expect((o != nullptr), 0)) {
217 if (kernel->get_allow_duplicated_objects_mode()) {
219 if (kernel->get_silence_mode() != true) {
220 std::cerr << "WARNING [OksObject constructor]:\n"
221 " Cannot create object "
222 << o;
223 if (fp) {
224 std::cerr << " while reading file \'" << fp->get_full_file_name() << '\'';
225 }
226 std::cerr << "\n"
227 " Skip above problem since OKS kernel is configured in \'ignore-duplicated-objects\' mode\n"
228 << " Create duplicated object with ID = \'" << uid.object_id << "\'\n";
229 }
230 } else {
231 std::stringstream e;
232 e << "the object was already loaded from file \'" << o->get_file()->get_full_file_name() << '\'';
233 throw oks::FailedCreateObject(this, e.str());
234 }
235 }
236 } else {
238 }
239
240 data = new OksData[c->p_instance_size];
241 p_user_data = nullptr;
242 p_int32_id = 0;
243 p_rcr = nullptr;
244 file = kernel->get_active_data();
245}

◆ init2()

void dunedaq::oks::OksObject::init2 ( bool skip_init = false)
private

Definition at line 275 of file object.cpp.

276{
277 int count = 0;
278 const OksClass* c = uid.class_id;
279
280 if (c->p_all_attributes) {
281 if (skip_init == false) {
282 for (const auto& i : *c->p_all_attributes)
283 data[count++] = i->p_init_data;
284 } else {
285 for (const auto& i : *c->p_all_attributes)
286 data[count++] = i->p_empty_init_data;
287 }
288 }
289
290 if (c->p_all_relationships) {
291 for (const auto& i : *c->p_all_relationships) {
292 OksData& d(data[count++]);
293 if (i->get_high_cardinality_constraint() != OksRelationship::Many) {
294 d.type = OksData::object_type;
295 d.data.OBJECT = nullptr;
296 } else {
297 d.type = OksData::list_type;
298 d.data.LIST = new OksData::List();
299 }
300 }
301 }
302}

◆ init3() [1/2]

void dunedaq::oks::OksObject::init3 ( )
private

Definition at line 317 of file object.cpp.

318{
319 init3(const_cast<OksClass*>(uid.class_id));
321}

◆ init3() [2/2]

void dunedaq::oks::OksObject::init3 ( OksClass * c)
private

Definition at line 305 of file object.cpp.

306{
307 if (__builtin_expect((c->p_indices != nullptr), 0)) {
308 for (auto& i : *c->p_indices)
309 i.second->insert(this);
310 }
311
312 c->add(this);
313 c->p_kernel->define(this);
314}

◆ is_consistent()

bool dunedaq::oks::OksObject::is_consistent ( const std::set< OksFile * > & includes,
const char * msg ) const

The method checks the schema constraints for given object and the file's includes. Return false, if object is inconsistent.

Definition at line 2917 of file object.cpp.

2918{
2919 unsigned short l1 = GetClass()->number_of_all_attributes();
2920 unsigned short l2 = l1 + GetClass()->number_of_all_relationships();
2921
2922 std::list<OksRelationship*>::const_iterator ri = GetClass()->all_relationships()->begin();
2923
2924 bool return_value = true;
2925
2926 while (l1 < l2) {
2927 OksDataInfo odi(l1, *ri);
2929
2930 if (d->type == OksData::object_type) {
2931 if (OksObject* o2 = d->data.OBJECT) {
2932 check_links_and_report(o2, includes, odi.relationship->get_name(), msg);
2933 }
2934 } else if (d->type == OksData::list_type) {
2935 for (OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
2936 if ((*li)->type == OksData::object_type) {
2937 if (OksObject* o2 = (*li)->data.OBJECT) {
2938 check_links_and_report(o2, includes, odi.relationship->get_name(), msg);
2939 }
2940 }
2941 }
2942 }
2943
2944 if (d->IsConsistent(odi.relationship, this, "ERROR") == false) {
2945 return_value = false;
2946 }
2947
2948 ++l1;
2949 ++ri;
2950 }
2951
2952 // check inclusion of the schema file
2953
2954 if (includes.find(GetClass()->get_file()) == includes.end()) {
2955 if (GetClass()->get_kernel()->get_silence_mode() == false) {
2956 std::cerr << "ERROR: the schema file is not included for object " << this
2957 << ".\n"
2958 " The data file \""
2960 << "\" containg above object\n"
2961 " cannot be loaded or edited without inclusion of additional files.\n"
2962 " The file shall explicitly or implicitly (i.e. via other included files) include schema file\n"
2963 " \""
2964 << GetClass()->get_file()->get_full_file_name() << "\" defining class \"" << GetClass()->get_name()
2965 << "\".\n";
2966 }
2967
2968 return false;
2969 }
2970
2971 return return_value;
2972}
size_t number_of_all_relationships() const noexcept
Definition class.hpp:988
size_t number_of_all_attributes() const noexcept
Definition class.hpp:976
OksFile * get_file() const noexcept
Definition class.hpp:352
const std::list< OksRelationship * > * all_relationships() const noexcept
Definition class.hpp:568
bool check_links_and_report(const OksObject *, const std::set< OksFile * > &, const std::string &, const char *) const
Definition object.cpp:2840

◆ is_duplicated()

bool dunedaq::oks::OksObject::is_duplicated ( ) const
inline

Definition at line 1667 of file object.hpp.

1667{ return (p_duplicated_object_id_idx != -1); }

◆ notify()

void dunedaq::oks::OksObject::notify ( )
inlineprivate

Definition at line 1754 of file object.hpp.

1755 {
1756 file->set_updated();
1757 change_notify();
1758 }

◆ operator delete()

void dunedaq::oks::OksObject::operator delete ( void * ptr)
inline

Fast delete operator.

Definition at line 1261 of file object.hpp.

1262 {
1263 boost::fast_pool_allocator<OksObject>::deallocate(reinterpret_cast<OksObject*>(ptr));
1264 }

◆ operator new()

void * dunedaq::oks::OksObject::operator new ( size_t )
inline

Fast new operator to reduce resources consumption.

Definition at line 1257 of file object.hpp.

1257{ return boost::fast_pool_allocator<OksObject>::allocate(); }

◆ operator!=()

bool dunedaq::oks::OksObject::operator!= ( const OksObject & ) const
delete

◆ operator=()

OksObject & dunedaq::oks::OksObject::operator= ( const OksObject & )
private

◆ operator==()

bool dunedaq::oks::OksObject::operator== ( const OksObject & o) const

The equality operator.

The operator returns true, if comparing objects belong to the same class or classes with equal names (e.g. belonging to different OksKernels) and their attributes and relationships are equal.

Definition at line 1590 of file object.cpp.

1591{
1592 if (are_equal_fast(this, &o) == false)
1593 return false;
1594
1596
1597 size_t count(0);
1598
1599 while (count < uid.class_id->p_instance_size) {
1600 if (data[count] == o.data[count])
1601 count++;
1602 else
1603 return false;
1604 }
1605
1606 return true;
1607}
static bool are_equal_fast(const OksObject *o1, const OksObject *o2)
The fast equal method.
Definition object.cpp:1578

◆ put()

void dunedaq::oks::OksObject::put ( OksXmlOutputStream & xmls,
bool force_defaults ) const
private

Definition at line 1735 of file object.cpp.

1736{
1738
1739 try {
1740 const OksClass* class_id = uid.class_id;
1741
1742 xmls.put_start_tag(obj_xml_tag, sizeof(obj_xml_tag) - 1);
1743
1744 xmls.put_attribute(class_xml_attribute, sizeof(class_xml_attribute) - 1, class_id->get_name().c_str());
1745 xmls.put_attribute(id_xml_attribute, sizeof(id_xml_attribute) - 1, uid.object_id.c_str());
1746
1747 xmls.put_eol();
1748
1749 int count = 0;
1750
1751 if (auto alist = class_id->all_attributes()) {
1752 for (const auto& a : *alist) {
1753 OksData& d = data[count++];
1754
1755 // store all attributes with value != initial, or date/time types which default values = now(), or non-numbers
1756 // or numbers with non-zero values
1757 if (force_defaults || d != a->p_init_data || a->p_data_type == OksData::date_type ||
1758 a->p_data_type == OksData::time_type ||
1759 (a->get_init_value().empty() == false &&
1760 (a->get_is_multi_values() == true || a->is_number() == false || a->get_init_value().size() > 1 ||
1761 a->get_init_value()[0] != '0'))) {
1762 xmls.put_raw(' ');
1763 xmls.put_start_tag(attribute_xml_tag, sizeof(attribute_xml_tag) - 1);
1764 xmls.put_attribute(name_xml_attribute, sizeof(name_xml_attribute) - 1, a->get_name().c_str());
1765 xmls.put_attribute(type_xml_attribute, sizeof(type_xml_attribute) - 1, a->get_type().c_str());
1766
1767 if (a->is_integer() && a->get_format() != OksAttribute::Dec) {
1768 xmls.get_stream().setf((a->get_format() == OksAttribute::Hex ? std::ios::hex : std::ios::oct),
1769 std::ios::basefield);
1770 xmls.get_stream().setf(std::ios::showbase);
1771 }
1772
1773 if (a->get_is_multi_values() == false) {
1774 xmls.put_attribute(value_xml_attribute, sizeof(value_xml_attribute) - 1, d);
1775 xmls.put_end_tag();
1776 } else {
1777 if (d.data.LIST->empty()) {
1778 xmls.put_end_tag();
1779 } else {
1780 if (a->p_ordered)
1781 d.sort();
1782
1783 xmls.put_eol();
1784
1785 for (const auto& x : *d.data.LIST) {
1786 xmls.put_raw(' ');
1787 xmls.put_raw(' ');
1788 xmls.put_start_tag(data_xml_tag, sizeof(data_xml_tag) - 1);
1789 xmls.put_attribute(value_xml_attribute, sizeof(value_xml_attribute) - 1, *x);
1790 xmls.put_end_tag();
1791 }
1792
1793 xmls.put_raw(' ');
1794 xmls.put_last_tag(attribute_xml_tag, sizeof(attribute_xml_tag) - 1);
1795 }
1796 }
1797
1798 if (a->is_integer() && a->get_format() != OksAttribute::Dec) {
1799 xmls.get_stream().setf(std::ios::dec, std::ios::basefield);
1800 xmls.get_stream().unsetf(std::ios::showbase);
1801 }
1802 }
1803 }
1804 }
1805
1806 if (const std::list<OksRelationship*>* rlist = class_id->all_relationships()) {
1807 for (const auto& r : *rlist) {
1808 OksData& rel_data = data[count++];
1809
1810 if (trim_dangling(rel_data, *class_id->p_kernel)) {
1811 xmls.put_raw(' ');
1812 xmls.put_start_tag(relationship_xml_tag, sizeof(relationship_xml_tag) - 1);
1813 xmls.put_attribute(name_xml_attribute, sizeof(name_xml_attribute) - 1, r->get_name().c_str());
1814
1815 if (r->get_high_cardinality_constraint() != OksRelationship::Many) {
1816 put_object_attributes(xmls, rel_data);
1817 xmls.put_end_tag();
1818 } else {
1819 if (r->p_ordered)
1820 rel_data.sort();
1821
1822 xmls.put_eol();
1823
1824 for (const auto& x : *rel_data.data.LIST) {
1825 xmls.put_raw(' ');
1826 xmls.put_raw(' ');
1827 xmls.put_start_tag(ref_xml_tag, sizeof(ref_xml_tag) - 1);
1828 put_object_attributes(xmls, *x);
1829 xmls.put_end_tag();
1830 }
1831
1832 xmls.put_raw(' ');
1833 xmls.put_last_tag(relationship_xml_tag, sizeof(relationship_xml_tag) - 1);
1834 }
1835 }
1836 }
1837 }
1838
1839 xmls.put_last_tag(obj_xml_tag, sizeof(obj_xml_tag) - 1);
1840 } catch (oks::exception& ex) {
1841 throw(oks::FailedSaveObject(this, ex));
1842 } catch (std::ios_base::failure& ex) {
1843 throw(oks::FailedSaveObject(this, std::string("caught std::ios_base::failure exception \"") + ex.what() + '\"'));
1844 } catch (std::exception& ex) {
1845 throw(oks::FailedSaveObject(this, std::string("caught std::exception \"") + ex.what() + '\"'));
1846 } catch (...) {
1847 throw(oks::FailedSaveObject(this, "unknown reason"));
1848 }
1849}
static const char relationship_xml_tag[]
Definition object.hpp:1799
static const char attribute_xml_tag[]
Definition object.hpp:1798
static void put_object_attributes(OksXmlOutputStream &, const OksData &)
Definition object.cpp:1714
static const char value_xml_attribute[]
Definition object.hpp:1808
static const char id_xml_attribute[]
Definition object.hpp:1802
static const char obj_xml_tag[]
Definition object.hpp:1796
static const char class_xml_attribute[]
Definition object.hpp:1800
static const char name_xml_attribute[]
Definition object.hpp:1804
static const char type_xml_attribute[]
Definition object.hpp:1805
static const char data_xml_tag[]
Definition object.hpp:1809
static const char ref_xml_tag[]
Definition object.hpp:1810
static bool trim_dangling(OksData &d, const OksKernel &kernel)
Definition object.cpp:1683

◆ put_object_attributes()

void dunedaq::oks::OksObject::put_object_attributes ( OksXmlOutputStream & xmls,
const OksData & d )
staticprivate

Definition at line 1714 of file object.cpp.

1715{
1716 const std::string* class_name = nullptr;
1717 const std::string* object_id = nullptr;
1718
1719 if (d.type == OksData::object_type) {
1720 class_name = &d.data.OBJECT->GetClass()->get_name();
1721 object_id = &d.data.OBJECT->GetId();
1722 } else if (d.type == OksData::uid_type) {
1723 class_name = &d.data.UID.class_id->get_name();
1724 object_id = d.data.UID.object_id;
1725 } else {
1726 class_name = d.data.UID2.class_id;
1727 object_id = d.data.UID2.object_id;
1728 }
1729
1730 xmls.put_attribute(class_xml_attribute, sizeof(class_xml_attribute) - 1, class_name->c_str());
1731 xmls.put_attribute(id_xml_attribute, sizeof(id_xml_attribute) - 1, object_id->c_str());
1732}

◆ read()

OksObject * dunedaq::oks::OksObject::read ( const oks::ReadFileParams & read_params)
staticprivate

Read OKS object from input stream.

Returns
The method returns a pointer to OksObject, or NULL object to indicate end-of-stream.
Exceptions
oks::exceptionis thrown in case of errors, e.g. bad input stream, duplicated object, abstract class of object.

Definition at line 357 of file object.cpp.

358{
359 // read 'object' tag header
360
361 try {
362 const char* tag_start(read_params.s.get_tag_start());
363
364 if (memcmp(tag_start, read_params.object_tag, read_params.object_tag_len)) {
365 if (!oks::cmp_str9(tag_start, "/oks-data")) {
366 read_params.s.throw_unexpected_tag(tag_start, read_params.object_tag);
367 }
368 return 0;
369 }
370 } catch (oks::exception& e) {
371 throw oks::FailedRead("start-of-object tag", e);
372 } catch (std::exception& e) {
373 throw oks::FailedRead("start-of-object tag", e.what());
374 }
375
376 // read object tag attributes
377
378 OksClass* c(nullptr);
379 std::string& id((const_cast<oks::ReadFileParams&>(read_params)).tmp); // use temporal string for fast assignment
380
381 try {
382 if (read_params.format != 'c') {
384 } else {
386 }
387 } catch (oks::exception& e) {
388 throw oks::FailedRead("object header", e);
389 } catch (std::exception& e) {
390 throw oks::FailedRead("object header", e.what());
391 }
392
393 if (!c) {
394 throw oks::BadFileData("object without class", read_params.s.get_line_no(), read_params.s.get_line_pos());
395 }
396
397 try {
398 oks::validate_not_empty(id, "object id");
399 } catch (std::exception& ex) {
400 throw oks::FailedRead("oks object",
401 oks::BadFileData(ex.what(), read_params.s.get_line_no(), read_params.s.get_line_pos()));
402 }
403
404 if (c && read_params.reload_objects) {
405 if (OksObject* o = read_params.reload_objects->pop(c, id)) {
406 o->read_body(read_params, true);
407 return o;
408 }
409 }
410
411 // check if this is the end of file
412
413 if (c == nullptr && id.empty()) {
414 return nullptr;
415 }
416
417 // create new object
418
419 OksObject* obj = new OksObject(read_params, c, id); // can throw exception
420
421 // check if we re-read the database and notify if required
422
423 if (read_params.reload_objects) {
424 read_params.reload_objects->created.push_back(obj);
425 obj->create_notify();
426
427 if (read_params.oks_kernel->get_verbose_mode()) {
428 TLOG_DEBUG(3) << "*** create object " << obj << " while reload data ***";
429 }
430 }
431
432 return obj;
433}
static const char class2_xml_attribute[]
Definition object.hpp:1801
static const char id2_xml_attribute[]
Definition object.hpp:1803
friend struct oks::ReadFileParams
Definition object.hpp:1151
bool cmp_str1(const char *s1, const char s2[2])
Definition cstring.hpp:15
bool cmp_str9(const char *s1, const char s2[10])
Definition cstring.hpp:105
void validate_not_empty(const std::string &value, const char *name)
bool cmp_str2(const char *s1, const char s2[3])
Definition cstring.hpp:21
bool cmp_str5(const char *s1, const char s2[6])
Definition cstring.hpp:57
msgpack::object obj
#define READ_OBJ_HEADER(F1, S1, F2, S2)
Definition object.cpp:323

◆ read_body()

void dunedaq::oks::OksObject::read_body ( const oks::ReadFileParams & read_params,
bool re_read )
private

Definition at line 542 of file object.cpp.

543{
544 std::string& i_name((const_cast<oks::ReadFileParams&>(read_params)).tmp);
545 bool non_silent_mode(!read_params.oks_kernel->get_silence_mode()); // detect if we need to print errors
546
547 OksData dd; // temporal data
548 const OksClass* c = uid.class_id; // pointer to object's class
549
550 bool was_updated = false; // is used when object is re-read from file
551 bool check_re_read = (re_read && read_params.oks_kernel->p_change_object_notify_fn);
552
553 char* __sanity; // used to check mu, token
554
555 // set file from which this object was read
556
557 file = read_params.f;
558
559 // is used by ReadFrom(relationship)
560
561 const_cast<oks::ReadFileParams&>(read_params).owner = this;
562
563 if (__builtin_expect((read_params.format != 'c'), 1)) {
564 OksDataInfo::Map::iterator info_i;
565 OksDataInfo* info(0);
566
567 // are used when object is re-read from file
568
569 std::list<const OksAttribute*>* read_attributes = nullptr;
570 std::list<const OksRelationship*>* read_relationships = nullptr;
571
572 if (__builtin_expect((check_re_read), 0)) {
573 if (c->p_all_attributes && !c->p_all_attributes->empty()) {
574 read_attributes = new std::list<const OksAttribute*>();
575 for (auto& i : *c->p_all_attributes)
576 read_attributes->push_back(i);
577 }
578
579 if (c->p_all_relationships && !c->p_all_relationships->empty()) {
580 read_relationships = new std::list<const OksRelationship*>();
581 for (auto& i : *c->p_all_relationships)
582 read_relationships->push_back(i);
583 }
584 } else if (__builtin_expect((c != nullptr), 1)) {
585 if (__builtin_expect((re_read == true), 0)) {
586 OksData* d_end = data + c->number_of_all_attributes() + c->number_of_all_relationships();
587 for (OksData* di = data; di < d_end; ++di) {
588 di->Clear();
589 }
590 }
591
592 init2();
593 }
594
595 // read object body
596
597 while (true)
598 try {
599
600 const char* tag_start = read_params.s.get_tag_start();
601
602 // check for closing tag
603
604 if (*tag_start == '/' && !memcmp(tag_start + 1, read_params.object_tag, read_params.object_tag_len)) {
605 break;
606 }
607
608 // extra check, if the object is empty
609
610 if (oks::cmp_str3(tag_start, "obj")) {
611 read_params.s.seek_position(-5);
612 break;
613 }
614
615 // read attribute
616
617 else if (oks::cmp_str4(tag_start, attribute_xml_tag)) {
619 int32_t num = -1; // -1 => no mv-data read
620 const OksAttribute* a(0);
621 OksXmlValue value;
622 bool attr_is_closed(false);
623
624 // read 'oks-attribute' tag attributes
625
626 try {
627
628 bool name_was_read(false);
629
630 while (true) {
631 OksXmlAttribute attr(read_params.s);
632
633 // check for close of tag
634 if (oks::cmp_str1(attr.name(), ">")) {
635 break;
636 }
637
638 if (read_params.format == 'n' && oks::cmp_str1(attr.name(), "/")) {
639 attr_is_closed = true;
640 break;
641 }
642
643 // check for known oks-attribute' attributes
644 if (oks::cmp_str4(attr.name(), name_xml_attribute)) {
645 name_was_read = true;
646 if (__builtin_expect((c != nullptr), 1)) {
647 i_name.assign(attr.value(), attr.value_len());
648 info_i = c->p_data_info->find(i_name);
649 if (__builtin_expect((info_i == c->p_data_info->end() || info_i->second->attribute == nullptr), 0)) {
650 if (non_silent_mode) {
651 std::string msg = std::string("Read object \"") + GetId() + '@' + c->get_name() + '\"';
652 std::lock_guard lock(OksKernel::p_parallel_out_mutex);
653 Oks::warning_msg(msg.c_str())
654 << " skip attribute \"" << attr.value() << "\", which is not defined in the schema\n";
655 }
656 } else {
657 info = info_i->second;
658 a = info->attribute;
659 }
660 }
661 } else if (oks::cmp_str4(attr.name(), type_xml_attribute)) {
662 type = OksAttribute::get_data_type(attr.value(), attr.value_len());
663 if (__builtin_expect((type == OksData::unknown_type), 0)) {
664 if (attr.value()[0] != 0 &&
665 ((attr.value()[0] == '-' && attr.value_len() != 1) || (attr.value()[0] != '-'))) {
666 __throw_unknown_type(read_params, attr.value());
667 }
668 }
669 } else if (read_params.format != 'n' && oks::cmp_str3(attr.name(), num_xml_attribute)) {
670 num = static_cast<int32_t>(strtol(attr.value(), &__sanity, 0));
671 if (__builtin_expect((*__sanity != 0 || errno == ERANGE), 0))
673 "strtoul", __sanity, attr.value(), read_params.s.get_line_no(), read_params.s.get_line_pos());
674 } else if (read_params.format == 'n' && oks::cmp_str3(attr.name(), value_xml_attribute)) {
675 value = read_params.s.get_value(attr.p_value_len);
676 } else {
677 read_params.s.throw_unexpected_attribute(attr.name());
678 }
679 }
680
681 if (__builtin_expect((!name_was_read), 0)) {
682 throw oks::BadFileData(
683 "attribute without name", read_params.s.get_line_no(), read_params.s.get_line_pos());
684 }
685
686 if (read_params.format == 'n' && value.is_empty() == true)
687 num = 0;
688 } catch (oks::exception& e) {
689 throw oks::FailedRead("attribute value header", e);
690 } catch (std::exception& e) {
691 throw oks::FailedRead("attribute value header", e.what());
692 }
693
694 // read 'oks-attribute' body
695 if (__builtin_expect((a != nullptr), 1)) {
696 OksData* d = &data[info->offset];
697 OksData* dx;
698
699 if (__builtin_expect((check_re_read), 0)) {
700 dx = &dd;
701 read_attributes->remove(a);
702 } else {
703 dx = d;
704 }
705
706 // set default type if it was not read from file
707 if (__builtin_expect((type == OksData::unknown_type), 0)) {
708 type = a->get_data_type();
709 }
710
711 try {
712
713 // read value and convert if necessary
714
715 if (num == -1) {
716 if (__builtin_expect((a->get_data_type() != type || a->get_is_multi_values()), 0)) {
717 OksAttribute a2((type != OksData::enum_type ? type : OksData::string_type), c);
718
719 OksData d2;
720 if (read_params.format != 'n')
721 d2.read(read_params, &a2);
722 else
723 d2.read(&a2, value);
724 d2.cvt(dx, a);
725 if (non_silent_mode) {
726 __report_type_cvt_warning(read_params, *a, *dx, type, num);
727 }
728 } else {
729 if (read_params.format != 'n')
730 dx->read(read_params, a);
731 else
732 dx->read(a, value);
733 }
734 } else {
735 if (__builtin_expect((a->get_data_type() != type || !a->get_is_multi_values()), 0)) {
736 OksAttribute a2((type != OksData::enum_type ? type : OksData::string_type), c);
737 OksData d2;
738 if (read_params.format != 'n')
739 d2.read(read_params, &a2, num);
740 else {
741 if (attr_is_closed == false)
742 d2.read(&a2, read_params);
743 else
744 d2.Set(new OksData::List());
745 }
746 d2.cvt(dx, a);
747 if (non_silent_mode) {
748 __report_type_cvt_warning(read_params, *a, *dx, type, num);
749 }
750 } else {
751 if (read_params.format != 'n')
752 dx->read(read_params, a, num);
753 else {
754 if (attr_is_closed == false)
755 dx->read(a, read_params);
756 else
757 dx->Set(new OksData::List());
758 }
759 }
760 }
761
762 // check validity range
763
764 dx->check_range(a);
765 } catch (oks::exception& e) {
766 throw oks::FailedReadObject(this, std::string("attribute \"") + a->get_name() + '\"', e);
767 } catch (std::exception& e) {
768 throw oks::FailedReadObject(this, std::string("attribute \"") + a->get_name() + '\"', e.what());
769 }
770
771 if (__builtin_expect((check_re_read), 0)) {
772 if (*dx != *d) {
773 was_updated = true;
774 *d = *dx;
775 }
776 dd.Clear();
777 }
778 } else {
779 try {
780 OksAttribute a2((type != OksData::enum_type ? type : OksData::string_type), c);
781 if (num == -1) {
782 // note, there is no need to read single-value in case of "normal" format
783 if (read_params.format != 'n')
784 OksData(read_params, &a2);
785 } else {
786 if (read_params.format != 'n')
787 OksData(read_params, &a2, num);
788 else
789 OksData(&a2, read_params);
790 }
791 } catch (oks::exception& e) {
792 throw oks::FailedReadObject(this, "dummu attribute", e);
793 } catch (std::exception& e) {
794 throw oks::FailedReadObject(this, "dummu attribute", e.what());
795 }
796 }
797
798 // read 'oks-attribute' close tag
799
800 if (read_params.format != 'n')
801 try {
802 const char* eoa_tag_start = read_params.s.get_tag_start();
803
804 if (!oks::cmp_str5(eoa_tag_start, "/attr")) {
805 std::string s("\'/attr\' is expected instead of \'");
806 s += eoa_tag_start;
807 s += '\'';
808 throw std::runtime_error(s.c_str());
809 }
810 } catch (oks::exception& e) {
811 throw oks::FailedRead(std::string("attribute\'s closing tag"), e);
812 } catch (std::exception& e) {
813 throw oks::FailedRead(std::string("attribute\'s closing tag"), e.what());
814 }
815
816 } // end of "read attribute"
817
818 // read relationship
819
820 else if (oks::cmp_str3(tag_start, relationship_xml_tag)) {
821 int32_t num = -1; // -1 => no mv-data read
822 OksRelationship* r(nullptr);
823 OksXmlRelValue value(read_params);
824
825 // read 'oks-relationship' tag attributes
826
827 try {
828 while (true) {
829 OksXmlAttribute attr(read_params.s);
830
831 // check for close of tag
832
833 if (oks::cmp_str1(attr.name(), ">") || (read_params.format == 'n' && oks::cmp_str1(attr.name(), "/"))) {
834 break;
835 }
836
837 // check for known oks-relationship' attributes
838
839 else if (oks::cmp_str4(attr.name(), name_xml_attribute)) {
840 if (__builtin_expect((c != nullptr), 1)) {
841 i_name.assign(attr.value(), attr.value_len());
842 info_i = c->p_data_info->find(i_name);
843 if (__builtin_expect((info_i == c->p_data_info->end() || info_i->second->relationship == nullptr),
844 0)) {
845 if (non_silent_mode) {
846 std::string msg = std::string("Read object \"") + GetId() + '@' + c->get_name() + '\"';
847 std::lock_guard lock(OksKernel::p_parallel_out_mutex);
848 Oks::warning_msg(msg.c_str())
849 << " skip relationship \"" << attr.value() << "\", which is not defined in the schema\n";
850 }
851 } else {
852 info = info_i->second;
853 r = const_cast<OksRelationship*>(info->relationship);
854 }
855 }
856 continue;
857 } else if (read_params.format == 'n') {
858 if (oks::cmp_str5(attr.name(), class_xml_attribute)) {
859 value.m_class = uid.class_id->get_kernel()->find_class(attr.value());
860 if (__builtin_expect((value.m_class == nullptr && attr.value_len() > 0), 0)) {
861 value.m_class_id = new OksString(attr.value(), attr.value_len());
862 }
863 continue;
864 } else if (oks::cmp_str2(attr.name(), id_xml_attribute)) {
865 value.m_value = read_params.s.get_value(attr.p_value_len);
866 continue;
867 }
868 } else {
869 if (oks::cmp_str3(attr.name(), num_xml_attribute)) {
870 num = static_cast<int32_t>(strtol(attr.value(), &__sanity, 0));
871 if (__builtin_expect((*__sanity != 0 || errno == ERANGE), 0))
873 "strtoul", __sanity, attr.value(), read_params.s.get_line_no(), read_params.s.get_line_pos());
874 continue;
875 }
876 }
877
878 read_params.s.throw_unexpected_attribute(attr.name());
879 }
880 } catch (oks::exception& e) {
881 throw oks::FailedRead("relationship value header", e);
882 } catch (std::exception& e) {
883 throw oks::FailedRead("relationship value header", e.what());
884 }
885
886 if (read_params.format == 'n' && value.is_empty() == true)
887 num = 0;
888
889 // read 'oks-relationship' body
890
891 if (__builtin_expect((r != nullptr), 1)) {
892 OksData* d = &data[info->offset];
893 OksData* dx;
894
895 OksRelationship::CardinalityConstraint cc = r->get_high_cardinality_constraint();
896
897 if (__builtin_expect((check_re_read), 0)) {
898 dx = &dd;
899 read_relationships->remove(r);
900 } else {
901 dx = d;
902 }
903
904 try {
905 if (num == -1) {
906 if (cc == OksRelationship::Many) {
907 __report_cardinality_cvt_warning(read_params, *r);
908 OksRelationship dummy(*r);
909 OksData d2;
910 if (read_params.format == 'n')
911 d2.read(&dummy, value);
912 else
913 d2.read(read_params, &dummy);
914 d2.ConvertTo(dx, r);
915 } else {
916 if (read_params.format == 'n')
917 dx->read(r, value);
918 else
919 dx->read(read_params, r);
920 }
921 } else {
922 if (cc != OksRelationship::Many) {
923 __report_cardinality_cvt_warning(read_params, *r);
924 OksRelationship dummy(*r);
925 OksData d2;
926 if (read_params.format == 'n')
927 d2.read(&dummy, read_params);
928 else
929 d2.read(read_params, &dummy, num);
930 d2.ConvertTo(dx, r);
931 } else {
932 if (read_params.format == 'n')
933 dx->read(r, read_params);
934 else
935 dx->read(read_params, r, num);
936 }
937 }
938 } catch (oks::exception& e) {
939 throw oks::FailedReadObject(this, std::string("relationship \"") + r->get_name() + '\"', e);
940 } catch (std::exception& e) {
941 throw oks::FailedReadObject(this, std::string("relationship \"") + r->get_name() + '\"', e.what());
942 }
943
944 if (check_re_read) {
945 if (*dx != *d) {
946 was_updated = true;
947 *d = *dx;
948 }
949 dd.Clear();
950 }
951 } else {
952 OksRelationship r("_ _ *** dummy *** _ _"); // temporal relationship to use right OksData constructor call
953
954 try {
955 if (num == -1) {
956 if (read_params.format != 'n')
957 OksData(read_params, &r);
958 } else {
959 if (read_params.format == 'n')
960 OksData(&r, read_params);
961 else
962 OksData(read_params, &r, num);
963 }
964 } catch (oks::exception& e) {
965 throw oks::FailedReadObject(this, "dummu relationship", e);
966 } catch (std::exception& e) {
967 throw oks::FailedReadObject(this, "dummu relationship", e.what());
968 }
969 }
970
971 // read 'oks-relationship' close tag
972
973 if (read_params.format != 'n')
974 try {
975 const char* eor_tag_start = read_params.s.get_tag_start();
976
977 if (!oks::cmp_str4(eor_tag_start, "/rel")) {
978 std::string s("\'/rel\' is expected instead of \'");
979 s += eor_tag_start;
980 s += '\'';
981 throw std::runtime_error(s.c_str());
982 }
983 } catch (oks::exception& e) {
984 throw oks::FailedRead(std::string("relationship\'s closing tag"), e);
985 } catch (std::exception& e) {
986 throw oks::FailedRead(std::string("relationship\'s closing tag"), e.what());
987 }
988
989 } // end of "read relationship"
990
991 }
992
993 catch (oks::exception& e) {
994 throw oks::FailedRead(std::string("object \"") + uid.object_id + '@' + c->get_name() + '\"', e);
995 } catch (std::exception& e) {
996 throw oks::FailedRead(std::string("object \"") + uid.object_id + '@' + c->get_name() + '\"', e.what());
997 }
998
999 // check that unread attributes & relationships have default values
1000
1001 if (__builtin_expect((check_re_read), 0)) {
1002 if (read_attributes) {
1003 if (!read_attributes->empty()) {
1004 for (auto i = read_attributes->begin(); i != read_attributes->end(); i = read_attributes->erase(i)) {
1005 OksData d = (*i)->p_init_data;
1006 try {
1007 OksData* d2(GetAttributeValue((*i)->get_name()));
1008 if (*d2 != d) {
1009 *d2 = d;
1010 was_updated = true;
1011 }
1012 } catch (oks::exception& ex) {
1013 throw oks::ObjectInitError(
1014 this, std::string("cannot reset default value of attribute \"") + (*i)->get_name() + '\"', ex);
1015 }
1016 }
1017 }
1018
1019 delete read_attributes;
1020 }
1021
1022 if (read_relationships) {
1023 if (!read_relationships->empty()) {
1024 for (auto i = read_relationships->begin(); i != read_relationships->end(); i = read_relationships->erase(i)) {
1025 OksData d;
1026 d.ReadFrom(*i);
1027 try {
1028 OksData* d2(GetRelationshipValue((*i)->get_name()));
1029 if (d2 && *d2 != d) {
1030 *d2 = d;
1031 was_updated = true;
1032 }
1033 } catch (oks::exception& ex) {
1034 throw oks::ObjectInitError(
1035 this, std::string("cannot reset value of relationship \"") + (*i)->get_name() + '\"', ex);
1036 }
1037 }
1038 }
1039
1040 delete read_relationships;
1041 }
1042 }
1043 } else {
1044 size_t count(0);
1045
1046 if (c == 0) {
1047 throw std::runtime_error(" ***** Can't read objects of undefined class *****\n"
1048 " ***** from file saved in non-extended format. *****\n"
1049 " ***** Fix the problem first. Processing terminated. *****\n");
1050 }
1051
1052 if (c->p_all_attributes) {
1053 for (const auto& i : *c->p_all_attributes) {
1054 if (check_re_read) {
1055 OksData d;
1056
1057 if (i->get_is_multi_values()) {
1058 d.read(read_params, i, __get_num(read_params));
1059 } else {
1060 d.read(read_params, i);
1061 }
1062
1063 if (d != data[count]) {
1064 data[count] = d;
1065 was_updated = true;
1066 }
1067 } else {
1068 if (i->get_is_multi_values()) {
1069 data[count].read(read_params, i, __get_num(read_params));
1070 } else {
1071 data[count].read(read_params, i);
1072 }
1073 }
1074
1075 count++;
1076 }
1077 }
1078
1079 if (c->p_all_relationships) {
1080 for (const auto& i : *c->p_all_relationships) {
1081 if (check_re_read) {
1082 OksData d;
1083
1084 if (i->get_high_cardinality_constraint() == OksRelationship::Many) {
1085 d.read(read_params, i, __get_num(read_params));
1086 } else {
1087 d.read(read_params, i);
1088 }
1089
1090 if (d != data[count]) {
1091 data[count] = d;
1092 was_updated = true;
1093 }
1094 } else {
1095 if (i->get_high_cardinality_constraint() == OksRelationship::Many) {
1096 data[count].read(read_params, i, __get_num(read_params));
1097 } else {
1098 data[count].read(read_params, i);
1099 }
1100 }
1101
1102 count++;
1103 }
1104 }
1105
1106 // read tag closing object
1107
1108 try {
1109 const char* tag_start = read_params.s.get_tag_start();
1110
1111 if (*tag_start != '/' || memcmp(tag_start + 1, read_params.object_tag, read_params.object_tag_len)) {
1112 std::ostringstream s;
1113 s << "Failed to read obj close tag (\'/" << read_params.object_tag << "\' is expected)";
1114 throw std::runtime_error(s.str().c_str());
1115 }
1116 } catch (oks::exception& e) {
1117 throw oks::FailedRead("object close tag", e);
1118 } catch (std::exception& e) {
1119 throw oks::FailedRead("object close tag", e.what());
1120 }
1121 }
1122
1123 if (was_updated)
1124 change_notify();
1125}
OksData::Type get_data_type() const noexcept
OksKernel * get_kernel() const noexcept
Definition class.hpp:348
void __report_type_cvt_warning(const oks::ReadFileParams &, const OksAttribute &, const OksData &, const OksData::Type, int32_t) const
Definition object.cpp:436
void __report_cardinality_cvt_warning(const oks::ReadFileParams &, const OksRelationship &) const
Definition object.cpp:510
int32_t __get_num(const oks::ReadFileParams &params)
Definition object.cpp:530
static const char num_xml_attribute[]
Definition object.hpp:1806
OksString()
to deallocate memory when destroyed
Definition object.hpp:421
bool cmp_str4(const char *s1, const char s2[5])
Definition cstring.hpp:45
static void __throw_unknown_type(const oks::ReadFileParams &params, const char *atype)
Definition object.cpp:522
bool cmp_str3(const char *s1, const char s2[4])
Definition cstring.hpp:33
void read(const oks::ReadFileParams &, const OksAttribute *, int32_t)
private methods which can be used by OksObject class only

◆ references()

void dunedaq::oks::OksObject::references ( OksObject::FSet & refs,
unsigned long recursion_depth,
bool add_self = false,
oks::ClassSet * classes = 0 ) const

The method puts to set objects recursively referenced by given object.

Definition at line 3043 of file object.cpp.

3044{
3045 struct RefData data(refs, classes);
3046
3047 std::lock_guard lock(uid.class_id->p_kernel->p_objects_refs_mutex);
3048
3049 OksObject::FSet tested_objs;
3050
3051 if (add_self) {
3052 insert2refs(this, recursion_depth + 1, data);
3053 }
3054
3055 _references(this, recursion_depth, data);
3056
3057 TLOG_DEBUG(2) << "OksObject::references(" << this << ", " << recursion_depth << ") returns " << refs.size()
3058 << " objects";
3059}
std::mutex p_objects_refs_mutex
Definition kernel.hpp:1967
std::unordered_set< OksObject *, oks::hash_obj_ptr, oks::equal_obj_ptr > FSet
Definition object.hpp:1171
static void _references(const OksObject *obj, unsigned long recursion_depth, RefData &data)
Definition object.cpp:3012
static void insert2refs(const OksObject *o, unsigned long recursion_depth, RefData &data)
Definition object.cpp:2993

◆ remove_RCR()

void dunedaq::oks::OksObject::remove_RCR ( OksObject * o,
const OksRelationship * r )
noexcept

Definition at line 2528 of file object.cpp.

2529{
2530 TLOG_DEBUG(4) << "object " << this << " removes RCR from object " << o << " through " << r->get_name();
2531
2532 if (r->get_is_composite() == false || !p_rcr)
2533 return;
2534
2535 for (std::list<OksRCR*>::iterator i = p_rcr->begin(); i != p_rcr->end(); ++i) {
2536 OksRCR* rcr = *i;
2537
2538 if (rcr->obj == o && rcr->relationship == r) {
2539 p_rcr->erase(i);
2540 delete rcr;
2541 break;
2542 }
2543 }
2544
2545 if (p_rcr->empty()) {
2546 delete p_rcr;
2547 p_rcr = nullptr;
2548 }
2549}

◆ RemoveRelationshipValue() [1/3]

void dunedaq::oks::OksObject::RemoveRelationshipValue ( const OksDataInfo * data_info,
OksObject * object )

Remove object value from multi-value relationship by offset.

In case of problems (e.g. relationship is single-value or there is no such object) the oks::exception is thrown.

The parameters are:

Parameters
data_infodescribes offset of relationship's value for given OKS class
objectthe object to be removed from relationship
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 2280 of file object.cpp.

2281{
2282 const OksRelationship* r = odi->relationship;
2283
2284 if (!object) {
2285 throw oks::ObjectSetError(this, true, r->get_name(), "cannot remove (null) object");
2286 }
2287
2288 if (r->get_high_cardinality_constraint() != OksRelationship::Many) {
2289 std::ostringstream text;
2290 text << "cannot remove object " << object << " since the relationship has no \'many\' high cardinality constraint";
2291 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2292 }
2293
2294 OksData d(object);
2295 size_t offset = odi->offset;
2297
2298 for (OksData::List::iterator i = list->begin(); i != list->end();) {
2299 OksData* d2 = *i;
2300 if (cmp_data(d2, &d)) {
2301 check_file_lock(0, r);
2302 object->remove_RCR(this, r);
2303 list->erase(i);
2304 delete d2;
2305 notify();
2306 return;
2307 } else
2308 ++i;
2309 }
2310
2311 std::ostringstream text;
2312 text << "cannot remove object " << object << " since the relationship\'s value has no such object";
2313 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2314}
static bool cmp_data(OksData *d, OksData *d2)
Definition object.cpp:2197

◆ RemoveRelationshipValue() [2/3]

void dunedaq::oks::OksObject::RemoveRelationshipValue ( const std::string & name,
OksObject * object )

Remove object value from multi-value relationship by name.

In case of problems (e.g. no relationship with such name, relationship is single-value or there is no such object) the oks::exception is thrown.

The parameters are:

Parameters
namename of relationship
objectthe object to be removed from relationship
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 2317 of file object.cpp.

2318{
2319 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2320
2321 if (i == uid.class_id->p_data_info->end()) {
2322 std::ostringstream text;
2323 text << "object " << this << " has no relationship \"" << name << '\"';
2324 throw oks::ObjectSetError(this, true, name, text.str());
2325 }
2326
2327 RemoveRelationshipValue(i->second, object);
2328}
void RemoveRelationshipValue(const std::string &name, OksObject *object)
Remove object value from multi-value relationship by name.
Definition object.cpp:2317

◆ RemoveRelationshipValue() [3/3]

void dunedaq::oks::OksObject::RemoveRelationshipValue ( const std::string & rel_name,
const std::string & class_name,
const std::string & object_i )

Remove class-name and object-id value from multi-value relationship by name.

In case of problems (e.g. no relationship with such name, no such object) the oks::exception is thrown.

The parameters are:

Parameters
rel_namename of relationship
class_nameclass name of the referenced object
object_idID of the referenced object
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 2453 of file object.cpp.

2454{
2455 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2456
2457 if (i == uid.class_id->p_data_info->end()) {
2458 std::ostringstream text;
2459 text << "object " << this << " has no relationship \"" << name << '\"';
2460 throw oks::ObjectSetError(this, true, name, text.str());
2461 }
2462
2463 OksDataInfo* odi = i->second;
2464 const OksRelationship* r = odi->relationship;
2465
2466 if (object_id.empty() || class_id.empty()) {
2467 throw oks::ObjectSetError(this, true, r->get_name(), "cannot remove (null) object");
2468 }
2469
2470 if (r->get_high_cardinality_constraint() != OksRelationship::Many) {
2471 std::ostringstream text;
2472 text << "cannot remove object \"" << object_id << '@' << class_id
2473 << "\" since the relationship has no \'many\' high cardinality constraint";
2474 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2475 }
2476
2477 size_t offset = odi->offset;
2478 OksData d(class_id, object_id);
2480
2481 for (OksData::List::iterator j = list->begin(); j != list->end();) {
2482 OksData* d2 = *j;
2483 if (cmp_data(d2, &d)) {
2484 check_file_lock(0, r);
2485 list->erase(j);
2486 delete d2;
2487 notify();
2488 return;
2489 } else
2490 ++j;
2491 }
2492
2493 std::ostringstream text;
2494 text << "cannot remove object \"" << object_id << '@' << class_id
2495 << "\" since the relationship\'s value has no such object";
2496 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2497}

◆ report_dangling_references()

std::string dunedaq::oks::OksObject::report_dangling_references ( ) const

The method returns string containing dangling references for given object.

Definition at line 2888 of file object.cpp.

2889{
2890 unsigned short l1 = GetClass()->number_of_all_attributes();
2891 unsigned short l2 = l1 + GetClass()->number_of_all_relationships();
2892
2893 std::list<OksRelationship*>::const_iterator ri = GetClass()->all_relationships()->begin();
2894
2895 std::string result;
2896
2897 while (l1 < l2) {
2898 OksDataInfo odi(l1, *ri);
2900
2901 if (d->type == OksData::list_type) {
2902 for (OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
2903 test_dangling_references(this, **li, **ri, result);
2904 }
2905 } else {
2906 test_dangling_references(this, *d, **ri, result);
2907 }
2908
2909 ++l1;
2910 ++ri;
2911 }
2912
2913 return result;
2914}
static void test_dangling_references(const OksObject *obj, const OksData &d, const OksRelationship &r, std::string &result)
Definition object.cpp:2872

◆ reverse_composite_rels()

const std::list< OksRCR * > * dunedaq::oks::OksObject::reverse_composite_rels ( ) const
inline

Return information about composite parents. The method returns list of the OKS object's reverse composite relationships.

Definition at line 1589 of file object.hpp.

1589{ return p_rcr; }

◆ satisfies()

bool dunedaq::oks::OksObject::satisfies ( const OksObject * goal,
const oks::QueryPathExpression & expresssion,
OksObject::List & path ) const

Definition at line 936 of file query.cpp.

937{
938 // check the object is not in the path
939
940 {
941 for (std::list<OksObject*>::const_iterator i = path.begin(); i != path.end(); ++i) {
942 if (*i == this)
943 return false;
944 }
945 }
946
947 path.push_back(const_cast<OksObject*>(this));
948
949 for (std::list<std::string>::const_iterator i = expression.get_rel_names().begin();
950 i != expression.get_rel_names().end();
951 ++i) {
952 OksData* d = 0;
953
954 if (!(*i).empty() && (*i)[0] == '?') {
955 std::string nm = (*i).substr(1);
956 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(nm);
957
958 if (i != uid.class_id->p_data_info->end()) {
959 d = GetRelationshipValue((*i).second);
960 } else {
961 continue;
962 }
963 } else {
964 try {
966 } catch (oks::exception& ex) {
967 Oks::error_msg("OksObject::satisfies") << ex.what() << std::endl;
968 continue;
969 }
970 }
971
972 // check if given relationship points to destination object
973
974 if (d->type == OksData::object_type && d->data.OBJECT == goal)
975 return true;
976 else if (d->type == OksData::list_type && d->data.LIST) {
977 for (OksData::List::iterator i2 = d->data.LIST->begin(); i2 != d->data.LIST->end(); ++i2) {
978 OksData* d2 = (*i2);
979 if (d2->type == OksData::object_type && d2->data.OBJECT == goal)
980 return true;
981 }
982 }
983
984 // go to next path, if there are no more expressions
985
986 if (!expression.get_next()) {
987 continue;
988 }
989
990 // check, if there is need for nested path lookup
991
992 else if (expression.get_use_nested_lookup()) {
993
994 // go directly
995
996 path.pop_back();
997 if (satisfies(goal, *expression.get_next(), path) == true)
998 return true;
999 path.push_back(const_cast<OksObject*>(this));
1000
1001 // go nested
1002
1003 if (d->type == OksData::object_type && d->data.OBJECT) {
1004 if (d->data.OBJECT->satisfies(goal, expression, path) == true)
1005 return true;
1006 } else if (d->type == OksData::list_type && d->data.LIST) {
1007 for (OksData::List::iterator i2 = d->data.LIST->begin(); i2 != d->data.LIST->end(); ++i2) {
1008 OksData* d2 = (*i2);
1009 if (d2->type == OksData::object_type && d2->data.OBJECT) {
1010 if (d2->data.OBJECT->satisfies(goal, expression, path) == true)
1011 return true;
1012 }
1013 }
1014 }
1015 }
1016
1017 else {
1018 if (d->type == OksData::object_type && d->data.OBJECT) {
1019 if (d->data.OBJECT->satisfies(goal, *expression.get_next(), path) == true)
1020 return true;
1021 } else if (d->type == OksData::list_type && d->data.LIST) {
1022 for (OksData::List::iterator i2 = d->data.LIST->begin(); i2 != d->data.LIST->end(); ++i2) {
1023 OksData* d2 = (*i2);
1024 if (d2->type == OksData::object_type && d2->data.OBJECT) {
1025 if (d2->data.OBJECT->satisfies(goal, *expression.get_next(), path) == true)
1026 return true;
1027 }
1028 }
1029 }
1030 }
1031 }
1032
1033 path.pop_back();
1034 return false;
1035}

◆ SatisfiesQueryExpression()

bool dunedaq::oks::OksObject::SatisfiesQueryExpression ( OksQueryExpression * query_exp) const

Check if object satisfies query expression.

The method parses query expression structures and applies them to the object's values. In case of incorrect query expression parameter the method throws exception.

Parameters
query_expthe query expression
Returns
true, if object satisfies given query expression.
Exceptions
std::exceptionis thrown in case of problems.

Definition at line 619 of file query.cpp.

620{
622
623 if (!qe) {
624 throw std::runtime_error("cannot execute nil query");
625 }
626
627 switch (qe->type()) {
629 OksComparator* cmp = (OksComparator*)qe;
630 const OksAttribute* a = cmp->attribute;
631 OksQuery::Comparator f = cmp->m_comp_f;
632
633 if (!a && !cmp->value) {
634 throw std::runtime_error("cannot execute query for nil attribute");
635 } else if (!f) {
636 throw std::runtime_error("cannot execute query for nil compare function");
637 }
638
639 const OksData* cmp_value(cmp->value);
640
641 if (f == OksQuery::reg_exp_cmp) {
642 if (!cmp->m_reg_exp) {
643 try {
644 std::string s(cmp->value->str());
645 cmp->m_reg_exp = new boost::regex(s.c_str());
646 } catch (std::exception& ex) {
647 throw oks::BadReqExp(cmp->value->str(), ex.what());
648 }
649 }
650 cmp_value = reinterpret_cast<const OksData*>(cmp->m_reg_exp);
651 }
652
653 if (!a) {
654 OksData d(GetId());
655 return (*f)(&d, cmp_value);
656 }
657
658 return (*f)(&(data[(*(uid.class_id->p_data_info->find(a->get_name()))).second->offset]), cmp_value);
659 }
660
662 if (!((OksRelationshipExpression*)qe)->relationship) {
663 throw std::runtime_error("cannot execute query for nil relationship");
664 } else {
665 OksData* d =
666 &data[((*(uid.class_id->p_data_info->find(((OksRelationshipExpression*)qe)->relationship->get_name())))
667 .second)
668 ->offset];
669
670 if (((OksRelationshipExpression*)qe)->relationship->get_high_cardinality_constraint() ==
672 if (!d->data.LIST || d->data.LIST->empty())
673 return false;
674
675 for (OksData::List::iterator i = d->data.LIST->begin(); i != d->data.LIST->end(); ++i) {
676 OksData* d2 = (*i);
677
678 if (d2->type == OksData::uid2_type) {
679 std::ostringstream text;
680 text << "cannot process relationship expression: object \"" << *d2->data.UID2.object_id << '@'
681 << *d2->data.UID2.class_id << "\" referenced through multi values relationship \""
682 << ((OksRelationshipExpression*)qe)->relationship->get_name() << "\" is not loaded in memory";
683 throw std::runtime_error(text.str().c_str());
684 }
685
686 if (((OksRelationshipExpression*)qe)->checkAllObjects == true) {
687 if (!d2->data.OBJECT ||
688 d2->data.OBJECT->SatisfiesQueryExpression(((OksRelationshipExpression*)qe)->p_expression) == false)
689 return false;
690 } else {
691 if (d2->data.OBJECT &&
692 d2->data.OBJECT->SatisfiesQueryExpression(((OksRelationshipExpression*)qe)->p_expression) == true)
693 return true;
694 }
695 }
696
697 return (((OksRelationshipExpression*)qe)->checkAllObjects == true) ? true : false;
698 } else {
699 if (d->type != OksData::object_type) {
700 std::ostringstream text;
701 text << "cannot process relationship expression: object \"" << *d
702 << "\" referenced through single value relationship \""
703 << ((OksRelationshipExpression*)qe)->relationship->get_name() << "\" is not loaded in memory";
704 throw std::runtime_error(text.str().c_str());
705 }
706
707 return (d->data.OBJECT
708 ? d->data.OBJECT->SatisfiesQueryExpression(((OksRelationshipExpression*)qe)->p_expression)
709 : false);
710 }
711 }
712
714 if (!((OksNotExpression*)qe)->p_expression) {
715 throw std::runtime_error("cannot process \'not\' expression: referenced query expression is nil");
716 }
717
718 return (SatisfiesQueryExpression(((OksNotExpression*)qe)->p_expression) ? false : true);
719
721 if (((OksAndExpression*)qe)->p_expressions.size() < 2) {
722 std::ostringstream text;
723 text << "cannot process \'and\' expression for " << ((OksAndExpression*)qe)->p_expressions.size()
724 << " argument (two or more arguments are required)";
725 throw std::runtime_error(text.str().c_str());
726 } else {
727 std::list<OksQueryExpression*>& elist = ((OksAndExpression*)qe)->p_expressions;
728
729 for (std::list<OksQueryExpression*>::iterator i = elist.begin(); i != elist.end(); ++i)
730 if (SatisfiesQueryExpression(*i) == false)
731 return false;
732
733 return true;
734 }
735
737 if (((OksOrExpression*)qe)->p_expressions.size() < 2) {
738 std::ostringstream text;
739 text << "cannot process \'or\' expression for " << ((OksAndExpression*)qe)->p_expressions.size()
740 << " argument (two or more arguments are required)";
741 throw std::runtime_error(text.str().c_str());
742 } else {
743 std::list<OksQueryExpression*>& elist = ((OksOrExpression*)qe)->p_expressions;
744
745 for (std::list<OksQueryExpression*>::iterator i = elist.begin(); i != elist.end(); ++i)
746 if (SatisfiesQueryExpression(*i) == true)
747 return true;
748
749 return false;
750 }
751
752 default: {
753 std::ostringstream text;
754 text << "unexpected query type " << (int)(qe->type());
755 throw std::runtime_error(text.str().c_str());
756 }
757 }
758}
bool SatisfiesQueryExpression(OksQueryExpression *query_exp) const
Check if object satisfies query expression.
Definition query.cpp:619
static bool reg_exp_cmp(const OksData *, const OksData *regexp)
Definition query.cpp:86
bool(*) Comparator(const OksData *, const OksData *)
Definition query.hpp:95

◆ set_file()

void dunedaq::oks::OksObject::set_file ( OksFile * file,
bool update_owner = true )

Move object to different file.

Move object to an existing file. Both, present file where object is stored and new destination file have to be writable by user.

The parameters are:

Parameters
filedestination file
update_ownermark original file as updated
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 1468 of file object.cpp.

1469{
1470 if (file != f) {
1471 try {
1472 if (update_owner) {
1473 file->lock();
1474 file->set_updated();
1475 }
1476
1477 f->lock();
1478 f->set_updated();
1479
1480 file = f;
1481 } catch (oks::exception& ex) {
1482 throw oks::CanNotSetFile(0, this, *f, ex);
1483 }
1484 }
1485}

◆ set_id()

void dunedaq::oks::OksObject::set_id ( const std::string & id)

Set object ID.

The ID has to be unique in scope of object's class and all classes participating in inheritance hierarchy of this class.

Parameters
idnew identity of the object In case of problems the oks::exception is thrown.

Definition at line 1488 of file object.cpp.

1489{
1490 if (new_id == uid.object_id)
1491 return;
1492
1493 try {
1494 oks::validate_not_empty(new_id, "object id");
1495 } catch (std::exception& ex) {
1496 throw oks::FailedRenameObject(this, ex.what());
1497 }
1498
1499 OksClass* c = const_cast<OksClass*>(uid.class_id);
1500
1501 if (c->get_object(new_id)) {
1502 throw oks::FailedRenameObject(this, "the object with such identity already exists");
1503 }
1504
1505 // build set of updated files and list of updated objects
1506
1507 std::set<OksFile*> updated_files;
1508 std::list<OksObject*> updated_objects;
1509
1510 updated_files.insert(file);
1511 updated_objects.push_back(this);
1512
1513 const OksClass::Map& classes = GetClass()->get_kernel()->classes();
1514
1515 for (OksClass::Map::const_iterator i = classes.begin(); i != classes.end(); ++i) {
1516 const OksClass* c(i->second);
1517 const OksObject::Map* objs = c->objects();
1518 size_t d_end = c->p_instance_size;
1519 size_t d_begin = c->p_all_attributes->size();
1520 if (objs && (d_end != d_begin)) {
1521 for (OksObject::Map::const_iterator j = objs->begin(); j != objs->end(); ++j) {
1522 OksObject* o(j->second);
1523
1524 // avoid multiple notification, when renamed object contains references to self
1525 if (o != this) {
1526 for (size_t k = d_begin; k != d_end && o; ++k) {
1527 const OksData& d = o->data[k];
1528 if (d.type == OksData::object_type && d.data.OBJECT == this) {
1529 updated_objects.push_back(o);
1530 updated_files.insert(o->file);
1531 o = nullptr; // break loop
1532 } else if (d.type == OksData::list_type && d.data.LIST) {
1533 const OksData::List& list = *d.data.LIST;
1534 for (OksData::List::const_iterator l = list.begin(); l != list.end(); ++l) {
1535 OksData* d2 = *l;
1536 if (d2->type == OksData::object_type && d2->data.OBJECT == this) {
1537 updated_objects.push_back(o);
1538 updated_files.insert(o->file);
1539 o = nullptr; // break loop
1540 break;
1541 }
1542 }
1543 }
1544 }
1545 }
1546 }
1547 }
1548 }
1549
1550 try {
1551 for (std::set<OksFile*>::const_iterator i = updated_files.begin(); i != updated_files.end(); ++i) {
1552 (*i)->lock();
1553 }
1554 } catch (oks::exception& ex) {
1555 throw oks::FailedRenameObject(this, ex);
1556 }
1557
1558 try {
1559 c->remove(this); // remove object from hash table
1560 uid.object_id = new_id; // change id
1561 c->add(this); // add object to hash table
1562 } catch (oks::exception& ex) {
1563 throw oks::FailedRenameObject(this, ex);
1564 }
1565
1566 for (std::set<OksFile*>::const_iterator i = updated_files.begin(); i != updated_files.end(); ++i) {
1567 (*i)->set_updated();
1568 }
1569
1570 if (get_change_notify()) {
1571 for (std::list<OksObject*>::const_iterator i = updated_objects.begin(); i != updated_objects.end(); ++i) {
1572 (*i)->change_notify();
1573 }
1574 }
1575}
const OksClass::Map & classes() const
Get classes.
Definition kernel.hpp:1711
notify_obj get_change_notify() const
Definition object.cpp:2793

◆ set_int32_id()

void dunedaq::oks::OksObject::set_int32_id ( int32_t object_id)
inline

Set object id is used to assign an object unique integer number. Such data are not stored on file and only exist while OksKernel object is not destroyed.

Definition at line 1628 of file object.hpp.

1628{ p_int32_id = object_id; }

◆ set_unique_id()

void dunedaq::oks::OksObject::set_unique_id ( )
private

Definition at line 151 of file object.cpp.

152{
154
155 p_duplicated_object_id_idx = uid.object_id.size();
156
157 std::lock_guard lock(uid.class_id->p_unique_id_mutex);
158
159 std::unique_ptr<char[]> unique_id(new char[p_duplicated_object_id_idx + 16]);
160
161 for (unsigned long i = 0; i < 0xFFFFFFFF; ++i) {
162 sprintf(unique_id.get(), "%s^%lu", uid.object_id.c_str(), i);
163 std::string id(unique_id.get());
164 if (uid.class_id->get_object(id) == nullptr) {
165 uid.object_id = id;
166 return;
167 }
168 }
169}
OksObject * get_object(const std::string &id) const noexcept
Get object by ID.
Definition class.cpp:1479
FELIX Initialization std::string initerror FELIX queue timed std::string queuename Unexpected chunk size

◆ SetAttributeValue() [1/2]

void dunedaq::oks::OksObject::SetAttributeValue ( const OksDataInfo * data_info,
OksData * data )

Set value of attribute by offset.

It the type of data do not match to the defined by the attribute of object's class, then the method tries to convert them and to print out warning message.

In case of problems (e.g. data are out of range) the oks::exception is thrown.

The parameters are:

Parameters
data_infodescribes offset of attribute's value for given OKS class
datanew attribute value
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 1866 of file object.cpp.

1867{
1868 size_t offset = odi->offset;
1869 const OksAttribute* a = odi->attribute;
1870 OksData d2; // can be needed by type conversion
1871
1872 if (data[offset].type != d->type) {
1873 if (uid.class_id->get_kernel()->get_silence_mode() == false) {
1874 Oks::warning_msg("OksObject::SetAttributeValue(const OksDataInfo *, OksData *)")
1875 << " * ODI attribute name: \'" << a->get_name()
1876 << "\'\n"
1877 " * ODI data offset: \'"
1878 << offset
1879 << "\'\n"
1880 " * OKS data (new): \'"
1881 << *d << "\' type: " << (int)d->type
1882 << "\n"
1883 " * OKS data (old): \'"
1884 << data[offset] << "\' type: " << (int)data[offset].type
1885 << "\n"
1886 " Object "
1887 << this
1888 << ":\n"
1889 " Convert attribute \""
1890 << a->get_name() << "\" value since the OksData::type is invalid\n";
1891 }
1892
1893 d->cvt(&d2, a);
1894 d = &d2;
1895 }
1896
1897 try {
1898 d->check_range(a);
1899 } catch (oks::AttributeReadError& ex) {
1900 throw oks::ObjectSetError(this, false, a->get_name(), ex);
1901 } catch (oks::AttributeRangeError& ex) {
1902 throw oks::ObjectSetError(this, false, a->get_name(), ex);
1903 }
1904
1905 check_file_lock(a, 0);
1906
1907 // set value and update index if any
1908
1909 {
1910 OksIndex* i = nullptr;
1911
1912 if (uid.class_id->p_indices) {
1913 OksIndex::Map::iterator j = uid.class_id->p_indices->find(a);
1914 if (j != uid.class_id->p_indices->end()) {
1915 i = j->second;
1916 }
1917 }
1918
1919 if (i)
1920 i->remove_obj(this);
1921 data[offset] = *d;
1922 if (i)
1923 i->insert(this);
1924 }
1925
1926 notify();
1927}
OksIndex::Map * p_indices
Definition class.hpp:906
bool get_silence_mode() const
Get status of silence mode. The method returns true, if the silence mode is switched 'On'....
Definition kernel.hpp:719
friend class OksIndex
Definition object.hpp:1148
enum dunedaq::oks::OksData::Type type

◆ SetAttributeValue() [2/2]

void dunedaq::oks::OksObject::SetAttributeValue ( const std::string & name,
OksData * data )

Set value of attribute by name.

It the type of data do not match to the defined by the attribute of object's class, then the method tries to convert them and to print out warning message.

In case of problems (e.g. no attribute with such name, data are out of range) the oks::exception is thrown.

The parameters are:

Parameters
namename of attribute
datanew attribute value
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 1930 of file object.cpp.

1931{
1932 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
1933
1934 if (i == uid.class_id->p_data_info->end()) {
1935 std::ostringstream text;
1936 text << "object " << this << " has no attribute \"" << name << '\"';
1937 throw oks::ObjectSetError(this, false, name, text.str());
1938 }
1939
1940 SetAttributeValue(i->second, d);
1941}
void SetAttributeValue(const std::string &name, OksData *data)
Set value of attribute by name.
Definition object.cpp:1930

◆ SetRelationshipValue() [1/5]

void dunedaq::oks::OksObject::SetRelationshipValue ( const OksDataInfo * data_info,
OksData * data,
bool skip_non_null_check = false )

Set value of relationship by offset.

In case of problems (e.g. wrong class type or cardinality constraint) the oks::exception is thrown.

The parameters are:

Parameters
data_infodescribes offset of relationship's value for given OKS class
datanew relationship value
skip_non_null_checkif true, ignore low cardinality constraint
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 1996 of file object.cpp.

1997{
1998 const OksRelationship* r = odi->relationship;
1999 size_t offset = odi->offset;
2000
2001 if ((data[offset].type != d->type) &&
2002 ((d->type == OksData::list_type) || (data[offset].type == OksData::list_type))) {
2003 std::ostringstream text;
2004 text << "OKS data type is invalid: must be "
2005 << (data[offset].type == OksData::object_type ? "an object)\n" : "a list); ") << "offset: " << offset
2006 << "; new: \'" << *d << "\'; old:" << data[offset] << '\'';
2007 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2008 }
2009
2010 // used to update RCRs
2011
2012 OksObject::FSet added_objs;
2013 OksObject::FSet removed_objs;
2014
2015 if (d->type == OksData::object_type) {
2016 OksObject* add_obj = d->data.OBJECT;
2018
2019 if (add_obj != rm_obj) {
2020 if (add_obj)
2021 added_objs.insert(add_obj);
2022 if (rm_obj)
2023 removed_objs.insert(rm_obj);
2024 } else {
2025 return; // new and old values are equal, nothing to do
2026 }
2027
2028 if (skip_non_null_check == false)
2029 check_non_null(r, d->data.OBJECT);
2030 check_class_type(r, d->data.OBJECT);
2031 } else if (d->type == OksData::list_type && d->data.LIST) {
2032 if (d->data.LIST->empty()) {
2033 if (r->get_low_cardinality_constraint() != OksRelationship::Zero && skip_non_null_check == false) {
2034 throw oks::ObjectSetError(
2035 this,
2036 true,
2037 r->get_name(),
2038 "set to empty list is not allowed since the relationship has non-zero low cardinality constraint");
2039 }
2040 }
2041
2042 for (const auto& i : *d->data.LIST) {
2043 if (i->type != OksData::object_type && i->type != OksData::uid2_type && i->type != OksData::uid_type) {
2044 throw oks::ObjectSetError(this, true, r->get_name(), "list contains non-objects");
2045 }
2046
2047 if ((i->type == OksData::object_type && !i->data.OBJECT) ||
2048 (i->type == OksData::uid2_type && !i->data.UID2.object_id) ||
2049 (i->type == OksData::uid_type && !i->data.UID.object_id)) {
2050 throw oks::ObjectSetError(this, true, r->get_name(), "list contains (null) object");
2051 }
2052
2053 if (i->type == OksData::object_type) {
2054 if (OksObject* o2 = i->data.OBJECT) {
2055 check_class_type(r, o2);
2056 added_objs.insert(o2);
2057 }
2058 }
2059 }
2060 } else {
2061 throw oks::ObjectSetError(
2062 this, true, r->get_name(), "the OKS data type is invalid (must be a list of objects or an object)");
2063 }
2064
2065 check_file_lock(0, r);
2066
2067 // put old value to objects removed from relationship
2068
2069 if (data[offset].type == OksData::list_type && data[offset].data.LIST) {
2070 for (const auto& i : *data[offset].data.LIST) {
2071 if (i->type == OksData::object_type && i->data.OBJECT) {
2072 removed_objs.insert(i->data.OBJECT);
2073 }
2074 }
2075 }
2076
2077 // remove RCRs
2078
2079 for (const auto& i : removed_objs) {
2080 if (added_objs.find(i) == added_objs.end()) {
2081 TLOG_DEBUG(4) << "object " << i << " was removed from relationship";
2082 i->remove_RCR(this, r);
2083 }
2084 }
2085
2086 // add RCRs
2087
2088 for (OksObject::FSet::const_iterator i = added_objs.begin(); i != added_objs.end(); ++i) {
2089 OksObject* add_obj = *i;
2090 if (removed_objs.find(add_obj) == removed_objs.end()) {
2091 TLOG_DEBUG(4) << "object " << add_obj << " was added to relationship";
2092 try {
2093 add_obj->add_RCR(this, r);
2094 } catch (oks::exception& ex) {
2095
2096 // reset updated RCRs
2097
2098 for (OksObject::FSet::const_iterator j = added_objs.begin(); j != i; ++j) {
2099 if (removed_objs.find(*j) == removed_objs.end()) {
2100 (*j)->remove_RCR(this, r);
2101 }
2102 }
2103
2104 for (OksObject::FSet::const_iterator j = removed_objs.begin(); j != removed_objs.end(); ++j) {
2105 if (added_objs.find(*j) == added_objs.end()) {
2106 try {
2107 (*j)->add_RCR(this, r);
2108 } catch (oks::exception&) {
2109 ;
2110 }
2111 }
2112 }
2113
2114 throw oks::ObjectSetError(this, true, r->get_name(), ex);
2115 }
2116 }
2117 }
2118
2119 data[offset] = *d;
2120
2121 notify();
2122}
void check_non_null(const OksRelationship *, const OksObject *)
Definition object.cpp:1958

◆ SetRelationshipValue() [2/5]

void dunedaq::oks::OksObject::SetRelationshipValue ( const OksDataInfo * data_info,
OksObject * object )

Set value of single-value relationship by offset.

In case of problems (e.g. wrong class type or relationship is multi-value) the oks::exception is thrown.

The parameters are:

Parameters
data_infodescribes offset of relationship's value for given OKS class
objectnew relationship value
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 2139 of file object.cpp.

2140{
2141 const OksRelationship* r = odi->relationship;
2142 OksData& d(data[odi->offset]);
2143
2144 if (r->get_high_cardinality_constraint() == OksRelationship::Many) {
2145 std::ostringstream text;
2146 text << "cannot set value " << object << " since the relationship has \'many\' high cardinality constraint";
2147 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2148 }
2149
2150 if (!object) {
2151 check_non_null(r, object);
2152 } else {
2153 check_class_type(r, object);
2154 }
2155
2156 check_file_lock(0, r);
2157
2158 if ((d.type == OksData::object_type) && d.data.OBJECT) {
2159 d.data.OBJECT->remove_RCR(this, r);
2160 }
2161
2162 if (object) {
2163 try {
2164 object->add_RCR(this, r);
2165 } catch (oks::exception& ex) {
2166 // restore RCR and throw exception
2167 if ((d.type == OksData::object_type) && d.data.OBJECT)
2168 try {
2169 d.data.OBJECT->add_RCR(this, r);
2170 } catch (oks::exception& ex2) {
2171 ;
2172 }
2173 throw oks::ObjectSetError(this, true, r->get_name(), ex);
2174 }
2175 }
2176
2177 d.Set(object);
2178
2179 notify();
2180}

◆ SetRelationshipValue() [3/5]

void dunedaq::oks::OksObject::SetRelationshipValue ( const std::string & name,
OksData * data,
bool skip_non_null_check = false )

Set value of relationship by name.

In case of problems (e.g. no relationship with such name, wrong class type or cardinality constraint) the oks::exception is thrown.

The parameters are:

Parameters
namename of relationship
datanew relationship value
skip_non_null_checkif true, ignore low cardinality constraint
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 2125 of file object.cpp.

2126{
2127 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2128
2129 if (i == uid.class_id->p_data_info->end()) {
2130 std::ostringstream text;
2131 text << "object " << this << " has no relationship \"" << name << '\"';
2132 throw oks::ObjectSetError(this, true, name, text.str());
2133 }
2134
2135 SetRelationshipValue(i->second, d, skip_non_null_check);
2136}

◆ SetRelationshipValue() [4/5]

void dunedaq::oks::OksObject::SetRelationshipValue ( const std::string & name,
OksObject * object )

Set value of single-value relationship by name.

In case of problems (e.g. no relationship with such name, wrong class type or relationship is multi-value) the oks::exception is thrown.

The parameters are:

Parameters
namename of relationship
objectnew relationship value
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 2183 of file object.cpp.

2184{
2185 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2186
2187 if (i == uid.class_id->p_data_info->end()) {
2188 std::ostringstream text;
2189 text << "object " << this << " has no relationship \"" << name << '\"';
2190 throw oks::ObjectSetError(this, true, name, text.str());
2191 }
2192
2193 SetRelationshipValue(i->second, o);
2194}

◆ SetRelationshipValue() [5/5]

void dunedaq::oks::OksObject::SetRelationshipValue ( const std::string & rel_name,
const std::string & class_name,
const std::string & object_id )

Set class-name and object-id value of single-value relationship by name.

In case of problems (e.g. no relationship with such name, wrong class type or relationship is multi-value) the oks::exception is thrown.

The parameters are:

Parameters
rel_namename of relationship
class_nameclass name of the referenced object
object_idID of the referenced object
Exceptions
oks::exceptionis thrown in case of problems.

Definition at line 2331 of file object.cpp.

2332{
2333 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2334
2335 if (i == uid.class_id->p_data_info->end()) {
2336 std::ostringstream text;
2337 text << "object " << this << " has no relationship \"" << name << '\"';
2338 throw oks::ObjectSetError(this, true, name, text.str());
2339 }
2340
2341 OksDataInfo* odi = i->second;
2342
2343 const OksRelationship* r = odi->relationship;
2344 size_t offset = odi->offset;
2345
2346 if (object_id.empty() || class_id.empty()) {
2347 check_non_null(r, 0);
2348 check_file_lock(0, r);
2349
2350 if ((data[offset].type == OksData::object_type) && data[offset].data.OBJECT) {
2351 data[offset].data.OBJECT->remove_RCR(this, r);
2352 }
2353
2354 data[offset].Set((OksObject*)0);
2355
2356 notify();
2357
2358 return;
2359 }
2360
2361 OksClass* c = uid.class_id->p_kernel->find_class(class_id);
2362
2363 if (c) {
2364 check_class_type(r, c);
2365 } else if (r->get_type() != class_id) {
2366 std::ostringstream text;
2367 text << "cannot set value \"" << object_id << '@' << class_id << "\" since the class \"" << class_id
2368 << "\" is not defined and it is impossible to check its validity for given type of relationship";
2369 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2370 }
2371
2372 if (r->get_high_cardinality_constraint() == OksRelationship::Many) {
2373 std::ostringstream text;
2374 text << "cannot set object \"" << object_id << '@' << class_id
2375 << "\" since the relationship has \'many\' high cardinality constraint";
2376 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2377 }
2378
2379 OksObject* o = nullptr;
2380
2381 if (c)
2382 o = c->get_object(object_id);
2383
2384 if (o) {
2385 SetRelationshipValue(name, o);
2386 } else {
2387 check_file_lock(0, r);
2388
2389 if ((data[offset].type == OksData::object_type) && data[offset].data.OBJECT) {
2390 data[offset].data.OBJECT->remove_RCR(this, r);
2391 }
2392
2393 data[offset].Set(class_id, object_id);
2394
2395 notify();
2396 }
2397}
void remove_RCR(OksObject *, const OksRelationship *) noexcept
Definition object.cpp:2528

◆ SetTransientData()

void dunedaq::oks::OksObject::SetTransientData ( void * d) const
inline

Set transient user data associated with given object. Such data are not stored on file and only exist while OksKernel object is not destroyed.

Definition at line 1614 of file object.hpp.

1614{ p_user_data = d; }

◆ unbind_file()

void dunedaq::oks::OksObject::unbind_file ( const OksFile * f)
private

Definition at line 2748 of file object.cpp.

2749{
2750 const size_t num_of_attrs(uid.class_id->number_of_all_attributes());
2751 const size_t num_of_rels(uid.class_id->number_of_all_relationships());
2752
2753 bool verbose = GetClass()->get_kernel()->get_verbose_mode();
2754
2755 for (size_t i = 0; i < num_of_rels; ++i) {
2756 OksData* d = &data[i + num_of_attrs];
2757
2758 if (d) {
2759 if (d->type == OksData::object_type) {
2760 OksObject* o = d->data.OBJECT;
2761
2762 if (o && o->file == f) {
2763 if (verbose)
2764 std::cout << "- unbind_file(\'" << f->get_full_file_name() << "\') in " << this << ": replace " << *d;
2765
2766 d->Set(o->GetClass(), o->GetId());
2767
2768 if (verbose)
2769 std::cout << " by " << *d << std::endl;
2770 }
2771 } else if (d->type == OksData::list_type && d->data.LIST) {
2772 for (const auto& j : *d->data.LIST) {
2773 if (j && j->type == OksData::object_type) {
2774 OksObject* o = j->data.OBJECT;
2775
2776 if (o && o->file == f) {
2777 if (verbose)
2778 std::cout << "+ unbind_file(\'" << f->get_full_file_name() << "\') in " << this << ": replace " << *j;
2779
2780 j->Set(o->GetClass(), o->GetId());
2781
2782 if (verbose)
2783 std::cout << " by " << *j << std::endl;
2784 }
2785 }
2786 }
2787 }
2788 }
2789 }
2790}
bool get_verbose_mode() const
Get status of verbose mode. The method returns true, if the verbose mode is switched 'On'.
Definition kernel.hpp:700

◆ oks::ReadFileParams

friend struct oks::ReadFileParams
friend

Definition at line 1151 of file object.hpp.

◆ oks::ReloadObjects

friend struct oks::ReloadObjects
friend

Definition at line 1152 of file object.hpp.

◆ OksClass

friend class OksClass
friend

Definition at line 1145 of file object.hpp.

◆ OksData

friend struct OksData
friend

Definition at line 1146 of file object.hpp.

◆ OksIndex

friend class OksIndex
friend

Definition at line 1148 of file object.hpp.

◆ OksKernel

friend class OksKernel
friend

Definition at line 1147 of file object.hpp.

◆ OksLoadObjectsJob

friend struct OksLoadObjectsJob
friend

Definition at line 1150 of file object.hpp.

◆ OksObjectSortBy

friend class OksObjectSortBy
friend

Definition at line 1149 of file object.hpp.

◆ operator<< [1/2]

std::ostream & operator<< ( std::ostream & out,
const OksObject & obj )
friend

Detailed stream operator.

Send to stream complete description of OKS object:

  • print class name and ID
  • print value of all attributes and relationships

Definition at line 1624 of file object.cpp.

1626{
1627 OSK_PROFILING(OksProfiler::ObjectOperatorOut, o.uid.class_id->p_kernel)
1628
1629 const OksClass* c = o.uid.class_id;
1630
1631 s << "Object " << &o << std::endl;
1632
1633 OksData* di = o.data;
1634
1635 // print attributes
1636
1637 {
1638 const std::list<OksAttribute*>* alist = c->all_attributes();
1639
1640 if (alist && !alist->empty()) {
1641 s << " Attributes are:\n";
1642
1643 for (std::list<OksAttribute*>::const_iterator i = alist->begin(); i != alist->end(); ++i) {
1644 if ((*i)->is_integer() && (*i)->get_format() != OksAttribute::Dec) {
1645 s.setf(((*i)->get_format() == OksAttribute::Hex ? std::ios::hex : std::ios::oct), std::ios::basefield);
1646 s.setf(std::ios::showbase);
1647 }
1648
1649 s << " " << (*i)->get_name() << ": " << *di++ << std::endl;
1650
1651 if ((*i)->is_integer() && (*i)->get_format() != OksAttribute::Dec) {
1652 s.setf(std::ios::dec, std::ios::basefield);
1653 s.unsetf(std::ios::showbase);
1654 }
1655 }
1656 } else
1657 s << " There are no attributes\n";
1658 }
1659
1660 // print relationships
1661
1662 {
1663 const std::list<OksRelationship*>* rlist = c->all_relationships();
1664
1665 if (rlist && !rlist->empty()) {
1666 s << " Relationships are:\n";
1667
1668 for (std::list<OksRelationship*>::const_iterator i = rlist->begin(); i != rlist->end(); ++i)
1669 s << " " << (*i)->get_name() << ": " << *di++ << std::endl;
1670 } else
1671 s << " There are no relationships\n";
1672 }
1673
1674 return s;
1675}

◆ operator<< [2/2]

std::ostream & operator<< ( std::ostream & s,
const OksObject * o )
friend

Short stream operator.

Send to stream OKS object reference in format "foo@bar" (i.e. object "foo" from class "bar")

Definition at line 1609 of file object.cpp.

1611{
1612 s << '\"';
1613
1614 if (o)
1615 s << o->GetId() << '@' << o->GetClass()->get_name();
1616 else
1617 s << "(null-obj)";
1618
1619 s << '\"';
1620
1621 return s;
1622}

Member Data Documentation

◆ attribute_xml_tag

const char dunedaq::oks::OksObject::attribute_xml_tag = "attr"
staticprivate

Definition at line 1798 of file object.hpp.

◆ class2_xml_attribute

const char dunedaq::oks::OksObject::class2_xml_attribute = "c"
staticprivate

Definition at line 1801 of file object.hpp.

◆ class_xml_attribute

const char dunedaq::oks::OksObject::class_xml_attribute = "class"
staticprivate

Definition at line 1800 of file object.hpp.

◆ data

OksData* dunedaq::oks::OksObject::data
private

Definition at line 1685 of file object.hpp.

◆ data_xml_tag

const char dunedaq::oks::OksObject::data_xml_tag = "data"
staticprivate

Definition at line 1809 of file object.hpp.

◆ file

OksFile* dunedaq::oks::OksObject::file
private

Definition at line 1690 of file object.hpp.

◆ id2_xml_attribute

const char dunedaq::oks::OksObject::id2_xml_attribute = "i"
staticprivate

Definition at line 1803 of file object.hpp.

◆ id_xml_attribute

const char dunedaq::oks::OksObject::id_xml_attribute = "id"
staticprivate

Definition at line 1802 of file object.hpp.

◆ name_xml_attribute

const char dunedaq::oks::OksObject::name_xml_attribute = "name"
staticprivate

Definition at line 1804 of file object.hpp.

◆ num_xml_attribute

const char dunedaq::oks::OksObject::num_xml_attribute = "num"
staticprivate

Definition at line 1806 of file object.hpp.

◆ obj2_xml_tag

const char dunedaq::oks::OksObject::obj2_xml_tag = "o"
staticprivate

Definition at line 1797 of file object.hpp.

◆ obj_xml_tag

const char dunedaq::oks::OksObject::obj_xml_tag = "obj"
staticprivate

Definition at line 1796 of file object.hpp.

◆ p_duplicated_object_id_idx

int32_t dunedaq::oks::OksObject::p_duplicated_object_id_idx
private

Definition at line 1689 of file object.hpp.

◆ p_int32_id

int32_t dunedaq::oks::OksObject::p_int32_id
private

Definition at line 1688 of file object.hpp.

◆ p_rcr

std::list<OksRCR*>* dunedaq::oks::OksObject::p_rcr
private

Definition at line 1686 of file object.hpp.

◆ p_user_data

void* dunedaq::oks::OksObject::p_user_data
mutableprivate

Definition at line 1687 of file object.hpp.

◆ ref_xml_tag

const char dunedaq::oks::OksObject::ref_xml_tag = "ref"
staticprivate

Definition at line 1810 of file object.hpp.

◆ relationship_xml_tag

const char dunedaq::oks::OksObject::relationship_xml_tag = "rel"
staticprivate

Definition at line 1799 of file object.hpp.

◆ type_xml_attribute

const char dunedaq::oks::OksObject::type_xml_attribute = "type"
staticprivate

Definition at line 1805 of file object.hpp.

◆ uid

struct dunedaq::oks::OksObject::OksUid dunedaq::oks::OksObject::uid
private

◆ value_xml_attribute

const char dunedaq::oks::OksObject::value_xml_attribute = "val"
staticprivate

Definition at line 1808 of file object.hpp.


The documentation for this class was generated from the following files: