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