From 535f5439dfa83c6292fa1d61f4c662c7978d3cf1 Mon Sep 17 00:00:00 2001 From: Jakob Blomer Date: Wed, 6 Nov 2024 16:02:29 +0100 Subject: [PATCH] [ntuple] allow for writing into TFile subdir (WIP) --- tree/ntuple/v7/inc/ROOT/RMiniFile.hxx | 3 +++ tree/ntuple/v7/src/RMiniFile.cxx | 21 +++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/tree/ntuple/v7/inc/ROOT/RMiniFile.hxx b/tree/ntuple/v7/inc/ROOT/RMiniFile.hxx index 412294ece0a38..9bd330c0d13c9 100644 --- a/tree/ntuple/v7/inc/ROOT/RMiniFile.hxx +++ b/tree/ntuple/v7/inc/ROOT/RMiniFile.hxx @@ -104,6 +104,7 @@ class RNTupleFileWriter { private: struct RFileProper { TFile *fFile = nullptr; + std::string fDirectory; /// Low-level writing using a TFile void Write(const void *buffer, size_t nbytes, std::int64_t offset); /// Writes an RBlob opaque key with the provided buffer as data record and returns the offset of the record @@ -178,6 +179,8 @@ private: explicit RNTupleFileWriter(std::string_view name, std::uint64_t maxKeySize); + static std::pair SplitNTupleName(std::string_view nameAndDir); + /// For a TFile container written by a C file stream, write the header and TFile object void WriteTFileSkeleton(int defaultCompression); /// The only key that will be visible in file->ls() diff --git a/tree/ntuple/v7/src/RMiniFile.cxx b/tree/ntuple/v7/src/RMiniFile.cxx index f5de3a53bf854..7881f187d09c6 100644 --- a/tree/ntuple/v7/src/RMiniFile.cxx +++ b/tree/ntuple/v7/src/RMiniFile.cxx @@ -1105,12 +1105,27 @@ ROOT::Experimental::Internal::RNTupleFileWriter::Recreate(std::string_view ntupl return writer; } +std::pair ROOT::Experimental::Internal::RNTupleFileWriter::SplitNTupleName( + std::string_view nameAndDir) +{ + const auto posLastSlash = nameAndDir.find_last_of('/'); + if (posLastSlash == std::string::npos) + return std::make_pair("", nameAndDir); + + if (posLastSlash == nameAndDir.size() - 1) + throw RException(R__FAIL("empty RNTuple name")); + + return std::make_pair(nameAndDir.substr(0, posLastSlash), nameAndDir.substr(posLastSlash + 1)); +} + std::unique_ptr ROOT::Experimental::Internal::RNTupleFileWriter::Append(std::string_view ntupleName, TFile &file, std::uint64_t maxKeySize) { - auto writer = std::unique_ptr(new RNTupleFileWriter(ntupleName, maxKeySize)); + auto [dir, name] = SplitNTupleName(ntupleName); + auto writer = std::unique_ptr(new RNTupleFileWriter(name, maxKeySize)); writer->fFileProper.fFile = &file; + writer->fFileProper.fDirectory = dir; return writer; } @@ -1124,7 +1139,9 @@ void ROOT::Experimental::Internal::RNTupleFileWriter::Commit() { if (fFileProper) { // Easy case, the ROOT file header and the RNTuple streaming is taken care of by TFile - fFileProper.fFile->WriteObject(&fNTupleAnchor, fNTupleName.c_str()); + auto dir = fFileProper.fFile->GetDirectory(fFileProper.fDirectory.c_str()); + dir->cd(); + dir->WriteObject(&fNTupleAnchor, fNTupleName.c_str()); // Make sure the streamer info records used in the RNTuple are written to the file TBufferFile buf(TBuffer::kWrite);