Attempt to fix #121.
This commit is contained in:
parent
2d8fbab362
commit
31cd7d5b01
@ -97,7 +97,41 @@ Message Message::fromSqlRecord(const QSqlRecord& record, bool* result) {
|
||||
*result = true;
|
||||
}
|
||||
|
||||
return message;
|
||||
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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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_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,25 +228,34 @@ 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.
|
||||
|
||||
// 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 (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.
|
||||
service->saveAllCachedData();
|
||||
}
|
||||
});
|
||||
|
||||
if (wait_for_future) {
|
||||
qDebug("Waiting for saving of cached service data to finish.");
|
||||
future.waitForFinished();
|
||||
}
|
||||
else {
|
||||
m_cacheSaveFutureWatcher->setFuture(future);
|
||||
}
|
||||
if (wait_for_future) {
|
||||
qDebug("Waiting for saving of cached service data to finish.");
|
||||
future.waitForFinished();
|
||||
}
|
||||
else {
|
||||
m_cacheSaveFutureWatcher->setFuture(future);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FeedReader::asyncCacheSaveFinished() {
|
||||
@ -257,9 +271,9 @@ void FeedReader::quit() {
|
||||
m_autoUpdateTimer->stop();
|
||||
}
|
||||
|
||||
checkServicesForAsyncOperations(true);
|
||||
checkServicesForAsyncOperations(false, true);
|
||||
|
||||
// Close worker threads.
|
||||
// Close worker threads.
|
||||
if (m_feedDownloaderThread != nullptr && m_feedDownloaderThread->isRunning()) {
|
||||
m_feedDownloader->stopRunningUpdate();
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
@ -118,5 +150,9 @@ QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<
|
||||
clearCache();
|
||||
m_cacheSaveMutex->unlock();
|
||||
|
||||
return QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>>(cached_data_read, cached_data_imp);
|
||||
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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user