]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librados_test_stub/TestRadosClient.cc
import 15.2.5
[ceph.git] / ceph / src / test / librados_test_stub / TestRadosClient.cc
CommitLineData
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 "test/librados_test_stub/TestRadosClient.h"
5#include "test/librados_test_stub/TestIoCtxImpl.h"
6#include "librados/AioCompletionImpl.h"
11fdf7f2 7#include "include/ceph_assert.h"
7c673cae
FG
8#include "common/ceph_json.h"
9#include "common/Finisher.h"
10#include <boost/bind.hpp>
11#include <boost/thread.hpp>
12#include <errno.h>
13
31f18b77 14#include <atomic>
11fdf7f2 15#include <sstream>
31f18b77 16
7c673cae
FG
17static int get_concurrency() {
18 int concurrency = 0;
19 char *env = getenv("LIBRADOS_CONCURRENCY");
20 if (env != NULL) {
21 concurrency = atoi(env);
22 }
23 if (concurrency == 0) {
24 concurrency = boost::thread::thread::hardware_concurrency();
25 }
26 if (concurrency == 0) {
27 concurrency = 1;
28 }
29 return concurrency;
30}
31
32namespace librados {
33
34static void finish_aio_completion(AioCompletionImpl *c, int r) {
9f95a23c 35 c->lock.lock();
7c673cae
FG
36 c->complete = true;
37 c->rval = r;
9f95a23c 38 c->lock.unlock();
7c673cae
FG
39
40 rados_callback_t cb_complete = c->callback_complete;
41 void *cb_complete_arg = c->callback_complete_arg;
42 if (cb_complete) {
43 cb_complete(c, cb_complete_arg);
44 }
45
46 rados_callback_t cb_safe = c->callback_safe;
47 void *cb_safe_arg = c->callback_safe_arg;
48 if (cb_safe) {
49 cb_safe(c, cb_safe_arg);
50 }
51
9f95a23c 52 c->lock.lock();
7c673cae
FG
53 c->callback_complete = NULL;
54 c->callback_safe = NULL;
9f95a23c 55 c->cond.notify_all();
7c673cae
FG
56 c->put_unlock();
57}
58
59class AioFunctionContext : public Context {
60public:
61 AioFunctionContext(const TestRadosClient::AioFunction &callback,
62 Finisher *finisher, AioCompletionImpl *c)
63 : m_callback(callback), m_finisher(finisher), m_comp(c)
64 {
65 if (m_comp != NULL) {
66 m_comp->get();
67 }
68 }
69
70 void finish(int r) override {
71 int ret = m_callback();
72 if (m_comp != NULL) {
73 if (m_finisher != NULL) {
9f95a23c 74 m_finisher->queue(new LambdaContext(boost::bind(
7c673cae
FG
75 &finish_aio_completion, m_comp, ret)));
76 } else {
77 finish_aio_completion(m_comp, ret);
78 }
79 }
80 }
81private:
82 TestRadosClient::AioFunction m_callback;
83 Finisher *m_finisher;
84 AioCompletionImpl *m_comp;
85};
86
87TestRadosClient::TestRadosClient(CephContext *cct,
88 TestWatchNotify *watch_notify)
89 : m_cct(cct->get()), m_watch_notify(watch_notify),
90 m_aio_finisher(new Finisher(m_cct))
91{
92 get();
93
94 // simulate multiple OSDs
95 int concurrency = get_concurrency();
96 for (int i = 0; i < concurrency; ++i) {
97 m_finishers.push_back(new Finisher(m_cct));
98 m_finishers.back()->start();
99 }
100
101 // replicate AIO callback processing
102 m_aio_finisher->start();
103}
104
105TestRadosClient::~TestRadosClient() {
106 flush_aio_operations();
107
108 for (size_t i = 0; i < m_finishers.size(); ++i) {
109 m_finishers[i]->stop();
110 delete m_finishers[i];
111 }
112 m_aio_finisher->stop();
113 delete m_aio_finisher;
114
115 m_cct->put();
116 m_cct = NULL;
117}
118
119void TestRadosClient::get() {
31f18b77 120 m_refcount++;
7c673cae
FG
121}
122
123void TestRadosClient::put() {
31f18b77 124 if (--m_refcount == 0) {
7c673cae
FG
125 shutdown();
126 delete this;
127 }
128}
129
130CephContext *TestRadosClient::cct() {
131 return m_cct;
132}
133
134int TestRadosClient::connect() {
135 return 0;
136}
137
138void TestRadosClient::shutdown() {
139}
140
141int TestRadosClient::wait_for_latest_osdmap() {
142 return 0;
143}
144
145int TestRadosClient::mon_command(const std::vector<std::string>& cmd,
146 const bufferlist &inbl,
147 bufferlist *outbl, std::string *outs) {
148 for (std::vector<std::string>::const_iterator it = cmd.begin();
149 it != cmd.end(); ++it) {
150 JSONParser parser;
151 if (!parser.parse(it->c_str(), it->length())) {
152 return -EINVAL;
153 }
154
155 JSONObjIter j_it = parser.find("prefix");
156 if (j_it.end()) {
157 return -EINVAL;
158 }
159
160 if ((*j_it)->get_data() == "osd tier add") {
161 return 0;
162 } else if ((*j_it)->get_data() == "osd tier cache-mode") {
163 return 0;
164 } else if ((*j_it)->get_data() == "osd tier set-overlay") {
165 return 0;
166 } else if ((*j_it)->get_data() == "osd tier remove-overlay") {
167 return 0;
168 } else if ((*j_it)->get_data() == "osd tier remove") {
169 return 0;
11fdf7f2
TL
170 } else if ((*j_it)->get_data() == "config-key rm") {
171 return 0;
f6b5b4d7
TL
172 } else if ((*j_it)->get_data() == "config set") {
173 return 0;
11fdf7f2
TL
174 } else if ((*j_it)->get_data() == "df") {
175 std::stringstream str;
176 str << R"({"pools": [)";
177
178 std::list<std::pair<int64_t, std::string>> pools;
179 pool_list(pools);
180 for (auto& pool : pools) {
181 if (pools.begin()->first != pool.first) {
182 str << ",";
183 }
184 str << R"({"name": ")" << pool.second << R"(", "stats": )"
185 << R"({"percent_used": 1.0, "bytes_used": 0, "max_avail": 0}})";
186 }
187
188 str << "]}";
189 outbl->append(str.str());
190 return 0;
7c673cae
FG
191 }
192 }
193 return -ENOSYS;
194}
195
196void TestRadosClient::add_aio_operation(const std::string& oid,
197 bool queue_callback,
198 const AioFunction &aio_function,
199 AioCompletionImpl *c) {
200 AioFunctionContext *ctx = new AioFunctionContext(
201 aio_function, queue_callback ? m_aio_finisher : NULL, c);
202 get_finisher(oid)->queue(ctx);
203}
204
205struct WaitForFlush {
206 int flushed() {
31f18b77 207 if (--count == 0) {
9f95a23c 208 aio_finisher->queue(new LambdaContext(boost::bind(
7c673cae
FG
209 &finish_aio_completion, c, 0)));
210 delete this;
211 }
212 return 0;
213 }
214
31f18b77 215 std::atomic<int64_t> count = { 0 };
7c673cae
FG
216 Finisher *aio_finisher;
217 AioCompletionImpl *c;
218};
219
220void TestRadosClient::flush_aio_operations() {
221 AioCompletionImpl *comp = new AioCompletionImpl();
222 flush_aio_operations(comp);
9f95a23c 223 comp->wait_for_complete();
7c673cae
FG
224 comp->put();
225}
226
227void TestRadosClient::flush_aio_operations(AioCompletionImpl *c) {
228 c->get();
229
230 WaitForFlush *wait_for_flush = new WaitForFlush();
31f18b77 231 wait_for_flush->count = m_finishers.size();
7c673cae
FG
232 wait_for_flush->aio_finisher = m_aio_finisher;
233 wait_for_flush->c = c;
234
235 for (size_t i = 0; i < m_finishers.size(); ++i) {
236 AioFunctionContext *ctx = new AioFunctionContext(
237 boost::bind(&WaitForFlush::flushed, wait_for_flush),
238 nullptr, nullptr);
239 m_finishers[i]->queue(ctx);
240 }
241}
242
243int TestRadosClient::aio_watch_flush(AioCompletionImpl *c) {
244 c->get();
9f95a23c 245 Context *ctx = new LambdaContext(boost::bind(
7c673cae
FG
246 &TestRadosClient::finish_aio_completion, this, c, _1));
247 get_watch_notify()->aio_flush(this, ctx);
248 return 0;
249}
250
251void TestRadosClient::finish_aio_completion(AioCompletionImpl *c, int r) {
252 librados::finish_aio_completion(c, r);
253}
254
255Finisher *TestRadosClient::get_finisher(const std::string &oid) {
256 std::size_t h = m_hash(oid);
257 return m_finishers[h % m_finishers.size()];
258}
259
260} // namespace librados