mfe.c File Reference

Go to the source code of this file.

Defines

#define SERVER_CACHE_SIZE   100000
#define ODB_UPDATE_TIME   1000
#define DEFAULT_FE_TIMEOUT   60000
#define EQUIPMENT_COMMON_STR   "\Event ID = WORD : 0\n\Trigger mask = WORD : 0\n\Buffer = STRING : [32] SYSTEM\n\Type = INT : 0\n\Source = INT : 0\n\Format = STRING : [8] FIXED\n\Enabled = BOOL : 0\n\Read on = INT : 0\n\Period = INT : 0\n\Event limit = DOUBLE : 0\n\Num subevents = DWORD : 0\n\Log history = INT : 0\n\Frontend host = STRING : [32] \n\Frontend name = STRING : [32] \n\Frontend file name = STRING : [256] \n\Status = STRING : [256] \n\Status color = STRING : [32] \n\"
#define EQUIPMENT_STATISTICS_STR   "\Events sent = DOUBLE : 0\n\Events per sec. = DOUBLE : 0\n\kBytes per sec. = DOUBLE : 0\n\"
#define MFE_ERROR_SIZE   10

Functions

INT frontend_init (void)
INT frontend_exit (void)
INT frontend_loop (void)
INT begin_of_run (INT run_number, char *error)
INT end_of_run (INT run_number, char *error)
INT pause_run (INT run_number, char *error)
INT resume_run (INT run_number, char *error)
INT poll_event (INT source, INT count, BOOL test)
INT interrupt_configure (INT cmd, INT source, POINTER_T adr)
int readout_thread (void *param)
void mfe_error_check (void)
int send_event (INT idx, BOOL manual_trig)
int receive_trigger_event (EQUIPMENT *eq)
void send_all_periodic_events (INT transition)
void interrupt_routine (void)
void readout_enable (BOOL flag)
int readout_enabled (void)
void display (BOOL bInit)
void rotate_wheel (void)
BOOL logger_root ()
INT check_polled_events (void)
void set_rate_period (int ms)
int get_rate_period ()
INT tr_start (INT rn, char *error)
INT tr_stop (INT rn, char *error)
INT tr_pause (INT rn, char *error)
INT tr_resume (INT rn, char *error)
INT manual_trigger (INT idx, void *prpc_param[])
int sc_thread (void *info)
INT device_driver (DEVICE_DRIVER *device_drv, INT cmd,...)
INT register_equipment (void)
INT initialize_equipment (void)
int set_equipment_status (const char *name, const char *eqipment_status, const char *status_color)
void update_odb (EVENT_HEADER *pevent, HNDLE hKey, INT format)
int message_print (const char *msg)
INT scheduler (void)
INT get_frontend_index ()
void mfe_set_error (void(*dispatcher)(const char *))
void mfe_error (const char *error)
int main (int argc, char *argv[])

Variables

char * frontend_name
char * frontend_file_name
BOOL frontend_call_loop
INT max_event_size
INT max_event_size_frag
INT event_buffer_size
INT display_period
INT rpc_mode = 1
INT run_state
INT run_number
DWORD actual_time
DWORD actual_millitime
DWORD rate_period
char host_name [HOST_NAME_LENGTH]
char exp_name [NAME_LENGTH]
char full_frontend_name [256]
INT max_bytes_per_sec
INT optimize = 0
INT fe_stop = 0
BOOL debug
DWORD auto_restart = 0
INT manual_trigger_event_id = 0
INT frontend_index = -1
BOOL lockout_readout_thread = TRUE
HNDLE hDB
EQUIPMENT equipment []
EQUIPMENTinterrupt_eq = NULL
EQUIPMENTmultithread_eq = NULL
BOOL slowcont_eq = FALSE
void * event_buffer
void * frag_buffer = NULL
int * n_events
int rbh1 = 0
int rbh2 = 0
int rbh1_next = 0
int rbh2_next = 0
volatile int stop_all_threads = 0
volatile int readout_thread_active = 0
static int _readout_enabled_flag = 0
void(*) mfe_error_dispatcher (const char *) = NULL
char mfe_error_str [MFE_ERROR_SIZE][256]
int mfe_error_r
int mfe_error_w
MUTEX_T * mfe_mutex = NULL


Define Documentation

#define DEFAULT_FE_TIMEOUT   60000

Definition at line 50 of file mfe.c.

Referenced by main().

#define EQUIPMENT_COMMON_STR   "\Event ID = WORD : 0\n\Trigger mask = WORD : 0\n\Buffer = STRING : [32] SYSTEM\n\Type = INT : 0\n\Source = INT : 0\n\Format = STRING : [8] FIXED\n\Enabled = BOOL : 0\n\Read on = INT : 0\n\Period = INT : 0\n\Event limit = DOUBLE : 0\n\Num subevents = DWORD : 0\n\Log history = INT : 0\n\Frontend host = STRING : [32] \n\Frontend name = STRING : [32] \n\Frontend file name = STRING : [256] \n\Status = STRING : [256] \n\Status color = STRING : [32] \n\"

Definition at line 103 of file mfe.c.

Referenced by register_equipment().

#define EQUIPMENT_STATISTICS_STR   "\Events sent = DOUBLE : 0\n\Events per sec. = DOUBLE : 0\n\kBytes per sec. = DOUBLE : 0\n\"

Definition at line 123 of file mfe.c.

Referenced by register_equipment().

#define MFE_ERROR_SIZE   10

Definition at line 2414 of file mfe.c.

Referenced by mfe_error(), and mfe_error_check().

#define ODB_UPDATE_TIME   1000

Definition at line 48 of file mfe.c.

#define SERVER_CACHE_SIZE   100000

Definition at line 46 of file mfe.c.

Referenced by register_equipment().


Function Documentation

INT begin_of_run ( INT  run_number,
char *  error 
)

INT check_polled_events ( void   ) 

Definition at line 1605 of file mfe.c.

Referenced by tr_stop().

01606 {
01607    EQUIPMENT_INFO *eq_info;
01608    EQUIPMENT *eq;
01609    EVENT_HEADER *pevent, *pfragment;
01610    DWORD readout_start, sent, size;
01611    INT i, idx, source, events_sent, status;
01612    char *pdata;
01613    unsigned char *pd;
01614 
01615    events_sent = 0;
01616    actual_millitime = ss_millitime();
01617 
01618    /*---- loop over equipment table -------------------------------*/
01619    for (idx = 0;; idx++) {
01620       eq = &equipment[idx];
01621       eq_info = &eq->info;
01622 
01623       /* check if end of equipment list */
01624       if (!eq->name[0])
01625          break;
01626 
01627       if (!eq_info->enabled)
01628          continue;
01629 
01630       if (eq->status != FE_SUCCESS)
01631          continue;
01632 
01633       if ((eq_info->eq_type & EQ_POLLED) == 0)
01634          continue;
01635 
01636       /*---- check polled events ----*/
01637       readout_start = actual_millitime;
01638       pevent = NULL;
01639 
01640       while ((source = poll_event(eq_info->source, eq->poll_count, FALSE)) > 0) {
01641          
01642          if (eq_info->eq_type & EQ_FRAGMENTED)
01643             pevent = frag_buffer;
01644          else
01645             pevent = (EVENT_HEADER *)event_buffer;
01646 
01647          /* compose MIDAS event header */
01648          pevent->event_id = eq_info->event_id;
01649          pevent->trigger_mask = eq_info->trigger_mask;
01650          pevent->data_size = 0;
01651          pevent->time_stamp = actual_time;
01652          pevent->serial_number = eq->serial_number;
01653 
01654          /* put source at beginning of event, will be overwritten by 
01655             user readout code, just a special feature used by some 
01656             multi-source applications */
01657          *(INT *) (pevent + 1) = source;
01658 
01659          if (eq->info.num_subevents) {
01660             eq->subevent_number = 0;
01661             do {
01662                *(INT *) ((char *) (pevent + 1) + pevent->data_size) = source;
01663 
01664                /* call user readout routine for subevent indicating offset */
01665                size = eq->readout((char *) (pevent + 1), pevent->data_size);
01666                pevent->data_size += size;
01667                if (size > 0) {
01668                   if (pevent->data_size + sizeof(EVENT_HEADER) >
01669                       (DWORD) max_event_size) {
01670                      cm_msg(MERROR, "check_polled_events",
01671                             "Event size %ld larger than maximum size %d",
01672                             (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01673                             max_event_size);
01674                   }
01675 
01676                   eq->subevent_number++;
01677                   eq->serial_number++;
01678                }
01679 
01680                /* wait for next event */
01681                do {
01682                   source = poll_event(eq_info->source, eq->poll_count, FALSE);
01683 
01684                   if (source == FALSE) {
01685                      actual_millitime = ss_millitime();
01686 
01687                      /* repeat no more than period */
01688                      if (actual_millitime - readout_start > (DWORD) eq_info->period)
01689                         break;
01690                   }
01691                } while (source == FALSE);
01692 
01693             } while (eq->subevent_number < eq->info.num_subevents && source);
01694 
01695             /* notify readout routine about end of super-event */
01696             pevent->data_size = eq->readout((char *) (pevent + 1), -1);
01697          } else {
01698             /* call user readout routine indicating event source */
01699             pevent->data_size = eq->readout((char *) (pevent + 1), 0);
01700 
01701             /* check event size */
01702             if (eq_info->eq_type & EQ_FRAGMENTED) {
01703                if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size_frag) {
01704                   cm_msg(MERROR, "check_polled_events",
01705                         "Event size %ld larger than maximum size %d for frag. ev.",
01706                         (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01707                         max_event_size_frag);
01708                   assert(FALSE);
01709                }
01710             } else {
01711                if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size) {
01712                   cm_msg(MERROR, "check_polled_events",
01713                         "Event size %ld larger than maximum size %d",
01714                         (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01715                         max_event_size);
01716                   assert(FALSE);
01717                }
01718             }
01719 
01720             /* increment serial number if event read out sucessfully */
01721             if (pevent->data_size)
01722                eq->serial_number++;
01723          }
01724 
01725          /* send event */
01726          if (pevent->data_size) {
01727 
01728             /* check for fragmented event */
01729             if (eq_info->eq_type & EQ_FRAGMENTED) {
01730                /* compose fragments */
01731                pfragment = event_buffer;
01732 
01733                /* compose MIDAS event header */
01734                memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01735                pfragment->event_id |= EVENTID_FRAG1;
01736 
01737                /* store total event size */
01738                pd = (unsigned char *) (pfragment + 1);
01739                size = pevent->data_size;
01740                for (i = 0; i < 4; i++) {
01741                   pd[i] = (unsigned char) (size & 0xFF);      /* little endian, please! */
01742                   size >>= 8;
01743                }
01744 
01745                pfragment->data_size = sizeof(DWORD);
01746 
01747                pdata = (char *) (pevent + 1);
01748 
01749                for (i = 0, sent = 0; sent < pevent->data_size; i++) {
01750                   if (i > 0) {
01751                      pfragment = event_buffer;
01752 
01753                      /* compose MIDAS event header */
01754                      memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01755                      pfragment->event_id |= EVENTID_FRAG;
01756 
01757                      /* copy portion of event */
01758                      size = pevent->data_size - sent;
01759                      if (size > max_event_size - sizeof(EVENT_HEADER))
01760                         size = max_event_size - sizeof(EVENT_HEADER);
01761 
01762                      memcpy(pfragment + 1, pdata, size);
01763                      pfragment->data_size = size;
01764                      sent += size;
01765                      pdata += size;
01766                   }
01767 
01768                   /* send event to buffer */
01769                   if (equipment[idx].buffer_handle) {
01770                      status = rpc_send_event(equipment[idx].buffer_handle, pfragment,
01771                                              pfragment->data_size + sizeof(EVENT_HEADER), SYNC, rpc_mode);
01772                      if (status != RPC_SUCCESS) {
01773                         cm_msg(MERROR, "check_polled_events", "rpc_send_event(SYNC) error %d", status);
01774                         return status;
01775                      }
01776 
01777                      /* flush events from buffer */
01778                      rpc_flush_event();
01779                   }
01780                }
01781             
01782             } else { /*-------------------*/
01783 
01784                /* send unfragmented event */
01785 
01786                /* send first event to ODB if logger writes in root format */
01787                if (pevent->serial_number == 0)
01788                   if (logger_root())
01789                      update_odb(pevent, eq->hkey_variables, eq->format);
01790 
01791                status = rpc_send_event(eq->buffer_handle, pevent,
01792                                        pevent->data_size + sizeof(EVENT_HEADER),
01793                                        SYNC, rpc_mode);
01794 
01795                if (status != SUCCESS) {
01796                   cm_msg(MERROR, "check_polled_events", "rpc_send_event error %d", status);
01797                   break;
01798                }
01799             }
01800 
01801             eq->bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
01802 
01803             if (eq->info.num_subevents) {
01804                eq->events_sent += eq->subevent_number;
01805                events_sent += eq->subevent_number;
01806             } else {
01807                eq->events_sent++;
01808                events_sent++;
01809             }
01810 
01811             rotate_wheel();
01812          }
01813 
01814          actual_millitime = ss_millitime();
01815 
01816          /* repeat no more than period */
01817          if (actual_millitime - readout_start > (DWORD) eq_info->period)
01818             break;
01819 
01820          /* quit if event limit is reached */
01821          if (eq_info->event_limit > 0 &&
01822              eq->stats.events_sent + eq->events_sent >= eq_info->event_limit)
01823             break;
01824       }
01825    }
01826 
01827    return events_sent;
01828 }

void display ( BOOL  bInit  ) 

Definition at line 1489 of file mfe.c.

01490 {
01491    INT i, status;
01492    time_t full_time;
01493    char str[30];
01494 
01495    if (bInit) {
01496       ss_clear_screen();
01497 
01498       if (host_name[0])
01499          strcpy(str, host_name);
01500       else
01501          strcpy(str, "<local>");
01502 
01503       ss_printf(0, 0, "%s connected to %s. Press \"!\" to exit", full_frontend_name, str);
01504       ss_printf(0, 1,
01505                 "================================================================================");
01506       ss_printf(0, 2, "Run status:   %s",
01507                 run_state == STATE_STOPPED ? "Stopped" : run_state ==
01508                 STATE_RUNNING ? "Running" : "Paused");
01509       ss_printf(25, 2, "Run number %d   ", run_number);
01510       ss_printf(0, 3,
01511                 "================================================================================");
01512       ss_printf(0, 4,
01513                 "Equipment     Status     Events     Events/sec Rate[kB/s] ODB->FE    FE->ODB");
01514       ss_printf(0, 5,
01515                 "--------------------------------------------------------------------------------");
01516       for (i = 0; equipment[i].name[0]; i++)
01517          ss_printf(0, i + 6, "%s", equipment[i].name);
01518    }
01519 
01520    /* display time */
01521    time(&full_time);
01522    strcpy(str, ctime(&full_time) + 11);
01523    str[8] = 0;
01524    ss_printf(72, 0, "%s", str);
01525 
01526    for (i = 0; equipment[i].name[0]; i++) {
01527       status = equipment[i].status;
01528 
01529       if ((status == 0 || status == FE_SUCCESS) && equipment[i].info.enabled)
01530          ss_printf(14, i + 6, "OK       ");
01531       else if (!equipment[i].info.enabled)
01532          ss_printf(14, i + 6, "Disabled ");
01533       else if (status == FE_ERR_ODB)
01534          ss_printf(14, i + 6, "ODB Error");
01535       else if (status == FE_ERR_HW)
01536          ss_printf(14, i + 6, "HW Error ");
01537       else if (status == FE_ERR_DISABLED)
01538          ss_printf(14, i + 6, "Disabled ");
01539       else if (status == FE_ERR_DRIVER)
01540          ss_printf(14, i + 6, "Driver err");
01541       else
01542          ss_printf(14, i + 6, "Unknown  ");
01543 
01544       if (equipment[i].stats.events_sent > 1E9)
01545          ss_printf(25, i + 6, "%1.3lfG     ", equipment[i].stats.events_sent / 1E9);
01546       else if (equipment[i].stats.events_sent > 1E6)
01547          ss_printf(25, i + 6, "%1.3lfM     ", equipment[i].stats.events_sent / 1E6);
01548       else
01549          ss_printf(25, i + 6, "%1.0lf      ", equipment[i].stats.events_sent);
01550       ss_printf(36, i + 6, "%1.1lf      ", equipment[i].stats.events_per_sec);
01551       ss_printf(47, i + 6, "%1.1lf      ", equipment[i].stats.kbytes_per_sec);
01552       ss_printf(58, i + 6, "%ld       ", equipment[i].odb_in);
01553       ss_printf(69, i + 6, "%ld       ", equipment[i].odb_out);
01554    }
01555 
01556    /* go to next line */
01557    ss_printf(0, i + 6, "");
01558 }

INT end_of_run ( INT  run_number,
char *  error 
)

INT frontend_exit ( void   ) 

INT frontend_init ( void   ) 

INT frontend_loop ( void   ) 

INT get_frontend_index (  ) 

Definition at line 2405 of file mfe.c.

02406 {
02407    return frontend_index;
02408 }

int get_rate_period (  ) 

Definition at line 136 of file mfe.c.

00137 {
00138    return rate_period;
00139 }

INT initialize_equipment ( void   ) 

Definition at line 755 of file mfe.c.

Referenced by main().

00756 {
00757    INT idx, i, j, k, n, count;
00758    char str[256];
00759    DWORD start_time, delta_time;
00760    EQUIPMENT_INFO *eq_info;
00761    EQUIPMENT_STATS *eq_stats;
00762    BOOL manual_trig_flag = FALSE;
00763 
00764    /* scan EQUIPMENT table from FRONTEND.C */
00765    for (idx = 0; equipment[idx].name[0]; idx++) {
00766       eq_info = &equipment[idx].info;
00767       eq_stats = &equipment[idx].stats;
00768 
00769       /*---- initialize interrupt events -----------------------------*/
00770 
00771       if (eq_info->eq_type & EQ_INTERRUPT) {
00772          /* install interrupt for interrupt events */
00773 
00774          for (i = 0; equipment[i].name[0]; i++)
00775             if (equipment[i].info.eq_type & EQ_POLLED) {
00776                equipment[idx].status = FE_ERR_DISABLED;
00777                cm_msg(MINFO, "initialize_equipment",
00778                       "Interrupt readout cannot be combined with polled readout");
00779             }
00780 
00781          if (equipment[idx].status != FE_ERR_DISABLED) {
00782             if (eq_info->enabled) {
00783                if (interrupt_eq) {
00784                   equipment[idx].status = FE_ERR_DISABLED;
00785                   cm_msg(MINFO, "initialize_equipment",
00786                          "Defined more than one equipment with interrupt readout");
00787                } else {
00788                   interrupt_eq = &equipment[idx];
00789 
00790                   /* create ring buffer for inter-thread data transfer */
00791                   if (!rbh1) {
00792                      rb_create(event_buffer_size, max_event_size, &rbh1);
00793                      rbh2 = rbh1;
00794                   }
00795 
00796                   /* establish interrupt handler */
00797                   interrupt_configure(CMD_INTERRUPT_ATTACH, eq_info->source,
00798                                       (POINTER_T) interrupt_routine);
00799                }
00800             } else {
00801                equipment[idx].status = FE_ERR_DISABLED;
00802                cm_msg(MINFO, "initialize_equipment",
00803                       "Equipment %s disabled in file \"frontend.c\"",
00804                       equipment[idx].name);
00805             }
00806          }
00807       }
00808 
00809       /*---- evaluate polling count ----------------------------------*/
00810 
00811       if (eq_info->eq_type & (EQ_POLLED | EQ_MULTITHREAD)) {
00812          if (eq_info->eq_type & EQ_INTERRUPT) {
00813             if (eq_info->eq_type & EQ_POLLED)
00814                cm_msg(MERROR, "register_equipment",
00815                   "Equipment \"%s\" cannot be of type EQ_INTERRUPT and EQ_POLLED at the same time", 
00816                   equipment[idx].name);
00817             else
00818                cm_msg(MERROR, "register_equipment",
00819                   "Equipment \"%s\" cannot be of type EQ_INTERRUPT and EQ_MULTITHREAD at the same time", 
00820                   equipment[idx].name);
00821             return 0;
00822          }
00823 
00824          if (display_period)
00825             printf("\nCalibrating");
00826 
00827          count = 1;
00828          do {
00829             if (display_period)
00830                printf(".");
00831 
00832             start_time = ss_millitime();
00833 
00834             poll_event(equipment[idx].info.source, count, TRUE);
00835 
00836             delta_time = ss_millitime() - start_time;
00837 
00838             if (count == 1 && delta_time > eq_info->period * 1.2) {
00839                cm_msg(MERROR, "register_equipment", "Polling routine with count=1 takes %d ms", delta_time);
00840                ss_sleep(3000);
00841                break;
00842             }
00843 
00844             if (delta_time > 0)
00845                count = (INT) ((double) count * eq_info->period / delta_time);
00846             else
00847                count *= 100;
00848 
00849          } while (delta_time > eq_info->period * 1.2 || delta_time < eq_info->period * 0.8);
00850 
00851          equipment[idx].poll_count = count;
00852       }
00853 
00854       /*---- initialize multithread events -------------------------*/
00855 
00856       if (eq_info->eq_type & EQ_MULTITHREAD) {
00857          /* install interrupt for interrupt events */
00858 
00859          for (i = 0; equipment[i].name[0]; i++)
00860             if (equipment[i].info.eq_type & EQ_POLLED) {
00861                equipment[idx].status = FE_ERR_DISABLED;
00862                cm_msg(MINFO, "initialize_equipment",
00863                       "Multi-threaded readout cannot be combined with polled readout for equipment \'%s\'", equipment[i].name);
00864             }
00865 
00866          if (equipment[idx].status != FE_ERR_DISABLED) {
00867             if (eq_info->enabled) {
00868                if (multithread_eq) {
00869                   equipment[idx].status = FE_ERR_DISABLED;
00870                   cm_msg(MINFO, "initialize_equipment",
00871                          "Defined more than one equipment with multi-threaded readout for equipment \'%s\'", equipment[i].name);
00872                } else {
00873                   multithread_eq = &equipment[idx];
00874 
00875                   /* create ring buffer for inter-thread data transfer */
00876                   if (!rbh1) {
00877                      rb_create(event_buffer_size, max_event_size, &rbh1);
00878                      rbh2 = rbh1;
00879                   }
00880 
00881                   /* create hardware reading thread */
00882                   readout_enable(FALSE);
00883                   ss_thread_create(readout_thread, multithread_eq);
00884                }
00885             } else {
00886                equipment[idx].status = FE_ERR_DISABLED;
00887                cm_msg(MINFO, "initialize_equipment",
00888                       "Equipment %s disabled in file \"frontend.c\"",
00889                       equipment[idx].name);
00890             }
00891          }
00892       }
00893 
00894       /*---- initialize slow control equipment ---------------------*/
00895 
00896       if (eq_info->eq_type & EQ_SLOW) {
00897 
00898          set_equipment_status(equipment[idx].name, "Initializing...", "yellow");
00899 
00900          /* resolve duplicate device names */
00901          for (i = 0; equipment[idx].driver[i].name[0]; i++)
00902             for (j = i + 1; equipment[idx].driver[j].name[0]; j++)
00903                if (equal_ustring(equipment[idx].driver[i].name,
00904                                  equipment[idx].driver[j].name)) {
00905                   strcpy(str, equipment[idx].driver[i].name);
00906                   for (k = 0, n = 0; equipment[idx].driver[k].name[0]; k++)
00907                      if (equal_ustring(str, equipment[idx].driver[k].name))
00908                         sprintf(equipment[idx].driver[k].name, "%s_%d", str, n++);
00909 
00910                   break;
00911                }
00912 
00913          /* loop over equipment list and call class driver's init method */
00914          if (eq_info->enabled) {
00915             printf("%s:\n", equipment[idx].name);
00916             equipment[idx].status = equipment[idx].cd(CMD_INIT, &equipment[idx]);
00917 
00918             if (equipment[idx].status == FE_SUCCESS)
00919                set_equipment_status(equipment[idx].name, "Ok", "#00FF00");
00920             else if (equipment[idx].status == FE_ERR_HW)
00921                set_equipment_status(equipment[idx].name, "Hardware error", "#FF0000");
00922             else if (equipment[idx].status == FE_ERR_ODB)
00923                set_equipment_status(equipment[idx].name, "ODB error", "#FF0000");
00924             else if (equipment[idx].status == FE_ERR_DRIVER)
00925                set_equipment_status(equipment[idx].name, "Driver error", "#FF0000");
00926             else
00927                set_equipment_status(equipment[idx].name, "Error", "#FF0000");
00928 
00929          } else {
00930             equipment[idx].status = FE_ERR_DISABLED;
00931             set_equipment_status(equipment[idx].name, "Disbled", "yellow");
00932          }
00933 
00934          /* now start threads if requested */
00935          if (equipment[idx].status == FE_SUCCESS)
00936             equipment[idx].cd(CMD_START, &equipment[idx]);   /* start threads for this equipment */
00937 
00938          /* remember that we have slowcontrol equipment (needed later for scheduler) */
00939          slowcont_eq = TRUE;
00940 
00941          /* let user read error messages */
00942          if (equipment[idx].status != FE_SUCCESS && 
00943              equipment[idx].status != FE_ERR_DISABLED)
00944             ss_sleep(3000);
00945       }
00946 
00947       /*---- register callback for manual triggered events -----------*/
00948       if (eq_info->eq_type & EQ_MANUAL_TRIG) {
00949          if (!manual_trig_flag)
00950             cm_register_function(RPC_MANUAL_TRIG, manual_trigger);
00951 
00952          manual_trig_flag = TRUE;
00953       }
00954    }
00955 
00956    if (slowcont_eq)
00957       cm_msg(MINFO, "initialize_equipment", "Slow control equipment initialized");
00958 
00959    return SUCCESS;
00960 }

INT interrupt_configure ( INT  cmd,
INT  source,
POINTER_T  adr 
)

Definition at line 252 of file frontend.c.

00253 {
00254    switch (cmd) {
00255    case CMD_INTERRUPT_ENABLE:
00256       break;
00257    case CMD_INTERRUPT_DISABLE:
00258       break;
00259    case CMD_INTERRUPT_ATTACH:
00260       break;
00261    case CMD_INTERRUPT_DETACH:
00262       break;
00263    }
00264    return SUCCESS;
00265 }

void interrupt_routine ( void   ) 

Definition at line 1295 of file mfe.c.

Referenced by initialize_equipment().

01296 {
01297    int status;
01298    EVENT_HEADER *pevent;
01299    void *p;
01300 
01301    /* get pointer for upcoming event.
01302       This is a blocking call if no space available */
01303    status = rb_get_wp(rbh1, &p, 100000);
01304 
01305    if (status == DB_SUCCESS) {
01306       pevent = (EVENT_HEADER *)p;
01307 
01308       /* compose MIDAS event header */
01309       pevent->event_id = interrupt_eq->info.event_id;
01310       pevent->trigger_mask = interrupt_eq->info.trigger_mask;
01311       pevent->data_size = 0;
01312       pevent->time_stamp = actual_time;
01313       pevent->serial_number = interrupt_eq->serial_number++;
01314 
01315       /* call user readout routine */
01316       pevent->data_size = interrupt_eq->readout((char *) (pevent + 1), 0);
01317 
01318       /* send event */
01319       if (pevent->data_size) {
01320 
01321          /* put event into ring buffer */
01322          rb_increment_wp(rbh1, sizeof(EVENT_HEADER) + pevent->data_size);
01323 
01324       } else
01325          interrupt_eq->serial_number--;
01326    }
01327 }

BOOL logger_root (  ) 

Definition at line 1578 of file mfe.c.

Referenced by receive_trigger_event().

01580 {
01581    int size, i, status;
01582    char str[80];
01583    HNDLE hKeyRoot, hKey;
01584 
01585    if (db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot) == DB_SUCCESS) {
01586       for (i = 0;; i++) {
01587          status = db_enum_key(hDB, hKeyRoot, i, &hKey);
01588          if (status == DB_NO_MORE_SUBKEYS)
01589             break;
01590 
01591          strcpy(str, "MIDAS");
01592          size = sizeof(str);
01593          db_get_value(hDB, hKey, "Settings/Format", str, &size, TID_STRING, TRUE);
01594 
01595          if (equal_ustring(str, "ROOT"))
01596             return TRUE;
01597       }
01598    }
01599 
01600    return FALSE;
01601 }

int main ( int  argc,
char *  argv[] 
)

Definition at line 2464 of file mfe.c.

02466 {
02467    INT status, i, j, size;
02468    INT daemon_flag;
02469    int sys_max_event_size = MAX_EVENT_SIZE;
02470 
02471    host_name[0] = 0;
02472    exp_name[0] = 0;
02473    debug = FALSE;
02474    daemon_flag = 0;
02475 
02476    setbuf(stdout, 0);
02477    setbuf(stderr, 0);
02478 
02479 #ifdef SIGPIPE
02480    signal(SIGPIPE, SIG_IGN);
02481 #endif
02482 
02483 #ifdef OS_VXWORKS
02484    if (ahost_name)
02485       strcpy(host_name, ahost_name);
02486    if (aexp_name)
02487       strcpy(exp_name, aexp_name);
02488    debug = adebug;
02489 #else
02490 
02491    /* get default from environment */
02492    cm_get_environment(host_name, sizeof(host_name), exp_name, sizeof(exp_name));
02493 
02494    /* parse command line parameters */
02495    for (i = 1; i < argc; i++) {
02496       if (argv[i][0] == '-' && argv[i][1] == 'd')
02497          debug = TRUE;
02498       else if (argv[i][0] == '-' && argv[i][1] == 'D')
02499          daemon_flag = 1;
02500       else if (argv[i][0] == '-' && argv[i][1] == 'O')
02501          daemon_flag = 2;
02502       else if (argv[i][0] == '-') {
02503          if (i + 1 >= argc || argv[i + 1][0] == '-')
02504             goto usage;
02505          if (argv[i][1] == 'e')
02506             strcpy(exp_name, argv[++i]);
02507          else if (argv[i][1] == 'h')
02508             strcpy(host_name, argv[++i]);
02509          else if (argv[i][1] == 'i')
02510             frontend_index = atoi(argv[++i]);
02511          else {
02512           usage:
02513             printf
02514                 ("usage: frontend [-h Hostname] [-e Experiment] [-d] [-D] [-O] [-i n]\n");
02515             printf("         [-d]     Used to debug the frontend\n");
02516             printf("         [-D]     Become a daemon\n");
02517             printf("         [-O]     Become a daemon but keep stdout\n");
02518             printf("         [-i n]   Set frontend index (used for event building)\n");
02519             return 0;
02520          }
02521       }
02522    }
02523 #endif
02524 
02525    /* check event and buffer sizes */
02526    if (event_buffer_size < 2 * max_event_size) {
02527       cm_msg(MERROR, "mainFE", "event_buffer_size %d too small for max. event size %d\n", event_buffer_size, max_event_size);
02528       ss_sleep(5000);
02529       return 1;
02530    }
02531 
02532 #ifdef OS_VXWORKS
02533    /* override event_buffer_size in case of VxWorks
02534       take remaining free memory and use 20% of it for rb_ */
02535    event_buffer_size = 2 * 10 * (max_event_size + sizeof(EVENT_HEADER) + sizeof(INT));
02536    if (event_buffer_size > memFindMax()) {
02537       cm_msg(MERROR, "mainFE", "Not enough mem space for event size");
02538       return 0;
02539    }
02540    /* takes overall 20% of the available memory resource for rb_() */
02541    event_buffer_size = 0.2 * memFindMax();
02542 #endif
02543 
02544    /* retrieve frontend index from environment if defined */
02545    if (getenv("MIDAS_FRONTEND_INDEX"))
02546       frontend_index = atoi(getenv("MIDAS_FRONTEND_INDEX"));
02547 
02548    /* add frontend index to frontend name if present */
02549    strcpy(full_frontend_name, frontend_name);
02550    if (frontend_index >= 0)
02551       sprintf(full_frontend_name + strlen(full_frontend_name), "%02d", frontend_index);
02552 
02553    /* inform user of settings */
02554    printf("Frontend name          :     %s\n", full_frontend_name);
02555    printf("Event buffer size      :     %d\n", event_buffer_size);
02556    printf("User max event size    :     %d\n", max_event_size);
02557    if (max_event_size_frag > 0)
02558       printf("User max frag. size    :     %d\n", max_event_size_frag);
02559    printf("# of events per buffer :     %d\n\n", event_buffer_size / max_event_size);
02560 
02561    if (daemon_flag) {
02562       printf("\nBecoming a daemon...\n");
02563       ss_daemon_init(daemon_flag == 2);
02564    }
02565   
02566    /* set default rate period */
02567    set_rate_period(3000);
02568 
02569    /* now connect to server */
02570    if (display_period) {
02571       if (host_name[0]) {
02572          if (exp_name[0])
02573             printf("Connect to experiment %s on host %s...\n", exp_name, host_name);
02574          else
02575             printf("Connect to experiment on host %s...\n", host_name);
02576       } else if (exp_name[0])
02577          printf("Connect to experiment %s...\n", exp_name);
02578       else
02579          printf("Connect to experiment...\n");
02580    }
02581 
02582    status = cm_connect_experiment1(host_name, exp_name, full_frontend_name,
02583                                    NULL, DEFAULT_ODB_SIZE, DEFAULT_FE_TIMEOUT);
02584    if (status != CM_SUCCESS) {
02585       cm_msg(MERROR, "mainFE", "Cannot connect to experiment \'%s\' on host \'%s\', status %d", exp_name, host_name, status);
02586       /* let user read message before window might close */
02587       ss_sleep(5000);
02588       return 1;
02589    }
02590 
02591    if (display_period)
02592       printf("OK\n");
02593 
02594    /* allocate buffer space */
02595    event_buffer = malloc(max_event_size);
02596    if (event_buffer == NULL) {
02597       cm_msg(MERROR, "mainFE", "mfe: Cannot allocate event buffer of max_event_size %d\n", max_event_size);
02598       return 1;
02599    }
02600 
02601    /* remomve any dead frontend */
02602    cm_cleanup(full_frontend_name, FALSE);
02603 
02604    /* shutdown previous frontend */
02605    status = cm_shutdown(full_frontend_name, FALSE);
02606    if (status == CM_SUCCESS && display_period) {
02607       printf("Previous frontend stopped\n");
02608 
02609       /* let user read message */
02610       ss_sleep(3000);
02611    }
02612 
02613    /* register transition callbacks */
02614    if (cm_register_transition(TR_START, tr_start, 500) != CM_SUCCESS ||
02615        cm_register_transition(TR_STOP, tr_stop, 500) != CM_SUCCESS ||
02616        cm_register_transition(TR_PAUSE, tr_pause, 500) != CM_SUCCESS ||
02617        cm_register_transition(TR_RESUME, tr_resume, 500) != CM_SUCCESS) {
02618       printf("Failed to start local RPC server");
02619       cm_disconnect_experiment();
02620 
02621       /* let user read message before window might close */
02622       ss_sleep(5000);
02623       return 1;
02624    }
02625 
02626    cm_get_experiment_database(&hDB, &status);
02627    /* set time from server */
02628 #ifdef OS_VXWORKS
02629    cm_synchronize(NULL);
02630 #endif
02631 
02632    size = sizeof(sys_max_event_size);
02633    status = db_get_value(hDB, 0, "/Experiment/MAX_EVENT_SIZE", &sys_max_event_size, &size, TID_DWORD, TRUE);
02634 
02635    if (max_event_size > sys_max_event_size) {
02636       cm_msg(MERROR, "mainFE", "Requested max_event_size (%d) exceeds max. system event size (%d)",
02637              max_event_size, sys_max_event_size);
02638       return 1;
02639    }
02640 
02641    /* turn off watchdog if in debug mode */
02642    if (debug)
02643       cm_set_watchdog_params(FALSE, 0);
02644 
02645    /* increase RPC timeout to 2min for logger with exabyte or blocked disk */
02646    rpc_set_option(-1, RPC_OTIMEOUT, 120000);
02647 
02648    /* set own message print function */
02649    if (display_period)
02650       cm_set_msg_print(MT_ALL, MT_ALL, message_print);
02651 
02652    /* reqister equipment in ODB */
02653    if (register_equipment() != SUCCESS) {
02654       if (display_period)
02655          printf("\n");
02656       cm_disconnect_experiment();
02657 
02658       /* let user read message before window might close */
02659       ss_sleep(5000);
02660       return 1;
02661    }
02662 
02663    /* call user init function */
02664    if (display_period)
02665       printf("Init hardware...\n");
02666    if (frontend_init() != SUCCESS) {
02667       if (display_period)
02668          printf("\n");
02669       cm_disconnect_experiment();
02670 
02671       /* let user read message before window might close */
02672       ss_sleep(5000);
02673       return 1;
02674    }
02675 
02676    initialize_equipment();
02677 
02678    if (display_period)
02679       printf("OK\n");
02680 
02681    /* initialize screen display */
02682    if (display_period) {
02683       ss_sleep(300);
02684       display(TRUE);
02685    }
02686 
02687    /* switch on interrupts or readout thread if running */
02688    if (run_state == STATE_RUNNING)
02689       readout_enable(TRUE);
02690 
02691    /* initialize ss_getchar */
02692    ss_getchar(0);
02693 
02694    /* call main scheduler loop */
02695    status = scheduler();
02696 
02697    /* stop readout thread */
02698    stop_all_threads = 1;
02699    rb_set_nonblocking();
02700    while (readout_thread_active)
02701       ss_sleep(100);
02702 
02703    /* reset terminal */
02704    ss_getchar(TRUE);
02705 
02706    /* switch off interrupts */
02707    if (interrupt_eq) {
02708       interrupt_configure(CMD_INTERRUPT_DISABLE, 0, 0);
02709       interrupt_configure(CMD_INTERRUPT_DETACH, 0, 0);
02710    }
02711 
02712    /* detach interrupts */
02713    if (interrupt_eq != NULL)
02714       interrupt_configure(CMD_INTERRUPT_DETACH, interrupt_eq->info.source, 0);
02715 
02716    /* call user exit function */
02717    frontend_exit();
02718 
02719    /* close slow control drivers */
02720    for (i = 0; equipment[i].name[0]; i++)
02721       if ((equipment[i].info.eq_type & EQ_SLOW) && equipment[i].status == FE_SUCCESS) {
02722 
02723          for (j = 0; equipment[i].driver[j].name[0]; j++)
02724             if (equipment[i].driver[j].flags & DF_MULTITHREAD)
02725                break;
02726 
02727          /* stop all threads if multithreaded */
02728          if (equipment[i].driver[j].name[0] && equipment[i].status == FE_SUCCESS)
02729             equipment[i].cd(CMD_STOP, &equipment[i]);   /* stop all threads */
02730       }
02731    for (i = 0; equipment[i].name[0]; i++)
02732       if ((equipment[i].info.eq_type & EQ_SLOW) && equipment[i].status == FE_SUCCESS)
02733          equipment[i].cd(CMD_EXIT, &equipment[i]);      /* close physical connections */
02734 
02735    free(n_events);
02736 
02737    /* close network connection to server */
02738    cm_disconnect_experiment();
02739 
02740    if (display_period) {
02741       if (status == RPC_SHUTDOWN) {
02742          ss_clear_screen();
02743          ss_printf(0, 0, "Frontend shut down.");
02744          ss_printf(0, 1, "");
02745       }
02746    }
02747 
02748    if (status != RPC_SHUTDOWN)
02749       printf("Network connection aborted.\n");
02750 
02751    return 0;
02752 }

INT manual_trigger ( INT  idx,
void *  prpc_param[] 
)

Definition at line 296 of file mfe.c.

00297 {
00298    int i;
00299 
00300    i = idx; /* avoid compiler warning */
00301    manual_trigger_event_id = CWORD(0);
00302    return SUCCESS;
00303 }

int message_print ( const char *  msg  ) 

Definition at line 1471 of file mfe.c.

Referenced by main().

01472 {
01473    char str[160];
01474 
01475    memset(str, ' ', 159);
01476    str[159] = 0;
01477 
01478    if (msg[0] == '[')
01479       msg = strchr(msg, ']') + 2;
01480 
01481    memcpy(str, msg, strlen(msg));
01482    ss_printf(0, 20, str);
01483 
01484    return 0;
01485 }

void mfe_error ( const char *  error  ) 

Definition at line 2435 of file mfe.c.

02438 {
02439    /* put error into FIFO */
02440    ss_mutex_wait_for(mfe_mutex, 1000);
02441    strlcpy(mfe_error_str[mfe_error_w], error, 256);
02442    mfe_error_w = (mfe_error_w + 1) % MFE_ERROR_SIZE;
02443    ss_mutex_release(mfe_mutex);
02444 }

void mfe_error_check ( void   ) 

Definition at line 2446 of file mfe.c.

02447 {
02448    if (mfe_mutex != NULL) {
02449       ss_mutex_wait_for(mfe_mutex, 1000);
02450       if (mfe_error_w != mfe_error_r) {
02451          if (mfe_error_dispatcher != NULL)
02452             mfe_error_dispatcher(mfe_error_str[mfe_error_r]);
02453          mfe_error_r = (mfe_error_r + 1) % MFE_ERROR_SIZE;
02454       }
02455       ss_mutex_release(mfe_mutex);
02456    }
02457 }

void mfe_set_error ( void(*)(const char *)  dispatcher  ) 

Definition at line 2419 of file mfe.c.

02420 {
02421    int status;
02422 
02423    mfe_error_dispatcher = dispatcher;
02424    mfe_error_r = mfe_error_w = 0;
02425    memset(mfe_error_str, 0, sizeof(mfe_error_str));
02426 
02427    if (mfe_mutex == NULL) {
02428       status = ss_mutex_create(&mfe_mutex);
02429       if (status != SS_SUCCESS && status != SS_CREATED)
02430          cm_msg(MERROR, "mfe_set_error", "Cannot create mutex\n");
02431    }
02432 
02433 }

INT pause_run ( INT  run_number,
char *  error 
)

INT poll_event ( INT  source,
INT  count,
BOOL  test 
)

Definition at line 86 of file midas_macro.h.

00090 {
00091    INT i, lam;
00092 
00093    for (i = 0; i < count; i++) {
00094       cam_lam_read(source >> 24, &lam);
00095       if (lam)
00096          if (!test)
00097             return TRUE;
00098    }
00099 
00100    return FALSE;
00101 }

void readout_enable ( BOOL  flag  ) 

Definition at line 1274 of file mfe.c.

Referenced by main(), tr_pause(), tr_resume(), tr_start(), and tr_stop().

01275 {
01276    _readout_enabled_flag = flag;
01277 
01278    if (interrupt_eq) {
01279       if (flag)
01280          interrupt_configure(CMD_INTERRUPT_ENABLE, 0, 0);
01281       else
01282          interrupt_configure(CMD_INTERRUPT_DISABLE, 0, 0);
01283    }
01284 
01285    if (multithread_eq) {
01286       /* readout thread might still be in readout, so wait until finished */
01287       if (flag == 0)
01288          while (readout_thread_active)
01289             ss_sleep(10);
01290    }
01291 }

int readout_enabled ( void   ) 

Definition at line 1269 of file mfe.c.

Referenced by readout_thread().

01270 {
01271    return _readout_enabled_flag;
01272 }

int readout_thread ( void *  param  ) 

Definition at line 1331 of file mfe.c.

01332 {
01333    int status, source;
01334    EVENT_HEADER *pevent;
01335    void *p;
01336 
01337    p = param; /* avoid compiler warning */
01338    while (!stop_all_threads) {
01339       /* obtain buffer space */
01340       if (rbh1_next) // if set by user code, use it
01341          rbh1 = rbh1_next;
01342 
01343       status = rb_get_wp(rbh1, &p, 0);
01344       if (stop_all_threads)
01345          break;
01346       if (status == DB_TIMEOUT) {
01347          // printf("readout_thread: Ring buffer is full, waiting for space!\n");
01348          ss_sleep(10);
01349          continue;
01350       }
01351       if (status != DB_SUCCESS)
01352          break;
01353 
01354       if (readout_enabled()) {
01355         
01356          /* indicate activity for readout_enable() */
01357          readout_thread_active = 1;
01358 
01359          /* check for new event */
01360          source = poll_event(multithread_eq->info.source, multithread_eq->poll_count, FALSE);
01361 
01362          if (source > 0) {
01363 
01364             if (stop_all_threads)
01365                break;
01366 
01367             pevent = (EVENT_HEADER *)p;
01368             /* put source at beginning of event, will be overwritten by 
01369                user readout code, just a special feature used by some 
01370                multi-source applications */
01371             *(INT *) (pevent + 1) = source;
01372             
01373             /* compose MIDAS event header */
01374             pevent->event_id = multithread_eq->info.event_id;
01375             pevent->trigger_mask = multithread_eq->info.trigger_mask;
01376             pevent->data_size = 0;
01377             pevent->time_stamp = actual_time;
01378             pevent->serial_number = multithread_eq->serial_number++;
01379 
01380             /* call user readout routine */
01381             pevent->data_size = multithread_eq->readout((char *) (pevent + 1), 0);
01382 
01383             /* check event size */
01384             if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size) {
01385                cm_msg(MERROR, "readout_thread",
01386                         "Event size %ld larger than maximum size %d",
01387                         (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01388                         max_event_size);
01389                assert(FALSE);
01390             }
01391 
01392             if (pevent->data_size > 0) {
01393                /* put event into ring buffer */
01394                rb_increment_wp(rbh1, sizeof(EVENT_HEADER) + pevent->data_size);
01395             } else
01396                multithread_eq->serial_number--;
01397          }
01398 
01399          readout_thread_active = 0;
01400 
01401       } else // readout_enabled
01402         ss_sleep(10);
01403 
01404    }
01405 
01406    readout_thread_active = 0;
01407 
01408    return 0;
01409 }

int receive_trigger_event ( EQUIPMENT eq  ) 

Definition at line 1413 of file mfe.c.

Referenced by tr_stop().

01414 {
01415    int status;
01416    EVENT_HEADER *prb, *pevent;
01417    void *p;
01418    int nbytes;
01419 
01420    if (0) {
01421       static int count = 0;
01422       if (((count++) % 100) == 0) {
01423          rb_get_buffer_level(rbh2, &nbytes);
01424          if (nbytes != 0)
01425             printf("mfe: ring buffer contains %d bytes\n", nbytes);
01426       }
01427    }
01428 
01429    status = rb_get_rp(rbh2, &p, 10);
01430    prb = (EVENT_HEADER *)p;
01431    if (status == DB_TIMEOUT)
01432       return 0;
01433 
01434    pevent = prb;
01435 
01436    /* send event */
01437    if (pevent->data_size) {
01438       if (eq->buffer_handle) {
01439          /* send first event to ODB if logger writes in root format */
01440          if (pevent->serial_number == 0)
01441             if (logger_root())
01442                update_odb(pevent, eq->hkey_variables, eq->format);
01443 
01444          status = rpc_send_event(eq->buffer_handle, pevent,
01445                                  pevent->data_size + sizeof(EVENT_HEADER),
01446                                  SYNC, rpc_mode);
01447 
01448          if (status != SUCCESS) {
01449             cm_msg(MERROR, "receive_trigger_event", "rpc_send_event error %d", status);
01450             return -1;
01451          }
01452 
01453          eq->bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
01454 
01455          if (eq->info.num_subevents)
01456             eq->events_sent += eq->subevent_number;
01457          else
01458             eq->events_sent++;
01459 
01460          rotate_wheel();
01461       }
01462    }
01463 
01464    rb_increment_rp(rbh2, sizeof(EVENT_HEADER) + prb->data_size);
01465 
01466    return prb->data_size;
01467 }

INT register_equipment ( void   ) 

Definition at line 541 of file mfe.c.

Referenced by main().

00542 {
00543    INT idx, size, status;
00544    char str[256];
00545    EQUIPMENT_INFO *eq_info;
00546    EQUIPMENT_STATS *eq_stats;
00547    HNDLE hKey;
00548    BANK_LIST *bank_list;
00549    DWORD dummy;
00550 
00551    /* get current ODB run state */
00552    size = sizeof(run_state);
00553    run_state = STATE_STOPPED;
00554    db_get_value(hDB, 0, "/Runinfo/State", &run_state, &size, TID_INT, TRUE);
00555    size = sizeof(run_number);
00556    run_number = 1;
00557    status =
00558        db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
00559    assert(status == SUCCESS);
00560 
00561    /* scan EQUIPMENT table from FRONTEND.C */
00562    for (idx = 0; equipment[idx].name[0]; idx++) {
00563       eq_info = &equipment[idx].info;
00564       eq_stats = &equipment[idx].stats;
00565 
00566       if (eq_info->event_id == 0) {
00567          printf("\nEvent ID 0 for %s not allowed\n", equipment[idx].name);
00568          cm_disconnect_experiment();
00569          ss_sleep(5000);
00570          exit(0);
00571       }
00572 
00573       /* init status */
00574       equipment[idx].status = FE_SUCCESS;
00575 
00576       /* check for % in equipment (needed for event building) */
00577       if (frontend_index != -1) {
00578          /* modify equipment name to <name>xx where xx is the frontend index */
00579          if (strchr(equipment[idx].name, '%')) {
00580             strcpy(str, equipment[idx].name);
00581             sprintf(equipment[idx].name, str, frontend_index);
00582          }
00583 
00584          /* modify event buffer name to <name>xx where xx is the frontend index */
00585          if (strchr(eq_info->buffer, '%')) {
00586             strcpy(str, eq_info->buffer);
00587             sprintf(eq_info->buffer, str, frontend_index);
00588          }
00589       } else {
00590          /* stip %.. */
00591          if (strchr(equipment[idx].name, '%'))
00592             *strchr(equipment[idx].name, '%') = 0;
00593          if (strchr(eq_info->buffer, '%'))
00594             *strchr(eq_info->buffer, '%') = 0;
00595       }
00596 
00597       sprintf(str, "/Equipment/%s/Common", equipment[idx].name);
00598 
00599       /* get last event limit from ODB */
00600       if (eq_info->eq_type != EQ_SLOW) {
00601          db_find_key(hDB, 0, str, &hKey);
00602          size = sizeof(double);
00603          if (hKey)
00604             db_get_value(hDB, hKey, "Event limit", &eq_info->event_limit, &size,
00605                          TID_DOUBLE, TRUE);
00606       }
00607 
00608       /* Create common subtree */
00609       status = db_check_record(hDB, 0, str, EQUIPMENT_COMMON_STR, FALSE);
00610       if (status == DB_NO_KEY || status == DB_STRUCT_MISMATCH) {
00611          db_create_record(hDB, 0, str, EQUIPMENT_COMMON_STR);
00612          db_find_key(hDB, 0, str, &hKey);
00613          db_set_record(hDB, hKey, eq_info, sizeof(EQUIPMENT_INFO), 0);
00614       } else if (status != DB_SUCCESS) {
00615          printf("Cannot check equipment record, status = %d\n", status);
00616          ss_sleep(3000);
00617       }
00618       db_find_key(hDB, 0, str, &hKey);
00619       assert(hKey);
00620 
00621       /* set fixed parameters from user structure */
00622       db_set_value(hDB, hKey, "Event ID", &eq_info->event_id, sizeof(WORD), 1, TID_WORD);
00623       db_set_value(hDB, hKey, "Type", &eq_info->eq_type, sizeof(INT), 1, TID_INT);
00624       db_set_value(hDB, hKey, "Source", &eq_info->source, sizeof(INT), 1, TID_INT);
00625 
00626       /* open hot link to equipment info */
00627       db_open_record(hDB, hKey, eq_info, sizeof(EQUIPMENT_INFO), MODE_READ, NULL, NULL);
00628 
00629       if (equal_ustring(eq_info->format, "YBOS"))
00630         assert(!"YBOS not supported anymore");
00631       else if (equal_ustring(eq_info->format, "FIXED"))
00632          equipment[idx].format = FORMAT_FIXED;
00633       else                      /* default format is MIDAS */
00634          equipment[idx].format = FORMAT_MIDAS;
00635 
00636       gethostname(eq_info->frontend_host, sizeof(eq_info->frontend_host));
00637       strcpy(eq_info->frontend_name, full_frontend_name);
00638       strcpy(eq_info->frontend_file_name, frontend_file_name);
00639       sprintf(eq_info->status, "%s@%s", full_frontend_name, eq_info->frontend_host);
00640       strcpy(eq_info->status_color, "#00FF00");
00641 
00642       /* update variables in ODB */
00643       db_set_record(hDB, hKey, eq_info, sizeof(EQUIPMENT_INFO), 0);
00644 
00645       /*---- Create variables record ---------------------------------*/
00646 
00647       sprintf(str, "/Equipment/%s/Variables", equipment[idx].name);
00648       if (equipment[idx].event_descrip) {
00649          if (equipment[idx].format == FORMAT_FIXED)
00650             db_check_record(hDB, 0, str, (char *) equipment[idx].event_descrip, TRUE);
00651          else {
00652             /* create bank descriptions */
00653             bank_list = (BANK_LIST *) equipment[idx].event_descrip;
00654 
00655             for (; bank_list->name[0]; bank_list++) {
00656                /* mabye needed later...
00657                   if (bank_list->output_flag == 0)
00658                   continue;
00659                 */
00660 
00661                if (bank_list->type == TID_STRUCT) {
00662                   sprintf(str, "/Equipment/%s/Variables/%s", equipment[idx].name,
00663                           bank_list->name);
00664                   status =
00665                       db_check_record(hDB, 0, str, strcomb((const char**)bank_list->init_str), TRUE);
00666                   if (status != DB_SUCCESS) {
00667                      printf("Cannot check/create record \"%s\", status = %d\n", str,
00668                             status);
00669                      ss_sleep(3000);
00670                   }
00671                } else {
00672                   sprintf(str, "/Equipment/%s/Variables/%s", equipment[idx].name,
00673                           bank_list->name);
00674                   dummy = 0;
00675                   db_set_value(hDB, 0, str, &dummy, rpc_tid_size(bank_list->type), 1,
00676                                bank_list->type);
00677                }
00678             }
00679          }
00680       } else
00681          db_create_key(hDB, 0, str, TID_KEY);
00682 
00683       sprintf(str, "/Equipment/%s/Variables", equipment[idx].name);
00684       db_find_key(hDB, 0, str, &hKey);
00685       equipment[idx].hkey_variables = hKey;
00686 
00687       /*---- Create and initialize statistics tree -------------------*/
00688 
00689       sprintf(str, "/Equipment/%s/Statistics", equipment[idx].name);
00690 
00691       status = db_check_record(hDB, 0, str, EQUIPMENT_STATISTICS_STR, TRUE);
00692       if (status != DB_SUCCESS) {
00693          printf("Cannot create/check statistics record \'%s\', error %d\n", str, status);
00694          ss_sleep(3000);
00695       }
00696 
00697       status = db_find_key(hDB, 0, str, &hKey);
00698       if (status != DB_SUCCESS) {
00699          printf("Cannot find statistics record \'%s\', error %d\n", str, status);
00700          ss_sleep(3000);
00701       }
00702 
00703       eq_stats->events_sent = 0;
00704       eq_stats->events_per_sec = 0;
00705       eq_stats->kbytes_per_sec = 0;
00706 
00707       /* open hot link to statistics tree */
00708       status =
00709           db_open_record(hDB, hKey, eq_stats, sizeof(EQUIPMENT_STATS), MODE_WRITE, NULL,
00710                          NULL);
00711       if (status != DB_SUCCESS) {
00712          cm_msg(MERROR, "register_equipment",
00713                 "Cannot open statistics record \'%s\', error %d. Probably other FE is using it",
00714                 str, status);
00715          ss_sleep(3000);
00716       }
00717 
00718       /*---- open event buffer ---------------------------------------*/
00719 
00720       /* check for fragmented event */
00721       if (eq_info->eq_type & EQ_FRAGMENTED) {
00722          if (frag_buffer == NULL)
00723             frag_buffer = malloc(max_event_size_frag);
00724 
00725          if (frag_buffer == NULL) {
00726             cm_msg(MERROR, "register_equipment",
00727                   "Not enough memory to allocate buffer for fragmented events");
00728             return SS_NO_MEMORY;
00729          }
00730       }
00731 
00732       if (eq_info->buffer[0]) {
00733          status =
00734              bm_open_buffer(eq_info->buffer, 2*MAX_EVENT_SIZE,
00735                             &equipment[idx].buffer_handle);
00736          if (status != BM_SUCCESS && status != BM_CREATED) {
00737             cm_msg(MERROR, "register_equipment",
00738                    "Cannot open event buffer \"%s\" size %d, bm_open_buffer() status %d", eq_info->buffer, 2*MAX_EVENT_SIZE, status);
00739             return 0;
00740          }
00741 
00742          /* set the default buffer cache size */
00743          bm_set_cache_size(equipment[idx].buffer_handle, 0, SERVER_CACHE_SIZE);
00744       } else
00745          equipment[idx].buffer_handle = 0;
00746    }
00747 
00748    n_events = calloc(sizeof(int), idx);
00749 
00750    return SUCCESS;
00751 }

