MIDAS
Loading...
Searching...
No Matches
SqlHistory Class Reference
Inheritance diagram for SqlHistory:
Collaboration diagram for SqlHistory:

Public Member Functions

 SqlHistory (SqlBase *b)
 
 ~SqlHistory ()
 
int hs_set_debug (int debug)
 set debug level, returns previous debug level
 
int hs_connect (const char *connect_string)
 returns HS_SUCCESS
 
int hs_disconnect ()
 disconnect from history, returns HS_SUCCESS
 
int Reconnect ()
 
int hs_clear_cache ()
 clear internal cache, returns HS_SUCCESS
 
int XReadIndex ()
 
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_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_flush_buffers ()
 flush buffered data to storage where it is visible to mhttpd
 
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 beginning of time"), returns HS_SUCCESS
 
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 exist(ed) at given time and later (value 0 means "all variables for this event that ever existed"), also see hs_get_tags(), returns HS_SUCCESS
 
int 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 hs_read_old_style (double start_time, double end_time, double interval, const char *event_name, const char *tag_name, int var_index, int *num_entries, time_t **time_buffer, double **data_buffer)
 
int hs_read (double start_time, double end_time, double interval, const char *event_name, const char *tag_name, int tag_index, int *num_entries, time_t **time_buffer, double **data_buffer)
 
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 tag_index[], int num_entries[], time_t *time_buffer[], double *data_buffer[], int st[])
 see hs_read(), returns HS_SUCCESS
 
int hs_read2 (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 *mean_buffer[], double *rms_buffer[], double *min_buffer[], double *max_buffer[], int read_status[])
 
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 status[])
 returns HS_SUCCESS
 
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 status[])
 returns HS_SUCCESS
 
- Public Member Functions inherited from MidasHistoryInterface
 MidasHistoryInterface ()
 history type: MIDAS, ODBC, SQLITE, etc
 
virtual ~MidasHistoryInterface ()
 

Public Attributes

SqlBasefSql
 
int fDebug
 
std::string fConnectString
 
int fConnectRetry
 
int fNextConnect
 
std::vector< Event * > fEvents
 
std::vector< std::string > fIndexEvents
 
bool fHaveIndex
 
bool fHaveXIndex
 
- Public Attributes inherited from MidasHistoryInterface
char name [NAME_LENGTH]
 
char type [NAME_LENGTH]
 history channel name
 

Detailed Description

Definition at line 1169 of file history_odbc.cxx.

Constructor & Destructor Documentation

◆ SqlHistory()

SqlHistory::SqlHistory ( SqlBase b)
inline

Definition at line 1182 of file history_odbc.cxx.

1183 {
1184 fDebug = 0;
1185 fConnectRetry = 0;
1186 fNextConnect = 0;
1187 fSql = b;
1188 fHaveIndex = false;
1189 fHaveXIndex = false;
1190 }
SqlBase * fSql

◆ ~SqlHistory()

SqlHistory::~SqlHistory ( )
inline

Definition at line 1192 of file history_odbc.cxx.

1193 {
1194 hs_disconnect();
1195 delete fSql;
1196 fSql = NULL;
1197 }
int hs_disconnect()
disconnect from history, returns HS_SUCCESS
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24
Here is the call graph for this function:

Member Function Documentation

◆ hs_clear_cache()

int SqlHistory::hs_clear_cache ( )
inlinevirtual

clear internal cache, returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 1276 of file history_odbc.cxx.

1277 {
1278 if (fDebug)
1279 printf("hs_clear_cache!\n");
1280
1281 gHaveIndex = true;
1282 gHaveIndexAll = false;
1283 fHaveXIndex = false;
1284
1285 for (unsigned i=0; i<gHistoryIndex.size(); i++) {
1287 delete ie;
1288 }
1289 gHistoryIndex.clear();
1290
1291 fIndexEvents.clear();
1292
1293 return HS_SUCCESS;
1294 }
std::vector< std::string > fIndexEvents
#define HS_SUCCESS
Definition midas.h:727
static int gHaveIndexAll
static int gHaveIndex
static std::vector< IndexEntry * > gHistoryIndex
INT i
Definition mdump.cxx:32
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_connect()

int SqlHistory::hs_connect ( const char connect_string)
inlinevirtual

returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 1208 of file history_odbc.cxx.

