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);
26Protocol::ChangeNotificationPtr ChangeRecorderJournalReader::loadQSettingsNotification(
QSettings *settings)
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) {
68 Protocol::ChangeNotificationPtr msg;
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) {
125 const Protocol::ChangeNotificationPtr &msg = notifications.
at(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?";
149Protocol::ChangeNotificationPtr ChangeRecorderJournalReader::loadQSettingsItemNotification(
QSettings *settings)
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);
172Protocol::ChangeNotificationPtr ChangeRecorderJournalReader::loadQSettingsCollectionNotification(
QSettings *settings)
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);
200 for (
int i = 0; i < cnt; ++i) {
207 stream >>
id >> parentId >> gid >>
type >> remoteId >> attributes;
208 Protocol::FetchTagsResponse tag;
210 tag.setParentId(parentId);
213 tag.setRemoteId(remoteId);
214 tag.setAttributes(attributes);
220Protocol::ChangeNotificationPtr ChangeRecorderJournalReader::loadItemNotification(
QDataStream &stream, quint64 version)
227 qint64 parentCollection;
228 qint64 parentDestCollection;
239 auto msg = Protocol::ItemChangeNotificationPtr::create();
246 stream >> parentCollection;
247 stream >> parentDestCollection;
251 Protocol::FetchItemsResponse item;
253 item.setRemoteId(remoteId);
254 item.setMimeType(mimeType);
256 msg->addMetadata(
"FETCH_ITEM");
257 }
else if (version >= 2) {
270 for (
int j = 0; j < entityCnt; ++j) {
271 Protocol::FetchItemsResponse item;
277 item.setParentId(i64);
279 item.setRemoteId(str);
281 item.setRemoteRevision(str);
287 item.setMimeType(str);
293 item.setTags(loadTags(stream));
295 item.setVirtualReferences(i64v);
297 for (
int k = 0; k < cnt; ++k) {
307 for (
int k = 0; k < cnt; ++k) {
308 Protocol::Ancestor ancestor;
312 ancestor.setRemoteId(str);
314 ancestor.setName(str);
316 ancestor.setAttributes(babaMap);
317 ancestors << ancestor;
319 item.setAncestors(ancestors);
322 for (
int k = 0; k < cnt; ++k) {
323 Protocol::StreamPayloadResponse part;
325 part.setPayloadName(ba);
326 Protocol::PartMetaData metaData;
328 metaData.setName(ba);
330 metaData.setSize(i64);
334 metaData.setStorageType(
static_cast<Protocol::PartMetaData::StorageType
>(i));
335 part.setMetaData(metaData);
340 item.setParts(parts);
342 item.setCachedParts(bav);
346 for (
int j = 0; j < entityCnt; ++j) {
349 stream >> remoteRevision;
352 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting";
355 Protocol::FetchItemsResponse item;
357 item.setRemoteId(remoteId);
358 item.setRemoteRevision(remoteRevision);
359 item.setMimeType(mimeType);
362 msg->addMetadata(
"FETCH_ITEM");
365 stream >> destinationResource;
366 stream >> parentCollection;
367 stream >> parentDestCollection;
369 stream >> addedFlags;
370 stream >> removedFlags;
371 if (version >= 0xA) {
372 addedTags = loadTags(stream);
373 removedTags = loadTags(stream);
374 }
else if (version >= 3) {
377 for (
const auto &tagId : tagIds) {
382 for (
const auto &tagId : tagIds) {
389 msg->setMustRetrieve(
boolean);
392 qCWarning(AKONADICORE_LOG) <<
"Error version is not correct here" <<
version;
396 msg->setOperation(
static_cast<Protocol::ItemChangeNotification::Operation
>(operation));
398 msg->setOperation(mapItemOperation(
static_cast<LegacyOp
>(operation)));
400 msg->setItems(items);
401 msg->setResource(resource);
402 msg->setDestinationResource(destinationResource);
403 msg->setParentCollection(parentCollection);
404 msg->setParentDestCollection(parentDestCollection);
405 msg->setItemParts(itemParts);
406 msg->setAddedFlags(addedFlags);
407 msg->setRemovedFlags(removedFlags);
408 msg->setAddedTags(addedTags);
409 msg->setRemovedTags(removedTags);
415 stream << static_cast<int>(tags.
count());
416 for (
const auto &tag : tags) {
417 stream << tag.id() << tag.parentId() << tag.gid() << tag.type() << tag.remoteId() << tag.attributes();
421void ChangeRecorderJournalWriter::saveItemNotification(
QDataStream &stream,
const Protocol::ItemChangeNotification &msg)
425 stream << int(msg.operation());
426 const auto &items = msg.items();
427 stream << static_cast<int>(items.
count());
428 for (
const auto &item : items) {
429 stream << item.id() << item.revision() << item.parentId() << item.remoteId() << item.remoteRevision() << item.gid() << item.size() << item.mimeType()
430 << item.mTime() << item.flags();
431 saveTags(stream, item.tags());
432 stream << item.virtualReferences();
433 const auto ancestors = item.ancestors();
434 stream << static_cast<int>(ancestors.
count());
435 for (
const auto &ancestor : ancestors) {
436 stream << ancestor.id() << ancestor.remoteId() << ancestor.name() << ancestor.attributes();
438 const auto parts = item.parts();
439 stream << static_cast<int>(parts.
count());
440 for (
const auto &part : parts) {
441 const auto metaData = part.metaData();
442 stream << part.payloadName() << metaData.name() << metaData.size() << metaData.
version() <<
static_cast<int>(metaData.storageType()) << part.data();
444 stream << item.cachedParts();
446 stream << msg.resource();
447 stream << msg.destinationResource();
448 stream << quint64(msg.parentCollection());
449 stream << quint64(msg.parentDestCollection());
450 stream << msg.itemParts();
451 stream << msg.addedFlags();
452 stream << msg.removedFlags();
453 saveTags(stream, msg.addedTags());
454 saveTags(stream, msg.removedTags());
455 stream << msg.mustRetrieve();
458Protocol::ChangeNotificationPtr ChangeRecorderJournalReader::loadCollectionNotification(
QDataStream &stream, quint64 version)
465 quint64 parentCollection;
466 quint64 parentDestCollection;
474 auto msg = Protocol::CollectionChangeNotificationPtr::create();
481 stream >> parentCollection;
482 stream >> parentDestCollection;
483 stream >> dummyString;
484 stream >> changedParts;
486 Protocol::FetchCollectionsResponse collection;
487 collection.setId(uid);
488 collection.setRemoteId(remoteId);
489 msg->setCollection(std::move(collection));
490 msg->addMetadata(
"FETCH_COLLECTION");
491 }
else if (version >= 2) {
503 Protocol::FetchCollectionsResponse collection;
505 collection.setId(uid);
507 collection.setParentId(uid);
509 collection.setName(str);
510 stream >> stringList;
511 collection.setMimeTypes(stringList);
513 collection.setRemoteId(str);
515 collection.setRemoteRevision(str);
517 collection.setResource(str);
519 Protocol::FetchCollectionStatsResponse stats;
523 stats.setUnseen(i64);
526 collection.setStatistics(stats);
529 collection.setSearchQuery(str);
531 collection.setSearchCollections(vb);
534 for (
int j = 0; j < entityCnt; ++j) {
535 Protocol::Ancestor ancestor;
539 ancestor.setRemoteId(str);
541 ancestor.setName(str);
543 ancestor.setAttributes(attrs);
547 qCWarning(AKONADICORE_LOG) <<
"Erorr reading saved notifications! Aborting";
551 collection.setAncestors(ancestors);
553 Protocol::CachePolicy cachePolicy;
555 cachePolicy.setInherit(b);
557 cachePolicy.setCheckInterval(i);
559 cachePolicy.setCacheTimeout(i);
561 cachePolicy.setSyncOnDemand(b);
562 stream >> stringList;
563 cachePolicy.setLocalParts(stringList);
564 collection.setCachePolicy(cachePolicy);
567 collection.setAttributes(attrs);
569 collection.setEnabled(b);
570 stream >>
reinterpret_cast<qint8 &
>(
tristate);
571 collection.setDisplayPref(
tristate);
572 stream >>
reinterpret_cast<qint8 &
>(
tristate);
574 stream >>
reinterpret_cast<qint8 &
>(
tristate);
578 collection.setIsVirtual(b);
580 msg->setCollection(std::move(collection));
582 for (
int j = 0; j < entityCnt; ++j) {
585 stream >> remoteRevision;
586 stream >> dummyString;
588 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting";
591 Protocol::FetchCollectionsResponse collection;
592 collection.setId(uid);
593 collection.setRemoteId(remoteId);
594 collection.setRemoteRevision(remoteRevision);
595 msg->setCollection(std::move(collection));
596 msg->addMetadata(
"FETCH_COLLECTION");
600 stream >> destinationResource;
601 stream >> parentCollection;
602 stream >> parentDestCollection;
603 stream >> changedParts;
611 qCWarning(AKONADICORE_LOG) <<
"Error version is not correct here" <<
version;
616 msg->setOperation(
static_cast<Protocol::CollectionChangeNotification::Operation
>(operation));
618 msg->setOperation(mapCollectionOperation(
static_cast<LegacyOp
>(operation)));
620 msg->setResource(resource);
621 msg->setDestinationResource(destinationResource);
622 msg->setParentCollection(parentCollection);
623 msg->setParentDestCollection(parentDestCollection);
624 msg->setChangedParts(changedParts);
628void Akonadi::ChangeRecorderJournalWriter::saveCollectionNotification(
QDataStream &stream,
const Protocol::CollectionChangeNotification &msg)
632 const auto &col = msg.collection();
634 stream << int(msg.operation());
637 stream << col.parentId();
638 stream << col.name();
639 stream << col.mimeTypes();
640 stream << col.remoteId();
641 stream << col.remoteRevision();
642 stream << col.resource();
643 const auto stats = col.statistics();
644 stream << stats.count();
645 stream << stats.unseen();
646 stream << stats.size();
647 stream << col.searchQuery();
648 stream << col.searchCollections();
649 const auto ancestors = col.ancestors();
650 stream << static_cast<int>(ancestors.
count());
651 for (
const auto &ancestor : ancestors) {
652 stream << ancestor.id() << ancestor.remoteId() << ancestor.name() << ancestor.attributes();
654 const auto cachePolicy = col.cachePolicy();
655 stream << cachePolicy.inherit();
656 stream << cachePolicy.checkInterval();
657 stream << cachePolicy.cacheTimeout();
658 stream << cachePolicy.syncOnDemand();
659 stream << cachePolicy.localParts();
660 stream << col.attributes();
661 stream << col.enabled();
662 stream << static_cast<qint8>(col.displayPref());
663 stream << static_cast<qint8>(col.syncPref());
664 stream << static_cast<qint8>(col.indexPref());
666 stream << col.isVirtual();
668 stream << msg.resource();
669 stream << msg.destinationResource();
670 stream << quint64(msg.parentCollection());
671 stream << quint64(msg.parentDestCollection());
672 stream << msg.changedParts();
673 stream << QSet<QByteArray>();
674 stream << QSet<QByteArray>();
675 stream << QSet<qint64>();
676 stream << QSet<qint64>();
679Protocol::ChangeNotificationPtr ChangeRecorderJournalReader::loadTagNotification(
QDataStream &stream, quint64 version)
692 auto msg = Protocol::TagChangeNotificationPtr::create();
701 stream >> dummyString;
704 Protocol::FetchTagsResponse tag;
706 tag.setRemoteId(remoteId.toLatin1());
707 msg->setTag(std::move(tag));
708 msg->addMetadata(
"FETCH_TAG");
709 }
else if (version >= 2) {
716 Protocol::FetchTagsResponse tag;
721 tag.setParentId(uid);
729 tag.setAttributes(attrs);
730 msg->setTag(std::move(tag));
734 for (
int j = 0; j < entityCnt; ++j) {
737 stream >> dummyString;
738 stream >> dummyString;
740 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting";
743 Protocol::FetchTagsResponse tag;
745 tag.setRemoteId(remoteId.toLatin1());
746 msg->setTag(std::move(tag));
747 msg->addMetadata(
"FETCH_TAG");
762 msg->setOperation(
static_cast<Protocol::TagChangeNotification::Operation
>(operation));
764 msg->setOperation(mapTagOperation(
static_cast<LegacyOp
>(operation)));
767 msg->setResource(resource);
771void Akonadi::ChangeRecorderJournalWriter::saveTagNotification(
QDataStream &stream,
const Protocol::TagChangeNotification &msg)
773 const auto &tag = msg.tag();
774 stream << int(msg.operation());
777 stream << tag.parentId();
779 stream << tag.type();
780 stream << tag.remoteId();
781 stream << tag.attributes();
782 stream << msg.resource();
785Protocol::ChangeNotificationPtr ChangeRecorderJournalReader::loadRelationNotification(
QDataStream &stream, quint64 version)
800 qCWarning(AKONADICORE_LOG) <<
"Invalid version of relation notification";
802 }
else if (version >= 2) {
813 for (
int j = 0; j < entityCnt; ++j) {
815 stream >> dummyString;
816 stream >> dummyString;
817 stream >> dummyString;
819 qCWarning(AKONADICORE_LOG) <<
"Error reading saved notifications! Aborting";
847Protocol::ItemChangeNotification::Operation ChangeRecorderJournalReader::mapItemOperation(LegacyOp op)
851 return Protocol::ItemChangeNotification::Add;
853 return Protocol::ItemChangeNotification::Modify;
855 return Protocol::ItemChangeNotification::Move;
857 return Protocol::ItemChangeNotification::Remove;
859 return Protocol::ItemChangeNotification::Link;
861 return Protocol::ItemChangeNotification::Unlink;
863 return Protocol::ItemChangeNotification::ModifyFlags;
865 return Protocol::ItemChangeNotification::ModifyTags;
866 case ModifyRelations:
869 qWarning() <<
"Unexpected operation type in item notification";
870 return Protocol::ItemChangeNotification::InvalidOp;
874Protocol::CollectionChangeNotification::Operation ChangeRecorderJournalReader::mapCollectionOperation(LegacyOp op)
878 return Protocol::CollectionChangeNotification::Add;
880 return Protocol::CollectionChangeNotification::Modify;
882 return Protocol::CollectionChangeNotification::Move;
884 return Protocol::CollectionChangeNotification::Remove;
886 return Protocol::CollectionChangeNotification::Subscribe;
888 return Protocol::CollectionChangeNotification::Unsubscribe;
890 qCWarning(AKONADICORE_LOG) <<
"Unexpected operation type in collection notification";
891 return Protocol::CollectionChangeNotification::InvalidOp;
895Protocol::TagChangeNotification::Operation ChangeRecorderJournalReader::mapTagOperation(LegacyOp op)
899 return Protocol::TagChangeNotification::Add;
901 return Protocol::TagChangeNotification::Modify;
903 return Protocol::TagChangeNotification::Remove;
905 qCWarning(AKONADICORE_LOG) <<
"Unexpected operation type in tag notification";
906 return Protocol::TagChangeNotification::InvalidOp;
910ChangeRecorderJournalReader::LegacyType ChangeRecorderJournalWriter::mapToLegacyType(Protocol::Command::Type type)
913 case Protocol::Command::ItemChangeNotification:
914 return ChangeRecorderJournalReader::Item;
915 case Protocol::Command::CollectionChangeNotification:
916 return ChangeRecorderJournalReader::Collection;
917 case Protocol::Command::TagChangeNotification:
918 return ChangeRecorderJournalReader::Tag;
920 qCWarning(AKONADICORE_LOG) <<
"Unexpected notification type";
921 return ChangeRecorderJournalReader::InvalidType;
Represents a collection of PIM items.
Helper integration between Akonadi and Qt.
char * toString(const EngineQuery &query)
KCALUTILS_EXPORT QString mimeType()
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
NETWORKMANAGERQT_EXPORT QString version()
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)
void reserve(qsizetype size)
iterator insert(const T &value)
QVariant value(QAnyStringView key) const const
QStringList toStringList() const const