MIDAS
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 More...
 
int MidasHistory::hs_disconnect ()
 disconnect from history, returns HS_SUCCESS More...
 
int MidasHistory::hs_set_debug (int debug)
 set debug level, returns previous debug level More...
 
int MidasHistory::hs_clear_cache ()
 clear internal cache, returns HS_SUCCESS More...
 
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 More...
 
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 More...
 
int MidasHistory::hs_flush_buffers ()
 flush buffered data to storage where it is visible to mhttpd More...
 
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 More...
 
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 More...
 
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 More...
 
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 More...
 
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 More...
 
INT hs_define_panel (const char *group, const char *panel, const std::vector< std::string > var)
 
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 = FLOAT : -inf",\
"Maximum = FLOAT : 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 3474 of file history.cxx.

Function Documentation

◆ MidasHistory()

MidasHistory::MidasHistory ( )
inline

Definition at line 2238 of file history.cxx.

2239  {
2240  fDebug = 0;
2241  }

◆ ~MidasHistory()

MidasHistory::~MidasHistory ( )
inline

Definition at line 2243 of file history.cxx.

2244  {
2245  // empty
2246  }

◆ AllocateEventId()

int MidasHistory::AllocateEventId ( const char *  event_name)
inline

Definition at line 2349 of file history.cxx.

2350  {
2351  int status;
2352  char name[256];
2353  STRLCPY(name, event_name);
2354  char *s = strchr(name, '/');
2355  if (s)
2356  *s = ':';
2357 
2358  // special event id for run transitions
2359  if (strcmp(name, "Run transitions")==0) {
2360  status = db_set_value(fDB, 0, "/History/Events/0", name, strlen(name)+1, 1, TID_STRING);
2361  assert(status == DB_SUCCESS);
2362  return 0;
2363  }
2364 
2365  if (1) {
2366  std::string tmp = msprintf("/Equipment/%s/Common/Event ID", name);
2367 
2368  WORD evid = 0;
2369  int size = sizeof(evid);
2370  status = db_get_value(fDB, 0, tmp.c_str(), &evid, &size, TID_WORD, FALSE);
2371  if (status == DB_SUCCESS) {
2372 
2373  std::string he = msprintf("/History/Events/%d", evid);
2374 
2375  std::string xname;
2376  status = db_get_value_string(fDB, 0, he.c_str(), 0, &xname);
2377  if (status == DB_SUCCESS && xname != event_name) {
2378  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);
2379  }
2380 
2381  status = db_set_value(fDB, 0, he.c_str(), name, strlen(name)+1, 1, TID_STRING);
2382  assert(status == DB_SUCCESS);
2383 
2384  //printf("AllocateEventId: event [%s] allocated common/event id %d\n", event_name, evid);
2385 
2386  return evid;
2387  }
2388  }
2389 
2390  for (int evid = 101; evid < 65000; evid++) {
2391  char tmp[256];
2392  HNDLE hKey;
2393 
2394  sprintf(tmp,"/History/Events/%d", evid);
2395 
2396  status = db_find_key(fDB, 0, tmp, &hKey);
2397  if (status != DB_SUCCESS) {
2398 
2399  status = db_set_value(fDB, 0, tmp, name, strlen(name)+1, 1, TID_STRING);
2400  assert(status == DB_SUCCESS);
2401 
2402  //printf("AllocateEventId: event [%s] allocated next sequential id %d\n", event_name, evid);
2403 
2404  return evid;
2405  }
2406  }
2407 
2408  cm_msg(MERROR, "AllocateEventId", "Cannot allocate history event id - all in use - please examine /History/Events");
2409  return -1;
2410  }
#define FALSE
Definition: cfortran.h:309
char name[NAME_LENGTH]
Definition: history.h:108
#define DB_SUCCESS
Definition: midas.h:637
unsigned short int WORD
Definition: mcstd.h:49
#define TID_WORD
Definition: midas.h:339
#define TID_STRING
Definition: midas.h:353
#define MERROR
Definition: midas.h:565
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition: midas.cxx:917
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
Definition: odb.cxx:5405
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:13937
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:5251
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition: odb.cxx:4069
#define STRLCPY(dst, src)
Definition: history.cxx:37
HNDLE hKey
Definition: lazylogger.cxx:207
std::string msprintf(const char *format,...)
Definition: midas.cxx:412
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 2414 of file history.cxx.

2415  {
2416  int disableTags;
2417  int oldTags;
2418  int size, status;
2419 
2420  /* create history tags for mhttpd */
2421 
2422  disableTags = 0;
2423  size = sizeof(disableTags);
2424  status = db_get_value(fDB, 0, "/History/DisableTags", &disableTags, &size, TID_BOOL, TRUE);
2425 
2426  oldTags = 0;
2427  size = sizeof(oldTags);
2428  status = db_get_value(fDB, 0, "/History/CreateOldTags", &oldTags, &size, TID_BOOL, FALSE);
2429 
2430  if (disableTags) {
2431  HNDLE hKey;
2432 
2433  status = db_find_key(fDB, 0, "/History/Tags", &hKey);
2434  if (status == DB_SUCCESS) {
2436  if (status != DB_SUCCESS)
2437  cm_msg(MERROR, "add_event", "Cannot delete /History/Tags, db_delete_key() status %d", status);
2438  }
2439 
2440  } else if (oldTags) {
2441 
2442  char buf[256];
2443 
2444  sprintf(buf, "/History/Tags/%d", event_id);
2445 
2446  //printf("Set tag \'%s\' = \'%s\'\n", buf, event_name);
2447 
2448  status = db_set_value(fDB, 0, buf, (void*)event_name, strlen(event_name)+1, 1, TID_STRING);
2449  assert(status == DB_SUCCESS);
2450 
2451  for (int i=0; i<ntags; i++) {
2452  WORD v = (WORD) tags[i].n_data;
2453  sprintf(buf, "/History/Tags/Tags %d/%s", event_id, tags[i].name);
2454 
2455  //printf("Set tag \'%s\' = %d\n", buf, v);
2456 
2457  status = db_set_value(fDB, 0, buf, &v, sizeof(v), 1, TID_WORD);
2458  assert(status == DB_SUCCESS);
2459 
2460  if (strlen(tags[i].name) == NAME_LENGTH-1)
2461  cm_msg(MERROR, "add_event",
2462  "Tag name \'%s\' in event %d (%s) may have been truncated to %d characters",
2463  tags[i].name, event_id, event_name, NAME_LENGTH-1);
2464  }
2465 
2466  } else {
2467 
2468  const int kLength = 32 + NAME_LENGTH + NAME_LENGTH;
2469  char buf[kLength];
2470  HNDLE hKey;
2471 
2472  sprintf(buf, "/History/Tags/%d", event_id);
2473  status = db_find_key(fDB, 0, buf, &hKey);
2474 
2475  if (status == DB_SUCCESS) {
2476  // add new tags
2477  KEY key;
2478 
2479  status = db_get_key(fDB, hKey, &key);
2480  assert(status == DB_SUCCESS);
2481 
2482  assert(key.type == TID_STRING);
2483 
2484  if (key.item_size < kLength && key.num_values == 1) {
2485  // old style tags are present. Convert them to new style!
2486 
2487  HNDLE hTags;
2488 
2489  cm_msg(MINFO, "add_event", "Converting old event %d (%s) tags to new style", event_id, event_name);
2490 
2491  strlcpy(buf, event_name, kLength);
2492 
2493  status = db_set_data(fDB, hKey, buf, kLength, 1, TID_STRING);
2494  assert(status == DB_SUCCESS);
2495 
2496  sprintf(buf, "/History/Tags/Tags %d", event_id);
2497 
2498  status = db_find_key(fDB, 0, buf, &hTags);
2499 
2500  if (status == DB_SUCCESS) {
2501  for (int i=0; ; i++) {
2502  HNDLE h;
2503  int size;
2504  KEY key;
2505  WORD w;
2506 
2507  status = db_enum_key(fDB, hTags, i, &h);
2508  if (status == DB_NO_MORE_SUBKEYS)
2509  break;
2510  assert(status == DB_SUCCESS);
2511 
2512  status = db_get_key(fDB, h, &key);
2513 
2514  size = sizeof(w);
2515  status = db_get_data(fDB, h, &w, &size, TID_WORD);
2516  assert(status == DB_SUCCESS);
2517 
2518  sprintf(buf, "%d[%d] %s", 0, w, key.name);
2519 
2520  status = db_set_data_index(fDB, hKey, buf, kLength, 1+i, TID_STRING);
2521  assert(status == DB_SUCCESS);
2522  }
2523 
2524  status = db_delete_key(fDB, hTags, TRUE);
2525  assert(status == DB_SUCCESS);
2526  }
2527 
2528  // format conversion has changed the key, get it again
2529  status = db_get_key(fDB, hKey, &key);
2530  assert(status == DB_SUCCESS);
2531  }
2532 
2533  if (1) {
2534  // add new tags
2535 
2536  int size = key.item_size * key.num_values;
2537  int num = key.num_values;
2538 
2539  char* s = (char*)malloc(size);
2540  assert(s != NULL);
2541 
2542  TAG* t = (TAG*)malloc(sizeof(TAG)*(key.num_values + ntags));
2543  assert(t != NULL);
2544 
2545  status = db_get_data(fDB, hKey, s, &size, TID_STRING);
2546  assert(status == DB_SUCCESS);
2547 
2548  for (int i=1; i<key.num_values; i++) {
2549  char* ss = s + i*key.item_size;
2550 
2551  t[i].type = 0;
2552  t[i].n_data = 0;
2553  t[i].name[0] = 0;
2554 
2555  if (isdigit(ss[0])) {
2556  //sscanf(ss, "%d[%d] %s", &t[i].type, &t[i].n_data, t[i].name);
2557 
2558  t[i].type = strtoul(ss, &ss, 0);
2559  assert(*ss == '[');
2560  ss++;
2561  t[i].n_data = strtoul(ss, &ss, 0);
2562  assert(*ss == ']');
2563  ss++;
2564  assert(*ss == ' ');
2565  ss++;
2566  strlcpy(t[i].name, ss, sizeof(t[i].name));
2567 
2568  //printf("type %d, n_data %d, name [%s]\n", t[i].type, t[i].n_data, t[i].name);
2569  }
2570  }
2571 
2572  for (int i=0; i<ntags; i++) {
2573  int k = 0;
2574 
2575  for (int j=1; j<key.num_values; j++) {
2576  if (equal_ustring((char*)tags[i].name, (char*)t[j].name)) {
2577  if ((tags[i].type!=t[j].type) || (tags[i].n_data!=t[j].n_data)) {
2578  cm_msg(MINFO, "add_event", "Event %d (%s) tag \"%s\" type and size changed from %d[%d] to %d[%d]",
2579  event_id, event_name,
2580  tags[i].name,
2581  t[j].type, t[j].n_data,
2582  tags[i].type, tags[i].n_data);
2583  k = j;
2584  break;
2585  }
2586 
2587  k = -1;
2588  break;
2589  }
2590  }
2591 
2592  // if tag not present, k==0, so append it to the array
2593 
2594  if (k==0)
2595  k = num;
2596 
2597  if (k > 0) {
2598  sprintf(buf, "%d[%d] %s", tags[i].type, tags[i].n_data, tags[i].name);
2599 
2600  status = db_set_data_index(fDB, hKey, buf, kLength, k, TID_STRING);
2601  assert(status == DB_SUCCESS);
2602 
2603  if (k >= num)
2604  num = k+1;
2605  }
2606  }
2607 
2608  free(s);
2609  free(t);
2610  }
2611 
2612  } else if (status == DB_NO_KEY) {
2613  // create new array of tags
2614  status = db_create_key(fDB, 0, buf, TID_STRING);
2615  assert(status == DB_SUCCESS);
2616 
2617  status = db_find_key(fDB, 0, buf, &hKey);
2618  assert(status == DB_SUCCESS);
2619 
2620  strlcpy(buf, event_name, kLength);
2621 
2622  status = db_set_data(fDB, hKey, buf, kLength, 1, TID_STRING);
2623  assert(status == DB_SUCCESS);
2624 
2625  for (int i=0; i<ntags; i++) {
2626  sprintf(buf, "%d[%d] %s", tags[i].type, tags[i].n_data, tags[i].name);
2627 
2628  status = db_set_data_index(fDB, hKey, buf, kLength, 1+i, TID_STRING);
2629  assert(status == DB_SUCCESS);
2630  }
2631  } else {
2632  cm_msg(MERROR, "add_event", "Error: db_find_key(%s) status %d", buf, status);
2633  return HS_FILE_ERROR;
2634  }
2635  }
2636 
2637  return HS_SUCCESS;
2638  }
char type[NAME_LENGTH]
history channel name
Definition: history.h:109
#define DB_NO_KEY
Definition: midas.h:648
#define DB_NO_MORE_SUBKEYS
Definition: midas.h:652
#define HS_SUCCESS
Definition: midas.h:733
#define HS_FILE_ERROR
Definition: midas.h:734
#define TID_BOOL
Definition: midas.h:347
#define MINFO
Definition: midas.h:566
BOOL equal_ustring(const char *str1, const char *str2)
Definition: odb.cxx:3191
INT db_delete_key(HNDLE hDB, HNDLE hKey, BOOL follow_links)
Definition: odb.cxx:3846
INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
Definition: odb.cxx:6529
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
Definition: odb.cxx:3298
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
Definition: odb.cxx:6009
INT db_set_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
Definition: odb.cxx:7642
INT db_set_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
Definition: odb.cxx:7209
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition: odb.cxx:5576
KEY key
Definition: mdump.cxx:37
INT i
Definition: mdump.cxx:35
#define TRUE
Definition: midas.h:182
#define NAME_LENGTH
Definition: midas.h:279
size_t EXPRT strlcpy(char *dst, const char *src, size_t size)
#define event_id
Definition: midas_macro.h:234
INT j
Definition: odbhist.cxx:40
INT k
Definition: odbhist.cxx:40
Definition: midas.h:1032
INT num_values
Definition: midas.h:1034
DWORD type
Definition: midas.h:1033
char name[NAME_LENGTH]
Definition: midas.h:1035
INT item_size
Definition: midas.h:1038
Definition: midas.h:1240
DWORD type
Definition: midas.h:1242
DWORD n_data
Definition: midas.h:1243
char name[NAME_LENGTH]
Definition: midas.h:1241
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 2301 of file history.cxx.

