Logo ROOT   6.14/05
Reference Guide
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 \ingroup tree
14 
15 Class implementing or helping the various TTree cloning method
16 */
17 
18 #include "TBasket.h"
19 #include "TBranch.h"
20 #include "TBranchClones.h"
21 #include "TBranchElement.h"
22 #include "TStreamerInfo.h"
23 #include "TBranchRef.h"
24 #include "TError.h"
25 #include "TProcessID.h"
26 #include "TMath.h"
27 #include "TTree.h"
28 #include "TTreeCloner.h"
29 #include "TFile.h"
30 #include "TLeafB.h"
31 #include "TLeafI.h"
32 #include "TLeafL.h"
33 #include "TLeafS.h"
34 #include "TLeafO.h"
35 #include "TLeafC.h"
36 #include "TFileCacheRead.h"
37 #include "TTreeCache.h"
38 
39 #include <algorithm>
40 
41 ////////////////////////////////////////////////////////////////////////////////
42 
44 {
45  if (fObject->fBasketSeek[i1] == fObject->fBasketSeek[i2]) {
46  if (fObject->fBasketEntry[i1] == fObject->fBasketEntry[i2]) {
47  return i1 < i2;
48  }
49  return fObject->fBasketEntry[i1] < fObject->fBasketEntry[i2];
50  }
51  return fObject->fBasketSeek[i1] < fObject->fBasketSeek[i2];
52 }
53 
54 ////////////////////////////////////////////////////////////////////////////////
55 
57 {
58  if (fObject->fBasketEntry[i1] == fObject->fBasketEntry[i2]) {
59  return i1 < i2;
60  }
61  return fObject->fBasketEntry[i1] < fObject->fBasketEntry[i2];
62 }
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 /// Constructor. This object would transfer the data from
66 /// 'from' to 'to' using the method indicated in method.
67 ///
68 /// The value of the parameter 'method' determines in which
69 /// order the branches' baskets are written to the output file.
70 ///
71 /// When a TTree is filled the data is stored in the individual
72 /// branches' basket. Each basket is written individually to
73 /// the disk as soon as it is full. In consequence the baskets
74 /// of branches that contain 'large' data chunk are written to
75 /// the disk more often.
76 ///
77 /// There is currently 3 supported sorting order:
78 ///
79 /// SortBasketsByOffset (the default)
80 /// SortBasketsByBranch
81 /// SortBasketsByEntry
82 ///
83 /// When using SortBasketsByOffset the baskets are written in
84 /// the output file in the same order as in the original file
85 /// (i.e. the basket are sorted on their offset in the original
86 /// file; Usually this also means that the baskets are sorted
87 /// on the index/number of the _last_ entry they contain)
88 ///
89 /// When using SortBasketsByBranch all the baskets of each
90 /// individual branches are stored contiguously. This tends to
91 /// optimize reading speed when reading a small number (1->5) of
92 /// branches, since all their baskets will be clustered together
93 /// instead of being spread across the file. However it might
94 /// decrease the performance when reading more branches (or the full
95 /// entry).
96 ///
97 /// When using SortBasketsByEntry the baskets with the lowest
98 /// starting entry are written first. (i.e. the baskets are
99 /// sorted on the index/number of the first entry they contain).
100 /// This means that on the file the baskets will be in the order
101 /// in which they will be needed when reading the whole tree
102 /// sequentially.
103 
104 TTreeCloner::TTreeCloner(TTree *from, TTree *to, Option_t *method, UInt_t options) :
105  fWarningMsg(),
106  fIsValid(kTRUE),
108  fOptions(options),
109  fFromTree(from),
110  fToTree(to),
111  fMethod(method),
112  fFromBranches( from ? from->GetListOfLeaves()->GetEntries()+1 : 0),
113  fToBranches( to ? to->GetListOfLeaves()->GetEntries()+1 : 0),
120  fPidOffset(0),
122  fToStartEntries(0),
123  fCacheSize(0LL),
124  fFileCache(nullptr),
125  fPrevCache(nullptr)
126 {
127  TString opt(method);
128  opt.ToLower();
129  if (opt.Contains("sortbasketsbybranch")) {
130  //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByBranch");
132  } else if (opt.Contains("sortbasketsbyentry")) {
133  //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByEntry");
135  } else {
136  //::Info("TTreeCloner::TTreeCloner","use: kSortBasketsByOffset");
138  }
140 
141  if (fFromTree == nullptr) {
142  if (to)
143  fWarningMsg.Form("An input TTree is required (cloning to %s).",
144  to->GetName());
145  else
146  fWarningMsg.Form("An input and output TTree are required.");
147  if (!(fOptions & kNoWarnings)) {
148  Warning("TTreeCloner::TTreeCloner", "%s", fWarningMsg.Data());
149  }
150  fIsValid = kFALSE;
151  }
152  if (fToTree == nullptr) {
153  fWarningMsg.Form("An output TTree is required (cloning %s).",
154  from ? from->GetName() : "no tree");
155  if (!(fOptions & kNoWarnings)) {
156  Warning("TTreeCloner::TTreeCloner", "%s", fWarningMsg.Data());
157  }
158  fIsValid = kFALSE;
159  } else if (fToTree->GetDirectory() == nullptr) {
160  fWarningMsg.Form("The output TTree (%s) must be associated with a directory.",
161  fToTree->GetName());
162  if (!(fOptions & kNoWarnings)) {
163  Warning("TTreeCloner::TTreeCloner", "%s", fWarningMsg.Data());
164  }
165  fIsValid = kFALSE;
166  } else if (fToTree->GetCurrentFile() == nullptr) {
167  fWarningMsg.Form("The output TTree (%s) must be associated with a directory (%s) that is in a file.",
169  if (!(fOptions & kNoWarnings)) {
170  Warning("TTreeCloner::TTreeCloner", "%s", fWarningMsg.Data());
171  }
172  fIsValid = kFALSE;
173  } else if (! fToTree->GetDirectory()->IsWritable()) {
175  fWarningMsg.Form("The output TTree (%s) must be associated with a writable file (%s).",
177  } else {
178  fWarningMsg.Form("The output TTree (%s) must be associated with a writable directory (%s in %s).",
180  }
181  if (!(fOptions & kNoWarnings)) {
182  Warning("TTreeCloner::TTreeCloner", "%s", fWarningMsg.Data());
183  }
184  fIsValid = kFALSE;
185  }
186 
187  if (fIsValid && (!(fOptions & kNoFileCache))) {
189  }
190 }
191 
192 ////////////////////////////////////////////////////////////////////////////////
193 /// Execute the cloning.
194 
196 {
197  if (!IsValid()) {
198  return kFALSE;
199  }
200  CreateCache();
203  CopyProcessIds();
205  CollectBaskets();
206  SortBaskets();
207  WriteBaskets();
209  RestoreCache();
210 
211  return kTRUE;
212 }
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 /// TTreeCloner destructor
216 
218 {
219  // The file cache was restored to its previous value at the end of Exec,
220  // we can safely delete our cache.
221  delete fFileCache;
222  delete [] fBasketBranchNum;
223  delete [] fBasketNum;
224  delete [] fBasketSeek;
225  delete [] fBasketEntry;
226  delete [] fBasketIndex;
227 }
228 
229 ////////////////////////////////////////////////////////////////////////////////
230 /// Before we can start adding new basket, we need to flush to
231 /// disk the partially filled baskets (the WriteBasket)
232 
234 {
235  for(Int_t i=0; i<fToBranches.GetEntries(); ++i) {
237  to->FlushOneBasket(to->GetWriteBasket());
238  }
239 }
240 
241 ////////////////////////////////////////////////////////////////////////////////
242 /// Fill the array of branches, adding the branch 'from' and 'to',
243 /// and matching the sub-branches of the 'from' and 'to' branches.
244 /// Returns the total number of baskets in all the from branch and
245 /// it sub-branches.
246 
248  // Since this is called from the constructor, this can not be a virtual function
249 
250  UInt_t numBaskets = 0;
251  if (from->InheritsFrom(TBranchClones::Class())) {
252  TBranchClones *fromclones = (TBranchClones*) from;
253  TBranchClones *toclones = (TBranchClones*) to;
254  numBaskets += CollectBranches(fromclones->fBranchCount, toclones->fBranchCount);
255 
256  } else if (from->InheritsFrom(TBranchElement::Class())) {
257  Int_t nb = from->GetListOfLeaves()->GetEntries();
258  Int_t fnb = to->GetListOfLeaves()->GetEntries();
259  if (nb != fnb && (nb == 0 || fnb == 0)) {
260  // We might be in the case where one branch is split
261  // while the other is not split. We must reject this match.
262  fWarningMsg.Form("The export branch and the import branch do not have the same split level. (The branch name is %s.)",
263  from->GetName());
264  if (!(fOptions & kNoWarnings)) {
265  Warning("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
266  }
268  fIsValid = kFALSE;
269  return 0;
270  }
271  if (((TBranchElement*) from)->GetStreamerType() != ((TBranchElement*) to)->GetStreamerType()) {
272  fWarningMsg.Form("The export branch and the import branch do not have the same streamer type. (The branch name is %s.)",
273  from->GetName());
274  if (!(fOptions & kNoWarnings)) {
275  Warning("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
276  }
277  fIsValid = kFALSE;
278  return 0;
279  }
280  TBranchElement *fromelem = (TBranchElement*) from;
281  TBranchElement *toelem = (TBranchElement*) to;
282  if (fromelem->fMaximum > toelem->fMaximum) toelem->fMaximum = fromelem->fMaximum;
283  } else {
284 
285  Int_t nb = from->GetListOfLeaves()->GetEntries();
286  Int_t fnb = to->GetListOfLeaves()->GetEntries();
287  if (nb != fnb) {
288  fWarningMsg.Form("The export branch and the import branch (%s) do not have the same number of leaves (%d vs %d)",
289  from->GetName(), fnb, nb);
290  if (!(fOptions & kNoWarnings)) {
291  Error("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
292  }
293  fIsValid = kFALSE;
294  return 0;
295  }
296  for (Int_t i=0;i<nb;i++) {
297 
298  TLeaf *fromleaf = (TLeaf*)from->GetListOfLeaves()->At(i);
299  TLeaf *toleaf = (TLeaf*)to->GetListOfLeaves()->At(i);
300  if (toleaf->IsA() != fromleaf->IsA() ) {
301  // The data type do not match, we can not do a fast merge.
302  fWarningMsg.Form("The export leaf and the import leaf (%s.%s) do not have the data type (%s vs %s)",
303  from->GetName(),fromleaf->GetName(),fromleaf->GetTypeName(),toleaf->GetTypeName());
304  if (! (fOptions & kNoWarnings) ) {
305  Warning("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
306  }
307  fIsValid = kFALSE;
309  return 0;
310  }
311  toleaf->IncludeRange( fromleaf );
312  }
313 
314  }
315 
316  fFromBranches.AddLast(from);
317  if (!from->TestBit(TBranch::kDoNotUseBufferMap)) {
318  // Make sure that we reset the Buffer's map if needed.
320  }
321  fToBranches.AddLast(to);
322 
323  numBaskets += from->GetWriteBasket();
324  numBaskets += CollectBranches(from->GetListOfBranches(),to->GetListOfBranches());
325 
326  return numBaskets;
327 }
328 
329 ////////////////////////////////////////////////////////////////////////////////
330 /// Fill the array of branches, matching the branches of the 'from' and 'to' arrays.
331 /// Returns the total number of baskets in all the branches.
332 
334 {
335  // Since this is called from the constructor, this can not be a virtual function
336 
337  Int_t fnb = from->GetEntries();
338  Int_t tnb = to->GetEntries();
339  if (!fnb || !tnb) {
340  return 0;
341  }
342 
343  UInt_t numBasket = 0;
344  Int_t fi = 0;
345  Int_t ti = 0;
346  while (ti < tnb) {
347  TBranch* fb = (TBranch*) from->UncheckedAt(fi);
348  TBranch* tb = (TBranch*) to->UncheckedAt(ti);
349  Int_t firstfi = fi;
350  while (strcmp(fb->GetName(), tb->GetName())) {
351  ++fi;
352  if (fi >= fnb) {
353  // continue at the beginning
354  fi = 0;
355  }
356  if (fi==firstfi) {
357  // We tried all the branches and there is not match.
358  fb = 0;
359  break;
360  }
361  fb = (TBranch*) from->UncheckedAt(fi);
362  }
363  if (fb) {
364  numBasket += CollectBranches(fb, tb);
365  ++fi;
366  if (fi >= fnb) {
367  fi = 0;
368  }
369  } else {
370  if (tb->GetMother()==tb) {
371  // Top level branch.
372  if (!(fOptions & kIgnoreMissingTopLevel)) {
373  fWarningMsg.Form("One of the export top level branches (%s) is not present in the import TTree.",
374  tb->GetName());
375  if (!(fOptions & kNoWarnings)) {
376  Error("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
377  }
378  fIsValid = kFALSE;
379  }
380  } else {
381  fWarningMsg.Form("One of the export sub-branches (%s) is not present in the import TTree.",
382  tb->GetName());
383  if (!(fOptions & kNoWarnings)) {
384  Error("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
385  }
386  fIsValid = kFALSE;
387  }
388  }
389  ++ti;
390  }
391  return numBasket;
392 }
393 
394 ////////////////////////////////////////////////////////////////////////////////
395 /// Fill the array of branches, matching the branches of the 'from' and 'to' TTrees
396 /// Returns the total number of baskets in all the branches.
397 
399 {
400  // Since this is called from the constructor, this can not be a virtual function
401 
402  if (!fFromTree || !fToTree) {
403  return 0;
404  }
407 
408  if (fFromTree->GetBranchRef()) {
409  fToTree->BranchRef();
411  }
412  return numBasket;
413 }
414 
415 ////////////////////////////////////////////////////////////////////////////////
416 /// Collect the information about the on-file basket that need
417 /// to be copied.
418 
420 {
422 
423  for(UInt_t i=0,bi=0; i<len; ++i) {
425  for(Int_t b=0; b<from->GetWriteBasket(); ++b,++bi) {
426  fBasketBranchNum[bi] = i;
427  fBasketNum[bi] = b;
428  fBasketSeek[bi] = from->GetBasketSeek(b);
429  //fprintf(stderr,"For %s %d %lld\n",from->GetName(),bi,fBasketSeek[bi]);
430  fBasketEntry[bi] = from->GetBasketEntry()[b];
431  fBasketIndex[bi] = bi;
432  }
433  }
434 }
435 
436 ////////////////////////////////////////////////////////////////////////////////
437 /// Make sure that all the needed TStreamerInfo are
438 /// present in the output file
439 
441 {
442  TFile *fromFile = fFromTree->GetDirectory()->GetFile();
443  TFile *toFile = fToTree->GetDirectory()->GetFile();
444  TList *l = fromFile->GetStreamerInfoList();
445  TIter next(l);
446  TStreamerInfo *oldInfo;
447  while ( (oldInfo = (TStreamerInfo*)next()) ) {
448  if (oldInfo->IsA() != TStreamerInfo::Class()) {
449  continue;
450  }
451  TStreamerInfo *curInfo = 0;
452  TClass *cl = TClass::GetClass(oldInfo->GetName());
453 
454  if (!cl->IsLoaded() || cl->GetNew()) {
455  // Insure that the TStreamerInfo is loaded
456  curInfo = (TStreamerInfo*)cl->GetStreamerInfo(oldInfo->GetClassVersion());
457  if (oldInfo->GetClassVersion()==1) {
458  // We may have a Foreign class let's look using the
459  // checksum:
460  TStreamerInfo *matchInfo = (TStreamerInfo*)cl->FindStreamerInfo(oldInfo->GetCheckSum());
461  if (matchInfo) {
462  curInfo = matchInfo;
463  }
464  }
465  curInfo->ForceWriteInfo(toFile);
466  } else {
467  // If there is no default constructor the GetStreamerInfo
468  // will not work. It also means (hopefully) that an
469  // inheriting class has a streamerInfo in the list (which
470  // will induces the setting of this streamerInfo)
471 
472  oldInfo->ForceWriteInfo(toFile);
473  }
474  }
475  delete l;
476 }
477 
478 ////////////////////////////////////////////////////////////////////////////////
479 /// Transfer the basket from the input file to the output file
480 
482 {
483  TBasket *basket = 0;
484  for(Int_t i=0; i<fToBranches.GetEntries(); ++i) {
485  TBranch *from = (TBranch*)fFromBranches.UncheckedAt( i );
486  TBranch *to = (TBranch*)fToBranches.UncheckedAt( i );
487 
488  basket = from->GetListOfBaskets()->GetEntries() ? from->GetBasket(from->GetWriteBasket()) : 0;
489  if (basket) {
490  basket = (TBasket*)basket->Clone();
491  basket->SetBranch(to);
492  to->AddBasket(*basket, kFALSE, fToStartEntries+from->GetBasketEntry()[from->GetWriteBasket()]);
493  } else {
495  }
496  // In older files, if the branch is a TBranchElement non-terminal 'object' branch, it's basket will contain 0
497  // events, in newer file in the same case, the write basket will be missing.
498  if (from->GetEntries()!=0 && from->GetWriteBasket()==0 && (basket==0 || basket->GetNevBuf()==0)) {
499  to->SetEntries(to->GetEntries()+from->GetEntries());
500  }
501  }
502 }
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 /// Make sure that all the needed TStreamerInfo are
506 /// present in the output file
507 
509 {
510  // NOTE: We actually need to merge the ProcessId somehow :(
511 
512  TFile *fromfile = fFromTree->GetDirectory()->GetFile();
513  TFile *tofile = fToTree->GetDirectory()->GetFile();
514 
515  fPidOffset = tofile->GetNProcessIDs();
516 
517  TIter next(fromfile->GetListOfKeys());
518  TKey *key;
519  TDirectory::TContext cur(fromfile);
520  while ((key = (TKey*)next())) {
521  if (!strcmp(key->GetClassName(),"TProcessID")) {
522  TProcessID *pid = (TProcessID*)key->ReadObjectAny(0);
523  if (!pid) continue;
524 
525  //UShort_t out = TProcessID::WriteProcessID(id,tofile);
526  UShort_t out = 0;
527  TObjArray *pids = tofile->GetListOfProcessIDs();
528  Int_t npids = tofile->GetNProcessIDs();
529  Bool_t wasIn = kFALSE;
530  for (Int_t i=0;i<npids;i++) {
531  if (pids->At(i) == pid) {out = (UShort_t)i; wasIn = kTRUE; break;}
532  }
533 
534  if (!wasIn) {
535  TDirectory *dirsav = gDirectory;
536  tofile->cd();
537  tofile->SetBit(TFile::kHasReferences);
538  pids->AddAtAndExpand(pid,npids);
539  pid->IncrementCount();
540  char name[32];
541  snprintf(name,32,"ProcessID%d",npids);
542  pid->Write(name);
543  tofile->IncrementProcessIDs();
544  if (gDebug > 0) {
545  Info("WriteProcessID", "name=%s, file=%s", name, tofile->GetName());
546  }
547  if (dirsav) dirsav->cd();
548  out = (UShort_t)npids;
549  }
550  if (out<fPidOffset) {
551  Error("CopyProcessIDs","Copied %s from %s might already exist!\n",
552  pid->GetName(),fromfile->GetName());
553  }
554  }
555  }
556 }
557 
558 ////////////////////////////////////////////////////////////////////////////////
559 /// Create a TFileCacheRead if it was requested.
560 
562 {
563  if (fCacheSize && fFromTree->GetCurrentFile()) {
565  auto prev = fFromTree->GetReadCache(f);
566  if (fFileCache && prev == fFileCache) {
567  return;
568  }
569  fPrevCache = prev;
570  // Remove the previous cache if any.
571  if (prev) f->SetCacheRead(nullptr, fFromTree);
572  // The constructor attach the new cache.
574  }
575 }
576 
577 ////////////////////////////////////////////////////////////////////////////////
578 /// Restore the TFileCacheRead to its previous value.
579 
581  if (IsValid() && fFileCache && fFromTree->GetCurrentFile()) {
583  f->SetCacheRead(nullptr,fFromTree); // Remove our file cache.
585  }
586 }
587 
588 ////////////////////////////////////////////////////////////////////////////////
589 /// Set the entries and import the cluster range of the
590 
592 {
593  // First undo, the external call to SetEntries
594  // We could improve the interface to optional tell the TTreeCloner that the
595  // SetEntries was not done.
597 
599 
600  // This is only updated by TTree::Fill upon seeing a Flush event in TTree::Fill
601  // So we need to propagate (this has also the advantage of turning on the
602  // history recording feature of SetAutoFlush for the next iteration)
604 
606 }
607 
608 ////////////////////////////////////////////////////////////////////////////////
609 /// Set the TFile cache size to be used.
610 /// Note that the default is to use the same size as the default TTreeCache for
611 /// the input tree.
612 /// \param size Size of the cache. Zero disable the use of the cache.
613 
615 {
616  fCacheSize = size;
617  if (IsValid() && fFileCache) {
618  if (fCacheSize == 0 || fCacheSize != fFileCache->GetBufferSize()) {
620  f->SetCacheRead(nullptr,fFromTree);
621  delete fFileCache;
622  fFileCache = nullptr;
623  }
624  }
625  // Note if the TFile cache is needed, it will be created at the
626  // beginning of Exec.
627 }
628 
629 ////////////////////////////////////////////////////////////////////////////////
630 /// Sort the basket according to the user request.
631 
633 {
634  // Currently this sort __has to__ preserve the order
635  // of basket for each individual branch.
636 
637  switch (fCloneMethod) {
639  // nothing to do, it is already sorted.
640  break;
641  case kSortBasketsByEntry: {
642  for(UInt_t i = 0; i < fMaxBaskets; ++i) { fBasketIndex[i] = i; }
643  std::sort(fBasketIndex, fBasketIndex+fMaxBaskets, CompareEntry( this) );
644  break;
645  }
647  default: {
648  for(UInt_t i = 0; i < fMaxBaskets; ++i) { fBasketIndex[i] = i; }
649  std::sort(fBasketIndex, fBasketIndex+fMaxBaskets, CompareSeek( this) );
650  break;
651  }
652  }
653 }
654 
655 ////////////////////////////////////////////////////////////////////////////////
656 /// Fill the file cache with the next set of basket.
657 ///
658 /// \param from index of the first lement of fFromBranches to start caching
659 /// \return The index of first element of fFromBranches that is not in the cache
661 {
662  if (!fFileCache) return 0;
663  // Reset the cache
664  fFileCache->Prefetch(0, 0);
665  Long64_t size = 0;
666  for (UInt_t j = from; j < fMaxBaskets; ++j) {
668 
669 
670  Int_t index = fBasketNum[ fBasketIndex[j] ];
671  Long64_t pos = frombr->GetBasketSeek(index);
672  Int_t len = frombr->GetBasketBytes()[index];
673  if (pos && len) {
674  size += len;
675  if (size > fFileCache->GetBufferSize()) {
676  return j;
677  }
678  fFileCache->Prefetch(pos,len);
679  }
680  }
681  return fMaxBaskets;
682 }
683 
684 ////////////////////////////////////////////////////////////////////////////////
685 /// Transfer the basket from the input file to the output file
686 
688 {
689  TBasket *basket = new TBasket();
690  for(UInt_t j = 0, notCached = 0; j<fMaxBaskets; ++j) {
693 
694  TFile *tofile = to->GetFile(0);
695  TFile *fromfile = from->GetFile(0);
696 
697  Int_t index = fBasketNum[ fBasketIndex[j] ];
698 
699  Long64_t pos = from->GetBasketSeek(index);
700  if (pos!=0) {
701  if (fFileCache && j >= notCached) {
702  notCached = FillCache(notCached);
703  }
704  if (from->GetBasketBytes()[index] == 0) {
705  from->GetBasketBytes()[index] = basket->ReadBasketBytes(pos, fromfile);
706  }
707  Int_t len = from->GetBasketBytes()[index];
708 
709  basket->LoadBasketBuffers(pos,len,fromfile,fFromTree);
711  basket->CopyTo(tofile);
712  to->AddBasket(*basket,kTRUE,fToStartEntries + from->GetBasketEntry()[index]);
713  } else {
714  TBasket *frombasket = from->GetBasket( index );
715  if (frombasket && frombasket->GetNevBuf()>0) {
716  TBasket *tobasket = (TBasket*)frombasket->Clone();
717  tobasket->SetBranch(to);
718  to->AddBasket(*tobasket, kFALSE, fToStartEntries+from->GetBasketEntry()[index]);
719  to->FlushOneBasket(to->GetWriteBasket());
720  }
721  }
722  }
723  delete basket;
724 }
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
TTreeCloner(const TTreeCloner &)=delete
Int_t ReadBasketBytes(Long64_t pos, TFile *file)
Read basket buffers in memory and cleanup.
Definition: TBasket.cxx:686
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
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:785
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:32
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us...
Definition: TTree.cxx:6036
UInt_t * fBasketIndex
[fMaxBaskets] ordered list of basket indices to be written.
Definition: TTreeCloner.h:56
An array of TObjects.
Definition: TObjArray.h:37
Long64_t * GetBasketEntry() const
Definition: TBranch.h:172
void ImportClusterRanges()
Set the entries and import the cluster range of the.
void RestoreCache()
Restore the TFileCacheRead to its previous value.
Long64_t * fBasketEntry
[fMaxBaskets] list of basket start entries.
Definition: TTreeCloner.h:55
long long Long64_t
Definition: RtypesCore.h:69
friend class CompareEntry
Definition: TTreeCloner.h:89
TObjArray * GetListOfBaskets()
Definition: TBranch.h:200
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:1136
A cache when reading files over the network.
const char Option_t
Definition: RtypesCore.h:62
void WriteBaskets()
Transfer the basket from the input file to the output file.
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2265
unsigned short UShort_t
Definition: RtypesCore.h:36
virtual const char * GetTypeName() const
Definition: TLeaf.h:89
Long64_t fToStartEntries
Number of entries in the target tree before any addition.
Definition: TTreeCloner.h:61
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:4420
TObjArray * GetListOfProcessIDs() const
Definition: TFile.h:219
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:47
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
void ForceWriteInfo(TFile *file, Bool_t force=kFALSE)
Recursively mark streamer infos for writing to a file.
Basic string class.
Definition: TString.h:131
TBranch * fBranchCount
Branch with clones count.
Definition: TBranchClones.h:37
#define f(i)
Definition: RSha256.hxx:104
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1100
virtual void Prefetch(Long64_t pos, Int_t len)
Add block of length len at position pos in the list of blocks to be prefetched.
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
ROOT::NewFunc_t GetNew() const
virtual TList * GetStreamerInfoList() final
Read the list of TStreamerInfo objects written to this file.
Definition: TFile.cxx:1394
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
void SetBranch(TBranch *branch)
Definition: TBasket.h:129
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:409
UInt_t fMaxBaskets
Definition: TTreeCloner.h:50
Int_t * GetBasketBytes() const
Definition: TBranch.h:171
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in &#39;fromtree&#39; to this tree, including the value of fAuto...
Definition: TTree.cxx:6090
void Class()
Definition: Class.C:29
virtual Bool_t IncludeRange(TLeaf *)
Definition: TLeaf.h:96
virtual Bool_t IsWritable() const
Definition: TDirectory.h:163
Int_t fMaximum
Maximum entries for a TClonesArray or variable array.
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process&#39;s memory.
Definition: TClass.cxx:5642
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,...)
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition: TTree.h:80
TObjArray * GetListOfBranches()
Definition: TBranch.h:201
TBasket * GetBasket(Int_t basket)
Return pointer to basket basketnumber in this Branch.
Definition: TBranch.cxx:1177
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:24
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:69
TFileCacheRead * fPrevCache
Cache that set before the TTreeCloner ctor for the &#39;from&#39; TTree if any.
Definition: TTreeCloner.h:65
void Error(const char *location, const char *msgfmt,...)
virtual TFile * GetFile() const
Definition: TDirectory.h:147
Bool_t IsValid()
Definition: TTreeCloner.h:121
virtual TTree * GetTree() const
Definition: TTree.h:438
virtual void IncrementProcessIDs()
Definition: TFile.h:240
A doubly linked list.
Definition: TList.h:44
TTree * fFromTree
Definition: TTreeCloner.h:44
virtual void AddLastBasket(Long64_t startEntry)
Add the start entry of the write basket (not yet created)
Definition: TBranch.cxx:584
virtual void IncrementPidOffset(UShort_t offset)
Increment fPidOffset by &#39;offset&#39;.
Definition: TKey.cxx:634
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:234
TVirtualStreamerInfo * FindStreamerInfo(TObjArray *arr, UInt_t checksum) const
Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum.
Definition: TClass.cxx:6737
UInt_t GetCheckSum() const
virtual void SetEntries(Long64_t entries)
Set the number of entries in this branch.
Definition: TBranch.cxx:2414
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.
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
Int_t GetWriteBasket() const
Definition: TBranch.h:193
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
Int_t IncrementCount()
Increase the reference count to this object.
Definition: TProcessID.cxx:311
unsigned int UInt_t
Definition: RtypesCore.h:42
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5205
Manages buffers for branches of a Tree.
Definition: TBasket.h:34
TObjArray fToBranches
Definition: TTreeCloner.h:48
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
TTreeCloner * fObject
Definition: TTreeCloner.h:75
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:371
friend class CompareSeek
Definition: TTreeCloner.h:88
void Warning(const char *location, const char *msgfmt,...)
Bool_t operator()(UInt_t i1, UInt_t i2)
Definition: TTreeCloner.cxx:56
A Branch for the case of an object.
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition: TBranch.cxx:1253
void CreateCache()
Create a TFileCacheRead if it was requested.
const Bool_t kFALSE
Definition: RtypesCore.h:88
UInt_t CollectBranches()
Fill the array of branches, matching the branches of the &#39;from&#39; and &#39;to&#39; TTrees Returns the total num...
Bool_t Exec()
Execute the cloning.
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
UInt_t * fBasketNum
[fMaxBaskets] index of the basket within the branch.
Definition: TTreeCloner.h:52
Long64_t GetCacheAutoSize(Bool_t withDefault=kFALSE) const
Used for automatic sizing of the cache.
Definition: TTree.cxx:5143
Bool_t operator()(UInt_t i1, UInt_t i2)
Definition: TTreeCloner.cxx:43
Describe directory structure in memory.
Definition: TDirectory.h:34
TDirectory * GetDirectory() const
Definition: TTree.h:383
virtual Int_t GetBufferSize() const
UInt_t fOptions
Definition: TTreeCloner.h:43
UInt_t FillCache(UInt_t from)
Fill the file cache with the next set of basket.
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
UShort_t fPidOffset
Offset to be added to the copied key/basket.
Definition: TTreeCloner.h:58
TObjArray * GetListOfLeaves()
Definition: TBranch.h:202
TFileCacheRead * fFileCache
File Cache used to reduce the number of individual reads.
Definition: TTreeCloner.h:64
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:2887
virtual Long64_t GetEntries() const
Definition: TTree.h:384
UInt_t fCloneMethod
Indicates which cloning method was selected.
Definition: TTreeCloner.h:60
void SetCacheSize(Int_t size)
Set the TFile cache size to be used.
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:74
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2198
UInt_t * fBasketBranchNum
[fMaxBaskets] Index of the branch(es) of the basket.
Definition: TTreeCloner.h:51
Int_t GetClassVersion() const
Long64_t GetEntries() const
Definition: TBranch.h:206
Int_t GetNevBuf() const
Definition: TBasket.h:117
Class implementing or helping the various TTree cloning method.
Definition: TTreeCloner.h:38
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
Definition: TDirectory.cxx:497
A Branch for the case of an array of clone objects.
Definition: TBranchClones.h:29
auto * l
Definition: textangle.C:4
virtual TList * GetListOfKeys() const
virtual Int_t GetNProcessIDs() const
Definition: TFile.h:222
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
virtual void AddBasket(TBasket &b, Bool_t ondisk, Long64_t startEntry)
Add the basket to this branch.
Definition: TBranch.cxx:518
#define snprintf
Definition: civetweb.c:1351
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
Bool_t fNeedConversion
True if the fast merge is not possible but a slow merge might possible.
Definition: TTreeCloner.h:42
virtual void AddLast(TObject *obj)
Add object in the next empty slot in the array.
Definition: TObjArray.cxx:177
A TTree object has a header with a name and a title.
Definition: TTree.h:70
#define gDirectory
Definition: TDirectory.h:213
TString fWarningMsg
Text of the error message lead to an &#39;invalid&#39; state.
Definition: TTreeCloner.h:39
Long64_t CopyTo(TFile *to)
Copy the basket of this branch onto the file to.
Definition: TBasket.cxx:136
void ResetBit(UInt_t f)
Definition: TObject.h:171
TTree * fToTree
Definition: TTreeCloner.h:45
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:1501
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8595
A TTree is a list of TBranches.
Definition: TBranch.h:62
Long64_t * fBasketSeek
[fMaxBaskets] list of basket position to be read.
Definition: TTreeCloner.h:54
Option_t * fMethod
Definition: TTreeCloner.h:46
virtual ~TTreeCloner()
TTreeCloner destructor.
void CopyMemoryBaskets()
Transfer the basket from the input file to the output file.
const Bool_t kTRUE
Definition: RtypesCore.h:87
void CollectBaskets()
Collect the information about the on-file basket that need to be copied.
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1718
char name[80]
Definition: TGX11.cxx:109
Int_t fCacheSize
Requested size of the file cache.
Definition: TTreeCloner.h:63
TObjArray fFromBranches
Definition: TTreeCloner.h:47
Int_t LoadBasketBuffers(Long64_t pos, Int_t len, TFile *file, TTree *tree=0)
Load basket buffers in memory without unziping.
Definition: TBasket.cxx:235
Bool_t fIsValid
Definition: TTreeCloner.h:41
const char * Data() const
Definition: TString.h:364