#include "lts_session_lock_handler.h" #include #include #include #include namespace LtsSession { TopicLockHandler::TopicLockHandler() : QObject() , m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("LtsSession.TopicLockHandler")) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } TopicLockHandler::~TopicLockHandler() { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } bool TopicLockHandler::init(const std::shared_ptr &coreFtc, int exerciseId) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; if (coreFtc == nullptr) return false; coreFtc->enableAll(); m_exerciseId = exerciseId; m_coreFtc = coreFtc; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; return true; } bool TopicLockHandler::lock() { INFO_LOG(m_logger) << "LOCK " << m_topicInfo.topicName(); TRACE_LOG(m_logger) << LOGFUNCTION << objStateAsString(); if (m_coreFtc == nullptr) return false; if (m_locked) { ERROR_LOG(m_logger) << LOGFUNCTION << ": called lock while still locked! " << m_lockEntityId; Q_ASSERT(false); return false; } const auto *sessionData = LtsSessionData::LtsSessionData::getInstance(); Core::TryLockEntityRequest req; req.id(m_lockEntityId); req.entityTypeName(m_topicInfo.topicName().toStdString()); req.entityId(m_topicInfo.entityId()); req.exerciseId(m_exerciseId); req.operatorId(sessionData->getOperatorId()); req.workstationId(sessionData->getWorkstationId()); try { const Core::TryLockEntityReply reply(m_coreFtc->tryLockEntityRequest(req)); TRACE_LOG(m_logger) << LOGFUNCTION << ": Reply received - state=" << objStateAsString() << " - reply=" << reply; if (reply.alreadyLocked().is_set()) { const Core::LockEntityError &alreadyLocked = reply.alreadyLocked().get(); INFO_LOG(m_logger) << LOGFUNCTION << ": Topic already locked by ws " << alreadyLocked.workstationName() << " and op " << alreadyLocked.operatorName(); const auto lockedBy(QStringLiteral("%2/%1").arg(QString::fromStdString(alreadyLocked.operatorName()), QString::fromStdString(alreadyLocked.workstationName()))); emit signalLockDialog(lockedBy); } else { DEBUG_LOG(m_logger) << LOGFUNCTION << ": Topic NOT already locked"; Q_ASSERT(reply.id() > 0); m_locked = true; m_lockEntityId = reply.id(); } } catch (const std::runtime_error &err) { ERROR_LOG(m_logger) << LOGFUNCTION << ": Failed to lock topic! " << err.what(); Q_ASSERT(false); return false; } return true; } bool TopicLockHandler::unlock() { INFO_LOG(m_logger) << "UNLOCK " << m_topicInfo.topicName() << " - " << m_lockEntityId; TRACE_LOG(m_logger) << LOGFUNCTION << objStateAsString(); if (m_coreFtc == nullptr) return false; if (!m_locked) { ERROR_LOG(m_logger) << LOGFUNCTION << ": Tried to unlock while unlocked.. " << objStateAsString(); Q_ASSERT(false); return false; } Q_ASSERT(m_lockEntityId > 0); const Core::TryUnlockEntityRequest req(m_lockEntityId); m_locked = false; m_lockEntityId = 0; try { const auto reply(m_coreFtc->tryUnlockEntityRequest(req)); TRACE_LOG(m_logger) << LOGFUNCTION << ": Reply received - state=" << objStateAsString() << " - reply=" << reply; DEBUG_LOG(m_logger) << LOGFUNCTION << ": Topic unlocked!"; } catch (const std::runtime_error &err) { ERROR_LOG(m_logger) << LOGFUNCTION << ": Failed to unlock topic! " << err.what(); return false; } emit signalUnlockDialog(); return true; } std::string TopicLockHandler::objStateAsString() const { std::ostringstream o; o << " m_topicInfoId=" << m_lockEntityId << ", entityId=" << m_topicInfo.entityId() << ", exId=" << m_exerciseId << ", lckd=" << m_locked << ", asked=" << m_askedForLock << ", delftrAnwr=" << m_deleteAfterAnswer; return o.str(); } bool TopicLockHandler::slotUnlock() { TRACE_LOG(m_logger) << LOGFUNCTION << " slotUnlock" << objStateAsString(); return unlock(); } void TopicLockHandler::slotTryLock(const LtsWidgets::TopicInfo &topicInfo) { TRACE_LOG(m_logger) << LOGFUNCTION << " START " << objStateAsString(); m_topicInfo = topicInfo; if (m_topicInfo.topicName().isEmpty() || !topicInfo.isValid()) { DEBUG_LOG(m_logger) << LOGFUNCTION << " no lockable topic, that's okay"; return; } lock(); TRACE_LOG(m_logger) << LOGFUNCTION << " END " << objStateAsString(); } void TopicLockHandler::slotFinalize() { TRACE_LOG(m_logger) << LOGFUNCTION << " START " << objStateAsString(); if (m_locked) { slotUnlock(); } deleteLater(); TRACE_LOG(m_logger) << LOGFUNCTION << " END " << objStateAsString(); } TopicLockHanderData::TopicLockHanderData() : QObject() { } void TopicLockHanderData::init(const std::shared_ptr &coreFtc, int exerciseId) { m_topicLockHandler = new TopicLockHandler(); m_topicLockHandler->init(coreFtc, exerciseId); connect(m_topicLockHandler.data(), &TopicLockHandler::signalLockDialog, this, &TopicLockHanderData::slotLock, Qt::UniqueConnection); connect(m_topicLockHandler.data(), &TopicLockHandler::signalUnlockDialog, this, &TopicLockHanderData::slotUnlock, Qt::UniqueConnection); } TopicLockHanderData::~TopicLockHanderData() { if (m_topicLockHandler) m_topicLockHandler->slotFinalize(); } void TopicLockHanderData::unlock() { qDebug() << "Debugname=" << m_debugName << ": " << " slotUnlock"; if (m_topicLockHandler) m_topicLockHandler->slotUnlock(); } bool TopicLockHanderData::isLocked() const { if (!m_topicLockHandler) { qDebug() << "Debugname=" << m_debugName << ": " << " isLocked -> no handler"; return false; } qDebug() << "Debugname=" << m_debugName << ": " << " isLocked = " << m_topicLockHandler->isLocked(); return m_topicLockHandler->isLocked(); } LtsWidgets::TopicInfo TopicLockHanderData::getTopicInfo() const { if (m_topicLockHandler) return m_topicLockHandler->getTopicInfo(); return {}; } void TopicLockHanderData::slotTryLock(const LtsWidgets::TopicInfo &topicInfo) { qDebug() << "Debugname=" << m_debugName << ": " << "slotTryLock " << m_topicLockHandler; if (!m_topicLockHandler) return; m_topicLockHandler->slotTryLock(topicInfo); } void TopicLockHanderData::slotLock(const QString &lockedBy) { qDebug() << "Debugname=" << m_debugName << ": " << "slotLock"; m_lockedBy = lockedBy; emit lockDataChanged(); } void TopicLockHanderData::slotUnlock() { qDebug() << "Debugname=" << m_debugName << ": " << "slotUnlock"; m_lockedBy.clear(); emit lockDataChanged(); } }