Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / librbd / operation / Request.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #ifndef CEPH_LIBRBD_OPERATION_REQUEST_H
5 #define CEPH_LIBRBD_OPERATION_REQUEST_H
6
7 #include "librbd/AsyncRequest.h"
8 #include "include/Context.h"
9 #include "common/RWLock.h"
10 #include "librbd/Utils.h"
11 #include "librbd/Journal.h"
12
13 namespace librbd {
14
15 class ImageCtx;
16
17 namespace operation {
18
19 template <typename ImageCtxT = ImageCtx>
20 class Request : public AsyncRequest<ImageCtxT> {
21 public:
22   Request(ImageCtxT &image_ctx, Context *on_finish,
23           uint64_t journal_op_tid = 0);
24
25   void send();
26
27 protected:
28   void finish(int r) override;
29   virtual void send_op() = 0;
30
31   virtual bool can_affect_io() const {
32     return false;
33   }
34   virtual journal::Event create_event(uint64_t op_tid) const = 0;
35
36   template <typename T, Context*(T::*MF)(int*)>
37   bool append_op_event(T *request) {
38     ImageCtxT &image_ctx = this->m_image_ctx;
39
40     assert(can_affect_io());
41     RWLock::RLocker owner_locker(image_ctx.owner_lock);
42     RWLock::RLocker snap_locker(image_ctx.snap_lock);
43     if (image_ctx.journal != nullptr) {
44       if (image_ctx.journal->is_journal_replaying()) {
45         Context *ctx = util::create_context_callback<T, MF>(request);
46         replay_op_ready(ctx);
47         return true;
48       } else if (image_ctx.journal->is_journal_appending()) {
49         Context *ctx = util::create_context_callback<T, MF>(request);
50         append_op_event(ctx);
51         return true;
52       }
53     }
54     return false;
55   }
56
57   bool append_op_event();
58
59   // NOTE: temporary until converted to new state machine format
60   Context *create_context_finisher(int r);
61   void finish_and_destroy(int r) override;
62
63 private:
64   struct C_AppendOpEvent : public Context {
65     Request *request;
66     Context *on_safe;
67     C_AppendOpEvent(Request *request, Context *on_safe)
68       : request(request), on_safe(on_safe) {
69     }
70     void finish(int r) override {
71       if (r >= 0) {
72         request->m_appended_op_event = true;
73       }
74       on_safe->complete(r);
75     }
76   };
77
78   struct C_CommitOpEvent : public Context {
79     Request *request;
80     int ret_val;
81     C_CommitOpEvent(Request *request, int ret_val)
82       : request(request), ret_val(ret_val) {
83     }
84     void finish(int r) override {
85       request->handle_commit_op_event(r, ret_val);
86       delete request;
87     }
88   };
89
90   uint64_t m_op_tid = 0;
91   bool m_appended_op_event = false;
92   bool m_committed_op_event = false;
93
94   void replay_op_ready(Context *on_safe);
95   void append_op_event(Context *on_safe);
96   void handle_op_event_safe(int r);
97
98   bool commit_op_event(int r);
99   void handle_commit_op_event(int r, int original_ret_val);
100
101 };
102
103 } // namespace operation
104 } // namespace librbd
105
106 extern template class librbd::operation::Request<librbd::ImageCtx>;
107
108 #endif // CEPH_LIBRBD_OPERATION_REQUEST_H