1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "rbd_replay/ActionTypes.h"
5 #include "include/assert.h"
6 #include "include/byteorder.h"
7 #include "include/stringify.h"
8 #include "common/Formatter.h"
10 #include <boost/variant.hpp>
12 namespace rbd_replay {
17 bool byte_swap_required(__u8 version) {
18 #if defined(CEPH_LITTLE_ENDIAN)
19 return (version == 0);
25 void decode_big_endian_string(std::string &str, bufferlist::iterator &it) {
26 #if defined(CEPH_LITTLE_ENDIAN)
29 length = swab(length);
37 class EncodeVisitor : public boost::static_visitor<void> {
39 explicit EncodeVisitor(bufferlist &bl) : m_bl(bl) {
42 template <typename Action>
43 inline void operator()(const Action &action) const {
44 ::encode(static_cast<uint8_t>(Action::ACTION_TYPE), m_bl);
51 class DecodeVisitor : public boost::static_visitor<void> {
53 DecodeVisitor(__u8 version, bufferlist::iterator &iter)
54 : m_version(version), m_iter(iter) {
57 template <typename Action>
58 inline void operator()(Action &action) const {
59 action.decode(m_version, m_iter);
63 bufferlist::iterator &m_iter;
66 class DumpVisitor : public boost::static_visitor<void> {
68 explicit DumpVisitor(Formatter *formatter) : m_formatter(formatter) {}
70 template <typename Action>
71 inline void operator()(const Action &action) const {
72 ActionType action_type = Action::ACTION_TYPE;
73 m_formatter->dump_string("action_type", stringify(action_type));
74 action.dump(m_formatter);
77 ceph::Formatter *m_formatter;
80 } // anonymous namespace
82 void Dependency::encode(bufferlist &bl) const {
84 ::encode(time_delta, bl);
87 void Dependency::decode(bufferlist::iterator &it) {
91 void Dependency::decode(__u8 version, bufferlist::iterator &it) {
93 ::decode(time_delta, it);
94 if (byte_swap_required(version)) {
96 time_delta = swab(time_delta);
100 void Dependency::dump(Formatter *f) const {
101 f->dump_unsigned("id", id);
102 f->dump_unsigned("time_delta", time_delta);
105 void Dependency::generate_test_instances(std::list<Dependency *> &o) {
106 o.push_back(new Dependency());
107 o.push_back(new Dependency(1, 123456789));
110 void ActionBase::encode(bufferlist &bl) const {
112 ::encode(thread_id, bl);
113 ::encode(dependencies, bl);
116 void ActionBase::decode(__u8 version, bufferlist::iterator &it) {
118 ::decode(thread_id, it);
120 uint32_t num_successors;
121 ::decode(num_successors, it);
123 uint32_t num_completion_successors;
124 ::decode(num_completion_successors, it);
127 if (byte_swap_required(version)) {
129 thread_id = swab(thread_id);
132 ::decode(dep_count, it);
133 dep_count = swab(dep_count);
134 dependencies.resize(dep_count);
135 for (uint32_t i = 0; i < dep_count; ++i) {
136 dependencies[i].decode(0, it);
139 ::decode(dependencies, it);
143 void ActionBase::dump(Formatter *f) const {
144 f->dump_unsigned("id", id);
145 f->dump_unsigned("thread_id", thread_id);
146 f->open_array_section("dependencies");
147 for (size_t i = 0; i < dependencies.size(); ++i) {
148 f->open_object_section("dependency");
149 dependencies[i].dump(f);
155 void ImageActionBase::encode(bufferlist &bl) const {
156 ActionBase::encode(bl);
157 ::encode(imagectx_id, bl);
160 void ImageActionBase::decode(__u8 version, bufferlist::iterator &it) {
161 ActionBase::decode(version, it);
162 ::decode(imagectx_id, it);
163 if (byte_swap_required(version)) {
164 imagectx_id = swab(imagectx_id);
168 void ImageActionBase::dump(Formatter *f) const {
170 f->dump_unsigned("imagectx_id", imagectx_id);
173 void IoActionBase::encode(bufferlist &bl) const {
174 ImageActionBase::encode(bl);
175 ::encode(offset, bl);
176 ::encode(length, bl);
179 void IoActionBase::decode(__u8 version, bufferlist::iterator &it) {
180 ImageActionBase::decode(version, it);
181 ::decode(offset, it);
182 ::decode(length, it);
183 if (byte_swap_required(version)) {
184 offset = swab(offset);
185 length = swab(length);
189 void IoActionBase::dump(Formatter *f) const {
190 ImageActionBase::dump(f);
191 f->dump_unsigned("offset", offset);
192 f->dump_unsigned("length", length);
195 void OpenImageAction::encode(bufferlist &bl) const {
196 ImageActionBase::encode(bl);
198 ::encode(snap_name, bl);
199 ::encode(read_only, bl);
202 void OpenImageAction::decode(__u8 version, bufferlist::iterator &it) {
203 ImageActionBase::decode(version, it);
204 if (byte_swap_required(version)) {
205 decode_big_endian_string(name, it);
206 decode_big_endian_string(snap_name, it);
209 ::decode(snap_name, it);
211 ::decode(read_only, it);
214 void OpenImageAction::dump(Formatter *f) const {
215 ImageActionBase::dump(f);
216 f->dump_string("name", name);
217 f->dump_string("snap_name", snap_name);
218 f->dump_bool("read_only", read_only);
221 void AioOpenImageAction::encode(bufferlist &bl) const {
222 ImageActionBase::encode(bl);
224 ::encode(snap_name, bl);
225 ::encode(read_only, bl);
228 void AioOpenImageAction::decode(__u8 version, bufferlist::iterator &it) {
229 ImageActionBase::decode(version, it);
230 if (byte_swap_required(version)) {
231 decode_big_endian_string(name, it);
232 decode_big_endian_string(snap_name, it);
235 ::decode(snap_name, it);
237 ::decode(read_only, it);
240 void AioOpenImageAction::dump(Formatter *f) const {
241 ImageActionBase::dump(f);
242 f->dump_string("name", name);
243 f->dump_string("snap_name", snap_name);
244 f->dump_bool("read_only", read_only);
247 void UnknownAction::encode(bufferlist &bl) const {
251 void UnknownAction::decode(__u8 version, bufferlist::iterator &it) {
254 void UnknownAction::dump(Formatter *f) const {
257 void ActionEntry::encode(bufferlist &bl) const {
258 ENCODE_START(1, 1, bl);
259 boost::apply_visitor(EncodeVisitor(bl), action);
263 void ActionEntry::decode(bufferlist::iterator &it) {
265 decode(struct_v, it);
269 void ActionEntry::decode_unversioned(bufferlist::iterator &it) {
273 void ActionEntry::decode(__u8 version, bufferlist::iterator &it) {
275 ::decode(action_type, it);
277 // select the correct action variant based upon the action_type
278 switch (action_type) {
279 case ACTION_TYPE_START_THREAD:
280 action = StartThreadAction();
282 case ACTION_TYPE_STOP_THREAD:
283 action = StopThreadAction();
285 case ACTION_TYPE_READ:
286 action = ReadAction();
288 case ACTION_TYPE_WRITE:
289 action = WriteAction();
291 case ACTION_TYPE_DISCARD:
292 action = DiscardAction();
294 case ACTION_TYPE_AIO_READ:
295 action = AioReadAction();
297 case ACTION_TYPE_AIO_WRITE:
298 action = AioWriteAction();
300 case ACTION_TYPE_AIO_DISCARD:
301 action = AioDiscardAction();
303 case ACTION_TYPE_OPEN_IMAGE:
304 action = OpenImageAction();
306 case ACTION_TYPE_CLOSE_IMAGE:
307 action = CloseImageAction();
309 case ACTION_TYPE_AIO_OPEN_IMAGE:
310 action = AioOpenImageAction();
312 case ACTION_TYPE_AIO_CLOSE_IMAGE:
313 action = AioCloseImageAction();
317 boost::apply_visitor(DecodeVisitor(version, it), action);
320 void ActionEntry::dump(Formatter *f) const {
321 boost::apply_visitor(DumpVisitor(f), action);
324 void ActionEntry::generate_test_instances(std::list<ActionEntry *> &o) {
325 Dependencies dependencies;
326 dependencies.push_back(Dependency(3, 123456789));
327 dependencies.push_back(Dependency(4, 234567890));
329 o.push_back(new ActionEntry(StartThreadAction()));
330 o.push_back(new ActionEntry(StartThreadAction(1, 123456789, dependencies)));
331 o.push_back(new ActionEntry(StopThreadAction()));
332 o.push_back(new ActionEntry(StopThreadAction(1, 123456789, dependencies)));
334 o.push_back(new ActionEntry(ReadAction()));
335 o.push_back(new ActionEntry(ReadAction(1, 123456789, dependencies, 3, 4, 5)));
336 o.push_back(new ActionEntry(WriteAction()));
337 o.push_back(new ActionEntry(WriteAction(1, 123456789, dependencies, 3, 4,
339 o.push_back(new ActionEntry(DiscardAction()));
340 o.push_back(new ActionEntry(DiscardAction(1, 123456789, dependencies, 3, 4,
342 o.push_back(new ActionEntry(AioReadAction()));
343 o.push_back(new ActionEntry(AioReadAction(1, 123456789, dependencies, 3, 4,
345 o.push_back(new ActionEntry(AioWriteAction()));
346 o.push_back(new ActionEntry(AioWriteAction(1, 123456789, dependencies, 3, 4,
348 o.push_back(new ActionEntry(AioDiscardAction()));
349 o.push_back(new ActionEntry(AioDiscardAction(1, 123456789, dependencies, 3, 4,
352 o.push_back(new ActionEntry(OpenImageAction()));
353 o.push_back(new ActionEntry(OpenImageAction(1, 123456789, dependencies, 3,
354 "image_name", "snap_name",
356 o.push_back(new ActionEntry(CloseImageAction()));
357 o.push_back(new ActionEntry(CloseImageAction(1, 123456789, dependencies, 3)));
359 o.push_back(new ActionEntry(AioOpenImageAction()));
360 o.push_back(new ActionEntry(AioOpenImageAction(1, 123456789, dependencies, 3,
361 "image_name", "snap_name",
363 o.push_back(new ActionEntry(AioCloseImageAction()));
364 o.push_back(new ActionEntry(AioCloseImageAction(1, 123456789, dependencies, 3)));
367 } // namespace action
368 } // namespace rbd_replay
370 std::ostream &operator<<(std::ostream &out,
371 const rbd_replay::action::ActionType &type) {
372 using namespace rbd_replay::action;
375 case ACTION_TYPE_START_THREAD:
376 out << "StartThread";
378 case ACTION_TYPE_STOP_THREAD:
381 case ACTION_TYPE_READ:
384 case ACTION_TYPE_WRITE:
387 case ACTION_TYPE_DISCARD:
390 case ACTION_TYPE_AIO_READ:
393 case ACTION_TYPE_AIO_WRITE:
396 case ACTION_TYPE_AIO_DISCARD:
399 case ACTION_TYPE_OPEN_IMAGE:
402 case ACTION_TYPE_CLOSE_IMAGE:
405 case ACTION_TYPE_AIO_OPEN_IMAGE:
406 out << "AioOpenImage";
408 case ACTION_TYPE_AIO_CLOSE_IMAGE:
409 out << "AioCloseImage";
412 out << "Unknown (" << static_cast<uint32_t>(type) << ")";