2302  {
2303  HNDLE hKeyRoot;
2304  int status;
2305  char name[256];
2306  STRLCPY(name, event_name);
2307  char *s = strchr(name, '/');
2308  if (s)
2309  *s = ':';
2310 
2311  //printf("Looking for event id for \'%s\'\n", name);
2312 
2313  status = db_find_key(fDB, 0, "/History/Events", &hKeyRoot);
2314  if (status == DB_SUCCESS) {
2315  for (int i = 0;; i++) {
2316  HNDLE hKey;
2317  KEY key;
2318 
2319  status = db_enum_key(fDB, hKeyRoot, i, &hKey);
2320  if (status != DB_SUCCESS)
2321  break;
2322 
2323  status = db_get_key(fDB, hKey, &key);
2324  assert(status == DB_SUCCESS);
2325 
2326  //printf("key \'%s\'\n", key.name);
2327 
2328  int evid = (WORD) strtol(key.name, NULL, 0);
2329  if (evid == 0)
2330  continue;
2331 
2332  char tmp[NAME_LENGTH+NAME_LENGTH+2];
2333  int size = sizeof(tmp);
2334  status = db_get_data(fDB, hKey, tmp, &size, TID_STRING);
2335  assert(status == DB_SUCCESS);
2336 
2337  //printf("got %d \'%s\' looking for \'%s\'\n", evid, tmp, name);
2338 
2339  if (equal_ustring(name, tmp))
2340  return evid;
2341  }
2342  }
2343 
2344  return -1;
2345  }
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 2958 of file history.cxx.

2959  {
2960  int event_id = -1;
2961 
2962  if (fDebug && event_name != NULL && tag_name != NULL)
2963  printf("xhs_event_id for event [%s], tag [%s]\n", event_name, tag_name);
2964 
2965  *pevid = 0;
2966 
2967  /* use "/History/Tags" if available */
2968  event_id = GetEventIdFromOdbTags(event_name, tag_name);
2969 
2970  /* if no Tags, use "/History/Events" and hs_get_tags() to read definition from history files */
2971  if (event_id < 0)
2972  event_id = GetEventIdFromHS(t, event_name, tag_name);
2973 
2974  /* if nothing works, use hs_get_event_id() */
2975  if (event_id <= 0) {
2976  DWORD evid = 0;
2977  int status = ::hs_get_event_id((DWORD)t, (char*)event_name, &evid);
2978  if (status != HS_SUCCESS)
2979  return status;
2980  event_id = evid;
2981  }
2982 
2983  if (event_id < 0)
2984  return HS_UNDEFINED_VAR;
2985 
2986  *pevid = event_id;
2987 
2988  return HS_SUCCESS;
2989  }
#define HS_UNDEFINED_VAR
Definition: midas.h:739
static INT hs_get_event_id(DWORD ltime, const char *name, DWORD *id)
Definition: history.cxx:996
int GetEventIdFromHS(time_t ltime, const char *evname, const char *tagname)
Definition: history.cxx:2814
int GetEventIdFromOdbTags(const char *evname, const char *tagname)
Definition: history.cxx:2884
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 2814 of file history.cxx.

2815  {
2816  HNDLE hKeyRoot;
2817  int status;
2818 
2819  status = db_find_key(fDB, 0, "/History/Events", &hKeyRoot);
2820  if (status != DB_SUCCESS) {
2821  return -1;
2822  }
2823 
2824  for (int i = 0;; i++) {
2825  HNDLE hKey;
2826  KEY key;
2827  int evid;
2828  char buf[256];
2829  int size;
2830  char *s;
2831  int ntags = 0;
2832  TAG* tags = NULL;
2833  char event_name[NAME_LENGTH];
2834 
2835  status = db_enum_key(fDB, hKeyRoot, i, &hKey);
2836  if (status != DB_SUCCESS)
2837  break;
2838 
2839  status = db_get_key(fDB, hKey, &key);
2840  assert(status == DB_SUCCESS);
2841 
2842  if (!isdigit(key.name[0]))
2843  continue;
2844 
2845  evid = atoi(key.name);
2846 
2847  assert(key.item_size < (int)sizeof(buf));
2848 
2849  size = sizeof(buf);
2850  status = db_get_data(fDB, hKey, buf, &size, TID_STRING);
2851  assert(status == DB_SUCCESS);
2852 
2853  strlcpy(event_name, buf, sizeof(event_name));
2854 
2855  s = strchr(buf,':');
2856  if (s)
2857  *s = 0;
2858 
2859  //printf("Found event %d, event [%s] name [%s], looking for [%s][%s]\n", evid, event_name, buf, evname, tagname);
2860 
2861  if (!equal_ustring((char *)evname, buf))
2862  continue;
2863 
2864  status = ::hs_get_tags((DWORD)ltime, evid, event_name, &ntags, &tags);
2865 
2866  for (int j=0; j<ntags; j++) {
2867  //printf("at %d [%s] looking for [%s]\n", j, tags[j].name, tagname);
2868 
2869  if (equal_ustring((char *)tagname, tags[j].name)) {
2870  if (tags)
2871  free(tags);
2872  return evid;
2873  }
2874  }
2875 
2876  if (tags)
2877  free(tags);
2878  tags = NULL;
2879  }
2880 
2881  return -1;
2882  }
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:3161
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 2884 of file history.cxx.

