00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "midas.h"
00013 #include "msystem.h"
00014 #include "hardware.h"
00015 #include "ftplib.h"
00016 #include "mcstd.h"
00017
00018 #define HAVE_LOGGING
00019 #include "mdsupport.h"
00020
00021
00022 #ifdef OS_WINNT
00023 #define VISUAL_CPLUSPLUS
00024 #endif
00025
00026 #ifdef OS_LINUX
00027 #define f2cFortran
00028 #endif
00029
00030 #ifdef HAVE_MYSQL
00031 #ifdef OS_UNIX
00032 #include <mysql/mysql.h>
00033 #include <mysql/mysqld_error.h>
00034 #endif
00035 #ifdef OS_WINNT
00036 #include <mysql.h>
00037 #include <mysqld_error.h>
00038 int errno;
00039 #endif
00040 void create_sql_tree();
00041 #endif
00042
00043 #ifdef USE_ROOT
00044 #include <TTree.h>
00045 #include <TLeaf.h>
00046 #endif
00047
00048 #ifndef MANA_LITE
00049 #include <cfortran.h>
00050 #include <hbook.h>
00051
00052
00053 #ifndef HFNOV
00054 #define HFNOV(A1,A2) CCALLSFSUB2(HFNOV,hfnov,INT,FLOATV,A1,A2)
00055 #endif
00056 #endif // MANA_LITE
00057
00058
00059
00060 #define FAL_MAIN
00061
00062 #define LOGGER_TIMEOUT 60000
00063
00064 #define SERVER_CACHE_SIZE 100000
00065
00066 #define ODB_UPDATE_TIME 1000
00067
00068 #define MAX_CHANNELS 10
00069 #define MAX_EVENTS 10
00070 #define MAX_HISTORY 20
00071
00072 char *fal_name = "FAL";
00073
00074 #ifndef DEBUG_TRANS
00075 #define DEBUG_TRANS 0
00076 #endif
00077
00078 BOOL in_stop_transition = FALSE;
00079 DWORD auto_restart = 0;
00080 BOOL tape_message = TRUE;
00081 BOOL verbose = FALSE;
00082
00083 LOG_CHN log_chn[MAX_CHANNELS];
00084
00085 struct hist_log_struct {
00086 WORD event_id;
00087 void *buffer;
00088 INT buffer_size;
00089 HNDLE hKeyVar;
00090 DWORD period;
00091 DWORD last_log;
00092 } hist_log[MAX_HISTORY];
00093
00094 INT run_state;
00095 INT run_number;
00096 DWORD actual_time;
00097 DWORD actual_millitime;
00098 char event_buffer[NET_BUFFER_SIZE];
00099 char host_name[HOST_NAME_LENGTH];
00100 char exp_name[NAME_LENGTH];
00101 HNDLE hDB;
00102
00103
00104 struct out_info_struct {
00105 char filename[256];
00106 BOOL rwnt;
00107 BOOL histo_dump;
00108 char histo_dump_filename[256];
00109 BOOL clear_histos;
00110 char last_histo_filename[256];
00111 BOOL events_to_odb;
00112 char global_memory_name[8];
00113 } out_info;
00114
00115
00116
00117 #ifdef extname
00118 int *pawc_;
00119 int quest_[100];
00120 #else
00121 int *PAWC;
00122 extern int QUEST[100];
00123 #endif
00124
00125 char *bstr = " ";
00126
00127
00128
00129 CHN_SETTINGS_STR(chn_settings_str);
00130
00131 #define EQUIPMENT_COMMON_STR "\
00132 Event ID = WORD : 0\n\
00133 Trigger mask = WORD : 0\n\
00134 Buffer = STRING : [32] SYSTEM\n\
00135 Type = INT : 0\n\
00136 Source = INT : 0\n\
00137 Format = STRING : [8] FIXED\n\
00138 Enabled = BOOL : 0\n\
00139 Read on = INT : 0\n\
00140 Period = INT : 0\n\
00141 Event limit = DOUBLE : 0\n\
00142 Num subevents = DWORD : 0\n\
00143 Log history = INT : 0\n\
00144 Frontend host = STRING : [32] \n\
00145 Frontend name = STRING : [32] \n\
00146 Frontend file name = STRING : [256] \n\
00147 "
00148
00149 #define EQUIPMENT_STATISTICS_STR "\
00150 Events sent = DOUBLE : 0\n\
00151 Events per sec. = DOUBLE : 0\n\
00152 kBytes per sec. = DOUBLE : 0\n\
00153 "
00154
00155 #define ANALYZER_REQUEST_STR "\
00156 Event ID = INT : 0\n\
00157 Trigger mask = INT : -1\n\
00158 Sampling type = INT : 1\n\
00159 Buffer = STRING : [32] SYSTEM\n\
00160 Enabled = BOOL : 1\n\
00161 Client name = STRING : [32] \n\
00162 Host = STRING : [32] \n\
00163 "
00164
00165 #define ANALYZER_STATS_STR "\
00166 Events received = DOUBLE : 0\n\
00167 Events per sec. = DOUBLE : 0\n\
00168 Events written = DOUBLE : 0\n\
00169 "
00170
00171 #define OUT_INFO_STR "\
00172 Filename = STRING : [256] run%05d.asc\n\
00173 RWNT = BOOL : 0\n\
00174 Histo Dump = BOOL : 0\n\
00175 Histo Dump Filename = STRING : [256] his%05d.rz\n\
00176 Clear histos = BOOL : 1\n\
00177 Last Histo Filename = STRING : [256] last.rz\n\
00178 Events to ODB = BOOL : 0\n\
00179 Global Memory Name = STRING : [8] ONLN\n\
00180 "
00181
00182
00183
00184 typedef struct {
00185 char *buffer;
00186 char *write_pointer;
00187 } MIDAS_INFO;
00188
00189
00190
00191
00192
00193 void send_event(INT index);
00194 void display(BOOL binit);
00195 void send_all_periodic_events(INT transition);
00196 void receive_event(HNDLE hBuf, HNDLE request_id, EVENT_HEADER * pevent);
00197 INT log_write(LOG_CHN * log_chn, EVENT_HEADER * pevent);
00198 void log_system_history(HNDLE hDB, HNDLE hKey, void *info);
00199 int print_message(const char *msg);
00200 void update_stats();
00201 void interrupt_routine(void);
00202 void interrupt_enable(BOOL flag);
00203 INT tr_start_fal(int run_number, char *error);
00204
00205
00206
00207 extern char *frontend_name;
00208 extern char *frontend_file_name;
00209 extern BOOL frontend_call_loop;
00210 extern char *frontend_file_name;
00211 extern INT display_period;
00212 extern INT frontend_init(void);
00213 extern INT frontend_exit(void);
00214 extern INT frontend_loop(void);
00215 extern INT begin_of_run(INT run_number, char *error);
00216 extern INT end_of_run(INT run_number, char *error);
00217 extern INT pause_run(INT run_number, char *error);
00218 extern INT resume_run(INT run_number, char *error);
00219 extern EQUIPMENT equipment[];
00220 extern INT poll_event(INT source, INT count, BOOL test);
00221 extern INT interrupt_configure(INT cmd, INT source, POINTER_T adr);
00222
00223
00224
00225 extern INT pawc_size;
00226 extern char *analyzer_name;
00227 extern INT analyzer_loop_period;
00228 extern INT analyzer_init(void);
00229 extern INT analyzer_exit(void);
00230 extern INT analyzer_loop(void);
00231 extern INT ana_begin_of_run(INT run_number, char *error);
00232 extern INT ana_end_of_run(INT run_number, char *error);
00233 extern INT ana_pause_run(INT run_number, char *error);
00234 extern INT ana_resume_run(INT run_number, char *error);
00235 extern ANALYZE_REQUEST analyze_request[];
00236 extern INT odb_size;
00237
00238 EQUIPMENT *interrupt_eq = NULL;
00239 EVENT_HEADER *interrupt_odb_buffer;
00240 BOOL interrupt_odb_buffer_valid;
00241
00242
00243
00244
00245
00246
00247
00248 void logger_init()
00249 {
00250 INT size, status;
00251 BOOL flag;
00252 HNDLE hKey;
00253 char str[256];
00254
00255
00256
00257 cm_get_path(str);
00258 size = sizeof(str);
00259 db_get_value(hDB, 0, "/Logger/Data dir", str, &size, TID_STRING, TRUE);
00260
00261 strcpy(str, "midas.log");
00262 size = sizeof(str);
00263 db_get_value(hDB, 0, "/Logger/Message file", str, &size, TID_STRING, TRUE);
00264
00265 size = sizeof(BOOL);
00266 flag = TRUE;
00267 db_get_value(hDB, 0, "/Logger/Write data", &flag, &size, TID_BOOL, TRUE);
00268
00269 flag = FALSE;
00270 db_get_value(hDB, 0, "/Logger/ODB Dump", &flag, &size, TID_BOOL, TRUE);
00271
00272 strcpy(str, "run%05d.odb");
00273 size = sizeof(str);
00274 db_get_value(hDB, 0, "/Logger/ODB Dump File", str, &size, TID_STRING, TRUE);
00275
00276 flag = FALSE;
00277 size = sizeof(BOOL);
00278 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
00279
00280 flag = TRUE;
00281 db_get_value(hDB, 0, "/Logger/Tape message", &flag, &size, TID_BOOL, TRUE);
00282
00283
00284 status = db_find_key(hDB, 0, "/Logger/Channels/0", &hKey);
00285 if (status != DB_SUCCESS) {
00286
00287 status = db_create_record(hDB, 0, "/Logger/Channels/0", strcomb(chn_settings_str));
00288 if (status != DB_SUCCESS)
00289 cm_msg(MERROR, "logger_init", "Cannot create channel entry in database");
00290 }
00291 #ifdef HAVE_MYSQL
00292 create_sql_tree();
00293 #endif
00294 }
00295
00296
00297
00298 void log_odb_dump(LOG_CHN * log_chn, short int event_id, INT run_number)
00299 {
00300 INT status, buffer_size, size;
00301 EVENT_HEADER *pevent;
00302
00303
00304 buffer_size = 10000;
00305 do {
00306 pevent = (EVENT_HEADER *) malloc(buffer_size);
00307 if (pevent == NULL) {
00308 cm_msg(MERROR, "log_odb_dump", "Cannot allocate ODB dump buffer");
00309 break;
00310 }
00311
00312 size = buffer_size - sizeof(EVENT_HEADER);
00313 status = db_copy_xml(hDB, 0, (char *) (pevent + 1), &size);
00314
00315
00316
00317 if (status != DB_TRUNCATED) {
00318 bm_compose_event(pevent, event_id, MIDAS_MAGIC,
00319 buffer_size - sizeof(EVENT_HEADER) - size + 1, run_number);
00320 log_write(log_chn, pevent);
00321 free(pevent);
00322 break;
00323 }
00324
00325
00326 free(pevent);
00327 buffer_size *= 2;
00328 } while (1);
00329 }
00330
00331
00332
00333 void odb_save(char *filename)
00334 {
00335 int size;
00336 char dir[256];
00337 char path[256];
00338
00339 if (strchr(filename, DIR_SEPARATOR) == NULL) {
00340 size = sizeof(dir);
00341 dir[0] = 0;
00342 db_get_value(hDB, 0, "/Logger/Data Dir", dir, &size, TID_STRING, TRUE);
00343 if (dir[0] != 0)
00344 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
00345 strcat(dir, DIR_SEPARATOR_STR);
00346 strcpy(path, dir);
00347 strcat(path, filename);
00348 } else
00349 strcpy(path, filename);
00350
00351 if (strstr(filename, ".xml") || strstr(filename, ".XML"))
00352 db_save_xml(hDB, 0, path);
00353 else
00354 db_save(hDB, 0, path, FALSE);
00355 }
00356
00357
00358 #ifdef HAVE_MYSQL
00359
00360
00361
00362
00363
00364 typedef struct {
00365 char column_name[NAME_LENGTH];
00366 char column_type[NAME_LENGTH];
00367 char data[256];
00368 } SQL_LIST;
00369
00370 char *mname[] = {
00371 "January",
00372 "February",
00373 "March",
00374 "April",
00375 "May",
00376 "June",
00377 "July",
00378 "August",
00379 "September",
00380 "October",
00381 "November",
00382 "December"
00383 };
00384
00385 void ctime_to_datetime(char *date)
00386 {
00387 char ctime_date[30];
00388 struct tm tms;
00389 int i;
00390
00391 strlcpy(ctime_date, date, sizeof(ctime_date));
00392 memset(&tms, 0, sizeof(struct tm));
00393
00394 for (i = 0; i < 12; i++)
00395 if (strncmp(ctime_date + 4, mname[i], 3) == 0)
00396 break;
00397 tms.tm_mon = i;
00398
00399 tms.tm_mday = atoi(ctime_date + 8);
00400 tms.tm_hour = atoi(ctime_date + 11);
00401 tms.tm_min = atoi(ctime_date + 14);
00402 tms.tm_sec = atoi(ctime_date + 17);
00403 tms.tm_year = atoi(ctime_date + 20) - 1900;
00404 tms.tm_isdst = -1;
00405
00406 if (tms.tm_year < 90)
00407 tms.tm_year += 100;
00408
00409 mktime(&tms);
00410 sprintf(date, "%d-%02d-%02d %02d-%02d-%02d",
00411 tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
00412 tms.tm_hour, tms.tm_min, tms.tm_sec);
00413 }
00414
00415
00416
00417 int mysql_query_debug(MYSQL * db, char *query)
00418 {
00419 int status;
00420
00421
00422
00423
00424 status = mysql_query(db, query);
00425
00426 if (status)
00427 cm_msg(MERROR, "mysql_query_debug", "SQL error: %s", mysql_error(db));
00428
00429 return status;
00430 }
00431
00432
00433
00434 int sql_get_columns(HNDLE hKeyRoot, SQL_LIST ** sql_list)
00435 {
00436 HNDLE hKey;
00437 int n, i, size, status;
00438 KEY key;
00439 char str[256], data[256];
00440
00441 for (i = 0;; i++) {
00442 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
00443 if (status == DB_NO_MORE_SUBKEYS)
00444 break;
00445 }
00446
00447 if (i == 0)
00448 return 0;
00449
00450 n = i;
00451
00452 *sql_list = (SQL_LIST *) malloc(sizeof(SQL_LIST) * n);
00453
00454 for (i = 0; i < n; i++) {
00455
00456
00457 db_enum_link(hDB, hKeyRoot, i, &hKey);
00458 db_get_key(hDB, hKey, &key);
00459 strlcpy((*sql_list)[i].column_name, key.name, NAME_LENGTH);
00460
00461
00462 db_enum_key(hDB, hKeyRoot, i, &hKey);
00463 db_get_key(hDB, hKey, &key);
00464
00465
00466 size = sizeof(data);
00467 db_get_data(hDB, hKey, data, &size, key.type);
00468 db_sprintf(str, data, size, 0, key.type);
00469 strcpy((*sql_list)[i].data, str);
00470
00471 if (key.type == TID_STRING) {
00472
00473 if (strlen(str) == 24 && str[10] == ' ' && str[13] == ':') {
00474 strcpy(str, "DATETIME");
00475 ctime_to_datetime((*sql_list)[i].data);
00476 } else if (key.item_size < 256)
00477 sprintf(str, "VARCHAR (%d)", key.item_size);
00478 else
00479 sprintf(str, " TEXT");
00480
00481 } else {
00482 switch (key.type) {
00483 case TID_BYTE:
00484 strcpy(str, "TINYINT UNSIGNED ");
00485 break;
00486 case TID_SBYTE:
00487 strcpy(str, "TINYINT ");
00488 break;
00489 case TID_CHAR:
00490 strcpy(str, "CHAR ");
00491 break;
00492 case TID_WORD:
00493 strcpy(str, "SMALLINT UNSIGNED ");
00494 break;
00495 case TID_SHORT:
00496 strcpy(str, "SMALLINT ");
00497 break;
00498 case TID_DWORD:
00499 strcpy(str, "INT UNSIGNED ");
00500 break;
00501 case TID_INT:
00502 strcpy(str, "INT ");
00503 break;
00504 case TID_BOOL:
00505 strcpy(str, "BOOLEAN ");
00506 break;
00507 case TID_FLOAT:
00508 strcpy(str, "FLOAT ");
00509 break;
00510 case TID_DOUBLE:
00511 strcpy(str, "DOUBLE ");
00512 break;
00513 default:
00514 cm_msg(MERROR, "sql_create_database",
00515 "No SQL type mapping for key \"%s\" of type %s", key.name,
00516 rpc_tid_name(key.type));
00517 }
00518 }
00519
00520 strcpy((*sql_list)[i].column_type, str);
00521 }
00522
00523 return n;
00524 }
00525
00526
00527
00528 BOOL sql_create_table(MYSQL * db, char *database, char *table, HNDLE hKeyRoot)
00529 {
00530 char str[256], query[5000];
00531 int i, n_col;
00532 SQL_LIST *sql_list;
00533
00534 sprintf(query, "CREATE TABLE `%s`.`%s` (", database, table);
00535
00536 n_col = sql_get_columns(hKeyRoot, &sql_list);
00537 if (n_col == 0) {
00538 db_get_path(hDB, hKeyRoot, str, sizeof(str));
00539 cm_msg(MERROR, "sql_create_database", "ODB tree \"%s\" contains no variables", str);
00540 return FALSE;
00541 }
00542
00543 for (i = 0; i < n_col; i++)
00544 sprintf(query + strlen(query), "`%s` %s NOT NULL, ", sql_list[i].column_name,
00545 sql_list[i].column_type);
00546
00547 sprintf(query + strlen(query), "PRIMARY KEY (`%s`))", sql_list[0].column_name);
00548 free(sql_list);
00549
00550 if (mysql_query_debug(db, query)) {
00551 cm_msg(MERROR, "sql_create_table", "Failed to create table: Error: %s",
00552 mysql_error(db));
00553 return FALSE;
00554 }
00555
00556 return TRUE;
00557 }
00558
00559
00560
00561 BOOL sql_modify_table(MYSQL * db, char *database, char *table, HNDLE hKeyRoot)
00562 {
00563 char str[256], query[5000];
00564 int i, n_col;
00565 SQL_LIST *sql_list;
00566
00567 n_col = sql_get_columns(hKeyRoot, &sql_list);
00568 if (n_col == 0) {
00569 db_get_path(hDB, hKeyRoot, str, sizeof(str));
00570 cm_msg(MERROR, "sql_modify_table", "ODB tree \"%s\" contains no variables", str);
00571 return FALSE;
00572 }
00573
00574 for (i = 0; i < n_col; i++) {
00575
00576
00577 if (i == 0)
00578 sprintf(query, "ALTER TABLE `%s`.`%s` ADD `%s` %s",
00579 database, table, sql_list[i].column_name, sql_list[i].column_type);
00580 else
00581 sprintf(query, "ALTER TABLE `%s`.`%s` ADD `%s` %s AFTER `%s`",
00582 database, table, sql_list[i].column_name, sql_list[i].column_type,
00583 sql_list[i - 1].column_name);
00584
00585 if (mysql_query_debug(db, query)) {
00586 if (mysql_errno(db) == ER_DUP_FIELDNAME) {
00587
00588
00589 sprintf(query, "ALTER TABLE `%s`.`%s` MODIFY `%s` %s",
00590 database, table, sql_list[i].column_name, sql_list[i].column_type);
00591
00592 if (mysql_query_debug(db, query)) {
00593 free(sql_list);
00594 cm_msg(MERROR, "sql_modify_table", "Failed to modify column: Error: %s",
00595 mysql_error(db));
00596 return FALSE;
00597 }
00598
00599 } else {
00600 free(sql_list);
00601 cm_msg(MERROR, "sql_modify_table", "Failed to add column: Error: %s",
00602 mysql_error(db));
00603 return FALSE;
00604 }
00605 }
00606 }
00607
00608 cm_msg(MINFO, "sql_insert", "SQL table \"%s\" modified successfully", table);
00609
00610 return TRUE;
00611 }
00612
00613
00614
00615 BOOL sql_create_database(MYSQL * db, char *database)
00616 {
00617 char query[256];
00618
00619 sprintf(query, "CREATE DATABASE `%s`", database);
00620 if (mysql_query_debug(db, query)) {
00621 cm_msg(MERROR, "sql_create_database", "Failed to create database: Error: %s",
00622 mysql_error(db));
00623 return FALSE;
00624 }
00625
00626
00627 sprintf(query, "USE `%s`", database);
00628 if (mysql_query_debug(db, query)) {
00629 cm_msg(MERROR, "sql_create_database", "Failed to select database: Error: %s",
00630 mysql_error(db));
00631 return FALSE;
00632 }
00633
00634 return TRUE;
00635 }
00636
00637
00638
00639 int sql_insert(MYSQL * db, char *database, char *table, HNDLE hKeyRoot, BOOL create_flag)
00640 {
00641 char query[5000], *pstr;
00642 int status, i, j, n_col;
00643 SQL_LIST *sql_list;
00644
00645
00646
00647
00648
00649 sprintf(query, "INSERT INTO `%s`.`%s` (", database, table);
00650 n_col = sql_get_columns(hKeyRoot, &sql_list);
00651 if (n_col == 0)
00652 return DB_SUCCESS;
00653
00654 for (i = 0; i < n_col; i++) {
00655 sprintf(query + strlen(query), "`%s`", sql_list[i].column_name);
00656 if (i < n_col - 1)
00657 strcat(query, ", ");
00658 }
00659
00660 strlcat(query, ") VALUES (", sizeof(query));
00661
00662 for (i = 0; i < n_col; i++) {
00663 strcat(query, "'");
00664
00665
00666 for (j = 0; j < (int) strlen(sql_list[i].data); j++) {
00667 if (sql_list[i].data[j] == '\\')
00668 strcat(query, "\\\\");
00669 else {
00670 pstr = query + strlen(query);
00671 *pstr++ = sql_list[i].data[j];
00672 *pstr = 0;
00673 }
00674 }
00675
00676 strcat(query, "'");
00677
00678 if (i < n_col - 1)
00679 strcat(query, ", ");
00680 }
00681
00682 free(sql_list);
00683 strlcat(query, ")", sizeof(query));
00684 if (mysql_query_debug(db, query)) {
00685
00686
00687 if (mysql_errno(db) == ER_DUP_ENTRY) {
00688
00689 return ER_DUP_ENTRY;
00690
00691 } else if (mysql_errno(db) == ER_NO_SUCH_TABLE && create_flag) {
00692
00693
00694 sql_create_table(db, database, table, hKeyRoot);
00695 if (mysql_query_debug(db, query)) {
00696 cm_msg(MERROR, "sql_insert", "Failed to update database: Error: %s",
00697 mysql_error(db));
00698 return mysql_errno(db);
00699 }
00700 } else if (mysql_errno(db) == ER_BAD_FIELD_ERROR && create_flag) {
00701
00702
00703 sql_modify_table(db, database, table, hKeyRoot);
00704 if (mysql_query_debug(db, query)) {
00705 cm_msg(MERROR, "sql_insert", "Failed to update database: Error: %s",
00706 mysql_error(db));
00707 return mysql_errno(db);
00708 }
00709
00710 } else {
00711 status = mysql_errno(db);
00712 cm_msg(MERROR, "sql_insert", "Failed to update database: Error: %s",
00713 mysql_error(db));
00714 return mysql_errno(db);
00715 }
00716 }
00717
00718 return DB_SUCCESS;
00719 }
00720
00721
00722
00723 int sql_update(MYSQL * db, char *database, char *table, HNDLE hKeyRoot, BOOL create_flag,
00724 char *where)
00725 {
00726 char query[5000];
00727 int i, n_col;
00728 SQL_LIST *sql_list;
00729
00730
00731
00732
00733
00734
00735 sprintf(query, "UPDATE `%s`.`%s` SET ", database, table);
00736 n_col = sql_get_columns(hKeyRoot, &sql_list);
00737 if (n_col == 0)
00738 return DB_SUCCESS;
00739
00740 for (i = 0; i < n_col; i++) {
00741 sprintf(query + strlen(query), "`%s`='%s'", sql_list[i].column_name,
00742 sql_list[i].data);
00743 if (i < n_col - 1)
00744 strcat(query, ", ");
00745 }
00746 free(sql_list);
00747
00748 sprintf(query + strlen(query), " %s", where);
00749 if (mysql_query_debug(db, query)) {
00750 if (mysql_errno(db) == ER_NO_SUCH_TABLE && create_flag) {
00751
00752
00753 sql_create_table(db, database, table, hKeyRoot);
00754 return sql_insert(db, database, table, hKeyRoot, create_flag);
00755
00756 } else if (mysql_errno(db) == ER_BAD_FIELD_ERROR && create_flag) {
00757
00758
00759 sql_modify_table(db, database, table, hKeyRoot);
00760 if (mysql_query_debug(db, query)) {
00761 cm_msg(MERROR, "sql_update", "Failed to update database: Error: %s",
00762 mysql_error(db));
00763 return mysql_errno(db);
00764 }
00765
00766 } else {
00767 cm_msg(MERROR, "sql_update", "Failed to update database: Error: %s",
00768 mysql_error(db));
00769 return mysql_errno(db);
00770 }
00771 }
00772
00773 return DB_SUCCESS;
00774 }
00775
00776
00777
00778 void create_sql_tree()
00779 {
00780 char hostname[80], username[80], password[80], database[80], table[80];
00781 int size, write_flag, create_flag;
00782 HNDLE hKeyRoot, hKey;
00783
00784 size = sizeof(create_flag);
00785 create_flag = 0;
00786 db_get_value(hDB, 0, "/Logger/SQL/Create database", &create_flag, &size, TID_BOOL,
00787 TRUE);
00788
00789 size = sizeof(write_flag);
00790 write_flag = 0;
00791 db_get_value(hDB, 0, "/Logger/SQL/Write data", &write_flag, &size, TID_BOOL, TRUE);
00792
00793 size = sizeof(hostname);
00794 strcpy(hostname, "localhost");
00795 db_get_value(hDB, 0, "/Logger/SQL/Hostname", hostname, &size, TID_STRING, TRUE);
00796
00797 size = sizeof(username);
00798 strcpy(username, "root");
00799 db_get_value(hDB, 0, "/Logger/SQL/Username", username, &size, TID_STRING, TRUE);
00800
00801 size = sizeof(password);
00802 password[0] = 0;
00803 db_get_value(hDB, 0, "/Logger/SQL/Password", password, &size, TID_STRING, TRUE);
00804
00805
00806 size = sizeof(database);
00807 db_get_value(hDB, 0, "/Experiment/Name", database, &size, TID_STRING, TRUE);
00808 db_get_value(hDB, 0, "/Logger/SQL/Database", database, &size, TID_STRING, TRUE);
00809
00810 size = sizeof(table);
00811 strcpy(table, "Runlog");
00812 db_get_value(hDB, 0, "/Logger/SQL/Table", table, &size, TID_STRING, TRUE);
00813
00814 db_find_key(hDB, 0, "/Logger/SQL/Links BOR", &hKeyRoot);
00815 if (!hKeyRoot) {
00816
00817 db_create_key(hDB, 0, "/Logger/SQL/Links BOR", TID_KEY);
00818
00819 if (db_find_key(hDB, 0, "/Runinfo/Run number", &hKey) == DB_SUCCESS)
00820 db_create_link(hDB, 0, "/Logger/SQL/Links BOR/Run number",
00821 "/Runinfo/Run number");
00822
00823 if (db_find_key(hDB, 0, "/Experiment/Run parameters/Comment", &hKey) == DB_SUCCESS)
00824 db_create_link(hDB, 0, "/Logger/SQL/Links BOR/Comment",
00825 "/Experiment/Run parameters/Comment");
00826
00827 if (db_find_key(hDB, 0, "/Runinfo/Start time", &hKey) == DB_SUCCESS)
00828 db_create_link(hDB, 0, "/Logger/SQL/Links BOR/Start time",
00829 "/Runinfo/Start time");
00830 }
00831
00832 db_find_key(hDB, 0, "/Logger/SQL/Links EOR", &hKeyRoot);
00833 if (!hKeyRoot) {
00834
00835 db_create_key(hDB, 0, "/Logger/SQL/Links EOR", TID_KEY);
00836
00837 if (db_find_key(hDB, 0, "/Runinfo/Stop time", &hKey) == DB_SUCCESS)
00838 db_create_link(hDB, 0, "/Logger/SQL/Links EOR/Stop time", "/Runinfo/Stop time");
00839
00840 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/Events sent", &hKey) ==
00841 DB_SUCCESS)
00842 db_create_link(hDB, 0, "/Logger/SQL/Links EOR/Number of events",
00843 "/Equipment/Trigger/Statistics/Events sent");
00844
00845 }
00846 }
00847
00848
00849
00850 void write_sql(BOOL bor)
00851 {
00852 MYSQL db;
00853 char hostname[80], username[80], password[80], database[80], table[80],
00854 query[5000], where[500];
00855 int status, size, write_flag, create_flag;
00856 BOOL insert;
00857 HNDLE hKey, hKeyRoot;
00858 SQL_LIST *sql_list;
00859
00860
00861 insert = bor;
00862
00863
00864 db_find_key(hDB, 0, "/Logger/SQL/Links BOR", &hKeyRoot);
00865 status = db_enum_link(hDB, hKeyRoot, 0, &hKey);
00866
00867
00868 if (status == DB_NO_MORE_SUBKEYS) {
00869 insert = TRUE;
00870 db_find_key(hDB, 0, "/Logger/SQL/Links EOR", &hKeyRoot);
00871 status = db_enum_link(hDB, hKeyRoot, 0, &hKey);
00872 if (status == DB_NO_MORE_SUBKEYS)
00873 return;
00874 }
00875
00876 sql_get_columns(hKeyRoot, &sql_list);
00877 sprintf(where, "WHERE `%s`='%s'", sql_list[0].column_name, sql_list[0].data);
00878 free(sql_list);
00879
00880
00881 if (bor) {
00882 db_find_key(hDB, 0, "/Logger/SQL/Links BOR", &hKeyRoot);
00883 if (!hKeyRoot) {
00884 cm_msg(MERROR, "write_sql", "Cannot find \"/Logger/SQL/Links BOR");
00885 return;
00886 }
00887 } else {
00888 db_find_key(hDB, 0, "/Logger/SQL/Links EOR", &hKeyRoot);
00889 if (!hKeyRoot) {
00890 cm_msg(MERROR, "write_sql", "Cannot find \"/Logger/SQL/Links EOR");
00891 return;
00892 }
00893 }
00894
00895 size = sizeof(create_flag);
00896 create_flag = 0;
00897 db_get_value(hDB, 0, "/Logger/SQL/Create database", &create_flag, &size, TID_BOOL,
00898 TRUE);
00899
00900 size = sizeof(write_flag);
00901 write_flag = 0;
00902 db_get_value(hDB, 0, "/Logger/SQL/Write data", &write_flag, &size, TID_BOOL, TRUE);
00903
00904 size = sizeof(hostname);
00905 strcpy(hostname, "localhost");
00906 db_get_value(hDB, 0, "/Logger/SQL/Hostname", hostname, &size, TID_STRING, TRUE);
00907
00908 size = sizeof(username);
00909 strcpy(username, "root");
00910 db_get_value(hDB, 0, "/Logger/SQL/Username", username, &size, TID_STRING, TRUE);
00911
00912 size = sizeof(password);
00913 password[0] = 0;
00914 db_get_value(hDB, 0, "/Logger/SQL/Password", password, &size, TID_STRING, TRUE);
00915
00916
00917 size = sizeof(database);
00918 db_get_value(hDB, 0, "/Experiment/Name", database, &size, TID_STRING, TRUE);
00919 db_get_value(hDB, 0, "/Logger/SQL/Database", database, &size, TID_STRING, TRUE);
00920
00921 size = sizeof(table);
00922 strcpy(table, "Runlog");
00923 db_get_value(hDB, 0, "/Logger/SQL/Table", table, &size, TID_STRING, TRUE);
00924
00925
00926 if (!write_flag)
00927 return;
00928
00929
00930 mysql_init(&db);
00931
00932 if (!mysql_real_connect(&db, hostname, username, password, NULL, 0, NULL, 0)) {
00933 cm_msg(MERROR, "write_sql", "Failed to connect to database: Error: %s",
00934 mysql_error(&db));
00935 mysql_close(&db);
00936 return;
00937 }
00938
00939
00940 sprintf(query, "USE `%s`", database);
00941 if (mysql_query_debug(&db, query)) {
00942
00943
00944 if (create_flag) {
00945 if (!sql_create_database(&db, database)) {
00946 mysql_close(&db);
00947 return;
00948 }
00949
00950 } else {
00951 cm_msg(MERROR, "write_sql", "Failed to select database: Error: %s",
00952 mysql_error(&db));
00953 mysql_close(&db);
00954 return;
00955 }
00956 }
00957
00958 if (insert) {
00959 status = sql_insert(&db, database, table, hKeyRoot, create_flag);
00960 if (status == ER_DUP_ENTRY)
00961 sql_update(&db, database, table, hKeyRoot, create_flag, where);
00962 } else
00963 sql_update(&db, database, table, hKeyRoot, create_flag, where);
00964
00965 mysql_close(&db);
00966 }
00967
00968 #endif // HAVE_MYSQL
00969
00970
00971
00972 INT tape_open(char *dev, INT * handle)
00973 {
00974 INT status, count;
00975 char buffer[16];
00976
00977 status = ss_tape_open(dev, O_RDWR | O_CREAT | O_TRUNC, handle);
00978 if (status != SS_SUCCESS)
00979 return status;
00980
00981
00982 count = sizeof(buffer);
00983 status = ss_tape_read(*handle, buffer, &count);
00984
00985 if (count == sizeof(buffer)) {
00986
00987 ss_tape_rskip(*handle, -1);
00988 cm_msg(MINFO, "tape_open",
00989 "Tape contains data, please spool tape with 'mtape seod'");
00990 cm_msg(MINFO, "tape_open",
00991 "or erase it with 'mtape weof', 'mtape rewind', then try again.");
00992 ss_tape_close(*handle);
00993 return SS_TAPE_ERROR;
00994 }
00995
00996 return SS_SUCCESS;
00997 }
00998
00999
01000
01001 INT ftp_error(char *message)
01002 {
01003 cm_msg(MERROR, "ftp_error", message);
01004 return 1;
01005 }
01006
01007 INT ftp_open(char *destination, FTP_CON ** con)
01008 {
01009 INT status;
01010 short port = 0;
01011 char *token, host_name[HOST_NAME_LENGTH],
01012 user[32], pass[32], directory[256], file_name[256], file_mode[256];
01013
01014
01015
01016
01017
01018
01019
01020 token = strtok(destination, ",");
01021 if (token)
01022 strcpy(host_name, token);
01023
01024 token = strtok(NULL, ", ");
01025 if (token)
01026 port = atoi(token);
01027
01028 token = strtok(NULL, ", ");
01029 if (token)
01030 strcpy(user, token);
01031
01032 token = strtok(NULL, ", ");
01033 if (token)
01034 strcpy(pass, token);
01035
01036 token = strtok(NULL, ", ");
01037 if (token)
01038 strcpy(directory, token);
01039
01040 token = strtok(NULL, ", ");
01041 if (token)
01042 strcpy(file_name, token);
01043
01044 token = strtok(NULL, ", ");
01045 file_mode[0] = 0;
01046 if (token)
01047 strcpy(file_mode, token);
01048
01049 #ifdef FAL_MAIN
01050 ftp_debug(NULL, ftp_error);
01051 #else
01052 ftp_debug((int (*)(char *)) puts, ftp_error);
01053 #endif
01054
01055 status = ftp_login(con, host_name, port, user, pass, "");
01056 if (status >= 0)
01057 return status;
01058
01059 status = ftp_chdir(*con, directory);
01060 if (status >= 0)
01061 return status;
01062
01063 status = ftp_binary(*con);
01064 if (status >= 0)
01065 return status;
01066
01067 if (file_mode[0]) {
01068 status = ftp_command(*con, "umask %s", file_mode, 200, 250, EOF);
01069 if (status >= 0)
01070 return status;
01071 }
01072
01073 if (ftp_open_write(*con, file_name) >= 0)
01074 return (*con)->err_no;
01075
01076 return SS_SUCCESS;
01077 }
01078
01079
01080
01081 INT midas_flush_buffer(LOG_CHN * log_chn)
01082 {
01083 INT status, size, written;
01084 MIDAS_INFO *info;
01085
01086 info = (MIDAS_INFO *) log_chn->format_info;
01087 size = (POINTER_T) info->write_pointer - (POINTER_T) info->buffer;
01088
01089 if (size == 0)
01090 return SS_SUCCESS;
01091
01092
01093 if (log_chn->type == LOG_TYPE_TAPE)
01094 status = ss_tape_write(log_chn->handle, info->buffer, size);
01095 else if (log_chn->type == LOG_TYPE_FTP)
01096 status =
01097 ftp_send(((FTP_CON *) log_chn->ftp_con)->data, info->buffer,
01098 size) == size ? SS_SUCCESS : SS_FILE_ERROR;
01099 else {
01100 #ifdef OS_WINNT
01101 WriteFile((HANDLE) log_chn->handle, info->buffer, size, (unsigned long *) &written,
01102 NULL);
01103 #else
01104 written = write(log_chn->handle, info->buffer, size);
01105 #endif
01106 status = written == size ? SS_SUCCESS : SS_FILE_ERROR;
01107 }
01108
01109 info->write_pointer = info->buffer;
01110
01111 return status;
01112 }
01113
01114
01115
01116
01117 INT midas_write(LOG_CHN * log_chn, EVENT_HEADER * pevent, INT evt_size)
01118 {
01119 INT status, size_left;
01120 MIDAS_INFO *info;
01121
01122 info = (MIDAS_INFO *) log_chn->format_info;
01123
01124
01125 size_left =
01126 TAPE_BUFFER_SIZE - ((POINTER_T) info->write_pointer - (POINTER_T) info->buffer);
01127
01128 if (size_left < evt_size) {
01129
01130 memcpy(info->write_pointer, pevent, size_left);
01131 info->write_pointer += size_left;
01132
01133
01134 status = midas_flush_buffer(log_chn);
01135 if (status != SS_SUCCESS)
01136 return status;
01137
01138
01139 while (evt_size - size_left >= TAPE_BUFFER_SIZE) {
01140 memcpy(info->buffer, (char *) pevent + size_left, TAPE_BUFFER_SIZE);
01141 info->write_pointer += TAPE_BUFFER_SIZE;
01142 size_left += TAPE_BUFFER_SIZE;
01143
01144 status = midas_flush_buffer(log_chn);
01145 if (status != SS_SUCCESS)
01146 return status;
01147 }
01148
01149
01150 memcpy(info->buffer, (char *) pevent + size_left, evt_size - size_left);
01151 info->write_pointer = info->buffer + (evt_size - size_left);
01152 } else {
01153
01154 memcpy(info->write_pointer, pevent, evt_size);
01155 info->write_pointer += evt_size;
01156 }
01157
01158
01159 log_chn->statistics.events_written++;
01160 log_chn->statistics.bytes_written += pevent->data_size + sizeof(EVENT_HEADER);
01161 log_chn->statistics.bytes_written_total += pevent->data_size + sizeof(EVENT_HEADER);
01162
01163 return SS_SUCCESS;
01164 }
01165
01166
01167
01168 INT midas_log_open(LOG_CHN * log_chn, INT run_number)
01169 {
01170 MIDAS_INFO *info;
01171 INT status;
01172
01173
01174 log_chn->format_info = (void **) malloc(sizeof(MIDAS_INFO));
01175
01176 info = (MIDAS_INFO *) log_chn->format_info;
01177 if (info == NULL) {
01178 log_chn->handle = 0;
01179 return SS_NO_MEMORY;
01180 }
01181
01182
01183 if ((info->buffer = (char *) malloc(TAPE_BUFFER_SIZE)) == NULL) {
01184 free(info);
01185 log_chn->handle = 0;
01186 return SS_NO_MEMORY;
01187 }
01188
01189 info->write_pointer = info->buffer;
01190
01191
01192 if (log_chn->type == LOG_TYPE_TAPE) {
01193 status = tape_open(log_chn->path, &log_chn->handle);
01194 if (status != SS_SUCCESS) {
01195 free(info->buffer);
01196 free(info);
01197 log_chn->handle = 0;
01198 return status;
01199 }
01200 } else if (log_chn->type == LOG_TYPE_FTP) {
01201 status = ftp_open(log_chn->path, (FTP_CON **) (&log_chn->ftp_con));
01202 if (status != SS_SUCCESS) {
01203 free(info->buffer);
01204 free(info);
01205 log_chn->handle = 0;
01206 return status;
01207 } else
01208 log_chn->handle = 1;
01209 } else {
01210
01211 if (strstr(log_chn->path, "null") == NULL) {
01212 log_chn->handle = open(log_chn->path, O_RDONLY);
01213 if (log_chn->handle > 0) {
01214
01215 if (lseek(log_chn->handle, 0, SEEK_END) > 0) {
01216 close(log_chn->handle);
01217 free(info->buffer);
01218 free(info);
01219 log_chn->handle = 0;
01220 return SS_FILE_EXISTS;
01221 }
01222 }
01223 }
01224 #ifdef OS_WINNT
01225 log_chn->handle =
01226 (int) CreateFile(log_chn->path, GENERIC_WRITE, FILE_SHARE_READ, NULL,
01227 CREATE_ALWAYS,
01228 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH |
01229 FILE_FLAG_SEQUENTIAL_SCAN, 0);
01230
01231 #else
01232 log_chn->handle =
01233 open(log_chn->path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
01234 0644);
01235 #endif
01236
01237 if (log_chn->handle < 0) {
01238 free(info->buffer);
01239 free(info);
01240 log_chn->handle = 0;
01241 return SS_FILE_ERROR;
01242 }
01243 }
01244
01245
01246 if (log_chn->settings.odb_dump)
01247 log_odb_dump(log_chn, EVENTID_BOR, run_number);
01248
01249 return SS_SUCCESS;
01250 }
01251
01252
01253
01254 INT midas_log_close(LOG_CHN * log_chn, INT run_number)
01255 {
01256
01257 if (log_chn->settings.odb_dump)
01258 log_odb_dump(log_chn, EVENTID_EOR, run_number);
01259
01260 midas_flush_buffer(log_chn);
01261
01262
01263 if (log_chn->type == LOG_TYPE_TAPE) {
01264
01265 ss_tape_write_eof(log_chn->handle);
01266 ss_tape_close(log_chn->handle);
01267 } else if (log_chn->type == LOG_TYPE_FTP) {
01268 ftp_close((FTP_CON *) log_chn->ftp_con);
01269 ftp_bye((FTP_CON *) log_chn->ftp_con);
01270 } else
01271 #ifdef OS_WINNT
01272 CloseHandle((HANDLE) log_chn->handle);
01273 #else
01274 close(log_chn->handle);
01275 #endif
01276
01277 free(((MIDAS_INFO *) log_chn->format_info)->buffer);
01278 free(log_chn->format_info);
01279
01280 return SS_SUCCESS;
01281 }
01282
01283
01284
01285 typedef struct {
01286 short int event_id;
01287 WORD format;
01288 HNDLE hDefKey;
01289 } EVENT_DEF;
01290
01291 EVENT_DEF *db_get_event_definition(short int event_id)
01292 {
01293 INT i, index, status, size;
01294 char str[80];
01295 HNDLE hKey, hKeyRoot;
01296 WORD id;
01297
01298 #define EVENT_DEF_CACHE_SIZE 30
01299 static EVENT_DEF *event_def = NULL;
01300
01301
01302 if (event_def == NULL)
01303 event_def = (EVENT_DEF *) calloc(EVENT_DEF_CACHE_SIZE, sizeof(EVENT_DEF));
01304
01305
01306 for (i = 0; event_def[i].event_id; i++)
01307 if (event_def[i].event_id == event_id)
01308 return &event_def[i];
01309
01310
01311 for (index = 0; index < EVENT_DEF_CACHE_SIZE; index++)
01312 if (event_def[index].event_id == 0)
01313 break;
01314
01315 if (index == EVENT_DEF_CACHE_SIZE) {
01316 cm_msg(MERROR, "db_get_event_definition", "too many event definitions");
01317 return NULL;
01318 }
01319
01320
01321 if (event_id < 0) {
01322 event_def[index].event_id = event_id;
01323 event_def[index].format = FORMAT_ASCII;
01324 event_def[index].hDefKey = 0;
01325 return &event_def[index];
01326 }
01327
01328 status = db_find_key(hDB, 0, "/equipment", &hKeyRoot);
01329 if (status != DB_SUCCESS) {
01330 cm_msg(MERROR, "db_get_event_definition", "cannot find /equipment entry in ODB");
01331 return NULL;
01332 }
01333
01334 for (i = 0;; i++) {
01335
01336 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
01337 if (status == DB_NO_MORE_SUBKEYS) {
01338 sprintf(str, "Cannot find event id %d under /equipment", event_id);
01339 cm_msg(MERROR, "db_get_event_definition", str);
01340 return NULL;
01341 }
01342
01343 size = sizeof(id);
01344 status = db_get_value(hDB, hKey, "Common/Event ID", &id, &size, TID_WORD, TRUE);
01345 if (status != DB_SUCCESS)
01346 continue;
01347
01348 if (id == event_id) {
01349
01350 event_def[index].event_id = id;
01351
01352 size = sizeof(str);
01353 str[0] = 0;
01354 db_get_value(hDB, hKey, "Common/Format", str, &size, TID_STRING, TRUE);
01355
01356 if (equal_ustring(str, "Fixed"))
01357 event_def[index].format = FORMAT_FIXED;
01358 else if (equal_ustring(str, "ASCII"))
01359 event_def[index].format = FORMAT_ASCII;
01360 else if (equal_ustring(str, "MIDAS"))
01361 event_def[index].format = FORMAT_MIDAS;
01362 else if (equal_ustring(str, "YBOS"))
01363 assert(!"YBOS not supported anymore");
01364 else if (equal_ustring(str, "DUMP"))
01365 event_def[index].format = FORMAT_DUMP;
01366 else {
01367 cm_msg(MERROR, "db_get_event_definition", "unknown data format");
01368 event_def[index].event_id = 0;
01369 return NULL;
01370 }
01371
01372 db_find_key(hDB, hKey, "Variables", &event_def[index].hDefKey);
01373 return &event_def[index];
01374 }
01375 }
01376 }
01377
01378
01379
01380 #define STR_INC(p,base) { p+=strlen(p); \
01381 if (p > base+sizeof(base)) \
01382 cm_msg(MERROR, "STR_INC", "ASCII buffer too small"); }
01383
01384
01385 INT dump_write(LOG_CHN * log_chn, EVENT_HEADER * pevent, INT evt_size)
01386 {
01387 INT status, size, i, j;
01388 EVENT_DEF *event_def;
01389 BANK_HEADER *pbh;
01390 BANK *pbk;
01391 BANK32 *pbk32;
01392 void *pdata;
01393 char buffer[100000], *pbuf, name[5], type_name[10];
01394 HNDLE hKey;
01395 KEY key;
01396 DWORD bkname;
01397 WORD bktype;
01398
01399 event_def = db_get_event_definition(pevent->event_id);
01400 if (event_def == NULL)
01401 return SS_SUCCESS;
01402
01403
01404 pbuf = buffer;
01405 name[4] = 0;
01406
01407 if (pevent->event_id == EVENTID_BOR)
01408 sprintf(pbuf, "%%ID BOR NR %d\n", pevent->serial_number);
01409 else if (pevent->event_id == EVENTID_EOR)
01410 sprintf(pbuf, "%%ID EOR NR %d\n", pevent->serial_number);
01411 else
01412 sprintf(pbuf, "%%ID %d TR %d NR %d\n", pevent->event_id, pevent->trigger_mask,
01413 pevent->serial_number);
01414 STR_INC(pbuf, buffer);
01415
01416
01417 if (event_def->format == FORMAT_MIDAS) {
01418 LRS1882_DATA *lrs1882;
01419 LRS1877_DATA *lrs1877;
01420 LRS1877_HEADER *lrs1877_header;
01421
01422 pbh = (BANK_HEADER *) (pevent + 1);
01423 bk_swap(pbh, FALSE);
01424
01425 pbk = NULL;
01426 pbk32 = NULL;
01427 do {
01428
01429 if (bk_is32(pbh)) {
01430 size = bk_iterate32(pbh, &pbk32, &pdata);
01431 if (pbk32 == NULL)
01432 break;
01433 bkname = *((DWORD *) pbk32->name);
01434 bktype = (WORD) pbk32->type;
01435 } else {
01436 size = bk_iterate(pbh, &pbk, &pdata);
01437 if (pbk == NULL)
01438 break;
01439 bkname = *((DWORD *) pbk->name);
01440 bktype = (WORD) pbk->type;
01441 }
01442
01443 if (rpc_tid_size(bktype & 0xFF))
01444 size /= rpc_tid_size(bktype & 0xFF);
01445
01446 lrs1882 = (LRS1882_DATA *) pdata;
01447 lrs1877 = (LRS1877_DATA *) pdata;
01448 lrs1877_header = (LRS1877_HEADER *) pdata;
01449
01450
01451 *((DWORD *) name) = bkname;
01452
01453 if ((bktype & 0xFF00) == 0)
01454 strcpy(type_name, rpc_tid_name(bktype & 0xFF));
01455 else if ((bktype & 0xFF00) == TID_LRS1882)
01456 strcpy(type_name, "LRS1882");
01457 else if ((bktype & 0xFF00) == TID_LRS1877)
01458 strcpy(type_name, "LRS1877");
01459 else if ((bktype & 0xFF00) == TID_PCOS3)
01460 strcpy(type_name, "PCOS3");
01461 else
01462 strcpy(type_name, "unknown");
01463
01464 sprintf(pbuf, "BK %s TP %s SZ %d\n", name, type_name, size);
01465 STR_INC(pbuf, buffer);
01466
01467
01468 for (i = 0; i < size; i++) {
01469 if ((bktype & 0xFF00) == 0)
01470 db_sprintf(pbuf, pdata, size, i, bktype & 0xFF);
01471
01472 else if ((bktype & 0xFF00) == TID_LRS1882)
01473 sprintf(pbuf, "GA %d CH %02d DA %d",
01474 lrs1882[i].geo_addr, lrs1882[i].channel, lrs1882[i].data);
01475
01476 else if ((bktype & 0xFF00) == TID_LRS1877) {
01477 if (i == 0)
01478 sprintf(pbuf, "GA %d BF %d CN %d",
01479 lrs1877_header[i].geo_addr, lrs1877_header[i].buffer,
01480 lrs1877_header[i].count);
01481 else
01482 sprintf(pbuf, "GA %d CH %02d ED %d DA %1.1lf",
01483 lrs1877[i].geo_addr, lrs1877[i].channel, lrs1877[i].edge,
01484 lrs1877[i].data * 0.5);
01485 }
01486
01487 else if ((bktype & 0xFF00) == TID_PCOS3)
01488 *pbuf = '\0';
01489 else
01490 db_sprintf(pbuf, pdata, size, i, bktype & 0xFF);
01491
01492 strcat(pbuf, "\n");
01493 STR_INC(pbuf, buffer);
01494 }
01495
01496 } while (1);
01497 }
01498
01499
01500 if (event_def->format == FORMAT_FIXED) {
01501 if (event_def->hDefKey == 0)
01502 cm_msg(MERROR, "dump_write", "cannot find event definition");
01503 else {
01504 pdata = (char *) (pevent + 1);
01505 for (i = 0;; i++) {
01506 status = db_enum_key(hDB, event_def->hDefKey, i, &hKey);
01507 if (status == DB_NO_MORE_SUBKEYS)
01508 break;
01509
01510 db_get_key(hDB, hKey, &key);
01511 sprintf(pbuf, "%s\n", key.name);
01512 STR_INC(pbuf, buffer);
01513
01514
01515 pdata = (void *) VALIGN(pdata, MIN(ss_get_struct_align(), key.item_size));
01516
01517 for (j = 0; j < key.num_values; j++) {
01518 db_sprintf(pbuf, pdata, key.item_size, j, key.type);
01519 strcat(pbuf, "\n");
01520 STR_INC(pbuf, buffer);
01521 }
01522
01523
01524 pdata = ((char *) pdata) + key.item_size * key.num_values;
01525 }
01526 }
01527 }
01528
01529
01530 if (event_def->format == FORMAT_ASCII) {
01531
01532 size = strlen(buffer);
01533 if (log_chn->type == LOG_TYPE_TAPE)
01534 status = ss_tape_write(log_chn->handle, buffer, size);
01535 else
01536 status = write(log_chn->handle, buffer, size) ==
01537 size ? SS_SUCCESS : SS_FILE_ERROR;
01538
01539
01540 size = strlen((char *) (pevent + 1));
01541 if (log_chn->type == LOG_TYPE_TAPE)
01542 status = ss_tape_write(log_chn->handle, (char *) (pevent + 1), size);
01543 else if (log_chn->type == LOG_TYPE_FTP)
01544 status = ftp_send(((FTP_CON *) log_chn->ftp_con)->data, buffer, size) == size ?
01545 SS_SUCCESS : SS_FILE_ERROR;
01546 else
01547 status = write(log_chn->handle, (char *) (pevent + 1), size) ==
01548 size ? SS_SUCCESS : SS_FILE_ERROR;
01549 } else {
01550
01551
01552
01553 strcat(pbuf, "\n");
01554 size = strlen(buffer);
01555
01556
01557 if (log_chn->type == LOG_TYPE_TAPE)
01558 status = ss_tape_write(log_chn->handle, buffer, size);
01559 else if (log_chn->type == LOG_TYPE_FTP)
01560 status = ftp_send(((FTP_CON *) log_chn->ftp_con)->data, buffer, size) == size ?
01561 SS_SUCCESS : SS_FILE_ERROR;
01562 else
01563 status = write(log_chn->handle, buffer, size) ==
01564 size ? SS_SUCCESS : SS_FILE_ERROR;
01565 }
01566
01567
01568 log_chn->statistics.events_written++;
01569 log_chn->statistics.bytes_written += size;
01570 log_chn->statistics.bytes_written_total += size;
01571
01572 return status;
01573 }
01574
01575
01576
01577 INT dump_log_open(LOG_CHN * log_chn, INT run_number)
01578 {
01579 INT status;
01580
01581
01582 if (log_chn->type == LOG_TYPE_TAPE) {
01583 status = tape_open(log_chn->path, &log_chn->handle);
01584 if (status != SS_SUCCESS) {
01585 log_chn->handle = 0;
01586 return status;
01587 }
01588 } else if (log_chn->type == LOG_TYPE_FTP) {
01589 status = ftp_open(log_chn->path, (FTP_CON **) (&log_chn->ftp_con));
01590 if (status != SS_SUCCESS) {
01591 log_chn->handle = 0;
01592 return status;
01593 } else
01594 log_chn->handle = 1;
01595 } else {
01596 log_chn->handle =
01597 open(log_chn->path, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644);
01598
01599 if (log_chn->handle < 0) {
01600 log_chn->handle = 0;
01601 return SS_FILE_ERROR;
01602 }
01603 }
01604
01605
01606 if (log_chn->settings.odb_dump)
01607 log_odb_dump(log_chn, EVENTID_BOR, run_number);
01608
01609 return SS_SUCCESS;
01610 }
01611
01612
01613
01614 INT dump_log_close(LOG_CHN * log_chn, INT run_number)
01615 {
01616
01617 if (log_chn->settings.odb_dump)
01618 log_odb_dump(log_chn, EVENTID_EOR, run_number);
01619
01620
01621 if (log_chn->type == LOG_TYPE_TAPE) {
01622
01623 ss_tape_write_eof(log_chn->handle);
01624 ss_tape_close(log_chn->handle);
01625 } else if (log_chn->type == LOG_TYPE_FTP) {
01626 ftp_close((FTP_CON *) log_chn->ftp_con);
01627 ftp_bye((FTP_CON *) log_chn->ftp_con);
01628 } else
01629 close(log_chn->handle);
01630
01631 return SS_SUCCESS;
01632 }
01633
01634
01635
01636 INT ascii_write(LOG_CHN * log_chn, EVENT_HEADER * pevent, INT evt_size)
01637 {
01638 INT status, size, i, j;
01639 EVENT_DEF *event_def;
01640 BANK_HEADER *pbh;
01641 BANK *pbk;
01642 BANK32 *pbk32;
01643 void *pdata;
01644 char buffer[10000], name[5], type_name[10];
01645 char *ph, header_line[10000];
01646 char *pd, data_line[10000];
01647 HNDLE hKey;
01648 KEY key;
01649 static short int last_event_id = -1;
01650 DWORD bkname;
01651 WORD bktype;
01652
01653 if (pevent->serial_number == 1)
01654 last_event_id = -1;
01655
01656 event_def = db_get_event_definition(pevent->event_id);
01657 if (event_def == NULL)
01658 return SS_SUCCESS;
01659
01660 name[4] = 0;
01661 header_line[0] = 0;
01662 data_line[0] = 0;
01663 ph = header_line;
01664 pd = data_line;
01665
01666
01667 if (event_def->format == FORMAT_MIDAS) {
01668 LRS1882_DATA *lrs1882;
01669 LRS1877_DATA *lrs1877;
01670 LRS1877_HEADER *lrs1877_header;
01671
01672 pbh = (BANK_HEADER *) (pevent + 1);
01673 bk_swap(pbh, FALSE);
01674
01675 pbk = NULL;
01676 pbk32 = NULL;
01677 do {
01678
01679 if (bk_is32(pbh)) {
01680 size = bk_iterate32(pbh, &pbk32, &pdata);
01681 if (pbk32 == NULL)
01682 break;
01683 bkname = *((DWORD *) pbk32->name);
01684 bktype = (WORD) pbk32->type;
01685 } else {
01686 size = bk_iterate(pbh, &pbk, &pdata);
01687 if (pbk == NULL)
01688 break;
01689 bkname = *((DWORD *) pbk->name);
01690 bktype = (WORD) pbk->type;
01691 }
01692
01693 if (rpc_tid_size(bktype & 0xFF))
01694 size /= rpc_tid_size(bktype & 0xFF);
01695
01696 lrs1882 = (LRS1882_DATA *) pdata;
01697 lrs1877 = (LRS1877_DATA *) pdata;
01698 lrs1877_header = (LRS1877_HEADER *) pdata;
01699
01700
01701 *((DWORD *) name) = bkname;
01702
01703 if ((bktype & 0xFF00) == 0)
01704 strcpy(type_name, rpc_tid_name(bktype & 0xFF));
01705 else if ((bktype & 0xFF00) == TID_LRS1882)
01706 strcpy(type_name, "LRS1882");
01707 else if ((bktype & 0xFF00) == TID_LRS1877)
01708 strcpy(type_name, "LRS1877");
01709 else if ((bktype & 0xFF00) == TID_PCOS3)
01710 strcpy(type_name, "PCOS3");
01711 else
01712 strcpy(type_name, "unknown");
01713
01714 sprintf(ph, "%s[%d]\t", name, size);
01715 STR_INC(ph, header_line);
01716
01717
01718 for (i = 0; i < size; i++) {
01719 db_sprintf(pd, pdata, size, i, bktype & 0xFF);
01720 strcat(pd, "\t");
01721 STR_INC(pd, data_line);
01722 }
01723
01724 } while (1);
01725 }
01726
01727
01728 if (event_def->format == FORMAT_FIXED) {
01729 if (event_def->hDefKey == 0)
01730 cm_msg(MERROR, "ascii_write", "cannot find event definition");
01731 else {
01732 pdata = (char *) (pevent + 1);
01733 for (i = 0;; i++) {
01734 status = db_enum_key(hDB, event_def->hDefKey, i, &hKey);
01735 if (status == DB_NO_MORE_SUBKEYS)
01736 break;
01737
01738 db_get_key(hDB, hKey, &key);
01739
01740
01741 pdata = (void *) VALIGN(pdata, MIN(ss_get_struct_align(), key.item_size));
01742
01743 for (j = 0; j < key.num_values; j++) {
01744 if (pevent->event_id != last_event_id) {
01745 if (key.num_values == 1)
01746 sprintf(ph, "%s\t", key.name);
01747 else
01748 sprintf(ph, "%s%d\t", key.name, j);
01749
01750 STR_INC(ph, header_line);
01751 }
01752
01753 db_sprintf(pd, pdata, key.item_size, j, key.type);
01754 strcat(pd, "\t");
01755 STR_INC(pd, data_line);
01756 }
01757
01758
01759 pdata = ((char *) pdata) + key.item_size * key.num_values;
01760 }
01761 }
01762 }
01763
01764 if (*(pd - 1) == '\t')
01765 *(pd - 1) = '\n';
01766
01767 if (last_event_id != pevent->event_id) {
01768 if (*(ph - 1) == '\t')
01769 *(ph - 1) = '\n';
01770 last_event_id = pevent->event_id;
01771 strcpy(buffer, header_line);
01772 strcat(buffer, data_line);
01773 } else
01774 strcpy(buffer, data_line);
01775
01776
01777 size = strlen(buffer);
01778
01779 if (log_chn->type == LOG_TYPE_TAPE)
01780 status = ss_tape_write(log_chn->handle, buffer, size);
01781 else if (log_chn->type == LOG_TYPE_FTP)
01782 status = ftp_send(((FTP_CON *) log_chn->ftp_con)->data, buffer, size) == size ?
01783 SS_SUCCESS : SS_FILE_ERROR;
01784 else
01785 status = write(log_chn->handle, buffer, size) == size ? SS_SUCCESS : SS_FILE_ERROR;
01786
01787
01788 log_chn->statistics.events_written++;
01789 log_chn->statistics.bytes_written += size;
01790 log_chn->statistics.bytes_written_total += size;
01791
01792 return status;
01793 }
01794
01795
01796
01797 INT ascii_log_open(LOG_CHN * log_chn, INT run_number)
01798 {
01799 INT status;
01800 EVENT_HEADER event;
01801
01802
01803 if (log_chn->type == LOG_TYPE_TAPE) {
01804 status = tape_open(log_chn->path, &log_chn->handle);
01805 if (status != SS_SUCCESS) {
01806 log_chn->handle = 0;
01807 return status;
01808 }
01809 } else if (log_chn->type == LOG_TYPE_FTP) {
01810 status = ftp_open(log_chn->path, (FTP_CON **) (&log_chn->ftp_con));
01811 if (status != SS_SUCCESS) {
01812 log_chn->handle = 0;
01813 return status;
01814 } else
01815 log_chn->handle = 1;
01816 } else {
01817 log_chn->handle =
01818 open(log_chn->path, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644);
01819
01820 if (log_chn->handle < 0) {
01821 log_chn->handle = 0;
01822 return SS_FILE_ERROR;
01823 }
01824 }
01825
01826
01827 if (log_chn->settings.odb_dump) {
01828 event.event_id = EVENTID_BOR;
01829 event.data_size = 0;
01830 event.serial_number = run_number;
01831
01832 ascii_write(log_chn, &event, sizeof(EVENT_HEADER));
01833 }
01834
01835 return SS_SUCCESS;
01836 }
01837
01838
01839
01840 INT ascii_log_close(LOG_CHN * log_chn, INT run_number)
01841 {
01842
01843 if (log_chn->type == LOG_TYPE_TAPE) {
01844
01845 ss_tape_write_eof(log_chn->handle);
01846 ss_tape_close(log_chn->handle);
01847 } else if (log_chn->type == LOG_TYPE_FTP) {
01848 ftp_close((FTP_CON *) log_chn->ftp_con);
01849 ftp_bye((FTP_CON *) log_chn->ftp_con);
01850 } else
01851 close(log_chn->handle);
01852
01853 return SS_SUCCESS;
01854 }
01855
01856
01857
01858 #ifdef USE_ROOT
01859
01860 #define MAX_BANKS 100
01861
01862 typedef struct {
01863 int event_id;
01864 TTree *tree;
01865 int n_branch;
01866 DWORD branch_name[MAX_BANKS];
01867 int branch_filled[MAX_BANKS];
01868 int branch_len[MAX_BANKS];
01869 TBranch *branch[MAX_BANKS];
01870 } EVENT_TREE;
01871
01872 typedef struct {
01873 TFile *f;
01874 int n_tree;
01875 EVENT_TREE *event_tree;
01876 } TREE_STRUCT;
01877
01878
01879
01880 INT root_book_trees(TREE_STRUCT * tree_struct)
01881 {
01882 int index, size, status;
01883 WORD id;
01884 char str[1000];
01885 HNDLE hKeyRoot, hKeyEq;
01886 KEY eqkey;
01887 EVENT_TREE *et;
01888
01889 status = db_find_key(hDB, 0, "/Equipment", &hKeyRoot);
01890 if (status != DB_SUCCESS) {
01891 cm_msg(MERROR, "root_book_trees", "cannot find \"/Equipment\" entry in ODB");
01892 return 0;
01893 }
01894
01895 tree_struct->n_tree = 0;
01896
01897 for (index = 0;; index++) {
01898
01899 status = db_enum_key(hDB, hKeyRoot, index, &hKeyEq);
01900 if (status == DB_NO_MORE_SUBKEYS)
01901 return 1;
01902
01903 db_get_key(hDB, hKeyEq, &eqkey);
01904
01905
01906 tree_struct->n_tree++;
01907 if (tree_struct->n_tree == 1)
01908 tree_struct->event_tree = (EVENT_TREE *) malloc(sizeof(EVENT_TREE));
01909 else
01910 tree_struct->event_tree =
01911 (EVENT_TREE *) realloc(tree_struct->event_tree,
01912 sizeof(EVENT_TREE) * tree_struct->n_tree);
01913
01914 et = tree_struct->event_tree + (tree_struct->n_tree - 1);
01915
01916 size = sizeof(id);
01917 status = db_get_value(hDB, hKeyEq, "Common/Event ID", &id, &size, TID_WORD, TRUE);
01918 if (status != DB_SUCCESS)
01919 continue;
01920
01921 et->event_id = id;
01922 et->n_branch = 0;
01923
01924
01925 size = sizeof(str);
01926 str[0] = 0;
01927 db_get_value(hDB, hKeyEq, "Common/Format", str, &size, TID_STRING, TRUE);
01928
01929 if (!equal_ustring(str, "MIDAS")) {
01930 cm_msg(MERROR, "root_book_events",
01931 "ROOT output only for MIDAS events, but %s in %s format", eqkey.name,
01932 str);
01933 return 0;
01934 }
01935
01936
01937 sprintf(str, "Event \"%s\", ID %d", eqkey.name, id);
01938 et->tree = new TTree(eqkey.name, str);
01939 }
01940
01941 return 1;
01942 }
01943
01944
01945
01946 INT root_book_bank(EVENT_TREE * et, HNDLE hKeyDef, int event_id, char *bank_name)
01947 {
01948 int i, status;
01949 char str[1000];
01950 HNDLE hKeyVar, hKeySubVar;
01951 KEY varkey, subvarkey;
01952
01953
01954 status = db_find_key(hDB, hKeyDef, bank_name, &hKeyVar);
01955 if (status != DB_SUCCESS) {
01956 cm_msg(MERROR, "root_book_bank", "received unknown bank \"%s\" in event #%d",
01957 bank_name, event_id);
01958 return 0;
01959 }
01960
01961 if (et->n_branch + 1 == MAX_BANKS) {
01962 cm_msg(MERROR, "root_book_bank", "max number of banks (%d) exceeded in event #%d",
01963 MAX_BANKS, event_id);
01964 return 0;
01965 }
01966
01967 db_get_key(hDB, hKeyVar, &varkey);
01968
01969 if (varkey.type != TID_KEY) {
01970
01971
01972 sprintf(str, "n%s/I:%s[n%s]/", varkey.name, varkey.name, varkey.name);
01973
01974 switch (varkey.type) {
01975 case TID_BYTE:
01976 case TID_CHAR:
01977 strcat(str, "b");
01978 break;
01979 case TID_SBYTE:
01980 strcat(str, "B");
01981 break;
01982 case TID_WORD:
01983 strcat(str, "s");
01984 break;
01985 case TID_SHORT:
01986 strcat(str, "S");
01987 break;
01988 case TID_DWORD:
01989 strcat(str, "i");
01990 break;
01991 case TID_INT:
01992 strcat(str, "I");
01993 break;
01994 case TID_BOOL:
01995 strcat(str, "I");
01996 break;
01997 case TID_FLOAT:
01998 strcat(str, "F");
01999 break;
02000 case TID_DOUBLE:
02001 strcat(str, "D");
02002 break;
02003 case TID_STRING:
02004 strcat(str, "C");
02005 break;
02006 }
02007
02008 et->branch[et->n_branch] = et->tree->Branch(bank_name, NULL, str);
02009 et->branch_name[et->n_branch] = *(DWORD *) bank_name;
02010 et->n_branch++;
02011 } else {
02012
02013 str[0] = 0;
02014
02015 for (i = 0;; i++) {
02016
02017 status = db_enum_key(hDB, hKeyVar, i, &hKeySubVar);
02018 if (status == DB_NO_MORE_SUBKEYS)
02019 break;
02020
02021 db_get_key(hDB, hKeySubVar, &subvarkey);
02022
02023 if (i != 0)
02024 strcat(str, ":");
02025 strcat(str, subvarkey.name);
02026 strcat(str, "/");
02027 switch (subvarkey.type) {
02028 case TID_BYTE:
02029 case TID_CHAR:
02030 strcat(str, "b");
02031 break;
02032 case TID_SBYTE:
02033 strcat(str, "B");
02034 break;
02035 case TID_WORD:
02036 strcat(str, "s");
02037 break;
02038 case TID_SHORT:
02039 strcat(str, "S");
02040 break;
02041 case TID_DWORD:
02042 strcat(str, "i");
02043 break;
02044 case TID_INT:
02045 strcat(str, "I");
02046 break;
02047 case TID_BOOL:
02048 strcat(str, "I");
02049 break;
02050 case TID_FLOAT:
02051 strcat(str, "F");
02052 break;
02053 case TID_DOUBLE:
02054 strcat(str, "D");
02055 break;
02056 case TID_STRING:
02057 strcat(str, "C");
02058 break;
02059 }
02060 }
02061
02062 et->branch[et->n_branch] = et->tree->Branch(bank_name, NULL, str);
02063 et->branch_name[et->n_branch] = *(DWORD *) bank_name;
02064 et->n_branch++;
02065 }
02066
02067 return 1;
02068 }
02069
02070
02071
02072 INT root_write(LOG_CHN * log_chn, EVENT_HEADER * pevent, INT evt_size)
02073 {
02074 INT size, i;
02075 char bank_name[32];
02076 EVENT_DEF *event_def;
02077 BANK_HEADER *pbh;
02078 void *pdata;
02079 static short int last_event_id = -1;
02080 TREE_STRUCT *ts;
02081 EVENT_TREE *et;
02082 BANK *pbk;
02083 BANK32 *pbk32;
02084 DWORD bklen;
02085 DWORD bkname;
02086 WORD bktype;
02087 TBranch *branch;
02088
02089 if (pevent->serial_number == 1)
02090 last_event_id = -1;
02091
02092 event_def = db_get_event_definition(pevent->event_id);
02093 if (event_def == NULL) {
02094 cm_msg(MERROR, "root_write", "Definition for event #%d not found under /Equipment",
02095 pevent->event_id);
02096 return SS_INVALID_FORMAT;
02097 }
02098
02099 ts = (TREE_STRUCT *) log_chn->format_info;
02100
02101 size = (INT) ts->f->GetBytesWritten();
02102
02103
02104
02105 if (event_def->format == FORMAT_MIDAS) {
02106 pbh = (BANK_HEADER *) (pevent + 1);
02107 bk_swap(pbh, FALSE);
02108
02109
02110 for (i = 0; i < ts->n_tree; i++)
02111 if (ts->event_tree[i].event_id == pevent->event_id)
02112 break;
02113
02114 if (i == ts->n_tree) {
02115 cm_msg(MERROR, "root_write", "Event #%d not booked by root_book_events()",
02116 pevent->event_id);
02117 return SS_INVALID_FORMAT;
02118 }
02119
02120 et = ts->event_tree + i;
02121
02122
02123 for (i = 0; i < et->n_branch; i++)
02124 et->branch_filled[i] = FALSE;
02125
02126
02127 pbk = NULL;
02128 pbk32 = NULL;
02129 do {
02130
02131 if (bk_is32(pbh)) {
02132 bklen = bk_iterate32(pbh, &pbk32, &pdata);
02133 if (pbk32 == NULL)
02134 break;
02135 bkname = *((DWORD *) pbk32->name);
02136 bktype = (WORD) pbk32->type;
02137 } else {
02138 bklen = bk_iterate(pbh, &pbk, &pdata);
02139 if (pbk == NULL)
02140 break;
02141 bkname = *((DWORD *) pbk->name);
02142 bktype = (WORD) pbk->type;
02143 }
02144
02145 if (rpc_tid_size(bktype & 0xFF))
02146 bklen /= rpc_tid_size(bktype & 0xFF);
02147
02148 *((DWORD *) bank_name) = bkname;
02149 bank_name[4] = 0;
02150
02151 for (i = 0; i < et->n_branch; i++)
02152 if (et->branch_name[i] == bkname)
02153 break;
02154
02155 if (i == et->n_branch)
02156 root_book_bank(et, event_def->hDefKey, pevent->event_id, bank_name);
02157
02158 branch = et->branch[i];
02159 et->branch_filled[i] = TRUE;
02160 et->branch_len[i] = bklen;
02161
02162 if (bktype != TID_STRUCT) {
02163 TIter next(branch->GetListOfLeaves());
02164 TLeaf *leaf = (TLeaf *) next();
02165
02166
02167 leaf->SetAddress(&et->branch_len[i]);
02168
02169 leaf = (TLeaf *) next();
02170 leaf->SetAddress(pdata);
02171 } else {
02172
02173 branch->SetAddress(pdata);
02174 }
02175
02176 } while (1);
02177
02178
02179 for (i = 0; i < et->n_branch; i++)
02180 if (!et->branch_filled[i])
02181 cm_msg(MERROR, "root_write",
02182 "Bank %s booked but not received, tree cannot be filled", bank_name);
02183
02184
02185 et->tree->Fill();
02186 }
02187
02188 size = (INT) ts->f->GetBytesWritten() - size;
02189
02190
02191 log_chn->statistics.events_written++;
02192 log_chn->statistics.bytes_written += size;
02193 log_chn->statistics.bytes_written_total += size;
02194
02195 return SS_SUCCESS;
02196 }
02197
02198
02199
02200 INT root_log_open(LOG_CHN * log_chn, INT run_number)
02201 {
02202 INT size, level;
02203 char str[256], name[256];
02204 EVENT_HEADER event;
02205 TREE_STRUCT *tree_struct;
02206
02207
02208 if (log_chn->type == LOG_TYPE_TAPE || log_chn->type == LOG_TYPE_FTP) {
02209 cm_msg(MERROR, "root_log_open", "ROOT files can only reside on disk");
02210 log_chn->handle = 0;
02211 return -1;
02212 } else {
02213
02214 if (strstr(log_chn->path, "null") == NULL) {
02215 log_chn->handle = open(log_chn->path, O_RDONLY);
02216 if (log_chn->handle > 0) {
02217
02218 if (lseek(log_chn->handle, 0, SEEK_END) > 0) {
02219 close(log_chn->handle);
02220 log_chn->handle = 0;
02221 return SS_FILE_EXISTS;
02222 }
02223 }
02224 }
02225
02226 name[0] = 0;
02227 size = sizeof(name);
02228 db_get_value(hDB, 0, "/Experiment/Name", name, &size, TID_STRING, TRUE);
02229
02230 sprintf(str, "MIDAS exp. %s, run #%d", name, run_number);
02231
02232 TFile *f = new TFile(log_chn->path, "create", str, 1);
02233 if (!f->IsOpen()) {
02234 delete f;
02235 log_chn->handle = 0;
02236 return SS_FILE_ERROR;
02237 }
02238 log_chn->handle = 1;
02239
02240
02241 level = 0;
02242 size = sizeof(level);
02243 db_get_value(hDB, log_chn->settings_hkey, "Compression", &level, &size, TID_INT,
02244 FALSE);
02245 f->SetCompressionLevel(level);
02246
02247
02248 tree_struct = (TREE_STRUCT *) malloc(sizeof(TREE_STRUCT));
02249 tree_struct->f = f;
02250
02251
02252 root_book_trees(tree_struct);
02253
02254
02255 log_chn->format_info = (void **) tree_struct;
02256 }
02257
02258
02259 if (log_chn->settings.odb_dump) {
02260 event.event_id = EVENTID_BOR;
02261 event.data_size = 0;
02262 event.serial_number = run_number;
02263
02264
02265 }
02266
02267 return SS_SUCCESS;
02268 }
02269
02270
02271
02272 INT root_log_close(LOG_CHN * log_chn, INT run_number)
02273 {
02274 TREE_STRUCT *ts;
02275
02276 ts = (TREE_STRUCT *) log_chn->format_info;
02277
02278
02279 ts->f->Write();
02280 ts->f->Close();
02281 delete ts->f;
02282
02283
02284 free(ts->event_tree);
02285 free(ts);
02286
02287 log_chn->format_info = NULL;
02288
02289 return SS_SUCCESS;
02290 }
02291
02292 #endif
02293
02294
02295
02296 INT log_open(LOG_CHN * log_chn, INT run_number)
02297 {
02298 INT status;
02299
02300 if (equal_ustring(log_chn->settings.format, "YBOS")) {
02301 assert(!"YBOS not supported anymore");
02302 } else if (equal_ustring(log_chn->settings.format, "ASCII")) {
02303 log_chn->format = FORMAT_ASCII;
02304 status = ascii_log_open(log_chn, run_number);
02305 } else if (equal_ustring(log_chn->settings.format, "DUMP")) {
02306 log_chn->format = FORMAT_DUMP;
02307 status = dump_log_open(log_chn, run_number);
02308 } else if (equal_ustring(log_chn->settings.format, "ROOT")) {
02309 #ifdef USE_ROOT
02310 log_chn->format = FORMAT_ROOT;
02311 status = root_log_open(log_chn, run_number);
02312 #else
02313 return SS_NO_ROOT;
02314 #endif
02315 } else if (equal_ustring(log_chn->settings.format, "MIDAS")) {
02316 log_chn->format = FORMAT_MIDAS;
02317 status = midas_log_open(log_chn, run_number);
02318 } else
02319 return SS_INVALID_FORMAT;
02320
02321 return status;
02322 }
02323
02324
02325
02326 INT log_close(LOG_CHN * log_chn, INT run_number)
02327 {
02328 if (log_chn->format == FORMAT_YBOS)
02329 assert(!"YBOS not supported anymore");
02330 if (log_chn->format == FORMAT_ASCII)
02331 ascii_log_close(log_chn, run_number);
02332
02333 if (log_chn->format == FORMAT_DUMP)
02334 dump_log_close(log_chn, run_number);
02335
02336 #ifdef USE_ROOT
02337 if (log_chn->format == FORMAT_ROOT)
02338 root_log_close(log_chn, run_number);
02339 #endif
02340
02341 if (log_chn->format == FORMAT_MIDAS)
02342 midas_log_close(log_chn, run_number);
02343
02344 log_chn->statistics.files_written += 1;
02345 log_chn->handle = 0;
02346 log_chn->ftp_con = NULL;
02347
02348 return SS_SUCCESS;
02349 }
02350
02351
02352
02353 INT log_write(LOG_CHN * log_chn, EVENT_HEADER * pevent)
02354 {
02355 INT status = 0, size, izero;
02356 DWORD actual_time, start_time, watchdog_timeout;
02357 BOOL watchdog_flag, flag;
02358 static BOOL stop_requested = FALSE;
02359 static DWORD last_checked = 0;
02360 HNDLE htape, stats_hkey;
02361 char tape_name[256];
02362 double dzero;
02363
02364 start_time = ss_millitime();
02365
02366 if (log_chn->format == FORMAT_YBOS)
02367 assert(!"YBOS not supported anymore");
02368
02369 if (log_chn->format == FORMAT_ASCII)
02370 status = ascii_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
02371
02372 if (log_chn->format == FORMAT_DUMP)
02373 status = dump_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
02374
02375 if (log_chn->format == FORMAT_MIDAS)
02376 status = midas_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
02377
02378 #ifdef USE_ROOT
02379 if (log_chn->format == FORMAT_ROOT)
02380 status = root_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
02381 #endif
02382
02383 actual_time = ss_millitime();
02384 if ((int) actual_time - (int) start_time > 3000)
02385 cm_msg(MINFO, "log_write", "Write operation on %s took %d ms", log_chn->path,
02386 actual_time - start_time);
02387
02388 if (status != SS_SUCCESS && !stop_requested) {
02389 if (status == SS_IO_ERROR)
02390 cm_msg(MTALK, "log_write", "Physical IO error on %s, stopping run",
02391 log_chn->path);
02392 else
02393 cm_msg(MTALK, "log_write", "Error writing to %s, stopping run", log_chn->path);
02394
02395 stop_requested = TRUE;
02396 cm_transition(TR_STOP, 0, NULL, 0, ASYNC, DEBUG_TRANS);
02397 stop_requested = FALSE;
02398
02399 return status;
02400 }
02401
02402
02403 if (!stop_requested && !in_stop_transition &&
02404 log_chn->settings.event_limit > 0 &&
02405 log_chn->statistics.events_written >= log_chn->settings.event_limit) {
02406 stop_requested = TRUE;
02407
02408 cm_msg(MTALK, "log_write", "stopping run after having received %d events",
02409 log_chn->settings.event_limit);
02410
02411 status = cm_transition(TR_STOP, 0, NULL, 0, ASYNC, DEBUG_TRANS);
02412 if (status != CM_SUCCESS)
02413 cm_msg(MERROR, "log_write", "cannot stop run after reaching event limit");
02414 stop_requested = FALSE;
02415
02416
02417 size = sizeof(BOOL);
02418 flag = FALSE;
02419 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
02420
02421 if (flag)
02422 auto_restart = ss_time() + 20;
02423
02424 return status;
02425 }
02426
02427
02428 if (!stop_requested && !in_stop_transition &&
02429 log_chn->settings.byte_limit > 0 &&
02430 log_chn->statistics.bytes_written >= log_chn->settings.byte_limit) {
02431 stop_requested = TRUE;
02432
02433 cm_msg(MTALK, "log_write", "stopping run after having received %1.0lf mega bytes",
02434 log_chn->statistics.bytes_written / 1E6);
02435
02436 status = cm_transition(TR_STOP, 0, NULL, 0, ASYNC, DEBUG_TRANS);
02437 if (status != CM_SUCCESS)
02438 cm_msg(MERROR, "log_write", "cannot stop run after reaching bytes limit");
02439 stop_requested = FALSE;
02440
02441
02442 size = sizeof(BOOL);
02443 flag = FALSE;
02444 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
02445
02446 if (flag)
02447 auto_restart = ss_time() + 20;
02448
02449 return status;
02450 }
02451
02452
02453 if (!stop_requested && !in_stop_transition &&
02454 log_chn->type == LOG_TYPE_TAPE &&
02455 log_chn->settings.tape_capacity > 0 &&
02456 log_chn->statistics.bytes_written_total >= log_chn->settings.tape_capacity) {
02457 stop_requested = TRUE;
02458 cm_msg(MTALK, "log_write", "tape capacity reached, stopping run");
02459
02460
02461 strcpy(tape_name, log_chn->path);
02462 stats_hkey = log_chn->stats_hkey;
02463
02464 status = cm_transition(TR_STOP, 0, NULL, 0, ASYNC, DEBUG_TRANS);
02465 if (status != CM_SUCCESS)
02466 cm_msg(MERROR, "log_write", "cannot stop run after reaching tape capacity");
02467 stop_requested = FALSE;
02468
02469
02470 ss_tape_open(tape_name, O_RDONLY, &htape);
02471 cm_msg(MTALK, "log_write", "rewinding tape %s, please wait", log_chn->path);
02472
02473 cm_get_watchdog_params(&watchdog_flag, &watchdog_timeout);
02474 cm_set_watchdog_params(watchdog_flag, 300000);
02475 ss_tape_unmount(htape);
02476 ss_tape_close(htape);
02477 cm_set_watchdog_params(watchdog_flag, watchdog_timeout);
02478
02479
02480 dzero = izero = 0;
02481 db_set_value(hDB, stats_hkey, "Bytes written total", &dzero,
02482 sizeof(dzero), 1, TID_DOUBLE);
02483 db_set_value(hDB, stats_hkey, "Files written", &izero, sizeof(izero), 1, TID_INT);
02484
02485 cm_msg(MTALK, "log_write", "Please insert new tape and start new run.");
02486
02487 return status;
02488 }
02489
02490
02491 actual_time = ss_millitime();
02492 if (log_chn->type == LOG_TYPE_DISK && actual_time - last_checked > 1000) {
02493 last_checked = actual_time;
02494
02495 if (ss_disk_free(log_chn->path) < 1E7 && !stop_requested && !in_stop_transition) {
02496 stop_requested = TRUE;
02497 cm_msg(MTALK, "log_write", "disk nearly full, stopping run");
02498
02499 status = cm_transition(TR_STOP, 0, NULL, 0, ASYNC, DEBUG_TRANS);
02500 if (status != CM_SUCCESS)
02501 cm_msg(MERROR, "log_write", "cannot stop run after reaching byte limit");
02502 stop_requested = FALSE;
02503 }
02504 }
02505
02506 return status;
02507 }
02508
02509
02510
02511 void log_history(HNDLE hDB, HNDLE hKey, void *info);
02512
02513 INT open_history()
02514 {
02515 INT size, index, i_tag, status, i, j, li, max_event_id;
02516 INT n_var, n_tags, n_names = 0;
02517 HNDLE hKeyRoot, hKeyVar, hKeyNames, hLinkKey, hVarKey, hKeyEq, hHistKey, hKey;
02518 DWORD history;
02519 TAG *tag;
02520 KEY key, varkey, linkkey, histkey;
02521 WORD event_id;
02522 char str[256], eq_name[NAME_LENGTH], hist_name[NAME_LENGTH];
02523 BOOL single_names;
02524
02525
02526 size = sizeof(str);
02527 str[0] = 0;
02528 status = db_get_value(hDB, 0, "/Logger/History Dir", str, &size, TID_STRING, FALSE);
02529 if (status != DB_SUCCESS)
02530 db_get_value(hDB, 0, "/Logger/Data Dir", str, &size, TID_STRING, TRUE);
02531
02532 if (str[0] != 0)
02533 hs_set_path(str);
02534
02535 if (db_find_key(hDB, 0, "/History/Links", &hKeyRoot) != DB_SUCCESS ||
02536 db_find_key(hDB, 0, "/History/Links/System", &hKeyRoot) != DB_SUCCESS) {
02537
02538 db_create_key(hDB, 0, "/History/Links", TID_KEY);
02539
02540 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/Events per sec.", &hKeyEq) ==
02541 DB_SUCCESS)
02542 db_create_link(hDB, 0, "/History/Links/System/Trigger per sec.",
02543 "/Equipment/Trigger/Statistics/Events per sec.");
02544
02545 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/kBytes per sec.", &hKeyEq) ==
02546 DB_SUCCESS)
02547 db_create_link(hDB, 0, "/History/Links/System/Trigger kB per sec.",
02548 "/Equipment/Trigger/Statistics/kBytes per sec.");
02549 }
02550
02551
02552
02553 max_event_id = 0;
02554
02555 status = db_find_key(hDB, 0, "/Equipment", &hKeyRoot);
02556 if (status != DB_SUCCESS) {
02557 cm_msg(MERROR, "open_history", "Cannot find Equipment entry in database");
02558 return 0;
02559 }
02560
02561
02562 for (index = 0; index < MAX_HISTORY; index++) {
02563 status = db_enum_key(hDB, hKeyRoot, index, &hKeyEq);
02564 if (status != DB_SUCCESS)
02565 break;
02566
02567
02568 size = sizeof(history);
02569 db_get_value(hDB, hKeyEq, "Common/Log history", &history, &size, TID_INT, TRUE);
02570
02571
02572 if (history > 0) {
02573
02574 db_get_key(hDB, hKeyEq, &key);
02575 strcpy(eq_name, key.name);
02576
02577
02578 status = db_find_key(hDB, hKeyEq, "Variables", &hKeyVar);
02579 if (status != DB_SUCCESS) {
02580 cm_msg(MERROR, "open_history",
02581 "Cannot find /Equipment/%s/Variables entry in database", eq_name);
02582 return 0;
02583 }
02584
02585 size = sizeof(event_id);
02586 db_get_value(hDB, hKeyEq, "Common/Event ID", &event_id, &size, TID_WORD, TRUE);
02587
02588 if (verbose)
02589 printf
02590 ("\n==================== Equipment \"%s\", ID %d =======================\n",
02591 eq_name, event_id);
02592
02593
02594 for (n_var = 0, n_tags = 0;; n_var++) {
02595 status = db_enum_key(hDB, hKeyVar, n_var, &hKey);
02596 if (status == DB_NO_MORE_SUBKEYS)
02597 break;
02598 db_get_key(hDB, hKey, &key);
02599 n_tags += key.num_values;
02600 }
02601
02602 if (n_var == 0)
02603 cm_msg(MERROR, "open_history", "defined event %d with no variables in ODB",
02604 event_id);
02605
02606
02607 tag = (TAG *) malloc(sizeof(TAG) * n_tags);
02608
02609 for (i = 0, i_tag = 0;; i++) {
02610 status = db_enum_key(hDB, hKeyVar, i, &hKey);
02611 if (status == DB_NO_MORE_SUBKEYS)
02612 break;
02613
02614
02615 db_get_key(hDB, hKey, &varkey);
02616
02617
02618 db_find_key(hDB, hKeyEq, "Settings/Names", &hKeyNames);
02619 single_names = (hKeyNames > 0);
02620 if (hKeyNames) {
02621 if (verbose)
02622 printf("Using \"/Equipment/%s/Settings/Names\" for variable \"%s\"\n",
02623 eq_name, varkey.name);
02624
02625
02626 db_get_key(hDB, hKeyNames, &key);
02627 n_names = key.num_values;
02628 } else {
02629 sprintf(str, "Settings/Names %s", varkey.name);
02630 db_find_key(hDB, hKeyEq, str, &hKeyNames);
02631 if (hKeyNames) {
02632 if (verbose)
02633 printf
02634 ("Using \"/Equipment/%s/Settings/Names %s\" for variable \"%s\"\n",
02635 eq_name, varkey.name, varkey.name);
02636
02637
02638 db_get_key(hDB, hKeyNames, &key);
02639 n_names = key.num_values;
02640 }
02641 }
02642
02643 if (hKeyNames && varkey.num_values != n_names) {
02644 cm_msg(MERROR, "open_history",
02645 "Mismatch between \"/Equipment/%s/Settings/%s\" and \"/Equipment/%s/Variables/%s\" (%d vs. %d entries)",
02646 eq_name, key.name, eq_name, varkey.name, n_names,
02647 varkey.num_values);
02648 free(tag);
02649 return 0;
02650 }
02651
02652 if (hKeyNames) {
02653
02654 for (j = 0; j < varkey.num_values; j++) {
02655
02656 size = NAME_LENGTH;
02657 db_get_data_index(hDB, hKeyNames, tag[i_tag].name, &size, j,
02658 TID_STRING);
02659
02660
02661 if (single_names) {
02662 if (strlen(tag[i_tag].name) + 1 + strlen(varkey.name) >= NAME_LENGTH) {
02663 cm_msg(MERROR, "open_history",
02664 "Name for history entry \"%s %s\" too long",
02665 tag[i_tag].name, varkey.name);
02666 free(tag);
02667 return 0;
02668 }
02669 strcat(tag[i_tag].name, " ");
02670 strcat(tag[i_tag].name, varkey.name);
02671 }
02672
02673 tag[i_tag].type = varkey.type;
02674 tag[i_tag].n_data = 1;
02675
02676 if (verbose)
02677 printf("Defined tag \"%s\", size 1\n", tag[i_tag].name);
02678
02679 i_tag++;
02680 }
02681 } else {
02682 strcpy(tag[i_tag].name, varkey.name);
02683 tag[i_tag].type = varkey.type;
02684 tag[i_tag].n_data = varkey.num_values;
02685
02686 if (verbose)
02687 printf("Defined tag \"%s\", size %d\n", tag[i_tag].name,
02688 varkey.num_values);
02689
02690 i_tag++;
02691 }
02692 }
02693
02694 hs_define_event(event_id, eq_name, tag, sizeof(TAG) * i_tag);
02695 free(tag);
02696
02697 if (verbose)
02698 printf("\n");
02699
02700
02701 hist_log[index].event_id = event_id;
02702 hist_log[index].hKeyVar = hKeyVar;
02703 db_get_record_size(hDB, hKeyVar, 0, &size);
02704 hist_log[index].buffer_size = size;
02705 hist_log[index].buffer = malloc(size);
02706 hist_log[index].period = history;
02707 hist_log[index].last_log = 0;
02708 if (hist_log[index].buffer == NULL) {
02709 cm_msg(MERROR, "open_history", "cannot allocate history buffer");
02710 return 0;
02711 }
02712
02713
02714 status = db_open_record(hDB, hKeyVar, hist_log[index].buffer,
02715 size, MODE_READ, log_history, NULL);
02716 if (status != DB_SUCCESS)
02717 cm_msg(MERROR, "open_history",
02718 "cannot open variable record for history logging");
02719
02720
02721 if (event_id > max_event_id)
02722 max_event_id = event_id;
02723 } else {
02724 hist_log[index].event_id = 0;
02725 hist_log[index].hKeyVar = 0;
02726 hist_log[index].buffer = NULL;
02727 hist_log[index].buffer_size = 0;
02728 hist_log[index].period = 0;
02729 }
02730 }
02731
02732 if (index == MAX_HISTORY) {
02733 cm_msg(MERROR, "open_history", "too many equipments for history");
02734 return 0;
02735 }
02736
02737
02738
02739
02740 max_event_id = ((int) ((max_event_id + 1) / 10) + 1) * 10;
02741
02742 status = db_find_key(hDB, 0, "/History/Links", &hKeyRoot);
02743 if (status == DB_SUCCESS) {
02744 for (li = 0;; li++) {
02745 status = db_enum_link(hDB, hKeyRoot, li, &hHistKey);
02746 if (status == DB_NO_MORE_SUBKEYS)
02747 break;
02748
02749 db_get_key(hDB, hHistKey, &histkey);
02750 strcpy(hist_name, histkey.name);
02751 db_enum_key(hDB, hKeyRoot, li, &hHistKey);
02752
02753 db_get_key(hDB, hHistKey, &key);
02754 if (key.type != TID_KEY) {
02755 cm_msg(MERROR, "open_history", "Only subkeys allows in /history/links");
02756 continue;
02757 }
02758
02759 if (verbose)
02760 printf
02761 ("\n==================== History link \"%s\", ID %d =======================\n",
02762 hist_name, max_event_id);
02763
02764
02765 for (i = n_var = 0;; i++) {
02766 status = db_enum_key(hDB, hHistKey, i, &hKey);
02767 if (status == DB_NO_MORE_SUBKEYS)
02768 break;
02769
02770 if (status == DB_SUCCESS && db_get_key(hDB, hKey, &key) == DB_SUCCESS) {
02771 if (key.type != TID_KEY)
02772 n_var++;
02773 } else {
02774 db_enum_link(hDB, hHistKey, i, &hKey);
02775 db_get_key(hDB, hKey, &key);
02776 cm_msg(MERROR, "open_history",
02777 "History link /History/Links/%s/%s is invalid", hist_name,
02778 key.name);
02779 return 0;
02780 }
02781 }
02782
02783 if (n_var == 0)
02784 cm_msg(MERROR, "open_history", "History event %s has no variables in ODB",
02785 hist_name);
02786 else {
02787
02788 tag = (TAG *) malloc(sizeof(TAG) * n_var);
02789
02790 for (i = 0, size = 0, n_var = 0;; i++) {
02791 status = db_enum_link(hDB, hHistKey, i, &hLinkKey);
02792 if (status == DB_NO_MORE_SUBKEYS)
02793 break;
02794
02795
02796 db_get_key(hDB, hLinkKey, &linkkey);
02797
02798 if (linkkey.type == TID_KEY)
02799 continue;
02800
02801
02802 db_enum_key(hDB, hHistKey, i, &hVarKey);
02803 if (db_get_key(hDB, hVarKey, &varkey) == DB_SUCCESS) {
02804
02805 if (histkey.type == TID_KEY)
02806 db_open_record(hDB, hVarKey, NULL, varkey.total_size, MODE_READ,
02807 log_system_history, (void *) (POINTER_T) index);
02808
02809 strcpy(tag[n_var].name, linkkey.name);
02810 tag[n_var].type = varkey.type;
02811 tag[n_var].n_data = varkey.num_values;
02812
02813 if (verbose)
02814 printf("Defined tag \"%s\", size %d\n", tag[n_var].name,
02815 varkey.num_values);
02816
02817 size += varkey.total_size;
02818 n_var++;
02819 }
02820 }
02821
02822
02823 if (histkey.type == TID_LINK)
02824 db_open_record(hDB, hHistKey, NULL, size, MODE_READ, log_system_history,
02825 (void *) (POINTER_T) index);
02826
02827 hs_define_event(max_event_id, hist_name, tag, sizeof(TAG) * n_var);
02828 free(tag);
02829
02830 if (verbose)
02831 printf("\n");
02832
02833
02834
02835 hist_log[index].event_id = max_event_id;
02836 hist_log[index].hKeyVar = hHistKey;
02837 hist_log[index].buffer_size = size;
02838 hist_log[index].buffer = malloc(size);
02839 hist_log[index].period = 10;
02840 hist_log[index].last_log = 0;
02841 if (hist_log[index].buffer == NULL) {
02842 cm_msg(MERROR, "open_history", "cannot allocate history buffer");
02843 return 0;
02844 }
02845
02846 index++;
02847 max_event_id++;
02848
02849 if (index == MAX_HISTORY) {
02850 cm_msg(MERROR, "open_history", "too many equipments for history");
02851 return 0;
02852 }
02853 }
02854 }
02855 }
02856
02857
02858
02859 tag = (TAG *) malloc(sizeof(TAG) * 2);
02860
02861 strcpy(tag[0].name, "State");
02862 tag[0].type = TID_DWORD;
02863 tag[0].n_data = 1;
02864
02865 strcpy(tag[1].name, "Run number");
02866 tag[1].type = TID_DWORD;
02867 tag[1].n_data = 1;
02868
02869 hs_define_event(0, "Run transitions", tag, sizeof(TAG) * 2);
02870 free(tag);
02871
02872 return CM_SUCCESS;
02873 }
02874
02875
02876
02877 void close_history()
02878 {
02879 INT i, status;
02880 HNDLE hKeyRoot, hKey;
02881
02882
02883 status = db_find_key(hDB, 0, "/History/Links", &hKeyRoot);
02884 if (status != DB_SUCCESS) {
02885 for (i = 0;; i++) {
02886 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
02887 if (status == DB_NO_MORE_SUBKEYS)
02888 break;
02889 db_close_record(hDB, hKey);
02890 }
02891 }
02892
02893
02894 for (i = 1; i < MAX_HISTORY; i++)
02895 if (hist_log[i].hKeyVar) {
02896 db_close_record(hDB, hist_log[i].hKeyVar);
02897 free(hist_log[i].buffer);
02898 }
02899 }
02900
02901
02902
02903 void log_history(HNDLE hDB, HNDLE hKey, void *info)
02904 {
02905 INT i, size;
02906
02907 for (i = 0; i < MAX_HISTORY; i++)
02908 if (hist_log[i].hKeyVar == hKey)
02909 break;
02910
02911 if (i == MAX_HISTORY)
02912 return;
02913
02914
02915 if (ss_time() - hist_log[i].last_log < hist_log[i].period)
02916 return;
02917
02918
02919 db_get_record_size(hDB, hKey, 0, &size);
02920 if (size != hist_log[i].buffer_size) {
02921 close_history();
02922 open_history();
02923 }
02924
02925 hs_write_event(hist_log[i].event_id, hist_log[i].buffer, hist_log[i].buffer_size);
02926 hist_log[i].last_log = ss_time();
02927 }
02928
02929
02930
02931 void log_system_history(HNDLE hDB, HNDLE hKey, void *info)
02932 {
02933 INT i, size, total_size, status, index;
02934 KEY key;
02935
02936 index = (INT) (POINTER_T) info;
02937
02938
02939 if (ss_time() - hist_log[index].last_log < hist_log[index].period)
02940 return;
02941
02942 for (i = 0, total_size = 0;; i++) {
02943 status = db_enum_key(hDB, hist_log[index].hKeyVar, i, &hKey);
02944 if (status == DB_NO_MORE_SUBKEYS)
02945 break;
02946
02947 db_get_key(hDB, hKey, &key);
02948 size = key.total_size;
02949 db_get_data(hDB, hKey, (char *) hist_log[index].buffer + total_size, &size,
02950 key.type);
02951 total_size += size;
02952 }
02953
02954 if (total_size != hist_log[index].buffer_size) {
02955 close_history();
02956 open_history();
02957 } else
02958 hs_write_event(hist_log[index].event_id, hist_log[index].buffer,
02959 hist_log[index].buffer_size);
02960
02961 hist_log[index].last_log = ss_time();
02962
02963
02964 if (!rpc_is_remote()) {
02965 db_lock_database(hDB);
02966 db_notify_clients(hDB, hist_log[index].hKeyVar, FALSE);
02967 db_unlock_database(hDB);
02968 }
02969
02970 }
02971
02972
02973
02974 INT log_callback(INT index, void *prpc_param[])
02975 {
02976 HNDLE hKeyRoot, hKeyChannel;
02977 INT i, status, size, channel, izero, htape, online_mode;
02978 DWORD watchdog_timeout;
02979 BOOL watchdog_flag;
02980 char str[256];
02981 double dzero;
02982
02983
02984 if (index == RPC_LOG_REWIND) {
02985 channel = *((INT *) prpc_param[0]);
02986
02987
02988 status = db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot);
02989 if (status != DB_SUCCESS) {
02990 cm_msg(MERROR, "log_callback", "cannot find Logger/Channels entry in database");
02991 return 0;
02992 }
02993
02994
02995 online_mode = 0;
02996 size = sizeof(online_mode);
02997 db_get_value(hDB, 0, "/Runinfo/online mode", &online_mode, &size, TID_INT, TRUE);
02998
02999 for (i = 0; i < MAX_CHANNELS; i++) {
03000 status = db_enum_key(hDB, hKeyRoot, i, &hKeyChannel);
03001 if (status == DB_NO_MORE_SUBKEYS)
03002 break;
03003
03004
03005 if (channel != i && channel != -1)
03006 continue;
03007
03008 if (status == DB_SUCCESS) {
03009 size = sizeof(str);
03010 status =
03011 db_get_value(hDB, hKeyChannel, "Settings/Type", str, &size, TID_STRING,
03012 TRUE);
03013 if (status != DB_SUCCESS)
03014 continue;
03015
03016 if (equal_ustring(str, "Tape")) {
03017 size = sizeof(str);
03018 status =
03019 db_get_value(hDB, hKeyChannel, "Settings/Filename", str, &size,
03020 TID_STRING, TRUE);
03021 if (status != DB_SUCCESS)
03022 continue;
03023
03024 if (ss_tape_open(str, O_RDONLY, &htape) == SS_SUCCESS) {
03025 cm_msg(MTALK, "log_callback", "rewinding tape #%d, please wait", i);
03026
03027 cm_get_watchdog_params(&watchdog_flag, &watchdog_timeout);
03028 cm_set_watchdog_params(watchdog_flag, 300000);
03029 ss_tape_rewind(htape);
03030 if (online_mode)
03031 ss_tape_unmount(htape);
03032 cm_set_watchdog_params(watchdog_flag, watchdog_timeout);
03033
03034 cm_msg(MINFO, "log_callback", "Tape %s rewound sucessfully", str);
03035 } else
03036 cm_msg(MERROR, "log_callback", "Cannot rewind tape %s", str);
03037
03038 ss_tape_close(htape);
03039
03040
03041 dzero = izero = 0;
03042 log_chn[i].statistics.bytes_written_total = 0;
03043 log_chn[i].statistics.files_written = 0;
03044 db_set_value(hDB, hKeyChannel, "Statistics/Bytes written total", &dzero,
03045 sizeof(dzero), 1, TID_DOUBLE);
03046 db_set_value(hDB, hKeyChannel, "Statistics/Files written", &izero,
03047 sizeof(izero), 1, TID_INT);
03048 }
03049 }
03050 }
03051
03052 cm_msg(MTALK, "log_callback", "tape rewind finished");
03053 }
03054
03055 return RPC_SUCCESS;
03056 }
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066 struct eb_struct {
03067 DWORD transition;
03068 DWORD run_number;
03069 } eb;
03070
03071
03072
03073 INT tr_start(INT run_number, char *error)
03074
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085
03086 {
03087 INT size, index, status;
03088 HNDLE hKeyRoot, hKeyChannel;
03089 char str[256], path[256], dir[256], data_dir[256];
03090 CHN_SETTINGS *chn_settings;
03091 KEY key;
03092 BOOL write_data, tape_flag = FALSE;
03093 time_t now;
03094 struct tm *tms;
03095
03096
03097 odb_save("last.xml");
03098
03099
03100 size = sizeof(BOOL);
03101 write_data = TRUE;
03102 db_get_value(hDB, 0, "/Logger/Write data", &write_data, &size, TID_BOOL, TRUE);
03103
03104
03105 size = sizeof(tape_message);
03106 db_get_value(hDB, 0, "/Logger/Tape message", &tape_message, &size, TID_BOOL, TRUE);
03107
03108
03109 status = db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot);
03110 if (status != DB_SUCCESS) {
03111
03112 status = db_create_record(hDB, 0, "/Logger/Channels/0/", strcomb(chn_settings_str));
03113 if (status != DB_SUCCESS) {
03114 strcpy(error, "Cannot create channel entry in database");
03115 cm_msg(MERROR, "tr_prestart", error);
03116 return 0;
03117 }
03118
03119 status = db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot);
03120 if (status != DB_SUCCESS) {
03121 strcpy(error, "Cannot create channel entry in database");
03122 cm_msg(MERROR, "tr_prestart", error);
03123 return 0;
03124 }
03125 }
03126
03127 for (index = 0; index < MAX_CHANNELS; index++) {
03128 status = db_enum_key(hDB, hKeyRoot, index, &hKeyChannel);
03129 if (status == DB_NO_MORE_SUBKEYS)
03130 break;
03131
03132
03133 db_get_key(hDB, hKeyChannel, &key);
03134 status = db_check_record(hDB, hKeyRoot, key.name, strcomb(chn_settings_str), TRUE);
03135 if (status != DB_SUCCESS && status != DB_OPEN_RECORD) {
03136 cm_msg(MERROR, "tr_prestart", "Cannot create/check channel record");
03137 break;
03138 }
03139
03140 if (status == DB_SUCCESS || status == DB_OPEN_RECORD) {
03141
03142
03143 if (log_chn[index].handle) {
03144 log_close(&log_chn[index], run_number);
03145 if (log_chn[index].type == LOG_TYPE_DISK) {
03146 cm_msg(MINFO, "tr_prestart", "Deleting previous file \"%s\"",
03147 log_chn[index].path);
03148 unlink(log_chn[index].path);
03149 }
03150 }
03151
03152
03153 if (log_chn[index].ftp_con)
03154 continue;
03155
03156
03157 status =
03158 db_find_key(hDB, hKeyChannel, "Settings", &log_chn[index].settings_hkey);
03159 if (status != DB_SUCCESS) {
03160 strcpy(error, "Cannot find channel settings info");
03161 cm_msg(MERROR, "tr_prestart", error);
03162 return 0;
03163 }
03164
03165
03166 status = db_find_key(hDB, hKeyChannel, "Statistics", &log_chn[index].stats_hkey);
03167 if (status != DB_SUCCESS) {
03168 strcpy(error, "Cannot find channel statistics info");
03169 cm_msg(MERROR, "tr_prestart", error);
03170 return 0;
03171 }
03172
03173
03174 size = sizeof(CHN_STATISTICS);
03175 db_get_record(hDB, log_chn[index].stats_hkey, &log_chn[index].statistics, &size,
03176 0);
03177
03178 log_chn[index].statistics.events_written = 0;
03179 log_chn[index].statistics.bytes_written = 0;
03180
03181 db_set_record(hDB, log_chn[index].stats_hkey, &log_chn[index].statistics, size,
03182 0);
03183
03184
03185 chn_settings = &log_chn[index].settings;
03186 size = sizeof(CHN_SETTINGS);
03187 status =
03188 db_get_record(hDB, log_chn[index].settings_hkey, chn_settings, &size, 0);
03189 if (status != DB_SUCCESS) {
03190 strcpy(error, "Cannot read channel info");
03191 cm_msg(MERROR, "tr_prestart", error);
03192 return 0;
03193 }
03194
03195
03196 if (log_chn[index].type == LOG_TYPE_TAPE &&
03197 chn_settings->tape_capacity > 0 &&
03198 log_chn[index].statistics.bytes_written_total >= chn_settings->tape_capacity)
03199 {
03200 strcpy(error, "Tape capacity reached. Please load new tape");
03201 cm_msg(MERROR, "tr_prestart", error);
03202 return 0;
03203 }
03204
03205
03206 if (!chn_settings->active || !write_data)
03207 continue;
03208
03209
03210 if (equal_ustring(chn_settings->type, "Tape"))
03211 log_chn[index].type = LOG_TYPE_TAPE;
03212 else if (equal_ustring(chn_settings->type, "FTP"))
03213 log_chn[index].type = LOG_TYPE_FTP;
03214 else if (equal_ustring(chn_settings->type, "Disk"))
03215 log_chn[index].type = LOG_TYPE_DISK;
03216 else {
03217 sprintf(error,
03218 "Invalid channel type \"%s\", pease use \"Tape\", \"FTP\" or \"Disk\"",
03219 chn_settings->type);
03220 cm_msg(MERROR, "tr_prestart", error);
03221 return 0;
03222 }
03223
03224 data_dir[0] = 0;
03225
03226
03227 if (log_chn[index].type == LOG_TYPE_DISK &&
03228 chn_settings->filename[0] != DIR_SEPARATOR) {
03229 size = sizeof(data_dir);
03230 dir[0] = 0;
03231 db_get_value(hDB, 0, "/Logger/Data Dir", data_dir, &size, TID_STRING, TRUE);
03232 if (data_dir[0] != 0)
03233 if (data_dir[strlen(data_dir) - 1] != DIR_SEPARATOR)
03234 strcat(data_dir, DIR_SEPARATOR_STR);
03235 strcpy(str, data_dir);
03236
03237
03238 if (chn_settings->subdir_format[0]) {
03239 tzset();
03240 time(&now);
03241 tms = localtime(&now);
03242
03243 strftime(dir, sizeof(dir), chn_settings->subdir_format, tms);
03244 strcat(str, dir);
03245 strcat(str, DIR_SEPARATOR_STR);
03246 }
03247
03248
03249 #ifdef OS_WINNT
03250 status = mkdir(str);
03251 #else
03252 status = mkdir(str, 0755);
03253 #endif
03254 #if !defined(HAVE_MYSQL) && !defined(OS_WINNT)
03255 if (status == -1 && errno != EEXIST)
03256 cm_msg(MERROR, "tr_prestart", "Cannot create subdirectory %s", str);
03257 #endif
03258
03259 strcat(str, chn_settings->filename);
03260 } else
03261 strcpy(str, chn_settings->filename);
03262
03263
03264 if (strchr(str, '%'))
03265 sprintf(path, str, run_number);
03266 else
03267 strcpy(path, str);
03268
03269 strcpy(log_chn[index].path, path);
03270
03271
03272 if (strncmp(path, data_dir, strlen(data_dir)) == 0)
03273 strcpy(str, path + strlen(data_dir));
03274 else
03275 strcpy(str, path);
03276 db_set_value(hDB, hKeyChannel, "Settings/Current filename", str, 256, 1,
03277 TID_STRING);
03278
03279 if (log_chn[index].type == LOG_TYPE_TAPE &&
03280 log_chn[index].statistics.bytes_written_total == 0 && tape_message) {
03281 tape_flag = TRUE;
03282 cm_msg(MTALK, "tr_prestart", "mounting tape #%d, please wait", index);
03283 }
03284
03285
03286 status = log_open(&log_chn[index], run_number);
03287
03288
03289 if (status != SS_SUCCESS) {
03290 if (status == SS_FILE_ERROR)
03291 sprintf(error, "Cannot open file %s (Disk full?)", path);
03292 if (status == SS_FILE_EXISTS)
03293 sprintf(error, "File %s exists already, run start aborted", path);
03294 if (status == SS_NO_TAPE)
03295 sprintf(error, "No tape in device %s", path);
03296 if (status == SS_TAPE_ERROR)
03297 sprintf(error, "Tape error, cannot start run");
03298 if (status == SS_DEV_BUSY)
03299 sprintf(error, "Device %s used by someone else", path);
03300 if (status == FTP_NET_ERROR || status == FTP_RESPONSE_ERROR)
03301 sprintf(error, "Cannot open FTP channel to [%s]", path);
03302 if (status == SS_NO_ROOT)
03303 sprintf(error,
03304 "No ROOT support compiled into mlogger, please compile with -DUSE_ROOT flag");
03305
03306 if (status == SS_INVALID_FORMAT)
03307 sprintf(error,
03308 "Invalid data format, please use \"MIDAS\", \"ASCII\", \"DUMP\" or \"ROOT\"");
03309
03310 cm_msg(MERROR, "tr_prestart", error);
03311 return 0;
03312 }
03313
03314
03315 if (log_chn[index].stats_hkey)
03316 db_close_record(hDB, log_chn[index].stats_hkey);
03317 if (log_chn[index].settings_hkey)
03318 db_close_record(hDB, log_chn[index].settings_hkey);
03319
03320
03321 status =
03322 db_open_record(hDB, log_chn[index].stats_hkey, &log_chn[index].statistics,
03323 sizeof(CHN_STATISTICS), MODE_WRITE, NULL, NULL);
03324 if (status != DB_SUCCESS)
03325 cm_msg(MERROR, "tr_prestart",
03326 "cannot open statistics record, probably other logger is using it");
03327
03328
03329 status =
03330 db_open_record(hDB, log_chn[index].settings_hkey, &log_chn[index].settings,
03331 sizeof(CHN_SETTINGS), MODE_READ, NULL, NULL);
03332 if (status != DB_SUCCESS)
03333 cm_msg(MERROR, "tr_prestart",
03334 "cannot open channel settings record, probably other logger is using it");
03335
03336 #ifndef FAL_MAIN
03337
03338 status =
03339 bm_open_buffer(chn_settings->buffer, 2*MAX_EVENT_SIZE,
03340 &log_chn[index].buffer_handle);
03341 if (status != BM_SUCCESS && status != BM_CREATED) {
03342 sprintf(error, "Cannot open buffer %s", str);
03343 cm_msg(MERROR, "tr_prestart", error);
03344 return 0;
03345 }
03346 bm_set_cache_size(log_chn[index].buffer_handle, 100000, 0);
03347
03348
03349 status = bm_request_event(log_chn[index].buffer_handle,
03350 (short) chn_settings->event_id,
03351 (short) chn_settings->trigger_mask,
03352 GET_ALL, &log_chn[index].request_id, receive_event);
03353
03354 if (status != BM_SUCCESS) {
03355 sprintf(error, "Cannot place event request");
03356 cm_msg(MERROR, "tr_prestart", error);
03357 return 0;
03358 }
03359
03360
03361 if (chn_settings->log_messages) {
03362 status =
03363 bm_open_buffer(MESSAGE_BUFFER_NAME, MESSAGE_BUFFER_SIZE,
03364 &log_chn[index].msg_buffer_handle);
03365 if (status != BM_SUCCESS && status != BM_CREATED) {
03366 sprintf(error, "Cannot open buffer %s", MESSAGE_BUFFER_NAME);
03367 cm_msg(MERROR, "tr_prestart", error);
03368 return 0;
03369 }
03370
03371
03372 status = bm_request_event(log_chn[index].msg_buffer_handle,
03373 (short) EVENTID_MESSAGE,
03374 (short) chn_settings->log_messages,
03375 GET_ALL, &log_chn[index].msg_request_id,
03376 receive_event);
03377
03378 if (status != BM_SUCCESS) {
03379 sprintf(error, "Cannot place event request");
03380 cm_msg(MERROR, "tr_prestart", error);
03381 return 0;
03382 }
03383 }
03384 #endif
03385 }
03386 }
03387
03388 if (tape_flag && tape_message)
03389 cm_msg(MTALK, "tr_prestart", "tape mounting finished");
03390
03391
03392 close_history();
03393 status = open_history();
03394 if (status != CM_SUCCESS) {
03395 sprintf(error, "Error in history system, aborting run start");
03396 cm_msg(MERROR, "tr_prestart", error);
03397 return 0;
03398 }
03399
03400
03401 eb.transition = STATE_RUNNING;
03402 eb.run_number = run_number;
03403 hs_write_event(0, &eb, sizeof(eb));
03404
03405 #ifdef HAVE_MYSQL
03406
03407 write_sql(TRUE);
03408 #endif
03409
03410 return CM_SUCCESS;
03411 }
03412
03413
03414
03415 INT tr_stop(INT run_number, char *error)
03416
03417
03418
03419
03420
03421
03422
03423 {
03424 INT i, size;
03425 BOOL flag, tape_flag = FALSE;
03426 char filename[256];
03427 char str[256];
03428
03429 if (in_stop_transition)
03430 return CM_SUCCESS;
03431
03432 in_stop_transition = TRUE;
03433 for (i = 0; i < MAX_CHANNELS; i++) {
03434 if (log_chn[i].handle || log_chn[i].ftp_con) {
03435
03436 if (log_chn[i].type == LOG_TYPE_TAPE && tape_message) {
03437 tape_flag = TRUE;
03438 cm_msg(MTALK, "tr_poststop", "closing tape channel #%d, please wait", i);
03439 }
03440 #ifndef FAL_MAIN
03441
03442 if (log_chn[i].buffer_handle) {
03443 #ifdef DELAYED_STOP
03444 DWORD start_time;
03445
03446 start_time = ss_millitime();
03447 do {
03448 cm_yield(100);
03449 } while (ss_millitime() - start_time < DELAYED_STOP);
03450 #else
03451 INT n_bytes;
03452 do {
03453 bm_get_buffer_level(log_chn[i].buffer_handle, &n_bytes);
03454 if (n_bytes > 0)
03455 cm_yield(100);
03456 } while (n_bytes > 0);
03457 #endif
03458 }
03459 #endif
03460
03461
03462 log_close(&log_chn[i], run_number);
03463
03464
03465 db_set_record(hDB, log_chn[i].stats_hkey, &log_chn[i].statistics,
03466 sizeof(CHN_STATISTICS), 0);
03467 db_close_record(hDB, log_chn[i].stats_hkey);
03468 db_close_record(hDB, log_chn[i].settings_hkey);
03469 log_chn[i].stats_hkey = log_chn[i].settings_hkey = 0;
03470 }
03471 }
03472
03473
03474 for (i = 0; i < MAX_CHANNELS; i++) {
03475 #ifndef FAL_MAIN
03476 if (log_chn[i].buffer_handle) {
03477 INT j;
03478
03479 bm_close_buffer(log_chn[i].buffer_handle);
03480 for (j = i + 1; j < MAX_CHANNELS; j++)
03481 if (log_chn[j].buffer_handle == log_chn[i].buffer_handle)
03482 log_chn[j].buffer_handle = 0;
03483 }
03484
03485 if (log_chn[i].msg_request_id)
03486 bm_delete_request(log_chn[i].msg_request_id);
03487 #endif
03488
03489
03490 memset(&log_chn[i].handle, 0, sizeof(LOG_CHN));
03491 }
03492
03493
03494 size = sizeof(flag);
03495 flag = 0;
03496 db_get_value(hDB, 0, "/Logger/ODB Dump", &flag, &size, TID_BOOL, TRUE);
03497 if (flag) {
03498 strcpy(str, "run%d.odb");
03499 size = sizeof(str);
03500 str[0] = 0;
03501 db_get_value(hDB, 0, "/Logger/ODB Dump File", str, &size, TID_STRING, TRUE);
03502 if (str[0] == 0)
03503 strcpy(str, "run%d.odb");
03504
03505
03506 if (strchr(str, '%'))
03507 sprintf(filename, str, run_number);
03508 else
03509 strcpy(filename, str);
03510
03511 odb_save(filename);
03512 }
03513 #ifdef HAVE_MYSQL
03514
03515 write_sql(FALSE);
03516 #endif
03517
03518 in_stop_transition = FALSE;
03519
03520 if (tape_flag & tape_message)
03521 cm_msg(MTALK, "tr_poststop", "all tape channels closed");
03522
03523
03524 eb.transition = STATE_STOPPED;
03525 eb.run_number = run_number;
03526 hs_write_event(0, &eb, sizeof(eb));
03527
03528 return CM_SUCCESS;
03529 }
03530
03531
03532
03533
03534
03535 void add_data_dir(char *result, char *file)
03536 {
03537 HNDLE hDB, hkey;
03538 char str[256];
03539 int size;
03540
03541 cm_get_experiment_database(&hDB, NULL);
03542 db_find_key(hDB, 0, "/Logger/Data dir", &hkey);
03543
03544 if (hkey) {
03545 size = sizeof(str);
03546 db_get_data(hDB, hkey, str, &size, TID_STRING);
03547 if (str[strlen(str) - 1] != DIR_SEPARATOR)
03548 strcat(str, DIR_SEPARATOR_STR);
03549 strcat(str, file);
03550 strcpy(result, str);
03551 } else
03552 strcpy(result, file);
03553 }
03554
03555
03556
03557 ANA_TEST **tl;
03558 int n_test = 0;
03559
03560 void test_register(ANA_TEST * t)
03561 {
03562 int i;
03563
03564
03565 for (i = 0; i < n_test; i++)
03566 if (tl[i] == t)
03567 break;
03568 if (i < n_test) {
03569 t->registered = TRUE;
03570 return;
03571 }
03572
03573
03574 if (n_test == 0) {
03575 tl = (ANA_TEST **) malloc(2 * sizeof(void *));
03576
03577
03578 tl[0] = (ANA_TEST *) malloc(sizeof(ANA_TEST));
03579 strcpy(tl[0]->name, "Always true");
03580 tl[0]->count = 0;
03581 tl[0]->value = TRUE;
03582 tl[0]->registered = TRUE;
03583 n_test++;
03584 } else
03585 tl = (ANA_TEST **) realloc(tl, (n_test + 1) * sizeof(void *));
03586
03587 tl[n_test] = t;
03588 t->count = 0;
03589 t->value = FALSE;
03590 t->registered = TRUE;
03591
03592 n_test++;
03593 }
03594
03595 void test_clear()
03596 {
03597 int i;
03598
03599
03600 for (i = 0; i < n_test; i++) {
03601 tl[i]->count = 0;
03602 tl[i]->value = FALSE;
03603 }
03604
03605
03606 if (n_test > 0)
03607 tl[0]->value = TRUE;
03608 }
03609
03610 void test_increment()
03611 {
03612 int i;
03613
03614
03615 for (i = 0; i < n_test; i++) {
03616 if (tl[i]->value)
03617 tl[i]->count++;
03618 if (i > 0)
03619 tl[i]->value = FALSE;
03620 }
03621 }
03622
03623 void test_write()
03624 {
03625 int i;
03626 char str[256];
03627
03628
03629 for (i = 0; i < n_test; i++) {
03630 sprintf(str, "/%s/Tests/%s", analyzer_name, tl[i]->name);
03631 db_set_value(hDB, 0, str, &tl[i]->count, sizeof(DWORD), 1, TID_DWORD);
03632 }
03633 }
03634
03635
03636
03637 INT tr_start_fal(INT rn, char *error)
03638
03639
03640
03641
03642
03643 {
03644 ANA_MODULE **module;
03645 INT i, j, status, size;
03646 char str[256];
03647 BANK_LIST *bank_list;
03648
03649
03650 tr_start(rn, error);
03651
03652
03653 for (i = 0; equipment[i].name[0]; i++) {
03654 equipment[i].serial_number = 1;
03655 equipment[i].odb_in = equipment[i].odb_out = 0;
03656 }
03657
03658
03659 for (i = 0; analyze_request[i].event_name[0]; i++) {
03660 analyze_request[i].events_received = 0;
03661 analyze_request[i].ar_stats.events_received = 0;
03662 }
03663
03664 for (i = 0; analyze_request[i].event_name[0]; i++) {
03665
03666 bank_list = analyze_request[i].bank_list;
03667
03668 if (bank_list != NULL)
03669 for (; bank_list->name[0]; bank_list++) {
03670 sprintf(str, "/%s/Bank switches/%s", analyzer_name, bank_list->name);
03671 bank_list->output_flag = FALSE;
03672 size = sizeof(DWORD);
03673 db_get_value(hDB, 0, str, &bank_list->output_flag, &size, TID_DWORD, TRUE);
03674 }
03675
03676
03677 module = analyze_request[i].ana_module;
03678 for (j = 0; module != NULL && module[j] != NULL; j++) {
03679 sprintf(str, "/%s/Module switches/%s", analyzer_name, module[j]->name);
03680 module[j]->enabled = TRUE;
03681 size = sizeof(BOOL);
03682 db_get_value(hDB, 0, str, &module[j]->enabled, &size, TID_BOOL, TRUE);
03683 }
03684 }
03685 #ifndef MANA_LITE
03686
03687 if (out_info.clear_histos) {
03688 for (i = 0; analyze_request[i].event_name[0]; i++)
03689 if (analyze_request[i].bank_list != NULL)
03690 if (HEXIST(analyze_request[i].ar_info.event_id))
03691 HRESET(analyze_request[i].ar_info.event_id, bstr);
03692 HRESET(0, bstr);
03693
03694 test_clear();
03695 }
03696 #endif
03697
03698 for (i = 0; analyze_request[i].event_name[0]; i++) {
03699 module = analyze_request[i].ana_module;
03700 for (j = 0; module != NULL && module[j] != NULL; j++)
03701 if (module[j]->bor != NULL && module[j]->enabled)
03702 module[j]->bor(run_number);
03703 }
03704
03705
03706
03707 status = begin_of_run(rn, error);
03708 if (status != CM_SUCCESS)
03709 return status;
03710
03711
03712 status = ana_begin_of_run(rn, error);
03713 if (status != CM_SUCCESS)
03714 return status;
03715
03716 run_state = STATE_RUNNING;
03717 run_number = rn;
03718
03719 send_all_periodic_events(TR_START);
03720
03721 ss_printf(14, 2, "Running");
03722 ss_printf(36, 2, "%d", rn);
03723
03724 return status;
03725 }
03726
03727
03728
03729 INT tr_stop_fal(INT rn, char *error)
03730
03731
03732
03733
03734
03735 {
03736 ANA_MODULE **module;
03737 INT i, j, status;
03738
03739
03740 status = end_of_run(rn, error);
03741 if (status != CM_SUCCESS)
03742 return status;
03743
03744
03745 if (run_state != STATE_STOPPED)
03746 send_all_periodic_events(TR_STOP);
03747
03748
03749 for (i = 0; analyze_request[i].event_name[0]; i++) {
03750 module = analyze_request[i].ana_module;
03751 for (j = 0; module != NULL && module[j] != NULL; j++)
03752 if (module[j]->eor != NULL && module[j]->enabled)
03753 module[j]->eor(run_number);
03754 }
03755
03756
03757 status = ana_end_of_run(run_number, error);
03758
03759
03760 update_stats();
03761
03762 #ifndef MANA_LITE
03763 {
03764 INT size;
03765 char str[256], file_name[256];
03766
03767
03768 if (out_info.histo_dump) {
03769 size = sizeof(str);
03770 str[0] = 0;
03771 db_get_value(hDB, 0, "/Logger/Data Dir", str, &size, TID_STRING, TRUE);
03772 if (str[0] != 0)
03773 if (str[strlen(str) - 1] != DIR_SEPARATOR)
03774 strcat(str, DIR_SEPARATOR_STR);
03775
03776 strcat(str, out_info.histo_dump_filename);
03777 if (strchr(str, '%') != NULL)
03778 sprintf(file_name, str, run_number);
03779 else
03780 strcpy(file_name, str);
03781
03782 strcpy(str, "NT");
03783 HRPUT(0, file_name, str);
03784 }
03785 }
03786 #endif
03787
03788
03789 tr_stop(rn, error);
03790
03791 run_state = STATE_STOPPED;
03792 run_number = rn;
03793
03794 ss_printf(14, 2, "Stopped");
03795
03796 return status;
03797 }
03798
03799
03800
03801 INT tr_pause(INT rn, char *error)
03802 {
03803 INT status;
03804
03805 status = pause_run(rn, error);
03806 if (status != CM_SUCCESS)
03807 return status;
03808
03809 status = ana_pause_run(rn, error);
03810 if (status != CM_SUCCESS)
03811 return status;
03812
03813 run_state = STATE_PAUSED;
03814 run_number = rn;
03815
03816 send_all_periodic_events(TR_PAUSE);
03817
03818 ss_printf(14, 2, "Paused");
03819
03820
03821 eb.transition = STATE_PAUSED;
03822 eb.run_number = run_number;
03823 hs_write_event(0, &eb, sizeof(eb));
03824
03825 return status;
03826 }
03827
03828
03829
03830 INT tr_resume(INT rn, char *error)
03831 {
03832 INT status;
03833
03834 status = resume_run(rn, error);
03835 if (status != CM_SUCCESS)
03836 return status;
03837
03838 status = ana_resume_run(rn, error);
03839 if (status != CM_SUCCESS)
03840 return status;
03841
03842 run_state = STATE_RUNNING;
03843 run_number = rn;
03844
03845 send_all_periodic_events(TR_RESUME);
03846
03847 ss_printf(14, 2, "Running");
03848
03849
03850 eb.transition = STATE_RUNNING;
03851 eb.run_number = run_number;
03852 hs_write_event(0, &eb, sizeof(eb));
03853
03854 return status;
03855 }
03856
03857
03858
03859
03860
03861 INT write_event_odb(EVENT_HEADER * pevent, ANALYZE_REQUEST * par)
03862 {
03863 INT status, size, n_data, i;
03864 BANK_HEADER *pbh;
03865 EVENT_DEF *event_def;
03866 BANK *pbk;
03867 BANK32 *pbk32;
03868 void *pdata;
03869 char name[5];
03870 HNDLE hKeyRoot, hKey;
03871 KEY key;
03872 DWORD bkname;
03873 WORD bktype;
03874
03875 event_def = db_get_event_definition(pevent->event_id);
03876 if (event_def == NULL)
03877 return SS_SUCCESS;
03878
03879
03880 if (event_def->format == FORMAT_MIDAS) {
03881 pbh = (BANK_HEADER *) (pevent + 1);
03882 pbk = NULL;
03883 pbk32 = NULL;
03884 do {
03885
03886 if (bk_is32(pbh)) {
03887 size = bk_iterate32(pbh, &pbk32, &pdata);
03888 if (pbk32 == NULL)
03889 break;
03890 bkname = *((DWORD *) pbk32->name);
03891 bktype = (WORD) pbk32->type;
03892 } else {
03893 size = bk_iterate(pbh, &pbk, &pdata);
03894 if (pbk == NULL)
03895 break;
03896 bkname = *((DWORD *) pbk->name);
03897 bktype = (WORD) pbk->type;
03898 }
03899
03900 n_data = size;
03901 if (rpc_tid_size(pbk->type & 0xFF))
03902 n_data /= rpc_tid_size(pbk->type & 0xFF);
03903
03904
03905 *((DWORD *) name) = bkname;
03906 name[4] = 0;
03907
03908 status = db_find_key(hDB, event_def->hDefKey, name, &hKeyRoot);
03909 if (status != DB_SUCCESS) {
03910 cm_msg(MERROR, "write_event_odb", "received unknown bank %s", name);
03911 continue;
03912 }
03913
03914 if (bktype == TID_STRUCT) {
03915
03916 for (i = 0;; i++) {
03917 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
03918 if (status == DB_NO_MORE_SUBKEYS)
03919 break;
03920
03921 db_get_key(hDB, hKey, &key);
03922
03923
03924 pdata = (void *) VALIGN(pdata, MIN(ss_get_struct_align(), key.item_size));
03925
03926 status = db_set_data(hDB, hKey, pdata, key.item_size * key.num_values,
03927 key.num_values, key.type);
03928 if (status != DB_SUCCESS) {
03929 cm_msg(MERROR, "write_event_odb", "cannot write %s to ODB", name);
03930 continue;
03931 }
03932
03933
03934 pdata = ((char *) pdata) + key.item_size * key.num_values;
03935 }
03936 } else {
03937 db_get_key(hDB, hKeyRoot, &key);
03938
03939
03940 if (n_data > 0) {
03941 status = db_set_data(hDB, hKeyRoot, pdata, size, n_data, key.type);
03942 if (status != DB_SUCCESS) {
03943 cm_msg(MERROR, "write_event_odb", "cannot write %s to ODB", name);
03944 continue;
03945 }
03946 }
03947 }
03948 } while (1);
03949 }
03950
03951
03952 if (event_def->format == FORMAT_FIXED) {
03953 if (db_set_record(hDB, event_def->hDefKey, (char *) (pevent + 1),
03954 pevent->data_size, 0) != DB_SUCCESS)
03955 cm_msg(MERROR, "write_event_odb", "event #%d size mismatch", pevent->event_id);
03956 }
03957
03958 return SUCCESS;
03959 }
03960
03961
03962
03963 char hbook_types[][8] = {
03964 "",
03965 ":U:8",
03966 ":I:8",
03967 ":I:8",
03968 ":U:16",
03969 ":I:16",
03970 ":U*4",
03971 ":I*4",
03972 ":I*4",
03973 ":R*4",
03974 ":R*8",
03975 ":U:8",
03976 ":C:32",
03977 "",
03978 "",
03979 "",
03980 "",
03981 "",
03982
03983 };
03984
03985 #ifndef MANA_LITE
03986 INT book_ntuples(void);
03987
03988 void banks_changed(INT hDB, INT hKey, void *info)
03989 {
03990 char str[80];
03991 HNDLE hkey;
03992
03993
03994 sprintf(str, "/%s/Bank switches", analyzer_name);
03995 db_find_key(hDB, 0, str, &hkey);
03996 db_close_record(hDB, hkey);
03997
03998 book_ntuples();
03999 print_message("N-tuples rebooked");
04000 }
04001
04002 INT book_ntuples(void)
04003 {
04004 INT index, i, j, status, n_tag, size, id;
04005 HNDLE hkey;
04006 KEY key;
04007 char rw_tag[512][8];
04008 char str[80], key_name[NAME_LENGTH], block_name[NAME_LENGTH];
04009 BANK_LIST *bank_list;
04010 EVENT_DEF *event_def;
04011
04012
04013 for (i = 0; analyze_request[i].event_name[0]; i++) {
04014 bank_list = analyze_request[i].bank_list;
04015
04016 if (bank_list != NULL)
04017 for (; bank_list->name[0]; bank_list++) {
04018 sprintf(str, "/%s/Bank switches/%s", analyzer_name, bank_list->name);
04019 bank_list->output_flag = FALSE;
04020 size = sizeof(DWORD);
04021 db_get_value(hDB, 0, str, &bank_list->output_flag, &size, TID_DWORD, TRUE);
04022 }
04023 }
04024
04025
04026 sprintf(str, "/%s/Bank switches", analyzer_name);
04027 db_find_key(hDB, 0, str, &hkey);
04028 db_open_record(hDB, hkey, NULL, 0, MODE_READ, banks_changed, NULL);
04029
04030
04031
04032
04033 for (index = 0; analyze_request[index].event_name[0]; index++) {
04034
04035 if (analyze_request[index].rwnt_buffer_size == 0)
04036 continue;
04037
04038 n_tag = 0;
04039
04040 strcpy(rw_tag[n_tag++], "Run");
04041 strcpy(rw_tag[n_tag++], "Number");
04042 strcpy(rw_tag[n_tag++], "Time");
04043
04044 bank_list = analyze_request[index].bank_list;
04045 if (bank_list == NULL) {
04046
04047 event_def =
04048 db_get_event_definition((short int) analyze_request[index].ar_info.event_id);
04049
04050 for (i = 0;; i++) {
04051 status = db_enum_key(hDB, event_def->hDefKey, i, &hkey);
04052 if (status == DB_NO_MORE_SUBKEYS)
04053 break;
04054
04055 db_get_key(hDB, hkey, &key);
04056
04057
04058 strcpy(key_name, key.name);
04059 for (j = 0; key_name[j]; j++) {
04060 if (!(key_name[j] >= 'a' && key_name[j] <= 'z') &&
04061 !(key_name[j] >= 'A' && key_name[j] <= 'Z') &&
04062 !(key_name[j] >= '0' && key_name[j] <= '9'))
04063 key_name[j] = '_';
04064 }
04065
04066 if (key.num_values > 1)
04067 for (j = 0; j < key.num_values; j++) {
04068 sprintf(str, "%s%d", key_name, j);
04069 strncpy(rw_tag[n_tag++], str, 8);
04070 if (n_tag >= 512) {
04071 cm_msg(MERROR, "book_ntuples",
04072 "Too much tags for RW N-tupeles (512 maximum)");
04073 return 0;
04074 }
04075 } else
04076 strncpy(rw_tag[n_tag++], key_name, 8);
04077 if (n_tag >= 512) {
04078 cm_msg(MERROR, "book_ntuples",
04079 "Too much tags for RW N-tupeles (512 maximum)");
04080 return 0;
04081 }
04082 }
04083 } else {
04084
04085 for (; bank_list->name[0]; bank_list++) {
04086
04087 bank_list->n_data = n_tag;
04088
04089 if (bank_list->output_flag == 0)
04090 continue;
04091
04092 if (bank_list->type != TID_STRUCT) {
04093 for (i = 0; i < (INT) bank_list->size; i++) {
04094 sprintf(str, "%s%d", bank_list->name, i);
04095 strncpy(rw_tag[n_tag++], str, 8);
04096 }
04097 } else {
04098
04099 for (i = 0;; i++) {
04100 status = db_enum_key(hDB, bank_list->def_key, i, &hkey);
04101 if (status == DB_NO_MORE_SUBKEYS)
04102 break;
04103
04104 db_get_key(hDB, hkey, &key);
04105
04106
04107 strcpy(key_name, key.name);
04108 for (j = 0; key_name[j]; j++) {
04109 if (!(key_name[j] >= 'a' && key_name[j] <= 'z') &&
04110 !(key_name[j] >= 'A' && key_name[j] <= 'Z') &&
04111 !(key_name[j] >= '0' && key_name[j] <= '9'))
04112 key_name[j] = '_';
04113 }
04114
04115 if (key.num_values > 1)
04116 for (j = 0; j < key.num_values; j++) {
04117 sprintf(str, "%s%d", key_name, j);
04118 strncpy(rw_tag[n_tag++], str, 8);
04119 if (n_tag >= 512) {
04120 cm_msg(MERROR, "book_ntuples",
04121 "Too much tags for RW N-tupeles (512 maximum)");
04122 return 0;
04123 }
04124 } else
04125 strncpy(rw_tag[n_tag++], key_name, 8);
04126 if (n_tag >= 512) {
04127 cm_msg(MERROR, "book_ntuples",
04128 "Too much tags for RW N-tupeles (512 maximum)");
04129 return 0;
04130 }
04131 }
04132 }
04133 }
04134 }
04135
04136
04137 strcpy(block_name, analyze_request[index].event_name);
04138 block_name[8] = 0;
04139 #ifndef MANA_LITE
04140 id = analyze_request[index].ar_info.event_id;
04141 if (HEXIST(id))
04142 HDELET(id);
04143
04144 HBOOKN(id, block_name, n_tag, bstr,
04145 n_tag * analyze_request[index].rwnt_buffer_size, rw_tag);
04146
04147 if (!HEXIST(id)) {
04148 printf("\n");
04149 cm_msg(MINFO, "book_ntuples",
04150 "Cannot book N-tuple #%d. Increase PAWC size via the -s flag or switch off banks",
04151 id);
04152 }
04153 #endif
04154 }
04155
04156 return SUCCESS;
04157 }
04158
04159
04160
04161 INT write_event_hbook(EVENT_HEADER * pevent, ANALYZE_REQUEST * par)
04162 {
04163 INT i, j, k, n, size, item_size, status;
04164 BANK *pbk;
04165 BANK32 *pbk32;
04166 BANK_LIST *pbl;
04167 BANK_HEADER *pbh;
04168 void *pdata;
04169 BOOL exclude, exclude_all;
04170 char block_name[5];
04171 float rwnt[512];
04172 EVENT_DEF *event_def;
04173 HNDLE hkey;
04174 KEY key;
04175 DWORD bkname;
04176 WORD bktype;
04177
04178 event_def = db_get_event_definition(pevent->event_id);
04179 if (event_def == NULL)
04180 return SS_SUCCESS;
04181
04182
04183 memset(rwnt, 0, sizeof(rwnt));
04184 rwnt[0] = (float) run_number;
04185 rwnt[1] = (float) pevent->serial_number;
04186 rwnt[2] = (float) pevent->time_stamp;
04187
04188
04189
04190 if (event_def->format == FORMAT_MIDAS) {
04191
04192 pbk = NULL;
04193 pbk32 = NULL;
04194 exclude_all = TRUE;
04195 do {
04196 pbh = (BANK_HEADER *) (pevent + 1);
04197
04198 if (bk_is32(pbh)) {
04199 size = bk_iterate32(pbh, &pbk32, &pdata);
04200 if (pbk32 == NULL)
04201 break;
04202 bkname = *((DWORD *) pbk32->name);
04203 bktype = (WORD) pbk32->type;
04204 } else {
04205 size = bk_iterate(pbh, &pbk, &pdata);
04206 if (pbk == NULL)
04207 break;
04208 bkname = *((DWORD *) pbk->name);
04209 bktype = (WORD) pbk->type;
04210 }
04211
04212
04213 *((DWORD *) block_name) = bkname;
04214 block_name[4] = 0;
04215
04216 exclude = FALSE;
04217 pbl = NULL;
04218 if (par->bank_list != NULL) {
04219 for (i = 0; par->bank_list[i].name[0]; i++)
04220 if (*((DWORD *) par->bank_list[i].name) == bkname) {
04221 pbl = &par->bank_list[i];
04222 exclude = (pbl->output_flag == 0);
04223 break;
04224 }
04225 if (par->bank_list[i].name[0] == 0)
04226 cm_msg(MERROR, "write_event_hbook", "Received unknown bank %s",
04227 block_name);
04228 }
04229
04230
04231 if (!exclude && pbl != NULL) {
04232 exclude_all = FALSE;
04233
04234 item_size = rpc_tid_size(bktype & 0xFF);
04235
04236 if ((bktype & 0xFF) != TID_STRUCT) {
04237 n = size / item_size;
04238
04239
04240 if (n > (INT) pbl->size) {
04241 cm_msg(MERROR, "write_event_hbook",
04242 "Bank %s has more (%d) entries than maximum value (%d)",
04243 block_name, n, pbl->size);
04244 continue;
04245 }
04246
04247
04248 for (i = 0; i < n; i++) {
04249 switch (bktype & 0xFF) {
04250 case TID_BYTE:
04251 rwnt[pbl->n_data + i] = (float) (*((BYTE *) pdata + i));
04252 break;
04253 case TID_WORD:
04254 rwnt[pbl->n_data + i] = (float) (*((WORD *) pdata + i));
04255 break;
04256 case TID_DWORD:
04257 rwnt[pbl->n_data + i] = (float) (*((DWORD *) pdata + i));
04258 break;
04259 case TID_FLOAT:
04260 rwnt[pbl->n_data + i] = (float) (*((float *) pdata + i));
04261 break;
04262 case TID_DOUBLE:
04263 rwnt[pbl->n_data + i] = (float) (*((double *) pdata + i));
04264 break;
04265 }
04266 }
04267
04268
04269 for (; i < (INT) pbl->size; i++)
04270 rwnt[pbl->n_data + i] = 0.f;
04271 } else {
04272
04273 k = pbl->n_data;
04274
04275 for (i = 0;; i++) {
04276 status = db_enum_key(hDB, pbl->def_key, i, &hkey);
04277 if (status == DB_NO_MORE_SUBKEYS)
04278 break;
04279
04280 db_get_key(hDB, hkey, &key);
04281
04282
04283 pdata =
04284 (void *) VALIGN(pdata, MIN(ss_get_struct_align(), key.item_size));
04285
04286 for (j = 0; j < key.num_values; j++) {
04287 switch (key.type & 0xFF) {
04288 case TID_BYTE:
04289 rwnt[k++] = (float) (*((BYTE *) pdata + j));
04290 break;
04291 case TID_WORD:
04292 rwnt[k++] = (float) (*((WORD *) pdata + j));
04293 break;
04294 case TID_SHORT:
04295 rwnt[k++] = (float) (*((short int *) pdata + j));
04296 break;
04297 case TID_INT:
04298 rwnt[k++] = (float) (*((INT *) pdata + j));
04299 break;
04300 case TID_DWORD:
04301 rwnt[k++] = (float) (*((DWORD *) pdata + j));
04302 break;
04303 case TID_BOOL:
04304 rwnt[k++] = (float) (*((BOOL *) pdata + j));
04305 break;
04306 case TID_FLOAT:
04307 rwnt[k++] = (float) (*((float *) pdata + j));
04308 break;
04309 case TID_DOUBLE:
04310 rwnt[k++] = (float) (*((double *) pdata + j));
04311 break;
04312 }
04313 }
04314
04315
04316 (char *) pdata += key.item_size * key.num_values;
04317 }
04318 }
04319 }
04320
04321 } while (TRUE);
04322
04323
04324 HFNOV(pevent->event_id, rwnt);
04325
04326 }
04327
04328
04329
04330
04331 if (event_def->format == FORMAT_FIXED) {
04332
04333 pdata = pevent + 1;
04334 k = 3;
04335
04336 for (i = 0;; i++) {
04337 status = db_enum_key(hDB, event_def->hDefKey, i, &hkey);
04338 if (status == DB_NO_MORE_SUBKEYS)
04339 break;
04340
04341 db_get_key(hDB, hkey, &key);
04342
04343
04344 pdata = (void *) VALIGN(pdata, MIN(ss_get_struct_align(), key.item_size));
04345
04346 for (j = 0; j < key.num_values; j++) {
04347 switch (key.type & 0xFF) {
04348 case TID_BYTE:
04349 rwnt[k++] = (float) (*((BYTE *) pdata + j));
04350 break;
04351 case TID_WORD:
04352 rwnt[k++] = (float) (*((WORD *) pdata + j));
04353 break;
04354 case TID_SHORT:
04355 rwnt[k++] = (float) (*((short int *) pdata + j));
04356 break;
04357 case TID_INT:
04358 rwnt[k++] = (float) (*((INT *) pdata + j));
04359 break;
04360 case TID_DWORD:
04361 rwnt[k++] = (float) (*((DWORD *) pdata + j));
04362 break;
04363 case TID_BOOL:
04364 rwnt[k++] = (float) (*((BOOL *) pdata + j));
04365 break;
04366 case TID_FLOAT:
04367 rwnt[k++] = (float) (*((float *) pdata + j));
04368 break;
04369 case TID_DOUBLE:
04370 rwnt[k++] = (float) (*((double *) pdata + j));
04371 break;
04372 }
04373 }
04374
04375
04376 (char *) pdata += key.item_size * key.num_values;
04377 }
04378
04379
04380 HFNOV(pevent->event_id, rwnt);
04381 }
04382
04383 return SUCCESS;
04384 }
04385 #endif
04386
04387
04388
04389 INT mana_init()
04390 {
04391 ANA_MODULE **module;
04392 INT i, j, status, size;
04393 HNDLE hkey;
04394 char str[256], block_name[32];
04395 BANK_LIST *bank_list;
04396 double dummy;
04397
04398
04399 sprintf(str, "/%s/Output", analyzer_name);
04400 db_create_record(hDB, 0, str, OUT_INFO_STR);
04401 db_find_key(hDB, 0, str, &hkey);
04402 status = db_open_record(hDB, hkey, &out_info, sizeof(out_info), MODE_READ, NULL, NULL);
04403 if (status != DB_SUCCESS) {
04404 cm_msg(MERROR, "bor", "Cannot read output info record");
04405 return 0;
04406 }
04407
04408
04409 for (i = 0; analyze_request[i].event_name[0]; i++) {
04410 bank_list = analyze_request[i].bank_list;
04411
04412 if (bank_list == NULL)
04413 continue;
04414
04415 for (; bank_list->name[0]; bank_list++) {
04416 strncpy(block_name, bank_list->name, 4);
04417 block_name[4] = 0;
04418
04419 if (bank_list->type == TID_STRUCT) {
04420 sprintf(str, "/Equipment/%s/Variables/%s", analyze_request[i].event_name,
04421 block_name);
04422 db_create_record(hDB, 0, str, strcomb((const char**)bank_list->init_str));
04423 db_find_key(hDB, 0, str, &hkey);
04424 bank_list->def_key = hkey;
04425 } else {
04426 sprintf(str, "/Equipment/%s/Variables/%s", analyze_request[i].event_name,
04427 block_name);
04428 dummy = 0;
04429 db_set_value(hDB, 0, str, &dummy, rpc_tid_size(bank_list->type), 1,
04430 bank_list->type);
04431 db_find_key(hDB, 0, str, &hkey);
04432 bank_list->def_key = hkey;
04433 }
04434 }
04435 }
04436
04437
04438 for (i = 0; analyze_request[i].event_name[0]; i++) {
04439 if (analyze_request[i].init_string) {
04440 sprintf(str, "/Equipment/%s/Variables", analyze_request[i].event_name);
04441 db_create_record(hDB, 0, str, strcomb((const char**)analyze_request[i].init_string));
04442 }
04443 }
04444 #ifndef MANA_LITE
04445
04446 HLIMAP(pawc_size / 4, out_info.global_memory_name);
04447 printf("\nGLOBAL MEMORY NAME = %s\n", out_info.global_memory_name);
04448
04449
04450 status = book_ntuples();
04451 if (status != SUCCESS)
04452 return status;
04453 #endif
04454
04455 status = analyzer_init();
04456 if (status != SUCCESS)
04457 return status;
04458
04459
04460 for (i = 0; analyze_request[i].event_name[0]; i++) {
04461 module = analyze_request[i].ana_module;
04462 for (j = 0; module != NULL && module[j] != NULL; j++) {
04463
04464 sprintf(str, "/%s/Module switches/%s", analyzer_name, module[j]->name);
04465 module[j]->enabled = TRUE;
04466 size = sizeof(BOOL);
04467 db_get_value(hDB, 0, str, &module[j]->enabled, &size, TID_BOOL, TRUE);
04468
04469 if (module[j]->init != NULL && module[j]->enabled)
04470 module[j]->init();
04471 }
04472 }
04473
04474 return SUCCESS;
04475 }
04476
04477
04478
04479 INT init_module_parameters()
04480 {
04481 INT i, j;
04482 ANA_MODULE **module;
04483 char str[80];
04484 HNDLE hkey;
04485
04486 for (i = 0; analyze_request[i].event_name[0]; i++) {
04487 module = analyze_request[i].ana_module;
04488 for (j = 0; module != NULL && module[j] != NULL; j++) {
04489 if (module[j]->parameters != NULL) {
04490 sprintf(str, "/%s/Parameters/%s", analyzer_name, module[j]->name);
04491
04492 if (module[j]->init_str)
04493 db_create_record(hDB, 0, str, strcomb((const char**)module[j]->init_str));
04494
04495 db_find_key(hDB, 0, str, &hkey);
04496 if (db_open_record(hDB, hkey, module[j]->parameters, module[j]->param_size,
04497 MODE_READ, NULL, NULL) != DB_SUCCESS) {
04498 cm_msg(MERROR, "init_module_parameters",
04499 "Cannot open \"%s\" parameters in ODB", str);
04500 return 0;
04501 }
04502 }
04503 }
04504 }
04505
04506 return SUCCESS;
04507 }
04508
04509
04510
04511 INT mana_exit()
04512 {
04513 ANA_MODULE **module;
04514 INT i, j;
04515
04516
04517 for (i = 0; analyze_request[i].event_name[0]; i++) {
04518 module = analyze_request[i].ana_module;
04519 for (j = 0; module != NULL && module[j] != NULL; j++)
04520 if (module[j]->exit != NULL && module[j]->enabled)
04521 module[j]->exit();
04522 }
04523
04524
04525 return analyzer_exit();
04526 }
04527
04528
04529
04530 struct last_time_event_struct {
04531 short int event_id;
04532 DWORD last_time;
04533 } last_time_event[50];
04534
04535 void process_event(EVENT_HEADER * pevent)
04536 {
04537 INT i, status;
04538 ANA_MODULE **module;
04539 ANALYZE_REQUEST *par;
04540 DWORD actual_time;
04541 EVENT_DEF *event_def;
04542
04543
04544 for (i = 0; i < MAX_CHANNELS; i++) {
04545 if (log_chn[i].handle == 0)
04546 continue;
04547
04548 log_write(&log_chn[i], pevent);
04549 }
04550
04551
04552 if (pevent->data_size == 0)
04553 return;
04554
04555
04556 par = analyze_request;
04557
04558 for (i = 0; par->event_name[0]; par++)
04559 if (par->ar_info.event_id == pevent->event_id) {
04560 par->events_received++;
04561
04562
04563 status = CM_SUCCESS;
04564 if (par->analyzer)
04565 status = par->analyzer(pevent, (void *) (pevent + 1));
04566
04567
04568 if (status == 0)
04569 return;
04570
04571
04572 module = par->ana_module;
04573 for (i = 0; module != NULL && module[i] != NULL; i++) {
04574 if (module[i]->enabled) {
04575 status = module[i]->analyzer(pevent, (void *) (pevent + 1));
04576
04577
04578 if (status == 0)
04579 return;
04580 }
04581 }
04582
04583
04584 event_def = db_get_event_definition(pevent->event_id);
04585 if (event_def == NULL)
04586 return;
04587
04588 if (event_def->format == FORMAT_MIDAS)
04589 pevent->data_size = bk_size((void *) (pevent + 1));
04590
04591
04592 test_increment();
04593 #ifndef MANA_LITE
04594 write_event_hbook(pevent, par);
04595 #endif
04596
04597 for (i = 0; equipment[i].name[0]; i++)
04598 if (equipment[i].info.event_id == pevent->event_id)
04599 break;
04600
04601 if ((equipment[i].info.read_on & RO_ODB) || equipment[i].info.history) {
04602
04603 actual_time = ss_millitime();
04604 for (i = 0; i < 50; i++) {
04605 if (last_time_event[i].event_id == pevent->event_id) {
04606 if (actual_time - last_time_event[i].last_time > 1000) {
04607 last_time_event[i].last_time = actual_time;
04608 write_event_odb(pevent, par);
04609 }
04610 break;
04611 }
04612 if (last_time_event[i].event_id == 0) {
04613 last_time_event[i].event_id = pevent->event_id;
04614 last_time_event[i].last_time = actual_time;
04615 write_event_odb(pevent, par);
04616 break;
04617 }
04618 }
04619 }
04620
04621 }
04622 }
04623
04624
04625
04626 INT manual_trigger(INT index, void *prpc_param[])
04627 {
04628 WORD event_id;
04629 INT i;
04630
04631 event_id = CWORD(0);
04632
04633 for (i = 0; equipment[i].name[0]; i++)
04634 if (equipment[i].info.event_id == event_id)
04635 send_event(i);
04636
04637 if (display_period)
04638 display(FALSE);
04639
04640 return SUCCESS;
04641 }
04642
04643
04644
04645 INT register_equipment(void)
04646 {
04647 INT index, count, size, status, i, j, k, n;
04648 char str[256];
04649 EQUIPMENT_INFO *eq_info;
04650 EQUIPMENT_STATS *eq_stats;
04651 DWORD start_time, delta_time;
04652 HNDLE hKey;
04653 BOOL manual_trig_flag = FALSE;
04654 BANK_LIST *bank_list;
04655 DWORD dummy;
04656
04657
04658 size = sizeof(run_state);
04659 run_state = STATE_STOPPED;
04660 db_get_value(hDB, 0, "/Runinfo/State", &run_state, &size, TID_INT, TRUE);
04661 size = sizeof(run_number);
04662 run_number = 1;
04663 db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
04664
04665
04666 for (index = 0; equipment[index].name[0]; index++) {
04667 eq_info = &equipment[index].info;
04668 eq_stats = &equipment[index].stats;
04669
04670 if (eq_info->event_id == 0) {
04671 printf("Event ID 0 for %s not allowed\n", equipment[index].name);
04672 ss_sleep(5000);
04673 }
04674
04675
04676 equipment[index].status = FE_SUCCESS;
04677
04678 sprintf(str, "/Equipment/%s/Common", equipment[index].name);
04679
04680
04681 if (eq_info->eq_type != EQ_SLOW) {
04682 db_find_key(hDB, 0, str, &hKey);
04683 size = sizeof(double);
04684 if (hKey)
04685 db_get_value(hDB, hKey, "Event limit", &eq_info->event_limit, &size,
04686 TID_DOUBLE, TRUE);
04687 }
04688
04689
04690 status = db_create_record(hDB, 0, str, EQUIPMENT_COMMON_STR);
04691 if (status != DB_SUCCESS) {
04692 printf("Cannot init equipment record, probably other FE is using it\n");
04693 ss_sleep(3000);
04694 }
04695 db_find_key(hDB, 0, str, &hKey);
04696
04697 if (equal_ustring(eq_info->format, "YBOS"))
04698 assert(!"YBOS not supported anymore");
04699 else if (equal_ustring(eq_info->format, "FIXED"))
04700 equipment[index].format = FORMAT_FIXED;
04701 else
04702 equipment[index].format = FORMAT_MIDAS;
04703
04704 gethostname(eq_info->frontend_host, sizeof(eq_info->frontend_host));
04705 strcpy(eq_info->frontend_name, frontend_name);
04706 strcpy(eq_info->frontend_file_name, frontend_file_name);
04707
04708
04709 db_set_record(hDB, hKey, eq_info, sizeof(EQUIPMENT_INFO), 0);
04710
04711
04712 db_open_record(hDB, hKey, eq_info, sizeof(EQUIPMENT_INFO), MODE_READ, NULL, NULL);
04713
04714
04715 sprintf(str, "/Equipment/%s/Variables", equipment[index].name);
04716 if (equipment[index].event_descrip) {
04717 if (equipment[index].format == FORMAT_FIXED)
04718 db_create_record(hDB, 0, str, (char *) equipment[index].event_descrip);
04719 else {
04720
04721 bank_list = (BANK_LIST *) equipment[index].event_descrip;
04722
04723 for (; bank_list->name[0]; bank_list++) {
04724
04725
04726
04727
04728
04729 if (bank_list->type == TID_STRUCT) {
04730 sprintf(str, "/Equipment/%s/Variables/%s", equipment[index].name,
04731 bank_list->name);
04732 db_create_record(hDB, 0, str, strcomb((const char**)bank_list->init_str));
04733 } else {
04734 sprintf(str, "/Equipment/%s/Variables/%s", equipment[index].name,
04735 bank_list->name);
04736 dummy = 0;
04737 db_set_value(hDB, 0, str, &dummy, rpc_tid_size(bank_list->type), 1,
04738 bank_list->type);
04739 }
04740 }
04741 }
04742 } else
04743 db_create_key(hDB, 0, str, TID_KEY);
04744
04745 sprintf(str, "/Equipment/%s/Variables", equipment[index].name);
04746 db_find_key(hDB, 0, str, &hKey);
04747 equipment[index].hkey_variables = hKey;
04748
04749
04750 sprintf(str, "/Equipment/%s/Statistics", equipment[index].name);
04751
04752
04753
04754
04755 status = db_find_key(hDB, 0, str, &hKey);
04756 if (status == DB_SUCCESS) {
04757 status = db_delete_key(hDB, hKey, FALSE);
04758 if (status != DB_SUCCESS) {
04759 printf("Cannot delete statistics record, error %d\n", status);
04760 ss_sleep(3000);
04761 }
04762 }
04763
04764 status = db_create_record(hDB, 0, str, EQUIPMENT_STATISTICS_STR);
04765 if (status != DB_SUCCESS) {
04766 printf("Cannot create statistics record, error %d\n", status);
04767 ss_sleep(3000);
04768 }
04769
04770 status = db_find_key(hDB, 0, str, &hKey);
04771 if (status != DB_SUCCESS) {
04772 printf("Cannot find statistics record, error %d\n", status);
04773 ss_sleep(3000);
04774 }
04775
04776 eq_stats->events_sent = 0;
04777 eq_stats->events_per_sec = 0;
04778 eq_stats->kbytes_per_sec = 0;
04779
04780
04781 status =
04782 db_open_record(hDB, hKey, eq_stats, sizeof(EQUIPMENT_STATS), MODE_WRITE, NULL,
04783 NULL);
04784 if (status != DB_SUCCESS) {
04785 printf
04786 ("Cannot open statistics record, error %d. Probably other FE is using it\n",
04787 status);
04788 ss_sleep(3000);
04789 }
04790
04791
04792 if (eq_info->buffer[0]) {
04793 status =
04794 bm_open_buffer(eq_info->buffer, 2*MAX_EVENT_SIZE,
04795 &equipment[index].buffer_handle);
04796 if (status != BM_SUCCESS && status != BM_CREATED) {
04797 cm_msg(MERROR, "register_equipment",
04798 "Cannot open event buffer. Try to reduce MAX_EVENT_SIZE in midas.h \
04799 and rebuild the system.");
04800 return 0;
04801 }
04802
04803
04804 bm_set_cache_size(equipment[index].buffer_handle, 0, SERVER_CACHE_SIZE);
04805 } else
04806 equipment[index].buffer_handle = 0;
04807
04808
04809 if (eq_info->eq_type & EQ_POLLED) {
04810 if (display_period)
04811 printf("\nCalibrating");
04812
04813 count = 1;
04814 do {
04815 if (display_period)
04816 printf(".");
04817
04818 start_time = ss_millitime();
04819
04820 poll_event(equipment[index].info.source, count, TRUE);
04821
04822 delta_time = ss_millitime() - start_time;
04823
04824 if (delta_time > 0)
04825 count = (INT) ((double) count * 100 / delta_time);
04826 else
04827 count *= 100;
04828 } while (delta_time > 120 || delta_time < 80);
04829
04830 equipment[index].poll_count = (INT) ((double) eq_info->period / 100 * count);
04831
04832 if (display_period)
04833 printf("OK\n");
04834 }
04835
04836
04837 if (eq_info->eq_type & EQ_INTERRUPT) {
04838
04839
04840 for (i = 0; equipment[i].name[0]; i++)
04841 if (equipment[i].info.eq_type & EQ_POLLED) {
04842 equipment[index].status = FE_ERR_DISABLED;
04843 cm_msg(MINFO, "register_equipment",
04844 "Interrupt readout cannot be combined with polled readout");
04845 }
04846
04847 if (equipment[index].status != FE_ERR_DISABLED) {
04848 if (eq_info->enabled) {
04849 if (interrupt_eq) {
04850 equipment[index].status = FE_ERR_DISABLED;
04851 cm_msg(MINFO, "register_equipment",
04852 "Defined more than one equipment with interrupt readout");
04853 } else {
04854 interrupt_configure(CMD_INTERRUPT_ATTACH, eq_info->source,
04855 (POINTER_T) interrupt_routine);
04856 interrupt_eq = &equipment[index];
04857 interrupt_odb_buffer =
04858 (EVENT_HEADER *) malloc(MAX_EVENT_SIZE + sizeof(EVENT_HEADER));
04859 }
04860 } else {
04861 equipment[index].status = FE_ERR_DISABLED;
04862 cm_msg(MINFO, "register_equipment",
04863 "Equipment %s disabled in file \"frontend.c\"",
04864 equipment[index].name);
04865 }
04866 }
04867 }
04868
04869
04870 if (eq_info->eq_type & EQ_SLOW) {
04871
04872 for (i = 0; equipment[index].driver[i].name[0]; i++)
04873 for (j = i + 1; equipment[index].driver[j].name[0]; j++)
04874 if (equal_ustring(equipment[index].driver[i].name,
04875 equipment[index].driver[j].name)) {
04876 strcpy(str, equipment[index].driver[i].name);
04877 for (k = 0, n = 0; equipment[index].driver[k].name[0]; k++)
04878 if (equal_ustring(str, equipment[index].driver[k].name))
04879 sprintf(equipment[index].driver[k].name, "%s_%d", str, n++);
04880
04881 break;
04882 }
04883
04884
04885 if (eq_info->enabled)
04886 equipment[index].status = equipment[index].cd(CMD_INIT, &equipment[index]);
04887 else {
04888 equipment[index].status = FE_ERR_DISABLED;
04889 cm_msg(MINFO, "register_equipment",
04890 "Equipment %s disabled in file \"frontend.c\"", equipment[index].name);
04891 }
04892
04893
04894 if (equipment[index].status != FE_SUCCESS)
04895 ss_sleep(3000);
04896 }
04897
04898
04899 if (eq_info->eq_type & EQ_MANUAL_TRIG) {
04900 if (!manual_trig_flag)
04901 cm_register_function(RPC_MANUAL_TRIG, manual_trigger);
04902
04903 manual_trig_flag = TRUE;
04904 }
04905 }
04906
04907 return SUCCESS;
04908 }
04909
04910
04911
04912 void register_requests(void)
04913 {
04914 INT index, status;
04915 char str[256];
04916 AR_INFO *ar_info;
04917 AR_STATS *ar_stats;
04918 HNDLE hKey;
04919
04920
04921 for (index = 0; analyze_request[index].event_name[0]; index++) {
04922 ar_info = &analyze_request[index].ar_info;
04923 ar_stats = &analyze_request[index].ar_stats;
04924
04925
04926 sprintf(str, "/%s/%s/Common", analyzer_name, analyze_request[index].event_name);
04927 db_create_record(hDB, 0, str, ANALYZER_REQUEST_STR);
04928 db_find_key(hDB, 0, str, &hKey);
04929 analyze_request[index].hkey_common = hKey;
04930
04931 strcpy(ar_info->client_name, analyzer_name);
04932 gethostname(ar_info->host, sizeof(ar_info->host));
04933 db_set_record(hDB, hKey, ar_info, sizeof(AR_INFO), 0);
04934
04935
04936 sprintf(str, "/%s/%s/Statistics", analyzer_name, analyze_request[index].event_name);
04937 db_create_record(hDB, 0, str, ANALYZER_STATS_STR);
04938 db_find_key(hDB, 0, str, &hKey);
04939
04940 ar_stats->events_received = 0;
04941 ar_stats->events_per_sec = 0;
04942 ar_stats->events_written = 0;
04943
04944
04945 status =
04946 db_open_record(hDB, hKey, ar_stats, sizeof(AR_STATS), MODE_WRITE, NULL, NULL);
04947 if (status != DB_SUCCESS)
04948 printf("Cannot open statistics record, probably other analyzer is using it\n");
04949 }
04950 }
04951
04952
04953
04954 void update_stats()
04955 {
04956 int i;
04957 AR_STATS *ar_stats;
04958 static DWORD last_time = 0;
04959 DWORD actual_time;
04960
04961 actual_time = ss_millitime();
04962
04963 if (last_time == 0)
04964 last_time = actual_time;
04965
04966 if (actual_time - last_time == 0)
04967 return;
04968
04969 for (i = 0; analyze_request[i].event_name[0]; i++) {
04970 ar_stats = &analyze_request[i].ar_stats;
04971 ar_stats->events_received += analyze_request[i].events_received;
04972 ar_stats->events_written += analyze_request[i].events_written;
04973 ar_stats->events_per_sec =
04974 (DWORD) (analyze_request[i].events_received /
04975 ((actual_time - last_time) / 1000.0));
04976 analyze_request[i].events_received = 0;
04977 analyze_request[i].events_written = 0;
04978 }
04979
04980
04981 db_send_changed_records();
04982
04983
04984 test_write();
04985
04986 last_time = actual_time;
04987 }
04988
04989
04990
04991 INT clear_histos(INT id1, INT id2)
04992 {
04993 #ifndef MANA_LITE
04994 INT i;
04995
04996 if (id1 != id2) {
04997 printf("Clear ID %d to ID %d\n", id1, id2);
04998 for (i = id1; i <= id2; i++)
04999 if (HEXIST(i))
05000 HRESET(i, bstr);
05001 } else {
05002 printf("Clear ID %d\n", id1);
05003 HRESET(id1, bstr);
05004 }
05005 #endif
05006 return SUCCESS;
05007 }
05008
05009
05010
05011 INT ana_callback(INT index, void *prpc_param[])
05012 {
05013 if (index == RPC_ANA_CLEAR_HISTOS)
05014 clear_histos(CINT(0), CINT(1));
05015
05016 return RPC_SUCCESS;
05017 }
05018
05019
05020
05021 void send_event(INT index)
05022 {
05023 EQUIPMENT_INFO *eq_info;
05024 EVENT_HEADER *pevent;
05025 INT i;
05026
05027 pevent = (EVENT_HEADER *) event_buffer;
05028
05029 eq_info = &equipment[index].info;
05030
05031 pevent->event_id = eq_info->event_id;
05032 pevent->trigger_mask = eq_info->trigger_mask;
05033 pevent->data_size = 0;
05034 pevent->time_stamp = ss_time();
05035 pevent->serial_number = equipment[index].serial_number++;
05036
05037 equipment[index].last_called = ss_millitime();
05038
05039
05040 *((EQUIPMENT **) (pevent + 1)) = &equipment[index];
05041 pevent->data_size = equipment[index].readout((char *) (pevent + 1), 0);
05042
05043
05044 if (pevent->data_size) {
05045 equipment[index].bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
05046 equipment[index].events_sent++;
05047
05048 equipment[index].stats.events_sent += equipment[index].events_sent;
05049 equipment[index].events_sent = 0;
05050
05051
05052 process_event(pevent);
05053
05054
05055 if (equipment[index].buffer_handle) {
05056 bm_send_event(equipment[index].buffer_handle, pevent,
05057 pevent->data_size + sizeof(EVENT_HEADER), SYNC);
05058
05059
05060 bm_flush_cache(equipment[index].buffer_handle, SYNC);
05061 }
05062 } else
05063 equipment[index].serial_number--;
05064
05065 for (i = 0; equipment[i].name[0]; i++)
05066 if (equipment[i].buffer_handle)
05067 bm_flush_cache(equipment[i].buffer_handle, SYNC);
05068 }
05069
05070
05071
05072 void send_all_periodic_events(INT transition)
05073 {
05074 EQUIPMENT_INFO *eq_info;
05075 INT i;
05076
05077 for (i = 0; equipment[i].name[0]; i++) {
05078 eq_info = &equipment[i].info;
05079
05080 if (!eq_info->enabled)
05081 continue;
05082
05083 if (transition == TR_START && (eq_info->read_on & RO_BOR) == 0)
05084 continue;
05085 if (transition == TR_STOP && (eq_info->read_on & RO_EOR) == 0)
05086 continue;
05087 if (transition == TR_PAUSE && (eq_info->read_on & RO_PAUSE) == 0)
05088 continue;
05089 if (transition == TR_RESUME && (eq_info->read_on & RO_RESUME) == 0)
05090 continue;
05091
05092 send_event(i);
05093 }
05094 }
05095
05096
05097
05098 BOOL interrupt_enabled;
05099
05100 void interrupt_enable(BOOL flag)
05101 {
05102 interrupt_enabled = flag;
05103
05104 if (interrupt_eq) {
05105 if (interrupt_enabled)
05106 interrupt_configure(CMD_INTERRUPT_ENABLE, 0, 0);
05107 else
05108 interrupt_configure(CMD_INTERRUPT_DISABLE, 0, 0);
05109 }
05110 }
05111
05112
05113
05114 void interrupt_routine(void)
05115 {
05116 EVENT_HEADER *pevent;
05117
05118
05119
05120 if ((pevent = dm_pointer_get()) == NULL)
05121 cm_msg(MERROR, "interrupt_routine", "interrupt, dm_pointer_get returned NULL");
05122
05123
05124 pevent->event_id = interrupt_eq->info.event_id;
05125 pevent->trigger_mask = interrupt_eq->info.trigger_mask;
05126 pevent->data_size = 0;
05127 pevent->time_stamp = actual_time;
05128 pevent->serial_number = interrupt_eq->serial_number++;
05129
05130
05131 pevent->data_size = interrupt_eq->readout((char *) (pevent + 1), 0);
05132
05133
05134 if (pevent->data_size) {
05135 interrupt_eq->bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
05136 interrupt_eq->events_sent++;
05137
05138 if (interrupt_eq->buffer_handle) {
05139 rpc_send_event(interrupt_eq->buffer_handle, pevent,
05140 pevent->data_size + sizeof(EVENT_HEADER), SYNC, 0);
05141 }
05142
05143
05144 if (interrupt_eq->info.read_on & RO_ODB || interrupt_eq->info.history) {
05145 if (actual_millitime - interrupt_eq->last_called > ODB_UPDATE_TIME) {
05146 interrupt_eq->last_called = actual_millitime;
05147 memcpy(interrupt_odb_buffer, pevent,
05148 pevent->data_size + sizeof(EVENT_HEADER));
05149 interrupt_odb_buffer_valid = TRUE;
05150 interrupt_eq->odb_out++;
05151 }
05152 }
05153 } else
05154 interrupt_eq->serial_number--;
05155
05156 }
05157
05158
05159
05160 int print_message(const char *msg)
05161 {
05162 char str[256];
05163
05164 memset(str, ' ', 159);
05165 str[159] = 0;
05166
05167 if (msg[0] == '[')
05168 msg = strchr(msg, ']') + 2;
05169
05170 memcpy(str, msg, strlen(msg));
05171 ss_printf(0, 20, str);
05172
05173 return 0;
05174 }
05175
05176
05177
05178 void receive_message(HNDLE hBuf, HNDLE id, EVENT_HEADER * pheader, void *message)
05179 {
05180
05181 print_message((const char *) message);
05182 }
05183
05184
05185
05186 void display(BOOL bInit)
05187 {
05188 INT i, status;
05189 time_t full_time;
05190 char str[30];
05191
05192 if (bInit) {
05193 ss_clear_screen();
05194
05195 if (host_name[0])
05196 strcpy(str, host_name);
05197 else
05198 strcpy(str, "<local>");
05199
05200 ss_printf(0, 0, "%s connected to %s. Press \"!\" to exit", fal_name, str);
05201 ss_printf(0, 1,
05202 "================================================================================");
05203 ss_printf(0, 2, "Run status: %s",
05204 run_state == STATE_STOPPED ? "Stopped" : run_state ==
05205 STATE_RUNNING ? "Running" : "Paused");
05206 ss_printf(25, 2, "Run number %ld ", run_number);
05207 ss_printf(0, 3,
05208 "================================================================================");
05209 ss_printf(0, 4,
05210 "Equipment Status Events Events/sec Rate[kB/s] ODB->FE FE->ODB");
05211 ss_printf(0, 5,
05212 "--------------------------------------------------------------------------------");
05213 for (i = 0; equipment[i].name[0]; i++)
05214 ss_printf(0, i + 6, "%s", equipment[i].name);
05215 }
05216
05217
05218 time(&full_time);
05219 strcpy(str, ctime(&full_time) + 11);
05220 str[8] = 0;
05221 ss_printf(72, 0, "%s", str);
05222
05223 for (i = 0; equipment[i].name[0]; i++) {
05224 status = equipment[i].status;
05225
05226 if ((status == 0 || status == FE_SUCCESS) && equipment[i].info.enabled)
05227 ss_printf(14, i + 6, "OK ");
05228 else if (!equipment[i].info.enabled)
05229 ss_printf(14, i + 6, "Disabled ");
05230 else if (status == FE_ERR_ODB)
05231 ss_printf(14, i + 6, "ODB Error");
05232 else if (status == FE_ERR_HW)
05233 ss_printf(14, i + 6, "HW Error ");
05234 else if (status == FE_ERR_DISABLED)
05235 ss_printf(14, i + 6, "Disabled ");
05236 else
05237 ss_printf(14, i + 6, "Unknown ");
05238
05239 if (equipment[i].stats.events_sent > 1E9)
05240 ss_printf(25, i + 6, "%1.3lfG ", equipment[i].stats.events_sent / 1E9);
05241 else if (equipment[i].stats.events_sent > 1E6)
05242 ss_printf(25, i + 6, "%1.3lfM ", equipment[i].stats.events_sent / 1E6);
05243 else
05244 ss_printf(25, i + 6, "%1.0lf ", equipment[i].stats.events_sent);
05245 ss_printf(36, i + 6, "%1.1lf ", equipment[i].stats.events_per_sec);
05246 ss_printf(47, i + 6, "%1.1lf ", equipment[i].stats.kbytes_per_sec);
05247 ss_printf(58, i + 6, "%ld ", equipment[i].odb_in);
05248 ss_printf(69, i + 6, "%ld ", equipment[i].odb_out);
05249 }
05250
05251
05252 ss_printf(0, i + 6, "");
05253 }
05254
05255
05256
05257 INT scheduler(void)
05258 {
05259 EQUIPMENT_INFO *eq_info;
05260 EQUIPMENT *eq;
05261 ANALYZE_REQUEST *ar;
05262 EVENT_HEADER *pevent;
05263 DWORD actual_time, actual_millitime,
05264 last_time_network = 0, last_time_display = 0, readout_start, source;
05265 INT i, j, index, status, ch, size, flag;
05266 char str[80];
05267
05268 pevent = (EVENT_HEADER *) event_buffer;
05269
05270
05271
05272 do {
05273 actual_millitime = ss_millitime();
05274 actual_time = ss_millitime();
05275
05276
05277 for (index = 0;; index++) {
05278 eq = &equipment[index];
05279 eq_info = &eq->info;
05280
05281
05282 if (!eq->name[0])
05283 break;
05284
05285 if (!eq_info->enabled)
05286 continue;
05287
05288 if (eq->status != FE_SUCCESS)
05289 continue;
05290
05291
05292 if ((eq_info->eq_type & EQ_SLOW) && eq->status == FE_SUCCESS) {
05293 if (eq_info->event_limit > 0 && run_state == STATE_RUNNING) {
05294 if (actual_time - eq->last_idle >= (DWORD) eq_info->event_limit) {
05295 eq->cd(CMD_IDLE, eq);
05296 eq->last_idle = actual_time;
05297 }
05298 } else
05299 eq->cd(CMD_IDLE, eq);
05300 }
05301
05302 if (run_state == STATE_STOPPED && (eq_info->read_on & RO_STOPPED) == 0)
05303 continue;
05304 if (run_state == STATE_PAUSED && (eq_info->read_on & RO_PAUSED) == 0)
05305 continue;
05306 if (run_state == STATE_RUNNING && (eq_info->read_on & RO_RUNNING) == 0)
05307 continue;
05308
05309
05310 if ((eq_info->eq_type & EQ_PERIODIC) || (eq_info->eq_type & EQ_SLOW)) {
05311 if (eq_info->period == 0)
05312 continue;
05313
05314
05315 if (actual_time - eq->last_called >= (DWORD) eq_info->period) {
05316 eq->last_called = actual_time;
05317
05318
05319 pevent->event_id = eq_info->event_id;
05320 pevent->trigger_mask = eq_info->trigger_mask;
05321 pevent->data_size = 0;
05322 pevent->time_stamp = actual_time;
05323 pevent->serial_number = eq->serial_number++;
05324
05325
05326 *((EQUIPMENT **) (pevent + 1)) = eq;
05327 pevent->data_size = eq->readout((char *) (pevent + 1), 0);
05328
05329
05330 if (pevent->data_size) {
05331 eq->bytes_sent += pevent->data_size;
05332 eq->events_sent++;
05333
05334
05335 process_event(pevent);
05336
05337
05338 if (eq->buffer_handle) {
05339 bm_send_event(eq->buffer_handle, pevent,
05340 pevent->data_size + sizeof(EVENT_HEADER), SYNC);
05341
05342
05343 bm_flush_cache(eq->buffer_handle, SYNC);
05344 }
05345
05346 } else
05347 eq->serial_number--;
05348
05349 eq->last_called = actual_time;
05350 }
05351 }
05352
05353
05354 if (eq_info->eq_type & EQ_POLLED) {
05355
05356 pevent->event_id = eq_info->event_id;
05357 pevent->trigger_mask = eq_info->trigger_mask;
05358 pevent->data_size = 0;
05359 readout_start = actual_time;
05360
05361 while ((source = poll_event(eq_info->source, eq->poll_count, FALSE))) {
05362 pevent->time_stamp = actual_time;
05363 pevent->serial_number = eq->serial_number++;
05364
05365
05366 *(INT *) (pevent + 1) = source;
05367
05368
05369 pevent->data_size = eq->readout((char *) (pevent + 1), 0);
05370
05371
05372 if (pevent->data_size) {
05373 if (eq->buffer_handle)
05374 bm_send_event(eq->buffer_handle, pevent,
05375 pevent->data_size + sizeof(EVENT_HEADER), SYNC);
05376
05377 eq->bytes_sent += pevent->data_size;
05378 eq->events_sent++;
05379
05380
05381 process_event(pevent);
05382 } else
05383 eq->serial_number--;
05384
05385 actual_time = ss_millitime();
05386
05387
05388 if (actual_time - readout_start > 100)
05389 break;
05390
05391
05392 if (eq_info->event_limit && eq->serial_number > eq_info->event_limit)
05393 break;
05394 }
05395
05396 }
05397
05398
05399 if (eq_info->eq_type != EQ_SLOW &&
05400 eq_info->event_limit &&
05401 eq->serial_number > eq_info->event_limit && run_state == STATE_RUNNING) {
05402
05403 if (cm_transition(TR_STOP, 0, str, sizeof(str), SYNC, FALSE) != CM_SUCCESS) {
05404 cm_msg(MERROR, "Cannot stop run: %s", str);
05405 }
05406
05407
05408 size = sizeof(BOOL);
05409 flag = FALSE;
05410 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
05411
05412 if (flag)
05413 auto_restart = ss_time() + 5;
05414 }
05415 }
05416
05417
05418 if (frontend_call_loop) {
05419 status = frontend_loop();
05420 if (status != CM_SUCCESS)
05421 status = RPC_SHUTDOWN;
05422 }
05423
05424
05425 if (display_period && actual_time - last_time_display > (DWORD) display_period) {
05426
05427 if (actual_time != last_time_display) {
05428 for (i = 0; equipment[i].name[0]; i++) {
05429 eq = &equipment[i];
05430 j = eq->serial_number;
05431 if (j > 0)
05432 j--;
05433 eq->stats.events_sent = j;
05434 eq->stats.events_per_sec =
05435 (DWORD) (eq->events_sent /
05436 ((actual_time - last_time_display) / 1000.0));
05437 eq->stats.kbytes_per_sec =
05438 eq->bytes_sent / 1024.0 / ((actual_time - last_time_display) / 1000.0);
05439
05440 eq->bytes_sent = 0;
05441 eq->events_sent = 0;
05442 }
05443
05444 for (i = 0; analyze_request[i].event_name[0]; i++) {
05445 ar = &analyze_request[i];
05446 ar->ar_stats.events_received += ar->events_received;
05447 ar->ar_stats.events_per_sec =
05448 (DWORD) (ar->events_received /
05449 ((actual_time - last_time_display) / 1000.0));
05450 ar->events_received = 0;
05451 }
05452
05453 }
05454
05455
05456 db_send_changed_records();
05457
05458
05459 update_stats();
05460
05461 display(FALSE);
05462
05463
05464 ch = 0;
05465 status = 0;
05466 while (ss_kbhit()) {
05467 ch = ss_getchar(0);
05468 if (ch == -1)
05469 ch = getchar();
05470
05471 if (ch == '!')
05472 status = RPC_SHUTDOWN;
05473 }
05474
05475 if (ch > 0)
05476 display(TRUE);
05477 if (status == RPC_SHUTDOWN)
05478 break;
05479
05480 last_time_display = actual_time;
05481 }
05482
05483
05484 if (run_state == STATE_RUNNING) {
05485
05486 if (actual_time - last_time_network > 100) {
05487 status = cm_yield(0);
05488 last_time_network = actual_time;
05489 } else
05490 status = RPC_SUCCESS;
05491 } else
05492
05493 status = cm_yield(100);
05494
05495
05496 if (auto_restart > 0 && ss_time() > auto_restart) {
05497 auto_restart = FALSE;
05498 size = sizeof(run_number);
05499 db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
05500
05501 cm_msg(MTALK, "main", "starting new run");
05502 status = cm_transition(TR_START, run_number + 1, NULL, 0, ASYNC, FALSE);
05503 if (status != CM_SUCCESS)
05504 cm_msg(MERROR, "main", "cannot restart run");
05505 }
05506
05507 } while (status != RPC_SHUTDOWN && status != SS_ABORT);
05508
05509 return status;
05510 }
05511
05512
05513
05514 #ifdef OS_VXWORKS
05515 int mfe(char *ahost_name, char *aexp_name, BOOL adebug)
05516 #else
05517 int main(int argc, char *argv[])
05518 #endif
05519 {
05520 INT status, i;
05521 BOOL debug;
05522
05523 host_name[0] = 0;
05524 exp_name[0] = 0;
05525 debug = FALSE;
05526
05527 #ifdef OS_VXWORKS
05528 if (ahost_name)
05529 strcpy(host_name, ahost_name);
05530 if (aexp_name)
05531 strcpy(exp_name, aexp_name);
05532 debug = adebug;
05533 #else
05534
05535
05536 cm_get_environment(host_name, sizeof(host_name), exp_name, sizeof(exp_name));
05537
05538
05539 for (i = 1; i < argc; i++) {
05540 if (argv[i][0] == '-' && argv[i][1] == 'd')
05541 debug = TRUE;
05542 else if (argv[i][0] == '-') {
05543 if (i + 1 >= argc || argv[i + 1][0] == '-')
05544 goto usage;
05545 if (argv[i][1] == 'e')
05546 strcpy(exp_name, argv[++i]);
05547 else if (argv[i][1] == 'h')
05548 strcpy(host_name, argv[++i]);
05549 #ifndef MANA_LITE
05550 else if (argv[i][1] == 's')
05551 pawc_size = atoi(argv[++i]);
05552 #endif
05553 else {
05554 usage:
05555 printf("usage: fal [-h Hostname] [-e Experiment] [-s pawc_size] [-d]\n\n");
05556 printf("-d(ebug) should be set if FAL is started inside a debugger\n");
05557 return 1;
05558 }
05559 }
05560 }
05561 #endif
05562
05563
05564 if (host_name[0])
05565 printf("Connect to experiment %s on host %s...", exp_name, host_name);
05566 else
05567 printf("Connect to experiment %s...", exp_name);
05568
05569 status = cm_connect_experiment1(host_name, exp_name, fal_name, NULL, odb_size,
05570 LOGGER_TIMEOUT);
05571 if (status != CM_SUCCESS) {
05572
05573 ss_sleep(5000);
05574 return 1;
05575 }
05576
05577 printf("OK\n");
05578
05579
05580 cm_set_msg_print(MT_ALL, MT_ALL, print_message);
05581
05582
05583 status = cm_exist(fal_name, FALSE);
05584 if (status == CM_SUCCESS) {
05585
05586 cm_cleanup(fal_name, FALSE);
05587
05588
05589 ss_sleep(2000);
05590
05591
05592 status = cm_exist(fal_name, FALSE);
05593 if (status == CM_SUCCESS) {
05594 printf("This program runs already and cannot be started twice.\n");
05595 printf("<Please hit return to exit>");
05596 getchar();
05597 cm_disconnect_experiment();
05598 return 1;
05599 }
05600
05601
05602 cm_disconnect_experiment();
05603 cm_connect_experiment1(host_name, exp_name, fal_name, NULL, odb_size,
05604 LOGGER_TIMEOUT);
05605 }
05606
05607 if (cm_register_transition(TR_START, tr_start_fal, 500) != CM_SUCCESS ||
05608 cm_register_transition(TR_STOP, tr_stop_fal, 500) != CM_SUCCESS ||
05609 cm_register_transition(TR_PAUSE, tr_pause, 500) != CM_SUCCESS ||
05610 cm_register_transition(TR_RESUME, tr_resume, 500) != CM_SUCCESS) {
05611 printf("Failed to start local RPC server");
05612 return 1;
05613 }
05614
05615 cm_get_experiment_database(&hDB, NULL);
05616
05617
05618 i = 1;
05619 db_set_value(hDB, 0, "/Runinfo/Online Mode", &i, sizeof(int), 1, TID_INT);
05620
05621
05622 if (debug)
05623 cm_set_watchdog_params(TRUE, 0);
05624
05625
05626 cm_set_msg_print(MT_ALL, MT_ALL, print_message);
05627
05628
05629 cm_msg_register(receive_message);
05630
05631
05632 cm_register_function(RPC_ANA_CLEAR_HISTOS, ana_callback);
05633
05634
05635 cm_register_function(RPC_LOG_REWIND, log_callback);
05636
05637
05638 printf("Init hardware...");
05639 if (frontend_init() != CM_SUCCESS) {
05640 printf("Cannot initialize hardware.\n");
05641 printf("<Please hit return to exit>");
05642 getchar();
05643 cm_disconnect_experiment();
05644 return 1;
05645 }
05646 printf("OK\n");
05647
05648
05649 register_equipment();
05650
05651
05652 if (init_module_parameters() != CM_SUCCESS) {
05653 cm_disconnect_experiment();
05654 return 1;
05655 }
05656
05657
05658 logger_init();
05659
05660
05661 printf("Init analyzer...");
05662 if (mana_init() != CM_SUCCESS) {
05663 printf("Cannot initialize analyzer.\n");
05664 printf("<Please hit return to exit>");
05665 getchar();
05666 cm_disconnect_experiment();
05667 return 0;
05668 }
05669 printf("OK\n");
05670
05671
05672 register_requests();
05673
05674
05675 open_history();
05676
05677
05678 ss_sleep(2000);
05679 display(TRUE);
05680
05681
05682 ss_getchar(0);
05683
05684
05685 scheduler();
05686
05687
05688 frontend_exit();
05689
05690
05691 for (i = 0; equipment[i].name[0]; i++)
05692 if ((equipment[i].info.eq_type & EQ_SLOW) && equipment[i].status == FE_SUCCESS)
05693 equipment[i].cd(CMD_EXIT, &equipment[i]);
05694
05695
05696 close_history();
05697
05698
05699 cm_disconnect_experiment();
05700
05701 ss_clear_screen();
05702 ss_printf(0, 0, "%s shut down.", fal_name);
05703 ss_printf(0, 1, "");
05704
05705 return 0;
05706 }