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