1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/librados_test_stub/TestIoCtxImpl.h"
5 #include "test/librados_test_stub/TestClassHandler.h"
6 #include "test/librados_test_stub/TestRadosClient.h"
7 #include "test/librados_test_stub/TestWatchNotify.h"
8 #include "librados/AioCompletionImpl.h"
9 #include "include/assert.h"
10 #include "common/Finisher.h"
11 #include "common/valgrind.h"
12 #include "objclass/objclass.h"
13 #include <boost/bind.hpp>
18 TestIoCtxImpl::TestIoCtxImpl() : m_client(NULL) {
22 TestIoCtxImpl::TestIoCtxImpl(TestRadosClient *client, int64_t pool_id,
23 const std::string& pool_name)
24 : m_client(client), m_pool_id(pool_id), m_pool_name(pool_name),
25 m_snap_seq(CEPH_NOSNAP)
31 TestIoCtxImpl::TestIoCtxImpl(const TestIoCtxImpl& rhs)
32 : m_client(rhs.m_client),
33 m_pool_id(rhs.m_pool_id),
34 m_pool_name(rhs.m_pool_name),
35 m_snap_seq(rhs.m_snap_seq)
41 TestIoCtxImpl::~TestIoCtxImpl() {
42 assert(m_pending_ops == 0);
45 void TestObjectOperationImpl::get() {
49 void TestObjectOperationImpl::put() {
50 if (--m_refcount == 0) {
51 ANNOTATE_HAPPENS_AFTER(&m_refcount);
52 ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(&m_refcount);
55 ANNOTATE_HAPPENS_BEFORE(&m_refcount);
59 void TestIoCtxImpl::get() {
63 void TestIoCtxImpl::put() {
64 if (--m_refcount == 0) {
70 uint64_t TestIoCtxImpl::get_instance_id() const {
71 return m_client->get_instance_id();
74 int64_t TestIoCtxImpl::get_id() {
78 uint64_t TestIoCtxImpl::get_last_version() {
82 std::string TestIoCtxImpl::get_pool_name() {
86 int TestIoCtxImpl::aio_flush() {
87 m_client->flush_aio_operations();
91 void TestIoCtxImpl::aio_flush_async(AioCompletionImpl *c) {
92 m_client->flush_aio_operations(c);
95 void TestIoCtxImpl::aio_notify(const std::string& oid, AioCompletionImpl *c,
96 bufferlist& bl, uint64_t timeout_ms,
100 C_AioNotify *ctx = new C_AioNotify(this, c);
101 m_client->get_watch_notify()->aio_notify(m_client, oid, bl, timeout_ms, pbl,
105 int TestIoCtxImpl::aio_operate(const std::string& oid, TestObjectOperationImpl &ops,
106 AioCompletionImpl *c, SnapContext *snap_context,
108 // TODO flags for now
111 m_client->add_aio_operation(oid, true, boost::bind(
112 &TestIoCtxImpl::execute_aio_operations, this, oid, &ops,
113 reinterpret_cast<bufferlist*>(0),
114 snap_context != NULL ? *snap_context : m_snapc), c);
118 int TestIoCtxImpl::aio_operate_read(const std::string& oid,
119 TestObjectOperationImpl &ops,
120 AioCompletionImpl *c, int flags,
122 // TODO ignoring flags for now
125 m_client->add_aio_operation(oid, true, boost::bind(
126 &TestIoCtxImpl::execute_aio_operations, this, oid, &ops, pbl, m_snapc), c);
130 int TestIoCtxImpl::aio_watch(const std::string& o, AioCompletionImpl *c,
131 uint64_t *handle, librados::WatchCtx2 *watch_ctx) {
134 C_AioNotify *ctx = new C_AioNotify(this, c);
135 if (m_client->is_blacklisted()) {
136 m_client->get_aio_finisher()->queue(ctx, -EBLACKLISTED);
138 m_client->get_watch_notify()->aio_watch(m_client, o, get_instance_id(),
139 handle, watch_ctx, ctx);
144 int TestIoCtxImpl::aio_unwatch(uint64_t handle, AioCompletionImpl *c) {
147 C_AioNotify *ctx = new C_AioNotify(this, c);
148 if (m_client->is_blacklisted()) {
149 m_client->get_aio_finisher()->queue(ctx, -EBLACKLISTED);
151 m_client->get_watch_notify()->aio_unwatch(m_client, handle, ctx);
156 int TestIoCtxImpl::exec(const std::string& oid, TestClassHandler *handler,
157 const char *cls, const char *method,
158 bufferlist& inbl, bufferlist* outbl,
159 const SnapContext &snapc) {
160 if (m_client->is_blacklisted()) {
161 return -EBLACKLISTED;
164 cls_method_cxx_call_t call = handler->get_method(cls, method);
169 return (*call)(reinterpret_cast<cls_method_context_t>(
170 handler->get_method_context(this, oid, snapc).get()), &inbl, outbl);
173 int TestIoCtxImpl::list_watchers(const std::string& o,
174 std::list<obj_watch_t> *out_watchers) {
175 if (m_client->is_blacklisted()) {
176 return -EBLACKLISTED;
179 return m_client->get_watch_notify()->list_watchers(o, out_watchers);
182 int TestIoCtxImpl::notify(const std::string& o, bufferlist& bl,
183 uint64_t timeout_ms, bufferlist *pbl) {
184 if (m_client->is_blacklisted()) {
185 return -EBLACKLISTED;
188 return m_client->get_watch_notify()->notify(m_client, o, bl, timeout_ms, pbl);
191 void TestIoCtxImpl::notify_ack(const std::string& o, uint64_t notify_id,
192 uint64_t handle, bufferlist& bl) {
193 m_client->get_watch_notify()->notify_ack(m_client, o, notify_id, handle,
194 m_client->get_instance_id(), bl);
197 int TestIoCtxImpl::operate(const std::string& oid, TestObjectOperationImpl &ops) {
198 AioCompletionImpl *comp = new AioCompletionImpl();
202 m_client->add_aio_operation(oid, false, boost::bind(
203 &TestIoCtxImpl::execute_aio_operations, this, oid, &ops,
204 reinterpret_cast<bufferlist*>(0), m_snapc), comp);
206 comp->wait_for_safe();
207 int ret = comp->get_return_value();
212 int TestIoCtxImpl::operate_read(const std::string& oid, TestObjectOperationImpl &ops,
214 AioCompletionImpl *comp = new AioCompletionImpl();
218 m_client->add_aio_operation(oid, false, boost::bind(
219 &TestIoCtxImpl::execute_aio_operations, this, oid, &ops, pbl,
222 comp->wait_for_complete();
223 int ret = comp->get_return_value();
228 void TestIoCtxImpl::aio_selfmanaged_snap_create(uint64_t *snapid,
229 AioCompletionImpl *c) {
230 m_client->add_aio_operation(
232 boost::bind(&TestIoCtxImpl::selfmanaged_snap_create, this, snapid), c);
235 void TestIoCtxImpl::aio_selfmanaged_snap_remove(uint64_t snapid,
236 AioCompletionImpl *c) {
237 m_client->add_aio_operation(
239 boost::bind(&TestIoCtxImpl::selfmanaged_snap_remove, this, snapid), c);
242 int TestIoCtxImpl::selfmanaged_snap_set_write_ctx(snap_t seq,
243 std::vector<snap_t>& snaps) {
244 std::vector<snapid_t> snap_ids(snaps.begin(), snaps.end());
245 m_snapc = SnapContext(seq, snap_ids);
249 int TestIoCtxImpl::set_alloc_hint(const std::string& oid,
250 uint64_t expected_object_size,
251 uint64_t expected_write_size) {
255 void TestIoCtxImpl::set_snap_read(snap_t seq) {
262 int TestIoCtxImpl::tmap_update(const std::string& oid, bufferlist& cmdbl) {
263 if (m_client->is_blacklisted()) {
264 return -EBLACKLISTED;
267 // TODO: protect against concurrent tmap updates
268 bufferlist tmap_header;
269 std::map<string,bufferlist> tmap;
271 int r = stat(oid, &size, NULL);
273 r = create(oid, false);
281 r = read(oid, size, 0, &inbl);
285 bufferlist::iterator iter = inbl.begin();
286 ::decode(tmap_header, iter);
287 ::decode(tmap, iter);
293 bufferlist::iterator iter = cmdbl.begin();
298 case CEPH_OSD_TMAP_SET:
299 ::decode(value, iter);
302 case CEPH_OSD_TMAP_RM:
313 ::encode(tmap_header, out);
315 r = write_full(oid, out, m_snapc);
319 int TestIoCtxImpl::unwatch(uint64_t handle) {
320 if (m_client->is_blacklisted()) {
321 return -EBLACKLISTED;
324 return m_client->get_watch_notify()->unwatch(m_client, handle);
327 int TestIoCtxImpl::watch(const std::string& o, uint64_t *handle,
328 librados::WatchCtx *ctx, librados::WatchCtx2 *ctx2) {
329 if (m_client->is_blacklisted()) {
330 return -EBLACKLISTED;
333 return m_client->get_watch_notify()->watch(m_client, o, get_instance_id(),
337 int TestIoCtxImpl::execute_operation(const std::string& oid,
338 const Operation &operation) {
339 if (m_client->is_blacklisted()) {
340 return -EBLACKLISTED;
343 TestRadosClient::Transaction transaction(m_client, oid);
344 return operation(this, oid);
347 int TestIoCtxImpl::execute_aio_operations(const std::string& oid,
348 TestObjectOperationImpl *ops,
350 const SnapContext &snapc) {
352 if (m_client->is_blacklisted()) {
355 TestRadosClient::Transaction transaction(m_client, oid);
356 for (ObjectOperations::iterator it = ops->ops.begin();
357 it != ops->ops.end(); ++it) {
358 ret = (*it)(this, oid, pbl, snapc);
369 void TestIoCtxImpl::handle_aio_notify_complete(AioCompletionImpl *c, int r) {
372 m_client->finish_aio_completion(c, r);
375 } // namespace librados