/******************************************************************************//** * @file FbdDiagDataImpl.cpp * @brief 功能块图(Diagram)数据接口实现 * @author yikenan * @version 1.0 * @date 2020/12/7 **********************************************************************************/ //< 屏蔽Protobuf编译告警 #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4100) #endif #include "FBD.pb.h" #ifdef __GNUC__ #pragma GCC diagnostic pop #endif #ifdef _MSC_VER #pragma warning(pop) #endif #include "boost/weak_ptr.hpp" #include "app_fbd/fbd_common/FbdSysInfoApi.h" #include "FbdDiagDataImpl.h" namespace iot_app { namespace app_fbd { //< 弱指针,观察者模式 static boost::weak_ptr g_wpSingleton; //< 保护 g_wpSingleton static boost::mutex g_mutexSingleton; //< 获取单例 FBD_COMMON_API CFbdDiagDataApiPtr getFbdDiagDataApi() { CFbdDiagDataImplPtr spInst = g_wpSingleton.lock(); if ( nullptr != spInst ) return spInst; boost::mutex::scoped_lock lock( g_mutexSingleton ); spInst = g_wpSingleton.lock(); if ( nullptr != spInst ) return spInst; spInst = boost::make_shared(); if ( iotSuccess == spInst->initialize()) { g_wpSingleton = spInst; return spInst; } return nullptr; } /***********************************************************************************************/ CFbdDiagDataImpl::CFbdDiagDataImpl() : m_pRdbTableMng( nullptr ) { m_pMutexModInfoTable = new boost::shared_mutex; m_pMutexModInputTable = new boost::shared_mutex; m_pMutexModOutputTable = new boost::shared_mutex; m_pMutexModPropTable = new boost::shared_mutex; m_pMutexGlobalVarMap = new boost::shared_mutex; } CFbdDiagDataImpl::~CFbdDiagDataImpl() { delete m_pRdbTableMng; m_pRdbTableMng = nullptr; delete m_pMutexModInfoTable; m_pMutexModInfoTable = nullptr; delete m_pMutexModInputTable; m_pMutexModInputTable = nullptr; delete m_pMutexModOutputTable; m_pMutexModOutputTable = nullptr; delete m_pMutexModPropTable; m_pMutexModPropTable = nullptr; delete m_pMutexGlobalVarMap; m_pMutexGlobalVarMap = nullptr; } int CFbdDiagDataImpl::initialize() { if ( nullptr == m_pRdbTableMng ) { CFbdSysInfoApiPtr ptrSysInfo = getFbdSysInfoApi(); if ( nullptr == ptrSysInfo || ptrSysInfo->getCurrentRunAppInfo().strAppName.empty()) { LOGERROR( "initialize(): 系统信息非预期,检查程序!" ); return iotFailed; } m_pRdbTableMng = new iot_dbms::CRdbTableMng( getFbdSysInfoApi()->getCurrentRunAppInfo().strAppName ); } if ( nullptr == m_pRdbTableMng || nullptr == m_pMutexModInfoTable || nullptr == m_pMutexModInputTable || nullptr == m_pMutexModOutputTable || nullptr == m_pMutexModPropTable ) { LOGERROR( "initialize(): 空指针,非预期,检查程序!" ); return iotFailed; } return iotSuccess; } int CFbdDiagDataImpl::getModProperty( const SFbdModPropKey &stPropertyKey, std::string &strValue ) const { strValue.clear(); if ( !stPropertyKey.isValid()) { LOGERROR( "getModProperty(): 无效的输入 stPropertyKey,返回失败!" ); return iotFailed; } //< 读锁 boost::shared_lock lock( *m_pMutexModInfoTable ); const auto &indexKey = m_objModPropTable.get(); const auto it = indexKey.find( stPropertyKey ); if ( indexKey.end() == it ) { LOGERROR( "getModProperty(): m_objModPropTable 中未找到记录 Key=[%s]", stPropertyKey.toString().c_str()); return iotFailed; } strValue = ( *it )->m_strValue; return iotSuccess; } int CFbdDiagDataImpl::getValKeyByModInput( const SFbdModInputKey &stInputKey, SFbdValueKey &stValueKey ) const { stValueKey.m_ptrModOutput = nullptr; if ( !stInputKey.isValid()) { LOGERROR( "getValKeyByModInput(): 无效的输入 stInputKey,返回失败!" ); return iotFailed; } SFbdModOutputKey stOutputKey; { //< 读锁 boost::shared_lock lock( *m_pMutexModInputTable ); const auto &indexKey = m_objModInputTable.get(); const auto it = indexKey.find( stInputKey ); if ( indexKey.end() == it ) { LOGERROR( "getValKeyByModInput(): m_objModInputTable 中未找到记录 Key=[%s]", stInputKey.toString().c_str()); return iotFailed; } stOutputKey = ( *it )->m_stOutputKey; } { //< 读锁 boost::shared_lock lock( *m_pMutexModOutputTable ); const auto &indexKey = m_objModOutputTable.get(); const auto it = indexKey.find( stOutputKey ); if ( indexKey.end() == it ) { LOGERROR( "getValKeyByModInput(): m_objModOutputTable 中未找到记录 Key=[%s]", stOutputKey.toString().c_str()); return iotFailed; } stValueKey.m_bWriteable = false; stValueKey.m_ptrModOutput = *it; } if ( stValueKey.isValid()) return iotSuccess; LOGERROR( "getValKeyByModInput(): 无效的输出,检查程序!" ); return iotFailed; } int CFbdDiagDataImpl::getValKeyByModOutput( const SFbdModOutputKey &stOutputKey, SFbdValueKey &stValueKey ) const { stValueKey.m_ptrModOutput = nullptr; if ( !stOutputKey.isValid()) { LOGERROR( "getValKeyByModOutput(): 无效的输入 stOutputKey,返回失败!" ); return iotFailed; } //< 读锁 boost::shared_lock lock( *m_pMutexModOutputTable ); const auto &indexKey = m_objModOutputTable.get(); const auto it = indexKey.find( stOutputKey ); if ( indexKey.end() == it ) { LOGERROR( "getValKeyByModOutput(): m_objModOutputTable 中未找到记录 Key=[%s]", stOutputKey.toString().c_str()); return iotFailed; } stValueKey.m_bWriteable = true; stValueKey.m_ptrModOutput = *it; if ( stValueKey.isValid()) return iotSuccess; LOGERROR( "getValKeyByModOutput(): 无效的输出,检查程序!" ); return iotFailed; } int CFbdDiagDataImpl::getNumericValByKey( const SFbdValueKey &stValueKey, SFbdNumericValue &stValAndSta ) const { stValAndSta.m_nStatus = CN_FBD_STATUS_Invalid; if ( !stValueKey.isValid()) { LOGERROR( "getNumericValByKey(): 无效的输入 stValueKey,返回失败!" ); return iotFailed; } //< 读锁 boost::shared_lock lock( *m_pMutexModOutputTable ); const SFbdNumericValue *pValue = boost::any_cast( &( stValueKey.m_ptrModOutput->m_anyOutputValue )); if ( nullptr == pValue ) { LOGERROR( "getNumericValByKey(): 类型不一致,key=[%s],type=[%s]", stValueKey.toString().c_str(), stValueKey.m_ptrModOutput->m_anyOutputValue.type().name()); return iotFailed; } stValAndSta = *pValue; return iotSuccess; } int CFbdDiagDataImpl::setNumericValByKey( const SFbdValueKey &stValueKey, const SFbdNumericValue &stValAndSta ) { if ( !stValueKey.isValid()) { LOGERROR( "setNumericValByKey(): 无效的输入 stValueKey,返回失败!" ); return iotFailed; } if ( !stValueKey.m_bWriteable ) { LOGERROR( "setNumericValByKey(): 非可写 Key" ); return iotFailed; } //< 写锁 boost::unique_lock lock( *m_pMutexModOutputTable ); stValueKey.m_ptrModOutput->m_anyOutputValue = stValAndSta; return iotSuccess; } int CFbdDiagDataImpl::getStringValByKey( const SFbdValueKey &stValueKey, SFbdStringValue &stValAndSta ) const { stValAndSta.m_nStatus = CN_FBD_STATUS_Invalid; if ( !stValueKey.isValid()) { LOGERROR( "getStringValByKey(): 无效的输入 stValueKey,返回失败!" ); return iotFailed; } //< 读锁 boost::shared_lock lock( *m_pMutexModOutputTable ); const SFbdStringValue *pValue = boost::any_cast( &( stValueKey.m_ptrModOutput->m_anyOutputValue )); if ( nullptr == pValue ) { LOGERROR( "getStringValByKey(): 类型不一致,key=[%s],type=[%s]", stValueKey.toString().c_str(), stValueKey.m_ptrModOutput->m_anyOutputValue.type().name()); return iotFailed; } stValAndSta = *pValue; return iotSuccess; } int CFbdDiagDataImpl::setStringValByKey( const SFbdValueKey &stValueKey, const SFbdStringValue &stValAndSta ) { if ( !stValueKey.isValid()) { LOGERROR( "setStringValByKey(): 无效的输入 stValueKey,返回失败!" ); return iotFailed; } if ( !stValueKey.m_bWriteable ) { LOGERROR( "setStringValByKey(): 非可写 Key" ); return iotFailed; } //< 写锁 boost::unique_lock lock( *m_pMutexModOutputTable ); stValueKey.m_ptrModOutput->m_anyOutputValue = stValAndSta; return iotSuccess; } int CFbdDiagDataImpl::getAlarmValByKey( const SFbdValueKey &stValueKey, SFbdAlarmValue &stValAndSta ) const { stValAndSta.m_nStatus = CN_FBD_STATUS_Invalid; if ( !stValueKey.isValid()) { LOGERROR( "getAlarmValByKey(): 无效的输入 stValueKey,返回失败!" ); return iotFailed; } //< 读锁 boost::shared_lock lock( *m_pMutexModOutputTable ); const SFbdAlarmValue *pValue = boost::any_cast( &( stValueKey.m_ptrModOutput->m_anyOutputValue )); if ( nullptr == pValue ) { LOGERROR( "getAlarmValByKey(): 类型不一致,key=[%s],type=[%s]", stValueKey.toString().c_str(), stValueKey.m_ptrModOutput->m_anyOutputValue.type().name()); return iotFailed; } stValAndSta = *pValue; return iotSuccess; } int CFbdDiagDataImpl::setAlarmValByKey( const SFbdValueKey &stValueKey, const SFbdAlarmValue &stValAndSta ) { if ( !stValueKey.isValid()) { LOGERROR( "setAlarmValByKey(): 无效的输入 stValueKey,返回失败!" ); return iotFailed; } if ( !stValueKey.m_bWriteable ) { LOGERROR( "setAlarmValByKey(): 非可写 Key" ); return iotFailed; } //< 写锁 boost::unique_lock lock( *m_pMutexModOutputTable ); stValueKey.m_ptrModOutput->m_anyOutputValue = stValAndSta; return iotSuccess; } int CFbdDiagDataImpl::getGlobalNumericValByKey(const std::string &strVarName, SFbdNumericValue &stValAndSta) const { stValAndSta.m_nStatus = CN_FBD_STATUS_Invalid; //< 读锁 boost::shared_lock lock(*m_pMutexGlobalVarMap); auto iter = m_mapGlobalVar.find(strVarName); if(iter == m_mapGlobalVar.end()) { return iotFailed; } const SFbdNumericValue *pValue = boost::any_cast(&(iter->second)); if ( nullptr == pValue ) { LOGERROR( "getGlobalNumericValByKey(): 类型不一致,key=[%s],type=[%s]", strVarName.c_str(), iter->second.type().name()); return iotFailed; } stValAndSta = *pValue; return iotSuccess; } int CFbdDiagDataImpl::setGlobalNumericValByKey(const std::string &strVarName, const SFbdNumericValue &stValAndSta) { //< 写锁 boost::unique_lock lock( *m_pMutexGlobalVarMap ); auto iter = m_mapGlobalVar.find(strVarName); if(iter == m_mapGlobalVar.end()) { return iotFailed; } iter->second = stValAndSta; return iotSuccess; } int CFbdDiagDataImpl::regGlobalNumericValByKey(const std::string &strVarName, const SFbdNumericValue &stValAndSta) { //< 写锁 boost::unique_lock lock( *m_pMutexGlobalVarMap ); auto iter = m_mapGlobalVar.find(strVarName); if(iter != m_mapGlobalVar.end()) { LOGINFO( "regGlobalNumericValByKey 变量[%s]已经存在",strVarName.c_str() ); //检查类型是否一致 if(iter->second.type() != typeid(SFbdNumericValue)) { LOGERROR( "regGlobalNumericValByKey(): 类型不一致,key=[%s],type=[%s]", strVarName.c_str(), iter->second.type().name()); return iotFBDErr_GlobalVarTypeMismatch; } return iotFBDErr_GlobalVarAlreadyExist; } m_mapGlobalVar[strVarName] = stValAndSta; return iotSuccess; } int CFbdDiagDataImpl::unregGlobalNumericVar(const std::string &strVarName) { //< 写锁 boost::unique_lock lock( *m_pMutexGlobalVarMap ); auto iter = m_mapGlobalVar.find(strVarName); if(iter != m_mapGlobalVar.end()) { m_mapGlobalVar.erase(iter); } return iotSuccess; } int CFbdDiagDataImpl::getGlobalStringValByKey(const std::string &strVarName, SFbdStringValue &stValAndSta) const { stValAndSta.m_nStatus = CN_FBD_STATUS_Invalid; //< 读锁 boost::shared_lock lock(*m_pMutexGlobalVarMap); auto iter = m_mapGlobalVar.find(strVarName); if(iter == m_mapGlobalVar.end()) { return iotFailed; } const SFbdStringValue *pValue = boost::any_cast(&(iter->second)); if ( nullptr == pValue ) { LOGERROR( "getGlobalStringValByKey(): 类型不一致,key=[%s],type=[%s]", strVarName.c_str(), iter->second.type().name()); return iotFailed; } stValAndSta = *pValue; return iotSuccess; } int CFbdDiagDataImpl::setGlobalStringValByKey(const std::string &strVarName, const SFbdStringValue &stValAndSta) { //< 写锁 boost::unique_lock lock( *m_pMutexGlobalVarMap ); auto iter = m_mapGlobalVar.find(strVarName); if(iter == m_mapGlobalVar.end()) { return iotFailed; } iter->second = stValAndSta; return iotSuccess; } int CFbdDiagDataImpl::regGlobalStringValByKey(const std::string &strVarName, const SFbdStringValue &stValAndSta) { //< 写锁 boost::unique_lock lock( *m_pMutexGlobalVarMap ); auto iter = m_mapGlobalVar.find(strVarName); if(iter != m_mapGlobalVar.end()) { LOGINFO( "regGlobalStringValByKey 变量[%s]已经存在",strVarName.c_str() ); //检查类型是否一致 if(iter->second.type() != typeid(SFbdStringValue)) { LOGERROR( "regGlobalStringValByKey(): 类型不一致,key=[%s],type=[%s]", strVarName.c_str(), iter->second.type().name()); return iotFBDErr_GlobalVarTypeMismatch; } return iotFBDErr_GlobalVarAlreadyExist; } m_mapGlobalVar[strVarName] = stValAndSta; return iotSuccess; } int CFbdDiagDataImpl::unregGlobalStringVar(const std::string &strVarName) { //< 写锁 boost::unique_lock lock( *m_pMutexGlobalVarMap ); auto iter = m_mapGlobalVar.find(strVarName); if(iter != m_mapGlobalVar.end()) { m_mapGlobalVar.erase(iter); } return iotSuccess; } /***********************************************************************************************/ int CFbdDiagDataImpl::getAllGroupInfo( std::vector &vecGrpInfo ) const { static const std::string strTableName = CN_TN_FbdGroup; iot_dbms::CRdbTableMngLockGuard lock( *m_pRdbTableMng, strTableName ); if ( !m_pRdbTableMng->selectAllColumnNoCondition( strTableName, vecGrpInfo )) { LOGERROR( "getAllGroupInfo(): 从RDB获取FBD组信息失败" ); return iotFailed; } return iotSuccess; } int CFbdDiagDataImpl::getModuleInfoByGroup( const int nFbdGrpId, std::vector &vecModuleInfo ) const { vecModuleInfo.clear(); //< 读锁 boost::shared_lock lock( *m_pMutexModInfoTable ); const auto &indexGrpId = m_objModInfoTable.get(); const size_t nCount = indexGrpId.count( nFbdGrpId ); if ( 0 == nCount ) { //< 允许空组,不作为错误 LOGWARN( "getModuleInfoByGroup(): m_objModInfoTable 中未找到记录 GroupId=[%d],返回成功", nFbdGrpId ); return iotSuccess; } //< 预先分配空间,避免频繁内存移动 vecModuleInfo.reserve( nCount + 1 ); const auto pairRange = indexGrpId.equal_range( nFbdGrpId ); for ( auto it = pairRange.first; pairRange.second != it; ++it ) { vecModuleInfo.emplace_back( **it ); } return iotSuccess; } int CFbdDiagDataImpl::deleteAllDataByGroup( const int nFbdGrpId ) { LOGINFO( "deleteAllDataByGroup(): 开始删除组 GrpId=[%d]", nFbdGrpId ); //< 写锁 boost::unique_lock lockModInfo( *m_pMutexModInfoTable ); auto &indexGrpId = m_objModInfoTable.get(); const auto pairModInfo = indexGrpId.equal_range( nFbdGrpId ); if ( pairModInfo.first == pairModInfo.second ) { LOGWARN( "deleteAllDataByGroup(): m_objModInfoTable 中未找到记录 GroupId=[%d],返回成功", nFbdGrpId ); return iotSuccess; } //< 按图名删除其他表中的记录 { //< 用于图名去重 std::set setDiagName; //< 写锁 boost::unique_lock lockModInput( *m_pMutexModInputTable ); boost::unique_lock lockModOutput( *m_pMutexModOutputTable ); boost::unique_lock lockModProp( *m_pMutexModPropTable ); auto &indexDiagName_Input = m_objModInputTable.get(); auto &indexDiagName_Output = m_objModOutputTable.get(); auto &indexDiagName_Prop = m_objModPropTable.get(); for ( auto itModInfo = pairModInfo.first; pairModInfo.second != itModInfo; ++itModInfo ) { const std::string &strDiagName = ( *itModInfo )->getDiagName(); if ( setDiagName.count( strDiagName ) != 0 ) { continue; //< 剔除重复的图名 } setDiagName.insert( strDiagName ); indexDiagName_Input.erase( strDiagName ); indexDiagName_Output.erase( strDiagName ); indexDiagName_Prop.erase( strDiagName ); } } //< 删除 ModInfoTable 中的记录 indexGrpId.erase( nFbdGrpId ); return iotSuccess; } int CFbdDiagDataImpl::insertAllDataByGroup( const SFbdGroupInfo &stGrpInfo, const SFbdGroupData &stGrpData ) { LOGINFO( "insertAllDataByGroup(): 开始插入组 Id=[%d], BusinessType=[%d], Name=[%s], Desc=[%s]", stGrpInfo.m_nId, stGrpInfo.m_nBusinessType, stGrpInfo.m_szName, stGrpInfo.m_szDesc ); //< m_objModInfoTable { //< 写锁 boost::unique_lock lockModInfo( *m_pMutexModInfoTable ); for ( const auto &ptrModInfo : stGrpData.m_vecPtrModInfo ) { const auto &pairRc = m_objModInfoTable.insert( ptrModInfo ); if ( !pairRc.second ) { LOGERROR( "insertAllDataByGroup(): 向 m_objModInfoTable 插入失败 mod_key=[%s]", ptrModInfo->m_stModKey.toString().c_str()); } } } //< m_objModInputTable { //< 写锁 boost::unique_lock lockModInput( *m_pMutexModInputTable ); for ( const auto &ptrModInput : stGrpData.m_vecPtrModInput ) { const auto &pairRc = m_objModInputTable.insert( ptrModInput ); if ( !pairRc.second ) { LOGERROR( "insertAllDataByGroup(): 向 m_objModInputTable 插入失败 Key=[%s]", ptrModInput->m_stInputKey.toString().c_str()); } } } //< m_objModOutputTable { //< 写锁 boost::unique_lock lockModOutput( *m_pMutexModOutputTable ); for ( const auto &ptrModOutput : stGrpData.m_vecPtrModOutput ) { const auto &pairRc = m_objModOutputTable.insert( ptrModOutput ); if ( !pairRc.second ) { LOGERROR( "insertAllDataByGroup(): 向 m_objModOutputTable 插入失败 Key=[%s]", ptrModOutput->m_stOutputKey.toString().c_str()); } } } //< m_objModPropTable { //< 写锁 boost::unique_lock lockModProp( *m_pMutexModPropTable ); for ( const auto &ptrModProp : stGrpData.m_vecPtrModProp ) { const auto &pairRc = m_objModPropTable.insert( ptrModProp ); if ( !pairRc.second ) { LOGERROR( "insertAllDataByGroup(): 向 m_objModPropTable 插入失败 Key=[%s]", ptrModProp->m_stPropKey.toString().c_str()); } } } return iotSuccess; } int CFbdDiagDataImpl::getDebugResponse( const iot_idl::SFBDDebugRequest &objReq, iot_idl::SFBDDebugResponse &objRep ) { const std::string &strDiagName = objReq.sdiagramname(); objRep.set_ngroupid( objReq.ngroupid()); objRep.set_sdiagramname( strDiagName ); int nStatus; //< 读锁 boost::shared_lock lock( *m_pMutexModOutputTable ); const auto &indexDiagName = m_objModOutputTable.get(); const auto pairModOutput = indexDiagName.equal_range( strDiagName ); for ( auto it = pairModOutput.first; it != pairModOutput.second; ++it ) { const SFbdModOutput &stModOutput = *( *it ); auto pDbgData = objRep.add_vecblock(); pDbgData->set_sinstancename( stModOutput.m_stOutputKey.m_stModKey.m_strModName ); pDbgData->set_noutportindex( stModOutput.m_stOutputKey.m_nOutputIndex ); stModOutput.getValueString( nStatus, *( pDbgData->mutable_svalue())); pDbgData->set_nvalid( nStatus ); } return iotSuccess; } } //< namespace app_fbd } //< namespace iot_app