From: Jason Dillaman Date: Fri, 4 Sep 2015 18:59:09 +0000 (-0400) Subject: librbd: support templating of ImageCtx for async state machines X-Git-Tag: v9.1.0~172^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=e8749b2a7f5a60dbfa03518315a1f1caa4039f59;p=ceph.git librbd: support templating of ImageCtx for async state machines This will facilitate the creation of unit test mocks to verify non-librados actions. The templates (by default) will be flagged as extern to avoid the translation unit bloat. Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/AsyncFlattenRequest.cc b/src/librbd/AsyncFlattenRequest.cc index 7555b179d511..9136220e57e7 100644 --- a/src/librbd/AsyncFlattenRequest.cc +++ b/src/librbd/AsyncFlattenRequest.cc @@ -18,11 +18,11 @@ namespace librbd { -class AsyncFlattenObjectContext : public C_AsyncObjectThrottle { +class AsyncFlattenObjectContext : public C_AsyncObjectThrottle<> { public: - AsyncFlattenObjectContext(AsyncObjectThrottle &throttle, ImageCtx *image_ctx, - uint64_t object_size, ::SnapContext snapc, - uint64_t object_no) + AsyncFlattenObjectContext(AsyncObjectThrottle<> &throttle, + ImageCtx *image_ctx, uint64_t object_size, + ::SnapContext snapc, uint64_t object_no) : C_AsyncObjectThrottle(throttle, *image_ctx), m_object_size(object_size), m_snapc(snapc), m_object_no(object_no) { @@ -94,11 +94,11 @@ void AsyncFlattenRequest::send() { ldout(cct, 5) << this << " send" << dendl; m_state = STATE_FLATTEN_OBJECTS; - AsyncObjectThrottle::ContextFactory context_factory( + AsyncObjectThrottle<>::ContextFactory context_factory( boost::lambda::bind(boost::lambda::new_ptr(), boost::lambda::_1, &m_image_ctx, m_object_size, m_snapc, boost::lambda::_2)); - AsyncObjectThrottle *throttle = new AsyncObjectThrottle( + AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>( this, m_image_ctx, context_factory, create_callback_context(), &m_prog_ctx, 0, m_overlap_objects); throttle->start_ops(m_image_ctx.concurrent_management_ops); diff --git a/src/librbd/AsyncFlattenRequest.h b/src/librbd/AsyncFlattenRequest.h index c2af903ef4da..01f16671c526 100644 --- a/src/librbd/AsyncFlattenRequest.h +++ b/src/librbd/AsyncFlattenRequest.h @@ -12,7 +12,7 @@ namespace librbd { class ImageCtx; class ProgressContext; -class AsyncFlattenRequest : public AsyncRequest +class AsyncFlattenRequest : public AsyncRequest<> { public: AsyncFlattenRequest(ImageCtx &image_ctx, Context *on_finish, diff --git a/src/librbd/AsyncObjectThrottle.cc b/src/librbd/AsyncObjectThrottle.cc index e6eb4aba9625..59b3a1f6021c 100644 --- a/src/librbd/AsyncObjectThrottle.cc +++ b/src/librbd/AsyncObjectThrottle.cc @@ -3,6 +3,7 @@ #include "librbd/AsyncObjectThrottle.h" #include "include/rbd/librbd.hpp" #include "common/RWLock.h" +#include "common/WorkQueue.h" #include "librbd/AsyncRequest.h" #include "librbd/ImageCtx.h" #include "librbd/internal.h" @@ -10,17 +11,11 @@ namespace librbd { -void C_AsyncObjectThrottle::finish(int r) { - RWLock::RLocker l(m_image_ctx.owner_lock); - m_finisher.finish_op(r); -} - -AsyncObjectThrottle::AsyncObjectThrottle(const AsyncRequest* async_request, - ImageCtx &image_ctx, - const ContextFactory& context_factory, - Context *ctx, ProgressContext *prog_ctx, - uint64_t object_no, - uint64_t end_object_no) +template +AsyncObjectThrottle::AsyncObjectThrottle( + const AsyncRequest* async_request, T &image_ctx, + const ContextFactory& context_factory, Context *ctx, + ProgressContext *prog_ctx, uint64_t object_no, uint64_t end_object_no) : m_lock(unique_lock_name("librbd::AsyncThrottle::m_lock", this)), m_async_request(async_request), m_image_ctx(image_ctx), m_context_factory(context_factory), m_ctx(ctx), m_prog_ctx(prog_ctx), @@ -29,7 +24,8 @@ AsyncObjectThrottle::AsyncObjectThrottle(const AsyncRequest* async_request, { } -void AsyncObjectThrottle::start_ops(uint64_t max_concurrent) { +template +void AsyncObjectThrottle::start_ops(uint64_t max_concurrent) { assert(m_image_ctx.owner_lock.is_locked()); bool complete; { @@ -48,11 +44,12 @@ void AsyncObjectThrottle::start_ops(uint64_t max_concurrent) { } } -void AsyncObjectThrottle::finish_op(int r) { +template +void AsyncObjectThrottle::finish_op(int r) { assert(m_image_ctx.owner_lock.is_locked()); bool complete; { - Mutex::Locker l(m_lock); + Mutex::Locker locker(m_lock); --m_current_ops; if (r < 0 && r != -ENOENT && m_ret == 0) { m_ret = r; @@ -67,7 +64,8 @@ void AsyncObjectThrottle::finish_op(int r) { } } -void AsyncObjectThrottle::start_next_op() { +template +void AsyncObjectThrottle::start_next_op() { bool done = false; while (!done) { if (m_async_request != NULL && m_async_request->is_canceled() && @@ -80,7 +78,7 @@ void AsyncObjectThrottle::start_next_op() { } uint64_t ono = m_object_no++; - C_AsyncObjectThrottle *ctx = m_context_factory(*this, ono); + C_AsyncObjectThrottle *ctx = m_context_factory(*this, ono); int r = ctx->send(); if (r < 0) { @@ -101,3 +99,5 @@ void AsyncObjectThrottle::start_next_op() { } } // namespace librbd + +template class librbd::AsyncObjectThrottle; diff --git a/src/librbd/AsyncObjectThrottle.h b/src/librbd/AsyncObjectThrottle.h index 222baf00d1bd..a83105145a49 100644 --- a/src/librbd/AsyncObjectThrottle.h +++ b/src/librbd/AsyncObjectThrottle.h @@ -5,13 +5,14 @@ #include "include/int_types.h" #include "include/Context.h" +#include "common/RWLock.h" #include #include "include/assert.h" namespace librbd { -class AsyncRequest; +template class AsyncRequest; class ProgressContext; struct ImageCtx; @@ -21,31 +22,37 @@ public: virtual void finish_op(int r) = 0; }; +template class C_AsyncObjectThrottle : public Context { public: C_AsyncObjectThrottle(AsyncObjectThrottleFinisher &finisher, - ImageCtx &image_ctx) - : m_image_ctx(image_ctx), m_finisher(finisher) - { + ImageCtxT &image_ctx) + : m_image_ctx(image_ctx), m_finisher(finisher) { } virtual int send() = 0; protected: - ImageCtx &m_image_ctx; + ImageCtxT &m_image_ctx; - virtual void finish(int r); + virtual void finish(int r) { + RWLock::RLocker locker(m_image_ctx.owner_lock); + m_finisher.finish_op(r); + } private: AsyncObjectThrottleFinisher &m_finisher; }; +template class AsyncObjectThrottle : public AsyncObjectThrottleFinisher { public: - typedef boost::function ContextFactory; + typedef boost::function< + C_AsyncObjectThrottle* (AsyncObjectThrottle&, + uint64_t)> ContextFactory; - AsyncObjectThrottle(const AsyncRequest *async_request, ImageCtx &image_ctx, + AsyncObjectThrottle(const AsyncRequest *async_request, + ImageCtxT &image_ctx, const ContextFactory& context_factory, Context *ctx, ProgressContext *prog_ctx, uint64_t object_no, uint64_t end_object_no); @@ -55,8 +62,8 @@ public: private: Mutex m_lock; - const AsyncRequest *m_async_request; - ImageCtx &m_image_ctx; + const AsyncRequest *m_async_request; + ImageCtxT &m_image_ctx; ContextFactory m_context_factory; Context *m_ctx; ProgressContext *m_prog_ctx; @@ -70,4 +77,6 @@ private: } // namespace librbd +extern template class librbd::AsyncObjectThrottle; + #endif // CEPH_LIBRBD_ASYNC_OBJECT_THROTTLE_H diff --git a/src/librbd/AsyncRequest.cc b/src/librbd/AsyncRequest.cc index 4fcb7afb0947..b6e41eb175ad 100644 --- a/src/librbd/AsyncRequest.cc +++ b/src/librbd/AsyncRequest.cc @@ -3,40 +3,50 @@ #include "librbd/AsyncRequest.h" #include "librbd/ImageCtx.h" #include "librbd/internal.h" +#include "common/WorkQueue.h" #include namespace librbd { -AsyncRequest::AsyncRequest(ImageCtx &image_ctx, Context *on_finish) +template +AsyncRequest::AsyncRequest(T &image_ctx, Context *on_finish) : m_image_ctx(image_ctx), m_on_finish(on_finish), m_canceled(false), m_xlist_item(this) { + assert(m_on_finish != NULL); Mutex::Locker l(m_image_ctx.async_ops_lock); m_image_ctx.async_requests.push_back(&m_xlist_item); } -AsyncRequest::~AsyncRequest() { +template +AsyncRequest::~AsyncRequest() { Mutex::Locker l(m_image_ctx.async_ops_lock); assert(m_xlist_item.remove_myself()); m_image_ctx.async_requests_cond.Signal(); } -void AsyncRequest::async_complete(int r) { +template +void AsyncRequest::async_complete(int r) { m_image_ctx.op_work_queue->queue(create_callback_context(), r); } -librados::AioCompletion *AsyncRequest::create_callback_completion() { +template +librados::AioCompletion *AsyncRequest::create_callback_completion() { return librados::Rados::aio_create_completion(create_callback_context(), NULL, rados_ctx_cb); } -Context *AsyncRequest::create_callback_context() { - return new FunctionContext(boost::bind(&AsyncRequest::complete, this, _1)); +template +Context *AsyncRequest::create_callback_context() { + return new FunctionContext(boost::bind(&AsyncRequest::complete, this, _1)); } -Context *AsyncRequest::create_async_callback_context() { - return new FunctionContext(boost::bind(&AsyncRequest::async_complete, this, +template +Context *AsyncRequest::create_async_callback_context() { + return new FunctionContext(boost::bind(&AsyncRequest::async_complete, this, _1));; } } // namespace librbd + +template class librbd::AsyncRequest; diff --git a/src/librbd/AsyncRequest.h b/src/librbd/AsyncRequest.h index c0a60131106b..483034958019 100644 --- a/src/librbd/AsyncRequest.h +++ b/src/librbd/AsyncRequest.h @@ -8,17 +8,15 @@ #include "include/rados/librados.hpp" #include "include/xlist.h" -/* DARWIN Missing ERESTART */ -#include "include/compat.h" - namespace librbd { class ImageCtx; +template class AsyncRequest { public: - AsyncRequest(ImageCtx &image_ctx, Context *on_finish); + AsyncRequest(ImageCtxT &image_ctx, Context *on_finish); virtual ~AsyncRequest(); void complete(int r) { @@ -41,7 +39,7 @@ public: } protected: - ImageCtx &m_image_ctx; + ImageCtxT &m_image_ctx; Context *m_on_finish; librados::AioCompletion *create_callback_completion(); @@ -59,26 +57,11 @@ protected: } private: bool m_canceled; - xlist::item m_xlist_item; -}; - -class C_AsyncRequest : public Context -{ -public: - C_AsyncRequest(AsyncRequest *req) - : m_req(req) - { - } - -protected: - virtual void finish(int r) { - m_req->complete(r); - } - -private: - AsyncRequest *m_req; + typename xlist *>::item m_xlist_item; }; } // namespace librbd +extern template class librbd::AsyncRequest; + #endif //CEPH_LIBRBD_ASYNC_REQUEST_H diff --git a/src/librbd/AsyncResizeRequest.h b/src/librbd/AsyncResizeRequest.h index c13677c51ceb..0acad6fb9504 100644 --- a/src/librbd/AsyncResizeRequest.h +++ b/src/librbd/AsyncResizeRequest.h @@ -12,7 +12,7 @@ namespace librbd class ImageCtx; class ProgressContext; -class AsyncResizeRequest : public AsyncRequest +class AsyncResizeRequest : public AsyncRequest<> { public: AsyncResizeRequest(ImageCtx &image_ctx, Context *on_finish, uint64_t new_size, diff --git a/src/librbd/AsyncTrimRequest.cc b/src/librbd/AsyncTrimRequest.cc index 801cf8959820..90668ce43123 100644 --- a/src/librbd/AsyncTrimRequest.cc +++ b/src/librbd/AsyncTrimRequest.cc @@ -24,9 +24,9 @@ namespace librbd { -class C_CopyupObject : public C_AsyncObjectThrottle { +class C_CopyupObject : public C_AsyncObjectThrottle<> { public: - C_CopyupObject(AsyncObjectThrottle &throttle, ImageCtx *image_ctx, + C_CopyupObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx, ::SnapContext snapc, uint64_t object_no) : C_AsyncObjectThrottle(throttle, *image_ctx), m_snapc(snapc), m_object_no(object_no) @@ -51,9 +51,9 @@ private: uint64_t m_object_no; }; -class C_RemoveObject : public C_AsyncObjectThrottle { +class C_RemoveObject : public C_AsyncObjectThrottle<> { public: - C_RemoveObject(AsyncObjectThrottle &throttle, ImageCtx *image_ctx, + C_RemoveObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx, uint64_t object_no) : C_AsyncObjectThrottle(throttle, *image_ctx), m_object_no(object_no) { @@ -203,10 +203,10 @@ void AsyncTrimRequest::send_copyup_objects() { m_state = STATE_COPYUP_OBJECTS; Context *ctx = create_callback_context(); - AsyncObjectThrottle::ContextFactory context_factory( + AsyncObjectThrottle<>::ContextFactory context_factory( boost::lambda::bind(boost::lambda::new_ptr(), boost::lambda::_1, &m_image_ctx, snapc, boost::lambda::_2)); - AsyncObjectThrottle *throttle = new AsyncObjectThrottle( + AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>( this, m_image_ctx, context_factory, ctx, &m_prog_ctx, copyup_start, copyup_end); throttle->start_ops(m_image_ctx.concurrent_management_ops); @@ -221,10 +221,10 @@ void AsyncTrimRequest::send_remove_objects() { m_state = STATE_REMOVE_OBJECTS; Context *ctx = create_callback_context(); - AsyncObjectThrottle::ContextFactory context_factory( + AsyncObjectThrottle<>::ContextFactory context_factory( boost::lambda::bind(boost::lambda::new_ptr(), boost::lambda::_1, &m_image_ctx, boost::lambda::_2)); - AsyncObjectThrottle *throttle = new AsyncObjectThrottle( + AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>( this, m_image_ctx, context_factory, ctx, &m_prog_ctx, m_delete_start, m_num_objects); throttle->start_ops(m_image_ctx.concurrent_management_ops); diff --git a/src/librbd/AsyncTrimRequest.h b/src/librbd/AsyncTrimRequest.h index cf69831993f0..2160c405a4ff 100644 --- a/src/librbd/AsyncTrimRequest.h +++ b/src/librbd/AsyncTrimRequest.h @@ -11,7 +11,7 @@ namespace librbd class ImageCtx; class ProgressContext; -class AsyncTrimRequest : public AsyncRequest +class AsyncTrimRequest : public AsyncRequest<> { public: AsyncTrimRequest(ImageCtx &image_ctx, Context *on_finish, diff --git a/src/librbd/CopyupRequest.cc b/src/librbd/CopyupRequest.cc index 2580af1f42a5..667d19d89c4c 100644 --- a/src/librbd/CopyupRequest.cc +++ b/src/librbd/CopyupRequest.cc @@ -26,9 +26,9 @@ namespace librbd { namespace { -class UpdateObjectMap : public C_AsyncObjectThrottle { +class UpdateObjectMap : public C_AsyncObjectThrottle<> { public: - UpdateObjectMap(AsyncObjectThrottle &throttle, ImageCtx *image_ctx, + UpdateObjectMap(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx, uint64_t object_no, const std::vector *snap_ids, size_t snap_id_idx) : C_AsyncObjectThrottle(throttle, *image_ctx), @@ -301,11 +301,11 @@ private: m_state = STATE_OBJECT_MAP; RWLock::RLocker owner_locker(m_ictx->owner_lock); - AsyncObjectThrottle::ContextFactory context_factory( + AsyncObjectThrottle<>::ContextFactory context_factory( boost::lambda::bind(boost::lambda::new_ptr(), boost::lambda::_1, m_ictx, m_object_no, &m_snap_ids, boost::lambda::_2)); - AsyncObjectThrottle *throttle = new AsyncObjectThrottle( + AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>( NULL, *m_ictx, context_factory, create_callback_context(), NULL, 0, m_snap_ids.size()); throttle->start_ops(m_ictx->concurrent_management_ops); diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc index 3e860322c991..bf161498f4d9 100644 --- a/src/librbd/ImageCtx.cc +++ b/src/librbd/ImageCtx.cc @@ -798,7 +798,7 @@ public: ldout(cct, 10) << "canceling async requests: count=" << async_requests.size() << dendl; - for (xlist::iterator it = async_requests.begin(); + for (xlist*>::iterator it = async_requests.begin(); !it.end(); ++it) { ldout(cct, 10) << "canceling async request: " << *it << dendl; (*it)->cancel(); diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index 16634f6cea61..3c7f170b5843 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -38,7 +38,7 @@ class PerfCounters; namespace librbd { class AsyncOperation; - class AsyncRequest; + template class AsyncRequest; class AsyncResizeRequest; class CopyupRequest; class ImageWatcher; @@ -122,7 +122,7 @@ namespace librbd { std::map copyup_list; xlist async_ops; - xlist async_requests; + xlist*> async_requests; Cond async_requests_cond; ObjectMap object_map; diff --git a/src/librbd/ObjectMap.h b/src/librbd/ObjectMap.h index abcf7372d326..115023306944 100644 --- a/src/librbd/ObjectMap.h +++ b/src/librbd/ObjectMap.h @@ -60,7 +60,7 @@ public: private: - class Request : public AsyncRequest { + class Request : public AsyncRequest<> { public: Request(ImageCtx &image_ctx, uint64_t snap_id, Context *on_finish) : AsyncRequest(image_ctx, on_finish), m_snap_id(snap_id), diff --git a/src/librbd/RebuildObjectMapRequest.cc b/src/librbd/RebuildObjectMapRequest.cc index f726e6647fbd..0a7950a8fb1d 100644 --- a/src/librbd/RebuildObjectMapRequest.cc +++ b/src/librbd/RebuildObjectMapRequest.cc @@ -22,9 +22,9 @@ namespace librbd { namespace { -class C_VerifyObject : public C_AsyncObjectThrottle { +class C_VerifyObject : public C_AsyncObjectThrottle<> { public: - C_VerifyObject(AsyncObjectThrottle &throttle, ImageCtx *image_ctx, + C_VerifyObject(AsyncObjectThrottle<> &throttle, ImageCtx *image_ctx, uint64_t snap_id, uint64_t object_no) : C_AsyncObjectThrottle(throttle, *image_ctx), m_snap_id(snap_id), m_object_no(object_no), m_oid(m_image_ctx.get_object_name(m_object_no)) @@ -296,10 +296,10 @@ void RebuildObjectMapRequest::send_verify_objects() { m_state = STATE_VERIFY_OBJECTS; ldout(cct, 5) << this << " send_verify_objects" << dendl; - AsyncObjectThrottle::ContextFactory context_factory( + AsyncObjectThrottle<>::ContextFactory context_factory( boost::lambda::bind(boost::lambda::new_ptr(), boost::lambda::_1, &m_image_ctx, snap_id, boost::lambda::_2)); - AsyncObjectThrottle *throttle = new AsyncObjectThrottle( + AsyncObjectThrottle<> *throttle = new AsyncObjectThrottle<>( this, m_image_ctx, context_factory, create_callback_context(), &m_prog_ctx, 0, num_objects); throttle->start_ops(cct->_conf->rbd_concurrent_management_ops); diff --git a/src/librbd/RebuildObjectMapRequest.h b/src/librbd/RebuildObjectMapRequest.h index a7708ad71caf..02a41ef568ca 100644 --- a/src/librbd/RebuildObjectMapRequest.h +++ b/src/librbd/RebuildObjectMapRequest.h @@ -11,7 +11,7 @@ namespace librbd { class ImageCtx; class ProgressContext; -class RebuildObjectMapRequest : public AsyncRequest { +class RebuildObjectMapRequest : public AsyncRequest<> { public: RebuildObjectMapRequest(ImageCtx &image_ctx, Context *on_finish,