Skip to content
Snippets Groups Projects
Commit 43279813 authored by Jonathan Hanks's avatar Jonathan Hanks Committed by Erik von Reis
Browse files

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.
parent e44008a7
No related branches found
No related tags found
No related merge requests found
......@@ -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
//
// 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
//
// 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
......@@ -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 )
......
......@@ -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;
}
......@@ -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
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