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 <errno.h>
00016 #include <assert.h>
00017
00018 #define HAVE_LOGGING
00019 #include "mdsupport.h"
00020
00021 #ifdef HAVE_ROOT
00022 #undef GetCurrentTime
00023 #include "TApplication.h"
00024 #include "TFile.h"
00025 #include "TNtuple.h"
00026 #include "TLeaf.h"
00027 #endif
00028
00029 #ifdef HAVE_ZLIB
00030 #include <zlib.h>
00031 #endif
00032
00033 #ifdef HAVE_MYSQL
00034 #ifdef OS_UNIX
00035 #include <mysql/mysql.h>
00036 #include <mysql/mysqld_error.h>
00037 #endif
00038 #ifdef OS_WINNT
00039 #include <mysql.h>
00040 #include <mysqld_error.h>
00041 int errno;
00042 #endif
00043 void create_sql_tree();
00044 #endif
00045
00046
00047
00048 #define LOGGER_TIMEOUT 60000
00049
00050 #define MAX_CHANNELS 10
00051
00052 INT local_state;
00053 BOOL in_stop_transition = FALSE;
00054 BOOL tape_message = TRUE;
00055 BOOL verbose = FALSE;
00056 BOOL stop_requested = FALSE;
00057 BOOL start_requested = FALSE;
00058 DWORD auto_restart = 0;
00059 DWORD run_start_time, subrun_start_time;
00060
00061 LOG_CHN log_chn[MAX_CHANNELS];
00062
00063 struct hist_log_s {
00064 char event_name[256];
00065 WORD event_id;
00066 char *buffer;
00067 INT buffer_size;
00068 HNDLE hKeyVar;
00069 DWORD n_var;
00070 DWORD period;
00071 DWORD last_log;
00072 };
00073
00074 static int hist_log_size = 0;
00075 static int hist_log_max = 0;
00076 static hist_log_s *hist_log = NULL;
00077
00078 HNDLE hDB;
00079
00080
00081
00082 CHN_SETTINGS_STR(chn_settings_str);
00083
00084
00085
00086 typedef struct {
00087 char *buffer;
00088 char *write_pointer;
00089 } MIDAS_INFO;
00090
00091
00092
00093 void receive_event(HNDLE hBuf, HNDLE request_id, EVENT_HEADER * pheader, void *pevent);
00094 INT log_write(LOG_CHN * log_chn, EVENT_HEADER * pheader);
00095 void log_system_history(HNDLE hDB, HNDLE hKey, void *info);
00096 int log_generate_file_name(LOG_CHN *log_chn);
00097
00098
00099
00100
00101
00102 void logger_init()
00103 {
00104 INT size, status, delay, index;
00105 BOOL flag;
00106 HNDLE hKey, hKeyChannel;
00107 KEY key;
00108 char str[256];
00109
00110
00111
00112 cm_get_path(str);
00113 size = sizeof(str);
00114 db_get_value(hDB, 0, "/Logger/Data dir", str, &size, TID_STRING, TRUE);
00115
00116 strcpy(str, "midas.log");
00117 size = sizeof(str);
00118 db_get_value(hDB, 0, "/Logger/Message file", str, &size, TID_STRING, TRUE);
00119
00120 size = sizeof(BOOL);
00121 flag = TRUE;
00122 db_get_value(hDB, 0, "/Logger/Write data", &flag, &size, TID_BOOL, TRUE);
00123
00124 flag = FALSE;
00125 db_get_value(hDB, 0, "/Logger/ODB Dump", &flag, &size, TID_BOOL, TRUE);
00126
00127 strcpy(str, "run%05d.odb");
00128 size = sizeof(str);
00129 db_get_value(hDB, 0, "/Logger/ODB Dump File", str, &size, TID_STRING, TRUE);
00130
00131 flag = FALSE;
00132 size = sizeof(BOOL);
00133 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
00134
00135 delay = 0;
00136 size = sizeof(INT);
00137 db_get_value(hDB, 0, "/Logger/Auto restart delay", &delay, &size, TID_INT, TRUE);
00138
00139 flag = TRUE;
00140 db_get_value(hDB, 0, "/Logger/Tape message", &flag, &size, TID_BOOL, TRUE);
00141
00142
00143 status = db_find_key(hDB, 0, "/Logger/Channels/0", &hKey);
00144 if (status != DB_SUCCESS) {
00145
00146 status = db_create_record(hDB, 0, "/Logger/Channels/0", strcomb(chn_settings_str));
00147 if (status != DB_SUCCESS)
00148 cm_msg(MERROR, "logger_init", "Cannot create channel entry in database");
00149 } else {
00150
00151 status = db_find_key(hDB, 0, "/Logger/Channels", &hKey);
00152 if (status == DB_SUCCESS) {
00153 for (index = 0; index < MAX_CHANNELS; index++) {
00154 status = db_enum_key(hDB, hKey, index, &hKeyChannel);
00155 if (status == DB_NO_MORE_SUBKEYS)
00156 break;
00157
00158 db_get_key(hDB, hKeyChannel, &key);
00159 status = db_check_record(hDB, hKey, key.name, strcomb(chn_settings_str), TRUE);
00160 if (status != DB_SUCCESS && status != DB_OPEN_RECORD) {
00161 cm_msg(MERROR, "logger_init", "Cannot create/check channel record");
00162 break;
00163 }
00164 }
00165 }
00166 }
00167 #ifdef HAVE_MYSQL
00168 create_sql_tree();
00169 #endif
00170 }
00171
00172
00173
00174 void log_odb_dump(LOG_CHN * log_chn, short int event_id, INT run_number)
00175 {
00176 INT status, buffer_size, size;
00177 EVENT_HEADER *pevent;
00178
00179
00180 buffer_size = 100000;
00181 do {
00182 pevent = (EVENT_HEADER *) malloc(buffer_size);
00183 if (pevent == NULL) {
00184 cm_msg(MERROR, "log_odb_dump", "Cannot allocate ODB dump buffer");
00185 break;
00186 }
00187
00188 size = buffer_size - sizeof(EVENT_HEADER);
00189 status = db_copy_xml(hDB, 0, (char *) (pevent + 1), &size);
00190
00191
00192
00193 if (status != DB_TRUNCATED) {
00194 bm_compose_event(pevent, event_id, MIDAS_MAGIC,
00195 buffer_size - sizeof(EVENT_HEADER) - size + 1, run_number);
00196 log_write(log_chn, pevent);
00197 free(pevent);
00198 break;
00199 }
00200
00201
00202 free(pevent);
00203 buffer_size *= 10;
00204 } while (1);
00205 }
00206
00207
00208
00209 void odb_save(const char *filename)
00210 {
00211 int size;
00212 char dir[256];
00213 char path[256];
00214
00215 if (strchr(filename, DIR_SEPARATOR) == NULL) {
00216 size = sizeof(dir);
00217 dir[0] = 0;
00218 db_get_value(hDB, 0, "/Logger/Data Dir", dir, &size, TID_STRING, TRUE);
00219 if (dir[0] != 0)
00220 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
00221 strcat(dir, DIR_SEPARATOR_STR);
00222 strcpy(path, dir);
00223 strcat(path, filename);
00224 } else
00225 strcpy(path, filename);
00226
00227 if (strstr(filename, ".xml") || strstr(filename, ".XML"))
00228 db_save_xml(hDB, 0, path);
00229 else
00230 db_save(hDB, 0, path, FALSE);
00231 }
00232
00233
00234 #ifdef HAVE_MYSQL
00235
00236
00237
00238
00239
00240 typedef struct {
00241 char column_name[NAME_LENGTH];
00242 char column_type[NAME_LENGTH];
00243 char data[256];
00244 } SQL_LIST;
00245
00246 char *mname[] = {
00247 "January",
00248 "February",
00249 "March",
00250 "April",
00251 "May",
00252 "June",
00253 "July",
00254 "August",
00255 "September",
00256 "October",
00257 "November",
00258 "December"
00259 };
00260
00261 void ctime_to_datetime(char *date)
00262 {
00263 char ctime_date[30];
00264 struct tm tms;
00265 int i;
00266
00267 strlcpy(ctime_date, date, sizeof(ctime_date));
00268 memset(&tms, 0, sizeof(struct tm));
00269
00270 for (i = 0; i < 12; i++)
00271 if (strncmp(ctime_date + 4, mname[i], 3) == 0)
00272 break;
00273 tms.tm_mon = i;
00274
00275 tms.tm_mday = atoi(ctime_date + 8);
00276 tms.tm_hour = atoi(ctime_date + 11);
00277 tms.tm_min = atoi(ctime_date + 14);
00278 tms.tm_sec = atoi(ctime_date + 17);
00279 tms.tm_year = atoi(ctime_date + 20) - 1900;
00280 tms.tm_isdst = -1;
00281
00282 if (tms.tm_year < 90)
00283 tms.tm_year += 100;
00284
00285 mktime(&tms);
00286 sprintf(date, "%d-%02d-%02d %02d-%02d-%02d",
00287 tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday, tms.tm_hour, tms.tm_min, tms.tm_sec);
00288 }
00289
00290
00291
00292 int mysql_query_debug(MYSQL * db, char *query)
00293 {
00294 int status, size, fh;
00295 char filename[256], path[256], dir[256];
00296 HNDLE hKey;
00297
00298
00299
00300
00301
00302 size = sizeof(filename);
00303 filename[0] = 0;
00304 db_get_value(hDB, 0, "/Logger/SQL/Logfile", filename, &size, TID_STRING, TRUE);
00305 if (filename[0]) {
00306 status = db_find_key(hDB, 0, "/Logger/Data dir", &hKey);
00307 if (status == DB_SUCCESS) {
00308 size = sizeof(dir);
00309 memset(dir, 0, size);
00310 db_get_value(hDB, 0, "/Logger/Data dir", dir, &size, TID_STRING, TRUE);
00311 if (dir[0] != 0)
00312 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
00313 strcat(dir, DIR_SEPARATOR_STR);
00314
00315 strcpy(path, dir);
00316 strcat(path, filename);
00317 } else {
00318 cm_get_path(dir);
00319 if (dir[0] != 0)
00320 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
00321 strcat(dir, DIR_SEPARATOR_STR);
00322
00323 strcpy(path, dir);
00324 strcat(path, filename);
00325 }
00326
00327 fh = open(path, O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE, 0644);
00328 if (fh < 0) {
00329 printf("Cannot open message log file %s\n", path);
00330 } else {
00331 write(fh, query, strlen(query));
00332 write(fh, ";\n", 2);
00333 close(fh);
00334 }
00335 }
00336
00337
00338 status = mysql_query(db, query);
00339
00340 if (status)
00341 cm_msg(MERROR, "mysql_query_debug", "SQL error: %s", mysql_error(db));
00342
00343 return status;
00344 }
00345
00346
00347
00348 int sql_get_columns(HNDLE hKeyRoot, SQL_LIST ** sql_list)
00349 {
00350 HNDLE hKey;
00351 int n, i, size, status;
00352 KEY key;
00353 char str[256], data[256];
00354
00355 for (i = 0;; i++) {
00356 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
00357 if (status == DB_NO_MORE_SUBKEYS)
00358 break;
00359 }
00360
00361 if (i == 0)
00362 return 0;
00363
00364 n = i;
00365
00366 *sql_list = (SQL_LIST *) malloc(sizeof(SQL_LIST) * n);
00367
00368 for (i = 0; i < n; i++) {
00369
00370
00371 db_enum_link(hDB, hKeyRoot, i, &hKey);
00372 db_get_link(hDB, hKey, &key);
00373 strlcpy((*sql_list)[i].column_name, key.name, NAME_LENGTH);
00374
00375
00376 db_enum_key(hDB, hKeyRoot, i, &hKey);
00377 db_get_key(hDB, hKey, &key);
00378
00379
00380 size = sizeof(data);
00381 db_get_data(hDB, hKey, data, &size, key.type);
00382 db_sprintf(str, data, size, 0, key.type);
00383 if (key.type == TID_BOOL)
00384 strcpy((*sql_list)[i].data, str[0] == 'y' || str[0] == 'Y' ? "1" : "0");
00385 else
00386 strcpy((*sql_list)[i].data, str);
00387
00388 if (key.type == TID_STRING) {
00389
00390 if (strlen(str) == 24 && str[10] == ' ' && str[13] == ':') {
00391 strcpy(str, "DATETIME");
00392 ctime_to_datetime((*sql_list)[i].data);
00393 } else if (key.item_size < 256)
00394 sprintf(str, "VARCHAR (%d)", key.item_size);
00395 else
00396 sprintf(str, " TEXT");
00397
00398 } else {
00399 switch (key.type) {
00400 case TID_BYTE:
00401 strcpy(str, "TINYINT UNSIGNED ");
00402 break;
00403 case TID_SBYTE:
00404 strcpy(str, "TINYINT ");
00405 break;
00406 case TID_CHAR:
00407 strcpy(str, "CHAR ");
00408 break;
00409 case TID_WORD:
00410 strcpy(str, "SMALLINT UNSIGNED ");
00411 break;
00412 case TID_SHORT:
00413 strcpy(str, "SMALLINT ");
00414 break;
00415 case TID_DWORD:
00416 strcpy(str, "INT UNSIGNED ");
00417 break;
00418 case TID_INT:
00419 strcpy(str, "INT ");
00420 break;
00421 case TID_BOOL:
00422 strcpy(str, "BOOLEAN ");
00423 break;
00424 case TID_FLOAT:
00425 strcpy(str, "FLOAT ");
00426 break;
00427 case TID_DOUBLE:
00428 strcpy(str, "DOUBLE ");
00429 break;
00430 default:
00431 cm_msg(MERROR, "sql_create_database",
00432 "No SQL type mapping for key \"%s\" of type %s", key.name, rpc_tid_name(key.type));
00433 }
00434 }
00435
00436 strcpy((*sql_list)[i].column_type, str);
00437 }
00438
00439 return n;
00440 }
00441
00442
00443
00444 BOOL sql_create_table(MYSQL * db, char *database, char *table, HNDLE hKeyRoot)
00445 {
00446 char str[256], query[5000];
00447 int i, n_col;
00448 SQL_LIST *sql_list;
00449
00450 sprintf(query, "CREATE TABLE `%s`.`%s` (", database, table);
00451
00452 n_col = sql_get_columns(hKeyRoot, &sql_list);
00453 if (n_col == 0) {
00454 db_get_path(hDB, hKeyRoot, str, sizeof(str));
00455 cm_msg(MERROR, "sql_create_database", "ODB tree \"%s\" contains no variables", str);
00456 return FALSE;
00457 }
00458
00459 for (i = 0; i < n_col; i++)
00460 sprintf(query + strlen(query), "`%s` %s NOT NULL, ", sql_list[i].column_name, sql_list[i].column_type);
00461
00462 sprintf(query + strlen(query), "PRIMARY KEY (`%s`))", sql_list[0].column_name);
00463 free(sql_list);
00464
00465 if (mysql_query_debug(db, query)) {
00466 cm_msg(MERROR, "sql_create_table", "Failed to create table: Error: %s", mysql_error(db));
00467 return FALSE;
00468 }
00469
00470 return TRUE;
00471 }
00472
00473
00474
00475 BOOL sql_modify_table(MYSQL * db, char *database, char *table, HNDLE hKeyRoot)
00476 {
00477 char str[256], query[5000];
00478 int i, n_col;
00479 SQL_LIST *sql_list;
00480
00481 n_col = sql_get_columns(hKeyRoot, &sql_list);
00482 if (n_col == 0) {
00483 db_get_path(hDB, hKeyRoot, str, sizeof(str));
00484 cm_msg(MERROR, "sql_modify_table", "ODB tree \"%s\" contains no variables", str);
00485 return FALSE;
00486 }
00487
00488 for (i = 0; i < n_col; i++) {
00489
00490
00491 if (i == 0)
00492 sprintf(query, "ALTER TABLE `%s`.`%s` ADD `%s` %s",
00493 database, table, sql_list[i].column_name, sql_list[i].column_type);
00494 else
00495 sprintf(query, "ALTER TABLE `%s`.`%s` ADD `%s` %s AFTER `%s`",
00496 database, table, sql_list[i].column_name, sql_list[i].column_type,
00497 sql_list[i - 1].column_name);
00498
00499 if (mysql_query_debug(db, query)) {
00500 if (mysql_errno(db) == ER_DUP_FIELDNAME) {
00501
00502
00503 sprintf(query, "ALTER TABLE `%s`.`%s` MODIFY `%s` %s",
00504 database, table, sql_list[i].column_name, sql_list[i].column_type);
00505
00506 if (mysql_query_debug(db, query)) {
00507 free(sql_list);
00508 cm_msg(MERROR, "sql_modify_table", "Failed to modify column: Error: %s", mysql_error(db));
00509 return FALSE;
00510 }
00511
00512 } else {
00513 free(sql_list);
00514 cm_msg(MERROR, "sql_modify_table", "Failed to add column: Error: %s", mysql_error(db));
00515 return FALSE;
00516 }
00517 }
00518 }
00519
00520 cm_msg(MINFO, "sql_insert", "SQL table '%s.%s' modified successfully", database, table);
00521
00522 return TRUE;
00523 }
00524
00525
00526
00527 BOOL sql_create_database(MYSQL * db, char *database)
00528 {
00529 char query[256];
00530
00531 sprintf(query, "CREATE DATABASE `%s`", database);
00532 if (mysql_query_debug(db, query)) {
00533 cm_msg(MERROR, "sql_create_database", "Failed to create database: Error: %s", mysql_error(db));
00534 return FALSE;
00535 }
00536
00537
00538 sprintf(query, "USE `%s`", database);
00539 if (mysql_query_debug(db, query)) {
00540 cm_msg(MERROR, "sql_create_database", "Failed to select database: Error: %s", mysql_error(db));
00541 return FALSE;
00542 }
00543
00544 return TRUE;
00545 }
00546
00547
00548
00549 int sql_insert(MYSQL * db, char *database, char *table, HNDLE hKeyRoot, BOOL create_flag)
00550 {
00551 char query[5000], str[5000];
00552 int status, i, n_col;
00553 SQL_LIST *sql_list;
00554
00555
00556
00557
00558
00559 sprintf(query, "INSERT INTO `%s`.`%s` (", database, table);
00560 n_col = sql_get_columns(hKeyRoot, &sql_list);
00561 if (n_col == 0)
00562 return DB_SUCCESS;
00563
00564 for (i = 0; i < n_col; i++) {
00565 sprintf(query + strlen(query), "`%s`", sql_list[i].column_name);
00566 if (i < n_col - 1)
00567 strcat(query, ", ");
00568 }
00569
00570 strlcat(query, ") VALUES (", sizeof(query));
00571
00572 for (i = 0; i < n_col; i++) {
00573 strlcat(query, "'", sizeof(query));
00574
00575 mysql_escape_string(str, sql_list[i].data, strlen(sql_list[i].data));
00576 strlcat(query, str, sizeof(query));
00577 strlcat(query, "'", sizeof(query));
00578
00579 if (i < n_col - 1)
00580 strlcat(query, ", ", sizeof(query));
00581 }
00582
00583 free(sql_list);
00584 strlcat(query, ")", sizeof(query));
00585 if (mysql_query_debug(db, query)) {
00586
00587
00588 if (mysql_errno(db) == ER_DUP_ENTRY) {
00589
00590 return ER_DUP_ENTRY;
00591
00592 } else if (mysql_errno(db) == ER_NO_SUCH_TABLE && create_flag) {
00593
00594
00595 sql_create_table(db, database, table, hKeyRoot);
00596 if (mysql_query_debug(db, query)) {
00597 cm_msg(MERROR, "sql_insert", "Failed to update database: Error: %s", mysql_error(db));
00598 return mysql_errno(db);
00599 }
00600 cm_msg(MINFO, "sql_insert", "SQL table '%s.%s' created successfully", database, table);
00601
00602 } else if (mysql_errno(db) == ER_BAD_FIELD_ERROR && create_flag) {
00603
00604
00605 sql_modify_table(db, database, table, hKeyRoot);
00606 if (mysql_query_debug(db, query)) {
00607 cm_msg(MERROR, "sql_insert", "Failed to update database: Error: %s", mysql_error(db));
00608 return mysql_errno(db);
00609 }
00610
00611 } else {
00612 status = mysql_errno(db);
00613 cm_msg(MERROR, "sql_insert", "Failed to update database: Error: %s", mysql_error(db));
00614 return mysql_errno(db);
00615 }
00616 }
00617
00618 return DB_SUCCESS;
00619 }
00620
00621
00622
00623 int sql_update(MYSQL * db, char *database, char *table, HNDLE hKeyRoot, BOOL create_flag, char *where)
00624 {
00625 char query[5000], str[10000];
00626 int i, n_col;
00627 SQL_LIST *sql_list;
00628
00629
00630
00631
00632
00633
00634 sprintf(query, "UPDATE `%s`.`%s` SET ", database, table);
00635 n_col = sql_get_columns(hKeyRoot, &sql_list);
00636 if (n_col == 0)
00637 return DB_SUCCESS;
00638
00639 for (i = 0; i < n_col; i++) {
00640 mysql_escape_string(str, sql_list[i].data, strlen(sql_list[i].data));
00641 sprintf(query + strlen(query), "`%s`='%s'", sql_list[i].column_name, str);
00642 if (i < n_col - 1)
00643 strcat(query, ", ");
00644 }
00645 free(sql_list);
00646
00647 sprintf(query + strlen(query), " %s", where);
00648 if (mysql_query_debug(db, query)) {
00649 if (mysql_errno(db) == ER_NO_SUCH_TABLE && create_flag) {
00650
00651
00652 sql_create_table(db, database, table, hKeyRoot);
00653 return sql_insert(db, database, table, hKeyRoot, create_flag);
00654
00655 } else if (mysql_errno(db) == ER_BAD_FIELD_ERROR && create_flag) {
00656
00657
00658 sql_modify_table(db, database, table, hKeyRoot);
00659 if (mysql_query_debug(db, query)) {
00660 cm_msg(MERROR, "sql_update", "Failed to update database: Error: %s", mysql_error(db));
00661 return mysql_errno(db);
00662 }
00663
00664 } else {
00665 cm_msg(MERROR, "sql_update", "Failed to update database: Error: %s", mysql_error(db));
00666 return mysql_errno(db);
00667 }
00668 }
00669
00670 return DB_SUCCESS;
00671 }
00672
00673
00674
00675 void create_sql_tree()
00676 {
00677 char hostname[80], username[80], password[80], database[80], table[80], filename[80];
00678 int size, write_flag, create_flag;
00679 HNDLE hKeyRoot, hKey;
00680
00681 size = sizeof(create_flag);
00682 create_flag = 0;
00683 db_get_value(hDB, 0, "/Logger/SQL/Create database", &create_flag, &size, TID_BOOL, TRUE);
00684
00685 size = sizeof(write_flag);
00686 write_flag = 0;
00687 db_get_value(hDB, 0, "/Logger/SQL/Write data", &write_flag, &size, TID_BOOL, TRUE);
00688
00689 size = sizeof(hostname);
00690 strcpy(hostname, "localhost");
00691 db_get_value(hDB, 0, "/Logger/SQL/Hostname", hostname, &size, TID_STRING, TRUE);
00692
00693 size = sizeof(username);
00694 strcpy(username, "root");
00695 db_get_value(hDB, 0, "/Logger/SQL/Username", username, &size, TID_STRING, TRUE);
00696
00697 size = sizeof(password);
00698 password[0] = 0;
00699 db_get_value(hDB, 0, "/Logger/SQL/Password", password, &size, TID_STRING, TRUE);
00700
00701
00702 size = sizeof(database);
00703 db_get_value(hDB, 0, "/Experiment/Name", database, &size, TID_STRING, TRUE);
00704 db_get_value(hDB, 0, "/Logger/SQL/Database", database, &size, TID_STRING, TRUE);
00705
00706 size = sizeof(table);
00707 strcpy(table, "Runlog");
00708 db_get_value(hDB, 0, "/Logger/SQL/Table", table, &size, TID_STRING, TRUE);
00709
00710 size = sizeof(filename);
00711 strcpy(filename, "sql.log");
00712 db_get_value(hDB, 0, "/Logger/SQL/Logfile", filename, &size, TID_STRING, TRUE);
00713
00714 db_find_key(hDB, 0, "/Logger/SQL/Links BOR", &hKeyRoot);
00715 if (!hKeyRoot) {
00716
00717 db_create_key(hDB, 0, "/Logger/SQL/Links BOR", TID_KEY);
00718
00719 if (db_find_key(hDB, 0, "/Runinfo/Run number", &hKey) == DB_SUCCESS)
00720 db_create_link(hDB, 0, "/Logger/SQL/Links BOR/Run number", "/Runinfo/Run number");
00721
00722 if (db_find_key(hDB, 0, "/Experiment/Run parameters/Comment", &hKey) == DB_SUCCESS)
00723 db_create_link(hDB, 0, "/Logger/SQL/Links BOR/Comment", "/Experiment/Run parameters/Comment");
00724
00725 if (db_find_key(hDB, 0, "/Runinfo/Start time", &hKey) == DB_SUCCESS)
00726 db_create_link(hDB, 0, "/Logger/SQL/Links BOR/Start time", "/Runinfo/Start time");
00727 }
00728
00729 db_find_key(hDB, 0, "/Logger/SQL/Links EOR", &hKeyRoot);
00730 if (!hKeyRoot) {
00731
00732 db_create_key(hDB, 0, "/Logger/SQL/Links EOR", TID_KEY);
00733
00734 if (db_find_key(hDB, 0, "/Runinfo/Stop time", &hKey) == DB_SUCCESS)
00735 db_create_link(hDB, 0, "/Logger/SQL/Links EOR/Stop time", "/Runinfo/Stop time");
00736
00737 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/Events sent", &hKey) == DB_SUCCESS)
00738 db_create_link(hDB, 0, "/Logger/SQL/Links EOR/Number of events",
00739 "/Equipment/Trigger/Statistics/Events sent");
00740
00741 }
00742 }
00743
00744
00745
00746 void write_sql(BOOL bor)
00747 {
00748 MYSQL db;
00749 char hostname[80], username[80], password[80], database[80], table[80], query[5000], where[500];
00750 int status, size, write_flag, create_flag;
00751 BOOL insert;
00752 HNDLE hKey, hKeyRoot;
00753 SQL_LIST *sql_list;
00754
00755
00756 size = sizeof(BOOL);
00757 write_flag = FALSE;
00758 db_get_value(hDB, 0, "/Logger/Write data", &write_flag, &size, TID_BOOL, TRUE);
00759 if (!write_flag)
00760 return;
00761
00762
00763 insert = bor;
00764
00765
00766 db_find_key(hDB, 0, "/Logger/SQL/Links BOR", &hKeyRoot);
00767 status = db_enum_link(hDB, hKeyRoot, 0, &hKey);
00768
00769
00770 if (status == DB_NO_MORE_SUBKEYS) {
00771 insert = TRUE;
00772 db_find_key(hDB, 0, "/Logger/SQL/Links EOR", &hKeyRoot);
00773 status = db_enum_link(hDB, hKeyRoot, 0, &hKey);
00774 if (status == DB_NO_MORE_SUBKEYS)
00775 return;
00776 }
00777
00778 sql_get_columns(hKeyRoot, &sql_list);
00779 sprintf(where, "WHERE `%s`='%s'", sql_list[0].column_name, sql_list[0].data);
00780 free(sql_list);
00781
00782
00783 if (bor) {
00784 db_find_key(hDB, 0, "/Logger/SQL/Links BOR", &hKeyRoot);
00785 if (!hKeyRoot) {
00786 cm_msg(MERROR, "write_sql", "Cannot find \"/Logger/SQL/Links BOR");
00787 return;
00788 }
00789 } else {
00790 db_find_key(hDB, 0, "/Logger/SQL/Links EOR", &hKeyRoot);
00791 if (!hKeyRoot) {
00792 cm_msg(MERROR, "write_sql", "Cannot find \"/Logger/SQL/Links EOR");
00793 return;
00794 }
00795 }
00796
00797 size = sizeof(create_flag);
00798 create_flag = 0;
00799 db_get_value(hDB, 0, "/Logger/SQL/Create database", &create_flag, &size, TID_BOOL, TRUE);
00800
00801 size = sizeof(write_flag);
00802 write_flag = 0;
00803 db_get_value(hDB, 0, "/Logger/SQL/Write data", &write_flag, &size, TID_BOOL, TRUE);
00804
00805 size = sizeof(hostname);
00806 strcpy(hostname, "localhost");
00807 db_get_value(hDB, 0, "/Logger/SQL/Hostname", hostname, &size, TID_STRING, TRUE);
00808
00809 size = sizeof(username);
00810 strcpy(username, "root");
00811 db_get_value(hDB, 0, "/Logger/SQL/Username", username, &size, TID_STRING, TRUE);
00812
00813 size = sizeof(password);
00814 password[0] = 0;
00815 db_get_value(hDB, 0, "/Logger/SQL/Password", password, &size, TID_STRING, TRUE);
00816
00817
00818 size = sizeof(database);
00819 db_get_value(hDB, 0, "/Experiment/Name", database, &size, TID_STRING, TRUE);
00820 db_get_value(hDB, 0, "/Logger/SQL/Database", database, &size, TID_STRING, TRUE);
00821
00822 size = sizeof(table);
00823 strcpy(table, "Runlog");
00824 db_get_value(hDB, 0, "/Logger/SQL/Table", table, &size, TID_STRING, TRUE);
00825
00826
00827 if (!write_flag)
00828 return;
00829
00830
00831 mysql_init(&db);
00832
00833 if (!mysql_real_connect(&db, hostname, username, password, NULL, 0, NULL, 0)) {
00834 cm_msg(MERROR, "write_sql", "Failed to connect to database: Error: %s", mysql_error(&db));
00835 mysql_close(&db);
00836 return;
00837 }
00838
00839
00840 sprintf(query, "USE `%s`", database);
00841 if (mysql_query_debug(&db, query)) {
00842
00843
00844 if (create_flag) {
00845 if (!sql_create_database(&db, database)) {
00846 mysql_close(&db);
00847 return;
00848 }
00849 cm_msg(MINFO, "write_sql", "Database \"%s\" created successfully", database);
00850
00851 } else {
00852 cm_msg(MERROR, "write_sql", "Failed to select database: Error: %s", mysql_error(&db));
00853 mysql_close(&db);
00854 return;
00855 }
00856 }
00857
00858 if (insert) {
00859 status = sql_insert(&db, database, table, hKeyRoot, create_flag);
00860 if (status == ER_DUP_ENTRY)
00861 sql_update(&db, database, table, hKeyRoot, create_flag, where);
00862 } else
00863 sql_update(&db, database, table, hKeyRoot, create_flag, where);
00864
00865 mysql_close(&db);
00866 }
00867
00868 #endif // HAVE_MYSQL
00869
00870
00871
00872 INT tape_open(char *dev, INT * handle)
00873 {
00874 INT status, count;
00875 char buffer[16];
00876
00877 status = ss_tape_open(dev, O_RDWR | O_CREAT | O_TRUNC, handle);
00878 if (status != SS_SUCCESS)
00879 return status;
00880
00881
00882 count = sizeof(buffer);
00883 status = ss_tape_read(*handle, buffer, &count);
00884
00885 if (count == sizeof(buffer)) {
00886
00887 ss_tape_rskip(*handle, -1);
00888 cm_msg(MINFO, "tape_open", "Tape contains data, please spool tape with 'mtape seod'");
00889 cm_msg(MINFO, "tape_open", "or erase it with 'mtape weof', 'mtape rewind', then try again.");
00890 ss_tape_close(*handle);
00891 return SS_TAPE_ERROR;
00892 }
00893
00894 return SS_SUCCESS;
00895 }
00896
00897
00898
00899 INT ftp_error(char *message)
00900 {
00901 cm_msg(MERROR, "ftp_error", message);
00902 return 1;
00903 }
00904
00905 INT ftp_open(char *destination, FTP_CON ** con)
00906 {
00907 INT status;
00908 short port = 0;
00909 char *token, host_name[HOST_NAME_LENGTH],
00910 user[32], pass[32], directory[256], file_name[256], file_mode[256];
00911
00912
00913
00914
00915
00916
00917
00918 token = strtok(destination, ",");
00919 if (token)
00920 strcpy(host_name, token);
00921
00922 token = strtok(NULL, ", ");
00923 if (token)
00924 port = atoi(token);
00925
00926 token = strtok(NULL, ", ");
00927 if (token)
00928 strcpy(user, token);
00929
00930 token = strtok(NULL, ", ");
00931 if (token)
00932 strcpy(pass, token);
00933
00934 token = strtok(NULL, ", ");
00935 if (token)
00936 strcpy(directory, token);
00937
00938 token = strtok(NULL, ", ");
00939 if (token)
00940 strcpy(file_name, token);
00941
00942 token = strtok(NULL, ", ");
00943 file_mode[0] = 0;
00944 if (token)
00945 strcpy(file_mode, token);
00946
00947 #ifdef FAL_MAIN
00948 ftp_debug(NULL, ftp_error);
00949 #else
00950 ftp_debug((int (*)(char *)) puts, ftp_error);
00951 #endif
00952
00953 status = ftp_login(con, host_name, port, user, pass, "");
00954 if (status >= 0)
00955 return status;
00956
00957 status = ftp_chdir(*con, directory);
00958 if (status >= 0)
00959 return status;
00960
00961 status = ftp_binary(*con);
00962 if (status >= 0)
00963 return status;
00964
00965 if (file_mode[0]) {
00966 status = ftp_command(*con, "umask %s", file_mode, 200, 250, EOF);
00967 if (status >= 0)
00968 return status;
00969 }
00970
00971 if (ftp_open_write(*con, file_name) >= 0)
00972 return (*con)->err_no;
00973
00974 return SS_SUCCESS;
00975 }
00976
00977
00978
00979 INT midas_flush_buffer(LOG_CHN * log_chn)
00980 {
00981 INT size, written;
00982 MIDAS_INFO *info;
00983
00984 info = (MIDAS_INFO *) log_chn->format_info;
00985 size = (POINTER_T) info->write_pointer - (POINTER_T) info->buffer;
00986
00987 if (size == 0)
00988 return 0;
00989
00990
00991 if (log_chn->type == LOG_TYPE_TAPE)
00992 written = ss_tape_write(log_chn->handle, info->buffer, size);
00993 else if (log_chn->type == LOG_TYPE_FTP)
00994 written =
00995 ftp_send(((FTP_CON *) log_chn->ftp_con)->data, info->buffer,
00996 size) == size ? SS_SUCCESS : SS_FILE_ERROR;
00997 else if (log_chn->gzfile) {
00998 #ifdef HAVE_ZLIB
00999 z_streamp s;
01000 INT i;
01001
01002 s = (z_streamp) log_chn->gzfile;
01003 written = s->total_out;
01004 i = gzwrite(log_chn->gzfile, info->buffer, size);
01005 if (i != size)
01006 return -1;
01007 written = s->total_out - written;
01008 #else
01009 assert(!"this cannot happen! support for ZLIB not compiled in");
01010 #endif
01011 } else if (log_chn->handle) {
01012 #ifdef OS_WINNT
01013 WriteFile((HANDLE) log_chn->handle, info->buffer, size, (unsigned long *) &written, NULL);
01014 #else
01015 written = write(log_chn->handle, info->buffer, size);
01016 #endif
01017 } else {
01018
01019 written = 0;
01020 }
01021
01022 info->write_pointer = info->buffer;
01023
01024 return written;
01025 }
01026
01027
01028
01029
01030 INT midas_write(LOG_CHN * log_chn, EVENT_HEADER * pevent, INT evt_size)
01031 {
01032 INT i, written, size_left;
01033 MIDAS_INFO *info;
01034
01035 info = (MIDAS_INFO *) log_chn->format_info;
01036 written = 0;
01037
01038
01039 size_left = TAPE_BUFFER_SIZE - ((POINTER_T) info->write_pointer - (POINTER_T) info->buffer);
01040
01041 if (size_left < evt_size) {
01042
01043 memcpy(info->write_pointer, pevent, size_left);
01044 info->write_pointer += size_left;
01045
01046
01047 written += midas_flush_buffer(log_chn);
01048 if (written < 0)
01049 return SS_FILE_ERROR;
01050
01051
01052 while (evt_size - size_left >= TAPE_BUFFER_SIZE) {
01053 memcpy(info->buffer, (char *) pevent + size_left, TAPE_BUFFER_SIZE);
01054 info->write_pointer += TAPE_BUFFER_SIZE;
01055 size_left += TAPE_BUFFER_SIZE;
01056
01057 i = midas_flush_buffer(log_chn);
01058 if (i < 0)
01059 return SS_FILE_ERROR;
01060
01061 written += i;
01062 }
01063
01064
01065 memcpy(info->buffer, (char *) pevent + size_left, evt_size - size_left);
01066 info->write_pointer = info->buffer + (evt_size - size_left);
01067 } else {
01068
01069 memcpy(info->write_pointer, pevent, evt_size);
01070 info->write_pointer += evt_size;
01071 }
01072
01073
01074 log_chn->statistics.events_written++;
01075 log_chn->statistics.bytes_written_uncompressed += evt_size;
01076 log_chn->statistics.bytes_written += written;
01077 log_chn->statistics.bytes_written_subrun += written;
01078 log_chn->statistics.bytes_written_total += written;
01079
01080 return SS_SUCCESS;
01081 }
01082
01083
01084
01085 INT midas_log_open(LOG_CHN * log_chn, INT run_number)
01086 {
01087 MIDAS_INFO *info;
01088 INT status;
01089
01090
01091 log_chn->format_info = (void **) malloc(sizeof(MIDAS_INFO));
01092
01093 info = (MIDAS_INFO *) log_chn->format_info;
01094 if (info == NULL) {
01095 log_chn->handle = 0;
01096 return SS_NO_MEMORY;
01097 }
01098
01099
01100 if ((info->buffer = (char *) malloc(TAPE_BUFFER_SIZE)) == NULL) {
01101 free(info);
01102 log_chn->handle = 0;
01103 return SS_NO_MEMORY;
01104 }
01105
01106 info->write_pointer = info->buffer;
01107
01108
01109 if (log_chn->type == LOG_TYPE_TAPE) {
01110 status = tape_open(log_chn->path, &log_chn->handle);
01111 if (status != SS_SUCCESS) {
01112 free(info->buffer);
01113 free(info);
01114 log_chn->handle = 0;
01115 return status;
01116 }
01117 } else if (log_chn->type == LOG_TYPE_FTP) {
01118 status = ftp_open(log_chn->path, &log_chn->ftp_con);
01119 if (status != SS_SUCCESS) {
01120 free(info->buffer);
01121 free(info);
01122 log_chn->handle = 0;
01123 return status;
01124 } else
01125 log_chn->handle = 1;
01126 } else {
01127
01128 if (strstr(log_chn->path, "null") == NULL) {
01129 log_chn->handle = open(log_chn->path, O_RDONLY);
01130 if (log_chn->handle > 0) {
01131
01132 if (lseek(log_chn->handle, 0, SEEK_END) > 0) {
01133 close(log_chn->handle);
01134 free(info->buffer);
01135 free(info);
01136 log_chn->handle = 0;
01137 return SS_FILE_EXISTS;
01138 }
01139 }
01140 }
01141
01142 log_chn->gzfile = NULL;
01143 log_chn->handle = 0;
01144
01145
01146 if (1) {
01147 char *sufp = strstr(log_chn->path, ".gz");
01148 int isgz = sufp && sufp[3]==0;
01149
01150 if (log_chn->compression>0 && !isgz) {
01151 cm_msg(MERROR, "midas_log_open", "Compression level %d enabled, but output file name \'%s\' does not end with '.gz'", log_chn->compression, log_chn->path);
01152 free(info->buffer);
01153 free(info);
01154 return SS_FILE_ERROR;
01155 }
01156
01157 if (log_chn->compression==0 && isgz) {
01158 cm_msg(MERROR, "midas_log_open",
01159 "Output file name ends with '.gz', but compression level is zero");
01160 free(info->buffer);
01161 free(info);
01162 return SS_FILE_ERROR;
01163 }
01164 }
01165
01166 #ifdef OS_WINNT
01167 log_chn->handle = (int) CreateFile(log_chn->path, GENERIC_WRITE, FILE_SHARE_READ, NULL,
01168 CREATE_ALWAYS,
01169 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_SEQUENTIAL_SCAN, 0);
01170 #else
01171 log_chn->handle = open(log_chn->path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
01172 #endif
01173 if (log_chn->handle < 0) {
01174 free(info->buffer);
01175 free(info);
01176 log_chn->handle = 0;
01177 return SS_FILE_ERROR;
01178 }
01179
01180 if (log_chn->compression > 0) {
01181 #ifdef HAVE_ZLIB
01182 log_chn->gzfile = gzdopen(log_chn->handle, "wb");
01183 if (log_chn->gzfile == NULL) {
01184 cm_msg(MERROR, "midas_log_open",
01185 "Error: gzdopen() failed, cannot open compression stream");
01186 free(info->buffer);
01187 free(info);
01188 log_chn->handle = 0;
01189 return SS_FILE_ERROR;
01190 }
01191
01192 gzsetparams(log_chn->gzfile, log_chn->compression, Z_DEFAULT_STRATEGY);
01193 #else
01194 cm_msg(MERROR, "midas_log_open", "Compression enabled but ZLIB support not compiled in");
01195 close(log_chn->handle);
01196 free(info->buffer);
01197 free(info);
01198 log_chn->handle = 0;
01199 return SS_FILE_ERROR;
01200 #endif
01201 }
01202 }
01203
01204
01205 if (log_chn->settings.odb_dump)
01206 log_odb_dump(log_chn, EVENTID_BOR, run_number);
01207
01208 return SS_SUCCESS;
01209 }
01210
01211
01212
01213 INT midas_log_close(LOG_CHN * log_chn, INT run_number)
01214 {
01215 int written;
01216
01217
01218 if (log_chn->settings.odb_dump)
01219 log_odb_dump(log_chn, EVENTID_EOR, run_number);
01220
01221 written = midas_flush_buffer(log_chn);
01222
01223
01224 log_chn->statistics.bytes_written += written;
01225 log_chn->statistics.bytes_written_total += written;
01226
01227
01228 if (log_chn->type == LOG_TYPE_TAPE) {
01229
01230 ss_tape_write_eof(log_chn->handle);
01231 ss_tape_close(log_chn->handle);
01232 } else if (log_chn->type == LOG_TYPE_FTP) {
01233 ftp_close(log_chn->ftp_con);
01234 ftp_bye(log_chn->ftp_con);
01235 } else {
01236 if (log_chn->gzfile) {
01237 #ifdef HAVE_ZLIB
01238 z_streamp s;
01239
01240 s = (z_streamp) log_chn->gzfile;
01241 written = s->total_out;
01242 gzflush(log_chn->gzfile, Z_FULL_FLUSH);
01243 written = s->total_out - written;
01244 gzclose(log_chn->gzfile);
01245 log_chn->statistics.bytes_written += written;
01246 log_chn->statistics.bytes_written_total += written;
01247 log_chn->gzfile = NULL;
01248 #else
01249 assert(!"this cannot happen! support for ZLIB not compiled in");
01250 #endif
01251 }
01252 #ifdef OS_WINNT
01253 CloseHandle((HANDLE) log_chn->handle);
01254 #else
01255 close(log_chn->handle);
01256 #endif
01257 log_chn->handle = 0;
01258 }
01259
01260 free(((MIDAS_INFO *) log_chn->format_info)->buffer);
01261 free(log_chn->format_info);
01262
01263 return SS_SUCCESS;
01264 }
01265
01266
01267
01268 typedef struct {
01269 short int event_id;
01270 WORD format;
01271 HNDLE hDefKey;
01272 } EVENT_DEF;
01273
01274 EVENT_DEF *db_get_event_definition(short int event_id)
01275 {
01276 INT i, index, status, size;
01277 char str[80];
01278 HNDLE hKey, hKeyRoot;
01279 WORD id;
01280
01281 #define EVENT_DEF_CACHE_SIZE 30
01282 static EVENT_DEF *event_def = NULL;
01283
01284
01285 if (event_def == NULL)
01286 event_def = (EVENT_DEF *) calloc(EVENT_DEF_CACHE_SIZE, sizeof(EVENT_DEF));
01287
01288
01289 for (i = 0; event_def[i].event_id; i++)
01290 if (event_def[i].event_id == event_id)
01291 return &event_def[i];
01292
01293
01294 for (index = 0; index < EVENT_DEF_CACHE_SIZE; index++)
01295 if (event_def[index].event_id == 0)
01296 break;
01297
01298 if (index == EVENT_DEF_CACHE_SIZE) {
01299 cm_msg(MERROR, "db_get_event_definition", "too many event definitions");
01300 return NULL;
01301 }
01302
01303
01304 if (event_id < 0) {
01305 event_def[index].event_id = event_id;
01306 event_def[index].format = FORMAT_ASCII;
01307 event_def[index].hDefKey = 0;
01308 return &event_def[index];
01309 }
01310
01311 status = db_find_key(hDB, 0, "/equipment", &hKeyRoot);
01312 if (status != DB_SUCCESS) {
01313 cm_msg(MERROR, "db_get_event_definition", "cannot find /equipment entry in ODB");
01314 return NULL;
01315 }
01316
01317 for (i = 0;; i++) {
01318
01319 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
01320 if (status == DB_NO_MORE_SUBKEYS) {
01321 sprintf(str, "Cannot find event id %d under /equipment", event_id);
01322 cm_msg(MERROR, "db_get_event_definition", str);
01323 return NULL;
01324 }
01325
01326 size = sizeof(id);
01327 status = db_get_value(hDB, hKey, "Common/Event ID", &id, &size, TID_WORD, TRUE);
01328 if (status != DB_SUCCESS)
01329 continue;
01330
01331 if (id == event_id) {
01332
01333 event_def[index].event_id = id;
01334
01335 size = sizeof(str);
01336 str[0] = 0;
01337 db_get_value(hDB, hKey, "Common/Format", str, &size, TID_STRING, TRUE);
01338
01339 if (equal_ustring(str, "Fixed"))
01340 event_def[index].format = FORMAT_FIXED;
01341 else if (equal_ustring(str, "ASCII"))
01342 event_def[index].format = FORMAT_ASCII;
01343 else if (equal_ustring(str, "MIDAS"))
01344 event_def[index].format = FORMAT_MIDAS;
01345 else if (equal_ustring(str, "YBOS"))
01346 event_def[index].format = FORMAT_YBOS;
01347 else if (equal_ustring(str, "DUMP"))
01348 event_def[index].format = FORMAT_DUMP;
01349 else {
01350 cm_msg(MERROR, "db_get_event_definition", "unknown data format");
01351 event_def[index].event_id = 0;
01352 return NULL;
01353 }
01354
01355 db_find_key(hDB, hKey, "Variables", &event_def[index].hDefKey);
01356 return &event_def[index];
01357 }
01358 }
01359 }
01360
01361
01362
01363 #define STR_INC(p,base) { p+=strlen(p); \
01364 if (p > base+sizeof(base)) \
01365 cm_msg(MERROR, "STR_INC", "ASCII buffer too small"); }
01366
01367
01368 INT dump_write(LOG_CHN * log_chn, EVENT_HEADER * pevent, INT evt_size)
01369 {
01370 INT status, size, i, j;
01371 EVENT_DEF *event_def;
01372 BANK_HEADER *pbh;
01373 BANK *pbk;
01374 BANK32 *pbk32;
01375 void *pdata;
01376 char buffer[100000], *pbuf, name[5], type_name[10];
01377 HNDLE hKey;
01378 KEY key;
01379 DWORD bkname;
01380 WORD bktype;
01381
01382 event_def = db_get_event_definition(pevent->event_id);
01383 if (event_def == NULL)
01384 return SS_SUCCESS;
01385
01386
01387 pbuf = buffer;
01388 name[4] = 0;
01389
01390 if (pevent->event_id == EVENTID_BOR)
01391 sprintf(pbuf, "%%ID BOR NR %d\n", pevent->serial_number);
01392 else if (pevent->event_id == EVENTID_EOR)
01393 sprintf(pbuf, "%%ID EOR NR %d\n", pevent->serial_number);
01394 else
01395 sprintf(pbuf, "%%ID %d TR %d NR %d\n", pevent->event_id, pevent->trigger_mask, pevent->serial_number);
01396 STR_INC(pbuf, buffer);
01397
01398
01399 if (event_def->format == FORMAT_MIDAS) {
01400 LRS1882_DATA *lrs1882;
01401 LRS1877_DATA *lrs1877;
01402 LRS1877_HEADER *lrs1877_header;
01403
01404 pbh = (BANK_HEADER *) (pevent + 1);
01405 bk_swap(pbh, FALSE);
01406
01407 pbk = NULL;
01408 pbk32 = NULL;
01409 do {
01410
01411 if (bk_is32(pbh)) {
01412 size = bk_iterate32(pbh, &pbk32, &pdata);
01413 if (pbk32 == NULL)
01414 break;
01415 bkname = *((DWORD *) pbk32->name);
01416 bktype = (WORD) pbk32->type;
01417 } else {
01418 size = bk_iterate(pbh, &pbk, &pdata);
01419 if (pbk == NULL)
01420 break;
01421 bkname = *((DWORD *) pbk->name);
01422 bktype = (WORD) pbk->type;
01423 }
01424
01425 if (rpc_tid_size(bktype & 0xFF))
01426 size /= rpc_tid_size(bktype & 0xFF);
01427
01428 lrs1882 = (LRS1882_DATA *) pdata;
01429 lrs1877 = (LRS1877_DATA *) pdata;
01430 lrs1877_header = (LRS1877_HEADER *) pdata;
01431
01432
01433 *((DWORD *) name) = bkname;
01434
01435 if ((bktype & 0xFF00) == 0)
01436 strcpy(type_name, rpc_tid_name(bktype & 0xFF));
01437 else if ((bktype & 0xFF00) == TID_LRS1882)
01438 strcpy(type_name, "LRS1882");
01439 else if ((bktype & 0xFF00) == TID_LRS1877)
01440 strcpy(type_name, "LRS1877");
01441 else if ((bktype & 0xFF00) == TID_PCOS3)
01442 strcpy(type_name, "PCOS3");
01443 else
01444 strcpy(type_name, "unknown");
01445
01446 sprintf(pbuf, "BK %s TP %s SZ %d\n", name, type_name, size);
01447 STR_INC(pbuf, buffer);
01448
01449
01450 for (i = 0; i < size; i++) {
01451 if ((bktype & 0xFF00) == 0)
01452 db_sprintf(pbuf, pdata, size, i, bktype & 0xFF);
01453
01454 else if ((bktype & 0xFF00) == TID_LRS1882)
01455 sprintf(pbuf, "GA %d CH %02d DA %d", lrs1882[i].geo_addr, lrs1882[i].channel, lrs1882[i].data);
01456
01457 else if ((bktype & 0xFF00) == TID_LRS1877) {
01458 if (i == 0)
01459 sprintf(pbuf, "GA %d BF %d CN %d",
01460 lrs1877_header[i].geo_addr, lrs1877_header[i].buffer, lrs1877_header[i].count);
01461 else
01462 sprintf(pbuf, "GA %d CH %02d ED %d DA %1.1lf",
01463 lrs1877[i].geo_addr, lrs1877[i].channel, lrs1877[i].edge, lrs1877[i].data * 0.5);
01464 }
01465
01466 else if ((bktype & 0xFF00) == TID_PCOS3)
01467 *pbuf = '\0';
01468 else
01469 db_sprintf(pbuf, pdata, size, i, bktype & 0xFF);
01470
01471 strcat(pbuf, "\n");
01472 STR_INC(pbuf, buffer);
01473 }
01474
01475 } while (1);
01476 }
01477
01478
01479 if (event_def->format == FORMAT_FIXED) {
01480 if (event_def->hDefKey == 0)
01481 cm_msg(MERROR, "dump_write", "cannot find event definition");
01482 else {
01483 pdata = (char *) (pevent + 1);
01484 for (i = 0;; i++) {
01485 status = db_enum_key(hDB, event_def->hDefKey, i, &hKey);
01486 if (status == DB_NO_MORE_SUBKEYS)
01487 break;
01488
01489 db_get_key(hDB, hKey, &key);
01490 sprintf(pbuf, "%s\n", key.name);
01491 STR_INC(pbuf, buffer);
01492
01493
01494 pdata = (void *) VALIGN(pdata, MIN(ss_get_struct_align(), key.item_size));
01495
01496 for (j = 0; j < key.num_values; j++) {
01497 db_sprintf(pbuf, pdata, key.item_size, j, key.type);
01498 strcat(pbuf, "\n");
01499 STR_INC(pbuf, buffer);
01500 }
01501
01502
01503 pdata = ((char *) pdata) + key.item_size * key.num_values;
01504 }
01505 }
01506 }
01507
01508
01509 if (event_def->format == FORMAT_ASCII) {
01510
01511 size = strlen(buffer);
01512 if (log_chn->type == LOG_TYPE_TAPE)
01513 status = ss_tape_write(log_chn->handle, buffer, size);
01514 else
01515 status = write(log_chn->handle, buffer, size) == size ? SS_SUCCESS : SS_FILE_ERROR;
01516
01517
01518 size = strlen((char *) (pevent + 1));
01519 if (log_chn->type == LOG_TYPE_TAPE)
01520 status = ss_tape_write(log_chn->handle, (char *) (pevent + 1), size);
01521 else if (log_chn->type == LOG_TYPE_FTP)
01522 status = ftp_send((log_chn->ftp_con)->data, buffer, size) == size ?
01523 SS_SUCCESS : SS_FILE_ERROR;
01524 else
01525 status = write(log_chn->handle, (char *) (pevent + 1), size) == size ? SS_SUCCESS : SS_FILE_ERROR;
01526 } else {
01527
01528
01529
01530 strcat(pbuf, "\n");
01531 size = strlen(buffer);
01532
01533
01534 if (log_chn->type == LOG_TYPE_TAPE)
01535 status = ss_tape_write(log_chn->handle, buffer, size);
01536 else if (log_chn->type == LOG_TYPE_FTP)
01537 status = ftp_send((log_chn->ftp_con)->data, buffer, size) == size ?
01538 SS_SUCCESS : SS_FILE_ERROR;
01539 else
01540 status = write(log_chn->handle, buffer, size) == size ? SS_SUCCESS : SS_FILE_ERROR;
01541 }
01542
01543
01544 log_chn->statistics.events_written++;
01545 log_chn->statistics.bytes_written += size;
01546 log_chn->statistics.bytes_written_total += size;
01547
01548 return status;
01549 }
01550
01551
01552
01553 INT dump_log_open(LOG_CHN * log_chn, INT run_number)
01554 {
01555 INT status;
01556
01557
01558 if (log_chn->type == LOG_TYPE_TAPE) {
01559 status = tape_open(log_chn->path, &log_chn->handle);
01560 if (status != SS_SUCCESS) {
01561 log_chn->handle = 0;
01562 return status;
01563 }
01564 } else if (log_chn->type == LOG_TYPE_FTP) {
01565 status = ftp_open(log_chn->path, &log_chn->ftp_con);
01566 if (status != SS_SUCCESS) {
01567 log_chn->handle = 0;
01568 return status;
01569 } else
01570 log_chn->handle = 1;
01571 } else {
01572 log_chn->handle = open(log_chn->path, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644);
01573
01574 if (log_chn->handle < 0) {
01575 log_chn->handle = 0;
01576 return SS_FILE_ERROR;
01577 }
01578 }
01579
01580
01581 if (log_chn->settings.odb_dump)
01582 log_odb_dump(log_chn, EVENTID_BOR, run_number);
01583
01584 return SS_SUCCESS;
01585 }
01586
01587
01588
01589 INT dump_log_close(LOG_CHN * log_chn, INT run_number)
01590 {
01591
01592 if (log_chn->settings.odb_dump)
01593 log_odb_dump(log_chn, EVENTID_EOR, run_number);
01594
01595
01596 if (log_chn->type == LOG_TYPE_TAPE) {
01597
01598 ss_tape_write_eof(log_chn->handle);
01599 ss_tape_close(log_chn->handle);
01600 } else if (log_chn->type == LOG_TYPE_FTP) {
01601 ftp_close(log_chn->ftp_con);
01602 ftp_bye(log_chn->ftp_con);
01603 } else
01604 close(log_chn->handle);
01605
01606 return SS_SUCCESS;
01607 }
01608
01609
01610
01611 INT ascii_write(LOG_CHN * log_chn, EVENT_HEADER * pevent, INT evt_size)
01612 {
01613 INT status, size, i, j;
01614 EVENT_DEF *event_def;
01615 BANK_HEADER *pbh;
01616 BANK *pbk;
01617 BANK32 *pbk32;
01618 void *pdata;
01619 char buffer[10000], name[5], type_name[10];
01620 char *ph, header_line[10000];
01621 char *pd, data_line[10000];
01622 HNDLE hKey;
01623 KEY key;
01624 static short int last_event_id = -1;
01625 DWORD bkname;
01626 WORD bktype;
01627
01628 if (pevent->serial_number == 0)
01629 last_event_id = -1;
01630
01631 event_def = db_get_event_definition(pevent->event_id);
01632 if (event_def == NULL)
01633 return SS_SUCCESS;
01634
01635 name[4] = 0;
01636 header_line[0] = 0;
01637 data_line[0] = 0;
01638 ph = header_line;
01639 pd = data_line;
01640
01641
01642 if (event_def->format == FORMAT_MIDAS) {
01643 LRS1882_DATA *lrs1882;
01644 LRS1877_DATA *lrs1877;
01645 LRS1877_HEADER *lrs1877_header;
01646
01647 pbh = (BANK_HEADER *) (pevent + 1);
01648 bk_swap(pbh, FALSE);
01649
01650 pbk = NULL;
01651 pbk32 = NULL;
01652 do {
01653
01654 if (bk_is32(pbh)) {
01655 size = bk_iterate32(pbh, &pbk32, &pdata);
01656 if (pbk32 == NULL)
01657 break;
01658 bkname = *((DWORD *) pbk32->name);
01659 bktype = (WORD) pbk32->type;
01660 } else {
01661 size = bk_iterate(pbh, &pbk, &pdata);
01662 if (pbk == NULL)
01663 break;
01664 bkname = *((DWORD *) pbk->name);
01665 bktype = (WORD) pbk->type;
01666 }
01667
01668 if (rpc_tid_size(bktype & 0xFF))
01669 size /= rpc_tid_size(bktype & 0xFF);
01670
01671 lrs1882 = (LRS1882_DATA *) pdata;
01672 lrs1877 = (LRS1877_DATA *) pdata;
01673 lrs1877_header = (LRS1877_HEADER *) pdata;
01674
01675
01676 *((DWORD *) name) = bkname;
01677
01678 if ((bktype & 0xFF00) == 0)
01679 strcpy(type_name, rpc_tid_name(bktype & 0xFF));
01680 else if ((bktype & 0xFF00) == TID_LRS1882)
01681 strcpy(type_name, "LRS1882");
01682 else if ((bktype & 0xFF00) == TID_LRS1877)
01683 strcpy(type_name, "LRS1877");
01684 else if ((bktype & 0xFF00) == TID_PCOS3)
01685 strcpy(type_name, "PCOS3");
01686 else
01687 strcpy(type_name, "unknown");
01688
01689 sprintf(ph, "%s[%d]\t", name, size);
01690 STR_INC(ph, header_line);
01691
01692
01693 for (i = 0; i < size; i++) {
01694 db_sprintf(pd, pdata, size, i, bktype & 0xFF);
01695 strcat(pd, "\t");
01696 STR_INC(pd, data_line);
01697 }
01698
01699 } while (1);
01700 }
01701
01702
01703 if (event_def->format == FORMAT_FIXED) {
01704 if (event_def->hDefKey == 0)
01705 cm_msg(MERROR, "ascii_write", "cannot find event definition");
01706 else {
01707 pdata = (char *) (pevent + 1);
01708 for (i = 0;; i++) {
01709 status = db_enum_key(hDB, event_def->hDefKey, i, &hKey);
01710 if (status == DB_NO_MORE_SUBKEYS)
01711 break;
01712
01713 db_get_key(hDB, hKey, &key);
01714
01715
01716 pdata = (void *) VALIGN(pdata, MIN(ss_get_struct_align(), key.item_size));
01717
01718 for (j = 0; j < key.num_values; j++) {
01719 if (pevent->event_id != last_event_id) {
01720 if (key.num_values == 1)
01721 sprintf(ph, "%s\t", key.name);
01722 else
01723 sprintf(ph, "%s%d\t", key.name, j);
01724
01725 STR_INC(ph, header_line);
01726 }
01727
01728 db_sprintf(pd, pdata, key.item_size, j, key.type);
01729 strcat(pd, "\t");
01730 STR_INC(pd, data_line);
01731 }
01732
01733
01734 pdata = ((char *) pdata) + key.item_size * key.num_values;
01735 }
01736 }
01737 }
01738
01739 if (*(pd - 1) == '\t')
01740 *(pd - 1) = '\n';
01741
01742 if (last_event_id != pevent->event_id) {
01743 if (*(ph - 1) == '\t')
01744 *(ph - 1) = '\n';
01745 last_event_id = pevent->event_id;
01746 strcpy(buffer, header_line);
01747 strcat(buffer, data_line);
01748 } else
01749 strcpy(buffer, data_line);
01750
01751
01752 size = strlen(buffer);
01753
01754 if (log_chn->type == LOG_TYPE_TAPE)
01755 status = ss_tape_write(log_chn->handle, buffer, size);
01756 else if (log_chn->type == LOG_TYPE_FTP)
01757 status = ftp_send(log_chn->ftp_con->data, buffer, size) == size ?
01758 SS_SUCCESS : SS_FILE_ERROR;
01759 else
01760 status = write(log_chn->handle, buffer, size) == size ? SS_SUCCESS : SS_FILE_ERROR;
01761
01762
01763 log_chn->statistics.events_written++;
01764 log_chn->statistics.bytes_written += size;
01765 log_chn->statistics.bytes_written_total += size;
01766
01767 return status;
01768 }
01769
01770
01771
01772 INT ascii_log_open(LOG_CHN * log_chn, INT run_number)
01773 {
01774 INT status;
01775 EVENT_HEADER event;
01776
01777
01778 if (log_chn->type == LOG_TYPE_TAPE) {
01779 status = tape_open(log_chn->path, &log_chn->handle);
01780 if (status != SS_SUCCESS) {
01781 log_chn->handle = 0;
01782 return status;
01783 }
01784 } else if (log_chn->type == LOG_TYPE_FTP) {
01785 status = ftp_open(log_chn->path, &log_chn->ftp_con);
01786 if (status != SS_SUCCESS) {
01787 log_chn->handle = 0;
01788 return status;
01789 } else
01790 log_chn->handle = 1;
01791 } else {
01792 log_chn->handle = open(log_chn->path, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644);
01793
01794 if (log_chn->handle < 0) {
01795 log_chn->handle = 0;
01796 return SS_FILE_ERROR;
01797 }
01798 }
01799
01800
01801 if (log_chn->settings.odb_dump) {
01802 event.event_id = EVENTID_BOR;
01803 event.data_size = 0;
01804 event.serial_number = run_number;
01805
01806 ascii_write(log_chn, &event, sizeof(EVENT_HEADER));
01807 }
01808
01809 return SS_SUCCESS;
01810 }
01811
01812
01813
01814 INT ascii_log_close(LOG_CHN * log_chn, INT run_number)
01815 {
01816
01817 if (log_chn->type == LOG_TYPE_TAPE) {
01818
01819 ss_tape_write_eof(log_chn->handle);
01820 ss_tape_close(log_chn->handle);
01821 } else if (log_chn->type == LOG_TYPE_FTP) {
01822 ftp_close(log_chn->ftp_con);
01823 ftp_bye(log_chn->ftp_con);
01824 } else
01825 close(log_chn->handle);
01826
01827 return SS_SUCCESS;
01828 }
01829
01830
01831
01832 #ifdef HAVE_ROOT
01833
01834 #define MAX_BANKS 100
01835
01836 typedef struct {
01837 int event_id;
01838 TTree *tree;
01839 int n_branch;
01840 DWORD branch_name[MAX_BANKS];
01841 int branch_filled[MAX_BANKS];
01842 int branch_len[MAX_BANKS];
01843 TBranch *branch[MAX_BANKS];
01844 } EVENT_TREE;
01845
01846 typedef struct {
01847 TFile *f;
01848 int n_tree;
01849 EVENT_TREE *event_tree;
01850 } TREE_STRUCT;
01851
01852
01853
01854 INT root_book_trees(TREE_STRUCT * tree_struct)
01855 {
01856 int index, size, status;
01857 WORD id;
01858 char str[1000];
01859 HNDLE hKeyRoot, hKeyEq;
01860 KEY eqkey;
01861 EVENT_TREE *et;
01862
01863 status = db_find_key(hDB, 0, "/Equipment", &hKeyRoot);
01864 if (status != DB_SUCCESS) {
01865 cm_msg(MERROR, "root_book_trees", "cannot find \"/Equipment\" entry in ODB");
01866 return 0;
01867 }
01868
01869 tree_struct->n_tree = 0;
01870
01871 for (index = 0;; index++) {
01872
01873 status = db_enum_key(hDB, hKeyRoot, index, &hKeyEq);
01874 if (status == DB_NO_MORE_SUBKEYS)
01875 return 1;
01876
01877 db_get_key(hDB, hKeyEq, &eqkey);
01878
01879
01880 tree_struct->n_tree++;
01881 if (tree_struct->n_tree == 1)
01882 tree_struct->event_tree = (EVENT_TREE *) malloc(sizeof(EVENT_TREE));
01883 else
01884 tree_struct->event_tree =
01885 (EVENT_TREE *) realloc(tree_struct->event_tree, sizeof(EVENT_TREE) * tree_struct->n_tree);
01886
01887 et = tree_struct->event_tree + (tree_struct->n_tree - 1);
01888
01889 size = sizeof(id);
01890 status = db_get_value(hDB, hKeyEq, "Common/Event ID", &id, &size, TID_WORD, TRUE);
01891 if (status != DB_SUCCESS)
01892 continue;
01893
01894 et->event_id = id;
01895 et->n_branch = 0;
01896
01897
01898 size = sizeof(str);
01899 str[0] = 0;
01900 db_get_value(hDB, hKeyEq, "Common/Format", str, &size, TID_STRING, TRUE);
01901
01902 if (!equal_ustring(str, "MIDAS")) {
01903 cm_msg(MERROR, "root_book_events",
01904 "ROOT output only for MIDAS events, but %s in %s format", eqkey.name, str);
01905 return 0;
01906 }
01907
01908
01909 sprintf(str, "Event \"%s\", ID %d", eqkey.name, id);
01910 et->tree = new TTree(eqkey.name, str);
01911 }
01912
01913 return 1;
01914 }
01915
01916
01917
01918 INT root_book_bank(EVENT_TREE * et, HNDLE hKeyDef, int event_id, char *bank_name)
01919 {
01920 int i, status;
01921 char str[1000];
01922 HNDLE hKeyVar, hKeySubVar;
01923 KEY varkey, subvarkey;
01924
01925
01926 status = db_find_key(hDB, hKeyDef, bank_name, &hKeyVar);
01927 if (status != DB_SUCCESS) {
01928 cm_msg(MERROR, "root_book_bank", "received unknown bank \"%s\" in event #%d", bank_name, event_id);
01929 return 0;
01930 }
01931
01932 if (et->n_branch + 1 == MAX_BANKS) {
01933 cm_msg(MERROR, "root_book_bank", "max number of banks (%d) exceeded in event #%d", MAX_BANKS, event_id);
01934 return 0;
01935 }
01936
01937 db_get_key(hDB, hKeyVar, &varkey);
01938
01939 if (varkey.type != TID_KEY) {
01940
01941
01942 sprintf(str, "n%s/I:%s[n%s]/", varkey.name, varkey.name, varkey.name);
01943
01944 switch (varkey.type) {
01945 case TID_BYTE:
01946 case TID_CHAR:
01947 strcat(str, "b");
01948 break;
01949 case TID_SBYTE:
01950 strcat(str, "B");
01951 break;
01952 case TID_WORD:
01953 strcat(str, "s");
01954 break;
01955 case TID_SHORT:
01956 strcat(str, "S");
01957 break;
01958 case TID_DWORD:
01959 strcat(str, "i");
01960 break;
01961 case TID_INT:
01962 strcat(str, "I");
01963 break;
01964 case TID_BOOL:
01965 strcat(str, "I");
01966 break;
01967 case TID_FLOAT:
01968 strcat(str, "F");
01969 break;
01970 case TID_DOUBLE:
01971 strcat(str, "D");
01972 break;
01973 case TID_STRING:
01974 strcat(str, "C");
01975 break;
01976 }
01977
01978 et->branch[et->n_branch] = et->tree->Branch(bank_name, NULL, str);
01979 et->branch_name[et->n_branch] = *(DWORD *) bank_name;
01980 et->n_branch++;
01981 } else {
01982
01983 str[0] = 0;
01984
01985 for (i = 0;; i++) {
01986
01987 status = db_enum_key(hDB, hKeyVar, i, &hKeySubVar);
01988 if (status == DB_NO_MORE_SUBKEYS)
01989 break;
01990
01991 db_get_key(hDB, hKeySubVar, &subvarkey);
01992
01993 if (i != 0)
01994 strcat(str, ":");
01995 strcat(str, subvarkey.name);
01996 strcat(str, "/");
01997 switch (subvarkey.type) {
01998 case TID_BYTE:
01999 case TID_CHAR:
02000 strcat(str, "b");
02001 break;
02002 case TID_SBYTE:
02003 strcat(str, "B");
02004 break;
02005 case TID_WORD:
02006 strcat(str, "s");
02007 break;
02008 case TID_SHORT:
02009 strcat(str, "S");
02010 break;
02011 case TID_DWORD:
02012 strcat(str, "i");
02013 break;
02014 case TID_INT:
02015 strcat(str, "I");
02016 break;
02017 case TID_BOOL:
02018 strcat(str, "I");
02019 break;
02020 case TID_FLOAT:
02021 strcat(str, "F");
02022 break;
02023 case TID_DOUBLE:
02024 strcat(str, "D");
02025 break;
02026 case TID_STRING:
02027 strcat(str, "C");
02028 break;
02029 }
02030 }
02031
02032 et->branch[et->n_branch] = et->tree->Branch(bank_name, NULL, str);
02033 et->branch_name[et->n_branch] = *(DWORD *) bank_name;
02034 et->n_branch++;
02035 }
02036
02037 return 1;
02038 }
02039
02040
02041
02042 INT root_write(LOG_CHN * log_chn, EVENT_HEADER * pevent, INT evt_size)
02043 {
02044 INT size, i;
02045 char bank_name[32];
02046 EVENT_DEF *event_def;
02047 BANK_HEADER *pbh;
02048 void *pdata;
02049 static short int last_event_id = -1;
02050 TREE_STRUCT *ts;
02051 EVENT_TREE *et;
02052 BANK *pbk;
02053 BANK32 *pbk32;
02054 DWORD bklen;
02055 DWORD bkname;
02056 WORD bktype;
02057 TBranch *branch;
02058
02059 if (pevent->serial_number == 0)
02060 last_event_id = -1;
02061
02062 event_def = db_get_event_definition(pevent->event_id);
02063 if (event_def == NULL) {
02064 cm_msg(MERROR, "root_write", "Definition for event #%d not found under /Equipment", pevent->event_id);
02065 return SS_INVALID_FORMAT;
02066 }
02067
02068 ts = (TREE_STRUCT *) log_chn->format_info;
02069
02070 size = (INT) ts->f->GetBytesWritten();
02071
02072
02073
02074 if (event_def->format == FORMAT_MIDAS) {
02075 pbh = (BANK_HEADER *) (pevent + 1);
02076 bk_swap(pbh, FALSE);
02077
02078
02079 for (i = 0; i < ts->n_tree; i++)
02080 if (ts->event_tree[i].event_id == pevent->event_id)
02081 break;
02082
02083 if (i == ts->n_tree) {
02084 cm_msg(MERROR, "root_write", "Event #%d not booked by root_book_events()", pevent->event_id);
02085 return SS_INVALID_FORMAT;
02086 }
02087
02088 et = ts->event_tree + i;
02089
02090
02091 for (i = 0; i < et->n_branch; i++)
02092 et->branch_filled[i] = FALSE;
02093
02094
02095 pbk = NULL;
02096 pbk32 = NULL;
02097 do {
02098
02099 if (bk_is32(pbh)) {
02100 bklen = bk_iterate32(pbh, &pbk32, &pdata);
02101 if (pbk32 == NULL)
02102 break;
02103 bkname = *((DWORD *) pbk32->name);
02104 bktype = (WORD) pbk32->type;
02105 } else {
02106 bklen = bk_iterate(pbh, &pbk, &pdata);
02107 if (pbk == NULL)
02108 break;
02109 bkname = *((DWORD *) pbk->name);
02110 bktype = (WORD) pbk->type;
02111 }
02112
02113 if (rpc_tid_size(bktype & 0xFF))
02114 bklen /= rpc_tid_size(bktype & 0xFF);
02115
02116 *((DWORD *) bank_name) = bkname;
02117 bank_name[4] = 0;
02118
02119 for (i = 0; i < et->n_branch; i++)
02120 if (et->branch_name[i] == bkname)
02121 break;
02122
02123 if (i == et->n_branch)
02124 root_book_bank(et, event_def->hDefKey, pevent->event_id, bank_name);
02125
02126 branch = et->branch[i];
02127 et->branch_filled[i] = TRUE;
02128 et->branch_len[i] = bklen;
02129
02130 if (bktype != TID_STRUCT) {
02131 TIter next(branch->GetListOfLeaves());
02132 TLeaf *leaf = (TLeaf *) next();
02133
02134
02135 leaf->SetAddress(&et->branch_len[i]);
02136
02137 leaf = (TLeaf *) next();
02138 leaf->SetAddress(pdata);
02139 } else {
02140
02141 branch->SetAddress(pdata);
02142 }
02143
02144 } while (1);
02145
02146
02147 for (i = 0; i < et->n_branch; i++)
02148 if (!et->branch_filled[i])
02149 cm_msg(MERROR, "root_write", "Bank %s booked but not received, tree cannot be filled", bank_name);
02150
02151
02152 et->tree->Fill();
02153 }
02154
02155 size = (INT) ts->f->GetBytesWritten() - size;
02156
02157
02158 log_chn->statistics.events_written++;
02159 log_chn->statistics.bytes_written += size;
02160 log_chn->statistics.bytes_written_total += size;
02161
02162 return SS_SUCCESS;
02163 }
02164
02165
02166
02167 INT root_log_open(LOG_CHN * log_chn, INT run_number)
02168 {
02169 INT size, level;
02170 char str[256], name[256];
02171 EVENT_HEADER event;
02172 TREE_STRUCT *tree_struct;
02173
02174
02175 if (log_chn->type == LOG_TYPE_TAPE || log_chn->type == LOG_TYPE_FTP) {
02176 cm_msg(MERROR, "root_log_open", "ROOT files can only reside on disk");
02177 log_chn->handle = 0;
02178 return -1;
02179 } else {
02180
02181 if (strstr(log_chn->path, "null") == NULL) {
02182 log_chn->handle = open(log_chn->path, O_RDONLY);
02183 if (log_chn->handle > 0) {
02184
02185 if (lseek(log_chn->handle, 0, SEEK_END) > 0) {
02186 close(log_chn->handle);
02187 log_chn->handle = 0;
02188 return SS_FILE_EXISTS;
02189 }
02190 }
02191 }
02192
02193 name[0] = 0;
02194 size = sizeof(name);
02195 db_get_value(hDB, 0, "/Experiment/Name", name, &size, TID_STRING, TRUE);
02196
02197 sprintf(str, "MIDAS exp. %s, run #%d", name, run_number);
02198
02199 TFile *f = new TFile(log_chn->path, "create", str, 1);
02200 if (!f->IsOpen()) {
02201 delete f;
02202 log_chn->handle = 0;
02203 return SS_FILE_ERROR;
02204 }
02205 log_chn->handle = 1;
02206
02207
02208 level = 0;
02209 size = sizeof(level);
02210 db_get_value(hDB, log_chn->settings_hkey, "Compression", &level, &size, TID_INT, FALSE);
02211 f->SetCompressionLevel(level);
02212
02213
02214 tree_struct = (TREE_STRUCT *) malloc(sizeof(TREE_STRUCT));
02215 tree_struct->f = f;
02216
02217
02218 root_book_trees(tree_struct);
02219
02220
02221 log_chn->format_info = (void **) tree_struct;
02222 }
02223
02224
02225 if (log_chn->settings.odb_dump) {
02226 event.event_id = EVENTID_BOR;
02227 event.data_size = 0;
02228 event.serial_number = run_number;
02229
02230
02231 }
02232
02233 return SS_SUCCESS;
02234 }
02235
02236
02237
02238 INT root_log_close(LOG_CHN * log_chn, INT run_number)
02239 {
02240 TREE_STRUCT *ts;
02241
02242 ts = (TREE_STRUCT *) log_chn->format_info;
02243
02244
02245 ts->f->Write();
02246 ts->f->Close();
02247 delete ts->f;
02248
02249
02250 free(ts->event_tree);
02251 free(ts);
02252
02253 log_chn->format_info = NULL;
02254
02255 return SS_SUCCESS;
02256 }
02257
02258 #endif
02259
02260
02261
02262 INT log_open(LOG_CHN * log_chn, INT run_number)
02263 {
02264 INT status;
02265
02266 if (equal_ustring(log_chn->settings.format, "YBOS")) {
02267 assert(!"YBOS not supported anymore");
02268 } else if (equal_ustring(log_chn->settings.format, "ASCII")) {
02269 log_chn->format = FORMAT_ASCII;
02270 status = ascii_log_open(log_chn, run_number);
02271 } else if (equal_ustring(log_chn->settings.format, "DUMP")) {
02272 log_chn->format = FORMAT_DUMP;
02273 status = dump_log_open(log_chn, run_number);
02274 } else if (equal_ustring(log_chn->settings.format, "ROOT")) {
02275 #ifdef HAVE_ROOT
02276 log_chn->format = FORMAT_ROOT;
02277 status = root_log_open(log_chn, run_number);
02278 #else
02279 return SS_NO_ROOT;
02280 #endif
02281 } else if (equal_ustring(log_chn->settings.format, "MIDAS")) {
02282 log_chn->format = FORMAT_MIDAS;
02283 status = midas_log_open(log_chn, run_number);
02284 } else
02285 return SS_INVALID_FORMAT;
02286
02287 return status;
02288 }
02289
02290
02291
02292 INT log_close(LOG_CHN * log_chn, INT run_number)
02293 {
02294 if (log_chn->format == FORMAT_YBOS)
02295 assert(!"YBOS not supported anymore");
02296
02297 if (log_chn->format == FORMAT_ASCII)
02298 ascii_log_close(log_chn, run_number);
02299
02300 if (log_chn->format == FORMAT_DUMP)
02301 dump_log_close(log_chn, run_number);
02302
02303 #ifdef HAVE_ROOT
02304 if (log_chn->format == FORMAT_ROOT)
02305 root_log_close(log_chn, run_number);
02306 #endif
02307
02308 if (log_chn->format == FORMAT_MIDAS)
02309 midas_log_close(log_chn, run_number);
02310
02311 log_chn->statistics.files_written += 1;
02312 log_chn->handle = 0;
02313 log_chn->ftp_con = NULL;
02314
02315 return SS_SUCCESS;
02316 }
02317
02318
02319
02320 int stop_the_run(int restart)
02321 {
02322 int status;
02323 char errstr[256];
02324 int size, flag, trans_flag;
02325
02326 if (restart) {
02327 size = sizeof(BOOL);
02328 flag = FALSE;
02329 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
02330
02331 if (flag) {
02332 start_requested = TRUE;
02333 auto_restart = 0;
02334 }
02335 }
02336
02337 stop_requested = TRUE;
02338
02339 size = sizeof(BOOL);
02340 flag = FALSE;
02341 db_get_value(hDB, 0, "/Logger/Async transitions", &flag, &size, TID_BOOL, TRUE);
02342
02343 if (flag)
02344 trans_flag = ASYNC;
02345 else
02346 trans_flag = DETACH;
02347
02348 status = cm_transition(TR_STOP, 0, errstr, sizeof(errstr), trans_flag, verbose);
02349 if (status != CM_SUCCESS) {
02350 cm_msg(MERROR, "log_write", "cannot stop the run: %s", errstr);
02351 return status;
02352 }
02353
02354 return status;
02355 }
02356
02357 int start_the_run()
02358 {
02359 int status, size, state, run_number;
02360 int flag, trans_flag;
02361 char errstr[256];
02362
02363 start_requested = FALSE;
02364 auto_restart = 0;
02365
02366
02367 size = sizeof(BOOL);
02368 flag = FALSE;
02369 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
02370
02371 if (!flag) {
02372 cm_msg(MINFO, "main", "Run auto restart canceled");
02373 return SUCCESS;
02374 }
02375
02376
02377 size = sizeof(state);
02378 status = db_get_value(hDB, 0, "Runinfo/State", &state, &size, TID_INT, TRUE);
02379 if (status != DB_SUCCESS) {
02380 cm_msg(MERROR, "main", "cannot get Runinfo/State in database");
02381 return status;
02382 }
02383
02384 if (state != STATE_STOPPED)
02385 return SUCCESS;
02386
02387 size = sizeof(run_number);
02388 status = db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
02389 assert(status == SUCCESS);
02390
02391 if (run_number <= 0) {
02392 cm_msg(MERROR, "main", "aborting on attempt to use invalid run number %d", run_number);
02393 abort();
02394 }
02395
02396 size = sizeof(BOOL);
02397 flag = FALSE;
02398 db_get_value(hDB, 0, "/Logger/Async transitions", &flag, &size, TID_BOOL, TRUE);
02399
02400 if (flag)
02401 trans_flag = ASYNC;
02402 else
02403 trans_flag = DETACH;
02404
02405 cm_msg(MTALK, "main", "starting new run");
02406 status = cm_transition(TR_START, run_number + 1, errstr, sizeof(errstr), trans_flag, verbose);
02407 if (status != CM_SUCCESS)
02408 cm_msg(MERROR, "main", "cannot restart run: %s", errstr);
02409
02410 return status;
02411 }
02412
02413 INT log_write(LOG_CHN * log_chn, EVENT_HEADER * pevent)
02414 {
02415 INT status = 0, size, izero;
02416 DWORD actual_time, start_time, watchdog_timeout, duration;
02417 BOOL watchdog_flag;
02418 static DWORD last_checked = 0;
02419 HNDLE htape, stats_hkey;
02420 char tape_name[256];
02421 double dzero;
02422
02423 start_time = ss_millitime();
02424
02425 if (log_chn->format == FORMAT_YBOS)
02426 assert(!"YBOS not supported anymore");
02427
02428 if (log_chn->format == FORMAT_ASCII)
02429 status = ascii_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
02430
02431 if (log_chn->format == FORMAT_DUMP)
02432 status = dump_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
02433
02434 if (log_chn->format == FORMAT_MIDAS)
02435 status = midas_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
02436
02437 #ifdef HAVE_ROOT
02438 if (log_chn->format == FORMAT_ROOT)
02439 status = root_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
02440 #endif
02441
02442 actual_time = ss_millitime();
02443 if ((int) actual_time - (int) start_time > 3000)
02444 cm_msg(MINFO, "log_write", "Write operation on %s took %d ms", log_chn->path, actual_time - start_time);
02445
02446 if (status != SS_SUCCESS && !stop_requested) {
02447 if (status == SS_IO_ERROR)
02448 cm_msg(MTALK, "log_write", "Physical IO error on %s, stopping run", log_chn->path);
02449 else
02450 cm_msg(MTALK, "log_write", "Error writing to %s, stopping run", log_chn->path);
02451
02452 stop_the_run(0);
02453
02454 return status;
02455 }
02456
02457
02458 if (!stop_requested && !in_stop_transition &&
02459 log_chn->settings.event_limit > 0 &&
02460 log_chn->statistics.events_written >= log_chn->settings.event_limit) {
02461 stop_requested = TRUE;
02462
02463 cm_msg(MTALK, "log_write", "stopping run after having received %1.0lf events",
02464 log_chn->settings.event_limit);
02465
02466 status = stop_the_run(1);
02467 return status;
02468 }
02469
02470
02471 duration = 0;
02472 size = sizeof(duration);
02473 db_get_value(hDB, 0, "/Logger/Subrun duration", &duration, &size, TID_DWORD, true);
02474 if (!stop_requested && duration > 0 && ss_time() >= subrun_start_time + duration) {
02475 int run_number;
02476
02477
02478
02479 size = sizeof(run_number);
02480 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
02481 assert(status == SUCCESS);
02482
02483 stop_requested = TRUE;
02484 log_close(log_chn, run_number);
02485 log_chn->subrun_number++;
02486 log_chn->statistics.bytes_written_subrun = 0;
02487 log_generate_file_name(log_chn);
02488 log_open(log_chn, run_number);
02489 subrun_start_time = ss_time();
02490 stop_requested = FALSE;
02491 }
02492
02493
02494 if (!stop_requested && log_chn->settings.subrun_byte_limit > 0 &&
02495 log_chn->statistics.bytes_written_subrun >= log_chn->settings.subrun_byte_limit) {
02496 int run_number;
02497
02498
02499
02500 size = sizeof(run_number);
02501 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
02502 assert(status == SUCCESS);
02503
02504 stop_requested = TRUE;
02505 log_close(log_chn, run_number);
02506 log_chn->subrun_number++;
02507 log_chn->statistics.bytes_written_subrun = 0;
02508 log_generate_file_name(log_chn);
02509 log_open(log_chn, run_number);
02510 subrun_start_time = ss_time();
02511 stop_requested = FALSE;
02512 }
02513
02514
02515 if (!stop_requested && !in_stop_transition &&
02516 log_chn->settings.byte_limit > 0 &&
02517 log_chn->statistics.bytes_written >= log_chn->settings.byte_limit) {
02518 stop_requested = TRUE;
02519
02520 cm_msg(MTALK, "log_write", "stopping run after having received %1.0lf mega bytes",
02521 log_chn->statistics.bytes_written / 1E6);
02522
02523 status = stop_the_run(1);
02524
02525 return status;
02526 }
02527
02528
02529 if (!stop_requested && !in_stop_transition &&
02530 log_chn->type == LOG_TYPE_TAPE &&
02531 log_chn->settings.tape_capacity > 0 &&
02532 log_chn->statistics.bytes_written_total >= log_chn->settings.tape_capacity) {
02533 stop_requested = TRUE;
02534 cm_msg(MTALK, "log_write", "tape capacity reached, stopping run");
02535
02536
02537 strcpy(tape_name, log_chn->path);
02538 stats_hkey = log_chn->stats_hkey;
02539
02540 status = stop_the_run(0);
02541
02542
02543 ss_tape_open(tape_name, O_RDONLY, &htape);
02544 cm_msg(MTALK, "log_write", "rewinding tape %s, please wait", log_chn->path);
02545
02546 cm_get_watchdog_params(&watchdog_flag, &watchdog_timeout);
02547 cm_set_watchdog_params(watchdog_flag, 300000);
02548 ss_tape_unmount(htape);
02549 ss_tape_close(htape);
02550 cm_set_watchdog_params(watchdog_flag, watchdog_timeout);
02551
02552
02553 dzero = izero = 0;
02554 db_set_value(hDB, stats_hkey, "Bytes written total", &dzero, sizeof(dzero), 1, TID_DOUBLE);
02555 db_set_value(hDB, stats_hkey, "Files written", &izero, sizeof(izero), 1, TID_INT);
02556
02557 cm_msg(MTALK, "log_write", "Please insert new tape and start new run.");
02558
02559 return status;
02560 }
02561
02562
02563 actual_time = ss_millitime();
02564 if (log_chn->type == LOG_TYPE_DISK && actual_time - last_checked > 1000) {
02565 last_checked = actual_time;
02566
02567 if (ss_disk_free(log_chn->path) < 1E7 && !stop_requested && !in_stop_transition) {
02568 stop_requested = TRUE;
02569 cm_msg(MTALK, "log_write", "disk nearly full, stopping run");
02570
02571 status = stop_the_run(0);
02572 }
02573 }
02574
02575 return status;
02576 }
02577
02578
02579
02580 void log_history(HNDLE hDB, HNDLE hKey, void *info);
02581
02582 #include "history.h"
02583
02584 static std::vector<MidasHistoryInterface*> mh;
02585
02586 static int add_event(int* indexp, int event_id, const char* event_name, HNDLE hKey, int ntags, const TAG* tags, int period, int hotlink)
02587 {
02588 int status;
02589 int size, i;
02590 int oldTags = 0;
02591 int disableTags = 0;
02592 int index = *indexp;
02593
02594 if (0) {
02595
02596 printf("add_event: event %d, name \"%s\", ntags %d\n", event_id, event_name, ntags);
02597 for (i=0; i<ntags; i++) {
02598 printf("tag %d: name \"%s\", type %d, n_data %d\n", i, tags[i].name, tags[i].type, tags[i].n_data);
02599 }
02600 }
02601
02602
02603
02604 for (i=0; i<index; i++) {
02605 if (hist_log[i].event_id == event_id) {
02606 cm_msg(MERROR, "add_event", "Duplicate event id %d for \'%s\'", event_id, event_name);
02607 return 0;
02608 }
02609 if (strcmp(hist_log[i].event_name, event_name) == 0) {
02610 cm_msg(MERROR, "add_event", "Duplicate event name \'%s\' with event id %d", event_name, event_id);
02611 return 0;
02612 }
02613 }
02614
02615 while (index >= hist_log_size) {
02616 int new_size = 2*hist_log_size;
02617
02618 if (hist_log_size == 0)
02619 new_size = 10;
02620
02621 hist_log = (hist_log_s*)realloc(hist_log, sizeof(hist_log[0])*new_size);
02622 assert(hist_log!=NULL);
02623
02624 hist_log_size = new_size;
02625 }
02626
02627 if (index >= hist_log_max)
02628 hist_log_max = index + 1;
02629
02630
02631 for (i=0; i<ntags; i++) {
02632 if (tags[i].type == TID_STRING) {
02633 cm_msg(MERROR, "add_event", "Invalid tag %d \'%s\' in event %d \'%s\': cannot do history for TID_STRING data, sorry!", i, tags[i].name, event_id, event_name);
02634 return 0;
02635 }
02636 if (rpc_tid_size(tags[i].type) == 0) {
02637 cm_msg(MERROR, "add_event", "Invalid tag %d \'%s\' in event %d \'%s\': type %d size is zero", i, tags[i].name, event_id, event_name, tags[i].type);
02638 return 0;
02639 }
02640 }
02641
02642
02643 for (i=0; i<ntags; i++) {
02644 if (isspace(tags[i].name[strlen(tags[i].name)-1])) {
02645 cm_msg(MERROR, "add_event", "Invalid tag %d \'%s\' in event %d \'%s\': has trailing spaces", i, tags[i].name, event_id, event_name);
02646 return 0;
02647 }
02648 }
02649
02650 for (unsigned i=0; i<mh.size(); i++) {
02651 status = mh[i]->hs_define_event(event_name, ntags, tags);
02652 if (status != HS_SUCCESS) {
02653 cm_msg(MERROR, "add_event", "Cannot define event \"%s\", hs_define_event() status %d", event_name, status);
02654 return 0;
02655 }
02656 }
02657
02658 status = hs_define_event(event_id, (char*)event_name, (TAG*)tags, sizeof(TAG) * ntags);
02659 assert(status == DB_SUCCESS);
02660
02661 status = db_get_record_size(hDB, hKey, 0, &size);
02662 assert(status == DB_SUCCESS);
02663
02664
02665 strlcpy(hist_log[index].event_name, event_name, sizeof(hist_log[index].event_name));
02666 hist_log[index].event_id = event_id;
02667 hist_log[index].n_var = ntags;
02668 hist_log[index].hKeyVar = hKey;
02669 hist_log[index].buffer_size = size;
02670 hist_log[index].buffer = (char*)malloc(size);
02671 hist_log[index].period = period;
02672 hist_log[index].last_log = 0;
02673
02674 if (hist_log[index].buffer == NULL) {
02675 cm_msg(MERROR, "add_event", "Cannot allocate data buffer for event \"%s\" size %d", event_name, size);
02676 return 0;
02677 }
02678
02679
02680 if (hotlink) {
02681 status = db_open_record(hDB, hKey, hist_log[index].buffer,
02682 size, MODE_READ, log_history, NULL);
02683 if (status != DB_SUCCESS) {
02684 cm_msg(MERROR, "add_event",
02685 "Cannot hotlink event %d \"%s\" for history logging, db_open_record() status %d",
02686 event_id, event_name, status);
02687 return status;
02688 }
02689 }
02690
02691 if (verbose)
02692 printf("Created event %d for equipment \"%s\", %d tags, size %d\n", event_id, event_name, ntags, size);
02693
02694
02695
02696 disableTags = 0;
02697 size = sizeof(disableTags);
02698 status = db_get_value(hDB, 0, "/History/DisableTags", &disableTags, &size, TID_BOOL, TRUE);
02699
02700 oldTags = 0;
02701 size = sizeof(oldTags);
02702 status = db_get_value(hDB, 0, "/History/CreateOldTags", &oldTags, &size, TID_BOOL, FALSE);
02703
02704 if (disableTags) {
02705 HNDLE hKey;
02706
02707 status = db_find_key(hDB, 0, "/History/Tags", &hKey);
02708 if (status == DB_SUCCESS) {
02709 status = db_delete_key(hDB, hKey, FALSE);
02710 if (status != DB_SUCCESS)
02711 cm_msg(MERROR, "add_event", "Cannot delete /History/Tags, db_delete_key() status %d", status);
02712 }
02713
02714 } else if (oldTags) {
02715
02716 char buf[256];
02717
02718 sprintf(buf, "/History/Tags/%d", event_id);
02719
02720
02721
02722 status = db_set_value(hDB, 0, buf, (void*)event_name, strlen(event_name)+1, 1, TID_STRING);
02723 assert(status == DB_SUCCESS);
02724
02725 for (i=0; i<ntags; i++) {
02726 WORD v = (WORD) tags[i].n_data;
02727 sprintf(buf, "/History/Tags/Tags %d/%s", event_id, tags[i].name);
02728
02729
02730
02731 status = db_set_value(hDB, 0, buf, &v, sizeof(v), 1, TID_WORD);
02732 assert(status == DB_SUCCESS);
02733
02734 if (strlen(tags[i].name) == NAME_LENGTH-1)
02735 cm_msg(MERROR, "add_event",
02736 "Tag name \'%s\' in event %d (%s) may have been truncated to %d characters",
02737 tags[i].name, event_id, event_name, NAME_LENGTH-1);
02738 }
02739
02740 } else {
02741
02742 const int kLength = 32 + NAME_LENGTH + NAME_LENGTH;
02743 char buf[kLength];
02744 HNDLE hKey;
02745
02746 sprintf(buf, "/History/Tags/%d", event_id);
02747 status = db_find_key(hDB, 0, buf, &hKey);
02748
02749 if (status == DB_SUCCESS) {
02750
02751 KEY key;
02752
02753 status = db_get_key(hDB, hKey, &key);
02754 assert(status == DB_SUCCESS);
02755
02756 assert(key.type == TID_STRING);
02757
02758 if (key.item_size < kLength && key.num_values == 1) {
02759
02760
02761 HNDLE hTags;
02762
02763 cm_msg(MINFO, "add_event", "Converting old event %d (%s) tags to new style", event_id, event_name);
02764
02765 status = db_set_data(hDB, hKey, event_name, kLength, 1, TID_STRING);
02766 assert(status == DB_SUCCESS);
02767
02768 sprintf(buf, "/History/Tags/Tags %d", event_id);
02769
02770 status = db_find_key(hDB, 0, buf, &hTags);
02771
02772 if (status == DB_SUCCESS) {
02773 for (i=0; ; i++) {
02774 HNDLE h;
02775 int size;
02776 KEY key;
02777 WORD w;
02778
02779 status = db_enum_key(hDB, hTags, i, &h);
02780 if (status == DB_NO_MORE_SUBKEYS)
02781 break;
02782 assert(status == DB_SUCCESS);
02783
02784 status = db_get_key(hDB, h, &key);
02785
02786 size = sizeof(w);
02787 status = db_get_data(hDB, h, &w, &size, TID_WORD);
02788 assert(status == DB_SUCCESS);
02789
02790 sprintf(buf, "%d[%d] %s", 0, w, key.name);
02791
02792 status = db_set_data_index(hDB, hKey, buf, kLength, 1+i, TID_STRING);
02793 assert(status == DB_SUCCESS);
02794 }
02795
02796 status = db_delete_key(hDB, hTags, TRUE);
02797 assert(status == DB_SUCCESS);
02798 }
02799
02800
02801 status = db_get_key(hDB, hKey, &key);
02802 assert(status == DB_SUCCESS);
02803 }
02804
02805 if (1) {
02806
02807
02808 int size = key.item_size * key.num_values;
02809 int num = key.num_values;
02810
02811 char* s = (char*)malloc(size);
02812 assert(s != NULL);
02813
02814 TAG* t = (TAG*)malloc(sizeof(TAG)*(key.num_values + ntags));
02815 assert(t != NULL);
02816
02817 status = db_get_data(hDB, hKey, s, &size, TID_STRING);
02818 assert(status == DB_SUCCESS);
02819
02820 for (i=1; i<key.num_values; i++) {
02821 char* ss = s + i*key.item_size;
02822
02823 t[i].type = 0;
02824 t[i].n_data = 0;
02825 t[i].name[0] = 0;
02826
02827 if (isdigit(ss[0])) {
02828
02829
02830 t[i].type = strtoul(ss, &ss, 0);
02831 assert(*ss == '[');
02832 ss++;
02833 t[i].n_data = strtoul(ss, &ss, 0);
02834 assert(*ss == ']');
02835 ss++;
02836 assert(*ss == ' ');
02837 ss++;
02838 strlcpy(t[i].name, ss, sizeof(t[i].name));
02839
02840
02841 }
02842 }
02843
02844 for (i=0; i<ntags; i++) {
02845 int j;
02846 int k = 0;
02847
02848 for (j=1; j<key.num_values; j++) {
02849 if (equal_ustring((char*)tags[i].name, (char*)t[j].name)) {
02850 if ((tags[i].type!=t[j].type) || (tags[i].n_data!=t[j].n_data)) {
02851 cm_msg(MINFO, "add_event", "Event %d (%s) tag \"%s\" type and size changed from %d[%d] to %d[%d]",
02852 event_id, event_name,
02853 tags[i].name,
02854 t[j].type, t[j].n_data,
02855 tags[i].type, tags[i].n_data);
02856 k = j;
02857 break;
02858 }
02859
02860 k = -1;
02861 break;
02862 }
02863 }
02864
02865
02866
02867 if (k==0)
02868 k = num;
02869
02870 if (k > 0) {
02871 sprintf(buf, "%d[%d] %s", tags[i].type, tags[i].n_data, tags[i].name);
02872
02873 status = db_set_data_index(hDB, hKey, buf, kLength, k, TID_STRING);
02874 assert(status == DB_SUCCESS);
02875
02876 if (k >= num)
02877 num = k+1;
02878 }
02879 }
02880
02881 free(s);
02882 free(t);
02883 }
02884
02885 } else if (status == DB_NO_KEY) {
02886
02887 status = db_create_key(hDB, 0, buf, TID_STRING);
02888 assert(status == DB_SUCCESS);
02889
02890 status = db_find_key(hDB, 0, buf, &hKey);
02891 assert(status == DB_SUCCESS);
02892
02893 status = db_set_data(hDB, hKey, event_name, kLength, 1, TID_STRING);
02894 assert(status == DB_SUCCESS);
02895
02896 for (i=0; i<ntags; i++) {
02897 sprintf(buf, "%d[%d] %s", tags[i].type, tags[i].n_data, tags[i].name);
02898
02899 status = db_set_data_index(hDB, hKey, buf, kLength, 1+i, TID_STRING);
02900 assert(status == DB_SUCCESS);
02901 }
02902 } else {
02903 cm_msg(MERROR, "add_event", "Error: db_find_key(%s) status %d", buf, status);
02904 return 0;
02905 }
02906 }
02907
02908 *indexp = index+1;
02909
02910 return SUCCESS;
02911 }
02912
02913 static int get_event_id(int eq_id, const char* eq_name, const char* var_name)
02914 {
02915 HNDLE hDB, hKeyRoot;
02916 char name[NAME_LENGTH+NAME_LENGTH+2];
02917 int status, i;
02918 WORD max_id = 0;
02919
02920 strlcpy(name, eq_name, sizeof(name));
02921 strlcat(name, ":", sizeof(name));
02922 strlcat(name, var_name, sizeof(name));
02923
02924
02925
02926 cm_get_experiment_database(&hDB, NULL);
02927
02928 status = db_find_key(hDB, 0, "/History/Events", &hKeyRoot);
02929 if (status == DB_SUCCESS) {
02930 for (i = 0;; i++) {
02931 HNDLE hKey;
02932 KEY key;
02933 WORD evid;
02934 int size;
02935 char tmp[NAME_LENGTH+NAME_LENGTH+2];
02936
02937 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
02938 if (status != DB_SUCCESS)
02939 break;
02940
02941 status = db_get_key(hDB, hKey, &key);
02942 assert(status == DB_SUCCESS);
02943
02944
02945
02946 evid = (WORD) strtol(key.name, NULL, 0);
02947 if (evid == 0)
02948 continue;
02949
02950 size = sizeof(tmp);
02951 status = db_get_data(hDB, hKey, tmp, &size, TID_STRING);
02952
02953 assert(status == DB_SUCCESS);
02954
02955
02956
02957 if (equal_ustring(name, tmp))
02958 return evid;
02959
02960 if (evid/1000 == eq_id)
02961 max_id = evid;
02962 }
02963 }
02964
02965
02966
02967 if (max_id == 0)
02968 max_id = eq_id * 1000;
02969
02970 if (max_id < 1000)
02971 max_id = 1000;
02972
02973 while (1) {
02974 char tmp[NAME_LENGTH+NAME_LENGTH+2];
02975 HNDLE hKey;
02976 WORD evid = max_id + 1;
02977
02978 sprintf(tmp,"/History/Events/%d", evid);
02979
02980 status = db_find_key(hDB, 0, tmp, &hKey);
02981 if (status == DB_SUCCESS) {
02982 max_id = evid;
02983 assert(max_id < 65000);
02984 continue;
02985 }
02986
02987 status = db_set_value(hDB, 0, tmp, name, strlen(name)+1, 1, TID_STRING);
02988 assert(status == DB_SUCCESS);
02989
02990 return evid;
02991 }
02992
02993
02994 return 0;
02995 }
02996
02997 INT open_history()
02998 {
02999 INT size, index, i_tag, status, i, j, li, max_event_id;
03000 int ieq;
03001 INT n_var, n_tags, n_names = 0;
03002 HNDLE hKeyRoot, hKeyVar, hKeyNames, hLinkKey, hVarKey, hKeyEq, hHistKey, hKey;
03003 DWORD history;
03004 TAG *tag = NULL;
03005 KEY key, varkey, linkkey, histkey;
03006 WORD eq_id;
03007 char str[256], eq_name[NAME_LENGTH], hist_name[NAME_LENGTH];
03008 BOOL single_names;
03009 int count_events = 0;
03010 int global_per_variable_history = 0;
03011
03012 for (unsigned i=0; i<mh.size(); i++)
03013 delete mh[i];
03014 mh.clear();
03015
03016 #ifdef HAVE_ODBC
03017 int debug = 0;
03018 size = sizeof(debug);
03019 status = db_get_value(hDB, 0, "/Logger/ODBC_Debug", &debug, &size, TID_INT, TRUE);
03020 assert(status==DB_SUCCESS);
03021
03022
03023 char dsn[256];
03024 size = sizeof(dsn);
03025 dsn[0] = 0;
03026
03027 status = db_get_value(hDB, 0, "/Logger/ODBC_DSN", dsn, &size, TID_STRING, TRUE);
03028 assert(status==DB_SUCCESS);
03029
03030 if (debug == 2) {
03031
03032 MidasHistoryInterface* hi = MakeMidasHistorySqlDebug();
03033 assert(hi);
03034
03035 hi->hs_set_debug(debug);
03036
03037 status = hi->hs_connect(dsn);
03038 if (status != HS_SUCCESS) {
03039 cm_msg(MERROR, "open_history", "Cannot connect to SQL debug driver \'%s\', status %d", dsn, status);
03040 return status;
03041 }
03042
03043 mh.push_back(hi);
03044
03045 } else if (strlen(dsn)>1 && dsn[0]!='#') {
03046
03047 MidasHistoryInterface* hi = MakeMidasHistoryODBC();
03048 assert(hi);
03049
03050 hi->hs_set_debug(debug);
03051
03052 status = hi->hs_connect(dsn);
03053 if (status != HS_SUCCESS) {
03054 cm_msg(MERROR, "open_history", "Cannot connect to ODBC database with DSN \'%s\', status %d", dsn, status);
03055 return status;
03056 }
03057
03058 mh.push_back(hi);
03059 }
03060 #endif
03061
03062 for (unsigned i=0; i<mh.size(); i++) {
03063 status = mh[i]->hs_clear_cache();
03064 assert(status == HS_SUCCESS);
03065 }
03066
03067
03068 size = sizeof(str);
03069 str[0] = 0;
03070 status = db_get_value(hDB, 0, "/Logger/History Dir", str, &size, TID_STRING, FALSE);
03071 if (status != DB_SUCCESS)
03072 db_get_value(hDB, 0, "/Logger/Data Dir", str, &size, TID_STRING, TRUE);
03073
03074 if (str[0] != 0)
03075 hs_set_path(str);
03076
03077 if (db_find_key(hDB, 0, "/History/Links", &hKeyRoot) != DB_SUCCESS ||
03078 db_find_key(hDB, 0, "/History/Links/System", &hKeyRoot) != DB_SUCCESS) {
03079
03080 db_create_key(hDB, 0, "/History/Links", TID_KEY);
03081
03082 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/Events per sec.", &hKeyEq) == DB_SUCCESS)
03083 db_create_link(hDB, 0, "/History/Links/System/Trigger per sec.",
03084 "/Equipment/Trigger/Statistics/Events per sec.");
03085
03086 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/kBytes per sec.", &hKeyEq) == DB_SUCCESS)
03087 db_create_link(hDB, 0, "/History/Links/System/Trigger kB per sec.",
03088 "/Equipment/Trigger/Statistics/kBytes per sec.");
03089 }
03090
03091
03092
03093 max_event_id = 0;
03094
03095 status = db_find_key(hDB, 0, "/Equipment", &hKeyRoot);
03096 if (status != DB_SUCCESS) {
03097 cm_msg(MERROR, "open_history", "Cannot find Equipment entry in database");
03098 return 0;
03099 }
03100
03101 size = sizeof(int);
03102 status = db_get_value(hDB, 0, "/History/PerVariableHistory", &global_per_variable_history, &size, TID_INT, TRUE);
03103 assert(status==DB_SUCCESS);
03104
03105
03106 index = 0;
03107 for (ieq = 0; ; ieq++) {
03108 status = db_enum_key(hDB, hKeyRoot, ieq, &hKeyEq);
03109 if (status != DB_SUCCESS)
03110 break;
03111
03112
03113 size = sizeof(history);
03114 db_get_value(hDB, hKeyEq, "Common/Log history", &history, &size, TID_INT, TRUE);
03115
03116
03117 if (history > 0) {
03118 BOOL per_variable_history = global_per_variable_history;
03119
03120
03121 db_get_key(hDB, hKeyEq, &key);
03122 strcpy(eq_name, key.name);
03123
03124 if (strchr(eq_name, ':'))
03125 cm_msg(MERROR, "open_history", "Equipment name \'%s\' contains characters \':\', this may break the history system", eq_name);
03126
03127 status = db_find_key(hDB, hKeyEq, "Variables", &hKeyVar);
03128 if (status != DB_SUCCESS) {
03129 cm_msg(MERROR, "open_history", "Cannot find /Equipment/%s/Variables entry in database", eq_name);
03130 return 0;
03131 }
03132
03133 size = sizeof(eq_id);
03134 status = db_get_value(hDB, hKeyEq, "Common/Event ID", &eq_id, &size, TID_WORD, TRUE);
03135 assert(status == DB_SUCCESS);
03136
03137 size = sizeof(int);
03138 status = db_get_value(hDB, hKeyEq, "Settings/PerVariableHistory", &per_variable_history, &size, TID_INT, FALSE);
03139 assert(status == DB_SUCCESS || status == DB_NO_KEY);
03140
03141 if (verbose)
03142 printf
03143 ("\n==================== Equipment \"%s\", ID %d =======================\n",
03144 eq_name, eq_id);
03145
03146
03147 for (n_var = 0, n_tags = 0;; n_var++) {
03148 status = db_enum_key(hDB, hKeyVar, n_var, &hKey);
03149 if (status == DB_NO_MORE_SUBKEYS)
03150 break;
03151 db_get_key(hDB, hKey, &key);
03152 if (key.type != TID_KEY) {
03153 n_tags += key.num_values;
03154 }
03155 else {
03156 int ii;
03157 for (ii=0;; ii++) {
03158 KEY vvarkey;
03159 HNDLE hhKey;
03160
03161 status = db_enum_key(hDB, hKey, ii, &hhKey);
03162 if (status == DB_NO_MORE_SUBKEYS)
03163 break;
03164
03165
03166 db_get_key(hDB, hhKey, &vvarkey);
03167
03168 n_tags += vvarkey.num_values;
03169 }
03170 }
03171 }
03172
03173 if (n_var == 0)
03174 cm_msg(MERROR, "open_history", "defined event %d with no variables in ODB", eq_id);
03175
03176
03177 tag = (TAG *) malloc(sizeof(TAG) * n_tags);
03178
03179 i_tag = 0;
03180 for (i=0; ; i++) {
03181 status = db_enum_key(hDB, hKeyVar, i, &hKey);
03182 if (status == DB_NO_MORE_SUBKEYS)
03183 break;
03184
03185
03186 db_get_key(hDB, hKey, &varkey);
03187
03188
03189 db_find_key(hDB, hKeyEq, "Settings/Names", &hKeyNames);
03190 single_names = (hKeyNames > 0);
03191 if (hKeyNames) {
03192 if (verbose)
03193 printf("Using \"/Equipment/%s/Settings/Names\" for variable \"%s\"\n",
03194 eq_name, varkey.name);
03195
03196
03197 db_get_key(hDB, hKeyNames, &key);
03198 n_names = key.num_values;
03199 } else {
03200 sprintf(str, "Settings/Names %s", varkey.name);
03201 db_find_key(hDB, hKeyEq, str, &hKeyNames);
03202 if (hKeyNames) {
03203 if (verbose)
03204 printf
03205 ("Using \"/Equipment/%s/Settings/Names %s\" for variable \"%s\"\n",
03206 eq_name, varkey.name, varkey.name);
03207
03208
03209 db_get_key(hDB, hKeyNames, &key);
03210 n_names = key.num_values;
03211 }
03212 }
03213
03214 if (hKeyNames && n_names < varkey.num_values) {
03215 cm_msg(MERROR, "open_history",
03216 "Array size mismatch: \"/Equipment/%s/Settings/%s\" has %d entries while \"/Equipment/%s/Variables/%s\" has %d entries",
03217 eq_name, key.name, n_names,
03218 eq_name, varkey.name, varkey.num_values);
03219 free(tag);
03220 return 0;
03221 }
03222
03223 if (hKeyNames) {
03224
03225 for (j = 0; j < varkey.num_values; j++) {
03226 char xname[256];
03227
03228 tag[i_tag].name[0] = 0;
03229
03230
03231 size = sizeof(xname);
03232 status = db_get_data_index(hDB, hKeyNames, xname, &size, j, TID_STRING);
03233 if (status == DB_SUCCESS)
03234 strlcpy(tag[i_tag].name, xname, sizeof(tag[i_tag].name));
03235
03236 if (strlen(tag[i_tag].name) < 1) {
03237 char buf[256];
03238 sprintf(buf, "%d", j);
03239 strlcpy(tag[i_tag].name, varkey.name, NAME_LENGTH);
03240 strlcat(tag[i_tag].name, "_", NAME_LENGTH);
03241 strlcat(tag[i_tag].name, buf, NAME_LENGTH);
03242 }
03243
03244
03245 if (single_names) {
03246 if (strlen(tag[i_tag].name) + 1 + strlen(varkey.name) >= NAME_LENGTH) {
03247 cm_msg(MERROR, "open_history",
03248 "Name for history entry \"%s %s\" too long", tag[i_tag].name, varkey.name);
03249 free(tag);
03250 return 0;
03251 }
03252 strlcat(tag[i_tag].name, " ", NAME_LENGTH);
03253 strlcat(tag[i_tag].name, varkey.name, NAME_LENGTH);
03254 }
03255
03256 tag[i_tag].type = varkey.type;
03257 tag[i_tag].n_data = 1;
03258
03259 if (verbose)
03260 printf("Defined tag %d, name \"%s\", type %d, num_values %d\n",
03261 i_tag, tag[i_tag].name, tag[i_tag].type, tag[i_tag].n_data);
03262
03263 i_tag++;
03264 }
03265 } else if (varkey.type == TID_KEY) {
03266 int ii;
03267 for (ii=0;; ii++) {
03268 KEY vvarkey;
03269 HNDLE hhKey;
03270
03271 status = db_enum_key(hDB, hKey, ii, &hhKey);
03272 if (status == DB_NO_MORE_SUBKEYS)
03273 break;
03274
03275
03276 db_get_key(hDB, hhKey, &vvarkey);
03277
03278 strlcpy(tag[i_tag].name, varkey.name, NAME_LENGTH);
03279 strlcat(tag[i_tag].name, "_", NAME_LENGTH);
03280 strlcat(tag[i_tag].name, vvarkey.name, NAME_LENGTH);
03281 tag[i_tag].type = vvarkey.type;
03282 tag[i_tag].n_data = vvarkey.num_values;
03283
03284 if (verbose)
03285 printf("Defined tag %d, name \"%s\", type %d, num_values %d\n", i_tag, tag[i_tag].name,
03286 tag[i_tag].type, tag[i_tag].n_data);
03287
03288 i_tag++;
03289 }
03290 } else {
03291 strlcpy(tag[i_tag].name, varkey.name, NAME_LENGTH);
03292 tag[i_tag].type = varkey.type;
03293 tag[i_tag].n_data = varkey.num_values;
03294
03295 if (verbose)
03296 printf("Defined tag %d, name \"%s\", type %d, num_values %d\n", i_tag, tag[i_tag].name,
03297 tag[i_tag].type, tag[i_tag].n_data);
03298
03299 i_tag++;
03300 }
03301
03302 if (per_variable_history && i_tag>0) {
03303 WORD event_id;
03304 char event_name[NAME_LENGTH];
03305
03306 event_id = get_event_id(eq_id, eq_name, varkey.name);
03307 assert(event_id > 0);
03308
03309 strlcpy(event_name, eq_name, NAME_LENGTH);
03310 strlcat(event_name, "/", NAME_LENGTH);
03311 strlcat(event_name, varkey.name, NAME_LENGTH);
03312
03313 assert(i_tag <= n_tags);
03314
03315 status = add_event(&index, event_id, event_name, hKey, i_tag, tag, history, 1);
03316 if (status != DB_SUCCESS)
03317 return status;
03318
03319 count_events++;
03320
03321 i_tag = 0;
03322 }
03323
03324 }
03325
03326 if (!per_variable_history && i_tag>0) {
03327 assert(i_tag <= n_tags);
03328
03329 status = add_event(&index, eq_id, eq_name, hKeyVar, i_tag, tag, history, 1);
03330 if (status != DB_SUCCESS)
03331 return status;
03332
03333 count_events++;
03334 }
03335
03336 if (tag)
03337 free(tag);
03338
03339
03340 if (eq_id > max_event_id)
03341 max_event_id = eq_id;
03342 }
03343 }
03344
03345
03346
03347
03348 max_event_id = ((int) ((max_event_id + 1) / 10) + 1) * 10;
03349
03350 status = db_find_key(hDB, 0, "/History/Links", &hKeyRoot);
03351 if (status == DB_SUCCESS) {
03352 for (li = 0;; li++) {
03353 status = db_enum_link(hDB, hKeyRoot, li, &hHistKey);
03354 if (status == DB_NO_MORE_SUBKEYS)
03355 break;
03356
03357 db_get_key(hDB, hHistKey, &histkey);
03358 strcpy(hist_name, histkey.name);
03359 db_enum_key(hDB, hKeyRoot, li, &hHistKey);
03360
03361 db_get_key(hDB, hHistKey, &key);
03362 if (key.type != TID_KEY) {
03363 cm_msg(MERROR, "open_history", "Only subkeys allows in /history/links");
03364 continue;
03365 }
03366
03367 if (verbose)
03368 printf
03369 ("\n==================== History link \"%s\", ID %d =======================\n",
03370 hist_name, max_event_id);
03371
03372
03373 for (i = n_var = 0;; i++) {
03374 status = db_enum_key(hDB, hHistKey, i, &hKey);
03375 if (status == DB_NO_MORE_SUBKEYS)
03376 break;
03377
03378 if (status == DB_SUCCESS && db_get_key(hDB, hKey, &key) == DB_SUCCESS) {
03379 if (key.type != TID_KEY)
03380 n_var++;
03381 } else {
03382 db_enum_link(hDB, hHistKey, i, &hKey);
03383 db_get_key(hDB, hKey, &key);
03384 cm_msg(MERROR, "open_history",
03385 "History link /History/Links/%s/%s is invalid", hist_name, key.name);
03386 return 0;
03387 }
03388 }
03389
03390 if (n_var == 0)
03391 cm_msg(MERROR, "open_history", "History event %s has no variables in ODB", hist_name);
03392 else {
03393
03394 tag = (TAG *) malloc(sizeof(TAG) * n_var);
03395
03396 for (i = 0, size = 0, n_var = 0;; i++) {
03397 status = db_enum_link(hDB, hHistKey, i, &hLinkKey);
03398 if (status == DB_NO_MORE_SUBKEYS)
03399 break;
03400
03401
03402 db_get_key(hDB, hLinkKey, &linkkey);
03403
03404 if (linkkey.type == TID_KEY)
03405 continue;
03406
03407
03408 db_enum_key(hDB, hHistKey, i, &hVarKey);
03409 if (db_get_key(hDB, hVarKey, &varkey) == DB_SUCCESS) {
03410
03411 if (histkey.type == TID_KEY)
03412 db_open_record(hDB, hVarKey, NULL, varkey.total_size, MODE_READ,
03413 log_system_history, (void *) (POINTER_T) index);
03414
03415 strcpy(tag[n_var].name, linkkey.name);
03416 tag[n_var].type = varkey.type;
03417 tag[n_var].n_data = varkey.num_values;
03418
03419 if (verbose)
03420 printf("Defined tag \"%s\", type %d, num_values %d\n",
03421 tag[n_var].name, tag[n_var].type, tag[n_var].n_data);
03422
03423 size += varkey.total_size;
03424 n_var++;
03425 }
03426 }
03427
03428
03429 if (histkey.type == TID_LINK)
03430 db_open_record(hDB, hHistKey, NULL, size, MODE_READ, log_system_history,
03431 (void *) (POINTER_T) index);
03432
03433 status = add_event(&index, max_event_id, hist_name, hHistKey, n_var, tag, 10, 0);
03434 if (status != DB_SUCCESS)
03435 return status;
03436
03437 free(tag);
03438
03439 count_events++;
03440 max_event_id++;
03441 }
03442 }
03443 }
03444
03445
03446
03447 tag = (TAG *) malloc(sizeof(TAG) * 2);
03448
03449 strcpy(tag[0].name, "State");
03450 tag[0].type = TID_DWORD;
03451 tag[0].n_data = 1;
03452
03453 strcpy(tag[1].name, "Run number");
03454 tag[1].type = TID_DWORD;
03455 tag[1].n_data = 1;
03456
03457 const char* event_name = "Run transitions";
03458
03459 for (unsigned i=0; i<mh.size(); i++) {
03460 status = mh[i]->hs_define_event(event_name, 2, tag);
03461 if (status != HS_SUCCESS) {
03462 cm_msg(MERROR, "add_event", "Cannot define event \"%s\", hs_define_event() status %d", event_name, status);
03463 return 0;
03464 }
03465 }
03466
03467 hs_define_event(0, (char*)event_name, tag, sizeof(TAG) * 2);
03468 free(tag);
03469
03470
03471
03472
03473
03474 return CM_SUCCESS;
03475 }
03476
03477
03478
03479 void close_history()
03480 {
03481 INT i, status;
03482 HNDLE hKeyRoot, hKey;
03483
03484
03485 status = db_find_key(hDB, 0, "/History/Links", &hKeyRoot);
03486 if (status != DB_SUCCESS) {
03487 for (i = 0;; i++) {
03488 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
03489 if (status == DB_NO_MORE_SUBKEYS)
03490 break;
03491 db_close_record(hDB, hKey);
03492 }
03493 }
03494
03495
03496 for (i = 1; i < hist_log_max; i++)
03497 if (hist_log[i].hKeyVar) {
03498 db_close_record(hDB, hist_log[i].hKeyVar);
03499 hist_log[i].hKeyVar = 0;
03500 if (hist_log[i].buffer)
03501 free(hist_log[i].buffer);
03502 hist_log[i].buffer = NULL;
03503 }
03504
03505 for (unsigned h=0; h<mh.size(); h++)
03506 status = mh[h]->hs_disconnect();
03507 }
03508
03509
03510
03511 void log_history(HNDLE hDB, HNDLE hKey, void *info)
03512 {
03513 INT i, size;
03514
03515 for (i = 0; i < hist_log_max; i++)
03516 if (hist_log[i].hKeyVar == hKey)
03517 break;
03518
03519 if (i == hist_log_max)
03520 return;
03521
03522
03523 if (ss_time() - hist_log[i].last_log < hist_log[i].period)
03524 return;
03525
03526
03527 db_get_record_size(hDB, hKey, 0, &size);
03528 if (size != hist_log[i].buffer_size) {
03529 close_history();
03530 open_history();
03531 return;
03532 }
03533
03534 hist_log[i].last_log = ss_time();
03535
03536 if (verbose)
03537 printf("write history event: id %d, timestamp %d, buffer %p, size %d\n", hist_log[i].event_id, hist_log[i].last_log, hist_log[i].buffer, hist_log[i].buffer_size);
03538
03539 hs_write_event(hist_log[i].event_id, hist_log[i].buffer, hist_log[i].buffer_size);
03540
03541 for (unsigned h=0; h<mh.size(); h++) {
03542 int status = mh[h]->hs_write_event(hist_log[i].event_name, hist_log[i].last_log, hist_log[i].buffer_size, hist_log[i].buffer);
03543 if (verbose)
03544 if (status != HS_SUCCESS)
03545 printf("hs_write_event() status %d\n", status);
03546 }
03547 }
03548
03549
03550
03551 void log_system_history(HNDLE hDB, HNDLE hKey, void *info)
03552 {
03553 INT size, total_size, status, index;
03554 DWORD i;
03555 KEY key;
03556
03557 index = (INT) (POINTER_T) info;
03558
03559
03560 if (ss_time() - hist_log[index].last_log < hist_log[index].period)
03561 return;
03562
03563 for (i = 0, total_size = 0;; i++) {
03564 status = db_enum_key(hDB, hist_log[index].hKeyVar, i, &hKey);
03565 if (status == DB_NO_MORE_SUBKEYS)
03566 break;
03567
03568 db_get_key(hDB, hKey, &key);
03569 size = key.total_size;
03570 db_get_data(hDB, hKey, (char *) hist_log[index].buffer + total_size, &size, key.type);
03571 total_size += size;
03572 }
03573
03574 if (i != hist_log[index].n_var) {
03575 close_history();
03576 open_history();
03577 } else {
03578 hist_log[index].last_log = ss_time();
03579
03580 hs_write_event(hist_log[index].event_id, hist_log[index].buffer, hist_log[index].buffer_size);
03581
03582 for (unsigned h=0; h<mh.size(); h++)
03583 mh[h]->hs_write_event(hist_log[index].event_name, hist_log[index].last_log, hist_log[index].buffer_size, hist_log[index].buffer);
03584 }
03585
03586
03587
03588 if (!rpc_is_remote()) {
03589 db_lock_database(hDB);
03590 db_notify_clients(hDB, hist_log[index].hKeyVar, FALSE);
03591 db_unlock_database(hDB);
03592 }
03593
03594 }
03595
03596
03597
03598 INT log_callback(INT index, void *prpc_param[])
03599 {
03600 HNDLE hKeyRoot, hKeyChannel;
03601 INT i, status, size, channel, izero, htape, online_mode;
03602 DWORD watchdog_timeout;
03603 BOOL watchdog_flag;
03604 char str[256];
03605 double dzero;
03606
03607
03608 if (index == RPC_LOG_REWIND) {
03609 channel = *((INT *) prpc_param[0]);
03610
03611
03612 status = db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot);
03613 if (status != DB_SUCCESS) {
03614 cm_msg(MERROR, "log_callback", "cannot find Logger/Channels entry in database");
03615 return 0;
03616 }
03617
03618
03619 online_mode = 0;
03620 size = sizeof(online_mode);
03621 db_get_value(hDB, 0, "/Runinfo/online mode", &online_mode, &size, TID_INT, TRUE);
03622
03623 for (i = 0; i < MAX_CHANNELS; i++) {
03624 status = db_enum_key(hDB, hKeyRoot, i, &hKeyChannel);
03625 if (status == DB_NO_MORE_SUBKEYS)
03626 break;
03627
03628
03629 if (channel != i && channel != -1)
03630 continue;
03631
03632 if (status == DB_SUCCESS) {
03633 size = sizeof(str);
03634 status = db_get_value(hDB, hKeyChannel, "Settings/Type", str, &size, TID_STRING, TRUE);
03635 if (status != DB_SUCCESS)
03636 continue;
03637
03638 if (equal_ustring(str, "Tape")) {
03639 size = sizeof(str);
03640 status = db_get_value(hDB, hKeyChannel, "Settings/Filename", str, &size, TID_STRING, TRUE);
03641 if (status != DB_SUCCESS)
03642 continue;
03643
03644 if (ss_tape_open(str, O_RDONLY, &htape) == SS_SUCCESS) {
03645 cm_msg(MTALK, "log_callback", "rewinding tape #%d, please wait", i);
03646
03647 cm_get_watchdog_params(&watchdog_flag, &watchdog_timeout);
03648 cm_set_watchdog_params(watchdog_flag, 300000);
03649 ss_tape_rewind(htape);
03650 if (online_mode)
03651 ss_tape_unmount(htape);
03652 cm_set_watchdog_params(watchdog_flag, watchdog_timeout);
03653
03654 cm_msg(MINFO, "log_callback", "Tape %s rewound sucessfully", str);
03655 } else
03656 cm_msg(MERROR, "log_callback", "Cannot rewind tape %s", str);
03657
03658 ss_tape_close(htape);
03659
03660
03661 dzero = izero = 0;
03662 log_chn[i].statistics.bytes_written_total = 0;
03663 log_chn[i].statistics.files_written = 0;
03664 db_set_value(hDB, hKeyChannel, "Statistics/Bytes written total", &dzero,
03665 sizeof(dzero), 1, TID_DOUBLE);
03666 db_set_value(hDB, hKeyChannel, "Statistics/Files written", &izero, sizeof(izero), 1, TID_INT);
03667 }
03668 }
03669 }
03670
03671 cm_msg(MTALK, "log_callback", "tape rewind finished");
03672 }
03673
03674 return RPC_SUCCESS;
03675 }
03676
03677
03678
03679 int log_generate_file_name(LOG_CHN *log_chn)
03680 {
03681 INT size, status, run_number;
03682 char str[256], path[256], dir[256], data_dir[256];
03683 CHN_SETTINGS *chn_settings;
03684 time_t now;
03685 struct tm *tms;
03686
03687 chn_settings = &log_chn->settings;
03688 size = sizeof(run_number);
03689 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
03690 assert(status == SUCCESS);
03691
03692 data_dir[0] = 0;
03693
03694
03695 if (log_chn->type == LOG_TYPE_DISK && chn_settings->filename[0] != DIR_SEPARATOR) {
03696 size = sizeof(data_dir);
03697 dir[0] = 0;
03698 db_get_value(hDB, 0, "/Logger/Data Dir", data_dir, &size, TID_STRING, TRUE);
03699 if (data_dir[0] != 0)
03700 if (data_dir[strlen(data_dir) - 1] != DIR_SEPARATOR)
03701 strcat(data_dir, DIR_SEPARATOR_STR);
03702 strcpy(str, data_dir);
03703
03704
03705 if (chn_settings->subdir_format[0]) {
03706 tzset();
03707 time(&now);
03708 tms = localtime(&now);
03709
03710 strftime(dir, sizeof(dir), chn_settings->subdir_format, tms);
03711 strcat(str, dir);
03712 strcat(str, DIR_SEPARATOR_STR);
03713 }
03714
03715
03716 #ifdef OS_WINNT
03717 status = mkdir(str);
03718 #else
03719 status = mkdir(str, 0755);
03720 #endif
03721 #if !defined(HAVE_MYSQL) && !defined(OS_WINNT)
03722 if (status == -1 && errno != EEXIST)
03723 cm_msg(MERROR, "log_generate_file_name", "Cannot create subdirectory %s", str);
03724 #endif
03725
03726 strcat(str, chn_settings->filename);
03727 } else
03728 strcpy(str, chn_settings->filename);
03729
03730
03731 if (strchr(str, '%')) {
03732 if (strchr(strchr(str, '%')+1, '%')) {
03733
03734 sprintf(path, str, run_number, log_chn->subrun_number);
03735 } else {
03736
03737 sprintf(path, str, run_number);
03738 }
03739 } else
03740 strcpy(path, str);
03741
03742 strcpy(log_chn->path, path);
03743
03744
03745 if (strncmp(path, data_dir, strlen(data_dir)) == 0)
03746 strcpy(str, path + strlen(data_dir));
03747 else
03748 strcpy(str, path);
03749 db_set_value(hDB, log_chn->settings_hkey, "Current filename", str, 256, 1, TID_STRING);
03750
03751 return CM_SUCCESS;
03752 }
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764 int close_channels(int run_number, BOOL* p_tape_flag)
03765 {
03766 int i;
03767 BOOL tape_flag = FALSE;
03768
03769 for (i = 0; i < MAX_CHANNELS; i++) {
03770 if (log_chn[i].handle || log_chn[i].ftp_con) {
03771
03772 if (log_chn[i].type == LOG_TYPE_TAPE && tape_message) {
03773 tape_flag = TRUE;
03774 cm_msg(MTALK, "tr_stop", "closing tape channel #%d, please wait", i);
03775 }
03776 #ifndef FAL_MAIN
03777
03778 if (log_chn[i].buffer_handle) {
03779 #ifdef DELAYED_STOP
03780 DWORD start_time;
03781
03782 start_time = ss_millitime();
03783 do {
03784 cm_yield(100);
03785 } while (ss_millitime() - start_time < DELAYED_STOP);
03786 #else
03787 INT n_bytes;
03788 do {
03789 bm_get_buffer_level(log_chn[i].buffer_handle, &n_bytes);
03790 if (n_bytes > 0)
03791 cm_yield(100);
03792 } while (n_bytes > 0);
03793 #endif
03794 }
03795 #endif
03796
03797
03798 log_close(&log_chn[i], run_number);
03799
03800
03801 db_set_record(hDB, log_chn[i].stats_hkey, &log_chn[i].statistics, sizeof(CHN_STATISTICS), 0);
03802 db_close_record(hDB, log_chn[i].stats_hkey);
03803 db_close_record(hDB, log_chn[i].settings_hkey);
03804 log_chn[i].stats_hkey = log_chn[i].settings_hkey = 0;
03805 }
03806 }
03807
03808 if (p_tape_flag)
03809 *p_tape_flag = tape_flag;
03810
03811 return SUCCESS;
03812 }
03813
03814 int close_buffers()
03815 {
03816 int i;
03817
03818
03819 for (i = 0; i < MAX_CHANNELS; i++) {
03820 #ifndef FAL_MAIN
03821 if (log_chn[i].buffer_handle) {
03822 INT j;
03823
03824 bm_close_buffer(log_chn[i].buffer_handle);
03825 for (j = i + 1; j < MAX_CHANNELS; j++)
03826 if (log_chn[j].buffer_handle == log_chn[i].buffer_handle)
03827 log_chn[j].buffer_handle = 0;
03828 }
03829
03830 if (log_chn[i].msg_request_id)
03831 bm_delete_request(log_chn[i].msg_request_id);
03832 #endif
03833
03834
03835 memset(&log_chn[i].handle, 0, sizeof(LOG_CHN));
03836 }
03837
03838 return SUCCESS;
03839 }
03840
03841
03842
03843 static int write_history(DWORD transition, DWORD run_number)
03844 {
03845 DWORD eb[2];
03846 eb[0] = transition;
03847 eb[1] = run_number;
03848
03849 hs_write_event(0, eb, sizeof(eb));
03850
03851 time_t now = time(NULL);
03852
03853 for (unsigned h=0; h<mh.size(); h++)
03854 mh[h]->hs_write_event("Run transitions", now, sizeof(eb), (const char*)eb);
03855
03856 return SUCCESS;
03857 }
03858
03859
03860
03861 INT tr_start(INT run_number, char *error)
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871
03872
03873
03874 {
03875 INT size, index, status;
03876 HNDLE hKeyRoot, hKeyChannel;
03877 CHN_SETTINGS *chn_settings;
03878 KEY key;
03879 BOOL write_data, tape_flag = FALSE;
03880
03881 if (verbose)
03882 printf("tr_start: run %d\n", run_number);
03883
03884
03885 odb_save("last.xml");
03886
03887 in_stop_transition = TRUE;
03888
03889 close_channels(run_number, NULL);
03890 close_buffers();
03891
03892 in_stop_transition = FALSE;
03893
03894 run_start_time = subrun_start_time = ss_time();
03895
03896
03897 size = sizeof(BOOL);
03898 write_data = TRUE;
03899 db_get_value(hDB, 0, "/Logger/Write data", &write_data, &size, TID_BOOL, TRUE);
03900
03901
03902 size = sizeof(tape_message);
03903 db_get_value(hDB, 0, "/Logger/Tape message", &tape_message, &size, TID_BOOL, TRUE);
03904
03905
03906 status = db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot);
03907 if (status != DB_SUCCESS) {
03908
03909 status = db_create_record(hDB, 0, "/Logger/Channels/0/", strcomb(chn_settings_str));
03910 if (status != DB_SUCCESS) {
03911 strcpy(error, "Cannot create channel entry in database");
03912 cm_msg(MERROR, "tr_start", error);
03913 return 0;
03914 }
03915
03916 status = db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot);
03917 if (status != DB_SUCCESS) {
03918 strcpy(error, "Cannot create channel entry in database");
03919 cm_msg(MERROR, "tr_start", error);
03920 return 0;
03921 }
03922 }
03923
03924 for (index = 0; index < MAX_CHANNELS; index++) {
03925 status = db_enum_key(hDB, hKeyRoot, index, &hKeyChannel);
03926 if (status == DB_NO_MORE_SUBKEYS)
03927 break;
03928
03929
03930 db_get_key(hDB, hKeyChannel, &key);
03931 status = db_check_record(hDB, hKeyRoot, key.name, strcomb(chn_settings_str), TRUE);
03932 if (status != DB_SUCCESS && status != DB_OPEN_RECORD) {
03933 cm_msg(MERROR, "tr_start", "Cannot create/check channel record, status %d", status);
03934 break;
03935 }
03936
03937 if (status == DB_SUCCESS || status == DB_OPEN_RECORD) {
03938
03939
03940 if (log_chn[index].handle) {
03941 log_close(&log_chn[index], run_number);
03942 if (log_chn[index].type == LOG_TYPE_DISK) {
03943 cm_msg(MINFO, "tr_start", "Deleting previous file \"%s\"", log_chn[index].path);
03944 unlink(log_chn[index].path);
03945 }
03946 }
03947
03948
03949 if (log_chn[index].ftp_con)
03950 continue;
03951
03952
03953 status = db_find_key(hDB, hKeyChannel, "Settings", &log_chn[index].settings_hkey);
03954 if (status != DB_SUCCESS) {
03955 strcpy(error, "Cannot find channel settings info");
03956 cm_msg(MERROR, "tr_start", error);
03957 return 0;
03958 }
03959
03960
03961 status = db_find_key(hDB, hKeyChannel, "Statistics", &log_chn[index].stats_hkey);
03962 if (status != DB_SUCCESS) {
03963 strcpy(error, "Cannot find channel statistics info");
03964 cm_msg(MERROR, "tr_start", error);
03965 return 0;
03966 }
03967
03968
03969 size = sizeof(CHN_STATISTICS);
03970 db_get_record(hDB, log_chn[index].stats_hkey, &log_chn[index].statistics, &size, 0);
03971
03972 log_chn[index].statistics.events_written = 0;
03973 log_chn[index].statistics.bytes_written = 0;
03974 log_chn[index].statistics.bytes_written_uncompressed = 0;
03975 log_chn[index].statistics.bytes_written_subrun = 0;
03976
03977 db_set_record(hDB, log_chn[index].stats_hkey, &log_chn[index].statistics, size, 0);
03978
03979
03980 chn_settings = &log_chn[index].settings;
03981 size = sizeof(CHN_SETTINGS);
03982 status = db_get_record(hDB, log_chn[index].settings_hkey, chn_settings, &size, 0);
03983 if (status != DB_SUCCESS) {
03984 strcpy(error, "Cannot read channel info");
03985 cm_msg(MERROR, "tr_start", error);
03986 return 0;
03987 }
03988
03989
03990 if (log_chn[index].type == LOG_TYPE_TAPE &&
03991 chn_settings->tape_capacity > 0 &&
03992 log_chn[index].statistics.bytes_written_total >= chn_settings->tape_capacity) {
03993 strcpy(error, "Tape capacity reached. Please load new tape");
03994 cm_msg(MERROR, "tr_start", error);
03995 return 0;
03996 }
03997
03998
03999 if (!chn_settings->active || !write_data)
04000 continue;
04001
04002
04003 if (equal_ustring(chn_settings->type, "Tape"))
04004 log_chn[index].type = LOG_TYPE_TAPE;
04005 else if (equal_ustring(chn_settings->type, "FTP"))
04006 log_chn[index].type = LOG_TYPE_FTP;
04007 else if (equal_ustring(chn_settings->type, "Disk"))
04008 log_chn[index].type = LOG_TYPE_DISK;
04009 else {
04010 sprintf(error,
04011 "Invalid channel type \"%s\", pease use \"Tape\", \"FTP\" or \"Disk\"",
04012 chn_settings->type);
04013 cm_msg(MERROR, "tr_start", error);
04014 return 0;
04015 }
04016
04017
04018 log_chn[index].compression = 0;
04019 size = sizeof(log_chn[index].compression);
04020 status = db_get_value(hDB, log_chn[index].settings_hkey, "Compression", &log_chn[index].compression, &size, TID_INT, FALSE);
04021
04022
04023 log_chn[index].subrun_number = 0;
04024
04025 log_generate_file_name(&log_chn[index]);
04026
04027 if (log_chn[index].type == LOG_TYPE_TAPE &&
04028 log_chn[index].statistics.bytes_written_total == 0 && tape_message) {
04029 tape_flag = TRUE;
04030 cm_msg(MTALK, "tr_start", "mounting tape #%d, please wait", index);
04031 }
04032
04033
04034 status = log_open(&log_chn[index], run_number);
04035
04036
04037 if (status != SS_SUCCESS) {
04038 if (status == SS_FILE_ERROR)
04039 sprintf(error, "Cannot open file \'%s\' (See messages)", log_chn[index].path);
04040 if (status == SS_FILE_EXISTS)
04041 sprintf(error, "File \'%s\' exists already, run start aborted", log_chn[index].path);
04042 if (status == SS_NO_TAPE)
04043 sprintf(error, "No tape in device \'%s\'", log_chn[index].path);
04044 if (status == SS_TAPE_ERROR)
04045 sprintf(error, "Tape error, cannot start run");
04046 if (status == SS_DEV_BUSY)
04047 sprintf(error, "Device \'%s\' used by someone else", log_chn[index].path);
04048 if (status == FTP_NET_ERROR || status == FTP_RESPONSE_ERROR)
04049 sprintf(error, "Cannot open FTP channel to \'%s\'", log_chn[index].path);
04050 if (status == SS_NO_ROOT)
04051 sprintf(error, "No ROOT support compiled into mlogger, please compile with -DHAVE_ROOT flag");
04052
04053 if (status == SS_INVALID_FORMAT)
04054 sprintf(error,
04055 "Invalid data format, please use \"MIDAS\", \"ASCII\", \"DUMP\" or \"ROOT\"");
04056
04057 cm_msg(MERROR, "tr_start", error);
04058 return 0;
04059 }
04060
04061
04062 if (log_chn[index].stats_hkey)
04063 db_close_record(hDB, log_chn[index].stats_hkey);
04064 if (log_chn[index].settings_hkey)
04065 db_close_record(hDB, log_chn[index].settings_hkey);
04066
04067
04068 status =
04069 db_open_record(hDB, log_chn[index].stats_hkey, &log_chn[index].statistics,
04070 sizeof(CHN_STATISTICS), MODE_WRITE, NULL, NULL);
04071 if (status != DB_SUCCESS)
04072 cm_msg(MERROR, "tr_start", "cannot open statistics record, probably other logger is using it");
04073
04074
04075 status =
04076 db_open_record(hDB, log_chn[index].settings_hkey, &log_chn[index].settings,
04077 sizeof(CHN_SETTINGS), MODE_READ, NULL, NULL);
04078 if (status != DB_SUCCESS)
04079 cm_msg(MERROR, "tr_start",
04080 "cannot open channel settings record, probably other logger is using it");
04081
04082 #ifndef FAL_MAIN
04083
04084 status = bm_open_buffer(chn_settings->buffer, 2 * MAX_EVENT_SIZE, &log_chn[index].buffer_handle);
04085 if (status != BM_SUCCESS && status != BM_CREATED) {
04086 sprintf(error, "Cannot open buffer %s", chn_settings->buffer);
04087 cm_msg(MERROR, "tr_start", error);
04088 return 0;
04089 }
04090 bm_set_cache_size(log_chn[index].buffer_handle, 100000, 0);
04091
04092
04093 status = bm_request_event(log_chn[index].buffer_handle,
04094 (short) chn_settings->event_id,
04095 (short) chn_settings->trigger_mask,
04096 GET_ALL, &log_chn[index].request_id, receive_event);
04097
04098 if (status != BM_SUCCESS) {
04099 sprintf(error, "Cannot place event request");
04100 cm_msg(MERROR, "tr_start", error);
04101 return 0;
04102 }
04103
04104
04105 if (chn_settings->log_messages) {
04106 status =
04107 bm_open_buffer(MESSAGE_BUFFER_NAME, MESSAGE_BUFFER_SIZE, &log_chn[index].msg_buffer_handle);
04108 if (status != BM_SUCCESS && status != BM_CREATED) {
04109 sprintf(error, "Cannot open buffer %s", MESSAGE_BUFFER_NAME);
04110 cm_msg(MERROR, "tr_start", error);
04111 return 0;
04112 }
04113
04114
04115 status = bm_request_event(log_chn[index].msg_buffer_handle,
04116 (short) EVENTID_MESSAGE,
04117 (short) chn_settings->log_messages,
04118 GET_ALL, &log_chn[index].msg_request_id, receive_event);
04119
04120 if (status != BM_SUCCESS) {
04121 sprintf(error, "Cannot place event request");
04122 cm_msg(MERROR, "tr_start", error);
04123 return 0;
04124 }
04125 }
04126 #endif
04127 }
04128 }
04129
04130 if (tape_flag && tape_message)
04131 cm_msg(MTALK, "tr_start", "tape mounting finished");
04132
04133
04134 close_history();
04135 status = open_history();
04136 if (status != CM_SUCCESS) {
04137 sprintf(error, "Error in history system, aborting run start");
04138 cm_msg(MERROR, "tr_start", error);
04139 return 0;
04140 }
04141
04142
04143 write_history(STATE_RUNNING, run_number);
04144
04145
04146 #ifdef HAVE_MYSQL
04147
04148 write_sql(TRUE);
04149 #endif
04150
04151 local_state = STATE_RUNNING;
04152 run_start_time = subrun_start_time = ss_time();
04153
04154 return CM_SUCCESS;
04155 }
04156
04157
04158
04159 INT tr_start_abort(INT run_number, char *error)
04160 {
04161 int i;
04162
04163 if (verbose)
04164 printf("tr_start_abort: run %d\n", run_number);
04165
04166 in_stop_transition = TRUE;
04167
04168 for (i = 0; i < MAX_CHANNELS; i++)
04169 if (log_chn[i].handle && log_chn[i].type == LOG_TYPE_DISK) {
04170 cm_msg(MINFO, "tr_start_abort", "Deleting previous file \"%s\"", log_chn[i].path);
04171 unlink(log_chn[i].path);
04172 }
04173
04174 close_channels(run_number, NULL);
04175 close_buffers();
04176
04177 in_stop_transition = FALSE;
04178
04179 local_state = STATE_STOPPED;
04180
04181 return CM_SUCCESS;
04182 }
04183
04184
04185
04186 INT tr_stop(INT run_number, char *error)
04187
04188
04189
04190
04191
04192
04193
04194 {
04195 INT size;
04196 BOOL flag, tape_flag = FALSE;
04197 char filename[256];
04198 char str[256];
04199
04200 if (verbose)
04201 printf("tr_stop: run %d\n", run_number);
04202
04203 if (in_stop_transition)
04204 return CM_SUCCESS;
04205
04206 in_stop_transition = TRUE;
04207
04208 close_channels(run_number, &tape_flag);
04209 close_buffers();
04210
04211
04212 size = sizeof(flag);
04213 flag = 0;
04214 db_get_value(hDB, 0, "/Logger/ODB Dump", &flag, &size, TID_BOOL, TRUE);
04215 if (flag) {
04216 strcpy(str, "run%d.odb");
04217 size = sizeof(str);
04218 str[0] = 0;
04219 db_get_value(hDB, 0, "/Logger/ODB Dump File", str, &size, TID_STRING, TRUE);
04220 if (str[0] == 0)
04221 strcpy(str, "run%d.odb");
04222
04223
04224 if (strchr(str, '%'))
04225 sprintf(filename, str, run_number);
04226 else
04227 strcpy(filename, str);
04228
04229 odb_save(filename);
04230 }
04231 #ifdef HAVE_MYSQL
04232
04233 write_sql(FALSE);
04234 #endif
04235
04236 in_stop_transition = FALSE;
04237
04238 if (tape_flag & tape_message)
04239 cm_msg(MTALK, "tr_stop", "all tape channels closed");
04240
04241
04242 write_history(STATE_STOPPED, run_number);
04243
04244
04245 stop_requested = FALSE;
04246
04247 if (start_requested) {
04248 int delay = 0;
04249 size = sizeof(delay);
04250 db_get_value(hDB, 0, "/Logger/Auto restart delay", &delay, &size, TID_INT, TRUE);
04251 auto_restart = ss_time() + delay;
04252 start_requested = FALSE;
04253 }
04254
04255 local_state = STATE_STOPPED;
04256
04257 return CM_SUCCESS;
04258 }
04259
04260
04261
04262
04263
04264 INT tr_pause(INT run_number, char *error)
04265 {
04266
04267 write_history(STATE_PAUSED, run_number);
04268
04269 local_state = STATE_PAUSED;
04270
04271 return CM_SUCCESS;
04272 }
04273
04274 INT tr_resume(INT run_number, char *error)
04275 {
04276
04277 write_history(STATE_RUNNING, run_number);
04278
04279 local_state = STATE_RUNNING;
04280
04281 return CM_SUCCESS;
04282 }
04283
04284
04285
04286 void receive_event(HNDLE hBuf, HNDLE request_id, EVENT_HEADER * pheader, void *pevent)
04287 {
04288 INT i;
04289
04290 if (verbose)
04291 printf("write data event: req %d, evid %d, timestamp %d, size %d\n", request_id, pheader->event_id, pheader->time_stamp, pheader->data_size);
04292
04293
04294 for (i = 0; i < MAX_CHANNELS; i++) {
04295 if (log_chn[i].handle == 0 && log_chn[i].ftp_con == NULL)
04296 continue;
04297
04298
04299 if (log_chn[i].request_id == request_id) {
04300 log_write(&log_chn[i], pheader);
04301 break;
04302 }
04303
04304
04305 if (log_chn[i].msg_request_id == request_id) {
04306 log_write(&log_chn[i], pheader);
04307 break;
04308 }
04309 }
04310 }
04311
04312
04313
04314 int main(int argc, char *argv[])
04315 {
04316 INT status, msg, i, size, ch = 0;
04317 char host_name[HOST_NAME_LENGTH], exp_name[NAME_LENGTH], dir[256];
04318 BOOL debug, daemon, save_mode;
04319 DWORD last_time_kb = 0;
04320 DWORD last_time_stat = 0;
04321 DWORD duration;
04322 HNDLE hktemp;
04323
04324 #ifdef HAVE_ROOT
04325 char **rargv;
04326 int rargc;
04327
04328
04329 rargc = 0;
04330 rargv = (char **) malloc(sizeof(char *) * 2);
04331 rargv[rargc] = (char *) malloc(strlen(argv[rargc]) + 1);
04332 strcpy(rargv[rargc], argv[rargc]);
04333 rargc++;
04334
04335
04336 rargv[rargc++] = "-b";
04337
04338 TApplication theApp("mlogger", &rargc, rargv);
04339
04340
04341 free(rargv[0]);
04342 free(rargv);
04343
04344 #endif
04345
04346 setbuf(stdout, NULL);
04347 setbuf(stderr, NULL);
04348
04349
04350 cm_get_environment(host_name, sizeof(host_name), exp_name, sizeof(exp_name));
04351
04352 debug = daemon = save_mode = FALSE;
04353
04354
04355 for (i = 1; i < argc; i++) {
04356 if (argv[i][0] == '-' && argv[i][1] == 'd')
04357 debug = TRUE;
04358 else if (argv[i][0] == '-' && argv[i][1] == 'D')
04359 daemon = TRUE;
04360 else if (argv[i][0] == '-' && argv[i][1] == 's')
04361 save_mode = TRUE;
04362 else if (argv[i][0] == '-' && argv[i][1] == 'v')
04363 verbose = TRUE;
04364 else if (argv[i][0] == '-') {
04365 if (i + 1 >= argc || argv[i + 1][0] == '-')
04366 goto usage;
04367 if (argv[i][1] == 'e')
04368 strcpy(exp_name, argv[++i]);
04369 else {
04370 usage:
04371 printf("usage: mlogger [-e Experiment] [-d] [-D] [-s] [-v]\n\n");
04372 return 1;
04373 }
04374 }
04375 }
04376
04377 if (daemon) {
04378 printf("Becoming a daemon...\n");
04379 ss_daemon_init(FALSE);
04380 }
04381
04382 status = cm_connect_experiment(host_name, exp_name, "Logger", NULL);
04383 if (status != CM_SUCCESS)
04384 return 1;
04385
04386
04387 status = cm_exist("Logger", FALSE);
04388 if (status == CM_SUCCESS) {
04389 printf("Logger runs already.\n");
04390 cm_disconnect_experiment();
04391 return 1;
04392 }
04393
04394 cm_get_experiment_database(&hDB, NULL);
04395
04396
04397 cm_set_watchdog_params(TRUE, LOGGER_TIMEOUT);
04398
04399
04400 if (debug)
04401 cm_set_watchdog_params(TRUE, 0);
04402
04403
04404 if (save_mode) {
04405 cm_set_watchdog_params(FALSE, 0);
04406 db_protect_database(hDB);
04407 }
04408
04409
04410 if (cm_register_transition(TR_START, tr_start, 200) != CM_SUCCESS) {
04411 cm_msg(MERROR, "main", "cannot register callbacks");
04412 return 1;
04413 }
04414
04415 cm_register_transition(TR_STARTABORT, tr_start_abort, 800);
04416 cm_register_transition(TR_STOP, tr_stop, 800);
04417 cm_register_transition(TR_PAUSE, tr_pause, 800);
04418 cm_register_transition(TR_RESUME, tr_resume, 200);
04419
04420
04421 cm_register_function(RPC_LOG_REWIND, log_callback);
04422
04423
04424 logger_init();
04425
04426
04427 local_state = STATE_STOPPED;
04428 size = sizeof(local_state);
04429 status = db_get_value(hDB, 0, "/Runinfo/State", &local_state, &size, TID_INT, true);
04430
04431
04432 if (open_history() != CM_SUCCESS) {
04433 printf("Error in history system, aborting startup.\n");
04434 cm_disconnect_experiment();
04435 return 1;
04436 }
04437
04438
04439 cm_set_msg_print(MT_ALL, 0, NULL);
04440
04441
04442 size = sizeof(dir);
04443 db_get_value(hDB, 0, "/Logger/Data dir", dir, &size, TID_STRING, TRUE);
04444 printf("Log directory is %s\n", dir);
04445 printf("Data directory is same as Log unless specified in channels/\n");
04446
04447
04448 size = sizeof(dir);
04449 dir[0] = 0;
04450 status = db_find_key(hDB, 0, "/Logger/History dir", &hktemp);
04451 if (status == DB_SUCCESS)
04452 db_get_value(hDB, 0, "/Logger/History dir", dir, &size, TID_STRING, TRUE);
04453 else
04454 sprintf(dir, "same as Log");
04455 printf("History directory is %s\n", dir);
04456
04457 size = sizeof(dir);
04458 dir[0] = 0;
04459 status = db_find_key(hDB, 0, "/Logger/Elog dir", &hktemp);
04460 if (status == DB_SUCCESS)
04461 db_get_value(hDB, 0, "/Logger/Elog dir", dir, &size, TID_STRING, TRUE);
04462 else
04463 sprintf(dir, "same as Log");
04464 printf("ELog directory is %s\n", dir);
04465
04466 #ifdef HAVE_MYSQL
04467 {
04468 char sql_host[256], sql_db[256], sql_table[256];
04469
04470 status = db_find_key(hDB, 0, "/Logger/SQL/Hostname", &hktemp);
04471 if (status == DB_SUCCESS) {
04472 size = 256;
04473 db_get_value(hDB, 0, "/Logger/SQL/Hostname", sql_host, &size, TID_STRING, FALSE);
04474 size = 256;
04475 db_get_value(hDB, 0, "/Logger/SQL/Database", sql_db, &size, TID_STRING, FALSE);
04476 size = 256;
04477 db_get_value(hDB, 0, "/Logger/SQL/Table", sql_table, &size, TID_STRING, FALSE);
04478 printf("SQL database is %s/%s/%s", sql_host, sql_db, sql_table);
04479 }
04480 }
04481 #endif
04482
04483 printf("\nMIDAS logger started. Stop with \"!\"\n");
04484
04485
04486 ss_getchar(0);
04487
04488 do {
04489 msg = cm_yield(1000);
04490
04491
04492 if (ss_millitime() - last_time_stat > 1000) {
04493 last_time_stat = ss_millitime();
04494 db_send_changed_records();
04495 }
04496
04497
04498 if (auto_restart && ss_time() > auto_restart) {
04499 status = start_the_run();
04500 }
04501
04502
04503 duration = 0;
04504 size = sizeof(duration);
04505 db_get_value(hDB, 0, "/Logger/Run duration", &duration, &size, TID_DWORD, true);
04506 if (!stop_requested && !in_stop_transition && local_state != STATE_STOPPED &&
04507 duration > 0 && ss_time() >= run_start_time + duration) {
04508 cm_msg(MTALK, "main", "stopping run after %d seconds", duration);
04509 status = stop_the_run(1);
04510 }
04511
04512
04513 if (ss_millitime() - last_time_kb > 1000) {
04514 last_time_kb = ss_millitime();
04515
04516 ch = 0;
04517 while (ss_kbhit()) {
04518 ch = ss_getchar(0);
04519 if (ch == -1)
04520 ch = getchar();
04521
04522 if ((char) ch == '!')
04523 break;
04524 }
04525 }
04526
04527 } while (msg != RPC_SHUTDOWN && msg != SS_ABORT && ch != '!');
04528
04529
04530 ss_getchar(TRUE);
04531
04532
04533 close_history();
04534
04535 cm_disconnect_experiment();
04536
04537 return 0;
04538 }