diff --git a/autotests/libs/itemsynctest.cpp b/autotests/libs/itemsynctest.cpp --- a/autotests/libs/itemsynctest.cpp +++ b/autotests/libs/itemsynctest.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -49,7 +50,7 @@ private: Item::List fetchItems(const Collection &col) { - qDebug() << col.remoteId(); + qDebug() << "fetching items from collection" << col.remoteId() << col.name(); ItemFetchJob *fetch = new ItemFetchJob(col, this); fetch->fetchScope().fetchFullPayload(); fetch->fetchScope().fetchAllAttributes(); @@ -575,6 +576,62 @@ syncer->deliveryDone(); QTRY_COMPARE(spy.count(), 1); } + + void testFullSyncManyItems() + { + const Collection col = Collection(collectionIdFromPath(QStringLiteral("res2/foo2"))); + QVERIFY(col.isValid()); + + Akonadi::Monitor monitor; + monitor.setCollectionMonitored(col); + QSignalSpy addedSpy(&monitor, SIGNAL(itemAdded(Akonadi::Item,Akonadi::Collection))); + QVERIFY(addedSpy.isValid()); + + const int itemCount = 1000; + for (int i = 0; i < itemCount; ++i) { + Item item(QStringLiteral("application/octet-stream")); + item.setRemoteId(QStringLiteral("rid") + QString::number(i)); + item.setGid(QStringLiteral("gid") + QString::number(i)); + item.setPayload("payload1"); + ItemCreateJob *job = new ItemCreateJob(item, col); + AKVERIFYEXEC(job); + } + + QTRY_COMPARE(addedSpy.count(), itemCount); + addedSpy.clear(); + + const Item::List origItems = fetchItems(col); + + //Since the item sync affects the knut resource we ensure we actually managed to load all items + //This needs to be adjusted should the testdataset change + QCOMPARE(origItems.size(), itemCount); + + QSignalSpy deletedSpy(&monitor, SIGNAL(itemRemoved(Akonadi::Item))); + QVERIFY(deletedSpy.isValid()); + QSignalSpy changedSpy(&monitor, SIGNAL(itemChanged(Akonadi::Item,QSet))); + QVERIFY(changedSpy.isValid()); + + QBENCHMARK { + ItemSync *syncer = new ItemSync(col); + syncer->setTransactionMode(ItemSync::SingleTransaction); + QSignalSpy transactionSpy(syncer, SIGNAL(transactionCommitted())); + QVERIFY(transactionSpy.isValid()); + syncer->setFullSyncItems(origItems); + AKVERIFYEXEC(syncer); + QCOMPARE(transactionSpy.count(), 1); + } + + const Item::List resultItems = fetchItems(col); + QCOMPARE(resultItems.count(), origItems.count()); + QTest::qWait(100); + QCOMPARE(deletedSpy.count(), 0); + QCOMPARE(addedSpy.count(), 0); + QCOMPARE(changedSpy.count(), 0); + + // delete all items; QBENCHMARK leads to the whole method being called more than once + ItemDeleteJob *job = new ItemDeleteJob(resultItems); + AKVERIFYEXEC(job); + } }; QTEST_AKONADIMAIN(ItemsyncTest) diff --git a/src/core/itemsync.cpp b/src/core/itemsync.cpp --- a/src/core/itemsync.cpp +++ b/src/core/itemsync.cpp @@ -344,9 +344,10 @@ if (mRemoteItemQueue.size() >= mBatchSize || mDeliveryDone) { //we have a new batch to process const int num = qMin(mBatchSize, mRemoteItemQueue.size()); - for (int i = 0; i < num; i++) { - mCurrentBatchRemoteItems << mRemoteItemQueue.takeFirst(); - } + mCurrentBatchRemoteItems.reserve(mBatchSize); + std::move(mRemoteItemQueue.begin(), mRemoteItemQueue.begin() + num, std::back_inserter(mCurrentBatchRemoteItems)); + mRemoteItemQueue.erase(mRemoteItemQueue.begin(), mRemoteItemQueue.begin() + num); + mCurrentBatchRemovedRemoteItems += mRemovedRemoteItemQueue; mRemovedRemoteItemQueue.clear(); } else {