PODIO v00-16-03
An Event-Data-Model Toolkit for High Energy Physics Experiments
Loading...
Searching...
No Matches
SIOReader.cc
Go to the documentation of this file.
1// podio specific includes
2#include "podio/SIOReader.h"
3
6#include "podio/EventStore.h"
7#include "podio/SIOBlock.h"
8#include "sio/definitions.h"
9
10#include <memory>
11#include <sio/compression/zlib.h>
12
13namespace podio {
14
16 m_eventNumber(0),
17 m_eventMetaData(std::make_shared<SIOEventMetaDataBlock>()),
18 m_runMetaData(std::make_shared<SIONumberedMetaDataBlock>("RunMetaData")),
19 m_collectionMetaData(std::make_shared<SIONumberedMetaDataBlock>("CollectionMetaData")) {
20 auto& libLoader [[maybe_unused]] = SIOBlockLibraryLoader::instance();
21}
22
23CollectionBase* SIOReader::readCollection(const std::string& name) {
24 if (m_lastEventRead != m_eventNumber) {
25 readEvent();
26 }
27
28 // Have we unpacked this already?
29 auto p =
30 std::find_if(begin(m_inputs), end(m_inputs), [&name](const SIOReader::Input& t) { return t.second == name; });
31
32 if (p != end(m_inputs)) {
33 p->first->setID(m_table->collectionID(name));
34 p->first->prepareAfterRead();
35 return p->first;
36 }
37
38 return nullptr;
39}
40
41std::map<int, GenericParameters>* SIOReader::readCollectionMetaData() {
42 // Always read a new map, because the EventStore takes ownership
43 m_collectionMetaData->data = new ColMDMap();
44 readMetaDataRecord(m_collectionMetaData);
45 return m_collectionMetaData->data;
46}
47
48std::map<int, GenericParameters>* SIOReader::readRunMetaData() {
49 // Always read a new map, because the EventStore takes ownership
50 m_runMetaData->data = new RunMDMap();
51 readMetaDataRecord(m_runMetaData);
52 return m_runMetaData->data;
53}
54
55podio::GenericParameters* SIOReader::readEventMetaData() {
56 if (m_lastEventRead != m_eventNumber) {
57 readEvent();
58 }
59 return m_eventMetaData->metadata;
60}
61
62void SIOReader::openFile(const std::string& filename) {
63 m_stream.open(filename, std::ios::binary);
64 if (!this->isValid()) {
65 throw std::runtime_error("File " + filename + " couldn't be found");
66 }
67 readCollectionIDTable();
68
69 if (!readFileTOCRecord()) {
70 reconstructFileTOCRecord();
71 }
72}
73
75 m_stream.close();
76}
77
79 // recreate the blocks, since the contents are owned and managed by the
80 // EventStore
81 createBlocks();
82
83 // skip possible intermediate records that are not event data
84 sio::api::go_to_record(m_stream, "event_record");
85
86 sio::record_info rec_info;
87 sio::api::read_record_info(m_stream, rec_info, m_info_buffer);
88 sio::api::read_record_data(m_stream, rec_info, m_rec_buffer);
89
90 m_unc_buffer.resize(rec_info._uncompressed_length);
91 sio::zlib_compression compressor;
92 compressor.uncompress(m_rec_buffer.span(), m_unc_buffer);
93 sio::api::read_blocks(m_unc_buffer.span(), m_blocks);
94
95 for (size_t i = 1; i < m_blocks.size(); ++i) {
96 auto* blk = static_cast<podio::SIOBlock*>(m_blocks[i].get());
97 m_inputs.emplace_back(blk->getCollection(), m_table->names()[i - 1]);
98 }
99
100 m_lastEventRead = m_eventNumber;
101}
102
103bool SIOReader::isValid() const {
104 return m_stream.good();
105}
106
108 ++m_eventNumber;
109 m_blocks.clear();
110 m_inputs.clear();
111}
112
113void SIOReader::goToEvent(unsigned eventNumber) {
114 // If we are already past the desired event number, rewind to the start first
115 if (eventNumber < (unsigned)m_eventNumber) {
116 m_stream.clear();
117 m_stream.seekg(0);
118 m_eventNumber = 0;
119 }
120
121 sio::api::go_to_record(m_stream, "event_record");
122 if ((eventNumber - m_eventNumber) > 0) {
123 sio::api::skip_n_records(m_stream, eventNumber - m_eventNumber);
124 }
125 m_eventNumber = eventNumber;
126
127 m_inputs.clear();
128 m_blocks.clear();
129}
130
131void SIOReader::createBlocks() {
132 // make sure that the first block is EventMetaData as it is also the first
133 // during wrting
134 m_eventMetaData->metadata = new GenericParameters(); // will be managed by EventStore (?)
135 m_blocks.push_back(m_eventMetaData);
136
137 for (size_t i = 0; i < m_typeNames.size(); ++i) {
138 const bool subsetColl = !m_subsetCollectionBits.empty() && m_subsetCollectionBits[i];
139 auto blk = podio::SIOBlockFactory::instance().createBlock(m_typeNames[i], m_table->names()[i], subsetColl);
140 m_blocks.push_back(blk);
141 }
142}
143
144void SIOReader::readCollectionIDTable() {
145 sio::record_info rec_info;
146 sio::api::read_record_info(m_stream, rec_info, m_info_buffer);
147 sio::api::read_record_data(m_stream, rec_info, m_rec_buffer);
148
149 m_unc_buffer.resize(rec_info._uncompressed_length);
150 sio::zlib_compression compressor;
151 compressor.uncompress(m_rec_buffer.span(), m_unc_buffer);
152
153 sio::block_list blocks;
154 blocks.emplace_back(std::make_shared<SIOCollectionIDTableBlock>());
155 blocks.emplace_back(std::make_shared<SIOVersionBlock>());
156 sio::api::read_blocks(m_unc_buffer.span(), blocks);
157
158 auto* idTableBlock = static_cast<SIOCollectionIDTableBlock*>(blocks[0].get());
159 m_table = std::make_shared<podio::CollectionIDTable>();
160 m_table.reset(idTableBlock->getTable());
161 m_typeNames = idTableBlock->getTypeNames();
162 m_subsetCollectionBits = idTableBlock->getSubsetCollectionBits();
163 m_fileVersion = static_cast<SIOVersionBlock*>(blocks[1].get())->version;
164}
165
166void SIOReader::readMetaDataRecord(const std::shared_ptr<SIONumberedMetaDataBlock>& mdBlock) {
167 const auto currPos = m_stream.tellg();
168 sio::api::go_to_record(m_stream, mdBlock->name());
169
170 sio::record_info rec_info;
171 sio::api::read_record_info(m_stream, rec_info, m_info_buffer);
172 sio::api::read_record_data(m_stream, rec_info, m_rec_buffer);
173
174 m_unc_buffer.resize(rec_info._uncompressed_length);
175 sio::zlib_compression compressor;
176 compressor.uncompress(m_rec_buffer.span(), m_unc_buffer);
177
178 sio::block_list blocks{};
179 blocks.push_back(mdBlock);
180 sio::api::read_blocks(m_unc_buffer.span(), blocks);
181
182 m_stream.seekg(currPos);
183}
184
185void SIOReader::reconstructFileTOCRecord() {
186 try {
187 // use a simple unary predicate that always returns true, and hence skips
188 // over all records, but as a sideffect populates the tocRecord
189 sio::api::skip_records(m_stream, [&](const sio::record_info& rec_info) {
190 m_tocRecord.addRecord(rec_info._name, rec_info._file_start);
191 return true;
192 });
193 } catch (sio::exception& e) {
194 if (e.code() != sio::error_code::eof) {
195 SIO_RETHROW(e, e.code(), e.what());
196 }
197 }
198
199 // rewind to the start of the file
200 m_stream.clear();
201 m_stream.seekg(0);
202}
203
204bool SIOReader::readFileTOCRecord() {
205 // Check if there is a dedicated marker at the end of the file that tells us
206 // where the TOC actually starts
207 m_stream.seekg(-sio_helpers::SIOTocInfoSize, std::ios_base::end);
208 uint64_t firstWords{0};
209 m_stream.read(reinterpret_cast<char*>(&firstWords), sizeof(firstWords));
210
211 const uint32_t marker = (firstWords >> 32) & 0xffffffff;
212 if (marker == sio_helpers::SIOTocMarker) {
213 const uint32_t position = firstWords & 0xffffffff;
214 m_stream.seekg(position);
215
216 sio::record_info rec_info;
217 sio::api::read_record_info(m_stream, rec_info, m_info_buffer);
218 sio::api::read_record_data(m_stream, rec_info, m_rec_buffer);
219
220 m_unc_buffer.resize(rec_info._uncompressed_length);
221 sio::zlib_compression compressor;
222 compressor.uncompress(m_rec_buffer.span(), m_unc_buffer);
223
224 sio::block_list blocks;
225 auto tocBlock = std::make_shared<SIOFileTOCRecordBlock>();
226 tocBlock->record = &m_tocRecord;
227 blocks.push_back(tocBlock);
228
229 sio::api::read_blocks(m_unc_buffer.span(), blocks);
230
231 m_unc_buffer.clear();
232 m_rec_buffer.clear();
233 m_stream.seekg(0);
234 return true;
235 }
236
237 m_stream.clear();
238 m_stream.seekg(0);
239 return false;
240}
241} // namespace podio
static SIOBlockFactory & instance()
Definition: SIOBlock.h:236
std::shared_ptr< SIOBlock > createBlock(const podio::CollectionBase *col, const std::string &name) const
Definition: SIOBlock.cc:110
static SIOBlockLibraryLoader & instance()
Definition: SIOBlock.h:263
Base class for sio::block handlers used with PODIO.
Definition: SIOBlock.h:60
void addRecord(const std::string &name, PositionType startPos)
Definition: SIOBlock.cc:184
void closeFile() override
Definition: SIOReader.cc:74
void readEvent() override
Read all collections requested.
Definition: SIOReader.cc:78
void openFile(const std::string &filename) override
Definition: SIOReader.cc:62
void endOfEvent() override
Prepare the reader to read the next event.
Definition: SIOReader.cc:107
bool isValid() const override
Check if file is valid.
Definition: SIOReader.cc:103
void goToEvent(unsigned iEvent) override
Definition: SIOReader.cc:113
std::map< int, GenericParameters > ColMDMap
Definition: EventStore.h:35
std::map< int, GenericParameters > RunMDMap
Definition: EventStore.h:34