Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
32 changes: 16 additions & 16 deletions io/io/inc/ROOT/RFile.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,15 @@ ROOT::RLogChannel &RFileLog();
## When and why should you use RFile

RFile is a modern and minimalistic interface to ROOT files, both local and remote, that can be used instead of TFile
when the following conditions are met:
- you want a simple interface that makes it easy to do things right and hard to do things wrong;
- you only need basic Put/Get operations and don't need the more advanced TFile/TDirectory functionalities;
- you want more robustness and better error reporting for those operations;
- you want clearer ownership semantics expressed through the type system rather than having objects "automagically"
handled for you via implicit ownership of raw pointers.
when you only need basic Put/Get operations and don't need the more advanced TFile/TDirectory functionalities.
It provides:
- a simple interface that makes it easy to do things right and hard to do things wrong;
- more robustness and better error reporting for those operations;
- clearer ownership semantics expressed through the type system.

RFile doesn't try to cover the entirety of use cases covered by TFile/TDirectory/TDirectoryFile and is not
a 1:1 replacement for them. It is meant to simplify the most common use cases and make them easier to handle by
minimizing the amount of ROOT-specific quirks and conforming to more standard C++ practices.
RFile doesn't cover the entirety of use cases covered by TFile/TDirectory/TDirectoryFile and is not
a 1:1 replacement for them. It is meant to simplify the most common use cases by following newer standard C++
practices.

## Ownership model

Expand All @@ -65,13 +64,11 @@ file).

## Directories

Differently from TFile, the RFile class itself is not also a "directory". In fact, there is no RDirectory class at all.

Directories are still an existing concept in RFile (since they are a concept in the ROOT binary format),
but they are usually interacted with indirectly, via the use of filesystem-like string-based paths. If you Put an object
in an RFile under the path "path/to/object", "object" will be stored under directory "to" which is in turn stored under
directory "path". This hierarchy is encoded in the ROOT file itself and it can provide some optimization and/or
conveniencies when querying objects.
Even though there is no equivalent of TDirectory in the RFile API, directories are still an existing concept in RFile
(since they are a concept in the ROOT binary format). However they are for now only interacted with indirectly, via the
use of filesystem-like string-based paths. If you Put an object in an RFile under the path "path/to/object", "object"
will be stored under directory "to" which is in turn stored under directory "path". This hierarchy is encoded in the
ROOT file itself and it can provide some optimization and/or conveniencies when querying objects.

For the most part, it is convenient to think about RFile in terms of a key-value storage where string-based paths are
used to refer to arbitrary objects. However, given the hierarchical nature of ROOT files, certain filesystem-like
Expand All @@ -96,8 +93,11 @@ auto myObj = file->Get<TH1D>("h");
~~~
*/
class RFile final {
/// Flags used in PutInternal()
enum PutFlags {
/// When encountering an object at the specified path, overwrite it with the new one instead of erroring out.
kPutAllowOverwrite = 0x1,
/// When overwriting an object, preserve the existing one and create a new cycle, rather than removing it.
kPutOverwriteKeepCycle = 0x2,
};

Expand Down
2 changes: 1 addition & 1 deletion io/io/src/RFile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ static void CheckExtension(std::string_view path)
}

if (!ROOT::EndsWith(path, ".root")) {
R__LOG_WARNING(RFileLog()) << "ROOT::RFile only supports ROOT files. The preferred file extension is \".root\"";
R__LOG_INFO(RFileLog()) << "ROOT::RFile only supports ROOT files. The preferred file extension is \".root\"";
}
}

Expand Down
15 changes: 8 additions & 7 deletions io/io/test/rfile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <ROOT/RError.hxx>
#include <ROOT/RFile.hxx>
#include <ROOT/TestSupport.hxx>
#include <numeric>
#include <ROOT/RLogger.hxx>

using ROOT::Experimental::RFile;

Expand Down Expand Up @@ -74,9 +74,6 @@ TEST(RFile, OpenInexistent)
{
FileRaii fileGuard("does_not_exist.root");

// make sure that the file really does not exist, in case a previous test didn't clean it up.
gSystem->Unlink(fileGuard.GetPath().c_str());

ROOT::TestSupport::CheckDiagsRAII diags;
diags.optionalDiag(kSysError, "TFile::TFile", "", false);
diags.optionalDiag(kError, "TFile::TFile", "", false);
Expand All @@ -101,7 +98,10 @@ TEST(RFile, OpenInexistent)
}

// This succeeds because Update creates the file if it doesn't exist.
EXPECT_NO_THROW(RFile::Update("does_not_exist.root"));
FileRaii fileGuard2("created_by_update.root");
// in case a previous run of the test failed to clean up, make sure the file doesn't exist:
gSystem->Unlink(fileGuard2.GetPath().c_str());
EXPECT_NO_THROW(RFile::Update(fileGuard2.GetPath()));
}

TEST(RFile, OpenForWriting)
Expand Down Expand Up @@ -148,8 +148,8 @@ TEST(RFile, CheckNoAutoRegistrationRead)
auto file = RFile::Open(fileGuard.GetPath());
EXPECT_EQ(gDirectory, gROOT);
auto hist = file->Get<TH1D>("hist");
EXPECT_EQ(hist->GetDirectory(), nullptr);
ASSERT_NE(hist, nullptr);
EXPECT_EQ(hist->GetDirectory(), nullptr);
EXPECT_FLOAT_EQ(hist->GetEntries(), 1);
}
// no double free should happen when ROOT exits
Expand Down Expand Up @@ -265,10 +265,11 @@ TEST(RFile, PutOverwrite)

TEST(RFile, WrongExtension)
{
ROOT::RLogScopedVerbosity logVerb(ROOT::ELogLevel::kInfo);
{
FileRaii fileGuard("test_rfile_wrong.root.1");
ROOT::TestSupport::CheckDiagsRAII diagsRaii;
diagsRaii.requiredDiag(kWarning, "ROOT.File", "preferred file extension is \".root\"", false);
diagsRaii.requiredDiag(kInfo, "ROOT.File", "preferred file extension is \".root\"", false);
RFile::Recreate(fileGuard.GetPath());
}
{
Expand Down