Logo ROOT   6.18/05
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 correspondence 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 (entry < 0)
618 return kFALSE;
619 if (!tree) {
620 if (!fLists) {
621 if (!fBlocks) return 0;
622 TEntryListBlock *block = 0;
623 Long64_t nblock = entry/kBlockSize;
624 block = (TEntryListBlock*)fBlocks->UncheckedAt(nblock);
625 if (!block) return 0;
626 Long64_t blockindex = entry - nblock*kBlockSize;
627 if (block->Remove(blockindex)){
628 fN--;
629 return 1;
630 }
631 } else {
633 if (fCurrent->Remove(entry)){
634 if (fLists)
635 fN--;
636 return 1;
637 }
638 }
639 } else {
640 Int_t localentry = tree->LoadTree(entry);
641 SetTree(tree->GetTree());
642 if (fCurrent){
643 if (fCurrent->Remove(localentry)) {
644 if (fLists)
645 fN--;
646 return 1;
647 }
648 }
649 }
650 return 0;
651}
652
653////////////////////////////////////////////////////////////////////////////////
654/// Return the number of the entry \#index of this TEntryList in the TTree or TChain
655/// See also Next().
656
658{
659
660 if (index>=fN){
661 return -1;
662 }
663 if (index==fLastIndexQueried+1){
664 //in a loop
665 return Next();
666 } else {
667 if (fBlocks) {
668 TEntryListBlock *block = 0;
669 Long64_t total_passed = 0;
670 Int_t i=0;
671 while (total_passed<=index && i<fNBlocks){
673 total_passed+=block->GetNPassed();
674 i++;
675 }
676 i--;
677 total_passed-=block->GetNPassed();
680 block->ResetIndices();
681 block = (TEntryListBlock*)fBlocks->UncheckedAt(i);
682 }
683
684 Long64_t localindex = index - total_passed;
685 Long64_t blockindex = block->GetEntry(localindex);
686 if (blockindex < 0) return -1;
687 Long64_t res = i*kBlockSize + blockindex;
688 fLastIndexQueried = index;
689 fLastIndexReturned = res;
690 return res;
691 } else {
692 //find the corresponding list
694 TIter next(fLists);
695 TEntryList *templist;
696 Long64_t ntotal = 0;
697 if (fCurrent){
698 //reset all indices of the current list
699 if (fCurrent->fBlocks){
702 block->ResetIndices();
705 }
706 }
707 while ((templist = (TEntryList*)next())){
708 if (!fShift){
709 ntotal += templist->GetN();
710 } else {
711 if (templist->GetTreeNumber() >= 0)
712 ntotal += templist->GetN();
713 }
714 if (ntotal > index)
715 break;
716 }
717 fCurrent = templist;
718 if (!fCurrent) return -1;
719 Long64_t localentry = index - (ntotal - fCurrent->GetN());
720 fLastIndexQueried = index;
721 fLastIndexReturned = fCurrent->GetEntry(localentry);
722 return fLastIndexReturned;
723 }
724
725 }
726 return -1;
727}
728
729////////////////////////////////////////////////////////////////////////////////
730/// Return the index of "index"-th non-zero entry in the TTree or TChain
731/// and the # of the corresponding tree in the chain
732
734{
735//If shift is true, then when the requested entry is found in an entry list,
736//for which there is no corresponding tree in the chain, this list is not
737//taken into account, and entry from the next list with a tree is returned.
738//Example:
739//First sublist - 20 entries, second sublist - 5 entries, third sublist - 10 entries
740//Second sublist doesn't correspond to any trees of the chain
741//Then, when GetEntryAndTree(21, treenum, kTRUE) is called, first entry of the
742//third sublist will be returned
743
744 Long64_t result = GetEntry(index);
745 if (result < 0) {
746 treenum = -1;
747 return result;
748 }
749 R__ASSERT(fLists == nullptr || (fLists != nullptr && fCurrent != nullptr));
750 if (fCurrent)
751 treenum = fCurrent->fTreeNumber;
752 else
753 treenum = fTreeNumber;
754 if (treenum < 0)
755 return -1;
756
757 return result;
758}
759
760////////////////////////////////////////////////////////////////////////////////
761/// To be able to re-localize the entry-list we identify the file by just the
762/// name and the anchor, i.e. we drop protocol, host, options, ...
763/// The result in the form 'file#anchor' (or 'file', if no anchor is present)
764/// is saved in 'fn'.
765/// The function optionally (is 'local' is defined) checks file locality (i.e.
766/// protocol 'file://') returning the result in '*local' .
767
768void TEntryList::GetFileName(const char *filename, TString &fn, Bool_t *local)
769{
770 TUrl u(filename, kTRUE);
771 if (local) *local = (!strcmp(u.GetProtocol(), "file")) ? kTRUE : kFALSE;
772 if (strlen(u.GetAnchor()) > 0) {
773 fn.Form("%s#%s", u.GetFile(), u.GetAnchor());
774 } else {
775 fn = u.GetFile();
776 }
777 // Done
778 return;
779}
780
781////////////////////////////////////////////////////////////////////////////////
782/// Return the entry list, corresponding to treename and filename
783/// By default, the filename is first tried as is, and then, if the corresponding list
784/// is not found, the filename is expanded to the absolute path, and compared again.
785/// To avoid it, use option "ne"
786
787TEntryList *TEntryList::GetEntryList(const char *treename, const char *filename, Option_t *opt)
788{
789 if (gDebug > 1)
790 Info("GetEntryList","tree: %s, file: %s",
791 (treename ? treename : "-"), (filename ? filename : "-"));
792
793 if (!treename || !filename) return 0;
794 TString option = opt;
795 option.ToUpper();
796 Bool_t nexp = option.Contains("NE");
797
798 TString fn;
799 Bool_t local;
800 GetFileName(filename, fn, &local);
801 if (nexp) local = kFALSE;
802
803 if (gDebug > 1)
804 Info("GetEntryList", "file: %s, local? %d", filename, local);
805
806 if (!fLists){
807 //there are no sublists
808 if (!strcmp(treename, fTreeName.Data()) && !(strcmp(fn.Data(), fFileName.Data()))){
809 return this;
810 } else {
811 //if the file is local, try the full name, unless "ne" option was specified
812 if (!nexp && local){
814 if (!gSystem->IsAbsoluteFileName(fn))
816 fn = gSystem->UnixPathName(fn);
817 if (!strcmp(treename, fTreeName.Data()) && !(strcmp(fn.Data(), fFileName.Data())))
818 return this;
819 }
820 return 0;
821 }
822 }
823
824 TString stotal = treename;
825 stotal.Append(fn);
826 ULong_t newhash = stotal.Hash();
827
828 TIter next(fLists);
829 TEntryList *templist;
830 while ((templist = (TEntryList*)next())){
831 if (templist->fStringHash==0){
832 stotal = templist->fTreeName + templist->fFileName;
833 templist->fStringHash = stotal.Hash();
834 }
835 if (gDebug > 1)
836 Info("GetEntryList", "file: %s (fn: %s), hash: %lu, element hash: %lu",
837 filename, fn.Data(), newhash, templist->fStringHash);
838 if (newhash == templist->fStringHash){
839 if (!strcmp(templist->GetTreeName(), treename) && !strcmp(templist->GetFileName(), fn.Data())){
840 return templist;
841 }
842 }
843 }
844
845 //didn't find anything for this filename, try the full name too
846 if (!nexp && local){
847 TString longname = fn;
848 gSystem->ExpandPathName(longname);
849 if (!gSystem->IsAbsoluteFileName(longname))
850 gSystem->PrependPathName(gSystem->pwd(), longname);
851 longname = gSystem->UnixPathName(longname);
852 stotal = treename;
853 stotal.Append(longname);
854 newhash = stotal.Hash();
855 next.Reset();
856 while ((templist = (TEntryList*)next())){
857 if (templist->fStringHash==0){
858 stotal = templist->fTreeName + templist->fFileName;
859 templist->fStringHash = stotal.Hash();
860 }
861 if (gDebug > 1)
862 Info("GetEntryList", "file: %s (longname: %s), hash: %lu, element hash: %lu",
863 filename, longname.Data(), newhash, templist->fStringHash);
864 if (newhash == templist->fStringHash){
865 if (templist->fTreeName == treename && templist->fFileName == longname){
866 return templist;
867 }
868 }
869 }
870 }
871 return 0;
872}
873
874////////////////////////////////////////////////////////////////////////////////
875/// Merge this list with the lists from the collection
876
878{
879 if (!list) return -1;
880 TIter next(list);
881 TEntryList *elist = 0;
882 while ((elist = (TEntryList*)next())) {
883 if (!elist->InheritsFrom(TEntryList::Class())) {
884 Error("Add","Attempt to add object of class: %s to a %s",elist->ClassName(),this->ClassName());
885 return -1;
886 }
887 Add(elist);
888 }
889 return 0;
890}
891
892////////////////////////////////////////////////////////////////////////////////
893/// Return the next non-zero entry index (next after fLastIndexQueried)
894/// this function is faster than GetEntry()
895
897{
898 Long64_t result;
899 if (fN == fLastIndexQueried+1 || fN==0){
900 return -1;
901 }
902 if (fBlocks){
904 TEntryListBlock *current_block = (TEntryListBlock*)fBlocks->UncheckedAt(iblock);
905 result = current_block->Next();
906 if (result>=0) {
908 fLastIndexReturned = result+kBlockSize*iblock;
909 return fLastIndexReturned;
910 }
911 else {
912 while (result<0 && iblock<fNBlocks-1) {
913 current_block->ResetIndices();
914 iblock++;
915 current_block = (TEntryListBlock*)fBlocks->UncheckedAt(iblock);
916 current_block->ResetIndices();
917 result = current_block->Next();
918 }
919 if (result<0) {
922 return -1;
923 }
925 fLastIndexReturned = result+kBlockSize*iblock;
926
927 return fLastIndexReturned;
928 }
929 } else {
930 if (!fCurrent) {
932 if (!fCurrent) return 0;
933 if (fShift) {
934 while (fCurrent->GetTreeNumber()<0) {
936 if (!fCurrent) return 0;
937 }
938 }
939 }
940 result = fCurrent->Next();
941 if (result>=0) {
943 fLastIndexReturned = result;
944 return result;
945 } else {
946 if (fCurrent){
947 //reset all indices of the current list
948 if (fCurrent->fBlocks){
951 block->ResetIndices();
954 }
955 }
956
957 //find the list with the next non-zero entry
958 while (result<0 && fCurrent!=((TEntryList*)fLists->Last())){
959 if (!fCurrent) return 0;
963 // fCurrent is guarantee to be non-zero because it is not the 'last'
964 // element of the list.
965 if (!fCurrent) return 0;
966 if (!fShift)
967 result = fCurrent->Next();
968 else {
969 if (fCurrent->GetTreeNumber() >= 0)
970 result = fCurrent->Next();
971 }
972 }
974 fLastIndexReturned = result;
975 return result;
976 }
977 }
978}
979
980////////////////////////////////////////////////////////////////////////////////
981/// Checks if the array representation is more economical and if so, switches to it
982
984{
985 if (fBlocks){
986 TEntryListBlock *block = 0;
987 for (Int_t i=0; i<fNBlocks; i++){
988 block = (TEntryListBlock*)fBlocks->UncheckedAt(i);
989 block->OptimizeStorage();
990 }
991 }
992}
993
994////////////////////////////////////////////////////////////////////////////////
995/// Print this list
996/// - option = "" - default - print the name of the tree and file
997/// - option = "all" - print all the entry numbers
998
999void TEntryList::Print(const Option_t* option) const
1000{
1001 TString opt = option;
1002 opt.ToUpper();
1003 if (fBlocks) {
1004 Printf("%s %s %lld", fTreeName.Data(), fFileName.Data(), fN);
1005 if (opt.Contains("A")){
1006 TEntryListBlock* block = 0;
1007 for (Int_t i=0; i<fNBlocks; i++){
1008 block = (TEntryListBlock*)fBlocks->UncheckedAt(i);
1009 Int_t shift = i*kBlockSize;
1010 block->PrintWithShift(shift);
1011 }
1012 }
1013 }
1014 else {
1015 TEntryList *elist = 0;
1016 if (fN>0){
1017 TIter next(fLists);
1018 while((elist = (TEntryList*)next())){
1019 elist->Print(option);
1020 }
1021 } else {
1022 if (!fLists) Printf("%s %s %lld", fTreeName.Data(), fFileName.Data(), fN);
1023 else {
1024 TIter next(fLists);
1025 while ((elist = (TEntryList*)next())){
1026 Printf("%s %s %lld", elist->GetTreeName(), elist->GetFileName(), elist->GetN());
1027 }
1028 }
1029 }
1030 }
1031}
1032
1033////////////////////////////////////////////////////////////////////////////////
1034/// Reset this list
1035
1036void TEntryList::Reset()
1037{
1038 //Maybe not delete, but just reset the number of blocks to 0????
1039
1040 if (fBlocks){
1041 fBlocks->Delete();
1042 delete fBlocks;
1043 fBlocks = 0;
1044 }
1045 if (fLists){
1046 if (!((TEntryList*)fLists->First())->GetDirectory()){
1047 fLists->Delete();
1048 }
1049 delete fLists;
1050 fLists = 0;
1051 }
1052 fCurrent = 0;
1053 fBlocks = 0;
1054 fNBlocks = 0;
1055 fN = 0;
1056 fTreeName = "";
1057 fFileName = "";
1058 fStringHash = 0;
1059 fTreeNumber = -1;
1060 fLastIndexQueried = -1;
1062 fReapply = kFALSE;
1063}
1064
1065////////////////////////////////////////////////////////////////////////////////
1066/// Add reference to directory dir. dir can be 0.
1067
1069{
1070 if (fDirectory == dir) return;
1071 if (fDirectory) fDirectory->Remove(this);
1072 fDirectory = dir;
1073 if (fDirectory) fDirectory->Append(this);
1074}
1075
1076////////////////////////////////////////////////////////////////////////////////
1077/// If a list for a tree with such name and filename exists, sets it as the current sublist
1078/// If not, creates this list and sets it as the current sublist
1079///
1080/// ! the filename is taken as provided, no extensions to full path or url !
1081
1082void TEntryList::SetTree(const char *treename, const char *filename)
1083{
1084 TEntryList *elist = 0;
1085
1086 TString fn;
1087 GetFileName(filename, fn);
1088
1089 TString stotal = treename;
1090 stotal.Append(fn.Data());
1091 //printf("setting tree %s\n", stotal.Data());
1092 ULong_t newhash = stotal.Hash();
1093 if (fLists) {
1094 //find the corresponding entry list and make it current
1096 if (fCurrent->fStringHash == 0){
1097 stotal = fCurrent->fTreeName + fCurrent->fFileName;
1098 fCurrent->fStringHash = stotal.Hash();
1099 }
1100 if (newhash == fCurrent->fStringHash){
1101 //this list is current
1102 if (!strcmp(fCurrent->fTreeName, treename) && !strcmp(fCurrent->fFileName, fn.Data())){
1103 return;
1104 }
1105 }
1106 TIter next(fLists);
1107 while ((elist = (TEntryList*)next())){
1108 if (newhash == elist->fStringHash){
1109 if (elist->fTreeName == treename && elist->fFileName == fn.Data()) {
1110 //the current entry list was changed. reset the fLastIndexQueried,
1111 //so that Next() doesn't start with the wrong current list
1112 //Also, reset those indices in the previously current list
1113 if (fCurrent->fBlocks){
1114 Int_t currentblock = (fCurrent->fLastIndexReturned)/kBlockSize;
1115 TEntryListBlock *block = (TEntryListBlock*)fCurrent->fBlocks->UncheckedAt(currentblock);
1116 block->ResetIndices();
1119 }
1120 fCurrent = elist;
1121 fLastIndexQueried = -3;
1122 return;
1123 }
1124 }
1125 }
1126 //didn't find an entry list for this tree, create a new one
1127 elist = new TEntryList("", "", treename, fn.Data());
1128 if (elist->GetDirectory()) {
1129 //sub lists are not added to the current directory
1130 elist->GetDirectory()->Remove(elist);
1131 elist->SetDirectory(0);
1132 }
1133 fLists->Add(elist);
1134 fCurrent = elist;
1135 return;
1136 } else {
1137 if (fN==0 && fTreeName=="" && fFileName==""){
1138 //this is the first tree set to this list
1139 fTreeName = treename;
1140 fFileName = fn;
1141 stotal = fTreeName + fFileName;
1142 //fStringHash = stotal.Hash();
1143 fStringHash = newhash;
1144 fCurrent = this;
1145 } else {
1146 if (fStringHash == 0){
1147 stotal = fTreeName + fFileName;
1148 fStringHash = stotal.Hash();
1149 }
1150 if (newhash != fStringHash){
1151 //we have a chain and already have an entry list for the first tree
1152 //move the first entry list to the fLists
1153 fLists = new TList();
1154 elist = new TEntryList();
1155 elist->fTreeName = fTreeName;
1156 elist->fFileName = fFileName;
1157 elist->fStringHash = fStringHash;
1158 elist->fN = fN;
1159 elist->fTreeNumber = fTreeNumber;
1160 elist->fBlocks = fBlocks;
1161 fBlocks = 0;
1162 elist->fNBlocks = fNBlocks;
1163 fLists->Add(elist);
1164 elist = new TEntryList("", "", treename, fn.Data());
1165 if (elist->GetDirectory()) {
1166 //sub lists are not added to the current directory
1167 elist->GetDirectory()->Remove(elist);
1168 elist->SetDirectory(0);
1169 }
1170 fLists->Add(elist);
1171 fCurrent = elist;
1172 //the current entry list was changed. reset the fLastIndexQueried,
1173 //so that Next() doesn't start with the wrong current list
1174 fLastIndexQueried = -3;
1175
1176 }
1177 else {
1178 //same tree as in the current entry list, don't do anything
1179 return;
1180 }
1181 }
1182 }
1183}
1184
1185////////////////////////////////////////////////////////////////////////////////
1186/// If a list for a tree with such name and filename exists, sets it as the current sublist
1187/// If not, creates this list and sets it as the current sublist
1188/// The name of the file, where the tree is, is taken as
1189/// `tree->GetTree()->GetCurrentFile()->GetName()`, and then expanded either to the absolute path,
1190/// or to full url. If, for some reason, you want to provide
1191/// the filename in a different format, use SetTree(const char *treename, const char *filename),
1192/// where the filename is taken "as is".
1193
1194void TEntryList::SetTree(const TTree *tree)
1195{
1196 if (!tree) return;
1197 auto thisTree = tree->GetTree();
1198 if (!thisTree) return;
1199
1200 TString treename;
1201 if (tree->GetDirectory()->InheritsFrom("TFile")) {
1202 treename = thisTree->GetName();
1203 } else {
1204 treename = TString::Format("%s/%s",tree->GetDirectory()->GetName(),thisTree->GetName());
1205 }
1206
1207 TString filename;
1208 if (tree->GetTree()->GetCurrentFile()){
1209 filename = tree->GetTree()->GetCurrentFile()->GetName();
1210 TUrl url(filename.Data(), kTRUE);
1211 if (!strcmp(url.GetProtocol(), "file")){
1212 gSystem->ExpandPathName(filename);
1213 if (!gSystem->IsAbsoluteFileName(filename))
1214 gSystem->PrependPathName(gSystem->pwd(), filename);
1215 filename = gSystem->UnixPathName(filename);
1216 url.SetFile(filename);
1217 }
1218 filename = url.GetUrl();
1219 } else {
1220 //memory-resident
1221 filename = "";
1222 }
1223 SetTree(treename, filename);
1224
1225}
1226
1227////////////////////////////////////////////////////////////////////////////////
1228/// Remove all the entries of this entry list, that are contained in elist
1229
1230void TEntryList::Subtract(const TEntryList *elist)
1231{
1232 TEntryList *templist = 0;
1233 if (!fLists){
1234 if (!fBlocks) return;
1235 //check if lists are for the same tree
1236 if (!elist->fLists){
1237 //second list is also only for 1 tree
1238 if (!strcmp(elist->fTreeName.Data(),fTreeName.Data()) &&
1239 !strcmp(elist->fFileName.Data(),fFileName.Data())){
1240 //same tree
1241 Long64_t n2 = elist->GetN();
1242 Long64_t entry;
1243 for (Int_t i=0; i<n2; i++){
1244 entry = (const_cast<TEntryList*>(elist))->GetEntry(i);
1245 Remove(entry);
1246 }
1247 } else {
1248 //different trees
1249 return;
1250 }
1251 } else {
1252 //second list has sublists, try to find one for the same tree as this list
1253 TIter next1(elist->GetLists());
1254 templist = 0;
1255 Bool_t found = kFALSE;
1256 while ((templist = (TEntryList*)next1())){
1257 if (!strcmp(templist->fTreeName.Data(),fTreeName.Data()) &&
1258 !strcmp(templist->fFileName.Data(),fFileName.Data())){
1259 found = kTRUE;
1260 break;
1261 }
1262 }
1263 if (found) {
1264 Subtract(templist);
1265 }
1266 }
1267 } else {
1268 //this list has sublists
1269 TIter next2(fLists);
1270 templist = 0;
1271 Long64_t oldn=0;
1272 while ((templist = (TEntryList*)next2())){
1273 oldn = templist->GetN();
1274 templist->Subtract(elist);
1275 fN = fN - oldn + templist->GetN();
1276 }
1277 }
1278 return;
1279}
1280
1281////////////////////////////////////////////////////////////////////////////////
1282
1284{
1285 TEntryList eresult = elist1;
1286 //eresult = elist1;
1287 // printf("internal in operator1\n");
1288 eresult.Print("all");
1289 eresult.Add(&elist2);
1290 // printf("internal in operator2\n");
1291 eresult.Print("all");
1292
1293 return eresult;
1294}
1295
1296////////////////////////////////////////////////////////////////////////////////
1297/// Relocate the file paths.
1298/// If `oldroot` is defined, replace `oldroot` with `newroot` in all file names,
1299/// i.e. `oldroot/re/st/of/the/path` will become `newroot`/re/st/of/the/path`.
1300/// If `oldroot` is null, the new path will be just `newroot/path`.
1301/// Relocation is mandatory to use the entry-list with the same dataset at a different
1302/// location (i.e. on a different cluster, machine or disks).
1303
1304Int_t TEntryList::RelocatePaths(const char *newroot, const char *oldroot)
1305{
1306 // At least newroot must be given
1307 if (!newroot || (newroot && strlen(newroot) <= 0)) {
1308 Warning("RelocatePaths", "the new location must be given!");
1309 return -1;
1310 }
1311
1312 if (strlen(GetName()) > 0)
1313 Info("RelocatePaths", "'%s': relocating paths '%s' to '%s'",
1314 GetName(), oldroot ? oldroot : "*", newroot);
1315
1316 Int_t nrl = 0, xnrl = 0;
1317 // Apply to all underlying lists, if any
1318 if (fLists) {
1319 TIter nxl(fLists);
1320 TEntryList *enl = 0;
1321 while ((enl = (TEntryList *) nxl())) {
1322 if ((xnrl = enl->RelocatePaths(newroot, oldroot)) < 0) {
1323 Warning("RelocatePaths", "problems relocating '%s'", enl->GetName());
1324 } else {
1325 nrl += xnrl;
1326 }
1327 }
1328 }
1329 // Apply to ourselves
1330 TString temp;
1331 Ssiz_t lo = 0;
1332 if (oldroot && (lo = strlen(oldroot)) > 0) {
1333 if (fFileName.BeginsWith(oldroot)) {
1334 fFileName.Replace(0, lo, newroot);
1335 nrl++;
1336 }
1337 } else {
1338 Ssiz_t ilst = fFileName.Last('/');
1339 if (ilst != kNPOS) {
1340 fFileName.Replace(0, ilst, newroot);
1341 } else {
1342 fFileName.Insert(0, TString::Format("%s/", newroot));
1343 }
1344 nrl++;
1345 }
1346 if (fStringHash != 0) {
1347 temp.Form("%s%s", fTreeName.Data(), fFileName.Data());
1348 fStringHash = temp.Hash();
1349 }
1350
1351 // Done
1352 return nrl;
1353}
1354
1355////////////////////////////////////////////////////////////////////////////////
1356/// Relocate entry list 'enlnm' in file 'fn' replacing 'oldroot' with 'newroot' in
1357/// filenames. If 'enlnm' is null or '*' all entry lists in the file are relocated.
1358/// Relocation is mandatory to use the entry-list with the same dataset at a different
1359/// location (i.e. on a different cluster, machine or disks).
1360/// This function can be called as many times as need to reach the desired result.
1361/// The existing 'locations' can be checked qith TEntryList::Scan .
1362
1363Int_t TEntryList::Relocate(const char *fn,
1364 const char *newroot, const char *oldroot, const char *enlnm)
1365{
1366 // Open the file for updating
1367 TFile *fl = TFile::Open(fn, "UPDATE");
1368 if (!fl || (fl&& fl->IsZombie())) {
1369 ::Error("TEntryList::Relocate", "file '%s' cannot be open for updating", fn);
1370 return -1;
1371 }
1372
1373 Int_t nrl = 0;
1374 // Read the lists
1375 TString nm(enlnm);
1376 if (nm.IsNull()) nm = "*";
1377 TRegexp nmrg(nm, kTRUE);
1378 TIter nxk(fl->GetListOfKeys());
1379 TKey *key = 0;
1380 while ((key = (TKey *) nxk())) {
1381 if (!strcmp(key->GetClassName(), "TEntryList")) {
1382 TString knm(key->GetName());
1383 if (knm.Index(nmrg) != kNPOS) {
1384 TEntryList *enl = dynamic_cast<TEntryList *>(fl->Get(knm));
1385 if (enl) {
1386 Int_t xnrl = enl->RelocatePaths(newroot, oldroot);
1387 if (xnrl >= 0) {
1388 enl->Write(knm, TObject::kOverwrite);
1389 nrl += xnrl;
1390 } else {
1391 ::Error("TEntryList::Relocate", "problems relocating '%s' ...", enl->GetName());
1392 }
1393 }
1394 }
1395 }
1396 }
1397 // Close the file
1398 fl->Close();
1399 delete fl;
1400 // Done
1401 return nrl;
1402}
1403
1404////////////////////////////////////////////////////////////////////////////////
1405/// Get in 'c' the string in common at the beginning of 'a' and 'b'
1406///
1407/// Return:
1408/// - 0 a and b are not contained in each other, i.e. c != a && c != b
1409/// - 1 a is contained in b, i.e. c == a (includes a == empty)
1410/// - 2 b is contained in a, i.e. c == b (includes b == empty)
1411/// - 3 b is a, i.e. c == b == a (includes a == b == empty)
1412/// Auxiliary function for path scans.
1413
1415{
1416 if (a == b) {
1417 c = a;
1418 return 3;
1419 }
1420 if (a.IsNull()) {
1421 c = "";
1422 return 1;
1423 }
1424 if (b.IsNull()) {
1425 c = "";
1426 return 2;
1427 }
1428 Bool_t ashort = (a.Length() > b.Length()) ? kFALSE : kTRUE;
1429 Ssiz_t len = (ashort) ? a.Length() : b.Length();
1430 Int_t lcom = 0;
1431 for (Int_t i = 0; i < len; i++) {
1432 if (a[i] != b[i]) break;
1433 lcom++;
1434 }
1435 if (lcom == len) {
1436 c = ashort ? a : b;
1437 return ashort ? 1 : 2;
1438 }
1439 c = a(0,lcom);
1440 // Done
1441 return 0;
1442}
1443
1444////////////////////////////////////////////////////////////////////////////////
1445/// Scan the paths to find the common roots. If 'roots' is defined, add
1446/// the found roots to the list as TObjStrings.
1447/// Return the number of roots found.
1448
1450{
1451 TList *xrl = roots ? roots : new TList;
1452
1453 Int_t nrl = 0;
1454 // Apply to all underlying lists, if any
1455 if (fLists) {
1456 TIter nxl(fLists);
1457 TEntryList *enl = 0;
1458 while ((enl = (TEntryList *) nxl()))
1459 nrl += enl->ScanPaths(xrl, kFALSE);
1460 }
1461 // Apply to ourselves
1462 Bool_t newobjs = kTRUE;
1463 TString path = gSystem->DirName(fFileName), com;
1464 TObjString *objs = 0;
1465 TIter nxr(xrl);
1466 while ((objs = (TObjString *) nxr())) {
1467 Int_t rc = 0;
1468 if ((rc = GetCommonString(path, objs->GetString(), com)) != 2) {
1469 TUrl ucom(com);
1470 if (strlen(ucom.GetFile()) > 0 && strcmp(ucom.GetFile(), "/")) {
1471 objs->SetString(com.Data());
1472 newobjs = kFALSE;
1473 break;
1474 }
1475 }
1476 }
1477 if (newobjs) xrl->Add(new TObjString(path));
1478
1479 // Done
1480 nrl = xrl->GetSize();
1481 if (notify) {
1482 Printf(" * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *");
1483 Printf(" * Entry-list: %s", GetName());
1484 Printf(" * %d common root paths found", nrl);
1485 nxr.Reset();
1486 while ((objs = (TObjString *) nxr())) {
1487 Printf(" * %s", objs->GetName());
1488 }
1489 Printf(" * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *");
1490 }
1491
1492 if (xrl != roots) {
1493 xrl->SetOwner(kTRUE);
1494 SafeDelete(xrl);
1495 }
1496
1497 // Done
1498 return nrl;
1499}
1500
1501////////////////////////////////////////////////////////////////////////////////
1502/// Scan TEntryList in 'fn' to find the common parts of paths.
1503/// If 'roots' is defined, add the found roots to the list as TObjStrings.
1504/// Return the number of common root paths found.
1505
1506Int_t TEntryList::Scan(const char *fn, TList *roots)
1507{
1508 // Open the file for updating
1509 TFile *fl = TFile::Open(fn);
1510 if (!fl || (fl&& fl->IsZombie())) {
1511 ::Error("TEntryList::Relocate", "file '%s' cannot be open for reading", fn);
1512 return -1;
1513 }
1514
1515 Int_t nrs = 0;
1516 // Read the lists
1517 TIter nxk(fl->GetListOfKeys());
1518 TKey *key = 0;
1519 while ((key = (TKey *) nxk())) {
1520 if (!strcmp(key->GetClassName(), "TEntryList")) {
1521 TEntryList *enl = dynamic_cast<TEntryList *>(fl->Get(key->GetName()));
1522 if (enl) {
1523 nrs += enl->ScanPaths(roots);
1524 } else {
1525 ::Error("TEntryList::Scan", "object entry-list '%s' not found or not loadable!", key->GetName());
1526 }
1527 }
1528 }
1529 // Close the file
1530 fl->Close();
1531 delete fl;
1532
1533 // Done
1534 return nrs;
1535}
1536
1537////////////////////////////////////////////////////////////////////////////////
1538/// Custom streamer for class TEntryList to handle the different interpretation
1539/// of fFileName between version 1 and >1 .
1540
1541void TEntryList::Streamer(TBuffer &b)
1542{
1543 if (b.IsReading()) {
1544 UInt_t R__s, R__c;
1545 Version_t R__v = b.ReadVersion(&R__s, &R__c);
1546 b.ReadClassBuffer(TEntryList::Class(), this, R__v, R__s, R__c);
1547 if (R__v <= 1) {
1548 // The filename contained also the protocol and host: this was dropped
1549 // in version > 1 to allow re-localization
1551 }
1552 } else {
1553 b.WriteClassBuffer(TEntryList::Class(), this);
1554 }
1555}
void Class()
Definition: Class.C:29
#define SafeDelete(p)
Definition: RConfig.hxx:543
#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:365
R__EXTERN Int_t gDebug
Definition: Rtypes.h:91
#define gDirectory
Definition: TDirectory.h:218
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)
Definition: TError.h:96
char name[80]
Definition: TGX11.cxx:109
void Printf(const char *fmt,...)
R__EXTERN TSystem * gSystem
Definition: TSystem.h:560
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
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:785
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:981
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:894
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:655
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:875
TEntryList * fCurrent
! currently filled entry list
Definition: TEntryList.h:32
virtual void Print(const Option_t *option="") const
Print this list.
Definition: TEntryList.cxx:997
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:731
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:766
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:914
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:3980
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:690
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:656
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:74
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:90
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:38
const TString & GetString() const
Definition: TObjString.h:46
void SetString(const char *s)
Definition: TObjString.h:45
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:892
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1138
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:638
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:2311
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2289
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:425
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 represents a columnar dataset.
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