#include "remvar.h" ///////////////////////////////////////////////////////////////////////////// CRemVariable::CRemVariable(void *pData, const std::type_info &rti, HSHM hShm, bool bIsDbPersitent, const char *pszName, int nIndex, CRemanent *pParent) : 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), m_bMustLog(false), m_bIsDbPersitent(bIsDbPersitent), m_nCbVarpath(0) { if(!pData || !hShm) { ASSERT(false); return; } m_data.pVoid = pData; m_hShm = hShm; if(rti == typeid(bool)) { m_vt = VT_bool; m_cache.boolVal = *m_data.pBool; } else if(rti == typeid(char)) { #ifdef __CHAR_UNSIGNED__ m_vt = VT_UI1; m_cache.UI1Val = *m_data.pUI1; #else m_vt = VT_I1; m_cache.I1Val = *m_data.pI1; #endif } else if(rti == typeid(signed char)) { m_vt = VT_I1; m_cache.I1Val = *m_data.pI1; } else if(rti == typeid(unsigned char)) { m_vt = VT_UI1; m_cache.UI1Val = *m_data.pUI1; } else if(rti == typeid(short)) { m_vt = VT_I2; m_cache.I2Val = *m_data.pI2; } else if(rti == typeid(unsigned short)) { m_vt = VT_UI2; m_cache.UI2Val = *m_data.pUI2; } else if(rti == typeid(int)) { m_vt = VT_I4; m_cache.I4Val = *m_data.pI4; } else if(rti == typeid(unsigned int)) { m_vt = VT_UI4; m_cache.UI4Val = *m_data.pUI4; } else if(rti == typeid(long)) { if(sizeof(long) == sizeof(long long)) { m_vt = VT_I8; m_cache.I8Val = *m_data.pI8; } else { m_vt = VT_I4; m_cache.I4Val = *m_data.pI4; } } else if(rti == typeid(unsigned long)) { if(sizeof(unsigned long) == sizeof(unsigned long long)) { m_vt = VT_UI8; m_cache.UI8Val = *m_data.pUI8; } else { m_vt = VT_UI4; m_cache.UI4Val = *m_data.pUI4; } } else if(rti == typeid(long long)) { m_vt = VT_I8; m_cache.I8Val = *m_data.pI8; } else if(rti == typeid(unsigned long long)) { m_vt = VT_UI8; m_cache.UI8Val = *m_data.pUI8; } else if(rti == typeid(float)) { m_vt = VT_float; m_cache.FloatVal = *m_data.pFloat; } else if(rti == typeid(double)) { m_vt = VT_double; m_cache.DoubleVal = *m_data.pDouble; } else { ASSERT(false); } } CRemVariable::~CRemVariable(void) { } ///////////////////////////////////////////////////////////////////////////// void CRemVariable::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; if(m_nIndex >= 0) { char szIndex[32]; sprintf(szIndex, "[%d]", m_nIndex); m_path += szIndex; } } else { m_path = pszMemberName; } m_pszPath = m_path.c_str(); m_nCbVarpath = m_path.length(); } bool CRemVariable::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(!bValueOnly) { if(fprintf(f, "\"%s\": ", m_name.c_str()) < 0) return false; } switch(m_vt) { case VT_bool: if(fprintf(f, "%s", m_cache.boolVal ? "true" : "false") < 0) return false; break; case VT_I1: if(fprintf(f, "%hhd", m_cache.I1Val) < 0) return false; break; case VT_UI1: if(fprintf(f, "%hhu", m_cache.UI1Val) < 0) return false; break; case VT_I2: if(fprintf(f, "%hd", m_cache.I2Val) < 0) return false; break; case VT_UI2: if(fprintf(f, "%hu", m_cache.UI2Val) < 0) return false; break; case VT_I4: if(fprintf(f, "%d", m_cache.I4Val) < 0) return false; break; case VT_UI4: if(fprintf(f, "%u", m_cache.UI4Val) < 0) return false; break; case VT_I8: if(fprintf(f, "%lld", m_cache.I8Val) < 0) return false; break; case VT_UI8: if(fprintf(f, "%llu", m_cache.UI8Val) < 0) return false; break; case VT_float: if(fprintf(f, "%.10g", m_cache.FloatVal) < 0) return false; break; case VT_double: if(fprintf(f, "%.20g", m_cache.DoubleVal) < 0) return false; break; default: break; } return true; } void CRemVariable::CreateMembersTable(CRemVarTable &vt) { vt.AddVar(static_cast(this)); } bool CRemVariable::SetJSONValue(const Json::Value &jv, bool fLock) { switch(jv.type()) { case Json::booleanValue: if(m_vt == VT_bool) { m_cache.boolVal = jv.asBool(); if(fLock) Lock(); *m_data.pBool = m_cache.boolVal; if(fLock) Unlock(); } else return false; break; case Json::intValue: switch(m_vt) { case VT_I1: m_cache.I1Val = jv.asInt(); if(fLock) Lock(); *m_data.pI1 = m_cache.I1Val; if(fLock) Unlock(); break; case VT_UI1: m_cache.UI1Val = jv.asInt(); if(fLock) Lock(); *m_data.pUI1 = m_cache.UI1Val; if(fLock) Unlock(); break; case VT_I2: m_cache.I2Val = jv.asInt(); if(fLock) Lock(); *m_data.pI2 = m_cache.I2Val; if(fLock) Unlock(); break; case VT_UI2: m_cache.UI2Val = jv.asInt(); if(fLock) Lock(); *m_data.pUI2 = m_cache.UI2Val; if(fLock) Unlock(); break; case VT_I4: m_cache.I4Val = jv.asInt(); if(fLock) Lock(); *m_data.pI4 = m_cache.I4Val; if(fLock) Unlock(); break; case VT_UI4: m_cache.UI4Val = jv.asUInt(); if(fLock) Lock(); *m_data.pUI4 = m_cache.UI4Val; if(fLock) Unlock(); break; case VT_I8: m_cache.I8Val = jv.asInt64(); if(fLock) Lock(); *m_data.pI8 = m_cache.I8Val; if(fLock) Unlock(); break; case VT_UI8: m_cache.UI8Val = jv.asUInt64(); if(fLock) Lock(); *m_data.pUI8 = m_cache.UI8Val; if(fLock) Unlock(); break; case VT_float: m_cache.FloatVal = jv.asFloat(); if(fLock) Lock(); *m_data.pFloat = m_cache.FloatVal; if(fLock) Unlock(); break; case VT_double: m_cache.DoubleVal = jv.asDouble(); if(fLock) Lock(); *m_data.pDouble = m_cache.DoubleVal; if(fLock) Unlock(); break; default: return false; } break; case Json::uintValue: switch(m_vt) { case VT_UI1: m_cache.UI1Val = jv.asUInt(); if(fLock) Lock(); *m_data.pUI1 = m_cache.UI1Val; if(fLock) Unlock(); break; case VT_UI2: m_cache.UI2Val = jv.asUInt(); if(fLock) Lock(); *m_data.pUI2 = m_cache.UI2Val; if(fLock) Unlock(); break; case VT_UI4: m_cache.UI4Val = jv.asUInt(); if(fLock) Lock(); *m_data.pUI4 = m_cache.UI4Val; if(fLock) Unlock(); break; case VT_UI8: m_cache.UI8Val = jv.asUInt64(); if(fLock) Lock(); *m_data.pUI8 = m_cache.UI8Val; if(fLock) Unlock(); break; case VT_float: m_cache.FloatVal = jv.asFloat(); if(fLock) Lock(); *m_data.pFloat = m_cache.FloatVal; if(fLock) Unlock(); break; case VT_double: m_cache.DoubleVal = jv.asDouble(); if(fLock) Lock(); *m_data.pDouble = m_cache.DoubleVal; if(fLock) Unlock(); break; default: return false; } break; case Json::realValue: switch(m_vt) { case VT_float: m_cache.FloatVal = jv.asFloat(); if(fLock) Lock(); *m_data.pFloat = m_cache.FloatVal; if(fLock) Unlock(); break; case VT_double: m_cache.DoubleVal = jv.asDouble(); if(fLock) Lock(); *m_data.pDouble = m_cache.DoubleVal; if(fLock) Unlock(); break; default: return false; } break; default: return false; } return true; } bool CRemVariable::SetDoubleValue(double val, bool fLock) { switch(m_vt) { case VT_bool: m_cache.boolVal = !!val; if(fLock) Lock(); *m_data.pBool = m_cache.boolVal; if(fLock) Unlock(); break; case VT_I1: m_cache.I1Val = (signed char)val; if(fLock) Lock(); *m_data.pI1 = m_cache.I1Val; if(fLock) Unlock(); break; case VT_UI1: m_cache.UI1Val = (unsigned char)val; if(fLock) Lock(); *m_data.pUI1 = m_cache.UI1Val; if(fLock) Unlock(); break; case VT_I2: m_cache.I2Val = (signed short)val; if(fLock) Lock(); *m_data.pI2 = m_cache.I2Val; if(fLock) Unlock(); break; case VT_UI2: m_cache.UI2Val = (unsigned short)val; if(fLock) Lock(); *m_data.pUI2 = m_cache.UI2Val; if(fLock) Unlock(); break; case VT_I4: m_cache.I4Val = (signed int)val; if(fLock) Lock(); *m_data.pI4 = m_cache.I4Val; if(fLock) Unlock(); break; case VT_UI4: m_cache.UI4Val = (unsigned int)val; if(fLock) Lock(); *m_data.pUI4 = m_cache.UI4Val; if(fLock) Unlock(); break; case VT_I8: m_cache.I8Val = (signed long long)val; if(fLock) Lock(); *m_data.pI8 = m_cache.I8Val; if(fLock) Unlock(); break; case VT_UI8: m_cache.UI8Val = (unsigned long long)val; if(fLock) Lock(); *m_data.pUI8 = m_cache.UI8Val; if(fLock) Unlock(); break; case VT_float: m_cache.FloatVal = (float)val; if(fLock) Lock(); *m_data.pFloat = m_cache.FloatVal; if(fLock) Unlock(); break; case VT_double: m_cache.DoubleVal = val; if(fLock) Lock(); *m_data.pDouble = m_cache.DoubleVal; if(fLock) Unlock(); break; default: return false; } return true; } unsigned long long CRemVariable::CheckUpdateShm(bool fLock) { CHECK_UPDATE_SHM_RETVAL rv = {1, 0}; if(m_bIsDbPersitent) return rv.nRetval; if(fLock) Lock(); switch(m_vt) { case VT_bool: if(m_cache.boolVal != *m_data.pBool) { m_cache.boolVal = *m_data.pBool; m_fLogValue = m_cache.boolVal ? 1.0 : 0.0; rv.nUpdated = 1; } break; case VT_I1: if(m_cache.I1Val != *m_data.pI1) { m_cache.I1Val = *m_data.pI1; m_fLogValue = (double)m_cache.I1Val; rv.nUpdated = 1; } break; case VT_UI1: if(m_cache.UI1Val != *m_data.pUI1) { m_cache.UI1Val = *m_data.pUI1; m_fLogValue = (double)m_cache.UI1Val; rv.nUpdated = 1; } break; case VT_I2: if(m_cache.I2Val != *m_data.pI2) { m_cache.I2Val = *m_data.pI2; m_fLogValue = (double)m_cache.I2Val; rv.nUpdated = 1; } break; case VT_UI2: if(m_cache.UI2Val != *m_data.pUI2) { m_cache.UI2Val = *m_data.pUI2; m_fLogValue = (double)m_cache.UI2Val; rv.nUpdated = 1; } break; case VT_I4: if(m_cache.I4Val != *m_data.pI4) { m_cache.I4Val = *m_data.pI4; m_fLogValue = (double)m_cache.I4Val; rv.nUpdated = 1; } break; case VT_UI4: if(m_cache.UI4Val != *m_data.pUI4) { m_cache.UI4Val = *m_data.pUI4; m_fLogValue = (double)m_cache.UI4Val; rv.nUpdated = 1; } break; case VT_I8: if(m_cache.I8Val != *m_data.pI8) { m_cache.I8Val = *m_data.pI8; m_fLogValue = (double)m_cache.I8Val; rv.nUpdated = 1; } break; case VT_UI8: if(m_cache.UI8Val != *m_data.pUI8) { m_cache.UI8Val = *m_data.pUI8; m_fLogValue = (double)m_cache.UI8Val; rv.nUpdated = 1; } break; case VT_float: if(m_cache.FloatVal != *m_data.pFloat) { m_cache.FloatVal = *m_data.pFloat; m_fLogValue = (double)m_cache.FloatVal; rv.nUpdated = 1; } break; case VT_double: if(m_cache.DoubleVal != *m_data.pDouble) { m_cache.DoubleVal = *m_data.pDouble; m_fLogValue = m_cache.DoubleVal; rv.nUpdated = 1; } break; default: rv.nUpdated = 0; break; } if(fLock) Unlock(); if(rv.nUpdated) { m_bMustLog = true; m_nUpdates++; } return rv.nRetval; } void CRemVariable::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 CRemVariable::Lock(void) { ::GfaIpcLockSHM(m_hShm); } void CRemVariable::Unlock(void) { ::GfaIpcUnlockSHM(m_hShm); }