Skip to content
Snippets Groups Projects
Commit a8f36762 authored by Miroslav Saur's avatar Miroslav Saur
Browse files

Merge branch 'avoid-padding-noise-bits-in-packing-checksums' into '2024-patches'

PackedDataChecksum: Avoid padding bits in checksums for aggregates

See merge request !4624
parents e450c308 30461fe5
No related branches found
No related tags found
2 merge requests!4624PackedDataChecksum: Avoid padding bits in checksums for aggregates,!4597Synchronize master branch with 2024-patches
Pipeline #7642369 passed
......@@ -8,10 +8,14 @@
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\*****************************************************************************/
#pragma once
#include "GaudiKernel/MsgStream.h"
#include <boost/crc.hpp>
#include <boost/pfr/core.hpp>
#include <map>
#include <string>
#include <tuple>
#include <type_traits>
#include <vector>
......@@ -24,29 +28,36 @@ namespace LHCb::Hlt::PackedData {
* @date 2016-01-03
*/
class PackedDataChecksum {
private:
constexpr static const std::string_view global_cksum_key = "_global_";
struct Adaptor {
PackedDataChecksum* parent;
PackedDataChecksum* parent = nullptr;
std::string_view key;
template <typename U>
void save( const U& arg ) {
parent->process( key, arg );
if ( parent ) { parent->process( key, arg ); }
}
};
public:
template <typename T>
void processObject( const T& x, std::string_view key ) {
auto processor = Adaptor{this, key};
Adaptor processor{this, key};
x.save( processor );
}
/// Obtain the current value of a checksum
int checksum( std::string_view key = "" ) { return cksum_for( key ).checksum(); }
auto checksum( std::string_view key = "" ) {
return ( global_cksum_key == key ? global_checksum() : cksum_for( key ).checksum() );
}
/// Obtain the current value of all checksums
std::map<std::string, int> checksums() const {
std::map<std::string, int> result;
for ( const auto& x : m_result ) { result.emplace( x.first, x.second.checksum() ); }
result.emplace( global_cksum_key, global_checksum() );
return result;
}
......@@ -59,41 +70,62 @@ namespace LHCb::Hlt::PackedData {
for ( const auto& x : cs.m_result ) {
msg << "Packed data checksum for '" << x.first << "' = " << std::hex << x.second.checksum() << endmsg;
}
return msg;
return msg << "Packed data checksum for '" << global_cksum_key << "' = " << std::hex << cs.global_checksum()
<< endmsg;
}
private:
[[nodiscard]] boost::crc_32_type& cksum_for( std::string_view k ) {
auto i = m_result.find( k );
if ( i == m_result.end() ) { i = m_result.emplace( k, boost::crc_32_type{} ).first; }
return i->second;
}
template <typename T>
void process( std::string_view key, const T& x ) {
void process( boost::crc_32_type& cksum, const T& x ) {
static_assert( std::is_trivially_copyable_v<T> );
cksum_for( key ).process_bytes( &x, sizeof( x ) );
// Add to a "global" checksum, too
cksum_for( "_global_" ).process_bytes( &x, sizeof( x ) );
if constexpr ( std::is_aggregate_v<T> ) {
boost::pfr::for_each_field( x, [&]( const auto& i ) { this->process( cksum, i ); } );
} else {
cksum.process_bytes( &x, sizeof( x ) );
}
}
// Specialization for pairs as they might be padded
template <typename T1, typename T2>
void process( std::string_view key, const std::pair<T1, T2>& x ) {
process( key, std::forward_as_tuple( x.first, x.second ) );
void process( boost::crc_32_type& cksum, const std::pair<T1, T2>& x ) {
process( cksum, std::forward_as_tuple( x.first, x.second ) );
}
template <typename... T>
void process( std::string_view key, const std::tuple<T...>& x ) {
std::apply( [&]( const auto&... arg ) { ( process( key, arg ), ... ); }, x );
void process( boost::crc_32_type& cksum, const std::tuple<T...>& x ) {
std::apply( [&]( const auto&... arg ) { ( process( cksum, arg ), ... ); }, x );
}
template <typename T>
void process( std::string_view key, const T& x ) {
process( cksum_for( key ), x );
}
template <typename T, typename Allocator>
void process( std::string_view key, const std::vector<T, Allocator>& v ) {
for ( const auto& x : v ) process( key, x );
auto& cksum = cksum_for( key );
for ( const auto& x : v ) { process( cksum, x ); }
}
std::map<std::string, boost::crc_32_type, std::less<>> m_result;
[[nodiscard]] boost::crc_32_type& cksum_for( std::string_view k ) {
auto i = m_result.find( k );
if ( i == m_result.end() ) { i = m_result.emplace( k, boost::crc_32_type{} ).first; }
return i->second;
/// Generate a single global checksum
boost::crc_32_type::value_type global_checksum() const {
boost::crc_32_type global_cksum;
for ( const auto& x : m_result ) {
const auto cksum = x.second.checksum();
global_cksum.process_bytes( &cksum, sizeof( cksum ) );
}
return global_cksum.checksum();
}
private:
// Map of all TES checksums
std::map<std::string, boost::crc_32_type, std::less<>> m_result;
};
} // namespace LHCb::Hlt::PackedData
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment