The Gaudi Framework  v41r0 (bdbe7744)
Loading...
Searching...
No Matches
Gaudi::NTuple::DiskBuffer::Reader Class Reference

#include </builds/gaudi/Gaudi/GaudiUtils/include/Gaudi/NTuple/DiskBuffer.h>

Collaboration diagram for Gaudi::NTuple::DiskBuffer::Reader:

Public Member Functions

 Reader (std::filesystem::path path)
 Open path and validate the preamble.
 ~Reader ()
 Reader (const Reader &)=delete
Reader & operator= (const Reader &)=delete
const std::string & header () const
bool compressed () const
bool next (std::span< const char > &record)
 Read the next record; false at a clean end of file. A partial block throws.
std::uint64_t entries () const
const std::filesystem::path & path () const

Private Member Functions

std::size_t read (void *dest, std::size_t bytes)
bool readBlock ()

Private Attributes

std::filesystem::path m_path
FileHandle m_file
std::uintmax_t m_size { 0 }
std::string m_header
bool m_compressed { false }
std::vector< char > m_stored
std::vector< char > m_block
std::size_t m_pos { 0 }
std::uint64_t m_entries { 0 }

Detailed Description

Definition at line 107 of file DiskBuffer.h.

Constructor & Destructor Documentation

◆ Reader() [1/2]

Reader::Reader ( std::filesystem::path path)
explicit

Open path and validate the preamble.

Definition at line 177 of file NTupleDiskBuffer.cpp.

177 : m_path( std::move( path ) ) {
178 m_file.reset( std::fopen( m_path.c_str(), "rb" ) );
179 if ( !m_file ) throw Error( m_path, "cannot open buffer file", errno );
180 std::setvbuf( m_file.get(), nullptr, _IOFBF, READ_BUFFER );
181 std::error_code ec;
182 m_size = std::filesystem::file_size( m_path, ec );
183 if ( ec ) m_size = 0;
184 char preamble[PREAMBLE];
185 if ( read( preamble, PREAMBLE ) != PREAMBLE || std::memcmp( preamble, MAGIC, sizeof( MAGIC ) ) != 0 )
186 throw Error( m_path, "not a Gaudi ntuple buffer file" );
187 const char* words = preamble + sizeof( MAGIC );
188 if ( get32( words ) != BYTE_ORDER_MARK ) throw Error( m_path, "buffer file has foreign byte order" );
189 if ( get32( words + 4 ) != VERSION ) throw Error( m_path, "unsupported buffer file version" );
190 switch ( get32( words + 8 ) ) {
191 case CODEC_NONE:
192 break;
193 case CODEC_ZSTD:
194 if ( !zstdAvailable() ) throw Error( m_path, "compressed buffer file but zstd is not available in this build" );
195 m_compressed = true;
196 break;
197 default:
198 throw Error( m_path, "unknown buffer file compression" );
199 }
200 const std::uint32_t headerLen = get32( words + 12 );
201 if ( headerLen > MAX_HEADER ) throw Error( m_path, "corrupt header length" );
202 m_header.resize( headerLen );
203 if ( read( m_header.data(), headerLen ) != headerLen ) throw Error( m_path, "truncated header" );
204}
std::size_t read(void *dest, std::size_t bytes)
const std::filesystem::path & path() const
Definition DiskBuffer.h:122
std::filesystem::path m_path
Definition DiskBuffer.h:128
bool zstdAvailable()
Whether this build can write and read compressed blocks.

◆ ~Reader()

Reader::~Reader ( )
default

◆ Reader() [2/2]

Gaudi::NTuple::DiskBuffer::Reader::Reader ( const Reader & )
delete

Member Function Documentation

◆ compressed()

bool Gaudi::NTuple::DiskBuffer::Reader::compressed ( ) const
inline

Definition at line 116 of file DiskBuffer.h.

116{ return m_compressed; }

◆ entries()

std::uint64_t Gaudi::NTuple::DiskBuffer::Reader::entries ( ) const
inline

Definition at line 121 of file DiskBuffer.h.

121{ return m_entries; }

◆ header()

const std::string & Gaudi::NTuple::DiskBuffer::Reader::header ( ) const
inline

Definition at line 115 of file DiskBuffer.h.

115{ return m_header; }

◆ next()

bool Reader::next ( std::span< const char > & record)

Read the next record; false at a clean end of file. A partial block throws.

Definition at line 251 of file NTupleDiskBuffer.cpp.

251 {
252 while ( m_pos == m_block.size() ) {
253 if ( !readBlock() ) return false;
254 }
255 if ( m_block.size() - m_pos < sizeof( std::uint32_t ) ) throw Error( m_path, "corrupt block: bad record length" );
256 const std::uint32_t len = get32( m_block.data() + m_pos );
257 m_pos += sizeof( std::uint32_t );
258 if ( m_block.size() - m_pos < len ) throw Error( m_path, "corrupt block: record crosses block end" );
259 record = std::span<const char>( m_block.data() + m_pos, len );
260 m_pos += len;
261 ++m_entries;
262 return true;
263}