INT resume_run ( INT  run_number,
char *  error 
)

void rotate_wheel ( void   ) 

Definition at line 1562 of file mfe.c.

Referenced by receive_trigger_event().

01563 {
01564    static DWORD last_wheel = 0, wheel_index = 0;
01565    static char wheel_char[] = { '-', '\\', '|', '/' };
01566 
01567    if (display_period) {
01568       if (ss_millitime() - last_wheel > 300) {
01569          last_wheel = ss_millitime();
01570          ss_printf(79, 2, "%c", wheel_char[wheel_index]);
01571          wheel_index = (wheel_index + 1) % 4;
01572       }
01573    }
01574 }

int sc_thread ( void *  info  ) 

Definition at line 307 of file mfe.c.

Referenced by device_driver().

00308 {
00309    DEVICE_DRIVER *device_drv = info;
00310    int i, status, cmd;
00311    int current_channel = 0;
00312    int current_priority_channel = 0;
00313    float value;
00314    int *last_update;
00315    unsigned int current_time;
00316    DWORD last_time;
00317 
00318    last_update = calloc(device_drv->channels, sizeof(int));
00319    last_time = ss_millitime();
00320 
00321    do {
00322       /* read one channel from device */
00323       for (cmd = CMD_GET_FIRST; cmd <= CMD_GET_LAST; cmd++) {
00324          value = (float)ss_nan();
00325          status = device_drv->dd(cmd, device_drv->dd_info, current_channel, &value);
00326 
00327          ss_semaphore_wait_for(device_drv->semaphore, 1000);
00328          device_drv->mt_buffer->channel[current_channel].variable[cmd] = value;
00329          device_drv->mt_buffer->status = status;
00330          ss_semaphore_release(device_drv->semaphore);
00331 
00332          // printf("TID %d: channel %d, value %f\n", ss_gettid(), current_channel, value);
00333       }
00334 
00335       /* switch to next channel in next loop */
00336       current_channel = (current_channel + 1) % device_drv->channels;
00337 
00338       /* check for priority channel */
00339       current_time = ss_millitime();
00340       i = (current_priority_channel + 1) % device_drv->channels;
00341       while (!(current_time - last_update[i] < 10000)) {
00342          i = (i + 1) % device_drv->channels;
00343          if (i == current_priority_channel) {
00344             /* non found, so finish */
00345             break;
00346          }
00347       }
00348 
00349       /* updated channel found, so read it additionally */
00350       if (current_time - last_update[i] < 10000) {
00351          current_priority_channel = i;
00352 
00353          for (cmd = CMD_GET_FIRST; cmd <= CMD_GET_LAST; cmd++) {
00354             status = device_drv->dd(cmd, device_drv->dd_info, i, &value);
00355 
00356             ss_semaphore_wait_for(device_drv->semaphore, 1000);
00357             device_drv->mt_buffer->channel[i].variable[cmd] = value;
00358             device_drv->mt_buffer->status = status;
00359             ss_semaphore_release(device_drv->semaphore);
00360          }
00361       }
00362 
00363       /* check if anything to write to device */
00364       for (i = 0; i < device_drv->channels; i++) {
00365 
00366          for (cmd = CMD_SET_FIRST; cmd <= CMD_SET_LAST; cmd++) {
00367             if (!ss_isnan(device_drv->mt_buffer->channel[i].variable[cmd])) {
00368                ss_semaphore_wait_for(device_drv->semaphore, 1000);
00369                value = device_drv->mt_buffer->channel[i].variable[cmd];
00370                device_drv->mt_buffer->channel[i].variable[cmd] = (float) ss_nan();
00371                device_drv->mt_buffer->status = status;
00372                ss_semaphore_release(device_drv->semaphore);
00373 
00374                status = device_drv->dd(cmd, device_drv->dd_info, i, value);
00375                last_update[i] = ss_millitime();
00376             }
00377          }
00378       }
00379 
00380       /* limit data rate if defined in equipment list */
00381       if (current_channel == 0)
00382          if (device_drv->pequipment && device_drv->pequipment->event_limit) {
00383             while (ss_millitime() - last_time < (DWORD)device_drv->pequipment->event_limit &&
00384                    !device_drv->stop_thread)
00385                ss_sleep(10);
00386             last_time = ss_millitime();
00387          }
00388 
00389    } while (device_drv->stop_thread == 0);
00390 
00391    free(last_update);
00392 
00393    /* signal stopped thread */
00394    device_drv->stop_thread = 2;
00395 
00396    return SUCCESS;
00397 }

INT scheduler ( void   ) 

Definition at line 1832 of file mfe.c.

Referenced by main().

