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  BindInfo
 
struct  OksUid
 
struct  SortById
 

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

Member Typedef Documentation

◆ FList

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

Definition at line 877 of file object.hpp.

◆ FSet

Definition at line 866 of file object.hpp.

◆ List

List of pointers to OksObject

Definition at line 875 of file object.hpp.

◆ Map

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

◆ notify_obj

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

Definition at line 848 of file object.hpp.

◆ Set

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

Set of pointers to OksObject

Definition at line 871 of file object.hpp.

◆ SMap

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

Map of pointers to OksObject sorted by object Id

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

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

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

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

◆ ~OksObject()

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

Definition at line 1364 of file object.cpp.

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

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

◆ OksObject() [4/5]

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

Definition at line 1276 of file object.cpp.

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

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

Member Function Documentation

◆ __get_num()

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

Definition at line 502 of file object.cpp.

503{
504 char * __sanity;
505 params.s.get_num_token('\"');
506 int32_t num = static_cast<int32_t>(strtol(params.s.m_cvt_char->m_buf, &__sanity, 0));
507 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());
508 return num;
509}
static void __throw_strto(const char *f, const char *where, const char *what, unsigned long line_no, unsigned long line_pos)
Definition xml.cpp:620

◆ __report_cardinality_cvt_warning()

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

Definition at line 485 of file object.cpp.

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

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

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

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

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

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

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

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

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

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

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

1601{
1602 if (o1 == o2)
1603 return true;
1604
1605 if (o1 == nullptr || o2 == nullptr)
1606 return false;
1607
1608 return (o1->uid.class_id->get_name() == o2->uid.class_id->get_name() && o1->uid.object_id == o2->uid.object_id);
1609}

◆ bind()

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

Definition at line 2626 of file object.cpp.

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

◆ bind_objects()

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

Binds objects and returns true on success

Definition at line 2731 of file object.cpp.

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

◆ change_notify()

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

Invoke change object notification.

Definition at line 2893 of file object.cpp.

2894{
2895 OksKernel * k = uid.class_id->p_kernel;
2896 if(k->p_change_object_notify_fn) {
2897 (*k->p_change_object_notify_fn)(this, k->p_change_object_notify_param);
2898 }
2899}

◆ check_class_type() [1/2]

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

Definition at line 2031 of file object.cpp.

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

◆ check_class_type() [2/2]

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

Definition at line 1481 of file object.hpp.

1481{ 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 3191 of file object.cpp.

3192{
3193 try {
3194 file->lock();
3195 }
3196 catch(oks::exception& ex) {
3197 throw oks::ObjectSetError(this, (a == nullptr), (a ? a->get_name() : r->get_name()), ex);
3198 }
3199}
void lock()
Lock OKS file.
Definition file.cpp:1012

◆ check_ids()

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

Definition at line 162 of file object.cpp.

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

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

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

◆ check_non_null()

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

Definition at line 2019 of file object.cpp.

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

◆ create_notify()

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

Invoke create object notification.

Definition at line 2879 of file object.cpp.

2880{
2881 OksKernel * k = uid.class_id->p_kernel;
2882
2883 if(k->p_create_object_notify_fn) {
2884 (*k->p_create_object_notify_fn)(this, k->p_create_object_notify_param);
2885 }
2886}

◆ delete_notify()

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

Invoke delete object notification.

Definition at line 2906 of file object.cpp.

2907{
2908 OksKernel * k = uid.class_id->p_kernel;
2909
2910 if(k->p_delete_object_notify_fn) {
2911 (*k->p_delete_object_notify_fn)(this, k->p_delete_object_notify_param);
2912 }
2913}

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

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

◆ find_path()

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

Definition at line 936 of file query.cpp.

937{
938 OksObject::List * path = new OksObject::List();
939
940 if(satisfies(query.get_goal_object(), *query.get_start_expression(), *path) == false) {
941 delete path;
942 path = 0;
943 }
944
945 return path;
946}
std::list< OksObject * > List
Definition object.hpp:875
bool satisfies(const OksObject *goal, const oks::QueryPathExpression &expresssion, OksObject::List &path) const
Definition query.cpp:950

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

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

◆ get_change_notify()

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

Definition at line 2869 of file object.cpp.

2870{
2871 return uid.class_id->p_kernel->p_change_object_notify_fn;
2872}

◆ get_file()

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

Get file of object.

Definition at line 1013 of file object.hpp.

1013{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 1358 of file object.hpp.

1358{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 1062 of file object.hpp.

1062{ 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 1919 of file object.cpp.

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

◆ GetClass()

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

Get class of object.

Definition at line 990 of file object.hpp.

990{return uid.class_id;}

◆ GetId()

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

Get object ID.

Definition at line 995 of file object.hpp.

995{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 1095 of file object.hpp.

1095{ 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 2004 of file object.cpp.

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

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

1343{return p_user_data;}

◆ init1()

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

Definition at line 182 of file object.cpp.

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

◆ init2()

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

Definition at line 275 of file object.cpp.

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

◆ init3() [1/2]

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

Definition at line 321 of file object.cpp.

322{
323 init3(const_cast<OksClass *>(uid.class_id));
325}

◆ init3() [2/2]

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

Definition at line 310 of file object.cpp.

311{
312 if( __builtin_expect((c->p_indices != nullptr), 0) ) {
313 for(auto& i : *c->p_indices) i.second->insert(this);
314 }
315
316 c->add(this);
317 c->p_kernel->define(this);
318}

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

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

◆ is_duplicated()

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

Definition at line 1390 of file object.hpp.

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

◆ notify()

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

Definition at line 1475 of file object.hpp.

1475 {
1476 file->set_updated();
1477 change_notify();
1478 }

◆ operator delete()

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

Fast delete operator.

Definition at line 965 of file object.hpp.

965{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 960 of file object.hpp.

960{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 1612 of file object.cpp.

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

◆ put()

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

Definition at line 1780 of file object.cpp.

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

◆ put_object_attributes()

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

Definition at line 1754 of file object.cpp.

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

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

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

◆ read_body()

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

Definition at line 513 of file object.cpp.

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

◆ references()

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

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

Definition at line 3110 of file object.cpp.

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

◆ remove_RCR()

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

Definition at line 2602 of file object.cpp.

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

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

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

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

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

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

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

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

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

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

1310{return p_rcr;}

◆ satisfies()

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

Definition at line 950 of file query.cpp.

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

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

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

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

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

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

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

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

1351{p_int32_id = object_id;}

◆ set_unique_id()

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

Definition at line 139 of file object.cpp.

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

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

◆ SetAttributeValue() [2/2]

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

Set value of attribute by name.

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

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

The parameters are:

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

Definition at line 1990 of file object.cpp.

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

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

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

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

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

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

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

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

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

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

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

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

1335{p_user_data = d;}

◆ unbind_file()

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

Definition at line 2825 of file object.cpp.

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

Friends And Related Symbol Documentation

◆ oks::ReadFileParams

friend struct oks::ReadFileParams
friend

Definition at line 843 of file object.hpp.

◆ oks::ReloadObjects

friend struct oks::ReloadObjects
friend

Definition at line 844 of file object.hpp.

◆ OksClass

friend class OksClass
friend

Definition at line 837 of file object.hpp.

◆ OksData

friend struct OksData
friend

Definition at line 838 of file object.hpp.

◆ OksIndex

friend class OksIndex
friend

Definition at line 840 of file object.hpp.

◆ OksKernel

friend class OksKernel
friend

Definition at line 839 of file object.hpp.

◆ OksLoadObjectsJob

friend struct OksLoadObjectsJob
friend

Definition at line 842 of file object.hpp.

◆ OksObjectSortBy

friend class OksObjectSortBy
friend

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

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

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

1635{
1636 s << '\"';
1637
1638 if(o)
1639 s << o->GetId() << '@' << o->GetClass()->get_name();
1640 else
1641 s << "(null-obj)";
1642
1643 s << '\"';
1644
1645 return s;
1646}

Member Data Documentation

◆ attribute_xml_tag

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

Definition at line 1515 of file object.hpp.

◆ class2_xml_attribute

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

Definition at line 1518 of file object.hpp.

◆ class_xml_attribute

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

Definition at line 1517 of file object.hpp.

◆ data

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

Definition at line 1405 of file object.hpp.

◆ data_xml_tag

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

Definition at line 1526 of file object.hpp.

◆ file

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

Definition at line 1410 of file object.hpp.

◆ id2_xml_attribute

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

Definition at line 1520 of file object.hpp.

◆ id_xml_attribute

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

Definition at line 1519 of file object.hpp.

◆ name_xml_attribute

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

Definition at line 1521 of file object.hpp.

◆ num_xml_attribute

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

Definition at line 1523 of file object.hpp.

◆ obj2_xml_tag

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

Definition at line 1514 of file object.hpp.

◆ obj_xml_tag

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

Definition at line 1513 of file object.hpp.

◆ p_duplicated_object_id_idx

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

Definition at line 1409 of file object.hpp.

◆ p_int32_id

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

Definition at line 1408 of file object.hpp.

◆ p_rcr

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

Definition at line 1406 of file object.hpp.

◆ p_user_data

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

Definition at line 1407 of file object.hpp.

◆ ref_xml_tag

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

Definition at line 1527 of file object.hpp.

◆ relationship_xml_tag

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

Definition at line 1516 of file object.hpp.

◆ type_xml_attribute

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

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


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