8#include "akonadicore_debug.h"
9#include "changerecorderjournal_p.h"
10#include "protocol_p.h"
21constexpr quint64 s_currentVersion = Q_UINT64_C(0x000A00000000);
22constexpr quint64 s_versionMask = Q_UINT64_C(0xFFFF00000000);
23constexpr quint64 s_sizeMask = Q_UINT64_C(0x0000FFFFFFFF);
28 switch (
static_cast<LegacyType
>(settings->
value(QStringLiteral(
"type")).toInt())) {
30 return loadQSettingsItemNotification(settings);
32 return loadQSettingsCollectionNotification(settings);
37 qWarning() <<
"Unexpected notification type in legacy store";
52 quint64 sizeAndVersion;
53 stream >> sizeAndVersion;
55 const quint64 size = sizeAndVersion & s_sizeMask;
56 const quint64
version = (sizeAndVersion & s_versionMask) >> 32;
58 quint64 startOffset = 0;
60 stream >> startOffset;
65 needsFullSave = startOffset > 0 ||
version == 0;
67 for (quint64 i = 0; i < size && !stream.atEnd(); ++i) {
73 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting. Corrupt file:" << device->
fileName();
77 switch (
static_cast<LegacyType
>(type)) {
79 msg = loadItemNotification(stream, version);
82 msg = loadCollectionNotification(stream, version);
85 msg = loadTagNotification(stream, version);
89 loadRelationNotification(stream, version);
92 qCWarning(AKONADICORE_LOG) <<
"Unknown notification type";
96 if (i < startOffset) {
100 if (msg && msg->isValid()) {
101 msg->setSessionId(sessionId);
114 const quint64 countAndVersion =
static_cast<quint64
>(notifications.
count()) | s_currentVersion;
119 stream << countAndVersion;
120 stream << quint64(0);
124 for (
int i = 0; i < notifications.
count(); ++i) {
130 stream << msg->sessionId();
131 stream << int(mapToLegacyType(msg->type()));
132 switch (msg->type()) {
133 case Protocol::Command::ItemChangeNotification:
134 saveItemNotification(stream, Protocol::cmdCast<Protocol::ItemChangeNotification>(msg));
136 case Protocol::Command::CollectionChangeNotification:
137 saveCollectionNotification(stream, Protocol::cmdCast<Protocol::CollectionChangeNotification>(msg));
139 case Protocol::Command::TagChangeNotification:
140 saveTagNotification(stream, Protocol::cmdCast<Protocol::TagChangeNotification>(msg));
143 qCWarning(AKONADICORE_LOG) <<
"Unexpected type?";
151 auto msg = Protocol::ItemChangeNotificationPtr::create();
152 msg->setSessionId(settings->
value(QStringLiteral(
"sessionId")).toByteArray());
153 msg->setOperation(mapItemOperation(
static_cast<LegacyOp
>(settings->
value(QStringLiteral(
"op")).toInt())));
154 Protocol::FetchItemsResponse item;
155 item.setId(settings->
value(QStringLiteral(
"uid")).toLongLong());
156 item.setRemoteId(settings->
value(QStringLiteral(
"rid")).
toString());
157 item.setMimeType(settings->
value(QStringLiteral(
"mimeType")).
toString());
158 msg->setItems({std::move(item)});
159 msg->addMetadata(
"FETCH_ITEM");
160 msg->setResource(settings->
value(QStringLiteral(
"resource")).toByteArray());
161 msg->setParentCollection(settings->
value(QStringLiteral(
"parentCol")).toLongLong());
162 msg->setParentDestCollection(settings->
value(QStringLiteral(
"parentDestCol")).toLongLong());
165 for (
const QString &entry : list) {
166 itemParts.
insert(entry.toLatin1());
168 msg->setItemParts(itemParts);
174 auto msg = Protocol::CollectionChangeNotificationPtr::create();
175 msg->setSessionId(settings->
value(QStringLiteral(
"sessionId")).toByteArray());
176 msg->setOperation(mapCollectionOperation(
static_cast<LegacyOp
>(settings->
value(QStringLiteral(
"op")).toInt())));
177 Protocol::FetchCollectionsResponse collection;
178 collection.setId(settings->
value(QStringLiteral(
"uid")).toLongLong());
179 collection.setRemoteId(settings->
value(QStringLiteral(
"rid")).
toString());
180 msg->setCollection(std::move(collection));
181 msg->addMetadata(
"FETCH_COLLECTION");
182 msg->setResource(settings->
value(QStringLiteral(
"resource")).toByteArray());
183 msg->setParentCollection(settings->
value(QStringLiteral(
"parentCol")).toLongLong());
184 msg->setParentDestCollection(settings->
value(QStringLiteral(
"parentDestCol")).toLongLong());
187 for (
const QString &entry : list) {
188 changedParts.
insert(entry.toLatin1());
190 msg->setChangedParts(changedParts);
199 for (
int i = 0; i < cnt; ++i) {
206 stream >>
id >> parentId >> gid >>
type >> remoteId >> attributes;
207 Protocol::FetchTagsResponse tag;
209 tag.setParentId(parentId);
212 tag.setRemoteId(remoteId);
213 tag.setAttributes(attributes);
226 qint64 parentCollection;
227 qint64 parentDestCollection;
238 auto msg = Protocol::ItemChangeNotificationPtr::create();
245 stream >> parentCollection;
246 stream >> parentDestCollection;
250 Protocol::FetchItemsResponse item;
252 item.setRemoteId(remoteId);
253 item.setMimeType(mimeType);
255 msg->addMetadata(
"FETCH_ITEM");
256 }
else if (version >= 2) {
269 for (
int j = 0; j < entityCnt; ++j) {
270 Protocol::FetchItemsResponse item;
276 item.setParentId(i64);
278 item.setRemoteId(str);
280 item.setRemoteRevision(str);
286 item.setMimeType(str);
292 item.setTags(loadTags(stream));
294 item.setVirtualReferences(i64v);
296 for (
int k = 0; k < cnt; ++k) {
306 for (
int k = 0; k < cnt; ++k) {
307 Protocol::Ancestor ancestor;
311 ancestor.setRemoteId(str);
313 ancestor.setName(str);
315 ancestor.setAttributes(babaMap);
316 ancestors << ancestor;
318 item.setAncestors(ancestors);
321 for (
int k = 0; k < cnt; ++k) {
322 Protocol::StreamPayloadResponse part;
324 part.setPayloadName(ba);
325 Protocol::PartMetaData metaData;
327 metaData.setName(ba);
329 metaData.setSize(i64);
333 metaData.setStorageType(
static_cast<Protocol::PartMetaData::StorageType
>(i));
334 part.setMetaData(metaData);
339 item.setParts(parts);
341 item.setCachedParts(bav);
345 for (
int j = 0; j < entityCnt; ++j) {
348 stream >> remoteRevision;
351 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting";
354 Protocol::FetchItemsResponse item;
356 item.setRemoteId(remoteId);
357 item.setRemoteRevision(remoteRevision);
358 item.setMimeType(mimeType);
361 msg->addMetadata(
"FETCH_ITEM");
364 stream >> destinationResource;
365 stream >> parentCollection;
366 stream >> parentDestCollection;
368 stream >> addedFlags;
369 stream >> removedFlags;
370 if (version >= 0xA) {
371 addedTags = loadTags(stream);
372 removedTags = loadTags(stream);
373 }
else if (version >= 3) {
376 for (
const auto &tagId : tagIds) {
381 for (
const auto &tagId : tagIds) {
388 msg->setMustRetrieve(
boolean);
391 qCWarning(AKONADICORE_LOG) <<
"Error version is not correct here" <<
version;
395 msg->setOperation(
static_cast<Protocol::ItemChangeNotification::Operation
>(operation));
397 msg->setOperation(mapItemOperation(
static_cast<LegacyOp
>(operation)));
399 msg->setItems(items);
400 msg->setResource(resource);
401 msg->setDestinationResource(destinationResource);
402 msg->setParentCollection(parentCollection);
403 msg->setParentDestCollection(parentDestCollection);
404 msg->setItemParts(itemParts);
405 msg->setAddedFlags(addedFlags);
406 msg->setRemovedFlags(removedFlags);
407 msg->setAddedTags(addedTags);
408 msg->setRemovedTags(removedTags);
414 stream << static_cast<int>(tags.
count());
415 for (
const auto &tag : tags) {
416 stream << tag.id() << tag.parentId() << tag.gid() << tag.type() << tag.remoteId() << tag.attributes();
420void ChangeRecorderJournalWriter::saveItemNotification(
QDataStream &stream,
const Protocol::ItemChangeNotification &msg)
424 stream << int(msg.operation());
425 const auto &items = msg.items();
426 stream << static_cast<int>(items.
count());
427 for (
const auto &item : items) {
428 stream << item.id() << item.revision() << item.parentId() << item.remoteId() << item.remoteRevision() << item.gid() << item.size() << item.mimeType()
429 << item.mTime() << item.flags();
430 saveTags(stream, item.tags());
431 stream << item.virtualReferences();
432 const auto ancestors = item.ancestors();
433 stream << static_cast<int>(ancestors.
count());
434 for (
const auto &ancestor : ancestors) {
435 stream << ancestor.id() << ancestor.remoteId() << ancestor.name() << ancestor.attributes();
437 const auto parts = item.parts();
438 stream << static_cast<int>(parts.
count());
439 for (
const auto &part : parts) {
440 const auto metaData = part.metaData();
441 stream << part.payloadName() << metaData.name() << metaData.size() << metaData.
version() <<
static_cast<int>(metaData.storageType()) << part.data();
443 stream << item.cachedParts();
445 stream << msg.resource();
446 stream << msg.destinationResource();
447 stream << quint64(msg.parentCollection());
448 stream << quint64(msg.parentDestCollection());
449 stream << msg.itemParts();
450 stream << msg.addedFlags();
451 stream << msg.removedFlags();
452 saveTags(stream, msg.addedTags());
453 saveTags(stream, msg.removedTags());
454 stream << msg.mustRetrieve();
464 quint64 parentCollection;
465 quint64 parentDestCollection;
473 auto msg = Protocol::CollectionChangeNotificationPtr::create();
480 stream >> parentCollection;
481 stream >> parentDestCollection;
482 stream >> dummyString;
483 stream >> changedParts;
485 Protocol::FetchCollectionsResponse collection;
486 collection.setId(uid);
487 collection.setRemoteId(remoteId);
488 msg->setCollection(std::move(collection));
489 msg->addMetadata(
"FETCH_COLLECTION");
490 }
else if (version >= 2) {
502 Protocol::FetchCollectionsResponse collection;
504 collection.setId(uid);
506 collection.setParentId(uid);
508 collection.setName(str);
509 stream >> stringList;
510 collection.setMimeTypes(stringList);
512 collection.setRemoteId(str);
514 collection.setRemoteRevision(str);
516 collection.setResource(str);
518 Protocol::FetchCollectionStatsResponse stats;
522 stats.setUnseen(i64);
525 collection.setStatistics(stats);
528 collection.setSearchQuery(str);
530 collection.setSearchCollections(vb);
533 for (
int j = 0; j < entityCnt; ++j) {
534 Protocol::Ancestor ancestor;
538 ancestor.setRemoteId(str);
540 ancestor.setName(str);
542 ancestor.setAttributes(attrs);
546 qCWarning(AKONADICORE_LOG) <<
"Erorr reading saved notifications! Aborting";
550 collection.setAncestors(ancestors);
552 Protocol::CachePolicy cachePolicy;
554 cachePolicy.setInherit(b);
556 cachePolicy.setCheckInterval(i);
558 cachePolicy.setCacheTimeout(i);
560 cachePolicy.setSyncOnDemand(b);
561 stream >> stringList;
562 cachePolicy.setLocalParts(stringList);
563 collection.setCachePolicy(cachePolicy);
566 collection.setAttributes(attrs);
568 collection.setEnabled(b);
569 stream >>
reinterpret_cast<qint8 &
>(
tristate);
570 collection.setDisplayPref(
tristate);
571 stream >>
reinterpret_cast<qint8 &
>(
tristate);
573 stream >>
reinterpret_cast<qint8 &
>(
tristate);
577 collection.setIsVirtual(b);
579 msg->setCollection(std::move(collection));
581 for (
int j = 0; j < entityCnt; ++j) {
584 stream >> remoteRevision;
585 stream >> dummyString;
587 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting";
590 Protocol::FetchCollectionsResponse collection;
591 collection.setId(uid);
592 collection.setRemoteId(remoteId);
593 collection.setRemoteRevision(remoteRevision);
594 msg->setCollection(std::move(collection));
595 msg->addMetadata(
"FETCH_COLLECTION");
599 stream >> destinationResource;
600 stream >> parentCollection;
601 stream >> parentDestCollection;
602 stream >> changedParts;
610 qCWarning(AKONADICORE_LOG) <<
"Error version is not correct here" <<
version;
615 msg->setOperation(
static_cast<Protocol::CollectionChangeNotification::Operation
>(operation));
617 msg->setOperation(mapCollectionOperation(
static_cast<LegacyOp
>(operation)));
619 msg->setResource(resource);
620 msg->setDestinationResource(destinationResource);
621 msg->setParentCollection(parentCollection);
622 msg->setParentDestCollection(parentDestCollection);
623 msg->setChangedParts(changedParts);
627void Akonadi::ChangeRecorderJournalWriter::saveCollectionNotification(
QDataStream &stream,
const Protocol::CollectionChangeNotification &msg)
631 const auto &col = msg.collection();
633 stream << int(msg.operation());
636 stream << col.parentId();
637 stream << col.name();
638 stream << col.mimeTypes();
639 stream << col.remoteId();
640 stream << col.remoteRevision();
641 stream << col.resource();
642 const auto stats = col.statistics();
643 stream << stats.count();
644 stream << stats.unseen();
645 stream << stats.size();
646 stream << col.searchQuery();
647 stream << col.searchCollections();
648 const auto ancestors = col.ancestors();
649 stream << static_cast<int>(ancestors.
count());
650 for (
const auto &ancestor : ancestors) {
651 stream << ancestor.id() << ancestor.remoteId() << ancestor.name() << ancestor.attributes();
653 const auto cachePolicy = col.cachePolicy();
654 stream << cachePolicy.inherit();
655 stream << cachePolicy.checkInterval();
656 stream << cachePolicy.cacheTimeout();
657 stream << cachePolicy.syncOnDemand();
658 stream << cachePolicy.localParts();
659 stream << col.attributes();
660 stream << col.enabled();
661 stream << static_cast<qint8>(col.displayPref());
662 stream << static_cast<qint8>(col.syncPref());
663 stream << static_cast<qint8>(col.indexPref());
665 stream << col.isVirtual();
667 stream << msg.resource();
668 stream << msg.destinationResource();
669 stream << quint64(msg.parentCollection());
670 stream << quint64(msg.parentDestCollection());
671 stream << msg.changedParts();
672 stream << QSet<QByteArray>();
673 stream << QSet<QByteArray>();
674 stream << QSet<qint64>();
675 stream << QSet<qint64>();
691 auto msg = Protocol::TagChangeNotificationPtr::create();
700 stream >> dummyString;
703 Protocol::FetchTagsResponse tag;
705 tag.setRemoteId(remoteId.toLatin1());
706 msg->setTag(std::move(tag));
707 msg->addMetadata(
"FETCH_TAG");
708 }
else if (version >= 2) {
715 Protocol::FetchTagsResponse tag;
720 tag.setParentId(uid);
728 tag.setAttributes(attrs);
729 msg->setTag(std::move(tag));
733 for (
int j = 0; j < entityCnt; ++j) {
736 stream >> dummyString;
737 stream >> dummyString;
739 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting";
742 Protocol::FetchTagsResponse tag;
744 tag.setRemoteId(remoteId.toLatin1());
745 msg->setTag(std::move(tag));
746 msg->addMetadata(
"FETCH_TAG");
761 msg->setOperation(
static_cast<Protocol::TagChangeNotification::Operation
>(operation));
763 msg->setOperation(mapTagOperation(
static_cast<LegacyOp
>(operation)));
766 msg->setResource(resource);
770void Akonadi::ChangeRecorderJournalWriter::saveTagNotification(
QDataStream &stream,
const Protocol::TagChangeNotification &msg)
772 const auto &tag = msg.tag();
773 stream << int(msg.operation());
776 stream << tag.parentId();
778 stream << tag.type();
779 stream << tag.remoteId();
780 stream << tag.attributes();
781 stream << msg.resource();
799 qCWarning(AKONADICORE_LOG) <<
"Invalid version of relation notification";
801 }
else if (version >= 2) {
812 for (
int j = 0; j < entityCnt; ++j) {
814 stream >> dummyString;
815 stream >> dummyString;
816 stream >> dummyString;
818 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting";
846Protocol::ItemChangeNotification::Operation ChangeRecorderJournalReader::mapItemOperation(LegacyOp op)
850 return Protocol::ItemChangeNotification::Add;
852 return Protocol::ItemChangeNotification::Modify;
854 return Protocol::ItemChangeNotification::Move;
856 return Protocol::ItemChangeNotification::Remove;
858 return Protocol::ItemChangeNotification::Link;
860 return Protocol::ItemChangeNotification::Unlink;
862 return Protocol::ItemChangeNotification::ModifyFlags;
864 return Protocol::ItemChangeNotification::ModifyTags;
865 case ModifyRelations:
868 qWarning() <<
"Unexpected operation type in item notification";
869 return Protocol::ItemChangeNotification::InvalidOp;
873Protocol::CollectionChangeNotification::Operation ChangeRecorderJournalReader::mapCollectionOperation(LegacyOp op)
877 return Protocol::CollectionChangeNotification::Add;
879 return Protocol::CollectionChangeNotification::Modify;
881 return Protocol::CollectionChangeNotification::Move;
883 return Protocol::CollectionChangeNotification::Remove;
885 return Protocol::CollectionChangeNotification::Subscribe;
887 return Protocol::CollectionChangeNotification::Unsubscribe;
889 qCWarning(AKONADICORE_LOG) <<
"Unexpected operation type in collection notification";
890 return Protocol::CollectionChangeNotification::InvalidOp;
894Protocol::TagChangeNotification::Operation ChangeRecorderJournalReader::mapTagOperation(LegacyOp op)
898 return Protocol::TagChangeNotification::Add;
900 return Protocol::TagChangeNotification::Modify;
902 return Protocol::TagChangeNotification::Remove;
904 qCWarning(AKONADICORE_LOG) <<
"Unexpected operation type in tag notification";
905 return Protocol::TagChangeNotification::InvalidOp;
909ChangeRecorderJournalReader::LegacyType ChangeRecorderJournalWriter::mapToLegacyType(Protocol::Command::Type type)
912 case Protocol::Command::ItemChangeNotification:
913 return ChangeRecorderJournalReader::Item;
914 case Protocol::Command::CollectionChangeNotification:
915 return ChangeRecorderJournalReader::Collection;
916 case Protocol::Command::TagChangeNotification:
917 return ChangeRecorderJournalReader::Tag;
919 qCWarning(AKONADICORE_LOG) <<
"Unexpected notification type";
920 return ChangeRecorderJournalReader::InvalidType;
Represents a collection of PIM items.
Helper integration between Akonadi and Qt.
char * toString(const EngineQuery &query)
KCALUTILS_EXPORT QString mimeType()
KCOREADDONS_EXPORT unsigned int 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
reference emplace_back(Args &&... args)
void push_back(parameter_type value)
iterator insert(const T &value)
QVariant value(QAnyStringView key) const const
QStringList toStringList() const const