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