logvar.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. #include <limits.h>
  2. #include <limits>
  3. #include "logvar.h"
  4. #include "debug.h"
  5. #define GET_BOOL_VAL(p, m) (!!(*p & m))
  6. #define SET_BIT(p, m) (*p |= m)
  7. #define CLR_BIT(p, m) (*p &= ~m)
  8. #define STORE_BIT(p, m, b) (b) ? SET_BIT(p, m) : CLR_BIT(p, m)
  9. /////////////////////////////////////////////////////////////////////////////
  10. CLogVariable::CLogVariable(LogTypes lt, void *pData, bool *pbLogCond, const std::type_info &rti, HSHM hShm, const char *pszName, int nIndex, CLoggable *pParent)
  11. : m_lt(lt), m_pbLogCond(pbLogCond), m_bOldLogCond(false), m_name(pszName), m_pszPath(NULL), m_nIndex(nIndex), m_vt(VT_Invalid), m_data({NULL}),
  12. m_fLastSample(0), m_fSamples(0), m_pParent(pParent), m_nUpdates(0), m_nTagID(0), m_nSampleCount(0), m_pnCvByte(NULL), m_nCvMask(0), m_bCvIsBit(false), m_bIsDbPersistant(_IS_DB_PERSISTENT_LOGTYPE(lt))
  13. {
  14. if(!pData || !hShm)
  15. {
  16. ASSERT(false);
  17. }
  18. m_bIsCondLog = _IS_CONDITIONAL_LOGTYPE(m_lt);
  19. m_bIsIntervalLog = _IS_INTERVAL_LOGTYPE(m_lt);
  20. if(m_bIsCondLog && !m_pbLogCond)
  21. {
  22. ASSERT(false);
  23. }
  24. m_data.pVoid = pData;
  25. m_hShm = hShm;
  26. m_fMin = std::numeric_limits<double>::infinity();
  27. m_fMax = -std::numeric_limits<double>::infinity();
  28. if(rti == typeid(bool))
  29. {
  30. m_vt = VT_bool;
  31. m_cache.boolVal = *m_data.pBool;
  32. }
  33. else if(rti == typeid(char))
  34. {
  35. #ifdef __CHAR_UNSIGNED__
  36. m_vt = VT_UI1;
  37. m_cache.UI1Val = *m_data.pUI1;
  38. #else
  39. m_vt = VT_I1;
  40. m_cache.I1Val = *m_data.pI1;
  41. #endif
  42. }
  43. else if(rti == typeid(signed char))
  44. {
  45. m_vt = VT_I1;
  46. m_cache.I1Val = *m_data.pI1;
  47. }
  48. else if(rti == typeid(unsigned char))
  49. {
  50. m_vt = VT_UI1;
  51. m_cache.UI1Val = *m_data.pUI1;
  52. }
  53. else if(rti == typeid(short))
  54. {
  55. m_vt = VT_I2;
  56. m_cache.I2Val = *m_data.pI2;
  57. }
  58. else if(rti == typeid(unsigned short))
  59. {
  60. m_vt = VT_UI2;
  61. m_cache.UI2Val = *m_data.pUI2;
  62. }
  63. else if(rti == typeid(int))
  64. {
  65. m_vt = VT_I4;
  66. m_cache.I4Val = *m_data.pI4;
  67. }
  68. else if(rti == typeid(unsigned int))
  69. {
  70. m_vt = VT_UI4;
  71. m_cache.UI4Val = *m_data.pUI4;
  72. }
  73. else if(rti == typeid(long))
  74. {
  75. if(sizeof(long) == sizeof(long long))
  76. {
  77. m_vt = VT_I8;
  78. m_cache.I8Val = *m_data.pI8;
  79. }
  80. else
  81. {
  82. m_vt = VT_I4;
  83. m_cache.I4Val = *m_data.pI4;
  84. }
  85. }
  86. else if(rti == typeid(unsigned long))
  87. {
  88. if(sizeof(unsigned long) == sizeof(unsigned long long))
  89. {
  90. m_vt = VT_UI8;
  91. m_cache.UI8Val = *m_data.pUI8;
  92. }
  93. else
  94. {
  95. m_vt = VT_UI4;
  96. m_cache.UI4Val = *m_data.pUI4;
  97. }
  98. }
  99. else if(rti == typeid(long long))
  100. {
  101. m_vt = VT_I8;
  102. m_cache.I8Val = *m_data.pI8;
  103. }
  104. else if(rti == typeid(unsigned long long))
  105. {
  106. m_vt = VT_UI8;
  107. m_cache.UI8Val = *m_data.pUI8;
  108. }
  109. else if(rti == typeid(float))
  110. {
  111. m_vt = VT_float;
  112. m_cache.FloatVal = *m_data.pFloat;
  113. }
  114. else if(rti == typeid(double))
  115. {
  116. m_vt = VT_double;
  117. m_cache.DoubleVal = *m_data.pDouble;
  118. }
  119. else
  120. {
  121. ASSERT(false);
  122. }
  123. }
  124. CLogVariable::CLogVariable(LogTypes lt, void *pData, void *pBase, size_t nCvOffset, unsigned int nCvBitNr, const std::type_info &rti, HSHM hShm, const char *pszName, int nIndex, CLoggable *pParent) :
  125. m_lt(lt), m_bOldLogCond(false), m_name(pszName), m_pszPath(NULL), m_nIndex(nIndex), m_fLastSample(0), m_fSamples(0), m_pParent(pParent), m_nUpdates(0), m_nTagID(0), m_nSampleCount(0), m_bCvIsBit(true), m_bIsDbPersistant(_IS_DB_PERSISTENT_LOGTYPE(lt))
  126. {
  127. if(!pData || !hShm || nCvBitNr > 7)
  128. {
  129. ASSERT(false);
  130. }
  131. m_bIsCondLog = _IS_CONDITIONAL_LOGTYPE(m_lt);
  132. m_bIsIntervalLog = _IS_INTERVAL_LOGTYPE(m_lt);
  133. m_data.pVoid = pData;
  134. m_hShm = hShm;
  135. m_fMin = std::numeric_limits<double>::infinity();
  136. m_fMax = -std::numeric_limits<double>::infinity();
  137. m_pnCvByte = (uint8_t*)pBase + nCvOffset;
  138. m_nCvMask = 0x01 << nCvBitNr;
  139. if(rti == typeid(bool))
  140. {
  141. m_vt = VT_bool;
  142. m_cache.boolVal = *m_data.pBool;
  143. }
  144. else if(rti == typeid(char))
  145. {
  146. #ifdef __CHAR_UNSIGNED__
  147. m_vt = VT_UI1;
  148. m_cache.UI1Val = *m_data.pUI1;
  149. #else
  150. m_vt = VT_I1;
  151. m_cache.I1Val = *m_data.pI1;
  152. #endif
  153. }
  154. else if(rti == typeid(signed char))
  155. {
  156. m_vt = VT_I1;
  157. m_cache.I1Val = *m_data.pI1;
  158. }
  159. else if(rti == typeid(unsigned char))
  160. {
  161. m_vt = VT_UI1;
  162. m_cache.UI1Val = *m_data.pUI1;
  163. }
  164. else if(rti == typeid(short))
  165. {
  166. m_vt = VT_I2;
  167. m_cache.I2Val = *m_data.pI2;
  168. }
  169. else if(rti == typeid(unsigned short))
  170. {
  171. m_vt = VT_UI2;
  172. m_cache.UI2Val = *m_data.pUI2;
  173. }
  174. else if(rti == typeid(int))
  175. {
  176. m_vt = VT_I4;
  177. m_cache.I4Val = *m_data.pI4;
  178. }
  179. else if(rti == typeid(unsigned int))
  180. {
  181. m_vt = VT_UI4;
  182. m_cache.UI4Val = *m_data.pUI4;
  183. }
  184. else if(rti == typeid(long))
  185. {
  186. if(sizeof(long) == sizeof(long long))
  187. {
  188. m_vt = VT_I8;
  189. m_cache.I8Val = *m_data.pI8;
  190. }
  191. else
  192. {
  193. m_vt = VT_I4;
  194. m_cache.I4Val = *m_data.pI4;
  195. }
  196. }
  197. else if(rti == typeid(unsigned long))
  198. {
  199. if(sizeof(unsigned long) == sizeof(unsigned long long))
  200. {
  201. m_vt = VT_UI8;
  202. m_cache.UI8Val = *m_data.pUI8;
  203. }
  204. else
  205. {
  206. m_vt = VT_UI4;
  207. m_cache.UI4Val = *m_data.pUI4;
  208. }
  209. }
  210. else if(rti == typeid(long long))
  211. {
  212. m_vt = VT_I8;
  213. m_cache.I8Val = *m_data.pI8;
  214. }
  215. else if(rti == typeid(unsigned long long))
  216. {
  217. m_vt = VT_UI8;
  218. m_cache.UI8Val = *m_data.pUI8;
  219. }
  220. else if(rti == typeid(float))
  221. {
  222. m_vt = VT_float;
  223. m_cache.FloatVal = *m_data.pFloat;
  224. }
  225. else if(rti == typeid(double))
  226. {
  227. m_vt = VT_double;
  228. m_cache.DoubleVal = *m_data.pDouble;
  229. }
  230. else
  231. {
  232. ASSERT(false);
  233. }
  234. }
  235. CLogVariable::~CLogVariable(void)
  236. {
  237. }
  238. /////////////////////////////////////////////////////////////////////////////
  239. void CLogVariable::InitPath(CLoggable *pParent, const char *pszMemberName)
  240. {
  241. if(!pszMemberName)
  242. pszMemberName = "";
  243. if(pParent)
  244. {
  245. m_path = pParent->GetPath();
  246. m_path += "/";
  247. m_path += pszMemberName;
  248. if(m_nIndex >= 0)
  249. {
  250. char szIndex[32];
  251. sprintf(szIndex, "[%d]", m_nIndex);
  252. m_path += szIndex;
  253. }
  254. }
  255. else
  256. {
  257. m_path = pszMemberName;
  258. }
  259. m_pszPath = m_path.c_str();
  260. }
  261. /////////////////////////////////////////////////////////////////////////////
  262. void CLogVariable::InitTagID(CDataLogger &rdl)
  263. {
  264. if((m_nTagID = rdl.GetTagID(m_pszPath, (int)m_vt, (int)m_lt)) == ULONG_MAX)
  265. {
  266. ASSERT(false);
  267. }
  268. }
  269. /////////////////////////////////////////////////////////////////////////////
  270. bool CLogVariable::CanLog(bool fLock)
  271. {
  272. if(!m_bIsCondLog)
  273. return true;
  274. bool bRet;
  275. if(fLock)
  276. Lock();
  277. if(m_bCvIsBit)
  278. bRet = GET_BOOL_VAL(m_pnCvByte, m_nCvMask);
  279. else
  280. bRet = *m_pbLogCond;
  281. if(fLock)
  282. Unlock();
  283. return bRet;
  284. }
  285. /////////////////////////////////////////////////////////////////////////////
  286. void CLogVariable::Sample(void)
  287. {
  288. if(!m_bIsIntervalLog)
  289. return;
  290. if(!CanLog(true))
  291. return;
  292. Lock();
  293. switch(m_vt)
  294. {
  295. case VT_bool:
  296. m_fLastSample = (*m_data.pBool) ? 1.0 : 0.0;
  297. break;
  298. case VT_I1:
  299. m_fLastSample = (double)*m_data.pI1;
  300. break;
  301. case VT_UI1:
  302. m_fLastSample = (double)*m_data.pUI1;
  303. break;
  304. case VT_I2:
  305. m_fLastSample = (double)*m_data.pI2;
  306. break;
  307. case VT_UI2:
  308. m_fLastSample = (double)*m_data.pUI2;
  309. break;
  310. case VT_I4:
  311. m_fLastSample = (double)*m_data.pI4;
  312. break;
  313. case VT_UI4:
  314. m_fLastSample = (double)*m_data.pUI4;
  315. break;
  316. case VT_I8:
  317. m_fLastSample = (double)*m_data.pI8;
  318. break;
  319. case VT_UI8:
  320. m_fLastSample = (double)*m_data.pUI8;
  321. break;
  322. case VT_float:
  323. m_fLastSample = (double)*m_data.pFloat;
  324. break;
  325. case VT_double:
  326. m_fLastSample = *m_data.pDouble;
  327. break;
  328. default:
  329. Unlock();
  330. ASSERT(false);
  331. return;
  332. }
  333. if(m_fMin > m_fLastSample)
  334. m_fMin = m_fLastSample;
  335. if(m_fMax < m_fLastSample)
  336. m_fMax = m_fLastSample;
  337. m_fSamples += m_fLastSample;
  338. m_nSampleCount++;
  339. Unlock();
  340. }
  341. /////////////////////////////////////////////////////////////////////////////
  342. void CLogVariable::LogInterval(time_t nTimestamp, CDataLogger &rdl)
  343. {
  344. if(!m_bIsIntervalLog)
  345. {
  346. m_fSamples = 0;
  347. m_nSampleCount = 0;
  348. return;
  349. }
  350. if(!CanLog(true))
  351. {
  352. m_fSamples = 0;
  353. m_nSampleCount = 0;
  354. return;
  355. }
  356. if(m_nSampleCount > 0)
  357. {
  358. if(!m_bIsDbPersistant)
  359. {
  360. if(m_nSampleCount > 1)
  361. m_fSamples /= (double)m_nSampleCount;
  362. rdl.Log(m_nTagID, m_fSamples, m_fMin, m_fMax, nTimestamp, m_nIndex, m_lt);
  363. }
  364. else
  365. {
  366. rdl.Log(m_nTagID, m_fLastSample, m_fMin, m_fMax, nTimestamp, m_nIndex, m_lt);
  367. }
  368. }
  369. m_fSamples = 0;
  370. m_fMin = std::numeric_limits<double>::infinity();
  371. m_fMax = -std::numeric_limits<double>::infinity();
  372. m_nSampleCount = 0;
  373. }
  374. /////////////////////////////////////////////////////////////////////////////
  375. void CLogVariable::LogValueChanged(time_t nTimestamp, CDataLogger &rdl, bool bStartup, bool bWriteNull)
  376. {
  377. if(m_bIsIntervalLog)
  378. return;
  379. if(bWriteNull) // force write of a NULL value and exit
  380. {
  381. rdl.Log(m_nTagID, 0.0, 0.0, 0.0, nTimestamp, m_nIndex, m_lt, true, bStartup);
  382. return;
  383. }
  384. double val;
  385. bool bCondition, bConditionChanged, bDoLog = false;
  386. bCondition = CanLog(true);
  387. bConditionChanged = (m_bOldLogCond != bCondition) || bStartup;
  388. m_bOldLogCond = bCondition;
  389. if(!bCondition && !bConditionChanged)
  390. return;
  391. Lock();
  392. switch(m_vt)
  393. {
  394. case VT_bool:
  395. if(bCondition && ((m_cache.boolVal != *m_data.pBool) || bConditionChanged)) // log, if either the value has changed or a condition transition from 0 to 1 has occured
  396. {
  397. m_cache.boolVal = *m_data.pBool;
  398. val = m_cache.boolVal ? 1.0 : 0.0;
  399. bDoLog = true;
  400. }
  401. break;
  402. case VT_I1:
  403. if(bCondition && ((m_cache.I1Val != *m_data.pI1) || bConditionChanged))
  404. {
  405. m_cache.I1Val = *m_data.pI1;
  406. val = (double)m_cache.I1Val;
  407. bDoLog = true;
  408. }
  409. break;
  410. case VT_UI1:
  411. if(bCondition && ((m_cache.UI1Val != *m_data.pUI1) || bConditionChanged))
  412. {
  413. m_cache.UI1Val = *m_data.pUI1;
  414. val = (double)m_cache.UI1Val;
  415. bDoLog = true;
  416. }
  417. break;
  418. case VT_I2:
  419. if(bCondition && ((m_cache.I2Val != *m_data.pI2) || bConditionChanged))
  420. {
  421. m_cache.I2Val = *m_data.pI2;
  422. val = (double)m_cache.I2Val;
  423. bDoLog = true;
  424. }
  425. break;
  426. case VT_UI2:
  427. if(bCondition && ((m_cache.UI2Val != *m_data.pUI2) || bConditionChanged))
  428. {
  429. m_cache.UI2Val = *m_data.pUI2;
  430. val = (double)m_cache.UI2Val;
  431. bDoLog = true;
  432. }
  433. break;
  434. case VT_I4:
  435. if(bCondition && ((m_cache.I4Val != *m_data.pI4) || bConditionChanged))
  436. {
  437. m_cache.I4Val = *m_data.pI4;
  438. val = (double)m_cache.I4Val;
  439. bDoLog = true;
  440. }
  441. break;
  442. case VT_UI4:
  443. if(bCondition && ((m_cache.UI4Val != *m_data.pUI4) || bConditionChanged))
  444. {
  445. m_cache.UI4Val = *m_data.pUI4;
  446. val = (double)m_cache.UI4Val;
  447. bDoLog = true;
  448. }
  449. break;
  450. case VT_I8:
  451. if(bCondition && ((m_cache.I8Val != *m_data.pI8) || bConditionChanged))
  452. {
  453. m_cache.I8Val = *m_data.pI8;
  454. val = (double)m_cache.I8Val;
  455. bDoLog = true;
  456. }
  457. break;
  458. case VT_UI8:
  459. if(bCondition && ((m_cache.UI8Val != *m_data.pUI8) || bConditionChanged))
  460. {
  461. m_cache.UI8Val = *m_data.pUI8;
  462. val = (double)m_cache.UI8Val;
  463. bDoLog = true;
  464. }
  465. break;
  466. case VT_float:
  467. if(bCondition && ((m_cache.FloatVal != *m_data.pFloat) || bConditionChanged))
  468. {
  469. m_cache.FloatVal = *m_data.pFloat;
  470. val = (double)m_cache.FloatVal;
  471. bDoLog = true;
  472. }
  473. break;
  474. case VT_double:
  475. if(bCondition && ((m_cache.DoubleVal != *m_data.pDouble) || bConditionChanged))
  476. {
  477. m_cache.DoubleVal = *m_data.pDouble;
  478. val = m_cache.DoubleVal;
  479. bDoLog = true;
  480. }
  481. break;
  482. default:
  483. ASSERT(false);
  484. break;
  485. }
  486. Unlock();
  487. if(bDoLog) // log value, if either the value has changed or a condition transition from 0 to 1 has occured
  488. {
  489. rdl.Log(m_nTagID, val, 0.0, 0.0, nTimestamp, m_nIndex, m_lt);
  490. }
  491. else if(!bCondition && bConditionChanged) // log a NULL value , if a condition transition from 1 to 0 has occured
  492. {
  493. rdl.Log(m_nTagID, 0.0, 0.0, 0.0, nTimestamp, m_nIndex, m_lt, true);
  494. }
  495. }
  496. /////////////////////////////////////////////////////////////////////////////
  497. void CLogVariable::Lock(void)
  498. {
  499. ::GfaIpcLockSHM(m_hShm);
  500. }
  501. /////////////////////////////////////////////////////////////////////////////
  502. void CLogVariable::Unlock(void)
  503. {
  504. ::GfaIpcUnlockSHM(m_hShm);
  505. }