datalogger.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // datalogger.h :
  2. //
  3. #if !defined(AGD_DATALOGGER_H__21BAEB7B_E478_4ED1_B9F6_FDBCE620C55B__INCLUDED_)
  4. #define AGD_DATALOGGER_H__21BAEB7B_E478_4ED1_B9F6_FDBCE620C55B__INCLUDED_
  5. #include <limits.h>
  6. #include <vector>
  7. #include <pthread.h>
  8. #ifndef _LIBBUILD
  9. #include <gfa/svc/common/mysqlwrap.h>
  10. #include <gfa/svc/common/logfile.h>
  11. #else // _LIBBUILD
  12. #include "common/mysqlwrap.h"
  13. #include "common/logfile.h"
  14. #endif // _LIBBUILD
  15. /////////////////////////////////////////////////////////////////////////////
  16. // datalogger.h - Declarations:
  17. #define _DL_DATABASE_ENGINE_INNODB 1
  18. #define _DL_DATABASE_ENGINE_MYISAM 2
  19. /////////////////////////////////////////////////////////////////////////////
  20. #define _DL_USE_NEW_TABLES_LAYOUT 1
  21. #define _DL_DATABSE_ENGINE _DL_DATABASE_ENGINE_INNODB
  22. /////////////////////////////////////////////////////////////////////////////
  23. #if _DL_DATABSE_ENGINE == _DL_DATABASE_ENGINE_INNODB
  24. #define _DL_DATABSE_ENGINE_NAME "InnoDB"
  25. #define _DL_MAX_VARPATH_LENGTH 767
  26. #elif _DL_DATABSE_ENGINE == _DL_DATABASE_ENGINE_MYISAM
  27. #define _DL_DATABSE_ENGINE_NAME "MyISAM"
  28. #define _DL_MAX_VARPATH_LENGTH 1000
  29. #else // _DL_DATABSE_ENGINE
  30. #error Invalid database engine!
  31. #endif // _DL_DATABSE_ENGINE
  32. /////////////////////////////////////////////////////////////////////////////
  33. #define _DL_NANOSECS_PER_SEC 1000000000
  34. #define _DL_MAX_DB_NAME_LENGTH 64
  35. #define _DL_MAX_DB_USER_LENGTH 64
  36. #define _DL_MAX_DB_PASS_LENGTH 64
  37. #define _DL_MAX_TABLE_NAME_LENGTH 64
  38. #define _SECONDS_PER_DAY 86400
  39. #define _MIDNIGHT_TIMESTAMP_UTC(t) ((t) / _SECONDS_PER_DAY * _SECONDS_PER_DAY)
  40. typedef enum _LogTypes
  41. {
  42. LT_NoLog,
  43. LT_IntervalConditional,
  44. LT_IntervalUnconditional,
  45. LT_ValueChangeConditional,
  46. LT_ValueChangeUnconditional,
  47. LT_IntervalConditionalRem,
  48. LT_IntervalUnconditionalRem,
  49. LT_ValueChangeConditionalRem,
  50. LT_ValueChangeUnconditionalRem
  51. }LogTypes, *LPLogTypes;
  52. #define _IS_VALID_LOGTYPE(lt) (((lt) > LT_NoLog) && ((lt) <= LT_ValueChangeUnconditionalRem))
  53. #define _IS_VALUE_CHANGE_LOGTYPE(lt) (((lt) == LT_ValueChangeConditional) || ((lt) == LT_ValueChangeUnconditional) || ((lt) == LT_ValueChangeConditionalRem) || ((lt) == LT_ValueChangeUnconditionalRem))
  54. #define _IS_INTERVAL_LOGTYPE(lt) (((lt) == LT_IntervalConditional) || ((lt) == LT_IntervalUnconditional) || ((lt) == LT_IntervalConditionalRem) || ((lt) == LT_IntervalUnconditionalRem))
  55. #define _IS_CONDITIONAL_LOGTYPE(lt) (((lt) == LT_ValueChangeConditional) || ((lt) == LT_IntervalConditional) || ((lt) == LT_ValueChangeConditionalRem) || ((lt) == LT_IntervalConditionalRem))
  56. #define _IS_UNCONDITIONAL_LOGTYPE(lt) (((lt) == LT_IntervalUnconditional) || ((lt) == LT_ValueChangeUnconditional) || ((lt) == LT_IntervalUnconditionalRem) || ((lt) == LT_ValueChangeUnconditionalRem))
  57. #define _IS_DB_PERSISTENT_LOGTYPE(lt) (((lt) >= LT_IntervalConditionalRem) && ((lt) <= LT_ValueChangeUnconditionalRem))
  58. typedef struct _DLPARAMS
  59. {
  60. char szDBName[_DL_MAX_DB_NAME_LENGTH];
  61. char szDBUser[_DL_MAX_DB_USER_LENGTH];
  62. char szDBPass[_DL_MAX_DB_PASS_LENGTH];
  63. char szTagsTable[_DL_MAX_TABLE_NAME_LENGTH];
  64. char szLogsTable[_DL_MAX_TABLE_NAME_LENGTH];
  65. char szLogsTableBD[_DL_MAX_TABLE_NAME_LENGTH]; // bad date logs table
  66. const char *pszBaseDir;
  67. unsigned int nIntvSample; // sample interval
  68. unsigned int nIntvLog; // log interval
  69. unsigned int nIntvFlush; // flush interval
  70. unsigned int nMaxAge; // Max age of Logs entries in days
  71. unsigned long long nMaxSize; // max. Logs table size in Byte
  72. bool bMinMax; // log min max values as well?
  73. }DLPARAMS, *LPDLPARAMS;
  74. typedef const DLPARAMS *LPCDLPARAMS;
  75. typedef struct _DL_LOG_ENTRY
  76. {
  77. unsigned long nTagID;
  78. time_t nTimestamp;
  79. double fValue;
  80. double fMin;
  81. double fMax;
  82. int nIndex;
  83. LogTypes lt;
  84. bool bNull;
  85. }DL_LOG_ENTRY, *LPDL_LOG_ENTRY;
  86. typedef const DL_LOG_ENTRY *LPCDL_LOG_ENTRY;
  87. typedef struct _MYSQL_GLOBAL_VARS
  88. {
  89. bool bLogsTblIsInnoDB;
  90. bool bInnoDbFilePerTable;
  91. bool bInnoDbIsBarracuda;
  92. bool bInnoDbIsStrictMode;
  93. char szInnoDbFileFormat[64];
  94. char szDataDir[PATH_MAX];
  95. }MYSQL_GLOBAL_VARS, *LPMYSQL_GLOBAL_VARS;
  96. typedef const MYSQL_GLOBAL_VARS *LPCMYSQL_GLOBAL_VARS;
  97. /////////////////////////////////////////////////////////////////////////////
  98. class CDataLogger
  99. {
  100. public:
  101. CDataLogger(LPCDLPARAMS pdlp, CLogfile &rlf);
  102. virtual ~CDataLogger(void);
  103. bool InitDatabase(bool bEnforceCreate = false);
  104. void Release(void);
  105. unsigned long GetTagID(const char *pszVarPath, int nDataType, int nLogType);
  106. bool Log(unsigned long nTagID, double fValue, double fMin, double fMax, time_t nTimestamp, int nIndex, LogTypes lt, bool bNull = false, bool bNoBadDateCheck = false);
  107. bool Flush(time_t nTimestamp);
  108. bool TableFileExists(const char *pszTableName);
  109. int64_t TableFileSize(const char *pszTableName);
  110. void SizeGuardTrigger(time_t ts);
  111. time_t LastLogTimestamp(void){
  112. return m_nLastLogTimestamp;}
  113. bool SizeGuardDayWorkDone(time_t ts){
  114. return m_nSGLastPassUTC == (unsigned long long)_MIDNIGHT_TIMESTAMP_UTC(ts);}
  115. bool Lock(void){
  116. return !::pthread_mutex_lock(&m_mtx);}
  117. bool TryLock(void){
  118. return !::pthread_mutex_trylock(&m_mtx);}
  119. bool Unlock(void){
  120. return !::pthread_mutex_unlock(&m_mtx);}
  121. private:
  122. bool CreateDatabase(CMySqlDB &rdb, bool bEnforceCreate = false);
  123. bool CreateTagsTable(CMySqlDB &rdb);
  124. bool AlterTagsTable(CMySqlDB &rdb);
  125. bool CreateLogsTable(CMySqlDB &rdb);
  126. bool CreateLogsBDTable(CMySqlDB &rdb);
  127. bool CheckTable(CMySqlDB &rdb, const char *pszTableName, bool &bExists, bool &bUseResortTable, bool &bIsInnoDB);
  128. // bool QueryTableSizes(CMySqlDB &rdb, const char *pszTableName);
  129. bool DoSizeGuard(void);
  130. bool ReadGlobalOptions(CMySqlDB &rdb);
  131. bool QueryServerVariable(CMySqlDB &rdb, const char *pszVarname, CMySqlVar &val);
  132. // bool QueryStatusVariable(CMySqlDB &rdb, const char *pszVarname, CMySqlVar &val);
  133. static void* SizeGuardWorker(void* pParam);
  134. unsigned long long SizeGuardLastPassRead(void);
  135. void SizeGuardLastPassWrite(unsigned long long ts);
  136. static size_t Timestamp2String(time_t t, char *pszBuffer, size_t nCbBuffer);
  137. static const char* Ns2String(unsigned long long nNs, char *pszBuffer, size_t nCbBuffer);
  138. static const char* Ms2String(double fMs, char *pszBuffer, size_t nCbBuffer);
  139. time_t GetLastLogTimestamp(CMySqlDB &rdb);
  140. private:
  141. CLogfile &m_lf;
  142. DLPARAMS m_dlp;
  143. MYSQL_GLOBAL_VARS m_gv;
  144. char m_szAppDir[PATH_MAX];
  145. std::vector<DL_LOG_ENTRY> m_logs;
  146. std::vector<DL_LOG_ENTRY> m_logsBD;
  147. pthread_t m_tidSGThread;
  148. bool m_bSGHasSizeLimitPrerequisites;
  149. bool m_bSGInProgress;
  150. bool m_bSGConfigured;
  151. unsigned long long m_nSGCurPassUTC;
  152. unsigned long long m_nSGLastPassUTC;
  153. pthread_mutex_t m_mtx;
  154. pthread_mutexattr_t m_mutexAttr;
  155. pthread_mutex_t m_condmtx1;
  156. pthread_cond_t m_cond1;
  157. time_t m_nLastLogTimestamp;
  158. bool m_bBadDateLogsDetected;
  159. };
  160. /////////////////////////////////////////////////////////////////////////////
  161. class CDataLoggerClock
  162. {
  163. public:
  164. CDataLoggerClock(unsigned long long nSampleTimeNs);
  165. virtual ~CDataLoggerClock(void);
  166. static unsigned long long GetNanoTick(struct timespec *pts = NULL);
  167. inline static unsigned long long GetMicroTick(struct timespec *pts = NULL){
  168. return GetNanoTick(pts) / 1000;}
  169. inline static unsigned long long GetMilliTick(struct timespec *pts = NULL){
  170. return GetNanoTick(pts) / 1000000;}
  171. inline static unsigned long long Timespec2NanoSec(const struct timespec *pts){
  172. return (unsigned long long)pts->tv_sec * _DL_NANOSECS_PER_SEC + (unsigned long long)pts-> tv_nsec;}
  173. inline static void NanoSec2Timespec(unsigned long long n, struct timespec *pts){
  174. if(pts){
  175. pts->tv_sec = n / _DL_NANOSECS_PER_SEC;
  176. pts->tv_nsec = n % _DL_NANOSECS_PER_SEC;
  177. }}
  178. inline static long long CompareTimespec(const struct timespec *pts1, const struct timespec *pts2){
  179. unsigned long long n1 = Timespec2NanoSec(pts1);
  180. unsigned long long n2 = Timespec2NanoSec(pts2);
  181. return (long long)(n1 - n2);}
  182. bool Sleep(bool &bTimerUnderrun, bool fAvoidCatchUpRaceOnTimerUnderrun);
  183. private:
  184. inline unsigned long long IncTime(struct timespec *pts, long long ns) const {
  185. unsigned long long n = Timespec2NanoSec(pts);
  186. n += ns;
  187. NanoSec2Timespec(n, pts);
  188. return n;}
  189. private:
  190. struct timespec m_tsDueTime;
  191. bool m_fSleepStarted;
  192. const long long m_nSampleTimeNs;
  193. };
  194. /////////////////////////////////////////////////////////////////////////////
  195. #endif // !defined(AGD_DATALOGGER_H__21BAEB7B_E478_4ED1_B9F6_FDBCE620C55B__INCLUDED_)