1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #ifndef CEPH_LIBRBD_JOURNAL_REPLAY_H
5 #define CEPH_LIBRBD_JOURNAL_REPLAY_H
7 #include "include/int_types.h"
8 #include "include/buffer_fwd.h"
9 #include "include/Context.h"
10 #include "common/ceph_mutex.h"
11 #include "librbd/io/Types.h"
12 #include "librbd/journal/Types.h"
13 #include <boost/variant.hpp>
15 #include <unordered_set>
16 #include <unordered_map>
21 namespace io
{ struct AioCompletion
; }
25 template <typename ImageCtxT
= ImageCtx
>
28 static Replay
*create(ImageCtxT
&image_ctx
) {
29 return new Replay(image_ctx
);
32 Replay(ImageCtxT
&image_ctx
);
35 int decode(bufferlist::const_iterator
*it
, EventEntry
*event_entry
);
36 void process(const EventEntry
&event_entry
,
37 Context
*on_ready
, Context
*on_safe
);
39 void shut_down(bool cancel_ops
, Context
*on_finish
);
40 void flush(Context
*on_finish
);
42 void replay_op_ready(uint64_t op_tid
, Context
*on_resume
);
45 typedef std::unordered_set
<int> ReturnValues
;
48 bool op_in_progress
= false;
49 bool finish_on_ready
= false;
50 Context
*on_op_finish_event
= nullptr;
51 Context
*on_start_ready
= nullptr;
52 Context
*on_start_safe
= nullptr;
53 Context
*on_finish_ready
= nullptr;
54 Context
*on_finish_safe
= nullptr;
55 Context
*on_op_complete
= nullptr;
56 ReturnValues op_finish_error_codes
;
57 ReturnValues ignore_error_codes
;
60 typedef std::list
<uint64_t> OpTids
;
61 typedef std::list
<Context
*> Contexts
;
62 typedef std::unordered_set
<Context
*> ContextSet
;
63 typedef std::unordered_map
<uint64_t, OpEvent
> OpEvents
;
65 struct C_OpOnComplete
: public Context
{
68 C_OpOnComplete(Replay
*replay
, uint64_t op_tid
)
69 : replay(replay
), op_tid(op_tid
) {
71 void finish(int r
) override
{
72 replay
->handle_op_complete(op_tid
, r
);
76 struct C_AioModifyComplete
: public Context
{
80 std::set
<int> filters
;
81 C_AioModifyComplete(Replay
*replay
, Context
*on_ready
,
82 Context
*on_safe
, std::set
<int> &&filters
)
83 : replay(replay
), on_ready(on_ready
), on_safe(on_safe
),
84 filters(std::move(filters
)) {
86 void finish(int r
) override
{
87 replay
->handle_aio_modify_complete(on_ready
, on_safe
, r
, filters
);
91 struct C_AioFlushComplete
: public Context
{
93 Context
*on_flush_safe
;
94 Contexts on_safe_ctxs
;
95 C_AioFlushComplete(Replay
*replay
, Context
*on_flush_safe
,
96 Contexts
&&on_safe_ctxs
)
97 : replay(replay
), on_flush_safe(on_flush_safe
),
98 on_safe_ctxs(on_safe_ctxs
) {
100 void finish(int r
) override
{
101 replay
->handle_aio_flush_complete(on_flush_safe
, on_safe_ctxs
, r
);
105 struct EventVisitor
: public boost::static_visitor
<void> {
110 EventVisitor(Replay
*_replay
, Context
*_on_ready
, Context
*_on_safe
)
111 : replay(_replay
), on_ready(_on_ready
), on_safe(_on_safe
) {
114 template <typename Event
>
115 inline void operator()(const Event
&event
) const {
116 replay
->handle_event(event
, on_ready
, on_safe
);
120 ImageCtxT
&m_image_ctx
;
122 ceph::mutex m_lock
= ceph::make_mutex("Replay<I>::m_lock");
124 uint64_t m_in_flight_aio_flush
= 0;
125 uint64_t m_in_flight_aio_modify
= 0;
126 Contexts m_aio_modify_unsafe_contexts
;
127 ContextSet m_aio_modify_safe_contexts
;
129 OpEvents m_op_events
;
130 uint64_t m_in_flight_op_events
= 0;
132 bool m_shut_down
= false;
133 Context
*m_flush_ctx
= nullptr;
134 Context
*m_on_aio_ready
= nullptr;
136 void handle_event(const AioDiscardEvent
&event
, Context
*on_ready
,
138 void handle_event(const AioWriteEvent
&event
, Context
*on_ready
,
140 void handle_event(const AioWriteSameEvent
&event
, Context
*on_ready
,
142 void handle_event(const AioCompareAndWriteEvent
&event
, Context
*on_ready
,
144 void handle_event(const AioFlushEvent
&event
, Context
*on_ready
,
146 void handle_event(const OpFinishEvent
&event
, Context
*on_ready
,
148 void handle_event(const SnapCreateEvent
&event
, Context
*on_ready
,
150 void handle_event(const SnapRemoveEvent
&event
, Context
*on_ready
,
152 void handle_event(const SnapRenameEvent
&event
, Context
*on_ready
,
154 void handle_event(const SnapProtectEvent
&event
, Context
*on_ready
,
156 void handle_event(const SnapUnprotectEvent
&event
, Context
*on_ready
,
158 void handle_event(const SnapRollbackEvent
&event
, Context
*on_ready
,
160 void handle_event(const RenameEvent
&event
, Context
*on_ready
,
162 void handle_event(const ResizeEvent
&event
, Context
*on_ready
,
164 void handle_event(const FlattenEvent
&event
, Context
*on_ready
,
166 void handle_event(const DemotePromoteEvent
&event
, Context
*on_ready
,
168 void handle_event(const SnapLimitEvent
&event
, Context
*on_ready
,
170 void handle_event(const UpdateFeaturesEvent
&event
, Context
*on_ready
,
172 void handle_event(const MetadataSetEvent
&event
, Context
*on_ready
,
174 void handle_event(const MetadataRemoveEvent
&event
, Context
*on_ready
,
176 void handle_event(const UnknownEvent
&event
, Context
*on_ready
,
179 void handle_aio_modify_complete(Context
*on_ready
, Context
*on_safe
,
180 int r
, std::set
<int> &filters
);
181 void handle_aio_flush_complete(Context
*on_flush_safe
, Contexts
&on_safe_ctxs
,
184 Context
*create_op_context_callback(uint64_t op_tid
, Context
*on_ready
,
185 Context
*on_safe
, OpEvent
**op_event
);
186 void handle_op_complete(uint64_t op_tid
, int r
);
188 io::AioCompletion
*create_aio_modify_completion(Context
*on_ready
,
190 io::aio_type_t aio_type
,
191 bool *flush_required
,
192 std::set
<int> &&filters
);
193 io::AioCompletion
*create_aio_flush_completion(Context
*on_safe
);
194 void handle_aio_completion(io::AioCompletion
*aio_comp
);
196 bool clipped_io(uint64_t image_offset
, io::AioCompletion
*aio_comp
);
200 } // namespace journal
201 } // namespace librbd
203 extern template class librbd::journal::Replay
<librbd::ImageCtx
>;
205 #endif // CEPH_LIBRBD_JOURNAL_REPLAY_H