Commit 68a55c5b authored by Shashwat Jolly's avatar Shashwat Jolly
Browse files

Handle collections and items fetch sync tokens properly

Also polished up the code - added some null checks and defines for fetch size
parent feb520cb
......@@ -16,6 +16,9 @@
#include "etesync_debug.h"
#include "settings.h"
#define ITEMS_FETCH_BATCH_SIZE 50
#define ITEM_SIZE_INITIAL_TRY 2000
using namespace Akonadi;
using namespace EteSyncAPI;
......@@ -44,6 +47,11 @@ void EntriesFetchJob::fetchEntries()
setErrorText(QStringLiteral("No cache for collection ") + mCollection.remoteId());
return;
}
if (!mAccount) {
setError(UserDefinedError);
setErrorText(QStringLiteral("EntriesFetchJob: Etebase account is empty"));
return;
}
EtebaseCollectionManagerPtr collectionManager(etebase_account_get_collection_manager(mAccount));
const QByteArray collectionCache = mCollection.attribute<EtebaseCacheAttribute>()->etebaseCache();
EtebaseCollectionPtr etesyncCollection(etebase_collection_manager_cache_load(collectionManager.get(), collectionCache.constData(), collectionCache.size()));
......@@ -59,7 +67,7 @@ void EntriesFetchJob::fetchEntries()
while (!done) {
EtebaseFetchOptionsPtr fetchOptions(etebase_fetch_options_new());
etebase_fetch_options_set_stoken(fetchOptions.get(), sToken);
etebase_fetch_options_set_limit(fetchOptions.get(), 50);
etebase_fetch_options_set_limit(fetchOptions.get(), ITEMS_FETCH_BATCH_SIZE);
EtebaseItemListResponsePtr itemList(etebase_item_manager_list(itemManager.get(), fetchOptions.get()));
if (!itemList) {
......@@ -70,6 +78,7 @@ void EntriesFetchJob::fetchEntries()
}
sToken = QString::fromUtf8(etebase_item_list_response_get_stoken(itemList.get()));
done = etebase_item_list_response_is_done(itemList.get());
uintptr_t dataLength = etebase_item_list_response_get_data_length(itemList.get());
......@@ -91,17 +100,18 @@ void EntriesFetchJob::fetchEntries()
}
}
mCollection.setRemoteRevision(QString::fromUtf8(etebase_collection_get_stoken(etesyncCollection.get())));
mCollection.setRemoteRevision(sToken);
}
void EntriesFetchJob::setupItem(Akonadi::Item &item, const EtebaseItem *etesyncItem, const QString &type)
{
qCDebug(ETESYNC_LOG) << "Setting up item" << etebase_item_get_uid(etesyncItem);
if (!etesyncItem) {
qCDebug(ETESYNC_LOG) << "Unable to setup item - etesyncItem is null";
return;
}
qCDebug(ETESYNC_LOG) << "Setting up item" << etebase_item_get_uid(etesyncItem);
if (type == ETEBASE_COLLECTION_TYPE_ADDRESS_BOOK) {
item.setMimeType(KContacts::Addressee::mimeType());
} else if (type == ETEBASE_COLLECTION_TYPE_CALENDAR) {
......@@ -117,9 +127,9 @@ void EntriesFetchJob::setupItem(Akonadi::Item &item, const EtebaseItem *etesyncI
item.setParentCollection(mCollection);
item.setRemoteId(itemUid);
QByteArray content(2000, '\0');
auto const len = etebase_item_get_content(etesyncItem, content.data(), 2000);
if (len > 2000) {
QByteArray content(ITEM_SIZE_INITIAL_TRY, '\0');
auto const len = etebase_item_get_content(etesyncItem, content.data(), ITEM_SIZE_INITIAL_TRY);
if (len > ITEM_SIZE_INITIAL_TRY) {
QByteArray content(len, '\0');
etebase_item_get_content(etesyncItem, content.data(), len);
item.setPayloadFromData(content);
......@@ -135,11 +145,16 @@ void EntriesFetchJob::setupItem(Akonadi::Item &item, const EtebaseItem *etesyncI
mItems.push_back(item);
}
void EntriesFetchJob::saveItemCache(const EtebaseItemManager *itemManager, const EtebaseItem *etebaseItem, Item &item)
void EntriesFetchJob::saveItemCache(const EtebaseItemManager *itemManager, const EtebaseItem *etesyncItem, Item &item)
{
qCDebug(ETESYNC_LOG) << "Saving cache for item" << etebase_item_get_uid(etebaseItem);
if (!etesyncItem) {
qCDebug(ETESYNC_LOG) << "Unable to save item cache - etesyncItem is null";
return;
}
qCDebug(ETESYNC_LOG) << "Saving cache for item" << etebase_item_get_uid(etesyncItem);
uintptr_t ret_size;
EtebaseCachePtr cache(etebase_item_manager_cache_save(itemManager, etebaseItem, &ret_size));
EtebaseCachePtr cache(etebase_item_manager_cache_save(itemManager, etesyncItem, &ret_size));
QByteArray cacheData((char *)cache.get(), ret_size);
EtebaseCacheAttribute *etebaseCacheAttribute = item.attribute<EtebaseCacheAttribute>(Item::AddIfMissing);
etebaseCacheAttribute->setEtebaseCache(cacheData);
......
......@@ -41,8 +41,8 @@ public:
protected:
void fetchEntries();
void setupItem(Akonadi::Item &item, const EtebaseItem *etebaseItem, const QString &type);
void saveItemCache(const EtebaseItemManager *itemManager, const EtebaseItem *etebaseItem, Akonadi::Item &item);
void setupItem(Akonadi::Item &item, const EtebaseItem *etesyncItem, const QString &type);
void saveItemCache(const EtebaseItemManager *itemManager, const EtebaseItem *etesyncItem, Akonadi::Item &item);
private:
const EtebaseAccount *mAccount = nullptr;
......
......@@ -137,6 +137,9 @@ Collection EteSyncResource::createRootCollection()
rootCollection.setParentCollection(Collection::root());
rootCollection.setRights(Collection::CanCreateCollection);
// Keep collection list stoken preserved
rootCollection.setRemoteRevision(mRootCollection.remoteRevision());
Akonadi::CachePolicy cachePolicy;
cachePolicy.setInheritFromParent(false);
cachePolicy.setSyncOnDemand(false);
......@@ -169,10 +172,10 @@ void EteSyncResource::slotCollectionsRetrieved(KJob *job)
collections.append(qobject_cast<JournalsFetchJob *>(job)->collections());
Collection::List removedCollections = qobject_cast<JournalsFetchJob *>(job)->removedCollections();
mJournalsCacheUpdateTime = QDateTime::currentDateTime();
collectionsRetrievedIncremental(collections, removedCollections);
mJournalsCacheUpdateTime = QDateTime::currentDateTime();
qCDebug(ETESYNC_LOG) << "Collections retrieval done";
}
......@@ -321,9 +324,10 @@ BaseHandler *EteSyncResource::fetchHandlerForCollection(const Akonadi::Collectio
void EteSyncResource::retrieveItems(const Akonadi::Collection &collection)
{
qCDebug(ETESYNC_LOG) << "Retrieving entries for journal" << collection.remoteId();
qCDebug(ETESYNC_LOG) << "Retrieving items for collection" << collection.remoteId();
const int timeSinceLastCacheUpdate = mJournalsCacheUpdateTime.secsTo(QDateTime::currentDateTime());
if (timeSinceLastCacheUpdate <= 30) {
qCDebug(ETESYNC_LOG) << "Retrieve items called immediately after collection fetch";
if (!collection.hasAttribute<EtebaseCacheAttribute>()) {
qCDebug(ETESYNC_LOG) << "No cache for collection" << collection.remoteId();
cancelTask(i18n("No cache for collection '%1'", collection.remoteId()));
......@@ -334,7 +338,9 @@ void EteSyncResource::retrieveItems(const Akonadi::Collection &collection)
EtebaseCollectionPtr etesyncCollection(etebase_collection_manager_cache_load(collectionManager.get(), collectionCache.constData(), collectionCache.size()));
const QString sToken = QString::fromUtf8(etebase_collection_get_stoken(etesyncCollection.get()));
qCDebug(ETESYNC_LOG) << "Comparing" << sToken << "and" << collection.remoteRevision();
if (sToken == collection.remoteRevision()) {
qCDebug(ETESYNC_LOG) << "Already up-to-date: Fetched collection and cached collection have the same stoken";
itemsRetrievalDone();
return;
}
......@@ -363,12 +369,13 @@ void EteSyncResource::slotItemsRetrieved(KJob *job)
Item::List items = qobject_cast<EntriesFetchJob *>(job)->items();
Item::List removedItems = qobject_cast<EntriesFetchJob *>(job)->removedItems();
itemsRetrievedIncremental(items, removedItems);
qCDebug(ETESYNC_LOG) << "Updating collection sync token";
Collection collection = qobject_cast<EntriesFetchJob *>(job)->collection();
qCDebug(ETESYNC_LOG) << "Setting collection" << collection.remoteId() << "'s sync token to" << collection.remoteRevision();
new CollectionModifyJob(collection, this);
itemsRetrievedIncremental(items, removedItems);
qCDebug(ETESYNC_LOG) << "Items retrieval done";
}
......
......@@ -17,6 +17,8 @@
#include "etebasecacheattribute.h"
#include "etesync_debug.h"
#define COLLECTIONS_FETCH_BATCH_SIZE 50
using namespace EteSyncAPI;
using namespace Akonadi;
......@@ -41,14 +43,20 @@ void JournalsFetchJob::start()
void JournalsFetchJob::fetchJournals()
{
QString stoken;
if (!mAccount) {
setError(UserDefinedError);
setErrorText(QStringLiteral("EntriesFetchJob: Etebase account is empty"));
return;
}
mSyncToken = mResourceCollection.remoteRevision();
bool done = 0;
EtebaseCollectionManagerPtr collectionManager(etebase_account_get_collection_manager(mAccount));
while (!done) {
EtebaseFetchOptionsPtr fetchOptions(etebase_fetch_options_new());
etebase_fetch_options_set_stoken(fetchOptions.get(), stoken);
etebase_fetch_options_set_limit(fetchOptions.get(), 30);
etebase_fetch_options_set_stoken(fetchOptions.get(), mSyncToken);
etebase_fetch_options_set_limit(fetchOptions.get(), COLLECTIONS_FETCH_BATCH_SIZE);
EtebaseCollectionListResponsePtr collectionList(etebase_collection_manager_list(collectionManager.get(), fetchOptions.get()));
if (!collectionList) {
......@@ -58,7 +66,7 @@ void JournalsFetchJob::fetchJournals()
return;
}
stoken = QString::fromUtf8(etebase_collection_list_response_get_stoken(collectionList.get()));
mSyncToken = QString::fromUtf8(etebase_collection_list_response_get_stoken(collectionList.get()));
done = etebase_collection_list_response_is_done(collectionList.get());
uintptr_t dataLength = etebase_collection_list_response_get_data_length(collectionList.get());
......@@ -82,7 +90,11 @@ void JournalsFetchJob::fetchJournals()
int removedCollectionsLength = etebase_collection_list_response_get_removed_memberships_length(collectionList.get());
if (removedCollectionsLength) {
const EtebaseRemovedCollection *removedEtesyncCollections[removedCollectionsLength];
etebase_collection_list_response_get_removed_memberships(collectionList.get(), removedEtesyncCollections);
if (etebase_collection_list_response_get_removed_memberships(collectionList.get(), removedEtesyncCollections)) {
setError(int(etesync_get_error_code()));
const char *err = etebase_error_get_message();
setErrorText(QString::fromUtf8(err));
}
for (int i = 0; i < removedCollectionsLength; i++) {
Collection collection;
const QString journalUid = QString::fromUtf8(etebase_removed_collection_get_uid(removedEtesyncCollections[i]));
......@@ -95,12 +107,13 @@ void JournalsFetchJob::fetchJournals()
void JournalsFetchJob::setupCollection(Akonadi::Collection &collection, const EtebaseCollection *etesyncCollection)
{
qCDebug(ETESYNC_LOG) << "Setting up collection" << etebase_collection_get_uid(etesyncCollection);
if (!etesyncCollection) {
qCDebug(ETESYNC_LOG) << "Unable to setup collection - etesyncCollection is null";
return;
}
qCDebug(ETESYNC_LOG) << "Setting up collection" << etebase_collection_get_uid(etesyncCollection);
EtebaseCollectionMetadataPtr metaData(etebase_collection_get_meta(etesyncCollection));
const QString type = QString::fromUtf8(etebase_collection_metadata_get_collection_type(metaData.get()));
......@@ -157,11 +170,16 @@ void JournalsFetchJob::setupCollection(Akonadi::Collection &collection, const Et
mCollections.push_back(collection);
}
void JournalsFetchJob::saveCollectionCache(const EtebaseCollectionManager *collectionManager, const EtebaseCollection *etebaseCollection, Collection &collection)
void JournalsFetchJob::saveCollectionCache(const EtebaseCollectionManager *collectionManager, const EtebaseCollection *etesyncCollection, Collection &collection)
{
qCDebug(ETESYNC_LOG) << "Saving cache for collection" << etebase_collection_get_uid(etebaseCollection);
if (!etesyncCollection) {
qCDebug(ETESYNC_LOG) << "Unable to save collection cache - etesyncCollection is null";
return;
}
qCDebug(ETESYNC_LOG) << "Saving cache for collection" << etebase_collection_get_uid(etesyncCollection);
uintptr_t ret_size;
EtebaseCachePtr cache(etebase_collection_manager_cache_save(collectionManager, etebaseCollection, &ret_size));
EtebaseCachePtr cache(etebase_collection_manager_cache_save(collectionManager, etesyncCollection, &ret_size));
QByteArray cacheData((char *)cache.get(), ret_size);
EtebaseCacheAttribute *etebaseCacheAttribute = collection.attribute<EtebaseCacheAttribute>(Collection::AddIfMissing);
etebaseCacheAttribute->setEtebaseCache(cacheData);
......
......@@ -42,7 +42,7 @@ public:
protected:
void fetchJournals();
void setupCollection(Akonadi::Collection &collection, const EtebaseCollection *etesyncCollection);
void saveCollectionCache(const EtebaseCollectionManager *collectionManager, const EtebaseCollection *etebaseCollection, Akonadi::Collection &collection);
void saveCollectionCache(const EtebaseCollectionManager *collectionManager, const EtebaseCollection *etesyncCollection, Akonadi::Collection &collection);
private:
const EtebaseAccount *mAccount = nullptr;
Akonadi::Collection::List mCollections;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment