29typedef std::map<std::string, std::string>
StringMap;
57#define FREE(x) { if (x) free(x); (x) = NULL; }
61 const char*
sign =
"";
105 printf(
"SmallIntToString: %d -> %s\n",
ii, v.c_str());
110static void xcmp(
const std::string& x,
const char* y)
113 printf(
"=>%s<=\n", x.c_str());
177 "xxxINVALIDxxxARRAY",
178 "xxxINVALIDxxxSTRUCT",
189 if (tid>=0 && tid<15)
192 static char buf[1024];
206 for (
int tid=0; tid<15; tid++)
209 printf(
"sql2midasType: Cannot convert SQL data type \'%s\' to a MIDAS data type!\n",
name);
251typedef std::map<std::string, sqlite3*>
DbMap;
268 int Connect(
const char* path);
275 int ListTables(std::vector<std::string> *
plist);
276 int ListColumns(
const char* table_name, std::vector<std::string> *
plist);
278 int Exec(
const char* table_name,
const char* sql);
279 int Prepare(
const char* table_name,
const char* sql,
sqlite3_stmt**
st);
283 int OpenTransaction(
const char* table_name);
308 fIsConnected =
false;
324int Sqlite::ConnectTable(
const char* table_name)
326 std::string
fname = fPath +
"/" +
"mh_" + table_name +
".sqlite3";
339#if SQLITE_VERSION_NUMBER >= 3006020
345#warning Missing sqlite3_extended_result_codes()!
350 Exec(table_name,
"PRAGMA journal_mode=persist;");
351 Exec(table_name,
"PRAGMA synchronous=normal;");
353 Exec(table_name,
"PRAGMA journal_size_limit=-1;");
356 Exec(table_name,
"PRAGMA legacy_file_format;");
357 Exec(table_name,
"PRAGMA synchronous;");
358 Exec(table_name,
"PRAGMA journal_mode;");
359 Exec(table_name,
"PRAGMA journal_size_limit;");
363 cm_msg(
MINFO,
"Sqlite::Connect",
"Table %s: connected to Sqlite file \'%s\'", table_name,
fname.c_str());
368sqlite3* Sqlite::GetTable(
const char* table_name)
379 return fMap[table_name];
382int Sqlite::Connect(
const char* path)
390 cm_msg(
MINFO,
"Sqlite::Connect",
"Connected to Sqlite database in \'%s\'", path);
397int Sqlite::Disconnect()
403 const char* table_name =
iter->first.c_str();
413 fIsConnected =
false;
418bool Sqlite::IsConnected()
423int Sqlite::OpenTransaction(
const char* table_name)
425 int status = Exec(table_name,
"BEGIN TRANSACTION");
429int Sqlite::CloseTransaction(
const char* table_name)
431 int status = Exec(table_name,
"COMMIT TRANSACTION");
435int Sqlite::Prepare(
const char* table_name,
const char* sql,
sqlite3_stmt**
st)
442 printf(
"Sqlite::Prepare(%s, %s)\n", table_name, sql);
447#if SQLITE_VERSION_NUMBER >= 3006020
450#warning Missing sqlite3_prepare_v2()!
468 printf(
"Sqlite::Step()\n");
488 printf(
"Sqlite::Finalize()\n");
510int Sqlite::ListTables(std::vector<std::string> *
plist)
516 printf(
"Sqlite::ListTables at path [%s]\n", fPath.c_str());
520 const char* cmd =
"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;";
533 const char*
dn =
de->d_name;
548 char table_name[256];
549 mstrlcpy(table_name,
dn+3,
sizeof(table_name));
550 char*
ss =
strstr(table_name,
".sqlite3");
559 status = Prepare(table_name, cmd, &
st);
582int Sqlite::ListColumns(
const char* table, std::vector<std::string> *
plist)
588 printf(
"Sqlite::ListColumns for table \'%s\'\n", table);
591 cmd =
"PRAGMA table_info(";
601 status = Prepare(table, cmd.c_str(), &
st);
626 printf(
"history_sqlite::callback---->\n");
634int Sqlite::Exec(
const char* table_name,
const char* sql)
649 printf(
"Sqlite::Exec(%s, %s)\n", table_name, sql);
687 std::vector<Tag>
tags;
714 const char* table_name =
e->table_name.c_str();
716 int n =
e->tags.size();
724 for (
int i=0;
i<
n;
i++) {
725 const Tag*t = &
e->tags[
i];
729 void* ptr = (
void*)(buf+
offset);
733 for (
int j=0;
j<arraySize;
j++) {
760 sprintf(s,
"\'%c\'",((
char*)ptr)[
j]);
778 sprintf(s,
"\'%.8g\'",((
float*)ptr)[
j]);
781 sprintf(s,
"\'%.16g\'",((
double*)ptr)[
j]);
794 strftime(s,
sizeof(s)-1,
"%Y-%m-%d %H:%M:%S.0",&
tms);
797 cmd =
"INSERT INTO \'";
799 cmd +=
"\' (_t_time, _i_time";
801 cmd +=
") VALUES (\'";
809 if (
e->transactionCount == 0)
810 sql->OpenTransaction(table_name);
812 e->transactionCount++;
814 int status = sql->Exec(table_name, cmd.c_str());
816 if (
e->transactionCount > 100000) {
818 sql->CloseTransaction(table_name);
819 e->transactionCount = 0;
835 for (
int i=0; s[
i]!=0;
i++) {
913 printf(
"hs_disconnect!\n");
929 cmd =
"SELECT event_name, _i_time FROM \'_event_name_";
931 cmd +=
"\' WHERE table_name='";
933 cmd +=
"' ORDER BY _i_time ASC;";
969 std::vector<std::string>
tables;
974 for (
unsigned i=0;
i<
tables.size();
i++) {
977 const char *s =
strstr(
tt,
"_event_name");
981 const char*
tn =
tt + 12;
999 cmd =
"SELECT column_name, tag_name, _i_time FROM \'_column_names_";
1001 cmd +=
"\' WHERE table_name='";
1003 cmd +=
"' ORDER BY _i_time ASC;";
1034 printf(
"read table [%s] column [%s] tag name [%s] time %d\n", table_name,
col_name.c_str(), tag_name.c_str(), (
int)
xxx_time);
1051 printf(
"hs_define_event: event name [%s] with %d tags\n", event_name,
ntags);
1057 for (
unsigned int i=0;
i<
fEvents.size();
i++)
1059 if (
fEvents[
i]->event_name == event_name) {
1061 printf(
"deleting exising event %s\n", event_name);
1076 cm_msg(
MERROR,
"hs_define_event",
"Error: History event \'%s\' has duplicate tag name \'%s\' at indices %d and %d", event_name, tags[
i].
name,
i,
j);
1085 e->event_name = event_name;
1089 if (table_name.length() < 1) {
1093 e->table_name = table_name;
1095 std::vector<std::string>
columns;
1120 cmd =
"CREATE TABLE \'";
1121 cmd +=
e->table_name;
1122 cmd +=
"\' (_t_time TIMESTAMP NOT NULL, _i_time INTEGER NOT NULL);";
1126 cmd =
"CREATE INDEX \'";
1127 cmd +=
e->table_name;
1128 cmd +=
"_i_time_index\' ON \'";
1129 cmd +=
e->table_name;
1130 cmd +=
"\' (_i_time ASC);";
1134 cmd =
"CREATE INDEX \'";
1135 cmd +=
e->table_name;
1136 cmd +=
"_t_time_index\' ON \'";
1137 cmd +=
e->table_name;
1138 cmd +=
"\' (_t_time);";
1142 cmd =
"CREATE TABLE \'_event_name_";
1143 cmd +=
e->table_name;
1144 cmd +=
"\' (table_name TEXT NOT NULL, event_name TEXT NOT NULL, _i_time INTEGER NOT NULL);";
1148 cmd =
"INSERT INTO \'_event_name_";
1149 cmd +=
e->table_name;
1150 cmd +=
"\' (table_name, event_name, _i_time) VALUES (\'";
1151 cmd +=
e->table_name;
1153 cmd +=
e->event_name;
1160 cmd =
"CREATE TABLE \'_column_names_";
1161 cmd +=
e->table_name;
1162 cmd +=
"\' (table_name TEXT NOT NULL, column_name TEXT NOT NULL, tag_name TEXT NOT NULL, tag_type TEXT NOT NULL, column_type TEXT NOT NULL, _i_time INTEGER NOT NULL);";
1169 for (
unsigned int j=0;
j<tags[
i].
n_data;
j++) {
1174 if (tags[
i].n_data > 1) {
1195 for (
unsigned k=0;
k<
e->tags.size();
k++) {
1196 if (
colname ==
e->tags[
k].column_name) {
1197 printf(
"hs_define_event: event [%s] tag [%s] duplicate column name [%s] with tag [%s]\n", event_name,
tagname.c_str(),
colname.c_str(),
e->tags[
k].tag.name);
1243 cmd =
"INSERT INTO \'_column_names_";
1244 cmd +=
e->table_name;
1245 cmd +=
"\' (table_name, column_name, tag_name, tag_type, column_type, _i_time) VALUES (\'";
1246 cmd +=
e->table_name;
1273 cmd =
"ALTER TABLE \'";
1274 cmd +=
e->table_name;
1275 cmd +=
"\' ADD COLUMN \'";
1294 e->tags.push_back(t);
1300 status =
fSql->CloseTransaction(
e->table_name.c_str());
1306 for (
unsigned int i=0;
i<
fEvents.size();
i++)
1320 int hs_write_event(
const char* event_name,
time_t timestamp,
int buffer_size,
const char* buffer)
1323 printf(
"hs_write_event: write event \'%s\', time %d, size %d\n", event_name, (
int)timestamp, buffer_size);
1329 if (
fEvents[
i]->event_name == event_name) {
1363 printf(
"hs_flush_buffers!\n");
1365 for (
unsigned int i=0;
i<
fEvents.size();
i++)
1381 std::vector<std::string> fEventsCache;
1390 printf(
"hs_clear_cache!\n");
1393 fEventsCache.clear();
1404 printf(
"ReadTablesCache!\n");
1414 printf(
"ReadEventsCache!\n");
1433 for (
unsigned j=0;
j<fEventsCache.size();
j++)
1434 if (fEventsCache[
j] ==
en) {
1442 fEventsCache.push_back(
en);
1466 printf(
"hs_get_events!\n");
1468 if (fEventsCache.size() == 0) {
1481 printf(
"hs_get_tags for [%s]\n", event_name);
1485 if (fEventsCache.size() == 0)
1493 if (
strcmp(
tn.c_str(), event_name) != 0)
1504 if (
cn ==
"_t_time")
1506 if (
cn ==
"_i_time")
1518 for (
unsigned k=0;
k<
ptags->size();
k++)
1530 ptags->push_back(t);
1536 printf(
"hs_get_tags: %d tags\n", (
int)
ptags->size());
1537 for (
unsigned i=0;
i<
ptags->size();
i++) {
1561 if (fEventsCache.size() == 0)
1578 }
else if (
strcmp(
en, event_name) == 0) {
1587 for (
int j=0; s[
j];
j++) {
1589 if ((event_name[
j]==0) && (s[
j]==
'/')) {
1594 if ((event_name[
j]==0) && (s[
j]==
'_')) {
1599 if (event_name[
j]==0) {
1654 last_written[
i] = 0;
1660 printf(
"For event [%s] tag [%s] index [%d] found %d entries: ", event_name[
i], tag_name[
i], var_index[
i], (
int)
xitem.size());
1661 for (
unsigned j=0;
j<
xitem.size();
j++) {
1667 if (
xitem.size() < 1)
1672 for (
unsigned j=0;
j<
xitem.size();
j++) {
1673 const char*
tn =
xitem[
j].tableName.c_str();
1674 const char*
cn =
xitem[
j].columnName.c_str();
1677 cmd =
"SELECT _i_time, \"";
1679 cmd +=
"\" FROM \'";
1681 cmd +=
"\' WHERE _i_time <= ";
1683 cmd +=
" ORDER BY _i_time DESC LIMIT 2;";
1690 printf(
"hs_get_last_written: event \"%s\", tag \"%s\", index %d: Read table \"%s\" column \"%s\": status %d\n",
1691 event_name[
i], tag_name[
i], var_index[
i],
1704 for (
int k=0; ;
k++) {
1717 printf(
"count %d, t %d, v %f, tt %d\n",
k, (
int)t, v, (
int)
tt);
1727 last_written[
i] =
tt;
1733 printf(
" event [%s] tag [%s] index [%d] last_written %d\n", event_name[
i], tag_name[
i], var_index[
i], (
int)last_written[
i]);
1743 const std::string&
tn,
1749 printf(
"hs_read_table: table [%s], start %f, end %f, dt %f\n",
tn.c_str(), start_time, end_time, end_time-start_time);
1753 printf(
"For event [%s] tag [%s] index [%d] found %d entries: ", event_name, tag_name,
tag_index, (
int)
xitem.size());
1754 for (
unsigned j=0;
j<
xitem.size();
j++) {
1760 if (
xitem.size() < 1)
1770 for (
unsigned j=0;
j<
vvv[
i].size();
j++) {
1777 collist += std::string(
"\"") +
vvv[
i][
j].columnName +
"\"";
1785 printf(
"From table [%s]\n",
tn.c_str());
1792 cmd +=
"SELECT _i_time, ";
1796 cmd +=
"\' WHERE _i_time>=";
1798 cmd +=
" and _i_time<=";
1800 cmd +=
" ORDER BY _i_time;";
1803 printf(
"hs_read_table: cmd %s\n", cmd.c_str());
1811 printf(
"hs_read_table: Read table \"%s\" columns \"%s\": status %d\n",
tn.c_str(),
collist.c_str(),
status);
1859 int num_var,
const char*
const event_name[],
const char*
const tag_name[],
const int tag_index[],
1878 if (event_name[
i]==
NULL) {
1885 for (
unsigned j=0;
j<
vvv[
i].size();
j++) {
1887 for (
unsigned k=0;
k<
ttt.size();
k++)
1900 printf(
"For event [%s] tag [%s] index [%d] found %d entries: ", event_name[
i], tag_name[
i],
tag_index[
i], (
int)
vvv[
i].size());
1901 for (
unsigned j=0;
j<
vvv[
i].size();
j++) {
1907 for (
unsigned k=0;
k<
ttt.size();
k++)
1912 for (
unsigned k=0;
k<
ttt.size();
k++) {
1913 const std::string
tn =
ttt[
k].c_str();
1998 (*fTimeBuffer)[pos] = t;
1999 (*fDataBuffer)[pos] = v;
2001 (*fNumEntries) = pos + 1;
2017 const char*
const event_name[],
const char*
const tag_name[],
const int var_index[],
2024 ReadBuffer** buffer =
new ReadBuffer*[
num_var];
2028 buffer[
i] =
new ReadBuffer(start_time, end_time,
interval);
2042 buffer[
i]->fNumEntries = &num_entries[
i];
2050 num_var, event_name, tag_name, var_index,
2054 buffer[
i]->Finish();
2085 double *fLastValuePtr;
2109 fLastTimePtr =
NULL;
2110 fLastValuePtr =
NULL;
2120 void Add(
time_t t,
double v)
2129 double a = t - fFirstTime;
2130 double b = fLastTime - fFirstTime;
2131 double fbin = fNumBins*a/b;
2137 else if (
ibin >= fNumBins)
2140 if (fSum0[
ibin] == 0) {
2164 if (t > *fLastTimePtr) {
2173 for (
int i=0;
i<fNumBins;
i++) {
2174 double num = fSum0[
i];
2194 int num_var,
const char*
const event_name[],
const char*
const tag_name[],
const int var_index[],
2226 num_var, event_name, tag_name, var_index,
2231 buffer[
i]->Finish();
virtual void Add(time_t time, double value)=0
char type[NAME_LENGTH]
history channel name
void Add(time_t t, double v)
void Realloc(int wantalloc)
std::vector< HsSchema * > fEvents
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_write_event(const char *event_name, time_t timestamp, int buffer_size, const char *buffer)
see hs_write_event(), returns HS_SUCCESS or HS_FILE_ERROR
int hs_read_buffer(time_t start_time, time_t end_time, int num_var, const char *const event_name[], const char *const var_name[], const int var_index[], MidasHistoryBufferInterface *buffer[], int hs_status[])
returns HS_SUCCESS
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
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 var_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 st[])
returns HS_SUCCESS
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...
int hs_get_last_written(time_t timestamp, int num_var, const char *const event_name[], const char *const var_name[], const int var_index[], time_t last_written[])
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 var_name[], const int var_index[], int num_entries[], time_t *time_buffer[], double *data_buffer[], int st[])
see hs_read(), returns HS_SUCCESS
int hs_clear_cache()
clear internal cache, returns HS_SUCCESS
std::string fConnectString
int hs_flush_buffers()
flush buffered data to storage where it is visible to mhttpd
virtual int ListColumns(const char *table, std::vector< std::string > *plist)=0
virtual double GetDouble(int column)=0
virtual bool IsConnected()=0
virtual int ListTables(std::vector< std::string > *plist)=0
virtual int Disconnect()=0
virtual int Prepare(const char *table_name, const char *sql)=0
virtual int Exec(const char *sql)=0
virtual int Connect(const char *dsn=0)=0
virtual const char * GetText(int column)=0
virtual int OpenTransaction(const char *table_name)=0
int hs_disconnect()
disconnect from history, returns HS_SUCCESS
int hs_set_debug(int debug)
set debug level, returns previous debug level
int hs_connect(const char *connect_string)
returns HS_SUCCESS
#define DB_NO_MORE_SUBKEYS
#define HS_UNDEFINED_EVENT
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
static std::string MidasNameToSqlName(const char *s)
int WriteEvent(SqlBase *sql, Event *e, time_t t, const char *buf, int size)
static const int tid_size[]
static int sql2midasType(const char *name)
static const char * midasTypeName(int tid)
static bool isCompatible(int tid, const char *sqlType)
static const char * tid_name[]
static void PrintTags(int ntags, const TAG tags[])
static const char * midas2sqlType(int tid)
static const char ** sql_type
static std::string MidasNameToSqlName(const char *s)
static std::string TimeToString(time_t t)
static void PrintTags(int ntags, const TAG tags[])
static std::string SmallIntToString(int i)
std::map< std::string, StringMap > StringMapMap
MidasHistoryInterface * MakeMidasHistorySqlite()
std::vector< int > IntVector
std::vector< std::string > StringVector
std::map< std::string, std::string > StringMap
std::map< std::string, StringVector > StringVectorMap
BOOL debug
debug printouts
struct callback_addr callback
BOOL match(char *pat, char *str)
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)