/** * @RDE_HEADER@ * Handler for ComponentStatus * $Id$ * $HeadURL$ * $Author$ * Created by Iuliana Ojog, SLSE, 2017-04-03 */ #include "component_status_handler.h" #include "dds_handler.h" #include #include #include namespace ComponentMonitor { ComponentStatusHandler::ComponentStatusHandler() : QObject() , m_logger(getLogger("ComponentStatusHandler")) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } ComponentStatusHandler::~ComponentStatusHandler() { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; m_ddsHandler = nullptr; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } bool ComponentStatusHandler::initialize(const std::shared_ptr &ddsHandler) { INFO_LOG(m_logger) << LOGFUNCTION << " START initialize ComponentStatusHandler"; // initialize database // empty / not required at CMO // initialize DDS m_ddsHandler = ddsHandler; DEBUG_LOG(m_logger) << LOGFUNCTION << " ddsHandler referenced"; m_ismDtc = m_ddsHandler->ismDtc(); if (!m_ismDtc) { ERROR_LOG(m_logger) << LOGFUNCTION << " Failure: no ismDtc"; return false; } // should be enabled earlier, but be sure: m_ismDtc->enableInstrumentationAsset(); m_ismDtc->waitForHistoricalDataInstrumentationAsset(2000); DEBUG_LOG(m_logger) << LOGFUNCTION << " instrumentationAssets-size = " << m_ismDtc->instrumentationAssets().size(); // get all instrumentation assets and keep them up-to-date: // InstrumentationAssetState may change (mounted, notMounted..) connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::instrumentationAssetChanged, this, &ComponentStatusHandler::onInstrumentationAssetChanged); // get: m_ismDtc->instrumentationAssets([this](const InfrastructureManagement::InstrumentationAsset & iAsset) { onInstrumentationAssetChanged(iAsset, DataModification::eAdded); }); // with a delay, dump state of each entry QTimer::singleShot(35000, this, &ComponentStatusHandler::dump); DEBUG_LOG(m_logger) << LOGFUNCTION << "initialize succesful, statusMapSize=" << statusMapSize(); INFO_LOG(m_logger) << LOGFUNCTION << " END initialize ComponentStatusHandler, statusMapSize=" << statusMapSize(); return true; } std::vector ComponentStatusHandler::getHostnames() const { std::vector ret; ret.reserve(m_statusMap.size()); for (CONST_ITERATOR_T it = m_statusMap.cbegin(); it != m_statusMap.cend(); ++it) ret.push_back(it->hostname()); return ret; } void ComponentStatusHandler::onInstrumentationAssetChanged(const InfrastructureManagement::InstrumentationAsset &iAsset, DataModification dataMod) { const InfrastructureManagement::MountingPointType_def::type mpType = iAsset.mountingPointTypeId().underlying(); if ((mpType != InfrastructureManagement::MountingPointType_def::IndoorCamera) && (mpType != InfrastructureManagement::MountingPointType_def::OutdoorCamera) && (mpType != InfrastructureManagement::MountingPointType_def::EffectGenerationControlUnit) && (mpType != InfrastructureManagement::MountingPointType_def::BuildingSensorModule) ) return; // [GUEZE-1489]: just IndoorCamera, OutdoorCamera, EGCU, BSM static int assetChangedCounter = 0; const int iAssetId = iAsset.id(); DEBUG_LOG(m_logger) << LOGFUNCTION << ", iAssetId=" << iAssetId << " (assetChangedCounter=" << ++assetChangedCounter << ")"; // Only mounted assets should be monitored: const bool bIsMounted = iAsset.assetStateId() == InfrastructureManagement::InstrumentationAssetState_def::Mounted; if (!bIsMounted) dataMod = DataModification::eRemoved; // hostname ist empty? const bool bNoHostname = iAsset.hostname().empty(); if (bNoHostname) dataMod = DataModification::eRemoved; ITERATOR_T it = m_statusMap.find(iAssetId); switch (dataMod) { case DataModification::eAdded: case DataModification::eModified: { ComponentStatus cs; cs.id(iAssetId); cs.hostname(iAsset.hostname()); cs.state(ComponentMonitor::ComponentState::Undefined); addUpdateInstrumentationAsset(it, cs); } break; case DataModification::eRemoved: { // remove only, if in internal map if (it != m_statusMap.end()) removeInstrumentationAsset(it); } break; default: // empty break; } } void ComponentStatusHandler::dump() { DEBUG_LOG(m_logger) << LOGFUNCTION << " +++++++++++++++++++++++++++++++++++++++++++++"; DEBUG_LOG(m_logger) << LOGFUNCTION << " +++++++++++++++++++++++++++++++++++++++++++++"; DEBUG_LOG(m_logger) << LOGFUNCTION << " DUMP START"; int counter = 0; // 1) write all Reachable: counter = 0; DEBUG_LOG(m_logger) << " +++++++++++++++++++++++++++++++++++++++++++++"; DEBUG_LOG(m_logger) << " REACHABLE:"; for (const ComponentStatus &status : qAsConst(m_statusMap)) { if (status.state().underlying() == ComponentState_def::Reachable) { DEBUG_LOG(m_logger) << " id=" << status.id() << ", host '" << status.hostname().c_str() << " -> Reachable"; ++counter; } } // for DEBUG_LOG(m_logger) << " REACHABLE hostCounter = " << counter; // 2) write all UnReachable: counter = 0; DEBUG_LOG(m_logger) << " +++++++++++++++++++++++++++++++++++++++++++++"; DEBUG_LOG(m_logger) << " UNREACHABLE:"; for (const ComponentStatus &status : qAsConst(m_statusMap)) { if (status.state().underlying() == ComponentState_def::Unreachable) { DEBUG_LOG(m_logger) << " id=" << status.id() << ", host '" << status.hostname().c_str() << " -> Unreachable"; ++counter; } } // for DEBUG_LOG(m_logger) << " UNREACHABLE hostCounter = " << counter; // 3) write all Undefined: counter = 0; DEBUG_LOG(m_logger) << " +++++++++++++++++++++++++++++++++++++++++++++"; DEBUG_LOG(m_logger) << " UNDEFINED:"; for (const ComponentStatus &status : qAsConst(m_statusMap)) { if (status.state().underlying() == ComponentState_def::Undefined) { DEBUG_LOG(m_logger) << " id=" << status.id() << ", host '" << status.hostname().c_str() << " -> Undefined"; ++counter; } } // for DEBUG_LOG(m_logger) << " UNDEFINED hostCounter = " << counter; DEBUG_LOG(m_logger) << LOGFUNCTION << " DUMP END"; DEBUG_LOG(m_logger) << LOGFUNCTION << " +++++++++++++++++++++++++++++++++++++++++++++"; DEBUG_LOG(m_logger) << LOGFUNCTION << " +++++++++++++++++++++++++++++++++++++++++++++"; } void ComponentStatusHandler::onNewState(const QString &hostname, bool reachable, long long lastCheckSec) { DEBUG_LOG(m_logger) << LOGFUNCTION << " hostname=" << hostname << ", reachable=" << reachable << ", lastCheckSec=" << lastCheckSec; if (hostname.isEmpty()) return; for (ITERATOR_T it = m_statusMap.begin(); it != m_statusMap.end(); ++it) { const QString hname = QString::fromStdString(it->hostname()); if (hname.compare(hostname, Qt::CaseInsensitive) == 0) { ComponentState_def::type newStateInner = reachable ? ComponentState_def::Reachable : ComponentState_def::Unreachable; ComponentStatus newCs = (*it); newCs.state(newStateInner); newCs.last_check(lastCheckSec); addUpdateInstrumentationAsset(it, newCs); } } // for } void ComponentStatusHandler::onUpdateLastCheckTimeDirect(const QStringList &hostnamesForUpdateLastCheckTime, qint64 lastCheckSec) { DEBUG_LOG(m_logger) << LOGFUNCTION << " START hostnamesForLastCheckTime=" << hostnamesForUpdateLastCheckTime.join(QStringLiteral(";")); for (ITERATOR_T it = m_statusMap.begin(); it != m_statusMap.end(); ++it) { ComponentStatus &cs = *it; const QString &curHostname = QString::fromStdString(cs.hostname()); if (!hostnamesForUpdateLastCheckTime.contains(curHostname, Qt::CaseInsensitive)) continue; // do not step backwards: if (lastCheckSec <= cs.last_check()) continue; const ComponentState_def::type curState = cs.state().underlying(); if ((curState == ComponentState_def::Reachable) || (curState == ComponentState_def::Unreachable)) { DEBUG_LOG(m_logger) << LOGFUNCTION << " updateLastCheckTimeDirect" << " host: '" << curHostname << "'" << " newLastCheck= " << lastCheckSec; INFO_LOG(m_logger) << LOGFUNCTION << " DIFF_2a (*it) " << (*it); cs.last_check(lastCheckSec); INFO_LOG(m_logger) << LOGFUNCTION << " DIFF_2b (*it) " << (*it); m_ddsHandler->dts()->publish(cs); } } // for } bool ComponentStatusHandler::addUpdateInstrumentationAsset(ComponentStatusHandler::ITERATOR_T it, const ComponentStatus &cs) { DEBUG_LOG(m_logger) << LOGFUNCTION << " START add/Update: cs=" << cs << ", curSize=" << m_statusMap.size() << ")"; const int id = cs.id(); if (it != m_statusMap.end()) { // real update? // (avoid publishing the same data) if ((*it) != cs) { INFO_LOG(m_logger) << LOGFUNCTION << " DIFF (*it) " << (*it); INFO_LOG(m_logger) << LOGFUNCTION << " DIFF cs " << cs; (*it) = cs; // m_statusMap.insert(id, cs); m_ddsHandler->dts()->publish(cs); } } else { // insert and publish: m_statusMap.insert(id, cs); m_ddsHandler->dts()->publish(cs); } DEBUG_LOG(m_logger) << LOGFUNCTION << " END add/Update: cs=" << cs << ", curSize=" << m_statusMap.size() << ")"; return true; } bool ComponentStatusHandler::removeInstrumentationAsset(ComponentStatusHandler::ITERATOR_T it) { const int id = it.value().id(); DEBUG_LOG(m_logger) << LOGFUNCTION << " remove: id=" << id; m_statusMap.remove(id); m_ddsHandler->dts()->removeComponentStatusByKey(id); return true; } } // namespace ComponentMonitor