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)
112 printf(
"->%s<-\n", y);
113 printf(
"=>%s<=\n", x.c_str());
177 "xxxINVALIDxxxARRAY",
178 "xxxINVALIDxxxSTRUCT",
189 if (tid>=0 && tid<15)
192 static char buf[1024];
193 sprintf(buf,
"TID_%d", tid);
206 for (
int tid=0; tid<15; tid++)
209 printf(
"sql2midasType: Cannot convert SQL data type \'%s\' to a MIDAS data type!\n",
name);
225 if (tid==
TID_FLOAT && strcmp(sqlType,
"double")==0)
230 if (tid==
TID_BYTE && strcmp(sqlType,
"tinyint")==0)
235 if (tid==
TID_WORD && strcmp(sqlType,
"tinyint")==0)
251typedef std::map<std::string, sqlite3*> DbMap;
268 int Connect(
const char* path);
272 int ConnectTable(
const char* table_name);
273 sqlite3* GetTable(
const char* table_name);
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);
280 int Step(sqlite3_stmt* st);
281 int Finalize(sqlite3_stmt** st);
283 int OpenTransaction(
const char* table_name);
284 int CloseTransaction(
const char* table_name);
286 const char* GetText(sqlite3_stmt* st,
int column);
287 int64_t GetInt64(sqlite3_stmt* st,
int column);
288 double GetDouble(sqlite3_stmt* st,
int column);
291const char* Sqlite::GetText(sqlite3_stmt* st,
int column)
293 return (
const char*)sqlite3_column_text(st, column);
296int64_t Sqlite::GetInt64(sqlite3_stmt* st,
int column)
298 return sqlite3_column_int64(st, column);
301double Sqlite::GetDouble(sqlite3_stmt* st,
int column)
303 return sqlite3_column_double(st, column);
308 fIsConnected =
false;
318const char* xsqlite3_errstr(sqlite3* db,
int errcode)
321 return sqlite3_errmsg(db);
324int Sqlite::ConnectTable(
const char* table_name)
326 std::string fname = fPath +
"/" +
"mh_" + table_name +
".sqlite3";
330 int status = sqlite3_open(fname.c_str(), &db);
332 if (
status != SQLITE_OK) {
333 cm_msg(
MERROR,
"Sqlite::Connect",
"Table %s: sqlite3_open(%s) error %d (%s)", table_name, fname.c_str(),
status, xsqlite3_errstr(db,
status));
339#if SQLITE_VERSION_NUMBER >= 3006020
340 status = sqlite3_extended_result_codes(db, 1);
341 if (
status != SQLITE_OK) {
342 cm_msg(
MERROR,
"Sqlite::Connect",
"Table %s: sqlite3_extended_result_codes(1) error %d (%s)", table_name,
status, xsqlite3_errstr(db,
status));
345#warning Missing sqlite3_extended_result_codes()!
348 fMap[table_name] = db;
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)
370 sqlite3* db = fMap[table_name];
375 int status = ConnectTable(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()
402 for (DbMap::iterator iter = fMap.begin(); iter != fMap.end(); ++iter) {
403 const char* table_name = iter->first.c_str();
404 sqlite3* db = iter->second;
405 int status = sqlite3_close(db);
406 if (
status != SQLITE_OK) {
407 cm_msg(
MERROR,
"Sqlite::Disconnect",
"sqlite3_close(%s) error %d (%s)", table_name,
status, xsqlite3_errstr(db,
status));
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)
437 sqlite3* db = GetTable(table_name);
442 printf(
"Sqlite::Prepare(%s, %s)\n", table_name, sql);
444 assert(fTempDB==NULL);
447#if SQLITE_VERSION_NUMBER >= 3006020
448 int status = sqlite3_prepare_v2(db, sql, strlen(sql), st, NULL);
450#warning Missing sqlite3_prepare_v2()!
451 int status = sqlite3_prepare(db, sql, strlen(sql), st, NULL);
457 std::string sqlstring = sql;
458 cm_msg(
MERROR,
"Sqlite::Prepare",
"Table %s: sqlite3_prepare_v2(%s...) error %d (%s)", table_name, sqlstring.substr(0,60).c_str(),
status, xsqlite3_errstr(db,
status));
465int Sqlite::Step(sqlite3_stmt* st)
468 printf(
"Sqlite::Step()\n");
472 int status = sqlite3_step(st);
474 if (
status == SQLITE_DONE)
485int Sqlite::Finalize(sqlite3_stmt** st)
488 printf(
"Sqlite::Finalize()\n");
492 int status = sqlite3_finalize(*st);
494 if (
status != SQLITE_OK) {
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;";
522 DIR *dir = opendir(fPath.c_str());
524 cm_msg(
MERROR,
"Sqlite::ListTables",
"Cannot opendir(%s), errno %d (%s)", fPath.c_str(), errno, strerror(errno));
529 const struct dirent*
de = readdir(dir);
533 const char* dn =
de->d_name;
540 s = strstr(dn,
"mh_");
544 s = strstr(dn,
".sqlite3");
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);
568 const char* tablename = GetText(st, 0);
570 plist->push_back(tablename);
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);
610 const char* colname = GetText(st, 1);
611 const char* coltype = GetText(st, 2);
613 plist->push_back(colname);
614 plist->push_back(coltype);
622static int callback_debug = 0;
624static int callback(
void *NotUsed,
int argc,
char **argv,
char **azColName){
625 if (callback_debug) {
626 printf(
"history_sqlite::callback---->\n");
627 for (
int i=0;
i<argc;
i++){
628 printf(
"history_sqlite::callback[%d] %s = %s\n",
i, azColName[
i], argv[
i] ? argv[
i] :
"NULL");
634int Sqlite::Exec(
const char* table_name,
const char* sql)
644 sqlite3* db = GetTable(table_name);
649 printf(
"Sqlite::Exec(%s, %s)\n", table_name, sql);
653 callback_debug = fDebug;
657 if (
status != SQLITE_OK) {
658 std::string sqlstring = sql;
659 cm_msg(
MERROR,
"Sqlite::Exec",
"Table %s: sqlite3_exec(%s...) error %d (%s)", table_name, sqlstring.substr(0,60).c_str(),
status, errmsg);
660 sqlite3_free(errmsg);
687 std::vector<Tag>
tags;
689 int transactionCount;
694 transactionCount = 0;
700 assert(transactionCount == 0);
706 for (
int i=0;
i<ntags;
i++)
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++) {
751 sprintf(s,
"unknownType%d", t->
tag.
type);
754 sprintf(s,
"%u",((uint8_t*)ptr)[
j]);
757 sprintf(s,
"%d",((int8_t*)ptr)[
j]);
760 sprintf(s,
"\'%c\'",((
char*)ptr)[
j]);
763 sprintf(s,
"%u",((uint16_t*)ptr)[
j]);
766 sprintf(s,
"%d",((int16_t*)ptr)[
j]);
769 sprintf(s,
"%u",((uint32_t*)ptr)[
j]);
772 sprintf(s,
"%d",((int32_t*)ptr)[
j]);
775 sprintf(s,
"%u",((uint32_t*)ptr)[
j]);
778 sprintf(s,
"\'%.8g\'",((
float*)ptr)[
j]);
781 sprintf(s,
"\'%.16g\'",((
double*)ptr)[
j]);
792 localtime_r(&t, &tms);
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++) {
837 if (isalpha(
c) || isdigit(
c))
856 std::vector<Event*> fEvents;
883 printf(
"hs_connect [%s]!\n", connect_string);
893 if (!connect_string || strlen(connect_string) < 1) {
895 connect_string =
".";
901 printf(
"hs_connect: connecting to SQL database \'%s\'\n",
fConnectString.c_str());
913 printf(
"hs_disconnect!\n");
924 std::string GetEventName(
const char* table_name)
929 cmd =
"SELECT event_name, _i_time FROM \'_event_name_";
931 cmd +=
"\' WHERE table_name='";
933 cmd +=
"' ORDER BY _i_time ASC;";
943 std::string xevent_name;
944 time_t xevent_time = 0;
957 xevent_time =
fSql->GetInt64(st, 1);
967 std::string GetTableName(
const char* event_name)
969 std::vector<std::string> tables;
974 for (
unsigned i=0;
i<tables.size();
i++) {
975 const char* tt = tables[
i].c_str();
977 const char *s = strstr(tt,
"_event_name");
981 const char* tn = tt + 12;
984 std::string xevent_name = GetEventName(tn);
986 if (strcmp(xevent_name.c_str(), event_name) == 0) {
999 cmd =
"SELECT column_name, tag_name, _i_time FROM \'_column_names_";
1001 cmd +=
"\' WHERE table_name='";
1003 cmd +=
"' ORDER BY _i_time ASC;";
1025 time_t xxx_time =
fSql->GetInt64(st, 2);
1028 (*ptag2col)[tag_name] = col_name;
1031 (*pcol2tag)[col_name] = tag_name;
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);
1063 if (fEvents[
i]->transactionCount > 0) {
1064 status =
fSql->CloseTransaction(fEvents[
i]->table_name.c_str());
1065 fEvents[
i]->transactionCount = 0;
1073 for (
int i=0;
i<ntags;
i++) {
1074 for (
int j=
i+1;
j<ntags;
j++) {
1075 if (strcmp(tags[
i].
name, tags[
j].
name) == 0) {
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;
1087 std::string table_name = GetTableName(event_name);
1089 if (table_name.length() < 1) {
1093 e->table_name = table_name;
1095 std::vector<std::string> columns;
1103 if (columns.size() > 0) {
1104 status = GetColumnNames(table_name.c_str(), &colnames, NULL);
1109 double now = time(NULL);
1115 if (columns.size() <= 0) {
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);";
1168 for (
int i=0;
i<ntags;
i++) {
1169 for (
unsigned int j=0;
j<tags[
i].
n_data;
j++) {
1170 int tagtype = tags[
i].
type;
1171 std::string tagname = tags[
i].
name;
1174 if (tags[
i].n_data > 1) {
1176 sprintf(s,
"[%d]",
j);
1179 sprintf(s,
"_%d",
j);
1183 std::string colname = colnames[tagname];
1185 if (colname.length() < 1) {
1187 colname = maybe_colname;
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);
1206 sprintf(s,
"_%d", rand());
1211 bool compatible =
true;
1213 for (
size_t k=0;
k<columns.size();
k+=2) {
1214 if (colname == columns[
k]) {
1230 sprintf(s,
"_%d", rand());
1241 if (colname != colnames[tagname]) {
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;
1263 bool column_exists =
false;
1264 for (
size_t k=0;
k<columns.size();
k+=2) {
1265 if (colname == columns[
k]) {
1266 column_exists =
true;
1271 if (!column_exists) {
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++)
1315 fEvents.push_back(
e);
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);
1328 for (
size_t i=0;
i<fEvents.size();
i++)
1329 if (fEvents[
i]->event_name == event_name) {
1363 printf(
"hs_flush_buffers!\n");
1365 for (
unsigned int i=0;
i<fEvents.size();
i++)
1367 if (fEvents[
i]->transactionCount > 0) {
1368 int xstatus =
fSql->CloseTransaction(fEvents[
i]->table_name.c_str());
1371 fEvents[
i]->transactionCount = 0;
1381 std::vector<std::string> fEventsCache;
1382 std::vector<std::string> fTablesCache;
1390 printf(
"hs_clear_cache!\n");
1392 fTablesCache.clear();
1393 fEventsCache.clear();
1394 fTableNamesCache.clear();
1395 fColumnsCache.clear();
1396 fColumnNamesCache.clear();
1401 void ReadTablesCache()
1404 printf(
"ReadTablesCache!\n");
1406 fTablesCache.clear();
1411 void ReadEventsCache()
1414 printf(
"ReadEventsCache!\n");
1416 if (fTablesCache.size() == 0)
1419 for (
unsigned i=0;
i<fTablesCache.size();
i++) {
1420 const char* tn = fTablesCache[
i].c_str();
1423 s = strstr(tn,
"_event_name_");
1426 s = strstr(tn,
"_column_names_");
1430 std::string en = GetEventName(tn);
1433 for (
unsigned j=0;
j<fEventsCache.size();
j++)
1434 if (fEventsCache[
j] == en) {
1439 fTableNamesCache[tn] = en;
1442 fEventsCache.push_back(en);
1446 void ReadColumnsCache(
const char* table_name)
1448 fColumnsCache[table_name].clear();
1451 fColumnNamesCache[table_name].clear();
1454 for (
unsigned i=0;
i<fColumnsCache[table_name].size();
i+=2) {
1455 const std::string cn = fColumnsCache[table_name][
i];
1456 fColumnNamesCache[table_name][cn] = cn;
1460 GetColumnNames(table_name, NULL, &fColumnNamesCache[table_name]);
1466 printf(
"hs_get_events!\n");
1468 if (fEventsCache.size() == 0) {
1473 *pevents = fEventsCache;
1478 int hs_get_tags(
const char* event_name, std::vector<TAG> *ptags)
1481 printf(
"hs_get_tags for [%s]\n", event_name);
1485 if (fEventsCache.size() == 0)
1488 bool not_found =
true;
1489 for (
unsigned i=0;
i<fTablesCache.size();
i++) {
1490 const std::string tn = fTablesCache[
i].c_str();
1491 const char* en = fTableNamesCache[tn].c_str();
1493 if (strcmp(tn.c_str(), event_name) != 0)
1494 if (strcmp(en, event_name) != 0)
1498 if (fColumnsCache[tn].size() == 0)
1499 ReadColumnsCache(tn.c_str());
1501 for (
unsigned int j=0;
j<fColumnsCache[tn].size();
j+=2) {
1502 const std::string cn = fColumnsCache[tn][
j];
1503 const std::string ct = fColumnsCache[tn][
j+1];
1504 if (cn ==
"_t_time")
1506 if (cn ==
"_i_time")
1509 const char* tagname = fColumnNamesCache[tn][cn].c_str();
1513 if (strlen(tagname) < 1)
1514 tagname = cn.c_str();
1518 for (
unsigned k=0;
k<ptags->size();
k++)
1519 if (strcmp((*ptags)[
k].
name, tagname) == 0) {
1526 mstrlcpy(t.
name, tagname,
sizeof(t.
name));
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++) {
1538 printf(
" tag[%d]: %s[%d] type %d\n",
i, (*ptags)[
i].
name, (*ptags)[
i].n_data, (*ptags)[
i].
type);
1551 XItem(
const char* tn,
const char* cn) : tableName(tn), columnName(cn) { };
1553 std::string tableName;
1554 std::string columnName;
1557 typedef std::vector<XItem> XItemVector;
1559 int FindItem(
const char*
const event_name,
const char*
const tag_name,
int tag_index, XItemVector* result)
1561 if (fEventsCache.size() == 0)
1566 bool newStyleEventName = (strchr(event_name,
'/')!=NULL);
1568 for (
unsigned i=0;
i<fTablesCache.size();
i++) {
1569 const char* tn = fTablesCache[
i].c_str();
1570 const char* en = fTableNamesCache[tn].c_str();
1576 if (strcmp(tn, event_name) == 0) {
1578 }
else if (strcmp(en, event_name) == 0) {
1580 }
else if (newStyleEventName) {
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) {
1604 if (tolower(event_name[
j]) != tolower(s[
j])) {
1614 if (fColumnNamesCache[tn].size() == 0)
1615 ReadColumnsCache(tn);
1617 for (
unsigned j=0;
j<fColumnsCache[tn].size();
j+=2) {
1618 const char* cn = fColumnsCache[tn][
j].c_str();
1619 const char*
name = fColumnNamesCache[tn][cn].c_str();
1620 if (strlen(
name) < 1)
1623 char alt_tag_name[1024];
1624 sprintf(alt_tag_name,
"%s[%d]", tag_name, tag_index);
1628 if (strcmp(cn, tag_name) != 0)
1629 if (strcmp(
name, tag_name) != 0)
1630 if (strcmp(
name, alt_tag_name) != 0)
1635 result->push_back(XItem(tn, cn));
1645 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[])
1647 double dstart_time = start_time;
1650 printf(
"hs_get_last_written: start time %.0f, num_var %d\n", dstart_time, num_var);
1653 for (
int i=0;
i<num_var;
i++) {
1654 last_written[
i] = 0;
1657 FindItem(event_name[
i], tag_name[
i], var_index[
i], &xitem);
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++) {
1662 printf(
" table [%s], column [%s]", xitem[
j].tableName.c_str(), xitem[
j].columnName.c_str());
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++) {
1709 time_t t =
fSql->GetInt64(st, 0);
1717 printf(
"count %d, t %d, v %f, tt %d\n",
k, (
int)t, v, (
int)tt);
1727 last_written[
i] = tt;
1731 printf(
"hs_get_last_written: start time %.0f, num_var %d\n", dstart_time, num_var);
1732 for (
int i=0;
i<num_var;
i++) {
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]);
1742 int hs_read_table(
double start_time,
double end_time,
1743 const std::string& tn,
1744 int num_var,
const XItemVector vvv[],
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++) {
1755 printf(
" table [%s], column [%s]", xitem[
j].tableName.c_str(), xitem[
j].columnName.c_str());
1760 if (xitem.size() < 1)
1767 std::string collist;
1769 for (
int i=0;
i<num_var;
i++) {
1770 for (
unsigned j=0;
j<vvv[
i].size();
j++) {
1771 if (vvv[
i][
j].tableName == tn) {
1772 colnames.push_back(vvv[
i][
j].columnName);
1773 colindex.push_back(
i);
1775 if (collist.length() > 0)
1777 collist += std::string(
"\"") + vvv[
i][
j].columnName +
"\"";
1782 int numcol = (int)colnames.size();
1785 printf(
"From table [%s]\n", tn.c_str());
1786 for (
int k=0;
k<numcol;
k++) {
1787 printf(
"read column [%s] var index [%d]\n", colnames[
k].c_str(), colindex[
k]);
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);
1831 time_t t =
fSql->GetInt64(st, 0);
1833 if (t < start_time || t > end_time)
1836 for (
int k=0;
k<numcol;
k++) {
1841 buffer[colindex[
k]]->
Add(t, v);
1847 for (
unsigned k=0;
k<colnames.size();
k++)
1851 printf(
"hs_read_table: read %d rows\n",
count);
1859 int num_var,
const char*
const event_name[],
const char*
const tag_name[],
const int tag_index[],
1864 printf(
"hs_read_buffer: %d variables\n", num_var);
1869 for (
int i=0;
i<num_var;
i++) {
1873 XItemVector vvv[num_var];
1876 for (
int i=0;
i<num_var;
i++) {
1878 if (event_name[
i]==NULL) {
1883 FindItem(event_name[
i], tag_name[
i], tag_index[
i], &vvv[
i]);
1885 for (
unsigned j=0;
j<vvv[
i].size();
j++) {
1887 for (
unsigned k=0;
k<ttt.size();
k++)
1888 if (ttt[
k] == vvv[
i][
j].tableName) {
1894 ttt.push_back(vvv[
i][
j].tableName);
1899 for (
int i=0;
i<num_var;
i++) {
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++) {
1902 printf(
" table [%s], column [%s]", vvv[
i][
j].tableName.c_str(), vvv[
i][
j].columnName.c_str());
1907 for (
unsigned k=0;
k<ttt.size();
k++)
1908 printf(
" %s", ttt[
k].c_str());
1912 for (
unsigned k=0;
k<ttt.size();
k++) {
1913 const std::string tn = ttt[
k].c_str();
1915 hs_read_table(start_time, end_time,
1943 ReadBuffer(time_t first_time, time_t
last_time, time_t interval)
1970 if (newalloc <= 1000)
1971 newalloc = wantalloc + 1000;
1984 void Add(time_t t,
double v)
1998 (*fTimeBuffer)[pos] = t;
1999 (*fDataBuffer)[pos] = v;
2001 (*fNumEntries) = pos + 1;
2015 int hs_read(time_t start_time, time_t end_time, time_t interval,
2017 const char*
const event_name[],
const char*
const tag_name[],
const int var_index[],
2019 time_t* time_buffer[],
double* data_buffer[],
2024 ReadBuffer** buffer =
new ReadBuffer*[num_var];
2027 for (
int i=0;
i<num_var;
i++) {
2028 buffer[
i] =
new ReadBuffer(start_time, end_time, interval);
2035 time_buffer[
i] = NULL;
2037 data_buffer[
i] = NULL;
2042 buffer[
i]->fNumEntries = &num_entries[
i];
2044 buffer[
i]->fTimeBuffer = &time_buffer[
i];
2046 buffer[
i]->fDataBuffer = &data_buffer[
i];
2050 num_var, event_name, tag_name, var_index,
2053 for (
int i=0;
i<num_var;
i++) {
2054 buffer[
i]->Finish();
2084 time_t *fLastTimePtr;
2085 double *fLastValuePtr;
2087 BinnedBuffer(time_t first_time, time_t
last_time,
int num_bins)
2091 fNumBins = num_bins;
2092 fFirstTime = first_time;
2095 fSum0 =
new double[num_bins];
2096 fSum1 =
new double[num_bins];
2097 fSum2 =
new double[num_bins];
2099 for (
int i=0;
i<num_bins;
i++) {
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];
2175 double mean = fSum1[
i]/num;
2176 double variance = fSum2[
i]/num-mean*mean;
2179 rms = sqrt(variance);
2193 int hs_read_binned(time_t start_time, time_t end_time,
int num_bins,
2194 int num_var,
const char*
const event_name[],
const char*
const tag_name[],
const int var_index[],
2196 int* count_bins[],
double* mean_bins[],
double* rms_bins[],
double* min_bins[],
double* max_bins[],
2197 time_t
last_time[],
double last_value[],
2202 BinnedBuffer** buffer =
new BinnedBuffer*[num_var];
2205 for (
int i=0;
i<num_var;
i++) {
2206 buffer[
i] =
new BinnedBuffer(start_time, end_time, num_bins);
2207 xbuffer[
i] = buffer[
i];
2210 buffer[
i]->fCount = count_bins[
i];
2212 buffer[
i]->fMean = mean_bins[
i];
2214 buffer[
i]->fRms = rms_bins[
i];
2216 buffer[
i]->fMin = min_bins[
i];
2218 buffer[
i]->fMax = max_bins[
i];
2222 buffer[
i]->fLastValuePtr = &last_value[
i];
2226 num_var, event_name, tag_name, var_index,
2230 for (
int i=0;
i<num_var;
i++) {
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)
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)