MIDAS
Loading...
Searching...
No Matches
Midas History Functions (hs_xxx)

Classes

class  MidasHistory
 

Macros

#define HISTORY_PANEL(_name)
 

Functions

static bool xwrite (const std::string &fn, int fh, const void *buf, size_t count)
 
static int xread (const std::string &fn, int fh, void *buf, size_t count, bool eof_ok=false)
 
static bool xseek (const std::string &fn, int fh, DWORD pos)
 
static bool xseek_end (const std::string &fn, int fh)
 
static bool xseek_cur (const std::string &fn, int fh, int offset)
 
static DWORD xcurpos (const std::string &fn, int fh)
 
static bool xtruncate (const std::string &fn, int fh, DWORD pos)
 
static INT hs_set_path (const char *path)
 
static INT hs_open_file (time_t ltime, const char *suffix, INT mode, std::string *pfile_name, int *fh)
 
static INT hs_gen_index (DWORD ltime)
 
static INT hs_search_file (DWORD *ltime, INT direction)
 
static INT hs_define_event (DWORD event_id, const char *name, const TAG *tag, DWORD size)
 
static INT hs_write_event (DWORD event_id, const void *data, DWORD size)
 
static INT hs_enum_events (DWORD ltime, char *event_name, DWORD *name_size, INT event_id[], DWORD *id_size)
 
static INT hs_count_events (DWORD ltime, DWORD *count)
 
static INT hs_get_event_id (DWORD ltime, const char *name, DWORD *id)
 
static INT hs_count_vars (DWORD ltime, DWORD event_id, DWORD *count)
 
static INT hs_enum_vars (DWORD ltime, DWORD event_id, char *var_name, DWORD *size, DWORD *var_n, DWORD *n_size)
 
static INT hs_get_var (DWORD ltime, DWORD event_id, const char *var_name, DWORD *type, INT *n_data)
 
static INT hs_get_tags (DWORD ltime, DWORD event_id, char event_name[NAME_LENGTH], int *n_tags, TAG **tags)
 
double hs_to_double (int tid, const void *ybuffer)
 
static INT hs_read (DWORD event_id, DWORD start_time, DWORD end_time, DWORD interval, const char *tag_name, DWORD var_index, DWORD *time_buffer, DWORD *tbsize, void *data_buffer, DWORD *dbsize, DWORD *data_type, DWORD *data_n, MidasHistoryBufferInterface *buffer)
 
static INT hs_dump (DWORD event_id, DWORD start_time, DWORD end_time, DWORD interval, BOOL binary_time)
 
 MidasHistory::MidasHistory ()
 
 MidasHistory::~MidasHistory ()
 
int MidasHistory::hs_connect (const char *path)
 returns HS_SUCCESS
 
int MidasHistory::hs_disconnect ()
 disconnect from history, returns HS_SUCCESS
 
int MidasHistory::hs_set_debug (int debug)
 set debug level, returns previous debug level
 
int MidasHistory::hs_clear_cache ()
 clear internal cache, returns HS_SUCCESS
 
int MidasHistory::FindEventId (const char *event_name)
 
int MidasHistory::AllocateEventId (const char *event_name)
 
int MidasHistory::CreateOdbTags (int event_id, const char *event_name, int ntags, const TAG tags[])
 
int MidasHistory::hs_define_event (const char *event_name, time_t timestamp, int ntags, const TAG tags[])
 see hs_define_event(), returns HS_SUCCESS or HS_FILE_ERROR
 
int MidasHistory::hs_write_event (const char *event_name, time_t timestamp, int data_size, const char *data)
 see hs_write_event(), returns HS_SUCCESS or HS_FILE_ERROR
 
int MidasHistory::hs_flush_buffers ()
 flush buffered data to storage where it is visible to mhttpd
 
int MidasHistory::GetEventsFromOdbEvents (std::vector< std::string > *events)
 
int MidasHistory::GetEventsFromOdbTags (std::vector< std::string > *events)
 
int MidasHistory::hs_get_events (time_t t, std::vector< std::string > *pevents)
 get list of events that exist(ed) at given time and later (value 0 means "return all events from beginning of time"), returns HS_SUCCESS
 
int MidasHistory::GetEventIdFromHS (time_t ltime, const char *evname, const char *tagname)
 
int MidasHistory::GetEventIdFromOdbTags (const char *evname, const char *tagname)
 
int MidasHistory::GetEventId (time_t t, const char *event_name, const char *tag_name, int *pevid)
 
int MidasHistory::GetTagsFromHS (const char *event_name, std::vector< TAG > *ptags)
 
int MidasHistory::GetTagsFromOdb (const char *event_name, std::vector< TAG > *ptags)
 
int MidasHistory::hs_get_tags (const char *event_name, time_t t, std::vector< TAG > *ptags)
 get list of history variables for given event (use event names returned by hs_get_events()) that exist(ed) at given time and later (value 0 means "all variables for this event that ever existed"), also see hs_get_tags(), returns HS_SUCCESS
 
int MidasHistory::hs_get_last_written (time_t start_time, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], time_t last_written[])
 
int MidasHistory::hs_read (time_t start_time, time_t end_time, time_t interval, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], int num_entries[], time_t *time_buffer[], double *data_buffer[], int read_status[])
 see hs_read(), returns HS_SUCCESS
 
int MidasHistory::hs_read_buffer (time_t start_time, time_t end_time, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], MidasHistoryBufferInterface *buffer[], int read_status[])
 returns HS_SUCCESS
 
int MidasHistory::hs_read_binned (time_t start_time, time_t end_time, int num_bins, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], int num_entries[], int *count_bins[], double *mean_bins[], double *rms_bins[], double *min_bins[], double *max_bins[], time_t *bins_first_time[], double *bins_first_value[], time_t *bins_last_time[], double *bins_last_value[], time_t last_time[], double last_value[], int read_status[])
 returns HS_SUCCESS
 
INT hs_define_panel (const char *group, const char *panel, const std::vector< std::string > var)
 
INT hs_define_panel2 (const char *group, const char *panel, const std::vector< std::string > var, const std::vector< std::string > label, const std::vector< std::string > formula, const std::vector< std::string > color)
 
MidasHistoryInterfaceMakeMidasHistory ()
 

Variables

static std::vector< HISTORY * > _history
 
static std::string _hs_path_name
 
HNDLE MidasHistory::fDB
 
int MidasHistory::fDebug
 
std::vector< std::string > MidasHistory::fEventsCache
 
std::map< std::string, std::vector< TAG > > MidasHistory::fTagsCache
 
std::map< std::string, intMidasHistory::fEvidCache
 

Detailed Description

dox


Macro Definition Documentation

◆ HISTORY_PANEL

