2 #define TRACE_NAME "HighFiveGroupedDataset"
3 #define TLVL_INSERTONE 6
4 #define TLVL_INSERTHEADER 7
5 #define TLVL_WRITEFRAGMENT 8
6 #define TLVL_WRITEFRAGMENT_V 9
7 #define TLVL_READNEXTEVENT 10
8 #define TLVL_READNEXTEVENT_V 11
9 #define TLVL_READFRAGMENT 12
10 #define TLVL_READFRAGMENT_V 13
11 #define TLVL_GETEVENTHEADER 14
13 #include <unordered_map>
14 #include "art/Framework/Services/Registry/ServiceHandle.h"
15 #include "artdaq-core/Data/ContainerFragmentLoader.hh"
16 #include "artdaq-demo-hdf5/HDF5/FragmentDataset.hh"
17 #include "artdaq-demo-hdf5/HDF5/highFive/HighFive/include/highfive/H5File.hpp"
18 #include "artdaq/ArtModules/ArtdaqFragmentNamingService.h"
19 #include "canvas/Persistency/Provenance/EventID.h"
53 void insertOne(artdaq::Fragment
const& frag)
override;
58 void insertMany(artdaq::Fragments
const& frags)
override;
65 void insertHeader(artdaq::detail::RawEventHeader
const& hdr)
override;
70 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>>
readNextEvent()
override;
76 std::unique_ptr<artdaq::detail::RawEventHeader>
getEventHeader(artdaq::Fragment::sequence_id_t
const& seqID)
override;
79 std::unique_ptr<HighFive::File> file_;
81 art::ServiceHandle<ArtdaqFragmentNamingServiceInterface> namingService_;
82 HighFive::DataSetCreateProps fragmentCProps_;
83 HighFive::DataSetAccessProps fragmentAProps_;
85 void writeFragment_(HighFive::Group& group, artdaq::Fragment
const& frag);
86 artdaq::FragmentPtr readFragment_(HighFive::DataSet
const& dataset);
92 :
FragmentDataset(ps, ps.get<std::string>(
"mode",
"write")), file_(nullptr), eventIndex_(0)
94 TLOG(TLVL_DEBUG) <<
"HighFiveGroupedDataset CONSTRUCTOR BEGIN";
95 if (
mode_ == FragmentDatasetMode::Read)
97 file_.reset(
new HighFive::File(ps.get<std::string>(
"fileName"), HighFive::File::ReadOnly));
101 file_.reset(
new HighFive::File(ps.get<std::string>(
"fileName"), HighFive::File::OpenOrCreate | HighFive::File::Truncate));
103 TLOG(TLVL_DEBUG) <<
"HighFiveGroupedDataset CONSTRUCTOR END";
108 TLOG(TLVL_DEBUG) <<
"~HighFiveGroupedDataset Begin/End ";
114 TLOG(TLVL_TRACE) <<
"insertOne BEGIN";
115 if (!file_->exist(std::to_string(frag.sequenceID())))
117 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for sequence ID " << frag.sequenceID();
118 file_->createGroup(std::to_string(frag.sequenceID()));
120 auto eventGroup = file_->getGroup(std::to_string(frag.sequenceID()));
122 if (frag.type() == Fragment::ContainerFragmentType)
124 TLOG(TLVL_INSERTONE) <<
"insertOne: Processing ContainerFragment";
125 ContainerFragment cf(frag);
126 if (cf.block_count() > 0)
128 TLOG(TLVL_INSERTONE) <<
"insertOne: Getting Fragment type name";
129 auto fragPtr = cf.at(0);
130 auto typeName = namingService_->GetInstanceNameForFragment(*fragPtr).second;
131 if (!eventGroup.exist(typeName))
133 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for type " << typeName;
134 eventGroup.createGroup(typeName);
137 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group and setting attributes";
138 auto typeGroup = eventGroup.getGroup(typeName);
139 auto containerGroup = typeGroup.createGroup(
"Container_" + std::to_string(frag.fragmentID()));
140 containerGroup.createAttribute(
"version", frag.version());
141 containerGroup.createAttribute(
"type", frag.type());
142 containerGroup.createAttribute(
"sequence_id", frag.sequenceID());
143 containerGroup.createAttribute(
"fragment_id", frag.fragmentID());
144 containerGroup.createAttribute(
"timestamp", frag.timestamp());
146 containerGroup.createAttribute(
"container_block_count", cf.block_count());
147 containerGroup.createAttribute(
"container_fragment_type", cf.fragment_type());
148 containerGroup.createAttribute(
"container_version", cf.metadata()->version);
149 containerGroup.createAttribute(
"container_missing_data", cf.missing_data());
151 TLOG(TLVL_INSERTONE) <<
"insertOne: Writing Container contained Fragments";
152 for (
size_t ii = 0; ii < cf.block_count(); ++ii)
158 writeFragment_(containerGroup, *fragPtr);
163 TLOG(TLVL_INSERTONE) <<
"insertOne: Writing Empty Container Fragment as standard Fragment";
164 auto typeName = namingService_->GetInstanceNameForFragment(frag).second;
165 if (!eventGroup.exist(typeName))
167 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for type " << typeName;
168 eventGroup.createGroup(typeName);
170 auto typeGroup = eventGroup.getGroup(typeName);
172 writeFragment_(typeGroup, frag);
177 TLOG(TLVL_INSERTONE) <<
"insertOne: Writing non-Container Fragment";
178 auto typeName = namingService_->GetInstanceNameForFragment(frag).second;
179 if (!eventGroup.exist(typeName))
181 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for type " << typeName;
182 eventGroup.createGroup(typeName);
184 auto typeGroup = eventGroup.getGroup(typeName);
186 writeFragment_(typeGroup, frag);
188 TLOG(TLVL_TRACE) <<
"insertOne END";
193 TLOG(TLVL_TRACE) <<
"insertMany BEGIN";
194 for (
auto& f : fs) insertOne(f);
195 TLOG(TLVL_TRACE) <<
"insertMany END";
200 TLOG(TLVL_TRACE) <<
"insertHeader BEGIN";
201 if (!file_->exist(std::to_string(hdr.sequence_id)))
203 TLOG(TLVL_INSERTHEADER) <<
"insertHeader: Creating group for event " << hdr.sequence_id;
204 file_->createGroup(std::to_string(hdr.sequence_id));
206 auto eventGroup = file_->getGroup(std::to_string(hdr.sequence_id));
207 eventGroup.createAttribute(
"run_id", hdr.run_id);
208 eventGroup.createAttribute(
"subrun_id", hdr.subrun_id);
209 eventGroup.createAttribute(
"event_id", hdr.event_id);
210 eventGroup.createAttribute(
"is_complete", hdr.is_complete);
211 TLOG(TLVL_TRACE) <<
"insertHeader END";
216 TLOG(TLVL_DEBUG) <<
"readNextEvent BEGIN";
217 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> output;
219 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Finding next event group in file";
220 auto groupNames = file_->listObjectNames();
221 while (eventIndex_ < groupNames.size() && file_->getObjectType(groupNames[eventIndex_]) != HighFive::ObjectType::Group)
226 if (groupNames.size() <= eventIndex_)
228 TLOG(TLVL_INFO) <<
"readNextEvent: No more events in file!";
232 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Getting event group " << groupNames[eventIndex_];
233 auto event_group = file_->getGroup(groupNames[eventIndex_]);
234 auto fragment_type_names = event_group.listObjectNames();
236 for (
auto& fragment_type : fragment_type_names)
238 if (event_group.getObjectType(fragment_type) != HighFive::ObjectType::Group)
242 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Reading Fragment type " << fragment_type;
243 auto type_group = event_group.getGroup(fragment_type);
244 auto fragment_names = type_group.listObjectNames();
246 for (
auto& fragment_name : fragment_names)
248 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Reading Fragment " << fragment_name;
249 auto node_type = type_group.getObjectType(fragment_name);
250 if (node_type == HighFive::ObjectType::Group)
252 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Fragment " << fragment_name <<
" is a Container";
253 auto container_group = type_group.getGroup(fragment_name);
254 Fragment::type_t type;
255 container_group.getAttribute(
"type").read<Fragment::type_t>(type);
256 Fragment::sequence_id_t seqID;
257 container_group.getAttribute(
"sequence_id").read(seqID);
258 Fragment::timestamp_t timestamp;
259 container_group.getAttribute(
"timestamp").read(timestamp);
260 Fragment::fragment_id_t fragID;
261 container_group.getAttribute(
"fragment_id").read(fragID);
262 if (!output.count(type))
264 output[type].reset(
new Fragments());
266 output[type]->emplace_back(seqID, fragID);
267 output[type]->back().setTimestamp(timestamp);
268 output[type]->back().setSystemType(type);
270 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Creating ContainerFragmentLoader for reading Container Fragments";
271 ContainerFragmentLoader cfl(output[type]->back());
273 Fragment::type_t container_fragment_type;
275 container_group.getAttribute(
"container_fragment_type").read(container_fragment_type);
276 container_group.getAttribute(
"container_missing_data").read(missing_data);
278 cfl.set_fragment_type(container_fragment_type);
279 cfl.set_missing_data(missing_data);
281 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Reading ContainerFragment Fragments";
282 auto fragments = container_group.listObjectNames();
283 for (
auto& fragname : fragments)
285 if (container_group.getObjectType(fragname) != HighFive::ObjectType::Dataset)
continue;
286 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: Calling readFragment_ BEGIN";
287 auto frag = readFragment_(container_group.getDataSet(fragname, fragmentAProps_));
288 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: Calling readFragment_ END";
290 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: Calling addFragment BEGIN";
291 cfl.addFragment(frag);
292 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: addFragment END";
295 else if (node_type == HighFive::ObjectType::Dataset)
297 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: Calling readFragment_ BEGIN";
298 auto frag = readFragment_(type_group.getDataSet(fragment_name, fragmentAProps_));
299 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: Calling readFragment_ END";
301 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Adding Fragment to output";
302 if (!output.count(frag->type()))
304 output[frag->type()].reset(
new artdaq::Fragments());
306 output[frag->type()]->push_back(*frag.release());
314 <<
"readNextEvent END output.size() = " << output.size();
320 TLOG(TLVL_TRACE) <<
"GetEventHeader BEGIN seqID=" << seqID;
321 if (!file_->exist(std::to_string(seqID)))
323 TLOG(TLVL_ERROR) <<
"Sequence ID " << seqID <<
" not found in input file!";
326 auto seqIDGroup = file_->getGroup(std::to_string(seqID));
328 uint32_t runID, subrunID, eventID;
329 seqIDGroup.getAttribute(
"run_id").read(runID);
330 seqIDGroup.getAttribute(
"subrun_id").read(subrunID);
331 seqIDGroup.getAttribute(
"event_id").read(eventID);
333 TLOG(TLVL_GETEVENTHEADER) <<
"Creating EventHeader with runID " << runID <<
", subrunID " << subrunID <<
", eventID " << eventID <<
" (seqID " << seqID <<
")";
334 artdaq::detail::RawEventHeader hdr(runID, subrunID, eventID, seqID);
335 seqIDGroup.getAttribute(
"is_complete").read(hdr.is_complete);
337 TLOG(TLVL_TRACE) <<
"GetEventHeader END";
338 return std::make_unique<artdaq::detail::RawEventHeader>(hdr);
341 void artdaq::hdf5::HighFiveGroupedDataset::writeFragment_(HighFive::Group& group, artdaq::Fragment
const& frag)
343 TLOG(TLVL_TRACE) <<
"writeFragment_ BEGIN";
345 auto datasetNameBase =
"Fragment_" + std::to_string(frag.fragmentID());
346 auto datasetName = datasetNameBase +
";1";
348 while (group.exist(datasetName))
350 TLOG(TLVL_WRITEFRAGMENT) <<
"writeFragment_: Duplicate Fragment ID " << frag.fragmentID() <<
" detected. If this is a ContainerFragment, this is expected, otherwise check configuration!";
351 datasetName = datasetNameBase +
";" + std::to_string(counter);
355 TLOG(TLVL_WRITEFRAGMENT) <<
"writeFragment_: Creating DataSpace";
356 HighFive::DataSpace fragmentSpace = HighFive::DataSpace({frag.size() - frag.headerSizeWords(), 1});
357 auto fragDset = group.createDataSet<RawDataType>(datasetName, fragmentSpace, fragmentCProps_, fragmentAProps_);
359 TLOG(TLVL_WRITEFRAGMENT) <<
"writeFragment_: Creating Attributes from Fragment Header";
360 auto fragHdr = frag.fragmentHeader();
361 fragDset.createAttribute(
"word_count", fragHdr.word_count);
362 fragDset.createAttribute(
"fragment_data_size", frag.size() - frag.headerSizeWords());
363 fragDset.createAttribute(
"version", fragHdr.version);
364 fragDset.createAttribute(
"type", fragHdr.type);
365 fragDset.createAttribute(
"metadata_word_count", fragHdr.metadata_word_count);
367 fragDset.createAttribute(
"sequence_id", fragHdr.sequence_id);
368 fragDset.createAttribute(
"fragment_id", fragHdr.fragment_id);
370 fragDset.createAttribute(
"timestamp", fragHdr.timestamp);
372 fragDset.createAttribute(
"valid", fragHdr.valid);
373 fragDset.createAttribute(
"complete", fragHdr.complete);
374 fragDset.createAttribute(
"atime_ns", fragHdr.atime_ns);
375 fragDset.createAttribute(
"atime_s", fragHdr.atime_s);
377 TLOG(TLVL_WRITEFRAGMENT_V) <<
"writeFragment_: Writing Fragment payload START";
378 fragDset.write(frag.headerBegin() + frag.headerSizeWords());
379 TLOG(TLVL_WRITEFRAGMENT_V) <<
"writeFragment_: Writing Fragment payload DONE";
380 TLOG(TLVL_TRACE) <<
"writeFragment_ END";
383 artdaq::FragmentPtr artdaq::hdf5::HighFiveGroupedDataset::readFragment_(HighFive::DataSet
const& dataset)
385 TLOG(TLVL_TRACE) <<
"readFragment_ BEGIN";
387 dataset.getAttribute(
"fragment_data_size").read(fragSize);
388 TLOG(TLVL_READFRAGMENT) <<
"readFragment_: Fragment size " << fragSize <<
", dataset size " << dataset.getDimensions()[0];
390 artdaq::FragmentPtr frag(
new Fragment(fragSize));
392 artdaq::Fragment::type_t type;
393 size_t metadata_size;
394 artdaq::Fragment::sequence_id_t seqID;
395 artdaq::Fragment::fragment_id_t fragID;
396 artdaq::Fragment::timestamp_t timestamp;
397 int valid, complete, atime_ns, atime_s;
399 TLOG(TLVL_READFRAGMENT) <<
"readFragment_: Reading Fragment header fields from dataset attributes";
400 dataset.getAttribute(
"type").read(type);
401 dataset.getAttribute(
"metadata_word_count").read(metadata_size);
403 dataset.getAttribute(
"sequence_id").read(seqID);
404 dataset.getAttribute(
"fragment_id").read(fragID);
406 dataset.getAttribute(
"timestamp").read(timestamp);
408 dataset.getAttribute(
"valid").read(valid);
409 dataset.getAttribute(
"complete").read(complete);
410 dataset.getAttribute(
"atime_ns").read(atime_ns);
411 dataset.getAttribute(
"atime_s").read(atime_s);
413 auto fragHdr = frag->fragmentHeader();
415 fragHdr.metadata_word_count = metadata_size;
417 fragHdr.sequence_id = seqID;
418 fragHdr.fragment_id = fragID;
420 fragHdr.timestamp = timestamp;
422 fragHdr.valid = valid;
423 fragHdr.complete = complete;
424 fragHdr.atime_ns = atime_ns;
425 fragHdr.atime_s = atime_s;
427 TLOG(TLVL_READFRAGMENT) <<
"readFragment_: Copying header into Fragment";
428 memcpy(frag->headerAddress(), &fragHdr,
sizeof(fragHdr));
430 TLOG(TLVL_READFRAGMENT_V) <<
"readFragment_: Reading payload data into Fragment BEGIN";
431 dataset.read(frag->headerAddress() + frag->headerSizeWords());
432 TLOG(TLVL_READFRAGMENT_V) <<
"readFragment_: Reading payload data into Fragment END";
434 TLOG(TLVL_TRACE) <<
"readFragment_ END";
std::unordered_map< artdaq::Fragment::type_t, std::unique_ptr< artdaq::Fragments > > readNextEvent() override
Read the next event from the Dataset (HDF5 file)
std::unique_ptr< artdaq::detail::RawEventHeader > getEventHeader(artdaq::Fragment::sequence_id_t const &seqID) override
Read a RawEventHeader from the Dataset (HDF5 file)
A FragmentDataset implementation which produces files where each event is a Group, and each Fragment_id_t within the group is either a dataset or a group if it is a ContainerFragment.
void insertOne(artdaq::Fragment const &frag) override
Insert a Fragment into the Dataset (write it to the HDF5 file)
HighFiveGroupedDataset(fhicl::ParameterSet const &ps)
HighFiveGroupedDataset Constructor.
void insertHeader(artdaq::detail::RawEventHeader const &hdr) override
Insert a RawEventHeader into the Dataset (write it to the HDF5 file)
FragmentDatasetMode mode_
Mode of this FragmentDataset, either FragmentDatasetMode::Write or FragmentDatasetMode::Read.
Base class that defines methods for reading and writing to HDF5 files via various implementation plug...
void insertMany(artdaq::Fragments const &frags) override
Insert several Fragments into the Dataset (write them to the HDF5 file)
virtual ~HighFiveGroupedDataset() noexcept
HighFiveGroupedDataset Destructor.