1209 {
1210 if (fDebug)
1211 printf("hs_connect %s!\n", connect_string);
1212
1213 assert(fSql);
1214
1215 if (fSql->IsConnected())
1216 if (strcmp(fConnectString.c_str(), connect_string) == 0)
1217 return HS_SUCCESS;
1218
1219 hs_disconnect();
1220
1222
1223 if (fDebug)
1224 printf("hs_connect: connecting to SQL database \'%s\'\n", fConnectString.c_str());
1225
1226 int status = fSql->Connect(fConnectString.c_str());
1227 if (status != DB_SUCCESS)
1228 return status;
1229
1230 std::vector<std::string> tables;
1231
1233 if (status != DB_SUCCESS)
1234 return status;
1235
1236 for (unsigned i=0; i<tables.size(); i++) {
1237 if (tables[i] == "_history_index") {
1238 fHaveIndex = true;
1239 break;
1240 }
1241 }
1242
1243 return HS_SUCCESS;
1244 }
virtual bool IsConnected()=0
virtual int ListTables(std::vector< std::string > *plist)=0
virtual int Connect(const char *dsn=0)=0
std::string fConnectString
#define DB_SUCCESS
Definition midas.h:631
DWORD status
Definition odbhist.cxx:39
Here is the call graph for this function:

◆ hs_define_event()

int SqlHistory::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 1357 of file history_odbc.cxx.

