void ExclusiveLock<I>::try_lock(Context *on_tried_lock) {
{
Mutex::Locker locker(m_lock);
- assert(m_image_ctx.owner_lock.is_wlocked());
+ assert(m_image_ctx.owner_lock.is_locked());
assert(!is_shutdown());
if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {
#include "include/encoding.h"
#include "include/stringify.h"
#include "common/errno.h"
+#include "common/WorkQueue.h"
#include <sstream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
}
}
-int ImageWatcher::notify_flatten(uint64_t request_id, ProgressContext &prog_ctx) {
+void ImageWatcher::notify_flatten(uint64_t request_id,
+ ProgressContext &prog_ctx,
+ Context *on_finish) {
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.exclusive_lock &&
!m_image_ctx.exclusive_lock->is_lock_owner());
bufferlist bl;
::encode(NotifyMessage(FlattenPayload(async_request_id)), bl);
- return notify_async_request(async_request_id, std::move(bl), prog_ctx);
+ notify_async_request(async_request_id, std::move(bl), prog_ctx, on_finish);
}
-int ImageWatcher::notify_resize(uint64_t request_id, uint64_t size,
- ProgressContext &prog_ctx) {
+void ImageWatcher::notify_resize(uint64_t request_id, uint64_t size,
+ ProgressContext &prog_ctx,
+ Context *on_finish) {
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.exclusive_lock &&
!m_image_ctx.exclusive_lock->is_lock_owner());
bufferlist bl;
::encode(NotifyMessage(ResizePayload(size, async_request_id)), bl);
- return notify_async_request(async_request_id, std::move(bl), prog_ctx);
+ notify_async_request(async_request_id, std::move(bl), prog_ctx, on_finish);
}
-int ImageWatcher::notify_snap_create(const std::string &snap_name) {
+void ImageWatcher::notify_snap_create(const std::string &snap_name,
+ Context *on_finish) {
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.exclusive_lock &&
!m_image_ctx.exclusive_lock->is_lock_owner());
bufferlist bl;
::encode(NotifyMessage(SnapCreatePayload(snap_name)), bl);
- return notify_lock_owner(std::move(bl));
+ notify_lock_owner(std::move(bl), on_finish);
}
-int ImageWatcher::notify_snap_rename(const snapid_t &src_snap_id,
- const std::string &dst_snap_name) {
+void ImageWatcher::notify_snap_rename(const snapid_t &src_snap_id,
+ const std::string &dst_snap_name,
+ Context *on_finish) {
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.exclusive_lock &&
!m_image_ctx.exclusive_lock->is_lock_owner());
bufferlist bl;
::encode(NotifyMessage(SnapRenamePayload(src_snap_id, dst_snap_name)), bl);
- return notify_lock_owner(std::move(bl));
+ notify_lock_owner(std::move(bl), on_finish);
}
-int ImageWatcher::notify_snap_remove(const std::string &snap_name) {
+
+void ImageWatcher::notify_snap_remove(const std::string &snap_name,
+ Context *on_finish) {
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.exclusive_lock &&
!m_image_ctx.exclusive_lock->is_lock_owner());
bufferlist bl;
::encode(NotifyMessage(SnapRemovePayload(snap_name)), bl);
- return notify_lock_owner(std::move(bl));
+ notify_lock_owner(std::move(bl), on_finish);
}
-int ImageWatcher::notify_snap_protect(const std::string &snap_name) {
+void ImageWatcher::notify_snap_protect(const std::string &snap_name,
+ Context *on_finish) {
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.exclusive_lock &&
!m_image_ctx.exclusive_lock->is_lock_owner());
bufferlist bl;
::encode(NotifyMessage(SnapProtectPayload(snap_name)), bl);
- return notify_lock_owner(std::move(bl));
+ notify_lock_owner(std::move(bl), on_finish);
}
-int ImageWatcher::notify_snap_unprotect(const std::string &snap_name) {
+void ImageWatcher::notify_snap_unprotect(const std::string &snap_name,
+ Context *on_finish) {
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.exclusive_lock &&
!m_image_ctx.exclusive_lock->is_lock_owner());
bufferlist bl;
::encode(NotifyMessage(SnapUnprotectPayload(snap_name)), bl);
- return notify_lock_owner(std::move(bl));
+ notify_lock_owner(std::move(bl), on_finish);
}
-int ImageWatcher::notify_rebuild_object_map(uint64_t request_id,
- ProgressContext &prog_ctx) {
+void ImageWatcher::notify_rebuild_object_map(uint64_t request_id,
+ ProgressContext &prog_ctx,
+ Context *on_finish) {
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.exclusive_lock &&
!m_image_ctx.exclusive_lock->is_lock_owner());
bufferlist bl;
::encode(NotifyMessage(RebuildObjectMapPayload(async_request_id)), bl);
- return notify_async_request(async_request_id, std::move(bl), prog_ctx);
+ notify_async_request(async_request_id, std::move(bl), prog_ctx, on_finish);
}
-int ImageWatcher::notify_rename(const std::string &image_name) {
+void ImageWatcher::notify_rename(const std::string &image_name,
+ Context *on_finish) {
assert(m_image_ctx.owner_lock.is_locked());
assert(m_image_ctx.exclusive_lock &&
!m_image_ctx.exclusive_lock->is_lock_owner());
bufferlist bl;
::encode(NotifyMessage(RenamePayload(image_name)), bl);
- return notify_lock_owner(std::move(bl));
+ notify_lock_owner(std::move(bl), on_finish);
}
void ImageWatcher::notify_header_update(Context *on_finish) {
}
}
-int ImageWatcher::notify_lock_owner(bufferlist &&bl) {
- C_SaferCond ctx;
- notify_lock_owner(std::move(bl), &ctx);
- return ctx.wait();
-}
-
void ImageWatcher::notify_lock_owner(bufferlist &&bl, Context *on_finish) {
+ assert(on_finish != nullptr);
assert(m_image_ctx.owner_lock.is_locked());
NotifyLockOwner *notify_lock_owner = NotifyLockOwner::create(
m_image_ctx, m_notifier, std::move(bl), on_finish);
notify_lock_owner->send();
}
+Context *ImageWatcher::remove_async_request(const AsyncRequestId &id) {
+ RWLock::WLocker async_request_locker(m_async_request_lock);
+ auto it = m_async_requests.find(id);
+ if (it != m_async_requests.end()) {
+ Context *on_complete = it->second.first;
+ m_async_requests.erase(it);
+ return on_complete;
+ }
+ return nullptr;
+}
+
void ImageWatcher::schedule_async_request_timed_out(const AsyncRequestId &id) {
Context *ctx = new FunctionContext(boost::bind(
&ImageWatcher::async_request_timed_out, this, id));
}
void ImageWatcher::async_request_timed_out(const AsyncRequestId &id) {
- RWLock::RLocker l(m_async_request_lock);
- std::map<AsyncRequestId, AsyncRequest>::iterator it =
- m_async_requests.find(id);
- if (it != m_async_requests.end()) {
- ldout(m_image_ctx.cct, 10) << this << " request timed-out: " << id << dendl;
- it->second.first->complete(-ERESTART);
+ Context *on_complete = remove_async_request(id);
+ if (on_complete != nullptr) {
+ ldout(m_image_ctx.cct, 5) << "async request timed out: " << id << dendl;
+ m_image_ctx.op_work_queue->queue(on_complete, -ETIMEDOUT);
}
}
-int ImageWatcher::notify_async_request(const AsyncRequestId &async_request_id,
- bufferlist &&in,
- ProgressContext& prog_ctx) {
+void ImageWatcher::notify_async_request(const AsyncRequestId &async_request_id,
+ bufferlist &&in,
+ ProgressContext& prog_ctx,
+ Context *on_finish) {
+ assert(on_finish != nullptr);
assert(m_image_ctx.owner_lock.is_locked());
ldout(m_image_ctx.cct, 10) << this << " async request: " << async_request_id
<< dendl;
- C_SaferCond ctx;
+ Context *on_notify = new FunctionContext([this, async_request_id](int r) {
+ if (r < 0) {
+ // notification failed -- don't expect updates
+ Context *on_complete = remove_async_request(async_request_id);
+ if (on_complete != nullptr) {
+ on_complete->complete(r);
+ }
+ }
+ });
+ Context *on_complete = new FunctionContext(
+ [this, async_request_id, on_finish](int r) {
+ m_task_finisher->cancel(Task(TASK_CODE_ASYNC_REQUEST, async_request_id));
+ on_finish->complete(r);
+ });
{
- RWLock::WLocker l(m_async_request_lock);
- m_async_requests[async_request_id] = AsyncRequest(&ctx, &prog_ctx);
+ RWLock::WLocker async_request_locker(m_async_request_lock);
+ m_async_requests[async_request_id] = AsyncRequest(on_complete, &prog_ctx);
}
- BOOST_SCOPE_EXIT( (&ctx)(async_request_id)(&m_task_finisher)
- (&m_async_requests)(&m_async_request_lock) ) {
- m_task_finisher->cancel(Task(TASK_CODE_ASYNC_REQUEST, async_request_id));
-
- RWLock::WLocker l(m_async_request_lock);
- m_async_requests.erase(async_request_id);
- } BOOST_SCOPE_EXIT_END
-
schedule_async_request_timed_out(async_request_id);
- int r = notify_lock_owner(std::move(in));
- if (r < 0) {
- return r;
- }
- return ctx.wait();
+ notify_lock_owner(std::move(in), on_notify);
}
int ImageWatcher::prepare_async_request(const AsyncRequestId& async_request_id,
bool ImageWatcher::handle_payload(const AsyncCompletePayload &payload,
C_NotifyAck *ack_ctx) {
- RWLock::RLocker l(m_async_request_lock);
- std::map<AsyncRequestId, AsyncRequest>::iterator req_it =
- m_async_requests.find(payload.async_request_id);
- if (req_it != m_async_requests.end()) {
+ Context *on_complete = remove_async_request(payload.async_request_id);
+ if (on_complete != nullptr) {
ldout(m_image_ctx.cct, 10) << this << " request finished: "
<< payload.async_request_id << "="
<< payload.result << dendl;
- req_it->second.first->complete(payload.result);
+ on_complete->complete(payload.result);
}
return true;
}
void unregister_watch(Context *on_finish);
void flush(Context *on_finish);
- int notify_flatten(uint64_t request_id, ProgressContext &prog_ctx);
- int notify_resize(uint64_t request_id, uint64_t size,
- ProgressContext &prog_ctx);
- int notify_snap_create(const std::string &snap_name);
- int notify_snap_rename(const snapid_t &src_snap_id,
- const std::string &dst_snap_name);
- int notify_snap_remove(const std::string &snap_name);
- int notify_snap_protect(const std::string &snap_name);
- int notify_snap_unprotect(const std::string &snap_name);
- int notify_rebuild_object_map(uint64_t request_id,
- ProgressContext &prog_ctx);
- int notify_rename(const std::string &image_name);
+ void notify_flatten(uint64_t request_id, ProgressContext &prog_ctx,
+ Context *on_finish);
+ void notify_resize(uint64_t request_id, uint64_t size,
+ ProgressContext &prog_ctx, Context *on_finish);
+ void notify_snap_create(const std::string &snap_name, Context *on_finish);
+ void notify_snap_rename(const snapid_t &src_snap_id,
+ const std::string &dst_snap_name,
+ Context *on_finish);
+ void notify_snap_remove(const std::string &snap_name, Context *on_finish);
+ void notify_snap_protect(const std::string &snap_name, Context *on_finish);
+ void notify_snap_unprotect(const std::string &snap_name, Context *on_finish);
+ void notify_rebuild_object_map(uint64_t request_id,
+ ProgressContext &prog_ctx, Context *on_finish);
+ void notify_rename(const std::string &image_name, Context *on_finish);
void notify_acquired_lock();
void notify_released_lock();
void handle_request_lock(int r);
void schedule_request_lock(bool use_timer, int timer_delay = -1);
- int notify_lock_owner(bufferlist &&bl);
void notify_lock_owner(bufferlist &&bl, Context *on_finish);
+ Context *remove_async_request(const watch_notify::AsyncRequestId &id);
void schedule_async_request_timed_out(const watch_notify::AsyncRequestId &id);
void async_request_timed_out(const watch_notify::AsyncRequestId &id);
- int notify_async_request(const watch_notify::AsyncRequestId &id,
- bufferlist &&in, ProgressContext& prog_ctx);
+ void notify_async_request(const watch_notify::AsyncRequestId &id,
+ bufferlist &&in, ProgressContext& prog_ctx,
+ Context *on_finish);
void schedule_async_progress(const watch_notify::AsyncRequestId &id,
uint64_t offset, uint64_t total);
#include "librbd/ImageCtx.h"
#include "librbd/ImageState.h"
#include "librbd/ImageWatcher.h"
+#include "librbd/Utils.h"
#include "librbd/operation/FlattenRequest.h"
#include "librbd/operation/RebuildObjectMapRequest.h"
#include "librbd/operation/RenameRequest.h"
}
};
+template <typename I>
+struct C_InvokeAsyncRequest : public Context {
+ /**
+ * @verbatim
+ *
+ * <start>
+ * |
+ * . . . . . . | . . . . . . . . . . . . . . . . . .
+ * . . | . .
+ * . v v v .
+ * . ACQUIRE_LOCK (skip if exclusive lock .
+ * . | disabled or has lock) .
+ * . | .
+ * . /--------/ \--------\ . . . . . . . . . . . . .
+ * . | | .
+ * . v v .
+ * LOCAL_REQUEST REMOTE_REQUEST
+ * | |
+ * | |
+ * \--------\ /--------/
+ * |
+ * v
+ * <finish>
+ *
+ * @endverbatim
+ */
+
+ I &image_ctx;
+ std::string request_type;
+ bool permit_snapshot;
+ boost::function<void(Context*)> local;
+ boost::function<void(Context*)> remote;
+ Context *on_finish;
+
+ C_InvokeAsyncRequest(I &image_ctx, const std::string& request_type,
+ bool permit_snapshot,
+ const boost::function<void(Context*)>& local,
+ const boost::function<void(Context*)>& remote,
+ Context *on_finish)
+ : image_ctx(image_ctx), request_type(request_type),
+ permit_snapshot(permit_snapshot), local(local), remote(remote),
+ on_finish(on_finish) {
+ }
+
+ void send() {
+ send_acquire_exclusive_lock();
+ }
+
+ void send_acquire_exclusive_lock() {
+ RWLock::RLocker owner_locker(image_ctx.owner_lock);
+ {
+ RWLock::RLocker snap_locker(image_ctx.snap_lock);
+ if (image_ctx.read_only ||
+ (!permit_snapshot && image_ctx.snap_id != CEPH_NOSNAP)) {
+ complete(-EROFS);
+ return;
+ }
+ }
+
+ if (image_ctx.exclusive_lock == nullptr) {
+ send_local_request();
+ return;
+ } else if (image_ctx.image_watcher == nullptr) {
+ complete(-EROFS);
+ return;
+ }
+
+ if (image_ctx.exclusive_lock->is_lock_owner() &&
+ image_ctx.exclusive_lock->accept_requests()) {
+ send_local_request();
+ return;
+ }
+
+ CephContext *cct = image_ctx.cct;
+ ldout(cct, 20) << __func__ << dendl;
+
+ Context *ctx = util::create_context_callback<
+ C_InvokeAsyncRequest<I>,
+ &C_InvokeAsyncRequest<I>::handle_acquire_exclusive_lock>(
+ this);
+ image_ctx.exclusive_lock->try_lock(ctx);
+ }
+
+ void handle_acquire_exclusive_lock(int r) {
+ CephContext *cct = image_ctx.cct;
+ ldout(cct, 20) << __func__ << ": r=" << r << dendl;
+
+ RWLock::RLocker owner_locker(image_ctx.owner_lock);
+ if (r < 0) {
+ complete(-EROFS);
+ return;
+ } else if (image_ctx.exclusive_lock->is_lock_owner()) {
+ send_local_request();
+ return;
+ }
+
+ send_remote_request();
+ }
+
+ void send_remote_request() {
+ assert(image_ctx.owner_lock.is_locked());
+
+ CephContext *cct = image_ctx.cct;
+ ldout(cct, 20) << __func__ << dendl;
+
+ Context *ctx = util::create_context_callback<
+ C_InvokeAsyncRequest<I>, &C_InvokeAsyncRequest<I>::handle_remote_request>(
+ this);
+ remote(ctx);
+ }
+
+ void handle_remote_request(int r) {
+ CephContext *cct = image_ctx.cct;
+ ldout(cct, 20) << __func__ << ": r=" << r << dendl;
+
+ if (r != -ETIMEDOUT && r != -ERESTART) {
+ complete(r);
+ return;
+ }
+
+ ldout(cct, 5) << request_type << " timed out notifying lock owner"
+ << dendl;
+ send_acquire_exclusive_lock();
+ }
+
+ void send_local_request() {
+ assert(image_ctx.owner_lock.is_locked());
+
+ CephContext *cct = image_ctx.cct;
+ ldout(cct, 20) << __func__ << dendl;
+
+ Context *ctx = util::create_context_callback<
+ C_InvokeAsyncRequest<I>, &C_InvokeAsyncRequest<I>::handle_local_request>(
+ this);
+ local(ctx);
+ }
+
+ void handle_local_request(int r) {
+ CephContext *cct = image_ctx.cct;
+ ldout(cct, 20) << __func__ << ": r=" << r << dendl;
+
+ if (r == -ERESTART) {
+ send_acquire_exclusive_lock();
+ return;
+ }
+ complete(r);
+ }
+
+ virtual void finish(int r) override {
+ on_finish->complete(r);
+ }
+};
+
} // anonymous namespace
template <typename I>
boost::ref(prog_ctx), _1),
boost::bind(&ImageWatcher::notify_flatten,
m_image_ctx.image_watcher, request_id,
- boost::ref(prog_ctx)));
+ boost::ref(prog_ctx), _1));
if (r < 0 && r != -EINVAL) {
return r;
boost::ref(prog_ctx), _1),
boost::bind(&ImageWatcher::notify_rebuild_object_map,
m_image_ctx.image_watcher, request_id,
- boost::ref(prog_ctx)));
+ boost::ref(prog_ctx), _1));
ldout(cct, 10) << "rebuild object map finished" << dendl;
if (r < 0) {
boost::bind(&Operations<I>::rename, this,
dstname, _1),
boost::bind(&ImageWatcher::notify_rename,
- m_image_ctx.image_watcher, dstname));
+ m_image_ctx.image_watcher, dstname,
+ _1));
if (r < 0 && r != -EEXIST) {
return r;
}
size, boost::ref(prog_ctx), _1, 0),
boost::bind(&ImageWatcher::notify_resize,
m_image_ctx.image_watcher, request_id,
- size, boost::ref(prog_ctx)));
+ size, boost::ref(prog_ctx), _1));
m_image_ctx.perfcounter->inc(l_librbd_resize);
ldout(cct, 2) << "resize finished" << dendl;
boost::bind(&Operations<I>::snap_create, this,
snap_name, _1, 0),
boost::bind(&ImageWatcher::notify_snap_create,
- m_image_ctx.image_watcher, snap_name));
+ m_image_ctx.image_watcher, snap_name,
+ _1));
if (r < 0 && r != -EEXIST) {
return r;
}
boost::bind(&Operations<I>::snap_remove, this,
snap_name, _1),
boost::bind(&ImageWatcher::notify_snap_remove,
- m_image_ctx.image_watcher, snap_name));
+ m_image_ctx.image_watcher, snap_name,
+ _1));
if (r < 0 && r != -ENOENT) {
return r;
}
snap_id, dstname, _1),
boost::bind(&ImageWatcher::notify_snap_rename,
m_image_ctx.image_watcher, snap_id,
- dstname));
+ dstname, _1));
if (r < 0 && r != -EEXIST) {
return r;
}
boost::bind(&Operations<I>::snap_protect, this,
snap_name, _1),
boost::bind(&ImageWatcher::notify_snap_protect,
- m_image_ctx.image_watcher, snap_name));
+ m_image_ctx.image_watcher, snap_name,
+ _1));
if (r < 0 && r != -EBUSY) {
return r;
}
boost::bind(&Operations<I>::snap_unprotect, this,
snap_name, _1),
boost::bind(&ImageWatcher::notify_snap_unprotect,
- m_image_ctx.image_watcher, snap_name));
+ m_image_ctx.image_watcher, snap_name,
+ _1));
if (r < 0 && r != -EINVAL) {
return r;
}
int Operations<I>::invoke_async_request(const std::string& request_type,
bool permit_snapshot,
const boost::function<void(Context*)>& local_request,
- const boost::function<int()>& remote_request) {
- CephContext *cct = m_image_ctx.cct;
- int r;
- do {
- C_SaferCond ctx;
- {
- RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
- {
- RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
- if (m_image_ctx.read_only ||
- (!permit_snapshot && m_image_ctx.snap_id != CEPH_NOSNAP)) {
- return -EROFS;
- }
- }
-
- while (m_image_ctx.exclusive_lock != nullptr) {
- r = prepare_image_update();
- if (r < 0) {
- return -EROFS;
- } else if (m_image_ctx.exclusive_lock->is_lock_owner()) {
- break;
- }
-
- r = remote_request();
- if (r != -ETIMEDOUT && r != -ERESTART) {
- return r;
- }
- ldout(cct, 5) << request_type << " timed out notifying lock owner"
- << dendl;
- }
-
- local_request(&ctx);
- }
-
- r = ctx.wait();
- if (r == -ERESTART) {
- ldout(cct, 5) << request_type << " interrupted: restarting" << dendl;
- }
- } while (r == -ERESTART);
- return r;
+ const boost::function<void(Context*)>& remote_request) {
+ C_SaferCond ctx;
+ C_InvokeAsyncRequest<I> *req = new C_InvokeAsyncRequest<I>(m_image_ctx,
+ request_type,
+ permit_snapshot,
+ local_request,
+ remote_request,
+ &ctx);
+ req->send();
+ return ctx.wait();
}
} // namespace librbd
int invoke_async_request(const std::string& request_type,
bool permit_snapshot,
- const boost::function<void(Context*)>& local_request,
- const boost::function<int()>& remote_request);
+ const boost::function<void(Context*)>& local,
+ const boost::function<void(Context*)>& remote);
};
} // namespace librbd
void operator()() {
RWLock::RLocker l(ictx->owner_lock);
- result = ictx->image_watcher->notify_flatten(0, *progress_context);
+ C_SaferCond ctx;
+ ictx->image_watcher->notify_flatten(0, *progress_context, &ctx);
+ result = ctx.wait();
}
};
void operator()() {
RWLock::RLocker l(ictx->owner_lock);
- result = ictx->image_watcher->notify_resize(0, 0, *progress_context);
+ C_SaferCond ctx;
+ ictx->image_watcher->notify_resize(0, 0, *progress_context, &ctx);
+ result = ctx.wait();
}
};
void operator()() {
RWLock::RLocker l(ictx->owner_lock);
- result = ictx->image_watcher->notify_rebuild_object_map(0, *progress_context);
+ C_SaferCond ctx;
+ ictx->image_watcher->notify_rebuild_object_map(0, *progress_context, &ctx);
+ result = ctx.wait();
}
};
m_notify_acks = {{NOTIFY_OP_SNAP_CREATE, create_response_message(0)}};
RWLock::RLocker l(ictx->owner_lock);
- ASSERT_EQ(0, ictx->image_watcher->notify_snap_create("snap"));
+ C_SaferCond notify_ctx;
+ ictx->image_watcher->notify_snap_create("snap", ¬ify_ctx);
+ ASSERT_EQ(0, notify_ctx.wait());
NotifyOps expected_notify_ops;
expected_notify_ops += NOTIFY_OP_SNAP_CREATE;
m_notify_acks = {{NOTIFY_OP_SNAP_CREATE, create_response_message(-EEXIST)}};
RWLock::RLocker l(ictx->owner_lock);
- ASSERT_EQ(-EEXIST, ictx->image_watcher->notify_snap_create("snap"));
+ C_SaferCond notify_ctx;
+ ictx->image_watcher->notify_snap_create("snap", ¬ify_ctx);
+ ASSERT_EQ(-EEXIST, notify_ctx.wait());
NotifyOps expected_notify_ops;
expected_notify_ops += NOTIFY_OP_SNAP_CREATE;
m_notify_acks = {{NOTIFY_OP_SNAP_RENAME, create_response_message(0)}};
RWLock::RLocker l(ictx->owner_lock);
- ASSERT_EQ(0, ictx->image_watcher->notify_snap_rename(1, "snap-rename"));
+ C_SaferCond notify_ctx;
+ ictx->image_watcher->notify_snap_rename(1, "snap-rename", ¬ify_ctx);
+ ASSERT_EQ(0, notify_ctx.wait());
NotifyOps expected_notify_ops;
expected_notify_ops += NOTIFY_OP_SNAP_RENAME;
m_notify_acks = {{NOTIFY_OP_SNAP_RENAME, create_response_message(-EEXIST)}};
RWLock::RLocker l(ictx->owner_lock);
- ASSERT_EQ(-EEXIST, ictx->image_watcher->notify_snap_rename(1, "snap-rename"));
+ C_SaferCond notify_ctx;
+ ictx->image_watcher->notify_snap_rename(1, "snap-rename", ¬ify_ctx);
+ ASSERT_EQ(-EEXIST, notify_ctx.wait());
NotifyOps expected_notify_ops;
expected_notify_ops += NOTIFY_OP_SNAP_RENAME;
m_notify_acks = {{NOTIFY_OP_SNAP_REMOVE, create_response_message(0)}};
RWLock::RLocker l(ictx->owner_lock);
- ASSERT_EQ(0, ictx->image_watcher->notify_snap_remove("snap"));
+ C_SaferCond notify_ctx;
+ ictx->image_watcher->notify_snap_remove("snap", ¬ify_ctx);
+ ASSERT_EQ(0, notify_ctx.wait());
NotifyOps expected_notify_ops;
expected_notify_ops += NOTIFY_OP_SNAP_REMOVE;
m_notify_acks = {{NOTIFY_OP_SNAP_PROTECT, create_response_message(0)}};
RWLock::RLocker l(ictx->owner_lock);
- ASSERT_EQ(0, ictx->image_watcher->notify_snap_protect("snap"));
+ C_SaferCond notify_ctx;
+ ictx->image_watcher->notify_snap_protect("snap", ¬ify_ctx);
+ ASSERT_EQ(0, notify_ctx.wait());
NotifyOps expected_notify_ops;
expected_notify_ops += NOTIFY_OP_SNAP_PROTECT;
m_notify_acks = {{NOTIFY_OP_SNAP_UNPROTECT, create_response_message(0)}};
RWLock::RLocker l(ictx->owner_lock);
- ASSERT_EQ(0, ictx->image_watcher->notify_snap_unprotect("snap"));
+ C_SaferCond notify_ctx;
+ ictx->image_watcher->notify_snap_unprotect("snap", ¬ify_ctx);
+ ASSERT_EQ(0, notify_ctx.wait());
NotifyOps expected_notify_ops;
expected_notify_ops += NOTIFY_OP_SNAP_UNPROTECT;
m_notify_acks = {{NOTIFY_OP_RENAME, create_response_message(0)}};
RWLock::RLocker l(ictx->owner_lock);
- ASSERT_EQ(0, ictx->image_watcher->notify_rename("new_name"));
+ C_SaferCond notify_ctx;
+ ictx->image_watcher->notify_rename("new_name", ¬ify_ctx);
+ ASSERT_EQ(0, notify_ctx.wait());
NotifyOps expected_notify_ops;
expected_notify_ops += NOTIFY_OP_RENAME;
ASSERT_TRUE(wait_for_notifies(*ictx));
ASSERT_TRUE(thread.timed_join(boost::posix_time::seconds(10)));
- ASSERT_EQ(-ERESTART, flatten_task.result);
+ ASSERT_EQ(-ETIMEDOUT, flatten_task.result);
}