PODIO v00-16-03
An Event-Data-Model Toolkit for High Energy Physics Experiments
Loading...
Searching...
No Matches
SIOLegacyReader.cc
Go to the documentation of this file.
2#include "podio/SIOBlock.h"
3
4#include "sioUtils.h"
5
6#include <sio/api.h>
7#include <sio/compression/zlib.h>
8#include <sio/definitions.h>
9
10namespace podio {
11
13 auto& libLoader [[maybe_unused]] = SIOBlockLibraryLoader::instance();
14}
15
16void SIOLegacyReader::openFile(const std::string& filename) {
17 m_stream.open(filename, std::ios::binary);
18 if (!m_stream.is_open()) {
19 throw std::runtime_error("File " + filename + " couldn't be opened");
20 }
21
22 // NOTE: reading TOC record first because that jumps back to the start of the file!
23 readFileTOCRecord();
24 readCollectionIDTable();
25}
26
27std::unique_ptr<SIOFrameData> SIOLegacyReader::readNextEntry(const std::string& name) {
28 if (name != m_categoryName) {
29 return nullptr;
30 }
31 // skip possible intermediate records that are not event data
32 try {
33 sio::api::go_to_record(m_stream, "event_record");
34 } catch (sio::exception&) {
35 // If anything goes wrong, return a nullptr
36 return nullptr;
37 }
38
39 auto [dataBuffer, dataInfo] = sio_utils::readRecord(m_stream, false);
40 // Need to work around the fact that sio::buffers are not copyable by copying
41 // the underlying buffer (vector<byte>) and then using that to move construct
42 // a new buffer
43 sio::buffer::container bufferBytes{m_tableBuffer.data(), m_tableBuffer.data() + m_tableBuffer.size()};
44 auto tableBuffer = sio::buffer(std::move(bufferBytes));
45
46 m_eventNumber++;
47 return std::make_unique<SIOFrameData>(std::move(dataBuffer), dataInfo._uncompressed_length, std::move(tableBuffer),
48 m_tableUncLength);
49}
50
51std::unique_ptr<podio::SIOFrameData> SIOLegacyReader::readEntry(const std::string& name, const unsigned entry) {
52 if (name != m_categoryName) {
53 return nullptr;
54 }
55
56 // Setting the event number to the desired one here and putting the stream to
57 // the right position is the necessary setup before simply handing off to readNextEntry
58 m_eventNumber = entry;
59 // NOTE: In legacy files the "events" are stored in "event_record" records
60 const auto recordPos = m_tocRecord.getPosition("event_record", entry);
61 if (recordPos == 0) {
62 return nullptr;
63 }
64 m_stream.seekg(recordPos);
65
66 return readNextEntry(name);
67}
68
69unsigned SIOLegacyReader::getEntries(const std::string& name) const {
70 if (name != "events") {
71 return 0;
72 }
73 return m_tocRecord.getNRecords("event_record");
74}
75
76void SIOLegacyReader::readCollectionIDTable() {
77 // Need to decompress the buffers here, because in this record not only the
78 // collectionID table is stored, but also the version information...
79 auto [infoBuffer, _] = sio_utils::readRecord(m_stream, true);
80
81 sio::block_list blocks;
82 blocks.emplace_back(std::make_shared<SIOCollectionIDTableBlock>());
83 blocks.emplace_back(std::make_shared<SIOVersionBlock>());
84 sio::api::read_blocks(infoBuffer.span(), blocks);
85
86 m_fileVersion = static_cast<SIOVersionBlock*>(blocks[1].get())->version;
87
88 // recompress the collection ID table block...
89 blocks.resize(1); // remove the SIOVersionBlock
90 auto tmpUncBuffer = sio::buffer{sio::mbyte};
91 auto tmpRecInfo = sio::api::write_record("dummy", tmpUncBuffer, blocks, 0);
92 sio::zlib_compression compressor;
93 compressor.set_level(6);
94 sio::api::compress_record(tmpRecInfo, tmpUncBuffer, m_tableBuffer, compressor);
95 m_tableUncLength = tmpRecInfo._uncompressed_length;
96}
97
98bool SIOLegacyReader::readFileTOCRecord() {
99 // Check if there is a dedicated marker at the end of the file that tells us
100 // where the TOC actually starts
101 m_stream.seekg(-sio_helpers::SIOTocInfoSize, std::ios_base::end);
102 uint64_t firstWords{0};
103 m_stream.read(reinterpret_cast<char*>(&firstWords), sizeof(firstWords));
104
105 const uint32_t marker = (firstWords >> 32) & 0xffffffff;
106 if (marker == sio_helpers::SIOTocMarker) {
107 const uint32_t position = firstWords & 0xffffffff;
108 m_stream.seekg(position);
109
110 const auto& [uncBuffer, _] = sio_utils::readRecord(m_stream);
111
112 sio::block_list blocks;
113 auto tocBlock = std::make_shared<SIOFileTOCRecordBlock>();
114 tocBlock->record = &m_tocRecord;
115 blocks.push_back(tocBlock);
116
117 sio::api::read_blocks(uncBuffer.span(), blocks);
118
119 m_stream.seekg(0);
120 return true;
121 }
122
123 m_stream.clear();
124 m_stream.seekg(0);
125 return false;
126}
127
128std::vector<std::string_view> SIOLegacyReader::getAvailableCategories() const {
129 return {m_categoryName};
130}
131
132} // namespace podio
static SIOBlockLibraryLoader & instance()
Definition: SIOBlock.h:263
PositionType getPosition(const std::string &name, unsigned iEntry=0) const
Definition: SIOBlock.cc:204
size_t getNRecords(const std::string &name) const
Definition: SIOBlock.cc:195
std::unique_ptr< podio::SIOFrameData > readEntry(const std::string &, const unsigned entry)
unsigned getEntries(const std::string &name) const
Returns the number of.
std::unique_ptr< podio::SIOFrameData > readNextEntry(const std::string &)
void openFile(const std::string &filename)
std::vector< std::string_view > getAvailableCategories() const
Get the names of all the availalable Frame categories in the current file(s)
std::pair< sio::buffer, sio::record_info > readRecord(sio::ifstream &stream, bool decompress=true, std::size_t initBufferSize=sio::mbyte)
Read the record into a buffer and potentially uncompress it.
Definition: sioUtils.h:18