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, int > MidasHistory::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 = DOUBLE : -inf",\
"Maximum = DOUBLE : inf",\
"Label = STRING : [32] ",\
"Colour = STRING : [32] ",\
"Formula = STRING : [64] ",\
"Show fill = BOOL : y",\
"",\
NULL }

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 3454 of file history.cxx.

3454 {\
3455"[.]",\
3456"Variables = STRING : [64] :",\
3457"Timescale = STRING : [32] 10m",\
3458"Zero ylow = BOOL : n",\
3459"Show run markers = BOOL : y",\
3460"Buttons = STRING[7] :",\
3461"[32] 10m",\
3462"[32] 1h",\
3463"[32] 3h",\
3464"[32] 12h",\
3465"[32] 24h",\
3466"[32] 3d",\
3467"[32] 7d",\
3468"Log axis = BOOL : n",\
3469"Show values = BOOL : y",\
3470"Sort vars = BOOL : n",\
3471"Show old vars = BOOL : n",\
3472"Minimum = DOUBLE : -inf",\
3473"Maximum = DOUBLE : inf",\
3474"Label = STRING : [32] ",\
3475"Colour = STRING : [32] ",\
3476"Formula = STRING : [64] ",\
3477"Show fill = BOOL : y",\
3478"",\
3479NULL }

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 2334 of file history.cxx.

2335 {
2336 int status;
2337 char name[256];
2338 mstrlcpy(name, event_name, sizeof(name));
2339 char *s = strchr(name, '/');
2340 if (s)
2341 *s = ':';
2342
2343 // special event id for run transitions
2344 if (strcmp(name, "Run transitions")==0) {
2345 status = db_set_value(fDB, 0, "/History/Events/0", name, strlen(name)+1, 1, TID_STRING);
2346 assert(status == DB_SUCCESS);
2347 return 0;
2348 }
2349
2350 if (1) {
2351 std::string tmp = msprintf("/Equipment/%s/Common/Event ID", name);
2352
2353 WORD evid = 0;
2354 int size = sizeof(evid);
2355 status = db_get_value(fDB, 0, tmp.c_str(), &evid, &size, TID_WORD, FALSE);
2356 if (status == DB_SUCCESS) {
2357
2358 std::string he = msprintf("/History/Events/%d", evid);
2359
2360 std::string xname;
2361 status = db_get_value_string(fDB, 0, he.c_str(), 0, &xname);
2362 if (status == DB_SUCCESS && xname != event_name) {
2363 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);
2364 }
2365
2366 status = db_set_value(fDB, 0, he.c_str(), name, strlen(name)+1, 1, TID_STRING);
2367 assert(status == DB_SUCCESS);
2368
2369 //printf("AllocateEventId: event [%s] allocated common/event id %d\n", event_name, evid);
2370
2371 return evid;
2372 }
2373 }
2374
2375 for (int evid = 101; evid < 65000; evid++) {
2376 char tmp[256];
2377 HNDLE hKey;
2378
2379 sprintf(tmp,"/History/Events/%d", evid);
2380
2381 status = db_find_key(fDB, 0, tmp, &hKey);
2382 if (status != DB_SUCCESS) {
2383
2384 status = db_set_value(fDB, 0, tmp, name, strlen(name)+1, 1, TID_STRING);
2385 assert(status == DB_SUCCESS);
2386
2387 //printf("AllocateEventId: event [%s] allocated next sequential id %d\n", event_name, evid);
2388
2389 return evid;
2390 }
2391 }
2392
2393 cm_msg(MERROR, "AllocateEventId", "Cannot allocate history event id - all in use - please examine /History/Events");
2394 return -1;
2395 }
#define FALSE
Definition cfortran.h:309
char name[NAME_LENGTH]
Definition history.h:111
#define DB_SUCCESS
Definition midas.h:632
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:930
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
Definition odb.cxx:5289
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:13818
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:5132
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4256
HNDLE hKey
std::string msprintf(const char *format,...)
Definition midas.cxx:419
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 2399 of file history.cxx.

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

2287 {
2288 HNDLE hKeyRoot;
2289 int status;
2290 char name[256];
2291 mstrlcpy(name, event_name, sizeof(name));
2292 char *s = strchr(name, '/');
2293 if (s)
2294 *s = ':';
2295
2296 //printf("Looking for event id for \'%s\'\n", name);
2297
2298 status = db_find_key(fDB, 0, "/History/Events", &hKeyRoot);
2299 if (status == DB_SUCCESS) {
2300 for (int i = 0;; i++) {
2301 HNDLE hKey;
2302 KEY key;
2303
2304 status = db_enum_key(fDB, hKeyRoot, i, &hKey);
2305 if (status != DB_SUCCESS)
2306 break;
2307
2309 assert(status == DB_SUCCESS);
2310
2311 //printf("key \'%s\'\n", key.name);
2312
2313 int evid = (WORD) strtol(key.name, NULL, 0);
2314 if (evid == 0)
2315 continue;
2316
2317 char tmp[NAME_LENGTH+NAME_LENGTH+2];
2318 int size = sizeof(tmp);
2319 status = db_get_data(fDB, hKey, tmp, &size, TID_STRING);
2320 assert(status == DB_SUCCESS);
2321
2322 //printf("got %d \'%s\' looking for \'%s\'\n", evid, tmp, name);
2323
2324 if (equal_ustring(name, tmp))
2325 return evid;
2326 }
2327 }
2328
2329 return -1;
2330 }
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 2938 of file history.cxx.

2939 {
2940 int event_id = -1;
2941
2942 if (fDebug && event_name != NULL && tag_name != NULL)
2943 printf("xhs_event_id for event [%s], tag [%s]\n", event_name, tag_name);
2944
2945 *pevid = 0;
2946
2947 /* use "/History/Tags" if available */
2948 event_id = GetEventIdFromOdbTags(event_name, tag_name);
2949
2950 /* if no Tags, use "/History/Events" and hs_get_tags() to read definition from history files */
2951 if (event_id < 0)
2952 event_id = GetEventIdFromHS(t, event_name, tag_name);
2953
2954 /* if nothing works, use hs_get_event_id() */
2955 if (event_id <= 0) {
2956 DWORD evid = 0;
2957 int status = ::hs_get_event_id((DWORD)t, (char*)event_name, &evid);
2958 if (status != HS_SUCCESS)
2959 return status;
2960 event_id = evid;
2961 }
2962
2963 if (event_id < 0)
2964 return HS_UNDEFINED_VAR;
2965
2966 *pevid = event_id;
2967
2968 return HS_SUCCESS;
2969 }
#define HS_UNDEFINED_VAR
Definition midas.h:734
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:2794
int GetEventIdFromOdbTags(const char *evname, const char *tagname)
Definition history.cxx:2864
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 2794 of file history.cxx.

2795 {
2796 HNDLE hKeyRoot;
2797 int status;
2798
2799 status = db_find_key(fDB, 0, "/History/Events", &hKeyRoot);
2800 if (status != DB_SUCCESS) {
2801 return -1;
2802 }
2803
2804 for (int i = 0;; i++) {
2805 HNDLE hKey;
2806 KEY key;
2807 int evid;
2808 char buf[256];
2809 int size;
2810 char *s;
2811 int ntags = 0;
2812 TAG* tags = NULL;
2813 char event_name[NAME_LENGTH];
2814
2815 status = db_enum_key(fDB, hKeyRoot, i, &hKey);
2816 if (status != DB_SUCCESS)
2817 break;
2818
2820 assert(status == DB_SUCCESS);
2821
2822 if (!isdigit(key.name[0]))
2823 continue;
2824
2825 evid = atoi(key.name);
2826
2827 assert(key.item_size < (int)sizeof(buf));
2828
2829 size = sizeof(buf);
2830 status = db_get_data(fDB, hKey, buf, &size, TID_STRING);
2831 assert(status == DB_SUCCESS);
2832
2833 mstrlcpy(event_name, buf, sizeof(event_name));
2834
2835 s = strchr(buf,':');
2836 if (s)
2837 *s = 0;
2838
2839 //printf("Found event %d, event [%s] name [%s], looking for [%s][%s]\n", evid, event_name, buf, evname, tagname);
2840
2841 if (!equal_ustring((char *)evname, buf))
2842 continue;
2843
2844 status = ::hs_get_tags((DWORD)ltime, evid, event_name, &ntags, &tags);
2845
2846 for (int j=0; j<ntags; j++) {
2847 //printf("at %d [%s] looking for [%s]\n", j, tags[j].name, tagname);
2848
2849 if (equal_ustring((char *)tagname, tags[j].name)) {
2850 if (tags)
2851 free(tags);
2852 return evid;
2853 }
2854 }
2855
2856 if (tags)
2857 free(tags);
2858 tags = NULL;
2859 }
2860
2861 return -1;
2862 }
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:3141
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 2864 of file history.cxx.

2865 {
2866 HNDLE hKeyRoot;
2867 int status;
2868
2869 status = db_find_key(fDB, 0, "/History/Tags", &hKeyRoot);
2870 if (status != DB_SUCCESS) {
2871 return -1;
2872 }
2873
2874 for (int i = 0;; i++) {
2875 HNDLE hKey;
2876 KEY key;
2877 int evid;
2878 char buf[256];
2879 int size;
2880 char *s;
2881
2882 status = db_enum_key(fDB, hKeyRoot, i, &hKey);
2883 if (status != DB_SUCCESS)
2884 break;
2885
2887 assert(status == DB_SUCCESS);
2888
2889 if (key.type != TID_STRING)
2890 continue;
2891
2892 if (!isdigit(key.name[0]))
2893 continue;
2894
2895 evid = atoi(key.name);
2896
2897 assert(key.item_size < (int)sizeof(buf));
2898
2899 size = sizeof(buf);
2900 status = db_get_data_index(fDB, hKey, buf, &size, 0, TID_STRING);
2901 assert(status == DB_SUCCESS);
2902
2903 s = strchr(buf,'/');
2904 if (s)
2905 *s = 0;
2906
2907 //printf("Found event %d, name [%s], looking for [%s][%s]\n", evid, buf, evname, tagname);
2908
2909 if (!equal_ustring((char *)evname, buf))
2910 continue;
2911
2912 for (int j=1; j<key.num_values; j++) {
2913 size = sizeof(buf);
2914 status = db_get_data_index(fDB, hKey, buf, &size, j, TID_STRING);
2915 assert(status == DB_SUCCESS);
2916
2917 if (!isdigit(buf[0]))
2918 continue;
2919
2920 s = strchr(buf,' ');
2921 if (!s)
2922 continue;
2923
2924 s++;
2925
2926 //printf("at %d [%s] [%s] compare to [%s]\n", j, buf, s, tagname);
2927
2928 if (equal_ustring((char *)tagname, s)) {
2929 //printf("Found evid %d\n", evid);
2930 return evid;
2931 }
2932 }
2933 }
2934
2935 return -1;
2936 }
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
Definition odb.cxx:6768
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 2653 of file history.cxx.

2654 {
2655 HNDLE hKeyRoot;
2656 int status;
2657
2658 status = db_find_key(fDB, 0, "/History/Events", &hKeyRoot);
2659 if (status != DB_SUCCESS) {
2660 return HS_FILE_ERROR;
2661 }
2662
2663 /* loop over tags to display event names */
2664 for (int i = 0;; i++) {
2665 HNDLE hKeyEq;
2666 char *s;
2667 char evname[1024+NAME_LENGTH];
2668 int size;
2669
2670 status = db_enum_key(fDB, hKeyRoot, i, &hKeyEq);
2671 if (status != DB_SUCCESS)
2672 break;
2673
2674 size = sizeof(evname);
2675 status = db_get_data(fDB, hKeyEq, evname, &size, TID_STRING);
2676 assert(status == DB_SUCCESS);
2677
2678 s = strchr(evname,':');
2679 if (s)
2680 *s = '/';
2681
2682 /* skip duplicated event names */
2683
2684 int found = 0;
2685 for (unsigned i=0; i<events->size(); i++) {
2686 if (equal_ustring(evname, (*events)[i].c_str())) {
2687 found = 1;
2688 break;
2689 }
2690 }
2691
2692 if (found)
2693 continue;
2694
2695 events->push_back(evname);
2696
2697 //printf("event \'%s\'\n", evname);
2698 }
2699
2700 return HS_SUCCESS;
2701 }
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 2703 of file history.cxx.

2704 {
2705 HNDLE hKeyRoot;
2706 int status;
2707
2708 status = db_find_key(fDB, 0, "/History/Tags", &hKeyRoot);
2709 if (status != DB_SUCCESS) {
2710 return HS_FILE_ERROR;
2711 }
2712
2713 /* loop over tags to display event names */
2714 for (int i = 0;; i++) {
2715 HNDLE hKeyEq;
2716 KEY key;
2717 char *s;
2718 WORD event_id;
2719 char evname[1024+NAME_LENGTH];
2720 int size;
2721
2722 status = db_enum_key(fDB, hKeyRoot, i, &hKeyEq);
2723 if (status != DB_SUCCESS)
2724 break;
2725
2726 /* get event name */
2727 db_get_key(fDB, hKeyEq, &key);
2728
2729 //printf("key \'%s\'\n", key.name);
2730
2731 if (key.type != TID_STRING)
2732 continue;
2733
2734 /* parse event name in format: "event_id" or "event_id:var_name" */
2735 s = key.name;
2736
2737 event_id = (WORD)strtoul(s,&s,0);
2738 if (event_id == 0)
2739 continue;
2740 if (s[0] != 0)
2741 continue;
2742
2743 size = sizeof(evname);
2744 status = db_get_data_index(fDB, hKeyEq, evname, &size, 0, TID_STRING);
2745 assert(status == DB_SUCCESS);
2746
2747 /* skip duplicated event names */
2748
2749 int found = 0;
2750 for (unsigned i=0; i<events->size(); i++) {
2751 if (equal_ustring(evname, (*events)[i].c_str())) {
2752 found = 1;
2753 break;
2754 }
2755 }
2756
2757 if (found)
2758 continue;
2759
2760 events->push_back(evname);
2761
2762 //printf("event %d \'%s\'\n", event_id, evname);
2763 }
2764
2765 return HS_SUCCESS;
2766 }
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 2971 of file history.cxx.

2972 {
2973 time_t now = time(NULL);
2974 int evid;
2975 int status = GetEventId(now, event_name, NULL, &evid);
2976 if (status != HS_SUCCESS)
2977 return status;
2978
2979 if (fDebug)
2980 printf("hs_get_tags: get tags for event [%s] %d\n", event_name, evid);
2981
2982 int ntags;
2983 TAG* tags;
2984 status = ::hs_get_tags((DWORD)now, evid, (char*)event_name, &ntags, &tags);
2985
2986 if (status != HS_SUCCESS)
2987 return status;
2988
2989 for (int i=0; i<ntags; i++)
2990 ptags->push_back(tags[i]);
2991
2992 if (tags)
2993 free(tags);
2994
2995 if (fDebug)
2996 printf("hs_get_tags: get tags for event [%s] %d, found %d tags\n", event_name, evid, ntags);
2997
2998 return HS_SUCCESS;
2999 }
int GetEventId(time_t t, const char *event_name, const char *tag_name, int *pevid)
Definition history.cxx:2938
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 3001 of file history.cxx.

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

2274 {
2275 if (fDebug)
2276 printf("hs_clear_cache!\n");
2277
2278 fEventsCache.clear();
2279 fTagsCache.clear();
2280 fEvidCache.clear();
2281 return HS_SUCCESS;
2282 }
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 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 db_delete(fDB, 0, "/History/ListSource");
2247
2248 ::hs_set_path(path);
2249
2250 if (fDebug)
2251 printf("hs_connect: path [%s]\n", path);
2252
2253 return HS_SUCCESS;
2254 }
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3026
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;
930 DEF_RECORD def_rec;
931
932 /* search latest history file */
933 status = hs_search_file(&ltime, -1);
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);
949 DWORD pos_fhd = xcurpos(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:1551
int INT
Definition midas.h:129
#define M_FREE(x)
Definition midas.h:1553
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;
1082 DEF_RECORD def_rec;
1083 HIST_RECORD rec;
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}
DWORD event_id
Definition midas.h:1368
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 2622 of file history.cxx.

2623 {
2624 int event_id = FindEventId(event_name);
2625 if (event_id < 0)
2626 event_id = AllocateEventId(event_name);
2627 if (event_id < 0)
2628 return HS_FILE_ERROR;
2629 fEvidCache[event_name] = event_id;
2630 CreateOdbTags(event_id, event_name, ntags, tags);
2631 return ::hs_define_event(event_id, (char*)event_name, (TAG*)tags, ntags*sizeof(TAG));
2632 }
int FindEventId(const char *event_name)
Definition history.cxx:2286
int AllocateEventId(const char *event_name)
Definition history.cxx:2334
int CreateOdbTags(int event_id, const char *event_name, int ntags, const TAG tags[])
Definition history.cxx:2399
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 {
460 HIST_RECORD rec, prev_rec;
461 DEF_RECORD def_rec;
462 time_t ltime;
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 */
471 cm_get_experiment_semaphore(NULL, NULL, &semaphore, NULL);
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);
515 DWORD fhd_pos = xcurpos(fnd, fhd);
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;
536 localtime_r(&ltime, &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 */
558 fhd_pos = xcurpos(fnd, fhd);
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:3048
#define SS_SUCCESS
Definition midas.h:664
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:3437
INT ss_semaphore_release(HNDLE semaphore_handle)
Definition system.cxx:2853
INT ss_semaphore_wait_for(HNDLE semaphore_handle, DWORD timeout_millisec)
Definition system.cxx:2711
INT index
Definition mana.cxx:271
#define RT_DEF
Definition midas.h:1357
#define name(x)
Definition midas_macro.h:24
MUTEX_T * tm
Definition odbedit.cxx:39
char str[256]
Definition odbhist.cxx:33
DWORD record_type
Definition midas.h:1360
DWORD time
Definition midas.h:1362
DWORD data_size
Definition midas.h:1364
DWORD event_id
Definition midas.h:1361
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 3482 of file history.cxx.

3483{
3484 HNDLE hDB, hKey, hKeyVar;
3485 HISTORY_PANEL(history_panel_str);
3486 char str[256];
3487
3488 const char *color[] = {
3489 "#00AAFF", "#FF9000", "#FF00A0", "#00C030",
3490 "#A0C0D0", "#D0A060", "#C04010", "#807060",
3491 "#F0C000", "#2090A0", "#D040D0", "#90B000",
3492 "#B0B040", "#B0B0FF", "#FFA0A0", "#A0FFA0",
3493 "#808080"};
3494
3496
3497 snprintf(str, sizeof(str), "/History/Display/%s/%s", group, panel);
3498
3499 db_create_record(hDB, 0, str, strcomb1(history_panel_str).c_str());
3500 db_find_key(hDB, 0, str, &hKey);
3501 if (!hKey)
3502 return DB_NO_MEMORY;
3503
3504 int i=0;
3505 for(auto const& v: var) {
3506 db_find_key(hDB, hKey, "Variables", &hKeyVar);
3507 db_set_data_index(hDB, hKeyVar, v.c_str(), 64, i, TID_STRING);
3508
3509 str[0] = 0;
3510 db_set_value_index(hDB, hKey, "Formula", str, 64, i, TID_STRING, false);
3511 db_set_value_index(hDB, hKey, "Label", str, 32, i, TID_STRING, false);
3512 db_set_value_index(hDB, hKey, "Colour", color[i < 16 ? i : 16], 32, i, TID_STRING, false);
3513
3514 i++;
3515 }
3516
3517 return HS_SUCCESS;
3518}
#define DB_NO_MEMORY
Definition midas.h:634
#define HISTORY_PANEL(_name)
Definition history.cxx:3454
std::string strcomb1(const char **list)
Definition odb.cxx:668
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:5239
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
Definition odb.cxx:12682
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 3520 of file history.cxx.

3523{
3524 HNDLE hDB, hKey, hKeyVar;
3525 HISTORY_PANEL(history_panel_str);
3526 char str[256];
3527
3528 const char *default_color[] = {
3529 "#00AAFF", "#FF9000", "#FF00A0", "#00C030",
3530 "#A0C0D0", "#D0A060", "#C04010", "#807060",
3531 "#F0C000", "#2090A0", "#D040D0", "#90B000",
3532 "#B0B040", "#B0B0FF", "#FFA0A0", "#A0FFA0",
3533 "#808080"};
3534
3536
3537 snprintf(str, sizeof(str), "/History/Display/%s/%s", group, panel);
3538
3539 db_create_record(hDB, 0, str, strcomb1(history_panel_str).c_str());
3540 db_find_key(hDB, 0, str, &hKey);
3541 if (!hKey)
3542 return DB_NO_MEMORY;
3543
3544 int i=0;
3545 for(auto const& v: var) {
3546 db_find_key(hDB, hKey, "Variables", &hKeyVar);
3547 db_set_data_index(hDB, hKeyVar, v.c_str(), 64, i, TID_STRING);
3548
3549 if (i < (int)formula.size())
3550 mstrlcpy(str, formula[i].c_str(), sizeof(str)-1);
3551 else
3552 str[0] = 0;
3553 db_set_value_index(hDB, hKey, "Formula", str, 64, i, TID_STRING, false);
3554
3555 if (i < (int)label.size())
3556 mstrlcpy(str, label[i].c_str(), sizeof(str)-1);
3557 else
3558 str[0] = 0;
3559 db_set_value_index(hDB, hKey, "Label", str, 32, i, TID_STRING, false);
3560
3561 if (i < (int)color.size())
3562 mstrlcpy(str, color[i].c_str(), sizeof(str)-1);
3563 else
3564 mstrlcpy(str, default_color[i < 16 ? i : 16], sizeof(str)-1);
3565 db_set_value_index(hDB, hKey, "Colour", str, 32, i, TID_STRING, false);
3566
3567 i++;
3568 }
3569
3570 return HS_SUCCESS;
3571}
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 2258 of file history.cxx.

2259 {
2261 return HS_SUCCESS;
2262 }
int hs_clear_cache()
clear internal cache, returns HS_SUCCESS
Definition history.cxx:2273
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{
1956 DWORD prev_time, last_irec_time;
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;
1961 INDEX_RECORD irec;
1962 HIST_RECORD rec, drec;
1963 INT old_def_offset, offset;
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);
2021 hs_gen_index(last_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) {
2033 char buf_name_length[NAME_LENGTH];
2034 xseek(fn, fh, rec.def_offset);
2035 xread(fn, fh, (char *) &drec, sizeof(drec));
2036 xread(fn, fh, buf_name_length, NAME_LENGTH);
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];
2077 ctime_r(&ltime, ctimebuf);
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 */
2121 ltime = (time_t) last_irec_time;
2122 struct tm tms;
2123 localtime_r(&ltime, &tms);
2124 tms.tm_hour = tms.tm_min = tms.tm_sec = 0;
2125 last_irec_time = (DWORD) ss_mktime(&tms);
2126
2127 last_irec_time += 3600 * 24;
2128 if (last_irec_time > end_time)
2129 break;
2130
2131 /* search next file */
2132 status = hs_search_file((DWORD *) & last_irec_time, 1);
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);
2138 hs_open_file(last_irec_time, "idf", O_RDONLY, &fnd, &fhd);
2139 hs_open_file(last_irec_time, "idx", O_RDONLY, &fni, &fhi);
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:730
static bool xseek_cur(const std::string &fn, int fh, int offset)
Definition history.cxx:121
void ss_tzset()
Definition system.cxx:3427
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
Definition odb.cxx:10716
INT rpc_tid_size(INT id)
Definition midas.cxx:11782
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;
849 DEF_RECORD def_rec;
850
851 /* search latest history file */
852 status = hs_search_file(&ltime, -1);
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);
899 *name_size = n * NAME_LENGTH;
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;
1156 DEF_RECORD def_rec;
1157 HIST_RECORD rec;
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 2645 of file history.cxx.

2646 {
2647 //printf("hs_flush_buffers!\n");
2648 return HS_SUCCESS;
2649 }

◆ 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;
260 HIST_RECORD rec;
261 INDEX_RECORD irec;
262 DEF_RECORD def_rec;
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:1356
DWORD def_offset
Definition midas.h:1370
char event_name[NAME_LENGTH]
Definition midas.h:1369
DWORD time
Definition midas.h:1375
DWORD offset
Definition midas.h:1376
DWORD event_id
Definition midas.h:1374
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;
1009 DEF_RECORD def_rec;
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:733
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 2768 of file history.cxx.

2769 {
2770 assert(pevents);
2771 pevents->clear();
2772
2773 if (fEventsCache.size() == 0) {
2774 int status;
2775
2776 if (fDebug)
2777 printf("hs_get_events: reading events list!\n");
2778
2780
2781 if (status != HS_SUCCESS)
2783
2784 if (status != HS_SUCCESS)
2785 return status;
2786 }
2787
2788 for (unsigned i=0; i<fEventsCache.size(); i++)
2789 pevents->push_back(fEventsCache[i]);
2790
2791 return HS_SUCCESS;
2792 }
int GetEventsFromOdbTags(std::vector< std::string > *events)
Definition history.cxx:2703
int GetEventsFromOdbEvents(std::vector< std::string > *events)
Definition history.cxx:2653
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 3168 of file history.cxx.

3169 {
3170 for (int i=0; i<num_var; i++)
3171 last_written[i] = 0;
3172 return HS_FILE_ERROR;
3173 }

◆ 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 3141 of file history.cxx.

3142 {
3143 std::vector<TAG>& ttt = fTagsCache[event_name];
3144
3145 if (ttt.size() == 0) {
3146 int status = HS_FILE_ERROR;
3147
3148 if (fDebug)
3149 printf("hs_get_tags: reading tags for event [%s]\n", event_name);
3150
3151 status = GetTagsFromOdb(event_name, &ttt);
3152
3153 if (status != HS_SUCCESS)
3154 status = GetTagsFromHS(event_name, &ttt);
3155
3156 if (status != HS_SUCCESS)
3157 return status;
3158 }
3159
3160 for (unsigned i=0; i<ttt.size(); i++)
3161 ptags->push_back(ttt[i]);
3162
3163 return HS_SUCCESS;
3164 }
int GetTagsFromOdb(const char *event_name, std::vector< TAG > *ptags)
Definition history.cxx:3001
int GetTagsFromHS(const char *event_name, std::vector< TAG > *ptags)
Definition history.cxx:2971
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;
1355 DEF_RECORD def_rec;
1356 HIST_RECORD rec;
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:12786
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;
1260 DEF_RECORD def_rec;
1261 HIST_RECORD rec;
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;
209 time_t ttime;
210
211 /* generate new file name YYMMDD.xxx */
212 ss_tzset(); // required by localtime_r()
213 ttime = (time_t) ltime;
214 localtime_r(&ttime, &tms);
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)
226 *pfile_name = file_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:226
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{
1488 DWORD prev_time, last_irec_time;
1489 int fh, fhd, fhi, cp = 0;
1490 std::string fn, fnd, fni;
1491 int delta;
1492 int status;
1493 int cache_size;
1494 INDEX_RECORD irec, *pirec;
1495 HIST_RECORD rec, drec;
1496 INT old_def_offset;
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);
1560 cache_size = xcurpos(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);
1665 hs_gen_index(last_irec_time);
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);
1683 hs_gen_index(last_irec_time);
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)
1755 *data_type = var_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
1766 var_size = rpc_tid_size(tag[tag_index].type);
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 */
1865 ltime = (time_t) last_irec_time;
1866 struct tm tms;
1867 localtime_r(&ltime, &tms);
1868 tms.tm_hour = tms.tm_min = tms.tm_sec = 0;
1869 last_irec_time = (DWORD) ss_mktime(&tms);
1870
1871 last_irec_time += 3600 * 24;
1872
1873 if (last_irec_time > end_time)
1874 break;
1875
1876 /* search next file */
1877 status = hs_search_file(&last_irec_time, 1);
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);
1883 hs_open_file(last_irec_time, "idf", O_RDONLY, &fnd, &fhd);
1884 hs_open_file(last_irec_time, "idx", O_RDONLY, &fni, &fhi);
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);
1892 cache_size = xcurpos(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:731
#define HS_WRONG_INDEX
Definition midas.h:732
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 3178 of file history.cxx.

3184 {
3185 DWORD* tbuffer = NULL;
3186 char* ybuffer = NULL;
3187 DWORD bsize, tsize;
3188 int hbuffer_size = 0;
3189
3190 if (hbuffer_size == 0) {
3191 hbuffer_size = 1000 * sizeof(DWORD);
3192 tbuffer = (DWORD*)malloc(hbuffer_size);
3193 ybuffer = (char*)malloc(hbuffer_size);
3194 }
3195
3196 for (int i=0; i<num_var; i++) {
3197 DWORD tid = 0;
3198 int event_id = 0;
3199
3200 if (event_name[i]==NULL) {
3201 read_status[i] = HS_UNDEFINED_EVENT;
3202 num_entries[i] = 0;
3203 continue;
3204 }
3205
3206 int status = GetEventId(end_time, event_name[i], tag_name[i], &event_id);
3207
3208 if (status != HS_SUCCESS) {
3209 read_status[i] = status;
3210 continue;
3211 }
3212
3213 DWORD n_point = 0;
3214
3215 do {
3216 bsize = tsize = hbuffer_size;
3217 memset(ybuffer, 0, bsize);
3218 status = ::hs_read(event_id, (DWORD)start_time, (DWORD)end_time, (DWORD)interval,
3219 tag_name[i], var_index[i],
3220 tbuffer, &tsize,
3221 ybuffer, &bsize,
3222 &tid, &n_point,
3223 NULL);
3224
3225 if (fDebug)
3226 printf("hs_read %d \'%s\' [%d] returned %d, %d entries\n", event_id, tag_name[i], var_index[i], status, n_point);
3227
3228 if (status == HS_TRUNCATED) {
3229 hbuffer_size *= 2;
3230 tbuffer = (DWORD*)realloc(tbuffer, hbuffer_size);
3231 assert(tbuffer);
3232 ybuffer = (char*)realloc(ybuffer, hbuffer_size);
3233 assert(ybuffer);
3234 }
3235
3236 } while (status == HS_TRUNCATED);
3237
3238 read_status[i] = status;
3239
3240 time_t* x = (time_t*)malloc(n_point*sizeof(time_t));
3241 assert(x);
3242 double* y = (double*)malloc(n_point*sizeof(double));
3243 assert(y);
3244
3245 time_buffer[i] = x;
3246 data_buffer[i] = y;
3247
3248 int n_vp = 0;
3249
3250 for (unsigned j = 0; j < n_point; j++) {
3251 x[n_vp] = tbuffer[j];
3252
3253 /* convert data to float */
3254 switch (tid) {
3255 default:
3256 y[n_vp] = 0;
3257 break;
3258 case TID_BYTE:
3259 y[n_vp] = *(((BYTE *) ybuffer) + j);
3260 break;
3261 case TID_SBYTE:
3262 y[n_vp] = *(((char *) ybuffer) + j);
3263 break;
3264 case TID_CHAR:
3265 y[n_vp] = *(((char *) ybuffer) + j);
3266 break;
3267 case TID_WORD:
3268 y[n_vp] = *(((WORD *) ybuffer) + j);
3269 break;
3270 case TID_SHORT:
3271 y[n_vp] = *(((short *) ybuffer) + j);
3272 break;
3273 case TID_DWORD:
3274 y[n_vp] = *(((DWORD *) ybuffer) + j);
3275 break;
3276 case TID_INT:
3277 y[n_vp] = *(((INT *) ybuffer) + j);
3278 break;
3279 case TID_BOOL:
3280 y[n_vp] = *(((BOOL *) ybuffer) + j);
3281 break;
3282 case TID_FLOAT:
3283 y[n_vp] = *(((float *) ybuffer) + j);
3284 break;
3285 case TID_DOUBLE:
3286 y[n_vp] = *(((double *) ybuffer) + j);
3287 break;
3288 }
3289
3290 n_vp++;
3291 }
3292
3293 num_entries[i] = n_vp;
3294 }
3295
3296 if (ybuffer)
3297 free(ybuffer);
3298 if (tbuffer)
3299 free(tbuffer);
3300
3301 return HS_SUCCESS;
3302 }
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:3178
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 3373 of file history.cxx.

3381 {
3382 int status;
3383
3384 MidasHistoryBinnedBuffer** buffer = new MidasHistoryBinnedBuffer*[num_var];
3386
3387 for (int i=0; i<num_var; i++) {
3388 buffer[i] = new MidasHistoryBinnedBuffer(start_time, end_time, num_bins);
3389 xbuffer[i] = buffer[i];
3390
3391 if (count_bins)
3392 buffer[i]->fCount = count_bins[i];
3393 if (mean_bins)
3394 buffer[i]->fMean = mean_bins[i];
3395 if (rms_bins)
3396 buffer[i]->fRms = rms_bins[i];
3397 if (min_bins)
3398 buffer[i]->fMin = min_bins[i];
3399 if (max_bins)
3400 buffer[i]->fMax = max_bins[i];
3401 if (bins_first_time)
3402 buffer[i]->fBinsFirstTime = bins_first_time[i];
3403 if (bins_first_value)
3404 buffer[i]->fBinsFirstValue = bins_first_value[i];
3405 if (bins_last_time)
3406 buffer[i]->fBinsLastTime = bins_last_time[i];
3407 if (bins_last_value)
3408 buffer[i]->fBinsLastValue = bins_last_value[i];
3409 if (last_time)
3410 buffer[i]->fLastTimePtr = &last_time[i];
3411 if (last_value)
3412 buffer[i]->fLastValuePtr = &last_value[i];
3413
3414 buffer[i]->Start();
3415 }
3416
3417 status = hs_read_buffer(start_time, end_time,
3418 num_var, event_name, tag_name, var_index,
3419 xbuffer,
3420 read_status);
3421
3422 for (int i=0; i<num_var; i++) {
3423 buffer[i]->Finish();
3424 if (num_entries)
3425 num_entries[i] = buffer[i]->fNumEntries;
3426 //if (0) {
3427 // for (int j=0; j<num_bins; j++) {
3428 // 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]);
3429 // }
3430 //}
3431 delete buffer[i];
3432 }
3433
3434 delete[] buffer;
3435 delete[] xbuffer;
3436
3437 return status;
3438 }
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:3336
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 3336 of file history.cxx.

3340 {
3341 for (int i=0; i<num_var; i++) {
3342 int event_id = 0;
3343
3344 if (event_name[i]==NULL) {
3345 read_status[i] = HS_UNDEFINED_EVENT;
3346 continue;
3347 }
3348
3349 int status = GetEventId(end_time, event_name[i], tag_name[i], &event_id);
3350
3351 if (status != HS_SUCCESS) {
3352 read_status[i] = status;
3353 continue;
3354 }
3355
3356 status = ::hs_read(event_id, (DWORD)start_time, (DWORD)end_time, 0,
3357 tag_name[i], var_index[i],
3358 NULL, NULL,
3359 NULL, NULL,
3360 NULL, NULL,
3361 buffer[i]);
3362
3363 if (fDebug) {
3364 printf("hs_read %d \'%s\' [%d] returned %d\n", event_id, tag_name[i], var_index[i], status);
3365 }
3366
3367 read_status[i] = status;
3368 }
3369
3370 return HS_SUCCESS;
3371 }
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)
420 hs_gen_index(*ltime);
421
422 return HS_SUCCESS;
423}
DWORD ss_time()
Definition system.cxx:3534
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 2266 of file history.cxx.

2267 {
2268 return debug;
2269 }
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 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 2636 of file history.cxx.

2637 {
2638 int event_id = fEvidCache[event_name];
2639 //printf("write event [%s] evid %d\n", event_name, event_id);
2640 return ::hs_write_event(event_id, (void*)data, data_size);
2641 }
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{
680 HIST_RECORD rec, drec;
681 DEF_RECORD def_rec;
682 INDEX_RECORD irec;
683 int fh, fhi, fhd;
684 DWORD last_pos_data, last_pos_index;
685 std::string fn, fni, fnd;
686 INT semaphore;
687 int status;
688 struct tm tmb, tmr;
689 time_t ltime;
690
691 /* request semaphore */
692 cm_get_experiment_semaphore(NULL, NULL, &semaphore, NULL);
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
DWORD def_offset
Definition midas.h:1363
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MakeMidasHistory()

MidasHistoryInterface * MakeMidasHistory ( )

Definition at line 3573 of file history.cxx.

3574{
3575#if 0
3576 // midas history is a singleton class
3577 static MidasHistory* gh = NULL;
3578 if (!gh)
3579 gh = new MidasHistory;
3580 return gh;
3581#endif
3582 return new MidasHistory();
3583}
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{
123 off_t off = lseek(fh, offset, SEEK_CUR);
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.