#include #include #include #include "remlogger.h" ///////////////////////////////////////////////////////////////////////////// CRemLogger::CRemLogger(LPCRLPARAMS pdlp) { memset(&m_rlp, 0, sizeof(m_rlp)); if(pdlp) memcpy(&m_rlp, pdlp, sizeof(m_rlp)); } CRemLogger::~CRemLogger(void) { } bool CRemLogger::InitDatabase(bool bCreateAlways) { CMySqlDB db; if(!db.Options(MYSQL_SET_CHARSET_NAME, "utf8")) { m_lastError = db.LastError(); return false; } if(!db.Options(MYSQL_INIT_COMMAND, "SET NAMES utf8")) { m_lastError = db.LastError(); return false; } if(!db.Connect("localhost", m_rlp.szDBUser, m_rlp.szDBPass, NULL)) { m_lastError = db.LastError(); return false; } if(!CreateDatabase(db, bCreateAlways)) return false; if(db.SelectDB(m_rlp.szDBName)) { m_lastError = db.LastError(); return false; } if(!CreateLogsTable(db)) return false; return true; } bool CRemLogger::CreateDatabase(CMySqlDB &rdb, bool bCreateAlways) { char szSql[_RL_MAX_DB_NAME_LENGTH + 64]; if(bCreateAlways) { sprintf(szSql, "drop database if exists `%s`", m_rlp.szDBName); rdb.Query(szSql); } sprintf(szSql, "create database if not exists `%s`", m_rlp.szDBName); CMySqlResult res = rdb.Query(szSql); bool bError = res.error(); if(bError) m_lastError = rdb.LastError(); return !bError; } bool CRemLogger::CreateLogsTable(CMySqlDB &rdb) { char szSql[_RL_MAX_TABLE_NAME_LENGTH + 512]; const char *pszFormat = "CREATE TABLE IF NOT EXISTS `%s` (" \ " `id` int(11) unsigned NOT NULL AUTO_INCREMENT," \ " `tslog` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," \ " `path` varchar(%u) CHARACTER SET ascii NOT NULL," \ " `nvalue` double DEFAULT NULL," \ " `svalue` varchar(%u) DEFAULT NULL," \ " KEY `nvalue` (`nvalue`)," \ " KEY `path` (`path`)," \ " KEY `tslog` (`tslog`)," \ " PRIMARY KEY (`id`)" \ ") ENGINE=InnoDB DEFAULT CHARSET=utf8"; sprintf(szSql, pszFormat, m_rlp.szLogsTable, _RL_MAX_VARPATH_LENGTH, _RL_MAX_STRVAL_LENGTH); CMySqlResult res = rdb.Query(szSql); bool bError = res.error(); if(bError) m_lastError = rdb.LastError(); return !bError; } bool CRemLogger::Log(const char *pszVarPath, size_t nCbVarPath, double fValue, const char *pszStrValue, size_t nCbStrValue, time_t nTimestamp, bool fNumeric) { REM_LOG_ENTRY log; memset(&log, 0, sizeof(log)); log.nTimestamp = nTimestamp; log.fNumeric = fNumeric; nCbVarPath = _MIN(nCbVarPath, (_RL_MAX_VARPATH_LENGTH - 1)); memcpy(log.szVarPath, pszVarPath, nCbVarPath); if(fNumeric) { log.fValue = fValue; } else { nCbStrValue = _MIN(nCbStrValue, (_RL_MAX_STRVAL_LENGTH - 1)); memcpy(log.szStrVal, pszStrValue, nCbStrValue); } if(m_logs.size() < _RL_MAX_BACKLOG) m_logs.push_back(log); return true; } bool CRemLogger::Flush(time_t nTimestamp) { CMySqlDB db; if(!db.Options(MYSQL_SET_CHARSET_NAME, "utf8")) { m_lastError = db.LastError(); return false; } if(!db.Options(MYSQL_INIT_COMMAND, "SET NAMES utf8")) { m_lastError = db.LastError(); return false; } std::string strSql; bool bError = false; char szSql[_RL_MAX_TABLE_NAME_LENGTH + _RL_MAX_VARPATH_LENGTH + _RL_MAX_STRVAL_LENGTH * 2 + 100]; if(!db.Connect("localhost", m_rlp.szDBUser, m_rlp.szDBPass, m_rlp.szDBName)) { m_lastError = db.LastError(); return false; } auto nSize = m_logs.size(); if(nSize > 0) { strSql.reserve((_RL_MAX_VARPATH_LENGTH + _RL_MAX_STRVAL_LENGTH * 2 + 50) * nSize); auto itFirst = m_logs.begin(); const REM_LOG_ENTRY &rle0 = *itFirst; if(rle0.fNumeric) sprintf(szSql, "insert into `%s` (`path`, `nvalue`, `svalue`) values ('%s', %.20g, NULL)", m_rlp.szLogsTable, rle0.szVarPath, rle0.fValue); else sprintf(szSql, "insert into `%s` (`path`, `nvalue`, `svalue`) values ('%s', NULL, '%s')", m_rlp.szLogsTable, rle0.szVarPath, db.EscapeString(rle0.szStrVal).c_str()); strSql = szSql; for(++itFirst; itFirst < m_logs.end(); itFirst++) { const REM_LOG_ENTRY &rle = *itFirst; if(rle.fNumeric) sprintf(szSql, ",('%s', %.20g, NULL)", rle.szVarPath, rle.fValue); else sprintf(szSql, ",('%s', NULL, '%s')", rle.szVarPath, db.EscapeString(rle.szStrVal).c_str()); strSql += szSql; } CMySqlResult res = db.Query(strSql.c_str()); bError = res.error(); if(bError) m_lastError = db.LastError(); } m_logs.clear(); return !bError; }