01833 {
01834    EQUIPMENT_INFO *eq_info;
01835    EQUIPMENT *eq;
01836    EVENT_HEADER *pevent, *pfragment;
01837    DWORD last_time_network = 0, last_time_display = 0, last_time_flush = 0, 
01838       readout_start, sent, size, last_time_rate = 0;
01839    INT i, j, idx, status = 0, ch, source, state, old_flag;
01840    char str[80], *pdata;
01841    unsigned char *pd;
01842    BOOL buffer_done, flag, force_update = FALSE;
01843 
01844    INT opt_max = 0, opt_index = 0, opt_tcp_size = 128, opt_cnt = 0;
01845    INT err;
01846 
01847 #ifdef OS_VXWORKS
01848    rpc_set_opt_tcp_size(1024);
01849 #ifdef PPCxxx
01850    rpc_set_opt_tcp_size(NET_TCP_SIZE);
01851 #endif
01852 #endif
01853 
01854    /*----------------- MAIN equipment loop ------------------------------*/
01855 
01856    last_time_rate = ss_millitime();
01857 
01858    do {
01859       actual_millitime = ss_millitime();
01860       actual_time = ss_time();
01861 
01862       /*---- loop over equipment table -------------------------------*/
01863       for (idx = 0;; idx++) {
01864          eq = &equipment[idx];
01865          eq_info = &eq->info;
01866 
01867          /* check if end of equipment list */
01868          if (!eq->name[0])
01869             break;
01870 
01871          if (!eq_info->enabled)
01872             continue;
01873 
01874          if (eq->status != FE_SUCCESS)
01875             continue;
01876 
01877          /*---- call idle routine for slow control equipment ----*/
01878          if ((eq_info->eq_type & EQ_SLOW) && eq->status == FE_SUCCESS) {
01879             /* if equipment is multi-threaded, read all channel in one loop */
01880              
01881             if (eq_info->event_limit > 0) {
01882                if (actual_millitime - eq->last_idle >= (DWORD) eq_info->event_limit) {
01883                   eq->cd(CMD_IDLE, eq);
01884                   eq->last_idle = actual_millitime;
01885                }
01886             } else
01887                eq->cd(CMD_IDLE, eq);
01888          }
01889 
01890          if (run_state == STATE_STOPPED && (eq_info->read_on & RO_STOPPED) == 0)
01891             continue;
01892          if (run_state == STATE_PAUSED && (eq_info->read_on & RO_PAUSED) == 0)
01893             continue;
01894          if (run_state == STATE_RUNNING && (eq_info->read_on & RO_RUNNING) == 0)
01895             continue;
01896 
01897          /*---- check periodic events ----*/
01898          if ((eq_info->eq_type & EQ_PERIODIC) || (eq_info->eq_type & EQ_SLOW)) {
01899             if (eq_info->period == 0)
01900                continue;
01901 
01902             /* check if period over */
01903             if (actual_millitime - eq->last_called >= (DWORD) eq_info->period) {
01904                /* disable interrupts or readout thread during this event */
01905                old_flag = readout_enabled();
01906                if (old_flag && lockout_readout_thread)
01907                   readout_enable(FALSE);
01908 
01909                /* readout and send event */
01910                status = send_event(idx, FALSE);
01911 
01912                if (status != CM_SUCCESS) {
01913                   cm_msg(MERROR, "scheduler", "send_event error %d", status);
01914                   goto net_error;
01915                }
01916 
01917                /* re-enable the interrupt or readout thread after periodic */
01918                if (old_flag)
01919                   readout_enable(TRUE);
01920             }
01921          }
01922 
01923          /*---- check polled events ----*/
01924          if (eq_info->eq_type & EQ_POLLED) {
01925             readout_start = actual_millitime;
01926             pevent = NULL;
01927 
01928             while ((source = poll_event(eq_info->source, eq->poll_count, FALSE)) > 0) {
01929                
01930                if (eq_info->eq_type & EQ_FRAGMENTED)
01931                   pevent = frag_buffer;
01932                else
01933                   pevent = (EVENT_HEADER *)event_buffer;
01934 
01935                /* compose MIDAS event header */
01936                pevent->event_id = eq_info->event_id;
01937                pevent->trigger_mask = eq_info->trigger_mask;
01938                pevent->data_size = 0;
01939                pevent->time_stamp = actual_time;
01940                pevent->serial_number = eq->serial_number;
01941 
01942                /* put source at beginning of event, will be overwritten by 
01943                   user readout code, just a special feature used by some 
01944                   multi-source applications */
01945                *(INT *) (pevent + 1) = source;
01946 
01947                if (eq->info.num_subevents) {
01948                   eq->subevent_number = 0;
01949                   do {
01950                      *(INT *) ((char *) (pevent + 1) + pevent->data_size) = source;
01951 
01952                      /* call user readout routine for subevent indicating offset */
01953                      size = eq->readout((char *) (pevent + 1), pevent->data_size);
01954                      pevent->data_size += size;
01955                      if (size > 0) {
01956                         if (pevent->data_size + sizeof(EVENT_HEADER) >
01957                             (DWORD) max_event_size) {
01958                            cm_msg(MERROR, "scheduler",
01959                                   "Event size %ld larger than maximum size %d",
01960                                   (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01961                                   max_event_size);
01962                         }
01963 
01964                         eq->subevent_number++;
01965                         eq->serial_number++;
01966                      }
01967 
01968                      /* wait for next event */
01969                      do {
01970                         source = poll_event(eq_info->source, eq->poll_count, FALSE);
01971 
01972                         if (source == FALSE) {
01973                            actual_millitime = ss_millitime();
01974 
01975                            /* repeat no more than period */
01976                            if (actual_millitime - readout_start > (DWORD) eq_info->period)
01977                               break;
01978                         }
01979                      } while (source == FALSE);
01980 
01981                   } while (eq->subevent_number < eq->info.num_subevents && source);
01982 
01983                   /* notify readout routine about end of super-event */
01984                   pevent->data_size = eq->readout((char *) (pevent + 1), -1);
01985                } else {
01986                   /* call user readout routine indicating event source */
01987                   pevent->data_size = eq->readout((char *) (pevent + 1), 0);
01988 
01989                   /* check event size */
01990                   if (eq_info->eq_type & EQ_FRAGMENTED) {
01991                      if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size_frag) {
01992                         cm_msg(MERROR, "send_event",
01993                               "Event size %ld larger than maximum size %d for frag. ev.",
01994                               (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01995                               max_event_size_frag);
01996                         assert(FALSE);
01997                      }
01998                   } else {
01999                      if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size) {
02000                         cm_msg(MERROR, "scheduler",
02001                               "Event size %ld larger than maximum size %d",
02002                               (long) (pevent->data_size + sizeof(EVENT_HEADER)),
02003                               max_event_size);
02004                         assert(FALSE);
02005                      }
02006                   }
02007 
02008                   /* increment serial number if event read out sucessfully */
02009                   if (pevent->data_size)
02010                      eq->serial_number++;
02011                }
02012 
02013                /* send event */
02014                if (pevent->data_size) {
02015 
02016                   /* check for fragmented event */
02017                   if (eq_info->eq_type & EQ_FRAGMENTED) {
02018                      /* compose fragments */
02019                      pfragment = event_buffer;
02020 
02021                      /* compose MIDAS event header */
02022                      memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
02023                      pfragment->event_id |= EVENTID_FRAG1;
02024 
02025                      /* store total event size */
02026                      pd = (unsigned char *) (pfragment + 1);
02027                      size = pevent->data_size;
02028                      for (i = 0; i < 4; i++) {
02029                         pd[i] = (unsigned char) (size & 0xFF);      /* little endian, please! */
02030                         size >>= 8;
02031                      }
02032 
02033                      pfragment->data_size = sizeof(DWORD);
02034 
02035                      pdata = (char *) (pevent + 1);
02036 
02037                      for (i = 0, sent = 0; sent < pevent->data_size; i++) {
02038                         if (i > 0) {
02039                            pfragment = event_buffer;
02040 
02041                            /* compose MIDAS event header */
02042                            memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
02043                            pfragment->event_id |= EVENTID_FRAG;
02044 
02045                            /* copy portion of event */
02046                            size = pevent->data_size - sent;
02047                            if (size > max_event_size - sizeof(EVENT_HEADER))
02048                               size = max_event_size - sizeof(EVENT_HEADER);
02049 
02050                            memcpy(pfragment + 1, pdata, size);
02051                            pfragment->data_size = size;
02052                            sent += size;
02053                            pdata += size;
02054                         }
02055 
02056                         /* send event to buffer */
02057                         if (equipment[idx].buffer_handle) {
02058                            status = rpc_send_event(equipment[idx].buffer_handle, pfragment,
02059                                                    pfragment->data_size + sizeof(EVENT_HEADER), SYNC, rpc_mode);
02060                            if (status != RPC_SUCCESS) {
02061                               cm_msg(MERROR, "scheduler", "rpc_send_event(SYNC) error %d", status);
02062                               return status;
02063                            }
02064 
02065                            /* flush events from buffer */
02066                            rpc_flush_event();
02067                         }
02068                      }
02069                   
02070                   } else { /*-------------------*/
02071 
02072                      /* send unfragmented event */
02073 
02074                      /* send first event to ODB if logger writes in root format */
02075                      if (pevent->serial_number == 0)
02076                         if (logger_root())
02077                            update_odb(pevent, eq->hkey_variables, eq->format);
02078 
02079                      status = rpc_send_event(eq->buffer_handle, pevent,
02080                                              pevent->data_size + sizeof(EVENT_HEADER),
02081                                              SYNC, rpc_mode);
02082 
02083                      if (status != SUCCESS) {
02084                         cm_msg(MERROR, "scheduler", "rpc_send_event error %d", status);
02085                         goto net_error;
02086                      }
02087                   }
02088 
02089                   eq->bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
02090 
02091                   if (eq->info.num_subevents)
02092                      eq->events_sent += eq->subevent_number;
02093                   else
02094                      eq->events_sent++;
02095 
02096                   rotate_wheel();
02097                }
02098 
02099                actual_millitime = ss_millitime();
02100 
02101                /* send event to ODB */
02102                if (pevent->data_size && (eq_info->read_on & RO_ODB)) {
02103                   if (actual_millitime - eq->last_called > ODB_UPDATE_TIME) {
02104                      eq->last_called = actual_millitime;
02105                      update_odb(pevent, eq->hkey_variables, eq->format);
02106                      eq->odb_out++;
02107                   }
02108                }
02109 
02110                /* repeat no more than period */
02111                if (actual_millitime - readout_start > (DWORD) eq_info->period)
02112                   break;
02113 
02114                /* quit if event limit is reached */
02115                if (eq_info->event_limit > 0 &&
02116                    eq->stats.events_sent + eq->events_sent >= eq_info->event_limit)
02117                   break;
02118             }
02119 
02120          }
02121 
02122          /*---- send interrupt events ----*/
02123          if (eq_info->eq_type & (EQ_INTERRUPT | EQ_MULTITHREAD)) {
02124             readout_start = actual_millitime;
02125 
02126             do {
02127                size = receive_trigger_event(eq);
02128                if ((int)size == -1)
02129                   goto net_error;
02130 
02131                actual_millitime = ss_millitime();
02132 
02133                /* repeat no more than period */
02134                if (actual_millitime - readout_start > (DWORD) eq_info->period)
02135                   break;
02136 
02137                /* quit if event limit is reached */
02138                if (eq_info->event_limit > 0 &&
02139                    eq->stats.events_sent + eq->events_sent >= eq_info->event_limit)
02140                   break;
02141 
02142             } while (size > 0);
02143 
02144             /* send event to ODB */
02145             pevent = (EVENT_HEADER *)event_buffer;
02146             if (size > 0 && pevent->data_size && (eq_info->read_on & RO_ODB || eq_info->history)) {
02147                if (actual_millitime - eq->last_called > ODB_UPDATE_TIME && pevent != NULL) {
02148                   eq->last_called = actual_millitime;
02149                   update_odb(pevent, eq->hkey_variables, eq->format);
02150                   eq->odb_out++;
02151                }
02152             }
02153          }
02154 
02155          /*---- check if event limit is reached ----*/
02156          if (eq_info->eq_type != EQ_SLOW &&
02157              eq_info->event_limit > 0 &&
02158              eq->stats.events_sent + eq->events_sent >= eq_info->event_limit &&
02159              run_state == STATE_RUNNING) {
02160             /* stop run */
02161             if (cm_transition(TR_STOP, 0, str, sizeof(str), SYNC, FALSE) != CM_SUCCESS)
02162                cm_msg(MERROR, "scheduler", "cannot stop run: %s", str);
02163 
02164             /* check if autorestart, main loop will take care of it */
02165             size = sizeof(BOOL);
02166             flag = FALSE;
02167             db_get_value(hDB, 0, "/Logger/Auto restart", &flag, (INT *)&size, TID_BOOL, TRUE);
02168 
02169             if (flag)
02170                auto_restart = ss_time() + 20;   /* restart in 20 sec. */
02171 
02172             /* update event display correctly */
02173             force_update = TRUE;
02174          }
02175       }
02176 
02177       /*---- check for error messages periodically -------------------*/
02178       mfe_error_check();
02179 
02180       /*---- call frontend_loop periodically -------------------------*/
02181       if (frontend_call_loop) {
02182          status = frontend_loop();
02183          if (status == RPC_SHUTDOWN || status == SS_ABORT) {
02184             status = RPC_SHUTDOWN;
02185             break;
02186          }
02187       }
02188 
02189       /*---- check for deferred transitions --------------------------*/
02190       cm_check_deferred_transition();
02191 
02192       /*---- check for manual triggered events -----------------------*/
02193       if (manual_trigger_event_id) {
02194          old_flag = readout_enabled();
02195          if (old_flag && lockout_readout_thread)
02196             readout_enable(FALSE);
02197 
02198          /* readout and send event */
02199          status = BM_INVALID_PARAM;
02200          for (i = 0; equipment[i].name[0]; i++)
02201             if (equipment[i].info.event_id == manual_trigger_event_id) {
02202                status = send_event(i, TRUE);
02203                break;
02204             }
02205 
02206          manual_trigger_event_id = 0;
02207 
02208          if (status != CM_SUCCESS) {
02209             cm_msg(MERROR, "scheduler", "send_event error %d", status);
02210             goto net_error;
02211          }
02212 
02213          /* re-enable the interrupt after periodic */
02214          if (old_flag)
02215             readout_enable(TRUE);
02216       }
02217 
02218       /*---- calculate rates and update status page periodically -----*/
02219       if (force_update ||
02220           (display_period
02221            && actual_millitime - last_time_display > (DWORD) display_period)
02222           || (!display_period && actual_millitime - last_time_display > 3000)) {
02223          force_update = FALSE;
02224 
02225          for (i = 0; equipment[i].name[0]; i++) {
02226             eq = &equipment[i];
02227             eq->stats.events_sent += eq->events_sent;
02228             n_events[i] += eq->events_sent;
02229             eq->events_sent = 0;
02230          }
02231 
02232          /* calculate rates after requested period */
02233          if (actual_millitime - last_time_rate > (DWORD)get_rate_period()) {
02234             max_bytes_per_sec = 0;
02235             for (i = 0; equipment[i].name[0]; i++) {
02236                eq = &equipment[i];
02237                eq->stats.events_per_sec =
02238                    n_events[i] / ((actual_millitime - last_time_rate) / 1000.0);
02239                eq->stats.kbytes_per_sec =
02240                    eq->bytes_sent / 1024.0 / ((actual_millitime - last_time_rate) /
02241                                               1000.0);
02242 
02243                if ((INT) eq->bytes_sent > max_bytes_per_sec)
02244                   max_bytes_per_sec = eq->bytes_sent;
02245 
02246                eq->bytes_sent = 0;
02247                n_events[i] = 0;
02248             }
02249 
02250             max_bytes_per_sec = (DWORD)
02251                 ((double) max_bytes_per_sec /
02252                  ((actual_millitime - last_time_rate) / 1000.0));
02253 
02254             last_time_rate = actual_millitime;
02255          }
02256 
02257          /* tcp buffer size evaluation */
02258          if (optimize) {
02259             opt_max = MAX(opt_max, (INT) max_bytes_per_sec);
02260             ss_printf(0, opt_index, "%6d : %5.1lf %5.1lf", opt_tcp_size,
02261                       opt_max / 1024.0, max_bytes_per_sec / 1024.0);
02262             if (++opt_cnt == 10) {
02263                opt_cnt = 0;
02264                opt_max = 0;
02265                opt_index++;
02266                opt_tcp_size = 1 << (opt_index + 7);
02267                rpc_set_opt_tcp_size(opt_tcp_size);
02268                if (1 << (opt_index + 7) > 0x8000) {
02269                   opt_index = 0;
02270                   opt_tcp_size = 1 << 7;
02271                   rpc_set_opt_tcp_size(opt_tcp_size);
02272                }
02273             }
02274          }
02275 
02276          /* propagate changes in equipment to ODB */
02277          rpc_set_option(-1, RPC_OTRANSPORT, RPC_FTCP);
02278          db_send_changed_records();
02279          rpc_set_option(-1, RPC_OTRANSPORT, RPC_TCP);
02280 
02281          if (display_period) {
02282             display(FALSE);
02283 
02284             /* check keyboard */
02285             ch = 0;
02286             status = 0;
02287             while (ss_kbhit()) {
02288                ch = ss_getchar(0);
02289                if (ch == -1)
02290                   ch = getchar();
02291 
02292                if (ch == '!')
02293                   status = RPC_SHUTDOWN;
02294             }
02295 
02296             if (ch > 0)
02297                display(TRUE);
02298             if (status == RPC_SHUTDOWN)
02299                break;
02300          }
02301 
02302          last_time_display = actual_millitime;
02303       }
02304 
02305       /*---- check to flush cache ------------------------------------*/
02306       if (actual_millitime - last_time_flush > 1000) {
02307          last_time_flush = actual_millitime;
02308 
02309          /* if cache on server is not filled in one second at current
02310             data rate, flush it now to make events available to consumers */
02311 
02312          if (max_bytes_per_sec < SERVER_CACHE_SIZE) {
02313             old_flag = readout_enabled();
02314             if (old_flag && lockout_readout_thread)
02315                readout_enable(FALSE);
02316 
02317             for (i = 0; equipment[i].name[0]; i++) {
02318                if (equipment[i].buffer_handle) {
02319                   /* check if buffer already flushed */
02320                   buffer_done = FALSE;
02321                   for (j = 0; j < i; j++)
02322                      if (equipment[i].buffer_handle == equipment[j].buffer_handle) {
02323                         buffer_done = TRUE;
02324                         break;
02325                      }
02326 
02327                   if (!buffer_done) {
02328                      rpc_set_option(-1, RPC_OTRANSPORT, RPC_FTCP);
02329                      rpc_flush_event();
02330                      err = bm_flush_cache(equipment[i].buffer_handle, ASYNC);
02331                      if ((err != BM_SUCCESS) && (err != BM_ASYNC_RETURN)) {
02332                         cm_msg(MERROR, "scheduler", "bm_flush_cache(ASYNC) error %d",
02333                                err);
02334                         return err;
02335                      }
02336                      rpc_set_option(-1, RPC_OTRANSPORT, RPC_TCP);
02337                   }
02338                }
02339             }
02340 
02341             if (old_flag)
02342                readout_enable(TRUE);
02343          }
02344       }
02345 
02346       /*---- check for auto restart --------------------------------*/
02347       if (auto_restart > 0 && ss_time() > auto_restart) {
02348          /* check if really stopped */
02349          size = sizeof(state);
02350          status = db_get_value(hDB, 0, "Runinfo/State", &state, (INT *)&size, TID_INT, TRUE);
02351          if (status != DB_SUCCESS)
02352             cm_msg(MERROR, "scheduler", "cannot get Runinfo/State in database");
02353 
02354          if (state == STATE_STOPPED) {
02355             auto_restart = 0;
02356             size = sizeof(run_number);
02357             status =
02358                   db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, (INT*)&size, TID_INT,
02359                              TRUE);
02360             assert(status == SUCCESS);
02361 
02362             if (run_number <= 0) {
02363                cm_msg(MERROR, "main", "aborting on attempt to use invalid run number %d",
02364                       run_number);
02365                abort();
02366             }
02367 
02368             cm_msg(MTALK, "main", "starting new run");
02369             status = cm_transition(TR_START, run_number + 1, NULL, 0, SYNC, FALSE);
02370             if (status != CM_SUCCESS)
02371                cm_msg(MERROR, "main", "cannot restart run");
02372          }
02373       }
02374 
02375       /*---- check network messages ----------------------------------*/
02376       if ((run_state == STATE_RUNNING && interrupt_eq == NULL) || slowcont_eq) {
02377          /* only call yield once every 100ms when running */
02378          if (actual_millitime - last_time_network > 100) {
02379             status = cm_yield(0);
02380             last_time_network = actual_millitime;
02381          } else
02382             status = RPC_SUCCESS;
02383       } else
02384          /* when run is stopped or interrupts used, 
02385             call yield with 100ms timeout */
02386          status = cm_yield(100);
02387 
02388       /* exit for VxWorks */
02389       if (fe_stop)
02390          status = RPC_SHUTDOWN;
02391 
02392       /* exit if CTRL-C pressed */
02393       if (cm_is_ctrlc_pressed())
02394          status = RPC_SHUTDOWN;
02395 
02396    } while (status != RPC_SHUTDOWN && status != SS_ABORT);
02397 
02398  net_error:
02399 
02400    return status;
02401 }

