11#ifndef HDF5LIBS_INCLUDE_HDF5LIBS_HDF5RAWDATAFILE_HPP_
12#define HDF5LIBS_INCLUDE_HDF5LIBS_HDF5RAWDATAFILE_HPP_
24#include <highfive/H5DataSet.hpp>
25#include <highfive/H5File.hpp>
26#include <highfive/H5Group.hpp>
27#include <highfive/H5Object.hpp>
28#include <nlohmann/json.hpp>
38#include <sys/statvfs.h>
48 func_name <<
" is deprecated. " << message,
49 ((std::string)func_name)((std::string)message))
53 "Issue when opening file " << file <<
": " << message,
54 ((std::string)file)((std::string)message))
57 IncompatibleOpenFlags,
58 "Issue when opening file " << file <<
": "
59 <<
"bad open flags " << open_flags,
60 ((std::string)file)((
unsigned)open_flags))
64 "No DUNEDAQ FileLayout information available."
65 <<
" Assigning version " <<
version,
69 IncompatibleFileLayoutVersion,
70 "FileLayout version incompatibility. Found version " <<
version <<
" but min allowed version is "
71 << min_allowed <<
" and max allowed version is "
73 ((uint32_t)
version)((uint32_t)min_allowed)((uint32_t)max_allowed))
77 "Record type attribute " << rt_attr <<
" does not match file layout config record name prefix "
79 ((std::string)rt_attr)((std::string)rt_fl))
82 WrongRecordTypeRequested,
83 "Record type requested " << rname <<
" does not match file layout config record name prefix "
85 ((std::string)rname)((std::string)rt_fl))
89 "Record ID with record number=" << rec_num <<
" and sequence number=" << seq_num <<
" not found.",
90 ((uint64_t)rec_num)((uint16_t)seq_num))
96 "The HDF5 Dataset associated with name \"" << data_set <<
"\" is invalid. (file = " <<
filename
98 ((std::string)data_set)((std::string)
filename))
104ERS_DECLARE_ISSUE(
hdf5libs, TimeSliceAlreadyExists,
"The TimeSlice record for " << name <<
" already exists.", ((std::string)name))
107 "Fragment type name \"" << name <<
"\" does not map to a valid type.", ((std::string)name))
110 "Subdetector name \"" << name <<
"\" does not map to a valid detector ID.", ((std::string)name))
130 typedef std::pair<uint64_t, daqdataformats::sequence_number_t> record_id_t;
131 typedef std::set<record_id_t, std::less<>> record_id_set;
133 inline static const std::string s_inprogress_suffix =
".writing";
136 HDF5RawDataFile(std::string file_name,
139 std::string application_name,
140 HDF5FileLayoutParameters fl_params,
141 HDF5SourceIDHandler::source_id_geo_id_map_t srcid_geoid_map,
142 unsigned compression_level = 0,
143 std::string inprogress_filename_suffix = s_inprogress_suffix,
144 unsigned open_flags = HighFive::File::Create);
147 explicit HDF5RawDataFile(
const std::string& file_name,
bool allow_writing =
false);
151 std::string get_file_name()
const {
return m_file_ptr->getName(); }
153 size_t get_recorded_size()
const noexcept {
return m_recorded_size; }
154 size_t get_uncompressed_raw_data_size()
const noexcept {
return m_uncompressed_raw_data_size; }
155 size_t get_total_file_size()
const noexcept {
return m_total_file_size; }
156 unsigned get_compression_level()
const noexcept {
return m_compression_level; }
158 std::string get_record_type()
const noexcept {
return m_record_type; }
160 bool is_trigger_record_type()
const noexcept {
return m_record_type.compare(
"TriggerRecord") == 0; }
161 bool is_timeslice_type()
const noexcept {
return m_record_type.compare(
"TimeSlice") == 0; }
163 const HDF5FileLayout& get_file_layout()
const {
return *(m_file_layout_ptr.get()); }
165 uint32_t get_version()
const
167 return m_file_layout_ptr->get_version();
177 HDF5SourceIDHandler::source_id_path_map_t& path_map);
179 HDF5SourceIDHandler::source_id_path_map_t& path_map);
185 void write_attribute(std::string name, T value);
187 void write_attribute(HighFive::Group& grp,
const std::string& name, T value);
189 void write_attribute(HighFive::DataSet& dset,
const std::string& name, T value);
191 std::vector<std::string> get_attribute_names();
193 T get_attribute(
const std::string& name);
195 T get_attribute(
const HighFive::Group& grp,
const std::string& name);
197 T get_attribute(
const HighFive::DataSet& dset, std::string name);
200 T get_attribute_if_exists(
const std::string& name,
const T& default_value);
202 std::vector<std::string> get_dataset_paths(std::string top_level_group_name =
"");
204 record_id_set get_all_record_ids();
205 record_id_set get_all_trigger_record_ids();
206 record_id_set get_all_timeslice_ids();
208 std::set<uint64_t> get_all_record_numbers();
209 std::set<daqdataformats::trigger_number_t> get_all_trigger_record_numbers();
210 std::set<daqdataformats::timeslice_number_t> get_all_timeslice_numbers();
212 std::vector<std::string> get_record_header_dataset_paths();
213 std::vector<std::string> get_trigger_record_header_dataset_paths();
214 std::vector<std::string> get_timeslice_header_dataset_paths();
216 std::string get_record_header_dataset_path(
const record_id_t& rid);
217 std::string get_record_header_dataset_path(
const uint64_t rec_num,
219 std::string get_trigger_record_header_dataset_path(
const record_id_t& rid);
222 std::string get_timeslice_header_dataset_path(
const record_id_t& rid);
226 std::vector<std::string> get_all_fragment_dataset_paths();
229 std::vector<std::string> get_fragment_dataset_paths(
const record_id_t& rid);
230 std::vector<std::string> get_fragment_dataset_paths(
const uint64_t rec_num,
235 std::vector<std::string> get_fragment_dataset_paths(
const std::string& subsystem_name);
238 std::vector<std::string> get_fragment_dataset_paths(
const record_id_t& rid,
240 std::vector<std::string> get_fragment_dataset_paths(
const record_id_t& rid,
const std::string& subsystem_name);
247 std::vector<std::string> get_fragment_dataset_paths(
const std::string& typestring,
251 std::set<daqdataformats::SourceID> get_source_ids(std::vector<std::string>
const& frag_dataset_paths);
254 HDF5SourceIDHandler::source_id_geo_id_map_t get_srcid_geoid_map()
const;
257 std::set<uint64_t> get_all_geo_ids()
const;
260 std::set<uint64_t> get_geo_ids(
const record_id_t& rid);
261 std::set<uint64_t> get_geo_ids(
const uint64_t rec_num,
264 return get_geo_ids(std::make_pair(rec_num, seq_num));
266 std::set<uint64_t> get_geo_ids_for_subdetector(
const record_id_t& rid,
268 std::set<uint64_t> get_geo_ids_for_subdetector(
const uint64_t rec_num,
272 return get_geo_ids_for_subdetector(std::make_pair(rec_num, seq_num), subdet);
274 std::set<uint64_t> get_geo_ids_for_subdetector(
const record_id_t& rid,
275 const std::string& subdet_name)
278 return get_geo_ids_for_subdetector(rid, subdet);
280 std::set<uint64_t> get_geo_ids_for_subdetector(
const uint64_t rec_num,
282 const std::string& subdet_name)
284 return get_geo_ids_for_subdetector(std::make_pair(rec_num, seq_num), subdet_name);
288 std::set<daqdataformats::SourceID> get_source_ids(
const record_id_t& rid);
289 std::set<daqdataformats::SourceID> get_source_ids(
const uint64_t rec_num,
292 return get_source_ids(std::make_pair(rec_num, seq_num));
299 return get_record_header_source_id(std::make_pair(rec_num, seq_num));
302 std::set<daqdataformats::SourceID> get_fragment_source_ids(
const record_id_t& rid);
303 std::set<daqdataformats::SourceID> get_fragment_source_ids(
const uint64_t rec_num,
306 return get_fragment_source_ids(std::make_pair(rec_num, seq_num));
310 std::set<daqdataformats::SourceID> get_source_ids_for_subsystem(
const record_id_t& rid,
312 std::set<daqdataformats::SourceID> get_source_ids_for_subsystem(
const record_id_t& rid,
313 const std::string& subsystem_name)
316 return get_source_ids_for_subsystem(rid, subsys);
318 std::set<daqdataformats::SourceID> get_source_ids_for_subsystem(
const uint64_t rec_num,
322 return get_source_ids_for_subsystem(std::make_pair(rec_num, seq_num), subsystem);
324 std::set<daqdataformats::SourceID> get_source_ids_for_subsystem(
const uint64_t rec_num,
326 const std::string& subsystem_name)
328 return get_source_ids_for_subsystem(std::make_pair(rec_num, seq_num), subsystem_name);
332 std::set<daqdataformats::SourceID> get_source_ids_for_fragment_type(
const record_id_t& rid,
334 std::set<daqdataformats::SourceID> get_source_ids_for_fragment_type(
const record_id_t& rid,
335 const std::string& frag_type_name)
338 if (frag_type == daqdataformats::FragmentType::kUnknown)
339 throw InvalidFragmentTypeString(
ERS_HERE, frag_type_name);
340 return get_source_ids_for_fragment_type(rid, frag_type);
342 std::set<daqdataformats::SourceID> get_source_ids_for_fragment_type(
const uint64_t rec_num,
346 return get_source_ids_for_fragment_type(std::make_pair(rec_num, seq_num), frag_type);
348 std::set<daqdataformats::SourceID> get_source_ids_for_fragment_type(
const uint64_t rec_num,
350 const std::string& frag_type_name)
352 return get_source_ids_for_fragment_type(std::make_pair(rec_num, seq_num), frag_type_name);
356 std::set<daqdataformats::SourceID> get_source_ids_for_fragtype_and_subdetector(
const record_id_t& rid,
357 const std::string& frag_type_name,
358 const std::string& subdet_name);
361 std::set<daqdataformats::SourceID> get_source_ids_for_subdetector(
const record_id_t& rid,
363 std::set<daqdataformats::SourceID> get_source_ids_for_subdetector(
const record_id_t& rid,
364 const std::string& subdet_name)
367 return get_source_ids_for_subdetector(rid, subdet);
369 std::set<daqdataformats::SourceID> get_source_ids_for_subdetector(
const uint64_t rec_num,
373 return get_source_ids_for_subdetector(std::make_pair(rec_num, seq_num), subdet);
375 std::set<daqdataformats::SourceID> get_source_ids_for_subdetector(
const uint64_t rec_num,
377 const std::string& subdet_name)
379 return get_source_ids_for_subdetector(std::make_pair(rec_num, seq_num), subdet_name);
386 return get_source_ids(get_fragment_dataset_paths(type));
388 std::set<daqdataformats::SourceID> get_source_ids(
const std::string& typestring)
390 return get_source_ids(get_fragment_dataset_paths(typestring));
394 std::unique_ptr<char[]> get_dataset_raw_data(
const std::string& dataset_path);
396 std::unique_ptr<daqdataformats::Fragment> get_frag_ptr(
const std::string& dataset_name);
397 std::unique_ptr<daqdataformats::TriggerRecordHeader> get_trh_ptr(
const std::string& dataset_name);
398 std::unique_ptr<daqdataformats::TimeSliceHeader> get_tsh_ptr(
const std::string& dataset_name);
400 std::unique_ptr<daqdataformats::Fragment> get_frag_ptr(
const record_id_t& rid,
402 std::unique_ptr<daqdataformats::Fragment> get_frag_ptr(
const uint64_t rec_num,
405 std::unique_ptr<daqdataformats::Fragment> get_frag_ptr(
const record_id_t& rid,
408 std::unique_ptr<daqdataformats::Fragment> get_frag_ptr(
const uint64_t rec_num,
412 std::unique_ptr<daqdataformats::Fragment> get_frag_ptr(
const record_id_t& rid,
413 const std::string& typestring,
415 std::unique_ptr<daqdataformats::Fragment> get_frag_ptr(
const uint64_t rec_num,
417 const std::string& typestring,
420 std::unique_ptr<daqdataformats::Fragment> get_frag_ptr(
const record_id_t& rid,
421 const uint64_t geo_id);
422 std::unique_ptr<daqdataformats::Fragment> get_frag_ptr(
const uint64_t rec_num,
424 const uint64_t geo_id);
426 std::unique_ptr<daqdataformats::TriggerRecordHeader> get_trh_ptr(
const record_id_t& rid);
430 return get_trh_ptr(std::make_pair(trig_num, seq_num));
433 std::unique_ptr<daqdataformats::TimeSliceHeader> get_tsh_ptr(
const record_id_t& rid);
436 return get_tsh_ptr(std::make_pair(ts_num, 0));
443 return get_trigger_record(std::make_pair(trig_num, seq_num));
449 std::vector<uint64_t> get_geo_ids_for_source_id(
const record_id_t& rid,
453 const uint64_t geo_id);
456 HDF5RawDataFile(
const HDF5RawDataFile&) =
delete;
457 HDF5RawDataFile& operator=(
const HDF5RawDataFile&) =
delete;
458 HDF5RawDataFile(HDF5RawDataFile&&) =
delete;
459 HDF5RawDataFile& operator=(HDF5RawDataFile&&) =
delete;
461 std::unique_ptr<HighFive::File> m_file_ptr;
462 std::unique_ptr<HDF5FileLayout> m_file_layout_ptr;
463 std::string m_bare_file_name;
464 unsigned m_compression_level;
465 unsigned m_open_flags;
468 size_t m_recorded_size;
469 size_t m_uncompressed_raw_data_size;
470 size_t m_total_file_size;
471 std::string m_record_type;
474 void write_file_layout();
475 void read_file_layout();
476 void check_file_layout();
479 void check_record_type(std::string);
482 std::tuple<size_t, std::string, HighFive::Group> do_write(std::vector<std::string>
const&,
const char*,
size_t,
unsigned compression_level);
485 void explore_subgroup(
const HighFive::Group& parent_group,
486 std::string relative_path,
487 std::vector<std::string>& path_list);
490 void add_record_level_info_to_caches_if_needed(record_id_t rid);
493 record_id_set m_all_record_ids_in_file;
494 HDF5SourceIDHandler::source_id_geo_id_map_t m_file_level_source_id_geo_id_map;
495 std::map<record_id_t, std::set<daqdataformats::SourceID>> m_source_id_cache;
496 std::map<record_id_t, daqdataformats::SourceID> m_record_header_source_id_cache;
497 std::map<record_id_t, std::set<daqdataformats::SourceID>> m_fragment_source_id_cache;
498 std::map<record_id_t, HDF5SourceIDHandler::source_id_path_map_t> m_source_id_path_cache;
499 std::map<record_id_t, HDF5SourceIDHandler::source_id_geo_id_map_t> m_source_id_geo_id_cache;
500 std::map<record_id_t, HDF5SourceIDHandler::subsystem_source_id_map_t> m_subsystem_source_id_cache;
501 std::map<record_id_t, HDF5SourceIDHandler::fragment_type_source_id_map_t> m_fragment_type_source_id_cache;
502 std::map<record_id_t, HDF5SourceIDHandler::subdetector_source_id_map_t> m_subdetector_source_id_cache;
508HDF5RawDataFile::write_attribute(std::string name, T value)
510 if (!m_file_ptr->hasAttribute(name))
511 m_file_ptr->createAttribute(name, value);
518HDF5RawDataFile::write_attribute(HighFive::Group& grp,
const std::string& name, T value)
520 if (!(grp.hasAttribute(name)))
521 grp.createAttribute<T>(name, value);
528HDF5RawDataFile::write_attribute(HighFive::DataSet& dset,
const std::string& name, T value)
530 if (!dset.hasAttribute(name))
531 dset.createAttribute<T>(name, value);
538HDF5RawDataFile::get_attribute(
const std::string& name)
540 if (!m_file_ptr->hasAttribute(name)) {
541 throw InvalidHDF5Attribute(
ERS_HERE, name);
543 auto attr = m_file_ptr->getAttribute(name);
551HDF5RawDataFile::get_attribute_if_exists(
const std::string& name,
const T& default_value)
553 if (!m_file_ptr->hasAttribute(name)) {
554 TLOG_DEBUG(7) <<
"Debug: Attribute \"" << name <<
"\" not found. Defaulting to " << default_value;
555 return default_value;
557 auto attr = m_file_ptr->getAttribute(name);
560 TLOG_DEBUG(7) <<
"Debug: Attribute \"" << name <<
"\" found. Value: " << value;
566HDF5RawDataFile::get_attribute(
const HighFive::Group& grp,
const std::string& name)
568 if (!(grp.hasAttribute(name))) {
569 throw InvalidHDF5Attribute(
ERS_HERE, name);
571 auto attr = grp.getAttribute(name);
579HDF5RawDataFile::get_attribute(
const HighFive::DataSet& dset, std::string name)
581 if (!dset.hasAttribute(name)) {
582 throw InvalidHDF5Attribute(
ERS_HERE, name);
584 auto attr = dset.getAttribute(name);
#define ERS_DECLARE_ISSUE(namespace_name, class_name, message, attributes)
#define TLOG_DEBUG(lvl,...)
PDS Frame with unphysical timestamp detected with ts
void warning(const Issue &issue)