Improved logging (now with time), preparation for #71.

This commit is contained in:
martinrotter 2017-04-21 08:04:23 +02:00
parent e2fa0aeea6
commit fcab295ab8
11 changed files with 159 additions and 9 deletions

View File

@ -326,7 +326,8 @@ HEADERS += src/core/feeddownloader.h \
src/services/standard/atomparser.h \
src/services/standard/feedparser.h \
src/services/standard/rdfparser.h \
src/services/standard/rssparser.h
src/services/standard/rssparser.h \
src/miscellaneous/serviceoperator.h
SOURCES += src/core/feeddownloader.cpp \
src/core/feedsmodel.cpp \
@ -444,7 +445,8 @@ SOURCES += src/core/feeddownloader.cpp \
src/services/standard/atomparser.cpp \
src/services/standard/feedparser.cpp \
src/services/standard/rdfparser.cpp \
src/services/standard/rssparser.cpp
src/services/standard/rssparser.cpp \
src/miscellaneous/serviceoperator.cpp
FORMS += src/gui/toolbareditor.ui \
src/network-web/downloaditem.ui \

View File

@ -373,7 +373,7 @@ void Application::onAboutToQuit() {
system()->removeTrolltechJunkRegistryKeys();
#endif
qApp->feedReader()->stop();
qApp->feedReader()->quit();
database()->saveDatabase();
if (mainForm() != nullptr) {

View File

@ -23,6 +23,8 @@
#include <cstdio>
#include <cstdlib>
#include <chrono>
#include <ctime>
Debugging::Debugging() {
@ -31,13 +33,18 @@ Debugging::Debugging() {
void Debugging::performLog(const char *message, QtMsgType type, const char *file, const char *function, int line) {
const char *type_string = typeToString(type);
std::time_t t = std::time(nullptr);
char mbstr[32];
std::strftime(mbstr, sizeof(mbstr), "%y/%d/%m %H:%M:%S", std::localtime(&t));
// Write to console.
if (file == 0 || function == 0 || line < 0) {
fprintf(stderr, "[%s] %s: %s\n", APP_LOW_NAME, type_string, message);
fprintf(stderr, "[%s] %s: %s (%s)\n", APP_LOW_NAME, type_string, message, mbstr);
}
else {
fprintf(stderr, "[%s] %s\n Type: %s\n File: %s (line %d)\n Function: %s\n\n",
APP_LOW_NAME, message, type_string, file, line, function);
fprintf(stderr, "[%s] %s (%s)\n Type: %s\n File: %s (line %d)\n Function: %s\n\n",
APP_LOW_NAME, message, mbstr, type_string, file, line, function);
}
if (type == QtFatalMsg) {

View File

@ -20,6 +20,7 @@
#include "services/standard/standardserviceentrypoint.h"
#include "services/owncloud/owncloudserviceentrypoint.h"
#include "services/tt-rss/ttrssserviceentrypoint.h"
#include "services/abstract/serviceroot.h"
#include "core/feedsmodel.h"
#include "core/feedsproxymodel.h"
@ -32,10 +33,12 @@
#include <QThread>
#include <QTimer>
#include <QtConcurrent/QtConcurrentRun>
FeedReader::FeedReader(QObject *parent)
: QObject(parent), m_feedServices(QList<ServiceEntryPoint*>()), m_autoUpdateTimer(new QTimer(this)),
: QObject(parent), m_feedServices(QList<ServiceEntryPoint*>()),
m_cacheSaveFutureWatcher(QFutureWatcher<void>()), m_autoUpdateTimer(new QTimer(this)),
m_feedDownloaderThread(nullptr), m_feedDownloader(nullptr),
m_dbCleanerThread(nullptr), m_dbCleaner(nullptr) {
m_feedsModel = new FeedsModel(this);
@ -43,8 +46,10 @@ FeedReader::FeedReader(QObject *parent)
m_messagesModel = new MessagesModel(this);
m_messagesProxyModel = new MessagesProxyModel(m_messagesModel, this);
connect(&m_cacheSaveFutureWatcher, &QFutureWatcher<void>::finished, this, &FeedReader::asyncCacheSaveFinished);
connect(m_autoUpdateTimer, &QTimer::timeout, this, &FeedReader::executeNextAutoUpdate);
updateAutoUpdateStatus();
asyncCacheSaveFinished();
if (qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool()) {
qDebug("Requesting update for all feeds on application startup.");
@ -209,11 +214,60 @@ void FeedReader::executeNextAutoUpdate() {
}
}
void FeedReader::stop() {
void FeedReader::checkServicesForAsyncOperations() {
checkServicesForAsyncOperations(false);
}
void FeedReader::checkServicesForAsyncOperations(bool wait_for_future) {
if (m_cacheSaveFutureWatcher.future().isStarted() || m_cacheSaveFutureWatcher.future().isRunning()) {
qDebug("Previous future is still running or was already started.");
// If we want to wait for future synchronously, we want to make sure that
// we save all cached data (app exit).
if (wait_for_future) {
qWarning("Waiting for previously started saving of cached service data.");
m_cacheSaveFutureWatcher.future().waitForFinished();
}
else {
qWarning("Some cached service data are being saved now, so aborting this saving cycle.");
// Some cache saving is now running.
return;
}
}
QFuture<void> future = QtConcurrent::run([&] {
foreach (ServiceRoot *service, m_feedsModel->serviceRoots()) {
// Store any cached data.
service->saveAllCachedData();
}
});
if (wait_for_future) {
qDebug("Waiting for saving of cached service data to finish.");
future.waitForFinished();
}
else {
m_cacheSaveFutureWatcher.setFuture(future);
}
}
void FeedReader::asyncCacheSaveFinished() {
qDebug("I will start next check for cached service data in 30 seconds.");
QTimer::singleShot(30000, [&] {
qDebug("Starting next check for cached service data in NOW.");
checkServicesForAsyncOperations(false);
});
}
void FeedReader::quit() {
if (m_autoUpdateTimer->isActive()) {
m_autoUpdateTimer->stop();
}
checkServicesForAsyncOperations(true);
// Close worker threads.
if (m_feedDownloaderThread != nullptr && m_feedDownloaderThread->isRunning()) {
m_feedDownloader->stopRunningUpdate();

View File

@ -23,12 +23,15 @@
#include "services/abstract/feed.h"
#include "core/feeddownloader.h"
#include <QFutureWatcher>
class FeedsModel;
class MessagesModel;
class MessagesProxyModel;
class FeedsProxyModel;
class ServiceEntryPoint;
class ServiceOperator;
class DatabaseCleaner;
class QTimer;
@ -69,11 +72,14 @@ class FeedReader : public QObject {
// Schedules all feeds from all accounts for update.
void updateAllFeeds();
void stopRunningFeedUpdate();
void stop();
void quit();
private slots:
// Is executed when next auto-update round could be done.
void executeNextAutoUpdate();
void checkServicesForAsyncOperations();
void checkServicesForAsyncOperations(bool wait_for_future);
void asyncCacheSaveFinished();
signals:
void feedUpdatesStarted();
@ -88,12 +94,16 @@ class FeedReader : public QObject {
MessagesModel *m_messagesModel;
MessagesProxyModel *m_messagesProxyModel;
QFutureWatcher<void> m_cacheSaveFutureWatcher;
// Auto-update stuff.
QTimer *m_autoUpdateTimer;
bool m_globalAutoUpdateEnabled;
int m_globalAutoUpdateInitialInterval;
int m_globalAutoUpdateRemainingInterval;
ServiceOperator *m_serviceOperator;
QThread *m_feedDownloaderThread;
FeedDownloader *m_feedDownloader;

View File

@ -0,0 +1,25 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
// RSS Guard 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, either version 3 of the License, or
// (at your option) any later version.
//
// RSS Guard 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 RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "miscellaneous/serviceoperator.h"
ServiceOperator::ServiceOperator(QObject *parent) : QObject(parent) {
}
ServiceOperator::~ServiceOperator() {
}

View File

@ -0,0 +1,36 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
// RSS Guard 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, either version 3 of the License, or
// (at your option) any later version.
//
// RSS Guard 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 RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef SERVICEOPERATOR_H
#define SERVICEOPERATOR_H
#include <QObject>
class ServiceOperator : public QObject {
Q_OBJECT
public:
explicit ServiceOperator(QObject *parent = 0);
virtual ~ServiceOperator();
signals:
public slots:
};
#endif // SERVICEOPERATOR_H

View File

@ -192,6 +192,9 @@ QList<Message> ServiceRoot::undeletedMessages() const {
return DatabaseQueries::getUndeletedMessagesForAccount(database, accountId());
}
void ServiceRoot::saveAllCachedData() {
}
void ServiceRoot::itemChanged(const QList<RootItem*> &items) {
emit dataChanged(items);
}

View File

@ -59,6 +59,7 @@ class ServiceRoot : public RootItem {
// NOTE: Caller does NOT take ownership of created menu!
virtual QList<QAction*> addItemMenu();
// Returns actions to display as context menu.
QList<QAction*> contextMenu();
// Returns list of specific actions to be shown in main window menu
@ -83,6 +84,10 @@ class ServiceRoot : public RootItem {
virtual void start(bool freshly_activated) = 0;
virtual void stop() = 0;
// Is called in short intervals in worker thread.
// Service can save its cached data (if any) here.
virtual void saveAllCachedData();
// Account ID corresponds with DB attribute Accounts (id).
int accountId() const;
void setAccountId(int account_id);

View File

@ -31,6 +31,8 @@
#include "services/owncloud/gui/formeditowncloudaccount.h"
#include "services/owncloud/gui/formowncloudfeeddetails.h"
#include <QThread>
OwnCloudServiceRoot::OwnCloudServiceRoot(RootItem *parent)
: ServiceRoot(parent), m_recycleBin(new OwnCloudRecycleBin(this)),
@ -195,6 +197,10 @@ void OwnCloudServiceRoot::saveAccountDataToDatabase() {
}
}
void OwnCloudServiceRoot::saveAllCachedData() {
QThread::msleep(2000);
}
void OwnCloudServiceRoot::addNewFeed(const QString &url) {
if (!qApp->feedUpdateLock()->tryLock()) {
// Lock was not obtained because

View File

@ -51,6 +51,8 @@ class OwnCloudServiceRoot : public ServiceRoot {
void updateTitle();
void saveAccountDataToDatabase();
void saveAllCachedData();
public slots:
void addNewFeed(const QString &url);
void addNewCategory();