1    	// $Id: StObject.cxx,v 1.28 2015/08/28 19:54:18 perev Exp $
2    	// $Log: StObject.cxx,v $
3    	// Revision 1.28  2015/08/28 19:54:18  perev
4    	// Add specific copy constructor to StObject.
5    	// This ctr set zero to bit 1<<22. This boit means that object belongs
6    	// to structured container. But copy obviously not.
7    	//
8    	// Revision 1.27  2012/06/11 15:08:41  fisyak
9    	// std namespace, warn off for x64
10   	//
11   	// Revision 1.26  2012/02/21 18:50:46  perev
12   	// bug #2281 fix
13   	//
14   	// Revision 1.22  2009/08/26 20:44:08  fine
15   	// fix the compilation issues under SL5_64_bits  gcc 4.3.2
16   	//
17   	// Revision 1.21  2006/08/10 03:34:38  perev
18   	// Assert==>assert
19   	//
20   	// Revision 1.20  2005/10/21 21:13:52  perev
21   	// test added to avoid copy to itself. Make walgrin happy
22   	//
23   	// Revision 1.19  2004/05/03 23:31:46  perev
24   	// Possible non init WarnOff
25   	//
26   	// Revision 1.18  2003/09/02 17:59:24  perev
27   	// gcc 3.2 updates + WarnOff
28   	//
29   	// Revision 1.17  2002/11/26 02:23:38  perev
30   	// new ROOT adoptation
31   	//
32   	// Revision 1.16  2002/01/27 23:46:49  perev
33   	// Zombie test added
34   	//
35   	// Revision 1.15  2001/05/30 17:46:41  perev
36   	// StEvent branching
37   	//
38   	// Revision 1.14  2000/09/30 17:48:27  perev
39   	// Zombies cons and loop for stru vector
40   	//
41   	// Revision 1.13  2000/09/15 15:11:58  perev
42   	// Zombie for StEvent
43   	//
44   	// Revision 1.12  2000/07/30 01:49:03  perev
45   	// StObject vers restored
46   	//
47   	// Revision 1.10  2000/06/19 01:28:26  perev
48   	// STL StEvent
49   	//
50   	// Revision 1.9  2000/04/23 01:00:45  perev
51   	// StEvent monolitic I/O
52   	//
53   	// Revision 1.8  2000/04/20 14:24:09  perev
54   	// StArray fixes
55   	//
56   	// Revision 1.7  2000/04/18 02:57:25  perev
57   	// StEvent browse
58   	//
59   	// Revision 1.6  1999/12/21 15:42:58  fine
60   	// remove compilation warning
61   	//
62   	// Revision 1.5  1999/12/13 21:40:41  perev
63   	// Remove warnings
64   	//
65   	// Revision 1.4  1999/11/17 14:22:10  perev
66   	// bug in dtor fix
67   	//
68   	// Revision 1.3  1999/11/15 23:09:10  perev
69   	// Streamer for StrArray and auto remove
70   	//
71   	// Revision 1.2  1999/06/23 20:31:04  perev
72   	// StArray I/O + browser
73   	//
74   	// Revision 1.1  1999/04/30 13:15:55  fisyak
75   	// Ad StObject, modification StArray for StRootEvent
76   	//
77   	#include "StObject.h"
78   	#include "TDataSetIter.h"
79   	#include "TROOT.h"
80   	#include "TError.h"
81   	#include "TMath.h"
82   	#include "TBrowser.h"
83   	#include "TClass.h"
84   	#include "StArray.h"
85   	#include "StAutoBrowse.h"
86   	#include "TSystem.h"
87   	
88   	StXRefManager 	 *StXRefManager::fgManager=0;
89   	UInt_t 	          StObject::fgTally=0;
90   	StXRefManagerList StXRefManager::fgManagerList;
91   	int StXRefManager::fgRWmode=-1;
92   	enum {kBelongs = (1<<22)};
93   	
94   	
95   	ClassImp(StObject)
96   	//_____________________________________________________________________________
97   	StObject::StObject(const StObject &sto):TObject(sto)
98   	{
99   	  SetBit(kBelongs,0);
100  	}
101  	//_____________________________________________________________________________
102  	StObject &StObject::operator=(const StObject &sto)
103  	{
104  	  TObject::operator=(sto);
105  	  SetBit(kBelongs,0); return *this;
106  	}
107  	//_____________________________________________________________________________
108  	StObject::~StObject()
109  	{
110  	}
111  	//_____________________________________________________________________________
112  	void StObject::Browse(TBrowser *tb)
113  	{
114  	  StAutoBrowse::Browse(this,tb);
115  	}
116  	//_____________________________________________________________________________
117  	Bool_t StObject::IsFolder() const
118  	{
119  	  return StAutoBrowse::Browse((TObject*)this,0);
120  	}
121  	//______________________________________________________________________________
122  	void StObject::Streamer(TBuffer &R__b)
123  	{
124  	//	Stream an object of class StObject.
125  	  unsigned char uc=0;
126  	
127  	  if (R__b.IsReading()) {
128  	    Version_t R__v = R__b.ReadVersion();
129  	
130  	    switch (R__v){
131  	      case 1:  TObject::Streamer(R__b); 			return;
132  	      case 2:  R__b >> uc; if (uc) TObject::Streamer(R__b); 	return;
133  	      default: TObject::Streamer(R__b);				return;
134  	     }
135  	
136  	  } else {
137  	    R__b.WriteVersion(StObject::Class());
138  	    if (fgTally) {
139  	      UInt_t udx = GetUniqueID();
140  	      if (!udx) { udx = ++fgTally; SetUniqueID(udx);}
141  	    } 
142  	    TObject::Streamer(R__b);
143  	  }
144  	}
145  	//______________________________________________________________________________
146  	UInt_t StObject::Ztreamer(TBuffer &R__b)
147  	{
148  	   UInt_t udx = GetUniqueID();
149  	   if (!udx) { udx = ++fgTally; SetUniqueID(udx);}
150  	   R__b << udx;
151  	   return udx;
152  	}
153  	
154  	ClassImp(StUUId)
155  	//_____________________________________________________________________________
156  	StUUId::StUUId()
157  	{
158  	   memset(fID,0,16);
159  	}
160  	//_____________________________________________________________________________
161  	void StUUId::Generate()
162  	{
163  	   static UInt_t uu[4] = {0,0,0,0};
164  	   if (!uu[0]) {
165  	     uu[3]  = TMath::Hash(gSystem->HostName());
166  	     uu[3] ^= TMath::Hash(gSystem->WorkingDirectory());
167  	     uu[2]  = (gSystem->GetPid())<<16;
168  	   }
169  	   if (fID[0])	return;
170  	   fID[3] = uu[3]; 
171  	   fID[2] = uu[2]++;
172  	   fID[1] = (UInt_t)((ULong_t)this);
173  	#if ROOT_VERSION_CODE < 335105 /* ROOT_VERSION(5,29,1) */
174  	   fID[0] = (UInt_t)((ULong_t)gSystem->Now());
175  	#else 
176  	   fID[0] = (UInt_t)((ULong64_t)gSystem->Now());
177  	#endif
178  	}
179  	
180  	//_____________________________________________________________________________
181  	void StUUId::Streamer(TBuffer &R__b)
182  	{ 
183  	  if (R__b.IsReading()) {
184  	     R__b.ReadFastArray (fID,4);
185  	  } else {
186  	     R__b.WriteFastArray(fID,4);
187  	  } 
188  	}
189  	//_____________________________________________________________________________
190  	StUUId &StUUId::operator=(const StUUId &from)
191  	{
192  	  if (this != &from) memcpy(fID,from.fID,sizeof(fID));
193  	  return *this;
194  	}
195  	//_____________________________________________________________________________
196  	StUUId &StUUId::operator=(const char  *from )
197  	{
198  	  memcpy(fID,from    ,16); return *this;
199  	}
200  	//_____________________________________________________________________________
201  	int StUUId::Compare(const StUUId &u2) const
202  	{
203  	  return memcmp(fID,u2.fID,16);
204  	}
205  	
206  	
207  	//_____________________________________________________________________________
208  	ClassImp(StXRef)
209  	//_____________________________________________________________________________
210  	StXRef::StXRef(const char *brName, StXRefMain *evt,UInt_t tally)
211  	 : TDataSet(brName,evt)
212  	{
213  	   SetMain(evt);
214  	   if (evt) SetUUId(evt->GetUUId());
215  	   SetTally(tally);
216  	   
217  	}
218  	//_____________________________________________________________________________
219  	StXRef::~StXRef()
220  	{
221  	}
222  	
223  	//_____________________________________________________________________________
224  	void StXRef::Streamer(TBuffer &R__b)
225  	{
226  	   UInt_t R__s,R__c;
227  	   
228  	   if (R__b.IsReading() ) { //READ
229  	      StXRefManager::fgRWmode = 0;
230  	      Version_t R__v = R__b.ReadVersion(&R__s,&R__c); if (R__v){};
231  	      fUUId.Streamer(R__b);
232  	      StXRefManager::Open(this);
233  	      TDataSet::Streamer(R__b);
234  	      R__b >> fTally;
235  	      StXRefManager::Close(this);
236  	      Synchro(1);
237  	      R__b.CheckByteCount(R__s,R__c,Class());
238  	
239  	   } else {
240  	      StXRefManager::fgRWmode = 1;
241  	      assert(!fUUId.IsNull());
242  	      Synchro(0);
243  	      R__c = R__b.WriteVersion(Class(),kTRUE);
244  	      fUUId.Streamer(R__b);
245  	      StXRefManager::Open(this);
246  	      TDataSet::Streamer(R__b);
247  	      StXRefManager::Close(this);
248  	      R__b << fTally;
249  	      R__b.SetByteCount(R__c,kTRUE);
250  	   }
251  	}
252  	//_____________________________________________________________________________
253  	StXRefMain *StXRef::GetMain()
254  	{
255  	  if (!fMain) {
256  	    fMain = MakeMain();
257  	    fMain->SetUUId(fUUId);
258  	  }
259  	  return fMain;
260  	}
261  	//_____________________________________________________________________________
262  	void StXRef::Add(TDataSet *ds)
263  	{
264  	   if (ds == this) 		return;
265  	   if (ds->GetParent() == this) return;
266  	   TDataSet *os = FindByName(ds->GetName());
267  	   if (os == ds) 		return;
268  	   if (os){
269  	     assert(os->IsA()==ds->IsA());
270  	     TDataSetIter   Next(this);
271  	     StXRef *xr;
272  	     while((xr = (StXRef*)Next())) {
273  	       if (!xr->InheritsFrom(Class())) 	continue;
274  	       if (fUUId.Compare(xr->GetUUId()))continue;
275  	       Remove(xr);
276  	     }
277  	   }  
278  	   if (ds->InheritsFrom(Class())) 
279  	      assert(!fUUId.Compare(((StXRef*)ds)->GetUUId()));
280  	   ds->Shunt(0); TDataSet::Add(ds);
281  	}
282  	
283  	//_____________________________________________________________________________
284  	ClassImp(StXRefMain)
285  	
286  	StXRefMain::~StXRefMain()
287  	{
288  	}
289  	//______________________________________________________________________________
290  	void StXRefMain::Streamer(TBuffer &R__b)
291  	{
292  	   StXRef::Streamer(R__b);  
293  	}
294  	//_____________________________________________________________________________
295  	StXRefManager::StXRefManager(const StUUId &id)
296  	{
297  	   fTally = 0;
298  	   fUpd = 0;
299  	   fUUId = id;
300  	   fMain=0;
301  	   fgManagerList.push_front(this);
302  	   fColList.push_front(0);
303  	}
304  	//_____________________________________________________________________________
305  	StXRefManager::~StXRefManager()
306  	{
307  	   
308  	   UInt_t umin,umax,u;
309  	   fObjTab.GetMiMax(umin,umax);
310  	   for (u=umin;u<=umax;u++) {
311  	     TObject **to = (TObject**)fObjTab.Get(u);
312  	     if (!to ) continue;
313  	     if (!*to) continue;
314  	     (*to)->SetUniqueID(0);
315  	   }
316  	
317  	   fgManagerList.remove(this);
318  	   if (fgManager==this) { fgManager=0; StObject::fgTally=0;}
319  	   fMain=0; fTally=0;
320  	   for (StCollListIter it = fColList.begin(); *it ;it++) {delete *it;}
321  	}
322  	
323  	
324  	//_____________________________________________________________________________
325  	void StXRefManager::Cd(StXRef *xref)
326  	{
327  	  StXRefManager *man = fgManager;
328  	  if (man) {
329  	     if (man->fTally!=StObject::fgTally) {//Was modified
330  	        man->fTally = StObject::fgTally;
331  	  }  } 
332  	
333  	  if (!man || man->fUUId.Compare(xref->GetUUId())!=0) {
334  	     StXRefManagerListIter it;
335  	     man = 0;
336  	     for (it=fgManagerList.begin();it!=fgManagerList.end();it++){
337  	       StXRefManager *m=*it;
338  	       if (m->fUUId.Compare(xref->GetUUId())!=0)	continue;
339  	       man = m; break;
340  	  }  }
341  	  fgManager = man;
342  	}
343  	//_____________________________________________________________________________
344  	void StXRefManager::Open(StXRef *xref)
345  	{
346  	  if (fgRWmode==1) {		//Writing
347  	    if (xref->IsMain()) StObject::fgTally=1;
348  	    return;
349  	  }
350  	
351  	  Cd(xref);
352  	  StXRefManager *man = fgManager;
353  	  if (!man) {
354  	     assert(xref->IsMain());
355  	     man = new StXRefManager(xref->GetUUId());
356  	     fgManagerList.push_front(man);
357  	     fgManager   = man;
358  	     StObject::fgTally=1;  
359  	  }
360  	  if (man->fMain==0) {
361  	     man->fMain  = xref->GetMain();
362  	  } else {
363  	     xref->SetMain(man->fMain);
364  	  }
365  	}
366  	//_____________________________________________________________________________
367  	void StXRefManager::Close(StXRef *xref)
368  	{
369  	  if (fgRWmode==1) {		//Writing
370  	    if (!xref->IsMain()) return;
371  	    StObject::fgTally=0;fgRWmode=-1;
372  	    return;
373  	  }
374  	  Cd(xref);
375  	  StXRefManager *man = fgManager;
376  	  assert(man);
377  	  if (xref->IsMain()) man->Update();
378  	  if (man->fMain && man->fMain!= xref) man->fMain->Add(xref);
379  	  if (!xref->IsMain()) return;
380  	  delete man; fgRWmode=-1; StObject::fgTally=0;
381  	}  
382  	
383  	
384  	//_____________________________________________________________________________
385  	void StXRefManager::AddColl (StProxyUrr *rarr)
386  	{   
387  	   fUpd=1; fColList.push_front(rarr);
388  	}
389  	//_____________________________________________________________________________
390  	void StXRefManager::AddColl (const StStrArray *sarr)
391  	{   
392  	   int size = sarr->size();
393  	   if (!size) 	return;
394  	   fUpd=1;
395  	   UInt_t u;
396  	   const TObject *to, **p;
397  	   const_VecTObjIter it= sarr->begin(); 
398  	   for(int i=0;i<size;i++) {
399  	     if (!(to = it[i]))			continue;
400  	     if (!(u = to->GetUniqueID()))	continue;
401  	     p = (const TObject**)fObjTab.GET(u);
402  	     if (*p) 	{// Used already		
403  	       if (*p == to)			continue;
404  	       assert(to->IsA() == (*p)->IsA()); 
405  	     }
406  	     *p = to;
407  	   }
408  	}
409  	//_____________________________________________________________________________
410  	void StXRefManager::Update ()
411  	{
412  	  if(!fUpd) return;
413  	  fUpd = 0;
414  	  StObjArray *arr;
415  	  StProxyUrr *urr;
416  	  StCollListIter it;
417  	  UInt_t idx,udx,sizeUrr,lst=999999;
418  	  TObject **p; 
419  	  for (it = fColList.begin(); (urr = *it);) {//List
420  	    sizeUrr = urr->size(); 
421  	    switch (urr->GetType()) {
422  	
423  	      case 1: 		//Link case
424  	      assert(sizeUrr==1);
425  	      lst = 2;
426  	      udx = (*urr)[0];
427  	      p = (TObject**)fObjTab.Get(udx);
428  	      if (!p || !(*p)) 		break;
429  	      urr->GetAdr()[0] = *p;
430  	      lst = 0;			break;
431  	
432  	      case 0: 		//refArray case 
433  	      lst=0;
434  	      arr = (StObjArray*)urr->GetArr(); assert(arr);
435  	      for (idx=0;idx<sizeUrr;idx++) { //RefArray loop 
436  	         udx = (*urr)[idx];
437  	         p = (TObject**)fObjTab.Get(udx);
438  	         if (!p || !(*p))	{(*urr)[lst++] = udx; continue;}
439  	         arr->push_back(*p); 
440  	      }//end RefArray loop
441  	    }
442  	    if (lst) { urr->resize(lst-1);     it++;      }
443  	    else     {it = fColList.erase(it); delete urr;}
444  	  }//end List
445  	
446  	}
447  	//_____________________________________________________________________________
448  	void StXRefManager::Clear (Option_t*)
449  	{}
450  	
451  	//_____________________________________________________________________________
452  	TDataSet *StXRefManager::GetMain()
453  	{
454  	   if (!fgManager) return 0;
455  	   return fgManager->fMain;
456  	}
457  	//_____________________________________________________________________________
458  	TPageMap::TPageMap()
459  	{
460  	
461  	  fList = 0;
462  	  fTopPage = NewPage();
463  	  fLstPage = 0;
464  	  fLstUdx  = 0;
465  	  fMinUdx = 1000000000;
466  	  fMaxUdx = 0;
467  	}
468  	//_____________________________________________________________________________
469  	
470  	
471  	TPageMap::~TPageMap()
472  	{
473  	   ULong_t *p,*n=0;
474  	   for (p = fList; p ; p = n) 
475  	   { n = (ULong_t*)p[0]; free(p);}
476  	}     
477  	//_____________________________________________________________________________
478  	ULong_t *TPageMap::NewPage()  
479  	{
480  	   int n = sizeof(ULong_t)*(kPAGE+1);
481  	   ULong_t *p = (ULong_t*)malloc(n); memset(p,0,n);
482  	   p[0] = (ULong_t)fList; fList = p;
483  	   return p+1;
484  	}
485  	
486  	//_____________________________________________________________________________
487  	ULong_t *TPageMap::Get(UInt_t udx) 
488  	{
489  	   if ((udx&kLAST) == fLstUdx) {
490  	      if (!fLstPage) 	return 0;
491  	
492  	   }  else {
493  	
494  	      fLstPage = 0;
495  	      fLstUdx = (udx&kLAST);
496  	      ULong_t *b = fTopPage;
497  	      UInt_t   u,s=kBITZ;
498  	      while(2001) {
499  	        u = (udx>>s)&kMASK;
500  	        b = (ULong_t*)b[u];
501  	        if (!b) 		return 0;
502  	        if (!(s -=kBITS))  	break;;
503  	      }
504  	      fLstPage = b;
505  	   }
506  	    return fLstPage + (udx&kMASK);
507  	}
508  	//_____________________________________________________________________________
509  	ULong_t *TPageMap::GET(UInt_t udx) 
510  	{
511  	   if (fMinUdx>udx) fMinUdx=udx;
512  	   if (fMaxUdx<udx) fMaxUdx=udx;
513  	
514  	   if ((udx&kLAST) != fLstUdx || fLstPage==0) {
515  	      fLstUdx = (udx&kLAST);
516  	      ULong_t *b = fTopPage,*a;
517  	      UInt_t   u,s=kBITZ;
518  	      while(2001) {
519  	        u = (udx>>s)&kMASK;
520  	        if (!(a = (ULong_t*)b[u])) 	{((ULong_t**)b)[u] = a = NewPage();}   
521  	        b = a;
522  	        if (!(s -=kBITS))  		break;;
523  	      }
524  	      fLstPage = b;
525  	   }
526  	   return fLstPage + (udx&kMASK);
527  	}
528  	//_____________________________________________________________________________
529  	void TPageMap::Test()
530  	{
531  	  TPageMap map;
532  	  
533  	  UInt_t range = 10000000;
534  	  UInt_t step  = range/1000;
535  	  UInt_t u;
536  	  for (u=1; u < range; u+=step)
537  	  {
538  	     ULong_t *p = map.GET(u);
539  	     assert(p);
540  	     assert(!*p);
541  	     *p = u;
542  	  }
543  	  for (u=1; u < range; u+=step)
544  	  {
545  	     ULong_t *p = map.Get(u);
546  	     assert(p);
547  	     assert(*p);
548  	     assert(*p==u);
549  	  }
550  	  printf(" TPageMap::Test() OK\n");
551  	}  
552  	  
553  	  
554  	   
555  	     
556  	
557  	
558  	
559  	
560  	
561