◆ operator=()

Reader & Gaudi::NTuple::DiskBuffer::Reader::operator= ( const Reader & )
delete

◆ path()

const std::filesystem::path & Gaudi::NTuple::DiskBuffer::Reader::path ( ) const
inline

Definition at line 122 of file DiskBuffer.h.

122{ return m_path; }

◆ read()

std::size_t Reader::read ( void * dest,
std::size_t bytes )
private

Definition at line 208 of file NTupleDiskBuffer.cpp.

208 {
209 const std::size_t got = std::fread( dest, 1, bytes, m_file.get() );
210 if ( got != bytes && std::ferror( m_file.get() ) ) throw Error( m_path, "read failed", errno );
211 return got;
212}

◆ readBlock()

bool Reader::readBlock ( )
private

Definition at line 214 of file NTupleDiskBuffer.cpp.

214 {
215 char hdr[BLOCK_HEADER];
216 const std::size_t got = read( hdr, sizeof( hdr ) );
217 if ( got == 0 ) return false;
218 if ( got != sizeof( hdr ) ) throw Error( m_path, "truncated block header" );
219 const std::uint32_t stored = get32( hdr ), raw = get32( hdr + 4 );
220 // check the lengths before allocating: a corrupt header must not turn into a huge resize
221 if ( stored > MAX_STORED || raw > MAX_STORED ) throw Error( m_path, "corrupt block header" );
222 const long pos = std::ftell( m_file.get() );
223 if ( m_size > 0 && pos >= 0 && stored > m_size - static_cast<std::uintmax_t>( pos ) )
224 throw Error( m_path, "truncated block" );
225 m_pos = 0;
226 if ( !m_compressed ) {
227 if ( stored != raw ) throw Error( m_path, "corrupt block header" );
228 if ( m_block.size() < raw ) m_block.resize( raw );
229 if ( read( m_block.data(), raw ) != raw ) throw Error( m_path, "truncated block" );
230 m_block.resize( raw );
231 return true;
232 }
233#ifdef GAUDI_USE_ZSTD
234 if ( m_stored.size() < stored ) m_stored.resize( stored );
235 if ( read( m_stored.data(), stored ) != stored ) throw Error( m_path, "truncated block" );
236 // the frame knows what it unpacks to: trust that over the block header
237 const unsigned long long content = ZSTD_getFrameContentSize( m_stored.data(), stored );
238 if ( content != ZSTD_CONTENTSIZE_UNKNOWN && content != ZSTD_CONTENTSIZE_ERROR && content != raw )
239 throw Error( m_path, "corrupt block header" );
240 if ( m_block.size() < raw ) m_block.resize( raw );
241 const std::size_t n = ZSTD_decompress( m_block.data(), raw, m_stored.data(), stored );
242 if ( ZSTD_isError( n ) ) throw Error( m_path, std::string( "corrupt block: " ) + ZSTD_getErrorName( n ) );
243 if ( n != raw ) throw Error( m_path, "corrupt block: size mismatch" );
244 m_block.resize( raw );
245 return true;
246#else
247 throw Error( m_path, "compressed buffer file but zstd is not available in this build" );
248#endif
249}

Member Data Documentation

◆ m_block

std::vector<char> Gaudi::NTuple::DiskBuffer::Reader::m_block
private

Definition at line 134 of file DiskBuffer.h.

◆ m_compressed

bool Gaudi::NTuple::DiskBuffer::Reader::m_compressed { false }
private

Definition at line 132 of file DiskBuffer.h.

132{ false };

◆ m_entries

std::uint64_t Gaudi::NTuple::DiskBuffer::Reader::m_entries { 0 }
private

Definition at line 136 of file DiskBuffer.h.

136{ 0 };

◆ m_file

FileHandle Gaudi::NTuple::DiskBuffer::Reader::m_file
private

Definition at line 129 of file DiskBuffer.h.

◆ m_header

std::string Gaudi::NTuple::DiskBuffer::Reader::m_header
private

Definition at line 131 of file DiskBuffer.h.

◆ m_path

std::filesystem::path Gaudi::NTuple::DiskBuffer::Reader::m_path
private

Definition at line 128 of file DiskBuffer.h.

◆ m_pos

std::size_t Gaudi::NTuple::DiskBuffer::Reader::m_pos { 0 }
private

Definition at line 135 of file DiskBuffer.h.

135{ 0 };

◆ m_size

std::uintmax_t Gaudi::NTuple::DiskBuffer::Reader::m_size { 0 }
private

Definition at line 130 of file DiskBuffer.h.

130{ 0 }; // file size, 0 if unknown: bounds a block length

◆ m_stored

std::vector<char> Gaudi::NTuple::DiskBuffer::Reader::m_stored
private

Definition at line 133 of file DiskBuffer.h.


The documentation for this class was generated from the following files: