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 #ifdef YBOS_SUPPORT
00020 #include "ybos.h"
00021 #endif
00022
00023
00024
00025
00026
00027 extern char *frontend_name;
00028 extern char *frontend_file_name;
00029 extern BOOL frontend_call_loop;
00030 extern INT max_event_size;
00031 extern INT max_event_size_frag;
00032 extern INT event_buffer_size;
00033 extern INT display_period;
00034 extern INT frontend_init(void);
00035 extern INT frontend_exit(void);
00036 extern INT frontend_loop(void);
00037 extern INT begin_of_run(INT run_number, char *error);
00038 extern INT end_of_run(INT run_number, char *error);
00039 extern INT pause_run(INT run_number, char *error);
00040 extern INT resume_run(INT run_number, char *error);
00041 extern INT poll_event(INT source, INT count, BOOL test);
00042 extern INT interrupt_configure(INT cmd, INT source, POINTER_T adr);
00043
00044
00045
00046
00047
00048 INT rpc_mode = 1;
00049
00050 #define SERVER_CACHE_SIZE 100000
00051
00052 #define ODB_UPDATE_TIME 1000
00053
00054 #define DEFAULT_FE_TIMEOUT 60000
00055
00056 INT run_state;
00057 INT run_number;
00058 DWORD actual_time;
00059 DWORD actual_millitime;
00060
00061 char host_name[HOST_NAME_LENGTH];
00062 char exp_name[NAME_LENGTH];
00063 char full_frontend_name[256];
00064
00065 INT max_bytes_per_sec;
00066 INT optimize = 0;
00067 INT fe_stop = 0;
00068 BOOL debug;
00069 DWORD auto_restart = 0;
00070 INT manual_trigger_event_id = 0;
00071 INT frontend_index = -1;
00072
00073 HNDLE hDB;
00074
00075 #ifdef YBOS_SUPPORT
00076 struct {
00077 DWORD ybos_type;
00078 DWORD odb_type;
00079 INT tsize;
00080 } id_map[] = {
00081 {
00082 A1_BKTYPE, TID_CHAR, 1}, {
00083 I1_BKTYPE, TID_BYTE, 1}, {
00084 I2_BKTYPE, TID_WORD, 2}, {
00085 I4_BKTYPE, TID_DWORD, 4}, {
00086 F4_BKTYPE, TID_FLOAT, 4}, {
00087 D8_BKTYPE, TID_DOUBLE, 8}, {
00088 0, 0, 0}
00089 };
00090 #endif
00091
00092 extern EQUIPMENT equipment[];
00093
00094 EQUIPMENT *interrupt_eq = NULL;
00095 EQUIPMENT *multithread_eq = NULL;
00096 BOOL slowcont_eq = FALSE;
00097 void *event_buffer;
00098 void *frag_buffer = NULL;
00099
00100
00101 int rbh1=0, rbh2=0, rbh1_next=0, rbh2_next=0;
00102 volatile int stop_all_threads = 0;
00103 int readout_thread(void *param);
00104 volatile int readout_thread_active = 0;
00105
00106 int send_event(INT idx);
00107 int receive_trigger_event(EQUIPMENT *eq);
00108 void send_all_periodic_events(INT transition);
00109 void interrupt_routine(void);
00110 void readout_enable(BOOL flag);
00111 int readout_enabled(void);
00112 void display(BOOL bInit);
00113 BOOL logger_root();
00114 INT check_polled_events(void);
00115
00116
00117
00118 #define EQUIPMENT_COMMON_STR "\
00119 Event ID = WORD : 0\n\
00120 Trigger mask = WORD : 0\n\
00121 Buffer = STRING : [32] SYSTEM\n\
00122 Type = INT : 0\n\
00123 Source = INT : 0\n\
00124 Format = STRING : [8] FIXED\n\
00125 Enabled = BOOL : 0\n\
00126 Read on = INT : 0\n\
00127 Period = INT : 0\n\
00128 Event limit = DOUBLE : 0\n\
00129 Num subevents = DWORD : 0\n\
00130 Log history = INT : 0\n\
00131 Frontend host = STRING : [32] \n\
00132 Frontend name = STRING : [32] \n\
00133 Frontend file name = STRING : [256] \n\
00134 "
00135
00136 #define EQUIPMENT_STATISTICS_STR "\
00137 Events sent = DOUBLE : 0\n\
00138 Events per sec. = DOUBLE : 0\n\
00139 kBytes per sec. = DOUBLE : 0\n\
00140 "
00141
00142
00143
00144
00145
00146 INT tr_start(INT rn, char *error)
00147 {
00148 INT i, status;
00149
00150
00151 for (i = 0; equipment[i].name[0]; i++) {
00152 equipment[i].serial_number = 0;
00153 equipment[i].subevent_number = 0;
00154 equipment[i].stats.events_sent = 0;
00155 equipment[i].odb_in = equipment[i].odb_out = 0;
00156 }
00157
00158 status = begin_of_run(rn, error);
00159
00160 if (status == CM_SUCCESS) {
00161 run_state = STATE_RUNNING;
00162 run_number = rn;
00163
00164 send_all_periodic_events(TR_START);
00165
00166 if (display_period) {
00167 ss_printf(14, 2, "Running ");
00168 ss_printf(36, 2, "%d", rn);
00169 }
00170
00171
00172 readout_enable(TRUE);
00173 }
00174
00175 return status;
00176 }
00177
00178
00179
00180 INT tr_stop(INT rn, char *error)
00181 {
00182 INT status, i;
00183 EQUIPMENT *eq;
00184
00185
00186 readout_enable(FALSE);
00187
00188 status = end_of_run(rn, error);
00189
00190
00191 if ((i = check_polled_events()) > 0) {
00192
00193 }
00194
00195 if (status == CM_SUCCESS) {
00196
00197 if (run_state != STATE_STOPPED)
00198 send_all_periodic_events(TR_STOP);
00199
00200 run_state = STATE_STOPPED;
00201 run_number = rn;
00202
00203 if (display_period)
00204 ss_printf(14, 2, "Stopped ");
00205 } else
00206 readout_enable(TRUE);
00207
00208 for (i = 0; equipment[i].name[0]; i++)
00209
00210 if (equipment[i].info.eq_type & (EQ_MULTITHREAD | EQ_INTERRUPT)) {
00211 while (receive_trigger_event(equipment+i) > 0);
00212 }
00213
00214
00215 rpc_flush_event();
00216 if (equipment[i].buffer_handle) {
00217 INT err = bm_flush_cache(equipment[i].buffer_handle, SYNC);
00218 if (err != BM_SUCCESS) {
00219 cm_msg(MERROR, "tr_stop", "bm_flush_cache(SYNC) error %d", err);
00220 return err;
00221 }
00222 }
00223
00224
00225 for (i = 0; equipment[i].name[0]; i++) {
00226 eq = &equipment[i];
00227 eq->stats.events_sent += eq->events_sent;
00228 eq->bytes_sent = 0;
00229 eq->events_sent = 0;
00230 }
00231
00232 db_send_changed_records();
00233
00234 return status;
00235 }
00236
00237
00238
00239 INT tr_pause(INT rn, char *error)
00240 {
00241 INT status;
00242
00243
00244 readout_enable(FALSE);
00245
00246 status = pause_run(rn, error);
00247
00248 if (status == CM_SUCCESS) {
00249 run_state = STATE_PAUSED;
00250 run_number = rn;
00251
00252 send_all_periodic_events(TR_PAUSE);
00253
00254 if (display_period)
00255 ss_printf(14, 2, "Paused ");
00256 } else
00257 readout_enable(TRUE);
00258
00259 return status;
00260 }
00261
00262
00263
00264 INT tr_resume(INT rn, char *error)
00265 {
00266 INT status;
00267
00268 status = resume_run(rn, error);
00269
00270 if (status == CM_SUCCESS) {
00271 run_state = STATE_RUNNING;
00272 run_number = rn;
00273
00274 send_all_periodic_events(TR_RESUME);
00275
00276 if (display_period)
00277 ss_printf(14, 2, "Running ");
00278
00279
00280 readout_enable(TRUE);
00281 }
00282
00283 return status;
00284 }
00285
00286
00287
00288 INT manual_trigger(INT idx, void *prpc_param[])
00289 {
00290 int i;
00291
00292 i = idx;
00293 manual_trigger_event_id = CWORD(0);
00294 return SUCCESS;
00295 }
00296
00297
00298
00299 int sc_thread(void *info)
00300 {
00301 DEVICE_DRIVER *device_drv = info;
00302 int i, status, cmd;
00303 int current_channel = 0;
00304 int current_priority_channel = 0;
00305 float value;
00306 int *last_update;
00307 unsigned int current_time;
00308
00309 last_update = calloc(device_drv->channels, sizeof(int));
00310
00311 do {
00312
00313 for (cmd = CMD_GET_FIRST; cmd <= CMD_GET_LAST; cmd++) {
00314 status = device_drv->dd(cmd, device_drv->dd_info, current_channel, &value);
00315
00316 ss_mutex_wait_for(device_drv->mutex, 1000);
00317 device_drv->mt_buffer->channel[current_channel].variable[cmd] = value;
00318 device_drv->mt_buffer->status = status;
00319 ss_mutex_release(device_drv->mutex);
00320
00321
00322 }
00323
00324
00325 current_channel = (current_channel + 1) % device_drv->channels;
00326
00327
00328 current_time = ss_millitime();
00329 i = (current_priority_channel + 1) % device_drv->channels;
00330 while (!(current_time - last_update[i] < 10000)) {
00331 i = (i + 1) % device_drv->channels;
00332 if (i == current_priority_channel) {
00333
00334 break;
00335 }
00336 }
00337
00338
00339 if (current_time - last_update[i] < 10000) {
00340 current_priority_channel = i;
00341
00342 for (cmd = CMD_GET_FIRST; cmd <= CMD_GET_LAST; cmd++) {
00343 status = device_drv->dd(cmd, device_drv->dd_info, i, &value);
00344
00345 ss_mutex_wait_for(device_drv->mutex, 1000);
00346 device_drv->mt_buffer->channel[i].variable[cmd] = value;
00347 device_drv->mt_buffer->status = status;
00348 ss_mutex_release(device_drv->mutex);
00349 }
00350 }
00351
00352
00353 for (i = 0; i < device_drv->channels; i++) {
00354
00355 for (cmd = CMD_SET_FIRST; cmd <= CMD_SET_LAST; cmd++) {
00356 if (!ss_isnan(device_drv->mt_buffer->channel[i].variable[cmd])) {
00357 ss_mutex_wait_for(device_drv->mutex, 1000);
00358 value = device_drv->mt_buffer->channel[i].variable[cmd];
00359 device_drv->mt_buffer->channel[i].variable[cmd] = (float) ss_nan();
00360 device_drv->mt_buffer->status = status;
00361 ss_mutex_release(device_drv->mutex);
00362
00363 status = device_drv->dd(cmd, device_drv->dd_info, i, value);
00364 last_update[i] = ss_millitime();
00365 }
00366 }
00367 }
00368
00369 } while (device_drv->stop_thread == 0);
00370
00371 free(last_update);
00372
00373
00374 device_drv->stop_thread = 2;
00375
00376 return SUCCESS;
00377 }
00378
00379
00380
00381 INT device_driver(DEVICE_DRIVER * device_drv, INT cmd, ...)
00382 {
00383 va_list argptr;
00384 HNDLE hKey;
00385 INT channel, status, i, j;
00386 float value, *pvalue;
00387 char *name, *label, str[256];
00388
00389 va_start(argptr, cmd);
00390 status = FE_SUCCESS;
00391
00392 switch (cmd) {
00393 case CMD_INIT:
00394 hKey = va_arg(argptr, HNDLE);
00395
00396 if (device_drv->flags & DF_MULTITHREAD) {
00397 status = device_drv->dd(CMD_INIT, hKey, &device_drv->dd_info,
00398 device_drv->channels, device_drv->flags,
00399 device_drv->bd);
00400
00401 if (status == FE_SUCCESS && (device_drv->flags & DF_MULTITHREAD)) {
00402
00403 device_drv->mt_buffer = (DD_MT_BUFFER *) calloc(1, sizeof(DD_MT_BUFFER));
00404 device_drv->mt_buffer->n_channels = device_drv->channels;
00405 device_drv->mt_buffer->channel = (DD_MT_CHANNEL *) calloc(device_drv->channels, sizeof(DD_MT_CHANNEL));
00406 assert(device_drv->mt_buffer->channel);
00407
00408
00409 for (i=0 ; i<device_drv->channels ; i++)
00410 for (j=CMD_SET_FIRST ; j<=CMD_SET_LAST ; j++)
00411 device_drv->mt_buffer->channel[i].variable[j] = (float)ss_nan();
00412
00413
00414 for (i = 0; i < device_drv->channels; i++)
00415 device_drv->dd(CMD_GET_LABEL, device_drv->dd_info, i,
00416 device_drv->mt_buffer->channel[i].label);
00417
00418
00419 sprintf(str, "DD_%s", device_drv->name);
00420 status = ss_mutex_create(str, &device_drv->mutex);
00421 if (status != SS_CREATED && status != SS_SUCCESS)
00422 return FE_ERR_DRIVER;
00423 status = FE_SUCCESS;
00424 }
00425 } else {
00426 status = device_drv->dd(CMD_INIT, hKey, &device_drv->dd_info,
00427 device_drv->channels, device_drv->flags,
00428 device_drv->bd);
00429 }
00430 break;
00431
00432 case CMD_START:
00433 if (device_drv->flags & DF_MULTITHREAD && device_drv->mt_buffer != NULL) {
00434
00435 device_drv->mt_buffer->thread_id = ss_thread_create(sc_thread, device_drv);
00436 }
00437 break;
00438
00439 case CMD_STOP:
00440 if (device_drv->flags & DF_MULTITHREAD && device_drv->mt_buffer != NULL) {
00441 device_drv->stop_thread = 1;
00442
00443 for (i = 0; i < 1000; i++) {
00444 if (device_drv->stop_thread == 2)
00445 break;
00446 ss_sleep(10);
00447 }
00448
00449
00450 if (i == 1000)
00451 ss_thread_kill(device_drv->mt_buffer->thread_id);
00452
00453 ss_mutex_delete(device_drv->mutex, TRUE);
00454 free(device_drv->mt_buffer->channel);
00455 free(device_drv->mt_buffer);
00456 }
00457 break;
00458
00459 case CMD_EXIT:
00460 status = device_drv->dd(CMD_EXIT, device_drv->dd_info);
00461 break;
00462
00463 case CMD_SET_LABEL:
00464 channel = va_arg(argptr, INT);
00465 label = va_arg(argptr, char *);
00466 status = device_drv->dd(CMD_SET_LABEL, device_drv->dd_info, channel, label);
00467 break;
00468
00469 case CMD_GET_LABEL:
00470 channel = va_arg(argptr, INT);
00471 name = va_arg(argptr, char *);
00472 status = device_drv->dd(CMD_GET_LABEL, device_drv->dd_info, channel, name);
00473 break;
00474
00475 default:
00476
00477 if (cmd >= CMD_SET_FIRST && cmd <= CMD_SET_LAST) {
00478
00479
00480 channel = va_arg(argptr, INT);
00481 value = (float) va_arg(argptr, double);
00482 if (device_drv->flags & DF_MULTITHREAD) {
00483 ss_mutex_wait_for(device_drv->mutex, 1000);
00484 device_drv->mt_buffer->channel[channel].variable[cmd] = value;
00485 status = device_drv->mt_buffer->status;
00486 ss_mutex_release(device_drv->mutex);
00487 } else {
00488 status = device_drv->dd(cmd, device_drv->dd_info, channel, value);
00489 }
00490
00491 } else if (cmd >= CMD_GET_FIRST && cmd <= CMD_GET_LAST) {
00492
00493
00494 channel = va_arg(argptr, INT);
00495 pvalue = va_arg(argptr, float *);
00496 if (device_drv->flags & DF_MULTITHREAD) {
00497 ss_mutex_wait_for(device_drv->mutex, 1000);
00498 *pvalue = device_drv->mt_buffer->channel[channel].variable[cmd];
00499 status = device_drv->mt_buffer->status;
00500 ss_mutex_release(device_drv->mutex);
00501 } else
00502 status = device_drv->dd(cmd, device_drv->dd_info, channel, pvalue);
00503
00504 } else {
00505
00506
00507 channel = va_arg(argptr, INT);
00508 pvalue = va_arg(argptr, float *);
00509 status = device_drv->dd(cmd, device_drv->dd_info, channel, pvalue);
00510 }
00511
00512 break;
00513 }
00514
00515 va_end(argptr);
00516 return status;
00517 }
00518
00519
00520
00521 INT register_equipment(void)
00522 {
00523 INT idx, count, size, status, i, j, k, n;
00524 char str[256];
00525 EQUIPMENT_INFO *eq_info;
00526 EQUIPMENT_STATS *eq_stats;
00527 DWORD start_time, delta_time;
00528 HNDLE hKey;
00529 BOOL manual_trig_flag = FALSE;
00530 BANK_LIST *bank_list;
00531 DWORD dummy;
00532
00533
00534 size = sizeof(run_state);
00535 run_state = STATE_STOPPED;
00536 db_get_value(hDB, 0, "/Runinfo/State", &run_state, &size, TID_INT, TRUE);
00537 size = sizeof(run_number);
00538 run_number = 1;
00539 status =
00540 db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
00541 assert(status == SUCCESS);
00542
00543
00544 for (idx = 0; equipment[idx].name[0]; idx++) {
00545 eq_info = &equipment[idx].info;
00546 eq_stats = &equipment[idx].stats;
00547
00548 if (eq_info->event_id == 0) {
00549 printf("\nEvent ID 0 for %s not allowed\n", equipment[idx].name);
00550 cm_disconnect_experiment();
00551 ss_sleep(5000);
00552 exit(0);
00553 }
00554
00555
00556 equipment[idx].status = FE_SUCCESS;
00557
00558
00559 if (frontend_index != -1) {
00560
00561 if (strchr(equipment[idx].name, '%')) {
00562 strcpy(str, equipment[idx].name);
00563 sprintf(equipment[idx].name, str, frontend_index);
00564 }
00565
00566
00567 if (strchr(eq_info->buffer, '%')) {
00568 strcpy(str, eq_info->buffer);
00569 sprintf(eq_info->buffer, str, frontend_index);
00570 }
00571 } else {
00572
00573 if (strchr(equipment[idx].name, '%'))
00574 *strchr(equipment[idx].name, '%') = 0;
00575 if (strchr(eq_info->buffer, '%'))
00576 *strchr(eq_info->buffer, '%') = 0;
00577 }
00578
00579 sprintf(str, "/Equipment/%s/Common", equipment[idx].name);
00580
00581
00582 if (eq_info->eq_type != EQ_SLOW) {
00583 db_find_key(hDB, 0, str, &hKey);
00584 size = sizeof(double);
00585 if (hKey)
00586 db_get_value(hDB, hKey, "Event limit", &eq_info->event_limit, &size,
00587 TID_DOUBLE, TRUE);
00588 }
00589
00590
00591 status = db_check_record(hDB, 0, str, EQUIPMENT_COMMON_STR, FALSE);
00592 if (status == DB_NO_KEY || status == DB_STRUCT_MISMATCH) {
00593 db_create_record(hDB, 0, str, EQUIPMENT_COMMON_STR);
00594 db_find_key(hDB, 0, str, &hKey);
00595 db_set_record(hDB, hKey, eq_info, sizeof(EQUIPMENT_INFO), 0);
00596 } else if (status != DB_SUCCESS) {
00597 printf("Cannot check equipment record, status = %d\n", status);
00598 ss_sleep(3000);
00599 }
00600 db_find_key(hDB, 0, str, &hKey);
00601 assert(hKey);
00602
00603
00604 db_set_value(hDB, hKey, "Event ID", &eq_info->event_id, sizeof(WORD), 1, TID_WORD);
00605 db_set_value(hDB, hKey, "Type", &eq_info->eq_type, sizeof(INT), 1, TID_INT);
00606 db_set_value(hDB, hKey, "Source", &eq_info->source, sizeof(INT), 1, TID_INT);
00607
00608
00609 db_open_record(hDB, hKey, eq_info, sizeof(EQUIPMENT_INFO), MODE_READ, NULL, NULL);
00610
00611 if (equal_ustring(eq_info->format, "YBOS"))
00612 equipment[idx].format = FORMAT_YBOS;
00613 else if (equal_ustring(eq_info->format, "FIXED"))
00614 equipment[idx].format = FORMAT_FIXED;
00615 else
00616 equipment[idx].format = FORMAT_MIDAS;
00617
00618 gethostname(eq_info->frontend_host, sizeof(eq_info->frontend_host));
00619 strcpy(eq_info->frontend_name, full_frontend_name);
00620 strcpy(eq_info->frontend_file_name, frontend_file_name);
00621
00622
00623 db_set_record(hDB, hKey, eq_info, sizeof(EQUIPMENT_INFO), 0);
00624
00625
00626
00627 sprintf(str, "/Equipment/%s/Variables", equipment[idx].name);
00628 if (equipment[idx].event_descrip) {
00629 if (equipment[idx].format == FORMAT_FIXED)
00630 db_check_record(hDB, 0, str, (char *) equipment[idx].event_descrip, TRUE);
00631 else {
00632
00633 bank_list = (BANK_LIST *) equipment[idx].event_descrip;
00634
00635 for (; bank_list->name[0]; bank_list++) {
00636
00637
00638
00639
00640
00641 if (bank_list->type == TID_STRUCT) {
00642 sprintf(str, "/Equipment/%s/Variables/%s", equipment[idx].name,
00643 bank_list->name);
00644 status =
00645 db_check_record(hDB, 0, str, strcomb(bank_list->init_str), TRUE);
00646 if (status != DB_SUCCESS) {
00647 printf("Cannot check/create record \"%s\", status = %d\n", str,
00648 status);
00649 ss_sleep(3000);
00650 }
00651 } else {
00652 sprintf(str, "/Equipment/%s/Variables/%s", equipment[idx].name,
00653 bank_list->name);
00654 dummy = 0;
00655 db_set_value(hDB, 0, str, &dummy, rpc_tid_size(bank_list->type), 1,
00656 bank_list->type);
00657 }
00658 }
00659 }
00660 } else
00661 db_create_key(hDB, 0, str, TID_KEY);
00662
00663 sprintf(str, "/Equipment/%s/Variables", equipment[idx].name);
00664 db_find_key(hDB, 0, str, &hKey);
00665 equipment[idx].hkey_variables = hKey;
00666
00667
00668
00669 sprintf(str, "/Equipment/%s/Statistics", equipment[idx].name);
00670
00671 status = db_check_record(hDB, 0, str, EQUIPMENT_STATISTICS_STR, TRUE);
00672 if (status != DB_SUCCESS) {
00673 printf("Cannot create/check statistics record \'%s\', error %d\n", str, status);
00674 ss_sleep(3000);
00675 }
00676
00677 status = db_find_key(hDB, 0, str, &hKey);
00678 if (status != DB_SUCCESS) {
00679 printf("Cannot find statistics record \'%s\', error %d\n", str, status);
00680 ss_sleep(3000);
00681 }
00682
00683 eq_stats->events_sent = 0;
00684 eq_stats->events_per_sec = 0;
00685 eq_stats->kbytes_per_sec = 0;
00686
00687
00688 status =
00689 db_open_record(hDB, hKey, eq_stats, sizeof(EQUIPMENT_STATS), MODE_WRITE, NULL,
00690 NULL);
00691 if (status != DB_SUCCESS) {
00692 cm_msg(MERROR, "register_equipment",
00693 "Cannot open statistics record \'%s\', error %d. Probably other FE is using it",
00694 str, status);
00695 ss_sleep(3000);
00696 }
00697
00698
00699
00700
00701 if (eq_info->eq_type & EQ_FRAGMENTED) {
00702 if (frag_buffer == NULL)
00703 frag_buffer = malloc(max_event_size_frag);
00704
00705 if (frag_buffer == NULL) {
00706 cm_msg(MERROR, "register_equipment",
00707 "Not enough memory to allocate buffer for fragmented events");
00708 return SS_NO_MEMORY;
00709 }
00710 }
00711
00712 if (eq_info->buffer[0]) {
00713 status =
00714 bm_open_buffer(eq_info->buffer, 2*MAX_EVENT_SIZE,
00715 &equipment[idx].buffer_handle);
00716 if (status != BM_SUCCESS && status != BM_CREATED) {
00717 cm_msg(MERROR, "register_equipment",
00718 "Cannot open event buffer \"%s\" size %d, bm_open_buffer() status %d", eq_info->buffer, 2*MAX_EVENT_SIZE, status);
00719 return 0;
00720 }
00721
00722
00723 bm_set_cache_size(equipment[idx].buffer_handle, 0, SERVER_CACHE_SIZE);
00724 } else
00725 equipment[idx].buffer_handle = 0;
00726
00727
00728
00729 if (eq_info->eq_type & (EQ_POLLED | EQ_MULTITHREAD)) {
00730 if (eq_info->eq_type & EQ_INTERRUPT) {
00731 if (eq_info->eq_type & EQ_POLLED)
00732 cm_msg(MERROR, "register_equipment",
00733 "Equipment \"%s\" cannot be of type EQ_INTERRUPT and EQ_POLLED at the same time",
00734 equipment[idx].name);
00735 else
00736 cm_msg(MERROR, "register_equipment",
00737 "Equipment \"%s\" cannot be of type EQ_INTERRUPT and EQ_MULTITHREAD at the same time",
00738 equipment[idx].name);
00739 return 0;
00740 }
00741
00742 if (display_period)
00743 printf("\nCalibrating");
00744
00745 count = 1;
00746 do {
00747 if (display_period)
00748 printf(".");
00749
00750 start_time = ss_millitime();
00751
00752 poll_event(equipment[idx].info.source, count, TRUE);
00753
00754 delta_time = ss_millitime() - start_time;
00755
00756 if (count == 1 && delta_time > eq_info->period * 1.2) {
00757 cm_msg(MERROR, "register_equipment", "Polling routine with count=1 takes %d ms", delta_time);
00758 ss_sleep(3000);
00759 break;
00760 }
00761
00762 if (delta_time > 0)
00763 count = (INT) ((double) count * eq_info->period / delta_time);
00764 else
00765 count *= 100;
00766
00767 } while (delta_time > eq_info->period * 1.2 || delta_time < eq_info->period * 0.8);
00768
00769 equipment[idx].poll_count = count;
00770
00771 if (display_period)
00772 printf("OK\n");
00773 }
00774
00775
00776
00777 if (eq_info->eq_type & EQ_INTERRUPT) {
00778
00779
00780 for (i = 0; equipment[i].name[0]; i++)
00781 if (equipment[i].info.eq_type & EQ_POLLED) {
00782 equipment[idx].status = FE_ERR_DISABLED;
00783 cm_msg(MINFO, "register_equipment",
00784 "Interrupt readout cannot be combined with polled readout");
00785 }
00786
00787 if (equipment[idx].status != FE_ERR_DISABLED) {
00788 if (eq_info->enabled) {
00789 if (interrupt_eq) {
00790 equipment[idx].status = FE_ERR_DISABLED;
00791 cm_msg(MINFO, "register_equipment",
00792 "Defined more than one equipment with interrupt readout");
00793 } else {
00794 interrupt_eq = &equipment[idx];
00795
00796
00797 if (!rbh1) {
00798 rb_create(event_buffer_size, max_event_size, &rbh1);
00799 rbh2 = rbh1;
00800 }
00801
00802
00803 interrupt_configure(CMD_INTERRUPT_ATTACH, eq_info->source,
00804 (POINTER_T) interrupt_routine);
00805 }
00806 } else {
00807 equipment[idx].status = FE_ERR_DISABLED;
00808 cm_msg(MINFO, "register_equipment",
00809 "Equipment %s disabled in file \"frontend.c\"",
00810 equipment[idx].name);
00811 }
00812 }
00813 }
00814
00815
00816
00817 if (eq_info->eq_type & EQ_MULTITHREAD) {
00818
00819
00820 for (i = 0; equipment[i].name[0]; i++)
00821 if (equipment[i].info.eq_type & EQ_POLLED) {
00822 equipment[idx].status = FE_ERR_DISABLED;
00823 cm_msg(MINFO, "register_equipment",
00824 "Multi-threaded readout cannot be combined with polled readout for equipment \'%s\'", equipment[i].name);
00825 }
00826
00827 if (equipment[idx].status != FE_ERR_DISABLED) {
00828 if (eq_info->enabled) {
00829 if (multithread_eq) {
00830 equipment[idx].status = FE_ERR_DISABLED;
00831 cm_msg(MINFO, "register_equipment",
00832 "Defined more than one equipment with multi-threaded readout for equipment \'%s\'", equipment[i].name);
00833 } else {
00834 multithread_eq = &equipment[idx];
00835
00836
00837 if (!rbh1) {
00838 rb_create(event_buffer_size, max_event_size, &rbh1);
00839 rbh2 = rbh1;
00840 }
00841
00842
00843 readout_enable(FALSE);
00844 ss_thread_create(readout_thread, multithread_eq);
00845 }
00846 } else {
00847 equipment[idx].status = FE_ERR_DISABLED;
00848 cm_msg(MINFO, "register_equipment",
00849 "Equipment %s disabled in file \"frontend.c\"",
00850 equipment[idx].name);
00851 }
00852 }
00853 }
00854
00855
00856
00857 if (eq_info->eq_type & EQ_SLOW) {
00858
00859 for (i = 0; equipment[idx].driver[i].name[0]; i++)
00860 for (j = i + 1; equipment[idx].driver[j].name[0]; j++)
00861 if (equal_ustring(equipment[idx].driver[i].name,
00862 equipment[idx].driver[j].name)) {
00863 strcpy(str, equipment[idx].driver[i].name);
00864 for (k = 0, n = 0; equipment[idx].driver[k].name[0]; k++)
00865 if (equal_ustring(str, equipment[idx].driver[k].name))
00866 sprintf(equipment[idx].driver[k].name, "%s_%d", str, n++);
00867
00868 break;
00869 }
00870
00871
00872 if (eq_info->enabled) {
00873 printf("%s:\n", equipment[idx].name);
00874 equipment[idx].status = equipment[idx].cd(CMD_INIT, &equipment[idx]);
00875 } else {
00876 equipment[idx].status = FE_ERR_DISABLED;
00877 cm_msg(MINFO, "register_equipment",
00878 "Equipment %s disabled in ODB", equipment[idx].name);
00879 }
00880
00881
00882 if (equipment[idx].status == FE_SUCCESS)
00883 equipment[idx].cd(CMD_START, &equipment[idx]);
00884
00885
00886 slowcont_eq = TRUE;
00887
00888
00889 if (equipment[idx].status != FE_SUCCESS &&
00890 equipment[idx].status != FE_ERR_DISABLED)
00891 ss_sleep(3000);
00892 }
00893
00894
00895 if (eq_info->eq_type & EQ_MANUAL_TRIG) {
00896 if (!manual_trig_flag)
00897 cm_register_function(RPC_MANUAL_TRIG, manual_trigger);
00898
00899 manual_trig_flag = TRUE;
00900 }
00901 }
00902
00903 if (slowcont_eq)
00904 cm_msg(MINFO, "register_equipment", "Slow control equipment initialized");
00905
00906 return SUCCESS;
00907 }
00908
00909
00910
00911 void update_odb(EVENT_HEADER * pevent, HNDLE hKey, INT format)
00912 {
00913 INT size, i, ni4, tsize, status, n_data;
00914 char *pdata;
00915 char name[5];
00916 BANK_HEADER *pbh;
00917 BANK *pbk;
00918 BANK32 *pbk32;
00919 char *pydata;
00920 DWORD odb_type;
00921 DWORD *pyevt, bkname;
00922 WORD bktype;
00923 HNDLE hKeyRoot, hKeyl;
00924 KEY key;
00925
00926
00927
00928
00929 if (format == FORMAT_FIXED) {
00930 if (db_set_record(hDB, hKey, (char *) (pevent + 1),
00931 pevent->data_size, 0) != DB_SUCCESS)
00932 cm_msg(MERROR, "update_odb", "event #%d size mismatch", pevent->event_id);
00933 } else if (format == FORMAT_MIDAS) {
00934 pbh = (BANK_HEADER *) (pevent + 1);
00935 pbk = NULL;
00936 pbk32 = NULL;
00937 do {
00938
00939 if (bk_is32(pbh)) {
00940 size = bk_iterate32(pbh, &pbk32, &pdata);
00941 if (pbk32 == NULL)
00942 break;
00943 bkname = *((DWORD *) pbk32->name);
00944 bktype = (WORD) pbk32->type;
00945 } else {
00946 size = bk_iterate(pbh, &pbk, &pdata);
00947 if (pbk == NULL)
00948 break;
00949 bkname = *((DWORD *) pbk->name);
00950 bktype = (WORD) pbk->type;
00951 }
00952
00953 n_data = size;
00954 if (rpc_tid_size(bktype & 0xFF))
00955 n_data /= rpc_tid_size(bktype & 0xFF);
00956
00957
00958 *((DWORD *) name) = bkname;
00959 name[4] = 0;
00960
00961 if (bktype == TID_STRUCT) {
00962 status = db_find_key(hDB, hKey, name, &hKeyRoot);
00963 if (status != DB_SUCCESS) {
00964 cm_msg(MERROR, "update_odb",
00965 "please define bank %s in BANK_LIST in frontend.c", name);
00966 continue;
00967 }
00968
00969
00970 for (i = 0;; i++) {
00971 status = db_enum_key(hDB, hKeyRoot, i, &hKeyl);
00972 if (status == DB_NO_MORE_SUBKEYS)
00973 break;
00974
00975 db_get_key(hDB, hKeyl, &key);
00976
00977
00978 if (key.type != TID_STRING && key.type != TID_LINK)
00979 pdata =
00980 (void *) VALIGN(pdata, MIN(ss_get_struct_align(), key.item_size));
00981
00982 status = db_set_data(hDB, hKeyl, pdata, key.item_size * key.num_values,
00983 key.num_values, key.type);
00984 if (status != DB_SUCCESS) {
00985 cm_msg(MERROR, "update_odb", "cannot write %s to ODB", name);
00986 continue;
00987 }
00988
00989
00990 pdata += key.item_size * key.num_values;
00991 }
00992 } else {
00993
00994 if (n_data > 0)
00995 db_set_value(hDB, hKey, name, pdata, size, n_data, bktype & 0xFF);
00996 }
00997
00998 } while (1);
00999 } else if (format == FORMAT_YBOS) {
01000 #ifdef YBOS_SUPPORT
01001 YBOS_BANK_HEADER *pybkh;
01002
01003
01004 pyevt = (DWORD *) (pevent + 1);
01005 pybkh = NULL;
01006 do {
01007
01008 ni4 = ybk_iterate(pyevt, &pybkh, (void *) (&pydata));
01009 if (pybkh == NULL || ni4 == 0)
01010 break;
01011
01012
01013 tsize = odb_type = 0;
01014 for (i = 0; id_map[0].ybos_type > 0; i++) {
01015 if (pybkh->type == id_map[i].ybos_type) {
01016 odb_type = id_map[i].odb_type;
01017 tsize = id_map[i].tsize;
01018 break;
01019 }
01020 }
01021
01022
01023 *((DWORD *) name) = pybkh->name;
01024 name[4] = 0;
01025
01026
01027 if (strncmp(name, "EVID", 4) == 0)
01028 continue;
01029
01030
01031 if (pybkh->type == D8_BKTYPE)
01032 ni4 /= 2;
01033 if (pybkh->type == I2_BKTYPE)
01034 ni4 *= 2;
01035 if (pybkh->type == I1_BKTYPE || pybkh->type == A1_BKTYPE)
01036 ni4 *= 4;
01037
01038
01039 size = ni4 * tsize;
01040 if ((status =
01041 db_set_value(hDB, hKey, name, pydata, size, ni4,
01042 odb_type & 0xFF)) != DB_SUCCESS) {
01043 printf("status:%d odb_type:%d name:%s ni4:%d size:%d tsize:%d\n", status,
01044 odb_type, name, ni4, size, tsize);
01045 for (i = 0; i < 6; i++) {
01046 printf("data: %f\n", *((float *) (pydata)));
01047 pydata += sizeof(float);
01048 }
01049 }
01050 } while (1);
01051 #endif
01052 }
01053
01054 rpc_set_option(-1, RPC_OTRANSPORT, RPC_TCP);
01055 }
01056
01057
01058
01059 int send_event(INT idx)
01060 {
01061 EQUIPMENT_INFO *eq_info;
01062 EVENT_HEADER *pevent, *pfragment;
01063 char *pdata;
01064 unsigned char *pd;
01065 INT i, status;
01066 DWORD sent, size;
01067
01068 eq_info = &equipment[idx].info;
01069
01070
01071 if (eq_info->eq_type & EQ_FRAGMENTED)
01072 pevent = frag_buffer;
01073 else
01074 pevent = (EVENT_HEADER *)event_buffer;
01075
01076
01077 pevent->event_id = eq_info->event_id;
01078 pevent->trigger_mask = eq_info->trigger_mask;
01079 pevent->data_size = 0;
01080 pevent->time_stamp = ss_time();
01081 pevent->serial_number = equipment[idx].serial_number++;
01082
01083 equipment[idx].last_called = ss_millitime();
01084
01085
01086 *((EQUIPMENT **) (pevent + 1)) = &equipment[idx];
01087 pevent->data_size = equipment[idx].readout((char *) (pevent + 1), 0);
01088
01089
01090 if (pevent->data_size) {
01091 if (eq_info->eq_type & EQ_FRAGMENTED) {
01092
01093 if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size_frag) {
01094 cm_msg(MERROR, "send_event",
01095 "Event size %ld larger than maximum size %d for frag. ev.",
01096 (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01097 max_event_size_frag);
01098 return SS_NO_MEMORY;
01099 }
01100
01101
01102 pfragment = event_buffer;
01103
01104
01105 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01106 pfragment->event_id |= EVENTID_FRAG1;
01107
01108
01109 pd = (unsigned char *) (pfragment + 1);
01110 size = pevent->data_size;
01111 for (i = 0; i < 4; i++) {
01112 pd[i] = (unsigned char) (size & 0xFF);
01113 size >>= 8;
01114 }
01115
01116 pfragment->data_size = sizeof(DWORD);
01117
01118 pdata = (char *) (pevent + 1);
01119
01120 for (i = 0, sent = 0; sent < pevent->data_size; i++) {
01121 if (i > 0) {
01122 pfragment = event_buffer;
01123
01124
01125 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01126 pfragment->event_id |= EVENTID_FRAG;
01127
01128
01129 size = pevent->data_size - sent;
01130 if (size > max_event_size - sizeof(EVENT_HEADER))
01131 size = max_event_size - sizeof(EVENT_HEADER);
01132
01133 memcpy(pfragment + 1, pdata, size);
01134 pfragment->data_size = size;
01135 sent += size;
01136 pdata += size;
01137 }
01138
01139
01140 if (equipment[idx].buffer_handle) {
01141 status = rpc_send_event(equipment[idx].buffer_handle, pfragment,
01142 pfragment->data_size + sizeof(EVENT_HEADER), SYNC, rpc_mode);
01143 if (status != RPC_SUCCESS) {
01144 cm_msg(MERROR, "send_event", "rpc_send_event(SYNC) error %d", status);
01145 return status;
01146 }
01147
01148
01149 rpc_flush_event();
01150 }
01151 }
01152
01153 if (equipment[idx].buffer_handle) {
01154
01155 status = bm_flush_cache(equipment[idx].buffer_handle, SYNC);
01156 if (status != BM_SUCCESS) {
01157 cm_msg(MERROR, "send_event", "bm_flush_cache(SYNC) error %d", status);
01158 return status;
01159 }
01160 }
01161 } else {
01162
01163
01164 if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size) {
01165 cm_msg(MERROR, "send_event", "Event size %ld larger than maximum size %d",
01166 (long) (pevent->data_size + sizeof(EVENT_HEADER)), max_event_size);
01167 return SS_NO_MEMORY;
01168 }
01169
01170
01171 if (equipment[idx].buffer_handle) {
01172 status = rpc_send_event(equipment[idx].buffer_handle, pevent,
01173 pevent->data_size + sizeof(EVENT_HEADER), SYNC, rpc_mode);
01174 if (status != BM_SUCCESS) {
01175 cm_msg(MERROR, "send_event", "bm_send_event(SYNC) error %d", status);
01176 return status;
01177 }
01178 rpc_flush_event();
01179 status = bm_flush_cache(equipment[idx].buffer_handle, SYNC);
01180 if (status != BM_SUCCESS) {
01181 cm_msg(MERROR, "send_event", "bm_flush_cache(SYNC) error %d", status);
01182 return status;
01183 }
01184 }
01185
01186
01187
01188 if ((eq_info->read_on & RO_ODB) ||
01189 (eq_info->history > 0 && (eq_info->eq_type & ~EQ_SLOW))) {
01190 update_odb(pevent, equipment[idx].hkey_variables, equipment[idx].format);
01191 equipment[idx].odb_out++;
01192 }
01193 }
01194
01195 equipment[idx].bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
01196 equipment[idx].events_sent++;
01197
01198 equipment[idx].stats.events_sent += equipment[idx].events_sent;
01199 equipment[idx].events_sent = 0;
01200 } else
01201 equipment[idx].serial_number--;
01202
01203 for (i = 0; equipment[i].name[0]; i++)
01204 if (equipment[i].buffer_handle) {
01205 status = bm_flush_cache(equipment[i].buffer_handle, SYNC);
01206 if (status != BM_SUCCESS) {
01207 cm_msg(MERROR, "send_event", "bm_flush_cache(SYNC) error %d", status);
01208 return status;
01209 }
01210 }
01211
01212 return CM_SUCCESS;
01213 }
01214
01215
01216
01217 void send_all_periodic_events(INT transition)
01218 {
01219 EQUIPMENT_INFO *eq_info;
01220 INT i;
01221
01222 for (i = 0; equipment[i].name[0]; i++) {
01223 eq_info = &equipment[i].info;
01224
01225 if (!eq_info->enabled || equipment[i].status != FE_SUCCESS)
01226 continue;
01227
01228 if (transition == TR_START && (eq_info->read_on & RO_BOR) == 0)
01229 continue;
01230 if (transition == TR_STOP && (eq_info->read_on & RO_EOR) == 0)
01231 continue;
01232 if (transition == TR_PAUSE && (eq_info->read_on & RO_PAUSE) == 0)
01233 continue;
01234 if (transition == TR_RESUME && (eq_info->read_on & RO_RESUME) == 0)
01235 continue;
01236
01237 send_event(i);
01238 }
01239 }
01240
01241
01242
01243 static int _readout_enabled_flag = 0;
01244
01245 int readout_enabled()
01246 {
01247 return _readout_enabled_flag;
01248 }
01249
01250 void readout_enable(BOOL flag)
01251 {
01252 _readout_enabled_flag = flag;
01253
01254 if (interrupt_eq) {
01255 if (flag)
01256 interrupt_configure(CMD_INTERRUPT_ENABLE, 0, 0);
01257 else
01258 interrupt_configure(CMD_INTERRUPT_DISABLE, 0, 0);
01259 }
01260
01261 if (multithread_eq) {
01262
01263 if (flag == 0)
01264 while (readout_thread_active);
01265 }
01266 }
01267
01268
01269
01270 void interrupt_routine(void)
01271 {
01272 int status;
01273 EVENT_HEADER *pevent;
01274 void *p;
01275
01276
01277
01278 status = rb_get_wp(rbh1, &p, 100000);
01279
01280 if (status == DB_SUCCESS) {
01281 pevent = (EVENT_HEADER *)p;
01282
01283
01284 pevent->event_id = interrupt_eq->info.event_id;
01285 pevent->trigger_mask = interrupt_eq->info.trigger_mask;
01286 pevent->data_size = 0;
01287 pevent->time_stamp = actual_time;
01288 pevent->serial_number = interrupt_eq->serial_number++;
01289
01290
01291 pevent->data_size = interrupt_eq->readout((char *) (pevent + 1), 0);
01292
01293
01294 if (pevent->data_size) {
01295
01296
01297 rb_increment_wp(rbh1, sizeof(EVENT_HEADER) + pevent->data_size);
01298
01299 } else
01300 interrupt_eq->serial_number--;
01301 }
01302 }
01303
01304
01305
01306 int readout_thread(void *param)
01307 {
01308 int status, source;
01309 EVENT_HEADER *pevent;
01310 void *p;
01311
01312 p = param;
01313 do {
01314
01315 if (rbh1_next)
01316 rbh1 = rbh1_next;
01317
01318 status = rb_get_wp(rbh1, &p, 10000);
01319 if (stop_all_threads)
01320 break;
01321 assert(status == DB_SUCCESS);
01322
01323 if (readout_enabled()) {
01324
01325
01326 readout_thread_active = 1;
01327
01328
01329 if ((source = poll_event(multithread_eq->info.source, multithread_eq->poll_count, FALSE)) > 0) {
01330
01331 if (stop_all_threads)
01332 break;
01333
01334 pevent = (EVENT_HEADER *)p;
01335
01336
01337
01338 *(INT *) (pevent + 1) = source;
01339
01340
01341 pevent->event_id = multithread_eq->info.event_id;
01342 pevent->trigger_mask = multithread_eq->info.trigger_mask;
01343 pevent->data_size = 0;
01344 pevent->time_stamp = actual_time;
01345 pevent->serial_number = multithread_eq->serial_number++;
01346
01347
01348 pevent->data_size = multithread_eq->readout((char *) (pevent + 1), 0);
01349
01350
01351 if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size) {
01352 cm_msg(MERROR, "readout_thread",
01353 "Event size %ld larger than maximum size %d",
01354 (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01355 max_event_size);
01356 assert(FALSE);
01357 }
01358
01359 if (pevent->data_size > 0) {
01360
01361 rb_increment_wp(rbh1, sizeof(EVENT_HEADER) + pevent->data_size);
01362 } else
01363 multithread_eq->serial_number--;
01364 }
01365
01366 readout_thread_active = 0;
01367
01368 } else
01369 ss_sleep(10);
01370
01371 } while (!stop_all_threads);
01372
01373 readout_thread_active = 0;
01374
01375 return 0;
01376 }
01377
01378
01379
01380 int receive_trigger_event(EQUIPMENT *eq)
01381 {
01382 int status;
01383 EVENT_HEADER *prb, *pevent;
01384 void *p;
01385
01386 status = rb_get_rp(rbh2, &p, 10);
01387 prb = (EVENT_HEADER *)p;
01388 if (status == DB_TIMEOUT)
01389 return 0;
01390
01391 pevent = (EVENT_HEADER *)event_buffer;
01392
01393
01394 memcpy(pevent, prb, prb->data_size + sizeof(EVENT_HEADER));
01395
01396
01397 rb_increment_rp(rbh2, sizeof(EVENT_HEADER) + prb->data_size);
01398
01399
01400 if (pevent->data_size) {
01401 if (eq->buffer_handle) {
01402
01403 if (pevent->serial_number == 0)
01404 if (logger_root())
01405 update_odb(pevent, eq->hkey_variables, eq->format);
01406
01407 status = rpc_send_event(eq->buffer_handle, pevent,
01408 pevent->data_size + sizeof(EVENT_HEADER),
01409 SYNC, rpc_mode);
01410
01411 if (status != SUCCESS) {
01412 cm_msg(MERROR, "scheduler", "rpc_send_event error %d", status);
01413 return -1;
01414 }
01415
01416 eq->bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
01417
01418 if (eq->info.num_subevents)
01419 eq->events_sent += eq->subevent_number;
01420 else
01421 eq->events_sent++;
01422 }
01423 }
01424
01425 return prb->data_size;
01426 }
01427
01428
01429
01430 int message_print(const char *msg)
01431 {
01432 char str[160];
01433
01434 memset(str, ' ', 159);
01435 str[159] = 0;
01436
01437 if (msg[0] == '[')
01438 msg = strchr(msg, ']') + 2;
01439
01440 memcpy(str, msg, strlen(msg));
01441 ss_printf(0, 20, str);
01442
01443 return 0;
01444 }
01445
01446
01447
01448 void display(BOOL bInit)
01449 {
01450 INT i, status;
01451 time_t full_time;
01452 char str[30];
01453
01454 if (bInit) {
01455 ss_clear_screen();
01456
01457 if (host_name[0])
01458 strcpy(str, host_name);
01459 else
01460 strcpy(str, "<local>");
01461
01462 ss_printf(0, 0, "%s connected to %s. Press \"!\" to exit", full_frontend_name, str);
01463 ss_printf(0, 1,
01464 "================================================================================");
01465 ss_printf(0, 2, "Run status: %s",
01466 run_state == STATE_STOPPED ? "Stopped" : run_state ==
01467 STATE_RUNNING ? "Running" : "Paused");
01468 ss_printf(25, 2, "Run number %d ", run_number);
01469 ss_printf(0, 3,
01470 "================================================================================");
01471 ss_printf(0, 4,
01472 "Equipment Status Events Events/sec Rate[kB/s] ODB->FE FE->ODB");
01473 ss_printf(0, 5,
01474 "--------------------------------------------------------------------------------");
01475 for (i = 0; equipment[i].name[0]; i++)
01476 ss_printf(0, i + 6, "%s", equipment[i].name);
01477 }
01478
01479
01480 time(&full_time);
01481 strcpy(str, ctime(&full_time) + 11);
01482 str[8] = 0;
01483 ss_printf(72, 0, "%s", str);
01484
01485 for (i = 0; equipment[i].name[0]; i++) {
01486 status = equipment[i].status;
01487
01488 if ((status == 0 || status == FE_SUCCESS) && equipment[i].info.enabled)
01489 ss_printf(14, i + 6, "OK ");
01490 else if (!equipment[i].info.enabled)
01491 ss_printf(14, i + 6, "Disabled ");
01492 else if (status == FE_ERR_ODB)
01493 ss_printf(14, i + 6, "ODB Error");
01494 else if (status == FE_ERR_HW)
01495 ss_printf(14, i + 6, "HW Error ");
01496 else if (status == FE_ERR_DISABLED)
01497 ss_printf(14, i + 6, "Disabled ");
01498 else if (status == FE_ERR_DRIVER)
01499 ss_printf(14, i + 6, "Driver err");
01500 else
01501 ss_printf(14, i + 6, "Unknown ");
01502
01503 if (equipment[i].stats.events_sent > 1E9)
01504 ss_printf(25, i + 6, "%1.3lfG ", equipment[i].stats.events_sent / 1E9);
01505 else if (equipment[i].stats.events_sent > 1E6)
01506 ss_printf(25, i + 6, "%1.3lfM ", equipment[i].stats.events_sent / 1E6);
01507 else
01508 ss_printf(25, i + 6, "%1.0lf ", equipment[i].stats.events_sent);
01509 ss_printf(36, i + 6, "%1.1lf ", equipment[i].stats.events_per_sec);
01510 ss_printf(47, i + 6, "%1.1lf ", equipment[i].stats.kbytes_per_sec);
01511 ss_printf(58, i + 6, "%ld ", equipment[i].odb_in);
01512 ss_printf(69, i + 6, "%ld ", equipment[i].odb_out);
01513 }
01514
01515
01516 ss_printf(0, i + 6, "");
01517 }
01518
01519
01520
01521 BOOL logger_root()
01522
01523 {
01524 int size, i, status;
01525 char str[80];
01526 HNDLE hKeyRoot, hKey;
01527
01528 if (db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot) == DB_SUCCESS) {
01529 for (i = 0;; i++) {
01530 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
01531 if (status == DB_NO_MORE_SUBKEYS)
01532 break;
01533
01534 strcpy(str, "MIDAS");
01535 size = sizeof(str);
01536 db_get_value(hDB, hKey, "Settings/Format", str, &size, TID_STRING, TRUE);
01537
01538 if (equal_ustring(str, "ROOT"))
01539 return TRUE;
01540 }
01541 }
01542
01543 return FALSE;
01544 }
01545
01546
01547
01548 INT check_polled_events(void)
01549 {
01550 EQUIPMENT_INFO *eq_info;
01551 EQUIPMENT *eq;
01552 EVENT_HEADER *pevent, *pfragment;
01553 DWORD readout_start, sent, size;
01554 INT i, idx, source, events_sent, status;
01555 char *pdata;
01556 unsigned char *pd;
01557
01558 events_sent = 0;
01559
01560
01561 for (idx = 0;; idx++) {
01562 eq = &equipment[idx];
01563 eq_info = &eq->info;
01564
01565
01566 if (!eq->name[0])
01567 break;
01568
01569 if (!eq_info->enabled)
01570 continue;
01571
01572 if (eq->status != FE_SUCCESS)
01573 continue;
01574
01575 if ((eq_info->eq_type & EQ_POLLED) == 0)
01576 continue;
01577
01578
01579 readout_start = actual_millitime;
01580 pevent = NULL;
01581
01582 while ((source = poll_event(eq_info->source, eq->poll_count, FALSE)) > 0) {
01583
01584 if (eq_info->eq_type & EQ_FRAGMENTED)
01585 pevent = frag_buffer;
01586 else
01587 pevent = (EVENT_HEADER *)event_buffer;
01588
01589
01590 pevent->event_id = eq_info->event_id;
01591 pevent->trigger_mask = eq_info->trigger_mask;
01592 pevent->data_size = 0;
01593 pevent->time_stamp = actual_time;
01594 pevent->serial_number = eq->serial_number;
01595
01596
01597
01598
01599 *(INT *) (pevent + 1) = source;
01600
01601 if (eq->info.num_subevents) {
01602 eq->subevent_number = 0;
01603 do {
01604 *(INT *) ((char *) (pevent + 1) + pevent->data_size) = source;
01605
01606
01607 size = eq->readout((char *) (pevent + 1), pevent->data_size);
01608 pevent->data_size += size;
01609 if (size > 0) {
01610 if (pevent->data_size + sizeof(EVENT_HEADER) >
01611 (DWORD) max_event_size) {
01612 cm_msg(MERROR, "scheduler",
01613 "Event size %ld larger than maximum size %d",
01614 (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01615 max_event_size);
01616 }
01617
01618 eq->subevent_number++;
01619 eq->serial_number++;
01620 }
01621
01622
01623 do {
01624 source = poll_event(eq_info->source, eq->poll_count, FALSE);
01625
01626 if (source == FALSE) {
01627 actual_millitime = ss_millitime();
01628
01629
01630 if (actual_millitime - readout_start > (DWORD) eq_info->period)
01631 break;
01632 }
01633 } while (source == FALSE);
01634
01635 } while (eq->subevent_number < eq->info.num_subevents && source);
01636
01637
01638 pevent->data_size = eq->readout((char *) (pevent + 1), -1);
01639 } else {
01640
01641 pevent->data_size = eq->readout((char *) (pevent + 1), 0);
01642
01643
01644 if (eq_info->eq_type & EQ_FRAGMENTED) {
01645 if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size_frag) {
01646 cm_msg(MERROR, "send_event",
01647 "Event size %ld larger than maximum size %d for frag. ev.",
01648 (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01649 max_event_size_frag);
01650 assert(FALSE);
01651 }
01652 } else {
01653 if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size) {
01654 cm_msg(MERROR, "scheduler",
01655 "Event size %ld larger than maximum size %d",
01656 (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01657 max_event_size);
01658 assert(FALSE);
01659 }
01660 }
01661
01662
01663 if (pevent->data_size)
01664 eq->serial_number++;
01665 }
01666
01667
01668 if (pevent->data_size) {
01669
01670
01671 if (eq_info->eq_type & EQ_FRAGMENTED) {
01672
01673 pfragment = event_buffer;
01674
01675
01676 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01677 pfragment->event_id |= EVENTID_FRAG1;
01678
01679
01680 pd = (unsigned char *) (pfragment + 1);
01681 size = pevent->data_size;
01682 for (i = 0; i < 4; i++) {
01683 pd[i] = (unsigned char) (size & 0xFF);
01684 size >>= 8;
01685 }
01686
01687 pfragment->data_size = sizeof(DWORD);
01688
01689 pdata = (char *) (pevent + 1);
01690
01691 for (i = 0, sent = 0; sent < pevent->data_size; i++) {
01692 if (i > 0) {
01693 pfragment = event_buffer;
01694
01695
01696 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01697 pfragment->event_id |= EVENTID_FRAG;
01698
01699
01700 size = pevent->data_size - sent;
01701 if (size > max_event_size - sizeof(EVENT_HEADER))
01702 size = max_event_size - sizeof(EVENT_HEADER);
01703
01704 memcpy(pfragment + 1, pdata, size);
01705 pfragment->data_size = size;
01706 sent += size;
01707 pdata += size;
01708 }
01709
01710
01711 if (equipment[idx].buffer_handle) {
01712 status = rpc_send_event(equipment[idx].buffer_handle, pfragment,
01713 pfragment->data_size + sizeof(EVENT_HEADER), SYNC, rpc_mode);
01714 if (status != RPC_SUCCESS) {
01715 cm_msg(MERROR, "send_event", "rpc_send_event(SYNC) error %d", status);
01716 return status;
01717 }
01718
01719
01720 rpc_flush_event();
01721 }
01722 }
01723
01724 } else {
01725
01726
01727
01728
01729 if (pevent->serial_number == 0)
01730 if (logger_root())
01731 update_odb(pevent, eq->hkey_variables, eq->format);
01732
01733 status = rpc_send_event(eq->buffer_handle, pevent,
01734 pevent->data_size + sizeof(EVENT_HEADER),
01735 SYNC, rpc_mode);
01736
01737 if (status != SUCCESS) {
01738 cm_msg(MERROR, "scheduler", "rpc_send_event error %d", status);
01739 break;
01740 }
01741 }
01742
01743 eq->bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
01744
01745 if (eq->info.num_subevents) {
01746 eq->events_sent += eq->subevent_number;
01747 events_sent += eq->subevent_number;
01748 } else {
01749 eq->events_sent++;
01750 events_sent++;
01751 }
01752 }
01753
01754 actual_millitime = ss_millitime();
01755
01756
01757 if (actual_millitime - readout_start > (DWORD) eq_info->period)
01758 break;
01759
01760
01761 if (eq_info->event_limit > 0 &&
01762 eq->stats.events_sent + eq->events_sent >= eq_info->event_limit)
01763 break;
01764 }
01765 }
01766
01767 return events_sent;
01768 }
01769
01770
01771
01772 INT scheduler(void)
01773 {
01774 EQUIPMENT_INFO *eq_info;
01775 EQUIPMENT *eq;
01776 EVENT_HEADER *pevent, *pfragment;
01777 DWORD last_time_network = 0, last_time_display = 0, last_time_flush = 0,
01778 readout_start, sent, size;
01779 INT i, j, idx, status = 0, ch, source, state, old_flag;
01780 char str[80], *pdata;
01781 unsigned char *pd;
01782 BOOL buffer_done, flag, force_update = FALSE;
01783
01784 INT opt_max = 0, opt_index = 0, opt_tcp_size = 128, opt_cnt = 0;
01785 INT err;
01786
01787 #ifdef OS_VXWORKS
01788 rpc_set_opt_tcp_size(1024);
01789 #ifdef PPCxxx
01790 rpc_set_opt_tcp_size(NET_TCP_SIZE);
01791 #endif
01792 #endif
01793
01794
01795
01796 do {
01797 actual_millitime = ss_millitime();
01798 actual_time = ss_time();
01799
01800
01801 for (idx = 0;; idx++) {
01802 eq = &equipment[idx];
01803 eq_info = &eq->info;
01804
01805
01806 if (!eq->name[0])
01807 break;
01808
01809 if (!eq_info->enabled)
01810 continue;
01811
01812 if (eq->status != FE_SUCCESS)
01813 continue;
01814
01815
01816 if ((eq_info->eq_type & EQ_SLOW) && eq->status == FE_SUCCESS) {
01817
01818
01819 if (eq_info->event_limit > 0) {
01820 if (actual_millitime - eq->last_idle >= (DWORD) eq_info->event_limit) {
01821 eq->cd(CMD_IDLE, eq);
01822 eq->last_idle = actual_millitime;
01823 }
01824 } else
01825 eq->cd(CMD_IDLE, eq);
01826 }
01827
01828 if (run_state == STATE_STOPPED && (eq_info->read_on & RO_STOPPED) == 0)
01829 continue;
01830 if (run_state == STATE_PAUSED && (eq_info->read_on & RO_PAUSED) == 0)
01831 continue;
01832 if (run_state == STATE_RUNNING && (eq_info->read_on & RO_RUNNING) == 0)
01833 continue;
01834
01835
01836 if ((eq_info->eq_type & EQ_PERIODIC) || (eq_info->eq_type & EQ_SLOW)) {
01837 if (eq_info->period == 0)
01838 continue;
01839
01840
01841 if (actual_millitime - eq->last_called >= (DWORD) eq_info->period) {
01842
01843 old_flag = readout_enabled();
01844 if (old_flag)
01845 readout_enable(FALSE);
01846
01847
01848 status = send_event(idx);
01849
01850 if (status != CM_SUCCESS) {
01851 cm_msg(MERROR, "scheduler", "send_event error %d", status);
01852 goto net_error;
01853 }
01854
01855
01856 if (old_flag)
01857 readout_enable(TRUE);
01858 }
01859 }
01860
01861
01862 if (eq_info->eq_type & EQ_POLLED) {
01863 readout_start = actual_millitime;
01864 pevent = NULL;
01865
01866 while ((source = poll_event(eq_info->source, eq->poll_count, FALSE)) > 0) {
01867
01868 if (eq_info->eq_type & EQ_FRAGMENTED)
01869 pevent = frag_buffer;
01870 else
01871 pevent = (EVENT_HEADER *)event_buffer;
01872
01873
01874 pevent->event_id = eq_info->event_id;
01875 pevent->trigger_mask = eq_info->trigger_mask;
01876 pevent->data_size = 0;
01877 pevent->time_stamp = actual_time;
01878 pevent->serial_number = eq->serial_number;
01879
01880
01881
01882
01883 *(INT *) (pevent + 1) = source;
01884
01885 if (eq->info.num_subevents) {
01886 eq->subevent_number = 0;
01887 do {
01888 *(INT *) ((char *) (pevent + 1) + pevent->data_size) = source;
01889
01890
01891 size = eq->readout((char *) (pevent + 1), pevent->data_size);
01892 pevent->data_size += size;
01893 if (size > 0) {
01894 if (pevent->data_size + sizeof(EVENT_HEADER) >
01895 (DWORD) max_event_size) {
01896 cm_msg(MERROR, "scheduler",
01897 "Event size %ld larger than maximum size %d",
01898 (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01899 max_event_size);
01900 }
01901
01902 eq->subevent_number++;
01903 eq->serial_number++;
01904 }
01905
01906
01907 do {
01908 source = poll_event(eq_info->source, eq->poll_count, FALSE);
01909
01910 if (source == FALSE) {
01911 actual_millitime = ss_millitime();
01912
01913
01914 if (actual_millitime - readout_start > (DWORD) eq_info->period)
01915 break;
01916 }
01917 } while (source == FALSE);
01918
01919 } while (eq->subevent_number < eq->info.num_subevents && source);
01920
01921
01922 pevent->data_size = eq->readout((char *) (pevent + 1), -1);
01923 } else {
01924
01925 pevent->data_size = eq->readout((char *) (pevent + 1), 0);
01926
01927
01928 if (eq_info->eq_type & EQ_FRAGMENTED) {
01929 if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size_frag) {
01930 cm_msg(MERROR, "send_event",
01931 "Event size %ld larger than maximum size %d for frag. ev.",
01932 (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01933 max_event_size_frag);
01934 assert(FALSE);
01935 }
01936 } else {
01937 if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size) {
01938 cm_msg(MERROR, "scheduler",
01939 "Event size %ld larger than maximum size %d",
01940 (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01941 max_event_size);
01942 assert(FALSE);
01943 }
01944 }
01945
01946
01947 if (pevent->data_size)
01948 eq->serial_number++;
01949 }
01950
01951
01952 if (pevent->data_size) {
01953
01954
01955 if (eq_info->eq_type & EQ_FRAGMENTED) {
01956
01957 pfragment = event_buffer;
01958
01959
01960 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01961 pfragment->event_id |= EVENTID_FRAG1;
01962
01963
01964 pd = (unsigned char *) (pfragment + 1);
01965 size = pevent->data_size;
01966 for (i = 0; i < 4; i++) {
01967 pd[i] = (unsigned char) (size & 0xFF);
01968 size >>= 8;
01969 }
01970
01971 pfragment->data_size = sizeof(DWORD);
01972
01973 pdata = (char *) (pevent + 1);
01974
01975 for (i = 0, sent = 0; sent < pevent->data_size; i++) {
01976 if (i > 0) {
01977 pfragment = event_buffer;
01978
01979
01980 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
01981 pfragment->event_id |= EVENTID_FRAG;
01982
01983
01984 size = pevent->data_size - sent;
01985 if (size > max_event_size - sizeof(EVENT_HEADER))
01986 size = max_event_size - sizeof(EVENT_HEADER);
01987
01988 memcpy(pfragment + 1, pdata, size);
01989 pfragment->data_size = size;
01990 sent += size;
01991 pdata += size;
01992 }
01993
01994
01995 if (equipment[idx].buffer_handle) {
01996 status = rpc_send_event(equipment[idx].buffer_handle, pfragment,
01997 pfragment->data_size + sizeof(EVENT_HEADER), SYNC, rpc_mode);
01998 if (status != RPC_SUCCESS) {
01999 cm_msg(MERROR, "send_event", "rpc_send_event(SYNC) error %d", status);
02000 return status;
02001 }
02002
02003
02004 rpc_flush_event();
02005 }
02006 }
02007
02008 } else {
02009
02010
02011
02012
02013 if (pevent->serial_number == 0)
02014 if (logger_root())
02015 update_odb(pevent, eq->hkey_variables, eq->format);
02016
02017 status = rpc_send_event(eq->buffer_handle, pevent,
02018 pevent->data_size + sizeof(EVENT_HEADER),
02019 SYNC, rpc_mode);
02020
02021 if (status != SUCCESS) {
02022 cm_msg(MERROR, "scheduler", "rpc_send_event error %d", status);
02023 goto net_error;
02024 }
02025 }
02026
02027 eq->bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
02028
02029 if (eq->info.num_subevents)
02030 eq->events_sent += eq->subevent_number;
02031 else
02032 eq->events_sent++;
02033 }
02034
02035 actual_millitime = ss_millitime();
02036
02037
02038 if (actual_millitime - readout_start > (DWORD) eq_info->period)
02039 break;
02040
02041
02042 if (eq_info->event_limit > 0 &&
02043 eq->stats.events_sent + eq->events_sent >= eq_info->event_limit)
02044 break;
02045 }
02046
02047 }
02048
02049
02050 if (eq_info->eq_type & (EQ_INTERRUPT | EQ_MULTITHREAD)) {
02051 readout_start = actual_millitime;
02052
02053 do {
02054 size = receive_trigger_event(eq);
02055 if ((int)size == -1)
02056 goto net_error;
02057
02058 actual_millitime = ss_millitime();
02059
02060
02061 if (actual_millitime - readout_start > (DWORD) eq_info->period)
02062 break;
02063
02064
02065 if (eq_info->event_limit > 0 &&
02066 eq->stats.events_sent + eq->events_sent >= eq_info->event_limit)
02067 break;
02068
02069 } while (size > 0);
02070
02071
02072 pevent = (EVENT_HEADER *)event_buffer;
02073 if (size > 0 && pevent->data_size && (eq_info->read_on & RO_ODB || eq_info->history)) {
02074 if (actual_millitime - eq->last_called > ODB_UPDATE_TIME && pevent != NULL) {
02075 eq->last_called = actual_millitime;
02076 update_odb(pevent, eq->hkey_variables, eq->format);
02077 eq->odb_out++;
02078 }
02079 }
02080 }
02081
02082
02083 if (eq_info->eq_type != EQ_SLOW &&
02084 eq_info->event_limit > 0 &&
02085 eq->stats.events_sent + eq->events_sent >= eq_info->event_limit &&
02086 run_state == STATE_RUNNING) {
02087
02088 if (cm_transition(TR_STOP, 0, str, sizeof(str), SYNC, FALSE) != CM_SUCCESS)
02089 cm_msg(MERROR, "scheduler", "cannot stop run: %s", str);
02090
02091
02092 size = sizeof(BOOL);
02093 flag = FALSE;
02094 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
02095
02096 if (flag)
02097 auto_restart = ss_time() + 20;
02098
02099
02100 force_update = TRUE;
02101 }
02102 }
02103
02104
02105 if (frontend_call_loop) {
02106 status = frontend_loop();
02107 if (status == RPC_SHUTDOWN || status == SS_ABORT) {
02108 status = RPC_SHUTDOWN;
02109 break;
02110 }
02111 }
02112
02113
02114 cm_check_deferred_transition();
02115
02116
02117 if (manual_trigger_event_id) {
02118 old_flag = readout_enabled();
02119 if (old_flag)
02120 readout_enable(FALSE);
02121
02122
02123 status = BM_INVALID_PARAM;
02124 for (i = 0; equipment[i].name[0]; i++)
02125 if (equipment[i].info.event_id == manual_trigger_event_id) {
02126 status = send_event(i);
02127 break;
02128 }
02129
02130 manual_trigger_event_id = 0;
02131
02132 if (status != CM_SUCCESS) {
02133 cm_msg(MERROR, "scheduler", "send_event error %d", status);
02134 goto net_error;
02135 }
02136
02137
02138 if (old_flag)
02139 readout_enable(TRUE);
02140 }
02141
02142
02143 if (force_update ||
02144 (display_period
02145 && actual_millitime - last_time_display > (DWORD) display_period)
02146 || (!display_period && actual_millitime - last_time_display > 3000)) {
02147 force_update = FALSE;
02148
02149
02150 if (actual_millitime != last_time_display) {
02151 max_bytes_per_sec = 0;
02152 for (i = 0; equipment[i].name[0]; i++) {
02153 eq = &equipment[i];
02154 eq->stats.events_sent += eq->events_sent;
02155 eq->stats.events_per_sec =
02156 eq->events_sent / ((actual_millitime - last_time_display) / 1000.0);
02157 eq->stats.kbytes_per_sec =
02158 eq->bytes_sent / 1024.0 / ((actual_millitime - last_time_display) /
02159 1000.0);
02160
02161 if ((INT) eq->bytes_sent > max_bytes_per_sec)
02162 max_bytes_per_sec = eq->bytes_sent;
02163
02164 eq->bytes_sent = 0;
02165 eq->events_sent = 0;
02166 }
02167
02168 max_bytes_per_sec = (DWORD)
02169 ((double) max_bytes_per_sec /
02170 ((actual_millitime - last_time_display) / 1000.0));
02171
02172
02173 if (optimize) {
02174 opt_max = MAX(opt_max, (INT) max_bytes_per_sec);
02175 ss_printf(0, opt_index, "%6d : %5.1lf %5.1lf", opt_tcp_size,
02176 opt_max / 1024.0, max_bytes_per_sec / 1024.0);
02177 if (++opt_cnt == 10) {
02178 opt_cnt = 0;
02179 opt_max = 0;
02180 opt_index++;
02181 opt_tcp_size = 1 << (opt_index + 7);
02182 rpc_set_opt_tcp_size(opt_tcp_size);
02183 if (1 << (opt_index + 7) > 0x8000) {
02184 opt_index = 0;
02185 opt_tcp_size = 1 << 7;
02186 rpc_set_opt_tcp_size(opt_tcp_size);
02187 }
02188 }
02189 }
02190
02191 }
02192
02193
02194 rpc_set_option(-1, RPC_OTRANSPORT, RPC_FTCP);
02195 db_send_changed_records();
02196 rpc_set_option(-1, RPC_OTRANSPORT, RPC_TCP);
02197
02198 if (display_period) {
02199 display(FALSE);
02200
02201
02202 ch = 0;
02203 status = 0;
02204 while (ss_kbhit()) {
02205 ch = ss_getchar(0);
02206 if (ch == -1)
02207 ch = getchar();
02208
02209 if (ch == '!')
02210 status = RPC_SHUTDOWN;
02211 }
02212
02213 if (ch > 0)
02214 display(TRUE);
02215 if (status == RPC_SHUTDOWN)
02216 break;
02217 }
02218
02219 last_time_display = actual_millitime;
02220 }
02221
02222
02223 if (actual_millitime - last_time_flush > 1000) {
02224 last_time_flush = actual_millitime;
02225
02226
02227
02228
02229 if (max_bytes_per_sec < SERVER_CACHE_SIZE) {
02230 old_flag = readout_enabled();
02231 if (old_flag)
02232 readout_enable(FALSE);
02233
02234 for (i = 0; equipment[i].name[0]; i++) {
02235 if (equipment[i].buffer_handle) {
02236
02237 buffer_done = FALSE;
02238 for (j = 0; j < i; j++)
02239 if (equipment[i].buffer_handle == equipment[j].buffer_handle) {
02240 buffer_done = TRUE;
02241 break;
02242 }
02243
02244 if (!buffer_done) {
02245 rpc_set_option(-1, RPC_OTRANSPORT, RPC_FTCP);
02246 rpc_flush_event();
02247 err = bm_flush_cache(equipment[i].buffer_handle, ASYNC);
02248 if ((err != BM_SUCCESS) && (err != BM_ASYNC_RETURN)) {
02249 cm_msg(MERROR, "scheduler", "bm_flush_cache(ASYNC) error %d",
02250 err);
02251 return err;
02252 }
02253 rpc_set_option(-1, RPC_OTRANSPORT, RPC_TCP);
02254 }
02255 }
02256 }
02257
02258 if (old_flag)
02259 readout_enable(TRUE);
02260 }
02261 }
02262
02263
02264 if (auto_restart > 0 && ss_time() > auto_restart) {
02265
02266 size = sizeof(state);
02267 status = db_get_value(hDB, 0, "Runinfo/State", &state, &size, TID_INT, TRUE);
02268 if (status != DB_SUCCESS)
02269 cm_msg(MERROR, "scheduler", "cannot get Runinfo/State in database");
02270
02271 if (state == STATE_STOPPED) {
02272 auto_restart = 0;
02273 size = sizeof(run_number);
02274 status =
02275 db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, &size, TID_INT,
02276 TRUE);
02277 assert(status == SUCCESS);
02278
02279 if (run_number <= 0) {
02280 cm_msg(MERROR, "main", "aborting on attempt to use invalid run number %d",
02281 run_number);
02282 abort();
02283 }
02284
02285 cm_msg(MTALK, "main", "starting new run");
02286 status = cm_transition(TR_START, run_number + 1, NULL, 0, SYNC, FALSE);
02287 if (status != CM_SUCCESS)
02288 cm_msg(MERROR, "main", "cannot restart run");
02289 }
02290 }
02291
02292
02293 if ((run_state == STATE_RUNNING && interrupt_eq == NULL) || slowcont_eq) {
02294
02295 if (actual_millitime - last_time_network > 100) {
02296 status = cm_yield(0);
02297 last_time_network = actual_millitime;
02298 } else
02299 status = RPC_SUCCESS;
02300 } else
02301
02302
02303 status = cm_yield(100);
02304
02305
02306 if (fe_stop)
02307 status = RPC_SHUTDOWN;
02308
02309
02310 if (cm_is_ctrlc_pressed())
02311 status = RPC_SHUTDOWN;
02312
02313 } while (status != RPC_SHUTDOWN && status != SS_ABORT);
02314
02315 net_error:
02316
02317 return status;
02318 }
02319
02320
02321
02322 INT get_frontend_index()
02323 {
02324 return frontend_index;
02325 }
02326
02327
02328
02329 #ifdef OS_VXWORKS
02330 int mfe(char *ahost_name, char *aexp_name, BOOL adebug)
02331 #else
02332 int main(int argc, char *argv[])
02333 #endif
02334 {
02335 INT status, i, j;
02336 INT daemon_flag;
02337
02338 host_name[0] = 0;
02339 exp_name[0] = 0;
02340 debug = FALSE;
02341 daemon_flag = 0;
02342
02343 setbuf(stdout, 0);
02344 setbuf(stderr, 0);
02345
02346 #ifdef SIGPIPE
02347 signal(SIGPIPE, SIG_IGN);
02348 #endif
02349
02350 #ifdef OS_VXWORKS
02351 if (ahost_name)
02352 strcpy(host_name, ahost_name);
02353 if (aexp_name)
02354 strcpy(exp_name, aexp_name);
02355 debug = adebug;
02356 #else
02357
02358
02359 cm_get_environment(host_name, sizeof(host_name), exp_name, sizeof(exp_name));
02360
02361
02362 for (i = 1; i < argc; i++) {
02363 if (argv[i][0] == '-' && argv[i][1] == 'd')
02364 debug = TRUE;
02365 else if (argv[i][0] == '-' && argv[i][1] == 'D')
02366 daemon_flag = 1;
02367 else if (argv[i][0] == '-' && argv[i][1] == 'O')
02368 daemon_flag = 2;
02369 else if (argv[i][0] == '-') {
02370 if (i + 1 >= argc || argv[i + 1][0] == '-')
02371 goto usage;
02372 if (argv[i][1] == 'e')
02373 strcpy(exp_name, argv[++i]);
02374 else if (argv[i][1] == 'h')
02375 strcpy(host_name, argv[++i]);
02376 else if (argv[i][1] == 'i')
02377 frontend_index = atoi(argv[++i]);
02378 else {
02379 usage:
02380 printf
02381 ("usage: frontend [-h Hostname] [-e Experiment] [-d] [-D] [-O] [-i n]\n");
02382 printf(" [-d] Used to debug the frontend\n");
02383 printf(" [-D] Become a daemon\n");
02384 printf(" [-O] Become a daemon but keep stdout\n");
02385 printf(" [-i n] Set frontend index (used for event building)\n");
02386 return 0;
02387 }
02388 }
02389 }
02390 #endif
02391
02392
02393 if (event_buffer_size < 2 * max_event_size) {
02394 cm_msg(MERROR, "mainFE", "event_buffer_size too small for max. event size\n");
02395 ss_sleep(5000);
02396 return 1;
02397 }
02398
02399 if (max_event_size > MAX_EVENT_SIZE) {
02400 cm_msg(MERROR, "mainFE", "Requested max_event_size (%d) exceeds max. system event size (%d)",
02401 max_event_size, MAX_EVENT_SIZE);
02402 ss_sleep(5000);
02403 return 1;
02404 }
02405
02406 #ifdef OS_VXWORKS
02407
02408
02409 event_buffer_size = 2 * 10 * (max_event_size + sizeof(EVENT_HEADER) + sizeof(INT));
02410 if (event_buffer_size > memFindMax()) {
02411 cm_msg(MERROR, "mainFE", "Not enough mem space for event size");
02412 return 0;
02413 }
02414
02415 event_buffer_size = 0.2 * memFindMax();
02416 #endif
02417
02418
02419 if (getenv("MIDAS_FRONTEND_INDEX"))
02420 frontend_index = atoi(getenv("MIDAS_FRONTEND_INDEX"));
02421
02422
02423 strcpy(full_frontend_name, frontend_name);
02424 if (frontend_index >= 0)
02425 sprintf(full_frontend_name + strlen(full_frontend_name), "%02d", frontend_index);
02426
02427
02428 printf("Frontend name : %s\n", full_frontend_name);
02429 printf("Event buffer size : %d\n", event_buffer_size);
02430 printf("System max event size : %d\n", MAX_EVENT_SIZE);
02431 printf("User max event size : %d\n", max_event_size);
02432 if (max_event_size_frag > 0)
02433 printf("User max frag. size : %d\n", max_event_size_frag);
02434 printf("# of events per buffer : %d\n\n", event_buffer_size / max_event_size);
02435
02436 if (daemon_flag) {
02437 printf("\nBecoming a daemon...\n");
02438 ss_daemon_init(daemon_flag == 2);
02439 }
02440
02441
02442 if (display_period) {
02443 if (host_name[0]) {
02444 if (exp_name[0])
02445 printf("Connect to experiment %s on host %s...\n", exp_name, host_name);
02446 else
02447 printf("Connect to experiment on host %s...\n", host_name);
02448 } else if (exp_name[0])
02449 printf("Connect to experiment %s...\n", exp_name);
02450 else
02451 printf("Connect to experiment...\n");
02452 }
02453
02454 status = cm_connect_experiment1(host_name, exp_name, full_frontend_name,
02455 NULL, DEFAULT_ODB_SIZE, DEFAULT_FE_TIMEOUT);
02456 if (status != CM_SUCCESS) {
02457
02458 ss_sleep(5000);
02459 return 1;
02460 }
02461
02462 if (display_period)
02463 printf("OK\n");
02464
02465
02466 event_buffer = malloc(max_event_size);
02467 if (event_buffer == NULL) {
02468 cm_msg(MERROR, "mainFE", "mfe: Not enough memory or event too big\n");
02469 return 1;
02470 }
02471
02472
02473 cm_cleanup(full_frontend_name, FALSE);
02474
02475
02476 status = cm_shutdown(full_frontend_name, FALSE);
02477 if (status == CM_SUCCESS && display_period) {
02478 printf("Previous frontend stopped\n");
02479
02480
02481 ss_sleep(3000);
02482 }
02483
02484
02485 if (cm_register_transition(TR_START, tr_start, 500) != CM_SUCCESS ||
02486 cm_register_transition(TR_STOP, tr_stop, 500) != CM_SUCCESS ||
02487 cm_register_transition(TR_PAUSE, tr_pause, 500) != CM_SUCCESS ||
02488 cm_register_transition(TR_RESUME, tr_resume, 500) != CM_SUCCESS) {
02489 printf("Failed to start local RPC server");
02490 cm_disconnect_experiment();
02491
02492
02493 ss_sleep(5000);
02494 return 1;
02495 }
02496
02497 cm_get_experiment_database(&hDB, &status);
02498
02499 #ifdef OS_VXWORKS
02500 cm_synchronize(NULL);
02501 #endif
02502
02503
02504 if (debug)
02505 cm_set_watchdog_params(FALSE, 0);
02506
02507
02508 rpc_set_option(-1, RPC_OTIMEOUT, 120000);
02509
02510
02511 if (display_period)
02512 cm_set_msg_print(MT_ALL, MT_ALL, message_print);
02513
02514
02515 if (display_period)
02516 printf("Init hardware...\n");
02517 if (frontend_init() != SUCCESS) {
02518 if (display_period)
02519 printf("\n");
02520 cm_disconnect_experiment();
02521
02522
02523 ss_sleep(5000);
02524 return 1;
02525 }
02526
02527
02528 if (register_equipment() != SUCCESS) {
02529 if (display_period)
02530 printf("\n");
02531 cm_disconnect_experiment();
02532
02533
02534 ss_sleep(5000);
02535 return 1;
02536 }
02537
02538 if (display_period)
02539 printf("OK\n");
02540
02541
02542 if (display_period) {
02543 ss_sleep(1000);
02544 display(TRUE);
02545 }
02546
02547
02548 if (run_state == STATE_RUNNING)
02549 readout_enable(TRUE);
02550
02551
02552 ss_getchar(0);
02553
02554
02555 status = scheduler();
02556
02557
02558 stop_all_threads = 1;
02559 rb_set_nonblocking();
02560 while (readout_thread_active)
02561 ss_sleep(100);
02562
02563
02564 ss_getchar(TRUE);
02565
02566
02567 if (interrupt_eq) {
02568 interrupt_configure(CMD_INTERRUPT_DISABLE, 0, 0);
02569 interrupt_configure(CMD_INTERRUPT_DETACH, 0, 0);
02570 }
02571
02572
02573 if (interrupt_eq != NULL)
02574 interrupt_configure(CMD_INTERRUPT_DETACH, interrupt_eq->info.source, 0);
02575
02576
02577 frontend_exit();
02578
02579
02580 for (i = 0; equipment[i].name[0]; i++)
02581 if ((equipment[i].info.eq_type & EQ_SLOW) && equipment[i].status == FE_SUCCESS) {
02582
02583 for (j = 0; equipment[i].driver[j].name[0]; j++)
02584 if (equipment[i].driver[j].flags & DF_MULTITHREAD)
02585 break;
02586
02587
02588 if (equipment[i].driver[j].name[0] && equipment[i].status == FE_SUCCESS)
02589 equipment[i].cd(CMD_STOP, &equipment[i]);
02590 }
02591 for (i = 0; equipment[i].name[0]; i++)
02592 if ((equipment[i].info.eq_type & EQ_SLOW) && equipment[i].status == FE_SUCCESS)
02593 equipment[i].cd(CMD_EXIT, &equipment[i]);
02594
02595
02596 cm_disconnect_experiment();
02597
02598 if (display_period) {
02599 if (status == RPC_SHUTDOWN) {
02600 ss_clear_screen();
02601 ss_printf(0, 0, "Frontend shut down.");
02602 ss_printf(0, 1, "");
02603 }
02604 }
02605
02606 if (status != RPC_SHUTDOWN)
02607 printf("Network connection aborted.\n");
02608
02609 return 0;
02610 }