00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <stdio.h>
00014 #include <assert.h>
00015 #include "midas.h"
00016 #include "msystem.h"
00017 #include "mcstd.h"
00018
00019
00020
00021
00022
00023 extern char *frontend_name;
00024 extern char *frontend_file_name;
00025 extern BOOL frontend_call_loop;
00026 extern INT max_event_size;
00027 extern INT max_event_size_frag;
00028 extern INT event_buffer_size;
00029 extern INT display_period;
00030 extern INT frontend_init(void);
00031 extern INT frontend_exit(void);
00032 extern INT frontend_loop(void);
00033 extern INT begin_of_run(INT run_number, char *error);
00034 extern INT end_of_run(INT run_number, char *error);
00035 extern INT pause_run(INT run_number, char *error);
00036 extern INT resume_run(INT run_number, char *error);
00037 extern INT poll_event(INT source, INT count, BOOL test);
00038 extern INT interrupt_configure(INT cmd, INT source, POINTER_T adr);
00039
00040
00041
00042
00043
00044 INT rpc_mode = 1;
00045
00046 #define SERVER_CACHE_SIZE 100000
00047
00048 #define ODB_UPDATE_TIME 1000
00049
00050 #define DEFAULT_FE_TIMEOUT 60000
00051
00052 INT run_state;
00053 INT run_number;
00054 DWORD actual_time;
00055 DWORD actual_millitime;
00056 DWORD rate_period;
00057
00058 char host_name[HOST_NAME_LENGTH];
00059 char exp_name[NAME_LENGTH];
00060 char full_frontend_name[256];
00061
00062 INT max_bytes_per_sec;
00063 INT optimize = 0;
00064 INT fe_stop = 0;
00065 BOOL debug;
00066 DWORD auto_restart = 0;
00067 INT manual_trigger_event_id = 0;
00068 INT frontend_index = -1;
00069 BOOL lockout_readout_thread = TRUE;
00070
00071 HNDLE hDB;
00072
00073 extern EQUIPMENT equipment[];
00074
00075 EQUIPMENT *interrupt_eq = NULL;
00076 EQUIPMENT *multithread_eq = NULL;
00077 BOOL slowcont_eq = FALSE;
00078 void *event_buffer;
00079 void *frag_buffer = NULL;
00080
00081 int *n_events;
00082
00083
00084 int rbh1=0, rbh2=0, rbh1_next=0, rbh2_next=0;
00085 volatile int stop_all_threads = 0;
00086 int readout_thread(void *param);
00087 volatile int readout_thread_active = 0;
00088 void mfe_error_check(void);
00089
00090 int send_event(INT idx, BOOL manual_trig);
00091 int receive_trigger_event(EQUIPMENT *eq);
00092 void send_all_periodic_events(INT transition);
00093 void interrupt_routine(void);
00094 void readout_enable(BOOL flag);
00095 int readout_enabled(void);
00096 void display(BOOL bInit);
00097 void rotate_wheel(void);
00098 BOOL logger_root();
00099 INT check_polled_events(void);
00100
00101
00102
00103 #define EQUIPMENT_COMMON_STR "\
00104 Event ID = WORD : 0\n\
00105 Trigger mask = WORD : 0\n\
00106 Buffer = STRING : [32] SYSTEM\n\
00107 Type = INT : 0\n\
00108 Source = INT : 0\n\
00109 Format = STRING : [8] FIXED\n\
00110 Enabled = BOOL : 0\n\
00111 Read on = INT : 0\n\
00112 Period = INT : 0\n\
00113 Event limit = DOUBLE : 0\n\
00114 Num subevents = DWORD : 0\n\
00115 Log history = INT : 0\n\
00116 Frontend host = STRING : [32] \n\
00117 Frontend name = STRING : [32] \n\
00118 Frontend file name = STRING : [256] \n\
00119 Status = STRING : [256] \n\
00120 Status color = STRING : [32] \n\
00121 "
00122
00123 #define EQUIPMENT_STATISTICS_STR "\
00124 Events sent = DOUBLE : 0\n\
00125 Events per sec. = DOUBLE : 0\n\
00126 kBytes per sec. = DOUBLE : 0\n\
00127 "
00128
00129
00130
00131 void set_rate_period(int ms)
00132 {
00133 rate_period = ms;
00134 }
00135
00136 int get_rate_period()
00137 {
00138 return rate_period;
00139 }
00140
00141
00142
00143
00144
00145 INT tr_start(INT rn, char *error)
00146 {
00147 INT i, status;
00148
00149
00150
00151 readout_enable(FALSE);
00152
00153
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
00176 readout_enable(TRUE);
00177 }
00178
00179 return status;
00180 }
00181
00182
00183
00184 INT tr_stop(INT rn, char *error)
00185 {
00186 INT status, i;
00187 EQUIPMENT *eq;
00188
00189
00190 readout_enable(FALSE);
00191
00192 status = end_of_run(rn, error);
00193
00194
00195 if ((i = check_polled_events()) > 0) {
00196
00197 }
00198
00199 if (status == CM_SUCCESS) {
00200
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
00214 if (equipment[i].info.eq_type & (EQ_MULTITHREAD | EQ_INTERRUPT)) {
00215 while (receive_trigger_event(equipment+i) > 0);
00216 }
00217
00218
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
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 }
00244
00245
00246
00247 INT tr_pause(INT rn, char *error)
00248 {
00249 INT status;
00250
00251
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 }
00269
00270
00271
00272 INT tr_resume(INT rn, char *error)
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
00288 readout_enable(TRUE);
00289 }
00290
00291 return status;
00292 }
00293
00294
00295
00296 INT manual_trigger(INT idx, void *prpc_param[])
00297 {
00298 int i;
00299
00300 i = idx;
00301 manual_trigger_event_id = CWORD(0);
00302 return SUCCESS;
00303 }
00304
00305
00306
00307 int sc_thread(void *info)
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
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
00333 }
00334
00335
00336 current_channel = (current_channel + 1) % device_drv->channels;
00337
00338
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
00345 break;
00346 }
00347 }
00348
00349
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
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
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
00394 device_drv->stop_thread = 2;
00395
00396 return SUCCESS;
00397 }
00398
00399
00400
00401 INT device_driver(DEVICE_DRIVER * device_drv, INT cmd, ...)
00402 {
00403 va_list argptr;
00404 HNDLE hKey;
00405 INT channel, status, i, j;
00406 float value, *pvalue;
00407 char *name, *label, str[256];
00408
00409 va_start(argptr, cmd);
00410 status = FE_SUCCESS;
00411
00412 switch (cmd) {
00413 case CMD_INIT:
00414 hKey = va_arg(argptr, HNDLE);
00415
00416 if (device_drv->flags & DF_MULTITHREAD) {
00417 status = device_drv->dd(CMD_INIT, hKey, &device_drv->dd_info,
00418 device_drv->channels, device_drv->flags,
00419 device_drv->bd);
00420
00421 if (status == FE_SUCCESS && (device_drv->flags & DF_MULTITHREAD)) {
00422
00423 device_drv->mt_buffer = (DD_MT_BUFFER *) calloc(1, sizeof(DD_MT_BUFFER));
00424 device_drv->mt_buffer->n_channels = device_drv->channels;
00425 device_drv->mt_buffer->channel = (DD_MT_CHANNEL *) calloc(device_drv->channels, sizeof(DD_MT_CHANNEL));
00426 assert(device_drv->mt_buffer->channel);
00427
00428
00429 for (i=0 ; i<device_drv->channels ; i++)
00430 for (j=CMD_SET_FIRST ; j<=CMD_SET_LAST ; j++)
00431 device_drv->mt_buffer->channel[i].variable[j] = (float)ss_nan();
00432
00433
00434 for (i = 0; i < device_drv->channels; i++)
00435 device_drv->dd(CMD_GET_LABEL, device_drv->dd_info, i,
00436 device_drv->mt_buffer->channel[i].label);
00437
00438
00439 sprintf(str, "DD_%s", device_drv->name);
00440 status = ss_semaphore_create(str, &device_drv->semaphore);
00441 if (status != SS_CREATED && status != SS_SUCCESS)
00442 return FE_ERR_DRIVER;
00443 status = FE_SUCCESS;
00444 }
00445 } else {
00446 status = device_drv->dd(CMD_INIT, hKey, &device_drv->dd_info,
00447 device_drv->channels, device_drv->flags,
00448 device_drv->bd);
00449 }
00450 break;
00451
00452 case CMD_START:
00453 if (device_drv->flags & DF_MULTITHREAD && device_drv->mt_buffer != NULL) {
00454
00455 device_drv->mt_buffer->thread_id = ss_thread_create(sc_thread, device_drv);
00456 }
00457 break;
00458
00459 case CMD_STOP:
00460 if (device_drv->flags & DF_MULTITHREAD && device_drv->mt_buffer != NULL) {
00461 device_drv->stop_thread = 1;
00462
00463 for (i = 0; i < 1000; i++) {
00464 if (device_drv->stop_thread == 2)
00465 break;
00466 ss_sleep(10);
00467 }
00468
00469
00470 if (i == 1000)
00471 ss_thread_kill(device_drv->mt_buffer->thread_id);
00472
00473 ss_semaphore_delete(device_drv->semaphore, TRUE);
00474 free(device_drv->mt_buffer->channel);
00475 free(device_drv->mt_buffer);
00476 }
00477 break;
00478
00479 case CMD_EXIT:
00480 status = device_drv->dd(CMD_EXIT, device_drv->dd_info);
00481 break;
00482
00483 case CMD_SET_LABEL:
00484 channel = va_arg(argptr, INT);
00485 label = va_arg(argptr, char *);
00486 status = device_drv->dd(CMD_SET_LABEL, device_drv->dd_info, channel, label);
00487 break;
00488
00489 case CMD_GET_LABEL:
00490 channel = va_arg(argptr, INT);
00491 name = va_arg(argptr, char *);
00492 status = device_drv->dd(CMD_GET_LABEL, device_drv->dd_info, channel, name);
00493 break;
00494
00495 default:
00496
00497 if (cmd >= CMD_SET_FIRST && cmd <= CMD_SET_LAST) {
00498
00499
00500 channel = va_arg(argptr, INT);
00501 value = (float) va_arg(argptr, double);
00502 if (device_drv->flags & DF_MULTITHREAD) {
00503 ss_semaphore_wait_for(device_drv->semaphore, 1000);
00504 device_drv->mt_buffer->channel[channel].variable[cmd] = value;
00505 status = device_drv->mt_buffer->status;
00506 ss_semaphore_release(device_drv->semaphore);
00507 } else {
00508 status = device_drv->dd(cmd, device_drv->dd_info, channel, value);
00509 }
00510
00511 } else if (cmd >= CMD_GET_FIRST && cmd <= CMD_GET_LAST) {
00512
00513
00514 channel = va_arg(argptr, INT);
00515 pvalue = va_arg(argptr, float *);
00516 if (device_drv->flags & DF_MULTITHREAD) {
00517 ss_semaphore_wait_for(device_drv->semaphore, 1000);
00518 *pvalue = device_drv->mt_buffer->channel[channel].variable[cmd];
00519 status = device_drv->mt_buffer->status;
00520 ss_semaphore_release(device_drv->semaphore);
00521 } else
00522 status = device_drv->dd(cmd, device_drv->dd_info, channel, pvalue);
00523
00524 } else {
00525
00526
00527 channel = va_arg(argptr, INT);
00528 pvalue = va_arg(argptr, float *);
00529 status = device_drv->dd(cmd, device_drv->dd_info, channel, pvalue);
00530 }
00531
00532 break;
00533 }
00534
00535 va_end(argptr);
00536 return status;
00537 }
00538
00539
00540
00541 INT register_equipment(void)
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
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
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
00574 equipment[idx].status = FE_SUCCESS;
00575
00576
00577 if (frontend_index != -1) {
00578
00579 if (strchr(equipment[idx].name, '%')) {
00580 strcpy(str, equipment[idx].name);
00581 sprintf(equipment[idx].name, str, frontend_index);
00582 }
00583
00584
00585 if (strchr(eq_info->buffer, '%')) {
00586 strcpy(str, eq_info->buffer);
00587 sprintf(eq_info->buffer, str, frontend_index);
00588 }
00589 } else {
00590
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
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
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
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
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
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
00643 db_set_record(hDB, hKey, eq_info, sizeof(EQUIPMENT_INFO), 0);
00644
00645
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
00653 bank_list = (BANK_LIST *) equipment[idx].event_descrip;
00654
00655 for (; bank_list->name[0]; bank_list++) {
00656
00657
00658
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
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
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
00719
00720
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
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 }
00752
00753
00754
00755 INT initialize_equipment(void)
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
00765 for (idx = 0; equipment[idx].name[0]; idx++) {
00766 eq_info = &equipment[idx].info;
00767 eq_stats = &equipment[idx].stats;
00768
00769
00770
00771 if (eq_info->eq_type & EQ_INTERRUPT) {
00772
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
00791 if (!rbh1) {
00792 rb_create(event_buffer_size, max_event_size, &rbh1);
00793 rbh2 = rbh1;
00794 }
00795
00796
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
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
00855
00856 if (eq_info->eq_type & EQ_MULTITHREAD) {
00857
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
00876 if (!rbh1) {
00877 rb_create(event_buffer_size, max_event_size, &rbh1);
00878 rbh2 = rbh1;
00879 }
00880
00881
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
00895
00896 if (eq_info->eq_type & EQ_SLOW) {
00897
00898 set_equipment_status(equipment[idx].name, "Initializing...", "yellow");
00899
00900
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
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
00935 if (equipment[idx].status == FE_SUCCESS)
00936 equipment[idx].cd(CMD_START, &equipment[idx]);
00937
00938
00939 slowcont_eq = TRUE;
00940
00941
00942 if (equipment[idx].status != FE_SUCCESS &&
00943 equipment[idx].status != FE_ERR_DISABLED)
00944 ss_sleep(3000);
00945 }
00946
00947
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 }
00961
00962
00963
00964 int set_equipment_status(const char *name, const char *eqipment_status, const char *status_color)
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 }
00987
00988
00989
00990 void update_odb(EVENT_HEADER * pevent, HNDLE hKey, INT format)
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
01005
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
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
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
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
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
01068 pdata += key.item_size * key.num_values;
01069 }
01070 } else {
01071
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 }
01083
01084
01085
01086 int send_event(INT idx, BOOL manual_trig)
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
01098 if (eq_info->eq_type & EQ_FRAGMENTED)
01099 pevent = frag_buffer;
01100 else
01101 pevent = (EVENT_HEADER *)event_buffer;
01102
01103
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
01113 *((EQUIPMENT **) (pevent + 1)) = &equipment[idx];
01114 pevent->data_size = equipment[idx].readout((char *) (pevent + 1), 0);
01115
01116
01117 if (pevent->data_size) {
01118 if (eq_info->eq_type & EQ_FRAGMENTED) {
01119
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
01129 pfragment = event_buffer;
01130
01131
01132 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01133 pfragment->event_id |= EVENTID_FRAG1;
01134
01135
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);
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
01152 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01153 pfragment->event_id |= EVENTID_FRAG;
01154
01155
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
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
01176 rpc_flush_event();
01177 }
01178 }
01179
01180 if (equipment[idx].buffer_handle) {
01181
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
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
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
01214
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 }
01238
01239
01240
01241 void send_all_periodic_events(INT transition)
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 }
01264
01265
01266
01267 static int _readout_enabled_flag = 0;
01268
01269 int readout_enabled()
01270 {
01271 return _readout_enabled_flag;
01272 }
01273
01274 void readout_enable(BOOL flag)
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
01287 if (flag == 0)
01288 while (readout_thread_active)
01289 ss_sleep(10);
01290 }
01291 }
01292
01293
01294
01295 void interrupt_routine(void)
01296 {
01297 int status;
01298 EVENT_HEADER *pevent;
01299 void *p;
01300
01301
01302
01303 status = rb_get_wp(rbh1, &p, 100000);
01304
01305 if (status == DB_SUCCESS) {
01306 pevent = (EVENT_HEADER *)p;
01307
01308
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
01316 pevent->data_size = interrupt_eq->readout((char *) (pevent + 1), 0);
01317
01318
01319 if (pevent->data_size) {
01320
01321
01322 rb_increment_wp(rbh1, sizeof(EVENT_HEADER) + pevent->data_size);
01323
01324 } else
01325 interrupt_eq->serial_number--;
01326 }
01327 }
01328
01329
01330
01331 int readout_thread(void *param)
01332 {
01333 int status, source;
01334 EVENT_HEADER *pevent;
01335 void *p;
01336
01337 p = param;
01338 while (!stop_all_threads) {
01339
01340 if (rbh1_next)
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
01348 ss_sleep(10);
01349 continue;
01350 }
01351 if (status != DB_SUCCESS)
01352 break;
01353
01354 if (readout_enabled()) {
01355
01356
01357 readout_thread_active = 1;
01358
01359
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
01369
01370
01371 *(INT *) (pevent + 1) = source;
01372
01373
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
01381 pevent->data_size = multithread_eq->readout((char *) (pevent + 1), 0);
01382
01383
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
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
01402 ss_sleep(10);
01403
01404 }
01405
01406 readout_thread_active = 0;
01407
01408 return 0;
01409 }
01410
01411
01412
01413 int receive_trigger_event(EQUIPMENT *eq)
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
01437 if (pevent->data_size) {
01438 if (eq->buffer_handle) {
01439
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 }
01468
01469
01470
01471 int message_print(const char *msg)
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 }
01486
01487
01488
01489 void display(BOOL bInit)
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
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
01557 ss_printf(0, i + 6, "");
01558 }
01559
01560
01561
01562 void rotate_wheel(void)
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 }
01575
01576
01577
01578 BOOL logger_root()
01579
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 }
01602
01603
01604
01605 INT check_polled_events(void)
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
01619 for (idx = 0;; idx++) {
01620 eq = &equipment[idx];
01621 eq_info = &eq->info;
01622
01623
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
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
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
01655
01656
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
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
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
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
01696 pevent->data_size = eq->readout((char *) (pevent + 1), -1);
01697 } else {
01698
01699 pevent->data_size = eq->readout((char *) (pevent + 1), 0);
01700
01701
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
01721 if (pevent->data_size)
01722 eq->serial_number++;
01723 }
01724
01725
01726 if (pevent->data_size) {
01727
01728
01729 if (eq_info->eq_type & EQ_FRAGMENTED) {
01730
01731 pfragment = event_buffer;
01732
01733
01734 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01735 pfragment->event_id |= EVENTID_FRAG1;
01736
01737
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);
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
01754 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01755 pfragment->event_id |= EVENTID_FRAG;
01756
01757
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
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
01778 rpc_flush_event();
01779 }
01780 }
01781
01782 } else {
01783
01784
01785
01786
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
01817 if (actual_millitime - readout_start > (DWORD) eq_info->period)
01818 break;
01819
01820
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 }
01829
01830
01831
01832 INT scheduler(void)
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
01855
01856 last_time_rate = ss_millitime();
01857
01858 do {
01859 actual_millitime = ss_millitime();
01860 actual_time = ss_time();
01861
01862
01863 for (idx = 0;; idx++) {
01864 eq = &equipment[idx];
01865 eq_info = &eq->info;
01866
01867
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
01878 if ((eq_info->eq_type & EQ_SLOW) && eq->status == FE_SUCCESS) {
01879
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
01898 if ((eq_info->eq_type & EQ_PERIODIC) || (eq_info->eq_type & EQ_SLOW)) {
01899 if (eq_info->period == 0)
01900 continue;
01901
01902
01903 if (actual_millitime - eq->last_called >= (DWORD) eq_info->period) {
01904
01905 old_flag = readout_enabled();
01906 if (old_flag && lockout_readout_thread)
01907 readout_enable(FALSE);
01908
01909
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
01918 if (old_flag)
01919 readout_enable(TRUE);
01920 }
01921 }
01922
01923
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
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
01943
01944
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
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
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
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
01984 pevent->data_size = eq->readout((char *) (pevent + 1), -1);
01985 } else {
01986
01987 pevent->data_size = eq->readout((char *) (pevent + 1), 0);
01988
01989
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
02009 if (pevent->data_size)
02010 eq->serial_number++;
02011 }
02012
02013
02014 if (pevent->data_size) {
02015
02016
02017 if (eq_info->eq_type & EQ_FRAGMENTED) {
02018
02019 pfragment = event_buffer;
02020
02021
02022 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
02023 pfragment->event_id |= EVENTID_FRAG1;
02024
02025
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);
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
02042 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
02043 pfragment->event_id |= EVENTID_FRAG;
02044
02045
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
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
02066 rpc_flush_event();
02067 }
02068 }
02069
02070 } else {
02071
02072
02073
02074
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
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
02111 if (actual_millitime - readout_start > (DWORD) eq_info->period)
02112 break;
02113
02114
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
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
02134 if (actual_millitime - readout_start > (DWORD) eq_info->period)
02135 break;
02136
02137
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
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
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
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
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;
02171
02172
02173 force_update = TRUE;
02174 }
02175 }
02176
02177
02178 mfe_error_check();
02179
02180
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
02190 cm_check_deferred_transition();
02191
02192
02193 if (manual_trigger_event_id) {
02194 old_flag = readout_enabled();
02195 if (old_flag && lockout_readout_thread)
02196 readout_enable(FALSE);
02197
02198
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
02214 if (old_flag)
02215 readout_enable(TRUE);
02216 }
02217
02218
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
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
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
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
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
02306 if (actual_millitime - last_time_flush > 1000) {
02307 last_time_flush = actual_millitime;
02308
02309
02310
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
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
02347 if (auto_restart > 0 && ss_time() > auto_restart) {
02348
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
02376 if ((run_state == STATE_RUNNING && interrupt_eq == NULL) || slowcont_eq) {
02377
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
02385
02386 status = cm_yield(100);
02387
02388
02389 if (fe_stop)
02390 status = RPC_SHUTDOWN;
02391
02392
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 }
02402
02403
02404
02405 INT get_frontend_index()
02406 {
02407 return frontend_index;
02408 }
02409
02410
02411
02412 void (*mfe_error_dispatcher)(const char *) = NULL;
02413
02414 #define MFE_ERROR_SIZE 10
02415 char mfe_error_str[MFE_ERROR_SIZE][256];
02416 int mfe_error_r, mfe_error_w;
02417 MUTEX_T *mfe_mutex = NULL;
02418
02419 void mfe_set_error(void (*dispatcher) (const char *))
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 }
02434
02435 void mfe_error(const char *error)
02436
02437
02438 {
02439
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 }
02445
02446 void mfe_error_check(void)
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 }
02458
02459
02460
02461 #ifdef OS_VXWORKS
02462 int mfe(char *ahost_name, char *aexp_name, BOOL adebug)
02463 #else
02464 int main(int argc, char *argv[])
02465 #endif
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
02492 cm_get_environment(host_name, sizeof(host_name), exp_name, sizeof(exp_name));
02493
02494
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
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
02534
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
02541 event_buffer_size = 0.2 * memFindMax();
02542 #endif
02543
02544
02545 if (getenv("MIDAS_FRONTEND_INDEX"))
02546 frontend_index = atoi(getenv("MIDAS_FRONTEND_INDEX"));
02547
02548
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
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
02567 set_rate_period(3000);
02568
02569
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
02587 ss_sleep(5000);
02588 return 1;
02589 }
02590
02591 if (display_period)
02592 printf("OK\n");
02593
02594
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
02602 cm_cleanup(full_frontend_name, FALSE);
02603
02604
02605 status = cm_shutdown(full_frontend_name, FALSE);
02606 if (status == CM_SUCCESS && display_period) {
02607 printf("Previous frontend stopped\n");
02608
02609
02610 ss_sleep(3000);
02611 }
02612
02613
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
02622 ss_sleep(5000);
02623 return 1;
02624 }
02625
02626 cm_get_experiment_database(&hDB, &status);
02627
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
02642 if (debug)
02643 cm_set_watchdog_params(FALSE, 0);
02644
02645
02646 rpc_set_option(-1, RPC_OTIMEOUT, 120000);
02647
02648
02649 if (display_period)
02650 cm_set_msg_print(MT_ALL, MT_ALL, message_print);
02651
02652
02653 if (register_equipment() != SUCCESS) {
02654 if (display_period)
02655 printf("\n");
02656 cm_disconnect_experiment();
02657
02658
02659 ss_sleep(5000);
02660 return 1;
02661 }
02662
02663
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
02672 ss_sleep(5000);
02673 return 1;
02674 }
02675
02676 initialize_equipment();
02677
02678 if (display_period)
02679 printf("OK\n");
02680
02681
02682 if (display_period) {
02683 ss_sleep(300);
02684 display(TRUE);
02685 }
02686
02687
02688 if (run_state == STATE_RUNNING)
02689 readout_enable(TRUE);
02690
02691
02692 ss_getchar(0);
02693
02694
02695 status = scheduler();
02696
02697
02698 stop_all_threads = 1;
02699 rb_set_nonblocking();
02700 while (readout_thread_active)
02701 ss_sleep(100);
02702
02703
02704 ss_getchar(TRUE);
02705
02706
02707 if (interrupt_eq) {
02708 interrupt_configure(CMD_INTERRUPT_DISABLE, 0, 0);
02709 interrupt_configure(CMD_INTERRUPT_DETACH, 0, 0);
02710 }
02711
02712
02713 if (interrupt_eq != NULL)
02714 interrupt_configure(CMD_INTERRUPT_DETACH, interrupt_eq->info.source, 0);
02715
02716
02717 frontend_exit();
02718
02719
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
02728 if (equipment[i].driver[j].name[0] && equipment[i].status == FE_SUCCESS)
02729 equipment[i].cd(CMD_STOP, &equipment[i]);
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]);
02734
02735 free(n_events);
02736
02737
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 }
02753
02754 #ifdef LINK_TEST
02755 char* frontend_name;
02756 char* frontend_file_name;
02757 BOOL frontend_call_loop;
02758 int event_buffer_size;
02759 int max_event_size;
02760 int max_event_size_frag;
02761 int display_period;
02762 EQUIPMENT equipment[1];
02763 int frontend_init() { return 0; };
02764 int frontend_exit() { return 0; };
02765 int begin_of_run(int runno,char* errstr) { return 0; };
02766 int end_of_run(int runno,char* errstr) { return 0; };
02767 int pause_run(int runno,char* errstr) { return 0; };
02768 int resume_run(int runno,char* errstr) { return 0; };
02769 int interrupt_configure(INT cmd, INT source, POINTER_T adr) { return 0; };
02770 int frontend_loop() { return 0; };
02771 int poll_event(INT source, INT count, BOOL test) { return 0; };
02772 #endif