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, PTYPE adr);
00043
00044
00045
00046
00047
00048 #undef USE_EVENT_CHANNEL
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 EVENT_HEADER *interrupt_odb_buffer;
00096 BOOL interrupt_odb_buffer_valid;
00097
00098 int send_event(INT index);
00099 void send_all_periodic_events(INT transition);
00100 void interrupt_routine(void);
00101 void interrupt_enable(BOOL flag);
00102 void display(BOOL bInit);
00103
00104
00105
00106 #define EQUIPMENT_COMMON_STR "\
00107 Event ID = WORD : 0\n\
00108 Trigger mask = WORD : 0\n\
00109 Buffer = STRING : [32] SYSTEM\n\
00110 Type = INT : 0\n\
00111 Source = INT : 0\n\
00112 Format = STRING : [8] FIXED\n\
00113 Enabled = BOOL : 0\n\
00114 Read on = INT : 0\n\
00115 Period = INT : 0\n\
00116 Event limit = DOUBLE : 0\n\
00117 Num subevents = DWORD : 0\n\
00118 Log history = INT : 0\n\
00119 Frontend host = STRING : [32] \n\
00120 Frontend name = STRING : [32] \n\
00121 Frontend file name = STRING : [256] \n\
00122 "
00123
00124 #define EQUIPMENT_STATISTICS_STR "\
00125 Events sent = DOUBLE : 0\n\
00126 Events per sec. = DOUBLE : 0\n\
00127 kBytes per sec. = DOUBLE : 0\n\
00128 "
00129
00130
00131
00132
00133
00134 INT tr_start(INT rn, char *error)
00135 {
00136 INT i, status;
00137
00138
00139 for (i = 0; equipment[i].name[0]; i++) {
00140 equipment[i].serial_number = 1;
00141 equipment[i].subevent_number = 0;
00142 equipment[i].stats.events_sent = 0;
00143 equipment[i].odb_in = equipment[i].odb_out = 0;
00144 }
00145
00146 status = begin_of_run(rn, error);
00147
00148 if (status == CM_SUCCESS) {
00149 run_state = STATE_RUNNING;
00150 run_number = rn;
00151
00152 send_all_periodic_events(TR_START);
00153
00154 if (display_period) {
00155 ss_printf(14, 2, "Running ");
00156 ss_printf(36, 2, "%d", rn);
00157 }
00158
00159
00160 interrupt_enable(TRUE);
00161 }
00162
00163 return status;
00164 }
00165
00166
00167
00168 INT tr_stop(INT rn, char *error)
00169 {
00170 INT status, i;
00171 EQUIPMENT *eq;
00172
00173
00174 interrupt_enable(FALSE);
00175
00176 status = end_of_run(rn, error);
00177
00178 if (status == CM_SUCCESS) {
00179
00180 if (run_state != STATE_STOPPED)
00181 send_all_periodic_events(TR_STOP);
00182
00183 run_state = STATE_STOPPED;
00184 run_number = rn;
00185
00186 if (display_period)
00187 ss_printf(14, 2, "Stopped ");
00188 } else
00189 interrupt_enable(TRUE);
00190
00191
00192 rpc_flush_event();
00193 for (i = 0; equipment[i].name[0]; i++)
00194 if (equipment[i].buffer_handle) {
00195 INT err = bm_flush_cache(equipment[i].buffer_handle, SYNC);
00196 if (err != BM_SUCCESS) {
00197 cm_msg(MERROR, "tr_prestop", "bm_flush_cache(SYNC) error %d", err);
00198 return err;
00199 }
00200 }
00201
00202
00203 for (i = 0; equipment[i].name[0]; i++) {
00204 eq = &equipment[i];
00205 eq->stats.events_sent += eq->events_sent;
00206 eq->bytes_sent = 0;
00207 eq->events_sent = 0;
00208 }
00209
00210 db_send_changed_records();
00211
00212 return status;
00213 }
00214
00215
00216
00217 INT tr_pause(INT rn, char *error)
00218 {
00219 INT status;
00220
00221
00222 interrupt_enable(FALSE);
00223
00224 status = pause_run(rn, error);
00225
00226 if (status == CM_SUCCESS) {
00227 run_state = STATE_PAUSED;
00228 run_number = rn;
00229
00230 send_all_periodic_events(TR_PAUSE);
00231
00232 if (display_period)
00233 ss_printf(14, 2, "Paused ");
00234 } else
00235 interrupt_enable(TRUE);
00236
00237 return status;
00238 }
00239
00240
00241
00242 INT tr_resume(INT rn, char *error)
00243 {
00244 INT status;
00245
00246 status = resume_run(rn, error);
00247
00248 if (status == CM_SUCCESS) {
00249 run_state = STATE_RUNNING;
00250 run_number = rn;
00251
00252 send_all_periodic_events(TR_RESUME);
00253
00254 if (display_period)
00255 ss_printf(14, 2, "Running ");
00256
00257
00258 interrupt_enable(TRUE);
00259 }
00260
00261 return status;
00262 }
00263
00264
00265
00266 INT manual_trigger(INT index, void *prpc_param[])
00267 {
00268 manual_trigger_event_id = CWORD(0);
00269 return SUCCESS;
00270 }
00271
00272
00273
00274 INT register_equipment(void)
00275 {
00276 INT index, count, size, status, i, j, k, n;
00277 char str[256];
00278 EQUIPMENT_INFO *eq_info;
00279 EQUIPMENT_STATS *eq_stats;
00280 DWORD start_time, delta_time;
00281 HNDLE hKey;
00282 BOOL manual_trig_flag = FALSE;
00283 BANK_LIST *bank_list;
00284 DWORD dummy;
00285
00286
00287 size = sizeof(run_state);
00288 run_state = STATE_STOPPED;
00289 db_get_value(hDB, 0, "/Runinfo/State", &run_state, &size, TID_INT, TRUE);
00290 size = sizeof(run_number);
00291 run_number = 1;
00292 status =
00293 db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
00294 assert(status == SUCCESS);
00295
00296
00297 for (index = 0; equipment[index].name[0]; index++) {
00298 eq_info = &equipment[index].info;
00299 eq_stats = &equipment[index].stats;
00300
00301 if (eq_info->event_id == 0) {
00302 printf("\nEvent ID 0 for %s not allowed\n", equipment[index].name);
00303 cm_disconnect_experiment();
00304 ss_sleep(5000);
00305 exit(0);
00306 }
00307
00308
00309 equipment[index].status = FE_SUCCESS;
00310
00311
00312 if (eq_info->eq_type & EQ_EB) {
00313
00314 if (frontend_index == -1) {
00315 printf("\nEquipment \"%s\" has EQ_EB set, but no", equipment[index].name);
00316 printf(" index specified via \"-i\" flag.\nExiting.");
00317 cm_disconnect_experiment();
00318 ss_sleep(5000);
00319 exit(0);
00320 }
00321
00322
00323 sprintf(equipment[index].name+strlen(equipment[index].name), "%02d", frontend_index);
00324
00325
00326 sprintf(eq_info->buffer+strlen(eq_info->buffer), "%02d", frontend_index);
00327 }
00328
00329 sprintf(str, "/Equipment/%s/Common", equipment[index].name);
00330
00331
00332 if (eq_info->eq_type != EQ_SLOW) {
00333 db_find_key(hDB, 0, str, &hKey);
00334 size = sizeof(double);
00335 if (hKey)
00336 db_get_value(hDB, hKey, "Event limit", &eq_info->event_limit, &size,
00337 TID_DOUBLE, TRUE);
00338 }
00339
00340
00341 status = db_check_record(hDB, 0, str, EQUIPMENT_COMMON_STR, TRUE);
00342 if (status != DB_SUCCESS) {
00343 printf("Cannot check equipment record, status = %d\n", status);
00344 ss_sleep(3000);
00345 }
00346 db_find_key(hDB, 0, str, &hKey);
00347
00348 if (equal_ustring(eq_info->format, "YBOS"))
00349 equipment[index].format = FORMAT_YBOS;
00350 else if (equal_ustring(eq_info->format, "FIXED"))
00351 equipment[index].format = FORMAT_FIXED;
00352 else
00353 equipment[index].format = FORMAT_MIDAS;
00354
00355 gethostname(eq_info->frontend_host, sizeof(eq_info->frontend_host));
00356 strcpy(eq_info->frontend_name, full_frontend_name);
00357 strcpy(eq_info->frontend_file_name, frontend_file_name);
00358
00359
00360 db_set_record(hDB, hKey, eq_info, sizeof(EQUIPMENT_INFO), 0);
00361
00362
00363 db_open_record(hDB, hKey, eq_info, sizeof(EQUIPMENT_INFO), MODE_READ, NULL, NULL);
00364
00365
00366 sprintf(str, "/Equipment/%s/Variables", equipment[index].name);
00367 if (equipment[index].event_descrip) {
00368 if (equipment[index].format == FORMAT_FIXED)
00369 db_check_record(hDB, 0, str, (char *) equipment[index].event_descrip, TRUE);
00370 else {
00371
00372 bank_list = (BANK_LIST *) equipment[index].event_descrip;
00373
00374 for (; bank_list->name[0]; bank_list++) {
00375
00376
00377
00378
00379
00380 if (bank_list->type == TID_STRUCT) {
00381 sprintf(str, "/Equipment/%s/Variables/%s", equipment[index].name,
00382 bank_list->name);
00383 status =
00384 db_check_record(hDB, 0, str, strcomb(bank_list->init_str), TRUE);
00385 if (status != DB_SUCCESS) {
00386 printf("Cannot check/create record \"%s\", status = %d\n", str,
00387 status);
00388 ss_sleep(3000);
00389 }
00390 } else {
00391 sprintf(str, "/Equipment/%s/Variables/%s", equipment[index].name,
00392 bank_list->name);
00393 dummy = 0;
00394 db_set_value(hDB, 0, str, &dummy, rpc_tid_size(bank_list->type), 1,
00395 bank_list->type);
00396 }
00397 }
00398 }
00399 } else
00400 db_create_key(hDB, 0, str, TID_KEY);
00401
00402 sprintf(str, "/Equipment/%s/Variables", equipment[index].name);
00403 db_find_key(hDB, 0, str, &hKey);
00404 equipment[index].hkey_variables = hKey;
00405
00406
00407
00408 sprintf(str, "/Equipment/%s/Statistics", equipment[index].name);
00409
00410 status = db_check_record(hDB, 0, str, EQUIPMENT_STATISTICS_STR, TRUE);
00411 if (status != DB_SUCCESS) {
00412 printf("Cannot create/check statistics record \'%s\', error %d\n", str, status);
00413 ss_sleep(3000);
00414 }
00415
00416 status = db_find_key(hDB, 0, str, &hKey);
00417 if (status != DB_SUCCESS) {
00418 printf("Cannot find statistics record \'%s\', error %d\n", str, status);
00419 ss_sleep(3000);
00420 }
00421
00422 eq_stats->events_sent = 0;
00423 eq_stats->events_per_sec = 0;
00424 eq_stats->kbytes_per_sec = 0;
00425
00426
00427 status =
00428 db_open_record(hDB, hKey, eq_stats, sizeof(EQUIPMENT_STATS), MODE_WRITE, NULL,
00429 NULL);
00430 if (status != DB_SUCCESS) {
00431 cm_msg(MERROR, "register_equipment",
00432 "Cannot open statistics record \'%s\', error %d. Probably other FE is using it",
00433 str, status);
00434 ss_sleep(3000);
00435 }
00436
00437
00438
00439 if (eq_info->buffer[0]) {
00440 status =
00441 bm_open_buffer(eq_info->buffer, EVENT_BUFFER_SIZE,
00442 &equipment[index].buffer_handle);
00443 if (status != BM_SUCCESS && status != BM_CREATED) {
00444 cm_msg(MERROR, "register_equipment",
00445 "Cannot open event buffer. Try to reduce EVENT_BUFFER_SIZE in midas.h \
00446 and rebuild the system.");
00447 return 0;
00448 }
00449
00450
00451 bm_set_cache_size(equipment[index].buffer_handle, 0, SERVER_CACHE_SIZE);
00452 } else
00453 equipment[index].buffer_handle = 0;
00454
00455
00456 if (eq_info->eq_type & EQ_POLLED) {
00457 if (display_period)
00458 printf("\nCalibrating");
00459
00460 count = 1;
00461 do {
00462 if (display_period)
00463 printf(".");
00464
00465 start_time = ss_millitime();
00466
00467 poll_event(equipment[index].info.source, count, TRUE);
00468
00469 delta_time = ss_millitime() - start_time;
00470
00471 if (delta_time > 0)
00472 count = (INT) ((double) count * 100 / delta_time);
00473 else
00474 count *= 100;
00475 } while (delta_time > 120 || delta_time < 80);
00476
00477 equipment[index].poll_count = (INT) ((double) eq_info->period / 100 * count);
00478
00479 if (display_period)
00480 printf("OK\n");
00481 }
00482
00483
00484 if (eq_info->eq_type & EQ_INTERRUPT) {
00485
00486
00487 for (i = 0; equipment[i].name[0]; i++)
00488 if (equipment[i].info.eq_type & EQ_POLLED) {
00489 equipment[index].status = FE_ERR_DISABLED;
00490 cm_msg(MINFO, "register_equipment",
00491 "Interrupt readout cannot be combined with polled readout");
00492 }
00493
00494 if (equipment[index].status != FE_ERR_DISABLED) {
00495 if (eq_info->enabled) {
00496 if (interrupt_eq) {
00497 equipment[index].status = FE_ERR_DISABLED;
00498 cm_msg(MINFO, "register_equipment",
00499 "Defined more than one equipment with interrupt readout");
00500 } else {
00501 interrupt_configure(CMD_INTERRUPT_ATTACH, eq_info->source,
00502 (PTYPE) interrupt_routine);
00503 interrupt_eq = &equipment[index];
00504 interrupt_odb_buffer = malloc(MAX_EVENT_SIZE + sizeof(EVENT_HEADER));
00505 }
00506 } else {
00507 equipment[index].status = FE_ERR_DISABLED;
00508 cm_msg(MINFO, "register_equipment",
00509 "Equipment %s disabled in file \"frontend.c\"",
00510 equipment[index].name);
00511 }
00512 }
00513 }
00514
00515
00516 if (eq_info->eq_type & EQ_SLOW) {
00517
00518 for (i = 0; equipment[index].driver[i].name[0]; i++)
00519 for (j = i + 1; equipment[index].driver[j].name[0]; j++)
00520 if (equal_ustring(equipment[index].driver[i].name,
00521 equipment[index].driver[j].name)) {
00522 strcpy(str, equipment[index].driver[i].name);
00523 for (k = 0, n = 0; equipment[index].driver[k].name[0]; k++)
00524 if (equal_ustring(str, equipment[index].driver[k].name))
00525 sprintf(equipment[index].driver[k].name, "%s_%d", str, n++);
00526
00527 break;
00528 }
00529
00530
00531 if (eq_info->enabled)
00532 equipment[index].status = equipment[index].cd(CMD_INIT, &equipment[index]);
00533 else {
00534 equipment[index].status = FE_ERR_DISABLED;
00535 cm_msg(MINFO, "register_equipment",
00536 "Equipment %s disabled in file \"frontend.c\"", equipment[index].name);
00537 }
00538
00539
00540 if (equipment[index].status != FE_SUCCESS)
00541 ss_sleep(3000);
00542 }
00543
00544
00545 if (eq_info->eq_type & EQ_MANUAL_TRIG) {
00546 if (!manual_trig_flag)
00547 cm_register_function(RPC_MANUAL_TRIG, manual_trigger);
00548
00549 manual_trig_flag = TRUE;
00550 }
00551 }
00552
00553 return SUCCESS;
00554 }
00555
00556
00557
00558 void update_odb(EVENT_HEADER * pevent, HNDLE hKey, INT format)
00559 {
00560 INT size, i, ni4, tsize, status, n_data;
00561 void *pdata;
00562 char name[5];
00563 BANK_HEADER *pbh;
00564 BANK *pbk;
00565 BANK32 *pbk32;
00566 void *pydata;
00567 DWORD odb_type;
00568 DWORD *pyevt, bkname;
00569 WORD bktype;
00570 HNDLE hKeyRoot, hKeyl;
00571 KEY key;
00572
00573
00574
00575
00576 if (format == FORMAT_FIXED) {
00577 if (db_set_record(hDB, hKey, (char *) (pevent + 1),
00578 pevent->data_size, 0) != DB_SUCCESS)
00579 cm_msg(MERROR, "update_odb", "event #%d size mismatch", pevent->event_id);
00580 } else if (format == FORMAT_MIDAS) {
00581 pbh = (BANK_HEADER *) (pevent + 1);
00582 pbk = NULL;
00583 pbk32 = NULL;
00584 do {
00585
00586 if (bk_is32(pbh)) {
00587 size = bk_iterate32(pbh, &pbk32, &pdata);
00588 if (pbk32 == NULL)
00589 break;
00590 bkname = *((DWORD *) pbk32->name);
00591 bktype = (WORD) pbk32->type;
00592 } else {
00593 size = bk_iterate(pbh, &pbk, &pdata);
00594 if (pbk == NULL)
00595 break;
00596 bkname = *((DWORD *) pbk->name);
00597 bktype = (WORD) pbk->type;
00598 }
00599
00600 n_data = size;
00601 if (rpc_tid_size(bktype & 0xFF))
00602 n_data /= rpc_tid_size(bktype & 0xFF);
00603
00604
00605 *((DWORD *) name) = bkname;
00606 name[4] = 0;
00607
00608 if (bktype == TID_STRUCT) {
00609 status = db_find_key(hDB, hKey, name, &hKeyRoot);
00610 if (status != DB_SUCCESS) {
00611 cm_msg(MERROR, "update_odb",
00612 "please define bank %s in BANK_LIST in frontend.c", name);
00613 continue;
00614 }
00615
00616
00617 for (i = 0;; i++) {
00618 status = db_enum_key(hDB, hKeyRoot, i, &hKeyl);
00619 if (status == DB_NO_MORE_SUBKEYS)
00620 break;
00621
00622 db_get_key(hDB, hKeyl, &key);
00623
00624
00625 if (key.type != TID_STRING && key.type != TID_LINK)
00626 pdata =
00627 (void *) VALIGN(pdata, MIN(ss_get_struct_align(), key.item_size));
00628
00629 status = db_set_data(hDB, hKeyl, pdata, key.item_size * key.num_values,
00630 key.num_values, key.type);
00631 if (status != DB_SUCCESS) {
00632 cm_msg(MERROR, "update_odb", "cannot write %s to ODB", name);
00633 continue;
00634 }
00635
00636
00637 (char *) pdata += key.item_size * key.num_values;
00638 }
00639 } else {
00640
00641 if (n_data > 0)
00642 db_set_value(hDB, hKey, name, pdata, size, n_data, bktype & 0xFF);
00643 }
00644
00645 } while (1);
00646 } else if (format == FORMAT_YBOS) {
00647 #ifdef YBOS_SUPPORT
00648 YBOS_BANK_HEADER *pybkh;
00649
00650
00651 pyevt = (DWORD *) (pevent + 1);
00652 pybkh = NULL;
00653 do {
00654
00655 ni4 = ybk_iterate(pyevt, &pybkh, &pydata);
00656 if (pybkh == NULL || ni4 == 0)
00657 break;
00658
00659
00660 tsize = odb_type = 0;
00661 for (i = 0; id_map[0].ybos_type > 0; i++) {
00662 if (pybkh->type == id_map[i].ybos_type) {
00663 odb_type = id_map[i].odb_type;
00664 tsize = id_map[i].tsize;
00665 break;
00666 }
00667 }
00668
00669
00670 *((DWORD *) name) = pybkh->name;
00671 name[4] = 0;
00672
00673
00674 if (strncmp(name, "EVID", 4) == 0)
00675 continue;
00676
00677
00678 if (pybkh->type == D8_BKTYPE)
00679 ni4 /= 2;
00680 if (pybkh->type == I2_BKTYPE)
00681 ni4 *= 2;
00682 if (pybkh->type == I1_BKTYPE || pybkh->type == A1_BKTYPE)
00683 ni4 *= 4;
00684
00685
00686 size = ni4 * tsize;
00687 if ((status =
00688 db_set_value(hDB, hKey, name, pydata, size, ni4,
00689 odb_type & 0xFF)) != DB_SUCCESS) {
00690 printf("status:%i odb_type:%li name:%s ni4:%i size:%i tsize:%i\n", status,
00691 odb_type, name, ni4, size, tsize);
00692 for (i = 0; i < 6; i++)
00693 printf("data: %f\n", *((float *) (pydata))++);
00694 }
00695 } while (1);
00696 #endif
00697 }
00698
00699 rpc_set_option(-1, RPC_OTRANSPORT, RPC_TCP);
00700 }
00701
00702
00703
00704 int send_event(INT index)
00705 {
00706 EQUIPMENT_INFO *eq_info;
00707 EVENT_HEADER *pevent, *pfragment;
00708 char *pdata;
00709 unsigned char *pd;
00710 INT i, status;
00711 DWORD sent, size;
00712 static void *frag_buffer = NULL;
00713
00714 eq_info = &equipment[index].info;
00715
00716
00717 if (eq_info->eq_type & EQ_FRAGMENTED) {
00718 if (frag_buffer == NULL)
00719 frag_buffer = malloc(max_event_size_frag);
00720
00721 if (frag_buffer == NULL) {
00722 cm_msg(MERROR, "send_event",
00723 "Not enough memory to allocate buffer for fragmented events");
00724 return SS_NO_MEMORY;
00725 }
00726
00727 pevent = frag_buffer;
00728 } else {
00729
00730 pevent = dm_pointer_get();
00731 if (pevent == NULL) {
00732 cm_msg(MERROR, "send_event", "dm_pointer_get not returning valid pointer");
00733 return SS_NO_MEMORY;
00734 }
00735 }
00736
00737
00738 pevent->event_id = eq_info->event_id;
00739 pevent->trigger_mask = eq_info->trigger_mask;
00740 pevent->data_size = 0;
00741 pevent->time_stamp = ss_time();
00742 pevent->serial_number = equipment[index].serial_number++;
00743
00744 equipment[index].last_called = ss_millitime();
00745
00746
00747 *((EQUIPMENT **) (pevent + 1)) = &equipment[index];
00748 pevent->data_size = equipment[index].readout((char *) (pevent + 1), 0);
00749
00750
00751 if (pevent->data_size) {
00752 if (eq_info->eq_type & EQ_FRAGMENTED) {
00753
00754 if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size_frag) {
00755 cm_msg(MERROR, "send_event",
00756 "Event size %ld larger than maximum size %d for frag. ev.",
00757 (long) (pevent->data_size + sizeof(EVENT_HEADER)),
00758 max_event_size_frag);
00759 return SS_NO_MEMORY;
00760 }
00761
00762
00763 pfragment = dm_pointer_get();
00764 if (pfragment == NULL) {
00765 cm_msg(MERROR, "send_event", "dm_pointer_get not returning valid pointer");
00766 return SS_NO_MEMORY;
00767 }
00768
00769
00770 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
00771 pfragment->event_id |= EVENTID_FRAG1;
00772
00773
00774 pd = (char *) (pfragment + 1);
00775 size = pevent->data_size;
00776 for (i = 0; i < 4; i++) {
00777 pd[i] = (unsigned char) (size & 0xFF);
00778 size >>= 8;
00779 }
00780
00781 pfragment->data_size = sizeof(DWORD);
00782
00783 pdata = (char *) (pevent + 1);
00784
00785 for (i = 0, sent = 0; sent < pevent->data_size; i++) {
00786 if (i > 0) {
00787 pfragment = dm_pointer_get();
00788
00789
00790 memcpy(pfragment, pevent, sizeof(EVENT_HEADER));
00791 pfragment->event_id |= EVENTID_FRAG;
00792
00793
00794 size = pevent->data_size - sent;
00795 if (size > max_event_size - sizeof(EVENT_HEADER))
00796 size = max_event_size - sizeof(EVENT_HEADER);
00797
00798 memcpy(pfragment + 1, pdata, size);
00799 pfragment->data_size = size;
00800 sent += size;
00801 pdata += size;
00802 }
00803
00804
00805 if (equipment[index].buffer_handle) {
00806 #ifdef USE_EVENT_CHANNEL
00807 dm_pointer_increment(equipment[index].buffer_handle,
00808 pfragment->data_size + sizeof(EVENT_HEADER));
00809 #else
00810 rpc_flush_event();
00811 status = bm_send_event(equipment[index].buffer_handle, pfragment,
00812 pfragment->data_size + sizeof(EVENT_HEADER), SYNC);
00813 if (status != BM_SUCCESS) {
00814 cm_msg(MERROR, "send_event", "bm_send_event(SYNC) error %d", status);
00815 return status;
00816 }
00817 #endif
00818 }
00819 }
00820
00821 if (equipment[index].buffer_handle) {
00822 #ifndef USE_EVENT_CHANNEL
00823 status = bm_flush_cache(equipment[index].buffer_handle, SYNC);
00824 if (status != BM_SUCCESS) {
00825 cm_msg(MERROR, "send_event", "bm_flush_cache(SYNC) error %d", status);
00826 return status;
00827 }
00828 #endif
00829 }
00830 } else {
00831
00832
00833 if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size) {
00834 cm_msg(MERROR, "send_event", "Event size %ld larger than maximum size %d",
00835 (long) (pevent->data_size + sizeof(EVENT_HEADER)), max_event_size);
00836 return SS_NO_MEMORY;
00837 }
00838
00839
00840 if (equipment[index].buffer_handle) {
00841 #ifdef USE_EVENT_CHANNEL
00842 dm_pointer_increment(equipment[index].buffer_handle,
00843 pevent->data_size + sizeof(EVENT_HEADER));
00844 #else
00845 rpc_flush_event();
00846 status = bm_send_event(equipment[index].buffer_handle, pevent,
00847 pevent->data_size + sizeof(EVENT_HEADER), SYNC);
00848 if (status != BM_SUCCESS) {
00849 cm_msg(MERROR, "send_event", "bm_send_event(SYNC) error %d", status);
00850 return status;
00851 }
00852 status = bm_flush_cache(equipment[index].buffer_handle, SYNC);
00853 if (status != BM_SUCCESS) {
00854 cm_msg(MERROR, "send_event", "bm_flush_cache(SYNC) error %d", status);
00855 return status;
00856 }
00857 #endif
00858 }
00859
00860
00861
00862 if ((eq_info->read_on & RO_ODB) ||
00863 (eq_info->history > 0 && (eq_info->eq_type & ~EQ_SLOW))) {
00864 update_odb(pevent, equipment[index].hkey_variables, equipment[index].format);
00865 equipment[index].odb_out++;
00866 }
00867 }
00868
00869 equipment[index].bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
00870 equipment[index].events_sent++;
00871
00872 equipment[index].stats.events_sent += equipment[index].events_sent;
00873 equipment[index].events_sent = 0;
00874 } else
00875 equipment[index].serial_number--;
00876
00877
00878 #ifdef USE_EVENT_CHANNEL
00879 if ((status = dm_area_flush()) != CM_SUCCESS)
00880 cm_msg(MERROR, "send_event", "dm_area_flush: %i", status);
00881 #endif
00882
00883 for (i = 0; equipment[i].name[0]; i++)
00884 if (equipment[i].buffer_handle) {
00885 status = bm_flush_cache(equipment[i].buffer_handle, SYNC);
00886 if (status != BM_SUCCESS) {
00887 cm_msg(MERROR, "send_event", "bm_flush_cache(SYNC) error %d", status);
00888 return status;
00889 }
00890 }
00891
00892 return CM_SUCCESS;
00893 }
00894
00895
00896
00897 void send_all_periodic_events(INT transition)
00898 {
00899 EQUIPMENT_INFO *eq_info;
00900 INT i;
00901
00902 for (i = 0; equipment[i].name[0]; i++) {
00903 eq_info = &equipment[i].info;
00904
00905 if (!eq_info->enabled || equipment[i].status != FE_SUCCESS)
00906 continue;
00907
00908 if (transition == TR_START && (eq_info->read_on & RO_BOR) == 0)
00909 continue;
00910 if (transition == TR_STOP && (eq_info->read_on & RO_EOR) == 0)
00911 continue;
00912 if (transition == TR_PAUSE && (eq_info->read_on & RO_PAUSE) == 0)
00913 continue;
00914 if (transition == TR_RESUME && (eq_info->read_on & RO_RESUME) == 0)
00915 continue;
00916
00917 send_event(i);
00918 }
00919 }
00920
00921
00922
00923 BOOL interrupt_enabled;
00924
00925 void interrupt_enable(BOOL flag)
00926 {
00927 interrupt_enabled = flag;
00928
00929 if (interrupt_eq) {
00930 if (interrupt_enabled)
00931 interrupt_configure(CMD_INTERRUPT_ENABLE, 0, 0);
00932 else
00933 interrupt_configure(CMD_INTERRUPT_DISABLE, 0, 0);
00934 }
00935 }
00936
00937
00938
00939 void interrupt_routine(void)
00940 {
00941 EVENT_HEADER *pevent;
00942
00943
00944
00945 if ((pevent = dm_pointer_get()) == NULL)
00946 cm_msg(MERROR, "interrupt_routine", "interrupt, dm_pointer_get returned NULL");
00947
00948
00949 pevent->event_id = interrupt_eq->info.event_id;
00950 pevent->trigger_mask = interrupt_eq->info.trigger_mask;
00951 pevent->data_size = 0;
00952 pevent->time_stamp = actual_time;
00953 pevent->serial_number = interrupt_eq->serial_number++;
00954
00955
00956 pevent->data_size = interrupt_eq->readout((char *) (pevent + 1), 0);
00957
00958
00959 if (pevent->data_size) {
00960 interrupt_eq->bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
00961 interrupt_eq->events_sent++;
00962
00963 if (interrupt_eq->buffer_handle) {
00964 #ifdef USE_EVENT_CHANNEL
00965 dm_pointer_increment(interrupt_eq->buffer_handle,
00966 pevent->data_size + sizeof(EVENT_HEADER));
00967 #else
00968 rpc_send_event(interrupt_eq->buffer_handle, pevent,
00969 pevent->data_size + sizeof(EVENT_HEADER), SYNC);
00970 #endif
00971 }
00972
00973
00974 if (interrupt_eq->info.read_on & RO_ODB || interrupt_eq->info.history) {
00975 if (actual_millitime - interrupt_eq->last_called > ODB_UPDATE_TIME) {
00976 interrupt_eq->last_called = actual_millitime;
00977 memcpy(interrupt_odb_buffer, pevent,
00978 pevent->data_size + sizeof(EVENT_HEADER));
00979 interrupt_odb_buffer_valid = TRUE;
00980 interrupt_eq->odb_out++;
00981 }
00982 }
00983 } else
00984 interrupt_eq->serial_number--;
00985
00986 }
00987
00988
00989
00990 int message_print(const char *msg)
00991 {
00992 char str[160];
00993
00994 memset(str, ' ', 159);
00995 str[159] = 0;
00996
00997 if (msg[0] == '[')
00998 msg = strchr(msg, ']') + 2;
00999
01000 memcpy(str, msg, strlen(msg));
01001 ss_printf(0, 20, str);
01002
01003 return 0;
01004 }
01005
01006
01007
01008 void display(BOOL bInit)
01009 {
01010 INT i, status;
01011 time_t full_time;
01012 char str[30];
01013
01014 if (bInit) {
01015 ss_clear_screen();
01016
01017 if (host_name[0])
01018 strcpy(str, host_name);
01019 else
01020 strcpy(str, "<local>");
01021
01022 ss_printf(0, 0, "%s connected to %s. Press \"!\" to exit", full_frontend_name, str);
01023 ss_printf(0, 1,
01024 "================================================================================");
01025 ss_printf(0, 2, "Run status: %s",
01026 run_state == STATE_STOPPED ? "Stopped" : run_state ==
01027 STATE_RUNNING ? "Running" : "Paused");
01028 ss_printf(25, 2, "Run number %d ", run_number);
01029 ss_printf(0, 3,
01030 "================================================================================");
01031 ss_printf(0, 4,
01032 "Equipment Status Events Events/sec Rate[kB/s] ODB->FE FE->ODB");
01033 ss_printf(0, 5,
01034 "--------------------------------------------------------------------------------");
01035 for (i = 0; equipment[i].name[0]; i++)
01036 ss_printf(0, i + 6, "%s", equipment[i].name);
01037 }
01038
01039
01040 time(&full_time);
01041 strcpy(str, ctime(&full_time) + 11);
01042 str[8] = 0;
01043 ss_printf(72, 0, "%s", str);
01044
01045 for (i = 0; equipment[i].name[0]; i++) {
01046 status = equipment[i].status;
01047
01048 if ((status == 0 || status == FE_SUCCESS) && equipment[i].info.enabled)
01049 ss_printf(14, i + 6, "OK ");
01050 else if (!equipment[i].info.enabled)
01051 ss_printf(14, i + 6, "Disabled ");
01052 else if (status == FE_ERR_ODB)
01053 ss_printf(14, i + 6, "ODB Error");
01054 else if (status == FE_ERR_HW)
01055 ss_printf(14, i + 6, "HW Error ");
01056 else if (status == FE_ERR_DISABLED)
01057 ss_printf(14, i + 6, "Disabled ");
01058 else
01059 ss_printf(14, i + 6, "Unknown ");
01060
01061 if (equipment[i].stats.events_sent > 1E9)
01062 ss_printf(25, i + 6, "%1.3lfG ", equipment[i].stats.events_sent / 1E9);
01063 else if (equipment[i].stats.events_sent > 1E6)
01064 ss_printf(25, i + 6, "%1.3lfM ", equipment[i].stats.events_sent / 1E6);
01065 else
01066 ss_printf(25, i + 6, "%1.0lf ", equipment[i].stats.events_sent);
01067 ss_printf(36, i + 6, "%1.1lf ", equipment[i].stats.events_per_sec);
01068 ss_printf(47, i + 6, "%1.1lf ", equipment[i].stats.kbytes_per_sec);
01069 ss_printf(58, i + 6, "%ld ", equipment[i].odb_in);
01070 ss_printf(69, i + 6, "%ld ", equipment[i].odb_out);
01071 }
01072
01073
01074 ss_printf(0, i + 6, "");
01075 }
01076
01077
01078
01079 BOOL logger_root()
01080
01081 {
01082 int size, i, status;
01083 char str[80];
01084 HNDLE hKeyRoot, hKey;
01085
01086 if (db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot) == DB_SUCCESS) {
01087 for (i = 0;; i++) {
01088 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
01089 if (status == DB_NO_MORE_SUBKEYS)
01090 break;
01091
01092 strcpy(str, "MIDAS");
01093 size = sizeof(str);
01094 db_get_value(hDB, hKey, "Settings/Format", str, &size, TID_STRING, TRUE);
01095
01096 if (equal_ustring(str, "ROOT"))
01097 return TRUE;
01098 }
01099 }
01100
01101 return FALSE;
01102 }
01103
01104
01105
01106 INT scheduler(void)
01107 {
01108 EQUIPMENT_INFO *eq_info;
01109 EQUIPMENT *eq;
01110 EVENT_HEADER *pevent;
01111 DWORD last_time_network = 0, last_time_display = 0, last_time_flush = 0, readout_start;
01112 INT i, j, index, status, ch, source, size, state;
01113 char str[80];
01114 BOOL buffer_done, flag, force_update = FALSE;
01115
01116 INT opt_max = 0, opt_index = 0, opt_tcp_size = 128, opt_cnt = 0;
01117 INT err;
01118
01119 #ifdef OS_VXWORKS
01120 rpc_set_opt_tcp_size(1024);
01121 #ifdef PPCxxx
01122 rpc_set_opt_tcp_size(NET_TCP_SIZE);
01123 #endif
01124 #endif
01125
01126
01127
01128 do {
01129 actual_millitime = ss_millitime();
01130 actual_time = ss_time();
01131
01132
01133 for (index = 0;; index++) {
01134 eq = &equipment[index];
01135 eq_info = &eq->info;
01136
01137
01138 if (!eq->name[0])
01139 break;
01140
01141 if (!eq_info->enabled)
01142 continue;
01143
01144 if (eq->status != FE_SUCCESS)
01145 continue;
01146
01147
01148 if ((eq_info->eq_type & EQ_SLOW) && eq->status == FE_SUCCESS) {
01149 if (eq_info->event_limit > 0 && run_state == STATE_RUNNING) {
01150 if (actual_time - eq->last_idle >= (DWORD) eq_info->event_limit) {
01151 eq->cd(CMD_IDLE, eq);
01152 eq->last_idle = actual_time;
01153 }
01154 } else
01155 eq->cd(CMD_IDLE, eq);
01156 }
01157
01158 if (run_state == STATE_STOPPED && (eq_info->read_on & RO_STOPPED) == 0)
01159 continue;
01160 if (run_state == STATE_PAUSED && (eq_info->read_on & RO_PAUSED) == 0)
01161 continue;
01162 if (run_state == STATE_RUNNING && (eq_info->read_on & RO_RUNNING) == 0)
01163 continue;
01164
01165
01166 if ((eq_info->eq_type & EQ_PERIODIC) || (eq_info->eq_type & EQ_SLOW)) {
01167 if (eq_info->period == 0)
01168 continue;
01169
01170
01171 if (actual_millitime - eq->last_called >= (DWORD) eq_info->period) {
01172
01173 interrupt_enable(FALSE);
01174
01175
01176 status = send_event(index);
01177
01178 if (status != CM_SUCCESS) {
01179 cm_msg(MERROR, "scheduler", "send_event error %d", status);
01180 goto net_error;
01181 }
01182
01183
01184 interrupt_enable(TRUE);
01185 }
01186 }
01187
01188
01189
01190 if (eq_info->eq_type & EQ_POLLED) {
01191 readout_start = actual_millitime;
01192 pevent = NULL;
01193
01194 while ((source = poll_event(eq_info->source, eq->poll_count, FALSE)) > 0) {
01195 pevent = dm_pointer_get();
01196 if (pevent == NULL) {
01197 cm_msg(MERROR, "scheduler",
01198 "polled, dm_pointer_get not returning valid pointer");
01199 status = SS_NO_MEMORY;
01200 goto net_error;
01201 }
01202
01203
01204 pevent->event_id = eq_info->event_id;
01205 pevent->trigger_mask = eq_info->trigger_mask;
01206 pevent->data_size = 0;
01207 pevent->time_stamp = actual_time;
01208 pevent->serial_number = eq->serial_number;
01209
01210
01211
01212
01213 *(INT *) (pevent + 1) = source;
01214
01215 if (eq->info.num_subevents) {
01216 eq->subevent_number = 0;
01217 do {
01218 *(INT *) ((char *) (pevent + 1) + pevent->data_size) = source;
01219
01220
01221 size = eq->readout((char *) (pevent + 1), pevent->data_size);
01222 pevent->data_size += size;
01223 if (size > 0) {
01224 if (pevent->data_size + sizeof(EVENT_HEADER) >
01225 (DWORD) max_event_size) {
01226 cm_msg(MERROR, "scheduler",
01227 "Event size %ld larger than maximum size %d",
01228 (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01229 max_event_size);
01230 }
01231
01232 eq->subevent_number++;
01233 eq->serial_number++;
01234 }
01235
01236
01237 do {
01238 source = poll_event(eq_info->source, eq->poll_count, FALSE);
01239
01240 if (source == FALSE) {
01241 actual_millitime = ss_millitime();
01242
01243
01244 if (actual_millitime - readout_start > (DWORD) eq_info->period)
01245 break;
01246 }
01247 } while (source == FALSE);
01248
01249 } while (eq->subevent_number < eq->info.num_subevents && source);
01250
01251
01252 pevent->data_size = eq->readout((char *) (pevent + 1), -1);
01253 } else {
01254
01255 pevent->data_size = eq->readout((char *) (pevent + 1), 0);
01256
01257
01258 if (pevent->data_size + sizeof(EVENT_HEADER) > (DWORD) max_event_size) {
01259 cm_msg(MERROR, "scheduler",
01260 "Event size %ld larger than maximum size %d",
01261 (long) (pevent->data_size + sizeof(EVENT_HEADER)),
01262 max_event_size);
01263 }
01264
01265
01266 if (pevent->data_size)
01267 eq->serial_number++;
01268 }
01269
01270
01271 if (pevent->data_size) {
01272 if (eq->buffer_handle) {
01273
01274 if (pevent->serial_number == 1)
01275 if (logger_root())
01276 update_odb(pevent, eq->hkey_variables, eq->format);
01277
01278 #ifdef USE_EVENT_CHANNEL
01279 dm_pointer_increment(eq->buffer_handle,
01280 pevent->data_size + sizeof(EVENT_HEADER));
01281 #else
01282 status = rpc_send_event(eq->buffer_handle, pevent,
01283 pevent->data_size + sizeof(EVENT_HEADER),
01284 SYNC);
01285
01286 if (status != SUCCESS) {
01287 cm_msg(MERROR, "scheduler", "rpc_send_event error %d", status);
01288 goto net_error;
01289 }
01290 #endif
01291
01292 eq->bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
01293
01294 if (eq->info.num_subevents)
01295 eq->events_sent += eq->subevent_number;
01296 else
01297 eq->events_sent++;
01298 }
01299 }
01300
01301 actual_millitime = ss_millitime();
01302
01303
01304 if (actual_millitime - readout_start > (DWORD) eq_info->period)
01305 break;
01306
01307
01308 if (eq_info->event_limit > 0 &&
01309 eq->stats.events_sent + eq->events_sent >= eq_info->event_limit)
01310 break;
01311 }
01312
01313
01314 if (pevent && (eq_info->read_on & RO_ODB || eq_info->history)) {
01315 if (actual_millitime - eq->last_called > ODB_UPDATE_TIME && pevent != NULL) {
01316 eq->last_called = actual_millitime;
01317 update_odb(pevent, eq->hkey_variables, eq->format);
01318 eq->odb_out++;
01319 }
01320 }
01321 }
01322
01323
01324 if (eq_info->eq_type & EQ_INTERRUPT) {
01325
01326
01327
01328 if (interrupt_odb_buffer_valid) {
01329 update_odb(interrupt_odb_buffer, interrupt_eq->hkey_variables,
01330 interrupt_eq->format);
01331 interrupt_odb_buffer_valid = FALSE;
01332 }
01333
01334 }
01335
01336
01337 if (eq_info->eq_type != EQ_SLOW &&
01338 eq_info->event_limit > 0 &&
01339 eq->stats.events_sent + eq->events_sent >= eq_info->event_limit &&
01340 run_state == STATE_RUNNING) {
01341
01342 if (cm_transition(TR_STOP, 0, str, sizeof(str), SYNC, FALSE) != CM_SUCCESS)
01343 cm_msg(MERROR, "scheduler", "cannot stop run: %s", str);
01344
01345
01346 size = sizeof(BOOL);
01347 flag = FALSE;
01348 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
01349
01350 if (flag)
01351 auto_restart = ss_time() + 20;
01352
01353
01354 force_update = TRUE;
01355 }
01356 }
01357
01358
01359 if (frontend_call_loop) {
01360 status = frontend_loop();
01361 if (status != CM_SUCCESS)
01362 status = RPC_SHUTDOWN;
01363 }
01364
01365
01366 cm_check_deferred_transition();
01367
01368
01369 if (manual_trigger_event_id) {
01370 interrupt_enable(FALSE);
01371
01372
01373 status = BM_INVALID_PARAM;
01374 for (i = 0; equipment[i].name[0]; i++)
01375 if (equipment[i].info.event_id == manual_trigger_event_id) {
01376 status = send_event(i);
01377 break;
01378 }
01379
01380 manual_trigger_event_id = 0;
01381
01382 if (status != CM_SUCCESS) {
01383 cm_msg(MERROR, "scheduler", "send_event error %d", status);
01384 goto net_error;
01385 }
01386
01387
01388 interrupt_enable(TRUE);
01389 }
01390
01391
01392 if (force_update ||
01393 (display_period
01394 && actual_millitime - last_time_display > (DWORD) display_period)
01395 || (!display_period && actual_millitime - last_time_display > 3000)) {
01396 force_update = FALSE;
01397
01398
01399 if (actual_millitime != last_time_display) {
01400 max_bytes_per_sec = 0;
01401 for (i = 0; equipment[i].name[0]; i++) {
01402 eq = &equipment[i];
01403 eq->stats.events_sent += eq->events_sent;
01404 eq->stats.events_per_sec =
01405 eq->events_sent / ((actual_millitime - last_time_display) / 1000.0);
01406 eq->stats.kbytes_per_sec =
01407 eq->bytes_sent / 1024.0 / ((actual_millitime - last_time_display) /
01408 1000.0);
01409
01410 if ((INT) eq->bytes_sent > max_bytes_per_sec)
01411 max_bytes_per_sec = eq->bytes_sent;
01412
01413 eq->bytes_sent = 0;
01414 eq->events_sent = 0;
01415 }
01416
01417 max_bytes_per_sec = (DWORD)
01418 ((double) max_bytes_per_sec /
01419 ((actual_millitime - last_time_display) / 1000.0));
01420
01421
01422 if (optimize) {
01423 opt_max = MAX(opt_max, (INT) max_bytes_per_sec);
01424 ss_printf(0, opt_index, "%6d : %5.1lf %5.1lf", opt_tcp_size,
01425 opt_max / 1024.0, max_bytes_per_sec / 1024.0);
01426 if (++opt_cnt == 10) {
01427 opt_cnt = 0;
01428 opt_max = 0;
01429 opt_index++;
01430 opt_tcp_size = 1 << (opt_index + 7);
01431 rpc_set_opt_tcp_size(opt_tcp_size);
01432 if (1 << (opt_index + 7) > 0x8000) {
01433 opt_index = 0;
01434 opt_tcp_size = 1 << 7;
01435 rpc_set_opt_tcp_size(opt_tcp_size);
01436 }
01437 }
01438 }
01439
01440 }
01441
01442
01443 rpc_set_option(-1, RPC_OTRANSPORT, RPC_FTCP);
01444 db_send_changed_records();
01445 rpc_set_option(-1, RPC_OTRANSPORT, RPC_TCP);
01446
01447 if (display_period) {
01448 display(FALSE);
01449
01450
01451 ch = 0;
01452 status = 0;
01453 while (ss_kbhit()) {
01454 ch = ss_getchar(0);
01455 if (ch == -1)
01456 ch = getchar();
01457
01458 if (ch == '!')
01459 status = RPC_SHUTDOWN;
01460 }
01461
01462 if (ch > 0)
01463 display(TRUE);
01464 if (status == RPC_SHUTDOWN)
01465 break;
01466 }
01467
01468 last_time_display = actual_millitime;
01469 }
01470
01471
01472 if (actual_millitime - last_time_flush > 1000) {
01473 last_time_flush = actual_millitime;
01474
01475
01476
01477
01478 if (max_bytes_per_sec < SERVER_CACHE_SIZE) {
01479 interrupt_enable(FALSE);
01480
01481 #ifdef USE_EVENT_CHANNEL
01482 if ((status = dm_area_flush()) != CM_SUCCESS)
01483 cm_msg(MERROR, "scheduler", "dm_area_flush: %i", status);
01484 #endif
01485
01486 for (i = 0; equipment[i].name[0]; i++) {
01487 if (equipment[i].buffer_handle) {
01488
01489 buffer_done = FALSE;
01490 for (j = 0; j < i; j++)
01491 if (equipment[i].buffer_handle == equipment[j].buffer_handle) {
01492 buffer_done = TRUE;
01493 break;
01494 }
01495
01496 if (!buffer_done) {
01497 rpc_set_option(-1, RPC_OTRANSPORT, RPC_FTCP);
01498 rpc_flush_event();
01499 err = bm_flush_cache(equipment[i].buffer_handle, ASYNC);
01500 if (err != BM_SUCCESS) {
01501 cm_msg(MERROR, "scheduler", "bm_flush_cache(ASYNC) error %d",
01502 err);
01503 return err;
01504 }
01505 rpc_set_option(-1, RPC_OTRANSPORT, RPC_TCP);
01506 }
01507 }
01508 }
01509 interrupt_enable(TRUE);
01510 }
01511 }
01512
01513
01514 if (auto_restart > 0 && ss_time() > auto_restart) {
01515
01516 size = sizeof(state);
01517 status = db_get_value(hDB, 0, "Runinfo/State", &state, &size, TID_INT, TRUE);
01518 if (status != DB_SUCCESS)
01519 cm_msg(MERROR, "scheduler", "cannot get Runinfo/State in database");
01520
01521 if (state == STATE_STOPPED) {
01522 auto_restart = 0;
01523 size = sizeof(run_number);
01524 status =
01525 db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, &size, TID_INT,
01526 TRUE);
01527 assert(status == SUCCESS);
01528
01529 if (run_number <= 0) {
01530 cm_msg(MERROR, "main", "aborting on attempt to use invalid run number %d",
01531 run_number);
01532 abort();
01533 }
01534
01535 cm_msg(MTALK, "main", "starting new run");
01536 status = cm_transition(TR_START, run_number + 1, NULL, 0, SYNC, FALSE);
01537 if (status != CM_SUCCESS)
01538 cm_msg(MERROR, "main", "cannot restart run");
01539 }
01540 }
01541
01542
01543 if (run_state == STATE_RUNNING && interrupt_eq == NULL) {
01544
01545 if (actual_millitime - last_time_network > 100) {
01546 status = cm_yield(0);
01547 last_time_network = actual_millitime;
01548 } else
01549 status = RPC_SUCCESS;
01550 } else
01551
01552
01553 status = cm_yield(100);
01554
01555
01556 if (fe_stop)
01557 status = RPC_SHUTDOWN;
01558
01559 } while (status != RPC_SHUTDOWN && status != SS_ABORT);
01560
01561 net_error:
01562
01563 return status;
01564 }
01565
01566
01567
01568 INT get_frontend_index()
01569 {
01570 return frontend_index;
01571 }
01572
01573
01574
01575 #ifdef OS_VXWORKS
01576 int mfe(char *ahost_name, char *aexp_name, BOOL adebug)
01577 #else
01578 int main(int argc, char *argv[])
01579 #endif
01580 {
01581 INT status, i, dm_size;
01582 INT daemon;
01583
01584 host_name[0] = 0;
01585 exp_name[0] = 0;
01586 debug = FALSE;
01587 daemon = 0;
01588
01589 setbuf(stdout, 0);
01590 setbuf(stderr, 0);
01591
01592 #ifdef SIGPIPE
01593 signal(SIGPIPE, SIG_IGN);
01594 #endif
01595
01596 #ifdef OS_VXWORKS
01597 if (ahost_name)
01598 strcpy(host_name, ahost_name);
01599 if (aexp_name)
01600 strcpy(exp_name, aexp_name);
01601 debug = adebug;
01602 #else
01603
01604
01605 cm_get_environment(host_name, sizeof(host_name), exp_name, sizeof(exp_name));
01606
01607
01608 for (i = 1; i < argc; i++) {
01609 if (argv[i][0] == '-' && argv[i][1] == 'd')
01610 debug = TRUE;
01611 else if (argv[i][0] == '-' && argv[i][1] == 'D')
01612 daemon = 1;
01613 else if (argv[i][0] == '-' && argv[i][1] == 'O')
01614 daemon = 2;
01615 else if (argv[i][0] == '-') {
01616 if (i + 1 >= argc || argv[i + 1][0] == '-')
01617 goto usage;
01618 if (argv[i][1] == 'e')
01619 strcpy(exp_name, argv[++i]);
01620 else if (argv[i][1] == 'h')
01621 strcpy(host_name, argv[++i]);
01622 else if (argv[i][1] == 'i')
01623 frontend_index = atoi(argv[++i]);
01624 else {
01625 usage:
01626 printf("usage: frontend [-h Hostname] [-e Experiment] [-d] [-D] [-O] [-i n]\n");
01627 printf(" [-d] Used to debug the frontend\n");
01628 printf(" [-D] Become a daemon\n");
01629 printf(" [-O] Become a daemon but keep stdout\n");
01630 printf(" [-i n] Set frontend index (used for event building)\n");
01631 return 0;
01632 }
01633 }
01634 }
01635 #endif
01636
01637
01638 if (event_buffer_size < 2 * max_event_size) {
01639 printf("event_buffer_size too small for max. event size\n");
01640 ss_sleep(5000);
01641 return 1;
01642 }
01643
01644 if (max_event_size > MAX_EVENT_SIZE) {
01645 printf("Requested max_event_size (%d) exceeds max. system event size (%d)",
01646 max_event_size, MAX_EVENT_SIZE);
01647 ss_sleep(5000);
01648 return 1;
01649 }
01650
01651 dm_size = event_buffer_size;
01652
01653 #ifdef OS_VXWORKS
01654
01655
01656 dm_size = 2 * 10 * (max_event_size + sizeof(EVENT_HEADER) + sizeof(INT));
01657 if (dm_size > memFindMax()) {
01658 cm_msg(MERROR, "mainFE", "Not enough mem space for event size");
01659 return 0;
01660 }
01661
01662 dm_size = 0.2 * memFindMax();
01663
01664
01665 dm_size /= 2;
01666 #endif
01667
01668
01669 #ifdef OS_MSDOS
01670 if (dm_size > 0x4000)
01671 dm_size = 0x4000;
01672 #endif
01673
01674
01675 strcpy(full_frontend_name, frontend_name);
01676 if (frontend_index >= 0)
01677 sprintf(full_frontend_name+strlen(full_frontend_name), "%02d", frontend_index);
01678
01679
01680 printf("Frontend name : %s\n", full_frontend_name);
01681 printf("Event buffer size : %d\n", event_buffer_size);
01682 printf("Buffer allocation : 2 x %d\n", dm_size);
01683 printf("System max event size : %d\n", MAX_EVENT_SIZE);
01684 printf("User max event size : %d\n", max_event_size);
01685 if (max_event_size_frag > 0)
01686 printf("User max frag. size : %d\n", max_event_size_frag);
01687 printf("# of events per buffer : %d\n\n", dm_size / max_event_size);
01688
01689 if (daemon) {
01690 printf("\nBecoming a daemon...\n");
01691 ss_daemon_init(daemon == 2);
01692 }
01693
01694
01695 if (display_period) {
01696 if (host_name[0])
01697 printf("Connect to experiment %s on host %s...", exp_name, host_name);
01698 else
01699 printf("Connect to experiment %s...", exp_name);
01700 }
01701
01702 status = cm_connect_experiment1(host_name, exp_name, full_frontend_name,
01703 NULL, DEFAULT_ODB_SIZE, DEFAULT_FE_TIMEOUT);
01704 if (status != CM_SUCCESS) {
01705
01706 ss_sleep(5000);
01707 return 1;
01708 }
01709
01710 if (display_period)
01711 printf("OK\n");
01712
01713
01714 status = dm_buffer_create(dm_size, max_event_size);
01715 if (status != CM_SUCCESS) {
01716 printf("dm_buffer_create: Not enough memory or event too big\n");
01717 return 1;
01718 }
01719
01720
01721 cm_cleanup(full_frontend_name, FALSE);
01722
01723
01724 status = cm_shutdown(full_frontend_name, FALSE);
01725 if (status == CM_SUCCESS && display_period) {
01726 printf("Previous frontend stopped\n");
01727
01728
01729 ss_sleep(3000);
01730 }
01731
01732
01733 if (cm_register_transition(TR_START, tr_start, 500) != CM_SUCCESS ||
01734 cm_register_transition(TR_STOP, tr_stop, 500) != CM_SUCCESS ||
01735 cm_register_transition(TR_PAUSE, tr_pause, 500) != CM_SUCCESS ||
01736 cm_register_transition(TR_RESUME, tr_resume, 500) != CM_SUCCESS) {
01737 printf("Failed to start local RPC server");
01738 cm_disconnect_experiment();
01739 dm_buffer_release();
01740
01741
01742 ss_sleep(5000);
01743 return 1;
01744 }
01745
01746 cm_get_experiment_database(&hDB, &status);
01747
01748
01749 #ifdef OS_VXWORKS
01750 cm_synchronize(NULL);
01751 #endif
01752
01753
01754 if (debug)
01755 cm_set_watchdog_params(TRUE, 0);
01756
01757
01758 rpc_set_option(-1, RPC_OTIMEOUT, 120000);
01759
01760
01761 if (display_period)
01762 cm_set_msg_print(MT_ALL, MT_ALL, message_print);
01763
01764
01765 if (display_period)
01766 printf("Init hardware...");
01767 if (frontend_init() != SUCCESS) {
01768 if (display_period)
01769 printf("\n");
01770 cm_disconnect_experiment();
01771 dm_buffer_release();
01772
01773
01774 ss_sleep(5000);
01775 return 1;
01776 }
01777
01778
01779 if (register_equipment() != SUCCESS) {
01780 if (display_period)
01781 printf("\n");
01782 cm_disconnect_experiment();
01783 dm_buffer_release();
01784
01785
01786 ss_sleep(5000);
01787 return 1;
01788 }
01789
01790 if (display_period)
01791 printf("OK\n");
01792
01793
01794 if (display_period) {
01795 ss_sleep(1000);
01796 display(TRUE);
01797 }
01798
01799
01800 if (interrupt_eq && run_state == STATE_RUNNING)
01801 interrupt_enable(TRUE);
01802
01803
01804 ss_getchar(0);
01805
01806
01807 status = scheduler();
01808
01809
01810 ss_getchar(TRUE);
01811
01812
01813 if (interrupt_eq) {
01814 interrupt_configure(CMD_INTERRUPT_DISABLE, 0, 0);
01815 interrupt_configure(CMD_INTERRUPT_DETACH, 0, 0);
01816 if (interrupt_odb_buffer)
01817 free(interrupt_odb_buffer);
01818 }
01819
01820
01821 if (interrupt_eq != NULL)
01822 interrupt_configure(CMD_INTERRUPT_DETACH, interrupt_eq->info.source, 0);
01823
01824
01825 frontend_exit();
01826
01827
01828 for (i = 0; equipment[i].name[0]; i++)
01829 if ((equipment[i].info.eq_type & EQ_SLOW) && equipment[i].status == FE_SUCCESS)
01830 equipment[i].cd(CMD_EXIT, &equipment[i]);
01831
01832
01833 cm_disconnect_experiment();
01834
01835 if (display_period) {
01836 if (status == RPC_SHUTDOWN) {
01837 ss_clear_screen();
01838 ss_printf(0, 0, "Frontend shut down.");
01839 ss_printf(0, 1, "");
01840 }
01841 }
01842
01843 if (status != RPC_SHUTDOWN)
01844 printf("Network connection aborted.\n");
01845
01846 dm_buffer_release();
01847
01848 return 0;
01849 }