DABC (Data Acquisition Backbone Core)  2.9.9
Object.cxx
Go to the documentation of this file.
1 // $Id: Object.cxx 4482 2020-04-15 14:47:18Z linev $
2 
3 /************************************************************
4  * The Data Acquisition Backbone Core (DABC) *
5  ************************************************************
6  * Copyright (C) 2009 - *
7  * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
8  * Planckstr. 1, 64291 Darmstadt, Germany *
9  * Contact: http://dabc.gsi.de *
10  ************************************************************
11  * This software can be used under the GPL license *
12  * agreements as stated in LICENSE.txt file *
13  * which is part of the distribution. *
14  ************************************************************/
15 
16 #include "dabc/Object.h"
17 
18 #include <cstdlib>
19 #include <fnmatch.h>
20 
21 #include "dabc/Manager.h"
22 #include "dabc/ReferencesVector.h"
23 
24 unsigned dabc::Object::gNumInstances = 0;
25 unsigned dabc::Object::gNumCreated = 0;
26 
27 namespace dabc {
28 
29 
30  const char* xmlDeviceNode = "Device";
31  const char* xmlThreadNode = "Thread";
32  const char* xmlMemoryPoolNode = "MemoryPool";
33  const char* xmlModuleNode = "Module";
34  const char* xmlConnectionNode = "Connection";
35 
36  const char* xmlQueueAttr = "queue";
37  const char* xmlBindAttr = "bind";
38  const char* xmlSignalAttr = "signal";
39  const char* xmlRateAttr = "rate";
40  const char* xmlLoopAttr = "loop";
41  const char* xmlInputQueueSize = "InputQueueSize";
42  const char* xmlOutputQueueSize = "OutputQueueSize";
43  const char* xmlInlineDataSize = "InlineDataSize";
44 
45  const char* xmlPoolName = "PoolName";
46  const char* xmlWorkPool = "Pool";
47  const char* xmlFixedLayout = "FixedLayout";
48  const char* xmlCleanupTimeout = "CleanupTimeout";
49  const char* xmlBufferSize = "BufferSize";
50  const char* xmlNumBuffers = "NumBuffers";
51  const char* xmlAlignment = "Alignment";
52  const char* xmlShowInfo = "ShowInfo";
53 
54  const char* xmlNumInputs = "NumInputs";
55  const char* xmlNumOutputs = "NumOutputs";
56  const char* xmlInputPrefix = "Input";
57  const char* xmlInputMask = "Input%u";
58  const char* xmlOutputPrefix = "Output";
59  const char* xmlOutputMask = "Output%u";
60  const char* xmlUseAcknowledge = "UseAcknowledge";
61  const char* xmlFlushTimeout = "FlushTimeout";
62  const char* xmlConnTimeout = "ConnTimeout";
63 
64  const char* xmlMcastAddr = "McastAddr";
65  const char* xmlMcastPort = "McastPort";
66  const char* xmlMcastRecv = "McastRecv";
67 
68  const char* xmlProtocol = "Protocol";
69  const char* xmlHostName = "HostName";
70  const char* xmlFileName = "FileName";
71  const char* xmlFileNumber = "FileNumber";
72  const char* xmlFileSizeLimit = "FileSizeLimit";
73  const char* xml_maxsize = "maxsize";
74  const char* xml_number = "number";
75  const char* xml_flush = "flush";
76 
77  const char* typeThread = "dabc::Thread";
78  const char* typeDevice = "dabc::Device";
79  const char* typeSocketDevice = "dabc::SocketDevice";
80  const char* typeSocketThread = "dabc::SocketThread";
81  const char* typeApplication = "dabc::Application";
82 
83 
84 #ifdef DABC_EXTRA_CHECKS
85  PointersVector gObjectGarbageCollector;
86  Mutex gObjectGarbageMutex;
87 #endif
88 
89 }
90 
103 dabc::Object::Object(const std::string &name, unsigned flags) :
104  fObjectFlags(flags),
105  fObjectParent(),
106  fObjectName(name),
107  fObjectMutex(0),
108  fObjectRefCnt(0),
109  fObjectChilds(0),
110  fObjectBlock(0)
111 {
112  DOUT5("Created object %s %p", GetName(), this);
113 
114  Constructor();
115 }
116 
117 dabc::Object::Object(Reference parent, const std::string &name, unsigned flags) :
118  fObjectFlags(flags),
119  fObjectParent(parent),
120  fObjectName(name),
121  fObjectMutex(0),
122  fObjectRefCnt(0),
123  fObjectChilds(0),
124  fObjectBlock(0)
125 {
126  DOUT5("Object created %s %p", GetName(), this);
127 
128  Constructor();
129 }
130 
131 
132 dabc::Object::Object(const ConstructorPair& pair, unsigned flags) :
133  fObjectFlags(flags),
134  fObjectParent(pair.parent),
135  fObjectName(pair.name),
136  fObjectMutex(0),
137  fObjectRefCnt(0),
138  fObjectChilds(0),
139  fObjectBlock(0)
140 {
141  DOUT5("Object created %s %p", GetName(), this);
142 
143  Constructor();
144 }
145 
146 
148 {
149  Destructor();
150 
151  DOUT5("Object destroyed %s %p", GetName(), this);
152 }
153 
155 {
156  LockGuard lock(fObjectMutex);
157  SetFlag(flIsOwner, on);
158 }
159 
161 {
162  LockGuard lock(fObjectMutex);
163  SetFlag(flAutoDestroy, on);
164 }
165 
166 
168 {
169  LockGuard lock(fObjectMutex);
170  return GetFlag(flIsOwner);
171 }
172 
174 {
175  LockGuard lock(fObjectMutex);
176  return GetFlag(flLogging);
177 }
178 
180 {
181  LockGuard lock(fObjectMutex);
182  return GetFlag(flChildsHidden);
183 }
184 
186 {
187  LockGuard lock(fObjectMutex);
188  return GetFlag(flTopXmlLevel);
189 }
190 
192 {
193  LockGuard lock(fObjectMutex);
194  return GetFlag(flHidden);
195 }
196 
198 {
199  LockGuard lock(fObjectMutex);
200  return SetFlag(flLogging, on);
201 }
202 
203 bool dabc::Object::IsName(const char* str, int len) const
204 {
205  if ((len==0) || (str==0)) return false;
206  if (len<0) return fObjectName.compare(str) == 0;
207  return ((int) fObjectName.length()==len) && (fObjectName.compare(0, len, str,len) == 0);
208 }
209 
211 {
212  gNumInstances++;
213 
214  // use non-recursive mutexes to see faster deadlock problems
215  // FIXME: should we use recursive in final version?
216 
217  if (!GetFlag(flNoMutex))
218  fObjectMutex = new Mutex(false);
219 
220  SetState(stNormal);
221 
222  fObjectParent.AddChild(this);
223 }
224 
226 {
227  #ifdef DABC_EXTRA_CHECKS
228  {
229  LockGuard lock(gObjectGarbageMutex);
230  gObjectGarbageCollector.remove(this);
231  }
232  #endif
233 
234  Mutex* m = 0;
235  bool delchilds = false;
236 
237  {
238  LockGuard lock(fObjectMutex);
239 
240  if ((GetState() != stDestructor) && (fObjectRefCnt!=0)) {
241  EOUT("Object %p %s deleted not via Destroy method refcounter %u", this, GetName(), fObjectRefCnt);
242  }
243 
244  SetState(stDestructor);
245 
246  if (fObjectRefCnt!=0) {
247  EOUT("!!!!!!!!!!!! Destructor called when refcounter %u obj:%s %p", fObjectRefCnt, GetName(), this);
248 // Object* obj = (Object*) 29387898;
249 // delete obj;
250  }
251 
252  if (fObjectChilds!=0) {
253 
254  if (fObjectChilds->GetSize() > 0)
255  EOUT("!!!!!!! CHILDS %u ARE NOT DELETED completely obj:%s %p", fObjectChilds->GetSize(), GetName(), this);
256 
257  if (fObjectBlock > 0)
258  EOUT("!!!! CHILDS ARE STILL BLOCKED %d!!!!!!!", fObjectBlock);
259 
260  delchilds = true;
261  }
262 
263  m = fObjectMutex;
264  fObjectMutex = 0;
265  }
266 
267  if (delchilds) RemoveChilds();
268 
269  // release reference on parent, remove from child should be already done
270  fObjectParent.Release();
271 
272  // destroy mutex
273  delete m; m=0;
274 
275  gNumInstances--;
276 }
277 
278 bool dabc::Object::IncReference(bool withmutex)
279 {
280  dabc::LockGuard lock(withmutex ? fObjectMutex : 0);
281 
282  if (GetState() == stDestructor) {
283  EOUT("OBJ:%p %s Inc reference during destructor", this, GetName());
284  return false;
285 // EOUT("Obj:%p %s Class:%s IncReference %u inside destructor :(",
286 // this, GetName(), ClassName(), fObjectRefCnt);
287  }
288 
289  fObjectRefCnt++;
290 
291  if (GetFlag(flLogging))
292  DOUT0("Obj:%s %p Class:%s IncReference +----- %u thrd:%s", GetName(), this, ClassName(), fObjectRefCnt, dabc::mgr.CurrentThread().GetName());
293 
294  return true;
295 }
296 
298 {
299  dabc::LockGuard lock(fObjectMutex);
300  SetFlag(flCleanup, true);
301 }
302 
304 {
305  return GetState() == stNormal;
306 }
307 
308 
310 {
311  dabc::LockGuard lock(fObjectMutex);
312 
313  return _IsNormalState();
314 }
315 
316 
317 bool dabc::Object::DecReference(bool ask_to_destroy, bool do_decrement, bool from_thread)
318 {
319  // check destroyment before we lock the mutex
320  // if method returns true, object destructor should follow
321 
322  bool viathrd = false;
323 
324  {
325  dabc::LockGuard lock(fObjectMutex);
326 
327 // if (GetFlag(flLogging)) {
328 // DOUT0("Call DecReference for object %p %s refcnt = %d, ask_to_destroy %s do_decrement %s state %d from_thread %s", this, GetName(), fObjectRefCnt, DBOOL(ask_to_destroy), DBOOL(do_decrement), GetState(), DBOOL(from_thread));
329 // }
330 
331 // if (GetFlag(flLogging))
332 // DOUT0("Obj:%s %p Class:%s DecReference %u destroy %s dodec %s state %d numchilds %u flags %x",
333 // GetName(), this, ClassName(),
334 // fObjectRefCnt, DBOOL(ask_to_destroy), DBOOL(do_decrement), GetState(),
335 // (fObjectChilds ? fObjectChilds->GetSize() : 0), fObjectFlags);
336 
337  if (do_decrement) {
338 
339  if (fObjectRefCnt==0) {
340  EOUT("Obj %p name:%s class:%s Reference counter is already 0", this, GetName(), ClassName());
341  throw dabc::Exception(ex_Object, "Reference counter is 0 - cannot decrease", GetName());
342  return false;
343  }
344 
345  // if (IsLogging()) DOUT0("Dec object refcounter in 389");
346  fObjectRefCnt--;
347 
348  if (GetFlag(flLogging))
349  DOUT0("Obj:%s %p Class:%s DecReference ----+- %u thrd:%s", GetName(), this, ClassName(), fObjectRefCnt, dabc::mgr.CurrentThread().GetName());
350  }
351 
352  switch (GetState()) {
353  case stConstructor:
354  EOUT("Object %s is not yet constructed - most probably, big failure", GetName());
355  return false;
356 
357  case stNormal:
358  // if autodestroy flag specified, object will be destroyed when no more external references are existing
359 
360  // if (GetFlag(flAutoDestroy) && (fObjectRefCnt <= (int)(fObjectChilds ? fObjectChilds->GetSize() : 0))) ask_to_destroy = true;
361  if (GetFlag(flAutoDestroy) && (fObjectRefCnt == 0)) ask_to_destroy = true;
362 
363  if (do_decrement && (fObjectChilds!=0) && ((unsigned) fObjectRefCnt == fObjectChilds->GetSize()) && GetFlag(flAutoDestroy)) {
364  ask_to_destroy = true;
365  // DOUT0("One could destroy object %s %p anyhow numrefs %u numchilds %u", GetName(), this, fObjectRefCnt, fObjectChilds->GetSize());
366  }
367 
368  if (!ask_to_destroy) return false;
369  viathrd = GetFlag(flHasThread);
370  break;
371 
372  // we are waiting for the thread, only thread call can unblock
373  case stWaitForThread:
374  if (!from_thread) {
375  DOUT2("Object %p %s tried to destroy not from thread - IGNORE", this, GetName());
376  return false;
377  }
378  break;
379 
380  // recursive call, ignore it
381  case stDoingDestroy:
382  return false;
383 
384  // if object already so far, it can be destroyed when no references remained
385  case stWaitForDestructor:
386  if (fObjectRefCnt == 0) {
387  if (_DoDeleteItself()) return false;
388 
389  // once return true, never do it again
390  // returning true means that destructor will be immediately call
391  SetState(stDestructor);
392 
393  return true;
394  }
395 
396  #ifdef DABC_EXTRA_CHECKS
397  {
398  LockGuard lock(gObjectGarbageMutex);
399  if (!gObjectGarbageCollector.has_ptr(this))
400  gObjectGarbageCollector.push_back(this);
401  }
402  #endif
403  return false;
404 
405  // in principal error, we are inside destructor
406  case stDestructor:
407  return false;
408  }
409 
410  if (viathrd) {
411  SetState(stWaitForThread);
412  // we delegate reference counter to the thread
413  fObjectRefCnt++;
414  if (GetFlag(flLogging))
415  DOUT0("Obj:%s %p Class:%s IncReference --+--- %u", GetName(), this, ClassName(), fObjectRefCnt);
416  } else {
417  SetState(stDoingDestroy);
418  }
419  }
420 
421  if (viathrd) {
422  if (DestroyByOwnThread()) return false;
423 
424  // it means thread do not want to destroy us, let do it normal way
425  dabc::LockGuard lock(fObjectMutex);
426  SetState(stDoingDestroy);
427  // thread reject destroyment, therefore refcounter can be decreased
428  // if (IsLogging()) DOUT0("Dec object refcounter in 459");
429  fObjectRefCnt--;
430 
431  if (GetFlag(flLogging))
432  DOUT0("Obj:%s %p Class:%s DecReference -----+ %u", GetName(), this, ClassName(), fObjectRefCnt);
433  }
434 
435 
436  if (IsLogging()) DOUT0("Calling object %p cleanup from_thrd=%s do_decrement=%s", this, DBOOL(from_thread), DBOOL(do_decrement));
437 
438  // Main point of all destroyment - call cleanup in correct place
439  ObjectCleanup();
440 
441 // if (IsLogging()) DOUT0("Did object cleanup");
442 
443  if (IsLogging())
444  DOUT0("DecRefe after cleanup %p cleanup %s mgr %p", this, DBOOL(GetFlag(flCleanup)), dabc::mgr());
445 
446  {
447 
448  LockGuard guard(fObjectMutex);
449 
450  if (GetFlag(flCleanup) && dabc::mgr()) {
451  // cleanup will be done by manager via reference
452  fObjectRefCnt++;
453  SetState(stWaitForDestructor);
454  if (GetFlag(flLogging))
455  DOUT0("Obj:%s %p Class:%s IncReference ---+-- %u", GetName(), this, ClassName(), fObjectRefCnt);
456  } else
457  if (fObjectRefCnt==0) {
458  // no need to deal with manager - can call destructor immediately
459  DOUT3("Obj:%p can be destroyed", this);
460  if (_DoDeleteItself()) {
461  SetState(stWaitForDestructor);
462  return false;
463  }
464  SetState(stDestructor);
465  return true;
466  } else {
468  SetState(stWaitForDestructor);
469  #ifdef DABC_EXTRA_CHECKS
470  {
471  LockGuard lock(gObjectGarbageMutex);
472  if (!gObjectGarbageCollector.has_ptr(this))
473  gObjectGarbageCollector.push_back(this);
474  }
475  #endif
476  return false;
477  }
478  }
479 
480  // special case - we already increment reference counter
481  Reference ref;
482  ref.fObj = this;
483  if (dabc::mgr()->DestroyObject(ref)) return false;
484 
485  // here reference will be released if manager does not accept destroyment
486 
487  LockGuard guard(fObjectMutex);
488 
489  if (fObjectRefCnt==0) {
490  // no need to deal with manager - can call destructor immediately
491  if (_DoDeleteItself()) {
492  SetState(stWaitForDestructor);
493  return false;
494  }
495 
496  DOUT3("Obj:%p can be destroyed", this);
497  SetState(stDestructor);
498  return true;
499  }
500 
501  return false;
502 }
503 
505 {
506  return DecReference(true, true, true);
507 }
508 
510 {
511  if (IsLogging())
512  DOUT1("OBJ:%p %s DELETETHIS cnt %u", this, GetName(), fObjectRefCnt);
513 
514  {
515  LockGuard lock(fObjectMutex);
516 
517  if (GetState()!=stNormal) {
518 // EOUT("Object %p already on the way to destroyment - do not harm it", this);
519  return;
520  }
521 
522  // this flag force object to be cleanup via manager
523  SetFlag(flCleanup, true);
524  }
525 
526  Destroy(this);
527 }
528 
529 
530 
531 
533 {
534  RemoveChilds();
535 
536  if (IsLogging()) {
537  DOUT0("Obj:%p %s refcnt %u Before remove from parent %p", this, GetName(), fObjectRefCnt, fObjectParent());
538  }
539 
540  // Than we remove reference on the object from parent
541  if (!fObjectParent.null())
542  fObjectParent()->RemoveChild(this, false);
543 
544  if (!fObjectParent.null()) {
545  EOUT("Parent still not yet cleaned !!!!");
546  fObjectParent.Release();
547  }
548 
549  if (IsLogging()) {
550  DOUT0("Obj:%p %s refcnt %u after remove from parent", this, GetName(), fObjectRefCnt);
551  }
552 
553  DOUT3("Obj:%s Class:%s Finish cleanup numrefs %u", GetName(), ClassName(), NumReferences());
554 
555 }
556 
558 {
559  dabc::LockGuard lock(fObjectMutex);
560 
561  return fObjectRefCnt;
562 }
563 
564 
565 bool dabc::Object::AddChild(Object* child, bool withmutex) throw()
566 {
567  return AddChildAt(child, (unsigned) -1, withmutex);
568 }
569 
570 bool dabc::Object::AddChildAt(Object* child, unsigned pos, bool withmutex)
571 {
572  if (child==0) return false;
573 
574  if (!child->fObjectParent.null() && (child->GetParent() != this)) {
575  EOUT("Cannot add child from other parent directly - first remove from old");
576  throw dabc::Exception(ex_Object, "Cannot add child from other parent", GetName());
577  return false;
578  }
579 
580  Reference ref(child);
581 
582  LockGuard guard(withmutex ? fObjectMutex : 0);
583 
584  if (child->fObjectParent.null()) {
585  child->fObjectParent.fObj = this; // not very nice, but will work
586  fObjectRefCnt++;
587  }
588 
589  // if object is owner of all childs, any child will get autodestroy flag
590  if (GetFlag(flIsOwner)) child->SetAutoDestroy(true);
591 
592  if (fObjectChilds==0) fObjectChilds = new ReferencesVector;
593 
594  if (pos == (unsigned) -1)
595  fObjectChilds->Add(ref);
596  else
597  fObjectChilds->AddAt(ref, pos);
598 
599  _ChildsChanged();
600 
601  return true;
602 }
603 
604 bool dabc::Object::RemoveChild(Object* child, bool cleanup) throw()
605 {
606  if (child==0) return false;
607 
608  if (child->fObjectParent() != this) return false;
609 
610  int cnt = 1000000;
611 
612  bool isowner = false;
613 
614  dabc::Reference childref;
615 
616  while (--cnt>0) {
617  LockGuard guard(fObjectMutex);
618 
619  if (fObjectChilds==0) return false;
620 
621  if (fObjectBlock>0) continue;
622 
623  isowner = GetFlag(flIsOwner);
624 
625  if (fObjectChilds->ExtractRef(child, childref)) {
626  // IMPORTANT: parent reference can be released only AFTER childs are decreased,
627  // otherwise reference will try to destroy parent
628  // IMPORTANT: we are under object mutex and can do anything
629 
630  _ChildsChanged();
631 
632  if (child->fObjectParent.fObj==this) {
633  child->fObjectParent.fObj = 0; // not very nice, but will work
634  if (fObjectRefCnt>1) {
635  fObjectRefCnt--;
636  } else {
637  fObjectRefCnt = 0;
638  if (fObjectChilds->GetSize() > 0)
639  DOUT0("Object %p %s refcnt==0 when numchild %u", this, GetName(), fObjectChilds->GetSize());
640  }
641  }
642  break;
643  }
644 
645  EOUT("Not able to extract child reference!!!");
646  exit(333);
647  }
648 
649  if (cleanup && isowner) childref.Destroy();
650  else childref.Release();
651 
652  #ifdef DABC_EXTRA_CHECKS
653  if (cnt < 999990)
654  DOUT0("Object %s Retry %d time before childs were unblocked", GetName(), 1000000-cnt);
655  #endif
656 
657  if (cnt==0) {
658  EOUT("HARD error!!!! - For a long time fObjectBlock=%d is blocked in object %p %s", fObjectBlock, this, GetName());
659  exit(055);
660  }
661 
662  return true;
663 }
664 
665 bool dabc::Object::RemoveChildAt(unsigned n, bool cleanup) throw()
666 {
667  return RemoveChild(GetChild(n), cleanup);
668 }
669 
670 unsigned dabc::Object::NumChilds() const
671 {
672  LockGuard guard(fObjectMutex);
673 
674  return fObjectChilds ? fObjectChilds->GetSize() : 0;
675 }
676 
678 {
679  LockGuard guard(fObjectMutex);
680 
681  return fObjectChilds==0 ? 0 : fObjectChilds->GetObject(n);
682 }
683 
685 {
686  LockGuard guard(fObjectMutex);
687 
688  Object* obj = (fObjectChilds==0) ? 0 : fObjectChilds->GetObject(n);
689 
690  if (obj==0) return Reference();
691 
692  IntGuard block(fObjectBlock);
693 
694  UnlockGuard unlock(fObjectMutex);
695 
696  return dabc::Reference(obj);
697 
698  // here will be mutex locked, fObjectBlock counter decremented and finally mutex unlocked again
699 }
700 
702 {
703  if (vect==0) return false;
704 
705  LockGuard guard(fObjectMutex);
706 
707  if (fObjectChilds==0) return true;
708 
709  PointersVector ptrs;
710 
711  for (unsigned n=0; n<fObjectChilds->GetSize(); n++)
712  ptrs.push_back(fObjectChilds->GetObject(n));
713 
714  IntGuard block(fObjectBlock);
715 
716  UnlockGuard unlock(fObjectMutex);
717 
718  for (unsigned n=0;n<ptrs.size();n++) {
719  Reference ref((Object*)ptrs[n]);
720  vect->Add(ref);
721  }
722 
723  return true;
724 
725  // here will be mutex locked, fObjectBlock counter decremented and finally mutex unlocked again
726 
727 }
728 
729 
730 dabc::Object* dabc::Object::FindChild(const char* name) const
731 {
732  return FindChildRef(name, false)();
733 }
734 
735 dabc::Reference dabc::Object::FindChildRef(const char* name, bool force) const throw()
736 {
737  Reference ref(const_cast<Object*> (this));
738 
739  return SearchForChild(ref, name, true, force);
740 }
741 
742 dabc::Reference dabc::Object::SearchForChild(Reference& ref, const char* name, bool firsttime, bool force) throw()
743 {
744  if (ref.null()) return ref;
745 
746  if ((name==0) || (strlen(name)==0)) return ref;
747 
748  if (*name=='/') {
749  if (firsttime) {
750  while (ref()->GetParent()!=0)
751  ref = Reference(ref()->GetParent());
752  return SearchForChild(ref, name+1, false, force);
753  } else {
754  // skip all slashes in the beginning
755  while (*name=='/') name++;
756  if (*name==0) return ref;
757  }
758  }
759 
760  int len = strlen(name);
761 
762  if ((len>=2) && (name[0]=='.') && (name[1] == '.')) {
763  if (len==2) return Reference(ref()->GetParent());
764 
765  if (name[2]=='/') {
766  ref = Reference(ref()->GetParent());
767  return SearchForChild(ref, name + 3, false, force);
768  }
769  }
770 
771  if ((len>=1) && (name[0]=='.')) {
772  if (len==1) return ref;
773  if (name[1]=='/')
774  return SearchForChild(ref, name + 2, false, force);
775  }
776 
777  const char* ptok = name;
778  while (*ptok!=0) {
779  if (*ptok == '/') break;
780  ptok++;
781  }
782 
783  Reference newref;
784 
785  {
786  LockGuard guard(ref()->fObjectMutex);
787 
788  dabc::Object *obj = (ref()->fObjectChilds==nullptr) ? nullptr : ref()->fObjectChilds->FindObject(name, ptok-name);
789 
790  // create new object under parent mutex - no one can create double entries simultaneously
791  if ((obj==0) && force) {
792  obj = ref()->CreateInstance(std::string(name, ptok-name));
793  ref()->AddChild(obj, false);
794  }
795 
796  if (obj!=0) {
797  IntGuard block(ref()->fObjectBlock);
798 
799  UnlockGuard unlock(ref()->fObjectMutex);
800 
801  // make reference outside parent mutex
802  newref = dabc::Reference(obj);
803  }
804  }
805 
806  ref << newref;
807 
808  if (*ptok==0) return ref;
809 
810  return SearchForChild(ref, ptok+1, false, force);
811 }
812 
813 
814 dabc::Reference dabc::Object::GetFolder(const std::string &name, bool force) throw()
815 {
816  Reference ref(this);
817 
818  return SearchForChild(ref, name.c_str(), true, force);
819 }
820 
821 bool dabc::Object::RemoveChilds(bool cleanup)
822 {
823  ReferencesVector* del_vect = 0;
824 
825  int cnt = 1000000;
826 
827  bool isowner = false;
828 
829  while (--cnt>0) {
830  LockGuard guard(fObjectMutex);
831 
832  // nothing to do
833  if (fObjectChilds==0) return true;
834 
835  if (fObjectBlock>0) continue;
836 
837  isowner = GetFlag(flIsOwner);
838  del_vect = fObjectChilds;
839  fObjectChilds = 0;
840  break;
841  }
842 
843  #ifdef DABC_EXTRA_CHECKS
844  if (cnt < 999990)
845  DOUT0("Object %s Retry %d times before childs were unblocked", 1000000-cnt);
846  #endif
847 
848  if (cnt==0) {
849  EOUT("HARD error!!!! - For a long time fObjectBlock=%d is blocked in object %p %s", fObjectBlock, this, GetName());
850  exit(055);
851  }
852 
853  if (IsLogging())
854  DOUT1("Obj:%s Deleting childs:%u", GetName(), del_vect ? del_vect->GetSize() : 0);
855 
856  if (del_vect) {
857 
858  // ensure that object do not longer reference parent
859  for (unsigned n=0;n<del_vect->GetSize();n++) {
860  Object* obj = del_vect->GetObject(n);
861  if (obj) obj->fObjectParent.Release();
862  }
863 
864  del_vect->Clear(isowner && cleanup);
865  delete del_vect;
866  }
867 
868  return true;
869 }
870 
871 void dabc::Object::SetName(const char *name)
872 {
873  LockGuard guard(fObjectMutex);
874 
875  if (fObjectRefCnt>0) {
876  EOUT("Cannot change object name when reference counter %d is not zero!!!", fObjectRefCnt);
877  throw dabc::Exception(ex_Object, "Cannot change object name when refcounter is not zero", GetName());
878  }
879 
880  fObjectName = name;
881 }
882 
883 
884 void dabc::Object::SetNameDirect(const char* name)
885 {
886  LockGuard guard(fObjectMutex);
887 
888  fObjectName = name;
889 }
890 
891 
921 void dabc::Object::Destroy(Object* obj) throw()
922 {
923  if (obj==0) return;
924 
925  if (obj->DecReference(true, false))
926  delete obj;
927 }
928 
930 {
931  return GetParent()==0 ? false : cfg.FindItem(GetName());
932 }
933 
934 dabc::Object::ConstructorPair dabc::Object::MakePair(Reference prnt, const std::string &fullnamearg, bool withmanager)
935 {
936  if (fullnamearg.empty() && prnt.null())
937  return ConstructorPair();
938 
939  const char* fullname = fullnamearg.empty() ? "---" : fullnamearg.c_str();
940  bool isrootfolder(false), isskipparent(false);
941  while (*fullname=='/') {
942  isrootfolder = true;
943  fullname++;
944  }
945 
946  if (!isrootfolder && (*fullname=='#')) {
947  fullname++;
948  isskipparent = true;
949  }
950 
951  if (prnt.null() && withmanager && !isskipparent) {
952  if (prnt.null()) prnt = dabc::mgr;
953  }
954 
955  const char* slash = strrchr(fullname, '/');
956 
957  ConstructorPair pair;
958 
959  if (slash!=0) {
960  pair.name = slash+1;
961  std::string path = std::string(fullname, slash - fullname);
962  if (!prnt.null())
963  prnt = prnt()->FindChildRef(path.c_str(), true);
964  } else {
965  pair.name = fullname;
966  }
967 
968  if (!isskipparent)
969  pair.parent = prnt;
970 
971  return pair;
972 }
973 
974 dabc::Object::ConstructorPair dabc::Object::MakePair(Object* prnt, const std::string &fullname, bool withmanager)
975 {
976  return dabc::Object::MakePair(Reference(prnt), fullname, withmanager);
977 }
978 
979 dabc::Object::ConstructorPair dabc::Object::MakePair(const std::string &fullname, bool withmanager)
980 {
981  return dabc::Object::MakePair(Reference(), fullname, withmanager);
982 }
983 
984 
986 {
987  if (obj==0) return false;
988 
989  Object* prnt = GetParent();
990 
991  while (prnt!=0) {
992  if (prnt==obj) return true;
993  prnt = prnt->GetParent();
994  }
995  return false;
996 }
997 
998 
999 bool dabc::Object::IsNameMatch(const std::string &mask) const
1000 {
1001  return NameMatch(fObjectName, mask);
1002 }
1003 
1004 bool dabc::Object::NameMatch(const std::string &name, const std::string &mask)
1005 {
1006  if ((mask.length()==0) || (name.length()==0))
1007  return name.length()==mask.length();
1008 
1009  size_t lastsepar(0), separ = mask.find_first_of(';',lastsepar);
1010 
1011  if (separ!=std::string::npos) {
1012  do {
1013  // FIXME!!!! code missing
1014 
1015 
1016 
1017  } while (lastsepar!=std::string::npos);
1018  }
1019 
1020 
1021  if (mask.find_first_of("*?") == std::string::npos) return name == mask;
1022 
1023  if (mask == "*") return true;
1024 
1025  return fnmatch(mask.c_str(), name.c_str(), FNM_NOESCAPE)==0;
1026 }
1027 
1028 bool dabc::Object::NameMatchM(const std::string &name, const std::string &mask)
1029 {
1030  size_t separ = mask.find_first_of(':');
1031 
1032  if (separ==std::string::npos) return NameMatch(name, mask);
1033 
1034  size_t lastsepar = 0;
1035 
1036  do {
1037 
1038  std::string submask;
1039 
1040  if (separ==std::string::npos)
1041  submask = mask.substr(lastsepar);
1042  else
1043  if (separ>lastsepar)
1044  submask = mask.substr(lastsepar, separ-lastsepar);
1045 
1046  if (!submask.empty())
1047  if (NameMatch(name, submask)) return true;
1048 
1049  lastsepar = separ;
1050  if (separ!=std::string::npos) {
1051  lastsepar++;
1052  separ = mask.find_first_of(':', lastsepar);
1053  }
1054 
1055  } while (lastsepar!=std::string::npos);
1056 
1057  return false;
1058 }
1059 
1060 
1061 void dabc::Object::FillFullName(std::string &fullname, Object* upto, bool exclude_top_parent) const
1062 {
1063  if ((GetParent()!=0) && (GetParent() != upto)) {
1064  GetParent()->FillFullName(fullname, upto, exclude_top_parent);
1065  fullname.append("/");
1066  }
1067 
1068  if (GetParent()==0) {
1069  if (exclude_top_parent) return;
1070  fullname.append("/");
1071  }
1072  fullname.append(GetName());
1073 }
1074 
1075 
1076 std::string dabc::Object::ItemName(bool compact) const
1077 {
1078  std::string res;
1079  if (IsParent(dabc::mgr()))
1080  dabc::mgr()->FillItemName(this, res, compact);
1081  else
1082  FillFullName(res, 0);
1083 
1084  return res;
1085 }
1086 
1087 
1088 // ============================================================================
1089 // FIXME: old code, should be adjusted
1090 
1091 
1092 void dabc::Object::Print(int lvl)
1093 {
1094  LockGuard guard(ObjectMutex());
1095  dabc::lgr()->Debug(lvl, "file", 1, "func", dabc::format("Object: %s Class:%s", GetName(), ClassName()).c_str());
1096 }
1097 
1098 
1100 {
1101 #ifdef DABC_EXTRA_CHECKS
1102  LockGuard lock(gObjectGarbageMutex);
1103 
1104  DOUT0("GarbageCollector: there are %u objects in collector now", gObjectGarbageCollector.size());
1105 
1106  for (unsigned n=0;n<gObjectGarbageCollector.size();n++) {
1107  Object* obj = (Object*) gObjectGarbageCollector.at(n);
1108  DOUT0(" obj:%p name:%s class:%s refcnt:%u", obj, obj->GetName(), obj->ClassName(), obj->fObjectRefCnt);
1109  }
1110 
1111 #endif
1112 
1113 }
1114 
1115 
1116 
1117 #ifdef DABC_EXTRA_CHECKS
1118 
1119 #include <list>
1120 #include <cstdio>
1121 #include <map>
1122 
1123 void dabc::Object::DebugObject(const char* classname, Object* instance, int kind)
1124 {
1125 
1126  typedef std::list<dabc::Object*> obj_list;
1127  typedef std::map<std::string,obj_list> full_map;
1128  typedef std::map<std::string,int> counts_map;
1129 
1130 
1131  static counts_map cnts;
1132  static full_map objs;
1133  static dabc::Mutex mutex(true);
1134 
1135  dabc::LockGuard lock(mutex);
1136 
1137  if (classname == 0) {
1138  printf("NUM ENTRIES = %u\n", (unsigned) cnts.size());
1139  for (counts_map::iterator iter = cnts.begin(); iter != cnts.end(); iter++) {
1140  printf(" CLASS = %s NUM = %d \n", iter->first.c_str(), iter->second);
1141 
1142  full_map::iterator iter2 = objs.find(iter->first);
1143  if (iter2!=objs.end())
1144  for (obj_list::iterator iter3 = iter2->second.begin(); iter3 != iter2->second.end(); iter3++)
1145  printf(" OBJ:%p NAME = %s\n", *iter3, (*iter3)->GetName());
1146  }
1147  } else {
1148  std::string name(classname);
1149  if (kind<0) cnts[name]--;
1150  else cnts[name]++;
1151 
1152  if (kind==10) objs[name].push_back(instance); else
1153  if (kind==-10) objs[name].remove(instance);
1154  }
1155 }
1156 
1157 #endif
Interface class between xml configuration and dabc objects.
Definition: ConfigIO.h:38
bool FindItem(const char *name)
Definition: ConfigIO.cxx:42
DABC exception.
Definition: Exception.h:57
Guard for integer value.
Definition: threads.h:240
Lock guard for posix mutex.
Definition: threads.h:127
static void Debug(int level, const char *filename, unsigned linenumber, const char *funcname, const char *message)
Definition: logging.h:106
posix pthread mutex
Definition: threads.h:61
Base class for most of the DABC classes.
Definition: Object.h:116
Reference fObjectParent
reference on the parent object
Definition: Object.h:176
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...
Definition: Object.cxx:604
bool IsName(const char *str) const
Checks if object name is same as provided string, thread safe
Definition: Object.h:298
void Destructor()
Destroys all internal data, reentrant.
Definition: Object.cxx:225
bool IsOwner() const
Returns true if object is owner of its children, thread safe
Definition: Object.cxx:167
bool IsTopXmlLevel() const
Return true if object should be searched in the top level of the xml file, thread safe
Definition: Object.cxx:185
ReferencesVector * fObjectChilds
list of the child objects
Definition: Object.h:180
virtual Object * CreateInstance(const std::string &name)
Method used to create new item to be placed as child of the object.
Definition: Object.h:241
bool IncReference(bool withmutex=true)
Increments reference counter, return false if it cannot be done.
Definition: Object.cxx:278
void FillFullName(std::string &fullname, Object *upto, bool exclude_top_parent=false) const
Method used to produce full item name,.
Definition: Object.cxx:1061
std::string ItemName(bool compact=true) const
Produce string, which can be used as name argument in dabc::mgr.FindItem(name) call.
Definition: Object.cxx:1076
Object * GetParent() const
Returns pointer on parent object, thread safe
Definition: Object.h:286
bool DecReference(bool ask_to_destroy, bool do_decrement=true, bool from_thread=false)
Decrements reference counter, return true if object must be destroyed.
Definition: Object.cxx:317
unsigned NumReferences()
Return number of references on the object.
Definition: Object.cxx:557
virtual void Print(int lvl=0)
Print object content on debug output.
Definition: Object.cxx:1092
void Constructor()
Initializes all variables of the object.
Definition: Object.cxx:210
virtual ~Object()
Definition: Object.cxx:147
bool RemoveChildAt(unsigned n, bool cleanup=true)
Detach child object from parent at specified position If cleanup==true and object is owner of child,...
Definition: Object.cxx:665
Reference GetChildRef(unsigned n) const
returns reference on child object
Definition: Object.cxx:684
static bool NameMatchM(const std::string &name, const std::string &mask)
Check if name matches to specified mask.
Definition: Object.cxx:1028
void SetNameDirect(const char *name)
Changes object name disregard of existing references.
Definition: Object.cxx:884
static unsigned gNumCreated
number of created instances, will used for object id
Definition: Object.h:133
Object(const ConstructorPair &pair, unsigned flags=flIsOwner)
Definition: Object.cxx:132
void SetLogging(bool on=true)
Sets logging flag, thread safe
Definition: Object.cxx:197
const char * GetName() const
Returns name of the object, thread safe
Definition: Object.h:295
void SetAutoDestroy(bool on=true)
Set autodestroy flag for the object Once enabled, object will be destroyed when last reference will b...
Definition: Object.cxx:160
static void InspectGarbageCollector()
\ brief Methods to inspect how many objects pointers are remained
Definition: Object.cxx:1099
int fObjectRefCnt
accounts how many references existing on the object, thread safe
Definition: Object.h:179
static ConstructorPair MakePair(Reference prnt, const std::string &fullname, bool withmanager=true)
Internal DABC method, used to produce pair - object parent and object name, which is typically should...
Definition: Object.cxx:934
virtual void ObjectCleanup()
User method to cleanup object content before it will be destroyed Main motivation is to release any r...
Definition: Object.cxx:532
bool DestroyCalledFromOwnThread()
Internal DABC method, should be called by thread which was requested to destroy object.
Definition: Object.cxx:504
bool IsNormalState()
Return true if object is in normal state.
Definition: Object.cxx:309
bool IsParent(Object *obj) const
Checks if specified argument is in the list of object parents.
Definition: Object.cxx:985
Reference GetFolder(const std::string &name, bool force=false)
Return folder of specified name, no special symbols allowed.
Definition: Object.cxx:814
static bool NameMatch(const std::string &name, const std::string &mask)
Check if name matches to specified mask.
Definition: Object.cxx:1004
bool AddChild(Object *child, bool withmutex=true)
Add object to list of child objects, thread safe
Definition: Object.cxx:565
Reference FindChildRef(const char *name, bool force=false) const
returns reference on child object with given name
Definition: Object.cxx:735
bool _IsNormalState()
Same as IsNormalState() but without mutex lock - user should lock mutex himself.
Definition: Object.cxx:303
static Reference SearchForChild(Reference &ref, const char *name, bool firsttime, bool force)
Definition: Object.cxx:742
bool RemoveChilds(bool cleanup=true)
Remove all childs.
Definition: Object.cxx:821
virtual const char * ClassName() const
Returns class name of the object instance.
Definition: Object.h:419
static void Destroy(Object *obj)
User method for object destroyment.
Definition: Object.cxx:921
bool IsNameMatch(const std::string &mask) const
Check if object name match to the mask.
Definition: Object.cxx:999
bool AddChildAt(Object *child, unsigned pos, bool withmutex=true)
Add object to list of child objects at specified position.
Definition: Object.cxx:570
void SetOwner(bool on=true)
Specifies if object will be owner of its new childs.
Definition: Object.cxx:154
bool IsChildsHidden() const
Return true if object wants to hide childs from hierarchy scan, thread safe
Definition: Object.cxx:179
static unsigned gNumInstances
actual number of existing instances
Definition: Object.h:132
bool GetAllChildRef(ReferencesVector *vect) const
Definition: Object.cxx:701
virtual bool Find(ConfigIO &cfg)
Method to locate object in xml file.
Definition: Object.cxx:929
bool IsLogging() const
Return true if object selected for logging, thread safe
Definition: Object.cxx:173
bool IsHidden() const
Return true if object wants to be hidden from hierarchy scan, thread safe
Definition: Object.cxx:191
void SetCleanupBit()
Method set cleanup bit that object will be cleaned up in all registered objects Used only by manager ...
Definition: Object.cxx:297
void DeleteThis()
Method should be used by the object to delete itself.
Definition: Object.cxx:509
void SetName(const char *name)
Changes object name.
Definition: Object.cxx:871
unsigned NumChilds() const
returns number of child objects
Definition: Object.cxx:670
Object * FindChild(const char *name) const
returns pointer on child object with given name
Definition: Object.cxx:730
Object * GetChild(unsigned n) const
returns pointer on child object
Definition: Object.cxx:677
Specialized vector with pointers.
Definition: Queue.h:340
Reference on the arbitrary object
Definition: Reference.h:73
void Release()
Releases reference on the object.
Definition: Reference.cxx:138
bool null() const
Returns true if reference contains nullptr.
Definition: Reference.h:151
Object * fObj
pointer on the object
Definition: Reference.h:80
void Destroy()
Release reference and starts destroyment of referenced object.
Definition: Reference.cxx:148
Vector of dabc::Reference objects.
Object * FindObject(const char *name, int len=-1) const
Simple search of object by name, no any subfolder structures.
unsigned GetSize() const
Returns number of items in vector.
bool Clear(bool asowner=false)
Clear all references, if owner specified objects will be destroyed.
bool Add(Reference &ref)
Add reference to the vector.
Object * GetObject(unsigned n) const
Returns pointer on the object.
Unlock guard for posix mutex.
Definition: threads.h:215
#define DOUT2(args ...)
Definition: logging.h:170
#define DOUT0(args ...)
Definition: logging.h:156
#define DOUT5(args ...)
Definition: logging.h:188
#define DOUT3(args ...)
Definition: logging.h:176
#define EOUT(args ...)
Definition: logging.h:150
#define DOUT1(args ...)
Definition: logging.h:162
#define DBOOL(arg)
Definition: logging.h:191
XMLNodePointer_t GetParent(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:917
XMLNodePointer_t GetChild(XMLNodePointer_t xmlnode)
Definition: XmlEngine.cxx:906
Event manipulation API.
Definition: api.h:23
const char * xmlWorkPool
Definition: Object.cxx:46
const char * xmlBufferSize
Definition: Object.cxx:49
const char * xmlNumOutputs
Definition: Object.cxx:55
const char * xmlOutputQueueSize
Definition: Object.cxx:42
const char * typeSocketThread
Definition: Object.cxx:80
const char * xml_maxsize
Definition: Object.cxx:73
const char * xmlFileName
Definition: Object.cxx:70
const char * xmlFixedLayout
Definition: Object.cxx:47
const char * typeSocketDevice
Definition: Object.cxx:79
const char * xmlInputMask
Definition: Object.cxx:57
const char * xmlOutputMask
Definition: Object.cxx:59
const char * xmlRateAttr
Definition: Object.cxx:39
ManagerRef mgr
Definition: Manager.cxx:42
std::string format(const char *fmt,...)
Definition: string.cxx:49
const char * xmlMcastAddr
Definition: Object.cxx:64
const char * xml_flush
Definition: Object.cxx:75
const char * xmlConnectionNode
Definition: Object.cxx:34
const char * xmlAlignment
Definition: Object.cxx:51
const char * xmlSignalAttr
Definition: Object.cxx:38
const char * xmlUseAcknowledge
Definition: Object.cxx:60
const char * xmlFlushTimeout
Definition: Object.cxx:61
const char * xmlOutputPrefix
Definition: Object.cxx:58
const char * xmlInputQueueSize
Definition: Object.cxx:41
const char * xmlLoopAttr
Definition: Object.cxx:40
const char * xmlBindAttr
Definition: Object.cxx:37
const char * xmlProtocol
Definition: Object.cxx:68
const char * xmlCleanupTimeout
Definition: Object.cxx:48
const char * xmlInlineDataSize
Definition: Object.cxx:43
const char * xml_number
Definition: Object.cxx:74
const char * xmlMemoryPoolNode
Definition: Object.cxx:32
const char * xmlNumBuffers
Definition: Object.cxx:50
const char * xmlShowInfo
Definition: Object.cxx:52
const char * xmlMcastPort
Definition: Object.cxx:65
const char * typeThread
Definition: Object.cxx:77
const char * xmlModuleNode
Definition: Object.cxx:33
const char * xmlPoolName
Definition: Object.cxx:45
const char * xmlConnTimeout
Definition: Object.cxx:62
const char * xmlFileNumber
Definition: Object.cxx:71
const char * xmlFileSizeLimit
Definition: Object.cxx:72
const char * xmlInputPrefix
Definition: Object.cxx:56
const char * xmlHostName
Definition: Object.cxx:69
const char * xmlMcastRecv
Definition: Object.cxx:66
@ ex_Object
Definition: Exception.h:38
const char * xmlQueueAttr
Definition: Object.cxx:36
const char * xmlDeviceNode
Definition: Object.cxx:30
const char * xmlThreadNode
Definition: Object.cxx:31
const char * xmlNumInputs
Definition: Object.cxx:54
Logger * lgr()
Definition: logging.cxx:483
const char * typeDevice
Definition: Object.cxx:78
const char * typeApplication
Definition: Object.cxx:81
Structure used to specify arguments for object constructor.
Definition: Object.h:247