2885  {
2886  HNDLE hKeyRoot;
2887  int status;
2888 
2889  status = db_find_key(fDB, 0, "/History/Tags", &hKeyRoot);
2890  if (status != DB_SUCCESS) {
2891  return -1;
2892  }
2893 
2894  for (int i = 0;; i++) {
2895  HNDLE hKey;
2896  KEY key;
2897  int evid;
2898  char buf[256];
2899  int size;
2900  char *s;
2901 
2902  status = db_enum_key(fDB, hKeyRoot, i, &hKey);
2903  if (status != DB_SUCCESS)
2904  break;
2905 
2906  status = db_get_key(fDB, hKey, &key);
2907  assert(status == DB_SUCCESS);
2908 
2909  if (key.type != TID_STRING)
2910  continue;
2911 
2912  if (!isdigit(key.name[0]))
2913  continue;
2914 
2915  evid = atoi(key.name);
2916 
2917  assert(key.item_size < (int)sizeof(buf));
2918 
2919  size = sizeof(buf);
2920  status = db_get_data_index(fDB, hKey, buf, &size, 0, TID_STRING);
2921  assert(status == DB_SUCCESS);
2922 
2923  s = strchr(buf,'/');
2924  if (s)
2925  *s = 0;
2926 
2927  //printf("Found event %d, name [%s], looking for [%s][%s]\n", evid, buf, evname, tagname);
2928 
2929  if (!equal_ustring((char *)evname, buf))
2930  continue;
2931 
2932  for (int j=1; j<key.num_values; j++) {
2933  size = sizeof(buf);
2934  status = db_get_data_index(fDB, hKey, buf, &size, j, TID_STRING);
2935  assert(status == DB_SUCCESS);
2936 
2937  if (!isdigit(buf[0]))
2938  continue;
2939 
2940  s = strchr(buf,' ');
2941  if (!s)
2942  continue;
2943 
2944  s++;
2945 
2946  //printf("at %d [%s] [%s] compare to [%s]\n", j, buf, s, tagname);
2947 
2948  if (equal_ustring((char *)tagname, s)) {
2949  //printf("Found evid %d\n", evid);
2950  return evid;
2951  }
2952  }
2953  }
2954 
2955  return -1;
2956  }
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
Definition: odb.cxx:6885
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 2673 of file history.cxx.

2674  {
2675  HNDLE hKeyRoot;
2676  int status;
2677 
2678  status = db_find_key(fDB, 0, "/History/Events", &hKeyRoot);
2679  if (status != DB_SUCCESS) {
2680  return HS_FILE_ERROR;
2681  }
2682 
2683  /* loop over tags to display event names */
2684  for (int i = 0;; i++) {
2685  HNDLE hKeyEq;
2686  char *s;
2687  char evname[1024+NAME_LENGTH];
2688  int size;
2689 
2690  status = db_enum_key(fDB, hKeyRoot, i, &hKeyEq);
2691  if (status != DB_SUCCESS)
2692  break;
2693 
2694  size = sizeof(evname);
2695  status = db_get_data(fDB, hKeyEq, evname, &size, TID_STRING);
2696  assert(status == DB_SUCCESS);
2697 
2698  s = strchr(evname,':');
2699  if (s)
2700  *s = '/';
2701 
2702  /* skip duplicated event names */
2703 
2704  int found = 0;
2705  for (unsigned i=0; i<events->size(); i++) {
2706  if (equal_ustring(evname, (*events)[i].c_str())) {
2707  found = 1;
2708  break;
2709  }
2710  }
2711 
2712  if (found)
2713  continue;
2714 
2715  events->push_back(evname);
2716 
2717  //printf("event \'%s\'\n", evname);
2718  }
2719 
2720  return HS_SUCCESS;
2721  }
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 2723 of file history.cxx.

2724  {
2725  HNDLE hKeyRoot;
2726  int status;
2727 
2728  status = db_find_key(fDB, 0, "/History/Tags", &hKeyRoot);
2729  if (status != DB_SUCCESS) {
2730  return HS_FILE_ERROR;
2731  }
2732 
2733  /* loop over tags to display event names */
2734  for (int i = 0;; i++) {
2735  HNDLE hKeyEq;
2736  KEY key;
2737  char *s;
2738  WORD event_id;
2739  char evname[1024+NAME_LENGTH];
2740  int size;
2741 
2742  status = db_enum_key(fDB, hKeyRoot, i, &hKeyEq);
2743  if (status != DB_SUCCESS)
2744  break;
2745 
2746  /* get event name */
2747  db_get_key(fDB, hKeyEq, &key);
2748 
2749  //printf("key \'%s\'\n", key.name);
2750 
2751  if (key.type != TID_STRING)
2752  continue;
2753 
2754  /* parse event name in format: "event_id" or "event_id:var_name" */
2755  s = key.name;
2756 
2757  event_id = (WORD)strtoul(s,&s,0);
2758  if (event_id == 0)
2759  continue;
2760  if (s[0] != 0)
2761  continue;
2762 
2763  size = sizeof(evname);
2764  status = db_get_data_index(fDB, hKeyEq, evname, &size, 0, TID_STRING);
2765  assert(status == DB_SUCCESS);
2766 
2767  /* skip duplicated event names */
2768 
2769  int found = 0;
2770  for (unsigned i=0; i<events->size(); i++) {
2771  if (equal_ustring(evname, (*events)[i].c_str())) {
2772  found = 1;
2773  break;
2774  }
2775  }
2776 
2777  if (found)
2778  continue;
2779 
2780  events->push_back(evname);
2781 
2782  //printf("event %d \'%s\'\n", event_id, evname);
2783  }
2784 
2785  return HS_SUCCESS;
2786  }
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 2991 of file history.cxx.

2992  {
2993  time_t now = time(NULL);
2994  int evid;
2995  int status = GetEventId(now, event_name, NULL, &evid);
2996  if (status != HS_SUCCESS)
2997  return status;
2998 
2999  if (fDebug)
3000  printf("hs_get_tags: get tags for event [%s] %d\n", event_name, evid);
3001 
3002  int ntags;
3003  TAG* tags;
3004  status = ::hs_get_tags((DWORD)now, evid, (char*)event_name, &ntags, &tags);
3005 
3006  if (status != HS_SUCCESS)
3007  return status;
3008 
3009  for (int i=0; i<ntags; i++)
3010  ptags->push_back(tags[i]);
3011 
3012  if (tags)
3013  free(tags);
3014 
3015  if (fDebug)
3016  printf("hs_get_tags: get tags for event [%s] %d, found %d tags\n", event_name, evid, ntags);
3017 
3018  return HS_SUCCESS;
3019  }
int GetEventId(time_t t, const char *event_name, const char *tag_name, int *pevid)
Definition: history.cxx:2958
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 3021 of file history.cxx.

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

2289  {
2290  if (fDebug)
2291  printf("hs_clear_cache!\n");
2292 
2293  fEventsCache.clear();
2294  fTagsCache.clear();
2295  fEvidCache.clear();
2296  return HS_SUCCESS;
2297  }
std::vector< std::string > fEventsCache
Definition: history.cxx:2233
std::map< std::string, std::vector< TAG > > fTagsCache
Definition: history.cxx:2234
std::map< std::string, int > fEvidCache
Definition: history.cxx:2235
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 2250 of file history.cxx.

2251  {
2253 
2254  /* delete obsolete odb entries */
2255 
2256  if (1) {
2257  HNDLE hKey;
2258  int status = db_find_key(fDB, 0, "/History/ListSource", &hKey);
2259  if (status == DB_SUCCESS)
2261  }
2262 
2263  ::hs_set_path(path);
2264 
2265  if (fDebug)
2266  printf("hs_connect: path [%s]\n", path);
2267 
2268  return HS_SUCCESS;
2269  }
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition: midas.cxx:3005
static INT hs_set_path(const char *path)
Definition: history.cxx:190
Here is the call graph for this function:

◆ hs_count_events()

static INT hs_count_events ( DWORD  ltime,
DWORD count 
)
static

Definition at line 919 of file history.cxx.

937 {
938  int fh, fhd;
939  std::string fn, fnd;
940  INT status, i, n;
941  DWORD *id;
942  DEF_RECORD def_rec;
943 
944  /* search latest history file */
945  status = hs_search_file(&ltime, -1);
946  if (status != HS_SUCCESS) {
947  cm_msg(MERROR, "hs_count_events", "cannot find recent history file");
948  return HS_FILE_ERROR;
949  }
950 
951  /* open history and definition files */
952  hs_open_file(ltime, "hst", O_RDONLY, &fn, &fh);
953  hs_open_file(ltime, "idf", O_RDONLY, &fnd, &fhd);
954  if (fh < 0 || fhd < 0) {
955  cm_msg(MERROR, "hs_count_events", "cannot open index files");
956  return HS_FILE_ERROR;
957  }
958 
959  /* allocate event id array */
960  xseek_end(fnd, fhd);
961  DWORD pos_fhd = xcurpos(fnd, fhd);
962  if (pos_fhd == (DWORD)-1) return HS_FILE_ERROR;
963  id = (DWORD *) M_MALLOC(pos_fhd/sizeof(def_rec) * sizeof(DWORD));
964  xseek(fnd, fhd, 0);
965 
966  /* loop over index file */
967  n = 0;
968  do {
969  /* read definition index record */
970  if (xread(fnd, fhd, (char *) &def_rec, sizeof(def_rec), true) <= 0)
971  break;
972 
973  /* look for existing entries */
974  for (i = 0; i < n; i++)
975  if (id[i] == def_rec.event_id)
976  break;
977 
978  /* new entry found */
979  if (i == n) {
980  id[i] = def_rec.event_id;
981  n++;
982  }
983  } while (TRUE);
984 
985 
986  M_FREE(id);
987  close(fh);
988  close(fhd);
989  *count = n;
990 
991  return HS_SUCCESS;
992 }
static INT hs_open_file(time_t ltime, const char *suffix, INT mode, std::string *pfile_name, int *fh)
Definition: history.cxx:218
static int xread(const std::string &fn, int fh, void *buf, size_t count, bool eof_ok=false)
Definition: history.cxx:85
static INT hs_search_file(DWORD *ltime, INT direction)
Definition: history.cxx:365
static DWORD xcurpos(const std::string &fn, int fh)
Definition: history.cxx:145
static bool xseek_end(const std::string &fn, int fh)
Definition: history.cxx:121
static bool xseek(const std::string &fn, int fh, DWORD pos)
Definition: history.cxx:109
DWORD n[4]
Definition: mana.cxx:247
double count
Definition: mdump.cxx:36
#define DWORD
Definition: mhdump.cxx:31
#define M_MALLOC(x)
Definition: midas.h:1550
int INT
Definition: midas.h:129
#define M_FREE(x)
Definition: midas.h:1552
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 1072 of file history.cxx.

1090 {
1091  int fh, fhd;
1092  std::string fn, fnd;
1093  INT i, n, status;
1094  DEF_RECORD def_rec;
1095  HIST_RECORD rec;
1096 
1097  /* search latest history file */
1098  status = hs_search_file(&ltime, -1);
1099  if (status != HS_SUCCESS) {
1100  cm_msg(MERROR, "hs_count_tags", "cannot find recent history file");
1101  return HS_FILE_ERROR;
1102  }
1103 
1104  /* open history and definition files */
1105  hs_open_file(ltime, "hst", O_RDONLY, &fn, &fh);
1106  hs_open_file(ltime, "idf", O_RDONLY, &fnd, &fhd);
1107  if (fh < 0 || fhd < 0) {
1108  cm_msg(MERROR, "hs_count_tags", "cannot open index files");
1109  return HS_FILE_ERROR;
1110  }
1111 
1112  /* search last definition */
1113  xseek_end(fnd, fhd);
1114  n = xcurpos(fnd, fhd) / sizeof(def_rec);
1115  def_rec.event_id = 0;
1116  for (i = n - 1; i >= 0; i--) {
1117  if (!xseek(fnd, fhd, i * sizeof(def_rec))) return HS_FILE_ERROR;
1118  if (xread(fnd, fhd, (char *) &def_rec, sizeof(def_rec)) < 0) return HS_FILE_ERROR;
1119  if (def_rec.event_id == event_id)
1120  break;
1121  }
1122  if (def_rec.event_id != event_id) {
1123  cm_msg(MERROR, "hs_count_tags", "event %d not found in index file", event_id);
1124  return HS_FILE_ERROR;
1125  }
1126 
1127  /* read definition */
1128  xseek(fn, fh, def_rec.def_offset);
1129  xread(fn, fh, (char *) &rec, sizeof(rec));
1130  *count = rec.data_size / sizeof(TAG);
1131 
1132  close(fh);
1133  close(fhd);
1134 
1135  return HS_SUCCESS;
1136 }
DWORD event_id
Definition: midas.h:1375
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 2642 of file history.cxx.

2643  {
2644  int event_id = FindEventId(event_name);
2645  if (event_id < 0)
2646  event_id = AllocateEventId(event_name);
2647  if (event_id < 0)
2648  return HS_FILE_ERROR;
2649  fEvidCache[event_name] = event_id;
2650  CreateOdbTags(event_id, event_name, ntags, tags);
2651  return ::hs_define_event(event_id, (char*)event_name, (TAG*)tags, ntags*sizeof(TAG));
2652  }
static INT hs_define_event(DWORD event_id, const char *name, const TAG *tag, DWORD size)
Definition: history.cxx:439
int FindEventId(const char *event_name)
Definition: history.cxx:2301
int AllocateEventId(const char *event_name)
Definition: history.cxx:2349
int CreateOdbTags(int event_id, const char *event_name, int ntags, const TAG tags[])
Definition: history.cxx:2414
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 439 of file history.cxx.

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

3503 {
3504  HNDLE hDB, hKey, hKeyVar;
3505  HISTORY_PANEL(history_panel_str);
3506  char str[256];
3507 
3508  const char *color[] = {
3509  "#00AAFF", "#FF9000", "#FF00A0", "#00C030",
3510  "#A0C0D0", "#D0A060", "#C04010", "#807060",
3511  "#F0C000", "#2090A0", "#D040D0", "#90B000",
3512  "#B0B040", "#B0B0FF", "#FFA0A0", "#A0FFA0",
3513  "#808080"};
3514 
3515  cm_get_experiment_database(&hDB, nullptr);
3516 
3517  snprintf(str, sizeof(str), "/History/Display/%s/%s", group, panel);
3518 
3519  db_create_record(hDB, 0, str, strcomb1(history_panel_str).c_str());
3520  db_find_key(hDB, 0, str, &hKey);
3521  if (!hKey)
3522  return DB_NO_MEMORY;
3523 
3524  int i=0;
3525  for(auto const& v: var) {
3526  db_find_key(hDB, hKey, "Variables", &hKeyVar);
3527  db_set_data_index(hDB, hKeyVar, v.c_str(), 64, i, TID_STRING);
3528 
3529  str[0] = 0;
3530  db_set_value_index(hDB, hKey, "Formula", str, 64, i, TID_STRING, false);
3531  db_set_value_index(hDB, hKey, "Label", str, 32, i, TID_STRING, false);
3532  db_set_value_index(hDB, hKey, "Colour", color[i < 16 ? i : 16], 32, i, TID_STRING, false);
3533 
3534  i++;
3535  }
3536 
3537  return HS_SUCCESS;
3538 }
#define DB_NO_MEMORY
Definition: midas.h:639
#define HISTORY_PANEL(_name)
Definition: history.cxx:3474
std::string strcomb1(const char **list)
Definition: odb.cxx:601
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:5355
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
Definition: odb.cxx:12803
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_disconnect()

int MidasHistory::hs_disconnect ( )
inlinevirtual

disconnect from history, returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 2273 of file history.cxx.

2274  {
2275  hs_clear_cache();
2276  return HS_SUCCESS;
2277  }
int hs_clear_cache()
clear internal cache, returns HS_SUCCESS
Definition: history.cxx:2288
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 1966 of file history.cxx.

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

857 {
858  int fh, fhd;
859  std::string fn, fnd;
860  INT status, i, n;
861  DEF_RECORD def_rec;
862 
863  /* search latest history file */
864  status = hs_search_file(&ltime, -1);
865  if (status != HS_SUCCESS) {
866  cm_msg(MERROR, "hs_enum_events", "cannot find recent history file");
867  return HS_FILE_ERROR;
868  }
869 
870  /* open history and definition files */
871  hs_open_file(ltime, "hst", O_RDONLY, &fn, &fh);
872  hs_open_file(ltime, "idf", O_RDONLY, &fnd, &fhd);
873  if (fh < 0 || fhd < 0) {
874  cm_msg(MERROR, "hs_enum_events", "cannot open index files");
875  return HS_FILE_ERROR;
876  }
877  xseek(fnd, fhd, 0);
878 
879  /* loop over definition index file */
880  n = 0;
881  do {
882  /* read event definition */
883  if (xread(fnd, fhd, (char *) &def_rec, sizeof(def_rec), true) <= 0)
884  break;
885 
886  /* look for existing entry for this event id */
887  for (i = 0; i < n; i++)
888  if (event_id[i] == (INT) def_rec.event_id) {
889  strcpy(event_name + i * NAME_LENGTH, def_rec.event_name);
890  break;
891  }
892 
893  /* new entry found */
894  if (i == n) {
895  if (((i * NAME_LENGTH) > ((INT) * name_size)) || ((i * sizeof(INT)) > (*id_size))) {
896  cm_msg(MERROR, "hs_enum_events", "index buffer too small");
897  close(fh);
898  close(fhd);
899  return HS_NO_MEMORY;
900  }
901 
902  /* copy definition record */
903  strcpy(event_name + i * NAME_LENGTH, def_rec.event_name);
904  event_id[i] = def_rec.event_id;
905  n++;
906  }
907  } while (TRUE);
908 
909  close(fh);
910  close(fhd);
911  *name_size = n * NAME_LENGTH;
912  *id_size = n * sizeof(INT);
913 
914  return HS_SUCCESS;
915 }
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 1140 of file history.cxx.

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

2666  {
2667  //printf("hs_flush_buffers!\n");
2668  return HS_SUCCESS;
2669  }

◆ hs_gen_index()

static INT hs_gen_index ( DWORD  ltime)
static

Definition at line 249 of file history.cxx.

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

1016 {
1017  int fh, fhd;
1018  std::string fn, fnd;
1019  INT status;
1020  DWORD lt;
1021  DEF_RECORD def_rec;
1022 
1023  /* search latest history file */
1024  if (ltime == 0)
1025  ltime = (DWORD) time(NULL);
1026 
1027  lt = ltime;
1028 
1029  do {
1030  status = hs_search_file(&lt, -1);
1031  if (status != HS_SUCCESS) {
1032  cm_msg(MERROR, "hs_count_events", "cannot find recent history file");
1033  return HS_FILE_ERROR;
1034  }
1035 
1036  /* open history and definition files */
1037  hs_open_file(lt, "hst", O_RDONLY, &fn, &fh);
1038  hs_open_file(lt, "idf", O_RDONLY, &fnd, &fhd);
1039  if (fh < 0 || fhd < 0) {
1040  cm_msg(MERROR, "hs_count_events", "cannot open index files");
1041  return HS_FILE_ERROR;
1042  }
1043 
1044  /* loop over index file */
1045  *id = 0;
1046  do {
1047  /* read definition index record */
1048  if (xread(fnd, fhd, (char *) &def_rec, sizeof(def_rec), true) <= 0)
1049  break;
1050 
1051  if (strcmp(name, def_rec.event_name) == 0) {
1052  *id = def_rec.event_id;
1053  close(fh);
1054  close(fhd);
1055  return HS_SUCCESS;
1056  }
1057  } while (TRUE);
1058 
1059  close(fh);
1060  close(fhd);
1061 
1062  /* not found -> go back one day */
1063  lt -= 3600 * 24;
1064 
1065  } while (lt > ltime - 3600 * 24 * 365 * 10); /* maximum 10 years */
1066 
1067  return HS_UNDEFINED_EVENT;
1068 }
#define HS_UNDEFINED_EVENT
Definition: midas.h:738
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 2788 of file history.cxx.

