case CEPH_OSD_OP_DELETE:
++ctx->num_write;
tracepoint(osd, do_osd_op_pre_delete, soid.oid.name.c_str(), soid.snap.val);
- if (ctx->obc->obs.oi.watchers.size()) {
- // Cannot delete an object with watchers
- result = -EBUSY;
- } else {
- result = _delete_oid(ctx, ctx->ignore_cache);
- }
+ result = _delete_oid(ctx, ctx->ignore_cache);
break;
case CEPH_OSD_OP_CLONERANGE:
}
oi.size = 0;
+ // disconnect all watchers
+ for (map<pair<uint64_t, entity_name_t>, watch_info_t>::iterator p =
+ oi.watchers.begin();
+ p != oi.watchers.end();
+ ++p) {
+ dout(20) << __func__ << " will disconnect watcher " << p->first << dendl;
+ ctx->watch_disconnects.push_back(
+ OpContext::watch_disconnect_t(p->first.first, p->first.second, true));
+ }
+ oi.watchers.clear();
+
// cache: cache: set whiteout on delete?
if (pool.info.cache_mode != pg_pool_t::CACHEMODE_NONE && !no_whiteout) {
dout(20) << __func__ << " setting whiteout on " << soid << dendl;
// --
+TEST_F(LibRadosWatchNotify, Watch2Delete) {
+ notify_io = ioctx;
+ notify_oid = "foo";
+ notify_err = 0;
+ char buf[128];
+ memset(buf, 0xcc, sizeof(buf));
+ 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,
+ watch_notify2_test_errcb, NULL));
+ ASSERT_EQ(0, rados_remove(ioctx, notify_oid));
+ int left = 180;
+ std::cout << "waiting up to " << left << " for disconnect notification ..."
+ << std::endl;
+ while (notify_err == 0 && --left) {
+ sleep(1);
+ }
+ ASSERT_TRUE(left > 0);
+ ASSERT_EQ(-ENOTCONN, notify_err);
+ ASSERT_EQ(-ENOTCONN, rados_watch_check(ioctx, handle));
+ rados_unwatch2(ioctx, handle);
+}
+
TEST_F(LibRadosWatchNotify, Watch2Timeout) {
notify_io = ioctx;
notify_oid = "foo";
notify_cookies.clear();
+ notify_err = 0;
char buf[128];
memset(buf, 0xcc, sizeof(buf));
ASSERT_EQ(0, rados_write(ioctx, notify_oid, buf, sizeof(buf), 0));