void send_all_periodic_events ( INT  transition  ) 

Definition at line 1241 of file mfe.c.

Referenced by tr_pause(), tr_resume(), tr_start(), tr_start_fal(), tr_stop(), and tr_stop_fal().

01242 {
01243    EQUIPMENT_INFO *eq_info;
01244    INT i;
01245 
01246    for (i = 0; equipment[i].name[0]; i++) {
01247       eq_info = &equipment[i].info;
01248 
01249       if (!eq_info->enabled || equipment[i].status != FE_SUCCESS)
01250          continue;
01251 
01252       if (transition == TR_START && (eq_info->read_on & RO_BOR) == 0)
01253          continue;
01254       if (transition == TR_STOP && (eq_info->read_on & RO_EOR) == 0)
01255          continue;
01256       if (transition == TR_PAUSE && (eq_info->read_on & RO_PAUSE) == 0)
01257          continue;
01258       if (transition == TR_RESUME && (eq_info->read_on & RO_RESUME) == 0)
01259          continue;
01260 
01261       send_event(i, FALSE);
01262    }
01263 }

int send_event ( INT  idx,
BOOL  manual_trig 
)

Definition at line 1086 of file mfe.c.

Referenced by manual_trigger(), and send_all_periodic_events().

01087 {
01088    EQUIPMENT_INFO *eq_info;
01089    EVENT_HEADER *pevent, *pfragment;
01090    char *pdata;
01091    unsigned char *pd;
01092    INT i, status;
01093    DWORD sent, size;
01094 
01095    eq_info = &equipment[idx].info;
01096 
01097    /* check for fragmented event */
01098    if (eq_info->eq_type & EQ_FRAGMENTED)
01099       pevent = frag_buffer;
01100    else
01101       pevent = (EVENT_HEADER *)event_buffer;
01102 
01103    /* compose MIDAS event header */
01104    pevent->event_id = eq_info->event_id;
01105    pevent->trigger_mask = eq_info->trigger_mask;
01106    pevent->data_size = (INT) manual_trig;
01107    pevent->time_stamp = ss_time();
01108    pevent->serial_number = equipment[idx].serial_number++;
01109 
01110    equipment[idx].last_called = ss_millitime();
01111 
01112    /* call user readout routine */
01113    *((EQUIPMENT **) (pevent + 1)) = &equipment[idx];
01114    pevent->data_size = equipment[idx].readout((char *) (pevent + 1), 0);
01115 
01116    /* send event */
01117    if (pevent->data_size) {
01118       if (eq_info->eq_type & EQ_FRAGMENTED) {
01119          /* fragment event */
01120          if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size_frag) {
01121             cm_msg(MERROR, "send_event",
01122                    "Event size %ld larger than maximum size %d for frag. ev.",
01123                    (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01124                    max_event_size_frag);
01125             return SS_NO_MEMORY;
01126          }
01127 
01128          /* compose fragments */
01129          pfragment = event_buffer;
01130 
01131          /* compose MIDAS event header */
01132          memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01133          pfragment->event_id |= EVENTID_FRAG1;
01134 
01135          /* store total event size */
01136          pd = (unsigned char *) (pfragment + 1);
01137          size = pevent->data_size;
01138          for (i = 0; i < 4; i++) {
01139             pd[i] = (unsigned char) (size & 0xFF);      /* little endian, please! */
01140             size >>= 8;
01141          }
01142 
01143          pfragment->data_size = sizeof(DWORD);
01144 
01145          pdata = (char *) (pevent + 1);
01146 
01147          for (i = 0, sent = 0; sent < pevent->data_size; i++) {
01148             if (i > 0) {
01149                pfragment = event_buffer;
01150 
01151                /* compose MIDAS event header */
01152                memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01153                pfragment->event_id |= EVENTID_FRAG;
01154 
01155                /* copy portion of event */
01156                size = pevent->data_size - sent;
01157                if (size > max_event_size - sizeof(EVENT_HEADER))
01158                   size = max_event_size - sizeof(EVENT_HEADER);
01159 
01160                memcpy(pfragment + 1, pdata, size);
01161                pfragment->data_size = size;
01162                sent += size;
01163                pdata += size;
01164             }
01165 
01166             /* send event to buffer */
01167             if (equipment[idx].buffer_handle) {
01168                status = rpc_send_event(equipment[idx].buffer_handle, pfragment,
01169                                        pfragment->data_size + sizeof(EVENT_HEADER), SYNC, rpc_mode);
01170                if (status != RPC_SUCCESS) {
01171                   cm_msg(MERROR, "send_event", "rpc_send_event(SYNC) error %d", status);
01172                   return status;
01173                }
01174 
01175                /* flush events from buffer */
01176                rpc_flush_event();
01177             }
01178          }
01179 
01180          if (equipment[idx].buffer_handle) {
01181             /* flush buffer cache on server side */
01182             status = bm_flush_cache(equipment[idx].buffer_handle, SYNC);
01183             if (status != BM_SUCCESS) {
01184                cm_msg(MERROR, "send_event", "bm_flush_cache(SYNC) error %d", status);
01185                return status;
01186             }
01187          }
01188       } else {
01189          /* send unfragmented event */
01190 
01191          if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size) {
01192             cm_msg(MERROR, "send_event", "Event size %ld larger than maximum size %d",
01193                    (long) (pevent->data_size + sizeof(EVENT_HEADER)), max_event_size);
01194             return SS_NO_MEMORY;
01195          }
01196 
01197          /* send event to buffer */
01198          if (equipment[idx].buffer_handle) {
01199             status = rpc_send_event(equipment[idx].buffer_handle, pevent,
01200                                     pevent->data_size + sizeof(EVENT_HEADER), SYNC, rpc_mode);
01201             if (status != BM_SUCCESS) {
01202                cm_msg(MERROR, "send_event", "bm_send_event(SYNC) error %d", status);
01203                return status;
01204             }
01205             rpc_flush_event();
01206             status = bm_flush_cache(equipment[idx].buffer_handle, SYNC);
01207             if (status != BM_SUCCESS) {
01208                cm_msg(MERROR, "send_event", "bm_flush_cache(SYNC) error %d", status);
01209                return status;
01210             }
01211          }
01212 
01213          /* send event to ODB if RO_ODB flag is set or history is on. Do not
01214             send SLOW events since the class driver does that */
01215          if ((eq_info->read_on & RO_ODB) ||
01216              (eq_info->history > 0 && (eq_info->eq_type & ~EQ_SLOW))) {
01217             update_odb(pevent, equipment[idx].hkey_variables, equipment[idx].format);
01218             equipment[idx].odb_out++;
01219          }
01220       }
01221 
01222       equipment[idx].bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
01223       equipment[idx].events_sent++;
01224    } else
01225       equipment[idx].serial_number--;
01226 
01227    for (i = 0; equipment[i].name[0]; i++)
01228       if (equipment[i].buffer_handle) {
01229          status = bm_flush_cache(equipment[i].buffer_handle, SYNC);
01230          if (status != BM_SUCCESS) {
01231             cm_msg(MERROR, "send_event", "bm_flush_cache(SYNC) error %d", status);
01232             return status;
01233          }
01234       }
01235 
01236    return CM_SUCCESS;
01237 }

int set_equipment_status ( const char *  name,
const char *  eqipment_status,
const char *  status_color 
)

Definition at line 964 of file mfe.c.

00965 {
00966    int status, idx;
00967    char str[256];
00968    HNDLE hKey;
00969 
00970    for (idx = 0; equipment[idx].name[0]; idx++)
00971       if (equal_ustring(equipment[idx].name, name))
00972          break;
00973 
00974    if (equal_ustring(equipment[idx].name, name)) {
00975       sprintf(str, "/Equipment/%s/Common", name);
00976       db_find_key(hDB, 0, str, &hKey);
00977       assert(hKey);
00978 
00979       status = db_set_value(hDB, hKey, "Status", eqipment_status, 256, 1, TID_STRING);
00980       assert(status == DB_SUCCESS);
00981       status = db_set_value(hDB, hKey, "Status color", status_color, 32, 1, TID_STRING);
00982       assert(status == DB_SUCCESS);
00983    }
00984 
00985    return SUCCESS;
00986 }

void set_rate_period ( int  ms  ) 

Definition at line 131 of file mfe.c.

Referenced by main().

00132 {
00133    rate_period = ms;
00134 }

INT tr_pause ( INT  rn,
char *  error 
)

Definition at line 247 of file mfe.c.

Referenced by main().

00248 {
00249    INT status;
00250 
00251    /* disable interrupts or readout thread */
00252    readout_enable(FALSE);
00253 
00254    status = pause_run(rn, error);
00255 
00256    if (status == CM_SUCCESS) {
00257       run_state = STATE_PAUSED;
00258       run_number = rn;
00259 
00260       send_all_periodic_events(TR_PAUSE);
00261 
00262       if (display_period)
00263          ss_printf(14, 2, "Paused  ");
00264    } else
00265       readout_enable(TRUE);
00266 
00267    return status;
00268 }

INT tr_resume ( INT  rn,
char *  error 
)

Definition at line 272 of file mfe.c.

Referenced by main().

00273 {
00274    INT status;
00275 
00276    status = resume_run(rn, error);
00277 
00278    if (status == CM_SUCCESS) {
00279       run_state = STATE_RUNNING;
00280       run_number = rn;
00281 
00282       send_all_periodic_events(TR_RESUME);
00283 
00284       if (display_period)
00285          ss_printf(14, 2, "Running ");
00286 
00287       /* enable interrupts or readout thread */
00288       readout_enable(TRUE);
00289    }
00290 
00291    return status;
00292 }

INT tr_start ( INT  rn,
char *  error 
)

Definition at line 145 of file mfe.c.

Referenced by main(), and tr_start_fal().

00146 {
00147    INT i, status;
00148 
00149    /* disable interrupts or readout thread
00150     * if somehow it was not stopped from previous run */
00151    readout_enable(FALSE);
00152 
00153    /* reset serial numbers */
00154    for (i = 0; equipment[i].name[0]; i++) {
00155       equipment[i].serial_number = 0;
00156       equipment[i].subevent_number = 0;
00157       equipment[i].stats.events_sent = 0;
00158       equipment[i].odb_in = equipment[i].odb_out = 0;
00159       n_events[i] = 0;
00160    }
00161 
00162    status = begin_of_run(rn, error);
00163 
00164    if (status == CM_SUCCESS) {
00165       run_state = STATE_RUNNING;
00166       run_number = rn;
00167 
00168       send_all_periodic_events(TR_START);
00169 
00170       if (display_period) {
00171          ss_printf(14, 2, "Running ");
00172          ss_printf(36, 2, "%d", rn);
00173       }
00174 
00175       /* enable interrupts or readout thread */
00176       readout_enable(TRUE);
00177    }
00178 
00179    return status;
00180 }

INT tr_stop ( INT  rn,
char *  error 
)

Definition at line 184 of file mfe.c.

Referenced by main(), and tr_stop_fal().

