Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A TChain whose trees have friend TChains stops updating #16805

Open
1 task done
lmoureaux opened this issue Oct 31, 2024 · 0 comments
Open
1 task done

A TChain whose trees have friend TChains stops updating #16805

lmoureaux opened this issue Oct 31, 2024 · 0 comments
Assignees
Labels

Comments

@lmoureaux
Copy link

lmoureaux commented Oct 31, 2024

Check duplicate issues.

  • Checked for duplicates

Description

Consider the following tree loading structure:

TChain c2 ---> TTree ---(friend)---> TChain c1 ---> TTree

When iterating over c2, branches coming from c1 stop updating after the first file boundary is reached in c1. They start updating again once a file boundary is reached in c2.

I think this is distinct from #16804 because in this case the issues lie in TChain::LoadTree, while for #16804 TChain::LoadTree is the sole culprit.

As in #16804, the root cause of the issue is that the following code is not invoked often enough:

root/tree/tree/src/TChain.cxx

Lines 1407 to 1434 in 2cc4b70

while ((frelement = (TChainElement*) fnext())) {
void* addr = frelement->GetBaddress();
if (addr) {
TBranch* br = fTree->GetBranch(frelement->GetName());
TBranch** pp = frelement->GetBranchPtr();
if (pp) {
// FIXME: What if br is zero here?
*pp = br;
}
if (br) {
if (!frelement->GetCheckedType()) {
Int_t res = CheckBranchAddressType(br, TClass::GetClass(frelement->GetBaddressClassName()),
(EDataType) frelement->GetBaddressType(), frelement->GetBaddressIsPtr());
if ((res & kNeedEnableDecomposedObj) && !br->GetMakeClass()) {
br->SetMakeClass(true);
}
frelement->SetDecomposedObj(br->GetMakeClass());
frelement->SetCheckedType(true);
}
// FIXME: We may have to tell the branch it should
// not be an owner of the object pointed at.
br->SetAddress(addr);
if (TestBit(kAutoDelete)) {
br->SetAutoDelete(true);
}
}
}
}

I will call the operation above an "address refresh".

TChain has code triggering an address refresh when needed for friends of the current tree:

root/tree/tree/src/TChain.cxx

Lines 1384 to 1393 in 2cc4b70

bool needUpdate = false;
if (fTree->GetListOfFriends()) {
for(auto fetree : ROOT::Detail::TRangeStaticCast<TFriendElement>(*fTree->GetListOfFriends())) {
if (fetree->IsUpdated()) {
needUpdate = true;
fetree->ResetUpdated();
}
}
}
if (needUpdate) {

Unfortunately this doesn't work for two reasons:

  1. The code cannot possibly be reached unless c2 itself has friends because of the following condition:
    if (fFriends) {

    In our case c2 doesn't have friends, but the fTree does. This is easy to fix (or work around).
  2. Even if fFriends is made non-null, fetree->IsUpdated() always returns false because TTree::LoadTree resets it:
    fe->ResetUpdated();

    Fixing this is much more annoying. For my application, I ended up subscribing to the Notify signal and calling TFriendElement::MarkUpdated again. This is only a partial solution because when c2 loads a new file, it doesn't reset friend elements that were marked updated, which would happen somewhere along this line:
    while ((fe = (TFriendElement*) next())) {

Reproducer

Rename to recursiveBugDemo.C and run the following macro: recursiveBugDemo.txt

It works similarly to #16804 and should only print true.

ROOT version

Seen in:

  • ROOT 6.30/04 (anaconda)
  • ROOT 6.28/04 (LCG 104)

I couldn't find any code change in master in the relevant areas.

Installation method

anaconda and LCG 104

Operating system

Linux (CentOS 9, Ubuntu 22.04, Ubuntu 24.04)

Additional context

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants