summaryrefslogtreecommitdiffstats
path: root/common/storage
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2018-02-15 10:19:08 +0100
committerChristian Mollekopf <chrigi_1@fastmail.fm>2018-02-15 11:08:52 +0100
commit531972042d4b610258c8af8a17ec3a99cd063dda (patch)
treeef4356ec141f0f1ccd756e8610b08553b866bf78 /common/storage
parentf51963f057bcbdd175114433913a1c5f0eebd546 (diff)
downloadsink-531972042d4b610258c8af8a17ec3a99cd063dda.tar.gz
sink-531972042d4b610258c8af8a17ec3a99cd063dda.zip
Fixed crashes due to concurrently running queries.
A single QueryRunner should never have multiple workers running at the same time. We did not properly enforce this in case of incremental updates coming in. The only way I managed to reproduce the crash: * Open a large folder with lots of unread mail in kube * Select a mail in the maillist and hold the down button * This will: * Repeatedly call fetch more * Trigger lot's of mark as read modifications that result in notifications. * Eventually it crashes somewhere in EntityStore, likely because of concurrent access of the filter structure which is shared through the state. We now ensure in the single threaded portion of the code that we only ever run one worker at a time. If we did receive an update during, we remember that change and fetch more once we're done. To be able to call fetch again that portion was also factored out into a separate function.
Diffstat (limited to 'common/storage')
-rw-r--r--common/storage/entitystore.cpp1
-rw-r--r--common/storage/entitystore.h1
2 files changed, 2 insertions, 0 deletions
diff --git a/common/storage/entitystore.cpp b/common/storage/entitystore.cpp
index 8fbc2ad..020f3fd 100644
--- a/common/storage/entitystore.cpp
+++ b/common/storage/entitystore.cpp
@@ -459,6 +459,7 @@ void EntityStore::indexLookup(const QByteArray &type, const QByteArray &property
459 459
460void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback) 460void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback)
461{ 461{
462 Q_ASSERT(d);
462 auto db = DataStore::mainDatabase(d->getTransaction(), type); 463 auto db = DataStore::mainDatabase(d->getTransaction(), type);
463 db.findLatest(uid, 464 db.findLatest(uid,
464 [=](const QByteArray &key, const QByteArray &value) { 465 [=](const QByteArray &key, const QByteArray &value) {
diff --git a/common/storage/entitystore.h b/common/storage/entitystore.h
index 00241f2..3eb0b7b 100644
--- a/common/storage/entitystore.h
+++ b/common/storage/entitystore.h
@@ -37,6 +37,7 @@ class SINK_EXPORT EntityStore
37public: 37public:
38 typedef QSharedPointer<EntityStore> Ptr; 38 typedef QSharedPointer<EntityStore> Ptr;
39 EntityStore(const ResourceContext &resourceContext, const Sink::Log::Context &); 39 EntityStore(const ResourceContext &resourceContext, const Sink::Log::Context &);
40 ~EntityStore() = default;
40 41
41 //Only the pipeline may call the following functions outside of tests 42 //Only the pipeline may call the following functions outside of tests
42 bool add(const QByteArray &type, ApplicationDomain::ApplicationDomainType newEntity, bool replayToSource); 43 bool add(const QByteArray &type, ApplicationDomain::ApplicationDomainType newEntity, bool replayToSource);