00185 {
00186    INT status, i;
00187    EQUIPMENT *eq;
00188 
00189    /* disable interrupts or readout thread */
00190    readout_enable(FALSE);
00191 
00192    status = end_of_run(rn, error);
00193 
00194    /* check if event(s) happened just before disabling the trigger */
00195    if ((i = check_polled_events()) > 0) {
00196       // cm_msg(MINFO, "tr_stop", "sent remaining %d polled events", i);
00197    }
00198 
00199    if (status == CM_SUCCESS) {
00200       /* don't send events if already stopped */
00201       if (run_state != STATE_STOPPED)
00202          send_all_periodic_events(TR_STOP);
00203 
00204       run_state = STATE_STOPPED;
00205       run_number = rn;
00206 
00207       if (display_period)
00208          ss_printf(14, 2, "Stopped ");
00209    } else
00210       readout_enable(TRUE);
00211 
00212    for (i = 0; equipment[i].name[0]; i++) {
00213       /* read remaining events from ring buffers */
00214       if (equipment[i].info.eq_type & (EQ_MULTITHREAD | EQ_INTERRUPT)) {
00215          while (receive_trigger_event(equipment+i) > 0);
00216       }
00217 
00218       /* flush remaining buffered events */
00219       rpc_flush_event();
00220       if (equipment[i].buffer_handle) {
00221          INT err = bm_flush_cache(equipment[i].buffer_handle, SYNC);
00222          if (err != BM_SUCCESS) {
00223             cm_msg(MERROR, "tr_stop", "bm_flush_cache(SYNC) error %d", err);
00224             return err;
00225          }
00226       }
00227    }
00228 
00229    /* update final statistics record in ODB */
00230    for (i = 0; equipment[i].name[0]; i++) {
00231       eq = &equipment[i];
00232       eq->stats.events_sent += eq->events_sent;
00233       eq->stats.events_per_sec = 0;
00234       eq->stats.kbytes_per_sec = 0;
00235       eq->bytes_sent = 0;
00236       eq->events_sent = 0;
00237       n_events[i] = 0;
00238    }
00239 
00240    db_send_changed_records();
00241 
00242    return status;
00243 }

void update_odb ( EVENT_HEADER pevent,
HNDLE  hKey,
INT  format 
)

Definition at line 990 of file mfe.c.

Referenced by receive_trigger_event(), and send_event().

00991 {
00992    INT size, i, status, n_data;
00993    char *pdata;
00994    char name[5];
00995    BANK_HEADER *pbh;
00996    BANK *pbk;
00997    BANK32 *pbk32;
00998    DWORD bkname;
00999    WORD bktype;
01000    HNDLE hKeyRoot, hKeyl;
01001    KEY key;
01002 
01003 
01004    /* outcommented since db_find_key does not work in FTCP mode, SR 25.4.03
01005       rpc_set_option(-1, RPC_OTRANSPORT, RPC_FTCP); */
01006 
01007    if (format == FORMAT_FIXED) {
01008       if (db_set_record(hDB, hKey, (char *) (pevent + 1),
01009                         pevent->data_size, 0) != DB_SUCCESS)
01010          cm_msg(MERROR, "update_odb", "event #%d size mismatch", pevent->event_id);
01011    } else if (format == FORMAT_MIDAS) {
01012       pbh = (BANK_HEADER *) (pevent + 1);
01013       pbk = NULL;
01014       pbk32 = NULL;
01015       do {
01016          /* scan all banks */
01017          if (bk_is32(pbh)) {
01018             size = bk_iterate32(pbh, &pbk32, &pdata);
01019             if (pbk32 == NULL)
01020                break;
01021             bkname = *((DWORD *) pbk32->name);
01022             bktype = (WORD) pbk32->type;
01023          } else {
01024             size = bk_iterate(pbh, &pbk, &pdata);
01025             if (pbk == NULL)
01026                break;
01027             bkname = *((DWORD *) pbk->name);
01028             bktype = (WORD) pbk->type;
01029          }
01030 
01031          n_data = size;
01032          if (rpc_tid_size(bktype & 0xFF))
01033             n_data /= rpc_tid_size(bktype & 0xFF);
01034 
01035          /* get bank key */
01036          *((DWORD *) name) = bkname;
01037          name[4] = 0;
01038 
01039          if (bktype == TID_STRUCT) {
01040             status = db_find_key(hDB, hKey, name, &hKeyRoot);
01041             if (status != DB_SUCCESS) {
01042                cm_msg(MERROR, "update_odb",
01043                       "please define bank %s in BANK_LIST in frontend.c", name);
01044                continue;
01045             }
01046 
01047             /* write structured bank */
01048             for (i = 0;; i++) {
01049                status = db_enum_key(hDB, hKeyRoot, i, &hKeyl);
01050                if (status == DB_NO_MORE_SUBKEYS)
01051                   break;
01052 
01053                db_get_key(hDB, hKeyl, &key);
01054 
01055                /* adjust for alignment */
01056                if (key.type != TID_STRING && key.type != TID_LINK)
01057                   pdata =
01058                       (void *) VALIGN(pdata, MIN(ss_get_struct_align(), key.item_size));
01059 
01060                status = db_set_data(hDB, hKeyl, pdata, key.item_size * key.num_values,
01061                                     key.num_values, key.type);
01062                if (status != DB_SUCCESS) {
01063                   cm_msg(MERROR, "update_odb", "cannot write %s to ODB", name);
01064                   continue;
01065                }
01066 
01067                /* shift data pointer to next item */
01068                pdata += key.item_size * key.num_values;
01069             }
01070          } else {
01071             /* write variable length bank  */
01072             if (n_data > 0)
01073                db_set_value(hDB, hKey, name, pdata, size, n_data, bktype & 0xFF);
01074          }
01075 
01076       } while (1);
01077    } else if (format == FORMAT_YBOS) {
01078      assert(!"YBOS not supported anymore");
01079    }
01080 
01081    rpc_set_option(-1, RPC_OTRANSPORT, RPC_TCP);
01082 }


Variable Documentation

int _readout_enabled_flag = 0 [static]

Definition at line 1267 of file mfe.c.

DWORD actual_millitime

Definition at line 55 of file mfe.c.

Referenced by check_polled_events(), scan_fragment(), and scheduler().

DWORD actual_time

Definition at line 54 of file mfe.c.

Referenced by check_polled_events(), interrupt_routine(), log_write(), process_event(), readout_thread(), scheduler(), and update_stats().

DWORD auto_restart = 0

Definition at line 66 of file mfe.c.

Referenced by log_write(), main(), start_the_run(), stop_the_run(), and tr_stop().

BOOL debug

Definition at line 65 of file mfe.c.

Referenced by cmp_names(), eb_user(), handFlush(), lazy_main(), lazy_maintain_free_space(), lazy_select_purge(), load_fragment(), main(), open_history(), scan_fragment(), set_history_path(), source_booking(), source_unbooking(), and vf48_ParameterRead().

INT display_period

Definition at line 32 of file ebuser.c.

Referenced by manual_trigger(), rotate_wheel(), tr_pause(), tr_resume(), tr_start(), and tr_stop().

EQUIPMENT equipment[]

Definition at line 59 of file ebuser.c.

void* event_buffer

Definition at line 78 of file mfe.c.

Referenced by check_polled_events(), main(), scheduler(), and send_event().

INT event_buffer_size

Definition at line 41 of file ebuser.c.

Referenced by initialize_equipment(), and main().

char exp_name[NAME_LENGTH]

Definition at line 59 of file mfe.c.

Referenced by main().

INT fe_stop = 0

Definition at line 64 of file mfe.c.

void* frag_buffer = NULL

Definition at line 79 of file mfe.c.

Referenced by check_polled_events(), and send_event().

BOOL frontend_call_loop

Definition at line 20 of file midas_macro.h.

char* frontend_file_name

Definition at line 26 of file ebuser.c.

Referenced by register_equipment().

INT frontend_index = -1

Definition at line 68 of file mfe.c.

Referenced by get_frontend_index(), main(), and register_equipment().

char* frontend_name

Definition at line 23 of file ebuser.c.

Referenced by load_fragment(), main(), register_equipment(), scan_fragment(), and tr_stop().

char full_frontend_name[256]

Definition at line 60 of file mfe.c.

Referenced by display(), main(), and register_equipment().

HNDLE hDB

Definition at line 71 of file mfe.c.

Referenced by add_data_dir(), add_event(), ana_end_of_run(), analyze_run(), analyzer_init(), ascii_write(), assemble_prompt(), book_ntuples(), bor(), build_done_list(), build_done_list_odb(), close_history(), cm_connect_client(), cm_connect_experiment1(), cm_disconnect_experiment(), cm_get_client_info(), cm_msg_log(), cm_msg_log1(), cm_msg_retrieve(), cm_set_watchdog_params(), cmd_dir(), command_loop(), condition_test(), convert_done_list(), db_get_event_definition(), do_jrpc_rev0(), dump_write(), el_submit(), evaluate_src(), exec_script(), gen_odb_attachment(), get_elog_url(), get_event_id(), get_variable_id(), get_variable_id_tags(), MidasHistory::GetEventsFromEquipment(), MidasHistory::GetEventsFromOdbEvents(), MidasHistory::GetEventsFromOdbTags(), MidasHistory::GetTagsFromEquipment(), MidasHistory::GetTagsFromOdb(), MidasHistory::hs_connect(), MidasHistory::hs_get_events(), init_module_parameters(), is_editable(), lazy_main(), lazy_maintain_check(), lazy_maintain_free_space(), lazy_select_purge(), load_fragment(), log_callback(), log_odb_dump(), log_write(), logger_init(), logger_root(), main(), mana_init(), odb_load(), odb_save(), open_history(), process_event(), register_equipment(), register_requests(), save_done_list(), set_equipment_status(), show_cnaf_page(), show_custom_gif(), show_custom_page(), show_elog_delete(), show_elog_new(), show_elog_page(), show_elog_query(), show_elog_submit_query(), show_form_query(), show_messages_page(), show_odb_tag(), show_rawfile(), show_sc_page(), show_status_page(), start_the_run(), stop_the_run(), submit_elog(), submit_form(), test_write(), tr_start(), tr_start_fal(), tr_stop(), tr_stop_fal(), update_odb(), write_event_ascii(), write_event_hbook(), and write_event_odb().

char host_name[HOST_NAME_LENGTH]

Definition at line 58 of file mfe.c.

Referenced by display(), ftp_data(), ftp_open(), main(), mftp_open(), sendmail(), server_loop(), and submit_elog().

EQUIPMENT* interrupt_eq = NULL

Definition at line 75 of file mfe.c.

Referenced by initialize_equipment(), interrupt_enable(), interrupt_routine(), main(), and readout_enable().

BOOL lockout_readout_thread = TRUE

Definition at line 69 of file mfe.c.

INT manual_trigger_event_id = 0

Definition at line 67 of file mfe.c.

Referenced by manual_trigger().

INT max_bytes_per_sec

Definition at line 62 of file mfe.c.

INT max_event_size

Definition at line 35 of file ebuser.c.

Referenced by check_polled_events(), handFlush(), initialize_equipment(), load_fragment(), readout_thread(), send_event(), source_booking(), and source_scan().

INT max_event_size_frag

Definition at line 38 of file ebuser.c.

Referenced by send_event().

void(*) mfe_error_dispatcher(const char *) = NULL

Definition at line 2412 of file mfe.c.

Referenced by mfe_error_check(), and mfe_set_error().

int mfe_error_r

Definition at line 2416 of file mfe.c.

char mfe_error_str[MFE_ERROR_SIZE][256]

Definition at line 2415 of file mfe.c.

int mfe_error_w

Definition at line 2416 of file mfe.c.

MUTEX_T* mfe_mutex = NULL

Definition at line 2417 of file mfe.c.

EQUIPMENT* multithread_eq = NULL

Definition at line 76 of file mfe.c.

Referenced by readout_enable(), and readout_thread().

int* n_events

Definition at line 81 of file mfe.c.

Referenced by tr_start().

INT optimize = 0

Definition at line 63 of file mfe.c.

DWORD rate_period

Definition at line 56 of file mfe.c.

Referenced by get_rate_period(), and set_rate_period().

int rbh1 = 0

Definition at line 84 of file mfe.c.

Referenced by initialize_equipment(), interrupt_routine(), and readout_thread().

int rbh1_next = 0

Definition at line 84 of file mfe.c.

Referenced by readout_thread().

int rbh2 = 0

Definition at line 84 of file mfe.c.

Referenced by initialize_equipment(), and receive_trigger_event().

int rbh2_next = 0

Definition at line 84 of file mfe.c.

volatile int readout_thread_active = 0

Definition at line 87 of file mfe.c.

Referenced by main(), readout_enable(), and readout_thread().

INT rpc_mode = 1

Definition at line 44 of file mfe.c.

Referenced by receive_trigger_event(), and send_event().

INT run_number

Definition at line 53 of file mfe.c.

Referenced by display(), el_submit(), export_hist(), generate_hist_graph(), loop_runs_offline(), register_equipment(), show_elog_new(), show_form_query(), tr_pause(), tr_resume(), tr_start(), and tr_stop().

INT run_state

Definition at line 52 of file mfe.c.

Referenced by display(), interprete(), lazy_condition_check(), main(), register_equipment(), scan_fragment(), scheduler(), tr_pause(), tr_resume(), tr_start(), tr_start_fal(), tr_stop(), and tr_stop_fal().

BOOL slowcont_eq = FALSE

Definition at line 77 of file mfe.c.

volatile int stop_all_threads = 0

Definition at line 85 of file mfe.c.

Referenced by main(), and readout_thread().


Midas DOC Version 3.0.0 ---- PSI Stefan Ritt ----
Contributions: Pierre-Andre Amaudruz - Sergio Ballestrero - Suzannah Daviel - Doxygen - Peter Green - Qing Gu - Greg Hackman - Gertjan Hofman - Paul Knowles - Exaos Lee - Rudi Meier - Glenn Moloney - Dave Morris - John M O'Donnell - Konstantin Olchanski - Renee Poutissou - Tamsen Schurman - Andreas Suter - Jan M.Wouters - Piotr Adam Zolnierczuk