|
||||
File indexing completed on 2025-01-18 10:10:45
0001 /// \file ROOT/RMiniFile.hxx 0002 /// \ingroup NTuple ROOT7 0003 /// \author Jakob Blomer <jblomer@cern.ch> 0004 /// \date 2019-12-22 0005 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback 0006 /// is welcome! 0007 0008 /************************************************************************* 0009 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * 0010 * All rights reserved. * 0011 * * 0012 * For the licensing terms see $ROOTSYS/LICENSE. * 0013 * For the list of contributors see $ROOTSYS/README/CREDITS. * 0014 *************************************************************************/ 0015 0016 #ifndef ROOT7_RMiniFile 0017 #define ROOT7_RMiniFile 0018 0019 #include <ROOT/RError.hxx> 0020 #include <ROOT/RNTuple.hxx> 0021 #include <string_view> 0022 0023 #include <cstdint> 0024 #include <cstdio> 0025 #include <memory> 0026 #include <string> 0027 0028 class TCollection; 0029 class TFile; 0030 class TFileMergeInfo; 0031 0032 namespace ROOT { 0033 0034 namespace Internal { 0035 class RRawFile; 0036 } 0037 0038 namespace Experimental { 0039 0040 namespace Internal { 0041 /// Holds status information of an open ROOT file during writing 0042 struct RTFileControlBlock; 0043 0044 // clang-format off 0045 /** 0046 \class ROOT::Experimental::Internal::RMiniFileReader 0047 \ingroup NTuple 0048 \brief Read RNTuple data blocks from a TFile container, provided by a RRawFile 0049 0050 A RRawFile is used for the byte access. The class implements a minimal subset of TFile, enough to extract 0051 RNTuple data keys. 0052 */ 0053 // clang-format on 0054 class RMiniFileReader { 0055 private: 0056 /// The raw file used to read byte ranges 0057 ROOT::Internal::RRawFile *fRawFile = nullptr; 0058 /// Indicates whether the file is a TFile container or an RNTuple bare file 0059 bool fIsBare = false; 0060 /// Used when the file container turns out to be a bare file 0061 RResult<RNTuple> GetNTupleBare(std::string_view ntupleName); 0062 /// Used when the file turns out to be a TFile container 0063 RResult<RNTuple> GetNTupleProper(std::string_view ntupleName); 0064 0065 RNTuple CreateAnchor(std::uint16_t versionEpoch, std::uint16_t versionMajor, std::uint16_t versionMinor, 0066 std::uint16_t versionPatch, std::uint64_t seekHeader, std::uint64_t nbytesHeader, 0067 std::uint64_t lenHeader, std::uint64_t seekFooter, std::uint64_t nbytesFooter, 0068 std::uint64_t lenFooter, std::uint64_t checksum); 0069 0070 public: 0071 RMiniFileReader() = default; 0072 /// Uses the given raw file to read byte ranges 0073 explicit RMiniFileReader(ROOT::Internal::RRawFile *rawFile); 0074 /// Extracts header and footer location for the RNTuple identified by ntupleName 0075 RResult<RNTuple> GetNTuple(std::string_view ntupleName); 0076 /// Reads a given byte range from the file into the provided memory buffer 0077 void ReadBuffer(void *buffer, size_t nbytes, std::uint64_t offset); 0078 }; 0079 0080 0081 // clang-format off 0082 /** 0083 \class ROOT::Experimental::Internal::RNTupleFileWriter 0084 \ingroup NTuple 0085 \brief Write RNTuple data blocks in a TFile or a bare file container 0086 0087 The writer can create a new TFile container for an RNTuple or add an RNTuple to an existing TFile. 0088 Creating a single RNTuple in a new TFile container can be done with a C file stream without a TFile class. 0089 Updating an existing TFile requires a proper TFile object. Also, writing a remote file requires a proper TFile object. 0090 A stand-alone version of RNTuple can remove the TFile based writer. 0091 */ 0092 // clang-format on 0093 class RNTupleFileWriter { 0094 private: 0095 struct RFileProper { 0096 TFile *fFile = nullptr; 0097 /// Low-level writing using a TFile 0098 void Write(const void *buffer, size_t nbytes, std::int64_t offset); 0099 /// Writes an RBlob opaque key with the provided buffer as data record and returns the offset of the record 0100 std::uint64_t WriteKey(const void *buffer, size_t nbytes, size_t len); 0101 operator bool() const { return fFile; } 0102 }; 0103 0104 struct RFileSimple { 0105 /// For the simplest cases, a C file stream can be used for writing 0106 FILE *fFile = nullptr; 0107 /// Keeps track of the seek offset 0108 std::uint64_t fFilePos = 0; 0109 /// Keeps track of the next key offset 0110 std::uint64_t fKeyOffset = 0; 0111 /// Keeps track of TFile control structures, which need to be updated on committing the data set 0112 std::unique_ptr<ROOT::Experimental::Internal::RTFileControlBlock> fControlBlock; 0113 0114 RFileSimple() = default; 0115 RFileSimple(const RFileSimple &other) = delete; 0116 RFileSimple(RFileSimple &&other) = delete; 0117 RFileSimple &operator =(const RFileSimple &other) = delete; 0118 RFileSimple &operator =(RFileSimple &&other) = delete; 0119 ~RFileSimple(); 0120 0121 /// Writes bytes in the open stream, either at fFilePos or at the given offset 0122 void Write(const void *buffer, size_t nbytes, std::int64_t offset = -1); 0123 /// Writes a TKey including the data record, given by buffer, into fFile; returns the file offset to the payload. 0124 /// The payload is already compressed 0125 std::uint64_t WriteKey(const void *buffer, std::size_t nbytes, std::size_t len, std::int64_t offset = -1, 0126 std::uint64_t directoryOffset = 100, 0127 const std::string &className = "", 0128 const std::string &objectName = "", 0129 const std::string &title = ""); 0130 operator bool() const { return fFile; } 0131 }; 0132 0133 // TODO(jblomer): wrap in an std::variant with C++17 0134 /// For updating existing files and for storing more than just an RNTuple in the file 0135 RFileProper fFileProper; 0136 /// For simple use cases, survives without libRIO dependency 0137 RFileSimple fFileSimple; 0138 /// A simple file can either be written as TFile container or as NTuple bare file 0139 bool fIsBare = false; 0140 /// The identifier of the RNTuple; A single writer object can only write a single RNTuple but multiple 0141 /// writers can operate on the same file if (and only if) they use a proper TFile object for writing. 0142 std::string fNTupleName; 0143 /// The file name without parent directory; only required when writing with a C file stream 0144 std::string fFileName; 0145 /// Header and footer location of the ntuple, written on Commit() 0146 RNTuple fNTupleAnchor; 0147 0148 explicit RNTupleFileWriter(std::string_view name); 0149 0150 /// For a TFile container written by a C file stream, write the header and TFile object 0151 void WriteTFileSkeleton(int defaultCompression); 0152 /// The only key that will be visible in file->ls() 0153 void WriteTFileNTupleKey(); 0154 /// Write the TList with the RNTuple key 0155 void WriteTFileKeysList(); 0156 /// Write the compressed streamer info record with the description of the RNTuple class 0157 void WriteTFileStreamerInfo(); 0158 /// Last record in the file 0159 void WriteTFileFreeList(); 0160 /// For a bare file, which is necessarily written by a C file stream, write file header 0161 void WriteBareFileSkeleton(int defaultCompression); 0162 0163 public: 0164 /// For testing purposes, RNTuple data can be written into a bare file container instead of a ROOT file 0165 enum class EContainerFormat { 0166 kTFile, // ROOT TFile 0167 kBare, // A thin envelope supporting a single RNTuple only 0168 }; 0169 0170 /// Create or truncate the local file given by path with the new empty RNTuple identified by ntupleName. 0171 /// Uses a C stream for writing 0172 static RNTupleFileWriter *Recreate(std::string_view ntupleName, std::string_view path, int defaultCompression, 0173 EContainerFormat containerFormat); 0174 /// Add a new RNTuple identified by ntupleName to the existing TFile. 0175 static RNTupleFileWriter *Append(std::string_view ntupleName, TFile &file); 0176 0177 RNTupleFileWriter(const RNTupleFileWriter &other) = delete; 0178 RNTupleFileWriter(RNTupleFileWriter &&other) = delete; 0179 RNTupleFileWriter &operator =(const RNTupleFileWriter &other) = delete; 0180 RNTupleFileWriter &operator =(RNTupleFileWriter &&other) = delete; 0181 ~RNTupleFileWriter(); 0182 0183 /// Writes the compressed header and registeres its location; lenHeader is the size of the uncompressed header. 0184 std::uint64_t WriteNTupleHeader(const void *data, size_t nbytes, size_t lenHeader); 0185 /// Writes the compressed footer and registeres its location; lenFooter is the size of the uncompressed footer. 0186 std::uint64_t WriteNTupleFooter(const void *data, size_t nbytes, size_t lenFooter); 0187 /// Writes a new record as an RBlob key into the file 0188 std::uint64_t WriteBlob(const void *data, size_t nbytes, size_t len); 0189 /// Reserves a new record as an RBlob key in the file. 0190 std::uint64_t ReserveBlob(size_t nbytes, size_t len); 0191 /// Write into a reserved record; the caller is responsible for making sure that the written byte range is in the 0192 /// previously reserved key. 0193 void WriteIntoReservedBlob(const void *buffer, size_t nbytes, std::int64_t offset); 0194 /// Writes the RNTuple key to the file so that the header and footer keys can be found 0195 void Commit(); 0196 }; 0197 0198 } // namespace Internal 0199 } // namespace Experimental 0200 } // namespace ROOT 0201 0202 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |