diff --git a/src/blackcore/corefacade.cpp b/src/blackcore/corefacade.cpp index 75f186907..423f84223 100644 --- a/src/blackcore/corefacade.cpp +++ b/src/blackcore/corefacade.cpp @@ -18,6 +18,7 @@ #include "blackcore/context/contextownaircraftimpl.h" #include "blackcore/context/contextsimulator.h" #include "blackmisc/sharedstate/datalinkdbus.h" +#include "blackmisc/loghistory.h" #include "blackcore/context/contextsimulatorimpl.h" #include "blackcore/data/launchersetup.h" #include "blackcore/corefacadeconfig.h" @@ -123,6 +124,15 @@ namespace BlackCore qFatal("Invalid application context mode"); } + // shared log history + m_logHistorySource = new CLogHistorySource(this); + m_logHistorySource->initialize(m_dataLinkDBus); + if (m_config.hasLocalCore()) + { + m_logHistory = new CLogHistory(this); + m_logHistory->initialize(m_dataLinkDBus); + } + // contexts if (m_contextApplication) { m_contextApplication->deleteLater(); } m_contextApplication = IContextApplication::create(this, m_config.getModeApplication(), m_dbusServer, m_dbusConnection); @@ -331,6 +341,10 @@ namespace BlackCore disconnect(this); // tear down shared state infrastructure + delete m_logHistory; + m_logHistory = nullptr; + delete m_logHistorySource; + m_logHistorySource = nullptr; delete m_dataLinkDBus; m_dataLinkDBus = nullptr; diff --git a/src/blackcore/corefacade.h b/src/blackcore/corefacade.h index 7434c4114..47b72ef05 100644 --- a/src/blackcore/corefacade.h +++ b/src/blackcore/corefacade.h @@ -26,6 +26,8 @@ namespace BlackMisc { class CDBusServer; + class CLogHistory; + class CLogHistorySource; namespace SharedState { @@ -68,6 +70,9 @@ namespace BlackCore //! Destructor virtual ~CCoreFacade() override { this->gracefulShutdown(); } + //! Transport mechanism for sharing state between applications + BlackMisc::SharedState::CDataLinkDBus *getDataLinkDBus() { return this->m_dataLinkDBus; } + //! DBus server (if applicable) const BlackMisc::CDBusServer *getDBusServer() const { return this->m_dbusServer; } @@ -191,6 +196,8 @@ namespace BlackCore // shared state infrastructure BlackMisc::SharedState::CDataLinkDBus *m_dataLinkDBus = nullptr; + BlackMisc::CLogHistory *m_logHistory = nullptr; + BlackMisc::CLogHistorySource *m_logHistorySource = nullptr; // contexts: // There is a reason why we do not use smart pointers here. When the context is deleted diff --git a/src/blackcore/corefacadeconfig.h b/src/blackcore/corefacadeconfig.h index aeaae6ebe..b2e361e45 100644 --- a/src/blackcore/corefacadeconfig.h +++ b/src/blackcore/corefacadeconfig.h @@ -73,6 +73,9 @@ namespace BlackCore //! Local settings? bool hasLocalSettings() const { return m_settings == Local || m_settings == LocalInDBusServer; } + //! Local core? + bool hasLocalCore() const { return m_application == Local || m_application == LocalInDBusServer; } + //! Requires server (at least one in server)? bool requiresDBusSever() const; diff --git a/src/blackmisc/loghistory.cpp b/src/blackmisc/loghistory.cpp new file mode 100644 index 000000000..a0086fe00 --- /dev/null +++ b/src/blackmisc/loghistory.cpp @@ -0,0 +1,41 @@ +/* Copyright (C) 2020 + * swift Project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated, + * or distributed except according to the terms contained in the LICENSE file. + */ + +//! \file + +#include "blackmisc/loghistory.h" +#include "blackmisc/loghandler.h" + +namespace BlackMisc +{ + CLogHistory::CLogHistory(QObject *parent) : CListJournal(parent) + { + } + + CLogHistorySource::CLogHistorySource(QObject *parent) : CListMutator(parent) + { + connect(CLogHandler::instance(), &CLogHandler::localMessageLogged, this, [this](auto&&... args) + { + this->addElement(args...); + }); + } + + CLogHistoryReplica::CLogHistoryReplica(QObject* parent) : CListObserver(parent) + { + } + + void CLogHistoryReplica::onElementAdded(const CStatusMessage &msg) + { + emit elementAdded(msg); + } + + void CLogHistoryReplica::onElementsReplaced(const CStatusMessageList &msgs) + { + emit elementsReplaced(msgs); + } +} diff --git a/src/blackmisc/loghistory.h b/src/blackmisc/loghistory.h new file mode 100644 index 000000000..17e515afc --- /dev/null +++ b/src/blackmisc/loghistory.h @@ -0,0 +1,75 @@ +/* Copyright (C) 2020 + * swift Project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated, + * or distributed except according to the terms contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKMISC_LOGHISTORY_H +#define BLACKMISC_LOGHISTORY_H + +#include "blackmisc/sharedstate/datalink.h" +#include "blackmisc/sharedstate/listjournal.h" +#include "blackmisc/sharedstate/listmutator.h" +#include "blackmisc/sharedstate/listobserver.h" +#include "blackmisc/statusmessagelist.h" +#include "blackmisc/logpattern.h" +#include + +namespace BlackMisc +{ + /*! + * Records all log messages to a list that persists for the lifetime of the application. + */ + class BLACKMISC_EXPORT CLogHistory : public SharedState::CListJournal + { + Q_OBJECT + BLACK_SHARED_STATE_CHANNEL("swift.log.history") + + public: + //! Constructor. + CLogHistory(QObject *parent = nullptr); + }; + + /*! + * Allows distributed insertion of log messages into a central CLogHistory. + */ + class BLACKMISC_EXPORT CLogHistorySource : public SharedState::CListMutator + { + Q_OBJECT + BLACK_SHARED_STATE_CHANNEL("swift.log.history") + + public: + //! Constructor. + CLogHistorySource(QObject *parent = nullptr); + }; + + /*! + * Allows distributed access to the log messages of a central CLogHistory. + */ + class BLACKMISC_EXPORT CLogHistoryReplica : public SharedState::CListObserver + { + Q_OBJECT + BLACK_SHARED_STATE_CHANNEL("swift.log.history") + + public: + //! Constructor. + CLogHistoryReplica(QObject *parent = nullptr); + + signals: + //! Signal emitted for each new log message. + void elementAdded(const BlackMisc::CStatusMessage &msg); + + //! Signal emitted when the whole history is updated wholesale. + void elementsReplaced(const BlackMisc::CStatusMessageList &msgs); + + private: + virtual void onElementAdded(const CStatusMessage &msg) override final; + virtual void onElementsReplaced(const CStatusMessageList &msgs) override final; + }; +} + +#endif diff --git a/src/blackmisc/logpattern.cpp b/src/blackmisc/logpattern.cpp index 868171603..ea6bc16c1 100644 --- a/src/blackmisc/logpattern.cpp +++ b/src/blackmisc/logpattern.cpp @@ -328,7 +328,7 @@ namespace BlackMisc QString categories = m_strings.values().join("|"); // clazy:exclude=container-anti-pattern switch (m_strategy) { - case Everything: strategy = "none"; break; + case Everything: strategy = "all"; break; case ExactMatch: strategy = "exact match:" + categories; break; case AnyOf: strategy = "any of:" + categories; break; case AllOf: strategy = "all of:" + categories; break; diff --git a/src/blackmisc/logpattern.h b/src/blackmisc/logpattern.h index 79aa79160..4f7099bfa 100644 --- a/src/blackmisc/logpattern.h +++ b/src/blackmisc/logpattern.h @@ -93,6 +93,9 @@ namespace BlackMisc //! Returns true if the given message matches this pattern. bool match(const CStatusMessage &message) const; + //! This class acts as a SharedState filter when stored in a CVariant. + bool matches(const CVariant &message) const { return match(message.to()); } + //! Returns true if this pattern is a proper subset of the other pattern. //! \see https://en.wikipedia.org/wiki/Proper_subset //! \details Pattern A is a proper subset of pattern B iff pattern B would match every category which pattern A matches,