Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RMiniFile.hxx
Go to the documentation of this file.
1/// \file ROOT/RMiniFile.hxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2019-12-22
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#ifndef ROOT7_RMiniFile
17#define ROOT7_RMiniFile
18
19#include <ROOT/RError.hxx>
20#include <ROOT/RNTuple.hxx>
22#include <ROOT/RSpan.hxx>
23#include <string_view>
24
25#include <cstdint>
26#include <cstdio>
27#include <memory>
28#include <string>
29
30class TDirectory;
31class TFileMergeInfo;
33
34namespace ROOT {
35
36namespace Internal {
37class RRawFile;
38}
39
40namespace Experimental {
41
42class RNTupleWriteOptions;
43
44namespace Internal {
45/// Holds status information of an open ROOT file during writing
46struct RTFileControlBlock;
47
48// clang-format off
49/**
50\class ROOT::Experimental::Internal::RMiniFileReader
51\ingroup NTuple
52\brief Read RNTuple data blocks from a TFile container, provided by a RRawFile
53
54A RRawFile is used for the byte access. The class implements a minimal subset of TFile, enough to extract
55RNTuple data keys.
56*/
57// clang-format on
59private:
60 /// The raw file used to read byte ranges
62 /// Indicates whether the file is a TFile container or an RNTuple bare file
63 bool fIsBare = false;
64 /// If `fMaxKeySize > 0` and ReadBuffer attempts to read `nbytes > maxKeySize`, it will assume the
65 /// blob being read is chunked and read all the chunks into the buffer. This is symmetrical to
66 /// what happens in `RNTupleFileWriter::WriteBlob()`.
67 std::uint64_t fMaxKeySize = 0;
68
69 /// Used when the file container turns out to be a bare file
71 /// Used when the file turns out to be a TFile container. The ntuplePath variable is either the ntuple name
72 /// or an ntuple name preceded by a directory (`myNtuple` or `foo/bar/myNtuple` or `/foo/bar/myNtuple`)
74
75 /// Searches for a key with the given name and type in the key index of the directory starting at offsetDir.
76 /// The offset points to the start of the TDirectory DATA section, without the key and without the name and title
77 /// of the TFile record (the root directory).
78 /// Return 0 if the key was not found. Otherwise returns the offset of found key.
79 std::uint64_t SearchInDirectory(std::uint64_t &offsetDir, std::string_view keyName, std::string_view typeName);
80
81public:
82 RMiniFileReader() = default;
83 /// Uses the given raw file to read byte ranges
85 /// Extracts header and footer location for the RNTuple identified by ntupleName
86 RResult<RNTuple> GetNTuple(std::string_view ntupleName);
87 /// Reads a given byte range from the file into the provided memory buffer.
88 /// If `nbytes > fMaxKeySize` it will perform chunked read from multiple blobs,
89 /// whose addresses are listed at the end of the first chunk.
90 void ReadBuffer(void *buffer, size_t nbytes, std::uint64_t offset);
91
92 std::uint64_t GetMaxKeySize() const { return fMaxKeySize; }
93 /// If the reader is not used to retrieve the anchor, we need to set the max key size manually
95};
96
97// clang-format off
98/**
99\class ROOT::Experimental::Internal::RNTupleFileWriter
100\ingroup NTuple
101\brief Write RNTuple data blocks in a TFile or a bare file container
102
103The writer can create a new TFile container for an RNTuple or add an RNTuple to an existing TFile.
104Creating a single RNTuple in a new TFile container can be done with a C file stream without a TFile class.
105Updating an existing TFile requires a proper TFile object. Also, writing a remote file requires a proper TFile object.
106A stand-alone version of RNTuple can remove the TFile based writer.
107*/
108// clang-format on
110private:
111 struct RFileProper {
112 /// A sub directory in fFile or nullptr if the data is stored in the root directory of the file
114 /// Low-level writing using a TFile
115 void Write(const void *buffer, size_t nbytes, std::int64_t offset);
116 /// Writes an RBlob opaque key with the provided buffer as data record and returns the offset of the record
117 std::uint64_t WriteKey(const void *buffer, size_t nbytes, size_t len);
118 operator bool() const { return fDirectory; }
119 };
120
121 struct RFileSimple {
122 /// Direct I/O requires that all buffers and write lengths are aligned. It seems 512 byte alignment is the minimum
123 /// for Direct I/O to work, but further testing showed that it results in worse performance than 4kB.
124 static constexpr int kBlockAlign = 4096;
125 /// During commit, WriteTFileKeysList() updates fNBytesKeys and fSeekKeys of the RTFFile located at
126 /// fSeekFileRecord. Given that the TFile key starts at offset 100 and the file name, which is written twice,
127 /// is shorter than 255 characters, we should need at most ~600 bytes. However, the header also needs to be
128 /// aligned to kBlockAlign...
129 static constexpr std::size_t kHeaderBlockSize = 4096;
130
131 // fHeaderBlock and fBlock are raw pointers because we have to manually call operator new and delete.
132 unsigned char *fHeaderBlock = nullptr;
133 std::size_t fBlockSize = 0;
134 std::uint64_t fBlockOffset = 0;
135 unsigned char *fBlock = nullptr;
136
137 /// For the simplest cases, a C file stream can be used for writing
138 FILE *fFile = nullptr;
139 /// Whether the C file stream has been opened with Direct I/O, introducing alignment requirements.
140 bool fDirectIO = false;
141 /// Keeps track of the seek offset
142 std::uint64_t fFilePos = 0;
143 /// Keeps track of the next key offset
144 std::uint64_t fKeyOffset = 0;
145 /// Keeps track of TFile control structures, which need to be updated on committing the data set
146 std::unique_ptr<ROOT::Experimental::Internal::RTFileControlBlock> fControlBlock;
147
149 RFileSimple(const RFileSimple &other) = delete;
153 ~RFileSimple();
154
155 void AllocateBuffers(std::size_t bufferSize);
156 void Flush();
157
158 /// Writes bytes in the open stream, either at fFilePos or at the given offset
159 void Write(const void *buffer, size_t nbytes, std::int64_t offset = -1);
160 /// Writes a TKey including the data record, given by buffer, into fFile; returns the file offset to the payload.
161 /// The payload is already compressed
162 std::uint64_t WriteKey(const void *buffer, std::size_t nbytes, std::size_t len, std::int64_t offset = -1,
163 std::uint64_t directoryOffset = 100, const std::string &className = "",
164 const std::string &objectName = "", const std::string &title = "");
165 operator bool() const { return fFile; }
166 };
167
168 // TODO(jblomer): wrap in an std::variant with C++17
169 /// For updating existing files and for storing more than just an RNTuple in the file
171 /// For simple use cases, survives without libRIO dependency
173 /// A simple file can either be written as TFile container or as NTuple bare file
174 bool fIsBare = false;
175 /// The identifier of the RNTuple; A single writer object can only write a single RNTuple but multiple
176 /// writers can operate on the same file if (and only if) they use a proper TFile object for writing.
177 std::string fNTupleName;
178 /// The file name without parent directory; only required when writing with a C file stream
179 std::string fFileName;
180 /// Header and footer location of the ntuple, written on Commit()
182 /// Set of streamer info records that should be written to the file.
183 /// The RNTuple class description is always present.
185
186 explicit RNTupleFileWriter(std::string_view name, std::uint64_t maxKeySize);
187
188 /// For a TFile container written by a C file stream, write the header and TFile object
190 /// The only key that will be visible in file->ls()
191 void WriteTFileNTupleKey();
192 /// Write the TList with the RNTuple key
193 void WriteTFileKeysList();
194 /// Write the compressed streamer info record with the description of the RNTuple class
196 /// Last record in the file
197 void WriteTFileFreeList();
198 /// For a bare file, which is necessarily written by a C file stream, write file header
200
201public:
202 /// For testing purposes, RNTuple data can be written into a bare file container instead of a ROOT file
203 enum class EContainerFormat {
204 kTFile, // ROOT TFile
205 kBare, // A thin envelope supporting a single RNTuple only
206 };
207
208 /// Create or truncate the local file given by path with the new empty RNTuple identified by ntupleName.
209 /// Uses a C stream for writing
210 static std::unique_ptr<RNTupleFileWriter> Recreate(std::string_view ntupleName, std::string_view path,
212 const RNTupleWriteOptions &options);
213 /// The directory parameter can also be a TFile object (TFile inherits from TDirectory).
214 static std::unique_ptr<RNTupleFileWriter>
215 Append(std::string_view ntupleName, TDirectory &fileOrDirectory, std::uint64_t maxKeySize);
216
222
223 /// Writes the compressed header and registeres its location; lenHeader is the size of the uncompressed header.
224 std::uint64_t WriteNTupleHeader(const void *data, size_t nbytes, size_t lenHeader);
225 /// Writes the compressed footer and registeres its location; lenFooter is the size of the uncompressed footer.
226 std::uint64_t WriteNTupleFooter(const void *data, size_t nbytes, size_t lenFooter);
227 /// Writes a new record as an RBlob key into the file
228 std::uint64_t WriteBlob(const void *data, size_t nbytes, size_t len);
229 /// Reserves a new record as an RBlob key in the file.
230 std::uint64_t ReserveBlob(size_t nbytes, size_t len);
231 /// Write into a reserved record; the caller is responsible for making sure that the written byte range is in the
232 /// previously reserved key.
233 void WriteIntoReservedBlob(const void *buffer, size_t nbytes, std::int64_t offset);
234 /// Ensures that the streamer info records passed as argument are written to the file
236 /// Writes the RNTuple key to the file so that the header and footer keys can be found
237 void Commit();
238};
239
240} // namespace Internal
241} // namespace Experimental
242} // namespace ROOT
243
244#endif
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
char name[80]
Definition TGX11.cxx:110
Read RNTuple data blocks from a TFile container, provided by a RRawFile.
Definition RMiniFile.hxx:58
bool fIsBare
Indicates whether the file is a TFile container or an RNTuple bare file.
Definition RMiniFile.hxx:63
void SetMaxKeySize(std::uint64_t maxKeySize)
If the reader is not used to retrieve the anchor, we need to set the max key size manually.
Definition RMiniFile.hxx:94
std::uint64_t SearchInDirectory(std::uint64_t &offsetDir, std::string_view keyName, std::string_view typeName)
Searches for a key with the given name and type in the key index of the directory starting at offsetD...
RResult< RNTuple > GetNTupleBare(std::string_view ntupleName)
Used when the file container turns out to be a bare file.
std::uint64_t fMaxKeySize
If fMaxKeySize > 0 and ReadBuffer attempts to read nbytes > maxKeySize, it will assume the blob being...
Definition RMiniFile.hxx:67
RResult< RNTuple > GetNTuple(std::string_view ntupleName)
Extracts header and footer location for the RNTuple identified by ntupleName.
ROOT::Internal::RRawFile * fRawFile
The raw file used to read byte ranges.
Definition RMiniFile.hxx:61
RResult< RNTuple > GetNTupleProper(std::string_view ntuplePath)
Used when the file turns out to be a TFile container.
void ReadBuffer(void *buffer, size_t nbytes, std::uint64_t offset)
Reads a given byte range from the file into the provided memory buffer.
Write RNTuple data blocks in a TFile or a bare file container.
RNTupleFileWriter(std::string_view name, std::uint64_t maxKeySize)
std::uint64_t WriteBlob(const void *data, size_t nbytes, size_t len)
Writes a new record as an RBlob key into the file.
std::string fNTupleName
The identifier of the RNTuple; A single writer object can only write a single RNTuple but multiple wr...
std::string fFileName
The file name without parent directory; only required when writing with a C file stream.
std::uint64_t WriteNTupleFooter(const void *data, size_t nbytes, size_t lenFooter)
Writes the compressed footer and registeres its location; lenFooter is the size of the uncompressed f...
void WriteTFileKeysList()
Write the TList with the RNTuple key.
void UpdateStreamerInfos(const RNTupleSerializer::StreamerInfoMap_t &streamerInfos)
Ensures that the streamer info records passed as argument are written to the file.
void Commit()
Writes the RNTuple key to the file so that the header and footer keys can be found.
RFileProper fFileProper
For updating existing files and for storing more than just an RNTuple in the file.
std::uint64_t ReserveBlob(size_t nbytes, size_t len)
Reserves a new record as an RBlob key in the file.
RFileSimple fFileSimple
For simple use cases, survives without libRIO dependency.
RNTupleFileWriter(const RNTupleFileWriter &other)=delete
void WriteTFileNTupleKey()
The only key that will be visible in file->ls()
void WriteTFileFreeList()
Last record in the file.
EContainerFormat
For testing purposes, RNTuple data can be written into a bare file container instead of a ROOT file.
RNTupleFileWriter & operator=(const RNTupleFileWriter &other)=delete
bool fIsBare
A simple file can either be written as TFile container or as NTuple bare file.
static std::unique_ptr< RNTupleFileWriter > Recreate(std::string_view ntupleName, std::string_view path, EContainerFormat containerFormat, const RNTupleWriteOptions &options)
Create or truncate the local file given by path with the new empty RNTuple identified by ntupleName.
static std::unique_ptr< RNTupleFileWriter > Append(std::string_view ntupleName, TDirectory &fileOrDirectory, std::uint64_t maxKeySize)
The directory parameter can also be a TFile object (TFile inherits from TDirectory).
void WriteTFileSkeleton(int defaultCompression)
For a TFile container written by a C file stream, write the header and TFile object.
void WriteBareFileSkeleton(int defaultCompression)
For a bare file, which is necessarily written by a C file stream, write file header.
void WriteTFileStreamerInfo()
Write the compressed streamer info record with the description of the RNTuple class.
std::uint64_t WriteNTupleHeader(const void *data, size_t nbytes, size_t lenHeader)
Writes the compressed header and registeres its location; lenHeader is the size of the uncompressed h...
RNTuple fNTupleAnchor
Header and footer location of the ntuple, written on Commit()
RNTupleFileWriter(RNTupleFileWriter &&other)=delete
RNTupleFileWriter & operator=(RNTupleFileWriter &&other)=delete
void WriteIntoReservedBlob(const void *buffer, size_t nbytes, std::int64_t offset)
Write into a reserved record; the caller is responsible for making sure that the written byte range i...
RNTupleSerializer::StreamerInfoMap_t fStreamerInfoMap
Set of streamer info records that should be written to the file.
std::map< Int_t, TVirtualStreamerInfo * > StreamerInfoMap_t
Common user-tunable settings for storing ntuples.
The RRawFile provides read-only access to local and remote files.
Definition RRawFile.hxx:43
Representation of an RNTuple data set in a ROOT file.
Definition RNTuple.hxx:69
Describe directory structure in memory.
Definition TDirectory.h:45
Abstract Interface class describing Streamer information for one class.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
void Write(const void *buffer, size_t nbytes, std::int64_t offset)
Low-level writing using a TFile.
std::uint64_t WriteKey(const void *buffer, size_t nbytes, size_t len)
Writes an RBlob opaque key with the provided buffer as data record and returns the offset of the reco...
TDirectory * fDirectory
A sub directory in fFile or nullptr if the data is stored in the root directory of the file.
bool fDirectIO
Whether the C file stream has been opened with Direct I/O, introducing alignment requirements.
std::unique_ptr< ROOT::Experimental::Internal::RTFileControlBlock > fControlBlock
Keeps track of TFile control structures, which need to be updated on committing the data set.
FILE * fFile
For the simplest cases, a C file stream can be used for writing.
RFileSimple & operator=(const RFileSimple &other)=delete
std::uint64_t fKeyOffset
Keeps track of the next key offset.
static constexpr int kBlockAlign
Direct I/O requires that all buffers and write lengths are aligned.
void Write(const void *buffer, size_t nbytes, std::int64_t offset=-1)
Writes bytes in the open stream, either at fFilePos or at the given offset.
static constexpr std::size_t kHeaderBlockSize
During commit, WriteTFileKeysList() updates fNBytesKeys and fSeekKeys of the RTFFile located at fSeek...
std::uint64_t fFilePos
Keeps track of the seek offset.
std::uint64_t WriteKey(const void *buffer, std::size_t nbytes, std::size_t len, std::int64_t offset=-1, std::uint64_t directoryOffset=100, const std::string &className="", const std::string &objectName="", const std::string &title="")
Writes a TKey including the data record, given by buffer, into fFile; returns the file offset to the ...
RFileSimple & operator=(RFileSimple &&other)=delete