1358 {
1359 int status;
1360
1361 if (fDebug) {
1362 printf("define event [%s] with %d tags:\n", event_name, ntags);
1363 PrintTags(ntags, tags);
1364 }
1365
1366 // delete all events with the same name
1367 for (unsigned int i=0; i<fEvents.size(); i++)
1368 if (fEvents[i])
1369 if (fEvents[i]->event_name == event_name) {
1370 if (fDebug)
1371 printf("deleting exising event %s\n", event_name);
1372 delete fEvents[i];
1373 fEvents[i] = NULL;
1374 }
1375
1376 Event* e = new Event();
1377
1378 e->event_name = event_name;
1379
1380 if (!fHaveIndex) {
1381 char buf[1024];
1382 sprintf(buf, "CREATE TABLE _history_index (event_name VARCHAR(256) NOT NULL, table_name VARCHAR(256), tag_name VARCHAR(256), column_name VARCHAR(256), itimestamp INTEGER NOT NULL);");
1383 int status = fSql->Exec(buf);
1384 if (status == DB_KEY_EXIST)
1385 /* do nothing */ ;
1386 else if (status != DB_SUCCESS)
1387 return status;
1388 fHaveIndex = true;
1389 }
1390
1391 IndexEntry* ie = FindIndexByEventName(event_name);
1392
1393 if (!ie) {
1394 ReadIndex(fSql, event_name);
1395 ie = FindIndexByEventName(event_name);
1396 }
1397
1398 if (!ie) {
1399 std::string table_name = MidasNameToSqlName(event_name);
1400
1401 char sss[102400];
1402 sprintf(sss, "INSERT INTO _history_index (event_name, table_name, itimestamp) VALUES (\'%s\', \'%s\', \'%.0f\');",
1403 event_name,
1404 table_name.c_str(),
1405 (double)timestamp);
1406
1407 int status = fSql->Exec(sss);
1408 if (status != DB_SUCCESS)
1409 return HS_FILE_ERROR;
1410
1411 ReadIndex(fSql, event_name);
1412 ie = FindIndexByEventName(event_name);
1413 }
1414
1415 if (!ie) {
1416 cm_msg(MERROR, "hs_define_event", "could not add event name to SQL history index table, see messages");
1417 return HS_FILE_ERROR;
1418 }
1419
1420 e->table_name = ie->table_name;
1421 e->active = true;
1422
1423 bool create_event = false;
1424
1425 int offset = 0;
1426 for (int i=0; i<ntags; i++) {
1427 for (unsigned int j=0; j<tags[i].n_data; j++) {
1428 std::string tagname = tags[i].name;
1429 std::string colname = MidasNameToSqlName(tags[i].name);
1430
1431 if (tags[i].n_data > 1) {
1432 char s[256];
1433 sprintf(s, "[%d]", j);
1434 tagname += s;
1435
1436 sprintf(s, "_%d", j);
1437 colname += s;
1438 }
1439
1441 if (!it) {
1442 // check for duplicate names
1443
1444 while (1) {
1445 bool dupe = false;
1446
1447 for (unsigned i=0; i<e->tags.size(); i++) {
1448 if (colname == e->tags[i].column_name) {
1449 //printf("duplicate name %s\n", colname.c_str());
1450 dupe = true;
1451 break;
1452 }
1453 }
1454
1455 if (!dupe)
1456 break;
1457
1458 char s[256];
1459 sprintf(s, "_%d", rand());
1460 colname += s;
1461 }
1462
1463 // add tag name to column name translation to the history index
1464
1465 char sss[102400];
1466 sprintf(sss, "INSERT INTO _history_index (event_name, tag_name, column_name, itimestamp) VALUES (\'%s\', \'%s\', \'%s\', \'%.0f\');",
1467 event_name,
1468 tagname.c_str(),
1469 colname.c_str(),
1470 (double)timestamp);
1471
1472 int status = fSql->Exec(sss);
1473 if (status != DB_SUCCESS)
1474 return HS_FILE_ERROR;
1475
1476 // reload the history index
1477
1478 ReadIndex(fSql, event_name);
1479 ie = FindIndexByEventName(event_name);
1480 assert(ie);
1481 it = FindIndexByTagName(ie, tagname.c_str());
1482 }
1483
1484 if (!it) {
1485 cm_msg(MERROR, "hs_define_event", "could not add event tags to SQL history index table, see messages");
1486 return HS_FILE_ERROR;
1487 }
1488
1489 Tag t;
1490 t.column_name = it->column_name;
1491 t.create = false;
1492 t.offset = offset;
1493 t.tag = tags[i];
1494 t.tag.n_data = 1;
1495 e->tags.push_back(t);
1496 int size = tid_size[tags[i].type];
1497 offset += size;
1498 }
1499 }
1500
1501 std::vector<std::string> columns;
1502
1503 status = fSql->ListColumns(e->table_name.c_str(), &columns);
1504 if (status != DB_SUCCESS)
1505 return status;
1506
1507 if (columns.size() <= 0)
1508 create_event = true;
1509
1510 for (unsigned i=0; i<e->tags.size(); i++) {
1511 // check for duplicate column names
1512 for (unsigned j=i+1; j<e->tags.size(); j++)
1513 if (e->tags[i].column_name == e->tags[j].column_name) {
1514 cm_msg(MERROR, "hs_define_event", "Error: History event \'%s\': Duplicated column name \'%s\' from tags %d \'%s\' and %d \'%s\'", event_name, e->tags[i].column_name.c_str(), i, e->tags[i].tag.name, j, e->tags[j].tag.name);
1515 e->active = false;
1516 break;
1517 }
1518
1519 // check if new column needs to be created
1520 bool found = false;
1521 for (size_t j=0; j<columns.size(); j+=2) {
1522 if (e->tags[i].column_name == columns[j]) {
1523 // column exists, check data type
1524 //printf("column \'%s\', data type %s\n", e->tags[i].column_name.c_str(), columns[j+1].c_str());
1525
1526 if (!isCompatible(e->tags[i].tag.type, columns[j+1].c_str())) {
1527 cm_msg(MERROR, "hs_define_event", "Error: History event \'%s\': Incompatible data type for tag \'%s\' type \'%s\', SQL column \'%s\' type \'%s\'", event_name, e->tags[i].tag.name, midasTypeName(e->tags[i].tag.type), columns[j].c_str(), columns[j+1].c_str());
1528 e->active = false;
1529 }
1530
1531 found = true;
1532 break;
1533 }
1534 }
1535
1536 if (!found) {
1537 // create it
1538 //printf("column \'%s\', data type %s --- create!\n", e->tags[i].column_name.c_str(), midasTypeName(e->tags[i].tag.type));
1539 e->tags[i].create = true;
1540 }
1541 }
1542
1543 if (create_event) {
1544 char buf[1024];
1545 sprintf(buf, "CREATE TABLE %s (_t_time TIMESTAMP NOT NULL, _i_time INTEGER NOT NULL, INDEX (_i_time), INDEX (_t_time));", e->table_name.c_str());
1546 status = fSql->Exec(buf);
1547 if (status != DB_SUCCESS) {
1548 e->active = false;
1549 return HS_FILE_ERROR;
1550 }
1551 }
1552
1553 for (size_t i=0; i<e->tags.size(); i++)
1554 if (e->tags[i].create) {
1555 char buf[1024];
1556
1557 sprintf(buf, "ALTER TABLE %s ADD COLUMN %s %s;",
1558 e->table_name.c_str(),
1559 e->tags[i].column_name.c_str(),
1560 midas2sqlType(e->tags[i].tag.type));
1561
1562 status = fSql->Exec(buf);
1563
1564 if (status != DB_SUCCESS) {
1565 e->active = false;
1566 return HS_FILE_ERROR;
1567 }
1568 }
1569
1570 // find empty slot in events list
1571 for (unsigned int i=0; i<fEvents.size(); i++)
1572 if (!fEvents[i]) {
1573 fEvents[i] = e;
1574 e = NULL;
1575 break;
1576 }
1577
1578 // if no empty slots, add at the end
1579 if (e)
1580 fEvents.push_back(e);
1581
1582 return HS_SUCCESS;
1583 }
char name[NAME_LENGTH]
Definition history.h:111
virtual int ListColumns(const char *table, std::vector< std::string > *plist)=0
virtual int Exec(const char *sql)=0
std::vector< Event * > fEvents
#define DB_KEY_EXIST
Definition midas.h:641
#define HS_FILE_ERROR
Definition midas.h:728
#define MERROR
Definition midas.h:559
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:915
static std::string MidasNameToSqlName(const char *s)
static const int tid_size[]
static const char * midasTypeName(int tid)
static IndexEntry * FindIndexByEventName(const char *event_name)
static IndexEntryTag * FindIndexByTagName(IndexEntry *ie, const char *tag_name)
static bool isCompatible(int tid, const char *sqlType)
static void PrintTags(int ntags, const TAG tags[])
static const char * midas2sqlType(int tid)
static int ReadIndex(SqlBase *sql, const char *event_name)
static int offset
Definition mgd.cxx:1500
INT j
Definition odbhist.cxx:40
DWORD type
Definition midas.h:1236
DWORD n_data
Definition midas.h:1237
char name[NAME_LENGTH]
Definition midas.h:1235
int offset
bool create
std::string column_name
static double e(void)
Definition tinyexpr.c:136
Here is the call graph for this function:

