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 *, SortByIdSMap
typedef std::unordered_map< const std::string *, OksObject *, oks::hash_str, oks::equal_strMap
typedef std::unordered_set< OksObject *, oks::hash_obj_ptr, oks::equal_obj_ptrFSet
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 OksClassGetClass () const
const std::string & GetId () const
void set_id (const std::string &id)
 Set object ID.
OksFileget_file () const
void set_file (OksFile *file, bool update_owner=true)
 Move object to different file.
OksDataGetAttributeValue (const std::string &name) const
 Get value of attribute by name.
OksDataGetAttributeValue (const OksDataInfo *i) const noexcept
 Get value of attribute by offset.
OksDataGetRelationshipValue (const std::string &) const
 Get value of relationship by name.
OksDataGetRelationshipValue (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.
FListget_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::Listfind_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)
OksObjectoperator= (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 OksObjectread (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
OksDatadata
std::list< OksRCR * > * p_rcr
void * p_user_data
int32_t p_int32_id
int32_t p_duplicated_object_id_idx
OksFilefile

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 840 of file object.hpp.

Member Typedef Documentation

◆ FList

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

Definition at line 882 of file object.hpp.

◆ FSet

Definition at line 871 of file object.hpp.

◆ List

List of pointers to OksObject

Definition at line 880 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 870 of file object.hpp.

◆ notify_obj

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

Definition at line 853 of file object.hpp.

◆ Set

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

Set of pointers to OksObject

Definition at line 876 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 865 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 1180 of file object.cpp.

1180 : data(nullptr), p_duplicated_object_id_idx(-1)
1181{
1183
1184 if(!c->p_kernel->get_active_data()) {
1185 Oks::error_msg("OksObject::OksObject(const OksClass*, const char *)") << " Can not create new object since there is no active data file\n";
1186 return;
1187 }
1188
1189 uid.class_id = c;
1190 uid.object_id = (object_id ? object_id : "");
1191
1192 try {
1193 init1();
1194 }
1195 catch(oks::exception& ex) {
1196 uid.class_id = nullptr;
1197 throw;
1198 }
1199
1200 init2(skip_init);
1201 init3();
1202
1203 file->set_updated();
1204}
struct dunedaq::oks::OksObject::OksUid uid
void init1(const OksFile *=0)
Definition object.cpp:187
void init2(bool skip_init=false)
Definition object.cpp:280
int32_t p_duplicated_object_id_idx
Definition object.hpp:1414
static std::ostream & error_msg(const char *)
Definition kernel.cpp:561
#define OSK_PROFILING(FID, K)
Definition defs.hpp:102

◆ 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 1206 of file object.cpp.

1206 : data(nullptr), p_duplicated_object_id_idx(-1)
1207{
1208 OSK_PROFILING(OksProfiler::ObjectCopyConstructor, parentObj.uid.class_id->p_kernel)
1209
1210 if(!parentObj.uid.class_id->p_kernel->get_active_data()) {
1211 Oks::error_msg("OksObject::OksObject(const OksObject&, const char *)") << " Can not create new object since there is no active data file\n";
1212 return;
1213 }
1214
1215 const OksClass *c = uid.class_id = parentObj.uid.class_id;
1216
1217 uid.object_id = (object_id ? object_id : "");
1218
1219 try {
1220 init1();
1221 }
1222 catch(oks::exception& ex) {
1223 uid.class_id = nullptr;
1224 throw;
1225 }
1226
1227
1228 int count = c->p_instance_size;
1229 int num_of_attr = c->p_all_attributes->size();
1230 int j = 0;
1231
1232 while(j < num_of_attr) {
1233 data[j] = parentObj.data[j];
1234 j++;
1235 }
1236
1237 try {
1238 std::list<OksRelationship *>::iterator i = c->p_all_relationships->begin();
1239
1240 while(j < count) {
1241 const OksRelationship * r = *i;
1242 const char * relationshipName = r->get_name().c_str();
1243
1244 if(parentObj.data[j].type == OksData::list_type) {
1245 data[j].Set(new OksData::List());
1246
1247 if(parentObj.data[j].data.LIST) {
1248 for(const auto& i2 : *parentObj.data[j].data.LIST) {
1249 if(i2->type == OksData::object_type)
1250 AddRelationshipValue(relationshipName, i2->data.OBJECT);
1251 else {
1252 OksData * uid_d = new OksData();
1253 uid_d = i2;
1254 data[j].data.LIST->push_back(uid_d);
1255 }
1256 }
1257 }
1258 }
1259 else {
1260 if(parentObj.data[j].type == OksData::object_type) {
1261 data[j].Set((OksObject *)0);
1262 SetRelationshipValue(relationshipName, parentObj.data[j].data.OBJECT);
1263 }
1264 else
1265 data[j] = parentObj.data[j];
1266 }
1267 ++j;
1268 ++i;
1269 }
1270 }
1271 catch(oks::exception& ex) {
1272 uid.class_id = nullptr;
1273 throw;
1274 }
1275
1276 init3();
1277
1278 file->set_updated();
1279}
friend class OksClass
Definition object.hpp:842
void AddRelationshipValue(const std::string &name, OksObject *object)
Add object value to multi-value relationship by name.
Definition object.cpp:2341
friend struct OksData
Definition object.hpp:843
void SetRelationshipValue(const std::string &name, OksData *data, bool skip_non_null_check=false)
Set value of relationship by name.
Definition object.cpp:2194
OksObject(const OksClass *oks_class, const char *object_id=0, bool skip_init=false)
OKS object constructor.
Definition object.cpp:1180
std::list< OksData *, boost::fast_pool_allocator< OksData * > > List
Definition object.hpp:460

◆ ~OksObject()

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

Definition at line 1369 of file object.cpp.

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

◆ 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 1157 of file object.cpp.

1157 : data(nullptr), p_duplicated_object_id_idx(-1)
1158{
1159 if(c) {
1161 }
1162
1163 uid.object_id = id;
1164 uid.class_id = c;
1165
1166 std::shared_lock lock(read_params.oks_kernel->p_schema_mutex); // protect schema and all objects from changes
1167
1168 if(c) {
1169 init1(read_params.f); // can throw exception; to be caught by caller (i.e. OksKernel)
1170 }
1171
1172 read_body(read_params, false);
1173
1174 if(c) {
1175 init3(c);
1176 }
1177}
void read_body(const oks::ReadFileParams &, bool)
Definition object.cpp:518

◆ OksObject() [4/5]

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

Definition at line 1281 of file object.cpp.

1281 : data(nullptr), p_duplicated_object_id_idx(-1)
1282{
1283 uid.class_id = nullptr;
1284 data = new OksData[offset+1];
1285 memcpy(static_cast<void *>(&data[offset]), static_cast<const void *>(d), sizeof(OksData));
1286}
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 1288 of file object.cpp.

1288 :
1289 data (new OksData[c->p_instance_size]),
1290 p_user_data (user_data),
1291 p_int32_id (int32_id),
1292 p_duplicated_object_id_idx (duplicated_object_id_idx),
1293 file (f)
1294
1295{
1296 uid.class_id = c;
1297 uid.object_id = id;
1298
1299 // set OksData type to unknown
1300 if(size_t data_size = c->p_instance_size * sizeof(OksData*)) {
1301 bzero(data, data_size);
1302 }
1303}

Member Function Documentation

◆ __get_num()

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

Definition at line 507 of file object.cpp.

508{
509 char * __sanity;
510 params.s.get_num_token('\"');
511 int32_t num = static_cast<int32_t>(strtol(params.s.m_cvt_char->m_buf, &__sanity, 0));
512 if(*__sanity != 0 || errno == ERANGE) OksXmlInputStream::__throw_strto("strtol", __sanity, params.s.m_cvt_char->m_buf, params.s.get_line_no(), params.s.get_line_pos());
513 return num;
514}
static void __throw_strto(const char *f, const char *where, const char *what, unsigned long line_no, unsigned long line_pos)
Definition xml.cpp:625

◆ __report_cardinality_cvt_warning()

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

Definition at line 490 of file object.cpp.

491{
492 std::lock_guard lock(OksKernel::p_parallel_out_mutex);
493 Oks::warning_msg(std::string("Read object \"") + GetId() + '@' + GetClass()->get_name() + '\"')
494 << " file: \"" << params.f->get_full_file_name() << "\" (line: " << params.s.get_line_no() << ", pos: " << params.s.get_line_pos() << ")\n"
495 " mismatch between relationship \"" << r.get_name() << "\" cardinality and its value (save data file with new schema)." << std::endl;
496}
static std::mutex p_parallel_out_mutex
Definition kernel.hpp:2051
const OksClass * GetClass() const
Definition object.hpp:995
const std::string & GetId() const
Definition object.hpp:1000
static std::ostream & warning_msg(const char *)
Definition kernel.cpp:568

◆ __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 456 of file object.cpp.

457{
458 const char * type_str;
459
460 switch (type) {
461 case OksData::s8_int_type: type_str = OksAttribute::s8_int_type ; break;
462 case OksData::u8_int_type: type_str = OksAttribute::u8_int_type ; break;
463 case OksData::s16_int_type: type_str = OksAttribute::s16_int_type ; break;
464 case OksData::u16_int_type: type_str = OksAttribute::u16_int_type ; break;
465 case OksData::s32_int_type: type_str = OksAttribute::s32_int_type ; break;
466 case OksData::u32_int_type: type_str = OksAttribute::u32_int_type ; break;
467 case OksData::s64_int_type: type_str = OksAttribute::s64_int_type ; break;
468 case OksData::u64_int_type: type_str = OksAttribute::u64_int_type ; break;
469 case OksData::float_type: type_str = OksAttribute::float_type ; break;
470 case OksData::double_type: type_str = OksAttribute::double_type ; break;
471 case OksData::bool_type: type_str = OksAttribute::bool_type ; break;
472 case OksData::class_type: type_str = OksAttribute::class_type ; break;
473 case OksData::date_type: type_str = OksAttribute::date_type ; break;
474 case OksData::time_type: type_str = OksAttribute::time_type ; break;
475 case OksData::string_type: type_str = OksAttribute::string_type ; break;
476 case OksData::enum_type: type_str = OksAttribute::enum_type ; break;
477 default: type_str = "unknown";
478
479 }
480
481 std::lock_guard lock(OksKernel::p_parallel_out_mutex);
482 Oks::warning_msg(std::string("Read object \"") + GetId() + '@' + GetClass()->get_name() + '\"')
483 << " file: \"" << params.f->get_full_file_name() << "\" (line: " << params.s.get_line_no() << ", pos: " << params.s.get_line_pos() << ")\n"
484 " convert value from wrong type \"" << (num == -1 ? "single" : "multi") << "-value " << type_str << "\" to \"" << (a.get_is_multi_values() ? "multi" : "single")
485 << "-value " << a.get_type() << "\" as required for attribute \"" << a.get_name() << "\"\n"
486 << " converted value: " << d << std::endl;
487}
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 2579 of file object.cpp.

2580{
2581 if(r->get_is_composite() == false) return;
2582
2583 TLOG_DEBUG(4) << "object " << this << " adds RCR to object " << o << " throught relationship \"" << r->get_name() << '\"';
2584
2585 if(!p_rcr) {
2586 p_rcr = new std::list<OksRCR *>();
2587 }
2588 else {
2589 for(const auto& i : *p_rcr) {
2590 if(i->relationship == r) {
2591 if(i->obj == o) {
2592 TLOG_DEBUG(4) << "[this=" << this << ", o=" << o << ", r=\"" << r->get_name() << "\"]: such RCR was already set.";
2593 return;
2594 }
2595 else if(r->get_is_exclusive()) {
2596 throw oks::AddRcrError(this, r->get_name(), o, i->obj);
2597 }
2598 }
2599 }
2600 }
2601
2602 p_rcr->push_back(new OksRCR(o, r));
2603}

◆ 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 2308 of file object.cpp.

2309{
2310 const OksRelationship * r = odi->relationship;
2311 size_t offset = odi->offset;
2312
2313 if(!object) {
2314 throw oks::ObjectSetError(this, true, r->get_name(), "the (null) value is not allowed");
2315 }
2316
2317 check_class_type(r, object);
2318
2319 if( r->get_high_cardinality_constraint() != OksRelationship::Many ) {
2320 std::ostringstream text;
2321 text << "cannot add value " << object << " since the relationship has no \'many\' high cardinality constraint";
2322 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2323 }
2324
2325 try {
2326 object->add_RCR(this, r);
2327 }
2328 catch(oks::exception& ex) {
2329 throw oks::ObjectSetError(this, true, r->get_name(), ex);
2330 }
2331
2332 check_file_lock(0, r);
2333
2334 data[offset].data.LIST->push_back(new OksData(object));
2335
2336 notify();
2337}
void check_file_lock(const OksAttribute *, const OksRelationship *)
Definition object.cpp:3196
void check_class_type(const OksRelationship *, const OksClass *)
Definition object.cpp:2036

◆ 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 2341 of file object.cpp.

2342{
2343 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2344
2345 if(i == uid.class_id->p_data_info->end()) {
2346 std::ostringstream text;
2347 text << "object " << this << " has no relationship \"" << name << '\"';
2348 throw oks::ObjectSetError(this, true, name, text.str());
2349 }
2350
2351 AddRelationshipValue(i->second, object);
2352}

◆ 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 2479 of file object.cpp.

2480{
2481 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2482
2483 if(i == uid.class_id->p_data_info->end()) {
2484 std::ostringstream text;
2485 text << "object " << this << " has no relationship \"" << name << '\"';
2486 throw oks::ObjectSetError(this, true, name, text.str());
2487 }
2488
2489 OksDataInfo * odi = i->second;
2490 const OksRelationship * r = odi->relationship;
2491
2492 if(class_id.empty() || object_id.empty()) {
2493 throw oks::ObjectSetError(this, true, r->get_name(), "cannot add (null) object");
2494 }
2495
2496 const std::string& r_class_type = r->get_type();
2497 size_t offset = odi->offset;
2498
2499 OksClass *c = uid.class_id->p_kernel->find_class(class_id);
2500
2501 if(c) {
2502 check_class_type(r, c);
2503 }
2504 else if(r_class_type != class_id) {
2505 std::ostringstream text;
2506 text << "cannot add value \"" << object_id << '@' << class_id << "\" since the class \"" << class_id
2507 << "\" is not defined and it is impossible to check its validity for given type of relationship";
2508 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2509 }
2510
2511 if(r->get_high_cardinality_constraint() != OksRelationship::Many) {
2512 std::ostringstream text;
2513 text << "cannot add object \"" << object_id << '@' << class_id << "\" since the relationship has no \'many\' high cardinality constraint";
2514 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2515 }
2516
2517 OksObject *o = nullptr;
2518
2519 if(c) o = c->get_object(object_id);
2520
2521 if(o) {
2522 AddRelationshipValue(odi, o);
2523 }
2524 else {
2525 check_file_lock(0, r);
2526 data[offset].data.LIST->push_back(new OksData(class_id, object_id));
2527 notify();
2528 }
2529}

◆ 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 1605 of file object.cpp.

1606{
1607 if (o1 == o2)
1608 return true;
1609
1610 if (o1 == nullptr || o2 == nullptr)
1611 return false;
1612
1613 return (o1->uid.class_id->get_name() == o2->uid.class_id->get_name() && o1->uid.object_id == o2->uid.object_id);
1614}

◆ bind()

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

Definition at line 2631 of file object.cpp.

2632{
2633 const OksClass * c(0);
2634 OksObject * o(0);
2635
2636 if(d->type == OksData::uid_type) {
2637 if(d->data.UID.class_id && !d->data.UID.object_id->empty()) {
2638 c = d->data.UID.class_id;
2639 o = c->get_object(d->data.UID.object_id);
2640 }
2641 else {
2642 d->Set((OksObject *)0);
2643 return;
2644 }
2645 }
2646 else {
2647 if(d->data.UID2.class_id->empty() || d->data.UID2.object_id->empty()) {
2648 d->Set((OksObject *)0);
2649 return;
2650 }
2651
2652 c = info.k->find_class(*d->data.UID2.class_id);
2653
2654 if(c) {
2655 o = c->get_object(d->data.UID2.object_id);
2656 }
2657 else {
2658 std::ostringstream text;
2659 text << "Class of object " << *d << " is not defined";
2660 throw oks::ObjectBindError(info.o, d, info.r, true, text.str(), "");
2661 }
2662 }
2663
2664 if(c != info.r->p_class_type) {
2665 if(const OksClass::FList * slist = c->all_super_classes()) {
2666 for(OksClass::FList::const_iterator i = slist->begin(); i != slist->end(); ++i) {
2667 if(info.r->p_class_type == *i) {
2668 goto check_passed;
2669 }
2670 }
2671 }
2672
2673 {
2674 std::ostringstream text;
2675 text << "The relationship has class type \"" << info.r->get_type() << "\" and the referenced object " << *d << " is not of that class or derived one";
2676 throw oks::ObjectBindError(info.o, d, info.r, true, text.str(), "");
2677 }
2678
2679 check_passed: ;
2680 }
2681
2682 if(!o) {
2683 std::ostringstream text;
2684 text << "Cannot find object " << *d;
2685 throw oks::ObjectBindError(info.o, d, info.r, false, text.str(), "");
2686 }
2687
2688 try {
2689 d->Set(o);
2690 o->add_RCR(info.o, info.r);
2691 }
2692 catch(oks::exception& ex) {
2693 std::ostringstream text;
2694 text << "Failed to set relationship value " << o;
2695 throw oks::ObjectBindError(info.o, d, info.r, true, text.str(), ex);
2696 }
2697}
std::list< OksClass *, boost::fast_pool_allocator< OksClass * > > FList
Definition class.hpp:240

◆ bind_objects()

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

Binds objects and returns true on success

Definition at line 2736 of file object.cpp.

2737{
2738 const OksClass * c = uid.class_id;
2739
2740 if(c->p_all_relationships->empty()) return; // if class has no relationships then nothing to do
2741
2742 BindInfo info;
2743 info.k = c->p_kernel;
2744 info.o = this;
2745
2746 OksData * d(data + c->number_of_all_attributes());
2747
2748 BindWarning warnings;
2749
2750 for (auto & i : (*c->p_all_relationships))
2751 {
2752 info.r = i;
2753
2754 if(d->type == OksData::object_type)
2755 {
2756 if (i->get_low_cardinality_constraint() == OksRelationship::One && d->data.OBJECT == nullptr) { warnings.add(i); }
2757 }
2758 else if (d->type == OksData::uid_type)
2759 {
2760 if (d->data.UID.object_id == nullptr)
2761 {
2762 if (i->get_low_cardinality_constraint() == OksRelationship::One) { warnings.add(i); }
2763 }
2764
2765 try
2766 {
2767 bind(d, info);
2768 }
2769 catch (oks::ObjectBindError& ex)
2770 {
2771 if (ex.p_is_error) { throw; }
2772 else { warnings.add(*ex.p_data, ex.p_rel); }
2773 }
2774 }
2775 else if (d->type == OksData::list_type)
2776 {
2777 if (d->data.LIST->empty())
2778 {
2779 if (i->get_low_cardinality_constraint() == OksRelationship::One) { warnings.add(i); }
2780 }
2781 else
2782 {
2783 for (const auto& i2 : *d->data.LIST)
2784 {
2785 if (i2->type == OksData::uid_type || i2->type == OksData::uid2_type)
2786 {
2787 try
2788 {
2789 bind(i2, info);
2790 }
2791 catch (oks::ObjectBindError& ex)
2792 {
2793 if (ex.p_is_error) { throw; }
2794 else { warnings.add(*ex.p_data, ex.p_rel); }
2795 }
2796 }
2797 }
2798 }
2799 }
2800 else if (d->type == OksData::uid2_type)
2801 {
2802 if (i->get_low_cardinality_constraint() == OksRelationship::One && d->data.UID2.object_id == nullptr) { warnings.add(i); }
2803 try
2804 {
2805 bind(d, info);
2806 }
2807 catch (oks::ObjectBindError& ex)
2808 {
2809 if (ex.p_is_error) { throw; }
2810 else { warnings.add(*ex.p_data, ex.p_rel); }
2811 }
2812 }
2813
2814 d++;
2815 }
2816
2817 if(warnings.p_warnings_count)
2818 {
2819 std::ostringstream text;
2820 const char * s1(warnings.p_warnings_count == 1 ? "is" : "are");
2821 const char * s2(warnings.p_warnings_count == 1 ? "" : "s");
2822 text << "There " << s1 << " " << warnings.p_warnings_count << " unresolved reference" << s2 << " from object " << this
2823 << '\n' << warnings.p_warnings->str();
2824 throw oks::ObjectBindError(this, 0, 0, false, text.str(), "");
2825 }
2826}
static void bind(OksData *, const BindInfo &)
Definition object.cpp:2631

◆ change_notify()

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

Invoke change object notification.

Definition at line 2898 of file object.cpp.

2899{
2900 OksKernel * k = uid.class_id->p_kernel;
2901 if(k->p_change_object_notify_fn) {
2902 (*k->p_change_object_notify_fn)(this, k->p_change_object_notify_param);
2903 }
2904}

◆ check_class_type() [1/2]

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

Definition at line 2036 of file object.cpp.

2037{
2038 if(!class_type) return;
2039
2040 const OksClass * rel_class_type = r->p_class_type;
2041
2042 if(class_type != rel_class_type) {
2043 OksClass::FList * super_classes = class_type->p_all_super_classes;
2044
2045 if(super_classes && !super_classes->empty()) {
2046 for(const auto& i : *super_classes) {
2047 if(rel_class_type == i) return;
2048 }
2049 }
2050
2051 std::ostringstream text;
2052 text << "set to an object of class \"" << class_type->get_name() << "\" is not allowed since the relationship's class type is \""
2053 << r->get_type() << "\" and the class \"" << class_type->get_name() << "\" has no such superclass";
2054 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2055 }
2056}

◆ check_class_type() [2/2]

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

Definition at line 1486 of file object.hpp.

1486{ if(o) { check_class_type(r, o->GetClass()); }}

◆ check_file_lock()

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

Definition at line 3196 of file object.cpp.

3197{
3198 try {
3199 file->lock();
3200 }
3201 catch(oks::exception& ex) {
3202 throw oks::ObjectSetError(this, (a == nullptr), (a ? a->get_name() : r->get_name()), ex);
3203 }
3204}

◆ check_ids()

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

Definition at line 167 of file object.cpp.

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

◆ 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 2921 of file object.cpp.

2922{
2923 if(get_file() != o2->get_file()) {
2924 if(includes.find(o2->get_file()) == includes.end()) {
2925 if(GetClass()->get_kernel()->get_silence_mode() == false) {
2926 std::cerr <<
2927 msg << ": no files inclusion path between referenced objects:\n"
2928 " object " << this << " from file \"" << get_file()->get_full_file_name() << "\" via relationship \"" << name << "\"\n"
2929 " has reference to object " << o2 << " from file \"" << o2->get_file()->get_full_file_name() << "\";\n"
2930 " file \"" << get_file()->get_full_file_name() << "\" includes " << includes.size() << " files:\n";
2931
2932 for(std::set<OksFile *>::const_iterator j = includes.begin(); j != includes.end(); ++j) {
2933 std::cerr << " * \'" << (*j)->get_full_file_name() << "\'\n";
2934 }
2935
2936 }
2937
2938 return false;
2939 }
2940 }
2941
2942 return true;
2943}
const std::string & get_full_file_name() const
Definition file.hpp:528
OksFile * get_file() const
Definition object.hpp:1018

◆ check_non_null()

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

Definition at line 2024 of file object.cpp.

2025{
2026 if(!o && r->get_low_cardinality_constraint() != OksRelationship::Zero) {
2027 throw oks::ObjectSetError(
2028 this, true, r->get_name(),
2029 "set to (null) is not allowed since the relationship has non-zero low cardinality constraint"
2030 );
2031 }
2032}

◆ create_notify()

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

Invoke create object notification.

Definition at line 2884 of file object.cpp.

2885{
2886 OksKernel * k = uid.class_id->p_kernel;
2887
2888 if(k->p_create_object_notify_fn) {
2889 (*k->p_create_object_notify_fn)(this, k->p_create_object_notify_param);
2890 }
2891}

◆ delete_notify()

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

Invoke delete object notification.

Definition at line 2911 of file object.cpp.

2912{
2913 OksKernel * k = uid.class_id->p_kernel;
2914
2915 if(k->p_delete_object_notify_fn) {
2916 (*k->p_delete_object_notify_fn)(this, k->p_delete_object_notify_param);
2917 }
2918}

◆ 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 1306 of file object.cpp.

1307{
1308 if(!o->uid.class_id || fast) {
1309 delete o;
1310 return;
1311 }
1312
1313 // check lack of references on object
1314
1315 std::unique_ptr<std::ostringstream> error_text;
1316
1317 const OksClass::Map & classes = o->uid.class_id->p_kernel->classes();
1318
1319 for(OksClass::Map::const_iterator i = classes.begin(); i != classes.end(); ++i) {
1320 OksClass *c(i->second);
1321 if(c->p_all_relationships == nullptr || c->p_all_relationships->empty()) continue;
1322
1323 if(const OksObject::Map * objects = c->objects()) {
1324 for(OksObject::Map::const_iterator j = objects->begin(); j != objects->end(); ++j) {
1325 size_t offset = c->number_of_all_attributes();
1326 for(std::list<OksRelationship *>::iterator k = c->p_all_relationships->begin(); k != c->p_all_relationships->end(); ++k, ++offset) {
1327 OksData * d = j->second->data + offset;
1328 OksObject * ref = nullptr;
1329
1330 if(d->type == OksData::object_type && d->data.OBJECT == o) {
1331 ref = j->second;
1332 }
1333 else if(d->type == OksData::list_type && d->data.LIST != nullptr) {
1334 for(const auto& l : *d->data.LIST) {
1335 if(l->type == OksData::object_type && l->data.OBJECT == o) {
1336 ref = j->second;
1337 break;
1338 }
1339 }
1340 }
1341
1342 if(ref) {
1343 if(!error_text.get()) {
1344 error_text.reset(new std::ostringstream());
1345 *error_text << "since it is referenced by:";
1346 }
1347 *error_text << "\n * object " << ref << " via relationship \"" << (*k)->get_name() << '\"';
1348 }
1349 }
1350 }
1351 }
1352 }
1353
1354 if(error_text.get()) {
1355 throw oks::FailedDestoyObject(o, error_text->str().c_str());
1356 }
1357
1358 try {
1359 o->file->lock();
1360 o->file->set_updated();
1361 }
1362 catch(oks::exception& ex) {
1363 throw oks::FailedDestoyObject(o, ex);
1364 }
1365
1366 delete o;
1367}
std::map< const char *, OksClass *, SortStr > Map
Definition class.hpp:238
std::unordered_map< const std::string *, OksObject *, oks::hash_str, oks::equal_str > Map
Definition object.hpp:870

◆ find_path()

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

Definition at line 941 of file query.cpp.

942{
943 OksObject::List * path = new OksObject::List();
944
945 if(satisfies(query.get_goal_object(), *query.get_start_expression(), *path) == false) {
946 delete path;
947 path = 0;
948 }
949
950 return path;
951}
std::list< OksObject * > List
Definition object.hpp:880
bool satisfies(const OksObject *goal, const oks::QueryPathExpression &expresssion, OksObject::List &path) const
Definition query.cpp:955

◆ 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 3134 of file object.cpp.

3135{
3136 bool any_name = (name == "*");
3137
3138 OksObject::FList * result = nullptr;
3139
3140 const OksClass::Map& all_classes(GetClass()->get_kernel()->classes());
3141
3142 for(OksClass::Map::const_iterator i = all_classes.begin(); i != all_classes.end(); ++i) {
3143 OksClass * c(i->second);
3144 if(any_name || c->find_relationship(name) != nullptr) {
3145 if(const OksObject::Map * objs = i->second->objects()) {
3146 for(OksObject::Map::const_iterator j = objs->begin(); j != objs->end(); ++j) {
3147 OksObject *o(j->second);
3148 unsigned short l1, l2;
3149
3150 if(any_name) {
3151 l1 = c->number_of_all_attributes();
3152 l2 = l1 + c->number_of_all_relationships();
3153 }
3154 else {
3155 l1 = c->data_info(name)->offset;
3156 l2 = l1+1;
3157 }
3158
3159 while(l1 < l2) {
3160 OksDataInfo odi(l1, (OksRelationship *)0);
3161 OksData * d(o->GetRelationshipValue(&odi));
3162
3163 if(d->type == OksData::object_type) {
3164 if(this == d->data.OBJECT) {
3165 if(!result) result = new OksObject::FList();
3166 result->push_back(o);
3167 break;
3168 }
3169 }
3170 else if(d->type == OksData::list_type) {
3171 bool found = false;
3172 for(OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
3173 OksData * lid(*li);
3174 if(lid->type == OksData::object_type) {
3175 if(this == lid->data.OBJECT) {
3176 if(!result) result = new OksObject::FList();
3177 result->push_back(o);
3178 found = true;
3179 break; // exit given relationship value iterator
3180 }
3181 }
3182 }
3183 if(found) break; //exit relationships iterator for given object
3184 }
3185 ++l1;
3186 }
3187 }
3188 }
3189 }
3190 }
3191
3192 return result;
3193}
std::list< OksObject *, boost::fast_pool_allocator< OksObject * > > FList
Definition object.hpp:882

◆ get_change_notify()

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

Definition at line 2874 of file object.cpp.

2875{
2876 return uid.class_id->p_kernel->p_change_object_notify_fn;
2877}

◆ get_file()

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

Get file of object.

Definition at line 1018 of file object.hpp.

1018{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 1363 of file object.hpp.

1363{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 1067 of file object.hpp.

1067{ 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 1924 of file object.cpp.

1925{
1926 OksDataInfo::Map::const_iterator i = uid.class_id->p_data_info->find(name);
1927
1928 if(i == uid.class_id->p_data_info->end()) {
1929 std::ostringstream text;
1930 text << "object " << this << " has no attribute \"" << name << '\"';
1931 throw oks::ObjectGetError(this, false, name, text.str());
1932 }
1933
1934 return GetAttributeValue(i->second);
1935}
OksData * GetAttributeValue(const std::string &name) const
Get value of attribute by name.
Definition object.cpp:1924

◆ GetClass()

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

Get class of object.

Definition at line 995 of file object.hpp.

995{return uid.class_id;}

◆ GetId()

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

Get object ID.

Definition at line 1000 of file object.hpp.

1000{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 1100 of file object.hpp.

1100{ 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 2009 of file object.cpp.

2010{
2011 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2012
2013 if(i == uid.class_id->p_data_info->end()) {
2014 std::ostringstream text;
2015 text << "object " << this << " has no relationship \"" << name << '\"';
2016 throw oks::ObjectGetError(this, false, name, text.str());
2017 }
2018
2019 return GetRelationshipValue(i->second);
2020}
OksData * GetRelationshipValue(const std::string &) const
Get value of relationship by name.
Definition object.cpp:2009

◆ 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 1348 of file object.hpp.

1348{return p_user_data;}

◆ init1()

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

Definition at line 187 of file object.cpp.

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

◆ init2()

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

Definition at line 280 of file object.cpp.

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

◆ init3() [1/2]

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

Definition at line 326 of file object.cpp.

327{
328 init3(const_cast<OksClass *>(uid.class_id));
330}

◆ init3() [2/2]

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

Definition at line 315 of file object.cpp.

316{
317 if( __builtin_expect((c->p_indices != nullptr), 0) ) {
318 for(auto& i : *c->p_indices) i.second->insert(this);
319 }
320
321 c->add(this);
322 c->p_kernel->define(this);
323}

◆ 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 2993 of file object.cpp.

2994{
2995 unsigned short l1 = GetClass()->number_of_all_attributes();
2996 unsigned short l2 = l1 + GetClass()->number_of_all_relationships();
2997
2998 std::list<OksRelationship *>::const_iterator ri = GetClass()->all_relationships()->begin();
2999
3000 bool return_value = true;
3001
3002 while(l1 < l2) {
3003 OksDataInfo odi(l1, *ri);
3005
3006 if(d->type == OksData::object_type) {
3007 if(OksObject * o2 = d->data.OBJECT) {
3008 check_links_and_report(o2, includes, odi.relationship->get_name(), msg);
3009 }
3010 }
3011 else if(d->type == OksData::list_type) {
3012 for(OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
3013 if((*li)->type == OksData::object_type) {
3014 if(OksObject * o2 = (*li)->data.OBJECT) {
3015 check_links_and_report(o2, includes, odi.relationship->get_name(), msg);
3016 }
3017 }
3018 }
3019 }
3020
3021 if(d->IsConsistent(odi.relationship, this, "ERROR") == false) {
3022 return_value = false;
3023 }
3024
3025 ++l1;
3026 ++ri;
3027 }
3028
3029 // check inclusion of the schema file
3030
3031 if(includes.find(GetClass()->get_file()) == includes.end()) {
3032 if(GetClass()->get_kernel()->get_silence_mode() == false) {
3033 std::cerr <<
3034 "ERROR: the schema file is not included for object " << this << ".\n"
3035 " The data file \"" << get_file()->get_full_file_name() << "\" containg above object\n"
3036 " cannot be loaded or edited without inclusion of additional files.\n"
3037 " The file shall explicitly or implicitly (i.e. via other included files) include schema file\n"
3038 " \"" << GetClass()->get_file()->get_full_file_name() << "\" defining class \"" << GetClass()->get_name() << "\".\n";
3039 }
3040
3041 return false;
3042 }
3043
3044
3045 return return_value;
3046}
size_t number_of_all_relationships() const noexcept
Definition class.hpp:1055
const std::string & get_name() const noexcept
Definition class.hpp:368
size_t number_of_all_attributes() const noexcept
Definition class.hpp:1041
OksFile * get_file() const noexcept
Definition class.hpp:343
const std::list< OksRelationship * > * all_relationships() const noexcept
Definition class.hpp:590
bool check_links_and_report(const OksObject *, const std::set< OksFile * > &, const std::string &, const char *) const
Definition object.cpp:2921

◆ is_duplicated()

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

Definition at line 1395 of file object.hpp.

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

◆ notify()

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

Definition at line 1480 of file object.hpp.

1480 {
1481 file->set_updated();
1482 change_notify();
1483 }

◆ operator delete()

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

Fast delete operator.

Definition at line 970 of file object.hpp.

970{boost::fast_pool_allocator<OksObject>::deallocate(reinterpret_cast<OksObject*>(ptr));}

◆ operator new()

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

Fast new operator to reduce resources consumption.

Definition at line 965 of file object.hpp.

965{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 1617 of file object.cpp.

1618{
1619 if (are_equal_fast(this, &o) == false)
1620 return false;
1621
1623
1624 size_t count(0);
1625
1626 while (count < uid.class_id->p_instance_size)
1627 {
1628 if (data[count] == o.data[count])
1629 count++;
1630 else
1631 return false;
1632 }
1633
1634 return true;
1635}
static bool are_equal_fast(const OksObject *o1, const OksObject *o2)
The fast equal method.
Definition object.cpp:1605

◆ put()

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

Definition at line 1785 of file object.cpp.

1786{
1788
1789 try
1790 {
1791 const OksClass * class_id = uid.class_id;
1792
1793 xmls.put_start_tag(obj_xml_tag, sizeof(obj_xml_tag)-1);
1794
1795 xmls.put_attribute(class_xml_attribute, sizeof(class_xml_attribute)-1, class_id->get_name().c_str());
1796 xmls.put_attribute(id_xml_attribute, sizeof(id_xml_attribute)-1, uid.object_id.c_str());
1797
1798 xmls.put_eol();
1799
1800 int count = 0;
1801
1802 if (auto alist = class_id->all_attributes())
1803 {
1804 for (const auto& a : *alist)
1805 {
1806 OksData& d = data[count++];
1807
1808 // store all attributes with value != initial, or date/time types which default values = now(), or non-numbers or numbers with non-zero values
1809 if (force_defaults || d != a->p_init_data || a->p_data_type == OksData::date_type || a->p_data_type == OksData::time_type || (a->get_init_value().empty() == false && (a->get_is_multi_values() == true || a->is_number() == false || a->get_init_value().size() > 1 || a->get_init_value()[0] != '0')))
1810 {
1811 xmls.put_raw(' ');
1812 xmls.put_start_tag(attribute_xml_tag, sizeof(attribute_xml_tag) - 1);
1813 xmls.put_attribute(name_xml_attribute, sizeof(name_xml_attribute) - 1, a->get_name().c_str());
1814 xmls.put_attribute(type_xml_attribute, sizeof(type_xml_attribute) - 1, a->get_type().c_str());
1815
1816 if (a->is_integer() && a->get_format() != OksAttribute::Dec)
1817 {
1818 xmls.get_stream().setf((a->get_format() == OksAttribute::Hex ? std::ios::hex : std::ios::oct), std::ios::basefield);
1819 xmls.get_stream().setf(std::ios::showbase);
1820 }
1821
1822 if (a->get_is_multi_values() == false)
1823 {
1824 xmls.put_attribute(value_xml_attribute, sizeof(value_xml_attribute) - 1, d);
1825 xmls.put_end_tag();
1826 }
1827 else
1828 {
1829 if (d.data.LIST->empty())
1830 {
1831 xmls.put_end_tag();
1832 }
1833 else
1834 {
1835 if(a->p_ordered)
1836 d.sort();
1837
1838 xmls.put_eol();
1839
1840 for (const auto& x : *d.data.LIST)
1841 {
1842 xmls.put_raw(' ');
1843 xmls.put_raw(' ');
1844 xmls.put_start_tag(data_xml_tag, sizeof(data_xml_tag) - 1);
1845 xmls.put_attribute(value_xml_attribute, sizeof(value_xml_attribute) - 1, *x);
1846 xmls.put_end_tag();
1847 }
1848
1849 xmls.put_raw(' ');
1850 xmls.put_last_tag(attribute_xml_tag, sizeof(attribute_xml_tag) - 1);
1851 }
1852 }
1853
1854 if (a->is_integer() && a->get_format() != OksAttribute::Dec)
1855 {
1856 xmls.get_stream().setf(std::ios::dec, std::ios::basefield);
1857 xmls.get_stream().unsetf(std::ios::showbase);
1858 }
1859 }
1860 }
1861 }
1862
1863 if (const std::list<OksRelationship *> * rlist = class_id->all_relationships())
1864 {
1865 for (const auto& r : *rlist)
1866 {
1867 OksData& rel_data = data[count++];
1868
1869 if (trim_dangling(rel_data, *class_id->p_kernel))
1870 {
1871 xmls.put_raw(' ');
1872 xmls.put_start_tag(relationship_xml_tag, sizeof(relationship_xml_tag) - 1);
1873 xmls.put_attribute(name_xml_attribute, sizeof(name_xml_attribute) - 1, r->get_name().c_str());
1874
1875 if (r->get_high_cardinality_constraint() != OksRelationship::Many)
1876 {
1877 put_object_attributes(xmls, rel_data);
1878 xmls.put_end_tag();
1879 }
1880 else
1881 {
1882 if(r->p_ordered)
1883 rel_data.sort();
1884
1885 xmls.put_eol();
1886
1887 for (const auto& x : *rel_data.data.LIST)
1888 {
1889 xmls.put_raw(' ');
1890 xmls.put_raw(' ');
1891 xmls.put_start_tag(ref_xml_tag, sizeof(ref_xml_tag) - 1);
1892 put_object_attributes(xmls, *x);
1893 xmls.put_end_tag();
1894 }
1895
1896 xmls.put_raw(' ');
1897 xmls.put_last_tag(relationship_xml_tag, sizeof(relationship_xml_tag) - 1);
1898 }
1899 }
1900 }
1901 }
1902
1903 xmls.put_last_tag(obj_xml_tag, sizeof(obj_xml_tag) - 1);
1904 }
1905 catch (oks::exception & ex)
1906 {
1907 throw(oks::FailedSaveObject(this, ex));
1908 }
1909 catch (std::ios_base::failure & ex)
1910 {
1911 throw(oks::FailedSaveObject(this, std::string("caught std::ios_base::failure exception \"") + ex.what() + '\"'));
1912 }
1913 catch (std::exception & ex)
1914 {
1915 throw(oks::FailedSaveObject(this, std::string("caught std::exception \"") + ex.what() + '\"'));
1916 }
1917 catch (...)
1918 {
1919 throw(oks::FailedSaveObject(this, "unknown reason"));
1920 }
1921}
static const char relationship_xml_tag[]
Definition object.hpp:1521
static const char attribute_xml_tag[]
Definition object.hpp:1520
static void put_object_attributes(OksXmlOutputStream &, const OksData &)
Definition object.cpp:1759
static const char value_xml_attribute[]
Definition object.hpp:1530
static const char id_xml_attribute[]
Definition object.hpp:1524
static const char obj_xml_tag[]
Definition object.hpp:1518
static const char class_xml_attribute[]
Definition object.hpp:1522
static const char name_xml_attribute[]
Definition object.hpp:1526
static const char type_xml_attribute[]
Definition object.hpp:1527
static const char data_xml_tag[]
Definition object.hpp:1531
static const char ref_xml_tag[]
Definition object.hpp:1532
static bool trim_dangling(OksData &d, const OksKernel &kernel)
Definition object.cpp:1718

◆ put_object_attributes()

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

Definition at line 1759 of file object.cpp.

1760{
1761 const std::string * class_name = nullptr;
1762 const std::string * object_id = nullptr;
1763
1764 if(d.type == OksData::object_type)
1765 {
1766 class_name = &d.data.OBJECT->GetClass()->get_name();
1767 object_id = &d.data.OBJECT->GetId();
1768 }
1769 else if(d.type == OksData::uid_type)
1770 {
1771 class_name = &d.data.UID.class_id->get_name();
1772 object_id = d.data.UID.object_id;
1773 }
1774 else
1775 {
1776 class_name = d.data.UID2.class_id;
1777 object_id = d.data.UID2.object_id;
1778 }
1779
1780 xmls.put_attribute(class_xml_attribute, sizeof(class_xml_attribute)-1, class_name->c_str());
1781 xmls.put_attribute(id_xml_attribute, sizeof(id_xml_attribute)-1, object_id->c_str());
1782}

◆ 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 368 of file object.cpp.

369{
370 // read 'object' tag header
371
372 try {
373 const char * tag_start(read_params.s.get_tag_start());
374
375 if(memcmp(tag_start, read_params.object_tag, read_params.object_tag_len)) {
376 if(!oks::cmp_str9(tag_start, "/oks-data")) {
377 read_params.s.throw_unexpected_tag(tag_start, read_params.object_tag);
378 }
379 return 0;
380 }
381 }
382 catch (oks::exception & e) {
383 throw oks::FailedRead("start-of-object tag", e);
384 }
385 catch (std::exception & e) {
386 throw oks::FailedRead("start-of-object tag", e.what());
387 }
388
389
390 // read object tag attributes
391
392 OksClass * c(nullptr);
393 std::string& id((const_cast<oks::ReadFileParams&>(read_params)).tmp); // use temporal string for fast assignment
394
395
396 try {
397 if(read_params.format != 'c') {
399 }
400 else {
402 }
403 }
404 catch(oks::exception & e) {
405 throw oks::FailedRead("object header", e);
406 }
407 catch (std::exception & e) {
408 throw oks::FailedRead("object header", e.what());
409 }
410
411 if(!c) {
412 throw oks::BadFileData("object without class", read_params.s.get_line_no(), read_params.s.get_line_pos());
413 }
414
415 try {
416 oks::validate_not_empty(id, "object id");
417 }
418 catch(std::exception& ex) {
419 throw oks::FailedRead("oks object", oks::BadFileData(ex.what(), read_params.s.get_line_no(), read_params.s.get_line_pos()));
420 }
421
422 if(c && read_params.reload_objects) {
423 if(OksObject * o = read_params.reload_objects->pop(c, id)) {
424 o->read_body(read_params, true);
425 return o;
426 }
427 }
428
429
430 // check if this is the end of file
431
432 if(c == nullptr && id.empty()) { return nullptr; }
433
434
435 // create new object
436
437 OksObject * obj = new OksObject(read_params, c, id); // can throw exception
438
439
440 // check if we re-read the database and notify if required
441
442 if(read_params.reload_objects) {
443 read_params.reload_objects->created.push_back(obj);
444 obj->create_notify();
445
446 if(read_params.oks_kernel->get_verbose_mode()) {
447 TLOG_DEBUG(3) << "*** create object " << obj << " while reload data ***";
448 }
449 }
450
451 return obj;
452}
static const char class2_xml_attribute[]
Definition object.hpp:1523
static const char id2_xml_attribute[]
Definition object.hpp:1525
friend struct oks::ReadFileParams
Definition object.hpp:848
bool cmp_str1(const char *s1, const char s2[2])
Definition cstring.hpp:14
bool cmp_str9(const char *s1, const char s2[10])
Definition cstring.hpp:74
void validate_not_empty(const std::string &value, const char *name)
bool cmp_str2(const char *s1, const char s2[3])
Definition cstring.hpp:18
bool cmp_str5(const char *s1, const char s2[6])
Definition cstring.hpp:42
msgpack::object obj
#define READ_OBJ_HEADER(F1, S1, F2, S2)
Definition object.cpp:332

◆ read_body()

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

Definition at line 518 of file object.cpp.

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

◆ 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 3115 of file object.cpp.

3116{
3117 struct RefData data(refs, classes);
3118
3119 std::lock_guard lock(uid.class_id->p_kernel->p_objects_refs_mutex);
3120
3121 OksObject::FSet tested_objs;
3122
3123 if(add_self) {
3124 insert2refs(this, recursion_depth + 1, data);
3125 }
3126
3127 _references(this, recursion_depth, data);
3128
3129 TLOG_DEBUG(2) << "OksObject::references(" << this << ", " << recursion_depth << ") returns " << refs.size() << " objects";
3130}
std::unordered_set< OksObject *, oks::hash_obj_ptr, oks::equal_obj_ptr > FSet
Definition object.hpp:871
static void _references(const OksObject *obj, unsigned long recursion_depth, RefData &data)
Definition object.cpp:3084
static void insert2refs(const OksObject *o, unsigned long recursion_depth, RefData &data)
Definition object.cpp:3064

◆ remove_RCR()

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

Definition at line 2607 of file object.cpp.

2608{
2609 TLOG_DEBUG(4) << "object " << this << " removes RCR from object " << o << " through " << r->get_name();
2610
2611 if(r->get_is_composite() == false || !p_rcr) return;
2612
2613 for(std::list<OksRCR *>::iterator i = p_rcr->begin(); i != p_rcr->end(); ++i) {
2614 OksRCR *rcr = *i;
2615
2616 if(rcr->obj == o && rcr->relationship == r) {
2617 p_rcr->erase(i);
2618 delete rcr;
2619 break;
2620 }
2621 }
2622
2623 if(p_rcr->empty()) {
2624 delete p_rcr;
2625 p_rcr = nullptr;
2626 }
2627}

◆ 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 2356 of file object.cpp.

2357{
2358 const OksRelationship * r = odi->relationship;
2359
2360 if(!object) {
2361 throw oks::ObjectSetError(this, true, r->get_name(), "cannot remove (null) object");
2362 }
2363
2364 if(r->get_high_cardinality_constraint() != OksRelationship::Many) {
2365 std::ostringstream text;
2366 text << "cannot remove object " << object << " since the relationship has no \'many\' high cardinality constraint";
2367 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2368 }
2369
2370 OksData d(object);
2371 size_t offset = odi->offset;
2372 OksData::List * list = data[offset].data.LIST;
2373
2374 for(OksData::List::iterator i = list->begin(); i != list->end();) {
2375 OksData * d2 = *i;
2376 if(cmp_data(d2, &d)) {
2377 check_file_lock(0, r);
2378 object->remove_RCR(this, r);
2379 list->erase(i);
2380 delete d2;
2381 notify();
2382 return;
2383 }
2384 else ++i;
2385 }
2386
2387 std::ostringstream text;
2388 text << "cannot remove object " << object << " since the relationship\'s value has no such object";
2389 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2390}
static bool cmp_data(OksData *d, OksData *d2)
Definition object.cpp:2268

◆ 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 2394 of file object.cpp.

2395{
2396 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2397
2398 if(i == uid.class_id->p_data_info->end()) {
2399 std::ostringstream text;
2400 text << "object " << this << " has no relationship \"" << name << '\"';
2401 throw oks::ObjectSetError(this, true, name, text.str());
2402 }
2403
2404 RemoveRelationshipValue(i->second, object);
2405}
void RemoveRelationshipValue(const std::string &name, OksObject *object)
Remove object value from multi-value relationship by name.
Definition object.cpp:2394

◆ 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 2533 of file object.cpp.

2534{
2535 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2536
2537 if(i == uid.class_id->p_data_info->end()) {
2538 std::ostringstream text;
2539 text << "object " << this << " has no relationship \"" << name << '\"';
2540 throw oks::ObjectSetError(this, true, name, text.str());
2541 }
2542
2543 OksDataInfo * odi = i->second;
2544 const OksRelationship * r = odi->relationship;
2545
2546 if(object_id.empty() || class_id.empty()) {
2547 throw oks::ObjectSetError(this, true, r->get_name(), "cannot remove (null) object");
2548 }
2549
2550 if( r->get_high_cardinality_constraint() != OksRelationship::Many ) {
2551 std::ostringstream text;
2552 text << "cannot remove object \"" << object_id << '@' << class_id << "\" since the relationship has no \'many\' high cardinality constraint";
2553 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2554 }
2555
2556 size_t offset = odi->offset;
2557 OksData d(class_id, object_id);
2558 OksData::List * list = data[offset].data.LIST;
2559
2560 for(OksData::List::iterator j = list->begin(); j != list->end();) {
2561 OksData * d2 = *j;
2562 if(cmp_data(d2, &d)) {
2563 check_file_lock(0, r);
2564 list->erase(j);
2565 delete d2;
2566 notify();
2567 return;
2568 }
2569 else ++j;
2570 }
2571
2572 std::ostringstream text;
2573 text << "cannot remove object \"" << object_id << '@' << class_id << "\" since the relationship\'s value has no such object";
2574 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2575}

◆ 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 2962 of file object.cpp.

2963{
2964 unsigned short l1 = GetClass()->number_of_all_attributes();
2965 unsigned short l2 = l1 + GetClass()->number_of_all_relationships();
2966
2967 std::list<OksRelationship *>::const_iterator ri = GetClass()->all_relationships()->begin();
2968
2969 std::string result;
2970
2971 while(l1 < l2) {
2972 OksDataInfo odi(l1, *ri);
2974
2975 if(d->type == OksData::list_type) {
2976 for(OksData::List::const_iterator li = d->data.LIST->begin(); li != d->data.LIST->end(); ++li) {
2977 test_dangling_references(this, **li, **ri, result);
2978 }
2979 }
2980 else {
2981 test_dangling_references(this, *d, **ri, result);
2982 }
2983
2984 ++l1;
2985 ++ri;
2986 }
2987
2988 return result;
2989}
static void test_dangling_references(const OksObject *obj, const OksData &d, const OksRelationship &r, std::string &result)
Definition object.cpp:2946

◆ 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 1315 of file object.hpp.

1315{return p_rcr;}

◆ satisfies()

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

Definition at line 955 of file query.cpp.

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

◆ 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 635 of file query.cpp.

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

◆ 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 1489 of file object.cpp.

1490{
1491 if(file != f) {
1492 try {
1493 if(update_owner) {
1494 file->lock();
1495 file->set_updated();
1496 }
1497
1498 f->lock();
1499 f->set_updated();
1500
1501 file = f;
1502 }
1503 catch(oks::exception& ex) {
1504 throw oks::CanNotSetFile(0, this, *f, ex);
1505 }
1506 }
1507}

◆ 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 1511 of file object.cpp.

1512{
1513 if(new_id == uid.object_id) return;
1514
1515 try {
1516 oks::validate_not_empty(new_id, "object id");
1517 }
1518 catch(std::exception& ex) {
1519 throw oks::FailedRenameObject(this, ex.what());
1520 }
1521
1522 OksClass *c = const_cast<OksClass *>(uid.class_id);
1523
1524 if(c->get_object(new_id)) {
1525 throw oks::FailedRenameObject(this, "the object with such identity already exists");
1526 }
1527
1528
1529 // build set of updated files and list of updated objects
1530
1531 std::set<OksFile *> updated_files;
1532 std::list<OksObject *> updated_objects;
1533
1534 updated_files.insert(file);
1535 updated_objects.push_back(this);
1536
1537 const OksClass::Map & classes = GetClass()->get_kernel()->classes();
1538
1539 for(OksClass::Map::const_iterator i = classes.begin(); i != classes.end(); ++i) {
1540 const OksClass * c(i->second);
1541 const OksObject::Map * objs = c->objects();
1542 size_t d_end = c->p_instance_size;
1543 size_t d_begin = c->p_all_attributes->size();
1544 if(objs && (d_end != d_begin)) {
1545 for(OksObject::Map::const_iterator j = objs->begin(); j != objs->end(); ++j) {
1546 OksObject * o(j->second);
1547
1548 // avoid multiple notification, when renamed object contains references to self
1549 if(o != this) {
1550 for(size_t k = d_begin; k != d_end && o; ++k) {
1551 const OksData & d = o->data[k];
1552 if(d.type == OksData::object_type && d.data.OBJECT == this) {
1553 updated_objects.push_back(o);
1554 updated_files.insert(o->file);
1555 o = nullptr; // break loop
1556 }
1557 else if(d.type == OksData::list_type && d.data.LIST) {
1558 const OksData::List & list = *d.data.LIST;
1559 for(OksData::List::const_iterator l = list.begin(); l != list.end(); ++l) {
1560 OksData * d2 = *l;
1561 if(d2->type == OksData::object_type && d2->data.OBJECT == this) {
1562 updated_objects.push_back(o);
1563 updated_files.insert(o->file);
1564 o = nullptr; // break loop
1565 break;
1566 }
1567 }
1568 }
1569 }
1570 }
1571 }
1572 }
1573 }
1574
1575 try {
1576 for(std::set<OksFile *>::const_iterator i = updated_files.begin(); i != updated_files.end(); ++i) {
1577 (*i)->lock();
1578 }
1579 }
1580 catch(oks::exception& ex) {
1581 throw oks::FailedRenameObject(this, ex);
1582 }
1583
1584 try {
1585 c->remove(this); // remove object from hash table
1586 uid.object_id = new_id; // change id
1587 c->add(this); // add object to hash table
1588 }
1589 catch(oks::exception& ex) {
1590 throw oks::FailedRenameObject(this, ex);
1591 }
1592
1593 for(std::set<OksFile *>::const_iterator i = updated_files.begin(); i != updated_files.end(); ++i) {
1594 (*i)->set_updated();
1595 }
1596
1597 if(get_change_notify()) {
1598 for(std::list<OksObject *>::const_iterator i = updated_objects.begin(); i != updated_objects.end(); ++i) {
1599 (*i)->change_notify();
1600 }
1601 }
1602}
OksKernel * get_kernel() const noexcept
Definition class.hpp:338
const OksClass::Map & classes() const
Get classes.
Definition kernel.hpp:1772
notify_obj get_change_notify() const
Definition object.cpp:2874

◆ 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 1356 of file object.hpp.

1356{p_int32_id = object_id;}

◆ set_unique_id()

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

Definition at line 144 of file object.cpp.

145{
147
148 p_duplicated_object_id_idx = uid.object_id.size();
149
150 std::lock_guard lock(uid.class_id->p_unique_id_mutex);
151
152 std::unique_ptr<char[]> unique_id(new char[p_duplicated_object_id_idx+16]);
153
154 for (unsigned long i = 0; i < 0xFFFFFFFF; ++i)
155 {
156 sprintf(unique_id.get(), "%s^%lu", uid.object_id.c_str(), i);
157 std::string id(unique_id.get());
158 if(uid.class_id->get_object(id) == nullptr)
159 {
160 uid.object_id = id;
161 return;
162 }
163 }
164}
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 1939 of file object.cpp.

1940{
1941 size_t offset = odi->offset;
1942 const OksAttribute * a = odi->attribute;
1943 OksData d2; // can be needed by type conversion
1944
1945 if(data[offset].type != d->type) {
1946 if(uid.class_id->get_kernel()->get_silence_mode() == false) {
1947 Oks::warning_msg("OksObject::SetAttributeValue(const OksDataInfo *, OksData *)")
1948 << " * ODI attribute name: \'" << a->get_name() << "\'\n"
1949 " * ODI data offset: \'" << offset << "\'\n"
1950 " * OKS data (new): \'" << *d << "\' type: " << (int)d->type << "\n"
1951 " * OKS data (old): \'" << data[offset] << "\' type: " << (int)data[offset].type << "\n"
1952 " Object " << this << ":\n"
1953 " Convert attribute \"" << a->get_name() << "\" value since the OksData::type is invalid\n";
1954 }
1955
1956 d->cvt(&d2, a);
1957 d=&d2;
1958 }
1959
1960 try {
1961 d->check_range(a);
1962 }
1963 catch(oks::AttributeReadError & ex) {
1964 throw oks::ObjectSetError(this, false, a->get_name(), ex);
1965 }
1966 catch(oks::AttributeRangeError & ex) {
1967 throw oks::ObjectSetError(this, false, a->get_name(), ex);
1968 }
1969
1970 check_file_lock(a, 0);
1971
1972
1973 // set value and update index if any
1974
1975 {
1976 OksIndex * i = nullptr;
1977
1978 if(uid.class_id->p_indices) {
1979 OksIndex::Map::iterator j = uid.class_id->p_indices->find(a);
1980 if(j != uid.class_id->p_indices->end()) {
1981 i = j->second;
1982 }
1983 }
1984
1985 if(i) i->remove_obj(this);
1986 data[offset] = *d;
1987 if(i) i->insert(this);
1988 }
1989
1990 notify();
1991}
friend class OksIndex
Definition object.hpp:845

◆ 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 1995 of file object.cpp.

1996{
1997 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
1998
1999 if(i == uid.class_id->p_data_info->end()) {
2000 std::ostringstream text;
2001 text << "object " << this << " has no attribute \"" << name << '\"';
2002 throw oks::ObjectSetError(this, false, name, text.str());
2003 }
2004
2005 SetAttributeValue(i->second, d);
2006}
void SetAttributeValue(const std::string &name, OksData *data)
Set value of attribute by name.
Definition object.cpp:1995

◆ 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 2060 of file object.cpp.

2061{
2062 const OksRelationship * r = odi->relationship;
2063 size_t offset = odi->offset;
2064
2065 if(
2066 (data[offset].type != d->type) &&
2067 ( (d->type == OksData::list_type) || (data[offset].type == OksData::list_type) )
2068 ) {
2069 std::ostringstream text;
2070 text << "OKS data type is invalid: must be " << (data[offset].type == OksData::object_type ? "an object)\n" : "a list); ")
2071 << "offset: " << offset << "; new: \'" << *d << "\'; old:" << data[offset] << '\'';
2072 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2073 }
2074
2075 // used to update RCRs
2076
2077 OksObject::FSet added_objs;
2078 OksObject::FSet removed_objs;
2079
2080 if(d->type == OksData::object_type) {
2081 OksObject * add_obj = d->data.OBJECT;
2082 OksObject * rm_obj = (data[offset].type == OksData::object_type ? data[offset].data.OBJECT : 0);
2083
2084 if(add_obj != rm_obj) {
2085 if(add_obj) added_objs.insert(add_obj);
2086 if(rm_obj) removed_objs.insert(rm_obj);
2087 }
2088 else {
2089 return; // new and old values are equal, nothing to do
2090 }
2091
2092 if(skip_non_null_check == false) check_non_null(r, d->data.OBJECT);
2093 check_class_type(r, d->data.OBJECT);
2094 }
2095 else if(d->type == OksData::list_type && d->data.LIST) {
2096 if(d->data.LIST->empty()) {
2097 if(r->get_low_cardinality_constraint() != OksRelationship::Zero && skip_non_null_check == false) {
2098 throw oks::ObjectSetError(
2099 this, true, r->get_name(),
2100 "set to empty list is not allowed since the relationship has non-zero low cardinality constraint"
2101 );
2102 }
2103 }
2104
2105 for(const auto& i : *d->data.LIST) {
2106 if(i->type != OksData::object_type && i->type != OksData::uid2_type && i->type != OksData::uid_type) {
2107 throw oks::ObjectSetError(this, true, r->get_name(), "list contains non-objects");
2108 }
2109
2110 if(
2111 (i->type == OksData::object_type && !i->data.OBJECT) ||
2112 (i->type == OksData::uid2_type && !i->data.UID2.object_id) ||
2113 (i->type == OksData::uid_type && !i->data.UID.object_id)
2114 ) {
2115 throw oks::ObjectSetError(this, true, r->get_name(), "list contains (null) object");
2116 }
2117
2118 if(i->type == OksData::object_type) {
2119 if(OksObject * o2 = i->data.OBJECT) {
2120 check_class_type(r, o2);
2121 added_objs.insert(o2);
2122 }
2123 }
2124 }
2125 }
2126 else {
2127 throw oks::ObjectSetError(
2128 this, true, r->get_name(),
2129 "the OKS data type is invalid (must be a list of objects or an object)"
2130 );
2131 }
2132
2133 check_file_lock(0, r);
2134
2135
2136 // put old value to objects removed from relationship
2137
2138 if(data[offset].type == OksData::list_type && data[offset].data.LIST) {
2139 for(const auto& i : *data[offset].data.LIST) {
2140 if(i->type == OksData::object_type && i->data.OBJECT) {
2141 removed_objs.insert(i->data.OBJECT);
2142 }
2143 }
2144 }
2145
2146
2147 // remove RCRs
2148
2149 for(const auto& i : removed_objs) {
2150 if(added_objs.find(i) == added_objs.end()) {
2151 TLOG_DEBUG(4) << "object " << i << " was removed from relationship";
2152 i->remove_RCR(this, r);
2153 }
2154 }
2155
2156
2157 // add RCRs
2158
2159 for(OksObject::FSet::const_iterator i = added_objs.begin(); i != added_objs.end(); ++i) {
2160 OksObject * add_obj = *i;
2161 if(removed_objs.find(add_obj) == removed_objs.end()) {
2162 TLOG_DEBUG(4) << "object " << add_obj << " was added to relationship";
2163 try {
2164 add_obj->add_RCR(this, r);
2165 }
2166 catch(oks::exception& ex) {
2167
2168 // reset updated RCRs
2169
2170 for(OksObject::FSet::const_iterator j = added_objs.begin(); j != i; ++j) {
2171 if(removed_objs.find(*j) == removed_objs.end()) {
2172 (*j)->remove_RCR(this, r);
2173 }
2174 }
2175
2176 for(OksObject::FSet::const_iterator j = removed_objs.begin(); j != removed_objs.end(); ++j) {
2177 if(added_objs.find(*j) == added_objs.end()) {
2178 try { (*j)->add_RCR(this, r); } catch (oks::exception&) { ; }
2179 }
2180 }
2181
2182 throw oks::ObjectSetError(this, true, r->get_name(), ex);
2183 }
2184 }
2185 }
2186
2187 data[offset] = *d;
2188
2189 notify();
2190}
void check_non_null(const OksRelationship *, const OksObject *)
Definition object.cpp:2024

◆ 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 2209 of file object.cpp.

2210{
2211 const OksRelationship *r = odi->relationship;
2212 OksData& d(data[odi->offset]);
2213
2214 if( r->get_high_cardinality_constraint() == OksRelationship::Many ) {
2215 std::ostringstream text;
2216 text << "cannot set value " << object << " since the relationship has \'many\' high cardinality constraint";
2217 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2218 }
2219
2220 if(!object) {
2221 check_non_null(r, object);
2222 }
2223 else {
2224 check_class_type(r, object);
2225 }
2226
2227 check_file_lock(0, r);
2228
2229 if((d.type == OksData::object_type) && d.data.OBJECT) {
2230 d.data.OBJECT->remove_RCR(this, r);
2231 }
2232
2233 if(object) {
2234 try {
2235 object->add_RCR(this, r);
2236 }
2237 catch(oks::exception& ex) {
2238 // restore RCR and throw exception
2239 if((d.type == OksData::object_type) && d.data.OBJECT)
2240 try { d.data.OBJECT->add_RCR(this, r); } catch(oks::exception& ex2) { ; }
2241 throw oks::ObjectSetError(this, true, r->get_name(), ex);
2242 }
2243 }
2244
2245 d.Set(object);
2246
2247 notify();
2248}

◆ 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 2194 of file object.cpp.

2195{
2196 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2197
2198 if(i == uid.class_id->p_data_info->end()) {
2199 std::ostringstream text;
2200 text << "object " << this << " has no relationship \"" << name << '\"';
2201 throw oks::ObjectSetError(this, true, name, text.str());
2202 }
2203
2204 SetRelationshipValue(i->second, d, skip_non_null_check);
2205}

◆ 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 2252 of file object.cpp.

2253{
2254 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2255
2256 if(i == uid.class_id->p_data_info->end()) {
2257 std::ostringstream text;
2258 text << "object " << this << " has no relationship \"" << name << '\"';
2259 throw oks::ObjectSetError(this, true, name, text.str());
2260 }
2261
2262 SetRelationshipValue(i->second, o);
2263}

◆ 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 2408 of file object.cpp.

2409{
2410 OksDataInfo::Map::iterator i = uid.class_id->p_data_info->find(name);
2411
2412 if(i == uid.class_id->p_data_info->end()) {
2413 std::ostringstream text;
2414 text << "object " << this << " has no relationship \"" << name << '\"';
2415 throw oks::ObjectSetError(this, true, name, text.str());
2416 }
2417
2418 OksDataInfo * odi = i->second;
2419
2420
2421 const OksRelationship * r = odi->relationship;
2422 size_t offset = odi->offset;
2423
2424 if(object_id.empty() || class_id.empty()) {
2425 check_non_null(r, 0);
2426 check_file_lock(0, r);
2427
2428 if( (data[offset].type == OksData::object_type) && data[offset].data.OBJECT ) {
2429 data[offset].data.OBJECT->remove_RCR(this, r);
2430 }
2431
2432 data[offset].Set((OksObject *)0);
2433
2434 notify();
2435
2436 return;
2437 }
2438
2439 OksClass *c = uid.class_id->p_kernel->find_class(class_id);
2440
2441 if(c) {
2442 check_class_type(r, c);
2443 }
2444 else if(r->get_type() != class_id) {
2445 std::ostringstream text;
2446 text << "cannot set value \"" << object_id << '@' << class_id << "\" since the class \"" << class_id
2447 << "\" is not defined and it is impossible to check its validity for given type of relationship";
2448 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2449 }
2450
2451 if(r->get_high_cardinality_constraint() == OksRelationship::Many) {
2452 std::ostringstream text;
2453 text << "cannot set object \"" << object_id << '@' << class_id << "\" since the relationship has \'many\' high cardinality constraint";
2454 throw oks::ObjectSetError(this, true, r->get_name(), text.str());
2455 }
2456
2457 OksObject *o = nullptr;
2458
2459 if(c) o = c->get_object(object_id);
2460
2461 if(o) {
2462 SetRelationshipValue(name, o);
2463 }
2464 else {
2465 check_file_lock(0, r);
2466
2467 if( (data[offset].type == OksData::object_type) && data[offset].data.OBJECT ) {
2468 data[offset].data.OBJECT->remove_RCR(this, r);
2469 }
2470
2471 data[offset].Set(class_id, object_id);
2472
2473 notify();
2474 }
2475}

◆ 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 1340 of file object.hpp.

1340{p_user_data = d;}

◆ unbind_file()

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

Definition at line 2830 of file object.cpp.

2831{
2832 const size_t num_of_attrs (uid.class_id->number_of_all_attributes());
2833 const size_t num_of_rels (uid.class_id->number_of_all_relationships());
2834
2835 bool verbose = GetClass()->get_kernel()->get_verbose_mode();
2836
2837 for(size_t i = 0; i < num_of_rels; ++i) {
2838 OksData *d = &data[i + num_of_attrs];
2839
2840 if(d) {
2841 if(d->type == OksData::object_type) {
2842 OksObject * o = d->data.OBJECT;
2843
2844 if(o && o->file == f) {
2845 if(verbose)
2846 std::cout << "- unbind_file(\'" << f->get_full_file_name() << "\') in " << this << ": replace " << *d;
2847
2848 d->Set(o->GetClass(), o->GetId());
2849
2850 if(verbose) std::cout << " by " << *d << std::endl;
2851 }
2852 }
2853 else if(d->type == OksData::list_type && d->data.LIST) {
2854 for(const auto& j : *d->data.LIST) {
2855 if(j && j->type == OksData::object_type) {
2856 OksObject * o = j->data.OBJECT;
2857
2858 if(o && o->file == f) {
2859 if(verbose)
2860 std::cout << "+ unbind_file(\'" << f->get_full_file_name() << "\') in " << this << ": replace " << *j;
2861
2862 j->Set(o->GetClass(), o->GetId());
2863
2864 if(verbose) std::cout << " by " << *j << std::endl;
2865 }
2866 }
2867 }
2868 }
2869 }
2870 }
2871}
bool get_verbose_mode() const
Get status of verbose mode. The method returns true, if the verbose mode is switched 'On'.
Definition kernel.hpp:670

◆ oks::ReadFileParams

friend struct oks::ReadFileParams
friend

Definition at line 848 of file object.hpp.

◆ oks::ReloadObjects

friend struct oks::ReloadObjects
friend

Definition at line 849 of file object.hpp.

◆ OksClass

friend class OksClass
friend

Definition at line 842 of file object.hpp.

◆ OksData

friend struct OksData
friend

Definition at line 843 of file object.hpp.

◆ OksIndex

friend class OksIndex
friend

Definition at line 845 of file object.hpp.

◆ OksKernel

friend class OksKernel
friend

Definition at line 844 of file object.hpp.

◆ OksLoadObjectsJob

friend struct OksLoadObjectsJob
friend

Definition at line 847 of file object.hpp.

◆ OksObjectSortBy

friend class OksObjectSortBy
friend

Definition at line 846 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 1654 of file object.cpp.

1656{
1657 OSK_PROFILING(OksProfiler::ObjectOperatorOut, o.uid.class_id->p_kernel)
1658
1659 const OksClass * c = o.uid.class_id;
1660
1661 s << "Object " << &o << std::endl;
1662
1663 OksData * di = o.data;
1664
1665
1666 // print attributes
1667
1668 {
1669 const std::list<OksAttribute *> * alist = c->all_attributes();
1670
1671 if(alist && !alist->empty()) {
1672 s << " Attributes are:\n";
1673
1674 for(std::list<OksAttribute *>::const_iterator i = alist->begin(); i != alist->end(); ++i) {
1675 if((*i)->is_integer() && (*i)->get_format() != OksAttribute::Dec) {
1676 s.setf(((*i)->get_format() == OksAttribute::Hex ? std::ios::hex : std::ios::oct), std::ios::basefield);
1677 s.setf(std::ios::showbase);
1678 }
1679
1680 s << " " << (*i)->get_name() << ": " << *di++ << std::endl;
1681
1682 if((*i)->is_integer() && (*i)->get_format() != OksAttribute::Dec) {
1683 s.setf(std::ios::dec, std::ios::basefield);
1684 s.unsetf(std::ios::showbase);
1685 }
1686 }
1687 }
1688 else
1689 s << " There are no attributes\n";
1690 }
1691
1692
1693 // print relationships
1694
1695 {
1696 const std::list<OksRelationship *> * rlist = c->all_relationships();
1697
1698 if(rlist && !rlist->empty()) {
1699 s << " Relationships are:\n";
1700
1701 for(std::list<OksRelationship *>::const_iterator i = rlist->begin(); i != rlist->end(); ++i)
1702 s << " " << (*i)->get_name() << ": " << *di++ << std::endl;
1703 }
1704 else
1705 s << " There are no relationships\n";
1706 }
1707
1708 return s;
1709}

◆ 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 1638 of file object.cpp.

1640{
1641 s << '\"';
1642
1643 if(o)
1644 s << o->GetId() << '@' << o->GetClass()->get_name();
1645 else
1646 s << "(null-obj)";
1647
1648 s << '\"';
1649
1650 return s;
1651}

Member Data Documentation

◆ attribute_xml_tag

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

Definition at line 1520 of file object.hpp.

◆ class2_xml_attribute

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

Definition at line 1523 of file object.hpp.

◆ class_xml_attribute

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

Definition at line 1522 of file object.hpp.

◆ data

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

Definition at line 1410 of file object.hpp.

◆ data_xml_tag

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

Definition at line 1531 of file object.hpp.

◆ file

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

Definition at line 1415 of file object.hpp.

◆ id2_xml_attribute

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

Definition at line 1525 of file object.hpp.

◆ id_xml_attribute

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

Definition at line 1524 of file object.hpp.

◆ name_xml_attribute

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

Definition at line 1526 of file object.hpp.

◆ num_xml_attribute

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

Definition at line 1528 of file object.hpp.

◆ obj2_xml_tag

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

Definition at line 1519 of file object.hpp.

◆ obj_xml_tag

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

Definition at line 1518 of file object.hpp.

◆ p_duplicated_object_id_idx

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

Definition at line 1414 of file object.hpp.

◆ p_int32_id

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

Definition at line 1413 of file object.hpp.

◆ p_rcr

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

Definition at line 1411 of file object.hpp.

◆ p_user_data

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

Definition at line 1412 of file object.hpp.

◆ ref_xml_tag

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

Definition at line 1532 of file object.hpp.

◆ relationship_xml_tag

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

Definition at line 1521 of file object.hpp.

◆ type_xml_attribute

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

Definition at line 1527 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 1530 of file object.hpp.


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