Attempt to fix #121.

This commit is contained in:
Martin Rotter 2017-09-09 14:14:25 +02:00
parent 2d8fbab362
commit 31cd7d5b01
9 changed files with 158 additions and 24 deletions

View File

@ -100,6 +100,40 @@ Message Message::fromSqlRecord(const QSqlRecord& record, bool* result) {
return message;
}
QDataStream& operator<<(QDataStream& out, const Message& myObj) {
out << myObj.m_accountId
<< myObj.m_customHash
<< myObj.m_customId
<< myObj.m_feedId
<< myObj.m_id
<< myObj.m_isImportant
<< myObj.m_isRead;
return out;
}
QDataStream& operator>>(QDataStream& in, Message& myObj) {
int accountId;
QString customHash;
QString customId;
QString feedId;
int id;
bool isImportant;
bool isRead;
in >> accountId >> customHash >> customId >> feedId >> id >> isImportant >> isRead;
myObj.m_accountId = accountId;
myObj.m_customHash = customHash;
myObj.m_customId = customId;
myObj.m_feedId = feedId;
myObj.m_id = id;
myObj.m_isImportant = isImportant;
myObj.m_isRead = isRead;
return in;
}
uint qHash(Message key, uint seed) {
Q_UNUSED(seed)
return (key.m_accountId * 10000) + key.m_id;

View File

@ -23,6 +23,7 @@
#include <QDateTime>
#include <QStringList>
#include <QSqlRecord>
#include <QDataStream>
// Represents single enclosure.
@ -79,6 +80,11 @@ class Message {
}
};
// Serialize message state.
// NOTE: This is used for persistent caching of message state changes.
QDataStream& operator<<(QDataStream& out, const Message& myObj);
QDataStream& operator>>(QDataStream& in, Message& myObj);
uint qHash(Message key, uint seed);
uint qHash(const Message& key);

View File

@ -83,14 +83,17 @@ void FeedReader::updateFeeds(const QList<Feed*>& feeds) {
if (m_feedDownloader == nullptr) {
m_feedDownloader = new FeedDownloader();
m_feedDownloaderThread = new QThread();
// Downloader setup.
qRegisterMetaType<QList<Feed*>>("QList<Feed*>");
m_feedDownloader->moveToThread(m_feedDownloaderThread);
connect(m_feedDownloaderThread, &QThread::finished, m_feedDownloaderThread, &QThread::deleteLater);
connect(m_feedDownloader, &FeedDownloader::updateFinished, this, &FeedReader::feedUpdatesFinished);
connect(m_feedDownloader, &FeedDownloader::updateProgress, this, &FeedReader::feedUpdatesProgress);
connect(m_feedDownloader, &FeedDownloader::updateStarted, this, &FeedReader::feedUpdatesStarted);
connect(m_feedDownloader, &FeedDownloader::updateFinished, qApp->feedUpdateLock(), &Mutex::unlock);
// Connections are made, start the feed downloader thread.
m_feedDownloaderThread->start();
}
@ -149,10 +152,12 @@ DatabaseCleaner* FeedReader::databaseCleaner() {
if (m_dbCleaner == nullptr) {
m_dbCleaner = new DatabaseCleaner();
m_dbCleanerThread = new QThread();
// Downloader setup.
qRegisterMetaType<CleanerOrders>("CleanerOrders");
m_dbCleaner->moveToThread(m_dbCleanerThread);
connect(m_dbCleanerThread, SIGNAL(finished()), m_dbCleanerThread, SLOT(deleteLater()));
// Connections are made, start the feed downloader thread.
m_dbCleanerThread->start();
}
@ -211,8 +216,8 @@ void FeedReader::checkServicesForAsyncOperations() {
checkServicesForAsyncOperations(false);
}
void FeedReader::checkServicesForAsyncOperations(bool wait_for_future) {
if (m_cacheSaveFutureWatcher->future().isRunning()) {
void FeedReader::checkServicesForAsyncOperations(bool wait_for_future, bool do_on_this_thread) {
if (!do_on_this_thread && m_cacheSaveFutureWatcher->future().isRunning()) {
qDebug("Previous future is still running.");
// If we want to wait for future synchronously, we want to make sure that
@ -223,11 +228,19 @@ void FeedReader::checkServicesForAsyncOperations(bool wait_for_future) {
}
else {
qWarning("Some cached service data are being saved now, so aborting this saving cycle.");
// Some cache saving is now running.
return;
}
}
if (do_on_this_thread) {
foreach (ServiceRoot* service, m_feedsModel->serviceRoots()) {
// Store any cached data.
service->saveAllCachedData();
}
}
else {
QFuture<void> future = QtConcurrent::run([&] {
foreach (ServiceRoot* service, m_feedsModel->serviceRoots()) {
// Store any cached data.
@ -242,6 +255,7 @@ void FeedReader::checkServicesForAsyncOperations(bool wait_for_future) {
else {
m_cacheSaveFutureWatcher->setFuture(future);
}
}
}
void FeedReader::asyncCacheSaveFinished() {
@ -257,7 +271,7 @@ void FeedReader::quit() {
m_autoUpdateTimer->stop();
}
checkServicesForAsyncOperations(true);
checkServicesForAsyncOperations(false, true);
// Close worker threads.
if (m_feedDownloaderThread != nullptr && m_feedDownloaderThread->isRunning()) {

View File

@ -79,7 +79,7 @@ class FeedReader : public QObject {
// Is executed when next auto-update round could be done.
void executeNextAutoUpdate();
void checkServicesForAsyncOperations();
void checkServicesForAsyncOperations(bool wait_for_future);
void checkServicesForAsyncOperations(bool wait_for_future, bool do_on_this_thread = false);
void asyncCacheSaveFinished();
signals:

View File

@ -17,9 +17,11 @@
#include "services/abstract/cacheforserviceroot.h"
#include "miscellaneous/application.h"
#include "miscellaneous/mutex.h"
#include <QSet>
#include <QDir>
CacheForServiceRoot::CacheForServiceRoot() : m_cacheSaveMutex(new Mutex(QMutex::NonRecursive, nullptr)),
@ -77,10 +79,24 @@ void CacheForServiceRoot::saveCacheToFile(int accId) {
m_cacheSaveMutex->lock();
// Save to file.
const QString file_cache = qApp->userDataPath() + QDir::separator() + QString::number(accId) + "-cached-msgs.dat";
if (isEmpty()) {
QFile::remove(file_cache);
}
else {
QFile file(file_cache);
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QDataStream stream(&file);
stream << m_cachedStatesImportant << m_cachedStatesRead;
file.flush();
file.close();
}
clearCache();
}
m_cacheSaveMutex->unlock();
}
@ -94,6 +110,22 @@ void CacheForServiceRoot::loadCacheFromFile(int accId) {
clearCache();
// Load from file.
const QString file_cache = qApp->userDataPath() + QDir::separator() + QString::number(accId) + "-cached-msgs.dat";
QFile file(file_cache);
if (file.exists()) {
if (file.open(QIODevice::ReadOnly)) {
QDataStream stream(&file);
stream >> m_cachedStatesImportant >> m_cachedStatesRead;
file.flush();
file.close();
}
file.remove();
}
// TODO: TODO
m_cacheSaveMutex->unlock();
}
@ -101,7 +133,7 @@ void CacheForServiceRoot::loadCacheFromFile(int accId) {
QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>> CacheForServiceRoot::takeMessageCache() {
m_cacheSaveMutex->lock();
if (m_cachedStatesRead.isEmpty() && m_cachedStatesImportant.isEmpty()) {
if (isEmpty()) {
// No cached changes.
m_cacheSaveMutex->unlock();
@ -120,3 +152,7 @@ QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<
return QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>>(cached_data_read, cached_data_imp);
}
bool CacheForServiceRoot::isEmpty() const {
return m_cachedStatesRead.isEmpty() && m_cachedStatesImportant.isEmpty();
}

View File

@ -46,6 +46,10 @@ class CacheForServiceRoot {
Mutex* m_cacheSaveMutex;
QMap<RootItem::ReadStatus, QStringList> m_cachedStatesRead;
QMap<RootItem::Importance, QList<Message>> m_cachedStatesImportant;
private:
bool isEmpty() const;
void clearCache();
};
#endif // CACHEFORSERVICEROOT_H

View File

@ -473,3 +473,33 @@ bool RootItem::removeChild(int index) {
return false;
}
}
QDataStream& operator>>(QDataStream& in, RootItem::ReadStatus& myObj) {
int obj;
in >> obj;
myObj = (RootItem::ReadStatus)obj;
return in;
}
QDataStream& operator<<(QDataStream& out, const RootItem::ReadStatus& myObj) {
out << (int)myObj;
return out;
}
QDataStream& operator>>(QDataStream& in, RootItem::Importance& myObj) {
int obj;
in >> obj;
myObj = (RootItem::Importance)obj;
return in;
}
QDataStream& operator<<(QDataStream& out, const RootItem::Importance& myObj) {
out << (int)myObj;
return out;
}

View File

@ -236,4 +236,12 @@ class RootItem : public QObject {
RootItem* m_parentItem;
};
QDataStream& operator<<(QDataStream& out, const RootItem::Importance& myObj);
QDataStream& operator>>(QDataStream& in, RootItem::Importance& myObj);
QDataStream& operator<<(QDataStream& out, const RootItem::ReadStatus& myObj);
QDataStream& operator>>(QDataStream& in, RootItem::ReadStatus& myObj);
#endif // ROOTITEM_H

View File

@ -92,6 +92,7 @@ RecycleBin* OwnCloudServiceRoot::recycleBin() const {
void OwnCloudServiceRoot::start(bool freshly_activated) {
Q_UNUSED(freshly_activated)
loadFromDatabase();
//loadCacheFromFile(accountId());
if (qApp->isFirstRun(QSL("3.1.1")) || (childCount() == 1 && child(0)->kind() == RootItemKind::Bin)) {
syncIn();
@ -99,6 +100,7 @@ void OwnCloudServiceRoot::start(bool freshly_activated) {
}
void OwnCloudServiceRoot::stop() {
//saveCacheToFile(accountId());
}
QString OwnCloudServiceRoot::code() const {