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

Merge branch 'local_dc_rate_specification' into 'master'

Update local_dc to better support running a standalone edc.

Closes #136

See merge request cds/advligorts!135
parents a5d6fc14 6226698c
No related branches found
No related tags found
1 merge request!135Update local_dc to better support running a standalone edc.
...@@ -97,20 +97,12 @@ popd ...@@ -97,20 +97,12 @@ popd
echo "$TDIR/ini_files/edcu.ini" > $TDIR/ini_files/master echo "$TDIR/ini_files/edcu.ini" > $TDIR/ini_files/master
echo "[X6:EDCU-EXC_1]" > "$TDIR/ini_files/tpchn_edc.par"
echo "ifoid = 1" >> "$TDIR/ini_files/tpchn_edc.par"
echo "rmid = 52" >> "$TDIR/ini_files/tpchn_edc.par"
echo "dcuid = 52" >> "$TDIR/ini_files/tpchn_edc.par"
echo "chnnum = 1" >> "$TDIR/ini_files/tpchn_edc.par"
echo "datatype = 4" >> "$TDIR/ini_files/tpchn_edc.par"
echo "datarate = 16" >> "$TDIR/ini_files/tpchn_edc.par"
sleep 1 sleep 1
"$STANDALONE_EDC" -b edc -i "$TDIR/ini_files/edcu.ini" -p X6: -l 127.0.0.1:9000 &> "$TDIR/logs/standalone_edc" & "$STANDALONE_EDC" -b edc -i "$TDIR/ini_files/edcu.ini" -p X6: -l 127.0.0.1:9000 &> "$TDIR/logs/standalone_edc" &
PID_STANDALONE_EDC=$! PID_STANDALONE_EDC=$!
"$LOCAL_DC" -b local_dc -m 100 -s edc -d "$TDIR/ini_files" &> "$TDIR/logs/local_dc" & "$LOCAL_DC" -b local_dc -m 100 -s edc:52 -d "$TDIR/ini_files" &> "$TDIR/logs/local_dc" &
PID_LOCAL_DC=$! PID_LOCAL_DC=$!
echo "Streamer PID = PID_LOCAL_DC" echo "Streamer PID = PID_LOCAL_DC"
......
add_executable(local_dc local_dc.c ${CMAKE_CURRENT_SOURCE_DIR}/../drv/rfm.c) add_executable(local_dc local_dc.c ${CMAKE_CURRENT_SOURCE_DIR}/../drv/rfm.c)
target_link_libraries(local_dc PUBLIC util) target_link_libraries(local_dc PUBLIC
args
util)
configure_file(test_local_dc.sh.in test_local_dc.sh @ONLY) configure_file(test_local_dc.sh.in test_local_dc.sh @ONLY)
add_executable(test_local_dc_unit_tests tests/test_local_dc_unit_tests.c)
target_include_directories(test_local_dc_unit_tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
add_test(NAME "test_local_dc" add_test(NAME "test_local_dc"
COMMAND /bin/bash ./test_local_dc.sh COMMAND /bin/bash ./test_local_dc.sh
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
add_test(NAME "test_local_dc_unit_tests"
COMMAND ./test_local_dc_unit_tests
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
install(TARGETS local_dc DESTINATION bin) install(TARGETS local_dc DESTINATION bin)
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include "args.h"
#include "../drv/crc.c" #include "../drv/crc.c"
#include "../include/daqmap.h" #include "../include/daqmap.h"
#include "../include/drv/fb.h" #include "../include/drv/fb.h"
...@@ -24,6 +25,7 @@ ...@@ -24,6 +25,7 @@
#include "../drv/gpstime/gpstime.h" #include "../drv/gpstime/gpstime.h"
#include <pthread.h> #include <pthread.h>
#include "modelrate.h" #include "modelrate.h"
#include "local_dc_utils.h"
#define MSG_BUF_SIZE 0x200000 #define MSG_BUF_SIZE 0x200000
...@@ -44,7 +46,6 @@ extern void* findSharedMemory( char* ); ...@@ -44,7 +46,6 @@ extern void* findSharedMemory( char* );
extern void* findSharedMemorySize( char*, int ); extern void* findSharedMemorySize( char*, int );
char modelnames[ DAQ_TRANSIT_MAX_DCU ][ 64 ]; char modelnames[ DAQ_TRANSIT_MAX_DCU ][ 64 ];
char* sysname;
int do_verbose = 0; int do_verbose = 0;
static volatile int keepRunning = 1; static volatile int keepRunning = 1;
char* ifo; char* ifo;
...@@ -56,33 +57,6 @@ char msg_buffer[ MSG_BUF_SIZE ]; ...@@ -56,33 +57,6 @@ char msg_buffer[ MSG_BUF_SIZE ];
int symmetricom_fd = -1; int symmetricom_fd = -1;
int daqStatBit[ 2 ]; int daqStatBit[ 2 ];
/*********************************************************************************/
/* U S A G E */
/* */
/*********************************************************************************/
void
Usage( )
{
fprintf( stderr, "Usage of local_dc:\n" );
fprintf( stderr, "local_dc -s <models> <OPTIONS>\n" );
fprintf( stderr,
" -b <buffer> : Name of the mbuf to concentrate the data to "
"locally (defaults to ifo)\n" );
fprintf( stderr, " -s <value> : Name of FE control models\n" );
fprintf( stderr,
" -m <value> : Local memory buffer size in megabytes\n" );
fprintf( stderr, " -l <filename> : log file name\n" );
fprintf( stderr, " -v 1 : Enable verbose output\n" );
fprintf( stderr,
" -d <directory> : Path to the gds tp dir used to lookup model "
"rates\n" );
fprintf( stderr,
" -w <value> : Number of ms to wait for models to finish\n");
fprintf( stderr, " -h : This helpscreen\n" );
fprintf( stderr, "\n" );
}
// ********************************************************************************************** // **********************************************************************************************
/// Get current GPS time from the symmetricom IRIG-B card /// Get current GPS time from the symmetricom IRIG-B card
unsigned long unsigned long
...@@ -406,8 +380,9 @@ int __CDECL ...@@ -406,8 +380,9 @@ int __CDECL
{ {
int counter = 0; int counter = 0;
int nsys = 1; int nsys = 1;
int dcuId[ 10 ];
int ii = 0; int ii = 0;
char* tmp = 0;
const char* gds_tp_dir_ = 0;
char* gds_tp_dir = 0; char* gds_tp_dir = 0;
int max_data_size_mb = 64; int max_data_size_mb = 64;
int max_data_size = 0; int max_data_size = 0;
...@@ -417,77 +392,126 @@ int __CDECL ...@@ -417,77 +392,126 @@ int __CDECL
int gps_stt = 0; int gps_stt = 0;
int gps_ok = 0; int gps_ok = 0;
unsigned long gps_time = 0; unsigned long gps_time = 0;
char* buffer_name = "local_dc"; char* buffer_name = NULL;
const char* buffer_name_ = NULL;
char* sysname;
int len; const char* sysname_;
int iter; char* sysname;
int do_wait = 1; const char* logfilename = NULL;
int do_bothways; int len;
extern char* optarg; int iter;
int do_wait = 1;
int do_bothways;
args_handle arg_parser = NULL;
sysname = NULL; sysname = NULL;
bzero( modelrates, sizeof( modelrates[ 0 ] ) * DAQ_TRANSIT_MAX_DCU );
bzero( dcuid, sizeof( dcuid[ 0 ] ) * DAQ_TRANSIT_MAX_DCU );
fprintf( fprintf(
stderr, "\n %s compiled %s : %s\n\n", argv[ 0 ], __DATE__, __TIME__ ); stderr, "\n %s compiled %s : %s\n\n", argv[ 0 ], __DATE__, __TIME__ );
ii = 0; ii = 0;
if ( argc < 3 ) arg_parser = args_create_parser(
"The local_dc process concentrates or combines the shared memory "
"buffers from LIGO FE models into one buffer formated for injestion "
"into the daqd or transmission over the network.\n"
"The local_dc needs to get some information from the model .par files. "
"For systems (such as the standalone edc) that do not have .par files "
"the dcuid & rate may be specified with the model rate (ex edc:52:16 "
"or edc:52, if not specified the rate defaults to 16Hz). Only do this "
"for special cases." );
if ( !arg_parser )
{ {
Usage( ); return -1;
return ( -1 ); }
args_add_string_ptr( arg_parser,
'b',
ARGS_NO_LONG,
"buffer",
"Name of the mbuf to write data to locally",
&buffer_name_,
"local_dc" );
args_add_int( arg_parser,
'm',
ARGS_NO_LONG,
"MB",
"Local memory buffer size",
&max_data_size_mb,
100 );
args_add_string_ptr( arg_parser,
's',
ARGS_NO_LONG,
"systems",
"Space seperated list of systems.",
&sysname_,
"" );
args_add_string_ptr( arg_parser,
'l',
ARGS_NO_LONG,
"file",
"Log file name",
&logfilename,
"-" );
args_add_int( arg_parser,
'v',
ARGS_NO_LONG,
"level",
"Enable verbose output",
&do_verbose,
0 );
args_add_string_ptr( arg_parser,
'd',
ARGS_NO_LONG,
"directory",
"Path to the gds tp dir used to lookup model rates",
&gds_tp_dir_,
NULL );
args_add_int( arg_parser,
'w',
ARGS_NO_LONG,
"ms",
"Number of ms to wait for models to finish",
&do_wait,
1 );
if ( args_parse( arg_parser, argc, argv ) < 0 )
{
exit( 1 );
} }
/* Get the parameters */ buffer_name = malloc( strlen( buffer_name_ ) + 1 );
while ( ( counter = getopt( argc, argv, "b:e:m:h:v:s:r:t:d:l:D:w:" ) ) != strncpy( buffer_name, buffer_name_, strlen( buffer_name_ ) + 1 );
EOF ) sysname = malloc( strlen( sysname_ ) + 1 );
switch ( counter ) strncpy( sysname, sysname_, strlen( sysname_ ) + 1 );
{ if ( gds_tp_dir_ )
case 'b': {
buffer_name = optarg; gds_tp_dir = malloc( strlen( gds_tp_dir_ ) + 1 );
break; strncpy( gds_tp_dir, gds_tp_dir_, strlen( gds_tp_dir_ ) + 1 );
}
case 'm': if ( max_data_size_mb < 20 )
max_data_size_mb = atoi( optarg ); {
if ( max_data_size_mb < 20 ) fprintf( stderr, "Min data block size is 20 MB\n" );
{ return -1;
fprintf( stderr, "Min data block size is 20 MB\n" ); }
return -1; if ( max_data_size_mb > 100 )
} {
if ( max_data_size_mb > 100 ) fprintf( stderr, "Max data block size is 100 MB\n" );
{ return -1;
fprintf( stderr, "Max data block size is 100 MB\n" ); }
return -1; fprintf( stderr, "sysnames = %s\n", sysname );
}
break; if ( strcmp( logfilename, "-" ) != 0 )
{
case 's': if ( 0 == freopen( logfilename, "w", stdout ) )
sysname = optarg; {
fprintf( stderr, "sysnames = %s\n", sysname ); perror( "freopen" );
continue; exit( 1 );
case 'l':
if ( 0 == freopen( optarg, "w", stdout ) )
{
perror( "freopen" );
exit( 1 );
}
setvbuf( stdout, NULL, _IOLBF, 0 );
stderr = stdout;
break;
case 'v':
do_verbose = atoi( optarg );
break;
case 'd':
gds_tp_dir = optarg;
break;
case 'w':
do_wait = atoi( optarg );
break;
case 'h':
Usage( );
return ( 0 );
} }
setvbuf( stdout, NULL, _IOLBF, 0 );
stderr = stdout;
}
max_data_size = max_data_size_mb * 1024 * 1024; max_data_size = max_data_size_mb * 1024 * 1024;
...@@ -506,16 +530,22 @@ int __CDECL ...@@ -506,16 +530,22 @@ int __CDECL
if ( !s ) if ( !s )
break; break;
sprintf( modelnames[ nsys ], "%s", s ); sprintf( modelnames[ nsys ], "%s", s );
dcuId[ nsys ] = 0;
nsys++; nsys++;
} }
} }
else else
{ {
Usage( ); args_fprint_usage( arg_parser, argv[ 0 ], stderr );
return ( 0 ); return ( 0 );
} }
for ( ii = 0; ii < nsys; ++ii )
{
extract_dcu_rate_from_name(
modelnames[ ii ], &dcuid[ ii ], &modelrates[ ii ] );
trim_dcuid_and_rate_from_name( modelnames[ ii ] );
}
// Open file descriptor for the gpstime driver // Open file descriptor for the gpstime driver
symmetricom_fd = open( "/dev/gpstime", O_RDWR | O_SYNC ); symmetricom_fd = open( "/dev/gpstime", O_RDWR | O_SYNC );
if ( symmetricom_fd < 0 ) if ( symmetricom_fd < 0 )
...@@ -560,20 +590,24 @@ int __CDECL ...@@ -560,20 +590,24 @@ int __CDECL
// Get model rates to get GDS TP data sizes. // Get model rates to get GDS TP data sizes.
for ( ii = 0; ii < nsys; ii++ ) for ( ii = 0; ii < nsys; ii++ )
{ {
status = get_model_rate_dcuid( if ( modelrates[ ii ] == 0 )
&modelrates[ ii ], &dcuid[ ii ], modelnames[ ii ], gds_tp_dir ); {
status = get_model_rate_dcuid(
&modelrates[ ii ], &dcuid[ ii ], modelnames[ ii ], gds_tp_dir );
if ( status != 0 || modelrates[ ii ] == 0 )
{
fprintf( stderr,
"Unable to determine the rate of %s\n",
modelnames[ ii ] );
exit( 1 );
}
}
fprintf( stderr, fprintf( stderr,
"Model %s rate = %d dcuid = %d\n", "Model %s rate = %d dcuid = %d\n",
modelnames[ ii ], modelnames[ ii ],
modelrates[ ii ], modelrates[ ii ],
dcuid[ ii ] ); dcuid[ ii ] );
if ( status != 0 || modelrates[ ii ] == 0 )
{
fprintf( stderr,
"Unable to determine the rate of %s\n",
modelnames[ ii ] );
exit( 1 );
}
} }
// Get pointers to local DAQ mbuf // Get pointers to local DAQ mbuf
...@@ -595,6 +629,9 @@ int __CDECL ...@@ -595,6 +629,9 @@ int __CDECL
error = send_to_local_memory( nsys, len, do_wait ); error = send_to_local_memory( nsys, len, do_wait );
} while ( error == 0 && keepRunning == 1 ); } while ( error == 0 && keepRunning == 1 );
free( (void*)gds_tp_dir_ );
free( (void*)sysname_ );
free( (void*)buffer_name );
// local_dc never returns unless there is a timeout - ie an error // local_dc never returns unless there is a timeout - ie an error
// or a signal (ctrl-c) has been sent, so it is killed // or a signal (ctrl-c) has been sent, so it is killed
// always return an error code. // always return an error code.
......
//
// Created by jonathan.hanks on 7/15/20.
//
#ifndef DAQD_TRUNK_LOCAL_DC_UTILS_H
#define DAQD_TRUNK_LOCAL_DC_UTILS_H
#include <string.h>
#include <stdlib.h>
/*!
* @brief given the tail of a system name + dcu + rate, extract the dcu + rate.
* @param input The text to parse must be either "model:dcuid:rate" or
* "model:dcuid"
* @param dcuIdDest Destination for the dcuid
* @param rateDest Destination for the rate
* @note this will always set *dcuIdDest & *rateDest if they are non-null
* If a dcuid is specified but a rate is not, the rate defaults to 16
* If a dcuid or rate is invalid it is set to 0
* If no dcuid (and thus also no rate) is specified then both are set to 0
*/
static void
extract_dcu_rate_from_name( const char* input, int* dcuIdDest, int* rateDest )
{
size_t size = 0;
char* buffer = 0;
char* sep = 0;
int dcuid = 0;
int rate = 0;
if ( dcuIdDest )
{
*dcuIdDest = 0;
}
if ( rateDest )
{
*rateDest = 0;
}
if ( !input )
{
return;
}
sep = strchr( input, ':' );
if ( sep == NULL )
{
return;
}
input = sep + 1;
size = strlen( input );
buffer = malloc( size + 1 );
strncpy( buffer, input, size + 1 );
sep = strchr( buffer, ':' );
if ( sep )
{
/* dcuid + rate */
*sep = '\0';
rate = (int)atoi( sep + 1 );
if ( *( sep + 1 ) == '\0' )
{
rate = 16;
}
}
else
{
/* dcuid only, default the rate */
rate = 16;
}
dcuid = (int)atoi( buffer );
free( buffer );
if ( dcuIdDest )
{
*dcuIdDest = dcuid;
}
if ( rateDest )
{
*rateDest = rate;
}
}
/*!
* @brief Trim off any :dcuid:rate or :dcuid portion from a model name
* @param name The name to trim
* @note safe to call with a NULL pointer. Modifies the string in place.
*/
void
trim_dcuid_and_rate_from_name( char* name )
{
char* sep = NULL;
if ( name )
{
sep = strchr( name, ':' );
if ( sep != NULL )
{
*sep = '\0';
}
}
}
#endif // DAQD_TRUNK_LOCAL_DC_UTILS_H
//
// Created by jonathan.hanks on 7/15/20.
//
#include <stdio.h>
#include "local_dc_utils.h"
int
test_extract_dcu_rate_from_name( const char* input,
int expected_dcu,
int expected_rate )
{
int dcu = 0;
int rate = 0;
extract_dcu_rate_from_name( input, &dcu, &rate );
if ( dcu != expected_dcu || rate != expected_rate )
{
fprintf( stderr,
"Given input '%s' expected %d %d, got %d %d\n",
input,
expected_dcu,
expected_rate,
dcu,
rate );
return 1;
}
return 0;
}
int
test_extract_dcu_rate_from_name_bad_params( )
{
int dcu = 52;
int rate = 256;
extract_dcu_rate_from_name( NULL, &dcu, &rate );
if ( dcu != 0 || rate != 0 )
{
fprintf( stderr, "dcu or rate was not cleared on bad input" );
return 1;
}
dcu = 52;
rate = 256;
extract_dcu_rate_from_name( "", &dcu, &rate );
if ( dcu != 0 || rate != 0 )
{
fprintf( stderr, "dcu or rate not cleared on short input" );
return 1;
}
dcu = 52;
rate = 256;
extract_dcu_rate_from_name( ":42:128", NULL, &rate );
if ( dcu != 52 || rate != 128 )
{
fprintf( stderr, "error when dcu dest was NULL" );
return 1;
}
dcu = 52;
rate = 256;
extract_dcu_rate_from_name( ":42:128", &dcu, NULL );
if ( dcu != 42 || rate != 256 )
{
fprintf( stderr, "error when rate dest was NULL" );
return 1;
}
dcu = 52;
rate = 256;
extract_dcu_rate_from_name( ":42:128", NULL, NULL );
if ( dcu != 52 || rate != 256 )
{
fprintf( stderr, "error when dcu and rate dest were NULL" );
return 1;
}
return 0;
}
void
do_extract_tests( )
{
if ( test_extract_dcu_rate_from_name( "model", 0, 0 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name( "model:52", 52, 16 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name( ":52", 52, 16 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name( ":52:100", 52, 100 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name( "model:52:100", 52, 100 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name( ":blah:100", 0, 100 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name( "model:blah:blah", 0, 0 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name( ":blah:blah", 0, 0 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name( ":42:blah", 42, 0 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name( ":42a:blah", 42, 0 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name( ":42a:128b", 42, 128 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name( ":", 0, 16 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name( "::", 0, 16 ) != 0 )
{
exit( 1 );
}
if ( test_extract_dcu_rate_from_name_bad_params( ) != 0 )
{
exit( 1 );
}
}
typedef struct Trim_tests
{
const char* input;
const char* output;
} Trim_tests;
void
do_trim_tests( )
{
#define TRIM_BUFFER_SIZE 100
int i = 0;
size_t input_len = 0;
char buffer[ TRIM_BUFFER_SIZE ];
Trim_tests tests[] = {
{ "model", "model" }, { "model:dcu:rate", "model" },
{ "model:dcu", "model" }, { "", "" },
{ NULL, NULL },
};
for ( i = 0; tests[ i ].input != NULL; ++i )
{
input_len = strlen( tests[ i ].input );
if ( input_len + 1 >= TRIM_BUFFER_SIZE )
{
fprintf( stderr,
"Invalid test, the destination buffer is too small to run "
"the test" );
exit( 1 );
}
strncpy( buffer, tests[ i ].input, TRIM_BUFFER_SIZE );
trim_dcuid_and_rate_from_name( buffer );
if ( strcmp( buffer, tests[ i ].output ) != 0 )
{
fprintf( stderr,
"Trim failure, input of '%s' with expected output of "
"'%s', got '%s' instead.\n",
tests[ i ].input,
tests[ i ].output,
buffer );
exit( 1 );
}
}
/* should be safe to call with a NULL pointer */
trim_dcuid_and_rate_from_name( NULL );
}
int
main( int argc, char* argv[] )
{
do_extract_tests( );
do_trim_tests( );
return 0;
}
\ 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