#define HISTORY_PANEL (   _name)
Value:
const char *_name[] = {\
"[.]",\
"Variables = STRING : [64] :",\
"Timescale = STRING : [32] 10m",\
"Zero ylow = BOOL : n",\
"Show run markers = BOOL : y",\
"Buttons = STRING[7] :",\
"[32] 10m",\
"[32] 1h",\
"[32] 3h",\
"[32] 12h",\
"[32] 24h",\
"[32] 3d",\
"[32] 7d",\
"Log axis = BOOL : n",\
"Show values = BOOL : y",\
"Sort vars = BOOL : n",\
"Show old vars = BOOL : n",\
"Minimum = FLOAT : -inf",\
"Maximum = FLOAT : inf",\
"Label = STRING : [32] ",\
"Colour = STRING : [32] ",\
"Formula = STRING : [64] ",\
"Show fill = BOOL : y",\
"",\
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24

Define history panel in ODB with certain variables and default values for everything else

Parameters
groupHistory group name
panelHistoryh panel name
varVector of variables
Returns
HS_SUCCESS

Definition at line 3464 of file history.cxx.

3464 {\
3465"[.]",\
3466"Variables = STRING : [64] :",\
3467"Timescale = STRING : [32] 10m",\
3468"Zero ylow = BOOL : n",\
3469"Show run markers = BOOL : y",\
3470"Buttons = STRING[7] :",\
3471"[32] 10m",\
3472"[32] 1h",\
3473"[32] 3h",\
3474"[32] 12h",\
3475"[32] 24h",\
3476"[32] 3d",\
3477"[32] 7d",\
3478"Log axis = BOOL : n",\
3479"Show values = BOOL : y",\
3480"Sort vars = BOOL : n",\
3481"Show old vars = BOOL : n",\
3482"Minimum = FLOAT : -inf",\
3483"Maximum = FLOAT : inf",\
3484"Label = STRING : [32] ",\
3485"Colour = STRING : [32] ",\
3486"Formula = STRING : [64] ",\
3487"Show fill = BOOL : y",\
3488"",\
3489NULL }

Function Documentation

◆ MidasHistory()

MidasHistory::MidasHistory ( )
inline

Definition at line 2228 of file history.cxx.

2229 {
2230 fDebug = 0;
2231 }

◆ ~MidasHistory()

MidasHistory::~MidasHistory ( )
inline

Definition at line 2233 of file history.cxx.

2234 {
2235 // empty
2236 }

◆ AllocateEventId()

int MidasHistory::AllocateEventId ( const char event_name)
inline

Definition at line 2339 of file history.cxx.

2340 {
2341 int status;
2342 char name[256];
2343 mstrlcpy(name, event_name, sizeof(name));
2344 char *s = strchr(name, '/');
2345 if (s)
2346 *s = ':';
2347
2348 // special event id for run transitions
2349 if (strcmp(name, "Run transitions")==0) {
2350 status = db_set_value(fDB, 0, "/History/Events/0", name, strlen(name)+1, 1, TID_STRING);
2351 assert(status == DB_SUCCESS);
2352 return 0;
2353 }
2354
2355 if (1) {
2356 std::string tmp = msprintf("/Equipment/%s/Common/Event ID", name);
2357
2358 WORD evid = 0;
2359 int size = sizeof(evid);
2360 status = db_get_value(fDB, 0, tmp.c_str(), &evid, &size, TID_WORD, FALSE);
2361 if (status == DB_SUCCESS) {
2362
2363 std::string he = msprintf("/History/Events/%d", evid);
2364
2365 std::string xname;
2366 status = db_get_value_string(fDB, 0, he.c_str(), 0, &xname);
2367 if (status == DB_SUCCESS && xname != event_name) {
2368 cm_msg(MERROR, "add_event", "History events \"%s\" and \"%s\" use the same history event id %d. If both equipments write to the history, their data will be mixed up. To fix this, enable per-variable history, turn off the \"MIDAS\" history (use \"FILE\" history) or change event IDs or set \"common/log history\" to zero", event_name, xname.c_str(), evid);
2369 }
2370
2371 status = db_set_value(fDB, 0, he.c_str(), name, strlen(name)+1, 1, TID_STRING);
2372 assert(status == DB_SUCCESS);
2373
2374 //printf("AllocateEventId: event [%s] allocated common/event id %d\n", event_name, evid);
2375
2376 return evid;
2377 }
2378 }
2379
2380 for (int evid = 101; evid < 65000; evid++) {
2381 char tmp[256];
2382 HNDLE hKey;
2383
2384 sprintf(tmp,"/History/Events/%d", evid);
2385
2386 status = db_find_key(fDB, 0, tmp, &hKey);
2387 if (status != DB_SUCCESS) {
2388
2390 assert(status == DB_SUCCESS);
2391
2392 //printf("AllocateEventId: event [%s] allocated next sequential id %d\n", event_name, evid);
2393
2394 return evid;
2395 }
2396 }
2397
2398 cm_msg(MERROR, "AllocateEventId", "Cannot allocate history event id - all in use - please examine /History/Events");
2399 return -1;
2400 }
#define FALSE
Definition cfortran.h:309
char name[NAME_LENGTH]
Definition history.h:111
#define DB_SUCCESS
Definition midas.h:631
unsigned short int WORD
Definition mcstd.h:49
#define TID_WORD
Definition midas.h:332
#define TID_STRING
Definition midas.h:346
#define MERROR
Definition midas.h:559
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:915
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
Definition odb.cxx:5415
INT EXPRT db_get_value_string(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, int index, std::string *s, BOOL create, int create_string_length)
Definition odb.cxx:13934
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
Definition odb.cxx:5261
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4079
HNDLE hKey
std::string msprintf(const char *format,...)
Definition midas.cxx:410
INT HNDLE
Definition midas.h:132
DWORD status
Definition odbhist.cxx:39
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CreateOdbTags()

int MidasHistory::CreateOdbTags ( int  event_id,
const char event_name,
int  ntags,
const TAG  tags[] 
)
inline

Definition at line 2404 of file history.cxx.

2405 {
2406 int disableTags;
2407 int oldTags;
2408 int size, status;
2409
2410 /* create history tags for mhttpd */
2411
2412 disableTags = 0;
2413 size = sizeof(disableTags);
2414 status = db_get_value(fDB, 0, "/History/DisableTags", &disableTags, &size, TID_BOOL, TRUE);
2415
2416 oldTags = 0;
2417 size = sizeof(oldTags);
2418 status = db_get_value(fDB, 0, "/History/CreateOldTags", &oldTags, &size, TID_BOOL, FALSE);
2419
2420 if (disableTags) {
2421 HNDLE hKey;
2422
2423 status = db_find_key(fDB, 0, "/History/Tags", &hKey);
2424 if (status == DB_SUCCESS) {
2426 if (status != DB_SUCCESS)
2427 cm_msg(MERROR, "add_event", "Cannot delete /History/Tags, db_delete_key() status %d", status);
2428 }
2429
2430 } else if (oldTags) {
2431
2432 char buf[256];
2433
2434 sprintf(buf, "/History/Tags/%d", event_id);
2435
2436 //printf("Set tag \'%s\' = \'%s\'\n", buf, event_name);
2437
2438 status = db_set_value(fDB, 0, buf, (void*)event_name, strlen(event_name)+1, 1, TID_STRING);
2439 assert(status == DB_SUCCESS);
2440
2441 for (int i=0; i<ntags; i++) {
2442 WORD v = (WORD) tags[i].n_data;
2443 sprintf(buf, "/History/Tags/Tags %d/%s", event_id, tags[i].name);
2444
2445 //printf("Set tag \'%s\' = %d\n", buf, v);
2446
2447 status = db_set_value(fDB, 0, buf, &v, sizeof(v), 1, TID_WORD);
2448 assert(status == DB_SUCCESS);
2449
2450 if (strlen(tags[i].name) == NAME_LENGTH-1)
2451 cm_msg(MERROR, "add_event",
2452 "Tag name \'%s\' in event %d (%s) may have been truncated to %d characters",
2453 tags[i].name, event_id, event_name, NAME_LENGTH-1);
2454 }
2455
2456 } else {
2457
2458 const int kLength = 32 + NAME_LENGTH + NAME_LENGTH;
2459 char buf[kLength];
2460 HNDLE hKey;
2461
2462 sprintf(buf, "/History/Tags/%d", event_id);
2463 status = db_find_key(fDB, 0, buf, &hKey);
2464
2465 if (status == DB_SUCCESS) {
2466 // add new tags
2467 KEY key;
2468
2470 assert(status == DB_SUCCESS);
2471
2472 assert(key.type == TID_STRING);
2473
2474 if (key.item_size < kLength && key.num_values == 1) {
2475 // old style tags are present. Convert them to new style!
2476
2477 HNDLE hTags;
2478
2479 cm_msg(MINFO, "add_event", "Converting old event %d (%s) tags to new style", event_id, event_name);
2480
2481 mstrlcpy(buf, event_name, kLength);
2482
2484 assert(status == DB_SUCCESS);
2485
2486 sprintf(buf, "/History/Tags/Tags %d", event_id);
2487
2488 status = db_find_key(fDB, 0, buf, &hTags);
2489
2490 if (status == DB_SUCCESS) {
2491 for (int i=0; ; i++) {
2492 HNDLE h;
2493 int size;
2494 KEY key;
2495 WORD w;
2496
2497 status = db_enum_key(fDB, hTags, i, &h);
2499 break;
2500 assert(status == DB_SUCCESS);
2501
2502 status = db_get_key(fDB, h, &key);
2503
2504 size = sizeof(w);
2505 status = db_get_data(fDB, h, &w, &size, TID_WORD);
2506 assert(status == DB_SUCCESS);
2507
2508 sprintf(buf, "%d[%d] %s", 0, w, key.name);
2509
2511 assert(status == DB_SUCCESS);
2512 }
2513
2515 assert(status == DB_SUCCESS);
2516 }
2517
2518 // format conversion has changed the key, get it again
2520 assert(status == DB_SUCCESS);
2521 }
2522
2523 if (1) {
2524 // add new tags
2525
2526 int size = key.item_size * key.num_values;
2527 int num = key.num_values;
2528
2529 char* s = (char*)malloc(size);
2530 assert(s != NULL);
2531
2532 TAG* t = (TAG*)malloc(sizeof(TAG)*(key.num_values + ntags));
2533 assert(t != NULL);
2534
2535 status = db_get_data(fDB, hKey, s, &size, TID_STRING);
2536 assert(status == DB_SUCCESS);
2537
2538 for (int i=1; i<key.num_values; i++) {
2539 char* ss = s + i*key.item_size;
2540
2541 t[i].type = 0;
2542 t[i].n_data = 0;
2543 t[i].name[0] = 0;
2544
2545 if (isdigit(ss[0])) {
2546 //sscanf(ss, "%d[%d] %s", &t[i].type, &t[i].n_data, t[i].name);
2547
2548 t[i].type = strtoul(ss, &ss, 0);
2549 assert(*ss == '[');
2550 ss++;
2551 t[i].n_data = strtoul(ss, &ss, 0);
2552 assert(*ss == ']');
2553 ss++;
2554 assert(*ss == ' ');
2555 ss++;
2556 mstrlcpy(t[i].name, ss, sizeof(t[i].name));
2557
2558 //printf("type %d, n_data %d, name [%s]\n", t[i].type, t[i].n_data, t[i].name);
2559 }
2560 }
2561
2562 for (int i=0; i<ntags; i++) {
2563 int k = 0;
2564
2565 for (int j=1; j<key.num_values; j++) {
2566 if (equal_ustring((char*)tags[i].name, (char*)t[j].name)) {
2567 if ((tags[i].type!=t[j].type) || (tags[i].n_data!=t[j].n_data)) {
2568 cm_msg(MINFO, "add_event", "Event %d (%s) tag \"%s\" type and size changed from %d[%d] to %d[%d]",
2569 event_id, event_name,
2570 tags[i].name,
2571 t[j].type, t[j].n_data,
2572 tags[i].type, tags[i].n_data);
2573 k = j;
2574 break;
2575 }
2576
2577 k = -1;
2578 break;
2579 }
2580 }
2581
2582 // if tag not present, k==0, so append it to the array
2583
2584 if (k==0)
2585 k = num;
2586
2587 if (k > 0) {
2588 sprintf(buf, "%d[%d] %s", tags[i].type, tags[i].n_data, tags[i].name);
2589
2591 assert(status == DB_SUCCESS);
2592
2593 if (k >= num)
2594 num = k+1;
2595 }
2596 }
2597
2598 free(s);
2599 free(t);
2600 }
2601
2602 } else if (status == DB_NO_KEY) {
2603 // create new array of tags
2604 status = db_create_key(fDB, 0, buf, TID_STRING);
2605 assert(status == DB_SUCCESS);
2606
2607 status = db_find_key(fDB, 0, buf, &hKey);
2608 assert(status == DB_SUCCESS);
2609
2610 mstrlcpy(buf, event_name, kLength);
2611
2613 assert(status == DB_SUCCESS);
2614
2615 for (int i=0; i<ntags; i++) {
2616 sprintf(buf, "%d[%d] %s", tags[i].type, tags[i].n_data, tags[i].name);
2617
2619 assert(status == DB_SUCCESS);
2620 }
2621 } else {
2622 cm_msg(MERROR, "add_event", "Error: db_find_key(%s) status %d", buf, status);
2623 return HS_FILE_ERROR;
2624 }
2625 }
2626
2627 return HS_SUCCESS;
2628 }
char type[NAME_LENGTH]
history channel name
Definition history.h:112
#define DB_NO_KEY
Definition midas.h:642
#define DB_NO_MORE_SUBKEYS
Definition midas.h:646
#define HS_SUCCESS
Definition midas.h:727
#define HS_FILE_ERROR
Definition midas.h:728
#define TID_BOOL
Definition midas.h:340
#define MINFO
Definition midas.h:560
BOOL equal_ustring(const char *str1, const char *str2)
Definition odb.cxx:3201
INT db_delete_key(HNDLE hDB, HNDLE hKey, BOOL follow_links)
Definition odb.cxx:3856
INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
Definition odb.cxx:6539
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
Definition odb.cxx:3308
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
Definition odb.cxx:6019
INT db_set_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
Definition odb.cxx:7648
INT db_set_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
Definition odb.cxx:7215
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5586
KEY key
Definition mdump.cxx:34
INT i
Definition mdump.cxx:32
#define TRUE
Definition midas.h:182
#define NAME_LENGTH
Definition midas.h:272
#define event_id
INT j
Definition odbhist.cxx:40
INT k
Definition odbhist.cxx:40
Definition midas.h:1026
INT num_values
Definition midas.h:1028
DWORD type
Definition midas.h:1027
char name[NAME_LENGTH]
Definition midas.h:1029
INT item_size
Definition midas.h:1032
Definition midas.h:1234
DWORD type
Definition midas.h:1236
DWORD n_data
Definition midas.h:1237
char name[NAME_LENGTH]
Definition midas.h:1235
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FindEventId()

int MidasHistory::FindEventId ( const char event_name)
inline

Definition at line 2291 of file history.cxx.

2292 {
2294 int status;
2295 char name[256];
2296 mstrlcpy(name, event_name, sizeof(name));
2297 char *s = strchr(name, '/');
2298 if (s)
2299 *s = ':';
2300
2301 //printf("Looking for event id for \'%s\'\n", name);
2302
2303 status = db_find_key(fDB, 0, "/History/Events", &hKeyRoot);
2304 if (status == DB_SUCCESS) {
2305 for (int i = 0;; i++) {
2306 HNDLE hKey;
2307 KEY key;
2308
2310 if (status != DB_SUCCESS)
2311 break;
2312
2314 assert(status == DB_SUCCESS);
2315
2316 //printf("key \'%s\'\n", key.name);
2317
2318 int evid = (WORD) strtol(key.name, NULL, 0);
2319 if (evid == 0)
2320 continue;
2321
2322 char tmp[NAME_LENGTH+NAME_LENGTH+2];
2323 int size = sizeof(tmp);
2324 status = db_get_data(fDB, hKey, tmp, &size, TID_STRING);
2325 assert(status == DB_SUCCESS);
2326
2327 //printf("got %d \'%s\' looking for \'%s\'\n", evid, tmp, name);
2328
2329 if (equal_ustring(name, tmp))
2330 return evid;
2331 }
2332 }
2333
2334 return -1;
2335 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetEventId()

int MidasHistory::GetEventId ( time_t  t,
const char event_name,
const char tag_name,
int pevid 
)
inline

Definition at line 2948 of file history.cxx.

2949 {
2950 int event_id = -1;
2951
2952 if (fDebug && event_name != NULL && tag_name != NULL)
2953 printf("xhs_event_id for event [%s], tag [%s]\n", event_name, tag_name);
2954
2955 *pevid = 0;
2956
2957 /* use "/History/Tags" if available */
2958 event_id = GetEventIdFromOdbTags(event_name, tag_name);
2959
2960 /* if no Tags, use "/History/Events" and hs_get_tags() to read definition from history files */
2961 if (event_id < 0)
2962 event_id = GetEventIdFromHS(t, event_name, tag_name);
2963
2964 /* if nothing works, use hs_get_event_id() */
2965 if (event_id <= 0) {
2966 DWORD evid = 0;
2967 int status = ::hs_get_event_id((DWORD)t, (char*)event_name, &evid);
2968 if (status != HS_SUCCESS)
2969 return status;
2970 event_id = evid;
2971 }
2972
2973 if (event_id < 0)
2974 return HS_UNDEFINED_VAR;
2975
2976 *pevid = event_id;
2977
2978 return HS_SUCCESS;
2979 }
#define HS_UNDEFINED_VAR
Definition midas.h:733
static INT hs_get_event_id(DWORD ltime, const char *name, DWORD *id)
Definition history.cxx:984
int GetEventIdFromHS(time_t ltime, const char *evname, const char *tagname)
Definition history.cxx:2804
int GetEventIdFromOdbTags(const char *evname, const char *tagname)
Definition history.cxx:2874
unsigned int DWORD
Definition mcstd.h:51
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetEventIdFromHS()

int MidasHistory::GetEventIdFromHS ( time_t  ltime,
const char evname,
const char tagname 
)
inline

Definition at line 2804 of file history.cxx.

2805 {
2807 int status;
2808
2809 status = db_find_key(fDB, 0, "/History/Events", &hKeyRoot);
2810 if (status != DB_SUCCESS) {
2811 return -1;
2812 }
2813
2814 for (int i = 0;; i++) {
2815 HNDLE hKey;
2816 KEY key;
2817 int evid;
2818 char buf[256];
2819 int size;
2820 char *s;
2821 int ntags = 0;
2822 TAG* tags = NULL;
2823 char event_name[NAME_LENGTH];
2824
2826 if (status != DB_SUCCESS)
2827 break;
2828
2830 assert(status == DB_SUCCESS);
2831
2832 if (!isdigit(key.name[0]))
2833 continue;
2834
2835 evid = atoi(key.name);
2836
2837 assert(key.item_size < (int)sizeof(buf));
2838
2839 size = sizeof(buf);
2840 status = db_get_data(fDB, hKey, buf, &size, TID_STRING);
2841 assert(status == DB_SUCCESS);
2842
2843 mstrlcpy(event_name, buf, sizeof(event_name));
2844
2845 s = strchr(buf,':');
2846 if (s)
2847 *s = 0;
2848
2849 //printf("Found event %d, event [%s] name [%s], looking for [%s][%s]\n", evid, event_name, buf, evname, tagname);
2850
2851 if (!equal_ustring((char *)evname, buf))
2852 continue;
2853
2854 status = ::hs_get_tags((DWORD)ltime, evid, event_name, &ntags, &tags);
2855
2856 for (int j=0; j<ntags; j++) {
2857 //printf("at %d [%s] looking for [%s]\n", j, tags[j].name, tagname);
2858
2859 if (equal_ustring((char *)tagname, tags[j].name)) {
2860 if (tags)
2861 free(tags);
2862 return evid;
2863 }
2864 }
2865
2866 if (tags)
2867 free(tags);
2868 tags = NULL;
2869 }
2870
2871 return -1;
2872 }
int hs_get_tags(const char *event_name, time_t t, std::vector< TAG > *ptags)
get list of history variables for given event (use event names returned by hs_get_events()) that exis...
Definition history.cxx:3151
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetEventIdFromOdbTags()

int MidasHistory::GetEventIdFromOdbTags ( const char evname,
const char tagname 
)
inline

Definition at line 2874 of file history.cxx.

2875 {
2877 int status;
2878
2879 status = db_find_key(fDB, 0, "/History/Tags", &hKeyRoot);
2880 if (status != DB_SUCCESS) {
2881 return -1;
2882 }
2883
2884 for (int i = 0;; i++) {
2885 HNDLE hKey;
2886 KEY key;
2887 int evid;
2888 char buf[256];
2889 int size;
2890 char *s;
2891
2893 if (status != DB_SUCCESS)
2894 break;
2895
2897 assert(status == DB_SUCCESS);
2898
2899 if (key.type != TID_STRING)
2900 continue;
2901
2902 if (!isdigit(key.name[0]))
2903 continue;
2904
2905 evid = atoi(key.name);
2906
2907 assert(key.item_size < (int)sizeof(buf));
2908
2909 size = sizeof(buf);
2910 status = db_get_data_index(fDB, hKey, buf, &size, 0, TID_STRING);
2911 assert(status == DB_SUCCESS);
2912
2913 s = strchr(buf,'/');
2914 if (s)
2915 *s = 0;
2916
2917 //printf("Found event %d, name [%s], looking for [%s][%s]\n", evid, buf, evname, tagname);
2918
2919 if (!equal_ustring((char *)evname, buf))
2920 continue;
2921
2922 for (int j=1; j<key.num_values; j++) {
2923 size = sizeof(buf);
2924 status = db_get_data_index(fDB, hKey, buf, &size, j, TID_STRING);
2925 assert(status == DB_SUCCESS);
2926
2927 if (!isdigit(buf[0]))
2928 continue;
2929
2930 s = strchr(buf,' ');
2931 if (!s)
2932 continue;
2933
2934 s++;
2935
2936 //printf("at %d [%s] [%s] compare to [%s]\n", j, buf, s, tagname);
2937
2938 if (equal_ustring((char *)tagname, s)) {
2939 //printf("Found evid %d\n", evid);
2940 return evid;
2941 }
2942 }
2943 }
2944
2945 return -1;
2946 }
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
Definition odb.cxx:6893
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetEventsFromOdbEvents()

int MidasHistory::GetEventsFromOdbEvents ( std::vector< std::string > *  events)
inline

Definition at line 2663 of file history.cxx.

2664 {
2666 int status;
2667
2668 status = db_find_key(fDB, 0, "/History/Events", &hKeyRoot);
2669 if (status != DB_SUCCESS) {
2670 return HS_FILE_ERROR;
2671 }
2672
2673 /* loop over tags to display event names */
2674 for (int i = 0;; i++) {
2675 HNDLE hKeyEq;
2676 char *s;
2677 char evname[1024+NAME_LENGTH];
2678 int size;
2679
2681 if (status != DB_SUCCESS)
2682 break;
2683
2684 size = sizeof(evname);
2686 assert(status == DB_SUCCESS);
2687
2688 s = strchr(evname,':');
2689 if (s)
2690 *s = '/';
2691
2692 /* skip duplicated event names */
2693
2694 int found = 0;
2695 for (unsigned i=0; i<events->size(); i++) {
2696 if (equal_ustring(evname, (*events)[i].c_str())) {
2697 found = 1;
2698 break;
2699 }
2700 }
2701
2702 if (found)
2703 continue;
2704
2705 events->push_back(evname);
2706
2707 //printf("event \'%s\'\n", evname);
2708 }
2709
2710 return HS_SUCCESS;
2711 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetEventsFromOdbTags()

int MidasHistory::GetEventsFromOdbTags ( std::vector< std::string > *  events)
inline

Definition at line 2713 of file history.cxx.

2714 {
2716 int status;
2717
2718 status = db_find_key(fDB, 0, "/History/Tags", &hKeyRoot);
2719 if (status != DB_SUCCESS) {
2720 return HS_FILE_ERROR;
2721 }
2722
2723 /* loop over tags to display event names */
2724 for (int i = 0;; i++) {
2725 HNDLE hKeyEq;
2726 KEY key;
2727 char *s;
2728 WORD event_id;
2729 char evname[1024+NAME_LENGTH];
2730 int size;
2731
2733 if (status != DB_SUCCESS)
2734 break;
2735
2736 /* get event name */
2738
2739 //printf("key \'%s\'\n", key.name);
2740
2741 if (key.type != TID_STRING)
2742 continue;
2743
2744 /* parse event name in format: "event_id" or "event_id:var_name" */
2745 s = key.name;
2746
2747 event_id = (WORD)strtoul(s,&s,0);
2748 if (event_id == 0)
2749 continue;
2750 if (s[0] != 0)
2751 continue;
2752
2753 size = sizeof(evname);
2755 assert(status == DB_SUCCESS);
2756
2757 /* skip duplicated event names */
2758
2759 int found = 0;
2760 for (unsigned i=0; i<events->size(); i++) {
2761 if (equal_ustring(evname, (*events)[i].c_str())) {
2762 found = 1;
2763 break;
2764 }
2765 }
2766
2767 if (found)
2768 continue;
2769
2770 events->push_back(evname);
2771
2772 //printf("event %d \'%s\'\n", event_id, evname);
2773 }
2774
2775 return HS_SUCCESS;
2776 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetTagsFromHS()

int MidasHistory::GetTagsFromHS ( const char event_name,
std::vector< TAG > *  ptags 
)
inline

Definition at line 2981 of file history.cxx.

2982 {
2983 time_t now = time(NULL);
2984 int evid;
2985 int status = GetEventId(now, event_name, NULL, &evid);
2986 if (status != HS_SUCCESS)
2987 return status;
2988
2989 if (fDebug)
2990 printf("hs_get_tags: get tags for event [%s] %d\n", event_name, evid);
2991
2992 int ntags;
2993 TAG* tags;
2994 status = ::hs_get_tags((DWORD)now, evid, (char*)event_name, &ntags, &tags);
2995
2996 if (status != HS_SUCCESS)
2997 return status;
2998
2999 for (int i=0; i<ntags; i++)
3000 ptags->push_back(tags[i]);
3001
3002 if (tags)
3003 free(tags);
3004
3005 if (fDebug)
3006 printf("hs_get_tags: get tags for event [%s] %d, found %d tags\n", event_name, evid, ntags);
3007
3008 return HS_SUCCESS;
3009 }
int GetEventId(time_t t, const char *event_name, const char *tag_name, int *pevid)
Definition history.cxx:2948
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetTagsFromOdb()

int MidasHistory::GetTagsFromOdb ( const char event_name,
std::vector< TAG > *  ptags 
)
inline

Definition at line 3011 of file history.cxx.

3012 {
3014 int status;
3015
3016 status = db_find_key(fDB, 0, "/History/Tags", &hKeyRoot);
3017 if (status != DB_SUCCESS) {
3018 return HS_FILE_ERROR;
3019 }
3020
3021 /* loop over equipment to display event name */
3022 for (int i = 0;; i++) {
3023 HNDLE hKey;
3024 KEY key;
3025 WORD event_id;
3026 char buf[256];
3027 int size;
3028 char* s;
3029
3031 if (status != DB_SUCCESS)
3032 break;
3033
3034 /* get event name */
3036 assert(status == DB_SUCCESS);
3037
3038 /* parse event id */
3039 if (!isdigit(key.name[0]))
3040 continue;
3041
3042 event_id = atoi(key.name);
3043 if (event_id == 0)
3044 continue;
3045
3046 if (key.item_size >= (int)sizeof(buf))
3047 continue;
3048
3049 if (key.num_values == 1) { // old format of "/History/Tags"
3050
3051 HNDLE hKeyDir;
3052 sprintf(buf, "Tags %d", event_id);
3054 if (status != DB_SUCCESS)
3055 continue;
3056
3057 /* loop over tags */
3058 for (int j=0; ; j++) {
3059 HNDLE hKey;
3060 WORD array;
3061 int size;
3062 char var_name[NAME_LENGTH];
3063
3065 if (status != DB_SUCCESS)
3066 break;
3067
3068 /* get event name */
3070 assert(status == DB_SUCCESS);
3071
3072 array = 1;
3073 size = sizeof(array);
3074 status = db_get_data(fDB, hKey, &array, &size, TID_WORD);
3075 assert(status == DB_SUCCESS);
3076
3077 mstrlcpy(var_name, key.name, sizeof(var_name));
3078
3079 //printf("Found %s, event %d (%s), tag (%s) array %d\n", key.name, event_id, event_name, var_name, array);
3080
3081 TAG t;
3082 mstrlcpy(t.name, var_name, sizeof(t.name));
3083 t.n_data = array;
3084 t.type = 0;
3085
3086 ptags->push_back(t);
3087 }
3088
3089 continue;
3090 }
3091
3092 if (key.type != TID_STRING)
3093 continue;
3094
3095 size = sizeof(buf);
3096 status = db_get_data_index(fDB, hKey, buf, &size, 0, TID_STRING);
3097 assert(status == DB_SUCCESS);
3098
3099 if (strchr(event_name, '/')==NULL) {
3100 char* s = strchr(buf, '/');
3101 if (s)
3102 *s = 0;
3103 }
3104
3105 //printf("evid %d, name [%s]\n", event_id, buf);
3106
3107 if (!equal_ustring(buf, event_name))
3108 continue;
3109
3110 /* loop over tags */
3111 for (int j=1; j<key.num_values; j++) {
3112 int array;
3113 int size;
3114 char var_name[NAME_LENGTH];
3115 int ev_type;
3116
3117 size = sizeof(buf);
3118 status = db_get_data_index(fDB, hKey, buf, &size, j, TID_STRING);
3119 assert(status == DB_SUCCESS);
3120
3121 //printf("index %d [%s]\n", j, buf);
3122
3123 if (!isdigit(buf[0]))
3124 continue;
3125
3126 sscanf(buf, "%d[%d]", &ev_type, &array);
3127
3128 s = strchr(buf, ' ');
3129 if (!s)
3130 continue;
3131 s++;
3132
3133 mstrlcpy(var_name, s, sizeof(var_name));
3134
3135 TAG t;
3136 mstrlcpy(t.name, var_name, sizeof(t.name));
3137 t.n_data = array;
3138 t.type = ev_type;
3139
3140 //printf("Found %s, event %d, tag (%s) array %d, type %d\n", buf, event_id, var_name, array, ev_type);
3141
3142 ptags->push_back(t);
3143 }
3144 }
3145
3146 return HS_SUCCESS;
3147 }
char var_name[256]
Definition odbhist.cxx:41
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_clear_cache()

int MidasHistory::hs_clear_cache ( )
inlinevirtual

clear internal cache, returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 2278 of file history.cxx.

2279 {
2280 if (fDebug)
2281 printf("hs_clear_cache!\n");
2282
2283 fEventsCache.clear();
2284 fTagsCache.clear();
2285 fEvidCache.clear();
2286 return HS_SUCCESS;
2287 }
std::vector< std::string > fEventsCache
Definition history.cxx:2223
std::map< std::string, std::vector< TAG > > fTagsCache
Definition history.cxx:2224
std::map< std::string, int > fEvidCache
Definition history.cxx:2225
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_connect()

int MidasHistory::hs_connect ( const char connect_string)
inlinevirtual

returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 2240 of file history.cxx.

2241 {
2243
2244 /* delete obsolete odb entries */
2245
2246 if (1) {
2247 HNDLE hKey;
2248 int status = db_find_key(fDB, 0, "/History/ListSource", &hKey);
2249 if (status == DB_SUCCESS)
2251 }
2252
2253 ::hs_set_path(path);
2254
2255 if (fDebug)
2256 printf("hs_connect: path [%s]\n", path);
2257
2258 return HS_SUCCESS;
2259 }
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3011
static INT hs_set_path(const char *path)
Definition history.cxx:178
Here is the call graph for this function:

◆ hs_count_events()

static INT hs_count_events ( DWORD  ltime,
DWORD count 
)
static

Definition at line 907 of file history.cxx.

925{
926 int fh, fhd;
927 std::string fn, fnd;
928 INT status, i, n;
929 DWORD *id;
931
932 /* search latest history file */
934 if (status != HS_SUCCESS) {
935 cm_msg(MERROR, "hs_count_events", "cannot find recent history file");
936 return HS_FILE_ERROR;
937 }
938
939 /* open history and definition files */
940 hs_open_file(ltime, "hst", O_RDONLY, &fn, &fh);
941 hs_open_file(ltime, "idf", O_RDONLY, &fnd, &fhd);
942 if (fh < 0 || fhd < 0) {
943 cm_msg(MERROR, "hs_count_events", "cannot open index files");
944 return HS_FILE_ERROR;
945 }
946
947 /* allocate event id array */
948 xseek_end(fnd, fhd);
950 if (pos_fhd == (DWORD)-1) return HS_FILE_ERROR;
951 id = (DWORD *) M_MALLOC(pos_fhd/sizeof(def_rec) * sizeof(DWORD));
952 xseek(fnd, fhd, 0);
953
954 /* loop over index file */
955 n = 0;
956 do {
957 /* read definition index record */
958 if (xread(fnd, fhd, (char *) &def_rec, sizeof(def_rec), true) <= 0)
959 break;
960
961 /* look for existing entries */
962 for (i = 0; i < n; i++)
963 if (id[i] == def_rec.event_id)
964 break;
965
966 /* new entry found */
967 if (i == n) {
968 id[i] = def_rec.event_id;
969 n++;
970 }
971 } while (TRUE);
972
973
974 M_FREE(id);
975 close(fh);
976 close(fhd);
977 *count = n;
978
979 return HS_SUCCESS;
980}
static INT hs_open_file(time_t ltime, const char *suffix, INT mode, std::string *pfile_name, int *fh)
Definition history.cxx:206
static int xread(const std::string &fn, int fh, void *buf, size_t count, bool eof_ok=false)
Definition history.cxx:73
static INT hs_search_file(DWORD *ltime, INT direction)
Definition history.cxx:353
static DWORD xcurpos(const std::string &fn, int fh)
Definition history.cxx:133
static bool xseek_end(const std::string &fn, int fh)
Definition history.cxx:109
static bool xseek(const std::string &fn, int fh, DWORD pos)
Definition history.cxx:97
DWORD n[4]
Definition mana.cxx:247
double count
Definition mdump.cxx:33
#define DWORD
Definition mhdump.cxx:31
#define M_MALLOC(x)
Definition midas.h:1552
int INT
Definition midas.h:129
#define M_FREE(x)
Definition midas.h:1554
Here is the call graph for this function:

◆ hs_count_vars()

static INT hs_count_vars ( DWORD  ltime,
DWORD  event_id,
DWORD count 
)
static

Definition at line 1060 of file history.cxx.

1078{
1079 int fh, fhd;
1080 std::string fn, fnd;
1081 INT i, n, status;
1084
1085 /* search latest history file */
1086 status = hs_search_file(&ltime, -1);
1087 if (status != HS_SUCCESS) {
1088 cm_msg(MERROR, "hs_count_tags", "cannot find recent history file");
1089 return HS_FILE_ERROR;
1090 }
1091
1092 /* open history and definition files */
1093 hs_open_file(ltime, "hst", O_RDONLY, &fn, &fh);
1094 hs_open_file(ltime, "idf", O_RDONLY, &fnd, &fhd);
1095 if (fh < 0 || fhd < 0) {
1096 cm_msg(MERROR, "hs_count_tags", "cannot open index files");
1097 return HS_FILE_ERROR;
1098 }
1099
1100 /* search last definition */
1101 xseek_end(fnd, fhd);
1102 n = xcurpos(fnd, fhd) / sizeof(def_rec);
1103 def_rec.event_id = 0;
1104 for (i = n - 1; i >= 0; i--) {
1105 if (!xseek(fnd, fhd, i * sizeof(def_rec))) return HS_FILE_ERROR;
1106 if (xread(fnd, fhd, (char *) &def_rec, sizeof(def_rec)) < 0) return HS_FILE_ERROR;
1107 if (def_rec.event_id == event_id)
1108 break;
1109 }
1110 if (def_rec.event_id != event_id) {
1111 cm_msg(MERROR, "hs_count_tags", "event %d not found in index file", event_id);
1112 return HS_FILE_ERROR;
1113 }
1114
1115 /* read definition */
1116 xseek(fn, fh, def_rec.def_offset);
1117 xread(fn, fh, (char *) &rec, sizeof(rec));
1118 *count = rec.data_size / sizeof(TAG);
1119
1120 close(fh);
1121 close(fhd);
1122
1123 return HS_SUCCESS;
1124}
Here is the call graph for this function:

◆ hs_define_event() [1/2]

int MidasHistory::hs_define_event ( const char event_name,
time_t  timestamp,
int  ntags,
const TAG  tags[] 
)
inlinevirtual

see hs_define_event(), returns HS_SUCCESS or HS_FILE_ERROR

Implements MidasHistoryInterface.

Definition at line 2632 of file history.cxx.

2633 {
2634 int event_id = FindEventId(event_name);
2635 if (event_id < 0)
2636 event_id = AllocateEventId(event_name);
2637 if (event_id < 0)
2638 return HS_FILE_ERROR;
2639 fEvidCache[event_name] = event_id;
2640 CreateOdbTags(event_id, event_name, ntags, tags);
2641 return ::hs_define_event(event_id, (char*)event_name, (TAG*)tags, ntags*sizeof(TAG));
2642 }
int FindEventId(const char *event_name)
Definition history.cxx:2291
int AllocateEventId(const char *event_name)
Definition history.cxx:2339
int CreateOdbTags(int event_id, const char *event_name, int ntags, const TAG tags[])
Definition history.cxx:2404
Here is the call graph for this function:

◆ hs_define_event() [2/2]

static INT hs_define_event ( DWORD  event_id,
const char name,
const TAG tag,
DWORD  size 
)
static

Definition at line 427 of file history.cxx.

458{
459 {
463 char str[256], event_name[NAME_LENGTH], *buffer;
464 int fh, fhi, fhd;
465 std::string fn, fni, fnd;
466 INT n, status, semaphore;
467
468 //printf("hs_define_event: event_id %d, name [%s]\n", event_id, name);
469
470 /* request semaphore */
472 status = ss_semaphore_wait_for(semaphore, 5 * 1000);
473 if (status != SS_SUCCESS)
474 return SUCCESS; /* someone else blocked the history system */
475
476 /* allocate new space for the new history descriptor */
477 /* check if history already open */
478 int index = -1;
479 for (unsigned i = 0; i < _history.size(); i++)
480 if (_history[i]->event_id == event_id) {
481 index = i;
482 break;
483 }
484
485 /* if not found, create new one */
486 if (index < 0) {
487 index = _history.size();
488 _history.push_back(new HISTORY);
489 }
490
491 /* assemble definition record header */
492 rec.record_type = RT_DEF;
493 rec.event_id = event_id;
494 rec.time = (DWORD) time(NULL);
495 rec.data_size = size;
496 mstrlcpy(event_name, name, NAME_LENGTH);
497
498 /* if history structure not set up, do so now */
499 if (!_history[index]->hist_fh) {
500 /* open history file */
501 hs_open_file(rec.time, "hst", O_CREAT | O_RDWR, &fn, &fh);
502 if (fh < 0) {
503 ss_semaphore_release(semaphore);
504 return HS_FILE_ERROR;
505 }
506
507 /* open index files */
508 hs_open_file(rec.time, "idf", O_CREAT | O_RDWR, &fnd, &fhd);
509 hs_open_file(rec.time, "idx", O_CREAT | O_RDWR, &fni, &fhi);
510 xseek_end(fn, fh);
511 xseek_end(fni, fhi);
512 xseek_end(fnd, fhd);
513
514 DWORD fh_pos = xcurpos(fn, fh);
516
517 if (fh_pos == (DWORD)-1) return HS_FILE_ERROR;
518 if (fhd_pos == (DWORD)-1) return HS_FILE_ERROR;
519
520 /* regenerate index if missing */
521 if (fh_pos > 0 && fhd_pos == 0) {
522 close(fh);
523 close(fhi);
524 close(fhd);
525 hs_gen_index(rec.time);
526 hs_open_file(rec.time, "hst", O_RDWR, &fn, &fh);
527 hs_open_file(rec.time, "idx", O_RDWR, &fni, &fhi);
528 hs_open_file(rec.time, "idf", O_RDWR, &fnd, &fhd);
529 xseek_end(fn, fh);
530 xseek_end(fni, fhi);
531 xseek_end(fnd, fhd);
532 }
533
534 ltime = (time_t) rec.time;
535 struct tm tmb;
537 tmb.tm_hour = tmb.tm_min = tmb.tm_sec = 0;
538
539 DWORD pos = xcurpos(fn, fh);
540 if (pos == (DWORD)-1) return HS_FILE_ERROR;
541
542 /* setup history structure */
543 _history[index]->hist_fn = fn;
544 _history[index]->index_fn = fni;
545 _history[index]->def_fn = fnd;
546 _history[index]->hist_fh = fh;
547 _history[index]->index_fh = fhi;
548 _history[index]->def_fh = fhd;
549 _history[index]->def_offset = pos;
550 _history[index]->event_id = event_id;
551 _history[index]->event_name = event_name;
552 _history[index]->base_time = (DWORD) ss_mktime(&tmb);
553 _history[index]->n_tag = size / sizeof(TAG);
554 _history[index]->tag = (TAG *) M_MALLOC(size);
555 memcpy(_history[index]->tag, tag, size);
556
557 /* search previous definition */
559 if (fhd_pos == (DWORD)-1) return HS_FILE_ERROR;
560 n = fhd_pos / sizeof(def_rec);
561 def_rec.event_id = 0;
562 for (int i = n - 1; i >= 0; i--) {
563 if (!xseek(fnd, fhd, i * sizeof(def_rec))) return HS_FILE_ERROR;
564 if (xread(fnd, fhd, (char *) &def_rec, sizeof(def_rec)) < 0) return HS_FILE_ERROR;
565 if (def_rec.event_id == event_id)
566 break;
567 }
568 xseek_end(fnd, fhd);
569
570 /* if definition found, compare it with new one */
571 if (def_rec.event_id == event_id) {
572 buffer = (char *) M_MALLOC(size);
573 memset(buffer, 0, size);
574
575 xseek(fn, fh, def_rec.def_offset);
576 xread(fn, fh, (char *) &prev_rec, sizeof(prev_rec));
577 xread(fn, fh, str, NAME_LENGTH);
578 xread(fn, fh, buffer, size);
579 xseek_end(fn, fh);
580
581 if (prev_rec.data_size != size || strcmp(str, event_name) != 0 || memcmp(buffer, tag, size) != 0) {
582 /* write definition to history file */
583 xwrite(fn, fh, (char *) &rec, sizeof(rec));
584 xwrite(fn, fh, event_name, NAME_LENGTH);
585 xwrite(fn, fh, (char *) tag, size);
586
587 /* write index record */
588 def_rec.event_id = event_id;
589 memcpy(def_rec.event_name, event_name, sizeof(event_name));
590 def_rec.def_offset = _history[index]->def_offset;
591 xwrite(fnd, fhd, (char *) &def_rec, sizeof(def_rec));
592 } else
593 /* definition identical, just remember old offset */
594 _history[index]->def_offset = def_rec.def_offset;
595
596 M_FREE(buffer);
597 } else {
598 /* write definition to history file */
599 xwrite(fn, fh, (char *) &rec, sizeof(rec));
600 xwrite(fn, fh, event_name, NAME_LENGTH);
601 xwrite(fn, fh, (char *) tag, size);
602
603 /* write definition index record */
604 def_rec.event_id = event_id;
605 memcpy(def_rec.event_name, event_name, sizeof(event_name));
606 def_rec.def_offset = _history[index]->def_offset;
607 xwrite(fn, fhd, (char *) &def_rec, sizeof(def_rec));
608 }
609 } else {
610 fn = _history[index]->hist_fn;
611 fnd = _history[index]->def_fn;
612 fh = _history[index]->hist_fh;
613 fhd = _history[index]->def_fh;
614
615 /* compare definition with previous definition */
616 buffer = (char *) M_MALLOC(size);
617 memset(buffer, 0, size);
618
619 xseek(fn, fh, _history[index]->def_offset);
620 xread(fn, fh, (char *) &prev_rec, sizeof(prev_rec));
621 xread(fn, fh, str, NAME_LENGTH);
622 xread(fn, fh, buffer, size);
623
624 xseek_end(fn, fh);
625 xseek_end(fnd, fhd);
626
627 if (prev_rec.data_size != size || strcmp(str, event_name) != 0 || memcmp(buffer, tag, size) != 0) {
628 /* save new definition offset */
629 DWORD pos = xcurpos(fn, fh);
630 if (pos == (DWORD)-1) return HS_FILE_ERROR;
631 _history[index]->def_offset = pos;
632
633 /* write definition to history file */
634 xwrite(fn, fh, (char *) &rec, sizeof(rec));
635 xwrite(fn, fh, event_name, NAME_LENGTH);
636 xwrite(fn, fh, (char *) tag, size);
637
638 /* write index record */
639 def_rec.event_id = event_id;
640 memcpy(def_rec.event_name, event_name, sizeof(event_name));
641 def_rec.def_offset = _history[index]->def_offset;
642 xwrite(fnd, fhd, (char *) &def_rec, sizeof(def_rec));
643 }
644
645 M_FREE(buffer);
646 }
647
648 ss_semaphore_release(semaphore);
649 }
650
651 return HS_SUCCESS;
652}
INT cm_get_experiment_semaphore(INT *semaphore_alarm, INT *semaphore_elog, INT *semaphore_history, INT *semaphore_msg)
Definition midas.cxx:3033
#define SS_SUCCESS
Definition midas.h:663
static std::vector< HISTORY * > _history
Definition history.cxx:45
static bool xwrite(const std::string &fn, int fh, const void *buf, size_t count)
Definition history.cxx:51
static INT hs_gen_index(DWORD ltime)
Definition history.cxx:237
#define SUCCESS
Definition mcstd.h:54
time_t ss_mktime(struct tm *tms)
Definition system.cxx:3365
INT ss_semaphore_release(HNDLE semaphore_handle)
Definition system.cxx:2781
INT ss_semaphore_wait_for(HNDLE semaphore_handle, DWORD timeout_millisec)
Definition system.cxx:2639
INT index
Definition mana.cxx:271
#define RT_DEF
Definition midas.h:1358
#define name(x)
Definition midas_macro.h:24
MUTEX_T * tm
Definition odbedit.cxx:39
char str[256]
Definition odbhist.cxx:33
Here is the call graph for this function:

◆ hs_define_panel()

INT hs_define_panel ( const char group,
const char panel,
const std::vector< std::string >  var 
)

Definition at line 3492 of file history.cxx.

3493{
3494 HNDLE hDB, hKey, hKeyVar;
3496 char str[256];
3497
3498 const char *color[] = {
3499 "#00AAFF", "#FF9000", "#FF00A0", "#00C030",
3500 "#A0C0D0", "#D0A060", "#C04010", "#807060",
3501 "#F0C000", "#2090A0", "#D040D0", "#90B000",
3502 "#B0B040", "#B0B0FF", "#FFA0A0", "#A0FFA0",
3503 "#808080"};
3504
3506
3507 snprintf(str, sizeof(str), "/History/Display/%s/%s", group, panel);
3508
3510 db_find_key(hDB, 0, str, &hKey);
3511 if (!hKey)
3512 return DB_NO_MEMORY;
3513
3514 int i=0;
3515 for(auto const& v: var) {
3516 db_find_key(hDB, hKey, "Variables", &hKeyVar);
3517 db_set_data_index(hDB, hKeyVar, v.c_str(), 64, i, TID_STRING);
3518
3519 str[0] = 0;
3520 db_set_value_index(hDB, hKey, "Formula", str, 64, i, TID_STRING, false);
3521 db_set_value_index(hDB, hKey, "Label", str, 32, i, TID_STRING, false);
3522 db_set_value_index(hDB, hKey, "Colour", color[i < 16 ? i : 16], 32, i, TID_STRING, false);
3523
3524 i++;
3525 }
3526
3527 return HS_SUCCESS;
3528}
#define DB_NO_MEMORY
Definition midas.h:633
#define HISTORY_PANEL(_name)
Definition history.cxx:3464
std::string strcomb1(const char **list)
Definition odb.cxx:598
INT db_set_value_index(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT idx, DWORD type, BOOL trunc)
Definition odb.cxx:5365
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
Definition odb.cxx:12800
HNDLE hDB
main ODB handle
Definition mana.cxx:207
char color[][16]
Definition mchart.cxx:32
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_define_panel2()

INT hs_define_panel2 ( const char group,
const char panel,
const std::vector< std::string >  var,
const std::vector< std::string >  label,
const std::vector< std::string >  formula,
const std::vector< std::string >  color 
)

Definition at line 3530 of file history.cxx.

3533{
3534 HNDLE hDB, hKey, hKeyVar;
3536 char str[256];
3537
3538 const char *default_color[] = {
3539 "#00AAFF", "#FF9000", "#FF00A0", "#00C030",
3540 "#A0C0D0", "#D0A060", "#C04010", "#807060",
3541 "#F0C000", "#2090A0", "#D040D0", "#90B000",
3542 "#B0B040", "#B0B0FF", "#FFA0A0", "#A0FFA0",
3543 "#808080"};
3544
3546
3547 snprintf(str, sizeof(str), "/History/Display/%s/%s", group, panel);
3548
3550 db_find_key(hDB, 0, str, &hKey);
3551 if (!hKey)
3552 return DB_NO_MEMORY;
3553
3554 int i=0;
3555 for(auto const& v: var) {
3556 db_find_key(hDB, hKey, "Variables", &hKeyVar);
3557 db_set_data_index(hDB, hKeyVar, v.c_str(), 64, i, TID_STRING);
3558
3559 if (i < (int)formula.size())
3560 mstrlcpy(str, formula[i].c_str(), sizeof(str)-1);
3561 else
3562 str[0] = 0;
3563 db_set_value_index(hDB, hKey, "Formula", str, 64, i, TID_STRING, false);
3564
3565 if (i < (int)label.size())
3566 mstrlcpy(str, label[i].c_str(), sizeof(str)-1);
3567 else
3568 str[0] = 0;
3569 db_set_value_index(hDB, hKey, "Label", str, 32, i, TID_STRING, false);
3570
3571 if (i < (int)color.size())
3572 mstrlcpy(str, color[i].c_str(), sizeof(str)-1);
3573 else
3574 mstrlcpy(str, default_color[i < 16 ? i : 16], sizeof(str)-1);
3575 db_set_value_index(hDB, hKey, "Colour", str, 32, i, TID_STRING, false);
3576
3577 i++;
3578 }
3579
3580 return HS_SUCCESS;
3581}
Here is the call graph for this function:

◆ hs_disconnect()

int MidasHistory::hs_disconnect ( )
inlinevirtual

disconnect from history, returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 2263 of file history.cxx.

2264 {
2266 return HS_SUCCESS;
2267 }
int hs_clear_cache()
clear internal cache, returns HS_SUCCESS
Definition history.cxx:2278
Here is the call graph for this function:

◆ hs_dump()

static INT hs_dump ( DWORD  event_id,
DWORD  start_time,
DWORD  end_time,
DWORD  interval,
BOOL  binary_time 
)
static

dox Display history for a given event at stdout. The output can be redirected to be read by Excel for example.

Parameters
event_idEvent ID
start_timeStarting Date/Time
end_timeEnd Date/Time
intervalMinimum time in seconds between reported
events. Can be used to skip events
binary_timeDisplay DWORD time stamp
Returns
HS_SUCCESS, HS_FILE_ERROR

Definition at line 1954 of file history.cxx.

1955{
1957 time_t ltime;
1958 int fh, fhd, fhi;
1959 std::string fn, fnd, fni;
1960 INT i, j, delta, status, n_tag = 0, old_n_tag = 0;
1964 TAG *tag = NULL, *old_tag = NULL;
1965 char data_buffer[10000];
1966
1967 ss_tzset(); // required by localtime_r()
1968
1969 /* if not time given, use present to one hour in past */
1970 if (start_time == 0)
1971 start_time = (DWORD) time(NULL) - 3600;
1972 if (end_time == 0)
1973 end_time = (DWORD) time(NULL);
1974
1975 /* search history file for start_time */
1976 status = hs_search_file(&start_time, 1);
1977 if (status != HS_SUCCESS) {
1978 cm_msg(MERROR, "hs_dump", "cannot find recent history file");
1979 return HS_FILE_ERROR;
1980 }
1981
1982 /* open history and definition files */
1983 hs_open_file(start_time, "hst", O_RDONLY, &fn, &fh);
1984 hs_open_file(start_time, "idf", O_RDONLY, &fnd, &fhd);
1985 hs_open_file(start_time, "idx", O_RDONLY, &fni, &fhi);
1986 if (fh < 0 || fhd < 0 || fhi < 0) {
1987 cm_msg(MERROR, "hs_dump", "cannot open index files");
1988 return HS_FILE_ERROR;
1989 }
1990
1991 /* search record closest to start time */
1992 xseek_end(fni, fhi);
1993 delta = (xcurpos(fni, fhi) / sizeof(irec)) / 2;
1994 xseek(fni, fhi, delta * sizeof(irec));
1995 do {
1996 delta = (int) (abs(delta) / 2.0 + 0.5);
1997 xread(fni, fhi, (char *) &irec, sizeof(irec));
1998 if (irec.time > start_time)
1999 delta = -delta;
2000
2001 xseek_cur(fni, fhi, (delta - 1) * sizeof(irec));
2002 } while (abs(delta) > 1 && irec.time != start_time);
2003 xread(fni, fhi, (char *) &irec, sizeof(irec));
2004 if (irec.time > start_time)
2005 delta = -abs(delta);
2006
2007 i = xcurpos(fni, fhi) + (delta - 1) * sizeof(irec);
2008 if (i <= 0)
2009 xseek(fni, fhi, 0);
2010 else
2011 xseek_cur(fni, fhi, (delta - 1) * sizeof(irec));
2012 xread(fni, fhi, (char *) &irec, sizeof(irec));
2013
2014 /* read records, skip wrong IDs */
2015 old_def_offset = -1;
2016 prev_time = 0;
2017 last_irec_time = 0;
2018 do {
2019 if (irec.time < last_irec_time) {
2020 cm_msg(MERROR, "hs_dump", "corrupted history data: time does not increase: %d -> %d", last_irec_time, irec.time);
2022 return HS_FILE_ERROR;
2023 }
2024 last_irec_time = irec.time;
2025 if (irec.event_id == event_id && irec.time <= end_time && irec.time >= start_time) {
2026 if (irec.time >= prev_time + interval) {
2027 prev_time = irec.time;
2028 xseek(fn, fh, irec.offset);
2029 xread(fn, fh, (char *) &rec, sizeof(rec));
2030
2031 /* if definition changed, read new definition */
2032 if ((INT) rec.def_offset != old_def_offset) {
2034 xseek(fn, fh, rec.def_offset);
2035 xread(fn, fh, (char *) &drec, sizeof(drec));
2037
2038 if (tag == NULL)
2039 tag = (TAG *) M_MALLOC(drec.data_size);
2040 else
2041 tag = (TAG *) realloc(tag, drec.data_size);
2042 if (tag == NULL)
2043 return HS_NO_MEMORY;
2044 xread(fn, fh, (char *) tag, drec.data_size);
2045 n_tag = drec.data_size / sizeof(TAG);
2046
2047 /* print tag names if definition has changed */
2048 if (old_tag == NULL || old_n_tag != n_tag || memcmp(old_tag, tag, drec.data_size) != 0) {
2049 printf("Date\t");
2050 for (i = 0; i < n_tag; i++) {
2051 if (tag[i].n_data == 1 || tag[i].type == TID_STRING)
2052 printf("%s\t", tag[i].name);
2053 else
2054 for (j = 0; j < (INT) tag[i].n_data; j++)
2055 printf("%s%d\t", tag[i].name, j);
2056 }
2057 printf("\n");
2058
2059 if (old_tag == NULL)
2060 old_tag = (TAG *) M_MALLOC(drec.data_size);
2061 else
2062 old_tag = (TAG *) realloc(old_tag, drec.data_size);
2063 memcpy(old_tag, tag, drec.data_size);
2064 old_n_tag = n_tag;
2065 }
2066
2067 old_def_offset = rec.def_offset;
2068 xseek(fn, fh, irec.offset + sizeof(rec));
2069 }
2070
2071 /* print time from header */
2072 if (binary_time)
2073 printf("%d ", irec.time);
2074 else {
2075 ltime = (time_t) irec.time;
2076 char ctimebuf[32];
2078 char str[256];
2079 mstrlcpy(str, ctimebuf + 4, sizeof(str));
2080 str[20] = '\t';
2081 printf("%s", str);
2082 }
2083
2084 /* read data */
2085 xread(fn, fh, data_buffer, rec.data_size);
2086
2087 /* interprete data from tag definition */
2088 offset = 0;
2089 for (i = 0; i < n_tag; i++) {
2090 /* strings have a length of n_data */
2091 if (tag[i].type == TID_STRING) {
2092 printf("%s\t", data_buffer + offset);
2093 offset += tag[i].n_data;
2094 } else if (tag[i].n_data == 1) {
2095 /* non-array data */
2096 std::string data_str = db_sprintf(data_buffer + offset, rpc_tid_size(tag[i].type), 0, tag[i].type);
2097 printf("%s\t", data_str.c_str());
2098 offset += rpc_tid_size(tag[i].type);
2099 } else
2100 /* loop over array data */
2101 for (j = 0; j < (INT) tag[i].n_data; j++) {
2102 std::string data_str = db_sprintf(data_buffer + offset, rpc_tid_size(tag[i].type), 0, tag[i].type);
2103 printf("%s\t", data_str.c_str());
2104 offset += rpc_tid_size(tag[i].type);
2105 }
2106 }
2107 printf("\n");
2108 }
2109 }
2110
2111 /* read next index record */
2112 i = xread(fni, fhi, (char *) &irec, sizeof(irec), true);
2113
2114 /* end of file: search next history file */
2115 if (i <= 0) {
2116 close(fh);
2117 close(fhd);
2118 close(fhi);
2119
2120 /* advance one day */
2122 struct tm tms;
2123 localtime_r(&ltime, &tms);
2124 tms.tm_hour = tms.tm_min = tms.tm_sec = 0;
2126
2127 last_irec_time += 3600 * 24;
2128 if (last_irec_time > end_time)
2129 break;
2130
2131 /* search next file */
2133 if (status != HS_SUCCESS)
2134 break;
2135
2136 /* open history and definition files */
2137 hs_open_file(last_irec_time, "hst", O_RDONLY, &fn, &fh);
2140 if (fh < 0 || fhd < 0 || fhi < 0) {
2141 cm_msg(MERROR, "hs_dump", "cannot open index files");
2142 break;
2143 }
2144
2145 /* read first record */
2146 i = xread(fni, fhi, (char *) &irec, sizeof(irec), true);
2147 if (i <= 0)
2148 break;
2149
2150 /* old definition becomes invalid */
2151 old_def_offset = -1;
2152 }
2153 } while (irec.time < end_time);
2154
2155 M_FREE(tag);
2156 M_FREE(old_tag);
2157 close(fh);
2158 close(fhd);
2159 close(fhi);
2160
2161 return HS_SUCCESS;
2162}
#define HS_NO_MEMORY
Definition midas.h:729
static bool xseek_cur(const std::string &fn, int fh, int offset)
Definition history.cxx:121
void ss_tzset()
Definition system.cxx:3355
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
Definition odb.cxx:10843
INT rpc_tid_size(INT id)
Definition midas.cxx:11757
INT type
Definition mana.cxx:269
static int offset
Definition mgd.cxx:1500
BOOL binary_time
Definition mhist.cxx:18
Here is the call graph for this function:

◆ hs_enum_events()

static INT hs_enum_events ( DWORD  ltime,
char event_name,
DWORD name_size,
INT  event_id[],
DWORD id_size 
)
static

Definition at line 823 of file history.cxx.

845{
846 int fh, fhd;
847 std::string fn, fnd;
848 INT status, i, n;
850
851 /* search latest history file */
853 if (status != HS_SUCCESS) {
854 cm_msg(MERROR, "hs_enum_events", "cannot find recent history file");
855 return HS_FILE_ERROR;
856 }
857
858 /* open history and definition files */
859 hs_open_file(ltime, "hst", O_RDONLY, &fn, &fh);
860 hs_open_file(ltime, "idf", O_RDONLY, &fnd, &fhd);
861 if (fh < 0 || fhd < 0) {
862 cm_msg(MERROR, "hs_enum_events", "cannot open index files");
863 return HS_FILE_ERROR;
864 }
865 xseek(fnd, fhd, 0);
866
867 /* loop over definition index file */
868 n = 0;
869 do {
870 /* read event definition */
871 if (xread(fnd, fhd, (char *) &def_rec, sizeof(def_rec), true) <= 0)
872 break;
873
874 /* look for existing entry for this event id */
875 for (i = 0; i < n; i++)
876 if (event_id[i] == (INT) def_rec.event_id) {
877 strcpy(event_name + i * NAME_LENGTH, def_rec.event_name);
878 break;
879 }
880
881 /* new entry found */
882 if (i == n) {
883 if (((i * NAME_LENGTH) > ((INT) * name_size)) || ((i * sizeof(INT)) > (*id_size))) {
884 cm_msg(MERROR, "hs_enum_events", "index buffer too small");
885 close(fh);
886 close(fhd);
887 return HS_NO_MEMORY;
888 }
889
890 /* copy definition record */
891 strcpy(event_name + i * NAME_LENGTH, def_rec.event_name);
892 event_id[i] = def_rec.event_id;
893 n++;
894 }
895 } while (TRUE);
896
897 close(fh);
898 close(fhd);
900 *id_size = n * sizeof(INT);
901
902 return HS_SUCCESS;
903}
Here is the call graph for this function:

◆ hs_enum_vars()

static INT hs_enum_vars ( DWORD  ltime,
DWORD  event_id,
char var_name,
DWORD size,
DWORD var_n,
DWORD n_size 
)
static

Definition at line 1128 of file history.cxx.

1151{
1152 char str[256];
1153 int fh, fhd;
1154 std::string fn, fnd;
1155 INT i, n, status;
1158 TAG *tag;
1159
1160 /* search latest history file */
1161 status = hs_search_file(&ltime, -1);
1162 if (status != HS_SUCCESS) {
1163 cm_msg(MERROR, "hs_enum_vars", "cannot find recent history file");
1164 return HS_FILE_ERROR;
1165 }
1166
1167 /* open history and definition files */
1168 hs_open_file(ltime, "hst", O_RDONLY, &fn, &fh);
1169 hs_open_file(ltime, "idf", O_RDONLY, &fnd, &fhd);
1170 if (fh < 0 || fhd < 0) {
1171 cm_msg(MERROR, "hs_enum_vars", "cannot open index files");
1172 return HS_FILE_ERROR;
1173 }
1174
1175 /* search last definition */
1176 xseek_end(fnd, fhd);
1177 n = xcurpos(fnd, fhd) / sizeof(def_rec);
1178 def_rec.event_id = 0;
1179 for (i = n - 1; i >= 0; i--) {
1180 if (!xseek(fnd, fhd, i * sizeof(def_rec))) return HS_FILE_ERROR;
1181 if (xread(fnd, fhd, (char *) &def_rec, sizeof(def_rec)) < 0) return HS_FILE_ERROR;
1182 if (def_rec.event_id == event_id)
1183 break;
1184 }
1185 if (def_rec.event_id != event_id) {
1186 cm_msg(MERROR, "hs_enum_vars", "event %d not found in index file", event_id);
1187 return HS_FILE_ERROR;
1188 }
1189
1190 /* read definition header */
1191 xseek(fn, fh, def_rec.def_offset);
1192 xread(fn, fh, (char *) &rec, sizeof(rec));
1193 xread(fn, fh, str, NAME_LENGTH);
1194
1195 /* read event definition */
1196 n = rec.data_size / sizeof(TAG);
1197 tag = (TAG *) M_MALLOC(rec.data_size);
1198 xread(fn, fh, (char *) tag, rec.data_size);
1199
1200 if (n * NAME_LENGTH > (INT) * size || n * sizeof(DWORD) > *n_size) {
1201
1202 /* store partial definition */
1203 for (i = 0; i < (INT) * size / NAME_LENGTH; i++) {
1204 strcpy(var_name + i * NAME_LENGTH, tag[i].name);
1205 var_n[i] = tag[i].n_data;
1206 }
1207
1208 cm_msg(MERROR, "hs_enum_vars", "tag buffer too small");
1209 M_FREE(tag);
1210 close(fh);
1211 close(fhd);
1212 return HS_NO_MEMORY;
1213 }
1214
1215 /* store full definition */
1216 for (i = 0; i < n; i++) {
1217 strcpy(var_name + i * NAME_LENGTH, tag[i].name);
1218 var_n[i] = tag[i].n_data;
1219 }
1220 *size = n * NAME_LENGTH;
1221 *n_size = n * sizeof(DWORD);
1222
1223 M_FREE(tag);
1224 close(fh);
1225 close(fhd);
1226
1227 return HS_SUCCESS;
1228}
Here is the call graph for this function:

◆ hs_flush_buffers()

int MidasHistory::hs_flush_buffers ( )
inlinevirtual

flush buffered data to storage where it is visible to mhttpd

Implements MidasHistoryInterface.

Definition at line 2655 of file history.cxx.

2656 {
2657 //printf("hs_flush_buffers!\n");
2658 return HS_SUCCESS;
2659 }

◆ hs_gen_index()

static INT hs_gen_index ( DWORD  ltime)
static

Definition at line 237 of file history.cxx.

257{
258 char event_name[NAME_LENGTH];
259 int fh, fhd, fhi;
263 int recovering = 0;
264 //time_t now = time(NULL);
265
266 cm_msg(MINFO, "hs_gen_index", "generating index files for time %d", (int) ltime);
267 printf("Recovering index files...\n");
268
269 if (ltime == 0)
270 ltime = (DWORD) time(NULL);
271
272 std::string fni;
273 std::string fnd;
274 std::string fn;
275
276 /* open new index file */
277 hs_open_file(ltime, "idx", O_RDWR | O_CREAT | O_TRUNC, &fni, &fhi);
278 hs_open_file(ltime, "idf", O_RDWR | O_CREAT | O_TRUNC, &fnd, &fhd);
279
280 if (fhd < 0 || fhi < 0) {
281 cm_msg(MERROR, "hs_gen_index", "cannot create index file");
282 return HS_FILE_ERROR;
283 }
284
285 /* open history file */
286 hs_open_file(ltime, "hst", O_RDONLY, &fn, &fh);
287 if (fh < 0)
288 return HS_FILE_ERROR;
289 xseek(fn, fh, 0);
290
291 /* loop over file records in .hst file */
292 do {
293 if (xread(fn, fh, (char *) &rec, sizeof(rec), true) <= 0) {
294 break;
295 }
296
297 /* check if record type is definition */
298 if (rec.record_type == RT_DEF) {
299 /* read name */
300 if (xread(fn, fh, event_name, sizeof(event_name)) < 0)
301 return HS_FILE_ERROR;
302
303 printf("Event definition %s, ID %d\n", event_name, rec.event_id);
304
305 /* write definition index record */
306 def_rec.event_id = rec.event_id;
307 memcpy(def_rec.event_name, event_name, sizeof(event_name));
308 DWORD pos = xcurpos(fn, fh);
309 if (pos == (DWORD)-1) return HS_FILE_ERROR;
310 def_rec.def_offset = pos - sizeof(event_name) - sizeof(rec);
311 xwrite(fnd, fhd, (char *) &def_rec, sizeof(def_rec));
312
313 //printf("data def at %d (age %d)\n", rec.time, now-rec.time);
314
315 /* skip tags */
316 xseek_cur(fn, fh, rec.data_size);
317 } else if (rec.record_type == RT_DATA && rec.data_size > 1 && rec.data_size < 1 * 1024 * 1024) {
318 /* write index record */
319 irec.event_id = rec.event_id;
320 irec.time = rec.time;
321 DWORD pos = xcurpos(fn, fh);
322 if (pos == (DWORD)-1) return HS_FILE_ERROR;
323 irec.offset = pos - sizeof(rec);
324 xwrite(fni, fhi, (char *) &irec, sizeof(irec));
325
326 //printf("data rec at %d (age %d)\n", rec.time, now-rec.time);
327
328 /* skip data */
329 xseek_cur(fn, fh, rec.data_size);
330 } else {
331 if (!recovering)
332 cm_msg(MERROR, "hs_gen_index", "broken history file for time %d, trying to recover", (int) ltime);
333
334 recovering = 1;
335 xseek_cur(fn, fh, 1 - (int)sizeof(rec));
336
337 continue;
338 }
339
340 } while (TRUE);
341
342 close(fh);
343 close(fhi);
344 close(fhd);
345
346 printf("...done.\n");
347
348 return HS_SUCCESS;
349}
#define RT_DATA
Definition midas.h:1357
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_get_event_id()

static INT hs_get_event_id ( DWORD  ltime,
const char name,
DWORD id 
)
static

Definition at line 984 of file history.cxx.

1004{
1005 int fh, fhd;
1006 std::string fn, fnd;
1007 INT status;
1008 DWORD lt;
1010
1011 /* search latest history file */
1012 if (ltime == 0)
1013 ltime = (DWORD) time(NULL);
1014
1015 lt = ltime;
1016
1017 do {
1018 status = hs_search_file(&lt, -1);
1019 if (status != HS_SUCCESS) {
1020 cm_msg(MERROR, "hs_count_events", "cannot find recent history file");
1021 return HS_FILE_ERROR;
1022 }
1023
1024 /* open history and definition files */
1025 hs_open_file(lt, "hst", O_RDONLY, &fn, &fh);
1026 hs_open_file(lt, "idf", O_RDONLY, &fnd, &fhd);
1027 if (fh < 0 || fhd < 0) {
1028 cm_msg(MERROR, "hs_count_events", "cannot open index files");
1029 return HS_FILE_ERROR;
1030 }
1031
1032 /* loop over index file */
1033 *id = 0;
1034 do {
1035 /* read definition index record */
1036 if (xread(fnd, fhd, (char *) &def_rec, sizeof(def_rec), true) <= 0)
1037 break;
1038
1039 if (strcmp(name, def_rec.event_name) == 0) {
1040 *id = def_rec.event_id;
1041 close(fh);
1042 close(fhd);
1043 return HS_SUCCESS;
1044 }
1045 } while (TRUE);
1046
1047 close(fh);
1048 close(fhd);
1049
1050 /* not found -> go back one day */
1051 lt -= 3600 * 24;
1052
1053 } while (lt > ltime - 3600 * 24 * 365 * 10); /* maximum 10 years */
1054
1055 return HS_UNDEFINED_EVENT;
1056}
#define HS_UNDEFINED_EVENT
Definition midas.h:732
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_get_events()

int MidasHistory::hs_get_events ( time_t  time_from,
std::vector< std::string > *  pevents 
)
inlinevirtual

get list of events that exist(ed) at given time and later (value 0 means "return all events from beginning of time"), returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 2778 of file history.cxx.

2779 {
2780 assert(pevents);
2781 pevents->clear();
2782
2783 if (fEventsCache.size() == 0) {
2784 int status;
2785
2786 if (fDebug)
2787 printf("hs_get_events: reading events list!\n");
2788
2790
2791 if (status != HS_SUCCESS)
2793
2794 if (status != HS_SUCCESS)
2795 return status;
2796 }
2797
2798 for (unsigned i=0; i<fEventsCache.size(); i++)
2799 pevents->push_back(fEventsCache[i]);
2800
2801 return HS_SUCCESS;
2802 }
int GetEventsFromOdbTags(std::vector< std::string > *events)
Definition history.cxx:2713
int GetEventsFromOdbEvents(std::vector< std::string > *events)
Definition history.cxx:2663
Here is the call graph for this function:

◆ hs_get_last_written()

int MidasHistory::hs_get_last_written ( time_t  start_time,
int  num_var,
const char *const  event_name[],
const char *const  tag_name[],
const int  var_index[],
time_t  last_written[] 
)
inlinevirtual

Implements MidasHistoryInterface.

Definition at line 3178 of file history.cxx.

3179 {
3180 for (int i=0; i<num_var; i++)
3181 last_written[i] = 0;
3182 return HS_FILE_ERROR;
3183 }
Here is the call graph for this function:

◆ hs_get_tags() [1/2]

int MidasHistory::hs_get_tags ( const char event_name,
time_t  time_from,
std::vector< TAG > *  ptags 
)
inlinevirtual

get list of history variables for given event (use event names returned by hs_get_events()) that exist(ed) at given time and later (value 0 means "all variables for this event that ever existed"), also see hs_get_tags(), returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 3151 of file history.cxx.

3152 {
3153 std::vector<TAG>& ttt = fTagsCache[event_name];
3154
3155 if (ttt.size() == 0) {
3156 int status = HS_FILE_ERROR;
3157
3158 if (fDebug)
3159 printf("hs_get_tags: reading tags for event [%s]\n", event_name);
3160
3161 status = GetTagsFromOdb(event_name, &ttt);
3162
3163 if (status != HS_SUCCESS)
3164 status = GetTagsFromHS(event_name, &ttt);
3165
3166 if (status != HS_SUCCESS)
3167 return status;
3168 }
3169
3170 for (unsigned i=0; i<ttt.size(); i++)
3171 ptags->push_back(ttt[i]);
3172
3173 return HS_SUCCESS;
3174 }
int GetTagsFromOdb(const char *event_name, std::vector< TAG > *ptags)
Definition history.cxx:3011
int GetTagsFromHS(const char *event_name, std::vector< TAG > *ptags)
Definition history.cxx:2981
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_get_tags() [2/2]

static INT hs_get_tags ( DWORD  ltime,
DWORD  event_id,
char  event_name[NAME_LENGTH],
int n_tags,
TAG **  tags 
)
static

Definition at line 1328 of file history.cxx.

1351{
1352 int fh, fhd;
1353 std::string fn, fnd;
1354 INT i, n, status;
1357
1358 *n_tags = 0;
1359 *tags = NULL;
1360
1361 if (rpc_is_remote())
1362 assert(!"RPC not implemented");
1363
1364 /* search latest history file */
1365 status = hs_search_file(&ltime, -1);
1366 if (status != HS_SUCCESS) {
1367 cm_msg(MERROR, "hs_get_tags", "cannot find recent history file, hs_search_file() status %d", status);
1368 return HS_FILE_ERROR;
1369 }
1370
1371 /* open history and definition files */
1372 hs_open_file(ltime, "hst", O_RDONLY, &fn, &fh);
1373 hs_open_file(ltime, "idf", O_RDONLY, &fnd, &fhd);
1374 if (fh < 0 || fhd < 0) {
1375 cm_msg(MERROR, "hs_get_tags", "cannot open index files for time %d", ltime);
1376 if (fh>0)
1377 close(fh);
1378 if (fhd>0)
1379 close(fhd);
1380 return HS_FILE_ERROR;
1381 }
1382
1383 /* search last definition */
1384 xseek_end(fnd, fhd);
1385 n = xcurpos(fnd, fhd) / sizeof(def_rec);
1386 def_rec.event_id = 0;
1387 for (i = n - 1; i >= 0; i--) {
1388 if (!xseek(fnd, fhd, i * sizeof(def_rec))) return HS_FILE_ERROR;
1389 if (xread(fnd, fhd, (char *) &def_rec, sizeof(def_rec)) < 0) return HS_FILE_ERROR;
1390 //printf("reading index file found event_id %d, looking for %d\n", def_rec.event_id, event_id);
1391 if (def_rec.event_id == event_id)
1392 break;
1393 }
1394
1395 if (def_rec.event_id != event_id) {
1396 //cm_msg(MERROR, "hs_get_tags", "event %d not found in index file", event_id);
1397 close(fh);
1398 close(fhd);
1399 return HS_UNDEFINED_EVENT;
1400 }
1401
1402 /* read definition header */
1403 if (!xseek(fn, fh, def_rec.def_offset)) return HS_FILE_ERROR;
1404 if (xread(fn, fh, (char *) &rec, sizeof(rec)) < 0) return HS_FILE_ERROR;
1405 if (xread(fn, fh, event_name, NAME_LENGTH) < 0) return HS_FILE_ERROR;
1406
1407 /* read event definition */
1408 *n_tags = rec.data_size / sizeof(TAG);
1409
1410 *tags = (TAG*) malloc(rec.data_size);
1411
1412 if (xread(fn, fh, (char *) (*tags), rec.data_size) < 0) return HS_FILE_ERROR;
1413
1414 close(fh);
1415 close(fhd);
1416
1417 return HS_SUCCESS;
1418}
bool rpc_is_remote(void)
Definition midas.cxx:12761
Here is the call graph for this function:

◆ hs_get_var()

static INT hs_get_var ( DWORD  ltime,
DWORD  event_id,
const char var_name,
DWORD type,
INT n_data 
)
static

Definition at line 1232 of file history.cxx.

1255{
1256 char str[256];
1257 int fh, fhd;
1258 std::string fn, fnd;
1259 INT i, n, status;
1262 TAG *tag;
1263
1264 /* search latest history file */
1265 status = hs_search_file(&ltime, -1);
1266 if (status != HS_SUCCESS) {
1267 cm_msg(MERROR, "hs_get_var", "cannot find recent history file");
1268 return HS_FILE_ERROR;
1269 }
1270
1271 /* open history and definition files */
1272 hs_open_file(ltime, "hst", O_RDONLY, &fn, &fh);
1273 hs_open_file(ltime, "idf", O_RDONLY, &fnd, &fhd);
1274 if (fh < 0 || fhd < 0) {
1275 cm_msg(MERROR, "hs_get_var", "cannot open index files");
1276 return HS_FILE_ERROR;
1277 }
1278
1279 /* search last definition */
1280 xseek_end(fnd, fhd);
1281 n = xcurpos(fnd, fhd) / sizeof(def_rec);
1282 def_rec.event_id = 0;
1283 for (i = n - 1; i >= 0; i--) {
1284 if (!xseek(fnd, fhd, i * sizeof(def_rec))) return HS_FILE_ERROR;
1285 if (xread(fnd, fhd, (char *) &def_rec, sizeof(def_rec)) < 0) return HS_FILE_ERROR;
1286 if (def_rec.event_id == event_id)
1287 break;
1288 }
1289 if (def_rec.event_id != event_id) {
1290 cm_msg(MERROR, "hs_get_var", "event %d not found in index file", event_id);
1291 return HS_FILE_ERROR;
1292 }
1293
1294 /* read definition header */
1295 xseek(fn, fh, def_rec.def_offset);
1296 xread(fn, fh, (char *) &rec, sizeof(rec));
1297 xread(fn, fh, str, NAME_LENGTH);
1298
1299 /* read event definition */
1300 n = rec.data_size / sizeof(TAG);
1301 tag = (TAG *) M_MALLOC(rec.data_size);
1302 xread(fn, fh, (char *) tag, rec.data_size);
1303
1304 /* search variable */
1305 for (i = 0; i < n; i++)
1306 if (strcmp(tag[i].name, var_name) == 0)
1307 break;
1308
1309 close(fh);
1310 close(fhd);
1311
1312 if (i < n) {
1313 *type = tag[i].type;
1314 *n_data = tag[i].n_data;
1315 } else {
1316 *type = *n_data = 0;
1317 cm_msg(MERROR, "hs_get_var", "variable %s not found", var_name);
1318 M_FREE(tag);
1319 return HS_UNDEFINED_VAR;
1320 }
1321
1322 M_FREE(tag);
1323 return HS_SUCCESS;
1324}
Here is the call graph for this function:

◆ hs_open_file()

static INT hs_open_file ( time_t  ltime,
const char suffix,
INT  mode,
std::string *  pfile_name,
int fh 
)
static

dox Open history file belonging to certain date. Internal use only.

Parameters
ltimeDate for which a history file should be opened.
suffixFile name suffix like "hst", "idx", "idf"
modeR/W access mode
fhFile handle
Returns
HS_SUCCESS

Definition at line 206 of file history.cxx.

207{
208 struct tm tms;
210
211 /* generate new file name YYMMDD.xxx */
212 ss_tzset(); // required by localtime_r()
213 ttime = (time_t) ltime;
215
216 //sprintf(file_name, "%s%02d%02d%02d.%s", _hs_path_name, tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday, suffix);
217 std::string file_name;
219 char tmp[100];
220 sprintf(tmp, "%02d%02d%02d", tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday);
221 file_name += tmp;
222 file_name += ".";
223 file_name += suffix;
224
225 if (pfile_name)
227
228 /* open file, add O_BINARY flag for Windows NT */
229 *fh = open(file_name.c_str(), mode | O_BINARY, 0644);
230
231 //printf("hs_open_file: time %d, file \'%s\', fh %d\n", (int)ltime, file_name.c_str(), *fh);
232
233 return HS_SUCCESS;
234}
static std::string _hs_path_name
Definition history.cxx:46
#define O_BINARY
Definition msystem.h:219
char file_name[256]
Definition odbhist.cxx:41
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_read() [1/2]

static INT hs_read ( DWORD  event_id,
DWORD  start_time,
DWORD  end_time,
DWORD  interval,
const char tag_name,
DWORD  var_index,
DWORD time_buffer,
DWORD tbsize,
void data_buffer,
DWORD dbsize,
DWORD data_type,
DWORD data_n,
MidasHistoryBufferInterface buffer 
)
static

Definition at line 1451 of file history.cxx.

1487{
1489 int fh, fhd, fhi, cp = 0;
1490 std::string fn, fnd, fni;
1491 int delta;
1492 int status;
1493 int cache_size;
1497 TAG *tag;
1498 char str[NAME_LENGTH];
1499 char *cache = NULL;
1500 time_t ltime;
1501
1502 int tag_index = -1;
1503 int var_type = -1;
1504 unsigned var_size = 0;
1505 unsigned var_offset = 0;
1506
1507 int ieof = 0;
1508
1509 //printf("hs_read event %d, time %d:%d, tagname: \'%s\', varindex: %d\n", event_id, start_time, end_time, tag_name, var_index);
1510
1511 ss_tzset(); // required by localtime_r()
1512
1513 /* if not time given, use present to one hour in past */
1514 if (start_time == 0)
1515 start_time = (DWORD) time(NULL) - 3600;
1516 if (end_time == 0)
1517 end_time = (DWORD) time(NULL);
1518
1519 if (data_n)
1520 *data_n = 0;
1521 prev_time = 0;
1522 last_irec_time = start_time;
1523
1524 /* search history file for start_time */
1525 status = hs_search_file(&start_time, 1);
1526 if (status != HS_SUCCESS) {
1527 //cm_msg(MERROR, "hs_read", "cannot find recent history file");
1528 if (data_n)
1529 *data_n = 0;
1530 if (tbsize)
1531 *tbsize = 0;
1532 if (dbsize)
1533 *dbsize = 0;
1534 return HS_FILE_ERROR;
1535 }
1536
1537 /* open history and definition files */
1538 hs_open_file(start_time, "hst", O_RDONLY, &fn, &fh);
1539 hs_open_file(start_time, "idf", O_RDONLY, &fnd, &fhd);
1540 hs_open_file(start_time, "idx", O_RDONLY, &fni, &fhi);
1541 if (fh < 0 || fhd < 0 || fhi < 0) {
1542 cm_msg(MERROR, "hs_read", "cannot open index files");
1543 if (tbsize)
1544 *tbsize = 0;
1545 if (dbsize)
1546 *dbsize = 0;
1547 if (data_n)
1548 *data_n = 0;
1549 if (fh > 0)
1550 close(fh);
1551 if (fhd > 0)
1552 close(fhd);
1553 if (fhi > 0)
1554 close(fhi);
1555 return HS_FILE_ERROR;
1556 }
1557
1558 /* try to read index file into cache */
1559 xseek_end(fni, fhi);
1561
1562 if (cache_size == 0) {
1563 goto nextday;
1564 }
1565
1566 if (cache_size > 0) {
1567 cache = (char *) M_MALLOC(cache_size);
1568 if (cache) {
1569 xseek(fni, fhi, 0);
1570 if (xread(fni, fhi, cache, cache_size) < 0) {
1571 M_FREE(cache);
1572 if (fh > 0)
1573 close(fh);
1574 if (fhd > 0)
1575 close(fhd);
1576 if (fhi > 0)
1577 close(fhi);
1578 return HS_FILE_ERROR;
1579 }
1580 }
1581
1582 /* search record closest to start time */
1583 if (cache == NULL) {
1584 xseek_end(fni, fhi);
1585 delta = (xcurpos(fni, fhi) / sizeof(irec)) / 2;
1586 xseek(fni, fhi, delta * sizeof(irec));
1587 do {
1588 delta = (int) (abs(delta) / 2.0 + 0.5);
1589 if (xread(fni, fhi, (char *) &irec, sizeof(irec)) < 0)
1590 return HS_FILE_ERROR;
1591 if (irec.time > start_time)
1592 delta = -delta;
1593
1594 xseek_cur(fni, fhi, (delta - 1) * sizeof(irec));
1595 } while (abs(delta) > 1 && irec.time != start_time);
1596 if (xread(fni, fhi, (char *) &irec, sizeof(irec)) < 0)
1597 return HS_FILE_ERROR;
1598 if (irec.time > start_time)
1599 delta = -abs(delta);
1600
1601 int i = xcurpos(fni, fhi) + (delta - 1) * sizeof(irec);
1602 if (i <= 0)
1603 xseek(fni, fhi, 0);
1604 else
1605 xseek_cur(fni, fhi, (delta - 1) * sizeof(irec));
1606 if (xread(fni, fhi, (char *) &irec, sizeof(irec)) < 0)
1607 return HS_FILE_ERROR;
1608 } else {
1609 delta = (cache_size / sizeof(irec)) / 2;
1610 cp = delta * sizeof(irec);
1611 do {
1612 delta = (int) (abs(delta) / 2.0 + 0.5);
1613 pirec = (INDEX_RECORD *) (cache + cp);
1614
1615 //printf("pirec %p, cache %p, cp %d\n", pirec, cache, cp);
1616
1617 if (pirec->time > start_time)
1618 delta = -delta;
1619
1620 cp = cp + delta * sizeof(irec);
1621
1622 if (cp < 0)
1623 cp = 0;
1624 if (cp >= cache_size)
1625 cp = cache_size - sizeof(irec);
1626 } while (abs(delta) > 1 && pirec->time != start_time);
1627 pirec = (INDEX_RECORD *) (cache + cp);
1628 if (pirec->time > start_time)
1629 delta = -abs(delta);
1630
1631 if (cp <= delta * (int) sizeof(irec))
1632 cp = 0;
1633 else
1634 cp = cp + delta * sizeof(irec);
1635
1636 if (cp >= cache_size)
1637 cp = cache_size - sizeof(irec);
1638 if (cp < 0)
1639 cp = 0;
1640
1641 memcpy(&irec, (INDEX_RECORD *) (cache + cp), sizeof(irec));
1642 cp += sizeof(irec);
1643 }
1644 } else { /* file size > 0 */
1645
1646 cache = NULL;
1647 irec.time = start_time;
1648 }
1649
1650 /* read records, skip wrong IDs */
1651 old_def_offset = -1;
1652 last_irec_time = start_time - 24 * 60 * 60;
1653 do {
1654 //printf("time %d -> %d\n", last_irec_time, irec.time);
1655
1656 if (irec.time < last_irec_time) {
1657 cm_msg(MERROR, "hs_read", "corrupted history data: time does not increase: %d -> %d", last_irec_time, irec.time);
1658 //*tbsize = *dbsize = *n = 0;
1659 if (fh > 0)
1660 close(fh);
1661 if (fhd > 0)
1662 close(fhd);
1663 if (fhi > 0)
1664 close(fhi);
1666 return HS_SUCCESS;
1667 }
1668 last_irec_time = irec.time;
1669 if (irec.event_id == event_id && irec.time <= end_time && irec.time >= start_time) {
1670 /* check if record time more than "interval" seconds after previous time */
1671 if (irec.time >= prev_time + interval) {
1672 prev_time = irec.time;
1673 xseek(fn, fh, irec.offset);
1674 if (xread(fn, fh, (char *) &rec, sizeof(rec)) < 0) {
1675 cm_msg(MERROR, "hs_read", "corrupted history data at time %d", (int) irec.time);
1676 //*tbsize = *dbsize = *n = 0;
1677 if (fh > 0)
1678 close(fh);
1679 if (fhd > 0)
1680 close(fhd);
1681 if (fhi > 0)
1682 close(fhi);
1684 return HS_SUCCESS;
1685 }
1686
1687 /* if definition changed, read new definition */
1688 if ((INT) rec.def_offset != old_def_offset) {
1689 xseek(fn, fh, rec.def_offset);
1690 xread(fn, fh, (char *) &drec, sizeof(drec));
1691 xread(fn, fh, str, NAME_LENGTH);
1692
1693 tag = (TAG *) M_MALLOC(drec.data_size);
1694 if (tag == NULL) {
1695 if (data_n)
1696 *data_n = 0;
1697 if (tbsize)
1698 *tbsize = 0;
1699 if (dbsize)
1700 *dbsize = 0;
1701 if (cache)
1702 M_FREE(cache);
1703 if (fh > 0)
1704 close(fh);
1705 if (fhd > 0)
1706 close(fhd);
1707 if (fhi > 0)
1708 close(fhi);
1709 return HS_NO_MEMORY;
1710 }
1711 xread(fn, fh, (char *) tag, drec.data_size);
1712
1713 /* find index of tag_name in new definition */
1714 for (DWORD i = 0; i < drec.data_size / sizeof(TAG); i++)
1715 if (equal_ustring(tag[i].name, tag_name)) {
1716 tag_index = i;
1717 break;
1718 }
1719
1720 /*
1721 if ((DWORD) i == drec.data_size/sizeof(TAG))
1722 {
1723 *n = *tbsize = *dbsize = 0;
1724 if (cache)
1725 M_FREE(cache);
1726
1727 return HS_UNDEFINED_VAR;
1728 }
1729 */
1730
1731 if (tag_index >= 0 && var_index >= tag[tag_index].n_data) {
1732 if (data_n)
1733 *data_n = 0;
1734 if (tbsize)
1735 *tbsize = 0;
1736 if (dbsize)
1737 *dbsize = 0;
1738 if (cache)
1739 M_FREE(cache);
1740 M_FREE(tag);
1741 if (fh > 0)
1742 close(fh);
1743 if (fhd > 0)
1744 close(fhd);
1745 if (fhi > 0)
1746 close(fhi);
1747 return HS_WRONG_INDEX;
1748 }
1749
1750 /* calculate offset for variable */
1751 if (tag_index >= 0) {
1752 var_type = tag[tag_index].type;
1753
1754 if (data_type)
1756
1757 /* loop over all previous variables */
1758 var_offset = 0;
1759 for (int i=0; i<tag_index; i++)
1760 var_offset += rpc_tid_size(tag[i].type) * tag[i].n_data;
1761
1762 /* strings have size n_data */
1763 if (tag[tag_index].type == TID_STRING)
1764 var_size = tag[tag_index].n_data;
1765 else
1767
1768 var_offset += var_size * var_index;
1769 }
1770
1771 M_FREE(tag);
1772 old_def_offset = rec.def_offset;
1773 xseek(fn, fh, irec.offset + sizeof(rec));
1774 }
1775
1776 if (buffer) {
1777 /* copy time from header */
1778 DWORD t = irec.time;
1779 char buf[16]; // biggest data is 8-byte "double"
1780 assert(var_size <= sizeof(buf));
1781 xseek_cur(fn, fh, var_offset);
1782 xread(fn, fh, buf, var_size);
1783 buffer->Add(t, hs_to_double(var_type, buf));
1784 } else if (tag_index >= 0 && data_n) {
1785 /* check if data fits in buffers */
1786 if ((*data_n) * sizeof(DWORD) >= *tbsize || (*data_n) * var_size >= *dbsize) {
1787 *dbsize = (*data_n) * var_size;
1788 *tbsize = (*data_n) * sizeof(DWORD);
1789 if (cache)
1790 M_FREE(cache);
1791 if (fh > 0)
1792 close(fh);
1793 if (fhd > 0)
1794 close(fhd);
1795 if (fhi > 0)
1796 close(fhi);
1797 return HS_TRUNCATED;
1798 }
1799
1800 /* copy time from header */
1801 time_buffer[*data_n] = irec.time;
1802
1803 /* copy data from record */
1804 xseek_cur(fn, fh, var_offset);
1805 xread(fn, fh, (char *) data_buffer + (*data_n) * var_size, var_size);
1806
1807 /* increment counter */
1808 (*data_n)++;
1809 }
1810 }
1811 }
1812
1813 /* read next index record */
1814 if (cache) {
1815 if (cp >= cache_size) {
1816 ieof = -1;
1817 M_FREE(cache);
1818 cache = NULL;
1819 } else {
1820
1821 try_again:
1822
1823 ieof = sizeof(irec);
1824
1825 memcpy(&irec, cache + cp, sizeof(irec));
1826 cp += sizeof(irec);
1827
1828 /* if history file is broken ... */
1829 if (irec.time < last_irec_time || irec.time > last_irec_time + 24 * 60 * 60) {
1830 //if (irec.time < last_irec_time) {
1831 //printf("time %d -> %d, cache_size %d, cp %d\n", last_irec_time, irec.time, cache_size, cp);
1832
1833 //printf("Seeking next record...\n");
1834
1835 while (cp < cache_size) {
1836 DWORD *evidp = (DWORD *) (cache + cp);
1837 if (*evidp == event_id) {
1838 //printf("Found at cp %d\n", cp);
1839 goto try_again;
1840 }
1841
1842 cp++;
1843 }
1844
1845 ieof = -1;
1846 }
1847 }
1848 } else {
1849 ieof = xread(fni, fhi, (char *) &irec, sizeof(irec), true);
1850 }
1851
1852 /* end of file: search next history file */
1853 if (ieof <= 0) {
1854 nextday:
1855
1856 if (fh > 0)
1857 close(fh);
1858 if (fhd > 0)
1859 close(fhd);
1860 if (fhi > 0)
1861 close(fhi);
1862 fh = fhd = fhi = 0;
1863
1864 /* advance one day */
1866 struct tm tms;
1867 localtime_r(&ltime, &tms);
1868 tms.tm_hour = tms.tm_min = tms.tm_sec = 0;
1870
1871 last_irec_time += 3600 * 24;
1872
1873 if (last_irec_time > end_time)
1874 break;
1875
1876 /* search next file */
1878 if (status != HS_SUCCESS)
1879 break;
1880
1881 /* open history and definition files */
1882 hs_open_file(last_irec_time, "hst", O_RDONLY, &fn, &fh);
1885 if (fh < 0 || fhd < 0 || fhi < 0) {
1886 cm_msg(MERROR, "hs_read", "cannot open index files");
1887 break;
1888 }
1889
1890 /* try to read index file into cache */
1891 xseek_end(fni, fhi);
1893
1894 if (cache_size == 0) {
1895 goto nextday;
1896 }
1897
1898 xseek(fni, fhi, 0);
1899 cache = (char *) M_MALLOC(cache_size); // FIXME: is this a memory leak?
1900 if (cache) {
1901 if (xread(fni, fhi, cache, cache_size) < 0) {
1902 break;
1903 }
1904 /* read first record */
1905 cp = 0;
1906 memcpy(&irec, cache, sizeof(irec));
1907 } else {
1908 /* read first record */
1909 if (xread(fni, fhi, (char *) &irec, sizeof(irec)) < 0) {
1910 break;
1911 }
1912 }
1913
1914 /* old definition becomes invalid */
1915 old_def_offset = -1;
1916 }
1917 //if (event_id==4 && irec.event_id == event_id)
1918 // printf("time %d end %d\n", irec.time, end_time);
1919 } while (irec.time < end_time);
1920
1921 if (cache)
1922 M_FREE(cache);
1923 if (fh)
1924 close(fh);
1925 if (fhd)
1926 close(fhd);
1927 if (fhi)
1928 close(fhi);
1929
1930 if (dbsize && data_n)
1931 *dbsize = *data_n * var_size;
1932 if (tbsize && data_n)
1933 *tbsize = *data_n * sizeof(DWORD);
1934
1935 return HS_SUCCESS;
1936}
virtual void Add(time_t time, double value)=0
#define HS_TRUNCATED
Definition midas.h:730
#define HS_WRONG_INDEX
Definition midas.h:731
double hs_to_double(int tid, const void *ybuffer)
Definition history.cxx:1420
Here is the call graph for this function:

◆ hs_read() [2/2]

int MidasHistory::hs_read ( time_t  start_time,
time_t  end_time,
time_t  interval,
int  num_var,
const char *const  event_name[],
const char *const  tag_name[],
const int  var_index[],
int  num_entries[],
time_t time_buffer[],
double data_buffer[],
int  status[] 
)
inlinevirtual

see hs_read(), returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 3188 of file history.cxx.

3194 {
3195 DWORD* tbuffer = NULL;
3196 char* ybuffer = NULL;
3197 DWORD bsize, tsize;
3198 int hbuffer_size = 0;
3199
3200 if (hbuffer_size == 0) {
3201 hbuffer_size = 1000 * sizeof(DWORD);
3203 ybuffer = (char*)malloc(hbuffer_size);
3204 }
3205
3206 for (int i=0; i<num_var; i++) {
3207 DWORD tid = 0;
3208 int event_id = 0;
3209
3210 if (event_name[i]==NULL) {
3212 num_entries[i] = 0;
3213 continue;
3214 }
3215
3216 int status = GetEventId(end_time, event_name[i], tag_name[i], &event_id);
3217
3218 if (status != HS_SUCCESS) {
3219 read_status[i] = status;
3220 continue;
3221 }
3222
3223 DWORD n_point = 0;
3224
3225 do {
3227 memset(ybuffer, 0, bsize);
3228 status = ::hs_read(event_id, (DWORD)start_time, (DWORD)end_time, (DWORD)interval,
3229 tag_name[i], var_index[i],
3230 tbuffer, &tsize,
3231 ybuffer, &bsize,
3232 &tid, &n_point,
3233 NULL);
3234
3235 if (fDebug)
3236 printf("hs_read %d \'%s\' [%d] returned %d, %d entries\n", event_id, tag_name[i], var_index[i], status, n_point);
3237
3238 if (status == HS_TRUNCATED) {
3239 hbuffer_size *= 2;
3241 assert(tbuffer);
3243 assert(ybuffer);
3244 }
3245
3246 } while (status == HS_TRUNCATED);
3247
3248 read_status[i] = status;
3249
3250 time_t* x = (time_t*)malloc(n_point*sizeof(time_t));
3251 assert(x);
3252 double* y = (double*)malloc(n_point*sizeof(double));
3253 assert(y);
3254
3255 time_buffer[i] = x;
3256 data_buffer[i] = y;
3257
3258 int n_vp = 0;
3259
3260 for (unsigned j = 0; j < n_point; j++) {
3261 x[n_vp] = tbuffer[j];
3262
3263 /* convert data to float */
3264 switch (tid) {
3265 default:
3266 y[n_vp] = 0;
3267 break;
3268 case TID_BYTE:
3269 y[n_vp] = *(((BYTE *) ybuffer) + j);
3270 break;
3271 case TID_SBYTE:
3272 y[n_vp] = *(((char *) ybuffer) + j);
3273 break;
3274 case TID_CHAR:
3275 y[n_vp] = *(((char *) ybuffer) + j);
3276 break;
3277 case TID_WORD:
3278 y[n_vp] = *(((WORD *) ybuffer) + j);
3279 break;
3280 case TID_SHORT:
3281 y[n_vp] = *(((short *) ybuffer) + j);
3282 break;
3283 case TID_DWORD:
3284 y[n_vp] = *(((DWORD *) ybuffer) + j);
3285 break;
3286 case TID_INT:
3287 y[n_vp] = *(((INT *) ybuffer) + j);
3288 break;
3289 case TID_BOOL:
3290 y[n_vp] = *(((BOOL *) ybuffer) + j);
3291 break;
3292 case TID_FLOAT:
3293 y[n_vp] = *(((float *) ybuffer) + j);
3294 break;
3295 case TID_DOUBLE:
3296 y[n_vp] = *(((double *) ybuffer) + j);
3297 break;
3298 }
3299
3300 n_vp++;
3301 }
3302
3303 num_entries[i] = n_vp;
3304 }
3305
3306 if (ybuffer)
3307 free(ybuffer);
3308 if (tbuffer)
3309 free(tbuffer);
3310
3311 return HS_SUCCESS;
3312 }
int hs_read(time_t start_time, time_t end_time, time_t interval, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], int num_entries[], time_t *time_buffer[], double *data_buffer[], int read_status[])
see hs_read(), returns HS_SUCCESS
Definition history.cxx:3188
unsigned char BYTE
Definition mcstd.h:48
#define TID_DOUBLE
Definition midas.h:343
#define TID_SBYTE
Definition midas.h:329
#define TID_SHORT
Definition midas.h:334
#define TID_BYTE
Definition midas.h:327
#define TID_CHAR
Definition midas.h:331
#define TID_INT
Definition midas.h:338
#define TID_FLOAT
Definition midas.h:341
#define TID_DWORD
Definition midas.h:336
DWORD BOOL
Definition midas.h:105
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_read_binned()

int MidasHistory::hs_read_binned ( time_t  start_time,
time_t  end_time,
int  num_bins,
int  num_var,
const char *const  event_name[],
const char *const  tag_name[],
const int  var_index[],
int  num_entries[],
int count_bins[],
double mean_bins[],
double rms_bins[],
double min_bins[],
double max_bins[],
time_t bins_first_time[],
double bins_first_value[],
time_t bins_last_time[],
double bins_last_value[],
time_t  last_time[],
double  last_value[],
int  status[] 
)
inlinevirtual

returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 3383 of file history.cxx.

3391 {
3392 int status;
3393
3396
3397 for (int i=0; i<num_var; i++) {
3398 buffer[i] = new MidasHistoryBinnedBuffer(start_time, end_time, num_bins);
3399 xbuffer[i] = buffer[i];
3400
3401 if (count_bins)
3402 buffer[i]->fCount = count_bins[i];
3403 if (mean_bins)
3404 buffer[i]->fMean = mean_bins[i];
3405 if (rms_bins)
3406 buffer[i]->fRms = rms_bins[i];
3407 if (min_bins)
3408 buffer[i]->fMin = min_bins[i];
3409 if (max_bins)
3410 buffer[i]->fMax = max_bins[i];
3411 if (bins_first_time)
3412 buffer[i]->fBinsFirstTime = bins_first_time[i];
3413 if (bins_first_value)
3414 buffer[i]->fBinsFirstValue = bins_first_value[i];
3415 if (bins_last_time)
3416 buffer[i]->fBinsLastTime = bins_last_time[i];
3417 if (bins_last_value)
3418 buffer[i]->fBinsLastValue = bins_last_value[i];
3419 if (last_time)
3420 buffer[i]->fLastTimePtr = &last_time[i];
3421 if (last_value)
3422 buffer[i]->fLastValuePtr = &last_value[i];
3423
3424 buffer[i]->Start();
3425 }
3426
3427 status = hs_read_buffer(start_time, end_time,
3428 num_var, event_name, tag_name, var_index,
3429 xbuffer,
3430 read_status);
3431
3432 for (int i=0; i<num_var; i++) {
3433 buffer[i]->Finish();
3434 if (num_entries)
3435 num_entries[i] = buffer[i]->fNumEntries;
3436 //if (0) {
3437 // for (int j=0; j<num_bins; j++) {
3438 // printf("var %d bin %d count %d, first %s last %s value first %f last %f\n", i, j, count_bins[i][j], TimeToString(bins_first_time[i][j]).c_str(), TimeToString(bins_last_time[i][j]).c_str(), bins_first_value[i][j], bins_last_value[i][j]);
3439 // }
3440 //}
3441 delete buffer[i];
3442 }
3443
3444 delete[] buffer;
3445 delete[] xbuffer;
3446
3447 return status;
3448 }
int hs_read_buffer(time_t start_time, time_t end_time, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], MidasHistoryBufferInterface *buffer[], int read_status[])
returns HS_SUCCESS
Definition history.cxx:3346
DWORD last_time
Definition mana.cxx:3070
Here is the call graph for this function:

◆ hs_read_buffer()

int MidasHistory::hs_read_buffer ( time_t  start_time,
time_t  end_time,
int  num_var,
const char *const  event_name[],
const char *const  tag_name[],
const int  var_index[],
MidasHistoryBufferInterface buffer[],
int  status[] 
)
inlinevirtual

returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 3346 of file history.cxx.

3350 {
3351 for (int i=0; i<num_var; i++) {
3352 int event_id = 0;
3353
3354 if (event_name[i]==NULL) {
3356 continue;
3357 }
3358
3359 int status = GetEventId(end_time, event_name[i], tag_name[i], &event_id);
3360
3361 if (status != HS_SUCCESS) {
3362 read_status[i] = status;
3363 continue;
3364 }
3365
3366 status = ::hs_read(event_id, (DWORD)start_time, (DWORD)end_time, 0,
3367 tag_name[i], var_index[i],
3368 NULL, NULL,
3369 NULL, NULL,
3370 NULL, NULL,
3371 buffer[i]);
3372
3373 if (fDebug) {
3374 printf("hs_read %d \'%s\' [%d] returned %d\n", event_id, tag_name[i], var_index[i], status);
3375 }
3376
3377 read_status[i] = status;
3378 }
3379
3380 return HS_SUCCESS;
3381 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_search_file()

static INT hs_search_file ( DWORD ltime,
INT  direction 
)
static

Definition at line 353 of file history.cxx.

374{
375 time_t lt;
376 int fh, fhd, fhi;
377 std::string fn;
378
379 ss_tzset(); // required by localtime_r()
380
381 if (*ltime == 0)
382 *ltime = ss_time();
383
384 lt = (time_t) * ltime;
385 do {
386 /* try to open history file for date "lt" */
387 hs_open_file(lt, "hst", O_RDONLY, &fn, &fh);
388
389 /* if not found, look for next day */
390 if (fh < 0)
391 lt += direction * 3600 * 24;
392
393 /* stop if more than a year before starting point or in the future */
394 } while (fh < 0 && (INT) * ltime - (INT) lt < 3600 * 24 * 365 && lt <= (time_t) ss_time());
395
396 if (fh < 0)
397 return HS_FILE_ERROR;
398
399 if (lt != (time_t) *ltime) {
400 /* if switched to new day, set start_time to 0:00 */
401 struct tm tms;
402 localtime_r(&lt, &tms);
403 tms.tm_hour = tms.tm_min = tms.tm_sec = 0;
404 *ltime = (DWORD) ss_mktime(&tms);
405 }
406
407 /* check if index files are there */
408 hs_open_file(*ltime, "idf", O_RDONLY, NULL, &fhd);
409 hs_open_file(*ltime, "idx", O_RDONLY, NULL, &fhi);
410
411 if (fh > 0)
412 close(fh);
413 if (fhd > 0)
414 close(fhd);
415 if (fhi > 0)
416 close(fhi);
417
418 /* generate them if not */
419 if (fhd < 0 || fhi < 0)
421
422 return HS_SUCCESS;
423}
DWORD ss_time()
Definition system.cxx:3462
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_set_debug()

int MidasHistory::hs_set_debug ( int  debug)
inlinevirtual

set debug level, returns previous debug level

Implements MidasHistoryInterface.

Definition at line 2271 of file history.cxx.

2272 {
2273 return debug;
2274 }
BOOL debug
debug printouts
Definition mana.cxx:254

◆ hs_set_path()

static INT hs_set_path ( const char path)
static

Sets the path for future history file accesses. Should be called before any other history function is called.

Parameters
pathDirectory where history files reside
Returns
HS_SUCCESS

Definition at line 178 of file history.cxx.

179{
180 assert(path);
181 assert(path[0] != 0);
182
183 _hs_path_name = path;
184
185 /* check for trailing directory seperator */
186 if (_hs_path_name.back() != DIR_SEPARATOR)
188
189 return HS_SUCCESS;
190}
#define DIR_SEPARATOR
Definition midas.h:193
#define DIR_SEPARATOR_STR
Definition midas.h:194
Here is the caller graph for this function:

◆ hs_to_double()

double hs_to_double ( int  tid,
const void ybuffer 
)

Definition at line 1420 of file history.cxx.

1421{
1422 int j = 0;
1423 /* convert data to float */
1424 switch (tid) {
1425 default:
1426 return 0;
1427 case TID_BYTE:
1428 return *(((BYTE *) ybuffer) + j);
1429 case TID_SBYTE:
1430 return *(((char *) ybuffer) + j);
1431 case TID_CHAR:
1432 return *(((char *) ybuffer) + j);
1433 case TID_WORD:
1434 return *(((WORD *) ybuffer) + j);
1435 case TID_SHORT:
1436 return *(((short *) ybuffer) + j);
1437 case TID_DWORD:
1438 return *(((DWORD *) ybuffer) + j);
1439 case TID_INT:
1440 return *(((INT *) ybuffer) + j);
1441 case TID_BOOL:
1442 return *(((BOOL *) ybuffer) + j);
1443 case TID_FLOAT:
1444 return *(((float *) ybuffer) + j);
1445 case TID_DOUBLE:
1446 return *(((double *) ybuffer) + j);
1447 }
1448 /* NOT REACHED */
1449}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_write_event() [1/2]

int MidasHistory::hs_write_event ( const char event_name,
time_t  timestamp,
int  data_size,
const char data 
)
inlinevirtual

see hs_write_event(), returns HS_SUCCESS or HS_FILE_ERROR

Implements MidasHistoryInterface.

Definition at line 2646 of file history.cxx.

2647 {
2648 int event_id = fEvidCache[event_name];
2649 //printf("write event [%s] evid %d\n", event_name, event_id);
2650 return ::hs_write_event(event_id, (void*)data, data_size);
2651 }
void * data
Definition mana.cxx:268

◆ hs_write_event() [2/2]

static INT hs_write_event ( DWORD  event_id,
const void data,
DWORD  size 
)
static

Definition at line 656 of file history.cxx.

679{
683 int fh, fhi, fhd;
685 std::string fn, fni, fnd;
686 INT semaphore;
687 int status;
688 struct tm tmb, tmr;
690
691 /* request semaphore */
693 status = ss_semaphore_wait_for(semaphore, 5 * 1000);
694 if (status != SS_SUCCESS) {
695 cm_msg(MERROR, "hs_write_event", "semaphore timeout");
696 return SUCCESS; /* someone else blocked the history system */
697 }
698
699 /* find index to history structure */
700 int index = -1;
701 for (unsigned i = 0; i < _history.size(); i++)
702 if (_history[i]->event_id == event_id) {
703 index = i;
704 break;
705 }
706 if (index < 0) {
707 ss_semaphore_release(semaphore);
708 return HS_UNDEFINED_EVENT;
709 }
710
711 /* assemble record header */
712 rec.record_type = RT_DATA;
713 rec.event_id = _history[index]->event_id;
714 rec.time = (DWORD) time(NULL);
715 rec.def_offset = _history[index]->def_offset;
716 rec.data_size = size;
717
718 irec.event_id = _history[index]->event_id;
719 irec.time = rec.time;
720
721 /* check if new day */
722 ltime = (time_t) rec.time;
723 localtime_r(&ltime, &tmr); // somebody must call tzset() before this.
724 ltime = (time_t) _history[index]->base_time;
725 localtime_r(&ltime, &tmb); // somebody must call tzset() before this.
726
727 if (tmr.tm_yday != tmb.tm_yday) {
728 /* close current history file */
729 close(_history[index]->hist_fh);
730 close(_history[index]->def_fh);
731 close(_history[index]->index_fh);
732
733 /* open new history file */
734 hs_open_file(rec.time, "hst", O_CREAT | O_RDWR, &fn, &fh);
735 if (fh < 0) {
736 ss_semaphore_release(semaphore);
737 return HS_FILE_ERROR;
738 }
739
740 /* open new index file */
741 hs_open_file(rec.time, "idx", O_CREAT | O_RDWR, &fni, &fhi);
742 if (fhi < 0) {
743 ss_semaphore_release(semaphore);
744 return HS_FILE_ERROR;
745 }
746
747 /* open new definition index file */
748 hs_open_file(rec.time, "idf", O_CREAT | O_RDWR, &fnd, &fhd);
749 if (fhd < 0) {
750 ss_semaphore_release(semaphore);
751 return HS_FILE_ERROR;
752 }
753
754 xseek_end(fn, fh);
755 xseek_end(fni, fhi);
756 xseek_end(fnd, fhd);
757
758 /* remember new file handles */
759 _history[index]->hist_fn = fn;
760 _history[index]->index_fn = fni;
761 _history[index]->def_fn = fnd;
762
763 _history[index]->hist_fh = fh;
764 _history[index]->index_fh = fhi;
765 _history[index]->def_fh = fhd;
766
767 _history[index]->def_offset = xcurpos(fn, fh);
768 rec.def_offset = _history[index]->def_offset;
769
770 tmr.tm_hour = tmr.tm_min = tmr.tm_sec = 0;
771 _history[index]->base_time = (DWORD) ss_mktime(&tmr);
772
773 /* write definition from _history structure */
774 drec.record_type = RT_DEF;
775 drec.event_id = _history[index]->event_id;
776 drec.time = rec.time;
777 drec.data_size = _history[index]->n_tag * sizeof(TAG);
778
779 xwrite(fn, fh, (char *) &drec, sizeof(drec));
780 xwrite(fn, fh, _history[index]->event_name.c_str(), NAME_LENGTH);
781 xwrite(fn, fh, (char *) _history[index]->tag, drec.data_size);
782
783 /* write definition index record */
784 def_rec.event_id = _history[index]->event_id;
785 memcpy(def_rec.event_name, _history[index]->event_name.c_str(), sizeof(def_rec.event_name));
786 def_rec.def_offset = _history[index]->def_offset;
787 xwrite(fnd, fhd, (char *) &def_rec, sizeof(def_rec));
788 }
789
790 /* go to end of file */
791 xseek_end(_history[index]->hist_fn, _history[index]->hist_fh);
792 last_pos_data = irec.offset = xcurpos(_history[index]->hist_fn, _history[index]->hist_fh);
793
794 /* write record header */
795 xwrite(_history[index]->hist_fn, _history[index]->hist_fh, (char *) &rec, sizeof(rec));
796
797 /* write data */
798 if (!xwrite(_history[index]->hist_fn, _history[index]->hist_fh, (char *) data, size)) {
799 /* disk maybe full? Do a roll-back! */
800 xtruncate(_history[index]->hist_fn, _history[index]->hist_fh, last_pos_data);
801 ss_semaphore_release(semaphore);
802 return HS_FILE_ERROR;
803 }
804
805 /* write index record */
806 xseek_end(_history[index]->index_fn, _history[index]->index_fh);
807 last_pos_index = xcurpos(_history[index]->index_fn, _history[index]->index_fh);
808 int size_of_irec = sizeof(irec);
809 if (!xwrite(_history[index]->index_fn, _history[index]->index_fh, (char *) &irec, size_of_irec)) {
810 /* disk maybe full? Do a roll-back! */
811 xtruncate(_history[index]->hist_fn, _history[index]->hist_fh, last_pos_data);
812 xtruncate(_history[index]->index_fn, _history[index]->index_fh, last_pos_index);
813 ss_semaphore_release(semaphore);
814 return HS_FILE_ERROR;
815 }
816
817 ss_semaphore_release(semaphore);
818 return HS_SUCCESS;
819}
static bool xtruncate(const std::string &fn, int fh, DWORD pos)
Definition history.cxx:152
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MakeMidasHistory()

MidasHistoryInterface * MakeMidasHistory ( )

Definition at line 3583 of file history.cxx.

3584{
3585#if 0
3586 // midas history is a singleton class
3587 static MidasHistory* gh = NULL;
3588 if (!gh)
3589 gh = new MidasHistory;
3590 return gh;
3591#endif
3592 return new MidasHistory();
3593}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ xcurpos()

static DWORD xcurpos ( const std::string &  fn,
int  fh 
)
static

Definition at line 133 of file history.cxx.

134{
135 off_t off = lseek(fh, 0, SEEK_CUR);
136
137 if (off < 0) {
138 cm_msg(MERROR, "xcurpos", "Error in lseek(0, SEEK_CUR) for file \"%s\", errno %d (%s)", fn.c_str(), errno, strerror(errno));
139 return -1;
140 }
141
142 DWORD dw = off;
143
144 if (dw != off) {
145 cm_msg(MERROR, "xcurpos", "Error: lseek(0, SEEK_CUR) for file \"%s\" returned value %llu does not fir into a DWORD, maybe file is bigger than 2GiB or 4GiB", fn.c_str(), (unsigned long long)off);
146 return -1;
147 }
148
149 return dw;
150}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ xread()

static int xread ( const std::string &  fn,
int  fh,
void buf,
size_t  count,
bool  eof_ok = false 
)
static

Definition at line 73 of file history.cxx.

74{
75 ssize_t rd = read(fh, buf, count);
76
77 if (rd < 0) {
78 cm_msg(MERROR, "xread", "Error reading from file \"%s\" errno %d (%s)", fn.c_str(), errno, strerror(errno));
79 return -1;
80 }
81
82 if (rd == 0) {
83 if (eof_ok)
84 return 0;
85 cm_msg(MERROR, "xread", "Error: Unexpected end-of-file when reading file \"%s\"", fn.c_str());
86 return -1;
87 }
88
89 if ((size_t)rd != count) {
90 cm_msg(MERROR, "xread", "Error: Truncated read from file \"%s\", requested %d bytes, read %d bytes", fn.c_str(), (int)count, (int)rd);
91 return -1;
92 }
93
94 return 1;
95}
#define read(n, a, f)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ xseek()

static bool xseek ( const std::string &  fn,
int  fh,
DWORD  pos 
)
static

Definition at line 97 of file history.cxx.

98{
99 off_t off = lseek(fh, pos, SEEK_SET);
100
101 if (off < 0) {
102 cm_msg(MERROR, "xseek", "Error in lseek(%llu, SEEK_SET) for file \"%s\", errno %d (%s)", (unsigned long long)pos, fn.c_str(), errno, strerror(errno));
103 return false;
104 }
105
106 return true;
107}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ xseek_cur()

static bool xseek_cur ( const std::string &  fn,
int  fh,
int  offset 
)
static

Definition at line 121 of file history.cxx.

122{
124
125 if (off < 0) {
126 cm_msg(MERROR, "xseek_cur", "Error in lseek(%d, SEEK_CUR) for file \"%s\", errno %d (%s)", offset, fn.c_str(), errno, strerror(errno));
127 return false;
128 }
129
130 return true;
131}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ xseek_end()

static bool xseek_end ( const std::string &  fn,
int  fh 
)
static

Definition at line 109 of file history.cxx.

110{
111 off_t off = lseek(fh, 0, SEEK_END);
112
113 if (off < 0) {
114 cm_msg(MERROR, "xseek_end", "Error in lseek(SEEK_END) to end-of-file for file \"%s\", errno %d (%s)", fn.c_str(), errno, strerror(errno));
115 return false;
116 }
117
118 return true;
119}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ xtruncate()

static bool xtruncate ( const std::string &  fn,
int  fh,
DWORD  pos 
)
static

Definition at line 152 of file history.cxx.

153{
154 off_t off = lseek(fh, pos, SEEK_SET);
155
156 if (off < 0) {
157 cm_msg(MERROR, "xtruncate", "Error in lseek(%llu) for file \"%s\", errno %d (%s)", (unsigned long long)pos, fn.c_str(), errno, strerror(errno));
158 return false;
159 }
160
161 int status = ftruncate(fh, pos);
162
163 if (status != 0) {
164 cm_msg(MERROR, "xtruncate", "Error setting file size of \"%s\" to %llu, errno %d (%s)", fn.c_str(), (unsigned long long)pos, errno, strerror(errno));
165 return false;
166 }
167
168 return true;
169}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ xwrite()

static bool xwrite ( const std::string &  fn,
int  fh,
const void buf,
size_t  count 
)
static

dox

Definition at line 51 of file history.cxx.

52{
53 ssize_t wr = write(fh, buf, count);
54
55 if (wr < 0) {
56 cm_msg(MERROR, "xwrite", "Error writing %d bytes to file \"%s\" errno %d (%s)", (int)count, fn.c_str(), errno, strerror(errno));
57 return false;
58 }
59
60 if ((size_t)wr != count) {
61 cm_msg(MERROR, "xwrite", "Error writing %d bytes to file \"%s\", short write %d bytes", (int)count, fn.c_str(), (int)wr);
62 return false;
63 }
64
65 return true;
66}
#define write(n, a, f, d)
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ _history

std::vector<HISTORY*> _history
static

dox

Definition at line 45 of file history.cxx.

◆ _hs_path_name

std::string _hs_path_name
static

Definition at line 46 of file history.cxx.

◆ fDB

HNDLE MidasHistory::fDB

Definition at line 2220 of file history.cxx.

◆ fDebug

int MidasHistory::fDebug

Definition at line 2221 of file history.cxx.

◆ fEventsCache

std::vector<std::string> MidasHistory::fEventsCache

Definition at line 2223 of file history.cxx.

◆ fEvidCache

std::map<std::string, int > MidasHistory::fEvidCache

Definition at line 2225 of file history.cxx.

◆ fTagsCache

std::map<std::string, std::vector<TAG> > MidasHistory::fTagsCache

Definition at line 2224 of file history.cxx.