]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: add reference counting in create_context_callback()
authorMahati Chamarthy <mahati.chamarthy@intel.com>
Wed, 28 Mar 2018 07:43:05 +0000 (03:43 -0400)
committerMahati Chamarthy <mahati.chamarthy@intel.com>
Mon, 11 Nov 2019 07:55:44 +0000 (13:25 +0530)
Callers can pass in objects (sub class of the RefCountedObject
class) to be reference counted to track in-flight asynchronous
operations. Object destuction should be performed by invoking
(final) ->put() in context callback handler.

Signed-off-by: Mahati Chamarthy <mahati.chamarthy@intel.com>
Signed-off-by: Venky Shankar <vshankar@redhat.com>
src/librbd/Utils.h

index 11a1634686e29f246de1d045973093bd0914f55b..c63504ac1a7d4c1be2a9820b26ee4784258d45d3 100644 (file)
@@ -9,6 +9,7 @@
 #include "include/ceph_assert.h"
 #include "include/Context.h"
 #include "common/zipkin_trace.h"
+#include "common/RefCountedObj.h"
 
 #include <atomic>
 #include <type_traits>
@@ -59,6 +60,23 @@ protected:
   }
 };
 
+template <typename T, void (T::*MF)(int)>
+class C_RefCallbackAdapter : public Context {
+  RefCountedPtr refptr;
+  Context *on_finish;
+
+public:
+  C_RefCallbackAdapter(T *obj, RefCountedPtr refptr)
+    : refptr(std::move(refptr)),
+      on_finish(new C_CallbackAdapter<T, MF>(obj)) {
+  }
+
+protected:
+  void finish(int r) override {
+    on_finish->complete(r);
+  }
+};
+
 template <typename T, Context*(T::*MF)(int*), bool destroy>
 class C_StateCallbackAdapter : public Context {
   T *obj;
@@ -81,6 +99,23 @@ protected:
   }
 };
 
+template <typename T, Context*(T::*MF)(int*)>
+class C_RefStateCallbackAdapter : public Context {
+  RefCountedPtr refptr;
+  Context *on_finish;
+
+public:
+  C_RefStateCallbackAdapter(T *obj, RefCountedPtr refptr)
+    : refptr(std::move(refptr)),
+      on_finish(new C_StateCallbackAdapter<T, MF, true>(obj)) {
+  }
+
+protected:
+  void finish(int r) override {
+    on_finish->complete(r);
+  }
+};
+
 template <typename WQ>
 struct C_AsyncCallback : public Context {
   WQ *op_work_queue;
@@ -156,6 +191,30 @@ Context *create_context_callback(T *obj) {
   return new detail::C_StateCallbackAdapter<T, MF, destroy>(obj);
 }
 
+//for reference counting objects
+template <typename T, void(T::*MF)(int) = &T::complete>
+Context *create_context_callback(T *obj, RefCountedPtr refptr) {
+  return new detail::C_RefCallbackAdapter<T, MF>(obj, refptr);
+}
+
+template <typename T, Context*(T::*MF)(int*)>
+Context *create_context_callback(T *obj, RefCountedPtr refptr) {
+  return new detail::C_RefStateCallbackAdapter<T, MF>(obj, refptr);
+}
+
+//for objects that don't inherit from RefCountedObj, to handle unit tests
+template <typename T, void(T::*MF)(int) = &T::complete, typename R>
+typename std::enable_if<not std::is_base_of<RefCountedPtr, R>::value, Context*>::type
+create_context_callback(T *obj, R *refptr) {
+  return new detail::C_CallbackAdapter<T, MF>(obj);
+}
+
+template <typename T, Context*(T::*MF)(int*), typename R, bool destroy=true>
+typename std::enable_if<not std::is_base_of<RefCountedPtr, R>::value, Context*>::type
+create_context_callback(T *obj, R *refptr) {
+  return new detail::C_StateCallbackAdapter<T, MF, destroy>(obj);
+}
+
 template <typename I>
 Context *create_async_context_callback(I &image_ctx, Context *on_finish) {
   // use async callback to acquire a clean lock context