]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librados: define error callback
authorSage Weil <sage@redhat.com>
Fri, 17 Oct 2014 03:09:07 +0000 (20:09 -0700)
committerSage Weil <sage@redhat.com>
Thu, 4 Dec 2014 18:32:37 +0000 (10:32 -0800)
This is the async notification of a watch error (failure to reconnect to
the object's OSD after a peering event or network disconnect).

Signed-off-by: Sage Weil <sage@redhat.com>
src/include/rados/librados.h
src/include/rados/librados.hpp
src/librados/librados.cc
src/test/librados/watch_notify.cc

index 9cf888c25f570aec5936accc829e46d3aa9f53e3..4347d0ae1b0efd61e302a46b991a6d160bb860ce 100644 (file)
@@ -1862,12 +1862,14 @@ CEPH_RADOS_API int rados_aio_cancel(rados_ioctx_t io,
  * @typedef rados_watchcb_t
  *
  * Callback activated when a notify is received on a watched
- * object. Parameters are:
- * - opcode undefined
- * - ver version of the watched object
- * - arg application-specific data
+ * object.
+ *
+ * @param opcode undefined
+ * @param ver version of the watched object
+ * @param arg application-specific data
  *
  * @note BUG: opcode is an internal detail that shouldn't be exposed
+ * @note BUG: ver is unused
  */
 typedef void (*rados_watchcb_t)(uint8_t opcode, uint64_t ver, void *arg);
 
@@ -1875,13 +1877,14 @@ typedef void (*rados_watchcb_t)(uint8_t opcode, uint64_t ver, void *arg);
  * @typedef rados_watchcb2_t
  *
  * Callback activated when a notify is received on a watched
- * object. Parameters are:
- * - arg opaque user-defined value provided to rados_watch2()
- * - notify_id an id for this notify event
- * - handle the watcher handle we are notifying
- * - notifier_id the unique client id for the notifier
- * - data payload from the notifier
- * - datalen length of payload buffer
+ * object.
+ *
+ * @param arg opaque user-defined value provided to rados_watch2()
+ * @param notify_id an id for this notify event
+ * @param handle the watcher handle we are notifying
+ * @param notifier_id the unique client id for the notifier
+ * @param data payload from the notifier
+ * @param datalen length of payload buffer
  */
 typedef void (*rados_watchcb2_t)(void *arg,
                                 uint64_t notify_id,
@@ -1890,6 +1893,20 @@ typedef void (*rados_watchcb2_t)(void *arg,
                                 void *data,
                                 size_t data_len);
 
+/**
+ * @typedef rados_watcherrcb_t
+ *
+ * Callback activated when we encounter an error with the watch session.
+ * This can happen when the location of the objects moves within the
+ * cluster and we fail to register our watch with the new object location,
+ * or when our connection with the object OSD is otherwise interrupted and
+ * we may have missed notify events.
+ *
+ * @param pre opaque user-defined value provided to rados_watch2()
+ * @param err error code
+ */
+  typedef void (*rados_watcherrcb_t)(void *pre, uint64_t cookie, int err);
+
 /**
  * Register an interest in an object
  *
@@ -1937,11 +1954,13 @@ CEPH_RADOS_API int rados_watch(rados_ioctx_t io, const char *o, uint64_t ver,
  * @param o the object to watch
  * @param handle where to store the internal id assigned to this watch
  * @param watchcb2 what to do when a notify is received on this object
+ * @param watcherrcb what to do when the watch session encounters an error
  * @param arg opaque value to pass to the callback
  * @returns 0 on success, negative error code on failure
  */
 int rados_watch2(rados_ioctx_t io, const char *o, uint64_t *handle,
-                rados_watchcb2_t watchcb, void *arg);
+                rados_watchcb2_t watchcb, rados_watcherrcb_t watcherrcb,
+                void *arg);
 
 /**
  * Unregister an interest in an object
index b79bd73e4578e4eefb11c6233c17ea7cf1d4773c..92780b2c5a63542ec9b4cd5f06f090e6d5fbd0e1 100644 (file)
@@ -156,6 +156,8 @@ namespace librados
   public:
     virtual ~WatchCtx2();
     /**
+     * Callback activated when we receive a notify event.
+     *
      * @param notify_id unique id for this notify event
      * @param cookie the watcher we are notifying
      * @param notifier_id the unique client id of the notifier
@@ -165,6 +167,13 @@ namespace librados
                               uint64_t cookie,
                               uint64_t notifier_id,
                               bufferlist& bl) = 0;
+    /**
+     * Callback activated when we encounter an error with the watch.
+     *
+     * @param cookie the watcher with the problem
+     * @param err error
+     */
+    virtual void handle_error(uint64_t cookie, int err) = 0;
   };
 
   struct CEPH_RADOS_API AioCompletion {
index 8077d28cd7a58cda91ef3db3a53dec93c7831f25..4b648ed394b4f65e9d6df537c1f39b8e6253557e 100644 (file)
@@ -3771,24 +3771,32 @@ extern "C" int rados_watch(rados_ioctx_t io, const char *o, uint64_t ver,
 
 struct C_WatchCB2 : public librados::WatchCtx2 {
   rados_watchcb2_t wcb;
+  rados_watcherrcb_t errcb;
   void *arg;
-  C_WatchCB2(rados_watchcb2_t _wcb, void *_arg) : wcb(_wcb), arg(_arg) {}
+  C_WatchCB2(rados_watchcb2_t _wcb,
+            rados_watcherrcb_t _errcb,
+            void *_arg) : wcb(_wcb), errcb(_errcb), arg(_arg) {}
   void handle_notify(uint64_t notify_id,
                     uint64_t cookie,
                     uint64_t notifier_gid,
                     bufferlist& bl) {
     wcb(arg, notify_id, cookie, notifier_gid, bl.c_str(), bl.length());
   }
+  void handle_error(uint64_t cookie, int err) {
+    errcb(arg, cookie, err);
+  }
 };
 
 extern "C" int rados_watch2(rados_ioctx_t io, const char *o, uint64_t *handle,
-                           rados_watchcb2_t watchcb, void *arg)
+                           rados_watchcb2_t watchcb,
+                           rados_watcherrcb_t watcherrcb,
+                           void *arg)
 {
   tracepoint(librados, rados_watch2_enter, io, o, handle, watchcb, arg);
   uint64_t *cookie = handle;
   librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
   object_t oid(o);
-  C_WatchCB2 *wc = new C_WatchCB2(watchcb, arg);
+  C_WatchCB2 *wc = new C_WatchCB2(watchcb, watcherrcb, arg);
   int ret = ctx->watch(oid, cookie, NULL, wc);
   tracepoint(librados, rados_watch_exit, ret, *handle);
   return ret;
index d41552492fcaf943d3ab4497bc1eba7fde203278..9e6536b77988cb689348ac2b115c38360bd9104e 100644 (file)
@@ -41,6 +41,7 @@ public:
 bufferlist notify_bl;
 rados_ioctx_t notify_io;
 const char *notify_oid = 0;
+int notify_err = 0;
 
 static void watch_notify2_test_cb(void *arg,
                                  uint64_t notify_id,
@@ -74,6 +75,11 @@ public:
       sleep(notify_sleep);
     notify_ioctx->notify_ack(notify_oid, notify_id, cookie, reply);
   }
+
+  void handle_error(uint64_t cookie, int err) {
+    std::cout << __func__ << " cookie " << cookie << std::endl;
+    notify_err = err;
+  }
 };
 
 TEST_F(LibRadosWatchNotify, WatchNotifyTest) {
@@ -99,7 +105,8 @@ TEST_F(LibRadosWatchNotify, WatchNotify2Test) {
   ASSERT_EQ(0, rados_write(ioctx, notify_oid, buf, sizeof(buf), 0));
   uint64_t handle;
   ASSERT_EQ(0,
-      rados_watch2(ioctx, notify_oid, &handle, watch_notify2_test_cb, NULL));
+      rados_watch2(ioctx, notify_oid, &handle, watch_notify2_test_cb,
+                  watch_notify2_test_errcb, NULL));
   char *reply_buf;
   size_t reply_buf_len;
   ASSERT_EQ(0, rados_notify2(ioctx, notify_oid,
@@ -124,9 +131,11 @@ TEST_F(LibRadosWatchNotify, WatchNotify2MultiTest) {
   ASSERT_EQ(0, rados_write(ioctx, notify_oid, buf, sizeof(buf), 0));
   uint64_t handle1, handle2;
   ASSERT_EQ(0,
-      rados_watch2(ioctx, notify_oid, &handle1, watch_notify2_test_cb, NULL));
+      rados_watch2(ioctx, notify_oid, &handle1, watch_notify2_test_cb,
+                  watch_notify2_test_errcb, NULL));
   ASSERT_EQ(0,
-      rados_watch2(ioctx, notify_oid, &handle2, watch_notify2_test_cb, NULL));
+      rados_watch2(ioctx, notify_oid, &handle2, watch_notify2_test_cb,
+                  watch_notify2_test_errcb, NULL));
   ASSERT_NE(handle1, handle2);
   char *reply_buf;
   size_t reply_buf_len;
@@ -154,7 +163,8 @@ TEST_F(LibRadosWatchNotify, WatchNotify2TimeoutTest) {
   ASSERT_EQ(0, rados_write(ioctx, notify_oid, buf, sizeof(buf), 0));
   uint64_t handle;
   ASSERT_EQ(0,
-      rados_watch2(ioctx, notify_oid, &handle, watch_notify2_test_cb, NULL));
+      rados_watch2(ioctx, notify_oid, &handle, watch_notify2_test_cb,
+                  watch_notify2_test_errcb, NULL));
   char *reply_buf;
   size_t reply_buf_len;
   ASSERT_EQ(-ETIMEDOUT, rados_notify2(ioctx, notify_oid,