template <typename I>
void ImageDispatchSpec<I>::finish(int r) {
+ image_dispatcher->finish(r, dispatch_layer, tid);
delete this;
}
template <typename I>
void ImageDispatchSpec<I>::fail(int r) {
+ dispatch_result = DISPATCH_RESULT_COMPLETE;
aio_comp->fail(r);
}
this->register_dispatch(image_dispatch);
}
+template <typename I>
+void ImageDispatcher<I>::finish(int r, ImageDispatchLayer image_dispatch_layer,
+ uint64_t tid) {
+ auto cct = this->m_image_ctx->cct;
+ ldout(cct, 20) << "tid=" << tid << dendl;
+
+ // loop in reverse order from last invoked dispatch layer calling its
+ // handle_finished method
+ while (image_dispatch_layer != IMAGE_DISPATCH_LAYER_NONE) {
+ std::shared_lock locker{this->m_lock};
+ auto it = this->m_dispatches.find(image_dispatch_layer);
+ image_dispatch_layer = static_cast<ImageDispatchLayer>(
+ image_dispatch_layer - 1);
+
+ if (it == this->m_dispatches.end()) {
+ continue;
+ }
+
+ // track callback while lock is dropped so that the layer cannot be shutdown
+ auto& dispatch_meta = it->second;
+ auto dispatch = dispatch_meta.dispatch;
+ auto async_op_tracker = dispatch_meta.async_op_tracker;
+ async_op_tracker->start_op();
+ locker.unlock();
+
+ dispatch->handle_finished(r, tid);
+
+ // safe since dispatch_meta cannot be deleted until ops finished
+ async_op_tracker->finish_op();
+ }
+}
+
template <typename I>
bool ImageDispatcher<I>::send_dispatch(
ImageDispatchInterface* image_dispatch,
public:
ImageDispatcher(ImageCtxT* image_ctx);
+ void finish(int r, ImageDispatchLayer image_dispatch_layer,
+ uint64_t tid) override;
+
protected:
bool send_dispatch(
ImageDispatchInterface* object_dispatch,
#include "include/int_types.h"
#include "librbd/io/DispatcherInterface.h"
#include "librbd/io/ImageDispatchInterface.h"
+#include "librbd/io/Types.h"
struct Context;
struct ImageDispatcherInterface
: public DispatcherInterface<ImageDispatchInterface> {
public:
+
+ virtual void finish(int r, ImageDispatchLayer image_dispatch_layer,
+ uint64_t tid) = 0;
+
};
} // namespace io
MOCK_METHOD2(shut_down_dispatch, void(ImageDispatchLayer, Context*));
MOCK_METHOD1(send, void(ImageDispatchSpec<>*));
+ MOCK_METHOD3(finish, void(int r, ImageDispatchLayer, uint64_t));
};
} // namespace io