1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "librbd/journal/Types.h"
5 #include "include/assert.h"
6 #include "include/stringify.h"
7 #include "include/types.h"
8 #include "common/Formatter.h"
16 class GetTypeVisitor : public boost::static_visitor<E> {
19 inline E operator()(const T&) const {
24 class EncodeVisitor : public boost::static_visitor<void> {
26 explicit EncodeVisitor(bufferlist &bl) : m_bl(bl) {
30 inline void operator()(const T& t) const {
31 ::encode(static_cast<uint32_t>(T::TYPE), m_bl);
38 class DecodeVisitor : public boost::static_visitor<void> {
40 DecodeVisitor(__u8 version, bufferlist::iterator &iter)
41 : m_version(version), m_iter(iter) {
45 inline void operator()(T& t) const {
46 t.decode(m_version, m_iter);
50 bufferlist::iterator &m_iter;
53 class DumpVisitor : public boost::static_visitor<void> {
55 explicit DumpVisitor(Formatter *formatter, const std::string &key)
56 : m_formatter(formatter), m_key(key) {}
59 inline void operator()(const T& t) const {
61 m_formatter->dump_string(m_key.c_str(), stringify(type));
65 ceph::Formatter *m_formatter;
69 } // anonymous namespace
71 void AioDiscardEvent::encode(bufferlist& bl) const {
74 ::encode(skip_partial_discard, bl);
77 void AioDiscardEvent::decode(__u8 version, bufferlist::iterator& it) {
81 ::decode(skip_partial_discard, it);
85 void AioDiscardEvent::dump(Formatter *f) const {
86 f->dump_unsigned("offset", offset);
87 f->dump_unsigned("length", length);
88 f->dump_bool("skip_partial_discard", skip_partial_discard);
91 uint32_t AioWriteEvent::get_fixed_size() {
92 return EventEntry::get_fixed_size() + 16 /* offset, length */;
95 void AioWriteEvent::encode(bufferlist& bl) const {
101 void AioWriteEvent::decode(__u8 version, bufferlist::iterator& it) {
102 ::decode(offset, it);
103 ::decode(length, it);
107 void AioWriteEvent::dump(Formatter *f) const {
108 f->dump_unsigned("offset", offset);
109 f->dump_unsigned("length", length);
112 void AioWriteSameEvent::encode(bufferlist& bl) const {
113 ::encode(offset, bl);
114 ::encode(length, bl);
118 void AioWriteSameEvent::decode(__u8 version, bufferlist::iterator& it) {
119 ::decode(offset, it);
120 ::decode(length, it);
124 void AioWriteSameEvent::dump(Formatter *f) const {
125 f->dump_unsigned("offset", offset);
126 f->dump_unsigned("length", length);
129 uint32_t AioCompareAndWriteEvent::get_fixed_size() {
130 return EventEntry::get_fixed_size() + 32 /* offset, length */;
133 void AioCompareAndWriteEvent::encode(bufferlist& bl) const {
134 ::encode(offset, bl);
135 ::encode(length, bl);
136 ::encode(cmp_data, bl);
137 ::encode(write_data, bl);
140 void AioCompareAndWriteEvent::decode(__u8 version, bufferlist::iterator& it) {
141 ::decode(offset, it);
142 ::decode(length, it);
143 ::decode(cmp_data, it);
144 ::decode(write_data, it);
147 void AioCompareAndWriteEvent::dump(Formatter *f) const {
148 f->dump_unsigned("offset", offset);
149 f->dump_unsigned("length", length);
152 void AioFlushEvent::encode(bufferlist& bl) const {
155 void AioFlushEvent::decode(__u8 version, bufferlist::iterator& it) {
158 void AioFlushEvent::dump(Formatter *f) const {
161 void OpEventBase::encode(bufferlist& bl) const {
162 ::encode(op_tid, bl);
165 void OpEventBase::decode(__u8 version, bufferlist::iterator& it) {
166 ::decode(op_tid, it);
169 void OpEventBase::dump(Formatter *f) const {
170 f->dump_unsigned("op_tid", op_tid);
173 void OpFinishEvent::encode(bufferlist& bl) const {
174 OpEventBase::encode(bl);
175 ::encode(op_tid, bl);
179 void OpFinishEvent::decode(__u8 version, bufferlist::iterator& it) {
180 OpEventBase::decode(version, it);
181 ::decode(op_tid, it);
185 void OpFinishEvent::dump(Formatter *f) const {
186 OpEventBase::dump(f);
187 f->dump_unsigned("op_tid", op_tid);
188 f->dump_int("result", r);
191 void SnapEventBase::encode(bufferlist& bl) const {
192 OpEventBase::encode(bl);
193 ::encode(snap_name, bl);
194 ::encode(cls::rbd::SnapshotNamespaceOnDisk(snap_namespace), bl);
197 void SnapEventBase::decode(__u8 version, bufferlist::iterator& it) {
198 OpEventBase::decode(version, it);
199 ::decode(snap_name, it);
201 cls::rbd::SnapshotNamespaceOnDisk sn;
203 snap_namespace = sn.snapshot_namespace;
207 void SnapEventBase::dump(Formatter *f) const {
208 OpEventBase::dump(f);
209 f->dump_string("snap_name", snap_name);
210 cls::rbd::SnapshotNamespaceOnDisk(snap_namespace).dump(f);
213 void SnapCreateEvent::encode(bufferlist &bl) const {
214 SnapEventBase::encode(bl);
217 void SnapCreateEvent::decode(__u8 version, bufferlist::iterator& it) {
218 SnapEventBase::decode(version, it);
220 cls::rbd::SnapshotNamespaceOnDisk sn;
222 snap_namespace = sn.snapshot_namespace;
226 void SnapCreateEvent::dump(Formatter *f) const {
227 SnapEventBase::dump(f);
230 void SnapLimitEvent::encode(bufferlist &bl) const {
231 OpEventBase::encode(bl);
235 void SnapLimitEvent::decode(__u8 version, bufferlist::iterator& it) {
236 OpEventBase::decode(version, it);
240 void SnapLimitEvent::dump(Formatter *f) const {
241 OpEventBase::dump(f);
242 f->dump_unsigned("limit", limit);
245 void SnapRenameEvent::encode(bufferlist& bl) const {
246 OpEventBase::encode(bl);
247 ::encode(dst_snap_name, bl);
248 ::encode(snap_id, bl);
249 ::encode(src_snap_name, bl);
252 void SnapRenameEvent::decode(__u8 version, bufferlist::iterator& it) {
253 OpEventBase::decode(version, it);
254 ::decode(dst_snap_name, it);
255 ::decode(snap_id, it);
257 ::decode(src_snap_name, it);
261 void SnapRenameEvent::dump(Formatter *f) const {
262 OpEventBase::dump(f);
263 f->dump_unsigned("src_snap_id", snap_id);
264 f->dump_string("src_snap_name", src_snap_name);
265 f->dump_string("dest_snap_name", dst_snap_name);
268 void RenameEvent::encode(bufferlist& bl) const {
269 OpEventBase::encode(bl);
270 ::encode(image_name, bl);
273 void RenameEvent::decode(__u8 version, bufferlist::iterator& it) {
274 OpEventBase::decode(version, it);
275 ::decode(image_name, it);
278 void RenameEvent::dump(Formatter *f) const {
279 OpEventBase::dump(f);
280 f->dump_string("image_name", image_name);
283 void ResizeEvent::encode(bufferlist& bl) const {
284 OpEventBase::encode(bl);
288 void ResizeEvent::decode(__u8 version, bufferlist::iterator& it) {
289 OpEventBase::decode(version, it);
293 void ResizeEvent::dump(Formatter *f) const {
294 OpEventBase::dump(f);
295 f->dump_unsigned("size", size);
298 void DemotePromoteEvent::encode(bufferlist& bl) const {
301 void DemotePromoteEvent::decode(__u8 version, bufferlist::iterator& it) {
304 void DemotePromoteEvent::dump(Formatter *f) const {
307 void UpdateFeaturesEvent::encode(bufferlist& bl) const {
308 OpEventBase::encode(bl);
309 ::encode(features, bl);
310 ::encode(enabled, bl);
313 void UpdateFeaturesEvent::decode(__u8 version, bufferlist::iterator& it) {
314 OpEventBase::decode(version, it);
315 ::decode(features, it);
316 ::decode(enabled, it);
319 void UpdateFeaturesEvent::dump(Formatter *f) const {
320 OpEventBase::dump(f);
321 f->dump_unsigned("features", features);
322 f->dump_bool("enabled", enabled);
325 void MetadataSetEvent::encode(bufferlist& bl) const {
326 OpEventBase::encode(bl);
331 void MetadataSetEvent::decode(__u8 version, bufferlist::iterator& it) {
332 OpEventBase::decode(version, it);
337 void MetadataSetEvent::dump(Formatter *f) const {
338 OpEventBase::dump(f);
339 f->dump_string("key", key);
340 f->dump_string("value", value);
343 void MetadataRemoveEvent::encode(bufferlist& bl) const {
344 OpEventBase::encode(bl);
348 void MetadataRemoveEvent::decode(__u8 version, bufferlist::iterator& it) {
349 OpEventBase::decode(version, it);
353 void MetadataRemoveEvent::dump(Formatter *f) const {
354 OpEventBase::dump(f);
355 f->dump_string("key", key);
358 void UnknownEvent::encode(bufferlist& bl) const {
362 void UnknownEvent::decode(__u8 version, bufferlist::iterator& it) {
365 void UnknownEvent::dump(Formatter *f) const {
368 EventType EventEntry::get_event_type() const {
369 return boost::apply_visitor(GetTypeVisitor<EventType>(), event);
372 void EventEntry::encode(bufferlist& bl) const {
373 ENCODE_START(4, 1, bl);
374 boost::apply_visitor(EncodeVisitor(bl), event);
379 void EventEntry::decode(bufferlist::iterator& it) {
383 ::decode(event_type, it);
385 // select the correct payload variant based upon the encoded op
386 switch (event_type) {
387 case EVENT_TYPE_AIO_DISCARD:
388 event = AioDiscardEvent();
390 case EVENT_TYPE_AIO_WRITE:
391 event = AioWriteEvent();
393 case EVENT_TYPE_AIO_FLUSH:
394 event = AioFlushEvent();
396 case EVENT_TYPE_OP_FINISH:
397 event = OpFinishEvent();
399 case EVENT_TYPE_SNAP_CREATE:
400 event = SnapCreateEvent();
402 case EVENT_TYPE_SNAP_REMOVE:
403 event = SnapRemoveEvent();
405 case EVENT_TYPE_SNAP_RENAME:
406 event = SnapRenameEvent();
408 case EVENT_TYPE_SNAP_PROTECT:
409 event = SnapProtectEvent();
411 case EVENT_TYPE_SNAP_UNPROTECT:
412 event = SnapUnprotectEvent();
414 case EVENT_TYPE_SNAP_ROLLBACK:
415 event = SnapRollbackEvent();
417 case EVENT_TYPE_RENAME:
418 event = RenameEvent();
420 case EVENT_TYPE_RESIZE:
421 event = ResizeEvent();
423 case EVENT_TYPE_FLATTEN:
424 event = FlattenEvent();
426 case EVENT_TYPE_DEMOTE_PROMOTE:
427 event = DemotePromoteEvent();
429 case EVENT_TYPE_UPDATE_FEATURES:
430 event = UpdateFeaturesEvent();
432 case EVENT_TYPE_METADATA_SET:
433 event = MetadataSetEvent();
435 case EVENT_TYPE_METADATA_REMOVE:
436 event = MetadataRemoveEvent();
438 case EVENT_TYPE_AIO_WRITESAME:
439 event = AioWriteSameEvent();
441 case EVENT_TYPE_AIO_COMPARE_AND_WRITE:
442 event = AioCompareAndWriteEvent();
445 event = UnknownEvent();
449 boost::apply_visitor(DecodeVisitor(struct_v, it), event);
456 void EventEntry::dump(Formatter *f) const {
457 boost::apply_visitor(DumpVisitor(f, "event_type"), event);
458 f->dump_stream("timestamp") << timestamp;
461 void EventEntry::encode_metadata(bufferlist& bl) const {
462 ENCODE_START(1, 1, bl);
463 ::encode(timestamp, bl);
467 void EventEntry::decode_metadata(bufferlist::iterator& it) {
469 ::decode(timestamp, it);
473 void EventEntry::generate_test_instances(std::list<EventEntry *> &o) {
474 o.push_back(new EventEntry(AioDiscardEvent()));
475 o.push_back(new EventEntry(AioDiscardEvent(123, 345, false), utime_t(1, 1)));
478 bl.append(std::string(32, '1'));
479 o.push_back(new EventEntry(AioWriteEvent()));
480 o.push_back(new EventEntry(AioWriteEvent(123, 456, bl), utime_t(1, 1)));
482 o.push_back(new EventEntry(AioFlushEvent()));
484 o.push_back(new EventEntry(OpFinishEvent(123, -1), utime_t(1, 1)));
486 o.push_back(new EventEntry(SnapCreateEvent(), utime_t(1, 1)));
487 o.push_back(new EventEntry(SnapCreateEvent(234, cls::rbd::UserSnapshotNamespace(), "snap"), utime_t(1, 1)));
489 o.push_back(new EventEntry(SnapRemoveEvent()));
490 o.push_back(new EventEntry(SnapRemoveEvent(345, cls::rbd::UserSnapshotNamespace(), "snap"), utime_t(1, 1)));
492 o.push_back(new EventEntry(SnapRenameEvent()));
493 o.push_back(new EventEntry(SnapRenameEvent(456, 1, "src snap", "dest snap"),
496 o.push_back(new EventEntry(SnapProtectEvent()));
497 o.push_back(new EventEntry(SnapProtectEvent(567, cls::rbd::UserSnapshotNamespace(), "snap"), utime_t(1, 1)));
499 o.push_back(new EventEntry(SnapUnprotectEvent()));
500 o.push_back(new EventEntry(SnapUnprotectEvent(678, cls::rbd::UserSnapshotNamespace(), "snap"), utime_t(1, 1)));
502 o.push_back(new EventEntry(SnapRollbackEvent()));
503 o.push_back(new EventEntry(SnapRollbackEvent(789, cls::rbd::UserSnapshotNamespace(), "snap"), utime_t(1, 1)));
505 o.push_back(new EventEntry(RenameEvent()));
506 o.push_back(new EventEntry(RenameEvent(890, "image name"), utime_t(1, 1)));
508 o.push_back(new EventEntry(ResizeEvent()));
509 o.push_back(new EventEntry(ResizeEvent(901, 1234), utime_t(1, 1)));
511 o.push_back(new EventEntry(FlattenEvent(123), utime_t(1, 1)));
513 o.push_back(new EventEntry(DemotePromoteEvent()));
515 o.push_back(new EventEntry(UpdateFeaturesEvent()));
516 o.push_back(new EventEntry(UpdateFeaturesEvent(123, 127, true), utime_t(1, 1)));
518 o.push_back(new EventEntry(MetadataSetEvent()));
519 o.push_back(new EventEntry(MetadataSetEvent(123, "key", "value"), utime_t(1, 1)));
521 o.push_back(new EventEntry(MetadataRemoveEvent()));
522 o.push_back(new EventEntry(MetadataRemoveEvent(123, "key"), utime_t(1, 1)));
527 void ImageClientMeta::encode(bufferlist& bl) const {
528 ::encode(tag_class, bl);
529 ::encode(resync_requested, bl);
532 void ImageClientMeta::decode(__u8 version, bufferlist::iterator& it) {
533 ::decode(tag_class, it);
534 ::decode(resync_requested, it);
537 void ImageClientMeta::dump(Formatter *f) const {
538 f->dump_unsigned("tag_class", tag_class);
539 f->dump_bool("resync_requested", resync_requested);
542 void MirrorPeerSyncPoint::encode(bufferlist& bl) const {
543 ::encode(snap_name, bl);
544 ::encode(from_snap_name, bl);
545 ::encode(object_number, bl);
546 ::encode(cls::rbd::SnapshotNamespaceOnDisk(snap_namespace), bl);
549 void MirrorPeerSyncPoint::decode(__u8 version, bufferlist::iterator& it) {
550 ::decode(snap_name, it);
551 ::decode(from_snap_name, it);
552 ::decode(object_number, it);
554 cls::rbd::SnapshotNamespaceOnDisk sn;
556 snap_namespace = sn.snapshot_namespace;
560 void MirrorPeerSyncPoint::dump(Formatter *f) const {
561 f->dump_string("snap_name", snap_name);
562 f->dump_string("from_snap_name", from_snap_name);
564 f->dump_unsigned("object_number", *object_number);
566 cls::rbd::SnapshotNamespaceOnDisk(snap_namespace).dump(f);
569 void MirrorPeerClientMeta::encode(bufferlist& bl) const {
570 ::encode(image_id, bl);
571 ::encode(static_cast<uint32_t>(state), bl);
572 ::encode(sync_object_count, bl);
573 ::encode(static_cast<uint32_t>(sync_points.size()), bl);
574 for (auto &sync_point : sync_points) {
575 sync_point.encode(bl);
577 ::encode(snap_seqs, bl);
580 void MirrorPeerClientMeta::decode(__u8 version, bufferlist::iterator& it) {
581 ::decode(image_id, it);
583 uint32_t decode_state;
584 ::decode(decode_state, it);
585 state = static_cast<MirrorPeerState>(decode_state);
587 ::decode(sync_object_count, it);
589 uint32_t sync_point_count;
590 ::decode(sync_point_count, it);
591 sync_points.resize(sync_point_count);
592 for (auto &sync_point : sync_points) {
593 sync_point.decode(version, it);
596 ::decode(snap_seqs, it);
599 void MirrorPeerClientMeta::dump(Formatter *f) const {
600 f->dump_string("image_id", image_id);
601 f->dump_stream("state") << state;
602 f->dump_unsigned("sync_object_count", sync_object_count);
603 f->open_array_section("sync_points");
604 for (auto &sync_point : sync_points) {
605 f->open_object_section("sync_point");
610 f->open_array_section("snap_seqs");
611 for (auto &pair : snap_seqs) {
612 f->open_object_section("snap_seq");
613 f->dump_unsigned("local_snap_seq", pair.first);
614 f->dump_unsigned("peer_snap_seq", pair.second);
620 void CliClientMeta::encode(bufferlist& bl) const {
623 void CliClientMeta::decode(__u8 version, bufferlist::iterator& it) {
626 void CliClientMeta::dump(Formatter *f) const {
629 void UnknownClientMeta::encode(bufferlist& bl) const {
633 void UnknownClientMeta::decode(__u8 version, bufferlist::iterator& it) {
636 void UnknownClientMeta::dump(Formatter *f) const {
639 ClientMetaType ClientData::get_client_meta_type() const {
640 return boost::apply_visitor(GetTypeVisitor<ClientMetaType>(), client_meta);
643 void ClientData::encode(bufferlist& bl) const {
644 ENCODE_START(2, 1, bl);
645 boost::apply_visitor(EncodeVisitor(bl), client_meta);
649 void ClientData::decode(bufferlist::iterator& it) {
652 uint32_t client_meta_type;
653 ::decode(client_meta_type, it);
655 // select the correct payload variant based upon the encoded op
656 switch (client_meta_type) {
657 case IMAGE_CLIENT_META_TYPE:
658 client_meta = ImageClientMeta();
660 case MIRROR_PEER_CLIENT_META_TYPE:
661 client_meta = MirrorPeerClientMeta();
663 case CLI_CLIENT_META_TYPE:
664 client_meta = CliClientMeta();
667 client_meta = UnknownClientMeta();
671 boost::apply_visitor(DecodeVisitor(struct_v, it), client_meta);
675 void ClientData::dump(Formatter *f) const {
676 boost::apply_visitor(DumpVisitor(f, "client_meta_type"), client_meta);
679 void ClientData::generate_test_instances(std::list<ClientData *> &o) {
680 o.push_back(new ClientData(ImageClientMeta()));
681 o.push_back(new ClientData(ImageClientMeta(123)));
682 o.push_back(new ClientData(MirrorPeerClientMeta()));
683 o.push_back(new ClientData(MirrorPeerClientMeta("image_id",
684 {{{}, "snap 2", "snap 1", 123}},
686 o.push_back(new ClientData(CliClientMeta()));
691 void TagPredecessor::encode(bufferlist& bl) const {
692 ::encode(mirror_uuid, bl);
693 ::encode(commit_valid, bl);
694 ::encode(tag_tid, bl);
695 ::encode(entry_tid, bl);
698 void TagPredecessor::decode(bufferlist::iterator& it) {
699 ::decode(mirror_uuid, it);
700 ::decode(commit_valid, it);
701 ::decode(tag_tid, it);
702 ::decode(entry_tid, it);
705 void TagPredecessor::dump(Formatter *f) const {
706 f->dump_string("mirror_uuid", mirror_uuid);
707 f->dump_string("commit_valid", commit_valid ? "true" : "false");
708 f->dump_unsigned("tag_tid", tag_tid);
709 f->dump_unsigned("entry_tid", entry_tid);
712 void TagData::encode(bufferlist& bl) const {
713 ::encode(mirror_uuid, bl);
714 predecessor.encode(bl);
717 void TagData::decode(bufferlist::iterator& it) {
718 ::decode(mirror_uuid, it);
719 predecessor.decode(it);
722 void TagData::dump(Formatter *f) const {
723 f->dump_string("mirror_uuid", mirror_uuid);
724 f->open_object_section("predecessor");
729 void TagData::generate_test_instances(std::list<TagData *> &o) {
730 o.push_back(new TagData());
731 o.push_back(new TagData("mirror-uuid"));
732 o.push_back(new TagData("mirror-uuid", "remote-mirror-uuid", true, 123, 234));
735 std::ostream &operator<<(std::ostream &out, const EventType &type) {
736 using namespace librbd::journal;
739 case EVENT_TYPE_AIO_DISCARD:
742 case EVENT_TYPE_AIO_WRITE:
745 case EVENT_TYPE_AIO_FLUSH:
748 case EVENT_TYPE_OP_FINISH:
751 case EVENT_TYPE_SNAP_CREATE:
754 case EVENT_TYPE_SNAP_REMOVE:
757 case EVENT_TYPE_SNAP_RENAME:
760 case EVENT_TYPE_SNAP_PROTECT:
761 out << "SnapProtect";
763 case EVENT_TYPE_SNAP_UNPROTECT:
764 out << "SnapUnprotect";
766 case EVENT_TYPE_SNAP_ROLLBACK:
767 out << "SnapRollback";
769 case EVENT_TYPE_RENAME:
772 case EVENT_TYPE_RESIZE:
775 case EVENT_TYPE_FLATTEN:
778 case EVENT_TYPE_DEMOTE_PROMOTE:
779 out << "Demote/Promote";
781 case EVENT_TYPE_UPDATE_FEATURES:
782 out << "UpdateFeatures";
784 case EVENT_TYPE_METADATA_SET:
785 out << "MetadataSet";
787 case EVENT_TYPE_METADATA_REMOVE:
788 out << "MetadataRemove";
790 case EVENT_TYPE_AIO_WRITESAME:
791 out << "AioWriteSame";
793 case EVENT_TYPE_AIO_COMPARE_AND_WRITE:
794 out << "AioCompareAndWrite";
797 out << "Unknown (" << static_cast<uint32_t>(type) << ")";
803 std::ostream &operator<<(std::ostream &out, const ClientMetaType &type) {
804 using namespace librbd::journal;
807 case IMAGE_CLIENT_META_TYPE:
808 out << "Master Image";
810 case MIRROR_PEER_CLIENT_META_TYPE:
811 out << "Mirror Peer";
813 case CLI_CLIENT_META_TYPE:
817 out << "Unknown (" << static_cast<uint32_t>(type) << ")";
823 std::ostream &operator<<(std::ostream &out, const ImageClientMeta &meta) {
824 out << "[tag_class=" << meta.tag_class << "]";
828 std::ostream &operator<<(std::ostream &out, const MirrorPeerSyncPoint &sync) {
829 out << "[snap_name=" << sync.snap_name << ", "
830 << "from_snap_name=" << sync.from_snap_name;
831 if (sync.object_number) {
832 out << ", " << *sync.object_number;
838 std::ostream &operator<<(std::ostream &out, const MirrorPeerState &state) {
840 case MIRROR_PEER_STATE_SYNCING:
843 case MIRROR_PEER_STATE_REPLAYING:
847 out << "Unknown (" << static_cast<uint32_t>(state) << ")";
853 std::ostream &operator<<(std::ostream &out, const MirrorPeerClientMeta &meta) {
854 out << "[image_id=" << meta.image_id << ", "
855 << "state=" << meta.state << ", "
856 << "sync_object_count=" << meta.sync_object_count << ", "
858 std::string delimiter;
859 for (auto &sync_point : meta.sync_points) {
860 out << delimiter << "[" << sync_point << "]";
863 out << "], snap_seqs=[";
865 for (auto &pair : meta.snap_seqs) {
866 out << delimiter << "["
867 << "local_snap_seq=" << pair.first << ", "
868 << "peer_snap_seq" << pair.second << "]";
875 std::ostream &operator<<(std::ostream &out, const TagPredecessor &predecessor) {
877 << "mirror_uuid=" << predecessor.mirror_uuid;
878 if (predecessor.commit_valid) {
880 << "tag_tid=" << predecessor.tag_tid << ", "
881 << "entry_tid=" << predecessor.entry_tid;
887 std::ostream &operator<<(std::ostream &out, const TagData &tag_data) {
889 << "mirror_uuid=" << tag_data.mirror_uuid << ", "
890 << "predecessor=" << tag_data.predecessor
895 } // namespace journal
896 } // namespace librbd