From 871a048580d5a464fb697713a5e0e2c52dee5208 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 27 Jan 2017 16:56:17 +0100 Subject: Ensure blooming queries filter as they should After the initial bloom, it should turn into a regular filter. --- common/datastorequery.cpp | 46 +++++++++++------ common/domain/applicationdomaintype.cpp | 1 + tests/querytest.cpp | 92 +++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 17 deletions(-) diff --git a/common/datastorequery.cpp b/common/datastorequery.cpp index d90d546..087f405 100644 --- a/common/datastorequery.cpp +++ b/common/datastorequery.cpp @@ -101,7 +101,7 @@ public: virtual ~Filter(){} - bool next(const std::function &callback) Q_DECL_OVERRIDE { + virtual bool next(const std::function &callback) Q_DECL_OVERRIDE { bool foundValue = false; while(!foundValue && mSource->next([this, callback, &foundValue](const ResultSet::Result &result) { SinkTrace() << "Filter: " << result.entity.identifier() << result.operation; @@ -273,14 +273,14 @@ public: } }; -class Bloom : public FilterBase { +class Bloom : public Filter { public: typedef QSharedPointer Ptr; QByteArray mBloomProperty; Bloom(const QByteArray &bloomProperty, FilterBase::Ptr source, DataStoreQuery *store) - : FilterBase(source, store), + : Filter(source, store), mBloomProperty(bloomProperty) { @@ -289,21 +289,33 @@ public: virtual ~Bloom(){} bool next(const std::function &callback) Q_DECL_OVERRIDE { - bool foundValue = false; - while(!foundValue && mSource->next([this, callback, &foundValue](const ResultSet::Result &result) { - auto bloomValue = result.entity.getProperty(mBloomProperty); - auto results = indexLookup(mBloomProperty, bloomValue); - for (const auto &r : results) { - readEntity(r, [&, this](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation operation) { - callback({entity, Sink::Operation_Creation}); - foundValue = true; - }); - } - return false; - })) - {} - return foundValue; + if (!mBloomed) { + //Initially we bloom on the first value that matches. + //From there on we just filter. + bool foundValue = false; + while(!foundValue && mSource->next([this, callback, &foundValue](const ResultSet::Result &result) { + mBloomValue = result.entity.getProperty(mBloomProperty); + auto results = indexLookup(mBloomProperty, mBloomValue); + SinkWarning() << "Bloomed on value " << mBloomValue << " and found " << results.size(); + for (const auto &r : results) { + readEntity(r, [&, this](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation operation) { + callback({entity, Sink::Operation_Creation}); + foundValue = true; + }); + } + return false; + })) + {} + mBloomed = true; + propertyFilter.insert(mBloomProperty, mBloomValue); + return foundValue; + } else { + //Filter on bloom value + return Filter::next(callback); + } } + QVariant mBloomValue; + bool mBloomed = false; }; DataStoreQuery::DataStoreQuery(const Sink::QueryBase &query, const QByteArray &type, EntityStore &store) diff --git a/common/domain/applicationdomaintype.cpp b/common/domain/applicationdomaintype.cpp index 6d16a3c..57d0f2d 100644 --- a/common/domain/applicationdomaintype.cpp +++ b/common/domain/applicationdomaintype.cpp @@ -30,6 +30,7 @@ namespace Sink { namespace ApplicationDomain { constexpr const char *Mail::ThreadId::name; +constexpr const char *Mail::Folder::name; static const int foo = [] { QMetaType::registerEqualsComparator(); diff --git a/tests/querytest.cpp b/tests/querytest.cpp index 92fc1f7..10f5567 100644 --- a/tests/querytest.cpp +++ b/tests/querytest.cpp @@ -11,6 +11,7 @@ #include "modelresult.h" #include "test.h" #include "testutils.h" +#include "applicationdomaintype.h" using namespace Sink; using namespace Sink::ApplicationDomain; @@ -632,6 +633,7 @@ private slots: auto folders = Sink::Store::read(query); QCOMPARE(folders.size(), 1); } + void testLivequeryUnmatchInThread() { // Setup @@ -707,6 +709,96 @@ private slots: auto mail = model->data(model->index(0, 0, QModelIndex{}), Sink::Store::DomainObjectRole).value(); QCOMPARE(mail->getUnread(), true); } + + void testBloom() + { + // Setup + auto folder1 = Folder::createEntity("sink.dummy.instance1"); + VERIFYEXEC(Sink::Store::create(folder1)); + + auto folder2 = Folder::createEntity("sink.dummy.instance1"); + VERIFYEXEC(Sink::Store::create(folder2)); + + auto mail1 = Mail::createEntity("sink.dummy.instance1"); + mail1.setUid("mail1"); + mail1.setFolder(folder1); + VERIFYEXEC(Sink::Store::create(mail1)); + + // Ensure all local data is processed + VERIFYEXEC(Sink::ResourceControl::flushMessageQueue("sink.dummy.instance1")); + + { + auto mail = Mail::createEntity("sink.dummy.instance1"); + mail.setUid("mail2"); + mail.setFolder(folder1); + VERIFYEXEC(Sink::Store::create(mail)); + } + { + auto mail = Mail::createEntity("sink.dummy.instance1"); + mail.setUid("mail3"); + mail.setFolder(folder2); + VERIFYEXEC(Sink::Store::create(mail)); + } + VERIFYEXEC(Sink::ResourceControl::flushMessageQueue("sink.dummy.instance1")); + + Query query; + query.setId("testFilterCreationInThread"); + query.filter(mail1.identifier()); + query.bloom(); + query.request(); + + auto model = Sink::Store::loadModel(query); + QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); + QCOMPARE(model->rowCount(), 2); + } + + void testLivequeryFilterCreationInThread() + { + // Setup + auto folder1 = Folder::createEntity("sink.dummy.instance1"); + VERIFYEXEC(Sink::Store::create(folder1)); + + auto folder2 = Folder::createEntity("sink.dummy.instance1"); + VERIFYEXEC(Sink::Store::create(folder2)); + + auto mail1 = Mail::createEntity("sink.dummy.instance1"); + mail1.setUid("mail1"); + mail1.setFolder(folder1); + VERIFYEXEC(Sink::Store::create(mail1)); + + // Ensure all local data is processed + VERIFYEXEC(Sink::ResourceControl::flushMessageQueue("sink.dummy.instance1")); + + Query query; + query.setId("testFilterCreationInThread"); + query.filter(mail1.identifier()); + query.bloom(); + query.sort(); + query.setFlags(Query::LiveQuery); + query.request(); + query.request(); + + auto model = Sink::Store::loadModel(query); + QTRY_COMPARE(model->rowCount(), 1); + + { + auto mail = Mail::createEntity("sink.dummy.instance1"); + mail.setUid("mail2"); + mail.setFolder(folder1); + VERIFYEXEC(Sink::Store::create(mail)); + } + { + auto mail = Mail::createEntity("sink.dummy.instance1"); + mail.setUid("mail3"); + mail.setFolder(folder2); + VERIFYEXEC(Sink::Store::create(mail)); + } + VERIFYEXEC(Sink::ResourceControl::flushMessageQueue("sink.dummy.instance1")); + + QTRY_COMPARE(model->rowCount(), 2); + QTest::qWait(100); + QCOMPARE(model->rowCount(), 2); + } }; QTEST_MAIN(QueryTest) -- cgit v1.2.3