21 #include "dabc/defines.h"
45 Stream(s, version, hlimit);
51 uint64_t pos = s.
size();
54 uint32_t storesz(0), storenum(0), storevers(0);
57 sz = s.
is_real() ? StoreSize(version, hlimit) : 0;
61 if ((hlimit>0) && (fArr.Size() > (
unsigned) hlimit)) first = fArr.Size() - hlimit;
63 bool cross_boundary =
false;
64 for (
unsigned n=first; n<fArr.Size();n++) {
66 if ((version>0) && (fArr.Item(n).version <= version)) {
67 cross_boundary = fArr.Item(n).version < version;
76 uint64_t mask = cross_boundary ? 1 : 0;
79 for (uint32_t n=first;n<fArr.Size();n++) {
80 if ((version>0) && (fArr.Item(n).version <= version))
continue;
81 fArr.Item(n).fields->Stream(s);
86 sz = ((uint64_t) storesz) * 8;
89 storenum = storenum & 0xffffff;
93 fCrossBoundary = (mask & 1) != 0;
95 if (fArr.Capacity()==0)
96 fArr.Allocate((
int)storenum > hlimit ? (int) storenum : hlimit);
98 for (uint32_t n=0;n<storenum;n++) {
102 if (fArr.Full()) fArr.PopOnly();
115 if (
null())
return false;
118 bool cross_boundary = GetObject()->fCrossBoundary;
121 if ((res.
hlimit()>0) && (GetObject()->fArr.Size() > res.
hlimit()))
122 first = GetObject()->fArr.Size() - res.
hlimit();
124 for (
unsigned n=first; n < GetObject()->fArr.Size();n++)
125 if (GetObject()->fArr.Item(n).version < res.
version())
126 { cross_boundary =
true;
break; }
134 for (
unsigned n=first; n < GetObject()->fArr.Size();n++) {
166 fNamesChanged(false),
167 fChildsChanged(false),
168 fDisableDataReading(false),
169 fDisableChildsReading(false),
170 fDisableReadingAsChild(false),
175 #ifdef DABC_EXTRA_CHECKS
176 DebugObject(
"Hierarchy",
this, 1);
184 #ifdef DABC_EXTRA_CHECKS
185 DebugObject(
"Hierarchy",
this, -1);
190 if (fHierarchyMutex!=0) {
191 delete fHierarchyMutex;
199 if (fHierarchyMutex==0) fHierarchyMutex =
new Mutex;
208 if (top==0)
return parent;
212 EOUT(
"Should never happen");
219 Stream(s, kind, version, hlimit);
230 uint64_t pos = s.
size();
233 uint32_t storesz(0), storenum(0), storevers(0);
238 bool store_fields(
true), store_childs(
true), store_history(
false), store_diff(
false);
239 std::string fields_prefix;
244 store_fields = fNamesVersion >= version;
245 store_childs = fNamesVersion >= version;
246 store_history =
false;
247 store_diff = store_fields;
251 store_childs =
false;
252 store_history = !fHist.null() && (hlimit>0);
256 store_fields = fNodeVersion >= version;
257 store_childs = fChildsVersion >= version;
258 store_history = !fHist.null() && (hlimit>0);
262 DOUT2(
"STORE %20s num_childs %u store %6s namesv %u nodevers %u childsvers %u", GetName(), NumChilds(),
DBOOL(store_childs), fNamesVersion, fNodeVersion, fChildsVersion);
264 uint64_t mask = (store_fields ? maskFieldsStored : 0) |
265 (store_childs ? maskChildsStored : 0) |
266 (store_diff ? maskDiffStored : 0) |
267 (store_history ? maskHistory : 0);
269 sz = s.
is_real() ? StoreSize(kind, version, hlimit) : 0;
274 if (store_childs) storenum = ((uint32_t) NumChilds());
275 storenum = storenum | (storevers<<24);
282 if (store_fields) Fields().Stream(s, fields_prefix);
284 if (store_history) fHist()->Stream(s, version, hlimit);
287 for (
unsigned n=0;n<NumChilds();n++) {
289 if (child==0)
continue;
291 child->
Stream(s, kind, version, hlimit);
299 sz = ((uint64_t) storesz)*8;
302 storenum = storenum & 0xffffff;
307 if (mask & maskFieldsStored) {
308 if (fDisableDataReading) {
310 EOUT(
"FAIL to skip fields part in the streamer for %s", ItemName().c_str());
312 DOUT3(
"SKIP FIELDS in %s", ItemName().c_str());
316 if (mask & maskDiffStored) { prefix =
"_"; fNamesChanged =
true; }
317 Fields().Stream(s, prefix);
321 if (mask & maskHistory) {
322 if (fDisableDataReading) {
324 EOUT(
"FAIL to skip history part in the streamer");
326 DOUT3(
"SKIP HISTORY in %s", ItemName().c_str());
328 if (fHist.null()) fHist.Allocate();
329 fHist()->Stream(s, version, hlimit);
333 if (mask & maskChildsStored) {
338 fChildsChanged =
true;
344 for (
unsigned srcnum=0; srcnum<storenum; srcnum++) {
346 std::string childname;
349 if (fDisableChildsReading) {
351 EOUT(
"FAIL to skip child %s in %s", childname.c_str(), ItemName().c_str());
353 DOUT0(
"SKIP CHILD %s in %s", childname.c_str(), ItemName().c_str());
360 unsigned findindx = candeletechilds ? tgtcnt : 0;
361 while (findindx<NumChilds()) {
362 if (
GetChild(findindx)->IsName(childname.c_str())) {
374 AddChildAt(child, tgtcnt);
378 while (findindx-- > tgtcnt) RemoveChildAt(tgtcnt,
true);
383 EOUT(
"FAIL to skip item %s completely", child->
ItemName().c_str());
387 child->
Stream(s, kind, version, hlimit);
395 while (tgtcnt < NumChilds()) RemoveChildAt(tgtcnt,
true);
408 fFields->SaveTo(res);
425 for (
unsigned n=0;n<NumChilds();n++) {
427 if (child==0)
continue;
443 if (node) fNodeChanged =
true;
444 if (hierarchy) fChildsChanged =
true;
446 for (
unsigned n=0;n<NumChilds();n++) {
448 if (child) child->
SetModified(node, hierarchy, recursive);
455 Fields().CopyFrom(cont->
Fields(),
true);
458 if (!fNodeChanged) fNodeChanged = Fields().WasChanged();
460 for (
unsigned n=0;n<cont->
NumChilds();n++) {
472 return fChildsChanged || fNodeChanged;
478 fNodeChanged =
false;
479 fChildsChanged =
false;
487 Fields().MoveFrom(cont->
Fields());
488 if (Fields().WasChanged()) fNodeChanged =
true;
498 while ((cnt1 < cont->NumChilds()) || (cnt2 < NumChilds())) {
500 RemoveChildAt(cnt2,
true);
501 fChildsChanged =
true;
506 if (cont_child.
null()) {
511 bool findchild(
false);
512 unsigned findindx(0);
514 for (
unsigned n=cnt2;n<NumChilds();n++)
527 cont_child()->SetModified(
true,
true,
true);
529 AddChildAt(cont_child(), cnt2);
531 fChildsChanged =
true;
537 while (findindx > cnt2) { RemoveChildAt(cnt2,
true); findindx--; fChildsChanged =
true; }
552 return fChildsChanged || fNodeChanged;
557 while ((indx>=0) && (indx<(
int) NumChilds())) {
559 if (child->
IsName(name.c_str()))
return child;
560 RemoveChildAt(indx,
true);
576 FillFullName(res, 0,
true);
583 if (top.
null())
return;
585 top()->BuildFieldsMap(&Fields());
587 if (top()->IsChildsHidden())
return;
592 for (
unsigned n=0;n<chlds.
GetSize();n++) {
594 if (chlds[n].GetObject()->IsHidden())
continue;
605 if (fHist.Capacity()==0)
return;
606 if (fHist()->fArr.Full()) fHist()->fArr.PopOnly();
614 if (fHist.Capacity()<=step)
return false;
616 RecordFieldsMap* hfields = fHist()->fArr.Item(fHist.Capacity()-step-1).fields;
626 if (fHist.Capacity()==0)
return;
627 while (fHist()->fArr.Size() > 0) fHist()->fArr.PopOnly();
633 if (fNodeChanged || fChildsChanged)
return true;
635 if (Fields().WasChanged()) { fNodeChanged =
true;
return true; }
638 for (
unsigned indx=0; indx < NumChilds(); indx++) {
641 fChildsChanged =
true;
651 if (!fHist.null())
return fHist.DoHistory();
654 while (prnt !=
nullptr) {
658 fHist()->fEnabled =
true;
659 fHist()->fChildsEnabled =
true;
680 for (
unsigned indx=0; indx < NumChilds(); indx++) {
682 if (child) child->
MarkReading(withchilds, readvalues, readchilds);
685 fDisableDataReading = !readvalues;
686 fDisableChildsReading = !readchilds;
695 for (
unsigned indx=0; indx < NumChilds(); indx++) {
700 if (mask != 0) fNodeChanged =
true;
707 bool fields_were_chaneged = Fields().WasChanged();
709 if (fields_were_chaneged) {
711 if (Fields().WasChangedWith(
"_")) fNamesChanged =
true;
716 if (fNodeChanged) { fNodeVersion = ver; mask = mask |
change_Value; }
717 if (fNamesChanged) { fNamesVersion = ver; mask = mask |
change_Names; }
718 if (fChildsChanged) { fChildsVersion = ver; mask = mask |
change_Childs; }
720 if (fNodeChanged && fAutoTime) {
725 if (CheckIfDoingHistory() && fields_were_chaneged) {
730 if (prev !=
nullptr) {
735 fHist()->fPrev = Fields().Clone();
739 Fields().ClearChangeFlags();
740 fNodeChanged =
false;
741 fNamesChanged =
false;
742 fChildsChanged =
false;
763 uint64_t next_ver = GetNextVersion();
766 unsigned mask = MarkVersionIfChanged(next_ver, tm,
true);
768 if (mask == 0)
return;
786 for (
unsigned indx=0; indx < NumChilds(); indx++) {
797 if (
null()) Create(
"Objects");
798 GetObject()->BuildObjectsHierarchy(top);
811 EOUT(
"Hierarchy structure MUST exist at this moment");
815 if (GetObject()->UpdateHierarchyFrom(src()))
816 GetObject()->MarkChangedItems();
823 if (src.
null())
return true;
826 EOUT(
"Hierarchy structure MUST exist at this moment");
830 if (GetObject()->DuplicateHierarchyFrom(src()))
831 GetObject()->MarkChangedItems();
841 if (length>0) GetObject()->EnableTimeRecording(withchilds);
843 if (GetObject()->fHist.Capacity() != length) {
845 GetObject()->fHist.Allocate(length);
846 GetObject()->fHist()->fEnabled =
true;
847 GetObject()->fHist()->fChildsEnabled = withchilds;
850 GetObject()->fHist.Release();
859 return null() ?
false : GetObject()->fHist.DoHistory();
865 if (
null() || (GetObject()->fHist.Capacity() == 0))
return false;
868 return ((GetObject()->fHist()->fRemoteReqVersion > 0) &&
869 (GetObject()->fHist()->fLocalReqVersion == GetObject()->GetVersion()));
877 uint64_t size = GetObject()->StoreSize(kind, version, hlimit);
880 if (res.
null())
return res;
884 if (GetObject()->Stream(outs, kind, version, hlimit)) {
886 if (size != outs.
size()) {
EOUT(
"Sizes mismatch %lu %lu", (
long unsigned) size, (
long unsigned) outs.
size()); }
898 if (buf.
null())
return false;
902 if (
null()) Create(
"RAW");
904 if (!GetObject()->Stream(inps)) {
905 EOUT(
"Cannot reconstruct hierarchy from the binary data!");
914 if (buf.
null())
return false;
917 EOUT(
"Hierarchy must be created before it can be updated");
923 if (!GetObject()->Stream(inps, kind)) {
924 EOUT(
"Cannot reconstruct hierarchy from the binary data!");
928 GetObject()->MarkChangedItems();
951 size_t pos = name.rfind(
"/");
952 if ((pos != std::string::npos) && !allowslahes) {
953 if (pos==0)
return GetHChild(name.substr(1), allowslahes, force, sortorder);
954 if (pos==name.length()-1)
return GetHChild(name.substr(0, name.length()-1), allowslahes, force, sortorder);
955 return GetHChild(name.substr(0, pos), allowslahes, force, sortorder).GetHChild(name.substr(pos+1), allowslahes, force, sortorder);
958 std::string itemname = name;
959 if (pos != std::string::npos) itemname = itemname.substr(pos+1);
960 if (itemname.empty()) itemname =
"item";
963 while ((pos = itemname.find_first_of(
"#:&?")) != std::string::npos)
964 itemname.replace(pos, 1,
"_");
966 if (itemname == name) {
971 }
else if (res.
null() && !force) {
978 for (
unsigned n=0;n<NumChilds();n++) {
981 std::string realname = res.
GetName();
985 if (realname == name)
return res;
987 if (sortorder && (first_big < 0) && (realname > name))
993 if (itemname != name) {
994 unsigned cnt = NumChilds();
995 std::string basename = itemname;
998 while (!FindChild(itemname.c_str()).null())
999 itemname = basename + std::to_string(cnt++);
1004 if (!sortorder || (first_big < 0))
1007 GetObject()->AddChildAt(res.
GetObject(), first_big);
1009 if (itemname != name)
1021 if (h.
null())
return false;
1025 while (!prnt.
null() && (prnt() != GetObject())) {
1043 return GetParent()->FindChildRef(masteritem.c_str());
1049 if (
null())
return false;
1052 if (itemname.empty()) item = *
this;
else item = FindChild(itemname.c_str());
1055 if (item.
null())
return true;
1058 if (hash==0)
return true;
1066 return (last_version==0) || (last_version<item.
GetVersion());
1072 if (
null())
return false;
1075 if (itemname.empty()) item = *
this;
1076 else item = FindChild(itemname.c_str());
1078 if (item.
null() && !dflt_master_name.empty()) {
1079 master = FindChild(dflt_master_name.c_str());
1080 DOUT2(
"Found default master %s res = %p", dflt_master_name.c_str(), master());
1101 std::string producer_name;
1104 while (!parent.
null()) {
1107 request_name = RelativeName(parent);
1108 if (!topmost)
break;
1113 return producer_name;
1120 if (h.
null())
return false;
1124 while (!prnt.
null() && (prnt() != GetObject())) {
1135 if (
null())
return std::string();
1136 return GetObject()->ItemName();
1144 if (prnt == 0)
break;
1154 return prnt ? prnt->
RemoveChild(GetObject(),
false) :
true;
1159 if (!
null()) GetObject()->MarkReading(withchlds,
false,
false);
1164 if (!
null()) GetObject()->fDisableReadingAsChild =
true;
1170 GetObject()->MarkReading(
false,
true,
true);
1172 if (upto.
null())
return;
1176 while (!prnt.
null()) {
1177 prnt()->MarkReading(
false,
false,
true);
1178 if (prnt == upto)
break;
1233 return cont ? cont->
next() :
false;
Reference on memory from memory pool.
unsigned SegmentSize(unsigned n=0) const
Returns size on the segment, no any boundary checks.
void SetTotalSize(BufferSize_t len)
Set total length of the buffer to specified value Size cannot be bigger than original size of the buf...
static Buffer CreateBuffer(BufferSize_t sz)
This static method create independent buffer for any other memory pools Therefore it can be used in s...
void * SegmentPtr(unsigned n=0) const
Returns pointer on the segment, no any boundary checks.
Represents command with its arguments.
bool SetUInt(const std::string &name, unsigned v)
Class for holding GMT time with precision of nanoseconds.
uint64_t AsJSDate() const
Return date and time in JS format - number of millisecond since 1.1.1970.
class, used for direct store of records in JSON/XML form
void CloseNode(const char *nodename)
void SetField(const char *name, const char *value)
void BeforeNextChild(const char *basename=0)
void CreateNode(const char *nodename)
bool fChildsChanged
indicate if something was changed in the hierarchy
HierarchyContainer(const std::string &name)
uint64_t GetNextVersion() const
unsigned MarkVersionIfChanged(uint64_t ver, uint64_t &tm, bool withchilds)
If item changed, marked with version, time stamp applied, history recording returns mask with changes...
void AddHistory(RecordFieldsMap *diff)
Add new entry to history.
bool CheckIfDoingHistory()
Return true if history activated for the node If necessary, history object will be initialized.
History fHist
special object with history data
void ClearHistoryEntries()
Clear all entries in history, but not history object itself.
HierarchyContainer * TopParent()
bool ExtractHistoryStep(RecordFieldsMap *fields, unsigned step)
Extract values of specified history step.
HierarchyContainer * CreateChildAt(const std::string &name, int indx)
Create child with specified name.
bool fNodeChanged
indicate if something was changed in the node during update
void SetModified(bool node, bool hierarchy, bool recursive=false)
Switch on node or hierarchy modified flags.
uint64_t GetVersion() const
bool DuplicateHierarchyFrom(HierarchyContainer *cont)
Duplicate hierarchy from provided container.
void MarkReading(bool withchilds, bool readvalues, bool readchilds)
Mark reading flags.
void EnableTimeRecording(bool withchilds=true)
Enable time recording for hierarchy element every time when item is changed.
virtual ~HierarchyContainer()
bool UpdateHierarchyFrom(HierarchyContainer *cont)
Update hierarchy from provided container.
bool Stream(iostream &s, unsigned kind=stream_Full, uint64_t v=0, unsigned hist_limit=0)
bool fDisableReadingAsChild
when true, object will not be updated when provided as child
virtual bool SaveTo(HStore &res, bool create_node=true)
Save hierarchy in json/xml form.
bool fNamesChanged
indicate if DNS structure was changed (either childs or relevant dabc fields)
void BuildObjectsHierarchy(const Reference &top)
void MarkChangedItems(uint64_t tm=0)
Central method, which analyzes all possible changes in node (and its childs) If any changes found,...
bool IsNodeChanged(bool withchilds=true)
Returns true if any node field was changed or removed/inserted If specified, all childs will be check...
uint64_t StoreSize(unsigned kind=stream_Full, uint64_t v=0, unsigned hist_limit=0)
Represents objects hierarchy of remote (or local) DABC process.
bool IsBinItemChanged(const std::string &itemname, uint64_t hash, uint64_t last_version=0)
Return true if one could suppose that binary item is changed and binary data must be regenerated.
void DisableReading(bool withchlds=true)
Mark all elements that non of data will be read.
bool FillBinHeader(const std::string &itemname, dabc::Command &cmd, uint64_t mhash=0, const std::string &dflt_master_name="")
Fill binary header with item and master versions.
Hierarchy GetTop() const
Returns reference on the top element of the hierarchy.
void DisableReadingAsChild()
Disable reading of element when it appears as child in the structure.
Hierarchy FindMaster() const
Find master item It is used in ROOT to specify position of streamer info.
bool HasLocalHistory() const
Returns true if item records history local, no need to request any other sources.
void MarkChangedItems(uint64_t tm=0)
If any field was modified, item will be marked with new version.
uint64_t GetVersion() const
Returns actual version of hierarchy entry.
bool Duplicate(const Hierarchy &src)
Duplicate hierarchy from the source.
bool RemoveHChild(const std::string &name, bool allowslahes=false)
Delete H item, including all empty parent folders.
std::string ItemName() const
Name which is used as item name in hierarchy.
bool DettachFromParent()
Detach from parent object.
const RecordField & Field(const std::string &name) const
Hierarchy GetHChild(const std::string &name, bool allowslahes=false, bool force=false, bool sortorder=false)
Return child, if necessary creates with full subfolder If force specified, missing childs and folders...
HistoryIter MakeHistoryIter()
Produce history iterator.
bool RemoveEmptyFolders(const std::string &path)
Removes folder and its parents as long as no other childs are present.
void EnableReading(const Hierarchy &upto=nullptr)
Enable element and all its parents to read data.
void Create(const std::string &name, bool withmutex=false)
Create top-level object with specified name.
std::string FindBinaryProducer(std::string &request_name, bool topmost=true)
Search for parent element, where binary_producer property is specified Returns name of binary produce...
bool UpdateFromBuffer(const dabc::Buffer &buf, HierarchyStreamKind kind=stream_Full)
Apply modification to hierarchy, using stored binary data
bool HasActualRemoteHistory() const
Returns true if remote history is recorded and it is up-to-date.
bool ReadFromBuffer(const dabc::Buffer &buf)
Read hierarchy from buffer.
bool Update(Hierarchy &src)
Reconstruct complete hierarchy, setting node/structure modifications fields correctly.
void BuildNew(Reference top)
Build objects hierarchy, referenced by top.
void EnableHistory(unsigned length=100, bool withchilds=false)
Activate history production for selected element and its childs.
bool Stream(iostream &s, uint64_t version, int hist_limit=-1)
uint64_t StoreSize(uint64_t version, int hist_limit=-1)
HistoryIterContainer(Hierarchy &src)
unsigned Capacity() const
Base class for most of the DABC classes.
bool RemoveChild(Object *child, bool cleanup=true)
Detach child from parent object If cleanup==true and parent is owner of child, child will be destroye...
bool IsName(const char *str) const
Checks if object name is same as provided string, thread safe
Object * GetParent() const
Returns pointer on parent object, thread safe
const char * GetName() const
Returns name of the object, thread safe
unsigned NumChilds() const
returns number of child objects
Object * GetChild(unsigned n) const
returns pointer on child object
Container for records fields.
void SetFieldsMap(RecordFieldsMap *newmap)
Replaces existing fields map.
RecordFieldsMap & Fields() const
uint64_t AsUInt(uint64_t dflt=0) const
std::string AsStr(const std::string &dflt="") const
void ApplyDiff(const RecordFieldsMap &diff)
Apply diff map One should use fields, generated with MakeAsDiffTo call.
void MakeAsDiffTo(const RecordFieldsMap &src)
In the map only modified fields are remained Also dabc:delete field can appear which marks all remove...
bool Stream(iostream &s, const std::string &nameprefix="")
bool SaveTo(HStore &res)
Save all field in json format.
dabc::Buffer SaveToBuffer()
bool SetFieldProtected(const std::string &name, bool on=true)
RecordField GetField(const std::string &name) const
bool HasField(const std::string &name) const
bool SetField(const std::string &name, const RecordField &v)
Reference on the arbitrary object
void Release()
Releases reference on the object.
const char * GetName() const
Return name of referenced object, if object not assigned, returns "---".
Reference GetParentRef() const
Returns reference on parent object.
Object * GetObject() const
Return pointer on the object.
bool GetAllChildRef(ReferencesVector *vect) const
Return references for all childs.
unsigned NumChilds() const
Return number of childs in referenced object.
bool null() const
Returns true if reference contains nullptr.
void Destroy()
Release reference and starts destroyment of referenced object.
Vector of dabc::Reference objects.
unsigned GetSize() const
Returns number of items in vector.
class to stream binary data
bool write_uint32(uint32_t v)
virtual bool is_real() const
bool read_uint64(uint64_t &v)
bool read_uint32(uint32_t &v)
virtual uint64_t size() const
return number of bytes, written or read from the stream
bool skip_object()
Insted of reading object we read size and shift on that size Only can be done where size stored as 32...
bool write_uint64(uint64_t v)
bool read_str(std::string &str)
Restore string from the stream.
bool write_str(const std::string &str)
Store string in the stream.
bool verify_size(uint64_t pos, uint64_t sz)
iostream class, which write and read data from memory
virtual uint64_t size() const
return number of bytes, written or read from the stream
special class only to define how many data will be written to the stream
virtual uint64_t size() const
return number of bytes, written or read from the stream
XMLNodePointer_t GetParent(XMLNodePointer_t xmlnode)
void AddChild(XMLNodePointer_t parent, XMLNodePointer_t child)
XMLNodePointer_t GetChild(XMLNodePointer_t xmlnode)
const char * prop_realname
std::string format(const char *fmt,...)
const char * prop_masteritem
const char * xmlTrueValue
const char * prop_producer
const char * prop_history
const char * prop_version
uint64_t version
version number
RecordFieldsMap * fields
all fields, which are preserved