◆ hs_disconnect()

int SqlHistory::hs_disconnect ( )
inlinevirtual

disconnect from history, returns HS_SUCCESS

Implements MidasHistoryInterface.

Definition at line 1246 of file history_odbc.cxx.

1247 {
1248 if (fDebug)
1249 printf("hs_disconnect!\n");
1250
1251 fSql->Disconnect();
1252
1254
1255 return HS_SUCCESS;
1256 }
virtual int Disconnect()=0
int hs_clear_cache()
clear internal cache, returns HS_SUCCESS
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_flush_buffers()

int SqlHistory::hs_flush_buffers ( )
inlinevirtual

flush buffered data to storage where it is visible to mhttpd

Implements MidasHistoryInterface.

Definition at line 1668 of file history_odbc.cxx.

1669 {
1670 if (fDebug)
1671 printf("hs_flush_buffers!\n");
1672 return HS_SUCCESS;
1673 }
Here is the call graph for this function:

◆ hs_get_events()

int SqlHistory::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 1679 of file history_odbc.cxx.

1680 {
1681 if (fDebug)
1682 printf("hs_get_events!\n");
1683
1684 if (fIndexEvents.size() == 0) {
1685
1686 if (fDebug)
1687 printf("hs_get_events: reading event names!\n");
1688
1690
1691 std::vector<std::string> tables;
1692 int status = fSql->ListTables(&tables);
1693 if (status != DB_SUCCESS)
1694 return status;
1695
1696 for (unsigned i=0; i<tables.size(); i++) {
1697 if (tables[i] == "_history_index")
1698 continue;
1699
1701 if (!ie) {
1704 }
1705
1706 if (ie)
1707 fIndexEvents.push_back(ie->event_name);
1708 else
1709 fIndexEvents.push_back(tables[i]);
1710 }
1711 }
1712
1713 assert(pevents);
1715
1716 return HS_SUCCESS;
1717 }
static IndexEntry * FindIndexByTableName(const char *table_name)
Here is the call graph for this function:

◆ hs_get_last_written()

int SqlHistory::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 1795 of file history_odbc.cxx.

1796 {
1797 for (int i=0; i<num_var; i++)
1798 last_written[i] = 0;
1799 return HS_FILE_ERROR;
1800 }
Here is the call graph for this function:

◆ hs_get_tags()

int SqlHistory::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 1719 of file history_odbc.cxx.

1720 {
1721 if (fDebug)
1722 printf("hs_get_tags for [%s]\n", event_name);
1723
1724 assert(ptags);
1725
1726 IndexEntry* ie = FindIndexByEventName(event_name);
1727
1728 if (!ie) {
1729 ReadIndex(fSql, event_name);
1730 ie = FindIndexByEventName(event_name);
1731 }
1732
1733 if (!ie) {
1734 XReadIndex();
1735 ie = FindIndexByEventName(event_name);
1736 }
1737
1738 if (!ie)
1739 return HS_UNDEFINED_EVENT;
1740
1741 if (ie->tags_cache.size() == 0) {
1742 if (fDebug)
1743 printf("hs_get_tags reading tags for [%s]\n", event_name);
1744
1745 std::string tname = ie->table_name;
1746
1747 std::vector<std::string> columns;
1748
1749 int status = fSql->ListColumns(tname.c_str(), &columns);
1750 if (status != DB_SUCCESS)
1751 return status;
1752
1753 if (columns.size() < 1) {
1754 cm_msg(MERROR, "hs_get_tags", "Cannot get columns for table \'%s\', try to reconnect to the database", tname.c_str());
1755
1756 int status = Reconnect();
1757 if (status != HS_SUCCESS)
1758 return status;
1759
1760 columns.clear();
1761 status = fSql->ListColumns(tname.c_str(), &columns);
1762 if (status != DB_SUCCESS)
1763 return status;
1764 }
1765
1766 //TAG* t = (TAG*)malloc(sizeof(TAG)*columns.size());
1767 //assert(t);
1768
1769 for (unsigned int j=0; j<columns.size(); j+=2) {
1770 if (columns[j] == "_t_time")
1771 continue;
1772 if (columns[j] == "_i_time")
1773 continue;
1774
1776
1777 TAG t;
1778 if (it)
1779 mstrlcpy(t.name, it->tag_name.c_str(), sizeof(t.name));
1780 else
1781 mstrlcpy(t.name, columns[j].c_str(), sizeof(t.name));
1782 t.type = sql2midasType(columns[j+1].c_str());
1783 t.n_data = 1;
1784
1785 ie->tags_cache.push_back(t);
1786 }
1787 }
1788
1789 for (unsigned i=0; i<ie->tags_cache.size(); i++)
1790 ptags->push_back(ie->tags_cache[i]);
1791
1792 return HS_SUCCESS;
1793 }
#define HS_UNDEFINED_EVENT
Definition midas.h:732
static int sql2midasType(const char *name)
static IndexEntryTag * FindIndexByColumnName(IndexEntry *ie, const char *column_name)
Definition midas.h:1234
Here is the call graph for this function:

