#include "remvar.h" #define GET_BOOL_VAL(p, m) (!!(*p & m)) #define SET_BIT(p, m) (*p |= m) #define CLR_BIT(p, m) (*p &= ~m) #define STORE_BIT(p, m, b) (b) ? SET_BIT(p, m) : CLR_BIT(p, m) ///////////////////////////////////////////////////////////////////////////// CRemBitVariable::CRemBitVariable(void *pData, size_t nOffset, int nBitNr, HSHM hShm, bool bIsDbPersitent, const char *pszName, CRemanent *pParent) : m_name(pszName), m_pszPath(NULL), m_hShm(hShm), m_pParent(pParent), m_nUpdates(0), m_fLogValue(0.0), m_bMustLog(false), m_bIsDbPersitent(bIsDbPersitent), m_nCbVarpath(0) { if(!pData || !hShm || (nBitNr > 7)) { ASSERT(false); return; } m_mask = (1 << nBitNr); m_pShmByte = (uint8_t*)pData + nOffset; Lock(); m_cacheVal = GET_BOOL_VAL(m_pShmByte, m_mask); Unlock(); } CRemBitVariable::~CRemBitVariable(void) { } ///////////////////////////////////////////////////////////////////////////// void CRemBitVariable::InitPath(CRemanent *pParent, const char *pszMemberName) { if(!pszMemberName) pszMemberName = ""; if(pParent) { m_path = pParent->GetPath(); if(m_path.size() > 0) m_path += "/"; m_path += pszMemberName; } else { m_path = pszMemberName; } m_pszPath = m_path.c_str(); m_nCbVarpath = m_path.length(); } bool CRemBitVariable::SaveJSON(FILE *f, int nIndent, bool bValueOnly, bool bWriteComma) { if(m_bIsDbPersitent) return true; if(bWriteComma) { if(fprintf(f, ",") < 0) return false; } if(!bValueOnly) { if(fprintf(f, "\n") < 0) return false; if(nIndent > 0) { if(fprintf(f, "%*s", nIndent * _JSON_SPACES_PER_TAB, "") < 0) return false; } if(fprintf(f, "\"%s\": ", m_name.c_str()) < 0) return false; } if(fprintf(f, "%s", m_cacheVal ? "true" : "false") < 0) return false; return true; } void CRemBitVariable::CreateMembersTable(CRemVarTable &vt) { if(!m_bIsDbPersitent) vt.AddVar(static_cast(this)); } bool CRemBitVariable::SetJSONValue(const Json::Value &jv, bool fLock) { bool bRet = true; if(fLock) Lock(); switch(jv.type()) { case Json::booleanValue: m_cacheVal = jv.asBool(); break; case Json::intValue: m_cacheVal = !!jv.asInt(); break; default: bRet = false; } if(bRet) { STORE_BIT(m_pShmByte, m_mask, m_cacheVal); } if(fLock) Unlock(); return bRet; } bool CRemBitVariable::SetDoubleValue(double val, bool fLock) { m_cacheVal = !!val; if(fLock) Lock(); STORE_BIT(m_pShmByte, m_mask, m_cacheVal); if(fLock) Unlock(); return true; } unsigned long long CRemBitVariable::CheckUpdateShm(bool fLock) { bool bVal; CHECK_UPDATE_SHM_RETVAL rv = {1, 0}; if(m_bIsDbPersitent) return rv.nRetval; if(fLock) Lock(); bVal = GET_BOOL_VAL(m_pShmByte, m_mask); if(m_cacheVal != bVal) { m_cacheVal = bVal; m_fLogValue = m_cacheVal ? 1.0 : 0.0; rv.nUpdated = 1; } if(fLock) Unlock(); if(rv.nUpdated) { m_bMustLog = true; m_nUpdates++; } return rv.nRetval; } void CRemBitVariable::Log(time_t ts, CRemLogger &rlogger) { if(!m_bIsDbPersitent && m_bMustLog) { rlogger.Log(m_pszPath, m_nCbVarpath, m_fLogValue, NULL, 0, ts, true); m_bMustLog = false; } } void CRemBitVariable::Lock(void) { ::GfaIpcLockSHM(m_hShm); } void CRemBitVariable::Unlock(void) { ::GfaIpcUnlockSHM(m_hShm); }