Dump object functionality
[u/mrichter/AliRoot.git] / STEER / CDB / AliOCDBtoolkit.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /*
17
18   Primary goal of the proposal was to provide functionality to browse and compare the content of the OCDB
19   specified by different means.
20
21   a.) galice.root               - as currently implemented by Ruben in MC (or any file with cdbMap, and cdbList)
22   b.) AliESDs.root              - for the reconstructed data
23   c.) ocdb snapshot             - as used for grid productions
24   d.) TMap(s)                   - as used internally in galice.root and AliESDs,root  
25   e.) log file (if possible)    - looks logs aways used similar syntax, tested and working
26   f.) C macro                   - custom macro
27
28   Content comparison should be done:
29   a.) on the level of symbolic links 
30   b.) on the level of content itself 
31   - by by byte comparison dif
32   - data member by data member comparison
33
34   Implementation assumption:
35   All input formats (a .. f) will  be converted to the TMap storages and TList if AliCDBIds 
36
37   Example usage:
38   AliOCDBtoolkit::MakeDiffExampleUseCase();
39
40
41
42   //=============================================================================
43   // Functionality to dump content of  objects in human readable format
44   //=============================================================================
45   Use case examples 
46   1.) compare oontent of alignent OCDB files for differnt yers
47   2.) compare ClusterParam for different periods
48   
49   
50    
51   =================================================================================================================
52   // 1.)
53   // Compare alignment example:
54   // Compare TPC alignemnt 2013 and 2010
55   //
56   AliOCDBtoolkit::DumpOCDBFile("/cvmfs/alice.gsi.de/alice/data/2013/OCDB/TPC/Align/Data/Run0_999999999_v1_s0.root","TPCalign2013.dump",1);
57   AliOCDBtoolkit::DumpOCDBFile("/cvmfs/alice.gsi.de/alice/data/2010/OCDB/TPC/Align/Data/Run0_999999999_v1_s0.root","TPCalign2010.dump",1);
58   diff  TPCalign2013.dump TPCalign2010.dump > TPCalign2013_TPCalign2010.diff
59   //
60   //    
61   =================================================================================================================
62   //  2.) 
63   // Compare CluterParam OCDB etry
64   //
65   AliOCDBtoolkit::DumpOCDBFile("/cvmfs/alice.gsi.de/alice/data/2010/OCDB/TPC/Calib/ClusterParam/Run131541_999999999_v2_s0.root","2010_TPC_Calib_ClusterParam_Run131541_999999999_v2_s0.dump",1);
66   AliOCDBtoolkit:: AliOCDBtoolkit::DumpOCDBFile("/cvmfs/alice.gsi.de/alice/data/2010/OCDB/TPC/Calib/ClusterParam/Run0_999999999_v1_s0.root","2010_TPC_Calib_ClusterParam_Run0_999999999_v1_s0.dump",1);
67   AliOCDBtoolkit::DumpOCDBFile("/cvmfs/alice.gsi.de/alice/data/2013/OCDB/TPC/Calib/ClusterParam/Run0_999999999_v1_s0.root","2013_TPC_Calib_ClusterParam_Run0_999999999_v1_s0.dump",1);
68   diff 2010_TPC_Calib_ClusterParam_Run131541_999999999_v2_s0.dump 2010_TPC_Calib_ClusterParam_Run0_999999999_v1_s0.dump
69  
70
71 */
72
73
74 using namespace std;
75
76 // STD
77 #include <iostream>
78 #include <algorithm>
79 #include <sstream>
80 #include <stdexcept>
81 #include <functional>
82 #include "TRealData.h"
83 #include "TDataMember.h"
84 #include "TClass.h"
85 #include "TROOT.h"
86 #include <TVectorD.h>
87 //
88 #include "TSystem.h"
89 #include "TObjArray.h"
90 #include "TString.h"
91 #include "TTree.h"
92 #include "TMessage.h"
93 //
94 #include "AliCDBManager.h"
95 #include "AliCDBEntry.h"
96 #include "AliOCDBtoolkit.h"
97
98
99
100 void AliOCDBtoolkit::MakeDiffExampleUseCase(){
101   //
102   // Example usage for the MC 
103   // To run example case, assuming presence of following files in working directory: 
104   //    - rec.log        
105   //    - galice.root   
106   //    - AliESDs.root
107   //
108   AliCDBManager * man = AliCDBManager::Instance();
109   LoadOCDBFromLog("rec.log",0);
110   const TMap *cdbMapLog= man->GetStorageMap();        // this is map of 
111   const TList *cdbListLog=man->GetRetrievedIds();     // this is list of AliCDBId
112   //  TList *cdbListLog0=man->GetRetrievedIds();     // this is list of AliCDBId
113   //
114   TFile *fmc = TFile::Open("galice.root");
115   TMap *cdbMapMC= (TMap*)fmc->Get("cdbMap");          // 
116   TList *cdbListMC0= (TList*)fmc->Get("cdbList");     // this is list of TObjStrings
117   TList *cdbListMC = ConvertListStringToCDBId(cdbListMC0);        // convert to the TObjArray of AliCDBids
118   //
119   TFile *fesd = TFile::Open("AliESDs.root");
120   TList *listESD = ((TTree*)fesd->Get("esdTree"))->GetUserInfo();
121   TMap *cdbMapESD= (TMap*)listESD->FindObject("cdbMap");  
122   TList *cdbListESD0= (TList*)listESD->FindObject("cdbList"); // this is list of TObjStrings
123   TList *cdbListESD = ConvertListStringToCDBId(cdbListESD0);              // convert to the TObjArray  of AliCDBids
124   //
125   //
126   //
127   printf("\n\n");
128   printf("Diff log>>>ESD\n\n:");
129   MakeDiff(cdbMapLog, cdbListLog, cdbMapESD, cdbListESD,0);
130   printf("\n\n");
131   printf("Diff ESD>>>log\n\n:");
132   MakeDiff(cdbMapESD, cdbListESD,cdbMapLog, cdbListLog,0);
133   // 
134   printf("\n\n");
135   printf("Diff ESD>>>MC\n\n:");
136   MakeDiff(cdbMapMC, cdbListMC, cdbMapESD, cdbListESD,0);
137 }
138
139
140 void AliOCDBtoolkit::DumpOCDBAsTxt(const TString fInput,const TString fType){
141   //
142   //
143   //
144   TFile *file;
145   const TMap *cdbMap;
146   const TList *cdbList;
147   //
148   //
149   
150   if(fType.EqualTo("MC",TString::kIgnoreCase)){
151         file = TFile::Open(fInput.Data());
152         cdbMap = (TMap*)file->Get("cdbMap");          // 
153         TList *cdbListMC0 = (TList*)file->Get("cdbList");     // this is list of TObjStrings
154         cdbList = ConvertListStringToCDBId(cdbListMC0);        // convert to the TObjArray of AliCDBids
155   } 
156     else if(fType.EqualTo("ESD",TString::kIgnoreCase)){
157       file = TFile::Open(fInput.Data());
158       TList *listESD = ((TTree*)file->Get("esdTree"))->GetUserInfo();
159       cdbMap = (TMap*)listESD->FindObject("cdbMap");  
160       TList *cdbListESD0= (TList*)listESD->FindObject("cdbList"); // this is list of TObjStrings
161       cdbList = ConvertListStringToCDBId(cdbListESD0);              // convert to the TObjArray  of AliCDBids
162     }
163     else if(fType.EqualTo("log",TString::kIgnoreCase)){
164         AliCDBManager * man = AliCDBManager::Instance();
165         LoadOCDBFromLog(fInput.Data(),0);
166         cdbMap = man->GetStorageMap();        // this is map of 
167         cdbList =man->GetRetrievedIds();     // this is list of AliCDBId
168     }
169     else{
170         printf("unsupported option: %s",fType.Data());
171         return;
172     }
173   cout <<"BEGINDUMP:" << endl;
174   DumpOCDB(cdbMap,cdbList);
175 }
176
177
178 Bool_t AliOCDBtoolkit::ParseInfoFromOcdbString(TString ocdbString, TString &ocdbPath, Int_t &run0, Int_t &run1, Int_t &version, Int_t &subVersion){
179   //
180   // Parse OCDB id string and provide basic ocdb information
181   //
182   //  a.) parse ocdbPath
183   Int_t indexBeginPath= ocdbString.Index("path: ")+7;
184   if (indexBeginPath<0) return kFALSE;
185   Int_t indexEndPath=ocdbString.Index(";",indexBeginPath);
186   if (indexEndPath<0) return kFALSE;
187   ocdbPath=TString(&(ocdbString.Data()[indexBeginPath]), indexEndPath-indexBeginPath-1);
188   // b.) parse runRange
189   Int_t indexRun0= ocdbString.Index(": [",indexEndPath)+3;
190   if (indexRun0<0) return kFALSE;
191   Int_t indexRun1= ocdbString.Index(",",indexRun0)+1;
192   if (indexRun1<0) return kFALSE;
193   run0=atoi(&(ocdbString.Data()[indexRun0]));
194   run1=atoi(&(ocdbString.Data()[indexRun1]));
195   AliCDBRunRange runRange(run0,run1);
196   //c.) parse version, subversion
197   Int_t indexVersion= ocdbString.Index("version: v",indexRun1)+10;
198   if (indexVersion<0) return kFALSE;
199   Int_t indexSubVersion= ocdbString.Index("_s",indexVersion)+2;
200   if (indexSubVersion<0) return kFALSE;
201   version=atoi(&(ocdbString.Data()[indexVersion]));
202   subVersion=atoi(&(ocdbString.Data()[indexSubVersion]));
203   return kTRUE;
204 }
205
206 Bool_t AliOCDBtoolkit::ParseInfoFromOcdbString(TString ocdbString, AliCDBId &cdbId){
207   //
208   // Parse OCDB id string and provide basic ocdb information and fillcdbID object
209   //
210   TString ocdbPath;
211   Int_t run0=0, run1=0;
212   Int_t version=0, subVersion=0;
213   Bool_t parseStatus = ParseInfoFromOcdbString(ocdbString, ocdbPath, run0,run1,version,subVersion); 
214   if (parseStatus) {
215     AliCDBRunRange runRange(run0,run1);
216     cdbId=AliCDBId(ocdbPath.Data(),runRange,version,subVersion);
217     AliCDBId* id = AliCDBId::MakeFromString(ocdbString);
218     cdbId=*id;
219     delete id;
220   }
221   //
222   return parseStatus;
223 }
224
225 TList  * AliOCDBtoolkit::ConvertListStringToCDBId(const TList *cdbList0){
226   //
227   // Convert input  list of the TObjString to list to AliCDBid 
228   //
229   Int_t entriesList0=cdbList0->GetEntries();
230   TList * array0 = new TList();
231   AliCDBId tmp0;
232   for (Int_t ientry0=0; ientry0<entriesList0; ientry0++){
233     if (cdbList0->At(ientry0)==0) continue;
234     Bool_t isId =  cdbList0->At(ientry0)->IsA()->InheritsFrom("AliCDBId");
235     if (isId){
236       array0->AddLast(cdbList0->At(ientry0));
237     }else{
238       Bool_t isString =  cdbList0->At(ientry0)->IsA()->InheritsFrom("TObjString");
239       if (isString){
240         TObjString* sid0 = dynamic_cast<TObjString*> (cdbList0->At(ientry0));
241         Bool_t status =  ParseInfoFromOcdbString(sid0->String(), tmp0);
242         if (!status) continue;
243         array0->AddLast(new AliCDBId(tmp0));
244       }
245     }
246   }
247   return array0;  
248 }
249
250
251
252 void AliOCDBtoolkit::LoadOCDBFromLog(const char *logName, Int_t verbose){
253   //
254   // Initilaize OCDB
255   // Load OCDB setting as specified in log
256   // Assuming fixed version of the log 
257   // AliCDBManager is initilaized - ocdbMap and ID list can be exported
258   //
259
260   // Parsing/loading sequence:
261   //    0.) SetDefault storage  *** Default Storage URI:
262   //    1.) SetSpecific storage  *** Specific storage
263   //    2.) SetRunNumber  Run number:
264   //    3.) Set used IDs
265   //
266   AliCDBManager * man = AliCDBManager::Instance();
267   //
268   // 0.) SetDefault storage  *** Default Storage URI:
269   // 
270   TString  defaultOCDB = gSystem->GetFromPipe(TString::Format("cat %s| grep \"Storage URI:\"",logName).Data());
271   TObjArray *array = defaultOCDB.Tokenize("\"");
272   man->SetDefaultStorage(array->Last()->GetName());
273   delete array;
274   //
275   // 1.) SetSpecific storage  *** Specific storage
276   //
277   TString  specificStorage  = gSystem->GetFromPipe(TString::Format("cat %s| grep \"Specific storage\"",logName).Data());
278   array = specificStorage.Tokenize("\"");
279   Int_t entries = array->GetEntries();
280   for (Int_t i=1; i<entries-2; i+=4){    
281     // add protection here line shuld be in expected format
282     if (verbose&2>0) printf("%s\t%s\n",array->At(i)->GetName(),array->At(i+2)->GetName());    
283     man->SetSpecificStorage(array->At(i)->GetName(),array->At(i+2)->GetName());
284   }
285   delete array;
286   //
287   // 2.) SetRunNumber  Run number:
288   //
289   TString  runLine  = gSystem->GetFromPipe(TString::Format("cat %s| grep \"I-AliCDBManager::Print: Run number =\"",logName).Data());
290   array = runLine.Tokenize("=");
291   Int_t run = 0;
292   if (array->GetEntries()>1) run=atoi(array->At(1)->GetName()); 
293   delete array;
294   man->SetRun(run);  
295   //
296   // 3.) Set used IDs
297   //   
298   TString  ids =   gSystem->GetFromPipe(TString::Format("cat %s| grep I-AliCDB | grep path| grep range | grep version", logName).Data());
299   array= ids.Tokenize("\n");
300   entries = array->GetEntries();
301   //
302   for (Int_t i=0; i<entries; i++){
303     //
304     TString ocdbString = array->At(i)->GetName();
305     TString ocdbEntry;
306     TString ocdbPath;
307     Int_t run0=0, run1=0;
308     Int_t version=0, subVersion=0;
309     Bool_t parseStatus = ParseInfoFromOcdbString(ocdbString, ocdbPath, run0,run1,version,subVersion); 
310     if (!parseStatus) continue;
311     AliCDBRunRange runRange(run0,run1);
312     //
313     if ((verbose&2)!=0) {
314       printf("%s/Run%d_%d_v%d_s%d.root\n",ocdbPath.Data(),run0,run1,version,subVersion); 
315     }
316     try {
317       AliCDBEntry*entry= man->Get(ocdbPath.Data(),runRange,version,subVersion);
318     } catch(const exception &e){
319       cerr << "OCDB retrieval failed!" << endl;
320       cerr << "Detailes: " << e.what() << endl;
321     }
322   }  
323   if ((verbose&1)!=0){
324     man->Print();
325     man->GetStorageMap()->Print();
326     man->GetRetrievedIds()->Print(); 
327   }
328 }
329
330
331 void AliOCDBtoolkit::LoadOCDBFromMap(const TMap */*cdbMap*/, const TList */*cdbList*/){
332   //
333   // Initilaize OCDB
334   // Load OCDB setting as specified in maps
335   // Or Do we have already implementation in AliCDBanager?
336 }
337
338
339
340 void AliOCDBtoolkit::MakeDiff(const TMap *cdbMap0, const TList *cdbList0, const TMap *cdbMap1, const TList *cdbList1, Int_t verbose){
341   //
342   //
343   // Print difference between the 2 ocdb maps
344   // Input:
345   //   maps and list charactireizing OCDB setup  
346   // Output:
347   //   To be decided, currently it is the teinal output
348   //
349   Int_t entriesList0=cdbList0->GetEntries();
350   Int_t entriesList1=cdbList1->GetEntries();
351   //
352   for (Int_t ientry0=0; ientry0<entriesList0; ientry0++){
353     AliCDBId *id0    = dynamic_cast<AliCDBId*> (cdbList0->At(ientry0));
354     AliCDBId *id1=0;
355     for (Int_t ientry1=0; ientry1<entriesList1; ientry1++){
356       AliCDBId *cid1    = dynamic_cast<AliCDBId*> (cdbList1->At(ientry1));
357       //id0.Print();
358       //cid1.Print();
359       if (cid1->GetPath().Contains(id0->GetPath().Data())==0) continue;
360       id1=cid1;
361     }
362     if (!id1) {
363       printf("Missing entry\t");
364       id0->Print();
365       continue;
366     }
367     Bool_t isOK=kTRUE;
368     if (id0->GetFirstRun()!= id1->GetFirstRun() ||id0->GetLastRun()!= id1->GetLastRun()){
369       printf("Differrent run range\n");
370       id0->Print();
371       id1->Print();
372     }    
373     if (id0->GetVersion()!= id1->GetVersion() ||id0->GetSubVersion()!= id1->GetSubVersion()){
374       printf("Differrent version\n");
375       id0->Print();
376       id1->Print();
377     }    
378   }
379 }
380
381 void AliOCDBtoolkit::DumpOCDB(const TMap *cdbMap0, const TList *cdbList0){
382   //
383   // Dump the OCDB configuatation as formated text file 
384   // with following collumns
385   // cdb name  prefix cdb path
386   // OCDB entries are sorted alphabetically
387   // e.g:
388   // TPC/Calib/RecoParam /hera/alice/jwagner/software/aliroot/AliRoot_TPCdev/OCDB/ TPC/Calib/RecoParam/Run0_999999999_v0_s0.root $SIZE_AliCDBEntry_Object $HASH_AliCDBEntry_Object
389   
390   AliCDBManager * man = AliCDBManager::Instance();
391   
392   TList * cdbList = (TList*) cdbList0;   // sorted array
393   cdbList->Sort();
394
395   TIter next(cdbList);
396   AliCDBId *CDBId;
397   TString cdbName;
398   TString cdbPath;
399   TObjString *ostr;
400   AliCDBEntry *cdbEntry;
401   UInt_t hash;
402   TMessage * file;
403   Int_t size; 
404   
405   while ((CDBId  =(AliCDBId*) next())){
406     cdbName = CDBId->GetPath();
407     ostr = (TObjString*)cdbMap0->GetValue(cdbName.Data());
408     if(!ostr) ostr = (TObjString*)cdbMap0->GetValue("default");
409     cdbPath = ostr->GetString();
410     if(cdbPath.Contains("local://"))cdbPath=cdbPath(8,cdbPath.Length()).Data();
411     
412     cdbEntry = (AliCDBEntry*) man->Get(*CDBId);
413     TObject *obj = cdbEntry->GetObject();
414     file = new TMessage(TBuffer::kWrite);
415     file->WriteObject(obj);
416     size = file->Length();
417     if(!obj){
418       printf("object %s empty!\n",cdbName.Data());
419       continue;
420     }
421     hash = TString::Hash(file->Buffer(),size);
422     printf("%s\t%s\t%s/Run%d_%d_v%d_s%d.root\t%d\t%u\n",
423            cdbName.Data(),
424            cdbPath.Data(),
425            cdbName.Data(),
426            CDBId->GetFirstRun(),
427            CDBId->GetLastRun(),
428            CDBId->GetVersion(),
429            CDBId->GetSubVersion(),
430            size,
431            hash
432            );
433     //if(!(CDBId->GetPathLevel(0)).Contains("TPC")) continue;
434     //cout << CDBId.ToString() << endl;
435     delete file;
436   }
437 }
438
439
440 //====================================================================================================
441 //  Dump object part
442 //==================================================================================================== 
443
444
445
446
447
448 void AliOCDBtoolkit::DumpOCDBFile(const char *finput , const char *foutput, Bool_t dumpMetaData, Bool_t xml){
449   //
450   //  
451   //  DumpOCDBFile("$ALICE_ROOT/OCDB/ITS/Align/Data/Run0_999999999_v0_s0.root", "ITS_Align_Data_Run0_999999999_v0_s0.dump")
452   //
453   if (finput==0) return ;
454   TFile *falignITS  = TFile::Open(finput);
455   AliCDBEntry *entry  = (AliCDBEntry*)falignITS->Get("AliCDBEntry");
456   if (!entry) return; 
457   TObject *obj = ((AliCDBEntry*)falignITS->Get("AliCDBEntry"))->GetObject();  
458
459   //
460   if (!xml){
461     if (dumpMetaData) gROOT->ProcessLine(TString::Format("((TObject*)%p)->Dump(); >%s",entry, foutput).Data());
462     if (!obj) return;
463     gROOT->ProcessLine(TString::Format("DumpObjectRecursive((TObject*)%p); >>%s",obj, foutput).Data());
464   }
465   if (xml){
466     TFile * f = TFile::Open(TString::Format("%s.xml",foutput).Data(),"recreate");
467     if (dumpMetaData) entry->Write("AliCDBEntry");
468     else obj->Write("AliCDBEntry");
469     f->Close();
470   }
471 }
472
473
474
475 void AliOCDBtoolkit::DumpObjectRecursive(TObject *obj){
476   //
477   //
478   //
479   Int_t counterRec=0;
480   printf("==> Dumping object at: %p, name=%s, class=%s)\n", obj, obj->GetName(), (obj->IsA()->GetName()));
481   DumpObjectRecursive(obj, TString(obj->IsA()->GetName())+".",counterRec);
482 }
483  
484 //
485 //
486 //
487 void AliOCDBtoolkit::DumpObjectRecursive(TObject *obj, TString prefix, Int_t &counterRec){
488   //
489   // Recursive dump of the TObject
490   // Dump all basic types and follow pointers to the objects
491   // current limitation:
492   //    a.) clases and structures not derived from TObject not followed (to fix)
493   //    b.) dynamic arrays not followed
494   //    c.) std maps,array ....  not followed
495   //    
496   //
497   if (!obj) return;
498   //
499   // Special case of Collection classes
500   //
501   if (obj->IsA()->InheritsFrom(TCollection::Class())) {
502     TIter myiter((TCollection*)obj);
503     TObject  *arObject=0;
504     Int_t counter=0;
505     while ((arObject = (TObject*)myiter.Next())) {
506       TString prefixArr = TString::Format("%s[%d]",prefix.Data(),counter);
507       DumpObjectRecursive(arObject,prefixArr,counterRec);
508       counter++;
509     } 
510     counterRec++;
511     return;
512   }
513
514   TClass * cl = obj->IsA();
515   if (!(cl->GetListOfRealData())) cl->BuildRealData();
516   TRealData* rd = 0;
517   TIter next(cl->GetListOfRealData());  
518   while ((rd = (TRealData*) next())) {
519     counterRec++;
520     TDataMember* dm = rd->GetDataMember();
521     TDataType* dtype = dm->GetDataType();
522     Int_t offset = rd->GetThisOffset();
523     char* pointer = ((char*) obj) + offset;
524     
525     if (dm->IsaPointer()) {
526       // We have a pointer to an object or a pointer to an array of basic types.
527       TClass* clobj = 0;
528       if (!dm->IsBasic()) {
529         clobj = TClass::GetClass(dm->GetTypeName());
530       }
531       if (clobj) {
532         // We have a pointer to an object.
533         //
534         if (!clobj->InheritsFrom(TObject::Class())) {
535           // It must be a TObject object.
536           continue; 
537         }
538         char** apointer = (char**) pointer;
539         TObject* robj = (TObject*) *apointer;
540         //      
541         if(!robj)
542           printf("M:%s%s\n",prefix.Data(),dm->GetName()); // Missing - 0 pointer
543         else{
544           printf("T:%s\t%s%s\n", clobj->GetName(),prefix.Data(), dm->GetName());
545           TString prefixNew=prefix;
546           prefixNew+=dm->GetName();
547           prefixNew+=".";
548           if (robj!=obj) DumpObjectRecursive(robj,prefixNew,counterRec);  // trivial check 
549           if (robj==obj){
550             printf("R:%s\t%s%s\n",clobj->GetName(),prefix.Data(), dm->GetName());
551           }
552         }
553       }
554     } else if (dm->IsBasic()) {
555       //
556       // Basic data type
557       //
558       const char* index = dm->GetArrayIndex();
559       if (dm->GetArrayDim()==0){
560         printf("B:\t%s%s\t%s\n", prefix.Data(),rd->GetName(), dtype->AsString(pointer));
561       }
562       //
563       // Basic array - fixed length
564       //
565       //      if (dm->GetArrayDim()>0 && strlen(index) != 0){
566       if (dm->GetArrayDim()>0 ){
567         printf("A:\t%s%s\t",prefix.Data(),rd->GetName());
568         Int_t counter=0;
569         for  (Int_t idim=0; idim<dm->GetArrayDim(); idim++){
570           //printf("A:%d\t%d\n", dm->GetArrayDim(),dm->GetMaxIndex(idim));
571           for (Int_t j=0; j<dm->GetMaxIndex(idim); j++){
572             printf("%s\t",dtype->AsString(pointer+dm->GetUnitSize()*counter));
573             counter++;
574             if (counter%5==0) printf("\nA:\t%s%s\t",prefix.Data(),rd->GetName());
575           }
576         }
577         printf("\n");
578       }
579       //
580       // Basic array - dynamic length
581       //
582       if (dm->GetArrayDim()>0 && strlen(index) != 0){
583         //
584         // Dump first only for the moment
585         //  
586         printf("B:\t%s%s\t%s\n",prefix.Data(),rd->GetName(), dtype->AsString(pointer));
587       }
588     } else {
589     }
590   }
591 }  
592
593 //
594 // Small checks to test the TRealData and TDataType
595 //
596
597
598
599 void DumpDataSimple(){
600   //
601   // Dump example for elenatr data types 
602   //
603   TObject *obj = new TVectorD(20);
604   TClass * cl = obj->IsA();
605   if (!cl->GetListOfRealData()) cl->BuildRealData();
606   //
607   TRealData* rd = 0;
608   rd = (TRealData*)(cl->GetListOfRealData()->FindObject("fNrows"));
609   TDataMember* dm = rd->GetDataMember();
610   TDataType* dtype = dm->GetDataType();
611   //
612   Int_t offset = rd->GetThisOffset();
613   char* pointer = ((char*) obj) + offset;
614   printf("%s\n",dtype->AsString(pointer));
615 }
616
617 void DumpDataArray(){
618   //
619   // print array example
620   // 
621   TObject *obj = new TVectorD(20);
622   TClass * cl = obj->IsA();
623   if (!cl->GetListOfRealData()) cl->BuildRealData();
624   TRealData* rd = 0;
625   rd = (TRealData*)(cl->GetListOfRealData()->FindObject("*fElements"));
626   TDataMember* dm = rd->GetDataMember();
627   TDataType* dtype = dm->GetDataType();
628   dtype->Print();
629   //
630   Int_t offset = rd->GetThisOffset();
631   char* pointer = ((char*) obj) + offset; 
632   printf("%s\n",dtype->AsString(pointer));
633 }
634
635 void DumpTObjectArray(){
636   //
637   //
638   //
639   TObjArray *array = new TObjArray(10);
640   for (Int_t i=0; i<10; i++) array->AddLast(new TNamed(Form("n%d",i), Form("n%d",i)));  
641    AliOCDBtoolkit::DumpObjectRecursive(array);
642   //
643   //
644   TObject *obj = array;
645   TClass * cl = obj->IsA();
646   if (!cl->GetListOfRealData()) cl->BuildRealData();
647   TRealData* rd = 0;
648   rd = (TRealData*)(cl->GetListOfRealData()->FindObject("*fCont"));
649   TDataMember* dm = rd->GetDataMember();
650   TDataType* dtype = dm->GetDataType();
651   //
652   Int_t offset = rd->GetThisOffset();
653   char* pointer = ((char*) obj) + offset;
654   char** apointer = (char**) pointer;
655   //we have pointer to pointer here
656   TObject** ppobj = (TObject**) *apointer;
657   (*ppobj)->Print();
658   //
659   TIter myiter(array);
660   TObject  *arObject; 
661   dtype->Print();
662   while ((arObject = (TObject*)myiter.Next())) {
663     AliOCDBtoolkit::DumpObjectRecursive(arObject);
664   } 
665 }