]>
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 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2014 Sebastien Ponce <sebastien.ponce@cern.ch> | |
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_LIBRADOSSTRIPERSTRIPER_MULTIAIOCOMPLETIONIMPL_H | |
16 | #define CEPH_LIBRADOSSTRIPERSTRIPER_MULTIAIOCOMPLETIONIMPL_H | |
17 | ||
18 | #include "common/Cond.h" | |
19 | #include "common/Mutex.h" | |
20 | ||
21 | #include "include/radosstriper/libradosstriper.hpp" | |
22 | ||
23 | struct libradosstriper::MultiAioCompletionImpl { | |
24 | ||
25 | Mutex lock; | |
26 | Cond cond; | |
27 | int ref, rval; | |
28 | int pending_complete, pending_safe; | |
29 | rados_callback_t callback_complete, callback_safe; | |
30 | void *callback_complete_arg, *callback_safe_arg; | |
31 | bool building; ///< true if we are still building this completion | |
32 | bufferlist bl; /// only used for read case in C api of rados striper | |
33 | std::list<bufferlist*> bllist; /// keep temporary buffer lists used for destriping | |
34 | ||
35 | MultiAioCompletionImpl() : lock("MultiAioCompletionImpl lock", false, false), | |
36 | ref(1), rval(0), | |
37 | pending_complete(0), pending_safe(0), | |
38 | callback_complete(0), callback_safe(0), | |
39 | callback_complete_arg(0), callback_safe_arg(0), | |
40 | building(true) {}; | |
41 | ||
42 | ~MultiAioCompletionImpl() { | |
43 | // deallocate temporary buffer lists | |
44 | for (std::list<bufferlist*>::iterator it = bllist.begin(); | |
45 | it != bllist.end(); | |
46 | it++) { | |
47 | delete *it; | |
48 | } | |
49 | bllist.clear(); | |
50 | } | |
51 | ||
52 | int set_complete_callback(void *cb_arg, rados_callback_t cb) { | |
53 | lock.Lock(); | |
54 | callback_complete = cb; | |
55 | callback_complete_arg = cb_arg; | |
56 | lock.Unlock(); | |
57 | return 0; | |
58 | } | |
59 | int set_safe_callback(void *cb_arg, rados_callback_t cb) { | |
60 | lock.Lock(); | |
61 | callback_safe = cb; | |
62 | callback_safe_arg = cb_arg; | |
63 | lock.Unlock(); | |
64 | return 0; | |
65 | } | |
66 | int wait_for_complete() { | |
67 | lock.Lock(); | |
68 | while (pending_complete) | |
69 | cond.Wait(lock); | |
70 | lock.Unlock(); | |
71 | return 0; | |
72 | } | |
73 | int wait_for_safe() { | |
74 | lock.Lock(); | |
75 | while (pending_safe) | |
76 | cond.Wait(lock); | |
77 | lock.Unlock(); | |
78 | return 0; | |
79 | } | |
80 | bool is_complete() { | |
81 | lock.Lock(); | |
82 | int r = pending_complete; | |
83 | lock.Unlock(); | |
84 | return 0 == r; | |
85 | } | |
86 | bool is_safe() { | |
87 | lock.Lock(); | |
88 | int r = pending_safe; | |
89 | lock.Unlock(); | |
90 | return r == 0; | |
91 | } | |
92 | void wait_for_complete_and_cb() { | |
93 | lock.Lock(); | |
94 | while (pending_complete || callback_complete) | |
95 | cond.Wait(lock); | |
96 | lock.Unlock(); | |
97 | } | |
98 | void wait_for_safe_and_cb() { | |
99 | lock.Lock(); | |
100 | while (pending_safe || callback_safe) | |
101 | cond.Wait(lock); | |
102 | lock.Unlock(); | |
103 | } | |
104 | bool is_complete_and_cb() { | |
105 | lock.Lock(); | |
106 | bool r = ((0 == pending_complete) && !callback_complete); | |
107 | lock.Unlock(); | |
108 | return r; | |
109 | } | |
110 | bool is_safe_and_cb() { | |
111 | lock.Lock(); | |
112 | int r = ((0 == pending_safe) && !callback_safe); | |
113 | lock.Unlock(); | |
114 | return r; | |
115 | } | |
116 | int get_return_value() { | |
117 | lock.Lock(); | |
118 | int r = rval; | |
119 | lock.Unlock(); | |
120 | return r; | |
121 | } | |
122 | void get() { | |
123 | lock.Lock(); | |
124 | _get(); | |
125 | lock.Unlock(); | |
126 | } | |
127 | void _get() { | |
128 | assert(lock.is_locked()); | |
129 | assert(ref > 0); | |
130 | ++ref; | |
131 | } | |
132 | void put() { | |
133 | lock.Lock(); | |
134 | put_unlock(); | |
135 | } | |
136 | void put_unlock() { | |
137 | assert(ref > 0); | |
138 | int n = --ref; | |
139 | lock.Unlock(); | |
140 | if (!n) | |
141 | delete this; | |
142 | } | |
143 | void add_request() { | |
144 | lock.Lock(); | |
145 | pending_complete++; | |
146 | _get(); | |
147 | pending_safe++; | |
148 | _get(); | |
149 | lock.Unlock(); | |
150 | } | |
151 | void add_safe_request() { | |
152 | lock.Lock(); | |
153 | pending_complete++; | |
154 | _get(); | |
155 | lock.Unlock(); | |
156 | } | |
157 | void complete() { | |
158 | assert(lock.is_locked()); | |
159 | if (callback_complete) { | |
160 | callback_complete(this, callback_complete_arg); | |
161 | callback_complete = 0; | |
162 | } | |
163 | cond.Signal(); | |
164 | } | |
165 | void safe() { | |
166 | assert(lock.is_locked()); | |
167 | if (callback_safe) { | |
168 | callback_safe(this, callback_safe_arg); | |
169 | callback_safe = 0; | |
170 | } | |
171 | cond.Signal(); | |
172 | }; | |
173 | ||
174 | void complete_request(ssize_t r); | |
175 | void safe_request(ssize_t r); | |
176 | void finish_adding_requests(); | |
177 | ||
178 | }; | |
179 | ||
224ce89b WB |
180 | void intrusive_ptr_add_ref(libradosstriper::MultiAioCompletionImpl*); |
181 | void intrusive_ptr_release(libradosstriper::MultiAioCompletionImpl*); | |
182 | ||
7c673cae | 183 | #endif // CEPH_LIBRADOSSTRIPERSTRIPER_MULTIAIOCOMPLETIONIMPL_H |