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

[ntuple] allow for writing into TFile subdir (WIP) #16838

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions tree/ntuple/v7/inc/ROOT/RMiniFile.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class RNTupleFileWriter {
private:
struct RFileProper {
TFile *fFile = nullptr;
std::string fDirectory;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either

Suggested change
std::string fDirectory;
TDirectory* fDirectory;

or

Suggested change
std::string fDirectory;
std::string fDirectoryPath;

/// 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
Expand Down Expand Up @@ -178,6 +179,8 @@ private:

explicit RNTupleFileWriter(std::string_view name, std::uint64_t maxKeySize);

static std::pair<std::string_view, std::string_view> 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()
Expand Down
21 changes: 19 additions & 2 deletions tree/ntuple/v7/src/RMiniFile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1105,12 +1105,27 @@ ROOT::Experimental::Internal::RNTupleFileWriter::Recreate(std::string_view ntupl
return writer;
}

std::pair<std::string_view, std::string_view> 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>
ROOT::Experimental::Internal::RNTupleFileWriter::Append(std::string_view ntupleName, TFile &file,
std::uint64_t maxKeySize)
{
auto writer = std::unique_ptr<RNTupleFileWriter>(new RNTupleFileWriter(ntupleName, maxKeySize));
auto [dir, name] = SplitNTupleName(ntupleName);
Copy link
Member

@pcanal pcanal Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that it would also be nice to have:

ROOT::Experimental::Internal::RNTupleFileWriter::Append(std::string_view ntupleName, TDIrectory &dir,
                                                        std::uint64_t maxKeySize) 
{
     if (!dir.GetFile())
        throw "We need a file";
   auto writer = std::unique_ptr<RNTupleFileWriter>(new RNTupleFileWriter(name, maxKeySize));
   writer->fFileProper.fFile = dir->GetFile();
   writer->fFileProper.fDirectory = &dir; 

(oups the type of fDirectory is wrong).

auto writer = std::unique_ptr<RNTupleFileWriter>(new RNTupleFileWriter(name, maxKeySize));
writer->fFileProper.fFile = &file;
writer->fFileProper.fDirectory = dir;
return writer;
}

Expand All @@ -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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A priori the cd is not needed. If it is then we need to use also a TDirectory::TContext to make the function have no net effect on gDirectory.

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);
Expand Down
Loading