]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "rbd_replay/ActionTypes.h" | |
11fdf7f2 | 5 | #include "include/ceph_assert.h" |
7c673cae FG |
6 | #include "include/byteorder.h" |
7 | #include "include/stringify.h" | |
8 | #include "common/Formatter.h" | |
9 | #include <iostream> | |
10 | #include <boost/variant.hpp> | |
11 | ||
12 | namespace rbd_replay { | |
13 | namespace action { | |
14 | ||
15 | namespace { | |
16 | ||
17 | bool byte_swap_required(__u8 version) { | |
18 | #if defined(CEPH_LITTLE_ENDIAN) | |
19 | return (version == 0); | |
20 | #else | |
21 | return false; | |
22 | #endif | |
23 | } | |
24 | ||
11fdf7f2 TL |
25 | void decode_big_endian_string(std::string &str, bufferlist::const_iterator &it) { |
26 | using ceph::decode; | |
7c673cae FG |
27 | #if defined(CEPH_LITTLE_ENDIAN) |
28 | uint32_t length; | |
11fdf7f2 | 29 | decode(length, it); |
7c673cae FG |
30 | length = swab(length); |
31 | str.clear(); | |
32 | it.copy(length, str); | |
33 | #else | |
11fdf7f2 | 34 | ceph_abort(); |
7c673cae FG |
35 | #endif |
36 | } | |
37 | ||
38 | class EncodeVisitor : public boost::static_visitor<void> { | |
39 | public: | |
40 | explicit EncodeVisitor(bufferlist &bl) : m_bl(bl) { | |
41 | } | |
42 | ||
43 | template <typename Action> | |
44 | inline void operator()(const Action &action) const { | |
11fdf7f2 TL |
45 | using ceph::encode; |
46 | encode(static_cast<uint8_t>(Action::ACTION_TYPE), m_bl); | |
7c673cae FG |
47 | action.encode(m_bl); |
48 | } | |
49 | private: | |
50 | bufferlist &m_bl; | |
51 | }; | |
52 | ||
53 | class DecodeVisitor : public boost::static_visitor<void> { | |
54 | public: | |
11fdf7f2 | 55 | DecodeVisitor(__u8 version, bufferlist::const_iterator &iter) |
7c673cae FG |
56 | : m_version(version), m_iter(iter) { |
57 | } | |
58 | ||
59 | template <typename Action> | |
60 | inline void operator()(Action &action) const { | |
61 | action.decode(m_version, m_iter); | |
62 | } | |
63 | private: | |
64 | __u8 m_version; | |
11fdf7f2 | 65 | bufferlist::const_iterator &m_iter; |
7c673cae FG |
66 | }; |
67 | ||
68 | class DumpVisitor : public boost::static_visitor<void> { | |
69 | public: | |
70 | explicit DumpVisitor(Formatter *formatter) : m_formatter(formatter) {} | |
71 | ||
72 | template <typename Action> | |
73 | inline void operator()(const Action &action) const { | |
74 | ActionType action_type = Action::ACTION_TYPE; | |
75 | m_formatter->dump_string("action_type", stringify(action_type)); | |
76 | action.dump(m_formatter); | |
77 | } | |
78 | private: | |
79 | ceph::Formatter *m_formatter; | |
80 | }; | |
81 | ||
82 | } // anonymous namespace | |
83 | ||
84 | void Dependency::encode(bufferlist &bl) const { | |
11fdf7f2 TL |
85 | using ceph::encode; |
86 | encode(id, bl); | |
87 | encode(time_delta, bl); | |
7c673cae FG |
88 | } |
89 | ||
11fdf7f2 | 90 | void Dependency::decode(bufferlist::const_iterator &it) { |
7c673cae FG |
91 | decode(1, it); |
92 | } | |
93 | ||
11fdf7f2 TL |
94 | void Dependency::decode(__u8 version, bufferlist::const_iterator &it) { |
95 | using ceph::decode; | |
96 | decode(id, it); | |
97 | decode(time_delta, it); | |
7c673cae FG |
98 | if (byte_swap_required(version)) { |
99 | id = swab(id); | |
100 | time_delta = swab(time_delta); | |
101 | } | |
102 | } | |
103 | ||
104 | void Dependency::dump(Formatter *f) const { | |
105 | f->dump_unsigned("id", id); | |
106 | f->dump_unsigned("time_delta", time_delta); | |
107 | } | |
108 | ||
109 | void Dependency::generate_test_instances(std::list<Dependency *> &o) { | |
110 | o.push_back(new Dependency()); | |
111 | o.push_back(new Dependency(1, 123456789)); | |
112 | } | |
113 | ||
114 | void ActionBase::encode(bufferlist &bl) const { | |
11fdf7f2 TL |
115 | using ceph::encode; |
116 | encode(id, bl); | |
117 | encode(thread_id, bl); | |
118 | encode(dependencies, bl); | |
7c673cae FG |
119 | } |
120 | ||
11fdf7f2 TL |
121 | void ActionBase::decode(__u8 version, bufferlist::const_iterator &it) { |
122 | using ceph::decode; | |
123 | decode(id, it); | |
124 | decode(thread_id, it); | |
7c673cae FG |
125 | if (version == 0) { |
126 | uint32_t num_successors; | |
11fdf7f2 | 127 | decode(num_successors, it); |
7c673cae FG |
128 | |
129 | uint32_t num_completion_successors; | |
11fdf7f2 | 130 | decode(num_completion_successors, it); |
7c673cae FG |
131 | } |
132 | ||
133 | if (byte_swap_required(version)) { | |
134 | id = swab(id); | |
135 | thread_id = swab(thread_id); | |
136 | ||
137 | uint32_t dep_count; | |
11fdf7f2 | 138 | decode(dep_count, it); |
7c673cae FG |
139 | dep_count = swab(dep_count); |
140 | dependencies.resize(dep_count); | |
141 | for (uint32_t i = 0; i < dep_count; ++i) { | |
142 | dependencies[i].decode(0, it); | |
143 | } | |
144 | } else { | |
11fdf7f2 | 145 | decode(dependencies, it); |
7c673cae FG |
146 | } |
147 | } | |
148 | ||
149 | void ActionBase::dump(Formatter *f) const { | |
150 | f->dump_unsigned("id", id); | |
151 | f->dump_unsigned("thread_id", thread_id); | |
152 | f->open_array_section("dependencies"); | |
153 | for (size_t i = 0; i < dependencies.size(); ++i) { | |
154 | f->open_object_section("dependency"); | |
155 | dependencies[i].dump(f); | |
156 | f->close_section(); | |
157 | } | |
158 | f->close_section(); | |
159 | } | |
160 | ||
161 | void ImageActionBase::encode(bufferlist &bl) const { | |
11fdf7f2 | 162 | using ceph::encode; |
7c673cae | 163 | ActionBase::encode(bl); |
11fdf7f2 | 164 | encode(imagectx_id, bl); |
7c673cae FG |
165 | } |
166 | ||
11fdf7f2 TL |
167 | void ImageActionBase::decode(__u8 version, bufferlist::const_iterator &it) { |
168 | using ceph::decode; | |
7c673cae | 169 | ActionBase::decode(version, it); |
11fdf7f2 | 170 | decode(imagectx_id, it); |
7c673cae FG |
171 | if (byte_swap_required(version)) { |
172 | imagectx_id = swab(imagectx_id); | |
173 | } | |
174 | } | |
175 | ||
176 | void ImageActionBase::dump(Formatter *f) const { | |
177 | ActionBase::dump(f); | |
178 | f->dump_unsigned("imagectx_id", imagectx_id); | |
179 | } | |
180 | ||
181 | void IoActionBase::encode(bufferlist &bl) const { | |
11fdf7f2 | 182 | using ceph::encode; |
7c673cae | 183 | ImageActionBase::encode(bl); |
11fdf7f2 TL |
184 | encode(offset, bl); |
185 | encode(length, bl); | |
7c673cae FG |
186 | } |
187 | ||
11fdf7f2 TL |
188 | void IoActionBase::decode(__u8 version, bufferlist::const_iterator &it) { |
189 | using ceph::decode; | |
7c673cae | 190 | ImageActionBase::decode(version, it); |
11fdf7f2 TL |
191 | decode(offset, it); |
192 | decode(length, it); | |
7c673cae FG |
193 | if (byte_swap_required(version)) { |
194 | offset = swab(offset); | |
195 | length = swab(length); | |
196 | } | |
197 | } | |
198 | ||
199 | void IoActionBase::dump(Formatter *f) const { | |
200 | ImageActionBase::dump(f); | |
201 | f->dump_unsigned("offset", offset); | |
202 | f->dump_unsigned("length", length); | |
203 | } | |
204 | ||
205 | void OpenImageAction::encode(bufferlist &bl) const { | |
11fdf7f2 | 206 | using ceph::encode; |
7c673cae | 207 | ImageActionBase::encode(bl); |
11fdf7f2 TL |
208 | encode(name, bl); |
209 | encode(snap_name, bl); | |
210 | encode(read_only, bl); | |
7c673cae FG |
211 | } |
212 | ||
11fdf7f2 TL |
213 | void OpenImageAction::decode(__u8 version, bufferlist::const_iterator &it) { |
214 | using ceph::decode; | |
7c673cae FG |
215 | ImageActionBase::decode(version, it); |
216 | if (byte_swap_required(version)) { | |
217 | decode_big_endian_string(name, it); | |
218 | decode_big_endian_string(snap_name, it); | |
219 | } else { | |
11fdf7f2 TL |
220 | decode(name, it); |
221 | decode(snap_name, it); | |
7c673cae | 222 | } |
11fdf7f2 | 223 | decode(read_only, it); |
7c673cae FG |
224 | } |
225 | ||
226 | void OpenImageAction::dump(Formatter *f) const { | |
227 | ImageActionBase::dump(f); | |
228 | f->dump_string("name", name); | |
229 | f->dump_string("snap_name", snap_name); | |
230 | f->dump_bool("read_only", read_only); | |
231 | } | |
232 | ||
233 | void AioOpenImageAction::encode(bufferlist &bl) const { | |
11fdf7f2 | 234 | using ceph::encode; |
7c673cae | 235 | ImageActionBase::encode(bl); |
11fdf7f2 TL |
236 | encode(name, bl); |
237 | encode(snap_name, bl); | |
238 | encode(read_only, bl); | |
7c673cae FG |
239 | } |
240 | ||
11fdf7f2 TL |
241 | void AioOpenImageAction::decode(__u8 version, bufferlist::const_iterator &it) { |
242 | using ceph::decode; | |
7c673cae FG |
243 | ImageActionBase::decode(version, it); |
244 | if (byte_swap_required(version)) { | |
245 | decode_big_endian_string(name, it); | |
246 | decode_big_endian_string(snap_name, it); | |
247 | } else { | |
11fdf7f2 TL |
248 | decode(name, it); |
249 | decode(snap_name, it); | |
7c673cae | 250 | } |
11fdf7f2 | 251 | decode(read_only, it); |
7c673cae FG |
252 | } |
253 | ||
254 | void AioOpenImageAction::dump(Formatter *f) const { | |
255 | ImageActionBase::dump(f); | |
256 | f->dump_string("name", name); | |
257 | f->dump_string("snap_name", snap_name); | |
258 | f->dump_bool("read_only", read_only); | |
259 | } | |
260 | ||
261 | void UnknownAction::encode(bufferlist &bl) const { | |
11fdf7f2 | 262 | ceph_abort(); |
7c673cae FG |
263 | } |
264 | ||
11fdf7f2 | 265 | void UnknownAction::decode(__u8 version, bufferlist::const_iterator &it) { |
7c673cae FG |
266 | } |
267 | ||
268 | void UnknownAction::dump(Formatter *f) const { | |
269 | } | |
270 | ||
271 | void ActionEntry::encode(bufferlist &bl) const { | |
272 | ENCODE_START(1, 1, bl); | |
273 | boost::apply_visitor(EncodeVisitor(bl), action); | |
274 | ENCODE_FINISH(bl); | |
275 | } | |
276 | ||
11fdf7f2 | 277 | void ActionEntry::decode(bufferlist::const_iterator &it) { |
7c673cae | 278 | DECODE_START(1, it); |
9f95a23c | 279 | decode_versioned(struct_v, it); |
7c673cae FG |
280 | DECODE_FINISH(it); |
281 | } | |
282 | ||
11fdf7f2 | 283 | void ActionEntry::decode_unversioned(bufferlist::const_iterator &it) { |
9f95a23c | 284 | decode_versioned(0, it); |
7c673cae FG |
285 | } |
286 | ||
9f95a23c | 287 | void ActionEntry::decode_versioned(__u8 version, bufferlist::const_iterator &it) { |
11fdf7f2 | 288 | using ceph::decode; |
7c673cae | 289 | uint8_t action_type; |
11fdf7f2 | 290 | decode(action_type, it); |
7c673cae FG |
291 | |
292 | // select the correct action variant based upon the action_type | |
293 | switch (action_type) { | |
294 | case ACTION_TYPE_START_THREAD: | |
295 | action = StartThreadAction(); | |
296 | break; | |
297 | case ACTION_TYPE_STOP_THREAD: | |
298 | action = StopThreadAction(); | |
299 | break; | |
300 | case ACTION_TYPE_READ: | |
301 | action = ReadAction(); | |
302 | break; | |
303 | case ACTION_TYPE_WRITE: | |
304 | action = WriteAction(); | |
305 | break; | |
306 | case ACTION_TYPE_DISCARD: | |
307 | action = DiscardAction(); | |
308 | break; | |
309 | case ACTION_TYPE_AIO_READ: | |
310 | action = AioReadAction(); | |
311 | break; | |
312 | case ACTION_TYPE_AIO_WRITE: | |
313 | action = AioWriteAction(); | |
314 | break; | |
315 | case ACTION_TYPE_AIO_DISCARD: | |
316 | action = AioDiscardAction(); | |
317 | break; | |
318 | case ACTION_TYPE_OPEN_IMAGE: | |
319 | action = OpenImageAction(); | |
320 | break; | |
321 | case ACTION_TYPE_CLOSE_IMAGE: | |
322 | action = CloseImageAction(); | |
323 | break; | |
324 | case ACTION_TYPE_AIO_OPEN_IMAGE: | |
325 | action = AioOpenImageAction(); | |
326 | break; | |
327 | case ACTION_TYPE_AIO_CLOSE_IMAGE: | |
328 | action = AioCloseImageAction(); | |
329 | break; | |
330 | } | |
331 | ||
332 | boost::apply_visitor(DecodeVisitor(version, it), action); | |
333 | } | |
334 | ||
335 | void ActionEntry::dump(Formatter *f) const { | |
336 | boost::apply_visitor(DumpVisitor(f), action); | |
337 | } | |
338 | ||
339 | void ActionEntry::generate_test_instances(std::list<ActionEntry *> &o) { | |
340 | Dependencies dependencies; | |
341 | dependencies.push_back(Dependency(3, 123456789)); | |
342 | dependencies.push_back(Dependency(4, 234567890)); | |
343 | ||
344 | o.push_back(new ActionEntry(StartThreadAction())); | |
345 | o.push_back(new ActionEntry(StartThreadAction(1, 123456789, dependencies))); | |
346 | o.push_back(new ActionEntry(StopThreadAction())); | |
347 | o.push_back(new ActionEntry(StopThreadAction(1, 123456789, dependencies))); | |
348 | ||
349 | o.push_back(new ActionEntry(ReadAction())); | |
350 | o.push_back(new ActionEntry(ReadAction(1, 123456789, dependencies, 3, 4, 5))); | |
351 | o.push_back(new ActionEntry(WriteAction())); | |
352 | o.push_back(new ActionEntry(WriteAction(1, 123456789, dependencies, 3, 4, | |
353 | 5))); | |
354 | o.push_back(new ActionEntry(DiscardAction())); | |
355 | o.push_back(new ActionEntry(DiscardAction(1, 123456789, dependencies, 3, 4, | |
356 | 5))); | |
357 | o.push_back(new ActionEntry(AioReadAction())); | |
358 | o.push_back(new ActionEntry(AioReadAction(1, 123456789, dependencies, 3, 4, | |
359 | 5))); | |
360 | o.push_back(new ActionEntry(AioWriteAction())); | |
361 | o.push_back(new ActionEntry(AioWriteAction(1, 123456789, dependencies, 3, 4, | |
362 | 5))); | |
363 | o.push_back(new ActionEntry(AioDiscardAction())); | |
364 | o.push_back(new ActionEntry(AioDiscardAction(1, 123456789, dependencies, 3, 4, | |
365 | 5))); | |
366 | ||
367 | o.push_back(new ActionEntry(OpenImageAction())); | |
368 | o.push_back(new ActionEntry(OpenImageAction(1, 123456789, dependencies, 3, | |
369 | "image_name", "snap_name", | |
370 | true))); | |
371 | o.push_back(new ActionEntry(CloseImageAction())); | |
372 | o.push_back(new ActionEntry(CloseImageAction(1, 123456789, dependencies, 3))); | |
373 | ||
374 | o.push_back(new ActionEntry(AioOpenImageAction())); | |
375 | o.push_back(new ActionEntry(AioOpenImageAction(1, 123456789, dependencies, 3, | |
376 | "image_name", "snap_name", | |
377 | true))); | |
378 | o.push_back(new ActionEntry(AioCloseImageAction())); | |
379 | o.push_back(new ActionEntry(AioCloseImageAction(1, 123456789, dependencies, 3))); | |
380 | } | |
381 | ||
7c673cae | 382 | std::ostream &operator<<(std::ostream &out, |
11fdf7f2 | 383 | const ActionType &type) { |
7c673cae FG |
384 | using namespace rbd_replay::action; |
385 | ||
386 | switch (type) { | |
387 | case ACTION_TYPE_START_THREAD: | |
388 | out << "StartThread"; | |
389 | break; | |
390 | case ACTION_TYPE_STOP_THREAD: | |
391 | out << "StopThread"; | |
392 | break; | |
393 | case ACTION_TYPE_READ: | |
394 | out << "Read"; | |
395 | break; | |
396 | case ACTION_TYPE_WRITE: | |
397 | out << "Write"; | |
398 | break; | |
399 | case ACTION_TYPE_DISCARD: | |
400 | out << "Discard"; | |
401 | break; | |
402 | case ACTION_TYPE_AIO_READ: | |
403 | out << "AioRead"; | |
404 | break; | |
405 | case ACTION_TYPE_AIO_WRITE: | |
406 | out << "AioWrite"; | |
407 | break; | |
408 | case ACTION_TYPE_AIO_DISCARD: | |
409 | out << "AioDiscard"; | |
410 | break; | |
411 | case ACTION_TYPE_OPEN_IMAGE: | |
412 | out << "OpenImage"; | |
413 | break; | |
414 | case ACTION_TYPE_CLOSE_IMAGE: | |
415 | out << "CloseImage"; | |
416 | break; | |
417 | case ACTION_TYPE_AIO_OPEN_IMAGE: | |
418 | out << "AioOpenImage"; | |
419 | break; | |
420 | case ACTION_TYPE_AIO_CLOSE_IMAGE: | |
421 | out << "AioCloseImage"; | |
422 | break; | |
423 | default: | |
424 | out << "Unknown (" << static_cast<uint32_t>(type) << ")"; | |
425 | break; | |
426 | } | |
427 | return out; | |
428 | } | |
429 | ||
11fdf7f2 TL |
430 | } // namespace action |
431 | } // namespace rbd_replay |