remvar.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. #include "remvar.h"
  2. /////////////////////////////////////////////////////////////////////////////
  3. CRemVariable::CRemVariable(void *pData, const std::type_info &rti, HSHM hShm, bool bIsDbPersitent, const char *pszName, int nIndex, CRemanent *pParent)
  4. : m_name(pszName), m_pszPath(NULL), m_nIndex(nIndex), m_vt(VT_Invalid), m_data({NULL}), m_pParent(pParent), m_nUpdates(0), m_fLogValue(0.0),
  5. m_bMustLog(false), m_bIsDbPersitent(bIsDbPersitent), m_nCbVarpath(0)
  6. {
  7. if(!pData || !hShm)
  8. {
  9. ASSERT(false);
  10. return;
  11. }
  12. m_data.pVoid = pData;
  13. m_hShm = hShm;
  14. if(rti == typeid(bool))
  15. {
  16. m_vt = VT_bool;
  17. m_cache.boolVal = *m_data.pBool;
  18. }
  19. else if(rti == typeid(char))
  20. {
  21. #ifdef __CHAR_UNSIGNED__
  22. m_vt = VT_UI1;
  23. m_cache.UI1Val = *m_data.pUI1;
  24. #else
  25. m_vt = VT_I1;
  26. m_cache.I1Val = *m_data.pI1;
  27. #endif
  28. }
  29. else if(rti == typeid(signed char))
  30. {
  31. m_vt = VT_I1;
  32. m_cache.I1Val = *m_data.pI1;
  33. }
  34. else if(rti == typeid(unsigned char))
  35. {
  36. m_vt = VT_UI1;
  37. m_cache.UI1Val = *m_data.pUI1;
  38. }
  39. else if(rti == typeid(short))
  40. {
  41. m_vt = VT_I2;
  42. m_cache.I2Val = *m_data.pI2;
  43. }
  44. else if(rti == typeid(unsigned short))
  45. {
  46. m_vt = VT_UI2;
  47. m_cache.UI2Val = *m_data.pUI2;
  48. }
  49. else if(rti == typeid(int))
  50. {
  51. m_vt = VT_I4;
  52. m_cache.I4Val = *m_data.pI4;
  53. }
  54. else if(rti == typeid(unsigned int))
  55. {
  56. m_vt = VT_UI4;
  57. m_cache.UI4Val = *m_data.pUI4;
  58. }
  59. else if(rti == typeid(long))
  60. {
  61. if(sizeof(long) == sizeof(long long))
  62. {
  63. m_vt = VT_I8;
  64. m_cache.I8Val = *m_data.pI8;
  65. }
  66. else
  67. {
  68. m_vt = VT_I4;
  69. m_cache.I4Val = *m_data.pI4;
  70. }
  71. }
  72. else if(rti == typeid(unsigned long))
  73. {
  74. if(sizeof(unsigned long) == sizeof(unsigned long long))
  75. {
  76. m_vt = VT_UI8;
  77. m_cache.UI8Val = *m_data.pUI8;
  78. }
  79. else
  80. {
  81. m_vt = VT_UI4;
  82. m_cache.UI4Val = *m_data.pUI4;
  83. }
  84. }
  85. else if(rti == typeid(long long))
  86. {
  87. m_vt = VT_I8;
  88. m_cache.I8Val = *m_data.pI8;
  89. }
  90. else if(rti == typeid(unsigned long long))
  91. {
  92. m_vt = VT_UI8;
  93. m_cache.UI8Val = *m_data.pUI8;
  94. }
  95. else if(rti == typeid(float))
  96. {
  97. m_vt = VT_float;
  98. m_cache.FloatVal = *m_data.pFloat;
  99. }
  100. else if(rti == typeid(double))
  101. {
  102. m_vt = VT_double;
  103. m_cache.DoubleVal = *m_data.pDouble;
  104. }
  105. else
  106. {
  107. ASSERT(false);
  108. }
  109. }
  110. CRemVariable::~CRemVariable(void)
  111. {
  112. }
  113. /////////////////////////////////////////////////////////////////////////////
  114. void CRemVariable::InitPath(CRemanent *pParent, const char *pszMemberName)
  115. {
  116. if(!pszMemberName)
  117. pszMemberName = "";
  118. if(pParent)
  119. {
  120. m_path = pParent->GetPath();
  121. if(m_path.size() > 0)
  122. m_path += "/";
  123. m_path += pszMemberName;
  124. if(m_nIndex >= 0)
  125. {
  126. char szIndex[32];
  127. sprintf(szIndex, "[%d]", m_nIndex);
  128. m_path += szIndex;
  129. }
  130. }
  131. else
  132. {
  133. m_path = pszMemberName;
  134. }
  135. m_pszPath = m_path.c_str();
  136. m_nCbVarpath = m_path.length();
  137. }
  138. bool CRemVariable::SaveJSON(FILE *f, int nIndent, bool bValueOnly, bool bWriteComma)
  139. {
  140. if(m_bIsDbPersitent)
  141. return true;
  142. if(bWriteComma)
  143. {
  144. if(fprintf(f, ",") < 0)
  145. return false;
  146. }
  147. if(!bValueOnly)
  148. {
  149. if(fprintf(f, "\n") < 0)
  150. return false;
  151. if(nIndent > 0)
  152. {
  153. if(fprintf(f, "%*s", nIndent * _JSON_SPACES_PER_TAB, "") < 0)
  154. return false;
  155. }
  156. }
  157. if(!bValueOnly)
  158. {
  159. if(fprintf(f, "\"%s\": ", m_name.c_str()) < 0)
  160. return false;
  161. }
  162. switch(m_vt)
  163. {
  164. case VT_bool:
  165. if(fprintf(f, "%s", m_cache.boolVal ? "true" : "false") < 0)
  166. return false;
  167. break;
  168. case VT_I1:
  169. if(fprintf(f, "%hhd", m_cache.I1Val) < 0)
  170. return false;
  171. break;
  172. case VT_UI1:
  173. if(fprintf(f, "%hhu", m_cache.UI1Val) < 0)
  174. return false;
  175. break;
  176. case VT_I2:
  177. if(fprintf(f, "%hd", m_cache.I2Val) < 0)
  178. return false;
  179. break;
  180. case VT_UI2:
  181. if(fprintf(f, "%hu", m_cache.UI2Val) < 0)
  182. return false;
  183. break;
  184. case VT_I4:
  185. if(fprintf(f, "%d", m_cache.I4Val) < 0)
  186. return false;
  187. break;
  188. case VT_UI4:
  189. if(fprintf(f, "%u", m_cache.UI4Val) < 0)
  190. return false;
  191. break;
  192. case VT_I8:
  193. if(fprintf(f, "%lld", m_cache.I8Val) < 0)
  194. return false;
  195. break;
  196. case VT_UI8:
  197. if(fprintf(f, "%llu", m_cache.UI8Val) < 0)
  198. return false;
  199. break;
  200. case VT_float:
  201. if(fprintf(f, "%.10g", m_cache.FloatVal) < 0)
  202. return false;
  203. break;
  204. case VT_double:
  205. if(fprintf(f, "%.20g", m_cache.DoubleVal) < 0)
  206. return false;
  207. break;
  208. default:
  209. break;
  210. }
  211. return true;
  212. }
  213. void CRemVariable::CreateMembersTable(CRemVarTable &vt)
  214. {
  215. vt.AddVar(static_cast<CRemanent*>(this));
  216. }
  217. bool CRemVariable::SetJSONValue(const Json::Value &jv, bool fLock)
  218. {
  219. switch(jv.type())
  220. {
  221. case Json::booleanValue:
  222. if(m_vt == VT_bool)
  223. {
  224. m_cache.boolVal = jv.asBool();
  225. if(fLock) Lock();
  226. *m_data.pBool = m_cache.boolVal;
  227. if(fLock) Unlock();
  228. }
  229. else
  230. return false;
  231. break;
  232. case Json::intValue:
  233. switch(m_vt)
  234. {
  235. case VT_I1:
  236. m_cache.I1Val = jv.asInt();
  237. if(fLock) Lock();
  238. *m_data.pI1 = m_cache.I1Val;
  239. if(fLock) Unlock();
  240. break;
  241. case VT_UI1:
  242. m_cache.UI1Val = jv.asInt();
  243. if(fLock) Lock();
  244. *m_data.pUI1 = m_cache.UI1Val;
  245. if(fLock) Unlock();
  246. break;
  247. case VT_I2:
  248. m_cache.I2Val = jv.asInt();
  249. if(fLock) Lock();
  250. *m_data.pI2 = m_cache.I2Val;
  251. if(fLock) Unlock();
  252. break;
  253. case VT_UI2:
  254. m_cache.UI2Val = jv.asInt();
  255. if(fLock) Lock();
  256. *m_data.pUI2 = m_cache.UI2Val;
  257. if(fLock) Unlock();
  258. break;
  259. case VT_I4:
  260. m_cache.I4Val = jv.asInt();
  261. if(fLock) Lock();
  262. *m_data.pI4 = m_cache.I4Val;
  263. if(fLock) Unlock();
  264. break;
  265. case VT_UI4:
  266. m_cache.UI4Val = jv.asUInt();
  267. if(fLock) Lock();
  268. *m_data.pUI4 = m_cache.UI4Val;
  269. if(fLock) Unlock();
  270. break;
  271. case VT_I8:
  272. m_cache.I8Val = jv.asInt64();
  273. if(fLock) Lock();
  274. *m_data.pI8 = m_cache.I8Val;
  275. if(fLock) Unlock();
  276. break;
  277. case VT_UI8:
  278. m_cache.UI8Val = jv.asUInt64();
  279. if(fLock) Lock();
  280. *m_data.pUI8 = m_cache.UI8Val;
  281. if(fLock) Unlock();
  282. break;
  283. case VT_float:
  284. m_cache.FloatVal = jv.asFloat();
  285. if(fLock) Lock();
  286. *m_data.pFloat = m_cache.FloatVal;
  287. if(fLock) Unlock();
  288. break;
  289. case VT_double:
  290. m_cache.DoubleVal = jv.asDouble();
  291. if(fLock) Lock();
  292. *m_data.pDouble = m_cache.DoubleVal;
  293. if(fLock) Unlock();
  294. break;
  295. default:
  296. return false;
  297. }
  298. break;
  299. case Json::uintValue:
  300. switch(m_vt)
  301. {
  302. case VT_UI1:
  303. m_cache.UI1Val = jv.asUInt();
  304. if(fLock) Lock();
  305. *m_data.pUI1 = m_cache.UI1Val;
  306. if(fLock) Unlock();
  307. break;
  308. case VT_UI2:
  309. m_cache.UI2Val = jv.asUInt();
  310. if(fLock) Lock();
  311. *m_data.pUI2 = m_cache.UI2Val;
  312. if(fLock) Unlock();
  313. break;
  314. case VT_UI4:
  315. m_cache.UI4Val = jv.asUInt();
  316. if(fLock) Lock();
  317. *m_data.pUI4 = m_cache.UI4Val;
  318. if(fLock) Unlock();
  319. break;
  320. case VT_UI8:
  321. m_cache.UI8Val = jv.asUInt64();
  322. if(fLock) Lock();
  323. *m_data.pUI8 = m_cache.UI8Val;
  324. if(fLock) Unlock();
  325. break;
  326. case VT_float:
  327. m_cache.FloatVal = jv.asFloat();
  328. if(fLock) Lock();
  329. *m_data.pFloat = m_cache.FloatVal;
  330. if(fLock) Unlock();
  331. break;
  332. case VT_double:
  333. m_cache.DoubleVal = jv.asDouble();
  334. if(fLock) Lock();
  335. *m_data.pDouble = m_cache.DoubleVal;
  336. if(fLock) Unlock();
  337. break;
  338. default:
  339. return false;
  340. }
  341. break;
  342. case Json::realValue:
  343. switch(m_vt)
  344. {
  345. case VT_float:
  346. m_cache.FloatVal = jv.asFloat();
  347. if(fLock) Lock();
  348. *m_data.pFloat = m_cache.FloatVal;
  349. if(fLock) Unlock();
  350. break;
  351. case VT_double:
  352. m_cache.DoubleVal = jv.asDouble();
  353. if(fLock) Lock();
  354. *m_data.pDouble = m_cache.DoubleVal;
  355. if(fLock) Unlock();
  356. break;
  357. default:
  358. return false;
  359. }
  360. break;
  361. default:
  362. return false;
  363. }
  364. return true;
  365. }
  366. bool CRemVariable::SetDoubleValue(double val, bool fLock)
  367. {
  368. switch(m_vt)
  369. {
  370. case VT_bool:
  371. m_cache.boolVal = !!val;
  372. if(fLock) Lock();
  373. *m_data.pBool = m_cache.boolVal;
  374. if(fLock) Unlock();
  375. break;
  376. case VT_I1:
  377. m_cache.I1Val = (signed char)val;
  378. if(fLock) Lock();
  379. *m_data.pI1 = m_cache.I1Val;
  380. if(fLock) Unlock();
  381. break;
  382. case VT_UI1:
  383. m_cache.UI1Val = (unsigned char)val;
  384. if(fLock) Lock();
  385. *m_data.pUI1 = m_cache.UI1Val;
  386. if(fLock) Unlock();
  387. break;
  388. case VT_I2:
  389. m_cache.I2Val = (signed short)val;
  390. if(fLock) Lock();
  391. *m_data.pI2 = m_cache.I2Val;
  392. if(fLock) Unlock();
  393. break;
  394. case VT_UI2:
  395. m_cache.UI2Val = (unsigned short)val;
  396. if(fLock) Lock();
  397. *m_data.pUI2 = m_cache.UI2Val;
  398. if(fLock) Unlock();
  399. break;
  400. case VT_I4:
  401. m_cache.I4Val = (signed int)val;
  402. if(fLock) Lock();
  403. *m_data.pI4 = m_cache.I4Val;
  404. if(fLock) Unlock();
  405. break;
  406. case VT_UI4:
  407. m_cache.UI4Val = (unsigned int)val;
  408. if(fLock) Lock();
  409. *m_data.pUI4 = m_cache.UI4Val;
  410. if(fLock) Unlock();
  411. break;
  412. case VT_I8:
  413. m_cache.I8Val = (signed long long)val;
  414. if(fLock) Lock();
  415. *m_data.pI8 = m_cache.I8Val;
  416. if(fLock) Unlock();
  417. break;
  418. case VT_UI8:
  419. m_cache.UI8Val = (unsigned long long)val;
  420. if(fLock) Lock();
  421. *m_data.pUI8 = m_cache.UI8Val;
  422. if(fLock) Unlock();
  423. break;
  424. case VT_float:
  425. m_cache.FloatVal = (float)val;
  426. if(fLock) Lock();
  427. *m_data.pFloat = m_cache.FloatVal;
  428. if(fLock) Unlock();
  429. break;
  430. case VT_double:
  431. m_cache.DoubleVal = val;
  432. if(fLock) Lock();
  433. *m_data.pDouble = m_cache.DoubleVal;
  434. if(fLock) Unlock();
  435. break;
  436. default:
  437. return false;
  438. }
  439. return true;
  440. }
  441. unsigned long long CRemVariable::CheckUpdateShm(bool fLock)
  442. {
  443. CHECK_UPDATE_SHM_RETVAL rv = {1, 0};
  444. if(m_bIsDbPersitent)
  445. return rv.nRetval;
  446. if(fLock)
  447. Lock();
  448. switch(m_vt)
  449. {
  450. case VT_bool:
  451. if(m_cache.boolVal != *m_data.pBool)
  452. {
  453. m_cache.boolVal = *m_data.pBool;
  454. m_fLogValue = m_cache.boolVal ? 1.0 : 0.0;
  455. rv.nUpdated = 1;
  456. }
  457. break;
  458. case VT_I1:
  459. if(m_cache.I1Val != *m_data.pI1)
  460. {
  461. m_cache.I1Val = *m_data.pI1;
  462. m_fLogValue = (double)m_cache.I1Val;
  463. rv.nUpdated = 1;
  464. }
  465. break;
  466. case VT_UI1:
  467. if(m_cache.UI1Val != *m_data.pUI1)
  468. {
  469. m_cache.UI1Val = *m_data.pUI1;
  470. m_fLogValue = (double)m_cache.UI1Val;
  471. rv.nUpdated = 1;
  472. }
  473. break;
  474. case VT_I2:
  475. if(m_cache.I2Val != *m_data.pI2)
  476. {
  477. m_cache.I2Val = *m_data.pI2;
  478. m_fLogValue = (double)m_cache.I2Val;
  479. rv.nUpdated = 1;
  480. }
  481. break;
  482. case VT_UI2:
  483. if(m_cache.UI2Val != *m_data.pUI2)
  484. {
  485. m_cache.UI2Val = *m_data.pUI2;
  486. m_fLogValue = (double)m_cache.UI2Val;
  487. rv.nUpdated = 1;
  488. }
  489. break;
  490. case VT_I4:
  491. if(m_cache.I4Val != *m_data.pI4)
  492. {
  493. m_cache.I4Val = *m_data.pI4;
  494. m_fLogValue = (double)m_cache.I4Val;
  495. rv.nUpdated = 1;
  496. }
  497. break;
  498. case VT_UI4:
  499. if(m_cache.UI4Val != *m_data.pUI4)
  500. {
  501. m_cache.UI4Val = *m_data.pUI4;
  502. m_fLogValue = (double)m_cache.UI4Val;
  503. rv.nUpdated = 1;
  504. }
  505. break;
  506. case VT_I8:
  507. if(m_cache.I8Val != *m_data.pI8)
  508. {
  509. m_cache.I8Val = *m_data.pI8;
  510. m_fLogValue = (double)m_cache.I8Val;
  511. rv.nUpdated = 1;
  512. }
  513. break;
  514. case VT_UI8:
  515. if(m_cache.UI8Val != *m_data.pUI8)
  516. {
  517. m_cache.UI8Val = *m_data.pUI8;
  518. m_fLogValue = (double)m_cache.UI8Val;
  519. rv.nUpdated = 1;
  520. }
  521. break;
  522. case VT_float:
  523. if(m_cache.FloatVal != *m_data.pFloat)
  524. {
  525. m_cache.FloatVal = *m_data.pFloat;
  526. m_fLogValue = (double)m_cache.FloatVal;
  527. rv.nUpdated = 1;
  528. }
  529. break;
  530. case VT_double:
  531. if(m_cache.DoubleVal != *m_data.pDouble)
  532. {
  533. m_cache.DoubleVal = *m_data.pDouble;
  534. m_fLogValue = m_cache.DoubleVal;
  535. rv.nUpdated = 1;
  536. }
  537. break;
  538. default:
  539. rv.nUpdated = 0;
  540. break;
  541. }
  542. if(fLock)
  543. Unlock();
  544. if(rv.nUpdated)
  545. {
  546. m_bMustLog = true;
  547. m_nUpdates++;
  548. }
  549. return rv.nRetval;
  550. }
  551. void CRemVariable::Log(time_t ts, CRemLogger &rlogger)
  552. {
  553. if(!m_bIsDbPersitent && m_bMustLog)
  554. {
  555. rlogger.Log(m_pszPath, m_nCbVarpath, m_fLogValue, NULL, 0, ts, true);
  556. m_bMustLog = false;
  557. }
  558. }
  559. void CRemVariable::Lock(void)
  560. {
  561. ::GfaIpcLockSHM(m_hShm);
  562. }
  563. void CRemVariable::Unlock(void)
  564. {
  565. ::GfaIpcUnlockSHM(m_hShm);
  566. }