8#include "akonadicore_debug.h"
9#include "changerecorderjournal_p.h"
20constexpr quint64 s_currentVersion = Q_UINT64_C(0x000900000000);
21constexpr quint64 s_versionMask = Q_UINT64_C(0xFFFF00000000);
22constexpr quint64 s_sizeMask = Q_UINT64_C(0x0000FFFFFFFF);
27 switch (
static_cast<LegacyType
>(settings->
value(QStringLiteral(
"type")).toInt())) {
29 return loadQSettingsItemNotification(settings);
31 return loadQSettingsCollectionNotification(settings);
36 qWarning() <<
"Unexpected notification type in legacy store";
51 quint64 sizeAndVersion;
52 stream >> sizeAndVersion;
54 const quint64 size = sizeAndVersion & s_sizeMask;
55 const quint64
version = (sizeAndVersion & s_versionMask) >> 32;
57 quint64 startOffset = 0;
59 stream >> startOffset;
64 needsFullSave = startOffset > 0 ||
version == 0;
66 for (quint64 i = 0; i < size && !stream.atEnd(); ++i) {
72 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting. Corrupt file:" << device->
fileName();
76 switch (
static_cast<LegacyType
>(type)) {
78 msg = loadItemNotification(stream, version);
81 msg = loadCollectionNotification(stream, version);
84 msg = loadTagNotification(stream, version);
88 loadRelationNotification(stream, version);
91 qCWarning(AKONADICORE_LOG) <<
"Unknown notification type";
95 if (i < startOffset) {
99 if (msg && msg->isValid()) {
100 msg->setSessionId(sessionId);
113 const quint64 countAndVersion =
static_cast<quint64
>(notifications.
count()) | s_currentVersion;
118 stream << countAndVersion;
119 stream << quint64(0);
123 for (
int i = 0; i < notifications.
count(); ++i) {
129 stream << msg->sessionId();
130 stream << int(mapToLegacyType(msg->type()));
131 switch (msg->type()) {
132 case Protocol::Command::ItemChangeNotification:
133 saveItemNotification(stream, Protocol::cmdCast<Protocol::ItemChangeNotification>(msg));
135 case Protocol::Command::CollectionChangeNotification:
136 saveCollectionNotification(stream, Protocol::cmdCast<Protocol::CollectionChangeNotification>(msg));
138 case Protocol::Command::TagChangeNotification:
139 saveTagNotification(stream, Protocol::cmdCast<Protocol::TagChangeNotification>(msg));
142 qCWarning(AKONADICORE_LOG) <<
"Unexpected type?";
150 auto msg = Protocol::ItemChangeNotificationPtr::create();
151 msg->setSessionId(settings->
value(QStringLiteral(
"sessionId")).toByteArray());
152 msg->setOperation(mapItemOperation(
static_cast<LegacyOp
>(settings->
value(QStringLiteral(
"op")).toInt())));
153 Protocol::FetchItemsResponse item;
154 item.setId(settings->
value(QStringLiteral(
"uid")).toLongLong());
155 item.setRemoteId(settings->
value(QStringLiteral(
"rid")).
toString());
156 item.setMimeType(settings->
value(QStringLiteral(
"mimeType")).
toString());
157 msg->setItems({std::move(item)});
158 msg->addMetadata(
"FETCH_ITEM");
159 msg->setResource(settings->
value(QStringLiteral(
"resource")).toByteArray());
160 msg->setParentCollection(settings->
value(QStringLiteral(
"parentCol")).toLongLong());
161 msg->setParentDestCollection(settings->
value(QStringLiteral(
"parentDestCol")).toLongLong());
164 for (
const QString &entry : list) {
165 itemParts.
insert(entry.toLatin1());
167 msg->setItemParts(itemParts);
173 auto msg = Protocol::CollectionChangeNotificationPtr::create();
174 msg->setSessionId(settings->
value(QStringLiteral(
"sessionId")).toByteArray());
175 msg->setOperation(mapCollectionOperation(
static_cast<LegacyOp
>(settings->
value(QStringLiteral(
"op")).toInt())));
176 Protocol::FetchCollectionsResponse collection;
177 collection.setId(settings->
value(QStringLiteral(
"uid")).toLongLong());
178 collection.setRemoteId(settings->
value(QStringLiteral(
"rid")).
toString());
179 msg->setCollection(std::move(collection));
180 msg->addMetadata(
"FETCH_COLLECTION");
181 msg->setResource(settings->
value(QStringLiteral(
"resource")).toByteArray());
182 msg->setParentCollection(settings->
value(QStringLiteral(
"parentCol")).toLongLong());
183 msg->setParentDestCollection(settings->
value(QStringLiteral(
"parentDestCol")).toLongLong());
186 for (
const QString &entry : list) {
187 changedParts.
insert(entry.toLatin1());
189 msg->setChangedParts(changedParts);
200 qint64 parentCollection;
201 qint64 parentDestCollection;
212 auto msg = Protocol::ItemChangeNotificationPtr::create();
219 stream >> parentCollection;
220 stream >> parentDestCollection;
224 Protocol::FetchItemsResponse item;
226 item.setRemoteId(remoteId);
227 item.setMimeType(mimeType);
229 msg->addMetadata(
"FETCH_ITEM");
230 }
else if (version >= 2) {
243 for (
int j = 0; j < entityCnt; ++j) {
244 Protocol::FetchItemsResponse item;
250 item.setParentId(i64);
252 item.setRemoteId(str);
254 item.setRemoteRevision(str);
260 item.setMimeType(str);
268 for (
int k = 0; k < cnt; ++k) {
269 Protocol::FetchTagsResponse tag;
273 tag.setParentId(i64);
281 tag.setAttributes(babaMap);
286 item.setVirtualReferences(i64v);
288 for (
int k = 0; k < cnt; ++k) {
298 for (
int k = 0; k < cnt; ++k) {
299 Protocol::Ancestor ancestor;
303 ancestor.setRemoteId(str);
305 ancestor.setName(str);
307 ancestor.setAttributes(babaMap);
308 ancestors << ancestor;
310 item.setAncestors(ancestors);
313 for (
int k = 0; k < cnt; ++k) {
314 Protocol::StreamPayloadResponse part;
316 part.setPayloadName(ba);
317 Protocol::PartMetaData metaData;
319 metaData.setName(ba);
321 metaData.setSize(i64);
325 metaData.setStorageType(
static_cast<Protocol::PartMetaData::StorageType
>(i));
326 part.setMetaData(metaData);
331 item.setParts(parts);
333 item.setCachedParts(bav);
337 for (
int j = 0; j < entityCnt; ++j) {
340 stream >> remoteRevision;
343 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting";
346 Protocol::FetchItemsResponse item;
348 item.setRemoteId(remoteId);
349 item.setRemoteRevision(remoteRevision);
350 item.setMimeType(mimeType);
353 msg->addMetadata(
"FETCH_ITEM");
356 stream >> destinationResource;
357 stream >> parentCollection;
358 stream >> parentDestCollection;
360 stream >> addedFlags;
361 stream >> removedFlags;
364 stream >> removedTags;
369 msg->setMustRetrieve(
boolean);
372 qCWarning(AKONADICORE_LOG) <<
"Error version is not correct here" <<
version;
376 msg->setOperation(
static_cast<Protocol::ItemChangeNotification::Operation
>(operation));
378 msg->setOperation(mapItemOperation(
static_cast<LegacyOp
>(operation)));
380 msg->setItems(items);
381 msg->setResource(resource);
382 msg->setDestinationResource(destinationResource);
383 msg->setParentCollection(parentCollection);
384 msg->setParentDestCollection(parentDestCollection);
385 msg->setItemParts(itemParts);
386 msg->setAddedFlags(addedFlags);
387 msg->setRemovedFlags(removedFlags);
388 msg->setAddedTags(addedTags);
389 msg->setRemovedTags(removedTags);
393void ChangeRecorderJournalWriter::saveItemNotification(
QDataStream &stream,
const Protocol::ItemChangeNotification &msg)
397 stream << int(msg.operation());
398 const auto &items = msg.items();
399 stream << static_cast<int>(items.
count());
400 for (
const auto &item : items) {
401 stream << item.id() << item.revision() << item.parentId() << item.remoteId() << item.remoteRevision() << item.gid() << item.size() << item.mimeType()
402 << item.mTime() << item.flags();
403 const auto tags = item.tags();
404 stream << static_cast<int>(tags.
count());
405 for (
const auto &tag : tags) {
406 stream << tag.id() << tag.parentId() << tag.gid() << tag.type() << tag.remoteId() << tag.attributes();
408 stream << item.virtualReferences();
409 const auto ancestors = item.ancestors();
410 stream << static_cast<int>(ancestors.
count());
411 for (
const auto &ancestor : ancestors) {
412 stream << ancestor.id() << ancestor.remoteId() << ancestor.name() << ancestor.attributes();
414 const auto parts = item.parts();
415 stream << static_cast<int>(parts.
count());
416 for (
const auto &part : parts) {
417 const auto metaData = part.metaData();
418 stream << part.payloadName() << metaData.name() << metaData.size() << metaData.
version() <<
static_cast<int>(metaData.storageType()) << part.data();
420 stream << item.cachedParts();
422 stream << msg.resource();
423 stream << msg.destinationResource();
424 stream << quint64(msg.parentCollection());
425 stream << quint64(msg.parentDestCollection());
426 stream << msg.itemParts();
427 stream << msg.addedFlags();
428 stream << msg.removedFlags();
429 stream << msg.addedTags();
430 stream << msg.removedTags();
431 stream << msg.mustRetrieve();
441 quint64 parentCollection;
442 quint64 parentDestCollection;
450 auto msg = Protocol::CollectionChangeNotificationPtr::create();
457 stream >> parentCollection;
458 stream >> parentDestCollection;
459 stream >> dummyString;
460 stream >> changedParts;
462 Protocol::FetchCollectionsResponse collection;
463 collection.setId(uid);
464 collection.setRemoteId(remoteId);
465 msg->setCollection(std::move(collection));
466 msg->addMetadata(
"FETCH_COLLECTION");
467 }
else if (version >= 2) {
479 Protocol::FetchCollectionsResponse collection;
481 collection.setId(uid);
483 collection.setParentId(uid);
485 collection.setName(str);
486 stream >> stringList;
487 collection.setMimeTypes(stringList);
489 collection.setRemoteId(str);
491 collection.setRemoteRevision(str);
493 collection.setResource(str);
495 Protocol::FetchCollectionStatsResponse stats;
499 stats.setUnseen(i64);
502 collection.setStatistics(stats);
505 collection.setSearchQuery(str);
507 collection.setSearchCollections(vb);
510 for (
int j = 0; j < entityCnt; ++j) {
511 Protocol::Ancestor ancestor;
515 ancestor.setRemoteId(str);
517 ancestor.setName(str);
519 ancestor.setAttributes(attrs);
523 qCWarning(AKONADICORE_LOG) <<
"Erorr reading saved notifications! Aborting";
527 collection.setAncestors(ancestors);
529 Protocol::CachePolicy cachePolicy;
531 cachePolicy.setInherit(b);
533 cachePolicy.setCheckInterval(i);
535 cachePolicy.setCacheTimeout(i);
537 cachePolicy.setSyncOnDemand(b);
538 stream >> stringList;
539 cachePolicy.setLocalParts(stringList);
540 collection.setCachePolicy(cachePolicy);
543 collection.setAttributes(attrs);
545 collection.setEnabled(b);
546 stream >>
reinterpret_cast<qint8 &
>(
tristate);
547 collection.setDisplayPref(
tristate);
548 stream >>
reinterpret_cast<qint8 &
>(
tristate);
550 stream >>
reinterpret_cast<qint8 &
>(
tristate);
554 collection.setIsVirtual(b);
556 msg->setCollection(std::move(collection));
558 for (
int j = 0; j < entityCnt; ++j) {
561 stream >> remoteRevision;
562 stream >> dummyString;
564 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting";
567 Protocol::FetchCollectionsResponse collection;
568 collection.setId(uid);
569 collection.setRemoteId(remoteId);
570 collection.setRemoteRevision(remoteRevision);
571 msg->setCollection(std::move(collection));
572 msg->addMetadata(
"FETCH_COLLECTION");
576 stream >> destinationResource;
577 stream >> parentCollection;
578 stream >> parentDestCollection;
579 stream >> changedParts;
587 qCWarning(AKONADICORE_LOG) <<
"Error version is not correct here" <<
version;
592 msg->setOperation(
static_cast<Protocol::CollectionChangeNotification::Operation
>(operation));
594 msg->setOperation(mapCollectionOperation(
static_cast<LegacyOp
>(operation)));
596 msg->setResource(resource);
597 msg->setDestinationResource(destinationResource);
598 msg->setParentCollection(parentCollection);
599 msg->setParentDestCollection(parentDestCollection);
600 msg->setChangedParts(changedParts);
604void Akonadi::ChangeRecorderJournalWriter::saveCollectionNotification(
QDataStream &stream,
const Protocol::CollectionChangeNotification &msg)
608 const auto &col = msg.collection();
610 stream << int(msg.operation());
613 stream << col.parentId();
614 stream << col.name();
615 stream << col.mimeTypes();
616 stream << col.remoteId();
617 stream << col.remoteRevision();
618 stream << col.resource();
619 const auto stats = col.statistics();
620 stream << stats.count();
621 stream << stats.unseen();
622 stream << stats.size();
623 stream << col.searchQuery();
624 stream << col.searchCollections();
625 const auto ancestors = col.ancestors();
626 stream << static_cast<int>(ancestors.
count());
627 for (
const auto &ancestor : ancestors) {
628 stream << ancestor.id() << ancestor.remoteId() << ancestor.name() << ancestor.attributes();
630 const auto cachePolicy = col.cachePolicy();
631 stream << cachePolicy.inherit();
632 stream << cachePolicy.checkInterval();
633 stream << cachePolicy.cacheTimeout();
634 stream << cachePolicy.syncOnDemand();
635 stream << cachePolicy.localParts();
636 stream << col.attributes();
637 stream << col.enabled();
638 stream << static_cast<qint8>(col.displayPref());
639 stream << static_cast<qint8>(col.syncPref());
640 stream << static_cast<qint8>(col.indexPref());
642 stream << col.isVirtual();
644 stream << msg.resource();
645 stream << msg.destinationResource();
646 stream << quint64(msg.parentCollection());
647 stream << quint64(msg.parentDestCollection());
648 stream << msg.changedParts();
649 stream << QSet<QByteArray>();
650 stream << QSet<QByteArray>();
651 stream << QSet<qint64>();
652 stream << QSet<qint64>();
668 auto msg = Protocol::TagChangeNotificationPtr::create();
677 stream >> dummyString;
680 Protocol::FetchTagsResponse tag;
682 tag.setRemoteId(remoteId.toLatin1());
683 msg->setTag(std::move(tag));
684 msg->addMetadata(
"FETCH_TAG");
685 }
else if (version >= 2) {
692 Protocol::FetchTagsResponse tag;
697 tag.setParentId(uid);
705 tag.setAttributes(attrs);
706 msg->setTag(std::move(tag));
710 for (
int j = 0; j < entityCnt; ++j) {
713 stream >> dummyString;
714 stream >> dummyString;
716 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting";
719 Protocol::FetchTagsResponse tag;
721 tag.setRemoteId(remoteId.toLatin1());
722 msg->setTag(std::move(tag));
723 msg->addMetadata(
"FETCH_TAG");
738 msg->setOperation(
static_cast<Protocol::TagChangeNotification::Operation
>(operation));
740 msg->setOperation(mapTagOperation(
static_cast<LegacyOp
>(operation)));
743 msg->setResource(resource);
747void Akonadi::ChangeRecorderJournalWriter::saveTagNotification(
QDataStream &stream,
const Protocol::TagChangeNotification &msg)
749 const auto &tag = msg.tag();
750 stream << int(msg.operation());
753 stream << tag.parentId();
755 stream << tag.type();
756 stream << tag.remoteId();
757 stream << tag.attributes();
758 stream << msg.resource();
776 qCWarning(AKONADICORE_LOG) <<
"Invalid version of relation notification";
778 }
else if (version >= 2) {
789 for (
int j = 0; j < entityCnt; ++j) {
791 stream >> dummyString;
792 stream >> dummyString;
793 stream >> dummyString;
795 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting";
823Protocol::ItemChangeNotification::Operation ChangeRecorderJournalReader::mapItemOperation(LegacyOp op)
827 return Protocol::ItemChangeNotification::Add;
829 return Protocol::ItemChangeNotification::Modify;
831 return Protocol::ItemChangeNotification::Move;
833 return Protocol::ItemChangeNotification::Remove;
835 return Protocol::ItemChangeNotification::Link;
837 return Protocol::ItemChangeNotification::Unlink;
839 return Protocol::ItemChangeNotification::ModifyFlags;
841 return Protocol::ItemChangeNotification::ModifyTags;
842 case ModifyRelations:
845 qWarning() <<
"Unexpected operation type in item notification";
846 return Protocol::ItemChangeNotification::InvalidOp;
850Protocol::CollectionChangeNotification::Operation ChangeRecorderJournalReader::mapCollectionOperation(LegacyOp op)
854 return Protocol::CollectionChangeNotification::Add;
856 return Protocol::CollectionChangeNotification::Modify;
858 return Protocol::CollectionChangeNotification::Move;
860 return Protocol::CollectionChangeNotification::Remove;
862 return Protocol::CollectionChangeNotification::Subscribe;
864 return Protocol::CollectionChangeNotification::Unsubscribe;
866 qCWarning(AKONADICORE_LOG) <<
"Unexpected operation type in collection notification";
867 return Protocol::CollectionChangeNotification::InvalidOp;
871Protocol::TagChangeNotification::Operation ChangeRecorderJournalReader::mapTagOperation(LegacyOp op)
875 return Protocol::TagChangeNotification::Add;
877 return Protocol::TagChangeNotification::Modify;
879 return Protocol::TagChangeNotification::Remove;
881 qCWarning(AKONADICORE_LOG) <<
"Unexpected operation type in tag notification";
882 return Protocol::TagChangeNotification::InvalidOp;
886ChangeRecorderJournalReader::LegacyType ChangeRecorderJournalWriter::mapToLegacyType(Protocol::Command::Type type)
889 case Protocol::Command::ItemChangeNotification:
890 return ChangeRecorderJournalReader::Item;
891 case Protocol::Command::CollectionChangeNotification:
892 return ChangeRecorderJournalReader::Collection;
893 case Protocol::Command::TagChangeNotification:
894 return ChangeRecorderJournalReader::Tag;
896 qCWarning(AKONADICORE_LOG) <<
"Unexpected notification type";
897 return ChangeRecorderJournalReader::InvalidType;
Represents a collection of PIM items.
Helper integration between Akonadi and Qt.
char * toString(const EngineQuery &query)
KCALUTILS_EXPORT QString mimeType()
KDB_EXPORT KDbVersionInfo version()
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
Status status() const const
int version() const const
virtual QString fileName() const const override
const_reference at(qsizetype i) const const
qsizetype count() const const
void push_back(parameter_type value)
void reserve(qsizetype size)
iterator insert(const T &value)
QVariant value(QAnyStringView key) const const
QStringList toStringList() const const