◆ hs_read() [1/2]

int SqlHistory::hs_read ( double  start_time,
double  end_time,
double  interval,
const char event_name,
const char tag_name,
int  tag_index,
int num_entries,
time_t **  time_buffer,
double **  data_buffer 
)
inline

Definition at line 1875 of file history_odbc.cxx.

1879 {
1880 *num_entries = 0;
1881 *time_buffer = NULL;
1882 *data_buffer = NULL;
1883
1884 if (fDebug)
1885 printf("hs_read: event [%s], tag [%s], index %d, start %f, end %f, dt %f, interval %f, max points %f\n",
1886 event_name, tag_name, tag_index,
1887 start_time, end_time, end_time-start_time, interval, (end_time-start_time)/interval);
1888
1889 if (event_name==NULL)
1890 return HS_SUCCESS;
1891
1892 IndexEntry*ie = FindIndexByEventName(event_name);
1893
1894 if (!ie) {
1895 ReadIndex(fSql, event_name);
1896 ie = FindIndexByEventName(event_name);
1897 }
1898
1899 if (!ie) {
1900 XReadIndex();
1901 ie = FindIndexByEventName(event_name);
1902 }
1903
1905
1906 if (ie)
1907 it = FindIndexByTagName(ie, tag_name);
1908
1909 if (ie && !it) { // maybe this is an array without "Names"?
1910 char xxx[256];
1911 sprintf(xxx, "%s[%d]", tag_name, tag_index);
1913 }
1914
1915 // new-style event name: "equipment_name/variable_name:tag_name"
1916 // old style event name: "equipment_name:tag_name" ("variable_name" is missing)
1917 bool oldStyleEventName = (strchr(event_name, '/')==NULL);
1918
1920 if (!ie || !it) {
1921 return hs_read_old_style(start_time, end_time, interval,
1922 event_name, tag_name, tag_index,
1923 num_entries,
1925 }
1926
1927 if (!it)
1928 return HS_UNDEFINED_VAR;
1929
1930 assert(ie);
1931 assert(it);
1932
1933 std::string tname = ie->table_name;
1934 std::string cname = it->column_name;
1935
1936 char cmd[256];
1937 sprintf(cmd, "SELECT _i_time, %s FROM %s WHERE _i_time>=%.0f and _i_time<=%.0f ORDER BY _i_time;",
1938 cname.c_str(), tname.c_str(),
1939 start_time, end_time);
1940
1941 int status = fSql->Exec(cmd);
1942
1943 if (fDebug) {
1944 printf("hs_read: event \"%s\", tag \"%s\", index %d: Read table \"%s\" column \"%s\": status %d, nrows: %d, ncolumns: %d\n",
1945 event_name, tag_name, tag_index,
1946 tname.c_str(),
1947 cname.c_str(),
1948 status,
1949 fSql->GetNumRows(),
1951 );
1952 }
1953
1954 if (status != SUCCESS) {
1955 return HS_FILE_ERROR;
1956 }
1957
1958 if (fSql->GetNumRows() == 0) {
1959 fSql->Done();
1960
1961 if (oldStyleEventName) {
1962 return hs_read_old_style(start_time, end_time, interval,
1963 event_name, tag_name, tag_index,
1964 num_entries,
1966 }
1967
1968 return HS_SUCCESS;
1969 }
1970
1971 int nrows = fSql->GetNumRows();
1972 int ncols = fSql->GetNumColumns();
1973
1974 if (nrows < 0)
1975 return HS_FILE_ERROR;
1976
1977 if (ncols < 1)
1978 return HS_FILE_ERROR;
1979
1980 *num_entries = 0;
1981 *time_buffer = (time_t*)malloc(nrows * sizeof(time_t));
1982 *data_buffer = (double*)malloc(nrows * sizeof(double));
1983
1984 /* Loop through the rows in the result-set */
1985 int row = 0;
1986 time_t tt = 0;
1987 int ann = 0;
1988 double att = 0;
1989 double avv = 0;
1990 while (1) {
1991 status = fSql->Fetch();
1992 if (status != DB_SUCCESS)
1993 break;
1994
1995 time_t t = 0;
1996 double v = 0;
1997
1998 const char* timedata = fSql->GetColumn(1);
1999 if (timedata)
2000 t = atoi(timedata);
2001
2002 const char* valuedata = fSql->GetColumn(2);
2003 if (valuedata)
2004 v = atof(valuedata);
2005
2006 if (t < start_time || t > end_time)
2007 continue;
2008
2009 //printf("Row %d, time %d, value %f\n", row, t, v);
2010 //printf("tt: %d, ann: %d\n", tt, ann);
2011
2012 if (tt == 0 || t >= tt + interval) {
2013
2014 if (ann > 0) {
2015 assert(row < nrows);
2016
2017 (*time_buffer)[row] = (time_t)(att/ann);
2018 (*data_buffer)[row] = avv/ann;
2019
2020 row++;
2021 (*num_entries) = row;
2022 }
2023
2024 ann = 0;
2025 att = 0;
2026 avv = 0;
2027 tt = t;
2028
2029 }
2030
2031 ann++;
2032 att += t;
2033 avv += v;
2034 }
2035
2036 if (ann > 0) {
2037 assert(row < nrows);
2038
2039 (*time_buffer)[row] = (time_t)(att/ann);
2040 (*data_buffer)[row] = avv/ann;
2041
2042 row++;
2043 (*num_entries) = row;
2044 }
2045
2046 fSql->Done();
2047
2048 if (fDebug)
2049 printf("hs_read: return %d entries\n", *num_entries);
2050
2051 return HS_SUCCESS;
2052 }
virtual int Fetch()=0
virtual const char * GetColumn(int icol)=0
virtual int Done()=0
virtual int GetNumColumns()=0
virtual int GetNumRows()=0
int hs_read_old_style(double start_time, double end_time, double interval, const char *event_name, const char *tag_name, int var_index, int *num_entries, time_t **time_buffer, double **data_buffer)
#define HS_UNDEFINED_VAR
Definition midas.h:733
#define SUCCESS
Definition mcstd.h:54
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_read() [2/2]

int SqlHistory::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 2054 of file history_odbc.cxx.

2060 {
2061 if (fDebug)
2062 printf("hs_read: %d variables\n", num_var);
2063
2064 if (!fSql->IsConnected())
2065 return HS_FILE_ERROR;
2066
2067 for (int i=0; i<num_var; i++) {
2068
2069 if (event_name[i]==NULL) {
2071 num_entries[i] = 0;
2072 continue;
2073 }
2074
2075 st[i] = hs_read((double)start_time, (double)end_time, (double)interval,
2076 event_name[i], tag_name[i], tag_index[i],
2077 &num_entries[i],
2078 &time_buffer[i], &data_buffer[i]);
2079 }
2080
2081 return HS_SUCCESS;
2082 }
int hs_read(double start_time, double end_time, double interval, const char *event_name, const char *tag_name, int tag_index, int *num_entries, time_t **time_buffer, double **data_buffer)
Here is the call graph for this function:

◆ hs_read2()

int SqlHistory::hs_read2 ( 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 mean_buffer[],
double rms_buffer[],
double min_buffer[],
double max_buffer[],
int  read_status[] 
)
inline

Definition at line 2086 of file history_odbc.cxx.

2096 {
2097 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);
2098
2099 for (int i=0; i<num_var; i++) {
2100 int num = num_entries[i];
2101 rms_buffer[i] = (double*)malloc(sizeof(double)*num);
2102 min_buffer[i] = (double*)malloc(sizeof(double)*num);
2103 max_buffer[i] = (double*)malloc(sizeof(double)*num);
2104
2105 for (int j=0; j<num; j++) {
2106 rms_buffer[i][j] = 0;
2107 min_buffer[i][j] = mean_buffer[i][j];
2108 max_buffer[i][j] = mean_buffer[i][j];
2109 }
2110 }
2111
2112 return status;
2113 }
Here is the call graph for this function:

◆ hs_read_binned()

int SqlHistory::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 2127 of file history_odbc.cxx.

2135 {
2136 return HS_FILE_ERROR;
2137 }

◆ hs_read_buffer()

int SqlHistory::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 2117 of file history_odbc.cxx.

2121 {
2122 return HS_FILE_ERROR;
2123 }

◆ hs_read_old_style()

int SqlHistory::hs_read_old_style ( double  start_time,
double  end_time,
double  interval,
const char event_name,
const char tag_name,
int  var_index,
int num_entries,
time_t **  time_buffer,
double **  data_buffer 
)
inline

Definition at line 1802 of file history_odbc.cxx.

1806 {
1807 if (fDebug) {
1808 printf("hs_read_old_style: event \"%s\", tag \"%s\"\n", event_name, tag_name);
1809 }
1810
1812
1813 for (unsigned e=0; e<gHistoryIndex.size(); e++) {
1814
1815 const char* s = gHistoryIndex[e]->event_name.c_str();
1816
1817 bool match = false;
1818 for (int j=0; s[j]; j++) {
1819
1820 if ((event_name[j]==0) && (s[j]=='/')) {
1821 match = true;
1822 break;
1823 }
1824
1825 if ((event_name[j]==0) && (s[j]=='_')) {
1826 match = true;
1827 break;
1828 }
1829
1830 if (event_name[j]==0) {
1831 match = false;
1832 break;
1833 }
1834
1835 if (tolower(event_name[j]) != tolower(s[j])) {
1836 match = false;
1837 break;
1838 }
1839 }
1840
1841 //printf("try %s, match %d\n", s, match);
1842
1843 if (match) {
1844 bool found_tag = false;
1846 for (unsigned v=0; v<ie->tags.size(); v++) {
1847 //printf("try tag [%s] looking for [%s]\n", ie->tags[v].tag_name.c_str(), tag_name);
1848 if (equal_ustring(tag_name, ie->tags[v].tag_name.c_str())) {
1849 found_tag = true;
1850 break;
1851 }
1852 }
1853
1854 if (!found_tag)
1855 match = false;
1856 }
1857
1858 if (match) {
1859 if (fDebug)
1860 printf("hs_read_old_style: event \"%s\", tag \"%s\", try matching event \'%s\'\n", event_name, tag_name, s);
1861
1862 int status = hs_read(start_time, end_time, interval,
1863 s, tag_name, var_index,
1864 num_entries,
1866
1867 if (status==HS_SUCCESS && *num_entries>0)
1868 return HS_SUCCESS;
1869 }
1870 }
1871
1872 return HS_UNDEFINED_VAR;
1873 }
BOOL equal_ustring(const char *str1, const char *str2)
Definition odb.cxx:3201
BOOL match(char *pat, char *str)
Definition odbedit.cxx:190
Here is the call graph for this function:
Here is the caller graph for this function:

◆ hs_set_debug()

int SqlHistory::hs_set_debug ( int  debug)
inlinevirtual

set debug level, returns previous debug level

Implements MidasHistoryInterface.

Definition at line 1199 of file history_odbc.cxx.

1200 {
1201 int old = fDebug;
1202 fDebug = debug;
1203 gTrace = debug;
1205 return old;
1206 }
virtual int SetDebug(int debug)=0
static int gTrace
BOOL debug
debug printouts
Definition mana.cxx:254
Here is the call graph for this function:

◆ hs_write_event()

int SqlHistory::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 1585 of file history_odbc.cxx.

1586 {
1587 if (fDebug)
1588 printf("hs_write_event: write event \'%s\', time %d, size %d\n", event_name, (int)timestamp, buffer_size);
1589
1590 // if disconnected, try to reconnect
1591
1592 if (!fSql->IsConnected()) {
1593 time_t now = time(NULL);
1594
1595 // too early to try reconnecting?
1596 if (fConnectRetry !=0 && now < fNextConnect) {
1597 return HS_FILE_ERROR;
1598 }
1599
1600 cm_msg(MINFO, "hs_write_event", "Trying to reconnect to SQL database \'%s\'", fConnectString.c_str());
1601
1602 int status = fSql->Connect(fConnectString.c_str());
1603
1604 if (status != DB_SUCCESS) {
1605
1606 // first retry in 5 seconds
1607 if (fConnectRetry == 0)
1608 fConnectRetry = 5;
1609
1611
1612 // exponential backoff
1613 fConnectRetry *= 2;
1614
1615 // but no more than every 10 minutes
1616 if (fConnectRetry > 10*60)
1617 fConnectRetry = 10*60;
1618
1619 return HS_FILE_ERROR;
1620 }
1621
1622 cm_msg(MINFO, "hs_write_event", "Reconnected to SQL database \'%s\'", fConnectString.c_str());
1623 }
1624
1625 fNextConnect = 0;
1626 fConnectRetry = 0;
1627
1628 Event *e = NULL;
1629
1630 // find this event
1631 for (size_t i=0; i<fEvents.size(); i++)
1632 if (fEvents[i]->event_name == event_name) {
1633 e = fEvents[i];
1634 break;
1635 }
1636
1637 // not found
1638 if (!e)
1639 return HS_UNDEFINED_EVENT;
1640
1641 // deactivated because of error?
1642 if (!e->active)
1643 return HS_FILE_ERROR;
1644
1645 int status = WriteEvent(fSql, e, timestamp, buffer, buffer_size);
1646
1647 // if could not write to SQL?
1648 if (status != HS_SUCCESS) {
1649
1650 // if lost SQL connection, try again later
1651
1652 if (!fSql->IsConnected()) {
1653 return HS_FILE_ERROR;
1654 }
1655
1656 // otherwise, deactivate this event
1657
1658 e->active = false;
1659
1660 cm_msg(MERROR, "hs_write_event", "Event \'%s\' disabled after write error %d into SQL database \'%s\'", event_name, status, fConnectString.c_str());
1661
1662 return HS_FILE_ERROR;
1663 }
1664
1665 return HS_SUCCESS;
1666 }
#define MINFO
Definition midas.h:560
int WriteEvent(SqlBase *sql, Event *e, time_t t, const char *buf, int size)
Here is the call graph for this function:

◆ Reconnect()

int SqlHistory::Reconnect ( )
inline

Definition at line 1258 of file history_odbc.cxx.

1259 {
1260 if (fDebug)
1261 printf("Reconnect to SQL database!\n");
1262
1263 fSql->Disconnect();
1264 fSql->Connect(fConnectString.c_str());
1265 if (!fSql->IsConnected()) {
1266 return HS_FILE_ERROR;
1267 }
1268
1269 return HS_SUCCESS;
1270 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ XReadIndex()

int SqlHistory::XReadIndex ( )
inline

Definition at line 1296 of file history_odbc.cxx.

1297 {
1298 if (fHaveXIndex)
1299 return HS_SUCCESS;
1300
1301 if (fDebug)
1302 printf("XReadIndex!\n");
1303
1304 std::vector<std::string> tables;
1305
1306 int status = fSql->ListTables(&tables);
1307 if (status != DB_SUCCESS)
1308 return status;
1309
1310 for (unsigned i=0; i<tables.size(); i++) {
1311 if (tables[i] == "_history_index")
1312 continue;
1313
1314 IndexEntry* ie = NULL; //FindEventName(tables[i].c_str());
1315
1316 if (!ie) {
1317 ie = new IndexEntry;
1318
1319 ie->table_name = tables[i];
1320 ie->event_name = ie->table_name;
1321
1322 gHistoryIndex.push_back(ie);
1323 }
1324
1325 std::vector<std::string> columns;
1326
1327 status = fSql->ListColumns(ie->table_name.c_str(), &columns);
1328 if (status != DB_SUCCESS)
1329 return status;
1330
1331 for (unsigned int j=0; j<columns.size(); j+=2) {
1332 if (columns[j] == "_t_time")
1333 continue;
1334 if (columns[j] == "_i_time")
1335 continue;
1336
1337 IndexEntryTag t;
1338 t.column_name = columns[j];
1339 t.tag_name = t.column_name;
1340 t.timestamp = 0;
1341
1342 ie->tags.push_back(t);
1343 }
1344 }
1345
1346 fHaveXIndex = true;
1347
1348 //PrintIndex();
1349
1350 return HS_SUCCESS;
1351 }
std::string table_name
int timestamp
std::string tag_name
std::string column_name
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ fConnectRetry

int SqlHistory::fConnectRetry

Definition at line 1175 of file history_odbc.cxx.

◆ fConnectString

std::string SqlHistory::fConnectString

Definition at line 1174 of file history_odbc.cxx.

◆ fDebug

int SqlHistory::fDebug

Definition at line 1173 of file history_odbc.cxx.

◆ fEvents

std::vector<Event*> SqlHistory::fEvents

Definition at line 1177 of file history_odbc.cxx.

◆ fHaveIndex

bool SqlHistory::fHaveIndex

Definition at line 1179 of file history_odbc.cxx.

◆ fHaveXIndex

bool SqlHistory::fHaveXIndex

Definition at line 1180 of file history_odbc.cxx.

◆ fIndexEvents

std::vector<std::string> SqlHistory::fIndexEvents

Definition at line 1178 of file history_odbc.cxx.

◆ fNextConnect

int SqlHistory::fNextConnect

Definition at line 1176 of file history_odbc.cxx.

◆ fSql

SqlBase* SqlHistory::fSql

Definition at line 1172 of file history_odbc.cxx.


The documentation for this class was generated from the following file: