summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2017-12-28 12:05:34 +0100
committerChristian Mollekopf <chrigi_1@fastmail.fm>2018-01-02 13:31:14 +0100
commit625190d311adfcf3f0436cfece82249a92489348 (patch)
tree1010950e14b57560ae90abe20a5657750ad27137
parent11b790ba6f06141db802273628ce2d191982677e (diff)
downloadsink-625190d311adfcf3f0436cfece82249a92489348.tar.gz
sink-625190d311adfcf3f0436cfece82249a92489348.zip
No parent query
-rw-r--r--common/modelresult.cpp59
-rw-r--r--common/modelresult.h6
-rw-r--r--common/notifier.cpp8
-rw-r--r--common/queryrunner.cpp22
-rw-r--r--common/queryrunner.h2
-rw-r--r--common/resourcefacade.cpp10
-rw-r--r--common/resultprovider.h91
-rw-r--r--common/store.cpp12
-rw-r--r--common/test.cpp17
-rw-r--r--tests/clientapitest.cpp22
-rw-r--r--tests/databasepopulationandfacadequerybenchmark.cpp4
-rw-r--r--tests/mailquerybenchmark.cpp8
-rw-r--r--tests/querytest.cpp7
13 files changed, 119 insertions, 149 deletions
diff --git a/common/modelresult.cpp b/common/modelresult.cpp
index 4295a44..e11ec9c 100644
--- a/common/modelresult.cpp
+++ b/common/modelresult.cpp
@@ -253,14 +253,14 @@ bool ModelResult<T, Ptr>::hasChildren(const QModelIndex &parent) const
253 if (mQuery.parentProperty().isEmpty() && parent.isValid()) { 253 if (mQuery.parentProperty().isEmpty() && parent.isValid()) {
254 return false; 254 return false;
255 } 255 }
256 //Figure out whether we have children 256 // //Figure out whether we have children
257 const auto id = parent.internalId(); 257 // const auto id = parent.internalId();
258 if (!mEntityChildrenFetched.contains(id)) { 258 // if (!mEntityChildrenFetched.contains(id)) {
259 //Since we don't retrieve that information as part of the entity, 259 // //Since we don't retrieve that information as part of the entity,
260 //we have to query for the children to see if we have some 260 // //we have to query for the children to see if we have some
261 auto p = const_cast<ModelResult<T, Ptr>*>(this); 261 // auto p = const_cast<ModelResult<T, Ptr>*>(this);
262 p->fetchMore(parent); 262 // p->fetchMore(parent);
263 } 263 // }
264 return QAbstractItemModel::hasChildren(parent); 264 return QAbstractItemModel::hasChildren(parent);
265} 265}
266 266
@@ -278,7 +278,9 @@ template <class T, class Ptr>
278void ModelResult<T, Ptr>::fetchMore(const QModelIndex &parent) 278void ModelResult<T, Ptr>::fetchMore(const QModelIndex &parent)
279{ 279{
280 SinkTraceCtx(mLogCtx) << "Fetching more: " << parent; 280 SinkTraceCtx(mLogCtx) << "Fetching more: " << parent;
281 fetchEntities(parent); 281 if (!parent.isValid()) {
282 fetchEntities();
283 }
282} 284}
283 285
284template <class T, class Ptr> 286template <class T, class Ptr>
@@ -287,10 +289,10 @@ void ModelResult<T, Ptr>::add(const Ptr &value)
287 const auto childId = qHash(*value); 289 const auto childId = qHash(*value);
288 const auto id = parentId(value); 290 const auto id = parentId(value);
289 // Ignore updates we get before the initial fetch is done 291 // Ignore updates we get before the initial fetch is done
290 if (!mEntityChildrenFetched.contains(id)) { 292 // if (!mEntityChildrenFetched.contains(id)) {
291 SinkTraceCtx(mLogCtx) << "Too early" << id; 293 // SinkTraceCtx(mLogCtx) << "Too early" << id;
292 return; 294 // return;
293 } 295 // }
294 if (mEntities.contains(childId)) { 296 if (mEntities.contains(childId)) {
295 SinkWarningCtx(mLogCtx) << "Entity already in model: " << value->identifier(); 297 SinkWarningCtx(mLogCtx) << "Entity already in model: " << value->identifier();
296 return; 298 return;
@@ -335,27 +337,27 @@ void ModelResult<T, Ptr>::remove(const Ptr &value)
335} 337}
336 338
337template <class T, class Ptr> 339template <class T, class Ptr>
338void ModelResult<T, Ptr>::fetchEntities(const QModelIndex &parent) 340void ModelResult<T, Ptr>::fetchEntities()
339{ 341{
340 Q_ASSERT(QThread::currentThread() == this->thread()); 342 Q_ASSERT(QThread::currentThread() == this->thread());
341 const auto id = getIdentifier(parent); 343 const auto id = getIdentifier({});
342 //There is already a fetch in progress, don't fetch again. 344 //There is already a fetch in progress, don't fetch again.
343 if (mEntityChildrenFetched.contains(id) && !mEntityChildrenFetchComplete.contains(id)) { 345 if (mEntityChildrenFetched.contains(id) && !mEntityChildrenFetchComplete.contains(id)) {
344 SinkTraceCtx(mLogCtx) << "A fetch is already in progress: " << parent; 346 SinkTraceCtx(mLogCtx) << "A fetch is already in progress.";
345 return; 347 return;
346 } 348 }
347 mEntityChildrenFetchComplete.remove(id); 349 mEntityChildrenFetchComplete.remove(id);
348 mEntityChildrenFetched.insert(id); 350 mEntityChildrenFetched.insert(id);
349 SinkTraceCtx(mLogCtx) << "Loading child entities of parent " << id; 351 SinkTraceCtx(mLogCtx) << "Loading child entities of parent " << id;
350 if (loadEntities) { 352 if (loadEntities) {
351 loadEntities(parent.data(DomainObjectRole).template value<Ptr>()); 353 loadEntities();
352 } else { 354 } else {
353 SinkWarningCtx(mLogCtx) << "No way to fetch entities"; 355 SinkWarningCtx(mLogCtx) << "No way to fetch entities";
354 } 356 }
355} 357}
356 358
357template <class T, class Ptr> 359template <class T, class Ptr>
358void ModelResult<T, Ptr>::setFetcher(const std::function<void(const Ptr &parent)> &fetcher) 360void ModelResult<T, Ptr>::setFetcher(const std::function<void()> &fetcher)
359{ 361{
360 SinkTraceCtx(mLogCtx) << "Setting fetcher"; 362 SinkTraceCtx(mLogCtx) << "Setting fetcher";
361 loadEntities = fetcher; 363 loadEntities = fetcher;
@@ -364,7 +366,7 @@ void ModelResult<T, Ptr>::setFetcher(const std::function<void(const Ptr &parent)
364template <class T, class Ptr> 366template <class T, class Ptr>
365void ModelResult<T, Ptr>::setEmitter(const typename Sink::ResultEmitter<Ptr>::Ptr &emitter) 367void ModelResult<T, Ptr>::setEmitter(const typename Sink::ResultEmitter<Ptr>::Ptr &emitter)
366{ 368{
367 setFetcher([this](const Ptr &parent) { mEmitter->fetch(parent); }); 369 setFetcher([this]() { mEmitter->fetch(); });
368 370
369 QPointer<QObject> guard(this); 371 QPointer<QObject> guard(this);
370 emitter->onAdded([this, guard](const Ptr &value) { 372 emitter->onAdded([this, guard](const Ptr &value) {
@@ -389,18 +391,19 @@ void ModelResult<T, Ptr>::setEmitter(const typename Sink::ResultEmitter<Ptr>::Pt
389 remove(value); 391 remove(value);
390 }); 392 });
391 }); 393 });
392 emitter->onInitialResultSetComplete([this, guard](const Ptr &parent, bool fetchedAll) { 394 emitter->onInitialResultSetComplete([this, guard](bool fetchedAll) {
393 SinkTraceCtx(mLogCtx) << "Initial result set complete. Fetched all: " << fetchedAll; 395 SinkTraceCtx(mLogCtx) << "Initial result set complete. Fetched all: " << fetchedAll;
394 Q_ASSERT(guard); 396 Q_ASSERT(guard);
395 Q_ASSERT(QThread::currentThread() == this->thread()); 397 Q_ASSERT(QThread::currentThread() == this->thread());
396 398
397 const qint64 parentId = parent ? qHash(*parent) : 0; 399 // const qint64 parentId = parent ? qHash(*parent) : 0;
398 const auto parentIndex = createIndexFromId(parentId); 400 // const auto parentIndex = createIndexFromId(parentId);
399 mEntityChildrenFetchComplete.insert(parentId); 401 mEntityChildrenFetchComplete.insert(0);
400 if (fetchedAll) { 402 if (fetchedAll) {
401 mEntityAllChildrenFetched.insert(parentId); 403 mEntityAllChildrenFetched.insert(0);
402 } 404 }
403 emit dataChanged(parentIndex, parentIndex, QVector<int>() << ChildrenFetchedRole); 405 // emit dataChanged(parentIndex, parentIndex, QVector<int>() << ChildrenFetchedRole);
406 emit dataChanged({}, {}, QVector<int>() << ChildrenFetchedRole);
404 }); 407 });
405 mEmitter = emitter; 408 mEmitter = emitter;
406} 409}
@@ -423,9 +426,9 @@ void ModelResult<T, Ptr>::modify(const Ptr &value)
423 } 426 }
424 auto id = parentId(value); 427 auto id = parentId(value);
425 // Ignore updates we get before the initial fetch is done 428 // Ignore updates we get before the initial fetch is done
426 if (!mEntityChildrenFetched.contains(id)) { 429 // if (!mEntityChildrenFetched.contains(id)) {
427 return; 430 // return;
428 } 431 // }
429 auto parent = createIndexFromId(id); 432 auto parent = createIndexFromId(id);
430 SinkTraceCtx(mLogCtx) << "Modified entity:" << value->identifier() << ", id: " << childId; 433 SinkTraceCtx(mLogCtx) << "Modified entity:" << value->identifier() << ", id: " << childId;
431 auto i = mTree[id].indexOf(childId); 434 auto i = mTree[id].indexOf(childId);
diff --git a/common/modelresult.h b/common/modelresult.h
index cc263cf..a4def81 100644
--- a/common/modelresult.h
+++ b/common/modelresult.h
@@ -65,7 +65,7 @@ public:
65 bool canFetchMore(const QModelIndex &parent) const; 65 bool canFetchMore(const QModelIndex &parent) const;
66 void fetchMore(const QModelIndex &parent); 66 void fetchMore(const QModelIndex &parent);
67 67
68 void setFetcher(const std::function<void(const Ptr &parent)> &fetcher); 68 void setFetcher(const std::function<void()> &fetcher);
69 69
70private: 70private:
71 void add(const Ptr &value); 71 void add(const Ptr &value);
@@ -75,7 +75,7 @@ private:
75 75
76 qint64 parentId(const Ptr &value); 76 qint64 parentId(const Ptr &value);
77 QModelIndex createIndexFromId(const qint64 &id) const; 77 QModelIndex createIndexFromId(const qint64 &id) const;
78 void fetchEntities(const QModelIndex &parent); 78 void fetchEntities();
79 79
80 Sink::Log::Context mLogCtx; 80 Sink::Log::Context mLogCtx;
81 // TODO we should be able to directly use T as index, with an appropriate hash function, and thus have a QMap<T, T> and QList<T> 81 // TODO we should be able to directly use T as index, with an appropriate hash function, and thus have a QMap<T, T> and QList<T>
@@ -88,7 +88,7 @@ private:
88 QMap<qint64 /* entity id */, int /* Status */> mEntityStatus; 88 QMap<qint64 /* entity id */, int /* Status */> mEntityStatus;
89 QList<QByteArray> mPropertyColumns; 89 QList<QByteArray> mPropertyColumns;
90 Sink::Query mQuery; 90 Sink::Query mQuery;
91 std::function<void(const Ptr &)> loadEntities; 91 std::function<void()> loadEntities;
92 typename Sink::ResultEmitter<Ptr>::Ptr mEmitter; 92 typename Sink::ResultEmitter<Ptr>::Ptr mEmitter;
93 async::ThreadBoundary threadBoundary; 93 async::ThreadBoundary threadBoundary;
94 QScopedPointer<Sink::Notifier> mNotifier; 94 QScopedPointer<Sink::Notifier> mNotifier;
diff --git a/common/notifier.cpp b/common/notifier.cpp
index 9aa6c90..131fd7a 100644
--- a/common/notifier.cpp
+++ b/common/notifier.cpp
@@ -82,16 +82,10 @@ Notifier::Notifier(const Sink::Query &resourceQuery) : d(new Sink::Notifier::Pri
82 resourceAccess->open(); 82 resourceAccess->open();
83 d->listenForNotifications(resourceAccess); 83 d->listenForNotifications(resourceAccess);
84 }); 84 });
85 emitter->onModified([](const ApplicationDomain::SinkResource::Ptr &) {
86 });
87 emitter->onRemoved([](const ApplicationDomain::SinkResource::Ptr &) {
88 });
89 emitter->onInitialResultSetComplete([](const ApplicationDomain::SinkResource::Ptr &, bool) {
90 });
91 emitter->onComplete([resourceCtx]() { 85 emitter->onComplete([resourceCtx]() {
92 SinkTraceCtx(resourceCtx) << "Resource query complete"; 86 SinkTraceCtx(resourceCtx) << "Resource query complete";
93 }); 87 });
94 emitter->fetch({}); 88 emitter->fetch();
95 if (resourceQuery.liveQuery()) { 89 if (resourceQuery.liveQuery()) {
96 d->mResourceEmitter = emitter; 90 d->mResourceEmitter = emitter;
97 } 91 }
diff --git a/common/queryrunner.cpp b/common/queryrunner.cpp
index f3a9af8..288ce27 100644
--- a/common/queryrunner.cpp
+++ b/common/queryrunner.cpp
@@ -51,7 +51,7 @@ public:
51 virtual ~QueryWorker(); 51 virtual ~QueryWorker();
52 52
53 ReplayResult executeIncrementalQuery(const Sink::Query &query, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, DataStoreQuery::State::Ptr state); 53 ReplayResult executeIncrementalQuery(const Sink::Query &query, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, DataStoreQuery::State::Ptr state);
54 ReplayResult executeInitialQuery(const Sink::Query &query, const typename DomainType::Ptr &parent, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, int batchsize, DataStoreQuery::State::Ptr state); 54 ReplayResult executeInitialQuery(const Sink::Query &query, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, int batchsize, DataStoreQuery::State::Ptr state);
55 55
56private: 56private:
57 void resultProviderCallback(const Sink::Query &query, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, const ResultSet::Result &result); 57 void resultProviderCallback(const Sink::Query &query, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, const ResultSet::Result &result);
@@ -70,34 +70,33 @@ QueryRunner<DomainType>::QueryRunner(const Sink::Query &query, const Sink::Resou
70 SinkWarningCtx(mLogCtx) << "A limited query without sorting is typically a bad idea, because there is no telling what you're going to get."; 70 SinkWarningCtx(mLogCtx) << "A limited query without sorting is typically a bad idea, because there is no telling what you're going to get.";
71 } 71 }
72 auto guardPtr = QPointer<QObject>(&guard); 72 auto guardPtr = QPointer<QObject>(&guard);
73 auto fetcher = [=](const typename DomainType::Ptr &parent) { 73 auto fetcher = [=]() {
74 const QByteArray parentId = parent ? parent->identifier() : QByteArray();
75 SinkTraceCtx(mLogCtx) << "Running fetcher. Batchsize: " << mBatchSize; 74 SinkTraceCtx(mLogCtx) << "Running fetcher. Batchsize: " << mBatchSize;
76 auto resultProvider = mResultProvider; 75 auto resultProvider = mResultProvider;
77 auto resultTransformation = mResultTransformation; 76 auto resultTransformation = mResultTransformation;
78 auto batchSize = mBatchSize; 77 auto batchSize = mBatchSize;
79 auto resourceContext = mResourceContext; 78 auto resourceContext = mResourceContext;
80 auto logCtx = mLogCtx; 79 auto logCtx = mLogCtx;
81 auto state = mQueryState.value(parentId); 80 auto state = mQueryState;
82 const bool runAsync = !query.synchronousQuery(); 81 const bool runAsync = !query.synchronousQuery();
83 //The lambda will be executed in a separate thread, so copy all arguments 82 //The lambda will be executed in a separate thread, so copy all arguments
84 async::run<ReplayResult>([=]() { 83 async::run<ReplayResult>([=]() {
85 QueryWorker<DomainType> worker(query, resourceContext, bufferType, resultTransformation, logCtx); 84 QueryWorker<DomainType> worker(query, resourceContext, bufferType, resultTransformation, logCtx);
86 return worker.executeInitialQuery(query, parent, *resultProvider, batchSize, state); 85 return worker.executeInitialQuery(query, *resultProvider, batchSize, state);
87 }, runAsync) 86 }, runAsync)
88 .then([this, parentId, query, parent, resultProvider, guardPtr](const ReplayResult &result) { 87 .then([this, query, resultProvider, guardPtr](const ReplayResult &result) {
89 if (!guardPtr) { 88 if (!guardPtr) {
90 //Not an error, the query can vanish at any time. 89 //Not an error, the query can vanish at any time.
91 return; 90 return;
92 } 91 }
93 mInitialQueryComplete = true; 92 mInitialQueryComplete = true;
94 mQueryState[parentId] = result.queryState; 93 mQueryState = result.queryState;
95 // Only send the revision replayed information if we're connected to the resource, there's no need to start the resource otherwise. 94 // Only send the revision replayed information if we're connected to the resource, there's no need to start the resource otherwise.
96 if (query.liveQuery()) { 95 if (query.liveQuery()) {
97 mResourceAccess->sendRevisionReplayedCommand(result.newRevision); 96 mResourceAccess->sendRevisionReplayedCommand(result.newRevision);
98 } 97 }
99 resultProvider->setRevision(result.newRevision); 98 resultProvider->setRevision(result.newRevision);
100 resultProvider->initialResultSetComplete(parent, result.replayedAll); 99 resultProvider->initialResultSetComplete(result.replayedAll);
101 }) 100 })
102 .exec(); 101 .exec();
103 }; 102 };
@@ -110,14 +109,13 @@ QueryRunner<DomainType>::QueryRunner(const Sink::Query &query, const Sink::Resou
110 Q_ASSERT(!query.synchronousQuery()); 109 Q_ASSERT(!query.synchronousQuery());
111 // Incremental updates are always loaded directly, leaving it up to the result to discard the changes if they are not interesting 110 // Incremental updates are always loaded directly, leaving it up to the result to discard the changes if they are not interesting
112 setQuery([=]() -> KAsync::Job<void> { 111 setQuery([=]() -> KAsync::Job<void> {
113 const QByteArray parentId;
114 auto resultProvider = mResultProvider; 112 auto resultProvider = mResultProvider;
115 auto resourceContext = mResourceContext; 113 auto resourceContext = mResourceContext;
116 auto logCtx = mLogCtx; 114 auto logCtx = mLogCtx;
117 auto state = mQueryState.value(parentId); 115 auto state = mQueryState;
118 if (!mInitialQueryComplete) { 116 if (!mInitialQueryComplete) {
119 SinkWarningCtx(mLogCtx) << "Can't start the incremental query before the initial query is complete"; 117 SinkWarningCtx(mLogCtx) << "Can't start the incremental query before the initial query is complete";
120 fetcher({}); 118 fetcher();
121 return KAsync::null(); 119 return KAsync::null();
122 } 120 }
123 if (mQueryInProgress) { 121 if (mQueryInProgress) {
@@ -240,7 +238,7 @@ ReplayResult QueryWorker<DomainType>::executeIncrementalQuery(const Sink::Query
240 238
241template <class DomainType> 239template <class DomainType>
242ReplayResult QueryWorker<DomainType>::executeInitialQuery( 240ReplayResult QueryWorker<DomainType>::executeInitialQuery(
243 const Sink::Query &query, const typename DomainType::Ptr &parent, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, int batchsize, DataStoreQuery::State::Ptr state) 241 const Sink::Query &query, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, int batchsize, DataStoreQuery::State::Ptr state)
244{ 242{
245 QTime time; 243 QTime time;
246 time.start(); 244 time.start();
diff --git a/common/queryrunner.h b/common/queryrunner.h
index 11a302f..a567b3c 100644
--- a/common/queryrunner.h
+++ b/common/queryrunner.h
@@ -96,7 +96,7 @@ private:
96 QSharedPointer<Sink::ResourceAccessInterface> mResourceAccess; 96 QSharedPointer<Sink::ResourceAccessInterface> mResourceAccess;
97 QSharedPointer<Sink::ResultProvider<typename DomainType::Ptr>> mResultProvider; 97 QSharedPointer<Sink::ResultProvider<typename DomainType::Ptr>> mResultProvider;
98 ResultTransformation mResultTransformation; 98 ResultTransformation mResultTransformation;
99 QHash<QByteArray, DataStoreQuery::State::Ptr> mQueryState; 99 DataStoreQuery::State::Ptr mQueryState;
100 int mBatchSize; 100 int mBatchSize;
101 QObject guard; 101 QObject guard;
102 Sink::Log::Context mLogCtx; 102 Sink::Log::Context mLogCtx;
diff --git a/common/resourcefacade.cpp b/common/resourcefacade.cpp
index 0687bbc..3dba3e5 100644
--- a/common/resourcefacade.cpp
+++ b/common/resourcefacade.cpp
@@ -110,7 +110,7 @@ LocalStorageQueryRunner<DomainType>::LocalStorageQueryRunner(const Query &query,
110 }; 110 };
111 111
112 QObject *guard = new QObject; 112 QObject *guard = new QObject;
113 mResultProvider->setFetcher([this, query, guard, &configNotifier, matchesTypeAndIds](const QSharedPointer<DomainType> &) { 113 mResultProvider->setFetcher([this, query, guard, &configNotifier, matchesTypeAndIds]() {
114 const auto entries = mConfigStore.getEntries(); 114 const auto entries = mConfigStore.getEntries();
115 for (const auto &res : entries.keys()) { 115 for (const auto &res : entries.keys()) {
116 const auto type = entries.value(res); 116 const auto type = entries.value(res);
@@ -127,7 +127,7 @@ LocalStorageQueryRunner<DomainType>::LocalStorageQueryRunner(const Query &query,
127 mResultProvider->add(entity); 127 mResultProvider->add(entity);
128 } 128 }
129 // TODO initialResultSetComplete should be implicit 129 // TODO initialResultSetComplete should be implicit
130 mResultProvider->initialResultSetComplete(typename DomainType::Ptr(), true); 130 mResultProvider->initialResultSetComplete(true);
131 mResultProvider->complete(); 131 mResultProvider->complete();
132 }); 132 });
133 if (query.liveQuery()) { 133 if (query.liveQuery()) {
@@ -390,11 +390,7 @@ QPair<KAsync::Job<void>, typename Sink::ResultEmitter<typename ApplicationDomain
390 auto resourceAccess = Sink::ResourceAccessFactory::instance().getAccess(resource->identifier(), ResourceConfig::getResourceType(resource->identifier())); 390 auto resourceAccess = Sink::ResourceAccessFactory::instance().getAccess(resource->identifier(), ResourceConfig::getResourceType(resource->identifier()));
391 monitorResource(accountIdentifier, *resource, resourceAccess); 391 monitorResource(accountIdentifier, *resource, resourceAccess);
392 }); 392 });
393 emitter->onModified([](const ApplicationDomain::SinkResource::Ptr &) {}); 393 emitter->fetch();
394 emitter->onRemoved([](const ApplicationDomain::SinkResource::Ptr &) {});
395 emitter->onInitialResultSetComplete([](const ApplicationDomain::SinkResource::Ptr &, bool) {});
396 emitter->onComplete([]() {});
397 emitter->fetch({});
398 runner->mResourceEmitter[accountIdentifier] = emitter; 394 runner->mResourceEmitter[accountIdentifier] = emitter;
399 } 395 }
400 396
diff --git a/common/resultprovider.h b/common/resultprovider.h
index d6feaf9..890e109 100644
--- a/common/resultprovider.h
+++ b/common/resultprovider.h
@@ -48,10 +48,10 @@ public:
48 virtual void add(const T &value) = 0; 48 virtual void add(const T &value) = 0;
49 virtual void modify(const T &value) = 0; 49 virtual void modify(const T &value) = 0;
50 virtual void remove(const T &value) = 0; 50 virtual void remove(const T &value) = 0;
51 virtual void initialResultSetComplete(const T &parent, bool) = 0; 51 virtual void initialResultSetComplete(bool) = 0;
52 virtual void complete() = 0; 52 virtual void complete() = 0;
53 virtual void clear() = 0; 53 virtual void clear() = 0;
54 virtual void setFetcher(const std::function<void(const T &parent)> &fetcher) = 0; 54 virtual void setFetcher(const std::function<void()> &fetcher) = 0;
55 55
56 void setRevision(qint64 revision) 56 void setRevision(qint64 revision)
57 { 57 {
@@ -102,10 +102,10 @@ public:
102 } 102 }
103 } 103 }
104 104
105 void initialResultSetComplete(const T &parent, bool replayedAll) 105 void initialResultSetComplete(bool replayedAll)
106 { 106 {
107 if (auto strongRef = mResultEmitter.toStrongRef()) { 107 if (auto strongRef = mResultEmitter.toStrongRef()) {
108 strongRef->initialResultSetComplete(parent, replayedAll); 108 strongRef->initialResultSetComplete(replayedAll);
109 } 109 }
110 } 110 }
111 111
@@ -134,9 +134,9 @@ public:
134 delete emitter; 134 delete emitter;
135 }); 135 });
136 mResultEmitter = sharedPtr; 136 mResultEmitter = sharedPtr;
137 sharedPtr->setFetcher([this](const T &parent) { 137 sharedPtr->setFetcher([this]() {
138 Q_ASSERT(mFetcher); 138 Q_ASSERT(mFetcher);
139 mFetcher(parent); 139 mFetcher();
140 }); 140 });
141 return sharedPtr; 141 return sharedPtr;
142 } 142 }
@@ -155,7 +155,7 @@ public:
155 return mResultEmitter.toStrongRef().isNull(); 155 return mResultEmitter.toStrongRef().isNull();
156 } 156 }
157 157
158 void setFetcher(const std::function<void(const T &parent)> &fetcher) 158 void setFetcher(const std::function<void()> &fetcher)
159 { 159 {
160 mFetcher = fetcher; 160 mFetcher = fetcher;
161 } 161 }
@@ -173,7 +173,7 @@ private:
173 173
174 QWeakPointer<ResultEmitter<T>> mResultEmitter; 174 QWeakPointer<ResultEmitter<T>> mResultEmitter;
175 std::function<void()> mOnDoneCallback; 175 std::function<void()> mOnDoneCallback;
176 std::function<void(const T &parent)> mFetcher; 176 std::function<void()> mFetcher;
177}; 177};
178 178
179/* 179/*
@@ -222,7 +222,7 @@ public:
222 removeHandler = handler; 222 removeHandler = handler;
223 } 223 }
224 224
225 void onInitialResultSetComplete(const std::function<void(const DomainType &, bool)> &handler) 225 void onInitialResultSetComplete(const std::function<void(bool)> &handler)
226 { 226 {
227 initialResultSetCompleteHandler = handler; 227 initialResultSetCompleteHandler = handler;
228 } 228 }
@@ -246,7 +246,9 @@ public:
246 { 246 {
247 QMutexLocker locker{&mMutex}; 247 QMutexLocker locker{&mMutex};
248 if (guardOk()) { 248 if (guardOk()) {
249 addHandler(value); 249 if (addHandler) {
250 addHandler(value);
251 }
250 } 252 }
251 } 253 }
252 254
@@ -254,7 +256,9 @@ public:
254 { 256 {
255 QMutexLocker locker{&mMutex}; 257 QMutexLocker locker{&mMutex};
256 if (guardOk()) { 258 if (guardOk()) {
257 modifyHandler(value); 259 if (modifyHandler) {
260 modifyHandler(value);
261 }
258 } 262 }
259 } 263 }
260 264
@@ -262,16 +266,20 @@ public:
262 { 266 {
263 QMutexLocker locker{&mMutex}; 267 QMutexLocker locker{&mMutex};
264 if (guardOk()) { 268 if (guardOk()) {
265 removeHandler(value); 269 if (removeHandler) {
270 removeHandler(value);
271 }
266 } 272 }
267 } 273 }
268 274
269 void initialResultSetComplete(const DomainType &parent, bool replayedAll) 275 void initialResultSetComplete(bool replayedAll)
270 { 276 {
271 //This callback is only ever called from the main thread, so we don't do any locking 277 //This callback is only ever called from the main thread, so we don't do any locking
272 if (initialResultSetCompleteHandler && guardOk()) { 278 if (initialResultSetCompleteHandler && guardOk()) {
273 //This can directly lead to our destruction and thus waitForMethodExecutionEnd 279 if (initialResultSetCompleteHandler) {
274 initialResultSetCompleteHandler(parent, replayedAll); 280 //This can directly lead to our destruction and thus waitForMethodExecutionEnd
281 initialResultSetCompleteHandler(replayedAll);
282 }
275 } 283 }
276 } 284 }
277 285
@@ -279,7 +287,9 @@ public:
279 { 287 {
280 QMutexLocker locker{&mMutex}; 288 QMutexLocker locker{&mMutex};
281 if (completeHandler && guardOk()) { 289 if (completeHandler && guardOk()) {
282 completeHandler(); 290 if (completeHandler) {
291 completeHandler();
292 }
283 } 293 }
284 } 294 }
285 295
@@ -287,19 +297,21 @@ public:
287 { 297 {
288 QMutexLocker locker{&mMutex}; 298 QMutexLocker locker{&mMutex};
289 if (clearHandler && guardOk()) { 299 if (clearHandler && guardOk()) {
290 clearHandler(); 300 if (clearHandler) {
301 clearHandler();
302 }
291 } 303 }
292 } 304 }
293 305
294 void setFetcher(const std::function<void(const DomainType &parent)> &fetcher) 306 void setFetcher(const std::function<void()> &fetcher)
295 { 307 {
296 mFetcher = fetcher; 308 mFetcher = fetcher;
297 } 309 }
298 310
299 virtual void fetch(const DomainType &parent) 311 virtual void fetch()
300 { 312 {
301 if (mFetcher) { 313 if (mFetcher) {
302 mFetcher(parent); 314 mFetcher();
303 } 315 }
304 } 316 }
305 317
@@ -309,11 +321,11 @@ private:
309 std::function<void(const DomainType &)> addHandler; 321 std::function<void(const DomainType &)> addHandler;
310 std::function<void(const DomainType &)> modifyHandler; 322 std::function<void(const DomainType &)> modifyHandler;
311 std::function<void(const DomainType &)> removeHandler; 323 std::function<void(const DomainType &)> removeHandler;
312 std::function<void(const DomainType &, bool)> initialResultSetCompleteHandler; 324 std::function<void(bool)> initialResultSetCompleteHandler;
313 std::function<void(void)> completeHandler; 325 std::function<void(void)> completeHandler;
314 std::function<void(void)> clearHandler; 326 std::function<void(void)> clearHandler;
315 327
316 std::function<void(const DomainType &parent)> mFetcher; 328 std::function<void()> mFetcher;
317 /* 329 /*
318 * This mutex is here to protect the emitter from getting destroyed while the producer-thread (ResultProvider) is calling into it, 330 * This mutex is here to protect the emitter from getting destroyed while the producer-thread (ResultProvider) is calling into it,
319 * and vice-verca, to protect the producer thread from calling into a destroyed emitter. 331 * and vice-verca, to protect the producer thread from calling into a destroyed emitter.
@@ -350,53 +362,50 @@ public:
350 emitter->onModified([this](const DomainType &value) { this->modify(value); }); 362 emitter->onModified([this](const DomainType &value) { this->modify(value); });
351 emitter->onRemoved([this](const DomainType &value) { this->remove(value); }); 363 emitter->onRemoved([this](const DomainType &value) { this->remove(value); });
352 auto ptr = emitter.data(); 364 auto ptr = emitter.data();
353 emitter->onInitialResultSetComplete([this, ptr](const DomainType &parent, bool replayedAll) { 365 emitter->onInitialResultSetComplete([this, ptr](bool replayedAll) {
354 auto hashValue = qHash(parent);
355 if (replayedAll) { 366 if (replayedAll) {
356 mAllResultsReplayed.remove(hashValue, ptr); 367 mAllResultsReplayed.remove(ptr);
357 } 368 }
358 mInitialResultSetInProgress.remove(hashValue, ptr); 369 mInitialResultSetInProgress.remove(ptr);
359 callInitialResultCompleteIfDone(parent); 370 callInitialResultCompleteIfDone();
360 }); 371 });
361 emitter->onComplete([this]() { this->complete(); }); 372 emitter->onComplete([this]() { this->complete(); });
362 emitter->onClear([this]() { this->clear(); }); 373 emitter->onClear([this]() { this->clear(); });
363 mEmitter << emitter; 374 mEmitter << emitter;
364 } 375 }
365 376
366 void callInitialResultCompleteIfDone(const DomainType &parent) 377 void callInitialResultCompleteIfDone()
367 { 378 {
368 auto hashValue = qHash(parent);
369 // Normally a parent is only in a single resource, except the toplevel (invalid) parent 379 // Normally a parent is only in a single resource, except the toplevel (invalid) parent
370 if (!mInitialResultSetInProgress.contains(hashValue) && mAllResultsFetched && !mResultEmitted) { 380 if (mInitialResultSetInProgress.isEmpty() && mAllResultsFetched && !mResultEmitted) {
371 bool allResourcesReplayedAll = mAllResultsReplayed.isEmpty();
372 mResultEmitted = true; 381 mResultEmitted = true;
373 this->initialResultSetComplete(parent, allResourcesReplayedAll); 382 this->initialResultSetComplete(mAllResultsReplayed.isEmpty());
374 } 383 }
375 } 384 }
376 385
377 void fetch(const DomainType &parent) Q_DECL_OVERRIDE 386 void fetch() Q_DECL_OVERRIDE
378 { 387 {
379 if (mEmitter.isEmpty()) { 388 if (mEmitter.isEmpty()) {
380 this->initialResultSetComplete(parent, true); 389 this->initialResultSetComplete(true);
381 } else { 390 } else {
382 mResultEmitted = false; 391 mResultEmitted = false;
383 mAllResultsFetched = false; 392 mAllResultsFetched = false;
393 mInitialResultSetInProgress.clear();
384 mAllResultsReplayed.clear(); 394 mAllResultsReplayed.clear();
385 const auto hashValue = qHash(parent);
386 for (const auto &emitter : mEmitter) { 395 for (const auto &emitter : mEmitter) {
387 mInitialResultSetInProgress.insert(hashValue, emitter.data()); 396 mInitialResultSetInProgress.insert(emitter.data());
388 mAllResultsReplayed.insert(hashValue, emitter.data()); 397 mAllResultsReplayed.insert(emitter.data());
389 emitter->fetch(parent); 398 emitter->fetch();
390 } 399 }
391 mAllResultsFetched = true; 400 mAllResultsFetched = true;
392 callInitialResultCompleteIfDone(parent); 401 callInitialResultCompleteIfDone();
393 } 402 }
394 } 403 }
395 404
396private: 405private:
397 QList<typename ResultEmitter<DomainType>::Ptr> mEmitter; 406 QList<typename ResultEmitter<DomainType>::Ptr> mEmitter;
398 QMultiMap<qint64, ResultEmitter<DomainType> *> mInitialResultSetInProgress; 407 QSet<ResultEmitter<DomainType>*> mInitialResultSetInProgress;
399 QMultiMap<qint64, ResultEmitter<DomainType> *> mAllResultsReplayed; 408 QSet<ResultEmitter<DomainType>*> mAllResultsReplayed;
400 bool mAllResultsFetched; 409 bool mAllResultsFetched;
401 bool mResultEmitted; 410 bool mResultEmitted;
402}; 411};
diff --git a/common/store.cpp b/common/store.cpp
index 1701a43..b16fa4e 100644
--- a/common/store.cpp
+++ b/common/store.cpp
@@ -136,12 +136,6 @@ QPair<typename AggregatingResultEmitter<typename DomainType::Ptr>::Ptr, typenam
136 Q_ASSERT(!resourceType.isEmpty()); 136 Q_ASSERT(!resourceType.isEmpty());
137 queryResource<DomainType>(resourceType, resource->identifier(), query, aggregatingEmitter, ctx).exec(); 137 queryResource<DomainType>(resourceType, resource->identifier(), query, aggregatingEmitter, ctx).exec();
138 }); 138 });
139 emitter->onModified([](const ApplicationDomain::SinkResource::Ptr &) {
140 });
141 emitter->onRemoved([](const ApplicationDomain::SinkResource::Ptr &) {
142 });
143 emitter->onInitialResultSetComplete([](const ApplicationDomain::SinkResource::Ptr &, bool) {
144 });
145 emitter->onComplete([query, aggregatingEmitter, resourceCtx]() { 139 emitter->onComplete([query, aggregatingEmitter, resourceCtx]() {
146 SinkTraceCtx(resourceCtx) << "Resource query complete"; 140 SinkTraceCtx(resourceCtx) << "Resource query complete";
147 }); 141 });
@@ -178,7 +172,7 @@ QSharedPointer<QAbstractItemModel> Store::loadModel(const Query &query)
178 //Keep the emitter alive 172 //Keep the emitter alive
179 if (auto resourceEmitter = result.second) { 173 if (auto resourceEmitter = result.second) {
180 model->setProperty("resourceEmitter", QVariant::fromValue(resourceEmitter)); //TODO only neceesary for live queries 174 model->setProperty("resourceEmitter", QVariant::fromValue(resourceEmitter)); //TODO only neceesary for live queries
181 resourceEmitter->fetch(ApplicationDomain::SinkResource::Ptr()); 175 resourceEmitter->fetch();
182 } 176 }
183 177
184 178
@@ -443,10 +437,10 @@ QList<DomainType> Store::read(const Sink::Query &query_)
443 }); 437 });
444 438
445 if (auto resourceEmitter = result.second) { 439 if (auto resourceEmitter = result.second) {
446 resourceEmitter->fetch(ApplicationDomain::SinkResource::Ptr()); 440 resourceEmitter->fetch();
447 } 441 }
448 442
449 aggregatingEmitter->fetch(typename DomainType::Ptr()); 443 aggregatingEmitter->fetch();
450 return list; 444 return list;
451} 445}
452 446
diff --git a/common/test.cpp b/common/test.cpp
index 237d3bb..52d79ca 100644
--- a/common/test.cpp
+++ b/common/test.cpp
@@ -150,22 +150,13 @@ public:
150 // We have to do it this way, otherwise we're not setting the fetcher right 150 // We have to do it this way, otherwise we're not setting the fetcher right
151 auto emitter = resultProvider->emitter(); 151 auto emitter = resultProvider->emitter();
152 152
153 resultProvider->setFetcher([query, resultProvider, this](const typename T::Ptr &parent) { 153 resultProvider->setFetcher([query, resultProvider, this]() {
154 if (parent) { 154 SinkTrace() << "Running the fetcher.";
155 SinkTrace() << "Running the fetcher " << parent->identifier();
156 } else {
157 SinkTrace() << "Running the fetcher.";
158 }
159 SinkTrace() << "-------------------------."; 155 SinkTrace() << "-------------------------.";
160 for (const auto &res : mTestAccount->entities<T>()) { 156 for (const auto &res : mTestAccount->entities<T>()) {
161 qDebug() << "Parent filter " << query.getFilter("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray(); 157 resultProvider->add(res.template staticCast<T>());
162 auto parentProperty = res->getProperty("parent").toByteArray();
163 if ((!parent && parentProperty.isEmpty()) || (parent && parentProperty == parent->identifier()) || query.parentProperty().isEmpty()) {
164 qDebug() << "Found a match" << res->identifier();
165 resultProvider->add(res.template staticCast<T>());
166 }
167 } 158 }
168 resultProvider->initialResultSetComplete(parent, true); 159 resultProvider->initialResultSetComplete(true);
169 }); 160 });
170 auto job = KAsync::start([query, resultProvider]() {}); 161 auto job = KAsync::start([query, resultProvider]() {});
171 return qMakePair(job, emitter); 162 return qMakePair(job, emitter);
diff --git a/tests/clientapitest.cpp b/tests/clientapitest.cpp
index 7e348c2..94818e1 100644
--- a/tests/clientapitest.cpp
+++ b/tests/clientapitest.cpp
@@ -13,7 +13,6 @@
13 13
14template <typename T> 14template <typename T>
15struct Result { 15struct Result {
16 QSharedPointer<T> parent;
17 bool fetchedAll; 16 bool fetchedAll;
18}; 17};
19 18
@@ -73,37 +72,28 @@ public:
73 // We have to do it this way, otherwise we're not setting the fetcher right 72 // We have to do it this way, otherwise we're not setting the fetcher right
74 auto emitter = resultProvider->emitter(); 73 auto emitter = resultProvider->emitter();
75 74
76 resultProvider->setFetcher([query, resultProvider, this, ctx](const typename T::Ptr &parent) { 75 resultProvider->setFetcher([query, resultProvider, this, ctx]() {
77 async::run<Result<T>>([=] { 76 async::run<Result<T>>([=] {
78 if (parent) { 77 SinkTraceCtx(ctx) << "Running the fetcher.";
79 SinkTraceCtx(ctx) << "Running the fetcher " << parent->identifier();
80 } else {
81 SinkTraceCtx(ctx) << "Running the fetcher.";
82 }
83 SinkTraceCtx(ctx) << "-------------------------."; 78 SinkTraceCtx(ctx) << "-------------------------.";
84 int count = 0; 79 int count = 0;
85 for (int i = offset; i < results.size(); i++) { 80 for (int i = offset; i < results.size(); i++) {
86 const auto res = results.at(i); 81 const auto res = results.at(i);
87 count++; 82 count++;
88 // SinkTraceCtx(ctx) << "Parent filter " << query.getFilter("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray(); 83 resultProvider->add(res);
89 auto parentProperty = res->getProperty("parent").toByteArray();
90 if ((!parent && parentProperty.isEmpty()) || (parent && parentProperty == parent->identifier()) || query.parentProperty().isEmpty()) {
91 // SinkTraceCtx(ctx) << "Found a hit" << res->identifier();
92 resultProvider->add(res);
93 }
94 if (query.limit()) { 84 if (query.limit()) {
95 if (count >= query.limit()) { 85 if (count >= query.limit()) {
96 SinkTraceCtx(ctx) << "Aborting early after " << count << "results."; 86 SinkTraceCtx(ctx) << "Aborting early after " << count << "results.";
97 offset = i + 1; 87 offset = i + 1;
98 bool fetchedAll = (i + 1 >= results.size()); 88 bool fetchedAll = (i + 1 >= results.size());
99 return Result<T>{parent, fetchedAll}; 89 return Result<T>{fetchedAll};
100 } 90 }
101 } 91 }
102 } 92 }
103 return Result<T>{parent, true}; 93 return Result<T>{true};
104 }, runAsync) 94 }, runAsync)
105 .then([=] (const Result<T> &r) { 95 .then([=] (const Result<T> &r) {
106 resultProvider->initialResultSetComplete(r.parent, r.fetchedAll); 96 resultProvider->initialResultSetComplete(r.fetchedAll);
107 }) 97 })
108 .exec(); 98 .exec();
109 }); 99 });
diff --git a/tests/databasepopulationandfacadequerybenchmark.cpp b/tests/databasepopulationandfacadequerybenchmark.cpp
index 4f81d1d..7f478cf 100644
--- a/tests/databasepopulationandfacadequerybenchmark.cpp
+++ b/tests/databasepopulationandfacadequerybenchmark.cpp
@@ -113,8 +113,8 @@ class DatabasePopulationAndFacadeQueryBenchmark : public QObject
113 QList<Sink::ApplicationDomain::Event::Ptr> list; 113 QList<Sink::ApplicationDomain::Event::Ptr> list;
114 emitter->onAdded([&list](const Sink::ApplicationDomain::Event::Ptr &event) { list << event; }); 114 emitter->onAdded([&list](const Sink::ApplicationDomain::Event::Ptr &event) { list << event; });
115 bool done = false; 115 bool done = false;
116 emitter->onInitialResultSetComplete([&done](const Sink::ApplicationDomain::Event::Ptr &event, bool) { done = true; }); 116 emitter->onInitialResultSetComplete([&done](bool) { done = true; });
117 emitter->fetch(Sink::ApplicationDomain::Event::Ptr()); 117 emitter->fetch();
118 QUICK_TRY_VERIFY(done); 118 QUICK_TRY_VERIFY(done);
119 QCOMPARE(list.size(), count); 119 QCOMPARE(list.size(), count);
120 120
diff --git a/tests/mailquerybenchmark.cpp b/tests/mailquerybenchmark.cpp
index 1d295b5..3eccfc3 100644
--- a/tests/mailquerybenchmark.cpp
+++ b/tests/mailquerybenchmark.cpp
@@ -96,8 +96,8 @@ class MailQueryBenchmark : public QObject
96 int i = 0; 96 int i = 0;
97 emitter->onAdded([&](const Mail::Ptr &) { i++; }); 97 emitter->onAdded([&](const Mail::Ptr &) { i++; });
98 bool done = false; 98 bool done = false;
99 emitter->onInitialResultSetComplete([&done](const Mail::Ptr &mail, bool) { done = true; }); 99 emitter->onInitialResultSetComplete([&done](bool) { done = true; });
100 emitter->fetch(Mail::Ptr()); 100 emitter->fetch();
101 QUICK_TRY_VERIFY(done); 101 QUICK_TRY_VERIFY(done);
102 return i; 102 return i;
103 } 103 }
@@ -273,8 +273,8 @@ private slots:
273 emitter->onRemoved([&](const Mail::Ptr &mail) { removed << mail; /*qWarning() << "Removed";*/ }); 273 emitter->onRemoved([&](const Mail::Ptr &mail) { removed << mail; /*qWarning() << "Removed";*/ });
274 emitter->onModified([&](const Mail::Ptr &mail) { modified << mail; /*qWarning() << "Modified";*/ }); 274 emitter->onModified([&](const Mail::Ptr &mail) { modified << mail; /*qWarning() << "Modified";*/ });
275 bool done = false; 275 bool done = false;
276 emitter->onInitialResultSetComplete([&done](const Mail::Ptr &mail, bool) { done = true; }); 276 emitter->onInitialResultSetComplete([&done](bool) { done = true; });
277 emitter->fetch(Mail::Ptr()); 277 emitter->fetch();
278 QUICK_TRY_VERIFY(done); 278 QUICK_TRY_VERIFY(done);
279 QCOMPARE(added.size(), expectedSize); 279 QCOMPARE(added.size(), expectedSize);
280 280
diff --git a/tests/querytest.cpp b/tests/querytest.cpp
index 6279fa9..5af8a99 100644
--- a/tests/querytest.cpp
+++ b/tests/querytest.cpp
@@ -245,8 +245,6 @@ private slots:
245 auto model = Sink::Store::loadModel<Folder>(query); 245 auto model = Sink::Store::loadModel<Folder>(query);
246 QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); 246 QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool());
247 QCOMPARE(model->rowCount(), 1); 247 QCOMPARE(model->rowCount(), 1);
248 model->fetchMore(model->index(0, 0));
249 QTRY_VERIFY(model->data(model->index(0, 0), Sink::Store::ChildrenFetchedRole).toBool());
250 QCOMPARE(model->rowCount(model->index(0, 0)), 1); 248 QCOMPARE(model->rowCount(model->index(0, 0)), 1);
251 } 249 }
252 250
@@ -266,7 +264,6 @@ private slots:
266 auto model = Sink::Store::loadModel<Folder>(query); 264 auto model = Sink::Store::loadModel<Folder>(query);
267 QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); 265 QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool());
268 QCOMPARE(model->rowCount(), 1); 266 QCOMPARE(model->rowCount(), 1);
269 model->fetchMore(model->index(0, 0));
270 267
271 auto subfolder = ApplicationDomainType::createEntity<Folder>("sink.dummy.instance1"); 268 auto subfolder = ApplicationDomainType::createEntity<Folder>("sink.dummy.instance1");
272 subfolder.setParent(folder.identifier()); 269 subfolder.setParent(folder.identifier());
@@ -274,9 +271,7 @@ private slots:
274 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue("sink.dummy.instance1")); 271 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue("sink.dummy.instance1"));
275 272
276 //Ensure the folder appears 273 //Ensure the folder appears
277 model->fetchMore(model->index(0, 0)); 274 QTRY_COMPARE(model->rowCount(model->index(0, 0)), 1);
278 QTRY_VERIFY(model->data(model->index(0, 0), Sink::Store::ChildrenFetchedRole).toBool());
279 QCOMPARE(model->rowCount(model->index(0, 0)), 1);
280 275
281 //...and dissapears again after removal 276 //...and dissapears again after removal
282 VERIFYEXEC(Sink::Store::remove<Folder>(subfolder)); 277 VERIFYEXEC(Sink::Store::remove<Folder>(subfolder));