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