ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TTreeCloner.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Author: Philippe Canal 07/11/2005
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TTreeCloner
13 Class implementing or helping the various TTree cloning method
14 */
15 
16 #include "TBasket.h"
17 #include "TBranch.h"
18 #include "TBranchClones.h"
19 #include "TBranchElement.h"
20 #include "TStreamerInfo.h"
21 #include "TBranchRef.h"
22 #include "TError.h"
23 #include "TProcessID.h"
24 #include "TMath.h"
25 #include "TTree.h"
26 #include "TTreeCloner.h"
27 #include "TFile.h"
28 #include "TLeafB.h"
29 #include "TLeafI.h"
30 #include "TLeafL.h"
31 #include "TLeafS.h"
32 #include "TLeafO.h"
33 #include "TLeafC.h"
34 
35 #include <algorithm>
36 
37 ////////////////////////////////////////////////////////////////////////////////
38 
40 {
41  if (fObject->fBasketSeek[i1] == fObject->fBasketSeek[i2]) {
42  if (fObject->fBasketEntry[i1] == fObject->fBasketEntry[i2]) {
43  return i1 < i2;
44  }
45  return fObject->fBasketEntry[i1] < fObject->fBasketEntry[i2];
46  }
47  return fObject->fBasketSeek[i1] < fObject->fBasketSeek[i2];
48 }
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 
53 {
54  if (fObject->fBasketEntry[i1] == fObject->fBasketEntry[i2]) {
55  return i1 < i2;
56  }
57  return fObject->fBasketEntry[i1] < fObject->fBasketEntry[i2];
58 }
59 
60 ////////////////////////////////////////////////////////////////////////////////
61 /// Constructor. This object would transfer the data from
62 /// 'from' to 'to' using the method indicated in method.
63 ///
64 /// The value of the parameter 'method' determines in which
65 /// order the branches' baskets are written to the output file.
66 ///
67 /// When a TTree is filled the data is stored in the individual
68 /// branches' basket. Each basket is written individually to
69 /// the disk as soon as it is full. In consequence the baskets
70 /// of branches that contain 'large' data chunk are written to
71 /// the disk more often.
72 ///
73 /// There is currently 3 supported sorting order:
74 ///
75 /// SortBasketsByOffset (the default)
76 /// SortBasketsByBranch
77 /// SortBasketsByEntry
78 ///
79 /// When using SortBasketsByOffset the baskets are written in
80 /// the output file in the same order as in the original file
81 /// (i.e. the basket are sorted on their offset in the original
82 /// file; Usually this also means that the baskets are sorted
83 /// on the index/number of the _last_ entry they contain)
84 ///
85 /// When using SortBasketsByBranch all the baskets of each
86 /// individual branches are stored contiguously. This tends to
87 /// optimize reading speed when reading a small number (1->5) of
88 /// branches, since all their baskets will be clustered together
89 /// instead of being spread across the file. However it might
90 /// decrease the performance when reading more branches (or the full
91 /// entry).
92 ///
93 /// When using SortBasketsByEntry the baskets with the lowest
94 /// starting entry are written first. (i.e. the baskets are
95 /// sorted on the index/number of the first entry they contain).
96 /// This means that on the file the baskets will be in the order
97 /// in which they will be needed when reading the whole tree
98 /// sequentially.
99 
100 TTreeCloner::TTreeCloner(TTree *from, TTree *to, Option_t *method, UInt_t options) :
101  fWarningMsg(),
102  fIsValid(kTRUE),
104  fOptions(options),
105  fFromTree(from),
106  fToTree(to),
107  fMethod(method),
108  fFromBranches( from ? from->GetListOfLeaves()->GetEntries()+1 : 0),
109  fToBranches( to ? to->GetListOfLeaves()->GetEntries()+1 : 0),
116  fPidOffset(0),
118  fToStartEntries(0)
119 {
120  TString opt(method);
121  opt.ToLower();
122  if (opt.Contains("sortbasketsbybranch")) {
123  //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByBranch");
125  } else if (opt.Contains("sortbasketsbyentry")) {
126  //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByEntry");
128  } else {
129  //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByOffset");
131  }
133 
134  if (fToTree == 0) {
135  fWarningMsg.Form("An output TTree is required (cloning %s).",
136  from->GetName());
137  if (!(fOptions & kNoWarnings)) {
138  Warning("TTreeCloner::TTreeCloner", "%s", fWarningMsg.Data());
139  }
140  fIsValid = kFALSE;
141  } else if (fToTree->GetDirectory() == 0) {
142  fWarningMsg.Form("The output TTree (%s) must be associated with a directory.",
143  fToTree->GetName());
144  if (!(fOptions & kNoWarnings)) {
145  Warning("TTreeCloner::TTreeCloner", "%s", fWarningMsg.Data());
146  }
147  fIsValid = kFALSE;
148  } else if (fToTree->GetCurrentFile() == 0) {
149  fWarningMsg.Form("The output TTree (%s) must be associated with a directory (%s) that is in a file.",
151  if (!(fOptions & kNoWarnings)) {
152  Warning("TTreeCloner::TTreeCloner", "%s", fWarningMsg.Data());
153  }
154  fIsValid = kFALSE;
155  } else if (! fToTree->GetDirectory()->IsWritable()) {
157  fWarningMsg.Form("The output TTree (%s) must be associated with a writable file (%s).",
159  } else {
160  fWarningMsg.Form("The output TTree (%s) must be associated with a writable directory (%s in %s).",
162  }
163  if (!(fOptions & kNoWarnings)) {
164  Warning("TTreeCloner::TTreeCloner", "%s", fWarningMsg.Data());
165  }
166  fIsValid = kFALSE;
167  }
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// Execute the cloning.
172 
174 {
175  if (!IsValid()) {
176  return kFALSE;
177  }
180  CopyProcessIds();
182  CollectBaskets();
183  SortBaskets();
184  WriteBaskets();
186 
187  return kTRUE;
188 }
189 
190 ////////////////////////////////////////////////////////////////////////////////
191 /// TTreeCloner destructor
192 
194 {
195  delete [] fBasketBranchNum;
196  delete [] fBasketNum;
197  delete [] fBasketSeek;
198  delete [] fBasketEntry;
199  delete [] fBasketIndex;
200 }
201 
202 ////////////////////////////////////////////////////////////////////////////////
203 /// Before we can start adding new basket, we need to flush to
204 /// disk the partially filled baskets (the WriteBasket)
205 
207 {
208  for(Int_t i=0; i<fToBranches.GetEntries(); ++i) {
210  to->FlushOneBasket(to->GetWriteBasket());
211  }
212 }
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 /// Fill the array of branches, adding the branch 'from' and 'to',
216 /// and matching the sub-branches of the 'from' and 'to' branches.
217 /// Returns the total number of baskets in all the from branch and
218 /// it sub-branches.
219 
221  // Since this is called from the constructor, this can not be a virtual function
222 
223  UInt_t numBaskets = 0;
224  if (from->InheritsFrom(TBranchClones::Class())) {
225  TBranchClones *fromclones = (TBranchClones*) from;
226  TBranchClones *toclones = (TBranchClones*) to;
227  numBaskets += CollectBranches(fromclones->fBranchCount, toclones->fBranchCount);
228 
229  } else if (from->InheritsFrom(TBranchElement::Class())) {
230  Int_t nb = from->GetListOfLeaves()->GetEntries();
231  Int_t fnb = to->GetListOfLeaves()->GetEntries();
232  if (nb != fnb && (nb == 0 || fnb == 0)) {
233  // We might be in the case where one branch is split
234  // while the other is not split. We must reject this match.
235  fWarningMsg.Form("The export branch and the import branch do not have the same split level. (The branch name is %s.)",
236  from->GetName());
237  if (!(fOptions & kNoWarnings)) {
238  Warning("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
239  }
241  fIsValid = kFALSE;
242  return 0;
243  }
244  if (((TBranchElement*) from)->GetStreamerType() != ((TBranchElement*) to)->GetStreamerType()) {
245  fWarningMsg.Form("The export branch and the import branch do not have the same streamer type. (The branch name is %s.)",
246  from->GetName());
247  if (!(fOptions & kNoWarnings)) {
248  Warning("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
249  }
250  fIsValid = kFALSE;
251  return 0;
252  }
253  TBranchElement *fromelem = (TBranchElement*) from;
254  TBranchElement *toelem = (TBranchElement*) to;
255  if (fromelem->fMaximum > toelem->fMaximum) toelem->fMaximum = fromelem->fMaximum;
256  } else {
257 
258  Int_t nb = from->GetListOfLeaves()->GetEntries();
259  Int_t fnb = to->GetListOfLeaves()->GetEntries();
260  if (nb != fnb) {
261  fWarningMsg.Form("The export branch and the import branch (%s) do not have the same number of leaves (%d vs %d)",
262  from->GetName(), fnb, nb);
263  if (!(fOptions & kNoWarnings)) {
264  Error("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
265  }
266  fIsValid = kFALSE;
267  return 0;
268  }
269  for (Int_t i=0;i<nb;i++) {
270 
271  TLeaf *fromleaf_gen = (TLeaf*)from->GetListOfLeaves()->At(i);
272  TLeaf *toleaf_gen = (TLeaf*)to->GetListOfLeaves()->At(i);
273  if (toleaf_gen->IsA() != fromleaf_gen->IsA() ) {
274  // The data type do not match, we can not do a fast merge.
275  fWarningMsg.Form("The export leaf and the import leaf (%s.%s) do not have the data type (%s vs %s)",
276  from->GetName(),fromleaf_gen->GetName(),fromleaf_gen->GetTypeName(),toleaf_gen->GetTypeName());
277  if (! (fOptions & kNoWarnings) ) {
278  Warning("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
279  }
280  fIsValid = kFALSE;
282  return 0;
283  }
284  if (fromleaf_gen->IsA()==TLeafI::Class()) {
285  TLeafI *fromleaf = (TLeafI*)fromleaf_gen;
286  TLeafI *toleaf = (TLeafI*)toleaf_gen;
287  if (fromleaf->GetMaximum() > toleaf->GetMaximum())
288  toleaf->SetMaximum( fromleaf->GetMaximum() );
289  if (fromleaf->GetMinimum() < toleaf->GetMinimum())
290  toleaf->SetMinimum( fromleaf->GetMinimum() );
291  } else if (fromleaf_gen->IsA()==TLeafL::Class()) {
292  TLeafL *fromleaf = (TLeafL*)fromleaf_gen;
293  TLeafL *toleaf = (TLeafL*)toleaf_gen;
294  if (fromleaf->GetMaximum() > toleaf->GetMaximum())
295  toleaf->SetMaximum( fromleaf->GetMaximum() );
296  if (fromleaf->GetMinimum() < toleaf->GetMinimum())
297  toleaf->SetMinimum( fromleaf->GetMinimum() );
298  } else if (fromleaf_gen->IsA()==TLeafB::Class()) {
299  TLeafB *fromleaf = (TLeafB*)fromleaf_gen;
300  TLeafB *toleaf = (TLeafB*)toleaf_gen;
301  if (fromleaf->GetMaximum() > toleaf->GetMaximum())
302  toleaf->SetMaximum( fromleaf->GetMaximum() );
303  if (fromleaf->GetMinimum() < toleaf->GetMinimum())
304  toleaf->SetMinimum( fromleaf->GetMinimum() );
305  } else if (fromleaf_gen->IsA()==TLeafS::Class()) {
306  TLeafS *fromleaf = (TLeafS*)fromleaf_gen;
307  TLeafS *toleaf = (TLeafS*)toleaf_gen;
308  if (fromleaf->GetMaximum() > toleaf->GetMaximum())
309  toleaf->SetMaximum( fromleaf->GetMaximum() );
310  if (fromleaf->GetMinimum() < toleaf->GetMinimum())
311  toleaf->SetMinimum( fromleaf->GetMinimum() );
312  } else if (fromleaf_gen->IsA()==TLeafO::Class()) {
313  TLeafO *fromleaf = (TLeafO*)fromleaf_gen;
314  TLeafO *toleaf = (TLeafO*)toleaf_gen;
315  if (fromleaf->GetMaximum() > toleaf->GetMaximum())
316  toleaf->SetMaximum( fromleaf->GetMaximum() );
317  if (fromleaf->GetMinimum() < toleaf->GetMinimum())
318  toleaf->SetMinimum( fromleaf->GetMinimum() );
319  } else if (fromleaf_gen->IsA()==TLeafC::Class()) {
320  TLeafC *fromleaf = (TLeafC*)fromleaf_gen;
321  TLeafC *toleaf = (TLeafC*)toleaf_gen;
322  if (fromleaf->GetMaximum() > toleaf->GetMaximum())
323  toleaf->SetMaximum( fromleaf->GetMaximum() );
324  if (fromleaf->GetMinimum() < toleaf->GetMinimum())
325  toleaf->SetMinimum( fromleaf->GetMinimum() );
326  if (fromleaf->GetLenStatic() > toleaf->GetLenStatic())
327  toleaf->SetLen(fromleaf->GetLenStatic());
328  }
329  }
330 
331  }
332 
333  fFromBranches.AddLast(from);
334  if (!from->TestBit(TBranch::kDoNotUseBufferMap)) {
335  // Make sure that we reset the Buffer's map if needed.
337  }
338  fToBranches.AddLast(to);
339 
340  numBaskets += from->GetWriteBasket();
341  numBaskets += CollectBranches(from->GetListOfBranches(),to->GetListOfBranches());
342 
343  return numBaskets;
344 }
345 
346 ////////////////////////////////////////////////////////////////////////////////
347 /// Fill the array of branches, matching the branches of the 'from' and 'to' arrays.
348 /// Returns the total number of baskets in all the branches.
349 
351 {
352  // Since this is called from the constructor, this can not be a virtual function
353 
354  Int_t fnb = from->GetEntries();
355  Int_t tnb = to->GetEntries();
356  if (!fnb || !tnb) {
357  return 0;
358  }
359 
360  UInt_t numBasket = 0;
361  Int_t fi = 0;
362  Int_t ti = 0;
363  while (ti < tnb) {
364  TBranch* fb = (TBranch*) from->UncheckedAt(fi);
365  TBranch* tb = (TBranch*) to->UncheckedAt(ti);
366  Int_t firstfi = fi;
367  while (strcmp(fb->GetName(), tb->GetName())) {
368  ++fi;
369  if (fi >= fnb) {
370  // continue at the beginning
371  fi = 0;
372  }
373  if (fi==firstfi) {
374  // We tried all the branches and there is not match.
375  fb = 0;
376  break;
377  }
378  fb = (TBranch*) from->UncheckedAt(fi);
379  }
380  if (fb) {
381  numBasket += CollectBranches(fb, tb);
382  ++fi;
383  if (fi >= fnb) {
384  fi = 0;
385  }
386  } else {
387  if (tb->GetMother()==tb) {
388  // Top level branch.
389  if (!(fOptions & kIgnoreMissingTopLevel)) {
390  fWarningMsg.Form("One of the export top level branches (%s) is not present in the import TTree.",
391  tb->GetName());
392  if (!(fOptions & kNoWarnings)) {
393  Error("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
394  }
395  fIsValid = kFALSE;
396  }
397  } else {
398  fWarningMsg.Form("One of the export sub-branches (%s) is not present in the import TTree.",
399  tb->GetName());
400  if (!(fOptions & kNoWarnings)) {
401  Error("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
402  }
403  fIsValid = kFALSE;
404  }
405  }
406  ++ti;
407  }
408  return numBasket;
409 }
410 
411 ////////////////////////////////////////////////////////////////////////////////
412 /// Fill the array of branches, matching the branches of the 'from' and 'to' TTrees
413 /// Returns the total number of baskets in all the branches.
414 
416 {
417  // Since this is called from the constructor, this can not be a virtual function
418 
419  if (!fFromTree || !fToTree) {
420  return 0;
421  }
424 
425  if (fFromTree->GetBranchRef()) {
426  fToTree->BranchRef();
428  }
429  return numBasket;
430 }
431 
432 ////////////////////////////////////////////////////////////////////////////////
433 /// Collect the information about the on-file basket that need
434 /// to be copied.
435 
437 {
439 
440  for(UInt_t i=0,bi=0; i<len; ++i) {
442  for(Int_t b=0; b<from->GetWriteBasket(); ++b,++bi) {
443  fBasketBranchNum[bi] = i;
444  fBasketNum[bi] = b;
445  fBasketSeek[bi] = from->GetBasketSeek(b);
446  //fprintf(stderr,"For %s %d %lld\n",from->GetName(),bi,fBasketSeek[bi]);
447  fBasketEntry[bi] = from->GetBasketEntry()[b];
448  fBasketIndex[bi] = bi;
449  }
450  }
451 }
452 
453 ////////////////////////////////////////////////////////////////////////////////
454 /// Make sure that all the needed TStreamerInfo are
455 /// present in the output file
456 
458 {
459  TFile *fromFile = fFromTree->GetDirectory()->GetFile();
460  TFile *toFile = fToTree->GetDirectory()->GetFile();
461  TList *l = fromFile->GetStreamerInfoList();
462  TIter next(l);
463  TStreamerInfo *oldInfo;
464  while ( (oldInfo = (TStreamerInfo*)next()) ) {
465  if (oldInfo->IsA() != TStreamerInfo::Class()) {
466  continue;
467  }
468  TStreamerInfo *curInfo = 0;
469  TClass *cl = TClass::GetClass(oldInfo->GetName());
470 
471  if ((cl->IsLoaded() && (cl->GetNew()!=0 || cl->HasDefaultConstructor()))
472  || !cl->IsLoaded()) {
473  // Insure that the TStreamerInfo is loaded
474  curInfo = (TStreamerInfo*)cl->GetStreamerInfo(oldInfo->GetClassVersion());
475  if (oldInfo->GetClassVersion()==1) {
476  // We may have a Foreign class let's look using the
477  // checksum:
478  TStreamerInfo *matchInfo = (TStreamerInfo*)cl->FindStreamerInfo(oldInfo->GetCheckSum());
479  if (matchInfo) {
480  curInfo = matchInfo;
481  }
482  }
483  curInfo->ForceWriteInfo(toFile);
484  } else {
485  // If there is no default constructor the GetStreamerInfo
486  // will not work. It also means (hopefully) that an
487  // inheriting class has a streamerInfo in the list (which
488  // will induces the setting of this streamerInfo)
489 
490  oldInfo->ForceWriteInfo(toFile);
491  }
492  }
493  delete l;
494 }
495 
496 ////////////////////////////////////////////////////////////////////////////////
497 /// Transfer the basket from the input file to the output file
498 
500 {
501  TBasket *basket = 0;
502  for(Int_t i=0; i<fToBranches.GetEntries(); ++i) {
503  TBranch *from = (TBranch*)fFromBranches.UncheckedAt( i );
504  TBranch *to = (TBranch*)fToBranches.UncheckedAt( i );
505 
506  basket = from->GetListOfBaskets()->GetEntries() ? from->GetBasket(from->GetWriteBasket()) : 0;
507  if (basket) {
508  basket = (TBasket*)basket->Clone();
509  basket->SetBranch(to);
510  to->AddBasket(*basket, kFALSE, fToStartEntries+from->GetBasketEntry()[from->GetWriteBasket()]);
511  } else {
513  }
514  // In older files, if the branch is a TBranchElement non-terminal 'object' branch, it's basket will contain 0
515  // events, in newer file in the same case, the write basket will be missing.
516  if (from->GetEntries()!=0 && from->GetWriteBasket()==0 && (basket==0 || basket->GetNevBuf()==0)) {
517  to->SetEntries(to->GetEntries()+from->GetEntries());
518  }
519  }
520 }
521 
522 ////////////////////////////////////////////////////////////////////////////////
523 /// Make sure that all the needed TStreamerInfo are
524 /// present in the output file
525 
527 {
528  // NOTE: We actually need to merge the ProcessId somehow :(
529 
530  TFile *fromfile = fFromTree->GetDirectory()->GetFile();
531  TFile *tofile = fToTree->GetDirectory()->GetFile();
532 
533  fPidOffset = tofile->GetNProcessIDs();
534 
535  TIter next(fromfile->GetListOfKeys());
536  TKey *key;
537  TDirectory::TContext cur(fromfile);
538  while ((key = (TKey*)next())) {
539  if (!strcmp(key->GetClassName(),"TProcessID")) {
540  TProcessID *pid = (TProcessID*)key->ReadObjectAny(0);
541  if (!pid) continue;
542 
543  //UShort_t out = TProcessID::WriteProcessID(id,tofile);
544  UShort_t out = 0;
545  TObjArray *pids = tofile->GetListOfProcessIDs();
546  Int_t npids = tofile->GetNProcessIDs();
547  Bool_t wasIn = kFALSE;
548  for (Int_t i=0;i<npids;i++) {
549  if (pids->At(i) == pid) {out = (UShort_t)i; wasIn = kTRUE; break;}
550  }
551 
552  if (!wasIn) {
553  TDirectory *dirsav = gDirectory;
554  tofile->cd();
555  tofile->SetBit(TFile::kHasReferences);
556  pids->AddAtAndExpand(pid,npids);
557  pid->IncrementCount();
558  char name[32];
559  snprintf(name,32,"ProcessID%d",npids);
560  pid->Write(name);
561  tofile->IncrementProcessIDs();
562  if (gDebug > 0) {
563  Info("WriteProcessID", "name=%s, file=%s", name, tofile->GetName());
564  }
565  if (dirsav) dirsav->cd();
566  out = (UShort_t)npids;
567  }
568  if (out<fPidOffset) {
569  Error("CopyProcessIDs","Copied %s from %s might already exist!\n",
570  pid->GetName(),fromfile->GetName());
571  }
572  }
573  }
574 }
575 
576 ////////////////////////////////////////////////////////////////////////////////
577 /// Set the entries and import the cluster range of the
578 
580 {
581  // First undo, the external call to SetEntries
582  // We could improve the interface to optional tell the TTreeCloner that the
583  // SetEntries was not done.
585 
587 
589 }
590 
591 ////////////////////////////////////////////////////////////////////////////////
592 /// Sort the basket according to the user request.
593 
595 {
596  // Currently this sort __has to__ preserve the order
597  // of basket for each individual branch.
598 
599  switch (fCloneMethod) {
601  // nothing to do, it is already sorted.
602  break;
603  case kSortBasketsByEntry: {
604  for(UInt_t i = 0; i < fMaxBaskets; ++i) { fBasketIndex[i] = i; }
605  std::sort(fBasketIndex, fBasketIndex+fMaxBaskets, CompareEntry( this) );
606  break;
607  }
609  default: {
610  for(UInt_t i = 0; i < fMaxBaskets; ++i) { fBasketIndex[i] = i; }
611  std::sort(fBasketIndex, fBasketIndex+fMaxBaskets, CompareSeek( this) );
612  break;
613  }
614  }
615 }
616 
617 ////////////////////////////////////////////////////////////////////////////////
618 /// Transfer the basket from the input file to the output file
619 
621 {
622  TBasket *basket = new TBasket();
623  for(UInt_t j=0; j<fMaxBaskets; ++j) {
626 
627  TFile *tofile = to->GetFile(0);
628  TFile *fromfile = from->GetFile(0);
629 
630  Int_t index = fBasketNum[ fBasketIndex[j] ];
631 
632  Long64_t pos = from->GetBasketSeek(index);
633  if (pos!=0) {
634  if (from->GetBasketBytes()[index] == 0) {
635  from->GetBasketBytes()[index] = basket->ReadBasketBytes(pos, fromfile);
636  }
637  Int_t len = from->GetBasketBytes()[index];
638 
639  basket->LoadBasketBuffers(pos,len,fromfile,fFromTree);
641  basket->CopyTo(tofile);
642  to->AddBasket(*basket,kTRUE,fToStartEntries + from->GetBasketEntry()[index]);
643  } else {
644  TBasket *frombasket = from->GetBasket( index );
645  if (frombasket && frombasket->GetNevBuf()>0) {
646  TBasket *tobasket = (TBasket*)frombasket->Clone();
647  tobasket->SetBranch(to);
648  to->AddBasket(*tobasket, kFALSE, fToStartEntries+from->GetBasketEntry()[index]);
649  to->FlushOneBasket(to->GetWriteBasket());
650  }
651  }
652  }
653  delete basket;
654 }
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:47
virtual Int_t GetNProcessIDs() const
Definition: TFile.h:199
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
virtual Int_t GetMinimum() const
Definition: TLeafL.h:46
Int_t ReadBasketBytes(Long64_t pos, TFile *file)
Read basket buffers in memory and cleanup.
Definition: TBasket.cxx:646
virtual void SetMaximum(Char_t max)
Definition: TLeafB.h:54
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:823
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:37
A TLeaf for an 8 bit Integer data type.
Definition: TLeafB.h:28
virtual Int_t GetMaximum() const
Definition: TLeafS.h:43
virtual Int_t GetMaximum() const
Definition: TLeafL.h:45
UInt_t * fBasketIndex
Definition: TTreeCloner.h:57
Bool_t HasDefaultConstructor() const
Return true if we have access to a default constructor.
Definition: TClass.cxx:6755
An array of TObjects.
Definition: TObjArray.h:39
void ImportClusterRanges()
Set the entries and import the cluster range of the.
Long64_t * fBasketEntry
Definition: TTreeCloner.h:56
long long Long64_t
Definition: RtypesCore.h:69
friend class CompareEntry
Definition: TTreeCloner.h:86
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:487
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
TObjArray * GetListOfBaskets()
Definition: TBranch.h:176
Int_t FlushOneBasket(UInt_t which)
If we have a write basket in memory and it contains some entries and has not yet been written to disk...
Definition: TBranch.cxx:1041
const char Option_t
Definition: RtypesCore.h:62
void WriteBaskets()
Transfer the basket from the input file to the output file.
virtual void SetMinimum(Int_t min)
Definition: TLeafC.h:56
unsigned short UShort_t
Definition: RtypesCore.h:36
virtual TList * GetListOfKeys() const
virtual void SetMaximum(Bool_t max)
Definition: TLeafO.h:54
virtual void SetMinimum(Long64_t min)
Definition: TLeafL.h:58
Long64_t fToStartEntries
Definition: TTreeCloner.h:62
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:45
void ForceWriteInfo(TFile *file, Bool_t force=kFALSE)
Recursively mark streamer infos for writing to a file.
virtual Int_t GetMinimum() const
Definition: TLeafI.h:46
Basic string class.
Definition: TString.h:137
TBranch * fBranchCount
Definition: TBranchClones.h:39
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1075
int Int_t
Definition: RtypesCore.h:41
ROOT::NewFunc_t GetNew() const
Return the wrapper around new ThisClass().
Definition: TClass.cxx:6793
bool Bool_t
Definition: RtypesCore.h:59
A TLeaf for a bool data type.
Definition: TLeafO.h:28
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition: TBranch.cxx:1144
virtual void SetMinimum(Bool_t min)
Definition: TLeafO.h:55
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:4987
A TLeaf for a variable length string.
Definition: TLeafC.h:28
Long64_t * GetBasketEntry() const
Definition: TBranch.h:149
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:732
void SetBranch(TBranch *branch)
Definition: TBasket.h:91
virtual void SetMaximum(Short_t max)
Definition: TLeafS.h:54
const char * Data() const
Definition: TString.h:349
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:409
UInt_t fMaxBaskets
Definition: TTreeCloner.h:51
virtual void SetMinimum(Char_t min)
Definition: TLeafB.h:55
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in 'fromtree' to this tree, including the value of fAuto...
Definition: TTree.cxx:5689
virtual Int_t GetMinimum() const
Definition: TLeafS.h:44
void Class()
Definition: Class.C:29
virtual void SetLen(Int_t len=1)
Definition: TLeaf.h:102
Int_t * GetBasketBytes() const
Definition: TBranch.h:148
void CloseOutWriteBaskets()
Before we can start adding new basket, we need to flush to disk the partially filled baskets (the Wri...
void Info(const char *location, const char *msgfmt,...)
virtual Int_t GetMinimum() const
Definition: TLeafC.h:44
Long64_t GetEntries() const
Definition: TBranch.h:182
TObjArray * GetListOfBranches()
Definition: TBranch.h:177
TBasket * GetBasket(Int_t basket)
Return pointer to basket basketnumber in this Branch.
Definition: TBranch.cxx:1082
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:63
void SortBaskets()
Sort the basket according to the user request.
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:30
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:34
Int_t GetNevBuf() const
Definition: TBasket.h:79
void Error(const char *location, const char *msgfmt,...)
Int_t GetClassVersion() const
virtual Int_t GetMaximum() const
Definition: TLeafB.h:43
TVirtualStreamerInfo * FindStreamerInfo(TObjArray *arr, UInt_t checksum) const
Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum.
Definition: TClass.cxx:6502
char * out
Definition: TBase64.cxx:29
Bool_t IsValid()
Definition: TTreeCloner.h:114
virtual void IncrementProcessIDs()
Definition: TFile.h:217
A doubly linked list.
Definition: TList.h:47
TTree * fFromTree
Definition: TTreeCloner.h:45
virtual TFile * GetFile() const
Definition: TDirectory.h:155
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:91
virtual void AddLastBasket(Long64_t startEntry)
Add the start entry of the write basket (not yet created)
Definition: TBranch.cxx:550
virtual void IncrementPidOffset(UShort_t offset)
Increment fPidOffset by 'offset'.
Definition: TKey.cxx:639
virtual const char * GetTypeName() const
Definition: TLeaf.h:81
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:222
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist...
Definition: TClass.cxx:4256
virtual void SetEntries(Long64_t entries)
Set the number of entries in this branch.
Definition: TBranch.cxx:2205
void CopyProcessIds()
Make sure that all the needed TStreamerInfo are present in the output file.
void CopyStreamerInfos()
Make sure that all the needed TStreamerInfo are present in the output file.
TDirectory * GetDirectory() const
Definition: TTree.h:385
virtual void SetMinimum(Short_t min)
Definition: TLeafS.h:55
virtual Int_t GetMinimum() const
Definition: TLeafB.h:44
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1533
UInt_t GetCheckSum() const
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2308
Int_t IncrementCount()
Increase the reference count to this object.
Definition: TProcessID.cxx:268
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:173
Manages buffers for branches of a Tree.
Definition: TBasket.h:38
virtual Int_t GetMinimum() const
Definition: TLeafO.h:44
TObjArray fToBranches
Definition: TTreeCloner.h:49
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:374
TLine * l
Definition: textangle.C:4
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
virtual TList * GetStreamerInfoList()
Read the list of TStreamerInfo objects written to this file.
Definition: TFile.cxx:1319
TTreeCloner * fObject
Definition: TTreeCloner.h:72
friend class CompareSeek
Definition: TTreeCloner.h:85
void Warning(const char *location, const char *msgfmt,...)
Bool_t operator()(UInt_t i1, UInt_t i2)
Definition: TTreeCloner.cxx:52
TTreeCloner(const TTreeCloner &)
A Branch for the case of an object.
virtual void SetMaximum(Long64_t max)
Definition: TLeafL.h:57
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5436
UInt_t CollectBranches()
Fill the array of branches, matching the branches of the 'from' and 'to' TTrees Returns the total num...
Bool_t Exec()
Execute the cloning.
virtual Int_t GetMaximum() const
Definition: TLeafC.h:43
UInt_t * fBasketNum
Definition: TTreeCloner.h:53
Bool_t operator()(UInt_t i1, UInt_t i2)
Definition: TTreeCloner.cxx:39
Describe directory structure in memory.
Definition: TDirectory.h:44
UInt_t fOptions
Definition: TTreeCloner.h:44
UShort_t fPidOffset
Definition: TTreeCloner.h:59
virtual TTree * GetTree() const
Definition: TTree.h:436
TObjArray * GetListOfLeaves()
Definition: TBranch.h:178
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2801
virtual Int_t GetMaximum() const
Definition: TLeafI.h:45
UInt_t fCloneMethod
Definition: TTreeCloner.h:61
#define name(a, b)
Definition: linkTestLib0.cpp:5
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2110
UInt_t * fBasketBranchNum
Definition: TTreeCloner.h:52
A TLeaf for a 16 bit Integer data type.
Definition: TLeafS.h:28
virtual void SetMaximum(Int_t max)
Definition: TLeafI.h:55
virtual void SetMinimum(Int_t min)
Definition: TLeafI.h:56
Class implementing or helping the various TTree cloning method.
Definition: TTreeCloner.h:39
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
Definition: TDirectory.cxx:433
A Branch for the case of an array of clone objects.
Definition: TBranchClones.h:31
virtual Int_t GetLenStatic() const
Definition: TLeaf.h:74
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
virtual Bool_t IsWritable() const
Definition: TDirectory.h:171
virtual Int_t GetMaximum() const
Definition: TLeafO.h:43
virtual void AddBasket(TBasket &b, Bool_t ondisk, Long64_t startEntry)
Add the basket to this branch.
Definition: TBranch.cxx:477
A TLeaf for a 64 bit Integer data type.
Definition: TLeafL.h:29
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
Bool_t fNeedConversion
Definition: TTreeCloner.h:43
virtual void AddLast(TObject *obj)
Add object in the next empty slot in the array.
Definition: TObjArray.cxx:169
virtual Long64_t GetEntries() const
Definition: TTree.h:386
A TTree object has a header with a name and a title.
Definition: TTree.h:98
#define gDirectory
Definition: TDirectory.h:221
TString fWarningMsg
Definition: TTreeCloner.h:40
Long64_t CopyTo(TFile *to)
Copy the basket of this branch onto the file to.
Definition: TBasket.cxx:164
void ResetBit(UInt_t f)
Definition: TObject.h:172
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
TTree * fToTree
Definition: TTreeCloner.h:46
virtual TFile * GetFile(Int_t mode=0)
Return pointer to the file where branch buffers reside, returns 0 in case branch buffers reside in th...
Definition: TBranch.cxx:1382
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8109
A TTree is a list of TBranches.
Definition: TBranch.h:58
virtual void SetMaximum(Int_t max)
Definition: TLeafC.h:55
const Bool_t kTRUE
Definition: Rtypes.h:91
Long64_t * fBasketSeek
Definition: TTreeCloner.h:55
TObjArray * GetListOfProcessIDs() const
Definition: TFile.h:196
Option_t * fMethod
Definition: TTreeCloner.h:47
virtual ~TTreeCloner()
TTreeCloner destructor.
void CopyMemoryBaskets()
Transfer the basket from the input file to the output file.
Int_t GetWriteBasket() const
Definition: TBranch.h:170
void CollectBaskets()
Collect the information about the on-file basket that need to be copied.
A TLeaf for an Integer data type.
Definition: TLeafI.h:29
TObjArray fFromBranches
Definition: TTreeCloner.h:48
Int_t LoadBasketBuffers(Long64_t pos, Int_t len, TFile *file, TTree *tree=0)
Load basket buffers in memory without unziping.
Definition: TBasket.cxx:226
Bool_t fIsValid
Definition: TTreeCloner.h:42