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