From 71a0167e0216f84588b492c84e92667847fbe5a5 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Tue, 18 Oct 2016 12:44:12 +0200 Subject: Use the ApplicationDomainType in the queries as well. We have to access properties, so we need the mapper anyways, and the ApplicationDomainType type shouldn't be a large overhead anyways. --- common/datastorequery.cpp | 94 +++++++++++++++++++----------------------- common/datastorequery.h | 18 +++----- common/domain/event.cpp | 10 ----- common/domain/event.h | 2 - common/domain/folder.cpp | 9 ---- common/domain/folder.h | 1 - common/domain/mail.cpp | 23 ----------- common/domain/mail.h | 1 - common/queryrunner.cpp | 18 +++----- common/resultset.h | 4 +- common/storage/entitystore.cpp | 9 ++++ common/storage/entitystore.h | 2 + 12 files changed, 66 insertions(+), 125 deletions(-) diff --git a/common/datastorequery.cpp b/common/datastorequery.cpp index 8897c29..f56ac91 100644 --- a/common/datastorequery.cpp +++ b/common/datastorequery.cpp @@ -19,8 +19,6 @@ #include "datastorequery.h" #include "log.h" -#include "entitybuffer.h" -#include "entity_generated.h" #include "applicationdomaintype.h" #include "folder.h" @@ -68,8 +66,8 @@ class Source : public FilterBase { if (mIt == mIds.constEnd()) { return false; } - readEntity(*mIt, [callback](const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) { - callback({uid, entityBuffer, entityBuffer.operation()}); + readEntity(*mIt, [callback](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation operation) { + callback({entity, operation}); }); mIt++; return mIt != mIds.constEnd(); @@ -110,23 +108,23 @@ public: 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.uid << result.operation; + SinkTrace() << "Filter: " << result.entity.identifier() << result.operation; //Always accept removals. They can't match the filter since the data is gone. if (result.operation == Sink::Operation_Removal) { - SinkTrace() << "Removal: " << result.uid << result.operation; + SinkTrace() << "Removal: " << result.entity.identifier() << result.operation; callback(result); foundValue = true; - } else if (matchesFilter(result.uid, result.buffer)) { - SinkTrace() << "Accepted: " << result.uid << result.operation; + } else if (matchesFilter(result.entity)) { + SinkTrace() << "Accepted: " << result.entity.identifier() << result.operation; callback(result); foundValue = true; //TODO if something did not match the filter so far but does now, turn into an add operation. } else { - SinkTrace() << "Rejected: " << result.uid << result.operation; + SinkTrace() << "Rejected: " << result.entity.identifier() << result.operation; //TODO emit a removal if we had the uid in the result set and this is a modification. //We don't know if this results in a removal from the dataset, so we emit a removal notification anyways - callback({result.uid, result.buffer, Sink::Operation_Removal, result.aggregateValues}); + callback({result.entity, Sink::Operation_Removal, result.aggregateValues}); } return false; })) @@ -134,9 +132,9 @@ public: return foundValue; } - bool matchesFilter(const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) { + bool matchesFilter(const ApplicationDomain::ApplicationDomainType &entity) { for (const auto &filterProperty : propertyFilter.keys()) { - const auto property = getProperty(entityBuffer.entity(), filterProperty); + const auto property = entity.getProperty(filterProperty); const auto comparator = propertyFilter.value(filterProperty); if (!comparator.matches(property)) { SinkTrace() << "Filtering entity due to property mismatch on filter: " << filterProperty << property << ":" << comparator.value; @@ -224,7 +222,7 @@ public: bool next(const std::function &callback) Q_DECL_OVERRIDE { bool foundValue = false; while(!foundValue && mSource->next([this, callback, &foundValue](const ResultSet::Result &result) { - auto reductionValue = getProperty(result.buffer.entity(), mReductionProperty); + auto reductionValue = result.entity.getProperty(mReductionProperty); if (!mReducedValues.contains(getByteArray(reductionValue))) { //Only reduce every value once. mReducedValues.insert(getByteArray(reductionValue)); @@ -234,18 +232,18 @@ public: QVariantList list; for (const auto r : results) { - readEntity(r, [&, this](const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) { + readEntity(r, [&, this](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation operation) { for (auto &aggregator : mAggregators) { if (!aggregator.property.isEmpty()) { - aggregator.process(getProperty(entityBuffer.entity(), aggregator.property)); + aggregator.process(entity.getProperty(aggregator.property)); } else { aggregator.process(); } } - auto selectionValue = getProperty(entityBuffer.entity(), mSelectionProperty); + auto selectionValue = entity.getProperty(mSelectionProperty); if (!selectionResultValue.isValid() || compare(selectionValue, selectionResultValue, mSelectionComparator)) { selectionResultValue = selectionValue; - selectionResult = uid; + selectionResult = entity.identifier(); } }); } @@ -255,8 +253,8 @@ public: aggregateValues.insert(aggregator.resultProperty, aggregator.result()); } - readEntity(selectionResult, [&, this](const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) { - callback({uid, entityBuffer, Sink::Operation_Creation, aggregateValues}); + readEntity(selectionResult, [&, this](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation operation) { + callback({entity, Sink::Operation_Creation, aggregateValues}); foundValue = true; }); } @@ -285,11 +283,11 @@ public: 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 = getProperty(result.buffer.entity(), mBloomProperty); + auto bloomValue = result.entity.getProperty(mBloomProperty); auto results = indexLookup(mBloomProperty, bloomValue); for (const auto r : results) { - readEntity(r, [&, this](const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) { - callback({uid, entityBuffer, Sink::Operation_Creation}); + readEntity(r, [&, this](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation operation) { + callback({entity, Sink::Operation_Creation}); foundValue = true; }); } @@ -300,23 +298,15 @@ public: } }; -DataStoreQuery::DataStoreQuery(const Sink::Query &query, const QByteArray &type, EntityStore::Ptr store, std::function getProperty) - : mQuery(query), mType(type), mGetProperty(getProperty), mStore(store) +DataStoreQuery::DataStoreQuery(const Sink::Query &query, const QByteArray &type, EntityStore::Ptr store) + : mQuery(query), mType(type), mStore(store) { setupQuery(); } void DataStoreQuery::readEntity(const QByteArray &key, const BufferCallback &resultCallback) { - mStore->readLatest(mType, key, [=](const QByteArray &key, const Sink::EntityBuffer &buffer) { - resultCallback(DataStore::uidFromKey(key), buffer); - return false; - }); -} - -QVariant DataStoreQuery::getProperty(const Sink::Entity &entity, const QByteArray &property) -{ - return mGetProperty(entity, property); + mStore->readLatest(mType, key, resultCallback); } QVector DataStoreQuery::indexLookup(const QByteArray &property, const QVariant &value) @@ -404,28 +394,28 @@ QVector DataStoreQuery::indexLookup(const QByteArray &property, cons /* } */ /* } */ -template -QSharedPointer prepareQuery(const QByteArray &type, Args && ... args) -{ - if (type == ApplicationDomain::getTypeName()) { - return ApplicationDomain::TypeImplementation::prepareQuery(std::forward(args)...); - } else if (type == ApplicationDomain::getTypeName()) { - return ApplicationDomain::TypeImplementation::prepareQuery(std::forward(args)...); - } else if (type == ApplicationDomain::getTypeName()) { - return ApplicationDomain::TypeImplementation::prepareQuery(std::forward(args)...); - } - Q_ASSERT(false); - return QSharedPointer(); -} +/* template */ +/* QSharedPointer prepareQuery(const QByteArray &type, Args && ... args) */ +/* { */ +/* if (type == ApplicationDomain::getTypeName()) { */ +/* return ApplicationDomain::TypeImplementation::prepareQuery(std::forward(args)...); */ +/* } else if (type == ApplicationDomain::getTypeName()) { */ +/* return ApplicationDomain::TypeImplementation::prepareQuery(std::forward(args)...); */ +/* } else if (type == ApplicationDomain::getTypeName()) { */ +/* return ApplicationDomain::TypeImplementation::prepareQuery(std::forward(args)...); */ +/* } */ +/* Q_ASSERT(false); */ +/* return QSharedPointer(); */ +/* } */ QByteArrayList DataStoreQuery::executeSubquery(const Query &subquery) { Q_ASSERT(!subquery.type.isEmpty()); - auto sub = prepareQuery(subquery.type, subquery, mStore); - auto result = sub->execute(); + auto sub = DataStoreQuery(subquery, subquery.type, mStore); + auto result = sub.execute(); QByteArrayList ids; while (result.next([&ids](const ResultSet::Result &result) { - ids << result.uid; + ids << result.entity.identifier(); })) {} return ids; @@ -518,7 +508,7 @@ ResultSet DataStoreQuery::update(qint64 baseRevision) mSource->add(incrementalResultSet); ResultSet::ValueGenerator generator = [this](const ResultSet::Callback &callback) -> bool { if (mCollector->next([this, callback](const ResultSet::Result &result) { - SinkTrace() << "Got incremental result: " << result.uid << result.operation; + SinkTrace() << "Got incremental result: " << result.entity.identifier() << result.operation; callback(result); })) { @@ -537,8 +527,8 @@ ResultSet DataStoreQuery::execute() ResultSet::ValueGenerator generator = [this](const ResultSet::Callback &callback) -> bool { if (mCollector->next([this, callback](const ResultSet::Result &result) { if (result.operation != Sink::Operation_Removal) { - SinkTrace() << "Got initial result: " << result.uid << result.operation; - callback(ResultSet::Result{result.uid, result.buffer, Sink::Operation_Creation, result.aggregateValues}); + SinkTrace() << "Got initial result: " << result.entity.identifier() << result.operation; + callback(ResultSet::Result{result.entity, Sink::Operation_Creation, result.aggregateValues}); } })) { diff --git a/common/datastorequery.h b/common/datastorequery.h index 77c8ed5..92235fd 100644 --- a/common/datastorequery.h +++ b/common/datastorequery.h @@ -35,21 +35,20 @@ class DataStoreQuery { public: typedef QSharedPointer Ptr; - DataStoreQuery(const Sink::Query &query, const QByteArray &type, Sink::Storage::EntityStore::Ptr store, std::function getProperty); + DataStoreQuery(const Sink::Query &query, const QByteArray &type, Sink::Storage::EntityStore::Ptr store); ResultSet execute(); ResultSet update(qint64 baseRevision); private: - typedef std::function FilterFunction; - typedef std::function BufferCallback; + typedef std::function FilterFunction; + typedef std::function BufferCallback; - virtual QVariant getProperty(const Sink::Entity &entity, const QByteArray &property); QVector indexLookup(const QByteArray &property, const QVariant &value); virtual void readEntity(const QByteArray &key, const BufferCallback &resultCallback); - ResultSet createFilteredSet(ResultSet &resultSet, const std::function &); + ResultSet createFilteredSet(ResultSet &resultSet, const FilterFunction &); QVector loadIncrementalResultSet(qint64 baseRevision); void setupQuery(); @@ -57,7 +56,6 @@ private: Sink::Query mQuery; const QByteArray mType; - std::function mGetProperty; bool mInitialQuery; QSharedPointer mCollector; QSharedPointer mSource; @@ -85,18 +83,12 @@ public: virtual ~FilterBase(){} - void readEntity(const QByteArray &key, const std::function &callback) + void readEntity(const QByteArray &key, const std::function &callback) { Q_ASSERT(mDatastore); mDatastore->readEntity(key, callback); } - QVariant getProperty(const Sink::Entity &entity, const QByteArray &property) - { - Q_ASSERT(mDatastore); - return mDatastore->getProperty(entity, property); - } - QVector indexLookup(const QByteArray &property, const QVariant &value) { Q_ASSERT(mDatastore); diff --git a/common/domain/event.cpp b/common/domain/event.cpp index 6717187..d50652d 100644 --- a/common/domain/event.cpp +++ b/common/domain/event.cpp @@ -87,13 +87,3 @@ QSharedPointer::BufferBuilder> > T propertyMapper->addMapping(&BufferBuilder::add_attachment); return propertyMapper; } - -DataStoreQuery::Ptr TypeImplementation::prepareQuery(const Sink::Query &query, Sink::Storage::EntityStore::Ptr store) -{ - auto mapper = initializeReadPropertyMapper(); - return DataStoreQuery::Ptr::create(query, ApplicationDomain::getTypeName(), store, [mapper](const Sink::Entity &entity, const QByteArray &property) { - - const auto localBuffer = Sink::EntityBuffer::readBuffer(entity.local()); - return mapper->getProperty(property, localBuffer); - }); -} diff --git a/common/domain/event.h b/common/domain/event.h index ce9691d..18e0f20 100644 --- a/common/domain/event.h +++ b/common/domain/event.h @@ -56,8 +56,6 @@ public: typedef Sink::ApplicationDomain::Buffer::EventBuilder BufferBuilder; static void configureIndex(TypeIndex &index); static QSet indexedProperties(); - static QSharedPointer prepareQuery(const Sink::Query &query, Sink::Storage::EntityStore::Ptr store); - static void index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::DataStore::Transaction &transaction); static void removeIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::DataStore::Transaction &transaction); static QSharedPointer > initializeReadPropertyMapper(); diff --git a/common/domain/folder.cpp b/common/domain/folder.cpp index 34e59f6..94727a3 100644 --- a/common/domain/folder.cpp +++ b/common/domain/folder.cpp @@ -91,12 +91,3 @@ QSharedPointer::BufferBuilder> > propertyMapper->addMapping(&BufferBuilder::add_specialpurpose); return propertyMapper; } - -DataStoreQuery::Ptr TypeImplementation::prepareQuery(const Sink::Query &query, Sink::Storage::EntityStore::Ptr store) -{ - auto mapper = initializeReadPropertyMapper(); - return DataStoreQuery::Ptr::create(query, ApplicationDomain::getTypeName(), store, [mapper](const Sink::Entity &entity, const QByteArray &property) { - const auto localBuffer = Sink::EntityBuffer::readBuffer(entity.local()); - return mapper->getProperty(property, localBuffer); - }); -} diff --git a/common/domain/folder.h b/common/domain/folder.h index 0a52b01..ea0d79a 100644 --- a/common/domain/folder.h +++ b/common/domain/folder.h @@ -49,7 +49,6 @@ public: typedef Sink::ApplicationDomain::Buffer::Folder Buffer; typedef Sink::ApplicationDomain::Buffer::FolderBuilder BufferBuilder; static void configureIndex(TypeIndex &index); - static QSharedPointer prepareQuery(const Sink::Query &query, Sink::Storage::EntityStore::Ptr store); static QSet indexedProperties(); static void index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::DataStore::Transaction &transaction); static void removeIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::DataStore::Transaction &transaction); diff --git a/common/domain/mail.cpp b/common/domain/mail.cpp index 9e3a824..b0a3aae 100644 --- a/common/domain/mail.cpp +++ b/common/domain/mail.cpp @@ -225,26 +225,3 @@ QSharedPointer::BufferBuilder> > Ty } -DataStoreQuery::Ptr TypeImplementation::prepareQuery(const Sink::Query &query, Sink::Storage::EntityStore::Ptr store) -{ - auto mapper = initializeReadPropertyMapper(); - return DataStoreQuery::Ptr::create(query, ApplicationDomain::getTypeName(), store, [mapper, store](const Sink::Entity &entity, const QByteArray &property) -> QVariant { - if (property == Mail::ThreadId::name) { - const auto localBuffer = Sink::EntityBuffer::readBuffer(entity.local()); - Q_ASSERT(localBuffer); - auto messageId = mapper->getProperty(Mail::MessageId::name, localBuffer); - //FIXME - //This is an index property that we have too lookup - /* auto thread = getIndex().secondaryLookup(messageId); */ - /* auto thread = store->secondaryLookup(messageId); */ - /* Q_ASSERT(!thread.isEmpty()); */ - /* return thread.first(); */ - return QVariant(); - } else { - const auto localBuffer = Sink::EntityBuffer::readBuffer(entity.local()); - Q_ASSERT(localBuffer); - return mapper->getProperty(property, localBuffer); - } - }); -} - diff --git a/common/domain/mail.h b/common/domain/mail.h index 6c1f670..81a0d1c 100644 --- a/common/domain/mail.h +++ b/common/domain/mail.h @@ -49,7 +49,6 @@ public: typedef Sink::ApplicationDomain::Buffer::Mail Buffer; typedef Sink::ApplicationDomain::Buffer::MailBuilder BufferBuilder; static void configureIndex(TypeIndex &index); - static QSharedPointer prepareQuery(const Sink::Query &query, Sink::Storage::EntityStore::Ptr storage); static QSet indexedProperties(); static void index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::DataStore::Transaction &transaction); static void removeIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::DataStore::Transaction &transaction); diff --git a/common/queryrunner.cpp b/common/queryrunner.cpp index 4422229..67e83ea 100644 --- a/common/queryrunner.cpp +++ b/common/queryrunner.cpp @@ -176,10 +176,7 @@ QueryWorker::~QueryWorker() template void QueryWorker::resultProviderCallback(const Sink::Query &query, Sink::ResultProviderInterface &resultProvider, const ResultSet::Result &result) { - auto adaptor = mResourceContext.adaptorFactory().createAdaptor(result.buffer.entity()); - Q_ASSERT(adaptor); - auto domainObject = DomainType{mResourceContext.instanceId(), result.uid, result.buffer.revision(), adaptor}; - auto valueCopy = Sink::ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation(domainObject, query.requestedProperties).template staticCast(); + auto valueCopy = Sink::ApplicationDomain::ApplicationDomainType::getInMemoryRepresentation(result.entity, query.requestedProperties).template staticCast(); for (auto it = result.aggregateValues.constBegin(); it != result.aggregateValues.constEnd(); it++) { valueCopy->setProperty(it.key(), it.value()); } @@ -208,12 +205,10 @@ QPair QueryWorker::executeIncrementalQuery(const Sin QTime time; time.start(); - auto entityStore = EntityStore::Ptr::create(mResourceContext); - const qint64 baseRevision = resultProvider.revision() + 1; - - auto preparedQuery = ApplicationDomain::TypeImplementation::prepareQuery(query, entityStore); - auto resultSet = preparedQuery->update(baseRevision); + auto entityStore = EntityStore::Ptr::create(mResourceContext); + auto preparedQuery = DataStoreQuery{query, ApplicationDomain::getTypeName(), entityStore}; + auto resultSet = preparedQuery.update(baseRevision); SinkTrace() << "Filtered set retrieved. " << Log::TraceTime(time.elapsed()); auto replayedEntities = resultSet.replaySet(0, 0, [this, query, &resultProvider](const ResultSet::Result &result) { resultProviderCallback(query, resultProvider, result); @@ -242,9 +237,8 @@ QPair QueryWorker::executeInitialQuery( } auto entityStore = EntityStore::Ptr::create(mResourceContext); - - auto preparedQuery = ApplicationDomain::TypeImplementation::prepareQuery(query, entityStore); - auto resultSet = preparedQuery->execute(); + auto preparedQuery = DataStoreQuery{query, ApplicationDomain::getTypeName(), entityStore}; + auto resultSet = preparedQuery.execute(); SinkTrace() << "Filtered set retrieved. " << Log::TraceTime(time.elapsed()); auto replayedEntities = resultSet.replaySet(offset, batchsize, [this, query, &resultProvider](const ResultSet::Result &result) { diff --git a/common/resultset.h b/common/resultset.h index a86a2e2..4f2c278 100644 --- a/common/resultset.h +++ b/common/resultset.h @@ -24,6 +24,7 @@ #include #include "metadata_generated.h" #include "entitybuffer.h" +#include "applicationdomaintype.h" /* * An iterator to a result set. @@ -34,8 +35,7 @@ class ResultSet { public: struct Result { - QByteArray uid; - Sink::EntityBuffer buffer; + Sink::ApplicationDomain::ApplicationDomainType entity; Sink::Operation operation; QMap aggregateValues; }; diff --git a/common/storage/entitystore.cpp b/common/storage/entitystore.cpp index 9615eca..fe63f0b 100644 --- a/common/storage/entitystore.cpp +++ b/common/storage/entitystore.cpp @@ -184,6 +184,15 @@ void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, cons }); } +void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function callback) +{ + readLatest(type, uid, [&](const QByteArray &uid, const EntityBuffer &buffer) { + auto adaptor = d->resourceContext.adaptorFactory(type).createAdaptor(buffer.entity()); + //TODO cache max revision for the duration of the transaction. + callback(ApplicationDomain::ApplicationDomainType{d->resourceContext.instanceId(), uid, DataStore::maxRevision(d->getTransaction()), adaptor}, buffer.operation()); + }); +} + ApplicationDomain::ApplicationDomainType EntityStore::readLatest(const QByteArray &type, const QByteArray &uid) { ApplicationDomain::ApplicationDomainType dt; diff --git a/common/storage/entitystore.h b/common/storage/entitystore.h index de29e87..455e9c3 100644 --- a/common/storage/entitystore.h +++ b/common/storage/entitystore.h @@ -26,6 +26,7 @@ #include "query.h" #include "storage.h" #include "resourcecontext.h" +#include "metadata_generated.h" namespace Sink { class EntityBuffer; @@ -56,6 +57,7 @@ public: void readLatest(const QByteArray &type, const QByteArray &uid, const std::function callback); void readLatest(const QByteArray &type, const QByteArray &uid, const std::function callback); + void readLatest(const QByteArray &type, const QByteArray &uid, const std::function callback); ApplicationDomain::ApplicationDomainType readLatest(const QByteArray &type, const QByteArray &uid); -- cgit v1.2.3