From: Sage Weil Date: Fri, 17 Oct 2014 03:09:07 +0000 (-0700) Subject: librados: define error callback X-Git-Tag: v0.91~142 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c973c93f3fa23a2b5d9171c2db3d45a03c0e1cb9;p=ceph.git librados: define error callback 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 --- diff --git a/src/include/rados/librados.h b/src/include/rados/librados.h index 9cf888c25f57..4347d0ae1b0e 100644 --- a/src/include/rados/librados.h +++ b/src/include/rados/librados.h @@ -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 diff --git a/src/include/rados/librados.hpp b/src/include/rados/librados.hpp index b79bd73e4578..92780b2c5a63 100644 --- a/src/include/rados/librados.hpp +++ b/src/include/rados/librados.hpp @@ -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 { diff --git a/src/librados/librados.cc b/src/librados/librados.cc index 8077d28cd7a5..4b648ed394b4 100644 --- a/src/librados/librados.cc +++ b/src/librados/librados.cc @@ -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; diff --git a/src/test/librados/watch_notify.cc b/src/test/librados/watch_notify.cc index d41552492fca..9e6536b77988 100644 --- a/src/test/librados/watch_notify.cc +++ b/src/test/librados/watch_notify.cc @@ -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,