$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_05_08
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #ifndef artdaq_core_Data_detail_RawFragmentHeader_hh 00002 #define artdaq_core_Data_detail_RawFragmentHeader_hh 00003 // detail::RawFragmentHeader is an overlay that provides the user's view 00004 // of the data contained within a Fragment. It is intended to be hidden 00005 // from the user of Fragment, as an implementation detail. The interface 00006 // of Fragment is intended to be used to access the data. 00007 00008 //#include <cstddef> 00009 #include <map> 00010 #include "artdaq-core/Data/dictionarycontrol.hh" 00011 #include "artdaq-core/Utilities/TimeUtils.hh" 00012 #include "cetlib_except/exception.h" 00013 00014 extern "C" { 00015 #include <stdint.h> 00016 } 00017 00018 namespace artdaq { 00019 namespace detail { 00020 struct RawFragmentHeader; 00021 } 00022 } // namespace artdaq 00023 00031 struct artdaq::detail::RawFragmentHeader 00032 { 00036 typedef unsigned long long RawDataType; 00037 00038 #if HIDE_FROM_ROOT 00039 typedef uint16_t version_t; 00040 typedef uint64_t sequence_id_t; 00041 typedef uint8_t type_t; 00042 typedef uint16_t fragment_id_t; 00043 typedef uint8_t metadata_word_count_t; 00044 typedef uint64_t timestamp_t; 00045 00046 // define special values for type_t 00047 static constexpr type_t INVALID_TYPE = 0; 00048 static constexpr type_t FIRST_USER_TYPE = 1; 00049 static constexpr type_t LAST_USER_TYPE = 224; 00050 static constexpr type_t FIRST_SYSTEM_TYPE = 225; 00051 static constexpr type_t LAST_SYSTEM_TYPE = 255; 00052 static constexpr type_t InvalidFragmentType = INVALID_TYPE; 00053 static constexpr type_t EndOfDataFragmentType = FIRST_SYSTEM_TYPE; 00054 static constexpr type_t DataFragmentType = FIRST_SYSTEM_TYPE + 1; 00055 static constexpr type_t InitFragmentType = FIRST_SYSTEM_TYPE + 2; 00056 static constexpr type_t EndOfRunFragmentType = FIRST_SYSTEM_TYPE + 3; 00057 static constexpr type_t EndOfSubrunFragmentType = FIRST_SYSTEM_TYPE + 4; 00058 static constexpr type_t ShutdownFragmentType = FIRST_SYSTEM_TYPE + 5; 00059 static constexpr type_t EmptyFragmentType = FIRST_SYSTEM_TYPE + 6; 00060 static constexpr type_t ContainerFragmentType = FIRST_SYSTEM_TYPE + 7; 00061 static constexpr type_t ErrorFragmentType = FIRST_SYSTEM_TYPE + 8; 00062 00067 static std::map<type_t, std::string> MakeSystemTypeMap() 00068 { 00069 return std::map<type_t, std::string>{ 00070 {type_t(DataFragmentType), "Data"}, 00071 {type_t(EmptyFragmentType), "Empty"}, 00072 {type_t(ErrorFragmentType), "Error"}, 00073 {type_t(InvalidFragmentType), "Invalid"}, 00074 {232, "Container"}}; 00075 } 00076 00081 static std::map<type_t, std::string> MakeVerboseSystemTypeMap() 00082 { 00083 return std::map<type_t, std::string>{ 00084 {type_t(EndOfDataFragmentType), "EndOfData"}, 00085 {type_t(DataFragmentType), "Data"}, 00086 {type_t(InitFragmentType), "Init"}, 00087 {type_t(EndOfRunFragmentType), "EndOfRun"}, 00088 {type_t(EndOfSubrunFragmentType), "EndOfSubrun"}, 00089 {type_t(ShutdownFragmentType), "Shutdown"}, 00090 {type_t(EmptyFragmentType), "Empty"}, 00091 {type_t(ContainerFragmentType), "Container"}}; 00092 } 00093 00099 static std::string SystemTypeToString(type_t type) 00100 { 00101 switch (type) 00102 { 00103 case INVALID_TYPE: 00104 return "INVALID"; 00105 case EndOfDataFragmentType: 00106 return "EndOfData"; 00107 case DataFragmentType: 00108 return "Data"; 00109 case InitFragmentType: 00110 return "Init"; 00111 case EndOfRunFragmentType: 00112 return "EndOfRun"; 00113 case EndOfSubrunFragmentType: 00114 return "EndOfSubrun"; 00115 case ShutdownFragmentType: 00116 return "Shutdown"; 00117 case EmptyFragmentType: 00118 return "Empty"; 00119 case ContainerFragmentType: 00120 return "Container"; 00121 } 00122 return "Unknown"; 00123 } 00124 00125 // Each of the following invalid values is chosen based on the 00126 // size of the bitfield in which the corresponding data are 00127 // encoded; if any of the sizes are changed, the corresponding 00128 // values must be updated. 00129 static const version_t InvalidVersion = 0xFFFF; 00130 static const version_t CurrentVersion = 0x2; 00131 static const sequence_id_t InvalidSequenceID = 0xFFFFFFFFFFFF; 00132 static const fragment_id_t InvalidFragmentID = 0xFFFF; 00133 static const timestamp_t InvalidTimestamp = 0xFFFFFFFFFFFFFFFF; 00134 00135 RawDataType word_count : 32; 00136 RawDataType version : 16; 00137 RawDataType type : 8; 00138 RawDataType metadata_word_count : 8; 00139 00140 RawDataType sequence_id : 48; 00141 RawDataType fragment_id : 16; 00142 00143 RawDataType timestamp : 64; 00144 00145 RawDataType valid : 1; 00146 RawDataType complete : 1; 00147 RawDataType atime_ns : 30; 00148 RawDataType atime_s : 32; 00149 00150 // **************************************************** 00151 // New fields MUST be added to the END of this list!!! 00152 // **************************************************** 00153 00158 static constexpr std::size_t num_words(); 00159 00165 void setUserType(uint8_t utype); 00166 00172 void setSystemType(uint8_t stype); 00173 00177 void touch(); 00182 struct timespec atime() const; 00188 struct timespec getLatency(bool touch); 00189 00190 #endif /* HIDE_FROM_ROOT */ 00191 }; 00192 00193 #if HIDE_FROM_ROOT 00194 inline constexpr std::size_t 00195 artdaq::detail::RawFragmentHeader::num_words() 00196 { 00197 return sizeof(detail::RawFragmentHeader) / sizeof(RawDataType); 00198 } 00199 00200 // Compile-time check that the assumption made in num_words() above is 00201 // actually true. 00202 static_assert((artdaq::detail::RawFragmentHeader::num_words() * 00203 sizeof(artdaq::detail::RawFragmentHeader::RawDataType)) == 00204 sizeof(artdaq::detail::RawFragmentHeader), 00205 "sizeof(RawFragmentHeader) is not an integer " 00206 "multiple of sizeof(RawDataType)!"); 00207 00208 inline void 00209 artdaq::detail::RawFragmentHeader::setUserType(uint8_t utype) 00210 { 00211 if (utype < FIRST_USER_TYPE || utype > LAST_USER_TYPE) 00212 { 00213 throw cet::exception("InvalidValue") 00214 << "RawFragmentHeader user types must be in the range of " 00215 << ((int)FIRST_USER_TYPE) << " to " << ((int)LAST_USER_TYPE) 00216 << " (bad type is " << ((int)utype) << ")."; 00217 } 00218 type = utype; 00219 } 00220 00221 inline void 00222 artdaq::detail::RawFragmentHeader::setSystemType(uint8_t stype) 00223 { 00224 if (stype < FIRST_SYSTEM_TYPE /*|| stype > LAST_SYSTEM_TYPE*/) 00225 { 00226 throw cet::exception("InvalidValue") 00227 << "RawFragmentHeader system types must be in the range of " 00228 << ((int)FIRST_SYSTEM_TYPE) << " to " << ((int)LAST_SYSTEM_TYPE); 00229 } 00230 type = stype; 00231 } 00232 00233 inline void artdaq::detail::RawFragmentHeader::touch() 00234 { 00235 auto time = artdaq::TimeUtils::get_realtime_clock(); 00236 atime_ns = time.tv_nsec; 00237 atime_s = time.tv_sec; 00238 } 00239 00240 inline struct timespec artdaq::detail::RawFragmentHeader::atime() const 00241 { 00242 struct timespec ts; 00243 ts.tv_nsec = atime_ns; 00244 ts.tv_sec = atime_s; 00245 return ts; 00246 } 00247 00248 inline struct timespec artdaq::detail::RawFragmentHeader::getLatency(bool touch) 00249 { 00250 auto a_time = atime(); 00251 auto time = artdaq::TimeUtils::get_realtime_clock(); 00252 00253 a_time.tv_sec = time.tv_sec - a_time.tv_sec; 00254 00255 if (a_time.tv_nsec > time.tv_nsec) 00256 { 00257 a_time.tv_sec--; 00258 a_time.tv_nsec = 1000000000 + time.tv_nsec - a_time.tv_nsec; 00259 } 00260 else 00261 { 00262 a_time.tv_nsec = time.tv_nsec - a_time.tv_nsec; 00263 } 00264 00265 if (touch) 00266 { 00267 atime_ns = time.tv_nsec; 00268 atime_s = time.tv_sec; 00269 } 00270 return a_time; 00271 } 00272 #endif 00273 00274 #endif /* artdaq_core_Data_detail_RawFragmentHeader_hh */