Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / librados / AioCompletionImpl.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2004-2012 Sage Weil <sage@newdream.net>
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software
11  * Foundation.  See file COPYING.
12  *
13  */
14
15 #ifndef CEPH_LIBRADOS_AIOCOMPLETIONIMPL_H
16 #define CEPH_LIBRADOS_AIOCOMPLETIONIMPL_H
17
18 #include "common/Cond.h"
19 #include "common/Mutex.h"
20
21 #include "include/buffer.h"
22 #include "include/rados/librados.h"
23 #include "include/rados/librados.hpp"
24 #include "include/xlist.h"
25 #include "osd/osd_types.h"
26
27 class IoCtxImpl;
28
29 struct librados::AioCompletionImpl {
30   Mutex lock;
31   Cond cond;
32   int ref, rval;
33   bool released;
34   bool complete;
35   version_t objver;
36   ceph_tid_t tid;
37
38   rados_callback_t callback_complete, callback_safe;
39   void *callback_complete_arg, *callback_safe_arg;
40
41   // for read
42   bool is_read;
43   bufferlist bl;
44   bufferlist *blp;
45   char *out_buf;
46
47   IoCtxImpl *io;
48   ceph_tid_t aio_write_seq;
49   xlist<AioCompletionImpl*>::item aio_write_list_item;
50
51   AioCompletionImpl() : lock("AioCompletionImpl lock", false, false),
52                         ref(1), rval(0), released(false),
53                         complete(false),
54                         objver(0),
55                         tid(0),
56                         callback_complete(0),
57                         callback_safe(0),
58                         callback_complete_arg(0),
59                         callback_safe_arg(0),
60                         is_read(false), blp(nullptr), out_buf(nullptr),
61                         io(NULL), aio_write_seq(0), aio_write_list_item(this) { }
62
63   int set_complete_callback(void *cb_arg, rados_callback_t cb) {
64     lock.Lock();
65     callback_complete = cb;
66     callback_complete_arg = cb_arg;
67     lock.Unlock();
68     return 0;
69   }
70   int set_safe_callback(void *cb_arg, rados_callback_t cb) {
71     lock.Lock();
72     callback_safe = cb;
73     callback_safe_arg = cb_arg;
74     lock.Unlock();
75     return 0;
76   }
77   int wait_for_complete() {
78     lock.Lock();
79     while (!complete)
80       cond.Wait(lock);
81     lock.Unlock();
82     return 0;
83   }
84   int wait_for_safe() {
85     return wait_for_complete();
86   }
87   int is_complete() {
88     lock.Lock();
89     int r = complete;
90     lock.Unlock();
91     return r;
92   }
93   int is_safe() {
94     return is_complete();
95   }
96   int wait_for_complete_and_cb() {
97     lock.Lock();
98     while (!complete || callback_complete || callback_safe)
99       cond.Wait(lock);
100     lock.Unlock();
101     return 0;
102   }
103   int wait_for_safe_and_cb() {
104     return wait_for_complete_and_cb();
105   }
106   int is_complete_and_cb() {
107     lock.Lock();
108     int r = complete && !callback_complete && !callback_safe;
109     lock.Unlock();
110     return r;
111   }
112   int is_safe_and_cb() {
113     return is_complete_and_cb();
114   }
115   int get_return_value() {
116     lock.Lock();
117     int r = rval;
118     lock.Unlock();
119     return r;
120   }
121   uint64_t get_version() {
122     lock.Lock();
123     version_t v = objver;
124     lock.Unlock();
125     return v;
126   }
127
128   void get() {
129     lock.Lock();
130     _get();
131     lock.Unlock();
132   }
133   void _get() {
134     assert(lock.is_locked());
135     assert(ref > 0);
136     ++ref;
137   }
138   void release() {
139     lock.Lock();
140     assert(!released);
141     released = true;
142     put_unlock();
143   }
144   void put() {
145     lock.Lock();
146     put_unlock();
147   }
148   void put_unlock() {
149     assert(ref > 0);
150     int n = --ref;
151     lock.Unlock();
152     if (!n)
153       delete this;
154   }
155 };
156
157 namespace librados {
158 struct C_AioComplete : public Context {
159   AioCompletionImpl *c;
160
161   explicit C_AioComplete(AioCompletionImpl *cc) : c(cc) {
162     c->_get();
163   }
164
165   void finish(int r) override {
166     rados_callback_t cb_complete = c->callback_complete;
167     void *cb_complete_arg = c->callback_complete_arg;
168     if (cb_complete)
169       cb_complete(c, cb_complete_arg);
170
171     rados_callback_t cb_safe = c->callback_safe;
172     void *cb_safe_arg = c->callback_safe_arg;
173     if (cb_safe)
174       cb_safe(c, cb_safe_arg);
175
176     c->lock.Lock();
177     c->callback_complete = NULL;
178     c->callback_safe = NULL;
179     c->cond.Signal();
180     c->put_unlock();
181   }
182 };
183
184 /**
185   * Fills in all completed request data, and calls both
186   * complete and safe callbacks if they exist.
187   *
188   * Not useful for usual I/O, but for special things like
189   * flush where we only want to wait for things to be safe,
190   * but allow users to specify any of the callbacks.
191   */
192 struct C_AioCompleteAndSafe : public Context {
193   AioCompletionImpl *c;
194
195   explicit C_AioCompleteAndSafe(AioCompletionImpl *cc) : c(cc) {
196     c->get();
197   }
198
199   void finish(int r) override {
200     c->lock.Lock();
201     c->rval = r;
202     c->complete = true;
203     c->lock.Unlock();
204
205     rados_callback_t cb_complete = c->callback_complete;
206     void *cb_complete_arg = c->callback_complete_arg;
207     if (cb_complete)
208       cb_complete(c, cb_complete_arg);
209
210     rados_callback_t cb_safe = c->callback_safe;
211     void *cb_safe_arg = c->callback_safe_arg;
212     if (cb_safe)
213       cb_safe(c, cb_safe_arg);
214
215     c->lock.Lock();
216     c->callback_complete = NULL;
217     c->callback_safe = NULL;
218     c->cond.Signal();
219     c->put_unlock();
220   }
221 };
222
223 }
224
225 #endif