diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-09-15 21:24:37 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-09-15 21:24:37 +0200 |
commit | 1deac558af4b1c9f04352ede7f8e172f11a70a6b (patch) | |
tree | 18d6e0441c4fb13f0c265ce6226d6e7179257fc8 /common/queryrunner.cpp | |
parent | 6d5be4fb7b8cbc450e2780905eaac9a18b486c5c (diff) | |
download | sink-1deac558af4b1c9f04352ede7f8e172f11a70a6b.tar.gz sink-1deac558af4b1c9f04352ede7f8e172f11a70a6b.zip |
Avoid crashing if the executing object is already gone when we go into
the continuation.
This happens if Kube is used to look at a folder that is currently being
freshly synchronized, so we continuously get new results.
Diffstat (limited to 'common/queryrunner.cpp')
-rw-r--r-- | common/queryrunner.cpp | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/common/queryrunner.cpp b/common/queryrunner.cpp index 052db39..11459f1 100644 --- a/common/queryrunner.cpp +++ b/common/queryrunner.cpp | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include <limits> | 21 | #include <limits> |
22 | #include <QTime> | 22 | #include <QTime> |
23 | #include <QPointer> | ||
23 | 24 | ||
24 | #include "commands.h" | 25 | #include "commands.h" |
25 | #include "log.h" | 26 | #include "log.h" |
@@ -71,6 +72,7 @@ QueryRunner<DomainType>::QueryRunner(const Sink::Query &query, const Sink::Resou | |||
71 | if (query.limit && query.sortProperty.isEmpty()) { | 72 | if (query.limit && query.sortProperty.isEmpty()) { |
72 | SinkWarning() << "A limited query without sorting is typically a bad idea."; | 73 | SinkWarning() << "A limited query without sorting is typically a bad idea."; |
73 | } | 74 | } |
75 | auto guardPtr = QPointer<QObject>(&guard); | ||
74 | // We delegate loading of initial data to the result provider, so it can decide for itself what it needs to load. | 76 | // We delegate loading of initial data to the result provider, so it can decide for itself what it needs to load. |
75 | mResultProvider->setFetcher([=](const typename DomainType::Ptr &parent) { | 77 | mResultProvider->setFetcher([=](const typename DomainType::Ptr &parent) { |
76 | const QByteArray parentId = parent ? parent->identifier() : QByteArray(); | 78 | const QByteArray parentId = parent ? parent->identifier() : QByteArray(); |
@@ -81,12 +83,20 @@ QueryRunner<DomainType>::QueryRunner(const Sink::Query &query, const Sink::Resou | |||
81 | worker.executeInitialQuery(query, parent, *resultProvider, mOffset[parentId], mBatchSize); | 83 | worker.executeInitialQuery(query, parent, *resultProvider, mOffset[parentId], mBatchSize); |
82 | resultProvider->initialResultSetComplete(parent); | 84 | resultProvider->initialResultSetComplete(parent); |
83 | } else { | 85 | } else { |
84 | async::run<QPair<qint64, qint64> >([=]() { | 86 | auto resultTransformation = mResultTransformation; |
85 | QueryWorker<DomainType> worker(query, instanceIdentifier, factory, bufferType, mResultTransformation); | 87 | auto offset = mOffset[parentId]; |
86 | const auto newRevisionAndReplayedEntities = worker.executeInitialQuery(query, parent, *resultProvider, mOffset[parentId], mBatchSize); | 88 | auto batchSize = mBatchSize; |
89 | //The lambda will be executed in a separate thread, so we're extra careful | ||
90 | async::run<QPair<qint64, qint64> >([resultTransformation, offset, batchSize, query, bufferType, instanceIdentifier, factory, resultProvider, parent]() { | ||
91 | QueryWorker<DomainType> worker(query, instanceIdentifier, factory, bufferType, resultTransformation); | ||
92 | const auto newRevisionAndReplayedEntities = worker.executeInitialQuery(query, parent, *resultProvider, offset, batchSize); | ||
87 | return newRevisionAndReplayedEntities; | 93 | return newRevisionAndReplayedEntities; |
88 | }) | 94 | }) |
89 | .template syncThen<void, QPair<qint64, qint64>>([=](const QPair<qint64, qint64> &newRevisionAndReplayedEntities) { | 95 | .template syncThen<void, QPair<qint64, qint64>>([this, parentId, query, parent, resultProvider, guardPtr](const QPair<qint64, qint64> &newRevisionAndReplayedEntities) { |
96 | if (!guardPtr) { | ||
97 | qWarning() << "The parent object is already gone"; | ||
98 | return; | ||
99 | } | ||
90 | mOffset[parentId] += newRevisionAndReplayedEntities.second; | 100 | mOffset[parentId] += newRevisionAndReplayedEntities.second; |
91 | // Only send the revision replayed information if we're connected to the resource, there's no need to start the resource otherwise. | 101 | // Only send the revision replayed information if we're connected to the resource, there's no need to start the resource otherwise. |
92 | if (query.liveQuery) { | 102 | if (query.liveQuery) { |
@@ -110,7 +120,11 @@ QueryRunner<DomainType>::QueryRunner(const Sink::Query &query, const Sink::Resou | |||
110 | const auto newRevisionAndReplayedEntities = worker.executeIncrementalQuery(query, *resultProvider); | 120 | const auto newRevisionAndReplayedEntities = worker.executeIncrementalQuery(query, *resultProvider); |
111 | return newRevisionAndReplayedEntities; | 121 | return newRevisionAndReplayedEntities; |
112 | }) | 122 | }) |
113 | .template syncThen<void, QPair<qint64, qint64> >([query, this, resultProvider](const QPair<qint64, qint64> &newRevisionAndReplayedEntities) { | 123 | .template syncThen<void, QPair<qint64, qint64> >([query, this, resultProvider, guardPtr](const QPair<qint64, qint64> &newRevisionAndReplayedEntities) { |
124 | if (!guardPtr) { | ||
125 | qWarning() << "The parent object is already gone"; | ||
126 | return; | ||
127 | } | ||
114 | // Only send the revision replayed information if we're connected to the resource, there's no need to start the resource otherwise. | 128 | // Only send the revision replayed information if we're connected to the resource, there's no need to start the resource otherwise. |
115 | mResourceAccess->sendRevisionReplayedCommand(newRevisionAndReplayedEntities.first); | 129 | mResourceAccess->sendRevisionReplayedCommand(newRevisionAndReplayedEntities.first); |
116 | resultProvider->setRevision(newRevisionAndReplayedEntities.first); | 130 | resultProvider->setRevision(newRevisionAndReplayedEntities.first); |