Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TEntryList.cxx
Go to the documentation of this file.
1// @(#)root/tree:$Id$
2// Author: Anna Kreshuk 27/10/2006
3
4/*************************************************************************
5 * Copyright (C) 1995-2006, 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 TEntryList
13\ingroup tree
14
15A List of entry numbers in a TTree or TChain.
16
17Note: It is recommended to use approaches such as TTreeReader::SetEntryRange or
18ROOT::RDataFrame instead of TEntryList if possible.
19
20## Operations on entry lists
21
22- __Add__() - if the lists are for the same tree, adds all the entries of the second list
23 to the first list. If the lists are for different trees, creates a TEntryList
24 with 2 sublists for each TTree. If the lists are for TChains, merges the ones
25 for the same trees and adds new sublists for the TTrees that were not included
26 in the first TEntryList
27- __Subtract__() - if the lists are for the same TTree, removes the entries of the second
28 list from the first list. If the lists are for TChains, loops over all
29 sub-lists
30- __GetEntry(n)__ - returns the n-th entry number
31- __Next__() - returns next entry number. Note, that this function is
32 much faster than GetEntry, and it's called when GetEntry() is called
33 for 2 or more indices in a row.
34
35## TTree::Draw() and TChain::Draw()
36
37Use option __entrylist__ to write the results of TTree::Draw and TChain::Draw into
38an entry list. Example:
39~~~ {.cpp}
40 tree->Draw(">>elist", "x<0 && y>0", "entrylist");
41 TEntryList *elist = (TEntryList*)gDirectory->Get("elist");
42~~~
43## Example of Loop on TEntryList with a TChain
44~~~ {.cpp}
45 void loopChain() {
46 TFile *fe = TFile::Open("myelist.root");
47 TEntryList *myelist = (TEntryList*)fe->Get("myelist");
48 TChain *chain = new TChain("ntuple");
49 chain->Add("hsimple.root");
50 chain->Add("hsimple2.root");
51 Long64_t listEntries = myelist->GetN();
52 Long64_t chainEntries = chain->GetEntries();
53 Int_t treenum = 0;
54 chain->SetEntryList(myelist);
55
56 for (entry=start;entry < end;entry++) {
57 entryNumber = chain->GetEntryNumber(entry);
58 if (entryNumber < 0) break;
59 localEntry = chain->LoadTree(entryNumber);
60 if (localEntry < 0) break;
61 ....
62 then either call
63 branch->GetEntry(localEntry);
64 or
65 chain->GetEntry(entryNumber);
66 In the later case the LoadTree is then somewhat redundant.
67 ...
68 }
69 }
70~~~
71When using the TEntryList interface directly, you can get the 'tree number' and entry in
72the current tree (i.e. value similar to the return value of LoadTree) from calling
73TEntryList::GetEntryAndTree:
74~~~ {.cpp}
75 Long64_t treeEntry = myelist->GetEntryAndTree(el,treenum);
76~~~
77to obtain the entry number within the chain you need to add to it the value of
78`treeEntry+ch->GetTreeOffset()[treenum]`
79such that the loop in the previous example can also be written as:
80~~~ {.cpp}
81 for (Long64_t el = 0; el < listEntries; el++) {
82 Long64_t treeEntry = myelist->GetEntryAndTree(el,treenum);
83 Long64_t chainEntry = treeEntry+ch->GetTreeOffset()[treenum];
84 printf("el=%lld, treeEntry=%lld, chainEntry=%lld, treenum=%d\n", el, treeEntry, chainEntry, treenum);
85
86 ch->LoadTree(chainEntry); // this also returns treeEntry
87 needed_branch->GetEntry(treeEntry);
88 }
89~~~
90## TSelectors
91
92To fill an TEntryList from a TSelector correctly, one must add the TEntryList object
93to the output list of the selector (TSelector::fOutput). This is the only way to
94make the sub-lists of the TEntryList switch when the current tree of the TChain is
95changed.
96
97## Using a TEntryList as input (TTree::SetEntryList() and TChain::SetEntryList())
98
99while the TTree::SetEntryList() function is only setting the TTree::fEntryList
100data member, the same function in TChain also finds correspondence between
101the TTrees of this TChain and the sub-lists of this TEntryList.
102
103## TEntryList and the current directory
104
105TEntryList objects are automatically added to the current directory (like TTrees).
106However, in case of a TEntryList for a chain, only the top-level entry list is added,
107not the sub-lists for specific trees. Placing entry lists in the current directory
108allows calling them as a part of a TTreeFormula expression, so if the user wants
109to extract a sublist from a TChain entry list via the GetEntryList() or some other
110function, they have to add it to the current directory to be able to use it in
111TTreeFormula expressions.
112
113## TEntryList and TEventList
114
115TTree::SetEventList() and TChain::SetEventList() transform a TEventList into a TEntryList
116See comments to those functions for more details
117
118## Types of entry lists
119There are two types of entry lists:
120
121#### 1.
122 for a TTree (fBlocks data member is non-zero)
123 Entry numbers are stored in TEntryListBlocks, which, in their turn, are stored
124 in the TObjArray fBlocks. The range of the entry numbers is cut into intervals
125 of kBlockSize entries (currently 64000), so that the first block contains
126 information which entries out of the first 64000 pass the selection, the second
127 block - which entries out of the 64000-127999 interval pass the selection, etc.
128 Some blocks, obviously, might be empty. The internal representation of entry
129 numbers in the blocks is described in the TEntryListBlock class description, and
130 this representation might be changed by calling OptimizeStorage() function
131 (when the list is filled via the Enter() function, this is done automatically,
132 except for the last block).
133 Individual entry lists can be merged (functions Merge() and Add())
134 to make an entry list for a TChain of corresponding TTrees.
135Begin_Macro
136entrylist_figure1.C
137End_Macro
138
139#### 2.
140 for a TChain (fLists data member is non-zero)
141 It contains a TList of sub-lists (TEntryList objects, corresponding to each TTree)
142 Trees and lists are matched by the TTree name and its file name (full path).
143 All sub-lists are returned by the GetLists() function and individual lists are
144 returned by GetEntryList() function. Such lists are no different from the lists for
145 TTrees, described above.
146Begin_Macro
147entrylist_figure2.C
148End_Macro
149
150
151*/
152
153#include "TEntryList.h"
154#include "TEntryListBlock.h"
155#include "TError.h"
156#include "TKey.h"
157#include "TBuffer.h"
158#include "TTree.h"
159#include "TFile.h"
160#include "TRegexp.h"
161#include "TSystem.h"
162#include "TObjString.h"
163
164
165////////////////////////////////////////////////////////////////////////////////
166/// default c-tor
167
168TEntryList::TEntryList() : fEntriesToProcess(0)
169{
170 fLists = nullptr;
171 fCurrent = nullptr;
172 fBlocks = nullptr;
173 fN = 0;
174 fNBlocks = 0;
175 fTreeName = "";
176 fFileName = "";
177 fStringHash = 0;
178 fTreeNumber = -1;
179 fDirectory = nullptr;
180 fReapply = false;
183 fShift = false;
184}
185
186////////////////////////////////////////////////////////////////////////////////
187/// c-tor with name and title
188
189TEntryList::TEntryList(const char *name, const char *title) :
190 TNamed(name, title),
191 fEntriesToProcess(0)
192{
193 fLists = nullptr;
194 fCurrent = nullptr;
195 fBlocks = nullptr;
196 fN = 0;
197 fNBlocks = 0;
198 fTreeName = "";
199 fFileName = "";
200 fStringHash = 0;
201 fTreeNumber = -1;
202 fReapply = false;
203
205 if (fDirectory) fDirectory->Append(this);
206
209 fShift = false;
210}
211
212////////////////////////////////////////////////////////////////////////////////
213/// constructor with name and title, which also sets the tree
214
215TEntryList::TEntryList(const char *name, const char *title, const TTree *tree):TNamed(name, title)
216{
217 fLists = nullptr;
218 fCurrent = nullptr;
219 fBlocks = nullptr;
220 fN = 0;
221 fNBlocks = 0;
222 fTreeNumber = -1;
224 fReapply = false;
225
227 if (fDirectory) fDirectory->Append(this);
228
231 fShift = false;
232}
233
234////////////////////////////////////////////////////////////////////////////////
235/// c-tor with name and title, which also sets the treename and the filename
236
237TEntryList::TEntryList(const char *name, const char *title, const char *treename, const char *filename) : TNamed(name, title),fEntriesToProcess(0)
238{
239 fLists = nullptr;
240 fCurrent = nullptr;
241 fBlocks = nullptr;
242 fNBlocks = 0;
243 fN = 0;
245 fTreeNumber = -1;
246 fReapply = false;
247
249 if (fDirectory) fDirectory->Append(this);
250
253 fShift = false;
254}
255
256////////////////////////////////////////////////////////////////////////////////
257/// c-tor, which sets the tree
258
259TEntryList::TEntryList(const TTree *tree) : fEntriesToProcess(0)
260{
261 fLists = nullptr;
262 fCurrent = nullptr;
263 fBlocks = nullptr;
264 fNBlocks = 0;
265 fN = 0;
266
267 SetTree(tree);
268 fTreeNumber = -1;
269
270 fReapply = false;
272 if (fDirectory) fDirectory->Append(this);
273
276 fShift = false;
277}
278
279////////////////////////////////////////////////////////////////////////////////
280/// copy c-tor
281
282TEntryList::TEntryList(const TEntryList &elist) : TNamed(elist)
283{
284 fNBlocks = elist.fNBlocks;
285 fTreeName = elist.fTreeName;
286 fFileName = elist.fFileName;
287 fStringHash = elist.fStringHash;
288 fTreeNumber = elist.fTreeNumber;
291 fN = elist.fN;
292 fShift = elist.fShift;
293 fLists = nullptr;
294 fBlocks = nullptr;
295 fReapply = elist.fReapply;
296 fCurrent = nullptr;
298 if (elist.fLists){
299 fLists = new TList();
300 TEntryList *el1 = nullptr;
301 TEntryList *el2 = nullptr;
302 TIter next(elist.fLists);
303 while((el1 = (TEntryList*)next())){
304 el2 = new TEntryList(*el1);
305 if (el1==elist.fCurrent)
306 fCurrent = el2;
307 fLists->Add(el2);
308 }
309 } else {
310 if (elist.fBlocks){
311 TEntryListBlock *block1 = nullptr;
312 TEntryListBlock *block2 = nullptr;
313 //or just copy it as a TObjArray??
314 fBlocks = new TObjArray();
315 for (Int_t i=0; i<fNBlocks; i++){
319 }
320 }
321 fCurrent = this;
322 }
323 fDirectory = nullptr;
324
325}
326
327////////////////////////////////////////////////////////////////////////////////
328/// Destructor.
329
331{
332 if (fBlocks){
333 fBlocks->Delete();
334 delete fBlocks;
335 }
336 fBlocks = nullptr;
337 if (fLists){
338 fLists->Delete();
339 delete fLists;
340 }
341
342 fLists = nullptr;
343
344 if (fDirectory) fDirectory->Remove(this);
345 fDirectory = nullptr;
346
347}
348
349////////////////////////////////////////////////////////////////////////////////
350/// \brief Add 2 entry lists.
351///
352/// \param[in] elist The list that should be added to the current one.
353///
354/// \note If you are creating a TEntryList for a TChain and you would like to
355/// have a one to one mapping between the sub lists of the TEntryList and
356/// the sub trees in the TChain, please do not call this function but use
357/// TEntryList::AddSubList instead and pair it with a call to
358/// TChain::SetEntryList with option "sync". See the AddSubList function
359/// documentation for an example usage. This helps for example in a
360/// testing or benchmark scenario where a TChain holds multiple times the
361/// same tree in the same file. In that case, this function would not be
362/// be able to distinguish different sub entry lists that refer to the
363/// same treename and filename. Instead it would create a union of all the
364/// sub entry lists into one list.
365
366void TEntryList::Add(const TEntryList *elist)
367{
368 if (fN==0){
369 if (!fLists && fTreeName=="" && fFileName==""){
370 //this list is empty. copy the other list completely
371 fNBlocks = elist->fNBlocks;
372 fTreeName = elist->fTreeName;
373 fFileName = elist->fFileName;
374 fStringHash = elist->fStringHash;
375 fTreeNumber = elist->fTreeNumber;
378 fN = elist->fN;
379 if (elist->fLists){
380 fLists = new TList();
381 TEntryList *el1 = nullptr;
382 TEntryList *el2 = nullptr;
383 TIter next(elist->fLists);
384 while((el1 = (TEntryList*)next())){
385 el2 = new TEntryList(*el1);
386 if (el1==elist->fCurrent)
387 fCurrent = el2;
388 fLists->Add(el2);
389 }
390 } else {
391 if (elist->fBlocks){
392 TEntryListBlock *block1 = nullptr;
393 TEntryListBlock *block2 = nullptr;
394 fBlocks = new TObjArray();
395 for (Int_t i=0; i<fNBlocks; i++){
399 }
400 }
401 fCurrent = nullptr;
402 }
403 return;
404 }
405 }
406
407 if (!fLists){
408 if (!elist->fLists){
409 if (!strcmp(elist->fTreeName.Data(),fTreeName.Data()) && !strcmp(elist->fFileName.Data(),fFileName.Data())){
410 //entry lists are for the same tree
411 if (!elist->fBlocks)
412 //the other list is empty list
413 return;
414 if (!fBlocks){
415 //this entry list is empty
416 TEntryListBlock *block1 = nullptr;
417 TEntryListBlock *block2 = nullptr;
418 fNBlocks = elist->fNBlocks;
419 fN = elist->fN;
420 fBlocks = new TObjArray();
421 for (Int_t i=0; i<fNBlocks; i++){
425 }
426 return;
427 }
428 //both not empty, merge block by block
429 TEntryListBlock *block1=nullptr;
430 TEntryListBlock *block2=nullptr;
431 Int_t i;
432 Int_t nmin = std::min(fNBlocks, elist->fNBlocks);
434 for (i=0; i<nmin; i++){
437 nold = block1->GetNPassed();
438 nnew = block1->Merge(block2);
439 fN = fN - nold + nnew;
440 }
442 Int_t nmax = elist->fNBlocks;
443 for (i=nmin; i<nmax; i++){
447 fN+=block1->GetNPassed();
448 fNBlocks++;
449 }
450 }
453 } else {
454 //entry lists are for different trees. create a chain entry list with
455 //2 sub lists for the first and second entry lists
458 fLists = new TList();
459 TEntryList *el = new TEntryList();
460 el->fTreeName = fTreeName;
461 el->fFileName = fFileName;
462 el->fBlocks = fBlocks;
463 fBlocks = nullptr;
464 el->fNBlocks = fNBlocks;
465 el->fN = fN;
466 el->fLastIndexQueried = -1;
467 el->fLastIndexReturned = 0;
468 fLists->Add(el);
469 el = new TEntryList(*elist);
470 el->fLastIndexQueried = -1;
471 el->fLastIndexReturned = 0;
472 fLists->Add(el);
473 fN+=el->GetN();
474 fCurrent = nullptr;
475 }
476 } else {
477 //second list already has sublists. add one by one
478 TEntryList *el = nullptr;
479 TIter next(elist->fLists);
480 while ((el = (TEntryList*)next())){
481 Add(el);
482 }
483 fCurrent = nullptr;
484 }
485 } else {
486 //there are already some sublists in this list, just add another one
487 if (!elist->fLists){
488 //the other list doesn't have sublists
489 TIter next(fLists);
490 TEntryList *el = nullptr;
491 bool found = false;
492 while ((el = (TEntryList*)next())){
493 if (!strcmp(el->fTreeName.Data(), elist->fTreeName.Data()) &&
494 !strcmp(el->fFileName.Data(), elist->fFileName.Data())){
495 // if (el->fStringHash == elist->fStringHash){
496 //found a list for the same tree
497 Long64_t oldn = el->GetN();
498 el->Add(elist);
499 found = true;
500 fN = fN - oldn + el->GetN();
501 break;
502 }
503 }
504 if (!found){
505 el = new TEntryList(*elist);
506 el->fLastIndexQueried = -1;
507 el->fLastIndexReturned = 0;
508 fLists->Add(el);
509 fN+=el->GetN();
510 }
511 } else {
512 //add all sublists from the other list
513 TEntryList *el = nullptr;
514 TIter next(elist->fLists);
515 while ((el = (TEntryList*)next())){
516 Add(el);
517 }
518 fCurrent = nullptr;
519 }
520 if (fCurrent){
521 if (fCurrent->fBlocks){
524 block->ResetIndices();
527 }
528 }
529 fCurrent = nullptr;
530 }
531
532}
533
534////////////////////////////////////////////////////////////////////////////////
535/// \brief Add a sub entry list to the current list.
536/// \param[in] elist an entry list that should be added as a sub list of this list.
537///
538/// This function is specifically targeted at situations where there is a global
539/// TEntryList that should hold one or more sub TEntryList objects. For example,
540/// if one wants to create a one to one mapping between the sub entry lists and
541/// the trees in the files that make a TChain. Note that in such cases this
542/// configuration of the entry list should be used in pair with the option \p "sync"
543/// of the function TChain::SetEntryList
544///
545/// ~~~{.cpp}
546/// // Create a TChain with two files. Each contains a tree with 20 entries
547/// TChain chain{"entries"};
548/// chain.Add("file_20entries_1.root");
549/// chain.Add("file_20entries_2.root");
550///
551/// // Create a global, empty TEntryList.
552/// TEntryList elists;
553/// // Create two entry lists. Each one will be referring to a different tree in the chain
554/// TEntryList elist1{"","","entries","file_20entries_1.root"};
555/// TEntryList elist2{"","","entries","file_20entries_2.root"};
556///
557/// // Select the first ten entries from the first tree and all entries from the second
558/// for(auto entry = 0; entry < 10; entry++){
559/// elist1.Enter(entry);
560/// }
561/// for(auto entry = 0; entry < 20; entry++){
562/// elist2.Enter(entry);
563/// }
564///
565/// // Add sub entry lists to the global list
566/// elists.AddSubList(&elist1);
567/// elists.AddSubList(&elist2);
568///
569/// // Set the entry list in the chain. Note the usage of option "sync"
570/// chain.SetEntryList(&elists, "sync");
571/// ~~~
572
574
575 auto elistcopy = new TEntryList{*elist};
576
577 fN += elistcopy->fN;
578
579 if (!fLists){
580 fLists = new TList();
581 }
583}
584
585////////////////////////////////////////////////////////////////////////////////
586/// - When tree = 0, returns from the current list
587/// - When tree != 0, finds the list, corresponding to this tree
588/// - When tree is a chain, the entry is assumed to be global index and the local
589/// entry is recomputed from the treeoffset information of the chain
590
592{
593 if (!tree){
594 if (fBlocks) {
595 //this entry list doesn't contain any sub-lists
596 TEntryListBlock *block = nullptr;
598 if (nblock >= fNBlocks) return 0;
600 return block->Contains(entry-nblock*kBlockSize);
601 }
602 if (fLists) {
604 return fCurrent->Contains(entry);
605 }
606 return 0;
607 } else {
608 Long64_t localEntry = tree->LoadTree(entry);
609 SetTree(tree->GetTree());
610 if (fCurrent)
612 }
613 return 0;
614
615}
616
617////////////////////////////////////////////////////////////////////////////////
618/// Called by TKey and others to automatically add us to a directory when we are read from a file.
619
621{
622 SetDirectory(dir);
623}
624
625////////////////////////////////////////////////////////////////////////////////
626/// Add entry \#entry to the list
627/// - When tree = 0, adds to the current list
628/// - When tree != 0, finds the list, corresponding to this tree
629/// - When tree is a chain, the entry is assumed to be global index and the local
630/// entry is recomputed from the treeoffset information of the chain
631
633{
634 if (!tree){
635 if (!fLists) {
636 if (!fBlocks) fBlocks = new TObjArray();
637 TEntryListBlock *block = nullptr;
639 if (nblock >= fNBlocks) {
640 if (fNBlocks>0){
642 if (!block) return false;
643 block->OptimizeStorage();
644 }
645 for (Int_t i=fNBlocks; i<=nblock; i++){
646 block = new TEntryListBlock();
647 fBlocks->Add(block);
648 }
649 fNBlocks = nblock+1;
650 }
652 if (block->Enter(entry-nblock*kBlockSize)) {
653 fN++;
654 return true;
655 }
656 } else {
657 //the entry in the current entry list
659 if (fCurrent->Enter(entry)) {
660 if (fLists)
661 fN++;
662 return true;
663 }
664 }
665 } else {
666 Long64_t localentry = tree->LoadTree(entry);
667 SetTree(tree->GetTree());
668 if (fCurrent){
669 if (fCurrent->Enter(localentry)) {
670 if (fLists)
671 fN++;
672 return true;
673 }
674 }
675 }
676 return false;
677
679
680bool TEntryList::Enter(Long64_t localentry, const char *treename, const char *filename)
681{
683 if (fCurrent) {
684 if (fCurrent->Enter(localentry)) {
685 if (fLists)
686 fN++;
687 return true;
688 }
689 }
690 return false;
691}
692
693/////////////////////////////////////////////////////////////////////////////
694/// \brief Enter all entries in a range in the TEntryList.
695/// \param[in] start starting entry to enter.
696/// \param[in] end ending entry to enter.
697/// \param[in] tree passed as is to TEntryList::Enter.
698/// \param[in] step step increase of the loop entering the entries.
699///
700/// This is a helper function that enters all entries between \p start
701/// (inclusive) and \p end (exclusive) to the TEntryList in a loop. It
702/// is useful also in PyROOT to avoid having to do the same in a Python loop.
703
704void TEntryList::EnterRange(Long64_t start, Long64_t end, TTree *tree, UInt_t step)
705{
706 for (auto entry = start; entry < end; entry += step) {
707 this->Enter(entry, tree);
708 }
709}
710
711////////////////////////////////////////////////////////////////////////////////
712/// Remove entry \#entry from the list
713/// - When tree = 0, removes from the current list
714/// - When tree != 0, finds the list, corresponding to this tree
715/// - When tree is a chain, the entry is assumed to be global index and the local
716/// entry is recomputed from the treeoffset information of the chain
717
719{
720 if (entry < 0)
721 return false;
722 if (!tree) {
723 if (!fLists) {
724 if (!fBlocks) return false;
725 TEntryListBlock *block = nullptr;
728 if (!block) return false;
730 if (block->Remove(blockindex)){
731 fN--;
732 return true;
733 }
734 } else {
736 if (fCurrent->Remove(entry)){
737 if (fLists)
738 fN--;
739 return true;
740 }
741 }
742 } else {
743 Int_t localentry = tree->LoadTree(entry);
744 SetTree(tree->GetTree());
745 if (fCurrent){
746 if (fCurrent->Remove(localentry)) {
747 if (fLists)
748 fN--;
749 return true;
750 }
751 }
752 }
753 return false;
754}
755
756////////////////////////////////////////////////////////////////////////////////
757/// Return the number of the entry \#index of this TEntryList in the TTree or TChain
758/// See also Next().
759
761{
762
763 if ((index>=fN) || (index<0)) {
764 return -1;
765 }
766 if (index==fLastIndexQueried+1){
767 //in a loop
768 return Next();
769 } else {
770 if (fBlocks) {
771 TEntryListBlock *block = nullptr;
773 Int_t i=0;
774 while (total_passed<=index && i<fNBlocks){
776 total_passed+=block->GetNPassed();
777 i++;
778 }
779 i--;
780 total_passed-=block->GetNPassed();
783 block->ResetIndices();
785 }
786
788 Long64_t blockindex = block->GetEntry(localindex);
789 if (blockindex < 0) return -1;
792 fLastIndexReturned = res;
793 return res;
794 } else {
795 //find the corresponding list
797 TIter next(fLists);
799 Long64_t ntotal = 0;
800 if (fCurrent){
801 //reset all indices of the current list
802 if (fCurrent->fBlocks){
805 block->ResetIndices();
808 }
809 }
810 while ((templist = (TEntryList*)next())){
811 if (!fShift){
812 ntotal += templist->GetN();
813 } else {
814 if (templist->GetTreeNumber() >= 0)
815 ntotal += templist->GetN();
816 }
817 if (ntotal > index)
818 break;
819 }
821 if (!fCurrent) return -1;
825 return fLastIndexReturned;
826 }
827
828 }
829 return -1;
830}
831
832////////////////////////////////////////////////////////////////////////////////
833/// Return the index of "index"-th non-zero entry in the TTree or TChain
834/// and the # of the corresponding tree in the chain
835
837{
838//If shift is true, then when the requested entry is found in an entry list,
839//for which there is no corresponding tree in the chain, this list is not
840//taken into account, and entry from the next list with a tree is returned.
841//Example:
842//First sublist - 20 entries, second sublist - 5 entries, third sublist - 10 entries
843//Second sublist doesn't correspond to any trees of the chain
844//Then, when GetEntryAndTree(21, treenum, true) is called, first entry of the
845//third sublist will be returned
846
848 if (result < 0) {
849 treenum = -1;
850 return result;
851 }
852 R__ASSERT(fLists == nullptr || (fLists != nullptr && fCurrent != nullptr));
853 if (fCurrent)
855 else
857 if (treenum < 0)
858 return -1;
859
860 return result;
861}
862
863////////////////////////////////////////////////////////////////////////////////
864/// To be able to re-localize the entry-list we identify the file by just the
865/// name and the anchor, i.e. we drop protocol, host, options, ...
866/// The result in the form 'file#anchor' (or 'file', if no anchor is present)
867/// is saved in 'fn'.
868/// The function optionally (is 'local' is defined) checks file locality (i.e.
869/// protocol 'file://') returning the result in '*local' .
870
871void TEntryList::GetFileName(const char *filename, TString &fn, bool *local)
872{
873 TUrl u(filename, true);
874 if (local) *local = (!strcmp(u.GetProtocol(), "file")) ? true : false;
875 if (strlen(u.GetAnchor()) > 0) {
876 fn.Form("%s#%s", u.GetFile(), u.GetAnchor());
877 } else {
878 fn = u.GetFile();
879 }
880 // Done
881 return;
882}
883
884////////////////////////////////////////////////////////////////////////////////
885/// Return the entry list, corresponding to treename and filename
886/// By default, the filename is first tried as is, and then, if the corresponding list
887/// is not found, the filename is expanded to the absolute path, and compared again.
888/// To avoid it, use option "ne"
889
890TEntryList *TEntryList::GetEntryList(const char *treename, const char *filename, Option_t *opt)
891{
892 if (gDebug > 1)
893 Info("GetEntryList","tree: %s, file: %s",
894 (treename ? treename : "-"), (filename ? filename : "-"));
895
896 if (!treename || !filename) return nullptr;
897 TString option = opt;
898 option.ToUpper();
899 bool nexp = option.Contains("NE");
900
901 TString fn;
902 bool local;
904 if (nexp) local = false;
905
906 if (gDebug > 1)
907 Info("GetEntryList", "file: %s, local? %d", filename, local);
908
909 if (!fLists){
910 //there are no sublists
911 if (!strcmp(treename, fTreeName.Data()) && !(strcmp(fn.Data(), fFileName.Data()))){
912 return this;
913 } else {
914 //if the file is local, try the full name, unless "ne" option was specified
915 if (!nexp && local){
920 if (!strcmp(treename, fTreeName.Data()) && !(strcmp(fn.Data(), fFileName.Data())))
921 return this;
922 }
923 return nullptr;
924 }
925 }
926
928 stotal.Append(fn);
929 ULong_t newhash = stotal.Hash();
930
931 TIter next(fLists);
933 while ((templist = (TEntryList*)next())){
934 if (templist->fStringHash==0){
935 stotal = templist->fTreeName + templist->fFileName;
936 templist->fStringHash = stotal.Hash();
937 }
938 if (gDebug > 1)
939 Info("GetEntryList", "file: %s (fn: %s), hash: %lu, element hash: %lu",
940 filename, fn.Data(), newhash, templist->fStringHash);
941 if (newhash == templist->fStringHash){
942 if (!strcmp(templist->GetTreeName(), treename) && !strcmp(templist->GetFileName(), fn.Data())){
943 return templist;
944 }
945 }
946 }
947
948 //didn't find anything for this filename, try the full name too
949 if (!nexp && local){
956 stotal.Append(longname);
957 newhash = stotal.Hash();
958 next.Reset();
959 while ((templist = (TEntryList*)next())){
960 if (templist->fStringHash==0){
961 stotal = templist->fTreeName + templist->fFileName;
962 templist->fStringHash = stotal.Hash();
963 }
964 if (gDebug > 1)
965 Info("GetEntryList", "file: %s (longname: %s), hash: %lu, element hash: %lu",
966 filename, longname.Data(), newhash, templist->fStringHash);
967 if (newhash == templist->fStringHash){
968 if (templist->fTreeName == treename && templist->fFileName == longname){
969 return templist;
970 }
971 }
972 }
973 }
974 return nullptr;
975}
976
977////////////////////////////////////////////////////////////////////////////////
978/// Merge this list with the lists from the collection
979
981{
982 if (!list) return -1;
983 TIter next(list);
984 TEntryList *elist = nullptr;
985 while ((elist = (TEntryList*)next())) {
986 if (!elist->InheritsFrom(TEntryList::Class())) {
987 Error("Add","Attempt to add object of class: %s to a %s",elist->ClassName(),this->ClassName());
988 return -1;
989 }
990 Add(elist);
991 }
992 return 0;
993}
994
995////////////////////////////////////////////////////////////////////////////////
996/// Return the next non-zero entry index (next after fLastIndexQueried)
997/// this function is faster than GetEntry()
998
1000{
1002 if (fN == fLastIndexQueried+1 || fN==0){
1003 return -1;
1004 }
1005 if (fBlocks){
1008 result = current_block->Next();
1009 if (result>=0) {
1012 return fLastIndexReturned;
1013 }
1014 else {
1015 while (result<0 && iblock<fNBlocks-1) {
1016 current_block->ResetIndices();
1017 iblock++;
1019 current_block->ResetIndices();
1020 result = current_block->Next();
1021 }
1022 if (result<0) {
1023 fLastIndexQueried = -1;
1025 return -1;
1026 }
1029
1030 return fLastIndexReturned;
1031 }
1032 } else {
1033 if (!fCurrent) {
1035 if (!fCurrent) return 0;
1036 if (fShift) {
1037 while (fCurrent->GetTreeNumber()<0) {
1039 if (!fCurrent) return 0;
1040 }
1041 }
1042 }
1043 result = fCurrent->Next();
1044 if (result>=0) {
1047 return result;
1048 } else {
1049 if (fCurrent){
1050 //reset all indices of the current list
1051 if (fCurrent->fBlocks){
1054 block->ResetIndices();
1057 }
1058 }
1059
1060 //find the list with the next non-zero entry
1061 while (result<0 && fCurrent!=((TEntryList*)fLists->Last())){
1062 if (!fCurrent) return 0;
1066 // fCurrent is guarantee to be non-zero because it is not the 'last'
1067 // element of the list.
1068 if (!fCurrent) return 0;
1069 if (!fShift)
1070 result = fCurrent->Next();
1071 else {
1072 if (fCurrent->GetTreeNumber() >= 0)
1073 result = fCurrent->Next();
1074 }
1075 }
1078 return result;
1079 }
1080 }
1081}
1082
1083////////////////////////////////////////////////////////////////////////////////
1084/// Checks if the array representation is more economical and if so, switches to it
1085
1087{
1088 if (fBlocks){
1089 TEntryListBlock *block = nullptr;
1090 for (Int_t i=0; i<fNBlocks; i++){
1092 block->OptimizeStorage();
1093 }
1094 }
1095}
1096
1097////////////////////////////////////////////////////////////////////////////////
1098/// Print this list
1099/// - option = "" - default - print the name of the tree and file
1100/// - option = "all" - print all the entry numbers
1101
1102void TEntryList::Print(const Option_t* option) const
1103{
1104 TString opt = option;
1105 opt.ToUpper();
1106 if (fBlocks) {
1107 Printf("%s %s %lld", fTreeName.Data(), fFileName.Data(), fN);
1108 if (opt.Contains("A")){
1109 TEntryListBlock* block = nullptr;
1110 for (Int_t i=0; i<fNBlocks; i++){
1112 Int_t shift = i*kBlockSize;
1113 block->PrintWithShift(shift);
1114 }
1115 }
1116 }
1117 else {
1118 TEntryList *elist = nullptr;
1119 if (fN>0){
1120 TIter next(fLists);
1121 while((elist = (TEntryList*)next())){
1122 elist->Print(option);
1123 }
1124 } else {
1125 if (!fLists) Printf("%s %s %lld", fTreeName.Data(), fFileName.Data(), fN);
1126 else {
1127 TIter next(fLists);
1128 while ((elist = (TEntryList*)next())){
1129 Printf("%s %s %lld", elist->GetTreeName(), elist->GetFileName(), elist->GetN());
1130 }
1131 }
1132 }
1133 }
1134}
1135
1136////////////////////////////////////////////////////////////////////////////////
1137/// Reset this list
1138
1139void TEntryList::Reset()
1140{
1141 //Maybe not delete, but just reset the number of blocks to 0????
1142
1143 if (fBlocks){
1144 fBlocks->Delete();
1145 delete fBlocks;
1146 fBlocks = nullptr;
1147 }
1148 if (fLists){
1149 if (!((TEntryList*)fLists->First())->GetDirectory()){
1150 fLists->Delete();
1151 }
1152 delete fLists;
1153 fLists = nullptr;
1154 }
1155 fCurrent = nullptr;
1156 fBlocks = nullptr;
1157 fNBlocks = 0;
1158 fN = 0;
1159 fTreeName = "";
1160 fFileName = "";
1161 fStringHash = 0;
1162 fTreeNumber = -1;
1163 fLastIndexQueried = -1;
1165 fReapply = false;
1166}
1167
1168////////////////////////////////////////////////////////////////////////////////
1169/// Add reference to directory dir. dir can be 0.
1170
1172{
1173 if (fDirectory == dir) return;
1174 if (fDirectory) fDirectory->Remove(this);
1175 fDirectory = dir;
1176 if (fDirectory) fDirectory->Append(this);
1177}
1178
1179////////////////////////////////////////////////////////////////////////////////
1180/// If a list for a tree with such name and filename exists, sets it as the current sublist
1181/// If not, creates this list and sets it as the current sublist
1182///
1183/// ! the filename is taken as provided, no extensions to full path or url !
1184
1185void TEntryList::SetTree(const char *treename, const char *filename)
1186{
1187 TEntryList *elist = nullptr;
1188
1189 TString fn;
1191
1193 stotal.Append(fn.Data());
1194 //printf("setting tree %s\n", stotal.Data());
1195 ULong_t newhash = stotal.Hash();
1196 if (fLists) {
1197 //find the corresponding entry list and make it current
1199 if (fCurrent->fStringHash == 0){
1201 fCurrent->fStringHash = stotal.Hash();
1202 }
1203 if (newhash == fCurrent->fStringHash){
1204 //this list is current
1206 return;
1207 }
1208 }
1209 TIter next(fLists);
1210 while ((elist = (TEntryList*)next())){
1211 if (newhash == elist->fStringHash){
1212 if (elist->fTreeName == treename && elist->fFileName == fn.Data()) {
1213 //the current entry list was changed. reset the fLastIndexQueried,
1214 //so that Next() doesn't start with the wrong current list
1215 //Also, reset those indices in the previously current list
1216 if (fCurrent->fBlocks){
1219 block->ResetIndices();
1222 }
1223 fCurrent = elist;
1224 fLastIndexQueried = -3;
1225 return;
1226 }
1227 }
1228 }
1229 //didn't find an entry list for this tree, create a new one
1230 elist = new TEntryList("", "", treename, fn.Data());
1231 if (elist->GetDirectory()) {
1232 //sub lists are not added to the current directory
1233 elist->GetDirectory()->Remove(elist);
1234 elist->SetDirectory(nullptr);
1235 }
1236 fLists->Add(elist);
1237 fCurrent = elist;
1238 return;
1239 } else {
1240 if (fN==0 && fTreeName=="" && fFileName==""){
1241 //this is the first tree set to this list
1243 fFileName = fn;
1245 //fStringHash = stotal.Hash();
1247 fCurrent = this;
1248 } else {
1249 if (fStringHash == 0){
1251 fStringHash = stotal.Hash();
1252 }
1253 if (newhash != fStringHash){
1254 //we have a chain and already have an entry list for the first tree
1255 //move the first entry list to the fLists
1256 fLists = new TList();
1257 elist = new TEntryList();
1258 elist->fTreeName = fTreeName;
1259 elist->fFileName = fFileName;
1260 elist->fStringHash = fStringHash;
1261 elist->fN = fN;
1262 elist->fTreeNumber = fTreeNumber;
1263 elist->fBlocks = fBlocks;
1264 fBlocks = nullptr;
1265 elist->fNBlocks = fNBlocks;
1266 fLists->Add(elist);
1267 elist = new TEntryList("", "", treename, fn.Data());
1268 if (elist->GetDirectory()) {
1269 //sub lists are not added to the current directory
1270 elist->GetDirectory()->Remove(elist);
1271 elist->SetDirectory(nullptr);
1272 }
1273 fLists->Add(elist);
1274 fCurrent = elist;
1275 //the current entry list was changed. reset the fLastIndexQueried,
1276 //so that Next() doesn't start with the wrong current list
1277 fLastIndexQueried = -3;
1278
1279 }
1280 else {
1281 //same tree as in the current entry list, don't do anything
1282 return;
1283 }
1284 }
1285 }
1286}
1287
1288////////////////////////////////////////////////////////////////////////////////
1289/// If a list for a tree with such name and filename exists, sets it as the current sublist
1290/// If not, creates this list and sets it as the current sublist
1291/// The name of the file, where the tree is, is taken as
1292/// `tree->GetTree()->GetCurrentFile()->GetName()`, and then expanded either to the absolute path,
1293/// or to full url. If, for some reason, you want to provide
1294/// the filename in a different format, use SetTree(const char *treename, const char *filename),
1295/// where the filename is taken "as is".
1296
1297void TEntryList::SetTree(const TTree *tree)
1298{
1299 if (!tree) return;
1300 auto thisTree = tree->GetTree();
1301 if (!thisTree) return;
1302
1304 if (tree->GetDirectory()->InheritsFrom("TFile")) {
1305 treename = thisTree->GetName();
1306 } else {
1307 treename = TString::Format("%s/%s",tree->GetDirectory()->GetName(),thisTree->GetName());
1308 }
1309
1311 if (tree->GetTree()->GetCurrentFile()){
1312 filename = tree->GetTree()->GetCurrentFile()->GetName();
1313 TUrl url(filename.Data(), true);
1314 if (!strcmp(url.GetProtocol(), "file")){
1319 url.SetFile(filename);
1320 }
1321 filename = url.GetUrl();
1322 } else {
1323 //memory-resident
1324 filename = "";
1325 }
1327
1328}
1329
1330////////////////////////////////////////////////////////////////////////////////
1331/// Remove all the entries of this entry list, that are contained in elist
1332
1333void TEntryList::Subtract(const TEntryList *elist)
1334{
1335 TEntryList *templist = nullptr;
1336 if (!fLists){
1337 if (!fBlocks) return;
1338 //check if lists are for the same tree
1339 if (!elist->fLists){
1340 //second list is also only for 1 tree
1341 if (!strcmp(elist->fTreeName.Data(),fTreeName.Data()) &&
1342 !strcmp(elist->fFileName.Data(),fFileName.Data())){
1343 //same tree
1344 Long64_t n2 = elist->GetN();
1346 for (Int_t i=0; i<n2; i++){
1347 entry = (const_cast<TEntryList*>(elist))->GetEntry(i);
1348 Remove(entry);
1349 }
1350 } else {
1351 //different trees
1352 return;
1353 }
1354 } else {
1355 //second list has sublists, try to find one for the same tree as this list
1356 TIter next1(elist->GetLists());
1357 templist = nullptr;
1358 bool found = false;
1359 while ((templist = (TEntryList*)next1())){
1360 if (!strcmp(templist->fTreeName.Data(),fTreeName.Data()) &&
1361 !strcmp(templist->fFileName.Data(),fFileName.Data())){
1362 found = true;
1363 break;
1364 }
1365 }
1366 if (found) {
1368 }
1369 }
1370 } else {
1371 //this list has sublists
1373 templist = nullptr;
1374 Long64_t oldn=0;
1375 while ((templist = (TEntryList*)next2())){
1376 oldn = templist->GetN();
1377 templist->Subtract(elist);
1378 fN = fN - oldn + templist->GetN();
1379 }
1380 }
1381 return;
1382}
1383
1384////////////////////////////////////////////////////////////////////////////////
1385
1387{
1389 //eresult = elist1;
1390 // printf("internal in operator1\n");
1391 eresult.Print("all");
1392 eresult.Add(&elist2);
1393 // printf("internal in operator2\n");
1394 eresult.Print("all");
1395
1396 return eresult;
1397}
1398
1399////////////////////////////////////////////////////////////////////////////////
1400/// Relocate the file paths.
1401/// If `oldroot` is defined, replace `oldroot` with `newroot` in all file names,
1402/// i.e. `oldroot/re/st/of/the/path` will become `newroot`/re/st/of/the/path`.
1403/// If `oldroot` is null, the new path will be just `newroot/path`.
1404/// Relocation is mandatory to use the entry-list with the same dataset at a different
1405/// location (i.e. on a different cluster, machine or disks).
1406
1407Int_t TEntryList::RelocatePaths(const char *newroot, const char *oldroot)
1408{
1409 // At least newroot must be given
1410 if (!newroot || (newroot && strlen(newroot) <= 0)) {
1411 Warning("RelocatePaths", "the new location must be given!");
1412 return -1;
1413 }
1414
1415 if (strlen(GetName()) > 0)
1416 Info("RelocatePaths", "'%s': relocating paths '%s' to '%s'",
1417 GetName(), oldroot ? oldroot : "*", newroot);
1418
1419 Int_t nrl = 0, xnrl = 0;
1420 // Apply to all underlying lists, if any
1421 if (fLists) {
1422 TIter nxl(fLists);
1423 TEntryList *enl = nullptr;
1424 while ((enl = (TEntryList *) nxl())) {
1425 if ((xnrl = enl->RelocatePaths(newroot, oldroot)) < 0) {
1426 Warning("RelocatePaths", "problems relocating '%s'", enl->GetName());
1427 } else {
1428 nrl += xnrl;
1429 }
1430 }
1431 }
1432 // Apply to ourselves
1433 TString temp;
1434 Ssiz_t lo = 0;
1435 if (oldroot && (lo = strlen(oldroot)) > 0) {
1437 fFileName.Replace(0, lo, newroot);
1438 nrl++;
1439 }
1440 } else {
1441 Ssiz_t ilst = fFileName.Last('/');
1442 if (ilst != kNPOS) {
1444 } else {
1446 }
1447 nrl++;
1448 }
1449 if (fStringHash != 0) {
1450 temp.Form("%s%s", fTreeName.Data(), fFileName.Data());
1451 fStringHash = temp.Hash();
1452 }
1453
1454 // Done
1455 return nrl;
1456}
1457
1458////////////////////////////////////////////////////////////////////////////////
1459/// Relocate entry list 'enlnm' in file 'fn' replacing 'oldroot' with 'newroot' in
1460/// filenames. If 'enlnm' is null or '*' all entry lists in the file are relocated.
1461/// Relocation is mandatory to use the entry-list with the same dataset at a different
1462/// location (i.e. on a different cluster, machine or disks).
1463/// This function can be called as many times as need to reach the desired result.
1464/// The existing 'locations' can be checked qith TEntryList::Scan .
1465
1466Int_t TEntryList::Relocate(const char *fn,
1467 const char *newroot, const char *oldroot, const char *enlnm)
1468{
1469 // Open the file for updating
1470 TFile *fl = TFile::Open(fn, "UPDATE");
1471 if (!fl || (fl&& fl->IsZombie())) {
1472 ::Error("TEntryList::Relocate", "file '%s' cannot be open for updating", fn);
1473 return -1;
1474 }
1475
1476 Int_t nrl = 0;
1477 // Read the lists
1478 TString nm(enlnm);
1479 if (nm.IsNull()) nm = "*";
1480 TRegexp nmrg(nm, true);
1481 TIter nxk(fl->GetListOfKeys());
1482 TKey *key = nullptr;
1483 while ((key = (TKey *) nxk())) {
1484 if (!strcmp(key->GetClassName(), "TEntryList")) {
1485 TString knm(key->GetName());
1486 if (knm.Index(nmrg) != kNPOS) {
1487 TEntryList *enl = dynamic_cast<TEntryList *>(fl->Get(knm));
1488 if (enl) {
1489 Int_t xnrl = enl->RelocatePaths(newroot, oldroot);
1490 if (xnrl >= 0) {
1491 enl->Write(knm, TObject::kOverwrite);
1492 nrl += xnrl;
1493 } else {
1494 ::Error("TEntryList::Relocate", "problems relocating '%s' ...", enl->GetName());
1495 }
1496 }
1497 }
1498 }
1499 }
1500 // Close the file
1501 fl->Close();
1502 delete fl;
1503 // Done
1504 return nrl;
1505}
1506
1507////////////////////////////////////////////////////////////////////////////////
1508/// Get in 'c' the string in common at the beginning of 'a' and 'b'
1509///
1510/// Return:
1511/// - 0 a and b are not contained in each other, i.e. c != a && c != b
1512/// - 1 a is contained in b, i.e. c == a (includes a == empty)
1513/// - 2 b is contained in a, i.e. c == b (includes b == empty)
1514/// - 3 b is a, i.e. c == b == a (includes a == b == empty)
1515/// Auxiliary function for path scans.
1516
1518{
1519 if (a == b) {
1520 c = a;
1521 return 3;
1522 }
1523 if (a.IsNull()) {
1524 c = "";
1525 return 1;
1526 }
1527 if (b.IsNull()) {
1528 c = "";
1529 return 2;
1530 }
1531 bool ashort = (a.Length() > b.Length()) ? false : true;
1532 Ssiz_t len = (ashort) ? a.Length() : b.Length();
1533 Int_t lcom = 0;
1534 for (Int_t i = 0; i < len; i++) {
1535 if (a[i] != b[i]) break;
1536 lcom++;
1537 }
1538 if (lcom == len) {
1539 c = ashort ? a : b;
1540 return ashort ? 1 : 2;
1541 }
1542 c = a(0,lcom);
1543 // Done
1544 return 0;
1545}
1546
1547////////////////////////////////////////////////////////////////////////////////
1548/// Scan the paths to find the common roots. If 'roots' is defined, add
1549/// the found roots to the list as TObjStrings.
1550/// Return the number of roots found.
1551
1553{
1554 TList *xrl = roots ? roots : new TList;
1555
1556 Int_t nrl = 0;
1557 // Apply to all underlying lists, if any
1558 if (fLists) {
1559 TIter nxl(fLists);
1560 TEntryList *enl = nullptr;
1561 while ((enl = (TEntryList *) nxl()))
1562 nrl += enl->ScanPaths(xrl, false);
1563 }
1564 // Apply to ourselves
1565 bool newobjs = true;
1567 TObjString *objs = nullptr;
1568 TIter nxr(xrl);
1569 while ((objs = (TObjString *) nxr())) {
1570 Int_t rc = 0;
1571 if ((rc = GetCommonString(path, objs->GetString(), com)) != 2) {
1572 TUrl ucom(com);
1573 if (strlen(ucom.GetFile()) > 0 && strcmp(ucom.GetFile(), "/")) {
1574 objs->SetString(com.Data());
1575 newobjs = false;
1576 break;
1577 }
1578 }
1579 }
1580 if (newobjs) xrl->Add(new TObjString(path));
1581
1582 // Done
1583 nrl = xrl->GetSize();
1584 if (notify) {
1585 Printf(" * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *");
1586 Printf(" * Entry-list: %s", GetName());
1587 Printf(" * %d common root paths found", nrl);
1588 nxr.Reset();
1589 while ((objs = (TObjString *) nxr())) {
1590 Printf(" * %s", objs->GetName());
1591 }
1592 Printf(" * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *");
1593 }
1594
1595 if (xrl != roots) {
1596 xrl->SetOwner(true);
1597 SafeDelete(xrl);
1598 }
1599
1600 // Done
1601 return nrl;
1602}
1603
1604////////////////////////////////////////////////////////////////////////////////
1605/// Scan TEntryList in 'fn' to find the common parts of paths.
1606/// If 'roots' is defined, add the found roots to the list as TObjStrings.
1607/// Return the number of common root paths found.
1608
1609Int_t TEntryList::Scan(const char *fn, TList *roots)
1610{
1611 // Open the file for updating
1612 TFile *fl = TFile::Open(fn);
1613 if (!fl || (fl&& fl->IsZombie())) {
1614 ::Error("TEntryList::Relocate", "file '%s' cannot be open for reading", fn);
1615 return -1;
1616 }
1617
1618 Int_t nrs = 0;
1619 // Read the lists
1620 TIter nxk(fl->GetListOfKeys());
1621 TKey *key = nullptr;
1622 while ((key = (TKey *) nxk())) {
1623 if (!strcmp(key->GetClassName(), "TEntryList")) {
1624 TEntryList *enl = dynamic_cast<TEntryList *>(fl->Get(key->GetName()));
1625 if (enl) {
1626 nrs += enl->ScanPaths(roots);
1627 } else {
1628 ::Error("TEntryList::Scan", "object entry-list '%s' not found or not loadable!", key->GetName());
1629 }
1630 }
1631 }
1632 // Close the file
1633 fl->Close();
1634 delete fl;
1635
1636 // Done
1637 return nrs;
1638}
1639
1640////////////////////////////////////////////////////////////////////////////////
1641/// Custom streamer for class TEntryList to handle the different interpretation
1642/// of fFileName between version 1 and >1 .
1643
1645{
1646 if (b.IsReading()) {
1647 UInt_t R__s, R__c;
1648 Version_t R__v = b.ReadVersion(&R__s, &R__c);
1649 b.ReadClassBuffer(TEntryList::Class(), this, R__v, R__s, R__c);
1650 if (R__v <= 1) {
1651 // The filename contained also the protocol and host: this was dropped
1652 // in version > 1 to allow re-localization
1654 }
1655 } else {
1656 b.WriteClassBuffer(TEntryList::Class(), this);
1657 }
1658}
#define SafeDelete(p)
Definition RConfig.hxx:533
#define b(i)
Definition RSha256.hxx:100
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
int Ssiz_t
String size (currently int)
Definition RtypesCore.h:81
unsigned long ULong_t
Unsigned long integer 4 bytes (unsigned long). Size depends on architecture.
Definition RtypesCore.h:69
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:131
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:83
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gDirectory
Definition TDirectory.h:385
static Int_t GetCommonString(TString a, TString b, TString &c)
Get in 'c' the string in common at the beginning of 'a' and 'b'.
TEntryList operator||(TEntryList &elist1, TEntryList &elist2)
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
char name[80]
Definition TGX11.cxx:110
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:627
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2509
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
Buffer base class used for serializing objects.
Definition TBuffer.h:43
Collection abstract base class.
Definition TCollection.h:65
Describe directory structure in memory.
Definition TDirectory.h:45
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
Used by TEntryList to store the entry numbers.
A List of entry numbers in a TTree or TChain.
Definition TEntryList.h:26
virtual bool Enter(Long64_t entry, TTree *tree=nullptr)
Add entry #entry to the list.
bool fReapply
If true, TTree::Draw will 'reapply' the original cut.
Definition TEntryList.h:49
Long64_t fLastIndexQueried
! used to optimize GetEntry() function from a loop
Definition TEntryList.h:44
virtual TEntryList * GetEntryList(const char *treename, const char *filename, Option_t *opt="")
Return the entry list, corresponding to treename and filename By default, the filename is first tried...
Long64_t fEntriesToProcess
used on proof to set the number of entries to process in a packet
Definition TEntryList.h:37
virtual Int_t GetTreeNumber() const
Definition TEntryList.h:81
static TClass * Class()
TString fFileName
name of the file, where the tree is
Definition TEntryList.h:39
virtual void OptimizeStorage()
Checks if the array representation is more economical and if so, switches to it.
virtual TList * GetLists() const
Definition TEntryList.h:76
virtual Int_t Contains(Long64_t entry, TTree *tree=nullptr)
Int_t fTreeNumber
! the index of the tree in the chain (used when the entry list is used as input (TTree::SetEntryList(...
Definition TEntryList.h:41
virtual Int_t ScanPaths(TList *roots, bool notify=true)
Scan the paths to find the common roots.
virtual bool Remove(Long64_t entry, TTree *tree=nullptr)
Remove entry #entry from the list.
virtual void SetTree(const TTree *tree)
If a list for a tree with such name and filename exists, sets it as the current sublist If not,...
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition TEntryList.h:48
virtual TDirectory * GetDirectory() const
Definition TEntryList.h:77
TObjArray * fBlocks
blocks with indices of passing events (TEntryListBlocks)
Definition TEntryList.h:35
virtual Long64_t GetEntryAndTree(Long64_t index, Int_t &treenum)
Return the index of "index"-th non-zero entry in the TTree or TChain and the # of the corresponding t...
virtual const char * GetFileName() const
Definition TEntryList.h:80
static Int_t Scan(const char *fn, TList *roots)
Scan TEntryList in 'fn' to find the common parts of paths.
virtual void DirectoryAutoAdd(TDirectory *)
Called by TKey and others to automatically add us to a directory when we are read from a file.
Long64_t fN
number of entries in the list
Definition TEntryList.h:36
Long64_t fLastIndexReturned
! used to optimize GetEntry() function from a loop
Definition TEntryList.h:45
virtual Long64_t Next()
Return the next non-zero entry index (next after fLastIndexQueried) this function is faster than GetE...
virtual void SetDirectory(TDirectory *dir)
Add reference to directory dir. dir can be 0.
void EnterRange(Long64_t start, Long64_t end, TTree *tree=nullptr, UInt_t step=1U)
Enter all entries in a range in the TEntryList.
virtual void Reset()
Reset this list.
Int_t fNBlocks
number of TEntryListBlocks
Definition TEntryList.h:34
virtual Long64_t GetEntry(Long64_t index)
Return the number of the entry #index of this TEntryList in the TTree or TChain See also Next().
void Streamer(TBuffer &) override
Custom streamer for class TEntryList to handle the different interpretation of fFileName between vers...
virtual Int_t RelocatePaths(const char *newloc, const char *oldloc=nullptr)
Relocate the file paths.
virtual const char * GetTreeName() const
Definition TEntryList.h:79
virtual Int_t Merge(TCollection *list)
Merge this list with the lists from the collection.
TEntryList * fCurrent
! currently filled entry list
Definition TEntryList.h:32
bool fShift
! true when some sub-lists don't correspond to trees (when the entry list is used as input in TChain)
Definition TEntryList.h:46
void Print(const Option_t *option="") const override
Print this list.
ULong_t fStringHash
! Hash value of a string of treename and filename
Definition TEntryList.h:40
static Int_t Relocate(const char *fn, const char *newroot, const char *oldroot=nullptr, const char *enlnm=nullptr)
Relocate entry list 'enlnm' in file 'fn' replacing 'oldroot' with 'newroot' in filenames.
TList * fLists
a list of underlying entry lists for each tree of a chain
Definition TEntryList.h:31
void GetFileName(const char *filename, TString &fn, bool *=nullptr)
To be able to re-localize the entry-list we identify the file by just the name and the anchor,...
~TEntryList() override
Destructor.
TString fTreeName
name of the tree
Definition TEntryList.h:38
void AddSubList(TEntryList *elist)
Add a sub entry list to the current list.
TEntryList()
default c-tor
virtual void Subtract(const TEntryList *elist)
Remove all the entries of this entry list, that are contained in elist.
virtual void Add(const TEntryList *elist)
Add 2 entry lists.
virtual Long64_t GetN() const
Definition TEntryList.h:78
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:131
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:3764
void Reset()
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
virtual const char * GetClassName() const
Definition TKey.h:75
A doubly linked list.
Definition TList.h:38
TObject * After(const TObject *obj) const override
Returns the object after object obj.
Definition TList.cxx:327
void Add(TObject *obj) override
Definition TList.h:81
TObject * Last() const override
Return the last object in the list. Returns 0 when list is empty.
Definition TList.cxx:690
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:656
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:467
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
An array of TObjects.
Definition TObjArray.h:31
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * UncheckedAt(Int_t i) const
Definition TObjArray.h:84
void Add(TObject *obj) override
Definition TObjArray.h:68
Collectable string class.
Definition TObjString.h:28
@ kOverwrite
overwrite existing object with same name
Definition TObject.h:98
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:543
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1045
Regular expression class.
Definition TRegexp.h:31
Basic string class.
Definition TString.h:138
TString & Insert(Ssiz_t pos, const char *s)
Definition TString.h:669
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition TString.h:702
const char * Data() const
Definition TString.h:384
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition TString.cxx:938
void ToUpper()
Change string to upper case.
Definition TString.cxx:1202
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:631
Bool_t IsNull() const
Definition TString.h:422
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition TString.cxx:684
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2384
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2362
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:640
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1285
const char * pwd()
Definition TSystem.h:434
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition TSystem.cxx:1092
virtual const char * UnixPathName(const char *unixpathname)
Convert from a local pathname to a Unix pathname.
Definition TSystem.cxx:1073
virtual Bool_t IsAbsoluteFileName(const char *dir)
Return true if dir is an absolute pathname.
Definition TSystem.cxx:961
virtual TString GetDirName(const char *pathname)
Return the directory name in pathname.
Definition TSystem.cxx:1042
A TTree represents a columnar dataset.
Definition TTree.h:89
This class represents a WWW compatible URL.
Definition TUrl.h:33
TCanvas * roots()
Definition roots.C:1