2789  {
2790  assert(pevents);
2791  pevents->clear();
2792 
2793  if (fEventsCache.size() == 0) {
2794  int status;
2795 
2796  if (fDebug)
2797  printf("hs_get_events: reading events list!\n");
2798 
2800 
2801  if (status != HS_SUCCESS)
2803 
2804  if (status != HS_SUCCESS)
2805  return status;
2806  }
2807 
2808  for (unsigned i=0; i<fEventsCache.size(); i++)
2809  pevents->push_back(fEventsCache[i]);
2810 
2811  return HS_SUCCESS;
2812  }
int GetEventsFromOdbTags(std::vector< std::string > *events)
Definition: history.cxx:2723
int GetEventsFromOdbEvents(std::vector< std::string > *events)
Definition: history.cxx:2673
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 3188 of file history.cxx.

3189  {
3190  for (int i=0; i<num_var; i++)
3191  last_written[i] = 0;
3192  return HS_FILE_ERROR;
3193  }

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

3162  {
3163  std::vector<TAG>& ttt = fTagsCache[event_name];
3164 
3165  if (ttt.size() == 0) {
3166  int status = HS_FILE_ERROR;
3167 
3168  if (fDebug)
3169  printf("hs_get_tags: reading tags for event [%s]\n", event_name);
3170 
3171  status = GetTagsFromOdb(event_name, &ttt);
3172 
3173  if (status != HS_SUCCESS)
3174  status = GetTagsFromHS(event_name, &ttt);
3175 
3176  if (status != HS_SUCCESS)
3177  return status;
3178  }
3179 
3180  for (unsigned i=0; i<ttt.size(); i++)
3181  ptags->push_back(ttt[i]);
3182 
3183  return HS_SUCCESS;
3184  }
int GetTagsFromOdb(const char *event_name, std::vector< TAG > *ptags)
Definition: history.cxx:3021
int GetTagsFromHS(const char *event_name, std::vector< TAG > *ptags)
Definition: history.cxx:2991
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 1340 of file history.cxx.

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

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

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

◆ hs_read() [1/2]

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

Definition at line 1463 of file history.cxx.

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

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

3401  {
3402  int status;
3403 
3404  MidasHistoryBinnedBuffer** buffer = new MidasHistoryBinnedBuffer*[num_var];
3405  MidasHistoryBufferInterface** xbuffer = new MidasHistoryBufferInterface*[num_var];
3406 
3407  for (int i=0; i<num_var; i++) {
3408  buffer[i] = new MidasHistoryBinnedBuffer(start_time, end_time, num_bins);
3409  xbuffer[i] = buffer[i];
3410 
3411  if (count_bins)
3412  buffer[i]->fCount = count_bins[i];
3413  if (mean_bins)
3414  buffer[i]->fMean = mean_bins[i];
3415  if (rms_bins)
3416  buffer[i]->fRms = rms_bins[i];
3417  if (min_bins)
3418  buffer[i]->fMin = min_bins[i];
3419  if (max_bins)
3420  buffer[i]->fMax = max_bins[i];
3421  if (bins_first_time)
3422  buffer[i]->fBinsFirstTime = bins_first_time[i];
3423  if (bins_first_value)
3424  buffer[i]->fBinsFirstValue = bins_first_value[i];
3425  if (bins_last_time)
3426  buffer[i]->fBinsLastTime = bins_last_time[i];
3427  if (bins_last_value)
3428  buffer[i]->fBinsLastValue = bins_last_value[i];
3429  if (last_time)
3430  buffer[i]->fLastTimePtr = &last_time[i];
3431  if (last_value)
3432  buffer[i]->fLastValuePtr = &last_value[i];
3433 
3434  buffer[i]->Start();
3435  }
3436 
3437  status = hs_read_buffer(start_time, end_time,
3438  num_var, event_name, tag_name, var_index,
3439  xbuffer,
3440  read_status);
3441 
3442  for (int i=0; i<num_var; i++) {
3443  buffer[i]->Finish();
3444  if (num_entries)
3445  num_entries[i] = buffer[i]->fNumEntries;
3446  //if (0) {
3447  // for (int j=0; j<num_bins; j++) {
3448  // 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]);
3449  // }
3450  //}
3451  delete buffer[i];
3452  }
3453 
3454  delete[] buffer;
3455  delete[] xbuffer;
3456 
3457  return status;
3458  }
time_t * fBinsLastTime
Definition: history.h:87
double * fBinsLastValue
Definition: history.h:88
time_t * fBinsFirstTime
Definition: history.h:85
double * fLastValuePtr
Definition: history.h:91
double * fBinsFirstValue
Definition: history.h:86
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:3356
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 3356 of file history.cxx.

3360  {
3361  for (int i=0; i<num_var; i++) {
3362  int event_id = 0;
3363 
3364  if (event_name[i]==NULL) {
3365  read_status[i] = HS_UNDEFINED_EVENT;
3366  continue;
3367  }
3368 
3369  int status = GetEventId(end_time, event_name[i], tag_name[i], &event_id);
3370 
3371  if (status != HS_SUCCESS) {
3372  read_status[i] = status;
3373  continue;
3374  }
3375 
3376  status = ::hs_read(event_id, (DWORD)start_time, (DWORD)end_time, 0,
3377  tag_name[i], var_index[i],
3378  NULL, NULL,
3379  NULL, NULL,
3380  NULL, NULL,
3381  buffer[i]);
3382 
3383  if (fDebug) {
3384  printf("hs_read %d \'%s\' [%d] returned %d\n", event_id, tag_name[i], var_index[i], status);
3385  }
3386 
3387  read_status[i] = status;
3388  }
3389 
3390  return HS_SUCCESS;
3391  }
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 365 of file history.cxx.

386 {
387  time_t lt;
388  int fh, fhd, fhi;
389  std::string fn;
390 
391  ss_tzset(); // required by localtime_r()
392 
393  if (*ltime == 0)
394  *ltime = ss_time();
395 
396  lt = (time_t) * ltime;
397  do {
398  /* try to open history file for date "lt" */
399  hs_open_file(lt, "hst", O_RDONLY, &fn, &fh);
400 
401  /* if not found, look for next day */
402  if (fh < 0)
403  lt += direction * 3600 * 24;
404 
405  /* stop if more than a year before starting point or in the future */
406  } while (fh < 0 && (INT) * ltime - (INT) lt < 3600 * 24 * 365 && lt <= (time_t) ss_time());
407 
408  if (fh < 0)
409  return HS_FILE_ERROR;
410 
411  if (lt != (time_t) *ltime) {
412  /* if switched to new day, set start_time to 0:00 */
413  struct tm tms;
414  localtime_r(&lt, &tms);
415  tms.tm_hour = tms.tm_min = tms.tm_sec = 0;
416  *ltime = (DWORD) ss_mktime(&tms);
417  }
418 
419  /* check if index files are there */
420  hs_open_file(*ltime, "idf", O_RDONLY, NULL, &fhd);
421  hs_open_file(*ltime, "idx", O_RDONLY, NULL, &fhi);
422 
423  if (fh > 0)
424  close(fh);
425  if (fhd > 0)
426  close(fhd);
427  if (fhi > 0)
428  close(fhi);
429 
430  /* generate them if not */
431  if (fhd < 0 || fhi < 0)
432  hs_gen_index(*ltime);
433 
434  return HS_SUCCESS;
435 }
DWORD ss_time()
Definition: system.cxx:3401
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 2281 of file history.cxx.

2282  {
2283  return debug;
2284  }
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 190 of file history.cxx.

191 {
192  assert(path);
193  assert(path[0] != 0);
194 
195  _hs_path_name = path;
196 
197  /* check for trailing directory seperator */
198  if (_hs_path_name.back() != DIR_SEPARATOR)
200 
201  return HS_SUCCESS;
202 }
#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 1432 of file history.cxx.

1433 {
1434  int j = 0;
1435  /* convert data to float */
1436  switch (tid) {
1437  default:
1438  return 0;
1439  case TID_BYTE:
1440  return *(((BYTE *) ybuffer) + j);
1441  case TID_SBYTE:
1442  return *(((char *) ybuffer) + j);
1443  case TID_CHAR:
1444  return *(((char *) ybuffer) + j);
1445  case TID_WORD:
1446  return *(((WORD *) ybuffer) + j);
1447  case TID_SHORT:
1448  return *(((short *) ybuffer) + j);
1449  case TID_DWORD:
1450  return *(((DWORD *) ybuffer) + j);
1451  case TID_INT:
1452  return *(((INT *) ybuffer) + j);
1453  case TID_BOOL:
1454  return *(((BOOL *) ybuffer) + j);
1455  case TID_FLOAT:
1456  return *(((float *) ybuffer) + j);
1457  case TID_DOUBLE:
1458  return *(((double *) ybuffer) + j);
1459  }
1460  /* NOT REACHED */
1461 }
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 2656 of file history.cxx.

2657  {
2658  int event_id = fEvidCache[event_name];
2659  //printf("write event [%s] evid %d\n", event_name, event_id);
2660  return ::hs_write_event(event_id, (void*)data, data_size);
2661  }
static INT hs_write_event(DWORD event_id, const void *data, DWORD size)
Definition: history.cxx:668
void * data
Definition: mana.cxx:268
Here is the call graph for this function:

◆ hs_write_event() [2/2]

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

Definition at line 668 of file history.cxx.

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

◆ MakeMidasHistory()

MidasHistoryInterface* MakeMidasHistory ( )

Definition at line 3541 of file history.cxx.

3542 {
3543 #if 0
3544  // midas history is a singleton class
3545  static MidasHistory* gh = NULL;
3546  if (!gh)
3547  gh = new MidasHistory;
3548  return gh;
3549 #endif
3550  return new MidasHistory();
3551 }
Here is the caller graph for this function:

◆ xcurpos()

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

Definition at line 145 of file history.cxx.

146 {
147  off_t off = lseek(fh, 0, SEEK_CUR);
148 
149  if (off < 0) {
150  cm_msg(MERROR, "xcurpos", "Error in lseek(0, SEEK_CUR) for file \"%s\", errno %d (%s)", fn.c_str(), errno, strerror(errno));
151  return -1;
152  }
153 
154  DWORD dw = off;
155 
156  if (dw != off) {
157  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);
158  return -1;
159  }
160 
161  return dw;
162 }
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 85 of file history.cxx.

86 {
87  ssize_t rd = read(fh, buf, count);
88 
89  if (rd < 0) {
90  cm_msg(MERROR, "xread", "Error reading from file \"%s\" errno %d (%s)", fn.c_str(), errno, strerror(errno));
91  return -1;
92  }
93 
94  if (rd == 0) {
95  if (eof_ok)
96  return 0;
97  cm_msg(MERROR, "xread", "Error: Unexpected end-of-file when reading file \"%s\"", fn.c_str());
98  return -1;
99  }
100 
101  if ((size_t)rd != count) {
102  cm_msg(MERROR, "xread", "Error: Truncated read from file \"%s\", requested %d bytes, read %d bytes", fn.c_str(), (int)count, (int)rd);
103  return -1;
104  }
105 
106  return 1;
107 }
#define read(n, a, f)
Definition: midas_macro.h:242
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 109 of file history.cxx.

110 {
111  off_t off = lseek(fh, pos, SEEK_SET);
112 
113  if (off < 0) {
114  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));
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:

◆ xseek_cur()

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

Definition at line 133 of file history.cxx.

134 {
135  off_t off = lseek(fh, offset, SEEK_CUR);
136 
137  if (off < 0) {
138  cm_msg(MERROR, "xseek_cur", "Error in lseek(%d, SEEK_CUR) for file \"%s\", errno %d (%s)", offset, fn.c_str(), errno, strerror(errno));
139  return false;
140  }
141 
142  return true;
143 }
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 121 of file history.cxx.

122 {
123  off_t off = lseek(fh, 0, SEEK_END);
124 
125  if (off < 0) {
126  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));
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:

◆ xtruncate()

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

Definition at line 164 of file history.cxx.

165 {
166  off_t off = lseek(fh, pos, SEEK_SET);
167 
168  if (off < 0) {
169  cm_msg(MERROR, "xtruncate", "Error in lseek(%llu) for file \"%s\", errno %d (%s)", (unsigned long long)pos, fn.c_str(), errno, strerror(errno));
170  return false;
171  }
172 
173  int status = ftruncate(fh, pos);
174 
175  if (status != 0) {
176  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));
177  return false;
178  }
179 
180  return true;
181 }
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 63 of file history.cxx.

64 {
65  ssize_t wr = write(fh, buf, count);
66 
67  if (wr < 0) {
68  cm_msg(MERROR, "xwrite", "Error writing %d bytes to file \"%s\" errno %d (%s)", (int)count, fn.c_str(), errno, strerror(errno));
69  return false;
70  }
71 
72  if ((size_t)wr != count) {
73  cm_msg(MERROR, "xwrite", "Error writing %d bytes to file \"%s\", short write %d bytes", (int)count, fn.c_str(), (int)wr);
74  return false;
75  }
76 
77  return true;
78 }
#define write(n, a, f, d)
Definition: midas_macro.h:245
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 57 of file history.cxx.

◆ _hs_path_name

std::string _hs_path_name
static

Definition at line 58 of file history.cxx.

◆ fDB

HNDLE MidasHistory::fDB

Definition at line 2230 of file history.cxx.

◆ fDebug

int MidasHistory::fDebug

Definition at line 2231 of file history.cxx.

◆ fEventsCache

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

Definition at line 2233 of file history.cxx.

◆ fEvidCache

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

Definition at line 2235 of file history.cxx.

◆ fTagsCache

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

Definition at line 2234 of file history.cxx.