29#define ODB_UPDATE_TIME 1000
31#define DEFAULT_FE_TIMEOUT 10000
33#define MAX_N_THREADS 32
190 cm_msg(
MERROR,
"tr_stop",
"bm_flush_cache(BM_WAIT) error %d", err);
199 eq->stats.events_sent +=
eq->events_sent;
200 eq->stats.events_per_sec = 0;
201 eq->stats.kbytes_per_sec = 0;
280 path +=
"/Equipment/";
286 int size =
sizeof(
eq->info);
289 cm_msg(
MINFO,
"eq_common_watcher",
"db_get_record(%s) status %d", path.c_str(),
status);
329#pragma GCC diagnostic push
330#pragma GCC diagnostic ignored "-Wformat-nonliteral"
352#pragma GCC diagnostic pop
359 if (
namepos != std::string::npos) {
371 if (
name.length() >= 32) {
373 "Equipment name %s%s%s too long, trimming down to %d characters",
387 if (
eq_info->write_cache_size == 0)
391 printf(
"ERROR: Cannot create equipment record \"%s\", db_set_record() status %d\n",
str,
status);
397 cm_msg(
MINFO,
"register_equipment",
"Correcting \"%s\", db_check_record() status %d",
str,
status);
400 printf(
"ERROR: Cannot check equipment record \"%s\", db_check_record() status %d\n",
str,
status);
408 printf(
"ERROR: Cannot find \"%s\", db_find_key() status %d",
str,
status);
416 printf(
"ERROR: Cannot check record \"%s\", db_check_record() status %d",
str,
status);
437 printf(
"ERROR: Cannot set record \"%s\", db_set_record() status %d",
str,
status);
454 printf(
"ERROR: Cannot get record \"%s\", db_get_record() status %d",
str,
status);
464 printf(
"ERROR: Cannot hotlink \"%s\", db_watch() status %d",
str,
status);
490 cm_msg(
MERROR,
"register_equipment",
"Cannot update equipment Common, db_set_record() status %d",
status);
500 cm_msg(
MERROR,
"register_equipment",
"Equipment \"%s\" contains RO_STOPPED or RO_ALWAYS. This can lead to undesired side-effect and should be removed.",
equipment[
idx].
name);
513 for (; bank_list->
name[0]; bank_list++) {
524 printf(
"Cannot check/create record \"%s\", status = %d\n",
str,
550 printf(
"Cannot create/check statistics record \'%s\', error %d\n",
str,
status);
556 printf(
"Cannot find statistics record \'%s\', error %d\n",
str,
status);
571 "Cannot change access mode for record \'%s\', error %d",
str,
status);
573 cm_msg(
MINFO,
"register_equipment",
"Recovered access mode for record \'%s\'",
str);
578 "Cannot open statistics record \'%s\', error %d",
str,
status);
591 "Not enough memory to allocate buffer for fragmented events");
615 for (
j = 0;
j <
idx;
j++) {
653 "Interrupt readout cannot be combined with polled readout");
669 "Equipment %s disabled in frontend",
681 "Equipment \"%s\" cannot be of type EQ_INTERRUPT and EQ_POLLED at the same time",
685 "Equipment \"%s\" cannot be of type EQ_INTERRUPT and EQ_MULTITHREAD at the same time",
723 if (
count > 2147483647.0) {
724 count = 2147483647.0;
742 "Multi-threaded readout cannot be combined with polled readout for equipment \'%s\'",
equipment[
i].
name);
750 "Defined more than one equipment with multi-threaded readout for equipment \'%s\'",
equipment[
i].
name);
764 "Equipment %s disabled in frontend",
777 "Equipment %s disabled in frontend",
790 cm_msg(
MERROR,
"initialize_equipment",
"Found slow control equipment \"%s\" with no device driver list, aborting",
824 strcpy(
str,
"Hardware error");
826 strcpy(
str,
"ODB error");
828 strcpy(
str,
"Driver error");
830 strcpy(
str,
"Partially disabled");
832 strcpy(
str,
"Error");
877 cm_msg(
MINFO,
"initialize_equipment",
"Slow control equipment initialized");
952 "Event size %ld larger than maximum size %d for frag. ev.",
966 pd = (
unsigned char *) (pfragment + 1);
968 for (
i = 0;
i < 4;
i++) {
969 pd[
i] = (
unsigned char) (size & 0xFF);
975 pdata = (
char *) (pevent + 1);
977 for (
i = 0, sent = 0; sent < pevent->
data_size;
i++) {
1022 cm_msg(
MERROR,
"send_event",
"Event size %ld larger than maximum size %d",
1154 assert(
rbh[
i] == 0);
1223 *(
INT *) (pevent + 1) = source;
1238 "Event size %ld larger than maximum size %d",
1270 unsigned int serial =
eq->events_collected;
1292 "Event collector: waiting for event serial %d since %1.1lf seconds, received already serial %d",
1303 if (pevent->data_size) {
1304 if (
eq->buffer_handle) {
1311 if (pevent->serial_number == 0)
1326 if (
eq->info.num_subevents)
1327 eq->events_sent +=
eq->subevent_number;
1331 eq->events_collected++;
1338 return prb->data_size;
1376 msg =
strchr(msg,
']') + 2;
1397 strcpy(
str,
"<local>");
1401 "================================================================================");
1407 "================================================================================");
1409 "Equipment Status Events Events/sec Rate[B/s] ODB->FE FE->ODB");
1411 "--------------------------------------------------------------------------------");
1505 static char wheel_char[] = {
'-',
'\\',
'|',
'/'};
1531 strcpy(
str,
"MIDAS");
1596 *(
INT *) (pevent + 1) = source;
1598 if (
eq->info.num_subevents) {
1599 eq->subevent_number = 0;
1601 *(
INT *) ((
char *) (pevent + 1) + pevent->
data_size) = source;
1604 size =
eq->readout((
char *) (pevent + 1), pevent->
data_size);
1609 "Event size %ld larger than maximum size %d",
1614 eq->subevent_number++;
1615 eq->serial_number++;
1622 if (source ==
FALSE) {
1629 }
while (source ==
FALSE);
1631 }
while (
eq->subevent_number <
eq->info.num_subevents && source);
1634 pevent->
data_size =
eq->readout((
char *) (pevent + 1), -1);
1637 pevent->
data_size =
eq->readout((
char *) (pevent + 1), 0);
1643 "Event size %ld larger than maximum size %d for frag. ev.",
1651 "Event size %ld larger than maximum size %d",
1660 eq->serial_number++;
1676 pd = (
unsigned char *) (pfragment + 1);
1678 for (
i = 0;
i < 4;
i++) {
1679 pd[
i] = (
unsigned char) (size & 0xFF);
1685 pdata = (
char *) (pevent + 1);
1687 for (
i = 0, sent = 0; sent < pevent->
data_size;
i++) {
1741 if (
eq->info.num_subevents) {
1742 eq->events_sent +=
eq->subevent_number;
1743 events_sent +=
eq->subevent_number;
1759 if (
eq_info->event_limit > 0 &&
eq->stats.events_sent +
eq->events_sent >=
eq_info->event_limit)
1917 *(
INT *) (pevent + 1) = source;
1919 if (
eq->info.num_subevents) {
1920 eq->subevent_number = 0;
1922 *(
INT *) ((
char *) (pevent + 1) + pevent->
data_size) = source;
1925 size =
eq->readout((
char *) (pevent + 1), pevent->
data_size);
1930 "Event size %ld larger than maximum size %d",
1935 eq->subevent_number++;
1936 eq->serial_number++;
1943 if (source ==
FALSE) {
1950 }
while (source ==
FALSE);
1952 }
while (
eq->subevent_number <
eq->info.num_subevents && source);
1955 pevent->
data_size =
eq->readout((
char *) (pevent + 1), -1);
1958 pevent->
data_size =
eq->readout((
char *) (pevent + 1), 0);
1964 "Event size %ld larger than maximum size %d for frag. ev.",
1972 "Event size %ld larger than maximum size %d",
1981 eq->serial_number++;
1997 pd = (
unsigned char *) (pfragment + 1);
1999 for (
i = 0;
i < 4;
i++) {
2000 pd[
i] = (
unsigned char) (size & 0xFF);
2006 pdata = (
char *) (pevent + 1);
2008 for (
i = 0, sent = 0; sent < pevent->
data_size;
i++) {
2062 if (
eq->info.num_subevents)
2063 eq->events_sent +=
eq->subevent_number;
2086 if (
eq_info->event_limit > 0 &&
eq->stats.events_sent +
eq->events_sent >=
eq_info->event_limit)
2097 if ((
int) size == -1)
2107 if (
eq_info->event_limit > 0 &&
eq->stats.events_sent +
eq->events_sent >=
eq_info->event_limit)
2132 size =
sizeof(
flag);
2137 size =
sizeof(delay);
2202 eq->stats.events_sent +=
eq->events_sent;
2204 eq->events_sent = 0;
2213 eq->stats.events_per_sec = ((
int)(
e * 100 + 0.5)) / 100.0;
2216 eq->stats.kbytes_per_sec = ((
int)(
e * 1000 + 0.5)) / 1000.0;
2298 for (
j = 0;
j <
i;
j++)
2314 cm_msg(
MERROR,
"scheduler",
"bm_flush_cache(BM_NO_WAIT) returned status %d", err);
2329 size =
sizeof(
state);
2332 cm_msg(
MERROR,
"scheduler",
"cannot get Runinfo/State in database");
2343 cm_msg(
MERROR,
"main",
"aborting on attempt to use invalid run number %d",
2399#define MFE_ERROR_SIZE 10
2414 cm_msg(
MERROR,
"mfe_set_error",
"Cannot create mutex\n");
2503 else if (
argv[
i][0] ==
'-' &&
argv[
i][1] ==
'D')
2505 else if (
argv[
i][0] ==
'-' &&
argv[
i][1] ==
'O')
2507 else if (
argv[
i][1] ==
'v') {
2512 }
else if (
argv[
i][0] ==
'-') {
2515 if (
argv[
i][1] ==
'e')
2517 else if (
argv[
i][1] ==
'h')
2519 else if (
argv[
i][1] ==
'i')
2521 else if (
argv[
i][1] ==
'-') {
2523 printf(
"usage: frontend [-h Hostname] [-e Experiment] [-d] [-D] [-O] [-v <n>] [-i <n>]\n");
2524 printf(
" [-d] Used to debug the frontend\n");
2525 printf(
" [-D] Become a daemon\n");
2526 printf(
" [-O] Become a daemon but keep stdout\n");
2527 printf(
" [-v <n>] Set verbosity level\n");
2528 printf(
" [-i <n>] Set frontend index (used for event building)\n");
2548 cm_msg(
MERROR,
"mfe_main",
"event_buffer_size %d MB exceeds maximum allowed size of %d MB\n",
2559 cm_msg(
MERROR,
"mainFE",
"Not enough mem space for event size");
2567 if (
getenv(
"MIDAS_FRONTEND_INDEX"))
2584 printf(
"\nBecoming a daemon...\n");
2600 printf(
"Connect to experiment...\n");
2645 printf(
"Failed to start local RPC server");
2677 printf(
"Init hardware...\n");
2688 cm_msg(
MERROR,
"mfe_main",
"Error status %d received from initialize_equipment, aborting",
status);
2789int begin_of_run(
int runno,
char *errstr) {
return 0; };
2790int end_of_run(
int runno,
char *errstr) {
return 0; };
2791int pause_run(
int runno,
char *errstr) {
return 0; };
2792int resume_run(
int runno,
char *errstr) {
return 0; };
INT transition(INT run_number, char *error)
INT bm_open_buffer(const char *buffer_name, INT buffer_size, INT *buffer_handle)
INT bm_set_cache_size(INT buffer_handle, size_t read_size, size_t write_size)
INT bm_flush_cache(int buffer_handle, int timeout_msec)
INT cm_register_transition(INT transition, INT(*func)(INT, char *), INT sequence_number)
INT cm_shutdown(const char *name, BOOL bUnique)
INT cm_yield(INT millisec)
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
INT cm_start_watchdog_thread()
INT cm_set_client_run_state(INT state)
INT cm_transition(INT transition, INT run_number, char *errstr, INT errstr_size, INT async_flag, INT debug_flag)
INT cm_register_function(INT id, INT(*func)(INT, void **))
INT cm_connect_experiment1(const char *host_name, const char *default_exp_name, const char *client_name, void(*func)(char *), INT odb_size, DWORD watchdog_timeout)
INT cm_cleanup(const char *client_name, BOOL ignore_timeout)
INT cm_set_client_info(HNDLE hDB, HNDLE *hKeyClient, const char *host_name, char *client_name, INT hw_type, const char *password, DWORD watchdog_timeout)
INT cm_disconnect_experiment(void)
INT cm_synchronize(DWORD *seconds)
INT cm_get_environment(char *host_name, int host_name_size, char *exp_name, int exp_name_size)
INT cm_check_deferred_transition()
BOOL cm_is_ctrlc_pressed()
INT cm_set_watchdog_params(BOOL call_watchdog, DWORD timeout)
#define DB_STRUCT_MISMATCH
#define DB_NO_MORE_SUBKEYS
#define CMD_INTERRUPT_ATTACH
#define CMD_INTERRUPT_DISABLE
#define CMD_INTERRUPT_ENABLE
#define FE_PARTIALLY_DISABLED
#define CMD_INTERRUPT_DETACH
std::string ss_gethostname()
INT ss_mutex_release(MUTEX_T *mutex)
INT ss_getchar(BOOL reset)
INT ss_mutex_create(MUTEX_T **mutex, BOOL recursive)
midas_thread_t ss_thread_create(INT(*thread_func)(void *), void *param)
INT ss_daemon_init(BOOL keep_stdout)
INT ss_sleep(INT millisec)
void ss_printf(INT x, INT y, const char *format,...)
INT ss_mutex_wait_for(MUTEX_T *mutex, INT timeout)
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
INT cm_set_msg_print(INT system_mask, INT user_mask, int(*func)(const char *))
BOOL equal_ustring(const char *str1, const char *str2)
INT db_send_changed_records()
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
std::string strcomb1(const char **list)
INT db_get_record1(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align, const char *rec_str)
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
INT db_get_record(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align)
INT db_set_mode(HNDLE hDB, HNDLE hKey, WORD mode, BOOL recurse)
INT db_watch(HNDLE hDB, HNDLE hKey, void(*dispatcher)(INT, INT, INT, void *), void *info)
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
INT db_open_record1(HNDLE hDB, HNDLE hKey, void *ptr, INT rec_size, WORD access_mode, void(*dispatcher)(INT, INT, void *), void *info, const char *rec_str)
INT db_set_record(HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
int rb_get_rp(int handle, void **p, int millisec)
int rb_get_wp(int handle, void **p, int millisec)
int rb_increment_rp(int handle, int size)
int rb_increment_wp(int handle, int size)
int rb_create(int size, int max_event_size, int *handle)
INT rpc_call(DWORD routine_id,...)
INT rpc_send_event(INT buffer_handle, const EVENT_HEADER *pevent, int unused, INT async_flag, INT mode)
INT rpc_set_opt_tcp_size(INT tcp_size)
#define RPC_BM_FLUSH_CACHE
#define DEFAULT_FE_TIMEOUT
void set_rate_period(int ms)
static INT tr_resume(INT rn, char *error)
static int flush_user_events(void)
char exp_name[NAME_LENGTH]
std::atomic< bool > _stop_all_threads(false)
void readout_enable(bool flag)
static int rbh[MAX_N_THREADS]
static std::atomic< bool > _readout_enabled_flag(false)
static void eq_common_watcher(INT hDB, INT, INT, void *info)
static int message_print(const char *msg)
static void send_all_periodic_events(INT transition)
INT manual_trigger(INT, void *prpc_param[])
static int send_event(INT idx, BOOL manual_trig)
static INT initialize_equipment(void)
void signal_readout_thread_active(int index, int flag)
int create_event_rb(int i)
int is_readout_thread_active()
void(* mfe_error_dispatcher)(const char *)
EQUIPMENT * multithread_eq
void mfe_get_args(int *argc, char ***argv)
BOOL debug
debug printouts
static int receive_trigger_event(EQUIPMENT *eq)
static INT check_user_events(void)
INT manual_trigger_event_id
static INT tr_pause(INT rn, char *error)
static INT frontend_index
void mfe_error(const char *error)
char full_frontend_name[256]
static INT check_polled_events(void)
static INT tr_start(INT rn, char *error)
static int _readout_thread(void *param)
static volatile int readout_thread_active[MAX_N_THREADS]
void mfe_set_error(void(*dispatcher)(const char *))
static void update_odb(const EVENT_HEADER *pevent, HNDLE hKey, INT format)
char mfe_error_str[MFE_ERROR_SIZE][256]
void mfe_error_check(void)
BOOL lockout_readout_thread
static INT register_equipment(void)
static INT tr_stop(INT rn, char *error)
int set_equipment_status(const char *name, const char *equipment_status, const char *status_class)
bool readout_enabled(void)
bool is_readout_thread_enabled()
void stop_readout_threads()
static void interrupt_routine(void)
char host_name[HOST_NAME_LENGTH]
const char * frontend_file_name
The frontend file name, don't change it.
BOOL equipment_common_overwrite
INT frontend_init(void)
Frontend initialization.
const char * frontend_name
The frontend name (client name) as seen by other MIDAS clients.
INT begin_of_run(__attribute__((unused)) INT rn, __attribute__((unused)) char *error)
INT frontend_exit()
Frontend exit.
INT poll_event(__attribute__((unused)) INT source, __attribute__((unused)) INT count, __attribute__((unused)) BOOL test)
INT interrupt_configure(__attribute__((unused)) INT cmd, __attribute__((unused)) INT source, __attribute__((unused)) PTYPE adr)
INT end_of_run(__attribute__((unused)) INT rn, __attribute__((unused)) char *error)
INT frontend_loop()
Frontend loop.
int cm_write_event_to_odb(HNDLE hDB, HNDLE hKey, const EVENT_HEADER *pevent, INT format)
#define MIN_WRITE_CACHE_SIZE
#define EQUIPMENT_STATISTICS_STR
#define DEFAULT_BUFFER_SIZE
#define EQUIPMENT_COMMON_STR
#define TRANSITION_ERROR_STRING_LENGTH
#define driver(name, count)
#define equipment(name, id, type, source, readon, period, readout, cd, driver)
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
INT(* readout)(char *, INT)