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