This a) makes the log db threaded by using QtConcurrent to run queries in a different thread but still keeps ordering of the queries and always only allows a single query at a time (QSql is not threadsafe). This fixes removeDevice calls failing if we take more than $jsonprc_timeout to clean a deleted device from the DB and keeps nymead responsive during that too. b) generally improces performance of the system by not requiring operations (emitting events, changing states) to wait for the sync log db entry to be made. c) drops some of the houskeeping code on nymea startup. While this will still do log db housekeeping if the DB exceeds maxDbSize, it will not run housekeeping on the DB any more at application startup. Reasoning for this is that there have been reports of rules/log entries beimg destroyed if a plugin can't be found at application startup. Given our general direction of working towards more dynamic plugin loading, this might happen more often in the future and we sure don't want to destroy rules etc when we just temporarily miss a plugin. d) tries to fix issue #226 by rotating the DB not only when it fails to open initially, but also when it fails to insert new entries.
138 lines
4.6 KiB
C++
138 lines
4.6 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* *
|
|
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
|
|
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
|
|
* *
|
|
* This file is part of nymea. *
|
|
* *
|
|
* nymea is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation, version 2 of the License. *
|
|
* *
|
|
* nymea is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with nymea. If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#ifndef LOGENGINE_H
|
|
#define LOGENGINE_H
|
|
|
|
#include "logentry.h"
|
|
#include "logfilter.h"
|
|
#include "types/event.h"
|
|
#include "types/action.h"
|
|
#include "types/browseritemaction.h"
|
|
#include "types/browseraction.h"
|
|
#include "ruleengine/rule.h"
|
|
|
|
#include <QObject>
|
|
#include <QSqlDatabase>
|
|
#include <QSqlQuery>
|
|
#include <QTimer>
|
|
#include <QFutureWatcher>
|
|
|
|
namespace nymeaserver {
|
|
|
|
class DatabaseJob;
|
|
class LogEngineFetchJob;
|
|
|
|
class LogEngine: public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
LogEngine(const QString &driver, const QString &dbName, const QString &hostname = QString("127.0.0.1"), const QString &username = QString(), const QString &password = QString(), int maxDBSize = 50000, QObject *parent = nullptr);
|
|
~LogEngine();
|
|
|
|
LogEngineFetchJob *logEntries(const LogFilter &filter = LogFilter());
|
|
|
|
void setMaxLogEntries(int maxLogEntries, int overflow);
|
|
void clearDatabase();
|
|
|
|
void logSystemEvent(const QDateTime &dateTime, bool active, Logging::LoggingLevel level = Logging::LoggingLevelInfo);
|
|
void logEvent(const Event &event);
|
|
void logAction(const Action &action, Logging::LoggingLevel level = Logging::LoggingLevelInfo, int errorCode = 0);
|
|
void logBrowserAction(const BrowserAction &browserAction, Logging::LoggingLevel level = Logging::LoggingLevelInfo, int errorCode = 0);
|
|
void logBrowserItemAction(const BrowserItemAction &browserItemAction, Logging::LoggingLevel level = Logging::LoggingLevelInfo, int errorCode = 0);
|
|
void logRuleTriggered(const Rule &rule);
|
|
void logRuleActiveChanged(const Rule &rule);
|
|
void logRuleEnabledChanged(const Rule &rule, const bool &enabled);
|
|
void logRuleActionsExecuted(const Rule &rule);
|
|
void logRuleExitActionsExecuted(const Rule &rule);
|
|
void removeDeviceLogs(const DeviceId &deviceId);
|
|
void removeRuleLogs(const RuleId &ruleId);
|
|
|
|
signals:
|
|
void logEntryAdded(const LogEntry &logEntry);
|
|
void logDatabaseUpdated();
|
|
|
|
private:
|
|
bool initDB(const QString &username, const QString &password);
|
|
void appendLogEntry(const LogEntry &entry);
|
|
void rotate(const QString &dbName);
|
|
|
|
|
|
bool migrateDatabaseVersion2to3();
|
|
|
|
private slots:
|
|
void checkDBSize();
|
|
|
|
void enqueJob(DatabaseJob *job);
|
|
void processQueue();
|
|
void handleJobFinished();
|
|
|
|
private:
|
|
QSqlDatabase m_db;
|
|
QString m_username;
|
|
QString m_password;
|
|
int m_dbMaxSize;
|
|
int m_overflow;
|
|
bool m_trimWarningPrinted = false;
|
|
int m_entryCount = 0;
|
|
bool m_dbMalformed = false;
|
|
|
|
QList<DatabaseJob*> m_jobQueue;
|
|
QFutureWatcher<DatabaseJob*> m_jobWatcher;
|
|
};
|
|
|
|
class DatabaseJob: public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
DatabaseJob(const QSqlQuery &query, QObject *parent): QObject(parent), m_query(query) {}
|
|
|
|
QSqlQuery query() const { return m_query; }
|
|
|
|
signals:
|
|
void finished();
|
|
|
|
private:
|
|
QSqlQuery m_query;
|
|
};
|
|
|
|
class LogEngineFetchJob: public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
LogEngineFetchJob(QObject *parent): QObject(parent) {}
|
|
|
|
QList<LogEntry> results() { return m_results; }
|
|
|
|
signals:
|
|
void finished();
|
|
|
|
private:
|
|
void addResult(const LogEntry &entry) { m_results.append(entry); }
|
|
QList<LogEntry> m_results;
|
|
|
|
friend class LogEngine;
|
|
|
|
};
|
|
}
|
|
|
|
#endif
|