Logo ROOT  
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 "TTree.h"
27 #include "TTreeCloner.h"
28 #include "TFile.h"
29 #include "TLeafB.h"
30 #include "TLeafI.h"
31 #include "TLeafL.h"
32 #include "TLeafS.h"
33 #include "TLeafO.h"
34 #include "TLeafC.h"
35 #include "TFileCacheRead.h"
36 #include "TTreeCache.h"
37 #include "snprintf.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 same 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.
584  f->SetCacheRead(fPrevCache, fFromTree);
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 }
TFileCacheRead::Prefetch
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.
Definition: TFileCacheRead.cxx:201
TClass::GetStreamerInfo
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:4504
l
auto * l
Definition: textangle.C:4
TBranch::GetBasketBytes
Int_t * GetBasketBytes() const
Definition: TBranch.h:210
TTreeCloner::CompareEntry::operator()
Bool_t operator()(UInt_t i1, UInt_t i2)
Definition: TTreeCloner.cxx:56
TTreeCloner::fBasketBranchNum
UInt_t * fBasketBranchNum
[fMaxBaskets] Index of the branch(es) of the basket.
Definition: TTreeCloner.h:42
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:91
TTreeCloner::fToTree
TTree * fToTree
Definition: TTreeCloner.h:36
TObject::TestBit
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
TLeafL.h
snprintf
#define snprintf
Definition: civetweb.c:1540
TTreeCloner::CompareSeek::fObject
TTreeCloner * fObject
Definition: TTreeCloner.h:66
TObjArray
An array of TObjects.
Definition: TObjArray.h:37
TTreeCloner::~TTreeCloner
virtual ~TTreeCloner()
TTreeCloner destructor.
Definition: TTreeCloner.cxx:217
TTreeCloner::fMaxBaskets
UInt_t fMaxBaskets
Definition: TTreeCloner.h:41
Warning
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition: TError.cxx:231
f
#define f(i)
Definition: RSha256.hxx:104
Option_t
const char Option_t
Definition: RtypesCore.h:66
TStreamerInfo.h
TBranchRef.h
TTreeCloner::CollectBaskets
void CollectBaskets()
Collect the information about the on-file basket that need to be copied.
Definition: TTreeCloner.cxx:419
TBranchElement
A Branch for the case of an object.
Definition: TBranchElement.h:39
UShort_t
unsigned short UShort_t
Definition: RtypesCore.h:40
TTreeCloner::fNeedConversion
Bool_t fNeedConversion
True if the fast merge is not possible but a slow merge might possible.
Definition: TTreeCloner.h:33
TString::Data
const char * Data() const
Definition: TString.h:369
TFileCacheRead::GetBufferSize
virtual Int_t GetBufferSize() const
Definition: TFileCacheRead.h:88
TKey::ReadObjectAny
virtual void * ReadObjectAny(const TClass *expectedClass)
To read an object (non deriving from TObject) from the file.
Definition: TKey.cxx:1015
TLeafS.h
TTreeCloner::TTreeCloner
TTreeCloner(const TTreeCloner &)=delete
TBranch::GetListOfBranches
TObjArray * GetListOfBranches()
Definition: TBranch.h:242
TTree::GetReadCache
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition: TTree.cxx:6216
TBranch::AddBasket
virtual void AddBasket(TBasket &b, Bool_t ondisk, Long64_t startEntry)
Add the basket to this branch.
Definition: TBranch.cxx:535
TBranch.h
Long64_t
long long Long64_t
Definition: RtypesCore.h:73
TTreeCloner::CopyMemoryBaskets
void CopyMemoryBaskets()
Transfer the basket from the input file to the output file.
Definition: TTreeCloner.cxx:481
TTree
A TTree represents a columnar dataset.
Definition: TTree.h:79
TLeaf::GetTypeName
virtual const char * GetTypeName() const
Definition: TLeaf.h:138
TTreeCloner::RestoreCache
void RestoreCache()
Restore the TFileCacheRead to its previous value.
Definition: TTreeCloner.cxx:580
TBranch::GetListOfBaskets
TObjArray * GetListOfBaskets()
Definition: TBranch.h:241
TBranch::SetEntries
virtual void SetEntries(Long64_t entries)
Set the number of entries in this branch.
Definition: TBranch.cxx:2678
TProcessID
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:74
TClass::IsLoaded
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5726
TProcessID::IncrementCount
Int_t IncrementCount()
Increase the reference count to this object.
Definition: TProcessID.cxx:313
TDirectoryFile::cd
Bool_t cd(const char *path=nullptr) override
Change current directory to "this" directory.
Definition: TDirectoryFile.cxx:340
TLeafO.h
TString::Contains
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:624
TObjArray::GetEntries
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:523
TTree::fFlushedBytes
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition: TTree.h:89
TDirectory::TContext
Small helper to keep current directory context.
Definition: TDirectory.h:47
TDirectory::cd
virtual Bool_t cd(const char *path=nullptr)
Change current directory to "this" directory.
Definition: TDirectory.cxx:498
TTreeCloner::fBasketIndex
UInt_t * fBasketIndex
[fMaxBaskets] ordered list of basket indices to be written.
Definition: TTreeCloner.h:47
TBasket::CopyTo
Long64_t CopyTo(TFile *to)
Copy the basket of this branch onto the file to.
Definition: TBasket.cxx:146
TTreeCloner::ImportClusterRanges
void ImportClusterRanges()
Set the entries and import the cluster range of the.
Definition: TTreeCloner.cxx:591
TTreeCloner::fPrevCache
TFileCacheRead * fPrevCache
Cache that set before the TTreeCloner ctor for the 'from' TTree if any.
Definition: TTreeCloner.h:56
TObjArray::UncheckedAt
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:90
TObjArray::At
TObject * At(Int_t idx) const
Definition: TObjArray.h:166
TTree.h
TTreeCloner::fBasketEntry
Long64_t * fBasketEntry
[fMaxBaskets] list of basket start entries.
Definition: TTreeCloner.h:46
TFile::GetListOfProcessIDs
TObjArray * GetListOfProcessIDs() const
Definition: TFile.h:228
TTreeCloner::fFromTree
TTree * fFromTree
Definition: TTreeCloner.h:35
TBasket::GetNevBuf
Int_t GetNevBuf() const
Definition: TBasket.h:129
TString
Basic string class.
Definition: TString.h:136
TTreeCloner::CompareEntry
friend class CompareEntry
Definition: TTreeCloner.h:80
TBranch::GetBasketEntry
Long64_t * GetBasketEntry() const
Definition: TBranch.h:211
TObject::InheritsFrom
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:445
TBranchClones::fBranchCount
TBranch * fBranchCount
Branch with clones count.
Definition: TBranchClones.h:37
b
#define b(i)
Definition: RSha256.hxx:100
TFile.h
bool
TTreeCloner::CompareSeek
friend class CompareSeek
Definition: TTreeCloner.h:79
TClass::FindStreamerInfo
TVirtualStreamerInfo * FindStreamerInfo(TObjArray *arr, UInt_t checksum) const
Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum.
Definition: TClass.cxx:6824
TDirectory::IsWritable
virtual Bool_t IsWritable() const
Definition: TDirectory.h:181
TTree::GetListOfBranches
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:483
TObjArray::AddLast
virtual void AddLast(TObject *obj)
Add object in the next empty slot in the array.
Definition: TObjArray.cxx:178
TTree::ImportClusterRanges
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in 'fromtree' to this tree, including the value of fAuto...
Definition: TTree.cxx:6270
TBranch::kDoNotUseBufferMap
@ kDoNotUseBufferMap
Definition: TBranch.h:108
TFile::GetStreamerInfoList
virtual TList * GetStreamerInfoList() final
Read the list of TStreamerInfo objects written to this file.
Definition: TFile.cxx:1358
TTreeCloner::CreateCache
void CreateCache()
Create a TFileCacheRead if it was requested.
Definition: TTreeCloner.cxx:561
TTreeCloner::kDefault
@ kDefault
Definition: TTreeCloner.h:59
TBasket::ReadBasketBytes
Int_t ReadBasketBytes(Long64_t pos, TFile *file)
Read basket buffers in memory and cleanup.
Definition: TBasket.cxx:698
TLeaf::IncludeRange
virtual Bool_t IncludeRange(TLeaf *)
Definition: TLeaf.h:145
TTreeCloner::kSortBasketsByEntry
@ kSortBasketsByEntry
Definition: TTreeCloner.h:62
TTree::GetTree
virtual TTree * GetTree() const
Definition: TTree.h:512
TTreeCloner::fToStartEntries
Long64_t fToStartEntries
Number of entries in the target tree before any addition.
Definition: TTreeCloner.h:52
TBranch
A TTree is a list of TBranches.
Definition: TBranch.h:89
TProcessID.h
TTree::GetCurrentFile
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5378
TString::Form
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2289
TDirectoryFile::GetListOfKeys
TList * GetListOfKeys() const override
Definition: TDirectoryFile.h:93
TStreamerInfo::ForceWriteInfo
void ForceWriteInfo(TFile *file, Bool_t force=kFALSE)
Recursively mark streamer infos for writing to a file.
Definition: TStreamerInfo.cxx:3096
TTreeCache.h
TTreeCloner::CompareSeek::operator()
Bool_t operator()(UInt_t i1, UInt_t i2)
Definition: TTreeCloner.cxx:43
TBranchElement.h
TFileCacheRead.h
TBranch::GetFile
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:1729
TObject::ResetBit
void ResetBit(UInt_t f)
Definition: TObject.h:171
TBranch::GetBasketSeek
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition: TBranch.cxx:1281
TKey::GetClassName
virtual const char * GetClassName() const
Definition: TKey.h:76
TStreamerInfo
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:44
TLeafI.h
TTreeCloner::fFileCache
TFileCacheRead * fFileCache
File Cache used to reduce the number of individual reads.
Definition: TTreeCloner.h:55
TLeaf
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:57
TObject::SetBit
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:696
TBranchClones
A Branch for the case of an array of clone objects.
Definition: TBranchClones.h:29
TTreeCloner
Class implementing or helping the various TTree cloning method.
Definition: TTreeCloner.h:29
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:92
TLeafC.h
TNamed::Clone
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:74
TTree::GetBranchRef
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:445
gDirectory
#define gDirectory
Definition: TDirectory.h:236
TTreeCloner::SortBaskets
void SortBaskets()
Sort the basket according to the user request.
Definition: TTreeCloner.cxx:632
TObjArray::AddAtAndExpand
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:235
TBasket::LoadBasketBuffers
Int_t LoadBasketBuffers(Long64_t pos, Int_t len, TFile *file, TTree *tree=0)
Load basket buffers in memory without unziping.
Definition: TBasket.cxx:245
TTreeCloner::FillCache
UInt_t FillCache(UInt_t from)
Fill the file cache with the next set of basket.
Definition: TTreeCloner.cxx:660
gDebug
Int_t gDebug
Definition: TROOT.cxx:590
TTreeCloner.h
TTreeCloner::IsValid
Bool_t IsValid()
Definition: TTreeCloner.h:112
TClass::GetClass
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:2925
TStreamerInfo::GetCheckSum
UInt_t GetCheckSum() const
Definition: TStreamerInfo.h:206
TFile::IncrementProcessIDs
virtual void IncrementProcessIDs()
Definition: TFile.h:249
TTreeCloner::fCloneMethod
UInt_t fCloneMethod
Indicates which cloning method was selected.
Definition: TTreeCloner.h:51
TLeafB.h
TKey::IncrementPidOffset
virtual void IncrementPidOffset(UShort_t offset)
Increment fPidOffset by 'offset'.
Definition: TKey.cxx:650
TBranchClones.h
TTreeCloner::CloseOutWriteBaskets
void CloseOutWriteBaskets()
Before we can start adding new basket, we need to flush to disk the partially filled baskets (the Wri...
Definition: TTreeCloner.cxx:233
TFile
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:54
TTree::GetCacheAutoSize
Long64_t GetCacheAutoSize(Bool_t withDefault=kFALSE) const
Used for automatic sizing of the cache.
Definition: TTree.cxx:5316
TTreeCloner::fMethod
Option_t * fMethod
Definition: TTreeCloner.h:37
unsigned int
TFileCacheRead
A cache when reading files over the network.
Definition: TFileCacheRead.h:22
TStreamerInfo::GetClassVersion
Int_t GetClassVersion() const
Definition: TStreamerInfo.h:208
TTree::GetDirectory
TDirectory * GetDirectory() const
Definition: TTree.h:457
TTreeCloner::kSortBasketsByBranch
@ kSortBasketsByBranch
Definition: TTreeCloner.h:60
TKey
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:28
TFile::GetNProcessIDs
virtual Int_t GetNProcessIDs() const
Definition: TFile.h:231
TTreeCloner::CopyStreamerInfos
void CopyStreamerInfos()
Make sure that all the needed TStreamerInfo are present in the output file.
Definition: TTreeCloner.cxx:440
TBranch::GetMother
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1982
TBasket
Manages buffers for branches of a Tree.
Definition: TBasket.h:34
TTreeCloner::fFromBranches
TObjArray fFromBranches
Definition: TTreeCloner.h:38
TTreeCloner::fIsValid
Bool_t fIsValid
Definition: TTreeCloner.h:32
TTreeCloner::fWarningMsg
TString fWarningMsg
Text of the error message lead to an 'invalid' state.
Definition: TTreeCloner.h:30
TTree::SetEntries
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8831
TClass::GetNew
ROOT::NewFunc_t GetNew() const
Return the wrapper around new ThisClass().
Definition: TClass.cxx:7184
Info
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition: TError.cxx:220
TClass
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
TTreeCloner::fBasketSeek
Long64_t * fBasketSeek
[fMaxBaskets] list of basket position to be read.
Definition: TTreeCloner.h:45
TObject::Write
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:795
TBranch::GetWriteBasket
Int_t GetWriteBasket() const
Definition: TBranch.h:234
TTreeCloner::CopyProcessIds
void CopyProcessIds()
Make sure that all the needed TStreamerInfo are present in the output file.
Definition: TTreeCloner.cxx:508
TDirectory::GetFile
virtual TFile * GetFile() const
Definition: TDirectory.h:165
name
char name[80]
Definition: TGX11.cxx:110
TBranch::AddLastBasket
virtual void AddLastBasket(Long64_t startEntry)
Add the start entry of the write basket (not yet created)
Definition: TBranch.cxx:601
TTreeCloner::fCacheSize
Int_t fCacheSize
Requested size of the file cache.
Definition: TTreeCloner.h:54
TDirectory
Describe directory structure in memory.
Definition: TDirectory.h:40
TBranchElement::fMaximum
Int_t fMaximum
Maximum entries for a TClonesArray or variable array.
Definition: TBranchElement.h:80
TTree::BranchRef
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2303
TIter
Definition: TCollection.h:233
TTreeCloner::kIgnoreMissingTopLevel
@ kIgnoreMissingTopLevel
Definition: TTreeCloner.h:95
TTreeCloner::kNoFileCache
@ kNoFileCache
Definition: TTreeCloner.h:96
TTreeCloner::fToBranches
TObjArray fToBranches
Definition: TTreeCloner.h:39
TTreeCloner::WriteBaskets
void WriteBaskets()
Transfer the basket from the input file to the output file.
Definition: TTreeCloner.cxx:687
TBranch::FlushOneBasket
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:1161
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
TTreeCloner::kSortBasketsByOffset
@ kSortBasketsByOffset
Definition: TTreeCloner.h:61
TBasket::SetBranch
void SetBranch(TBranch *branch)
Definition: TBasket.h:148
Class
void Class()
Definition: Class.C:29
TString::ToLower
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1125
TBranch::GetListOfLeaves
TObjArray * GetListOfLeaves()
Definition: TBranch.h:243
TTreeCloner::fPidOffset
UShort_t fPidOffset
Offset to be added to the copied key/basket.
Definition: TTreeCloner.h:49
TBranch::GetBasket
TBasket * GetBasket(Int_t basket)
Definition: TBranch.h:209
TTree::GetEntries
virtual Long64_t GetEntries() const
Definition: TTree.h:458
TTreeCloner::CollectBranches
UInt_t CollectBranches()
Fill the array of branches, matching the branches of the 'from' and 'to' TTrees Returns the total num...
Definition: TTreeCloner.cxx:398
TTreeCloner::Exec
Bool_t Exec()
Execute the cloning.
Definition: TTreeCloner.cxx:195
TTreeCloner::SetCacheSize
void SetCacheSize(Int_t size)
Set the TFile cache size to be used.
Definition: TTreeCloner.cxx:614
TBranch::GetEntries
Long64_t GetEntries() const
Definition: TBranch.h:247
TBasket.h
TTreeCloner::fBasketNum
UInt_t * fBasketNum
[fMaxBaskets] index of the basket within the branch.
Definition: TTreeCloner.h:43
TList
A doubly linked list.
Definition: TList.h:44
TTreeCloner::kNoWarnings
@ kNoWarnings
Definition: TTreeCloner.h:94
TFile::kHasReferences
@ kHasReferences
Definition: TFile.h:184
int
Error
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition: TError.cxx:187
TError.h
TTreeCloner::fOptions
UInt_t fOptions
Definition: TTreeCloner.h:34