remlogger.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #include <string.h>
  2. #include <malloc.h>
  3. #include <limits.h>
  4. #include "remlogger.h"
  5. /////////////////////////////////////////////////////////////////////////////
  6. CRemLogger::CRemLogger(LPCRLPARAMS pdlp)
  7. {
  8. memset(&m_rlp, 0, sizeof(m_rlp));
  9. if(pdlp)
  10. memcpy(&m_rlp, pdlp, sizeof(m_rlp));
  11. }
  12. CRemLogger::~CRemLogger(void)
  13. {
  14. }
  15. bool CRemLogger::InitDatabase(bool bCreateAlways)
  16. {
  17. CMySqlDB db;
  18. if(!db.Options(MYSQL_SET_CHARSET_NAME, "utf8"))
  19. {
  20. m_lastError = db.LastError();
  21. return false;
  22. }
  23. if(!db.Options(MYSQL_INIT_COMMAND, "SET NAMES utf8"))
  24. {
  25. m_lastError = db.LastError();
  26. return false;
  27. }
  28. if(!db.Connect("localhost", m_rlp.szDBUser, m_rlp.szDBPass, NULL))
  29. {
  30. m_lastError = db.LastError();
  31. return false;
  32. }
  33. if(!CreateDatabase(db, bCreateAlways))
  34. return false;
  35. if(db.SelectDB(m_rlp.szDBName))
  36. {
  37. m_lastError = db.LastError();
  38. return false;
  39. }
  40. if(!CreateLogsTable(db))
  41. return false;
  42. return true;
  43. }
  44. bool CRemLogger::CreateDatabase(CMySqlDB &rdb, bool bCreateAlways)
  45. {
  46. char szSql[_RL_MAX_DB_NAME_LENGTH + 64];
  47. if(bCreateAlways)
  48. {
  49. sprintf(szSql, "drop database if exists `%s`", m_rlp.szDBName);
  50. rdb.Query(szSql);
  51. }
  52. sprintf(szSql, "create database if not exists `%s`", m_rlp.szDBName);
  53. CMySqlResult res = rdb.Query(szSql);
  54. bool bError = res.error();
  55. if(bError)
  56. m_lastError = rdb.LastError();
  57. return !bError;
  58. }
  59. bool CRemLogger::CreateLogsTable(CMySqlDB &rdb)
  60. {
  61. char szSql[_RL_MAX_TABLE_NAME_LENGTH + 512];
  62. const char *pszFormat =
  63. "CREATE TABLE IF NOT EXISTS `%s` (" \
  64. " `id` int(11) unsigned NOT NULL AUTO_INCREMENT," \
  65. " `tslog` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," \
  66. " `path` varchar(%u) CHARACTER SET ascii NOT NULL," \
  67. " `nvalue` double DEFAULT NULL," \
  68. " `svalue` varchar(%u) DEFAULT NULL," \
  69. " KEY `nvalue` (`nvalue`)," \
  70. " KEY `path` (`path`)," \
  71. " KEY `tslog` (`tslog`)," \
  72. " PRIMARY KEY (`id`)" \
  73. ") ENGINE=InnoDB DEFAULT CHARSET=utf8";
  74. sprintf(szSql, pszFormat, m_rlp.szLogsTable, _RL_MAX_VARPATH_LENGTH, _RL_MAX_STRVAL_LENGTH);
  75. CMySqlResult res = rdb.Query(szSql);
  76. bool bError = res.error();
  77. if(bError)
  78. m_lastError = rdb.LastError();
  79. return !bError;
  80. }
  81. bool CRemLogger::Log(const char *pszVarPath, size_t nCbVarPath, double fValue, const char *pszStrValue, size_t nCbStrValue, time_t nTimestamp, bool fNumeric)
  82. {
  83. REM_LOG_ENTRY log;
  84. memset(&log, 0, sizeof(log));
  85. log.nTimestamp = nTimestamp;
  86. log.fNumeric = fNumeric;
  87. nCbVarPath = _MIN(nCbVarPath, (_RL_MAX_VARPATH_LENGTH - 1));
  88. memcpy(log.szVarPath, pszVarPath, nCbVarPath);
  89. if(fNumeric)
  90. {
  91. log.fValue = fValue;
  92. }
  93. else
  94. {
  95. nCbStrValue = _MIN(nCbStrValue, (_RL_MAX_STRVAL_LENGTH - 1));
  96. memcpy(log.szStrVal, pszStrValue, nCbStrValue);
  97. }
  98. if(m_logs.size() < _RL_MAX_BACKLOG)
  99. m_logs.push_back(log);
  100. return true;
  101. }
  102. bool CRemLogger::Flush(time_t nTimestamp)
  103. {
  104. CMySqlDB db;
  105. if(!db.Options(MYSQL_SET_CHARSET_NAME, "utf8"))
  106. {
  107. m_lastError = db.LastError();
  108. return false;
  109. }
  110. if(!db.Options(MYSQL_INIT_COMMAND, "SET NAMES utf8"))
  111. {
  112. m_lastError = db.LastError();
  113. return false;
  114. }
  115. std::string strSql;
  116. bool bError = false;
  117. char szSql[_RL_MAX_TABLE_NAME_LENGTH + _RL_MAX_VARPATH_LENGTH + _RL_MAX_STRVAL_LENGTH * 2 + 100];
  118. if(!db.Connect("localhost", m_rlp.szDBUser, m_rlp.szDBPass, m_rlp.szDBName))
  119. {
  120. m_lastError = db.LastError();
  121. return false;
  122. }
  123. auto nSize = m_logs.size();
  124. if(nSize > 0)
  125. {
  126. strSql.reserve((_RL_MAX_VARPATH_LENGTH + _RL_MAX_STRVAL_LENGTH * 2 + 50) * nSize);
  127. auto itFirst = m_logs.begin();
  128. const REM_LOG_ENTRY &rle0 = *itFirst;
  129. if(rle0.fNumeric)
  130. sprintf(szSql, "insert into `%s` (`path`, `nvalue`, `svalue`) values ('%s', %.20g, NULL)", m_rlp.szLogsTable, rle0.szVarPath, rle0.fValue);
  131. else
  132. sprintf(szSql, "insert into `%s` (`path`, `nvalue`, `svalue`) values ('%s', NULL, '%s')", m_rlp.szLogsTable, rle0.szVarPath, db.EscapeString(rle0.szStrVal).c_str());
  133. strSql = szSql;
  134. for(++itFirst; itFirst < m_logs.end(); itFirst++)
  135. {
  136. const REM_LOG_ENTRY &rle = *itFirst;
  137. if(rle.fNumeric)
  138. sprintf(szSql, ",('%s', %.20g, NULL)", rle.szVarPath, rle.fValue);
  139. else
  140. sprintf(szSql, ",('%s', NULL, '%s')", rle.szVarPath, db.EscapeString(rle.szStrVal).c_str());
  141. strSql += szSql;
  142. }
  143. CMySqlResult res = db.Query(strSql.c_str());
  144. bError = res.error();
  145. if(bError)
  146. m_lastError = db.LastError();
  147. }
  148. m_logs.clear();
  149. return !bError;
  150. }