#include #include #include "logvar.h" #include "debug.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) ///////////////////////////////////////////////////////////////////////////// CLogBitVariable::CLogBitVariable(LogTypes lt, void *pData, size_t nOffset, unsigned int nBitNr, bool *pbLogCond, HSHM hShm, const char *pszName, CLoggable *pParent) : m_lt(lt), m_pbLogCond(pbLogCond), m_bOldLogCond(false), m_name(pszName), m_pszPath(NULL), m_fLastSample(0), m_fSamples(0), m_hShm(hShm), m_pParent(pParent), m_nUpdates(0), m_nTagID(0), m_nSampleCount(0), m_bCvIsBit(false), m_bIsDbPersistant(_IS_DB_PERSISTENT_LOGTYPE(lt)) { if(!pData || !hShm || nBitNr > 7) { ASSERT(false); } m_bIsCondLog = _IS_CONDITIONAL_LOGTYPE(m_lt); m_bIsIntervalLog = _IS_INTERVAL_LOGTYPE(m_lt); if(m_bIsCondLog && !m_pbLogCond) { ASSERT(false); } m_fMin = std::numeric_limits::infinity(); m_fMax = -std::numeric_limits::infinity(); m_pnByte = (uint8_t*)pData + nOffset; m_nMask = 0x01 << nBitNr; Lock(); m_cacheVal = GET_BOOL_VAL(m_pnByte, m_nMask); Unlock(); } CLogBitVariable::CLogBitVariable(LogTypes lt, void *pData, size_t nOffset, unsigned int nBitNr, size_t nCvOffset, unsigned int nCvBitNr, HSHM hShm, const char *pszName, CLoggable *pParent) : m_lt(lt), m_pbLogCond(NULL), m_bOldLogCond(false), m_name(pszName), m_pszPath(NULL), 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)) { if(!pData || !hShm || nBitNr > 7 || nCvBitNr > 7) { ASSERT(false); } m_bIsCondLog = _IS_CONDITIONAL_LOGTYPE(m_lt); m_bIsIntervalLog = _IS_INTERVAL_LOGTYPE(m_lt); m_hShm = hShm; m_fMin = std::numeric_limits::infinity(); m_fMax = -std::numeric_limits::infinity(); m_pnByte = (uint8_t*)pData + nOffset; m_nMask = 0x01 << nBitNr; m_pnCvByte = (uint8_t*)pData + nCvOffset; m_nCvMask = 0x01 << nCvBitNr; Lock(); m_cacheVal = GET_BOOL_VAL(m_pnByte, m_nMask); Unlock(); } CLogBitVariable::~CLogBitVariable(void) { } ///////////////////////////////////////////////////////////////////////////// void CLogBitVariable::InitPath(CLoggable *pParent, const char *pszMemberName) { if(!pszMemberName) pszMemberName = ""; if(pParent) { m_path = pParent->GetPath(); m_path += "/"; m_path += pszMemberName; } else { m_path = pszMemberName; } m_pszPath = m_path.c_str(); } ///////////////////////////////////////////////////////////////////////////// void CLogBitVariable::InitTagID(CDataLogger &rdl) { if((m_nTagID = rdl.GetTagID(m_pszPath, (int)CLogVariable::VT_bool, (int)m_lt)) == ULONG_MAX) { ASSERT(false); } } ///////////////////////////////////////////////////////////////////////////// bool CLogBitVariable::CanLog(bool fLock) { if(!m_bIsCondLog) return true; bool bRet; if(fLock) Lock(); if(m_bCvIsBit) bRet = GET_BOOL_VAL(m_pnCvByte, m_nCvMask); else bRet = *m_pbLogCond; if(fLock) Unlock(); return bRet; } ///////////////////////////////////////////////////////////////////////////// void CLogBitVariable::Sample(void) { if(!m_bIsIntervalLog) return; Lock(); if(CanLog(false)) { m_fLastSample = GET_BOOL_VAL(m_pnByte, m_nMask) ? 1.0 : 0.0; if(m_fMin > m_fLastSample) m_fMin = m_fLastSample; if(m_fMax < m_fLastSample) m_fMax = m_fLastSample; m_fSamples += m_fLastSample; m_nSampleCount++; } Unlock(); } ///////////////////////////////////////////////////////////////////////////// void CLogBitVariable::LogInterval(time_t nTimestamp, CDataLogger &rdl) { if(!m_bIsIntervalLog) { m_fSamples = 0; m_nSampleCount = 0; return; } if(!CanLog(true)) { m_fSamples = 0; m_nSampleCount = 0; return; } if(m_nSampleCount > 0) { if(!m_bIsDbPersistant) { if(m_nSampleCount > 1) m_fSamples /= (double)m_nSampleCount; rdl.Log(m_nTagID, m_fSamples, m_fMin, m_fMax, nTimestamp, -1, m_lt); } else { rdl.Log(m_nTagID, m_fLastSample, m_fMin, m_fMax, nTimestamp, -1, m_lt); } } m_fSamples = 0; m_fMin = std::numeric_limits::infinity(); m_fMax = -std::numeric_limits::infinity(); m_nSampleCount = 0; } ///////////////////////////////////////////////////////////////////////////// void CLogBitVariable::LogValueChanged(time_t nTimestamp, CDataLogger &rdl, bool bStartup, bool bWriteNull) { if(m_bIsIntervalLog) return; if(bWriteNull) // force write of a NULL value and exit { rdl.Log(m_nTagID, 0.0, 0.0, 0.0, nTimestamp, -1, m_lt, true, bStartup); return; } bool val, bCondition, bConditionChanged; Lock(); if((bCondition = CanLog(false))) val = GET_BOOL_VAL(m_pnByte, m_nMask); Unlock(); bConditionChanged = (m_bOldLogCond != bCondition) || bStartup; m_bOldLogCond = bCondition; if(!bCondition && !bConditionChanged) return; if(bCondition && ((m_cacheVal != val) || bConditionChanged)) // log value, if either the value has changed or a condition transition from 0 to 1 has occured { m_cacheVal = val; double fVal = m_cacheVal ? 1.0 : 0.0; rdl.Log(m_nTagID, fVal, 0.0, 0.0, nTimestamp, -1, m_lt); } else if(!bCondition && bConditionChanged) // log a NULL value , if a condition transition from 1 to 0 has occured { rdl.Log(m_nTagID, 0.0, 0.0, 0.0, nTimestamp, -1, m_lt, true); } } ///////////////////////////////////////////////////////////////////////////// void CLogBitVariable::Lock(void) { ::GfaIpcLockSHM(m_hShm); } ///////////////////////////////////////////////////////////////////////////// void CLogBitVariable::Unlock(void) { ::GfaIpcUnlockSHM(m_hShm); }