35#if !defined(OS_VXWORKS)
43#ifndef DOXYGEN_SHOULD_SKIP_THIS
51static bool xwrite(
const std::string& fn,
int fh,
const void *buf,
size_t count)
61 cm_msg(
MERROR,
"xwrite",
"Error writing %d bytes to file \"%s\", short write %d bytes", (
int)
count, fn.c_str(), (
int)
wr);
85 cm_msg(
MERROR,
"xread",
"Error: Unexpected end-of-file when reading file \"%s\"", fn.c_str());
90 cm_msg(
MERROR,
"xread",
"Error: Truncated read from file \"%s\", requested %d bytes, read %d bytes", fn.c_str(), (
int)
count, (
int)
rd);
102 cm_msg(
MERROR,
"xseek",
"Error in lseek(%llu, SEEK_SET) for file \"%s\", errno %d (%s)", (
unsigned long long)pos, fn.c_str(),
errno,
strerror(
errno));
145 cm_msg(
MERROR,
"xcurpos",
"Error: lseek(0, SEEK_CUR) for file \"%s\" returned value %llu does not fir into a DWORD, maybe file is bigger than 2GiB or 4GiB", fn.c_str(), (
unsigned long long)
off);
164 cm_msg(
MERROR,
"xtruncate",
"Error setting file size of \"%s\" to %llu, errno %d (%s)", fn.c_str(), (
unsigned long long)pos,
errno,
strerror(
errno));
181 assert(path[0] != 0);
193#ifndef DOXYGEN_SHOULD_SKIP_THIS
266 cm_msg(
MINFO,
"hs_gen_index",
"generating index files for time %d", (
int)
ltime);
267 printf(
"Recovering index files...\n");
281 cm_msg(
MERROR,
"hs_gen_index",
"cannot create index file");
300 if (
xread(fn,
fh, event_name,
sizeof(event_name)) < 0)
303 printf(
"Event definition %s, ID %d\n", event_name,
rec.event_id);
310 def_rec.def_offset = pos -
sizeof(event_name) -
sizeof(
rec);
317 }
else if (
rec.record_type ==
RT_DATA &&
rec.data_size > 1 &&
rec.data_size < 1 * 1024 * 1024) {
323 irec.offset = pos -
sizeof(
rec);
332 cm_msg(
MERROR,
"hs_gen_index",
"broken history file for time %d, trying to recover", (
int)
ltime);
391 lt += direction * 3600 * 24;
403 tms.tm_hour =
tms.tm_min =
tms.tm_sec = 0;
495 rec.data_size = size;
537 tmb.tm_hour =
tmb.tm_min =
tmb.tm_sec = 0;
562 for (
int i =
n - 1;
i >= 0;
i--) {
716 rec.data_size = size;
727 if (
tmr.tm_yday !=
tmb.tm_yday) {
770 tmr.tm_hour =
tmr.tm_min =
tmr.tm_sec = 0;
854 cm_msg(
MERROR,
"hs_enum_events",
"cannot find recent history file");
861 if (
fh < 0 ||
fhd < 0) {
862 cm_msg(
MERROR,
"hs_enum_events",
"cannot open index files");
875 for (
i = 0;
i <
n;
i++)
884 cm_msg(
MERROR,
"hs_enum_events",
"index buffer too small");
935 cm_msg(
MERROR,
"hs_count_events",
"cannot find recent history file");
942 if (
fh < 0 ||
fhd < 0) {
943 cm_msg(
MERROR,
"hs_count_events",
"cannot open index files");
962 for (
i = 0;
i <
n;
i++)
1006 std::string fn,
fnd;
1020 cm_msg(
MERROR,
"hs_count_events",
"cannot find recent history file");
1027 if (
fh < 0 ||
fhd < 0) {
1028 cm_msg(
MERROR,
"hs_count_events",
"cannot open index files");
1053 }
while (
lt >
ltime - 3600 * 24 * 365 * 10);
1080 std::string fn,
fnd;
1088 cm_msg(
MERROR,
"hs_count_tags",
"cannot find recent history file");
1095 if (
fh < 0 ||
fhd < 0) {
1096 cm_msg(
MERROR,
"hs_count_tags",
"cannot open index files");
1104 for (
i =
n - 1;
i >= 0;
i--) {
1154 std::string fn,
fnd;
1163 cm_msg(
MERROR,
"hs_enum_vars",
"cannot find recent history file");
1170 if (
fh < 0 ||
fhd < 0) {
1171 cm_msg(
MERROR,
"hs_enum_vars",
"cannot open index files");
1179 for (
i =
n - 1;
i >= 0;
i--) {
1196 n =
rec.data_size /
sizeof(
TAG);
1208 cm_msg(
MERROR,
"hs_enum_vars",
"tag buffer too small");
1216 for (
i = 0;
i <
n;
i++) {
1258 std::string fn,
fnd;
1267 cm_msg(
MERROR,
"hs_get_var",
"cannot find recent history file");
1274 if (
fh < 0 ||
fhd < 0) {
1275 cm_msg(
MERROR,
"hs_get_var",
"cannot open index files");
1283 for (
i =
n - 1;
i >= 0;
i--) {
1300 n =
rec.data_size /
sizeof(
TAG);
1305 for (
i = 0;
i <
n;
i++)
1316 *
type = *n_data = 0;
1353 std::string fn,
fnd;
1362 assert(!
"RPC not implemented");
1367 cm_msg(
MERROR,
"hs_get_tags",
"cannot find recent history file, hs_search_file() status %d",
status);
1374 if (
fh < 0 ||
fhd < 0) {
1387 for (
i =
n - 1;
i >= 0;
i--) {
1446 return *(((
double *)
ybuffer) +
j);
1451static 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)
1490 std::string fn,
fnd,
fni;
1514 if (start_time == 0)
1541 if (
fh < 0 ||
fhd < 0 ||
fhi < 0) {
1591 if (
irec.time > start_time)
1598 if (
irec.time > start_time)
1617 if (
pirec->time > start_time)
1628 if (
pirec->time > start_time)
1647 irec.time = start_time;
1675 cm_msg(
MERROR,
"hs_read",
"corrupted history data at time %d", (
int)
irec.time);
1868 tms.tm_hour =
tms.tm_min =
tms.tm_sec = 0;
1885 if (
fh < 0 ||
fhd < 0 ||
fhi < 0) {
1919 }
while (
irec.time < end_time);
1959 std::string fn,
fnd,
fni;
1970 if (start_time == 0)
1978 cm_msg(
MERROR,
"hs_dump",
"cannot find recent history file");
1986 if (
fh < 0 ||
fhd < 0 ||
fhi < 0) {
1998 if (
irec.time > start_time)
2004 if (
irec.time > start_time)
2045 n_tag =
drec.data_size /
sizeof(
TAG);
2050 for (
i = 0;
i < n_tag;
i++) {
2054 for (
j = 0;
j < (
INT) tag[
i].n_data;
j++)
2089 for (
i = 0;
i < n_tag;
i++) {
2094 }
else if (tag[
i].n_data == 1) {
2101 for (
j = 0;
j < (
INT) tag[
i].n_data;
j++) {
2124 tms.tm_hour =
tms.tm_min =
tms.tm_sec = 0;
2140 if (
fh < 0 ||
fhd < 0 ||
fhi < 0) {
2153 }
while (
irec.time < end_time);
2165#ifndef DOXYGEN_SHOULD_SKIP_THIS
2181 for (
i=0, p=0;
names[p]!=0;
i++) {
2196 for (
i=0, p=0;
names[p]!=0;
i++) {
2256 printf(
"hs_connect: path [%s]\n", path);
2281 printf(
"hs_clear_cache!\n");
2305 for (
int i = 0;;
i++) {
2323 int size =
sizeof(
tmp);
2359 int size =
sizeof(
evid);
2368 cm_msg(
MERROR,
"add_event",
"History events \"%s\" and \"%s\" use the same history event id %d. If both equipments write to the history, their data will be mixed up. To fix this, enable per-variable history, turn off the \"MIDAS\" history (use \"FILE\" history) or change event IDs or set \"common/log history\" to zero", event_name,
xname.c_str(),
evid);
2398 cm_msg(
MERROR,
"AllocateEventId",
"Cannot allocate history event id - all in use - please examine /History/Events");
2427 cm_msg(
MERROR,
"add_event",
"Cannot delete /History/Tags, db_delete_key() status %d",
status);
2452 "Tag name \'%s\' in event %d (%s) may have been truncated to %d characters",
2479 cm_msg(
MINFO,
"add_event",
"Converting old event %d (%s) tags to new style",
event_id, event_name);
2491 for (
int i=0; ;
i++) {
2529 char* s = (
char*)
malloc(size);
2567 if ((tags[
i].
type!=t[
j].
type) || (tags[
i].n_data!=t[
j].n_data)) {
2568 cm_msg(
MINFO,
"add_event",
"Event %d (%s) tag \"%s\" type and size changed from %d[%d] to %d[%d]",
2572 tags[
i].
type, tags[
i].n_data);
2650 return ::hs_write_event(
event_id, (
void*)
data, data_size);
2674 for (
int i = 0;;
i++) {
2695 for (
unsigned i=0;
i<
events->size();
i++) {
2724 for (
int i = 0;;
i++) {
2760 for (
unsigned i=0;
i<
events->size();
i++) {
2787 printf(
"hs_get_events: reading events list!\n");
2814 for (
int i = 0;;
i++) {
2843 mstrlcpy(event_name, buf,
sizeof(event_name));
2884 for (
int i = 0;;
i++) {
2953 printf(
"xhs_event_id for event [%s], tag [%s]\n", event_name, tag_name);
2990 printf(
"hs_get_tags: get tags for event [%s] %d\n", event_name,
evid);
3000 ptags->push_back(tags[
i]);
3006 printf(
"hs_get_tags: get tags for event [%s] %d, found %d tags\n", event_name,
evid,
ntags);
3022 for (
int i = 0;;
i++) {
3058 for (
int j=0; ;
j++) {
3073 size =
sizeof(array);
3086 ptags->push_back(t);
3100 char* s =
strchr(buf,
'/');
3142 ptags->push_back(t);
3155 if (
ttt.size() == 0) {
3159 printf(
"hs_get_tags: reading tags for event [%s]\n", event_name);
3170 for (
unsigned i=0;
i<
ttt.size();
i++)
3181 last_written[
i] = 0;
3190 const char*
const event_name[],
const char*
const tag_name[],
const int var_index[],
3210 if (event_name[
i]==
NULL) {
3229 tag_name[
i], var_index[
i],
3303 num_entries[
i] =
n_vp;
3318 const char*
const event_name[],
const char*
const tag_name[],
const int var_index[],
3327 int status =
hs_read(start_time, end_time,
interval,
num_var, event_name, tag_name, var_index, num_entries,
time_buffer,
mean_buffer,
read_status);
3330 int num = num_entries[
i];
3335 for (
int j=0;
j<
num;
j++) {
3347 int num_var,
const char*
const event_name[],
const char*
const tag_name[],
const int var_index[],
3354 if (event_name[
i]==
NULL) {
3367 tag_name[
i], var_index[
i],
3384 int num_var,
const char*
const event_name[],
const char*
const tag_name[],
const int var_index[],
3428 num_var, event_name, tag_name, var_index,
3464#define HISTORY_PANEL(_name) const char *_name[] = {\
3466"Variables = STRING : [64] :",\
3467"Timescale = STRING : [32] 10m",\
3468"Zero ylow = BOOL : n",\
3469"Show run markers = BOOL : y",\
3470"Buttons = STRING[7] :",\
3478"Log axis = BOOL : n",\
3479"Show values = BOOL : y",\
3480"Sort vars = BOOL : n",\
3481"Show old vars = BOOL : n",\
3482"Minimum = FLOAT : -inf",\
3483"Maximum = FLOAT : inf",\
3484"Label = STRING : [32] ",\
3485"Colour = STRING : [32] ",\
3486"Formula = STRING : [64] ",\
3487"Show fill = BOOL : y",\
3498 const char *
color[] = {
3499 "#00AAFF",
"#FF9000",
"#FF00A0",
"#00C030",
3500 "#A0C0D0",
"#D0A060",
"#C04010",
"#807060",
3501 "#F0C000",
"#2090A0",
"#D040D0",
"#90B000",
3502 "#B0B040",
"#B0B0FF",
"#FFA0A0",
"#A0FFA0",
3515 for(
auto const& v:
var) {
3531 const std::vector<std::string> label,
const std::vector<std::string> formula,
3532 const std::vector<std::string>
color)
3539 "#00AAFF",
"#FF9000",
"#FF00A0",
"#00C030",
3540 "#A0C0D0",
"#D0A060",
"#C04010",
"#807060",
3541 "#F0C000",
"#2090A0",
"#D040D0",
"#90B000",
3542 "#B0B040",
"#B0B0FF",
"#FFA0A0",
"#A0FFA0",
3555 for(
auto const& v:
var) {
3559 if (
i < (
int)formula.size())
3565 if (
i < (
int)label.size())
3571 if (
i < (
int)
color.size())
virtual void Add(time_t time, double value)=0
char type[NAME_LENGTH]
history channel name
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
INT cm_get_experiment_semaphore(INT *semaphore_alarm, INT *semaphore_elog, INT *semaphore_history, INT *semaphore_msg)
#define DB_NO_MORE_SUBKEYS
#define HS_UNDEFINED_EVENT
static INT hs_open_file(time_t ltime, const char *suffix, INT mode, std::string *pfile_name, int *fh)
static std::vector< HISTORY * > _history
static int xread(const std::string &fn, int fh, void *buf, size_t count, bool eof_ok=false)
int GetEventsFromOdbTags(std::vector< std::string > *events)
static INT hs_enum_vars(DWORD ltime, DWORD event_id, char *var_name, DWORD *size, DWORD *var_n, DWORD *n_size)
MidasHistoryInterface * MakeMidasHistory()
static INT hs_search_file(DWORD *ltime, INT direction)
int 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
static bool xwrite(const std::string &fn, int fh, const void *buf, size_t count)
int hs_flush_buffers()
flush buffered data to storage where it is visible to mhttpd
int 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[])
static INT hs_define_event(DWORD event_id, const char *name, const TAG *tag, DWORD size)
static bool xtruncate(const std::string &fn, int fh, DWORD pos)
int hs_disconnect()
disconnect from history, returns HS_SUCCESS
int GetEventId(time_t t, const char *event_name, const char *tag_name, int *pevid)
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
static INT hs_count_vars(DWORD ltime, DWORD event_id, DWORD *count)
int hs_write_event(const char *event_name, time_t timestamp, int data_size, const char *data)
see hs_write_event(), returns HS_SUCCESS or HS_FILE_ERROR
int GetTagsFromOdb(const char *event_name, std::vector< TAG > *ptags)
static DWORD xcurpos(const std::string &fn, int fh)
int hs_set_debug(int debug)
set debug level, returns previous debug level
int hs_read_binned(time_t start_time, time_t end_time, int num_bins, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], int num_entries[], int *count_bins[], double *mean_bins[], double *rms_bins[], double *min_bins[], double *max_bins[], time_t *bins_first_time[], double *bins_first_value[], time_t *bins_last_time[], double *bins_last_value[], time_t last_time[], double last_value[], int read_status[])
returns HS_SUCCESS
INT hs_define_panel2(const char *group, const char *panel, const std::vector< std::string > var, const std::vector< std::string > label, const std::vector< std::string > formula, const std::vector< std::string > color)
INT hs_define_panel(const char *group, const char *panel, const std::vector< std::string > var)
int FindEventId(const char *event_name)
int GetEventsFromOdbEvents(std::vector< std::string > *events)
static INT hs_count_events(DWORD ltime, DWORD *count)
static INT hs_get_tags(DWORD ltime, DWORD event_id, char event_name[NAME_LENGTH], int *n_tags, TAG **tags)
int GetTagsFromHS(const char *event_name, std::vector< TAG > *ptags)
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...
int 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 begi...
static bool xseek_end(const std::string &fn, int fh)
std::vector< std::string > fEventsCache
#define HISTORY_PANEL(_name)
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_get_event_id(DWORD ltime, const char *name, DWORD *id)
static INT hs_enum_events(DWORD ltime, char *event_name, DWORD *name_size, INT event_id[], DWORD *id_size)
int hs_clear_cache()
clear internal cache, returns HS_SUCCESS
static bool xseek_cur(const std::string &fn, int fh, int offset)
double hs_to_double(int tid, const void *ybuffer)
static INT hs_get_var(DWORD ltime, DWORD event_id, const char *var_name, DWORD *type, INT *n_data)
static INT hs_gen_index(DWORD ltime)
int AllocateEventId(const char *event_name)
int CreateOdbTags(int event_id, const char *event_name, int ntags, const TAG tags[])
int GetEventIdFromHS(time_t ltime, const char *evname, const char *tagname)
std::map< std::string, std::vector< TAG > > fTagsCache
static INT hs_set_path(const char *path)
static INT hs_dump(DWORD event_id, DWORD start_time, DWORD end_time, DWORD interval, BOOL binary_time)
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
static bool xseek(const std::string &fn, int fh, DWORD pos)
int GetEventIdFromOdbTags(const char *evname, const char *tagname)
int hs_connect(const char *path)
returns HS_SUCCESS
static std::string _hs_path_name
static INT hs_write_event(DWORD event_id, const void *data, DWORD size)
std::map< std::string, int > fEvidCache
time_t ss_mktime(struct tm *tms)
INT ss_semaphore_release(HNDLE semaphore_handle)
INT ss_semaphore_wait_for(HNDLE semaphore_handle, DWORD timeout_millisec)
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
BOOL equal_ustring(const char *str1, const char *str2)
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
INT db_delete_key(HNDLE hDB, HNDLE hKey, BOOL follow_links)
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
std::string strcomb1(const char **list)
INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
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)
INT db_set_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
INT db_set_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
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)
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
BOOL debug
debug printouts
std::string msprintf(const char *format,...)
#define DIR_SEPARATOR_STR
#define write(n, a, f, d)
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)