summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vrátil <dvratil@kde.org>2016-08-14 15:28:56 (GMT)
committerDaniel Vrátil <dvratil@kde.org>2016-08-14 15:31:37 (GMT)
commite8a9d532884dc8af703bce75a437e44bc9af24c3 (patch)
tree353c4d8ebdf4d1dcb8e3e998afe9189a9975c21a
parent4331088e2900a3ea3df06a468dd9d5d99dc82fe7 (diff)
Port local mail resources to new retrieveItems() API
The Maildir, MBox and MixedMaildir resources are most affected by the poor performance of ResourceBase::retrieveItem(). This change ports those resources to the new retrieveItems() API which provides batch retrieval of missing payload parts.
-rw-r--r--CMakeLists.txt2
-rw-r--r--resources/maildir/maildirresource.cpp26
-rw-r--r--resources/maildir/maildirresource.h2
-rw-r--r--resources/mbox/mboxresource.cpp29
-rw-r--r--resources/mbox/mboxresource.h2
-rw-r--r--resources/mixedmaildir/mixedmaildirresource.cpp6
-rw-r--r--resources/mixedmaildir/mixedmaildirresource.h2
-rw-r--r--resources/mixedmaildir/mixedmaildirstore.cpp11
-rw-r--r--resources/shared/filestore/abstractlocalstore.cpp40
-rw-r--r--resources/shared/filestore/abstractlocalstore.h2
-rw-r--r--resources/shared/filestore/itemfetchjob.cpp9
-rw-r--r--resources/shared/filestore/itemfetchjob.h2
-rw-r--r--resources/shared/filestore/storeinterface.h4
13 files changed, 90 insertions, 47 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cde773b..ba508d0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -57,7 +57,7 @@ set(QT_REQUIRED_VERSION "5.5.0")
set(KDEPIMRUNTIME_LIB_VERSION "${KDEPIM_RUNTIME_VERSION_NUMBER}")
set(KDEPIMRUNTIME_LIB_SOVERSION "5")
-set(AKONADI_VERSION "5.3.40")
+set(AKONADI_VERSION "5.3.42")
set(KCONTACTS_LIB_VERSION "5.3.40")
set(KCALENDARCORE_LIB_VERSION "5.3.40")
diff --git a/resources/maildir/maildirresource.cpp b/resources/maildir/maildirresource.cpp
index 91a459c..9b5f400 100644
--- a/resources/maildir/maildirresource.cpp
+++ b/resources/maildir/maildirresource.cpp
@@ -198,26 +198,32 @@ MaildirResource::~ MaildirResource()
delete mSettings;
}
-bool MaildirResource::retrieveItem(const Akonadi::Item &item, const QSet<QByteArray> &parts)
+bool MaildirResource::retrieveItems(const Akonadi::Item::List &items, const QSet<QByteArray> &parts)
{
Q_UNUSED(parts);
- const Maildir md = maildirForCollection(item.parentCollection());
+ const Maildir md = maildirForCollection(items.at(0).parentCollection());
if (!md.isValid()) {
cancelTask(i18n("Unable to fetch item: The maildir folder \"%1\" is not valid.",
md.path()));
return false;
}
- const QByteArray data = md.readEntry(item.remoteId());
- KMime::Message *mail = new KMime::Message();
- mail->setContent(KMime::CRLFtoLF(data));
- mail->parse();
+ Akonadi::Item::List rv;
+ rv.reserve(items.count());
+ for (const Akonadi::Item &item : items) {
+ const QByteArray data = md.readEntry(item.remoteId());
+ KMime::Message *mail = new KMime::Message();
+ mail->setContent(KMime::CRLFtoLF(data));
+ mail->parse();
- Item i(item);
- i.setPayload(KMime::Message::Ptr(mail));
- Akonadi::MessageFlags::copyMessageFlags(*mail, i);
- itemRetrieved(i);
+ Item i(item);
+ i.setPayload(KMime::Message::Ptr(mail));
+ Akonadi::MessageFlags::copyMessageFlags(*mail, i);
+ rv.push_back(i);
+ }
+
+ itemsRetrieved(rv);
return true;
}
diff --git a/resources/maildir/maildirresource.h b/resources/maildir/maildirresource.h
index 76b864b..74d95c1 100644
--- a/resources/maildir/maildirresource.h
+++ b/resources/maildir/maildirresource.h
@@ -50,7 +50,7 @@ public Q_SLOTS:
protected Q_SLOTS:
void retrieveCollections() Q_DECL_OVERRIDE;
void retrieveItems(const Akonadi::Collection &col) Q_DECL_OVERRIDE;
- bool retrieveItem(const Akonadi::Item &item, const QSet<QByteArray> &parts) Q_DECL_OVERRIDE;
+ bool retrieveItems(const Akonadi::Item::List &items, const QSet<QByteArray> &parts) Q_DECL_OVERRIDE;
protected:
virtual QString itemMimeType() const;
diff --git a/resources/mbox/mboxresource.cpp b/resources/mbox/mboxresource.cpp
index 209adbe..c7f4699 100644
--- a/resources/mbox/mboxresource.cpp
+++ b/resources/mbox/mboxresource.cpp
@@ -149,7 +149,7 @@ void MboxResource::retrieveItems(const Akonadi::Collection &col)
itemsRetrieved(items);
}
-bool MboxResource::retrieveItem(const Akonadi::Item &item, const QSet<QByteArray> &parts)
+bool MboxResource::retrieveItems(const Akonadi::Item::List &items, const QSet<QByteArray> &parts)
{
Q_UNUSED(parts);
@@ -162,18 +162,23 @@ bool MboxResource::retrieveItem(const Akonadi::Item &item, const QSet<QByteArray
return false;
}
- const QString rid = item.remoteId();
- const quint64 offset = itemOffset(rid);
- KMime::Message *mail = mMBox->readMessage(KMBox::MBoxEntry(offset));
- if (!mail) {
- Q_EMIT error(i18n("Failed to read message with uid '%1'.", rid));
- return false;
+ Akonadi::Item::List rv;
+ rv.reserve(items.count());
+ for (const auto &item : items) {
+ const QString rid = item.remoteId();
+ const quint64 offset = itemOffset(rid);
+ KMime::Message *mail = mMBox->readMessage(KMBox::MBoxEntry(offset));
+ if (!mail) {
+ Q_EMIT error(i18n("Failed to read message with uid '%1'.", rid));
+ return false;
+ }
+
+ Item i(item);
+ i.setPayload(KMime::Message::Ptr(mail));
+ Akonadi::MessageFlags::copyMessageFlags(*mail, i);
+ rv.push_back(i);
}
-
- Item i(item);
- i.setPayload(KMime::Message::Ptr(mail));
- Akonadi::MessageFlags::copyMessageFlags(*mail, i);
- itemRetrieved(i);
+ itemsRetrieved(rv);
return true;
}
diff --git a/resources/mbox/mboxresource.h b/resources/mbox/mboxresource.h
index 1cf624d..6a9d541 100644
--- a/resources/mbox/mboxresource.h
+++ b/resources/mbox/mboxresource.h
@@ -37,7 +37,7 @@ public:
~MboxResource();
protected Q_SLOTS:
- bool retrieveItem(const Akonadi::Item &item, const QSet<QByteArray> &parts) Q_DECL_OVERRIDE;
+ bool retrieveItems(const Akonadi::Item::List &items, const QSet<QByteArray> &parts) Q_DECL_OVERRIDE;
void retrieveItems(const Akonadi::Collection &col) Q_DECL_OVERRIDE;
protected:
diff --git a/resources/mixedmaildir/mixedmaildirresource.cpp b/resources/mixedmaildir/mixedmaildirresource.cpp
index 27fb759..5c52e4c 100644
--- a/resources/mixedmaildir/mixedmaildirresource.cpp
+++ b/resources/mixedmaildir/mixedmaildirresource.cpp
@@ -266,11 +266,11 @@ void MixedMaildirResource::retrieveItems(const Collection &col)
status(Running, i18nc("@info:status", "Synchronizing email folder %1", col.name()));
}
-bool MixedMaildirResource::retrieveItem(const Item &item, const QSet<QByteArray> &parts)
+bool MixedMaildirResource::retrieveItems(const Item::List &items, const QSet<QByteArray> &parts)
{
Q_UNUSED(parts);
- FileStore::ItemFetchJob *job = mStore->fetchItem(item);
+ FileStore::ItemFetchJob *job = mStore->fetchItems(items);
if (parts.contains(Item::FullPayload)) {
job->fetchScope().fetchFullPayload(true);
} else {
@@ -565,7 +565,7 @@ void MixedMaildirResource::retrieveItemResult(KJob *job)
Q_ASSERT(fetchJob != 0);
Q_ASSERT(!fetchJob->items().isEmpty());
- itemRetrieved(fetchJob->items().at(0));
+ itemsRetrieved(fetchJob->items());
}
void MixedMaildirResource::itemAddedResult(KJob *job)
diff --git a/resources/mixedmaildir/mixedmaildirresource.h b/resources/mixedmaildir/mixedmaildirresource.h
index 03fa499..59c862a 100644
--- a/resources/mixedmaildir/mixedmaildirresource.h
+++ b/resources/mixedmaildir/mixedmaildirresource.h
@@ -43,7 +43,7 @@ public Q_SLOTS:
protected Q_SLOTS:
void retrieveCollections() Q_DECL_OVERRIDE;
void retrieveItems(const Akonadi::Collection &col) Q_DECL_OVERRIDE;
- bool retrieveItem(const Akonadi::Item &item, const QSet<QByteArray> &parts) Q_DECL_OVERRIDE;
+ bool retrieveItems(const Akonadi::Item::List &items, const QSet<QByteArray> &parts) Q_DECL_OVERRIDE;
protected:
void aboutToQuit() Q_DECL_OVERRIDE;
diff --git a/resources/mixedmaildir/mixedmaildirstore.cpp b/resources/mixedmaildir/mixedmaildirstore.cpp
index 137a7cd..e33e688 100644
--- a/resources/mixedmaildir/mixedmaildirstore.cpp
+++ b/resources/mixedmaildir/mixedmaildirstore.cpp
@@ -1660,7 +1660,10 @@ bool MixedMaildirStore::Private::visit(FileStore::ItemFetchJob *job)
scope.payloadParts().contains(MessagePart::Envelope);
const bool fetchSingleItem = job->collection().remoteId().isEmpty();
- const Collection collection = fetchSingleItem ? job->item().parentCollection() : job->collection();
+ const bool fetchItemsBatch = !job->items().isEmpty() && !job->item().isValid();
+ const Collection collection = fetchSingleItem ? job->item().parentCollection() :
+ fetchItemsBatch ? job->items().at(0).parentCollection() :
+ job->collection();
QString path;
QString errorText;
@@ -1675,7 +1678,7 @@ bool MixedMaildirStore::Private::visit(FileStore::ItemFetchJob *job)
if (folderType == MBoxFolder) {
MBoxHash::iterator findIt = mMBoxes.find(path);
- if (findIt == mMBoxes.end() || !fetchSingleItem) {
+ if (findIt == mMBoxes.end() || (!fetchSingleItem || !fetchItemsBatch)) {
MBoxPtr mbox = findIt != mMBoxes.end() ? findIt.value() : MBoxPtr(new MBoxContext);
if (!mbox->load(path)) {
errorText = i18nc("@info:status", "Failed to load MBox folder %1", path);
@@ -1695,6 +1698,8 @@ bool MixedMaildirStore::Private::visit(FileStore::ItemFetchJob *job)
Item::List items;
if (fetchSingleItem) {
items << job->item();
+ } else if (fetchItemsBatch) {
+ items = job->items();
} else {
listCollection(job, findIt.value(), collection, items);
}
@@ -1734,6 +1739,8 @@ bool MixedMaildirStore::Private::visit(FileStore::ItemFetchJob *job)
Item::List items;
if (fetchSingleItem) {
items << job->item();
+ } else if (fetchItemsBatch) {
+ items = job->items();
} else {
listCollection(job, mdPtr, collection, items);
}
diff --git a/resources/shared/filestore/abstractlocalstore.cpp b/resources/shared/filestore/abstractlocalstore.cpp
index 447ef06..5ccad15 100644
--- a/resources/shared/filestore/abstractlocalstore.cpp
+++ b/resources/shared/filestore/abstractlocalstore.cpp
@@ -563,22 +563,25 @@ FileStore::ItemFetchJob *FileStore::AbstractLocalStore::fetchItems(const Collect
return job;
}
-FileStore::ItemFetchJob *FileStore::AbstractLocalStore::fetchItem(const Item &item) const
-{
- FileStore::ItemFetchJob *job = new FileStore::ItemFetchJob(item, d->mSession);
-
- if (d->mTopLevelCollection.remoteId().isEmpty()) {
- const QString message = i18nc("@info:status", "Configured storage location is empty");
- qCritical() << message;
- qCritical() << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType()
- << ", parentCollection=" << item.parentCollection().remoteId() << ")";
- d->mSession->setError(job, FileStore::Job::InvalidStoreState, message);
- } else if (item.remoteId().isEmpty()) {
- const QString message = i18nc("@info:status", "Given item identifier is empty");
- qCritical() << message;
- qCritical() << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType()
- << ", parentCollection=" << item.parentCollection().remoteId() << ")";
- d->mSession->setError(job, FileStore::Job::InvalidJobContext, message);
+FileStore::ItemFetchJob *FileStore::AbstractLocalStore::fetchItems(const Item::List &items) const
+{
+ FileStore::ItemFetchJob *job = new FileStore::ItemFetchJob(items, d->mSession);
+
+ if (items.size() == 1) {
+ const Akonadi::Item &item = items[0];
+ if (d->mTopLevelCollection.remoteId().isEmpty()) {
+ const QString message = i18nc("@info:status", "Configured storage location is empty");
+ qCritical() << message;
+ qCritical() << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType()
+ << ", parentCollection=" << item.parentCollection().remoteId() << ")";
+ d->mSession->setError(job, FileStore::Job::InvalidStoreState, message);
+ } else if (item.remoteId().isEmpty()) {
+ const QString message = i18nc("@info:status", "Given item identifier is empty");
+ qCritical() << message;
+ qCritical() << "Item(remoteId=" << item.remoteId() << ", mimeType=" << item.mimeType()
+ << ", parentCollection=" << item.parentCollection().remoteId() << ")";
+ d->mSession->setError(job, FileStore::Job::InvalidJobContext, message);
+ }
}
int errorCode = 0;
@@ -591,6 +594,11 @@ FileStore::ItemFetchJob *FileStore::AbstractLocalStore::fetchItem(const Item &it
return job;
}
+FileStore::ItemFetchJob *FileStore::AbstractLocalStore::fetchItem(const Item &item) const
+{
+ return fetchItems({ item });
+}
+
FileStore::ItemCreateJob *FileStore::AbstractLocalStore::createItem(const Item &item, const Collection &collection)
{
FileStore::ItemCreateJob *job = new FileStore::ItemCreateJob(item, collection, d->mSession);
diff --git a/resources/shared/filestore/abstractlocalstore.h b/resources/shared/filestore/abstractlocalstore.h
index 63d13b3..11b43bb 100644
--- a/resources/shared/filestore/abstractlocalstore.h
+++ b/resources/shared/filestore/abstractlocalstore.h
@@ -63,6 +63,8 @@ public:
ItemFetchJob *fetchItems(const Collection &collection) const Q_DECL_OVERRIDE;
+ ItemFetchJob *fetchItems(const Item::List &items) const Q_DECL_OVERRIDE;
+
ItemFetchJob *fetchItem(const Item &item) const Q_DECL_OVERRIDE;
ItemCreateJob *createItem(const Item &item, const Collection &collection) Q_DECL_OVERRIDE;
diff --git a/resources/shared/filestore/itemfetchjob.cpp b/resources/shared/filestore/itemfetchjob.cpp
index d5bf24d..4b23637 100644
--- a/resources/shared/filestore/itemfetchjob.cpp
+++ b/resources/shared/filestore/itemfetchjob.cpp
@@ -52,6 +52,15 @@ FileStore::ItemFetchJob::ItemFetchJob(const Item &item, FileStore::AbstractJobSe
session->addJob(this);
}
+FileStore::ItemFetchJob::ItemFetchJob(const Item::List &items, FileStore::AbstractJobSession *session)
+ : FileStore::Job(session), d(new Private())
+{
+ d->mItems = items;
+
+ session->addJob(this);
+}
+
+
FileStore::ItemFetchJob::~ItemFetchJob()
{
delete d;
diff --git a/resources/shared/filestore/itemfetchjob.h b/resources/shared/filestore/itemfetchjob.h
index aa9ea32..07fabe7 100644
--- a/resources/shared/filestore/itemfetchjob.h
+++ b/resources/shared/filestore/itemfetchjob.h
@@ -46,6 +46,8 @@ public:
explicit ItemFetchJob(const Item &item, AbstractJobSession *session = Q_NULLPTR);
+ explicit ItemFetchJob(const Item::List &items, AbstractJobSession *session = Q_NULLPTR);
+
virtual ~ItemFetchJob();
Collection collection() const;
diff --git a/resources/shared/filestore/storeinterface.h b/resources/shared/filestore/storeinterface.h
index 6491324..fb0331b 100644
--- a/resources/shared/filestore/storeinterface.h
+++ b/resources/shared/filestore/storeinterface.h
@@ -22,6 +22,8 @@
#include "akonadi-filestore_export.h"
+#include <QVector>
+
// TODO not nice, collection fetch type should probably be in its own header
#include "collectionfetchjob.h"
@@ -65,6 +67,8 @@ public:
virtual ItemFetchJob *fetchItems(const Collection &collection) const = 0;
+ virtual ItemFetchJob *fetchItems(const QVector<Item> &items) const = 0;
+
virtual ItemFetchJob *fetchItem(const Item &item) const = 0;
virtual ItemCreateJob *createItem(const Item &item, const Collection &collection) = 0;