From be8dba1827ec54ec11d9a3ef143db9ad7f7f38df Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Mon, 26 Sep 2016 11:58:38 +0200 Subject: The threading reduction is working. --- common/domain/applicationdomaintype.h | 8 ++++ common/domain/mail.cpp | 80 ++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 33 deletions(-) (limited to 'common/domain') diff --git a/common/domain/applicationdomaintype.h b/common/domain/applicationdomaintype.h index c853397..c824251 100644 --- a/common/domain/applicationdomaintype.h +++ b/common/domain/applicationdomaintype.h @@ -79,6 +79,12 @@ void set##NAME(const QByteArray &value) { setProperty(NAME::name, QVariant::fromValue(value)); } \ QByteArray get##NAME() const { return getProperty(NAME::name).value(); } \ +#define SINK_INDEX_PROPERTY(TYPE, NAME, LOWERCASENAME) \ + struct NAME { \ + static constexpr const char *name = #LOWERCASENAME; \ + typedef TYPE Type; \ + }; \ + namespace Sink { namespace ApplicationDomain { @@ -240,6 +246,7 @@ struct SINK_EXPORT Mail : public Entity { SINK_PROPERTY(bool, Sent, sent); SINK_EXTRACTED_PROPERTY(QByteArray, MessageId, messageId); SINK_EXTRACTED_PROPERTY(QByteArray, ParentMessageId, parentMessageId); + SINK_INDEX_PROPERTY(QByteArray, ThreadId, threadId); }; /** @@ -378,6 +385,7 @@ class SINK_EXPORT TypeImplementation; #undef SINK_EXTRACTED_PROPERTY #undef SINK_BLOB_PROPERTY #undef SINK_REFERENCE_PROPERTY +#undef SINK_INDEX_PROPERTY Q_DECLARE_METATYPE(Sink::ApplicationDomain::ApplicationDomainType) Q_DECLARE_METATYPE(Sink::ApplicationDomain::ApplicationDomainType::Ptr) diff --git a/common/domain/mail.cpp b/common/domain/mail.cpp index 483a2f2..2b6eb84 100644 --- a/common/domain/mail.cpp +++ b/common/domain/mail.cpp @@ -60,6 +60,10 @@ static TypeIndex &getIndex() index->addPropertyWithSorting(Mail::Folder::name, Mail::Date::name); index->addProperty(Mail::MessageId::name); index->addProperty(Mail::ParentMessageId::name); + + index->addProperty(); + index->addSecondaryProperty(); + index->addSecondaryProperty(); } return *index; } @@ -120,42 +124,44 @@ static QString stripOffPrefixes(const QString &subject) static void updateThreadingIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction) { - auto messageId = bufferAdaptor.getProperty(Mail::MessageId::name).toByteArray(); - auto parentMessageId = bufferAdaptor.getProperty(Mail::ParentMessageId::name).toByteArray(); - auto subject = bufferAdaptor.getProperty(Mail::Subject::name).toString(); + auto messageId = bufferAdaptor.getProperty(Mail::MessageId::name); + auto parentMessageId = bufferAdaptor.getProperty(Mail::ParentMessageId::name); + auto subject = bufferAdaptor.getProperty(Mail::Subject::name); - Index msgIdIndex("msgId", transaction); - Index msgIdThreadIdIndex("msgIdThreadId", transaction); - Index subjectThreadIdIndex("subjectThreadId", transaction); + auto normalizedSubject = stripOffPrefixes(subject.toString()).toUtf8(); - //Add the message to the index - Q_ASSERT(msgIdIndex.lookup(messageId).isEmpty()); - msgIdIndex.add(messageId, identifier); + QVector thread; - auto normalizedSubject = stripOffPrefixes(subject).toUtf8(); + //a child already registered our thread. + thread = getIndex().secondaryLookup(messageId, transaction); - QByteArray thread; //If parent is already available, add to thread of parent - if (!parentMessageId.isEmpty() && !msgIdIndex.lookup(parentMessageId).isEmpty()) { - thread = msgIdThreadIdIndex.lookup(parentMessageId); - msgIdThreadIdIndex.add(messageId, thread); - subjectThreadIdIndex.add(normalizedSubject, thread); - } else { + if (thread.isEmpty() && parentMessageId.isValid()) { + thread = getIndex().secondaryLookup(parentMessageId, transaction); + SinkTrace() << "Found parent"; + } + if (thread.isEmpty()) { //Try to lookup the thread by subject: - thread = subjectThreadIdIndex.lookup(normalizedSubject); - if (!thread.isEmpty()) { - msgIdThreadIdIndex.add(messageId, thread); + thread = getIndex().secondaryLookup(normalizedSubject, transaction); + if (thread.isEmpty()) { + SinkTrace() << "Created a new thread "; + thread << QUuid::createUuid().toByteArray(); } else { - thread = QUuid::createUuid().toByteArray(); - subjectThreadIdIndex.add(normalizedSubject, thread); - if (!parentMessageId.isEmpty()) { - //Register parent with thread for when it becomes available - msgIdThreadIdIndex.add(parentMessageId, thread); - } } } - Q_ASSERT(!thread.isEmpty()); - msgIdThreadIdIndex.add(messageId, thread); + + //We should have found the thread by now + if (!thread.isEmpty()) { + if (parentMessageId.isValid()) { + //Register parent with thread for when it becomes available + getIndex().index(parentMessageId, thread.first(), transaction); + } + getIndex().index(messageId, thread.first(), transaction); + getIndex().index(thread.first(), messageId, transaction); + getIndex().index(normalizedSubject, thread.first(), transaction); + } else { + SinkWarning() << "Couldn't find a thread for: " << messageId; + } } void TypeImplementation::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction) @@ -214,13 +220,21 @@ QSharedPointer::BufferBuilder> > Ty DataStoreQuery::Ptr TypeImplementation::prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction) { - - - auto mapper = initializeReadPropertyMapper(); - return DataStoreQuery::Ptr::create(query, ApplicationDomain::getTypeName(), transaction, getIndex(), [mapper](const Sink::Entity &entity, const QByteArray &property) { - + auto mapper = initializeReadPropertyMapper(); + return DataStoreQuery::Ptr::create(query, ApplicationDomain::getTypeName(), transaction, getIndex(), [mapper, &transaction](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); + //This is an index property that we have too lookup + auto thread = getIndex().secondaryLookup(messageId, transaction); + Q_ASSERT(!thread.isEmpty()); + return thread.first(); + } else { + const auto localBuffer = Sink::EntityBuffer::readBuffer(entity.local()); + Q_ASSERT(localBuffer); return mapper->getProperty(property, localBuffer); - }); + } + }); } -- cgit v1.2.3