// vim: ts=8 sw=2 smarttab
#include "common/WorkQueue.h"
+#include "common/errno.h"
#include "librbd/ImageCtx.h"
#include "librbd/Journal.h"
#include "librbd/Utils.h"
CacheGenContextURef ctx = make_gen_lambda_context<ObjectCacheRequest*,
std::function<void(ObjectCacheRequest*)>>
- ([this, read_data, dispatch_result, on_dispatched,
- oid, object_off, object_len](ObjectCacheRequest* ack) {
- handle_read_cache(ack, object_off, object_len, read_data,
- dispatch_result, on_dispatched);
+ ([this, read_data, dispatch_result, on_dispatched, object_no, object_off,
+ object_len, snap_id, &parent_trace](ObjectCacheRequest* ack) {
+ handle_read_cache(ack, object_no, object_off, object_len, snap_id,
+ parent_trace, read_data, dispatch_result,
+ on_dispatched);
});
m_cache_client->lookup_object(m_image_ctx->data_ctx.get_namespace(),
template <typename I>
void ParentCacheObjectDispatch<I>::handle_read_cache(
- ObjectCacheRequest* ack, uint64_t read_off, uint64_t read_len,
- ceph::bufferlist* read_data, io::DispatchResult* dispatch_result,
- Context* on_dispatched) {
+ ObjectCacheRequest* ack, uint64_t object_no, uint64_t read_off,
+ uint64_t read_len, librados::snap_t snap_id,
+ const ZTracer::Trace &parent_trace, ceph::bufferlist* read_data,
+ io::DispatchResult* dispatch_result, Context* on_dispatched) {
auto cct = m_image_ctx->cct;
ldout(cct, 20) << dendl;
ceph_assert(ack->type == RBDSC_READ_REPLY);
std::string file_path = ((ObjectCacheReadReplyData*)ack)->cache_path;
- ceph_assert(file_path != "");
+ if (file_path.empty()) {
+ auto ctx = new LambdaContext(
+ [this, dispatch_result, on_dispatched](int r) {
+ if (r < 0 && r != -ENOENT) {
+ lderr(m_image_ctx->cct) << "failed to read parent: "
+ << cpp_strerror(r) << dendl;
+ }
+ *dispatch_result = io::DISPATCH_RESULT_COMPLETE;
+ on_dispatched->complete(r);
+ });
+ io::util::read_parent<I>(m_image_ctx, object_no, read_off, read_len,
+ snap_id, parent_trace, read_data, ctx);
+ return;
+ }
// try to read from parent image cache
int r = read_object(file_path, read_data, read_off, read_len, on_dispatched);
int read_object(std::string file_path, ceph::bufferlist* read_data,
uint64_t offset, uint64_t length, Context *on_finish);
- void handle_read_cache(
- ceph::immutable_obj_cache::ObjectCacheRequest* ack,
- uint64_t read_off, uint64_t read_len,
- ceph::bufferlist* read_data,
- io::DispatchResult* dispatch_result,
- Context* on_dispatched);
+ void handle_read_cache(ceph::immutable_obj_cache::ObjectCacheRequest* ack,
+ uint64_t object_no, uint64_t read_off,
+ uint64_t read_len, librados::snap_t snap_id,
+ const ZTracer::Trace &parent_trace,
+ ceph::bufferlist* read_data,
+ io::DispatchResult* dispatch_result,
+ Context* on_dispatched);
int handle_register_client(bool reg);
void create_cache_session(Context* on_finish, bool is_reconnect);
#include "include/Context.h"
#include "tools/immutable_object_cache/CacheClient.h"
#include "test/immutable_object_cache/MockCacheDaemon.h"
+#include "librbd/io/Utils.h"
#include "librbd/cache/ParentCacheObjectDispatch.h"
#include "test/librbd/test_mock_fixture.h"
#include "test/librbd/mock/MockImageCtx.h"
struct MockParentImageCacheImageCtx : public MockImageCtx {
MockParentImageCacheImageCtx(ImageCtx& image_ctx)
- : MockImageCtx(image_ctx), shared_cache_path("/tmp/socket/path"){
+ : MockImageCtx(image_ctx) {
}
~MockParentImageCacheImageCtx() {}
-
- std::string shared_cache_path;
};
}; // anonymous namespace
}; // namespace cache
+namespace io {
+namespace util {
+
+namespace {
+
+struct Mock {
+ static Mock* s_instance;
+
+ Mock() {
+ s_instance = this;
+ }
+
+ MOCK_METHOD8(read_parent,
+ void(librbd::MockParentImageCacheImageCtx *, uint64_t, uint64_t,
+ uint64_t, librados::snap_t, const ZTracer::Trace &,
+ ceph::bufferlist*, Context*));
+};
+
+Mock *Mock::s_instance = nullptr;
+
+} // anonymous namespace
+
+template<> void read_parent(
+ librbd::MockParentImageCacheImageCtx *image_ctx, uint64_t object_no,
+ uint64_t off, uint64_t len, librados::snap_t snap_id,
+ const ZTracer::Trace &trace, ceph::bufferlist* data, Context* on_finish) {
+ Mock::s_instance->read_parent(image_ctx, object_no, off, len, snap_id, trace,
+ data, on_finish);
+}
+
+} // namespace util
+} // namespace io
+
}; // namespace librbd
#include "librbd/cache/ParentCacheObjectDispatch.cc"
class TestMockParentCacheObjectDispatch : public TestMockFixture {
public :
typedef cache::ParentCacheObjectDispatch<librbd::MockParentImageCacheImageCtx> MockParentImageCache;
+ typedef io::util::Mock MockUtils;
// ====== mock cache client ====
void expect_cache_run(MockParentImageCache& mparent_image_cache, bool ret_val) {
})));
}
+ void expect_read_parent(MockUtils &mock_utils, uint64_t object_no,
+ uint64_t off, uint64_t len, librados::snap_t snap_id,
+ int r) {
+ EXPECT_CALL(mock_utils,
+ read_parent(_, object_no, off, len, snap_id, _, _, _))
+ .WillOnce(WithArg<7>(CompleteContext(r, static_cast<ContextWQ*>(nullptr))));
+ }
+
void expect_cache_close(MockParentImageCache& mparent_image_cache, int ret_val) {
auto& expect = EXPECT_CALL(*(mparent_image_cache.get_cache_client()), close());
delete mock_parent_image_cache;
}
+TEST_F(TestMockParentCacheObjectDispatch, test_read_dne) {
+ librbd::ImageCtx* ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+ MockParentImageCacheImageCtx mock_image_ctx(*ictx);
+ mock_image_ctx.child = &mock_image_ctx;
+
+ auto mock_parent_image_cache = MockParentImageCache::create(&mock_image_ctx);
+
+ expect_cache_run(*mock_parent_image_cache, 0);
+ C_SaferCond conn_cond;
+ Context* handle_connect = new LambdaContext([&conn_cond](int ret) {
+ ASSERT_EQ(ret, 0);
+ conn_cond.complete(0);
+ });
+ expect_cache_async_connect(*mock_parent_image_cache, 0, handle_connect);
+ Context* ctx = new LambdaContext([](bool reg) {
+ ASSERT_EQ(reg, true);
+ });
+ expect_cache_register(*mock_parent_image_cache, ctx, 0);
+ expect_io_object_dispatcher_register_state(*mock_parent_image_cache, 0);
+ expect_cache_close(*mock_parent_image_cache, 0);
+ expect_cache_stop(*mock_parent_image_cache, 0);
+
+ mock_parent_image_cache->init();
+ conn_cond.wait();
+
+ ASSERT_EQ(mock_parent_image_cache->get_object_dispatch_layer(),
+ io::OBJECT_DISPATCH_LAYER_PARENT_CACHE);
+ expect_cache_session_state(*mock_parent_image_cache, true);
+ ASSERT_EQ(mock_parent_image_cache->get_cache_client()->is_session_work(),
+ true);
+
+ EXPECT_CALL(*(mock_parent_image_cache->get_cache_client()), is_session_work())
+ .WillOnce(Return(true));
+
+ expect_cache_lookup_object(*mock_parent_image_cache, "");
+
+ MockUtils mock_utils;
+ expect_read_parent(mock_utils, 0, 0, 4096, CEPH_NOSNAP, 0);
+
+ C_SaferCond on_dispatched;
+ io::DispatchResult dispatch_result;
+ mock_parent_image_cache->read(0, 0, 4096, CEPH_NOSNAP, 0, {}, nullptr,
+ nullptr, nullptr, &dispatch_result, nullptr,
+ &on_dispatched);
+ ASSERT_EQ(0, on_dispatched.wait());
+
+ mock_parent_image_cache->get_cache_client()->close();
+ mock_parent_image_cache->get_cache_client()->stop();
+ delete mock_parent_image_cache;
+}
+
} // namespace librbd