Logo ROOT   6.16/01
Reference Guide
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
17There are two types of entry lists:
18
19#### 1.
20 for a TTree (fBlocks data member is non-zero)
21 Entry numbers are stored in TEntryListBlocks, which, in their turn, are stored
22 in the TObjArray fBlocks. The range of the entry numbers is cut into intervals
23 of kBlockSize entries (currently 64000), so that the first block contains
24 information which entries out of the first 64000 pass the selection, the second
25 block - which entries out of the 64000-127999 interval pass the selection, etc.
26 Some blocks, obviously, might be empty. The internal representation of entry
27 numbers in the blocks is described in the TEntryListBlock class description, and
28 this representation might be changed by calling OptimizeStorage() function
29 (when the list is filled via the Enter() function, this is done automatically,
30 except for the last block).
31 Individual entry lists can be merged (functions Merge() and Add())
32 to make an entry list for a TChain of corresponding TTrees.
33Begin_Macro
34entrylist_figure1.C
35End_Macro
36
37#### 2.
38 for a TChain (fLists data member is non-zero)
39 It contains a TList of sub-lists (TEntryList objects, corresponding to each TTree)
40 Trees and lists are matched by the TTree name and its file name (full path).
41 All sub-lists are returned by the GetLists() function and individual lists are
42 returned by GetEntryList() function. Such lists are no different from the lists for
43 TTrees, described above.
44Begin_Macro
45entrylist_figure2.C
46End_Macro
47
48## Operations on entry lists
49
50- __Add__() - if the lists are for the same tree, adds all the entries of the second list
51 to the first list. If the lists are for different trees, creates a TEntryList
52 with 2 sublists for each TTree. If the lists are for TChains, merges the ones
53 for the same trees and adds new sublists for the TTrees that were not included
54 in the first TEntryList
55- __Subtract__() - if the lists are for the same TTree, removes the entries of the second
56 list from the first list. If the lists are for TChains, loops over all
57 sub-lists
58- __GetEntry(n)__ - returns the n-th entry number
59- __Next__() - returns next entry number. Note, that this function is
60 much faster than GetEntry, and it's called when GetEntry() is called
61 for 2 or more indices in a row.
62
63## TTree::Draw() and TChain::Draw()
64
65Use option __entrylist__ to write the results of TTree::Draw and TChain::Draw into
66an entry list. Example:
67~~~ {.cpp}
68 tree->Draw(">>elist", "x<0 && y>0", "entrylist");
69 TEntryList *elist = (TEntryList*)gDirectory->Get("elist");
70~~~
71## Example of Loop on TEntryList with a TChain
72~~~ {.cpp}
73 void loopChain() {
74 TFile *fe = TFile::Open("myelist.root");
75 TEntryList *myelist = (TEntryList*)fe->Get("myelist");
76 TChain *chain = new TChain("ntuple");
77 chain->Add("hsimple.root");
78 chain->Add("hsimple2.root");
79 Long64_t listEntries = myelist->GetN();
80 Long64_t chainEntries = chain->GetEntries();
81 Int_t treenum = 0;
82 chain->SetEntryList(myelist);
83
84 for (entry=start;entry < end;entry++) {
85 entryNumber = chain->GetEntryNumber(entry);
86 if (entryNumber < 0) break;
87 localEntry = chain->LoadTree(entryNumber);
88 if (localEntry < 0) break;
89 ....
90 then either call
91 branch->GetEntry(localEntry);
92 or
93 chain->GetEntry(entryNumber);
94 In the later case the LoadTree is then somewhat redudant.
95 ...
96 }
97 }
98~~~
99When using the TEntryList interface directly, you can get the 'tree number' and entry in
100the current tree (i.e. value similar to the return value of LoadTree) from calling
101TEntryList::GetEntryAndTree:
102~~~ {.cpp}
103 Long64_t treeEntry = myelist->GetEntryAndTree(el,treenum);
104~~~
105to obtain the entry number within the chain you need to add to it the value of
106`treeEntry+ch->GetTreeOffset()[treenum]`
107such that the loop in the previous example can also be written as:
108~~~ {.cpp}
109 for (Long64_t el = 0; el < listEntries; el++) {
110 Long64_t treeEntry = myelist->GetEntryAndTree(el,treenum);
111 Long64_t chainEntry = treeEntry+ch->GetTreeOffset()[treenum];
112 printf("el=%lld, treeEntry=%lld, chainEntry=%lld, treenum=%d\n", el, treeEntry, chainEntry, treenum);
113
114 ch->LoadTree(chainEntry); // this also returns treeEntry
115 needed_branch->GetEntry(treeEntry);
116 }
117~~~
118## TSelectors
119
120To fill an TEntryList from a TSelector correctly, one must add the TEntryList object
121to the output list of the selector (TSelector::fOutput). This is the only way to
122make the sub-lists of the TEntryList switch when the current tree of the TChain is
123changed.
124
125## Using a TEntryList as input (TTree::SetEntryList() and TChain::SetEntryList())
126
127while the TTree::SetEntryList() function is only setting the TTree::fEntryList
128data member, the same function in TChain also finds correspondance between
129the TTrees of this TChain and the sub-lists of this TEntryList.
130
131## TEntryList and the current directory
132
133TEntryList objects are automatically added to the current directory (like TTrees).
134However, in case of a TEntryList for a chain, only the top-level entry list is added,
135not the sub-lists for specific trees. Placing entry lists in the current directory
136allows calling them as a part of a TTreeFormula expression, so if the user wants
137to extract a sublist from a TChain entry list via the GetEntryList() or some other
138function, they have to add it to the current directory to be able to use it in
139TTreeFormula expressions.
140
141## TEntryList and TEventList
142
143TTree::SetEventList() and TChain::SetEventList() transform a TEventList into a TEntryList
144See comments to those functions for more details
145*/
146
147#include "TEntryList.h"
148#include "TEntryListBlock.h"
149#include "TError.h"
150#include "TKey.h"
151#include "TTree.h"
152#include "TFile.h"
153#include "TRegexp.h"
154#include "TSystem.h"
155
157
158////////////////////////////////////////////////////////////////////////////////
159/// default c-tor
160
161TEntryList::TEntryList() : fEntriesToProcess(0)
162{
163 fLists = 0;
164 fCurrent = 0;
165 fBlocks = 0;
166 fN = 0;
167 fNBlocks = 0;
168 fTreeName = "";
169 fFileName = "";
170 fStringHash = 0;
171 fTreeNumber = -1;
172 fDirectory = 0;
176 fShift = kFALSE;
177}
178
179////////////////////////////////////////////////////////////////////////////////
180/// c-tor with name and title
181
182TEntryList::TEntryList(const char *name, const char *title) :
183 TNamed(name, title),
184 fEntriesToProcess(0)
185{
186 fLists = 0;
187 fCurrent = 0;
188 fBlocks = 0;
189 fN = 0;
190 fNBlocks = 0;
191 fTreeName = "";
192 fFileName = "";
193 fStringHash = 0;
194 fTreeNumber = -1;
196
198 if (fDirectory) fDirectory->Append(this);
199
202 fShift = kFALSE;
203}
204
205////////////////////////////////////////////////////////////////////////////////
206/// constructor with name and title, which also sets the tree
207
208TEntryList::TEntryList(const char *name, const char *title, const TTree *tree):TNamed(name, title)
209{
210 fLists = 0;
211 fCurrent = 0;
212 fBlocks = 0;
213 fN = 0;
214 fNBlocks = 0;
215 fTreeNumber = -1;
218
220 if (fDirectory) fDirectory->Append(this);
221
224 fShift = kFALSE;
225}
226
227////////////////////////////////////////////////////////////////////////////////
228/// c-tor with name and title, which also sets the treename and the filename
229
230TEntryList::TEntryList(const char *name, const char *title, const char *treename, const char *filename) : TNamed(name, title),fEntriesToProcess(0)
231{
232 fLists = 0;
233 fCurrent = 0;
234 fBlocks = 0;
235 fNBlocks = 0;
236 fN = 0;
237 SetTree(treename, filename);
238 fTreeNumber = -1;
240
242 if (fDirectory) fDirectory->Append(this);
243
246 fShift = kFALSE;
247}
248
249////////////////////////////////////////////////////////////////////////////////
250/// c-tor, which sets the tree
251
252TEntryList::TEntryList(const TTree *tree) : fEntriesToProcess(0)
253{
254 fLists = 0;
255 fCurrent = 0;
256 fBlocks = 0;
257 fNBlocks = 0;
258 fN = 0;
259
260 SetTree(tree);
261 fTreeNumber = -1;
262
265 if (fDirectory) fDirectory->Append(this);
266
269 fShift = kFALSE;
270}
271
272////////////////////////////////////////////////////////////////////////////////
273/// copy c-tor
274
275TEntryList::TEntryList(const TEntryList &elist) : TNamed(elist)
276{
277 fNBlocks = elist.fNBlocks;
278 fTreeName = elist.fTreeName;
279 fFileName = elist.fFileName;
280 fStringHash = elist.fStringHash;
281 fTreeNumber = elist.fTreeNumber;
284 fN = elist.fN;
285 fShift = elist.fShift;
286 fLists = 0;
287 fBlocks = 0;
288 fReapply = elist.fReapply;
289 fCurrent = 0;
291 if (elist.fLists){
292 fLists = new TList();
293 TEntryList *el1 = 0;
294 TEntryList *el2 = 0;
295 TIter next(elist.fLists);
296 while((el1 = (TEntryList*)next())){
297 el2 = new TEntryList(*el1);
298 if (el1==elist.fCurrent)
299 fCurrent = el2;
300 fLists->Add(el2);
301 }
302 } else {
303 if (elist.fBlocks){
304 TEntryListBlock *block1 = 0;
305 TEntryListBlock *block2 = 0;
306 //or just copy it as a TObjArray??
307 fBlocks = new TObjArray();
308 for (Int_t i=0; i<fNBlocks; i++){
309 block1 = (TEntryListBlock*)elist.fBlocks->UncheckedAt(i);
310 block2 = new TEntryListBlock(*block1);
311 fBlocks->Add(block2);
312 }
313 }
314 fCurrent = this;
315 }
316 fDirectory = 0;
317
318}
319
320////////////////////////////////////////////////////////////////////////////////
321/// Destructor.
322
324{
325 if (fBlocks){
326 fBlocks->Delete();
327 delete fBlocks;
328 }
329 fBlocks = 0;
330 if (fLists){
331 fLists->Delete();
332 delete fLists;
333 }
334
335 fLists = 0;
336
337 if (fDirectory) fDirectory->Remove(this);
338 fDirectory = 0;
339
340}
341
342////////////////////////////////////////////////////////////////////////////////
343/// Add 2 entry lists
344
345void TEntryList::Add(const TEntryList *elist)
346{
347 if (fN==0){
348 if (!fLists && fTreeName=="" && fFileName==""){
349 //this list is empty. copy the other list completely
350 fNBlocks = elist->fNBlocks;
351 fTreeName = elist->fTreeName;
352 fFileName = elist->fFileName;
353 fStringHash = elist->fStringHash;
354 fTreeNumber = elist->fTreeNumber;
357 fN = elist->fN;
358 if (elist->fLists){
359 fLists = new TList();
360 TEntryList *el1 = 0;
361 TEntryList *el2 = 0;
362 TIter next(elist->fLists);
363 while((el1 = (TEntryList*)next())){
364 el2 = new TEntryList(*el1);
365 if (el1==elist->fCurrent)
366 fCurrent = el2;
367 fLists->Add(el2);
368 }
369 } else {
370 if (elist->fBlocks){
371 TEntryListBlock *block1 = 0;
372 TEntryListBlock *block2 = 0;
373 fBlocks = new TObjArray();
374 for (Int_t i=0; i<fNBlocks; i++){
375 block1 = (TEntryListBlock*)elist->fBlocks->UncheckedAt(i);
376 block2 = new TEntryListBlock(*block1);
377 fBlocks->Add(block2);
378 }
379 }
380 fCurrent = 0;
381 }
382 return;
383 }
384 }
385
386 if (!fLists){
387 if (!elist->fLists){
388 if (!strcmp(elist->fTreeName.Data(),fTreeName.Data()) && !strcmp(elist->fFileName.Data(),fFileName.Data())){
389 //entry lists are for the same tree
390 if (!elist->fBlocks)
391 //the other list is empty list
392 return;
393 if (!fBlocks){
394 //this entry list is empty
395 TEntryListBlock *block1 = 0;
396 TEntryListBlock *block2 = 0;
397 fNBlocks = elist->fNBlocks;
398 fN = elist->fN;
399 fBlocks = new TObjArray();
400 for (Int_t i=0; i<fNBlocks; i++){
401 block1 = (TEntryListBlock*)elist->fBlocks->UncheckedAt(i);
402 block2 = new TEntryListBlock(*block1);
403 fBlocks->Add(block2);
404 }
405 return;
406 }
407 //both not empty, merge block by block
408 TEntryListBlock *block1=0;
409 TEntryListBlock *block2=0;
410 Int_t i;
411 Int_t nmin = TMath::Min(fNBlocks, elist->fNBlocks);
412 Long64_t nnew, nold;
413 for (i=0; i<nmin; i++){
414 block1 = (TEntryListBlock*)fBlocks->UncheckedAt(i);
415 block2 = (TEntryListBlock*)elist->fBlocks->UncheckedAt(i);
416 nold = block1->GetNPassed();
417 nnew = block1->Merge(block2);
418 fN = fN - nold + nnew;
419 }
420 if (fNBlocks<elist->fNBlocks){
421 Int_t nmax = elist->fNBlocks;
422 for (i=nmin; i<nmax; i++){
423 block2 = (TEntryListBlock*)elist->fBlocks->UncheckedAt(i);
424 block1 = new TEntryListBlock(*block2);
425 fBlocks->Add(block1);
426 fN+=block1->GetNPassed();
427 fNBlocks++;
428 }
429 }
432 } else {
433 //entry lists are for different trees. create a chain entry list with
434 //2 sub lists for the first and second entry lists
437 fLists = new TList();
438 TEntryList *el = new TEntryList();
439 el->fTreeName = fTreeName;
440 el->fFileName = fFileName;
441 el->fBlocks = fBlocks;
442 fBlocks = 0;
443 el->fNBlocks = fNBlocks;
444 el->fN = fN;
445 el->fLastIndexQueried = -1;
446 el->fLastIndexReturned = 0;
447 fLists->Add(el);
448 el = new TEntryList(*elist);
449 el->fLastIndexQueried = -1;
450 el->fLastIndexReturned = 0;
451 fLists->Add(el);
452 fN+=el->GetN();
453 fCurrent = 0;
454 }
455 } else {
456 //second list already has sublists. add one by one
457 TEntryList *el = 0;
458 TIter next(elist->fLists);
459 while ((el = (TEntryList*)next())){
460 Add(el);
461 }
462 fCurrent = 0;
463 }
464 } else {
465 //there are already some sublists in this list, just add another one
466 if (!elist->fLists){
467 //the other list doesn't have sublists
468 TIter next(fLists);
469 TEntryList *el = 0;
470 Bool_t found = kFALSE;
471 while ((el = (TEntryList*)next())){
472 if (!strcmp(el->fTreeName.Data(), elist->fTreeName.Data()) &&
473 !strcmp(el->fFileName.Data(), elist->fFileName.Data())){
474 // if (el->fStringHash == elist->fStringHash){
475 //found a list for the same tree
476 Long64_t oldn = el->GetN();
477 el->Add(elist);
478 found = kTRUE;
479 fN = fN - oldn + el->GetN();
480 break;
481 }
482 }
483 if (!found){
484 el = new TEntryList(*elist);
485 el->fLastIndexQueried = -1;
486 el->fLastIndexReturned = 0;
487 fLists->Add(el);
488 fN+=el->GetN();
489 }
490 } else {
491 //add all sublists from the other list
492 TEntryList *el = 0;
493 TIter next(elist->fLists);
494 while ((el = (TEntryList*)next())){
495 Add(el);
496 }
497 fCurrent = 0;
498 }
499 if (fCurrent){
500 if (fCurrent->fBlocks){
503 block->ResetIndices();
506 }
507 }
508 fCurrent = 0;
509 }
510
511}
512
513////////////////////////////////////////////////////////////////////////////////
514/// - When tree = 0, returns from the current list
515/// - When tree != 0, finds the list, corresponding to this tree
516/// - When tree is a chain, the entry is assumed to be global index and the local
517/// entry is recomputed from the treeoffset information of the chain
518
520{
521 if (!tree){
522 if (fBlocks) {
523 //this entry list doesn't contain any sub-lists
524 TEntryListBlock *block = 0;
525 Int_t nblock = entry/kBlockSize;
526 if (nblock >= fNBlocks) return 0;
527 block = (TEntryListBlock*)fBlocks->UncheckedAt(nblock);
528 return block->Contains(entry-nblock*kBlockSize);
529 }
530 if (fLists) {
532 return fCurrent->Contains(entry);
533 }
534 return 0;
535 } else {
536 Long64_t localEntry = tree->LoadTree(entry);
537 SetTree(tree->GetTree());
538 if (fCurrent)
539 return fCurrent->Contains(localEntry);
540 }
541 return 0;
542
543}
544
545////////////////////////////////////////////////////////////////////////////////
546/// Called by TKey and others to automatically add us to a directory when we are read from a file.
547
549{
550 SetDirectory(dir);
551}
552
553////////////////////////////////////////////////////////////////////////////////
554/// Add entry \#entry to the list
555/// - When tree = 0, adds to the current list
556/// - When tree != 0, finds the list, corresponding to this tree
557/// - When tree is a chain, the entry is assumed to be global index and the local
558/// entry is recomputed from the treeoffset information of the chain
559
561{
562 if (!tree){
563 if (!fLists) {
564 if (!fBlocks) fBlocks = new TObjArray();
565 TEntryListBlock *block = 0;
566 Long64_t nblock = entry/kBlockSize;
567 if (nblock >= fNBlocks) {
568 if (fNBlocks>0){
570 if (!block) return 0;
571 block->OptimizeStorage();
572 }
573 for (Int_t i=fNBlocks; i<=nblock; i++){
574 block = new TEntryListBlock();
575 fBlocks->Add(block);
576 }
577 fNBlocks = nblock+1;
578 }
579 block = (TEntryListBlock*)fBlocks->UncheckedAt(nblock);
580 if (block->Enter(entry-nblock*kBlockSize)) {
581 fN++;
582 return 1;
583 }
584 } else {
585 //the entry in the current entry list
587 if (fCurrent->Enter(entry)) {
588 if (fLists)
589 fN++;
590 return 1;
591 }
592 }
593 } else {
594 Long64_t localentry = tree->LoadTree(entry);
595 SetTree(tree->GetTree());
596 if (fCurrent){
597 if (fCurrent->Enter(localentry)) {
598 if (fLists)
599 fN++;
600 return 1;
601 }
602 }
603 }
604 return 0;
605
606}
607
608////////////////////////////////////////////////////////////////////////////////
609/// Remove entry \#entry from the list
610/// - When tree = 0, removes from the current list
611/// - When tree != 0, finds the list, corresponding to this tree
612/// - When tree is a chain, the entry is assumed to be global index and the local
613/// entry is recomputed from the treeoffset information of the chain
614
616{
617 if (!tree){
618 if (!fLists) {
619 if (!fBlocks) return 0;
620 TEntryListBlock *block = 0;
621 Long64_t nblock = entry/kBlockSize;
622 block = (TEntryListBlock*)fBlocks->UncheckedAt(nblock);
623 if (!block) return 0;
624 Long64_t blockindex = entry - nblock*kBlockSize;
625 if (block->Remove(blockindex)){
626 fN--;
627 return 1;
628 }
629 } else {
631 if (fCurrent->Remove(entry)){
632 if (fLists)
633 fN--;
634 return 1;
635 }
636 }
637 } else {
638 Int_t localentry = tree->LoadTree(entry);
639 SetTree(tree->GetTree());
640 if (fCurrent){
641 if (fCurrent->Remove(localentry)) {
642 if (fLists)
643 fN--;
644 return 1;
645 }
646 }
647 }
648 return 0;
649}
650
651////////////////////////////////////////////////////////////////////////////////
652/// Return the number of the entry \#index of this TEntryList in the TTree or TChain
653/// See also Next().
654
656{
657
658 if (index>=fN){
659 return -1;
660 }
661 if (index==fLastIndexQueried+1){
662 //in a loop
663 return Next();
664 } else {
665 if (fBlocks) {
666 TEntryListBlock *block = 0;
667 Long64_t total_passed = 0;
668 Int_t i=0;
669 while (total_passed<=index && i<fNBlocks){
671 total_passed+=block->GetNPassed();
672 i++;
673 }
674 i--;
675 total_passed-=block->GetNPassed();
678 block->ResetIndices();
679 block = (TEntryListBlock*)fBlocks->UncheckedAt(i);
680 }
681
682 Long64_t localindex = index - total_passed;
683 Long64_t blockindex = block->GetEntry(localindex);
684 if (blockindex < 0) return -1;
685 Long64_t res = i*kBlockSize + blockindex;
686 fLastIndexQueried = index;
687 fLastIndexReturned = res;
688 return res;
689 } else {
690 //find the corresponding list
692 TIter next(fLists);
693 TEntryList *templist;
694 Long64_t ntotal = 0;
695 if (fCurrent){
696 //reset all indices of the current list
697 if (fCurrent->fBlocks){
700 block->ResetIndices();
703 }
704 }
705 while ((templist = (TEntryList*)next())){
706 if (!fShift){
707 ntotal += templist->GetN();
708 } else {
709 if (templist->GetTreeNumber() >= 0)
710 ntotal += templist->GetN();
711 }
712 if (ntotal > index)
713 break;
714 }
715 fCurrent = templist;
716 if (!fCurrent) return -1;
717 Long64_t localentry = index - (ntotal - fCurrent->GetN());
718 fLastIndexQueried = index;
719 fLastIndexReturned = fCurrent->GetEntry(localentry);
720 return fLastIndexReturned;
721 }
722
723 }
724 return -1;
725}
726
727////////////////////////////////////////////////////////////////////////////////
728/// Return the index of "index"-th non-zero entry in the TTree or TChain
729/// and the # of the corresponding tree in the chain
730
732{
733//If shift is true, then when the requested entry is found in an entry list,
734//for which there is no corresponding tree in the chain, this list is not
735//taken into account, and entry from the next list with a tree is returned.
736//Example:
737//First sublist - 20 entries, second sublist - 5 entries, third sublist - 10 entries
738//Second sublist doesn't correspond to any trees of the chain
739//Then, when GetEntryAndTree(21, treenum, kTRUE) is called, first entry of the
740//third sublist will be returned
741
742 Long64_t result = GetEntry(index);
743 if (fLists)
744 treenum = fCurrent->fTreeNumber;
745 else
746 treenum = fTreeNumber;
747 if (treenum<0) return -1;
748
749 return result;
750}
751
752////////////////////////////////////////////////////////////////////////////////
753/// To be able to re-localize the entry-list we identify the file by just the
754/// name and the anchor, i.e. we drop protocol, host, options, ...
755/// The result in the form 'file#anchor' (or 'file', if no anchor is present)
756/// is saved in 'fn'.
757/// The function optionally (is 'local' is defined) checks file locality (i.e.
758/// protocol 'file://') returning the result in '*local' .
759
760void TEntryList::GetFileName(const char *filename, TString &fn, Bool_t *local)
761{
762 TUrl u(filename, kTRUE);
763 if (local) *local = (!strcmp(u.GetProtocol(), "file")) ? kTRUE : kFALSE;
764 if (strlen(u.GetAnchor()) > 0) {
765 fn.Form("%s#%s", u.GetFile(), u.GetAnchor());
766 } else {
767 fn = u.GetFile();
768 }
769 // Done
770 return;
771}
772
773////////////////////////////////////////////////////////////////////////////////
774/// Return the entry list, corresponding to treename and filename
775/// By default, the filename is first tried as is, and then, if the corresponding list
776/// is not found, the filename is expanded to the absolute path, and compared again.
777/// To avoid it, use option "ne"
778
779TEntryList *TEntryList::GetEntryList(const char *treename, const char *filename, Option_t *opt)
780{
781 if (gDebug > 1)
782 Info("GetEntryList","tree: %s, file: %s",
783 (treename ? treename : "-"), (filename ? filename : "-"));
784
785 if (!treename || !filename) return 0;
786 TString option = opt;
787 option.ToUpper();
788 Bool_t nexp = option.Contains("NE");
789
790 TString fn;
791 Bool_t local;
792 GetFileName(filename, fn, &local);
793 if (nexp) local = kFALSE;
794
795 if (gDebug > 1)
796 Info("GetEntryList", "file: %s, local? %d", filename, local);
797
798 if (!fLists){
799 //there are no sublists
800 if (!strcmp(treename, fTreeName.Data()) && !(strcmp(fn.Data(), fFileName.Data()))){
801 return this;
802 } else {
803 //if the file is local, try the full name, unless "ne" option was specified
804 if (!nexp && local){
806 if (!gSystem->IsAbsoluteFileName(fn))
808 fn = gSystem->UnixPathName(fn);
809 if (!strcmp(treename, fTreeName.Data()) && !(strcmp(fn.Data(), fFileName.Data())))
810 return this;
811 }
812 return 0;
813 }
814 }
815
816 TString stotal = treename;
817 stotal.Append(fn);
818 ULong_t newhash = stotal.Hash();
819
820 TIter next(fLists);
821 TEntryList *templist;
822 while ((templist = (TEntryList*)next())){
823 if (templist->fStringHash==0){
824 stotal = templist->fTreeName + templist->fFileName;
825 templist->fStringHash = stotal.Hash();
826 }
827 if (gDebug > 1)
828 Info("GetEntryList", "file: %s (fn: %s), hash: %lu, element hash: %lu",
829 filename, fn.Data(), newhash, templist->fStringHash);
830 if (newhash == templist->fStringHash){
831 if (!strcmp(templist->GetTreeName(), treename) && !strcmp(templist->GetFileName(), fn.Data())){
832 return templist;
833 }
834 }
835 }
836
837 //didn't find anything for this filename, try the full name too
838 if (!nexp && local){
839 TString longname = fn;
840 gSystem->ExpandPathName(longname);
841 if (!gSystem->IsAbsoluteFileName(longname))
842 gSystem->PrependPathName(gSystem->pwd(), longname);
843 longname = gSystem->UnixPathName(longname);
844 stotal = treename;
845 stotal.Append(longname);
846 newhash = stotal.Hash();
847 next.Reset();
848 while ((templist = (TEntryList*)next())){
849 if (templist->fStringHash==0){
850 stotal = templist->fTreeName + templist->fFileName;
851 templist->fStringHash = stotal.Hash();
852 }
853 if (gDebug > 1)
854 Info("GetEntryList", "file: %s (longname: %s), hash: %lu, element hash: %lu",
855 filename, longname.Data(), newhash, templist->fStringHash);
856 if (newhash == templist->fStringHash){
857 if (templist->fTreeName == treename && templist->fFileName == longname){
858 return templist;
859 }
860 }
861 }
862 }
863 return 0;
864}
865
866////////////////////////////////////////////////////////////////////////////////
867/// Merge this list with the lists from the collection
868
870{
871 if (!list) return -1;
872 TIter next(list);
873 TEntryList *elist = 0;
874 while ((elist = (TEntryList*)next())) {
875 if (!elist->InheritsFrom(TEntryList::Class())) {
876 Error("Add","Attempt to add object of class: %s to a %s",elist->ClassName(),this->ClassName());
877 return -1;
878 }
879 Add(elist);
880 }
881 return 0;
882}
883
884////////////////////////////////////////////////////////////////////////////////
885/// Return the next non-zero entry index (next after fLastIndexQueried)
886/// this function is faster than GetEntry()
887
889{
890 Long64_t result;
891 if (fN == fLastIndexQueried+1 || fN==0){
892 return -1;
893 }
894 if (fBlocks){
896 TEntryListBlock *current_block = (TEntryListBlock*)fBlocks->UncheckedAt(iblock);
897 result = current_block->Next();
898 if (result>=0) {
900 fLastIndexReturned = result+kBlockSize*iblock;
901 return fLastIndexReturned;
902 }
903 else {
904 while (result<0 && iblock<fNBlocks-1) {
905 current_block->ResetIndices();
906 iblock++;
907 current_block = (TEntryListBlock*)fBlocks->UncheckedAt(iblock);
908 current_block->ResetIndices();
909 result = current_block->Next();
910 }
911 if (result<0) {
914 return -1;
915 }
917 fLastIndexReturned = result+kBlockSize*iblock;
918
919 return fLastIndexReturned;
920 }
921 } else {
922 if (!fCurrent) {
924 if (!fCurrent) return 0;
925 if (fShift) {
926 while (fCurrent->GetTreeNumber()<0) {
928 if (!fCurrent) return 0;
929 }
930 }
931 }
932 result = fCurrent->Next();
933 if (result>=0) {
935 fLastIndexReturned = result;
936 return result;
937 } else {
938 if (fCurrent){
939 //reset all indices of the current list
940 if (fCurrent->fBlocks){
943 block->ResetIndices();
946 }
947 }
948
949 //find the list with the next non-zero entry
950 while (result<0 && fCurrent!=((TEntryList*)fLists->Last())){
951 if (!fCurrent) return 0;
955 // fCurrent is guarantee to be non-zero because it is not the 'last'
956 // element of the list.
957 if (!fCurrent) return 0;
958 if (!fShift)
959 result = fCurrent->Next();
960 else {
961 if (fCurrent->GetTreeNumber() >= 0)
962 result = fCurrent->Next();
963 }
964 }
966 fLastIndexReturned = result;
967 return result;
968 }
969 }
970}
971
972////////////////////////////////////////////////////////////////////////////////
973/// Checks if the array representation is more economical and if so, switches to it
974
976{
977 if (fBlocks){
978 TEntryListBlock *block = 0;
979 for (Int_t i=0; i<fNBlocks; i++){
980 block = (TEntryListBlock*)fBlocks->UncheckedAt(i);
981 block->OptimizeStorage();
982 }
983 }
984}
985
986////////////////////////////////////////////////////////////////////////////////
987/// Print this list
988/// - option = "" - default - print the name of the tree and file
989/// - option = "all" - print all the entry numbers
990
991void TEntryList::Print(const Option_t* option) const
992{
993 TString opt = option;
994 opt.ToUpper();
995 if (fBlocks) {
996 Printf("%s %s %lld", fTreeName.Data(), fFileName.Data(), fN);
997 if (opt.Contains("A")){
998 TEntryListBlock* block = 0;
999 for (Int_t i=0; i<fNBlocks; i++){
1000 block = (TEntryListBlock*)fBlocks->UncheckedAt(i);
1001 Int_t shift = i*kBlockSize;
1002 block->PrintWithShift(shift);
1003 }
1004 }
1005 }
1006 else {
1007 TEntryList *elist = 0;
1008 if (fN>0){
1009 TIter next(fLists);
1010 while((elist = (TEntryList*)next())){
1011 elist->Print(option);
1012 }
1013 } else {
1014 if (!fLists) Printf("%s %s %lld", fTreeName.Data(), fFileName.Data(), fN);
1015 else {
1016 TIter next(fLists);
1017 while ((elist = (TEntryList*)next())){
1018 Printf("%s %s %lld", elist->GetTreeName(), elist->GetFileName(), elist->GetN());
1019 }
1020 }
1021 }
1022 }
1023}
1024
1025////////////////////////////////////////////////////////////////////////////////
1026/// Reset this list
1027
1028void TEntryList::Reset()
1029{
1030 //Maybe not delete, but just reset the number of blocks to 0????
1031
1032 if (fBlocks){
1033 fBlocks->Delete();
1034 delete fBlocks;
1035 fBlocks = 0;
1036 }
1037 if (fLists){
1038 if (!((TEntryList*)fLists->First())->GetDirectory()){
1039 fLists->Delete();
1040 }
1041 delete fLists;
1042 fLists = 0;
1043 }
1044 fCurrent = 0;
1045 fBlocks = 0;
1046 fNBlocks = 0;
1047 fN = 0;
1048 fTreeName = "";
1049 fFileName = "";
1050 fStringHash = 0;
1051 fTreeNumber = -1;
1052 fLastIndexQueried = -1;
1054 fReapply = kFALSE;
1055}
1056
1057////////////////////////////////////////////////////////////////////////////////
1058/// Add reference to directory dir. dir can be 0.
1059
1061{
1062 if (fDirectory == dir) return;
1063 if (fDirectory) fDirectory->Remove(this);
1064 fDirectory = dir;
1065 if (fDirectory) fDirectory->Append(this);
1066}
1067
1068////////////////////////////////////////////////////////////////////////////////
1069/// If a list for a tree with such name and filename exists, sets it as the current sublist
1070/// If not, creates this list and sets it as the current sublist
1071///
1072/// ! the filename is taken as provided, no extensions to full path or url !
1073
1074void TEntryList::SetTree(const char *treename, const char *filename)
1075{
1076 TEntryList *elist = 0;
1077
1078 TString fn;
1079 GetFileName(filename, fn);
1080
1081 TString stotal = treename;
1082 stotal.Append(fn.Data());
1083 //printf("setting tree %s\n", stotal.Data());
1084 ULong_t newhash = stotal.Hash();
1085 if (fLists) {
1086 //find the corresponding entry list and make it current
1088 if (fCurrent->fStringHash == 0){
1089 stotal = fCurrent->fTreeName + fCurrent->fFileName;
1090 fCurrent->fStringHash = stotal.Hash();
1091 }
1092 if (newhash == fCurrent->fStringHash){
1093 //this list is current
1094 if (!strcmp(fCurrent->fTreeName, treename) && !strcmp(fCurrent->fFileName, fn.Data())){
1095 return;
1096 }
1097 }
1098 TIter next(fLists);
1099 while ((elist = (TEntryList*)next())){
1100 if (newhash == elist->fStringHash){
1101 if (elist->fTreeName == treename && elist->fFileName == fn.Data()) {
1102 //the current entry list was changed. reset the fLastIndexQueried,
1103 //so that Next() doesn't start with the wrong current list
1104 //Also, reset those indices in the previously current list
1105 if (fCurrent->fBlocks){
1106 Int_t currentblock = (fCurrent->fLastIndexReturned)/kBlockSize;
1107 TEntryListBlock *block = (TEntryListBlock*)fCurrent->fBlocks->UncheckedAt(currentblock);
1108 block->ResetIndices();
1111 }
1112 fCurrent = elist;
1113 fLastIndexQueried = -3;
1114 return;
1115 }
1116 }
1117 }
1118 //didn't find an entry list for this tree, create a new one
1119 elist = new TEntryList("", "", treename, fn.Data());
1120 if (elist->GetDirectory()) {
1121 //sub lists are not added to the current directory
1122 elist->GetDirectory()->Remove(elist);
1123 elist->SetDirectory(0);
1124 }
1125 fLists->Add(elist);
1126 fCurrent = elist;
1127 return;
1128 } else {
1129 if (fN==0 && fTreeName=="" && fFileName==""){
1130 //this is the first tree set to this list
1131 fTreeName = treename;
1132 fFileName = fn;
1133 stotal = fTreeName + fFileName;
1134 //fStringHash = stotal.Hash();
1135 fStringHash = newhash;
1136 fCurrent = this;
1137 } else {
1138 if (fStringHash == 0){
1139 stotal = fTreeName + fFileName;
1140 fStringHash = stotal.Hash();
1141 }
1142 if (newhash != fStringHash){
1143 //we have a chain and already have an entry list for the first tree
1144 //move the first entry list to the fLists
1145 fLists = new TList();
1146 elist = new TEntryList();
1147 elist->fTreeName = fTreeName;
1148 elist->fFileName = fFileName;
1149 elist->fStringHash = fStringHash;
1150 elist->fN = fN;
1151 elist->fTreeNumber = fTreeNumber;
1152 elist->fBlocks = fBlocks;
1153 fBlocks = 0;
1154 elist->fNBlocks = fNBlocks;
1155 fLists->Add(elist);
1156 elist = new TEntryList("", "", treename, fn.Data());
1157 if (elist->GetDirectory()) {
1158 //sub lists are not added to the current directory
1159 elist->GetDirectory()->Remove(elist);
1160 elist->SetDirectory(0);
1161 }
1162 fLists->Add(elist);
1163 fCurrent = elist;
1164 //the current entry list was changed. reset the fLastIndexQueried,
1165 //so that Next() doesn't start with the wrong current list
1166 fLastIndexQueried = -3;
1167
1168 }
1169 else {
1170 //same tree as in the current entry list, don't do anything
1171 return;
1172 }
1173 }
1174 }
1175}
1176
1177////////////////////////////////////////////////////////////////////////////////
1178/// If a list for a tree with such name and filename exists, sets it as the current sublist
1179/// If not, creates this list and sets it as the current sublist
1180/// The name of the file, where the tree is, is taken as
1181/// `tree->GetTree()->GetCurrentFile()->GetName()`, and then expanded either to the absolute path,
1182/// or to full url. If, for some reason, you want to provide
1183/// the filename in a different format, use SetTree(const char *treename, const char *filename),
1184/// where the filename is taken "as is".
1185
1186void TEntryList::SetTree(const TTree *tree)
1187{
1188 if (!tree) return;
1189 auto thisTree = tree->GetTree();
1190 if (!thisTree) return;
1191
1192 TString treename;
1193 if (tree->GetDirectory()->InheritsFrom("TFile")) {
1194 treename = thisTree->GetName();
1195 } else {
1196 treename = TString::Format("%s/%s",tree->GetDirectory()->GetName(),thisTree->GetName());
1197 }
1198
1199 TString filename;
1200 if (tree->GetTree()->GetCurrentFile()){
1201 filename = tree->GetTree()->GetCurrentFile()->GetName();
1202 TUrl url(filename.Data(), kTRUE);
1203 if (!strcmp(url.GetProtocol(), "file")){
1204 gSystem->ExpandPathName(filename);
1205 if (!gSystem->IsAbsoluteFileName(filename))
1206 gSystem->PrependPathName(gSystem->pwd(), filename);
1207 filename = gSystem->UnixPathName(filename);
1208 url.SetFile(filename);
1209 }
1210 filename = url.GetUrl();
1211 } else {
1212 //memory-resident
1213 filename = "";
1214 }
1215 SetTree(treename, filename);
1216
1217}
1218
1219////////////////////////////////////////////////////////////////////////////////
1220/// Remove all the entries of this entry list, that are contained in elist
1221
1222void TEntryList::Subtract(const TEntryList *elist)
1223{
1224 TEntryList *templist = 0;
1225 if (!fLists){
1226 if (!fBlocks) return;
1227 //check if lists are for the same tree
1228 if (!elist->fLists){
1229 //second list is also only for 1 tree
1230 if (!strcmp(elist->fTreeName.Data(),fTreeName.Data()) &&
1231 !strcmp(elist->fFileName.Data(),fFileName.Data())){
1232 //same tree
1233 Long64_t n2 = elist->GetN();
1234 Long64_t entry;
1235 for (Int_t i=0; i<n2; i++){
1236 entry = (const_cast<TEntryList*>(elist))->GetEntry(i);
1237 Remove(entry);
1238 }
1239 } else {
1240 //different trees
1241 return;
1242 }
1243 } else {
1244 //second list has sublists, try to find one for the same tree as this list
1245 TIter next1(elist->GetLists());
1246 templist = 0;
1247 Bool_t found = kFALSE;
1248 while ((templist = (TEntryList*)next1())){
1249 if (!strcmp(templist->fTreeName.Data(),fTreeName.Data()) &&
1250 !strcmp(templist->fFileName.Data(),fFileName.Data())){
1251 found = kTRUE;
1252 break;
1253 }
1254 }
1255 if (found) {
1256 Subtract(templist);
1257 }
1258 }
1259 } else {
1260 //this list has sublists
1261 TIter next2(fLists);
1262 templist = 0;
1263 Long64_t oldn=0;
1264 while ((templist = (TEntryList*)next2())){
1265 oldn = templist->GetN();
1266 templist->Subtract(elist);
1267 fN = fN - oldn + templist->GetN();
1268 }
1269 }
1270 return;
1271}
1272
1273////////////////////////////////////////////////////////////////////////////////
1274
1276{
1277 TEntryList eresult = elist1;
1278 //eresult = elist1;
1279 // printf("internal in operator1\n");
1280 eresult.Print("all");
1281 eresult.Add(&elist2);
1282 // printf("internal in operator2\n");
1283 eresult.Print("all");
1284
1285 return eresult;
1286}
1287
1288////////////////////////////////////////////////////////////////////////////////
1289/// Relocate the file paths.
1290/// If `oldroot` is defined, replace `oldroot` with `newroot` in all file names,
1291/// i.e. `oldroot/re/st/of/the/path` will become `newroot`/re/st/of/the/path`.
1292/// If `oldroot` is null, the new path will be just `newroot/path`.
1293/// Relocation is mandatory to use the entry-list with the same dataset at a different
1294/// location (i.e. on a different cluster, machine or disks).
1295
1296Int_t TEntryList::RelocatePaths(const char *newroot, const char *oldroot)
1297{
1298 // At least newroot must be given
1299 if (!newroot || (newroot && strlen(newroot) <= 0)) {
1300 Warning("RelocatePaths", "the new location must be given!");
1301 return -1;
1302 }
1303
1304 if (strlen(GetName()) > 0)
1305 Info("RelocatePaths", "'%s': relocating paths '%s' to '%s'",
1306 GetName(), oldroot ? oldroot : "*", newroot);
1307
1308 Int_t nrl = 0, xnrl = 0;
1309 // Apply to all underlying lists, if any
1310 if (fLists) {
1311 TIter nxl(fLists);
1312 TEntryList *enl = 0;
1313 while ((enl = (TEntryList *) nxl())) {
1314 if ((xnrl = enl->RelocatePaths(newroot, oldroot)) < 0) {
1315 Warning("RelocatePaths", "problems relocating '%s'", enl->GetName());
1316 } else {
1317 nrl += xnrl;
1318 }
1319 }
1320 }
1321 // Apply to ourselves
1322 TString temp;
1323 Ssiz_t lo = 0;
1324 if (oldroot && (lo = strlen(oldroot)) > 0) {
1325 if (fFileName.BeginsWith(oldroot)) {
1326 fFileName.Replace(0, lo, newroot);
1327 nrl++;
1328 }
1329 } else {
1330 Ssiz_t ilst = fFileName.Last('/');
1331 if (ilst != kNPOS) {
1332 fFileName.Replace(0, ilst, newroot);
1333 } else {
1334 fFileName.Insert(0, TString::Format("%s/", newroot));
1335 }
1336 nrl++;
1337 }
1338 if (fStringHash != 0) {
1339 temp.Form("%s%s", fTreeName.Data(), fFileName.Data());
1340 fStringHash = temp.Hash();
1341 }
1342
1343 // Done
1344 return nrl;
1345}
1346
1347////////////////////////////////////////////////////////////////////////////////
1348/// Relocate entry list 'enlnm' in file 'fn' replacing 'oldroot' with 'newroot' in
1349/// filenames. If 'enlnm' is null or '*' all entry lists in the file are relocated.
1350/// Relocation is mandatory to use the entry-list with the same dataset at a different
1351/// location (i.e. on a different cluster, machine or disks).
1352/// This function can be called as many times as need to reach the desired result.
1353/// The existing 'locations' can be checked qith TEntryList::Scan .
1354
1355Int_t TEntryList::Relocate(const char *fn,
1356 const char *newroot, const char *oldroot, const char *enlnm)
1357{
1358 // Open the file for updating
1359 TFile *fl = TFile::Open(fn, "UPDATE");
1360 if (!fl || (fl&& fl->IsZombie())) {
1361 ::Error("TEntryList::Relocate", "file '%s' cannot be open for updating", fn);
1362 return -1;
1363 }
1364
1365 Int_t nrl = 0;
1366 // Read the lists
1367 TString nm(enlnm);
1368 if (nm.IsNull()) nm = "*";
1369 TRegexp nmrg(nm, kTRUE);
1370 TIter nxk(fl->GetListOfKeys());
1371 TKey *key = 0;
1372 while ((key = (TKey *) nxk())) {
1373 if (!strcmp(key->GetClassName(), "TEntryList")) {
1374 TString knm(key->GetName());
1375 if (knm.Index(nmrg) != kNPOS) {
1376 TEntryList *enl = dynamic_cast<TEntryList *>(fl->Get(knm));
1377 if (enl) {
1378 Int_t xnrl = enl->RelocatePaths(newroot, oldroot);
1379 if (xnrl >= 0) {
1380 enl->Write(knm, TObject::kOverwrite);
1381 nrl += xnrl;
1382 } else {
1383 ::Error("TEntryList::Relocate", "problems relocating '%s' ...", enl->GetName());
1384 }
1385 }
1386 }
1387 }
1388 }
1389 // Close the file
1390 fl->Close();
1391 delete fl;
1392 // Done
1393 return nrl;
1394}
1395
1396////////////////////////////////////////////////////////////////////////////////
1397/// Get in 'c' the string in common at the beginning of 'a' and 'b'
1398///
1399/// Return:
1400/// - 0 a and b are not contained in each other, i.e. c != a && c != b
1401/// - 1 a is contained in b, i.e. c == a (includes a == empty)
1402/// - 2 b is contained in a, i.e. c == b (includes b == empty)
1403/// - 3 b is a, i.e. c == b == a (includes a == b == empty)
1404/// Auxiliary function for path scans.
1405
1407{
1408 if (a == b) {
1409 c = a;
1410 return 3;
1411 }
1412 if (a.IsNull()) {
1413 c = "";
1414 return 1;
1415 }
1416 if (b.IsNull()) {
1417 c = "";
1418 return 2;
1419 }
1420 Bool_t ashort = (a.Length() > b.Length()) ? kFALSE : kTRUE;
1421 Ssiz_t len = (ashort) ? a.Length() : b.Length();
1422 Int_t lcom = 0;
1423 for (Int_t i = 0; i < len; i++) {
1424 if (a[i] != b[i]) break;
1425 lcom++;
1426 }
1427 if (lcom == len) {
1428 c = ashort ? a : b;
1429 return ashort ? 1 : 2;
1430 }
1431 c = a(0,lcom);
1432 // Done
1433 return 0;
1434}
1435
1436////////////////////////////////////////////////////////////////////////////////
1437/// Scan the paths to find the common roots. If 'roots' is defined, add
1438/// the found roots to the list as TObjStrings.
1439/// Return the number of roots found.
1440
1442{
1443 TList *xrl = roots ? roots : new TList;
1444
1445 Int_t nrl = 0;
1446 // Apply to all underlying lists, if any
1447 if (fLists) {
1448 TIter nxl(fLists);
1449 TEntryList *enl = 0;
1450 while ((enl = (TEntryList *) nxl()))
1451 nrl += enl->ScanPaths(xrl, kFALSE);
1452 }
1453 // Apply to ourselves
1454 Bool_t newobjs = kTRUE;
1455 TString path = gSystem->DirName(fFileName), com;
1456 TObjString *objs = 0;
1457 TIter nxr(xrl);
1458 while ((objs = (TObjString *) nxr())) {
1459 Int_t rc = 0;
1460 if ((rc = GetCommonString(path, objs->GetString(), com)) != 2) {
1461 TUrl ucom(com);
1462 if (strlen(ucom.GetFile()) > 0 && strcmp(ucom.GetFile(), "/")) {
1463 objs->SetString(com.Data());
1464 newobjs = kFALSE;
1465 break;
1466 }
1467 }
1468 }
1469 if (newobjs) xrl->Add(new TObjString(path));
1470
1471 // Done
1472 nrl = xrl->GetSize();
1473 if (notify) {
1474 Printf(" * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *");
1475 Printf(" * Entry-list: %s", GetName());
1476 Printf(" * %d common root paths found", nrl);
1477 nxr.Reset();
1478 while ((objs = (TObjString *) nxr())) {
1479 Printf(" * %s", objs->GetName());
1480 }
1481 Printf(" * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *");
1482 }
1483
1484 if (xrl != roots) {
1485 xrl->SetOwner(kTRUE);
1486 SafeDelete(xrl);
1487 }
1488
1489 // Done
1490 return nrl;
1491}
1492
1493////////////////////////////////////////////////////////////////////////////////
1494/// Scan TEntryList in 'fn' to find the common parts of paths.
1495/// If 'roots' is defined, add the found roots to the list as TObjStrings.
1496/// Return the number of common root paths found.
1497
1498Int_t TEntryList::Scan(const char *fn, TList *roots)
1499{
1500 // Open the file for updating
1501 TFile *fl = TFile::Open(fn);
1502 if (!fl || (fl&& fl->IsZombie())) {
1503 ::Error("TEntryList::Relocate", "file '%s' cannot be open for reading", fn);
1504 return -1;
1505 }
1506
1507 Int_t nrs = 0;
1508 // Read the lists
1509 TIter nxk(fl->GetListOfKeys());
1510 TKey *key = 0;
1511 while ((key = (TKey *) nxk())) {
1512 if (!strcmp(key->GetClassName(), "TEntryList")) {
1513 TEntryList *enl = dynamic_cast<TEntryList *>(fl->Get(key->GetName()));
1514 if (enl) {
1515 nrs += enl->ScanPaths(roots);
1516 } else {
1517 ::Error("TEntryList::Scan", "object entry-list '%s' not found or not loadable!", key->GetName());
1518 }
1519 }
1520 }
1521 // Close the file
1522 fl->Close();
1523 delete fl;
1524
1525 // Done
1526 return nrs;
1527}
1528
1529////////////////////////////////////////////////////////////////////////////////
1530/// Custom streamer for class TEntryList to handle the different interpretation
1531/// of fFileName between version 1 and >1 .
1532
1533void TEntryList::Streamer(TBuffer &b)
1534{
1535 if (b.IsReading()) {
1536 UInt_t R__s, R__c;
1537 Version_t R__v = b.ReadVersion(&R__s, &R__c);
1538 b.ReadClassBuffer(TEntryList::Class(), this, R__v, R__s, R__c);
1539 if (R__v <= 1) {
1540 // The filename contained also the protocol and host: this was dropped
1541 // in version > 1 to allow re-localization
1543 }
1544 } else {
1545 b.WriteClassBuffer(TEntryList::Class(), this);
1546 }
1547}
void Class()
Definition: Class.C:29
#define SafeDelete(p)
Definition: RConfig.hxx:529
#define b(i)
Definition: RSha256.hxx:100
#define c(i)
Definition: RSha256.hxx:101
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
int Ssiz_t
Definition: RtypesCore.h:63
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
bool Bool_t
Definition: RtypesCore.h:59
long long Long64_t
Definition: RtypesCore.h:69
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
R__EXTERN Int_t gDebug
Definition: Rtypes.h:90
#define gDirectory
Definition: TDirectory.h:213
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 Printf
Definition: TGeoToOCC.h:18
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
Collection abstract base class.
Definition: TCollection.h:63
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
virtual TList * GetListOfKeys() const
Describe directory structure in memory.
Definition: TDirectory.h:34
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:190
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
Used by TEntryList to store the entry numbers.
void OptimizeStorage()
If there are < kBlockSize or >kBlockSize*15 entries, change to an array representation.
Int_t Next()
Return the next non-zero entry Faster than GetEntry() function.
Int_t GetNPassed()
Returns the number of entries, passing the selection.
void PrintWithShift(Int_t shift) const
Print the indices of this block + shift (used from TEntryList::Print()) to print the current values.
Bool_t Enter(Int_t entry)
If the block has already been optimized and the entries are stored as a list and not as bits,...
Bool_t Remove(Int_t entry)
Remove entry #entry If the block has already been optimized and the entries are stored as a list and ...
Int_t Contains(Int_t entry)
True if the block contains entry #entry.
Int_t GetEntry(Int_t entry)
Return entry #entry.
Int_t Merge(TEntryListBlock *block)
Merge with the other block Returns the resulting number of entries in the block.
A List of entry numbers in a TTree or TChain.
Definition: TEntryList.h:26
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...
Definition: TEntryList.cxx:777
Long64_t fEntriesToProcess
used on proof to set the number of entries to process in a packet
Definition: TEntryList.h:37
Bool_t fReapply
If true, TTree::Draw will 'reapply' the original cut.
Definition: TEntryList.h:49
virtual Int_t GetTreeNumber() const
Definition: TEntryList.h:78
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.
Definition: TEntryList.cxx:973
virtual TList * GetLists() const
Definition: TEntryList.h:73
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 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:74
TObjArray * fBlocks
blocks with indices of passing events (TEntryListBlocks)
Definition: TEntryList.h:35
virtual Int_t Contains(Long64_t entry, TTree *tree=0)
Definition: TEntryList.cxx:517
virtual const char * GetFileName() const
Definition: TEntryList.h:77
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.
Definition: TEntryList.cxx:546
virtual ~TEntryList()
Destructor.
Definition: TEntryList.cxx:321
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...
Definition: TEntryList.cxx:886
virtual void SetDirectory(TDirectory *dir)
Add reference to directory dir. dir can be 0.
virtual void Reset()
Reset this list.
virtual Bool_t Enter(Long64_t entry, TTree *tree=0)
Add entry #entry to the list.
Definition: TEntryList.cxx:558
virtual Long64_t GetEntry(Int_t index)
Return the number of the entry #index of this TEntryList in the TTree or TChain See also Next().
Definition: TEntryList.cxx:653
Int_t fNBlocks
number of TEntryListBlocks
Definition: TEntryList.h:34
virtual const char * GetTreeName() const
Definition: TEntryList.h:76
virtual Int_t Merge(TCollection *list)
Merge this list with the lists from the collection.
Definition: TEntryList.cxx:867
TEntryList * fCurrent
! currently filled entry list
Definition: TEntryList.h:32
virtual void Print(const Option_t *option="") const
Print this list.
Definition: TEntryList.cxx:989
virtual Long64_t GetEntryAndTree(Int_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...
Definition: TEntryList.cxx:729
virtual Int_t RelocatePaths(const char *newloc, const char *oldloc=0)
Relocate the file paths.
virtual Bool_t Remove(Long64_t entry, TTree *tree=0)
Remove entry #entry from the list.
Definition: TEntryList.cxx:613
Bool_t 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
static Int_t Relocate(const char *fn, const char *newroot, const char *oldroot=0, const char *enlnm=0)
Relocate entry list 'enlnm' in file 'fn' replacing 'oldroot' with 'newroot' in filenames.
ULong_t fStringHash
! Hash value of a string of treename and filename
Definition: TEntryList.h:40
TList * fLists
a list of underlying entry lists for each tree of a chain
Definition: TEntryList.h:31
virtual Int_t ScanPaths(TList *roots, Bool_t notify=kTRUE)
Scan the paths to find the common roots.
TString fTreeName
name of the tree
Definition: TEntryList.h:38
TEntryList()
default c-tor
Definition: TEntryList.cxx:159
void GetFileName(const char *filename, TString &fn, Bool_t *=0)
To be able to re-localize the entry-list we identify the file by just the name and the anchor,...
Definition: TEntryList.cxx:758
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.
Definition: TEntryList.cxx:343
virtual Long64_t GetN() const
Definition: TEntryList.h:75
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:48
virtual void Close(Option_t *option="")
Close a file.
Definition: TFile.cxx:912
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseGeneralPurpose, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3975
void Reset()
Definition: TCollection.h:252
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:24
virtual const char * GetClassName() const
Definition: TKey.h:71
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * After(const TObject *obj) const
Returns the object after object obj.
Definition: TList.cxx:327
virtual TObject * Last() const
Return the last object in the list. Returns 0 when list is empty.
Definition: TList.cxx:689
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:655
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
void Add(TObject *obj)
Definition: TObjArray.h:73
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
Collectable string class.
Definition: TObjString.h:28
const char * GetName() const
Returns name of object.
Definition: TObjString.h:39
const TString & GetString() const
Definition: TObjString.h:47
void SetString(const char *s)
Definition: TObjString.h:46
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:785
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition: TObject.h:134
@ kOverwrite
overwrite existing object with same name
Definition: TObject.h:88
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
Regular expression class.
Definition: TRegexp.h:31
Basic string class.
Definition: TString.h:131
TString & Insert(Ssiz_t pos, const char *s)
Definition: TString.h:644
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:677
const char * Data() const
Definition: TString.h:364
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:876
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1113
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition: TString.cxx:626
TString & Append(const char *cs)
Definition: TString.h:559
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:2286
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1264
const char * pwd()
Definition: TSystem.h:405
virtual const char * DirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1013
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1071
virtual const char * UnixPathName(const char *unixpathname)
Convert from a Unix pathname to a local pathname.
Definition: TSystem.cxx:1053
virtual Bool_t IsAbsoluteFileName(const char *dir)
Return true if dir is an absolute pathname.
Definition: TSystem.cxx:958
A TTree object has a header with a name and a title.
Definition: TTree.h:71
This class represents a WWW compatible URL.
Definition: TUrl.h:35
const char * GetAnchor() const
Definition: TUrl.h:73
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition: TUrl.cxx:385
const char * GetFile() const
Definition: TUrl.h:72
const char * GetProtocol() const
Definition: TUrl.h:67
void SetFile(const char *file)
Definition: TUrl.h:88
static constexpr double nm
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
Definition: tree.py:1
TCanvas * roots()
Definition: roots.C:1
auto * a
Definition: textangle.C:12