Skip to content

Commit

Permalink
[io] Fix TFileMerger getDirectory not considering full path
Browse files Browse the repository at this point in the history
  • Loading branch information
silverweed committed Sep 24, 2024
1 parent a7f8615 commit 2a814b4
Showing 1 changed file with 19 additions and 6 deletions.
25 changes: 19 additions & 6 deletions io/io/src/TFileMerger.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ to be merged, like the standalone hadd program.
#include "TMemFile.h"
#include "TVirtualMutex.h"

#include <ROOT/StringUtils.hxx>

#ifdef WIN32
// For _getmaxstdio
#include <cstdio>
Expand Down Expand Up @@ -132,7 +134,7 @@ Bool_t TFileMerger::AddFile(const char *url, Bool_t cpProgress)
Printf("%s Source file %d: %s", fMsgPrefix.Data(), fFileList.GetEntries() + fExcessFiles.GetEntries() + 1, url);
}

TFile *newfile = 0;
TFile *newfile = nullptr;
TString localcopy;

if (fFileList.GetEntries() >= (fMaxOpenedFiles-1)) {
Expand Down Expand Up @@ -164,7 +166,7 @@ Bool_t TFileMerger::AddFile(const char *url, Bool_t cpProgress)
// Zombie files should also be skipped
if (newfile && newfile->IsZombie()) {
delete newfile;
newfile = 0;
newfile = nullptr;
}

if (!newfile) {
Expand Down Expand Up @@ -435,6 +437,16 @@ Bool_t WriteCycleInOrder(const TString &name, TIter &nextkey, TIter &peeknextkey
return WriteOneAndDelete(name, cl, obj, kFALSE, kTRUE, target) && result;
};

TDirectory *LookupObjByFullPath(TDirectory *dir, const TString &path, std::span<std::string> pathPieces = {})
{
assert(!pathPieces.empty());
const auto &nextPiece = pathPieces.front();
auto *child = dir->GetDirectory(nextPiece.c_str());
if (pathPieces.size() == 1 || !child)
return child;
return LookupObjByFullPath(child, path, { pathPieces.begin() + 1, pathPieces.size() - 1 });
};

} // anonymous namespace

Bool_t TFileMerger::MergeOne(TDirectory *target, TList *sourcelist, Int_t type, TFileMergeInfo &info,
Expand Down Expand Up @@ -543,9 +555,10 @@ Bool_t TFileMerger::MergeOne(TDirectory *target, TList *sourcelist, Int_t type,
Bool_t canBeMerged = kTRUE;

TList dirtodelete;
auto getDirectory = [&dirtodelete](TDirectory *parent, const char *name, const TString &pathname)
auto getDirectory = [&dirtodelete](TDirectory *parent, const TString &pathname)
{
TDirectory *result = dynamic_cast<TDirectory*>(parent->GetList()->FindObject(name));
auto pathPieces = ROOT::Split(pathname, "\\/");
TDirectory *result = LookupObjByFullPath(parent, pathname, pathPieces);
if (!result) {
result = parent->GetDirectory(pathname);
if (result && result != parent)
Expand Down Expand Up @@ -632,7 +645,7 @@ Bool_t TFileMerger::MergeOne(TDirectory *target, TList *sourcelist, Int_t type,
} else {
do {
// make sure we are at the correct directory level by cd'ing to path
TDirectory *ndir = getDirectory(nextsource, target->GetName(), path);
TDirectory *ndir = getDirectory(nextsource, path);
if (ndir) {
// For consistency (and persformance), we reset the MustCleanup be also for those
// 'key' retrieved indirectly.
Expand Down Expand Up @@ -715,7 +728,7 @@ Bool_t TFileMerger::MergeOne(TDirectory *target, TList *sourcelist, Int_t type,
} else {
while (nextsource) {
// make sure we are at the correct directory level by cd'ing to path
TDirectory *ndir = getDirectory(nextsource, target->GetName(), path);
TDirectory *ndir = getDirectory(nextsource, path);
if (ndir) {
ndir->cd();
TKey *key2 = (TKey*)ndir->GetListOfKeys()->FindObject(keyname);
Expand Down

0 comments on commit 2a814b4

Please sign in to comment.