From 0c1f6da51631c0a573a44e2f93eb4012d52dfe5c Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 20 Oct 2016 17:46:10 +0200 Subject: Get access to properties in indexes. --- common/domain/event.cpp | 5 +++ common/domain/event.h | 2 ++ common/domain/folder.cpp | 5 +++ common/domain/folder.h | 2 ++ common/domain/mail.cpp | 10 ++++++ common/domain/mail.h | 2 ++ common/domainadaptor.h | 52 ++++++++++++++++++++++++++++-- common/domaintypeadaptorfactoryinterface.h | 3 +- common/mail/threadindexer.cpp | 6 ++-- common/storage/entitystore.cpp | 31 +++++++++++------- common/typeindex.cpp | 8 ++--- common/typeindex.h | 14 ++++++-- 12 files changed, 114 insertions(+), 26 deletions(-) diff --git a/common/domain/event.cpp b/common/domain/event.cpp index a8098b7..10c92bb 100644 --- a/common/domain/event.cpp +++ b/common/domain/event.cpp @@ -50,3 +50,8 @@ void TypeImplementation::configure(WritePropertyMapper &pr propertyMapper.addMapping(&BufferBuilder::add_uid); propertyMapper.addMapping(&BufferBuilder::add_attachment); } + +void TypeImplementation::configure(IndexPropertyMapper &) +{ + +} diff --git a/common/domain/event.h b/common/domain/event.h index d85b9b3..b683f5f 100644 --- a/common/domain/event.h +++ b/common/domain/event.h @@ -26,6 +26,7 @@ template class ReadPropertyMapper; template class WritePropertyMapper; +class IndexPropertyMapper; class TypeIndex; @@ -49,6 +50,7 @@ public: static void configure(TypeIndex &); static void configure(ReadPropertyMapper &); static void configure(WritePropertyMapper &); + static void configure(IndexPropertyMapper &indexPropertyMapper); }; } diff --git a/common/domain/folder.cpp b/common/domain/folder.cpp index e6701ac..4bc2efb 100644 --- a/common/domain/folder.cpp +++ b/common/domain/folder.cpp @@ -51,3 +51,8 @@ void TypeImplementation::configure(WritePropertyMapper &p propertyMapper.addMapping(&BufferBuilder::add_icon); propertyMapper.addMapping(&BufferBuilder::add_specialpurpose); } + +void TypeImplementation::configure(IndexPropertyMapper &) +{ + +} diff --git a/common/domain/folder.h b/common/domain/folder.h index 3c83794..f232ab5 100644 --- a/common/domain/folder.h +++ b/common/domain/folder.h @@ -24,6 +24,7 @@ template class ReadPropertyMapper; template class WritePropertyMapper; +class IndexPropertyMapper; class TypeIndex; @@ -43,6 +44,7 @@ public: static void configure(TypeIndex &); static void configure(ReadPropertyMapper &); static void configure(WritePropertyMapper &); + static void configure(IndexPropertyMapper &indexPropertyMapper); }; } diff --git a/common/domain/mail.cpp b/common/domain/mail.cpp index 8abe259..c1b0b34 100644 --- a/common/domain/mail.cpp +++ b/common/domain/mail.cpp @@ -27,6 +27,7 @@ #include "entitybuffer.h" #include "entity_generated.h" #include "mail/threadindexer.h" +#include "domainadaptor.h" #include "mail_generated.h" @@ -53,6 +54,15 @@ void TypeImplementation::configure(TypeIndex &index) index.addSecondaryProperty(); } +void TypeImplementation::configure(IndexPropertyMapper &indexPropertyMapper) +{ + indexPropertyMapper.addIndexLookupProperty([](TypeIndex &index, const ApplicationDomain::BufferAdaptor &entity) { + auto messageId = entity.getProperty(Mail::MessageId::name); + auto thread = index.secondaryLookup(messageId); + Q_ASSERT(!thread.isEmpty()); + return thread.first(); + }); +} void TypeImplementation::configure(ReadPropertyMapper &propertyMapper) { diff --git a/common/domain/mail.h b/common/domain/mail.h index c12976a..e052448 100644 --- a/common/domain/mail.h +++ b/common/domain/mail.h @@ -26,6 +26,7 @@ template class ReadPropertyMapper; template class WritePropertyMapper; +class IndexPropertyMapper; class TypeIndex; @@ -44,6 +45,7 @@ public: static void configure(TypeIndex &index); static void configure(ReadPropertyMapper &propertyMapper); static void configure(WritePropertyMapper &propertyMapper); + static void configure(IndexPropertyMapper &indexPropertyMapper); }; } diff --git a/common/domainadaptor.h b/common/domainadaptor.h index 0eb90b3..0f5bdc7 100644 --- a/common/domainadaptor.h +++ b/common/domainadaptor.h @@ -83,6 +83,42 @@ static void createBufferPartBuffer(const Sink::ApplicationDomain::ApplicationDom } } +class IndexPropertyMapper +{ +public: + typedef std::function Accessor; + virtual ~IndexPropertyMapper(){}; + + virtual QVariant getProperty(const QByteArray &key, TypeIndex &index, const Sink::ApplicationDomain::BufferAdaptor &adaptor) const + { + auto accessor = mReadAccessors.value(key); + Q_ASSERT(accessor); + if (!accessor) { + return QVariant(); + } + return accessor(index, adaptor); + } + + bool hasMapping(const QByteArray &key) const + { + return mReadAccessors.contains(key); + } + + QList availableProperties() const + { + return mReadAccessors.keys(); + } + + template + void addIndexLookupProperty(const Accessor &accessor) + { + mReadAccessors.insert(Property::name, accessor); + } + +private: + QHash mReadAccessors; +}; + /** * A generic adaptor implementation that uses a property mapper to read/write values. */ @@ -107,6 +143,8 @@ public: return mResourceMapper->getProperty(key, mResourceBuffer); } else if (mLocalBuffer && mLocalMapper->hasMapping(key)) { return mLocalMapper->getProperty(key, mLocalBuffer); + } else if (mIndex && mIndexMapper->hasMapping(key)) { + return mIndexMapper->getProperty(key, *mIndex, *this); } SinkWarning() << "No mapping available for key " << key << mLocalBuffer << mResourceBuffer; return QVariant(); @@ -117,13 +155,15 @@ public: */ virtual QList availableProperties() const Q_DECL_OVERRIDE { - return mResourceMapper->availableProperties() + mLocalMapper->availableProperties(); + return mResourceMapper->availableProperties() + mLocalMapper->availableProperties() + mIndexMapper->availableProperties(); } LocalBuffer const *mLocalBuffer; ResourceBuffer const *mResourceBuffer; QSharedPointer> mLocalMapper; QSharedPointer> mResourceMapper; + QSharedPointer mIndexMapper; + TypeIndex *mIndex; }; /** @@ -142,11 +182,14 @@ public: : mLocalMapper(QSharedPointer>::create()), mResourceMapper(QSharedPointer>::create()), mLocalWriteMapper(QSharedPointer>::create()), - mResourceWriteMapper(QSharedPointer>::create()) + mResourceWriteMapper(QSharedPointer>::create()), + mIndexMapper(QSharedPointer::create()) { Sink::ApplicationDomain::TypeImplementation::configure(*mLocalMapper); Sink::ApplicationDomain::TypeImplementation::configure(*mLocalWriteMapper); + Sink::ApplicationDomain::TypeImplementation::configure(*mIndexMapper); } + virtual ~DomainTypeAdaptorFactory(){}; /** @@ -154,13 +197,15 @@ public: * * This returns by default a DatastoreBufferAdaptor initialized with the corresponding property mappers. */ - virtual QSharedPointer createAdaptor(const Sink::Entity &entity) Q_DECL_OVERRIDE + virtual QSharedPointer createAdaptor(const Sink::Entity &entity, TypeIndex *index = nullptr) Q_DECL_OVERRIDE { auto adaptor = QSharedPointer>::create(); adaptor->mLocalBuffer = Sink::EntityBuffer::readBuffer(entity.local()); adaptor->mLocalMapper = mLocalMapper; adaptor->mResourceBuffer = Sink::EntityBuffer::readBuffer(entity.resource()); adaptor->mResourceMapper = mResourceMapper; + adaptor->mIndexMapper = mIndexMapper; + adaptor->mIndex = index; return adaptor; } @@ -198,4 +243,5 @@ protected: QSharedPointer> mResourceMapper; QSharedPointer> mLocalWriteMapper; QSharedPointer> mResourceWriteMapper; + QSharedPointer mIndexMapper; }; diff --git a/common/domaintypeadaptorfactoryinterface.h b/common/domaintypeadaptorfactoryinterface.h index 8829c87..4becbe5 100644 --- a/common/domaintypeadaptorfactoryinterface.h +++ b/common/domaintypeadaptorfactoryinterface.h @@ -20,6 +20,7 @@ #include +class TypeIndex; namespace Sink { namespace ApplicationDomain { class BufferAdaptor; @@ -37,7 +38,7 @@ class DomainTypeAdaptorFactoryInterface public: typedef QSharedPointer Ptr; virtual ~DomainTypeAdaptorFactoryInterface(){}; - virtual QSharedPointer createAdaptor(const Sink::Entity &entity) = 0; + virtual QSharedPointer createAdaptor(const Sink::Entity &entity, TypeIndex *index = nullptr) = 0; /* * Creates a buffer from @param domainType diff --git a/common/mail/threadindexer.cpp b/common/mail/threadindexer.cpp index 4a18625..17ee31e 100644 --- a/common/mail/threadindexer.cpp +++ b/common/mail/threadindexer.cpp @@ -91,16 +91,16 @@ void ThreadIndexer::updateThreadingIndex(const QByteArray &identifier, const App QVector thread; //a child already registered our thread. - thread = index().secondaryLookup(messageId, transaction); + thread = index().secondaryLookup(messageId); //If parent is already available, add to thread of parent if (thread.isEmpty() && parentMessageId.isValid()) { - thread = index().secondaryLookup(parentMessageId, transaction); + thread = index().secondaryLookup(parentMessageId); SinkTrace() << "Found parent"; } if (thread.isEmpty()) { //Try to lookup the thread by subject: - thread = index().secondaryLookup(normalizedSubject, transaction); + thread = index().secondaryLookup(normalizedSubject); if (thread.isEmpty()) { SinkTrace() << "Created a new thread "; thread << QUuid::createUuid().toByteArray(); diff --git a/common/storage/entitystore.cpp b/common/storage/entitystore.cpp index f7f235e..dce2fc6 100644 --- a/common/storage/entitystore.cpp +++ b/common/storage/entitystore.cpp @@ -69,9 +69,8 @@ public: /* return *index; */ /* } */ - TypeIndex &typeIndex(const QByteArray &type) + TypeIndex &cachedIndex(const QByteArray &type) { - /* return applyType(type); */ if (indexByType.contains(type)) { return *indexByType.value(type); } @@ -92,7 +91,19 @@ public: } indexByType.insert(type, index); return *index; + TypeIndex &typeIndex(const QByteArray &type) + { + auto &index = cachedIndex(type); + index.mTransaction = &transaction; + return index; + } + + ApplicationDomain::ApplicationDomainType createApplicationDomainType(const QByteArray &type, const QByteArray &uid, qint64 revision, const EntityBuffer &buffer) + { + auto adaptor = resourceContext.adaptorFactory(type).createAdaptor(buffer.entity(), &typeIndex(type)); + return ApplicationDomain::ApplicationDomainType{resourceContext.instanceId(), uid, revision, adaptor}; } + }; EntityStore::EntityStore(const ResourceContext &context) @@ -373,17 +384,16 @@ 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()); - callback(ApplicationDomain::ApplicationDomainType{d->resourceContext.instanceId(), uid, DataStore::maxRevision(d->getTransaction()), adaptor}); + //TODO cache max revision for the duration of the transaction. + callback(d->createApplicationDomainType(type, uid, DataStore::maxRevision(d->getTransaction()), buffer)); }); } 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()); + callback(d->createApplicationDomainType(type, uid, DataStore::maxRevision(d->getTransaction()), buffer), buffer.operation()); }); } @@ -410,8 +420,7 @@ void EntityStore::readEntity(const QByteArray &type, const QByteArray &key, cons void EntityStore::readEntity(const QByteArray &type, const QByteArray &uid, const std::function callback) { readEntity(type, uid, [&](const QByteArray &uid, const EntityBuffer &buffer) { - auto adaptor = d->resourceContext.adaptorFactory(type).createAdaptor(buffer.entity()); - callback(ApplicationDomain::ApplicationDomainType{d->resourceContext.instanceId(), uid, DataStore::maxRevision(d->getTransaction()), adaptor}); + callback(d->createApplicationDomainType(type, uid, DataStore::maxRevision(d->getTransaction()), buffer)); }); } @@ -432,8 +441,7 @@ void EntityStore::readAll(const QByteArray &type, const std::function bool { auto uid = DataStore::uidFromKey(key); auto buffer = Sink::EntityBuffer{value.data(), value.size()}; - auto adaptor = d->resourceContext.adaptorFactory(type).createAdaptor(buffer.entity()); - callback(ApplicationDomain::ApplicationDomainType{d->resourceContext.instanceId(), uid, DataStore::maxRevision(d->getTransaction()), adaptor}); + callback(d->createApplicationDomainType(type, uid, DataStore::maxRevision(d->getTransaction()), buffer)); return true; }, [&](const DataStore::Error &error) { SinkWarning() << "Error during query: " << error.message; }); @@ -480,8 +488,7 @@ void EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qi void EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qint64 revision, const std::function callback) { readPrevious(type, uid, revision, [&](const QByteArray &uid, const EntityBuffer &buffer) { - auto adaptor = d->resourceContext.adaptorFactory(type).createAdaptor(buffer.entity()); - callback(ApplicationDomain::ApplicationDomainType{d->resourceContext.instanceId(), uid, DataStore::maxRevision(d->getTransaction()), adaptor}); + callback(d->createApplicationDomainType(type, uid, DataStore::maxRevision(d->getTransaction()), buffer)); }); } diff --git a/common/typeindex.cpp b/common/typeindex.cpp index 8f5de4f..036b662 100644 --- a/common/typeindex.cpp +++ b/common/typeindex.cpp @@ -238,10 +238,10 @@ void TypeIndex::index(const QByteArray &leftName, const QBy } template <> -QVector TypeIndex::secondaryLookup(const QByteArray &leftName, const QByteArray &rightName, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction) +QVector TypeIndex::secondaryLookup(const QByteArray &leftName, const QByteArray &rightName, const QVariant &value) { QVector keys; - Index index(indexName(leftName + rightName), transaction); + Index index(indexName(leftName + rightName), *mTransaction); const auto lookupKey = getByteArray(value); index.lookup( lookupKey, [&](const QByteArray &value) { keys << value; }, [=](const Index::Error &error) { SinkWarning() << "Error in index: " << error.message << value; }); @@ -250,10 +250,10 @@ QVector TypeIndex::secondaryLookup(const QByteArray &lef } template <> -QVector TypeIndex::secondaryLookup(const QByteArray &leftName, const QByteArray &rightName, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction) +QVector TypeIndex::secondaryLookup(const QByteArray &leftName, const QByteArray &rightName, const QVariant &value) { QVector keys; - Index index(indexName(leftName + rightName), transaction); + Index index(indexName(leftName + rightName), *mTransaction); const auto lookupKey = getByteArray(value); index.lookup( lookupKey, [&](const QByteArray &value) { keys << value; }, [=](const Index::Error &error) { SinkWarning() << "Error in index: " << error.message << value; }); diff --git a/common/typeindex.h b/common/typeindex.h index 041e04a..3cffb1e 100644 --- a/common/typeindex.h +++ b/common/typeindex.h @@ -25,6 +25,12 @@ #include "indexer.h" #include +namespace Sink { +namespace Storage { + class EntityStore; +} +} + class TypeIndex { public: @@ -66,13 +72,13 @@ public: QVector lookup(const QByteArray &property, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction); template - QVector secondaryLookup(const QVariant &value, Sink::Storage::DataStore::Transaction &transaction) + QVector secondaryLookup(const QVariant &value) { - return secondaryLookup(Left::name, Right::name, value, transaction); + return secondaryLookup(Left::name, Right::name, value); } template - QVector secondaryLookup(const QByteArray &leftName, const QByteArray &rightName, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction); + QVector secondaryLookup(const QByteArray &leftName, const QByteArray &rightName, const QVariant &value); template void index(const QVariant &leftValue, const QVariant &rightValue, Sink::Storage::DataStore::Transaction &transaction) @@ -85,6 +91,7 @@ public: private: + friend class Sink::Storage::EntityStore; QByteArray indexName(const QByteArray &property, const QByteArray &sortProperty = QByteArray()) const; QByteArray mType; SINK_DEBUG_COMPONENT(mType) @@ -93,6 +100,7 @@ private: // QMap mSecondaryProperties; QList mCustomIndexer; + Sink::Storage::DataStore::Transaction *mTransaction; QHash> mIndexer; QHash> mSortIndexer; }; -- cgit v1.2.3