From 43279813ad717652783fc0a5fa447625e919791d Mon Sep 17 00:00:00 2001 From: Jonathan Hanks <jonathan.hanks@ligo.org> Date: Tue, 18 Aug 2020 12:32:15 -0500 Subject: [PATCH] Updates to the mbuf_probe check_size test to fix bugs in testing. * Properly record the expected crc config value * Do some output on the first cycle so that we know the test is progressing. --- src/drv/mbuf/mbuf_probe/CMakeLists.txt | 5 +- src/drv/mbuf/mbuf_probe/check_size.cc | 320 +++++++++++++++++++++++++ src/drv/mbuf/mbuf_probe/check_size.hh | 22 ++ src/drv/mbuf/mbuf_probe/gap_check.cc | 48 +--- src/drv/mbuf/mbuf_probe/mbuf_probe.cc | 48 +++- src/drv/mbuf/mbuf_probe/mbuf_probe.hh | 67 +++++- 6 files changed, 450 insertions(+), 60 deletions(-) create mode 100644 src/drv/mbuf/mbuf_probe/check_size.cc create mode 100644 src/drv/mbuf/mbuf_probe/check_size.hh diff --git a/src/drv/mbuf/mbuf_probe/CMakeLists.txt b/src/drv/mbuf/mbuf_probe/CMakeLists.txt index b27b0321b..715c84526 100644 --- a/src/drv/mbuf/mbuf_probe/CMakeLists.txt +++ b/src/drv/mbuf/mbuf_probe/CMakeLists.txt @@ -4,12 +4,13 @@ add_executable(mbuf_probe mbuf_probe.cc mbuf_decoders.cc analyze_daq_multi_dc.cc - analyze_rmipc.cc) + analyze_rmipc.cc + check_size.cc) target_include_directories(mbuf_probe PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/../../include ) -target_link_libraries(mbuf_probe PUBLIC driver::shmem) +target_link_libraries(mbuf_probe PUBLIC driver::shmem driver::ini_parsing) target_requires_cpp11(mbuf_probe PRIVATE) install(TARGETS mbuf_probe DESTINATION bin) \ No newline at end of file diff --git a/src/drv/mbuf/mbuf_probe/check_size.cc b/src/drv/mbuf/mbuf_probe/check_size.cc new file mode 100644 index 000000000..01301fed0 --- /dev/null +++ b/src/drv/mbuf/mbuf_probe/check_size.cc @@ -0,0 +1,320 @@ +// +// Created by jonathan.hanks on 8/13/20. +// + +#include "check_size.hh" + +#include <algorithm> +#include <array> +#include <fstream> +#include <iostream> + +#include "daq_core.h" +#include "daq_core_defs.h" +#include "daq_data_types.h" + +#include "daqmap.h" +extern "C" { +#include "param.h" +} + +namespace check_mbuf_sizes +{ + typedef struct ini_file_info + { + ini_file_info( ) + : dcu_sizes( ), dcu_config_crc( ), last_dcuid( 0 ), valid( true ) + { + std::fill( dcu_sizes.begin( ), dcu_sizes.end( ), 0 ); + std::fill( dcu_config_crc.begin( ), dcu_config_crc.end( ), 0 ); + } + ini_file_info( const ini_file_info& ) noexcept = default; + ini_file_info& operator=( const ini_file_info& ) noexcept = default; + + std::array< unsigned int, DAQ_TRANSIT_MAX_DCU > dcu_sizes; + std::array< unsigned long, DAQ_TRANSIT_MAX_DCU > dcu_config_crc; + int last_dcuid; + bool valid; + } size_info; + + int + channel_callback( char* channel_name, + struct CHAN_PARAM* params, + void* user ) + { + auto* info = reinterpret_cast< ini_file_info* >( user ); + int chan_size = data_type_size( params->datatype ) * + ( params->datarate / DAQ_NUM_DATA_BLOCKS_PER_SECOND ); + if ( chan_size == 0 ) + { + info->valid = false; + } + else + { + info->dcu_sizes[ params->dcuid ] += chan_size; + } + info->last_dcuid = params->dcuid; + return 1; + } + + ini_file_info + load_master( const std::string& fname ) + { + ini_file_info sysinfo; + // File names are specified in `master_config' file + std::ifstream mcf( fname ); + + for ( std::string line; std::getline( mcf, line ); ) + { + std::string trimmed_line; + trimmed_line.reserve( line.size( ) ); + std::copy_if( line.begin( ), + line.end( ), + std::back_inserter( trimmed_line ), + []( const char ch ) -> bool { return ch != ' '; } ); + if ( line.front( ) == '#' ) + { + continue; + } + if ( trimmed_line.empty( ) || trimmed_line.front( ) == '#' ) + { + continue; + } + + std::string ext = + ( trimmed_line.size( ) > 4 + ? trimmed_line.substr( trimmed_line.size( ) - 4 ) + : "" ); + auto testpoint = ( ext == ".par" ); + + unsigned long file_crc = 0; + sysinfo.valid = true; + sysinfo.last_dcuid = -1; + int parse_status = + ::parseConfigFile( const_cast< char* >( trimmed_line.c_str( ) ), + &file_crc, + channel_callback, + testpoint, + 0, + reinterpret_cast< void* >( &sysinfo ) ); + if ( parse_status == 0 || !sysinfo.valid || sysinfo.last_dcuid < 0 ) + { + std::cerr << "Unable to process " << trimmed_line + << " either the file is invalid, bad data types, or " + "other error (" + << sysinfo.valid << ", " << sysinfo.last_dcuid + << ")\n"; + if ( sysinfo.last_dcuid >= 0 ) + { + sysinfo.dcu_sizes[ sysinfo.last_dcuid ] = 0; + } + } + else + { + sysinfo.dcu_config_crc[ sysinfo.last_dcuid ] = file_crc; + } + } + return sysinfo; + } + + int + check_size_rmipc( volatile void* buffer, + std::size_t buffer_size, + const ::ConfigOpts& options ) + { + if ( options.analysis_type != MBUF_RMIPC || + buffer_size != 64 * 1024 * 1024 ) + { + return 0; + } + + load_master( options.ini_file_fname ); + + unsigned int prev_config_crc{ 0 }; + unsigned int prev_data_size{ 0 }; + + auto header = reinterpret_cast< const volatile rmIpcStr* >( buffer ); + + ini_file_info dcu_reference; + bool noted_crc_change{ false }; + + bool have_inis = false; + if ( !options.ini_file_fname.empty( ) ) + { + dcu_reference = load_master( options.ini_file_fname ); + have_inis = true; + } + + bool first_iteration = true; + while ( true ) + { + wait_until_changed< const unsigned int, 5000 >( &header->cycle, + header->cycle ); + + auto cur_cycle = header->cycle; + auto dcuid = header->dcuId; + + if ( !first_iteration ) + { + if ( have_inis ) + { + if ( header->crc != dcu_reference.dcu_config_crc[ dcuid ] && + !noted_crc_change ) + { + std::cout + << "config change on dcu " << dcuid << " from " + << dcu_reference.dcu_config_crc[ dcuid ] << " to " + << header->crc << "\n"; + noted_crc_change = true; + } + if ( dcu_reference.dcu_sizes[ dcuid ] != + header->dataBlockSize ) + { + std::cout << "wrong data size on " << dcuid + << " expected " + << dcu_reference.dcu_sizes[ dcuid ] << " got " + << header->dataBlockSize << "\n"; + } + } + else + { + if ( prev_config_crc != header->crc && !noted_crc_change ) + { + std::cout << "config change on dcu " << dcuid + << " from " << prev_config_crc << " to " + << header->crc << "\n"; + noted_crc_change; + } + if ( prev_data_size != header->dataBlockSize ) + { + std::cout << "data size change on dcu " << dcuid + << " from " << prev_data_size << " to " + << header->dataBlockSize << "\n"; + } + } + } + prev_config_crc = header->crc; + prev_data_size = header->dataBlockSize; + + if ( first_iteration ) + { + std::cout + << "Completed the first iteration of the check_size test" + << std::endl; + first_iteration = false; + } + } + return 0; + } + + int + check_size_multi( volatile void* buffer, + std::size_t buffer_size, + const ::ConfigOpts& options ) + { + if ( !buffer || buffer_size < DAQD_MIN_SHMEM_BUFFER_SIZE || + buffer_size > DAQD_MAX_SHMEM_BUFFER_SIZE || + options.analysis_type != MBUF_DAQ_MULTI_DC ) + { + return 0; + } + + load_master( options.ini_file_fname ); + + std::array< unsigned int, DAQ_TRANSIT_MAX_DCU > prev_config_crc{}; + std::array< unsigned int, DAQ_TRANSIT_MAX_DCU > prev_data_size{}; + + std::fill( prev_config_crc.begin( ), prev_config_crc.end( ), 0 ); + std::fill( prev_data_size.begin( ), prev_data_size.end( ), 0 ); + + auto multi_header = + reinterpret_cast< const volatile daq_multi_cycle_data_t* >( + buffer ); + + ini_file_info dcu_reference; + std::array< bool, DAQ_TRANSIT_MAX_DCU > noted_crc_change{}; + std::fill( noted_crc_change.begin( ), noted_crc_change.end( ), false ); + bool have_inis = false; + if ( !options.ini_file_fname.empty( ) ) + { + dcu_reference = load_master( options.ini_file_fname ); + have_inis = true; + } + + bool first_iteration = true; + while ( true ) + { + wait_for_time_change< 5000 >( multi_header->header ); + + auto cur_cycle = multi_header->header.curCycle; + auto cycle_data_size = multi_header->header.cycleDataSize; + + auto cur_cylce_block = + reinterpret_cast< const volatile daq_multi_dcu_data_t* >( + &multi_header->dataBlock[ 0 ] + + (cycle_data_size)*cur_cycle ); + auto total_models = cur_cylce_block->header.dcuTotalModels; + + for ( auto i = 0; i < total_models; ++i ) + { + auto& cur_header = cur_cylce_block->header.dcuheader[ i ]; + auto dcuid = cur_header.dcuId; + + if ( !first_iteration ) + { + if ( have_inis ) + { + if ( cur_header.fileCrc != + dcu_reference.dcu_config_crc[ dcuid ] && + !noted_crc_change[ dcuid ] ) + { + std::cout << "config change on dcu " << dcuid + << " from " + << dcu_reference.dcu_config_crc[ dcuid ] + << " to " << cur_header.fileCrc << "\n"; + noted_crc_change[ dcuid ] = true; + } + if ( dcu_reference.dcu_sizes[ dcuid ] != + cur_header.dataBlockSize ) + { + std::cout << "wrong data size on " << dcuid + << " expected " + << dcu_reference.dcu_sizes[ dcuid ] + << " got " << cur_header.dataBlockSize + << "\n"; + } + } + else + { + if ( prev_config_crc[ dcuid ] != cur_header.fileCrc && + !noted_crc_change[ dcuid ] ) + { + std::cout << "config change on dcu " << dcuid + << " from " << prev_config_crc[ dcuid ] + << " to " << cur_header.fileCrc << "\n"; + noted_crc_change[ dcuid ]; + } + if ( prev_data_size[ dcuid ] != + cur_header.dataBlockSize ) + { + std::cout << "data size change on dcu " << dcuid + << " from " << prev_data_size[ dcuid ] + << " to " << cur_header.dataBlockSize + << "\n"; + } + } + } + prev_config_crc[ dcuid ] = cur_header.fileCrc; + prev_data_size[ dcuid ] = cur_header.dataBlockSize; + } + if ( first_iteration ) + { + std::cout + << "Completed the first iteration of the check_size test" + << std::endl; + first_iteration = false; + } + } + return 0; + } +} // namespace check_mbuf_sizes \ No newline at end of file diff --git a/src/drv/mbuf/mbuf_probe/check_size.hh b/src/drv/mbuf/mbuf_probe/check_size.hh new file mode 100644 index 000000000..221135bca --- /dev/null +++ b/src/drv/mbuf/mbuf_probe/check_size.hh @@ -0,0 +1,22 @@ +// +// Created by jonathan.hanks on 8/13/20. +// + +#ifndef DAQD_TRUNK_CHECK_SIZE_HH +#define DAQD_TRUNK_CHECK_SIZE_HH + +#include <cstddef> + +#include "mbuf_probe.hh" + +namespace check_mbuf_sizes +{ + int check_size_rmipc( volatile void* buffer, + std::size_t buffer_Size, + const ConfigOpts& options ); + int check_size_multi( volatile void* buffer, + std::size_t buffer_Size, + const ConfigOpts& options ); +} // namespace check_mbuf_sizes + +#endif // DAQD_TRUNK_CHECK_SIZE_HH diff --git a/src/drv/mbuf/mbuf_probe/gap_check.cc b/src/drv/mbuf/mbuf_probe/gap_check.cc index 2e1fce44f..3d3479590 100644 --- a/src/drv/mbuf/mbuf_probe/gap_check.cc +++ b/src/drv/mbuf/mbuf_probe/gap_check.cc @@ -2,58 +2,12 @@ // Created by jonathan.hanks on 3/13/20. // #include "gap_check.hh" -#include <chrono> -#include <daq_core.h> - -#include <sys/time.h> -#include <unistd.h> #include <iostream> +#include "mbuf_probe.hh" namespace check_gap { - static std::int64_t - time_now_ms( ) - { - timeval tv; - gettimeofday( &tv, 0 ); - return static_cast< std::uint64_t >( tv.tv_sec * 1000 + - tv.tv_usec / 1000 ); - } - - struct cycle_sample_t - { - unsigned int cycle; - unsigned int gps; - unsigned int gps_nano; - unsigned int gps_cycle; - std::uint64_t time_ms; - }; - - cycle_sample_t - wait_for_time_change( volatile daq_multi_cycle_header_t& header ) - { - cycle_sample_t results; - unsigned int cur_cycle = header.curCycle; - while ( header.curCycle == cur_cycle ) - { - usleep( 2000 ); - } - results.time_ms = time_now_ms( ); - results.cycle = header.curCycle; - - unsigned int stride = header.cycleDataSize; - volatile char* buffer_data = - reinterpret_cast< volatile char* >( &header ) + - sizeof( daq_multi_cycle_header_t ); - volatile daq_dc_data_t* daq = - reinterpret_cast< volatile daq_dc_data_t* >( - buffer_data + stride * header.curCycle ); - results.gps = daq->header.dcuheader[ 0 ].timeSec; - results.gps_nano = daq->header.dcuheader[ 0 ].timeNSec; - results.gps_cycle = daq->header.dcuheader[ 0 ].cycle; - return results; - } int check_gaps( volatile void* buffer, std::size_t buffer_size ) diff --git a/src/drv/mbuf/mbuf_probe/mbuf_probe.cc b/src/drv/mbuf/mbuf_probe/mbuf_probe.cc index 4e81684ac..e1879d559 100644 --- a/src/drv/mbuf/mbuf_probe/mbuf_probe.cc +++ b/src/drv/mbuf/mbuf_probe/mbuf_probe.cc @@ -28,6 +28,10 @@ #include "analyze_daq_multi_dc.hh" #include "analyze_rmipc.hh" #include "gap_check.hh" +#include "check_size.hh" + +const int OK = 0; +const int ERROR = 1; void usage( const char* progname ) @@ -42,6 +46,8 @@ usage( const char* progname ) std::cout << "\tanalyze - continually read the mbuf and do some analysis\n"; std::cout << "\tgap_check - continually scan the buffers looking for " "gaps/jumps in the data stream\n"; + std::cout << "\tcheck_sizes - check the given buffer's data segment sizes " + "against the expected size as calculated in the ini files."; std::cout << "\t-b <buffer name> - The name of the buffer to act on\n"; std::cout << "\t-m <buffer size in MB> - The size of the buffer in megabytes\n"; @@ -49,6 +55,8 @@ usage( const char* progname ) "multiple of 4k)\n"; std::cout << "\t-o <filename> - Output file for the copy operation " "(defaults to probe_out.bin)\n"; + std::cout << "\t-i <filename> - Path to the master ini file (only used " + "for the check_size action)\n"; std::cout << "\t--struct <type> - Type of structure to analyze [rmIpcStr]\n"; std::cout << "\t--dcu <dcuid> - Optional DCU id used to select a dcu for " @@ -79,6 +87,7 @@ parse_options( int argc, char* argv[] ) command_lookup.insert( std::make_pair( "delete", DELETE ) ); command_lookup.insert( std::make_pair( "analyze", ANALYZE ) ); command_lookup.insert( std::make_pair( "gap_check", GAP_CHECK ) ); + command_lookup.insert( std::make_pair( "check_size", CHECK_SIZE ) ); std::map< std::string, MBufStructures > struct_lookup; struct_lookup.insert( std::make_pair( "rmIpcStr", MBUF_RMIPC ) ); @@ -157,6 +166,17 @@ parse_options( int argc, char* argv[] ) is >> offset; opts.decoder = DataDecoder( offset, format_spec ); } + else if ( arg == "-i" ) + { + if ( args.empty( ) ) + { + opts.set_error( + "You must specify a ini file path when using -i" ); + return opts; + } + opts.ini_file_fname = args.front( ); + args.pop_front( ); + } else if ( arg == "--struct" ) { if ( args.empty( ) ) @@ -325,9 +345,6 @@ list_shmem_segments( ) int handle_analyze( const ConfigOpts& opts ) { - const int OK = 0; - const int ERROR = 1; - volatile void* buffer = shmem_open_segment( opts.buffer_name.c_str( ), opts.buffer_size ); switch ( opts.analysis_type ) @@ -348,9 +365,6 @@ handle_analyze( const ConfigOpts& opts ) int handle_gap_check( const ConfigOpts& opts ) { - const int OK = 0; - const int ERROR = 1; - if ( opts.analysis_type != MBUF_DAQ_MULTI_DC ) { std::cout << "daq_multi_cycle is the only mode that the crc_check is " @@ -363,6 +377,26 @@ handle_gap_check( const ConfigOpts& opts ) return OK; } +int +handle_check_size( const ConfigOpts& opts ) +{ + volatile void* buffer = + shmem_open_segment( opts.buffer_name.c_str( ), opts.buffer_size ); + switch ( opts.analysis_type ) + { + case MBUF_RMIPC: + check_mbuf_sizes::check_size_rmipc( buffer, opts.buffer_size, opts ); + break; + case MBUF_DAQ_MULTI_DC: + check_mbuf_sizes::check_size_multi( buffer, opts.buffer_size, opts ); + break; + default: + std::cout << "Unknown analysis type for the check size commandn"; + return ERROR; + } + return OK; +} + int main( int argc, char* argv[] ) { @@ -408,6 +442,8 @@ main( int argc, char* argv[] ) return handle_analyze( opts ); case GAP_CHECK: return handle_gap_check( opts ); + case CHECK_SIZE: + return handle_check_size( opts ); } return 0; } diff --git a/src/drv/mbuf/mbuf_probe/mbuf_probe.hh b/src/drv/mbuf/mbuf_probe/mbuf_probe.hh index 2b1e64c71..9609af1d6 100644 --- a/src/drv/mbuf/mbuf_probe/mbuf_probe.hh +++ b/src/drv/mbuf/mbuf_probe/mbuf_probe.hh @@ -5,12 +5,17 @@ #ifndef DAQD_MBUF_PROBE_HH #define DAQD_MBUF_PROBE_HH +#include <chrono> #include <cstddef> #include <string> #include <vector> +#include <type_traits> +#include <sys/time.h> #include <unistd.h> +#include <daq_core.h> + #include "mbuf_decoders.hh" enum MBufCommands @@ -22,6 +27,7 @@ enum MBufCommands DELETE, ANALYZE, GAP_CHECK, + CHECK_SIZE, }; enum MBufStructures @@ -35,8 +41,9 @@ struct ConfigOpts { ConfigOpts( ) : action( INVALID ), buffer_size( 0 ), buffer_name( "" ), - output_fname( "probe_out.bin" ), error_msg( "" ), dcu_id( -1 ), - decoder( ), analysis_type( MBUF_INVALID ) + output_fname( "probe_out.bin" ), error_msg( "" ), + ini_file_fname( "" ), dcu_id( -1 ), decoder( ), + analysis_type( MBUF_INVALID ) { } MBufCommands action; @@ -44,6 +51,7 @@ struct ConfigOpts std::string buffer_name; std::string output_fname; std::string error_msg; + std::string ini_file_fname; int dcu_id; DataDecoder decoder; MBufStructures analysis_type; @@ -115,6 +123,13 @@ struct ConfigOpts "as well as daq_multi_cycle" ); } break; + case CHECK_SIZE: + if ( buffer_name.empty( ) || buffer_size == 0 ) + { + set_error( "To check sizes you must specify a buffer, size, " + "and optionally an ini file" ); + } + break; case INVALID: default: set_error( "Please select a valid action" ); @@ -134,17 +149,59 @@ struct ConfigOpts } }; -template < typename T > +template < typename T, int CheckPeriodUS = 250 > unsigned int wait_until_changed( volatile T* counter, T old_counter ) { - T cur_cycle = *counter; + typename std::remove_const< T >::type cur_cycle = *counter; do { - usleep( 250 ); + usleep( CheckPeriodUS ); cur_cycle = *counter; } while ( cur_cycle == old_counter ); return cur_cycle; } +inline std::int64_t +time_now_ms( ) +{ + timeval tv; + gettimeofday( &tv, 0 ); + return static_cast< std::uint64_t >( tv.tv_sec * 1000 + tv.tv_usec / 1000 ); +} + +struct cycle_sample_t +{ + unsigned int cycle; + unsigned int gps; + unsigned int gps_nano; + unsigned int gps_cycle; + std::uint64_t time_ms; +}; + +template < int CheckPeriodUS = 2000 > +cycle_sample_t +wait_for_time_change( const volatile daq_multi_cycle_header_t& header ) +{ + cycle_sample_t results; + unsigned int cur_cycle = header.curCycle; + while ( header.curCycle == cur_cycle ) + { + usleep( CheckPeriodUS ); + } + results.time_ms = time_now_ms( ); + results.cycle = header.curCycle; + + unsigned int stride = header.cycleDataSize; + const volatile char* buffer_data = + reinterpret_cast< const volatile char* >( &header ) + + sizeof( daq_multi_cycle_header_t ); + const volatile daq_dc_data_t* daq = + reinterpret_cast< const volatile daq_dc_data_t* >( + buffer_data + stride * header.curCycle ); + results.gps = daq->header.dcuheader[ 0 ].timeSec; + results.gps_nano = daq->header.dcuheader[ 0 ].timeNSec; + results.gps_cycle = daq->header.dcuheader[ 0 ].cycle; + return results; +} #endif // DAQD_MBUF_PROBE_HH -- GitLab