Skip to content
Snippets Groups Projects
Commit f8bd42d0 authored by Erik von Reis's avatar Erik von Reis
Browse files

Merge branch 'updates_to_fix_shmem_receiver_prev_gps' into 'master'

Track the previous gps second in the daqd shmem_receiver

Closes #189

See merge request cds/advligorts!172
parents c0f83051 b35b5c22
No related branches found
No related tags found
1 merge request!172Track the previous gps second in the daqd shmem_receiver
......@@ -63,17 +63,20 @@ public:
std::uint64_t spin_count = 0;
unsigned int cur_cycle = *cycle_ptr;
while ( cur_cycle == prev_cycle_ )
unsigned int max_cycle = get_max_cycle( );
while ( cur_cycle == prev_cycle_ || get_total_dcus( cur_cycle ) == 0 )
{
wait( );
cur_cycle = *cycle_ptr;
verify_cycle_state( cur_cycle, max_cycle );
++spin_count;
if ( spin_count == 2000 )
{
signal_stalled_( );
}
}
unsigned int max_cycle = get_max_cycle( );
max_cycle = get_max_cycle( );
verify_cycle_state( cur_cycle, max_cycle );
cur_cycle = handle_cycle_jumps( cur_cycle, max_cycle );
......@@ -91,6 +94,7 @@ public:
start, start + copy_size, reinterpret_cast< char* >( &data_ ) );
prev_cycle_ = cur_cycle;
prev_gps_ = data_.header.dcuheader[ 0 ].timeSec;
return &data_;
}
......@@ -112,6 +116,16 @@ private:
.timeSec;
}
unsigned int
get_total_dcus( unsigned int cycle )
{
unsigned int cycle_stride = shmem_->header.cycleDataSize;
char* start = const_cast< char* >( &shmem_->dataBlock[ 0 ] );
start += cycle * cycle_stride;
return reinterpret_cast< daq_multi_dcu_data_t* >( start )
->header.dcuTotalModels;
}
void
verify_cycle_state( unsigned int cur_cycle, unsigned int max_cycle )
{
......@@ -142,11 +156,11 @@ private:
unsigned int prev = prev_cycle_;
unsigned int prev_gps = prev_gps_;
if ( new_cycle == ( prev + 1 ) % max_cycle )
auto next_cycle = ( prev + 1 ) % max_cycle;
if ( new_cycle == next_cycle )
{
return new_cycle;
}
auto next_cycle = ( prev + 1 ) % max_cycle;
while ( next_cycle != new_cycle )
{
auto expected_gps = prev_gps;
......@@ -155,7 +169,8 @@ private:
++expected_gps;
}
auto actual_gps = get_gps( next_cycle );
if ( actual_gps == expected_gps )
if ( actual_gps == expected_gps &&
get_total_dcus( next_cycle ) != 0 )
{
return next_cycle;
}
......
......@@ -7,6 +7,30 @@
#include "raii.hh"
#include "catch.hpp"
namespace
{
void
setup_basic_data( daq_multi_cycle_data_t& shmem )
{
auto cycle_data_size = shmem.header.cycleDataSize =
sizeof( shmem.dataBlock ) / 16;
for ( int i = 0; i < 16; ++i )
{
auto start = ( &shmem.dataBlock[ 0 ] ) + i * cycle_data_size;
auto* cur_segment =
reinterpret_cast< daq_multi_dcu_data_t* >( start );
cur_segment->header.dcuTotalModels = 1;
cur_segment->header.dcuheader[ 0 ].cycle = i;
cur_segment->header.dcuheader[ 0 ].timeSec = 1000000000;
cur_segment->header.fullDataBlockSize = 64;
auto start_data =
reinterpret_cast< char* >( &cur_segment->dataBlock[ 0 ] );
std::fill( start_data, start_data + 64, i );
}
}
} // namespace
TEST_CASE(
"ShMemReceiver should get the next available cycle when it starts up" )
{
......@@ -32,7 +56,8 @@ TEST_CASE(
}
ShMemReceiver recv(
reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ), sizeof( daq_multi_cycle_data_t) );
reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ),
sizeof( daq_multi_cycle_data_t ) );
recv.reset_previous_cycle( 4, 1000000000 );
auto data = recv.receive_data( );
REQUIRE( data->dataBlock[ 0 ] == 5 );
......@@ -62,12 +87,44 @@ TEST_CASE( "ShMemReceiver should try to catch up if it sees a jump" )
}
ShMemReceiver recv(
reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ), sizeof( daq_multi_cycle_data_t ) );
reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ),
sizeof( daq_multi_cycle_data_t ) );
recv.reset_previous_cycle( 0, 1000000000 );
auto data = recv.receive_data( );
REQUIRE( data->dataBlock[ 0 ] == 1 );
}
TEST_CASE( "ShMemReceiver treats a 0 dcu cycle as a skipped cycle" )
{
auto shmem = raii::make_unique_ptr< daq_multi_cycle_data_t >( );
shmem->header.maxCycle = 16;
shmem->header.curCycle = 6;
shmem->header.cycleDataSize = sizeof( shmem->dataBlock ) / 16;
auto cycle_data_size = shmem->header.cycleDataSize;
for ( int i = 0; i < 16; ++i )
{
auto start = ( &shmem->dataBlock[ 0 ] ) + i * cycle_data_size;
auto* cur_segment = reinterpret_cast< daq_multi_dcu_data_t* >( start );
cur_segment->header.dcuTotalModels = ( i == 5 ? 0 : 1 );
cur_segment->header.dcuheader[ 0 ].cycle = i;
cur_segment->header.dcuheader[ 0 ].timeSec = 1000000000;
cur_segment->header.fullDataBlockSize = 64;
auto start_data =
reinterpret_cast< char* >( &cur_segment->dataBlock[ 0 ] );
std::fill( start_data, start_data + 64, i );
}
ShMemReceiver recv(
reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ),
sizeof( daq_multi_cycle_data_t ) );
recv.reset_previous_cycle( 4, 1000000000 );
auto data = recv.receive_data( );
REQUIRE( data->dataBlock[ 0 ] == 6 );
}
TEST_CASE( "ShMemReceiver should try to catch up if it sees a jump, even when "
"the cycle counter wraps around" )
{
......@@ -101,6 +158,39 @@ TEST_CASE( "ShMemReceiver should try to catch up if it sees a jump, even when "
REQUIRE( data->dataBlock[ 0 ] == 11 );
}
TEST_CASE( "ShMemReceiver should try to catch up if it sees a jump, even when "
"the cycle counter wraps around or there is a 0 dcu segment" )
{
auto shmem = raii::make_unique_ptr< daq_multi_cycle_data_t >( );
shmem->header.maxCycle = 16;
shmem->header.curCycle = 5;
shmem->header.cycleDataSize = sizeof( shmem->dataBlock ) / 16;
auto cycle_data_size = shmem->header.cycleDataSize;
for ( int i = 0; i < 16; ++i )
{
auto start = ( &shmem->dataBlock[ 0 ] ) + i * cycle_data_size;
auto* cur_segment = reinterpret_cast< daq_multi_dcu_data_t* >( start );
cur_segment->header.dcuTotalModels = ( i == 15 ? 0 : 1 );
cur_segment->header.dcuheader[ 0 ].cycle = i;
cur_segment->header.dcuheader[ 0 ].timeSec =
1000000000 + ( i <= 5 ? 1 : 0 );
cur_segment->header.fullDataBlockSize = 64;
auto start_data =
reinterpret_cast< char* >( &cur_segment->dataBlock[ 0 ] );
std::fill( start_data, start_data + 64, i );
}
ShMemReceiver recv(
reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ),
sizeof( daq_multi_cycle_data_t ) );
recv.reset_previous_cycle( 10, 1000000000 );
auto data = recv.receive_data( );
REQUIRE( data->dataBlock[ 0 ] == 11 );
}
TEST_CASE( "ShMemReceiver should try to catch up but will jump if needed" )
{
auto shmem = raii::make_unique_ptr< daq_multi_cycle_data_t >( );
......@@ -132,45 +222,48 @@ TEST_CASE( "ShMemReceiver should try to catch up but will jump if needed" )
REQUIRE( data->dataBlock[ 0 ] == 5 );
}
TEST_CASE( "ShMemReceiver will throw an exception if max cycles is too big")
TEST_CASE( "ShMemReceiver will throw an exception if max cycles is too big" )
{
auto shmem = raii::make_unique_ptr< daq_multi_cycle_data_t >( );
shmem->header.maxCycle = 65;
shmem->header.curCycle = 5;
shmem->header.cycleDataSize = sizeof( shmem->dataBlock ) / 16;
setup_basic_data( *shmem );
ShMemReceiver recv(
reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ),
sizeof( daq_multi_cycle_data_t ) );
reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ),
sizeof( daq_multi_cycle_data_t ) );
recv.reset_previous_cycle( 0, 1000000000 - 1 );
REQUIRE_THROWS_AS(recv.receive_data(), std::runtime_error);
REQUIRE_THROWS_AS( recv.receive_data( ), std::runtime_error );
}
TEST_CASE( "ShMemReceiver will throw an exception if curCycle is too big")
TEST_CASE( "ShMemReceiver will throw an exception if curCycle is too big" )
{
auto shmem = raii::make_unique_ptr< daq_multi_cycle_data_t >( );
shmem->header.maxCycle = 16;
shmem->header.curCycle = 15;
shmem->header.cycleDataSize = sizeof( shmem->dataBlock ) / 16;
setup_basic_data( *shmem );
ShMemReceiver recv(
reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ),
sizeof( daq_multi_cycle_data_t ) );
reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ),
sizeof( daq_multi_cycle_data_t ) );
recv.reset_previous_cycle( 15, 1000000000 - 1 );
shmem->header.curCycle = 16;
REQUIRE_THROWS_AS(recv.receive_data(), std::runtime_error);
REQUIRE_THROWS_AS( recv.receive_data( ), std::runtime_error );
}
TEST_CASE( "ShMemReceiver will throw an exception if cycleDataSize*maxCycle is too big")
TEST_CASE( "ShMemReceiver will throw an exception if cycleDataSize*maxCycle is "
"too big" )
{
auto shmem = raii::make_unique_ptr< daq_multi_cycle_data_t >( );
shmem->header.maxCycle = 16;
shmem->header.curCycle = 15;
shmem->header.cycleDataSize = sizeof( shmem->dataBlock ) / 16;
ShMemReceiver recv(
reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ),
sizeof( daq_multi_cycle_data_t ) );
reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ),
sizeof( daq_multi_cycle_data_t ) );
recv.reset_previous_cycle( 15, 1000000000 - 1 );
shmem->header.curCycle = 0;
// this does not take away the header size, so it should lead to an overflow condition
shmem->header.cycleDataSize = sizeof(daq_multi_cycle_data_t)/16;
REQUIRE_THROWS_AS(recv.receive_data(), std::runtime_error);
// this does not take away the header size, so it should lead to an overflow
// condition
shmem->header.cycleDataSize = sizeof( daq_multi_cycle_data_t ) / 16;
REQUIRE_THROWS_AS( recv.receive_data( ), std::runtime_error );
}
\ No newline at end of file
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