image_replayer/snapshot/test_mock_Replayer.cc
image_sync/test_mock_SyncPointCreateRequest.cc
image_sync/test_mock_SyncPointPruneRequest.cc
- pool_watcher/test_mock_RefreshImagesRequest.cc
+ pool_watcher/test_mock_RefreshEntitiesRequest.cc
)
add_ceph_unittest(unittest_rbd_mirror)
}
void map_image(const std::string &global_image_id) {
- ASSERT_TRUE(m_policy->add_image(global_image_id));
+ auto global_id = image_map::GlobalId(MIRROR_ENTITY_TYPE_IMAGE,
+ global_image_id);
- ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_TRUE(m_policy->add_entity(global_id, 1));
- ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
- ASSERT_FALSE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
+
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_id));
+ ASSERT_FALSE(m_policy->finish_action(global_id, 0));
}
void unmap_image(const std::string &global_image_id) {
- ASSERT_TRUE(m_policy->remove_image(global_image_id));
+ auto global_id = image_map::GlobalId(MIRROR_ENTITY_TYPE_IMAGE,
+ global_image_id);
+
+ ASSERT_TRUE(m_policy->remove_entity(global_id));
- ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_MAP_REMOVE, m_policy->start_action(global_image_id));
- ASSERT_FALSE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_REMOVE, m_policy->start_action(global_id));
+ ASSERT_FALSE(m_policy->finish_action(global_id, 0));
}
void shuffle_image(const std::string &global_image_id) {
- ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ auto global_id = image_map::GlobalId(MIRROR_ENTITY_TYPE_IMAGE,
+ global_image_id);
+
+ ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
- ASSERT_FALSE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_id));
+ ASSERT_FALSE(m_policy->finish_action(global_id, 0));
}
Policy *m_policy;
TEST_F(TestImageMapPolicy, NegativeLookup) {
const std::string global_image_id = "global id 1";
- LookupInfo info = m_policy->lookup(global_image_id);
+ LookupInfo info = m_policy->lookup({MIRROR_ENTITY_TYPE_IMAGE,
+ global_image_id});
ASSERT_TRUE(info.instance_id == UNMAPPED_INSTANCE_ID);
}
TEST_F(TestImageMapPolicy, Init) {
const std::string global_image_id = "global id 1";
- m_policy->init({{global_image_id, {"9876", {}, {}}}});
+ m_policy->init({{{MIRROR_ENTITY_TYPE_IMAGE, global_image_id},
+ {"9876", {}, {}}}});
ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
ASSERT_FALSE(m_policy->finish_action(global_image_id, 0));
map_image(global_image_id);
- LookupInfo info = m_policy->lookup(global_image_id);
+ LookupInfo info = m_policy->lookup({MIRROR_ENTITY_TYPE_IMAGE,
+ global_image_id});
ASSERT_TRUE(info.instance_id != UNMAPPED_INSTANCE_ID);
}
// map image
map_image(global_image_id);
- LookupInfo info = m_policy->lookup(global_image_id);
+ LookupInfo info = m_policy->lookup({MIRROR_ENTITY_TYPE_IMAGE,
+ global_image_id});
ASSERT_TRUE(info.instance_id != UNMAPPED_INSTANCE_ID);
// unmap image
unmap_image(global_image_id);
- info = m_policy->lookup(global_image_id);
+ info = m_policy->lookup({MIRROR_ENTITY_TYPE_IMAGE, global_image_id});
ASSERT_TRUE(info.instance_id == UNMAPPED_INSTANCE_ID);
}
// map image
map_image(global_image_id);
- LookupInfo info = m_policy->lookup(global_image_id);
+ LookupInfo info = m_policy->lookup({MIRROR_ENTITY_TYPE_IMAGE,
+ global_image_id});
ASSERT_TRUE(info.instance_id != UNMAPPED_INSTANCE_ID);
}
- std::set<std::string> shuffle_global_image_ids;
- m_policy->add_instances({"9876"}, &shuffle_global_image_ids);
+ image_map::GlobalIds shuffle_global_ids;
+ m_policy->add_instances({"9876"}, &shuffle_global_ids);
- for (auto const &global_image_id : shuffle_global_image_ids) {
- shuffle_image(global_image_id);
+ for (auto const &global_id : shuffle_global_ids) {
+ ASSERT_EQ(global_id.type, MIRROR_ENTITY_TYPE_IMAGE);
+ shuffle_image(global_id.id);
- LookupInfo info = m_policy->lookup(global_image_id);
+ LookupInfo info = m_policy->lookup(global_id);
ASSERT_TRUE(info.instance_id != UNMAPPED_INSTANCE_ID);
}
}
"global id 1", "global id 2", "global id 3", "global id 4", "global id 5"
};
- std::set<std::string> shuffle_global_image_ids;
+ image_map::GlobalIds shuffle_global_ids;
m_policy->add_instances({stringify(m_local_io_ctx.get_instance_id())},
- &shuffle_global_image_ids);
+ &shuffle_global_ids);
for (auto const &global_image_id : global_image_ids) {
// map image
map_image(global_image_id);
- LookupInfo info = m_policy->lookup(global_image_id);
+ LookupInfo info = m_policy->lookup({MIRROR_ENTITY_TYPE_IMAGE,
+ global_image_id});
ASSERT_TRUE(info.instance_id != UNMAPPED_INSTANCE_ID);
}
- m_policy->add_instances({"9876"}, &shuffle_global_image_ids);
+ m_policy->add_instances({"9876"}, &shuffle_global_ids);
- for (auto const &global_image_id : shuffle_global_image_ids) {
- shuffle_image(global_image_id);
+ for (auto const &global_id : shuffle_global_ids) {
+ ASSERT_EQ(global_id.type, MIRROR_ENTITY_TYPE_IMAGE);
+ shuffle_image(global_id.id);
- LookupInfo info = m_policy->lookup(global_image_id);
+ LookupInfo info = m_policy->lookup(global_id);
ASSERT_TRUE(info.instance_id != UNMAPPED_INSTANCE_ID);
}
// record which of the images got migrated to the new instance
- std::set<std::string> remapped_global_image_ids;
- for (auto const &global_image_id: shuffle_global_image_ids) {
- LookupInfo info = m_policy->lookup(global_image_id);
+ image_map::GlobalIds remapped_global_ids;
+ for (auto const &global_id: shuffle_global_ids) {
+ LookupInfo info = m_policy->lookup(global_id);
if (info.instance_id == "9876") {
- remapped_global_image_ids.emplace(global_image_id);
+ remapped_global_ids.emplace(global_id);
}
}
- shuffle_global_image_ids.clear();
- m_policy->remove_instances({"9876"}, &shuffle_global_image_ids);
+ shuffle_global_ids.clear();
+ m_policy->remove_instances({"9876"}, &shuffle_global_ids);
- ASSERT_TRUE(shuffle_global_image_ids == remapped_global_image_ids);
+ ASSERT_TRUE(shuffle_global_ids == remapped_global_ids);
- for (auto const &global_image_id : shuffle_global_image_ids) {
- shuffle_image(global_image_id);
+ for (auto const &global_id : shuffle_global_ids) {
+ shuffle_image(global_id.id);
- LookupInfo info = m_policy->lookup(global_image_id);
+ LookupInfo info = m_policy->lookup(global_id);
ASSERT_TRUE(info.instance_id != UNMAPPED_INSTANCE_ID);
}
}
TEST_F(TestImageMapPolicy, RetryMapUpdate) {
- const std::string global_image_id = "global id 1";
+ auto global_id = image_map::GlobalId(MIRROR_ENTITY_TYPE_IMAGE,
+ "global id 1");
- ASSERT_TRUE(m_policy->add_image(global_image_id));
+ ASSERT_TRUE(m_policy->add_entity(global_id, 1));
- ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_image_id));
+ ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_id));
// on-disk map update failed
- ASSERT_TRUE(m_policy->finish_action(global_image_id, -EIO));
+ ASSERT_TRUE(m_policy->finish_action(global_id, -EIO));
- ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
- ASSERT_FALSE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_id));
+ ASSERT_FALSE(m_policy->finish_action(global_id, 0));
- LookupInfo info = m_policy->lookup(global_image_id);
+ LookupInfo info = m_policy->lookup(global_id);
ASSERT_TRUE(info.instance_id != UNMAPPED_INSTANCE_ID);
}
TEST_F(TestImageMapPolicy, MapFailureAndUnmap) {
- const std::string global_image_id = "global id 1";
+ auto global_id = image_map::GlobalId(MIRROR_ENTITY_TYPE_IMAGE,
+ "global id 1");
- ASSERT_TRUE(m_policy->add_image(global_image_id));
+ ASSERT_TRUE(m_policy->add_entity(global_id, 1));
- ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_id));
- std::set<std::string> shuffle_global_image_ids;
- m_policy->add_instances({"9876"}, &shuffle_global_image_ids);
- ASSERT_TRUE(shuffle_global_image_ids.empty());
+ image_map::GlobalIds shuffle_global_ids;
+ m_policy->add_instances({"9876"}, &shuffle_global_ids);
+ ASSERT_TRUE(shuffle_global_ids.empty());
m_policy->remove_instances({stringify(m_local_io_ctx.get_instance_id())},
- &shuffle_global_image_ids);
- ASSERT_TRUE(shuffle_global_image_ids.empty());
+ &shuffle_global_ids);
+ ASSERT_TRUE(shuffle_global_ids.empty());
- ASSERT_TRUE(m_policy->finish_action(global_image_id, -EBLOCKLISTED));
+ ASSERT_TRUE(m_policy->finish_action(global_id, -EBLOCKLISTED));
- ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, -ENOENT));
+ ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, -ENOENT));
- ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
- ASSERT_FALSE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_id));
+ ASSERT_FALSE(m_policy->finish_action(global_id, 0));
- ASSERT_TRUE(m_policy->remove_image(global_image_id));
+ ASSERT_TRUE(m_policy->remove_entity(global_id));
- ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_MAP_REMOVE, m_policy->start_action(global_image_id));
- ASSERT_FALSE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_REMOVE, m_policy->start_action(global_id));
+ ASSERT_FALSE(m_policy->finish_action(global_id, 0));
}
TEST_F(TestImageMapPolicy, ReshuffleWithMapFailure) {
"global id 6"
};
- std::set<std::string> shuffle_global_image_ids;
+ image_map::GlobalIds shuffle_global_ids;
m_policy->add_instances({stringify(m_local_io_ctx.get_instance_id())},
- &shuffle_global_image_ids);
+ &shuffle_global_ids);
for (auto const &global_image_id : global_image_ids) {
// map image
map_image(global_image_id);
- LookupInfo info = m_policy->lookup(global_image_id);
+ LookupInfo info = m_policy->lookup({MIRROR_ENTITY_TYPE_IMAGE,
+ global_image_id});
ASSERT_TRUE(info.instance_id != UNMAPPED_INSTANCE_ID);
}
- m_policy->add_instances({"9876"}, &shuffle_global_image_ids);
- ASSERT_FALSE(shuffle_global_image_ids.empty());
+ m_policy->add_instances({"9876"}, &shuffle_global_ids);
+ ASSERT_FALSE(shuffle_global_ids.empty());
- const std::string global_image_id = *(shuffle_global_image_ids.begin());
- shuffle_global_image_ids.clear();
+ auto global_id = *(shuffle_global_ids.begin());
+ shuffle_global_ids.clear();
- ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_id));
// peer unavailable
- m_policy->remove_instances({"9876"}, &shuffle_global_image_ids);
- ASSERT_TRUE(shuffle_global_image_ids.empty());
+ m_policy->remove_instances({"9876"}, &shuffle_global_ids);
+ ASSERT_TRUE(shuffle_global_ids.empty());
- ASSERT_TRUE(m_policy->finish_action(global_image_id, -EBLOCKLISTED));
+ ASSERT_TRUE(m_policy->finish_action(global_id, -EBLOCKLISTED));
- ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
- ASSERT_FALSE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_id));
+ ASSERT_FALSE(m_policy->finish_action(global_id, 0));
}
TEST_F(TestImageMapPolicy, ShuffleFailureAndRemove) {
"global id 6"
};
- std::set<std::string> shuffle_global_image_ids;
+ image_map::GlobalIds shuffle_global_ids;
m_policy->add_instances({stringify(m_local_io_ctx.get_instance_id())},
- &shuffle_global_image_ids);
+ &shuffle_global_ids);
for (auto const &global_image_id : global_image_ids) {
// map image
map_image(global_image_id);
- LookupInfo info = m_policy->lookup(global_image_id);
+ LookupInfo info = m_policy->lookup({MIRROR_ENTITY_TYPE_IMAGE,
+ global_image_id});
ASSERT_TRUE(info.instance_id != UNMAPPED_INSTANCE_ID);
}
- m_policy->add_instances({"9876"}, &shuffle_global_image_ids);
- ASSERT_FALSE(shuffle_global_image_ids.empty());
+ m_policy->add_instances({"9876"}, &shuffle_global_ids);
+ ASSERT_FALSE(shuffle_global_ids.empty());
- std::string global_image_id = *(shuffle_global_image_ids.begin());
- shuffle_global_image_ids.clear();
+ auto global_id = *(shuffle_global_ids.begin());
+ shuffle_global_ids.clear();
- ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_id));
// peer unavailable
- m_policy->remove_instances({"9876"}, &shuffle_global_image_ids);
- ASSERT_TRUE(shuffle_global_image_ids.empty());
+ m_policy->remove_instances({"9876"}, &shuffle_global_ids);
+ ASSERT_TRUE(shuffle_global_ids.empty());
- ASSERT_TRUE(m_policy->finish_action(global_image_id, -EBLOCKLISTED));
+ ASSERT_TRUE(m_policy->finish_action(global_id, -EBLOCKLISTED));
- ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
- ASSERT_FALSE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_id));
+ ASSERT_FALSE(m_policy->finish_action(global_id, 0));
- ASSERT_TRUE(m_policy->remove_image(global_image_id));
+ ASSERT_TRUE(m_policy->remove_entity(global_id));
- ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_MAP_REMOVE, m_policy->start_action(global_image_id));
- ASSERT_FALSE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_REMOVE, m_policy->start_action(global_id));
+ ASSERT_FALSE(m_policy->finish_action(global_id, 0));
- LookupInfo info = m_policy->lookup(global_image_id);
+ LookupInfo info = m_policy->lookup(global_id);
ASSERT_TRUE(info.instance_id == UNMAPPED_INSTANCE_ID);
}
TEST_F(TestImageMapPolicy, InitialInstanceUpdate) {
- const std::string global_image_id = "global id 1";
+ auto global_id = image_map::GlobalId(MIRROR_ENTITY_TYPE_IMAGE,
+ "global id 1");
- m_policy->init({{global_image_id, {"9876", {}, {}}}});
+ m_policy->init({{global_id, {"9876", {}, {}}}});
- ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_id));
auto instance_id = stringify(m_local_io_ctx.get_instance_id());
- std::set<std::string> shuffle_global_image_ids;
- m_policy->add_instances({instance_id}, &shuffle_global_image_ids);
+ image_map::GlobalIds shuffle_global_ids;
+ m_policy->add_instances({instance_id}, &shuffle_global_ids);
- ASSERT_EQ(0U, shuffle_global_image_ids.size());
- ASSERT_TRUE(m_policy->finish_action(global_image_id, -ENOENT));
+ ASSERT_EQ(0U, shuffle_global_ids.size());
+ ASSERT_TRUE(m_policy->finish_action(global_id, -ENOENT));
- ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_RELEASE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_image_id));
- ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_MAP_UPDATE, m_policy->start_action(global_id));
+ ASSERT_TRUE(m_policy->finish_action(global_id, 0));
- ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
- ASSERT_FALSE(m_policy->finish_action(global_image_id, 0));
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_id));
+ ASSERT_FALSE(m_policy->finish_action(global_id, 0));
}
} // namespace image_map
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "test/rbd_mirror/test_mock_fixture.h"
+#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
+#include "test/librados_test_stub/MockTestMemRadosClient.h"
+#include "test/librbd/mock/MockImageCtx.h"
+#include "tools/rbd_mirror/pool_watcher/RefreshEntitiesRequest.h"
+#include "include/stringify.h"
+
+namespace librbd {
+namespace {
+
+struct MockTestImageCtx : public librbd::MockImageCtx {
+ explicit MockTestImageCtx(librbd::ImageCtx &image_ctx)
+ : librbd::MockImageCtx(image_ctx) {
+ }
+};
+
+} // anonymous namespace
+} // namespace librbd
+
+// template definitions
+#include "tools/rbd_mirror/pool_watcher/RefreshEntitiesRequest.cc"
+template class rbd::mirror::pool_watcher::RefreshEntitiesRequest<librbd::MockTestImageCtx>;
+
+namespace rbd {
+namespace mirror {
+namespace pool_watcher {
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::StrEq;
+using ::testing::WithArg;
+
+class TestMockPoolWatcherRefreshEntitiesRequest : public TestMockFixture {
+public:
+ typedef RefreshEntitiesRequest<librbd::MockTestImageCtx> MockRefreshEntitiesRequest;
+
+ void expect_mirror_image_list(librados::IoCtx &io_ctx,
+ const std::map<std::string, std::string> &ids,
+ int r) {
+ bufferlist bl;
+ encode(ids, bl);
+
+ EXPECT_CALL(get_mock_io_ctx(io_ctx),
+ exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_image_list"),
+ _, _, _, _))
+ .WillOnce(DoAll(WithArg<5>(Invoke([bl](bufferlist *out_bl) {
+ *out_bl = bl;
+ })),
+ Return(r)));
+ }
+
+};
+
+TEST_F(TestMockPoolWatcherRefreshEntitiesRequest, Success) {
+ InSequence seq;
+ expect_mirror_image_list(m_remote_io_ctx, {{"local id", "global id"}}, 0);
+
+ C_SaferCond ctx;
+ std::map<MirrorEntity, std::string> entities;
+ MockRefreshEntitiesRequest *req = new MockRefreshEntitiesRequest(
+ m_remote_io_ctx, &entities, &ctx);
+
+ req->send();
+ ASSERT_EQ(0, ctx.wait());
+
+ std::map<MirrorEntity, std::string> expected_entities =
+ {{{MIRROR_ENTITY_TYPE_IMAGE, "global id", 1}, "local id"}};
+ ASSERT_EQ(expected_entities, entities);
+}
+
+TEST_F(TestMockPoolWatcherRefreshEntitiesRequest, LargeDirectory) {
+ InSequence seq;
+ std::map<std::string, std::string> mirror_list;
+ std::map<MirrorEntity, std::string> expected_entities;
+ for (uint32_t idx = 1; idx <= 1024; ++idx) {
+ mirror_list.insert(std::make_pair("local id " + stringify(idx),
+ "global id " + stringify(idx)));
+ expected_entities.insert(
+ {{MIRROR_ENTITY_TYPE_IMAGE, "global id " + stringify(idx), 1},
+ "local id " + stringify(idx)});
+ }
+
+ expect_mirror_image_list(m_remote_io_ctx, mirror_list, 0);
+ expect_mirror_image_list(m_remote_io_ctx, {{"local id", "global id"}}, 0);
+
+ C_SaferCond ctx;
+ std::map<MirrorEntity, std::string> entities;
+ MockRefreshEntitiesRequest *req = new MockRefreshEntitiesRequest(
+ m_remote_io_ctx, &entities, &ctx);
+
+ req->send();
+ ASSERT_EQ(0, ctx.wait());
+
+ expected_entities.insert(
+ {{MIRROR_ENTITY_TYPE_IMAGE, "global id", 1}, "local id"});
+ ASSERT_EQ(expected_entities, entities);
+}
+
+TEST_F(TestMockPoolWatcherRefreshEntitiesRequest, MirrorImageListError) {
+ InSequence seq;
+ expect_mirror_image_list(m_remote_io_ctx, {}, -EINVAL);
+
+ C_SaferCond ctx;
+ std::map<MirrorEntity, std::string> entities;
+ MockRefreshEntitiesRequest *req = new MockRefreshEntitiesRequest(
+ m_remote_io_ctx, &entities, &ctx);
+
+ req->send();
+ ASSERT_EQ(-EINVAL, ctx.wait());
+}
+
+} // namespace pool_watcher
+} // namespace mirror
+} // namespace rbd
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "test/rbd_mirror/test_mock_fixture.h"
-#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
-#include "test/librados_test_stub/MockTestMemRadosClient.h"
-#include "test/librbd/mock/MockImageCtx.h"
-#include "tools/rbd_mirror/pool_watcher/RefreshImagesRequest.h"
-#include "include/stringify.h"
-
-namespace librbd {
-namespace {
-
-struct MockTestImageCtx : public librbd::MockImageCtx {
- explicit MockTestImageCtx(librbd::ImageCtx &image_ctx)
- : librbd::MockImageCtx(image_ctx) {
- }
-};
-
-} // anonymous namespace
-} // namespace librbd
-
-// template definitions
-#include "tools/rbd_mirror/pool_watcher/RefreshImagesRequest.cc"
-template class rbd::mirror::pool_watcher::RefreshImagesRequest<librbd::MockTestImageCtx>;
-
-namespace rbd {
-namespace mirror {
-namespace pool_watcher {
-
-using ::testing::_;
-using ::testing::DoAll;
-using ::testing::InSequence;
-using ::testing::Invoke;
-using ::testing::Return;
-using ::testing::StrEq;
-using ::testing::WithArg;
-
-class TestMockPoolWatcherRefreshImagesRequest : public TestMockFixture {
-public:
- typedef RefreshImagesRequest<librbd::MockTestImageCtx> MockRefreshImagesRequest;
-
- void expect_mirror_image_list(librados::IoCtx &io_ctx,
- const std::map<std::string, std::string> &ids,
- int r) {
- bufferlist bl;
- encode(ids, bl);
-
- EXPECT_CALL(get_mock_io_ctx(io_ctx),
- exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_image_list"),
- _, _, _, _))
- .WillOnce(DoAll(WithArg<5>(Invoke([bl](bufferlist *out_bl) {
- *out_bl = bl;
- })),
- Return(r)));
- }
-
-};
-
-TEST_F(TestMockPoolWatcherRefreshImagesRequest, Success) {
- InSequence seq;
- expect_mirror_image_list(m_remote_io_ctx, {{"local id", "global id"}}, 0);
-
- C_SaferCond ctx;
- ImageIds image_ids;
- MockRefreshImagesRequest *req = new MockRefreshImagesRequest(
- m_remote_io_ctx, &image_ids, &ctx);
-
- req->send();
- ASSERT_EQ(0, ctx.wait());
-
- ImageIds expected_image_ids = {{"global id", "local id"}};
- ASSERT_EQ(expected_image_ids, image_ids);
-}
-
-TEST_F(TestMockPoolWatcherRefreshImagesRequest, LargeDirectory) {
- InSequence seq;
- std::map<std::string, std::string> mirror_list;
- ImageIds expected_image_ids;
- for (uint32_t idx = 1; idx <= 1024; ++idx) {
- mirror_list.insert(std::make_pair("local id " + stringify(idx),
- "global id " + stringify(idx)));
- expected_image_ids.insert({{"global id " + stringify(idx),
- "local id " + stringify(idx)}});
- }
-
- expect_mirror_image_list(m_remote_io_ctx, mirror_list, 0);
- expect_mirror_image_list(m_remote_io_ctx, {{"local id", "global id"}}, 0);
-
- C_SaferCond ctx;
- ImageIds image_ids;
- MockRefreshImagesRequest *req = new MockRefreshImagesRequest(
- m_remote_io_ctx, &image_ids, &ctx);
-
- req->send();
- ASSERT_EQ(0, ctx.wait());
-
- expected_image_ids.insert({"global id", "local id"});
- ASSERT_EQ(expected_image_ids, image_ids);
-}
-
-TEST_F(TestMockPoolWatcherRefreshImagesRequest, MirrorImageListError) {
- InSequence seq;
- expect_mirror_image_list(m_remote_io_ctx, {}, -EINVAL);
-
- C_SaferCond ctx;
- ImageIds image_ids;
- MockRefreshImagesRequest *req = new MockRefreshImagesRequest(
- m_remote_io_ctx, &image_ids, &ctx);
-
- req->send();
- ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-} // namespace pool_watcher
-} // namespace mirror
-} // namespace rbd
using namespace std::chrono_literals;
-using rbd::mirror::ImageId;
-using rbd::mirror::ImageIds;
+using rbd::mirror::MirrorEntity;
+using rbd::mirror::MirrorEntities;
using rbd::mirror::PoolWatcher;
using rbd::mirror::PeerSpec;
using rbd::mirror::RadosRef;
struct PoolWatcherListener : public rbd::mirror::pool_watcher::Listener {
TestPoolWatcher *test;
ceph::condition_variable cond;
- ImageIds image_ids;
+ set<string> image_ids;
explicit PoolWatcherListener(TestPoolWatcher *test) : test(test) {
}
void handle_update(const std::string &mirror_uuid,
- ImageIds &&added_image_ids,
- ImageIds &&removed_image_ids) override {
+ MirrorEntities &&added_entities,
+ MirrorEntities &&removed_entities) override {
std::lock_guard locker{test->m_lock};
- for (auto &image_id : removed_image_ids) {
- image_ids.erase(image_id);
+ for (auto &entity : removed_entities) {
+ EXPECT_EQ(entity.type, rbd::mirror::MIRROR_ENTITY_TYPE_IMAGE);
+ image_ids.erase(entity.global_id);
+ }
+ for (auto &entity : added_entities) {
+ EXPECT_EQ(entity.type, rbd::mirror::MIRROR_ENTITY_TYPE_IMAGE);
+ image_ids.insert(entity.global_id);
}
- image_ids.insert(added_image_ids.begin(), added_image_ids.end());
cond.notify_all();
}
};
m_pool_watcher->init();
}
- string get_image_id(librados::IoCtx *ioctx, const string &image_name) {
- string obj = librbd::util::id_obj_name(image_name);
- string id;
- EXPECT_EQ(0, librbd::cls_client::get_id(ioctx, obj, &id));
- return id;
- }
-
void create_image(const string &pool_name, bool mirrored=true,
string *image_name=nullptr) {
uint64_t features = librbd::util::get_rbd_default_features(g_ceph_context);
sizeof(mirror_image_info)));
image.close();
- m_mirrored_images.insert(ImageId(
- mirror_image_info.global_id, get_image_id(&ioctx, name)));
+ m_mirrored_images.insert(mirror_image_info.global_id);
}
if (image_name != nullptr)
*image_name = name;
sizeof(mirror_image_info)));
image.close();
- m_mirrored_images.insert(ImageId(
- mirror_image_info.global_id, get_image_id(&cioctx, name)));
+ m_mirrored_images.insert(mirror_image_info.global_id);
}
if (image_name != nullptr)
*image_name = name;
std::unique_ptr<PoolWatcher<> > m_pool_watcher;
set<string> m_pools;
- ImageIds m_mirrored_images;
+ set<string> m_mirrored_images;
uint64_t m_image_number;
uint64_t m_snap_number;
template <>
struct LoadRequest<librbd::MockTestImageCtx> {
- std::map<std::string, cls::rbd::MirrorImageMap> *image_map;
+ std::map<GlobalId, cls::rbd::MirrorImageMap> *image_map;
Context *on_finish = nullptr;
static LoadRequest *s_instance;
static LoadRequest *create(librados::IoCtx &ioctx,
- std::map<std::string, cls::rbd::MirrorImageMap> *image_map,
+ std::map<GlobalId, cls::rbd::MirrorImageMap> *image_map,
Context *on_finish) {
ceph_assert(s_instance != nullptr);
s_instance->image_map = image_map;
Context *on_finish = nullptr;
static UpdateRequest *s_instance;
static UpdateRequest *create(librados::IoCtx &ioctx,
- std::map<std::string, cls::rbd::MirrorImageMap> &&update_mapping,
- std::set<std::string> &&global_image_ids,
+ std::map<GlobalId, cls::rbd::MirrorImageMap> &&update_mapping,
+ GlobalIds &&removed_global_ids,
Context *on_finish) {
ceph_assert(s_instance != nullptr);
s_instance->on_finish = on_finish;
}
}
+ MirrorEntities make_image_entities(const std::set<std::string> &global_image_ids) {
+ MirrorEntities entities;
+ for (auto &global_image_id : global_image_ids) {
+ entities.emplace(MIRROR_ENTITY_TYPE_IMAGE, global_image_id, 1);
+ }
+ return entities;
+ }
+
ceph::mutex m_lock = ceph::make_mutex("TestMockImageMap::m_lock");
ceph::condition_variable m_cond;
uint32_t m_notify_update_count = 0;
std::set<std::string> global_image_ids{
"global id 1", "global id 2"
};
- std::set<std::string> global_image_ids_ack(global_image_ids);
// UPDATE_MAPPING+ACQUIRE
expect_add_event(mock_threads);
listener_acquire_images(mock_listener, global_image_ids, &peer_ack_ctxs);
// initial image list
- mock_image_map->update_images("", std::move(global_image_ids), {});
+ auto entities = make_image_entities(global_image_ids);
+ mock_image_map->update_images("", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(global_image_ids.size()));
// remote peer ACKs image acquire request
- remote_peer_ack_nowait(mock_image_map.get(), global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
std::set<std::string> initial_global_image_ids{
"global id 1", "global id 2"
};
- std::set<std::string> initial_global_image_ids_ack(initial_global_image_ids);
-
std::set<std::string> remove_global_image_ids{
"global id 1", "global id 2"
};
- std::set<std::string> remove_global_image_ids_ack(remove_global_image_ids);
// UPDATE_MAPPING+ACQUIRE
expect_add_event(mock_threads);
&peer_ack_ctxs);
// initial image list
- mock_image_map->update_images("", std::move(initial_global_image_ids), {});
+ auto entities = make_image_entities(initial_global_image_ids);
+ mock_image_map->update_images("", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(initial_global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(initial_global_image_ids.size()));
// remote peer ACKs image acquire request
- remote_peer_ack_nowait(mock_image_map.get(), initial_global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), initial_global_image_ids, 0,
&peer_ack_ctxs);
// RELEASE+REMOVE_MAPPING
0);
// remove images
- mock_image_map->update_images("", {}, std::move(remove_global_image_ids));
- ASSERT_TRUE(wait_for_listener_notify(remove_global_image_ids_ack.size()));
+ entities = make_image_entities(remove_global_image_ids);
+ mock_image_map->update_images("", {}, std::move(entities));
+ ASSERT_TRUE(wait_for_listener_notify(remove_global_image_ids.size()));
- remote_peer_ack_wait(mock_image_map.get(), remove_global_image_ids_ack, 0,
+ remote_peer_ack_wait(mock_image_map.get(), remove_global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
std::set<std::string> initial_global_image_ids{
"global id 1", "global id 2"
};
- std::set<std::string> initial_global_image_ids_ack(initial_global_image_ids);
-
std::set<std::string> remove_global_image_ids{
"global id 1", "global id 2"
};
- std::set<std::string> remove_global_image_ids_ack(remove_global_image_ids);
// UPDATE_MAPPING+ACQUIRE
expect_add_event(mock_threads);
&peer_ack_ctxs);
// initial image list
- mock_image_map->update_images("uuid1", std::move(initial_global_image_ids),
- {});
+ auto entities = make_image_entities(initial_global_image_ids);
+ mock_image_map->update_images("uuid1", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(initial_global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(initial_global_image_ids.size()));
// remote peer ACKs image acquire request
- remote_peer_ack_nowait(mock_image_map.get(), initial_global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), initial_global_image_ids, 0,
&peer_ack_ctxs);
// RELEASE+REMOVE_MAPPING
0);
// remove images
- mock_image_map->update_images("uuid1", {}, std::move(remove_global_image_ids));
- ASSERT_TRUE(wait_for_listener_notify(remove_global_image_ids_ack.size() * 2));
+ entities = make_image_entities(remove_global_image_ids);
+ mock_image_map->update_images("uuid1", {}, std::move(entities));
+ ASSERT_TRUE(wait_for_listener_notify(remove_global_image_ids.size() * 2));
- remote_peer_ack_nowait(mock_image_map.get(), remove_global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), remove_global_image_ids, 0,
&peer_remove_ack_ctxs);
- remote_peer_ack_wait(mock_image_map.get(), remove_global_image_ids_ack, 0,
+ remote_peer_ack_wait(mock_image_map.get(), remove_global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
std::set<std::string> initial_global_image_ids{
"global id 1", "global id 2"
};
- std::set<std::string> initial_global_image_ids_dup(initial_global_image_ids);
- std::set<std::string> initial_global_image_ids_ack(initial_global_image_ids);
std::set<std::string> remove_global_image_ids{
"global id 1", "global id 2"
};
- std::set<std::string> remove_global_image_ids_dup(remove_global_image_ids);
- std::set<std::string> remove_global_image_ids_ack(remove_global_image_ids);
// UPDATE_MAPPING+ACQUIRE
expect_add_event(mock_threads);
&peer_ack_ctxs);
// initial image list
- mock_image_map->update_images("uuid1", std::move(initial_global_image_ids), {});
+ auto entities = make_image_entities(initial_global_image_ids);
+ mock_image_map->update_images("uuid1", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(initial_global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(initial_global_image_ids.size()));
// trigger duplicate "add" event
wait_for_scheduled_task();
- mock_image_map->update_images("uuid1", std::move(initial_global_image_ids_dup), {});
+ entities = make_image_entities(initial_global_image_ids);
+ mock_image_map->update_images("uuid1", std::move(entities), {});
// remote peer ACKs image acquire request
- remote_peer_ack_nowait(mock_image_map.get(), initial_global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), initial_global_image_ids, 0,
&peer_ack_ctxs);
// RELEASE+REMOVE_MAPPING
update_map_request(mock_threads, mock_update_request, remove_global_image_ids, 0);
// remove images
- mock_image_map->update_images("uuid1", {}, std::move(remove_global_image_ids));
- ASSERT_TRUE(wait_for_listener_notify(remove_global_image_ids_ack.size() * 2));
+ entities = make_image_entities(remove_global_image_ids);
+ mock_image_map->update_images("uuid1", {}, std::move(entities));
+ ASSERT_TRUE(wait_for_listener_notify(remove_global_image_ids.size() * 2));
- remote_peer_ack_nowait(mock_image_map.get(), remove_global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), remove_global_image_ids, 0,
&peer_remove_ack_ctxs);
- remote_peer_ack_wait(mock_image_map.get(), remove_global_image_ids_ack, 0,
+ remote_peer_ack_wait(mock_image_map.get(), remove_global_image_ids, 0,
&peer_ack_ctxs);
// trigger duplicate "remove" notification
- mock_image_map->update_images("uuid1", {}, std::move(remove_global_image_ids_dup));
+ entities = make_image_entities(remove_global_image_ids);
+ mock_image_map->update_images("uuid1", {}, std::move(entities));
wait_for_scheduled_task();
ASSERT_EQ(0, when_shut_down(mock_image_map.get()));
std::set<std::string> initial_global_image_ids{
"global id 1", "global id 2"
};
- std::set<std::string> initial_global_image_ids_ack(initial_global_image_ids);
// UPDATE_MAPPING failure
expect_add_event(mock_threads);
&peer_ack_ctxs);
// initial image list
- mock_image_map->update_images("uuid1", std::move(initial_global_image_ids), {});
+ auto entities = make_image_entities(initial_global_image_ids);
+ mock_image_map->update_images("uuid1", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(initial_global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(initial_global_image_ids.size()));
// remote peer ACKs image acquire request
- remote_peer_ack_nowait(mock_image_map.get(), initial_global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), initial_global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
std::set<std::string> initial_remote_global_image_ids{
"global id 1"
};
- std::set<std::string> initial_remote_global_image_ids_ack(initial_remote_global_image_ids);
// local image set
std::set<std::string> initial_local_global_image_ids{
std::set<std::string> remote_remove_global_image_ids{
"global id 1"
};
- std::set<std::string> remote_remove_global_image_ids_ack(remote_remove_global_image_ids);
-
std::set<std::string> local_remove_global_image_ids{
"global id 1"
};
- std::set<std::string> local_remove_global_image_ids_ack(local_remove_global_image_ids);
// UPDATE_MAPPING+ACQUIRE
expect_add_event(mock_threads);
&peer_ack_ctxs);
// initial remote image list
- mock_image_map->update_images("uuid1", std::move(initial_remote_global_image_ids), {});
+ auto entities = make_image_entities(initial_remote_global_image_ids);
+ mock_image_map->update_images("uuid1", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(initial_remote_global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(initial_remote_global_image_ids.size()));
// remote peer ACKs image acquire request
- remote_peer_ack_nowait(mock_image_map.get(),
- initial_remote_global_image_ids_ack, 0,
- &peer_ack_ctxs);
+ remote_peer_ack_nowait(mock_image_map.get(), initial_remote_global_image_ids,
+ 0, &peer_ack_ctxs);
// set initial local image list -- this is a no-op from policy pov
- mock_image_map->update_images("", std::move(initial_local_global_image_ids), {});
+ entities = make_image_entities(initial_local_global_image_ids);
+ mock_image_map->update_images("", std::move(entities), {});
// remove remote images -- this should be a no-op from policy pov
// except the listener notification
listener_remove_images(mock_listener, "uuid1", remote_remove_global_image_ids,
&peer_ack_remove_ctxs);
- mock_image_map->update_images("uuid1", {}, std::move(remote_remove_global_image_ids));
- ASSERT_TRUE(wait_for_listener_notify(remote_remove_global_image_ids_ack.size()));
+ entities = make_image_entities(remote_remove_global_image_ids);
+ mock_image_map->update_images("uuid1", {}, std::move(entities));
+ ASSERT_TRUE(wait_for_listener_notify(remote_remove_global_image_ids.size()));
// RELEASE+REMOVE_MAPPING
expect_add_event(mock_threads);
update_map_request(mock_threads, mock_update_request, local_remove_global_image_ids, 0);
// remove local images
- mock_image_map->update_images("", {}, std::move(local_remove_global_image_ids));
- ASSERT_TRUE(wait_for_listener_notify(local_remove_global_image_ids_ack.size()));
+ entities = make_image_entities(local_remove_global_image_ids);
+ mock_image_map->update_images("", {}, std::move(entities));
+ ASSERT_TRUE(wait_for_listener_notify(local_remove_global_image_ids.size()));
- remote_peer_ack_nowait(mock_image_map.get(), local_remove_global_image_ids_ack,
+ remote_peer_ack_nowait(mock_image_map.get(), local_remove_global_image_ids,
0, &peer_ack_remove_ctxs);
- remote_peer_ack_wait(mock_image_map.get(), local_remove_global_image_ids_ack,
+ remote_peer_ack_wait(mock_image_map.get(), local_remove_global_image_ids,
0, &peer_ack_ctxs);
wait_for_scheduled_task();
std::set<std::string> global_image_ids{
"global id 1", "global id 2", "global id 3", "global id 4", "global id 5"
};
- std::set<std::string> global_image_ids_ack(global_image_ids);
// UPDATE_MAPPING+ACQUIRE
expect_add_event(mock_threads);
&peer_ack_ctxs);
// initial image list
- mock_image_map->update_images("uuid1", std::move(global_image_ids), {});
+ auto entities = make_image_entities(global_image_ids);
+ mock_image_map->update_images("uuid1", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(global_image_ids.size()));
// remote peer ACKs image acquire request
- remote_peer_ack_nowait(mock_image_map.get(), global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
std::set<std::string> global_image_ids{
"global id 1", "global id 2", "global id 3", "global id 4", "global id 5"
};
- std::set<std::string> global_image_ids_ack(global_image_ids);
expect_add_event(mock_threads);
&peer_ack_ctxs);
// set initial image list
- mock_image_map->update_images("uuid1", std::move(global_image_ids), {});
+ auto entities = make_image_entities(global_image_ids);
+ mock_image_map->update_images("uuid1", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(global_image_ids.size()));
// remote peer ACKs image acquire request -- completing action
- remote_peer_ack_nowait(mock_image_map.get(), global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
"global id 11", "global id 12", "global id 13", "global id 14"
};
- std::map<std::string, cls::rbd::MirrorImageMap> image_mapping;
+ std::map<GlobalId, cls::rbd::MirrorImageMap> image_mapping;
+ bufferlist bl;
+ image_map::PolicyMetaNone policy_meta;
+ encode(image_map::PolicyData(1, policy_meta), bl);
for (auto& global_image_id : global_image_ids) {
- image_mapping[global_image_id] = {m_local_instance_id, {}, {}};
+ GlobalId global_id{MIRROR_ENTITY_TYPE_IMAGE, global_image_id};
+ image_mapping[global_id] = {m_local_instance_id, {}, bl};
}
// ACQUIRE
mock_image_map->update_instances_added({m_local_instance_id});
- std::set<std::string> global_image_ids_ack(global_image_ids);
-
// remote peer ACKs image acquire request -- completing action
- ASSERT_TRUE(wait_for_listener_notify(global_image_ids_ack.size()));
- remote_peer_ack_nowait(mock_image_map.get(), global_image_ids_ack, 0,
+ ASSERT_TRUE(wait_for_listener_notify(global_image_ids.size()));
+ remote_peer_ack_nowait(mock_image_map.get(), global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
&peer_ack_ctxs);
// set initial image list
- mock_image_map->update_images("uuid1", std::move(global_image_ids), {});
+ auto entities = make_image_entities(global_image_ids);
+ mock_image_map->update_images("uuid1", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(global_image_ids.size()));
// remote peer ACKs image acquire request -- completing action
- remote_peer_ack_nowait(mock_image_map.get(), global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
std::set<std::string> global_image_ids{
"global id 1", "global id 2", "global id 3", "remote id 4",
};
- std::set<std::string> global_image_ids_ack(global_image_ids);
-
- std::set<std::string> remove_global_image_ids{
- "global id 1"
- };
- std::set<std::string> remove_global_image_ids_ack(remove_global_image_ids);
expect_add_event(mock_threads);
// UPDATE_MAPPING+ACQUIRE
&peer_ack_ctxs);
// initial image list
- mock_image_map->update_images("uuid1", std::move(global_image_ids), {});
+ auto entities = make_image_entities(global_image_ids);
+ mock_image_map->update_images("uuid1", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(global_image_ids.size()));
- remote_peer_ack_nowait(mock_image_map.get(), global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
&peer_ack_ctxs);
wait_for_scheduled_task();
- std::set<std::string> shuffled_global_image_ids_ack(shuffled_global_image_ids);
-
// RELEASE
std::map<std::string, Context*> peer_ack_remove_ctxs;
expect_add_event(mock_threads);
expect_update_request(mock_update_request, 0);
- mock_image_map->update_images("uuid1", {}, std::move(shuffled_global_image_ids));
- ASSERT_TRUE(wait_for_listener_notify(shuffled_global_image_ids_ack.size() * 2));
+ entities = make_image_entities(shuffled_global_image_ids);
+ mock_image_map->update_images("uuid1", {}, std::move(entities));
+ ASSERT_TRUE(wait_for_listener_notify(shuffled_global_image_ids.size() * 2));
// instance failed -- update policy for instance removal
mock_image_map->update_instances_removed({"9876"});
std::set<std::string> global_image_ids{
"global id 1", "global id 2", "global id 3", "remote id 4",
};
- std::set<std::string> global_image_ids_ack(global_image_ids);
// UPDATE_MAPPING+ACQUIRE
expect_add_event(mock_threads);
&peer_ack_ctxs);
// initial image list
- mock_image_map->update_images("uuid1", std::move(global_image_ids), {});
+ auto entities = make_image_entities(global_image_ids);
+ mock_image_map->update_images("uuid1", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(global_image_ids.size()));
// remote peer ACKs image acquire request
- remote_peer_ack_nowait(mock_image_map.get(), global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
&remap_peer_ack_ctxs);
wait_for_scheduled_task();
- std::set<std::string> shuffled_global_image_ids_ack(shuffled_global_image_ids);
-
// remove image
std::map<std::string, Context*> peer_ack_remove_ctxs;
listener_remove_images(mock_listener, "uuid1", shuffled_global_image_ids,
&peer_ack_ctxs);
update_map_request(mock_threads, mock_update_request, shuffled_global_image_ids, 0);
- mock_image_map->update_images("uuid1", {}, std::move(shuffled_global_image_ids));
- ASSERT_TRUE(wait_for_listener_notify(shuffled_global_image_ids_ack.size() * 2));
+ entities = make_image_entities(shuffled_global_image_ids);
+ mock_image_map->update_images("uuid1", {}, std::move(entities));
+ ASSERT_TRUE(wait_for_listener_notify(shuffled_global_image_ids.size() * 2));
- remote_peer_ack_nowait(mock_image_map.get(), shuffled_global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), shuffled_global_image_ids, 0,
&peer_ack_remove_ctxs);
- remote_peer_ack_wait(mock_image_map.get(), shuffled_global_image_ids_ack, 0,
+ remote_peer_ack_wait(mock_image_map.get(), shuffled_global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
std::set<std::string> initial_remote_global_image_ids{
"global id 1", "global id 2", "global id 3"
};
- std::set<std::string> initial_remote_global_image_ids_ack(initial_remote_global_image_ids);
// remote/local images to remove
std::set<std::string> remote_removed_global_image_ids{
"global id 1", "global id 2", "global id 3"
};
- std::set<std::string> remote_removed_global_image_ids_ack(remote_removed_global_image_ids);
std::set<std::string> remote_added_global_image_ids{
"global id 1", "global id 2", "global id 3"
};
- std::set<std::string> remote_added_global_image_ids_ack(remote_added_global_image_ids);
// UPDATE_MAPPING+ACQUIRE
expect_add_event(mock_threads);
&peer_ack_ctxs);
// initial remote image list
- mock_image_map->update_images("uuid1", std::move(initial_remote_global_image_ids), {});
+ auto entities = make_image_entities(initial_remote_global_image_ids);
+ mock_image_map->update_images("uuid1", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(initial_remote_global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(initial_remote_global_image_ids.size()));
// remote peer ACKs image acquire request
remote_peer_ack_nowait(mock_image_map.get(),
- initial_remote_global_image_ids_ack, 0,
+ initial_remote_global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
&peer_ack_ctxs);
update_map_request(mock_threads, mock_update_request, remote_removed_global_image_ids, 0);
- mock_image_map->update_images("uuid1", {}, std::move(remote_removed_global_image_ids));
- ASSERT_TRUE(wait_for_listener_notify(remote_removed_global_image_ids_ack.size() * 2));
+ entities = make_image_entities(remote_removed_global_image_ids);
+ mock_image_map->update_images("uuid1", {}, std::move(entities));
+ ASSERT_TRUE(wait_for_listener_notify(remote_removed_global_image_ids.size() * 2));
remote_peer_ack_nowait(mock_image_map.get(),
- remote_removed_global_image_ids_ack, 0,
+ remote_removed_global_image_ids, 0,
&peer_remove_ack_ctxs);
remote_peer_ack_wait(mock_image_map.get(),
- remote_removed_global_image_ids_ack, 0,
+ remote_removed_global_image_ids, 0,
&peer_ack_ctxs);
// UPDATE_MAPPING+ACQUIRE
listener_acquire_images(mock_listener, remote_added_global_image_ids,
&peer_ack_ctxs);
- mock_image_map->update_images("uuid2", std::move(remote_added_global_image_ids), {});
+ entities = make_image_entities(remote_added_global_image_ids);
+ mock_image_map->update_images("uuid2", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(remote_added_global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(remote_added_global_image_ids.size()));
// remote peer ACKs image acquire request
- remote_peer_ack_nowait(mock_image_map.get(),
- remote_added_global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), remote_added_global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
"global id 1", "global id 2", "global id 3", "global id 4", "global id 5",
"global id 6", "global id 7", "global id 8", "global id 9", "global id 10",
};
- std::set<std::string> global_image_ids_ack(global_image_ids);
// UPDATE_MAPPING+ACQUIRE
expect_add_event(mock_threads);
&peer_ack_ctxs);
// initial image list
- mock_image_map->update_images("", std::move(global_image_ids), {});
+ auto entities = make_image_entities(global_image_ids);
+ mock_image_map->update_images("", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(global_image_ids.size()));
// remote peer ACKs image acquire request
- remote_peer_ack_nowait(mock_image_map.get(), global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
wait_for_scheduled_task();
// remove all shuffled images -- make way for rebalance
- std::set<std::string> shuffled_global_image_ids_ack(shuffled_global_image_ids);
// RELEASE+REMOVE_MAPPING
expect_add_event(mock_threads);
update_map_request(mock_threads, mock_update_request, shuffled_global_image_ids,
0);
- mock_image_map->update_images("", {}, std::move(shuffled_global_image_ids));
- ASSERT_TRUE(wait_for_listener_notify(shuffled_global_image_ids_ack.size()));
+ entities = make_image_entities(shuffled_global_image_ids);
+ mock_image_map->update_images("", {}, std::move(entities));
+ ASSERT_TRUE(wait_for_listener_notify(shuffled_global_image_ids.size()));
- remote_peer_ack_wait(mock_image_map.get(), shuffled_global_image_ids_ack, 0,
+ remote_peer_ack_wait(mock_image_map.get(), shuffled_global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
shuffled_global_image_ids.clear();
- shuffled_global_image_ids_ack.clear();
std::set<std::string> new_global_image_ids = {
"global id 11"
};
- std::set<std::string> new_global_image_ids_ack(new_global_image_ids);
expect_add_event(mock_threads);
expect_update_request(mock_update_request, 0);
expect_listener_images_unmapped(mock_listener, 2, &shuffled_global_image_ids,
&peer_ack_ctxs);
- mock_image_map->update_images("", std::move(new_global_image_ids), {});
+ entities = make_image_entities(new_global_image_ids);
+ mock_image_map->update_images("", std::move(entities), {});
ASSERT_TRUE(wait_for_map_update(1));
- ASSERT_TRUE(wait_for_listener_notify(new_global_image_ids_ack.size()));
+ ASSERT_TRUE(wait_for_listener_notify(new_global_image_ids.size()));
// set rebalance interval
CephContext *cct = reinterpret_cast<CephContext *>(m_local_io_ctx.cct());
cct->_conf.set_val("rbd_mirror_image_policy_rebalance_timeout", "5");
- remote_peer_ack_nowait(mock_image_map.get(), new_global_image_ids_ack, 0,
+ remote_peer_ack_nowait(mock_image_map.get(), new_global_image_ids, 0,
&peer_ack_ctxs);
wait_for_scheduled_task();
MOCK_METHOD1(update_instances_removed, void(const std::vector<std::string>&));
MOCK_METHOD3(update_images_mock, void(const std::string&,
- const std::set<std::string>&,
- const std::set<std::string>&));
+ const MirrorEntities&,
+ const MirrorEntities&));
void update_images(const std::string& mirror_uuid,
- std::set<std::string>&& added,
- std::set<std::string>&& removed) {
+ MirrorEntities &&added,
+ MirrorEntities &&removed) {
update_images_mock(mirror_uuid, added, removed);
}
#include "librbd/MirroringWatcher.h"
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/PoolWatcher.h"
-#include "tools/rbd_mirror/pool_watcher/RefreshImagesRequest.h"
+#include "tools/rbd_mirror/pool_watcher/RefreshEntitiesRequest.h"
#include "include/stringify.h"
using namespace std::chrono_literals;
namespace pool_watcher {
template <>
-struct RefreshImagesRequest<librbd::MockTestImageCtx> {
- ImageIds *image_ids = nullptr;
+struct RefreshEntitiesRequest<librbd::MockTestImageCtx> {
+ std::map<MirrorEntity, std::string> *entities = nullptr;
Context *on_finish = nullptr;
- static RefreshImagesRequest *s_instance;
- static RefreshImagesRequest *create(librados::IoCtx &io_ctx,
- ImageIds *image_ids,
+ static RefreshEntitiesRequest *s_instance;
+ static RefreshEntitiesRequest *create(librados::IoCtx &io_ctx,
+ std::map<MirrorEntity, std::string> *entities,
Context *on_finish) {
ceph_assert(s_instance != nullptr);
- s_instance->image_ids = image_ids;
+ s_instance->entities = entities;
s_instance->on_finish = on_finish;
return s_instance;
}
MOCK_METHOD0(send, void());
- RefreshImagesRequest() {
+ RefreshEntitiesRequest() {
s_instance = this;
}
};
-RefreshImagesRequest<librbd::MockTestImageCtx> *RefreshImagesRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+RefreshEntitiesRequest<librbd::MockTestImageCtx> *RefreshEntitiesRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
} // namespace pool_watcher
public:
typedef PoolWatcher<librbd::MockTestImageCtx> MockPoolWatcher;
typedef Threads<librbd::MockTestImageCtx> MockThreads;
- typedef pool_watcher::RefreshImagesRequest<librbd::MockTestImageCtx> MockRefreshImagesRequest;
+ typedef pool_watcher::RefreshEntitiesRequest<librbd::MockTestImageCtx> MockRefreshEntitiesRequest;
typedef librbd::MockMirroringWatcher MockMirroringWatcher;
typedef librbd::MirroringWatcher<librbd::MockTestImageCtx> MirroringWatcher;
MockListener(TestMockPoolWatcher *test) : test(test) {
}
- MOCK_METHOD3(mock_handle_update, void(const std::string &, const ImageIds &,
- const ImageIds &));
+ MOCK_METHOD3(mock_handle_update, void(const std::string &,
+ const MirrorEntities &,
+ const MirrorEntities &));
void handle_update(const std::string &mirror_uuid,
- ImageIds &&added_image_ids,
- ImageIds &&removed_image_ids) override {
- mock_handle_update(mirror_uuid, added_image_ids, removed_image_ids);
+ MirrorEntities &&added_entities,
+ MirrorEntities &&removed_entities) override {
+ mock_handle_update(mirror_uuid, added_entities, removed_entities);
}
};
.WillOnce(CompleteContext(r));
}
- void expect_refresh_images(MockRefreshImagesRequest &request,
- const ImageIds &image_ids, int r) {
+ void expect_refresh_entities(MockRefreshEntitiesRequest &request,
+ const std::map<MirrorEntity, std::string> &entities,
+ int r) {
EXPECT_CALL(request, send())
- .WillOnce(Invoke([&request, image_ids, r]() {
- *request.image_ids = image_ids;
+ .WillOnce(Invoke([&request, entities, r]() {
+ *request.entities = entities;
request.on_finish->complete(r);
}));
}
void expect_listener_handle_update(MockListener &mock_listener,
const std::string &mirror_uuid,
- const ImageIds &added_image_ids,
- const ImageIds &removed_image_ids) {
- EXPECT_CALL(mock_listener, mock_handle_update(mirror_uuid, added_image_ids,
- removed_image_ids))
+ const MirrorEntities &added_entities,
+ const MirrorEntities &removed_entities) {
+ EXPECT_CALL(mock_listener, mock_handle_update(mirror_uuid, added_entities,
+ removed_entities))
.WillOnce(WithoutArgs(Invoke([this]() {
std::lock_guard locker{m_lock};
++m_update_count;
}
}
+ template <typename K, typename V>
+ std::set<K> get_keys(const std::map<K, V> &key_vals) {
+ std::set<K> keys;
+ for (auto &[key, val] : key_vals) {
+ keys.insert(key);
+ }
+ return keys;
+ }
+
ceph::mutex m_lock = ceph::make_mutex("TestMockPoolWatcher::m_lock");
ceph::condition_variable m_cond;
uint32_t m_update_count = 0;
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- MockRefreshImagesRequest mock_refresh_images_request;
- expect_refresh_images(mock_refresh_images_request, {}, 0);
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
+ expect_refresh_entities(mock_refresh_entities_request, {}, 0);
MockListener mock_listener(this);
expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- ImageIds image_ids{
- {"global id 1", "remote id 1"},
- {"global id 2", "remote id 2"}};
- MockRefreshImagesRequest mock_refresh_images_request;
- expect_refresh_images(mock_refresh_images_request, image_ids, 0);
+ std::map<MirrorEntity, std::string> entities{
+ {{MIRROR_ENTITY_TYPE_IMAGE, "global id 1", 1}, "remote id 1"},
+ {{MIRROR_ENTITY_TYPE_IMAGE, "global id 2", 1}, "remote id 2"}};
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
+ expect_refresh_entities(mock_refresh_entities_request, entities, 0);
MockListener mock_listener(this);
- expect_listener_handle_update(mock_listener, "remote uuid", image_ids, {});
+ expect_listener_handle_update(mock_listener, "remote uuid",
+ get_keys(entities), {});
MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
"remote uuid", mock_listener);
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- ImageIds image_ids{
- {"global id 1", "remote id 1"},
- {"global id 2", "remote id 2"}};
- MockRefreshImagesRequest mock_refresh_images_request;
+ std::map<MirrorEntity, std::string> entities{
+ {{MIRROR_ENTITY_TYPE_IMAGE, "global id 1", 1}, "remote id 1"},
+ {{MIRROR_ENTITY_TYPE_IMAGE, "global id 2", 1}, "remote id 2"}};
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
bool refresh_sent = false;
- EXPECT_CALL(mock_refresh_images_request, send())
- .WillOnce(Invoke([this, &mock_refresh_images_request, &image_ids,
+ EXPECT_CALL(mock_refresh_entities_request, send())
+ .WillOnce(Invoke([this, &mock_refresh_entities_request, &entities,
&refresh_sent]() {
- *mock_refresh_images_request.image_ids = image_ids;
+ *mock_refresh_entities_request.entities = entities;
std::lock_guard locker{m_lock};
refresh_sent = true;
MockListener mock_listener(this);
- image_ids = {
- {"global id 1", "remote id 1a"},
- {"global id 3", "remote id 3"}};
- expect_listener_handle_update(mock_listener, "remote uuid", image_ids, {});
+ entities = {
+ {{MIRROR_ENTITY_TYPE_IMAGE, "global id 1", 1}, "remote id 1a"},
+ {{MIRROR_ENTITY_TYPE_IMAGE, "global id 3", 1}, "remote id 3"}};
+ expect_listener_handle_update(mock_listener, "remote uuid",
+ get_keys(entities), {});
MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
"remote uuid", mock_listener);
MirroringWatcher::get_instance().handle_image_updated(
cls::rbd::MIRROR_IMAGE_STATE_ENABLED, "remote id 3", "global id 3");
- mock_refresh_images_request.on_finish->complete(0);
+ mock_refresh_entities_request.on_finish->complete(0);
ASSERT_TRUE(wait_for_update(1));
expect_mirroring_watcher_unregister(mock_mirroring_watcher, 0);
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- ImageIds image_ids{
- {"global id 1", "remote id 1"},
- {"global id 2", "remote id 2"}};
- MockRefreshImagesRequest mock_refresh_images_request;
- expect_refresh_images(mock_refresh_images_request, image_ids, 0);
+ std::map<MirrorEntity, std::string> entities{
+ {{MIRROR_ENTITY_TYPE_IMAGE, "global id 1", 1}, "remote id 1"},
+ {{MIRROR_ENTITY_TYPE_IMAGE, "global id 2", 1}, "remote id 2"}};
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
+ expect_refresh_entities(mock_refresh_entities_request, entities, 0);
EXPECT_CALL(*mock_threads.work_queue, queue(_, _))
.WillOnce(Invoke([this](Context *ctx, int r) {
}));
MockListener mock_listener(this);
- expect_listener_handle_update(mock_listener, "remote uuid", image_ids, {});
+ expect_listener_handle_update(mock_listener, "remote uuid",
+ get_keys(entities), {});
Context *notify_ctx = nullptr;
EXPECT_CALL(*mock_threads.work_queue, queue(_, _))
}));
expect_listener_handle_update(
mock_listener, "remote uuid",
- {{"global id 1", "remote id 1a"}, {"global id 3", "remote id 3"}},
- {{"global id 1", "remote id 1"}, {"global id 2", "remote id 2"}});
+ {{MIRROR_ENTITY_TYPE_IMAGE, "global id 1", 1},
+ {MIRROR_ENTITY_TYPE_IMAGE, "global id 3", 1}},
+ {{MIRROR_ENTITY_TYPE_IMAGE, "global id 1", 1},
+ {MIRROR_ENTITY_TYPE_IMAGE, "global id 2", 1}});
MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
"remote uuid", mock_listener);
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- MockRefreshImagesRequest mock_refresh_images_request;
- expect_refresh_images(mock_refresh_images_request, {}, 0);
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
+ expect_refresh_entities(mock_refresh_entities_request, {}, 0);
MockListener mock_listener(this);
expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- MockRefreshImagesRequest mock_refresh_images_request;
- expect_refresh_images(mock_refresh_images_request, {}, 0);
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
+ expect_refresh_entities(mock_refresh_entities_request, {}, 0);
MockListener mock_listener(this);
expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- MockRefreshImagesRequest mock_refresh_images_request;
- expect_refresh_images(mock_refresh_images_request, {}, -EBLOCKLISTED);
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
+ expect_refresh_entities(mock_refresh_entities_request, {}, -EBLOCKLISTED);
MockListener mock_listener(this);
MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- MockRefreshImagesRequest mock_refresh_images_request;
- expect_refresh_images(mock_refresh_images_request, {}, -ENOENT);
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
+ expect_refresh_entities(mock_refresh_entities_request, {}, -ENOENT);
MockListener mock_listener(this);
expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- MockRefreshImagesRequest mock_refresh_images_request;
- expect_refresh_images(mock_refresh_images_request, {}, -EINVAL);
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
+ expect_refresh_entities(mock_refresh_entities_request, {}, -EINVAL);
expect_timer_add_event(mock_threads);
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, false);
- expect_refresh_images(mock_refresh_images_request, {}, 0);
+ expect_refresh_entities(mock_refresh_entities_request, {}, 0);
MockListener mock_listener(this);
expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- MockRefreshImagesRequest mock_refresh_images_request;
- expect_refresh_images(mock_refresh_images_request, {}, 0);
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
+ expect_refresh_entities(mock_refresh_entities_request, {}, 0);
MockListener mock_listener(this);
expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
expect_timer_add_event(mock_threads);
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, false);
- expect_refresh_images(mock_refresh_images_request, {{"global id", "image id"}}, 0);
- expect_listener_handle_update(mock_listener, "remote uuid",
- {{"global id", "image id"}}, {});
+ MirrorEntity entity = {MIRROR_ENTITY_TYPE_IMAGE, "global id", 1};
+ expect_refresh_entities(mock_refresh_entities_request, {{entity, "image id"}}, 0);
+ expect_listener_handle_update(mock_listener, "remote uuid", {entity}, {});
MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
"remote uuid", mock_listener);
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- MockRefreshImagesRequest mock_refresh_images_request;
- expect_refresh_images(mock_refresh_images_request, {}, 0);
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
+ expect_refresh_entities(mock_refresh_entities_request, {}, 0);
MockListener mock_listener(this);
expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- MockRefreshImagesRequest mock_refresh_images_request;
- expect_refresh_images(mock_refresh_images_request, {}, 0);
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
+ expect_refresh_entities(mock_refresh_entities_request, {}, 0);
MockListener mock_listener(this);
expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
expect_timer_add_event(mock_threads);
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, false);
- expect_refresh_images(mock_refresh_images_request, {{"global id", "image id"}}, 0);
- expect_listener_handle_update(mock_listener, "remote uuid",
- {{"global id", "image id"}}, {});
+ MirrorEntity entity = {MIRROR_ENTITY_TYPE_IMAGE, "global id", 1};
+ expect_refresh_entities(mock_refresh_entities_request, {{entity, "image id"}}, 0);
+ expect_listener_handle_update(mock_listener, "remote uuid", {entity}, {});
MockPoolWatcher mock_pool_watcher(&mock_threads, m_remote_io_ctx,
"remote uuid", mock_listener);
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, true);
expect_mirroring_watcher_register(mock_mirroring_watcher, 0);
- MockRefreshImagesRequest mock_refresh_images_request;
+ MockRefreshEntitiesRequest mock_refresh_entities_request;
- EXPECT_CALL(mock_refresh_images_request, send())
- .WillOnce(Invoke([&mock_refresh_images_request]() {
- *mock_refresh_images_request.image_ids = {};
+ EXPECT_CALL(mock_refresh_entities_request, send())
+ .WillOnce(Invoke([&mock_refresh_entities_request]() {
+ *mock_refresh_entities_request.entities = {};
MirroringWatcher::get_instance().handle_rewatch_complete(0);
- mock_refresh_images_request.on_finish->complete(0);
+ mock_refresh_entities_request.on_finish->complete(0);
}));
expect_timer_add_event(mock_threads);
expect_mirroring_watcher_is_unregistered(mock_mirroring_watcher, false);
- expect_refresh_images(mock_refresh_images_request, {}, 0);
+ expect_refresh_entities(mock_refresh_entities_request, {}, 0);
MockListener mock_listener(this);
expect_listener_handle_update(mock_listener, "remote uuid", {}, {});
image_sync/SyncPointCreateRequest.cc
image_sync/SyncPointPruneRequest.cc
image_sync/Utils.cc
- pool_watcher/RefreshImagesRequest.cc
+ pool_watcher/RefreshEntitiesRequest.cc
service_daemon/Types.cc)
add_library(rbd_mirror_internal STATIC
using ::operator<<;
using image_map::Policy;
+using image_map::GlobalId;
+using image_map::GlobalIds;
using librbd::util::unique_lock_name;
using librbd::util::create_async_context_callback;
template <typename I>
struct ImageMap<I>::C_NotifyInstance : public Context {
ImageMap* image_map;
- std::string global_image_id;
+ GlobalId global_id;
bool acquire_release;
- C_NotifyInstance(ImageMap* image_map, const std::string& global_image_id,
+ C_NotifyInstance(ImageMap* image_map, const GlobalId& global_id,
bool acquire_release)
- : image_map(image_map), global_image_id(global_image_id),
+ : image_map(image_map), global_id(global_id),
acquire_release(acquire_release) {
image_map->start_async_op();
}
void finish(int r) override {
if (acquire_release) {
- image_map->handle_peer_ack(global_image_id, r);
+ image_map->handle_peer_ack(global_id, r);
} else {
- image_map->handle_peer_ack_remove(global_image_id, r);
+ image_map->handle_peer_ack_remove(global_id, r);
}
image_map->finish_async_op();
}
}
template <typename I>
-void ImageMap<I>::continue_action(const std::set<std::string> &global_image_ids,
- int r) {
+void ImageMap<I>::continue_action(const GlobalIds &global_ids, int r) {
dout(20) << dendl;
{
return;
}
- for (auto const &global_image_id : global_image_ids) {
- bool schedule = m_policy->finish_action(global_image_id, r);
+ for (auto const &global_id : global_ids) {
+ bool schedule = m_policy->finish_action(global_id, r);
if (schedule) {
- schedule_action(global_image_id);
+ schedule_action(global_id);
}
}
}
template <typename I>
void ImageMap<I>::handle_update_request(
- const Updates &updates,
- const std::set<std::string> &remove_global_image_ids, int r) {
+ const Updates &updates, const GlobalIds &remove_global_ids, int r) {
dout(20) << "r=" << r << dendl;
- std::set<std::string> global_image_ids;
+ GlobalIds global_ids;
- global_image_ids.insert(remove_global_image_ids.begin(),
- remove_global_image_ids.end());
+ global_ids.insert(remove_global_ids.begin(), remove_global_ids.end());
for (auto const &update : updates) {
- global_image_ids.insert(update.global_image_id);
+ global_ids.insert({update.entity.type, update.entity.global_id});
}
- continue_action(global_image_ids, r);
+ continue_action(global_ids, r);
}
template <typename I>
-void ImageMap<I>::update_image_mapping(Updates&& map_updates,
- std::set<std::string>&& map_removals) {
+void ImageMap<I>::update_image_mapping(Updates &&map_updates,
+ GlobalIds &&map_removals) {
if (map_updates.empty() && map_removals.empty()) {
return;
}
// empty meta policy for now..
image_map::PolicyMetaNone policy_meta;
- bufferlist bl;
- encode(image_map::PolicyData(policy_meta), bl);
-
// prepare update map
- std::map<std::string, cls::rbd::MirrorImageMap> update_mapping;
+ std::map<GlobalId, cls::rbd::MirrorImageMap> update_mapping;
for (auto const &update : map_updates) {
+ bufferlist bl;
+ encode(image_map::PolicyData(update.entity.count, policy_meta), bl);
+
update_mapping.emplace(
- update.global_image_id, cls::rbd::MirrorImageMap(update.instance_id,
- update.mapped_time, bl));
+ GlobalId{update.entity.type, update.entity.global_id},
+ cls::rbd::MirrorImageMap(update.instance_id, update.mapped_time, bl));
}
start_async_op();
ceph_assert(m_timer_task == nullptr);
Updates map_updates;
- std::set<std::string> map_removals;
+ GlobalIds map_removals;
Updates acquire_updates;
Updates release_updates;
// gather updates by advancing the state machine
m_lock.lock();
- for (auto const &global_image_id : m_global_image_ids) {
- image_map::ActionType action_type =
- m_policy->start_action(global_image_id);
- image_map::LookupInfo info = m_policy->lookup(global_image_id);
+ for (auto const &global_id : m_global_ids) {
+ image_map::ActionType action_type = m_policy->start_action(global_id);
+ image_map::LookupInfo info = m_policy->lookup(global_id);
- dout(15) << "global_image_id=" << global_image_id << ", "
+ dout(15) << "global_id=" << global_id << ", "
<< "action=" << action_type << ", "
<< "instance=" << info.instance_id << dendl;
switch (action_type) {
continue;
case image_map::ACTION_TYPE_MAP_UPDATE:
ceph_assert(info.instance_id != image_map::UNMAPPED_INSTANCE_ID);
- map_updates.emplace_back(global_image_id, info.instance_id,
- info.mapped_time);
+ map_updates.emplace_back(
+ MirrorEntity{global_id.type, global_id.id, info.weight},
+ info.instance_id, info.mapped_time);
break;
case image_map::ACTION_TYPE_MAP_REMOVE:
- map_removals.emplace(global_image_id);
+ map_removals.emplace(global_id);
break;
case image_map::ACTION_TYPE_ACQUIRE:
ceph_assert(info.instance_id != image_map::UNMAPPED_INSTANCE_ID);
- acquire_updates.emplace_back(global_image_id, info.instance_id);
+ acquire_updates.emplace_back(
+ MirrorEntity{global_id.type, global_id.id, info.weight},
+ info.instance_id);
break;
case image_map::ACTION_TYPE_RELEASE:
ceph_assert(info.instance_id != image_map::UNMAPPED_INSTANCE_ID);
- release_updates.emplace_back(global_image_id, info.instance_id);
+ release_updates.emplace_back(
+ MirrorEntity{global_id.type, global_id.id, info.weight},
+ info.instance_id);
break;
}
}
- m_global_image_ids.clear();
+ m_global_ids.clear();
m_lock.unlock();
// notify listener (acquire, release) and update on-disk map. note
template <typename I>
void ImageMap<I>::schedule_update_task() {
std::lock_guard timer_lock{m_threads->timer_lock};
- schedule_update_task(m_threads->timer_lock);
+ CephContext *cct = reinterpret_cast<CephContext *>(m_ioctx.cct());
+ double after = cct->_conf.get_val<double>("rbd_mirror_image_policy_update_throttle_interval");
+ schedule_update_task(m_threads->timer_lock, after);
}
template <typename I>
-void ImageMap<I>::schedule_update_task(const ceph::mutex &timer_lock) {
+void ImageMap<I>::schedule_update_task(const ceph::mutex &timer_lock,
+ double after) {
ceph_assert(ceph_mutex_is_locked(m_threads->timer_lock));
schedule_rebalance_task();
{
std::lock_guard locker{m_lock};
- if (m_global_image_ids.empty()) {
+ if (m_global_ids.empty()) {
return;
}
}
process_updates();
});
- CephContext *cct = reinterpret_cast<CephContext *>(m_ioctx.cct());
- double after = cct->_conf.get_val<double>("rbd_mirror_image_policy_update_throttle_interval");
-
dout(20) << "scheduling image check update (" << m_timer_task << ")"
<< " after " << after << " second(s)" << dendl;
m_threads->timer->add_event_after(after, m_timer_task);
{
std::lock_guard locker{m_lock};
- if (m_async_op_tracker.empty() && m_global_image_ids.empty()){
+ if (m_async_op_tracker.empty() && m_global_ids.empty()){
dout(20) << "starting rebalance" << dendl;
- std::set<std::string> remap_global_image_ids;
- m_policy->add_instances({}, &remap_global_image_ids);
+ GlobalIds remap_global_ids;
+ m_policy->add_instances({}, &remap_global_ids);
- for (auto const &global_image_id : remap_global_image_ids) {
- schedule_action(global_image_id);
+ for (auto const &global_id : remap_global_ids) {
+ schedule_action(global_id);
}
}
}
- schedule_update_task(m_threads->timer_lock);
+ schedule_update_task();
}
template <typename I>
}
template <typename I>
-void ImageMap<I>::schedule_action(const std::string &global_image_id) {
- dout(20) << "global_image_id=" << global_image_id << dendl;
+void ImageMap<I>::schedule_action(const GlobalId &global_id) {
+ dout(20) << "global_id=" << global_id << dendl;
ceph_assert(ceph_mutex_is_locked(m_lock));
- m_global_image_ids.emplace(global_image_id);
+ m_global_ids.emplace(global_id);
}
template <typename I>
<< "release=[" << release << "]" << dendl;
for (auto const &update : acquire) {
- m_listener.acquire_image(
- update.global_image_id, update.instance_id,
- create_async_context_callback(
- m_threads->work_queue,
- new C_NotifyInstance(this, update.global_image_id, true)));
+ auto global_id = GlobalId(update.entity.type, update.entity.global_id);
+ if (update.entity.type == MIRROR_ENTITY_TYPE_IMAGE) {
+ m_listener.acquire_image(
+ update.entity.global_id, update.instance_id,
+ create_async_context_callback(
+ m_threads->work_queue,
+ new C_NotifyInstance(this, global_id, true)));
+ } else if (update.entity.type == MIRROR_ENTITY_TYPE_GROUP) {
+ // TODO
+ } else {
+ ceph_abort_msgf("invalid mirror entity type: %d",
+ (int)update.entity.type);
+ }
}
for (auto const &update : release) {
- m_listener.release_image(
- update.global_image_id, update.instance_id,
- create_async_context_callback(
- m_threads->work_queue,
- new C_NotifyInstance(this, update.global_image_id, true)));
+ auto global_id = GlobalId(update.entity.type, update.entity.global_id);
+ if (update.entity.type == MIRROR_ENTITY_TYPE_IMAGE || update.entity.count != 0) {
+ m_listener.release_image(
+ update.entity.global_id, update.instance_id,
+ create_async_context_callback(
+ m_threads->work_queue,
+ new C_NotifyInstance(this, global_id, true)));
+ } else if (update.entity.type == MIRROR_ENTITY_TYPE_GROUP) {
+ // TODO
+ } else {
+ ceph_abort_msgf("invalid mirror entity type: %d",
+ (int)update.entity.type);
+ }
}
}
<< "remove=[" << remove << "]" << dendl;
for (auto const &update : remove) {
- m_listener.remove_image(
- mirror_uuid, update.global_image_id, update.instance_id,
- create_async_context_callback(
- m_threads->work_queue,
- new C_NotifyInstance(this, update.global_image_id, false)));
+ auto global_id = GlobalId(update.entity.type, update.entity.global_id);
+ if (update.entity.type == MIRROR_ENTITY_TYPE_IMAGE) {
+ m_listener.remove_image(
+ mirror_uuid, update.entity.global_id, update.instance_id,
+ create_async_context_callback(
+ m_threads->work_queue,
+ new C_NotifyInstance(this, global_id, false)));
+ } else if (update.entity.type == MIRROR_ENTITY_TYPE_GROUP) {
+ // TODO
+ } else {
+ ceph_abort_msgf("invalid mirror entity type: %d",
+ (int)update.entity.type);
+ }
}
}
template <typename I>
-void ImageMap<I>::handle_load(const std::map<std::string,
+void ImageMap<I>::handle_load(const std::map<GlobalId,
cls::rbd::MirrorImageMap> &image_mapping) {
dout(20) << dendl;
}
template <typename I>
-void ImageMap<I>::handle_peer_ack_remove(const std::string &global_image_id,
- int r) {
+void ImageMap<I>::handle_peer_ack_remove(const GlobalId &global_id, int r) {
std::lock_guard locker{m_lock};
- dout(5) << "global_image_id=" << global_image_id << dendl;
+ dout(5) << "global_id=" << global_id << dendl;
if (r < 0) {
- derr << "failed to remove global_image_id=" << global_image_id << dendl;
+ derr << "failed to remove global_id=" << global_id << dendl;
}
- auto peer_it = m_peer_map.find(global_image_id);
+ auto peer_it = m_peer_map.find(global_id);
if (peer_it == m_peer_map.end()) {
return;
}
template <typename I>
void ImageMap<I>::update_images_added(
const std::string &mirror_uuid,
- const std::set<std::string> &global_image_ids) {
+ const MirrorEntities &entities) {
dout(5) << "mirror_uuid=" << mirror_uuid << ", "
- << "global_image_ids=[" << global_image_ids << "]" << dendl;
+ << "entities=[" << entities << "]" << dendl;
ceph_assert(ceph_mutex_is_locked(m_lock));
- for (auto const &global_image_id : global_image_ids) {
- auto result = m_peer_map[global_image_id].insert(mirror_uuid);
- if (result.second && m_peer_map[global_image_id].size() == 1) {
- if (m_policy->add_image(global_image_id)) {
- schedule_action(global_image_id);
+ for (auto &entity : entities) {
+ auto global_id = GlobalId(entity.type, entity.global_id);
+ auto result = m_peer_map[global_id].insert(mirror_uuid);
+ if ((result.second || entity.type == MIRROR_ENTITY_TYPE_GROUP)) {
+ if (m_policy->add_entity(global_id, entity.count)) {
+ schedule_action(global_id);
}
}
}
template <typename I>
void ImageMap<I>::update_images_removed(
const std::string &mirror_uuid,
- const std::set<std::string> &global_image_ids) {
+ const MirrorEntities &entities) {
dout(5) << "mirror_uuid=" << mirror_uuid << ", "
- << "global_image_ids=[" << global_image_ids << "]" << dendl;
+ << "entities=[" << entities << "]" << dendl;
ceph_assert(ceph_mutex_is_locked(m_lock));
Updates to_remove;
- for (auto const &global_image_id : global_image_ids) {
- image_map::LookupInfo info = m_policy->lookup(global_image_id);
- bool image_mapped = (info.instance_id != image_map::UNMAPPED_INSTANCE_ID);
+ for (auto &entity : entities) {
+ auto global_id = GlobalId(entity.type, entity.global_id);
+ image_map::LookupInfo info = m_policy->lookup(global_id);
+ bool entity_mapped = (info.instance_id != image_map::UNMAPPED_INSTANCE_ID);
- bool image_removed = image_mapped;
+ bool entity_removed = entity_mapped;
bool peer_removed = false;
- auto peer_it = m_peer_map.find(global_image_id);
+ auto peer_it = m_peer_map.find(global_id);
if (peer_it != m_peer_map.end()) {
auto& peer_set = peer_it->second;
peer_removed = peer_set.erase(mirror_uuid);
- image_removed = peer_removed && peer_set.empty();
+ entity_removed = peer_removed && peer_set.empty();
}
- if (image_mapped && peer_removed && !mirror_uuid.empty()) {
+ if (entity_mapped && peer_removed && !mirror_uuid.empty()) {
// peer image has been deleted
- to_remove.emplace_back(global_image_id, info.instance_id);
+ to_remove.emplace_back(entity, info.instance_id);
}
- if (image_removed) {
+ if (entity_removed) {
// local and peer images have been deleted
- if (m_policy->remove_image(global_image_id)) {
- schedule_action(global_image_id);
+ if (m_policy->remove_entity(global_id)) {
+ schedule_action(global_id);
}
}
}
dout(20) << "instance_ids=" << filtered_instance_ids << dendl;
- std::set<std::string> remap_global_image_ids;
- m_policy->add_instances(filtered_instance_ids, &remap_global_image_ids);
+ GlobalIds remap_global_ids;
+ m_policy->add_instances(filtered_instance_ids, &remap_global_ids);
- for (auto const &global_image_id : remap_global_image_ids) {
- schedule_action(global_image_id);
+ for (auto const &global_id : remap_global_ids) {
+ schedule_action(global_id);
}
}
dout(20) << "instance_ids=" << filtered_instance_ids << dendl;
- std::set<std::string> remap_global_image_ids;
- m_policy->remove_instances(filtered_instance_ids, &remap_global_image_ids);
+ GlobalIds remap_global_ids;
+ m_policy->remove_instances(filtered_instance_ids, &remap_global_ids);
- for (auto const &global_image_id : remap_global_image_ids) {
- schedule_action(global_image_id);
+ for (auto const &global_id : remap_global_ids) {
+ schedule_action(global_id);
}
}
template <typename I>
void ImageMap<I>::update_images(const std::string &mirror_uuid,
- std::set<std::string> &&added_global_image_ids,
- std::set<std::string> &&removed_global_image_ids) {
+ MirrorEntities &&added_entities,
+ MirrorEntities &&removed_entities) {
dout(5) << "mirror_uuid=" << mirror_uuid << ", " << "added_count="
- << added_global_image_ids.size() << ", " << "removed_count="
- << removed_global_image_ids.size() << dendl;
+ << added_entities.size() << ", " << "removed_count="
+ << removed_entities.size() << dendl;
{
std::lock_guard locker{m_lock};
return;
}
- if (!removed_global_image_ids.empty()) {
- update_images_removed(mirror_uuid, removed_global_image_ids);
+ if (!removed_entities.empty()) {
+ update_images_removed(mirror_uuid, removed_entities);
}
- if (!added_global_image_ids.empty()) {
- update_images_added(mirror_uuid, added_global_image_ids);
+ if (!added_entities.empty()) {
+ update_images_added(mirror_uuid, added_entities);
}
}
}
template <typename I>
-void ImageMap<I>::handle_peer_ack(const std::string &global_image_id, int r) {
- dout (20) << "global_image_id=" << global_image_id << ", r=" << r
- << dendl;
+void ImageMap<I>::handle_peer_ack(const GlobalId &global_id, int r) {
+ dout (20) << "global_id=" << global_id << ", r=" << r << dendl;
- continue_action({global_image_id}, r);
+ continue_action({global_id}, r);
}
template <typename I>
// update (add/remove) images
void update_images(const std::string &mirror_uuid,
- std::set<std::string> &&added_global_image_ids,
- std::set<std::string> &&removed_global_image_ids);
+ MirrorEntities &&added_entities,
+ MirrorEntities &&removed_entities);
// add/remove instances
void update_instances_added(const std::vector<std::string> &instances);
const std::string& instance_id, image_map::Listener &listener);
struct Update {
- std::string global_image_id;
+ MirrorEntity entity;
std::string instance_id;
utime_t mapped_time;
- Update(const std::string &global_image_id, const std::string &instance_id,
+ Update(const MirrorEntity &entity, const std::string &instance_id,
utime_t mapped_time)
- : global_image_id(global_image_id),
- instance_id(instance_id),
- mapped_time(mapped_time) {
+ : entity(entity), instance_id(instance_id), mapped_time(mapped_time) {
}
- Update(const std::string &global_image_id, const std::string &instance_id)
- : Update(global_image_id, instance_id, ceph_clock_now()) {
+ Update(const MirrorEntity &entity, const std::string &instance_id)
+ : Update(entity, instance_id, ceph_clock_now()) {
}
friend std::ostream& operator<<(std::ostream& os,
const Update& update) {
- os << "{global_image_id=" << update.global_image_id << ", "
+ os << "{entity=" << update.entity << ", "
<< "instance_id=" << update.instance_id << "}";
return os;
}
bool m_shutting_down = false;
AsyncOpTracker m_async_op_tracker;
- // global_image_id -> registered peers ("" == local, remote otherwise)
- std::map<std::string, std::set<std::string> > m_peer_map;
+ // global_id -> registered peers ("" == local, remote otherwise)
+ std::map<image_map::GlobalId, std::set<std::string>> m_peer_map;
- std::set<std::string> m_global_image_ids;
+ image_map::GlobalIds m_global_ids;
Context *m_rebalance_task = nullptr;
ImageMap *image_map;
Context *on_finish;
- std::map<std::string, cls::rbd::MirrorImageMap> image_mapping;
+ std::map<image_map::GlobalId, cls::rbd::MirrorImageMap> image_mapping;
C_LoadMap(ImageMap *image_map, Context *on_finish)
: image_map(image_map),
m_async_op_tracker.wait_for_ops(on_finish);
}
- void handle_peer_ack(const std::string &global_image_id, int r);
- void handle_peer_ack_remove(const std::string &global_image_id, int r);
+ void handle_peer_ack(const image_map::GlobalId &global_id, int r);
+ void handle_peer_ack_remove(const image_map::GlobalId &global_id, int r);
- void handle_load(const std::map<std::string, cls::rbd::MirrorImageMap> &image_mapping);
+ void handle_load(const std::map<image_map::GlobalId,
+ cls::rbd::MirrorImageMap> &image_mapping);
void handle_update_request(const Updates &updates,
- const std::set<std::string> &remove_global_image_ids, int r);
+ const image_map::GlobalIds &remove_global_ids,
+ int r);
// continue (retry or resume depending on state machine) processing
// current action.
- void continue_action(const std::set<std::string> &global_image_ids, int r);
+ void continue_action(const image_map::GlobalIds &global_id, int r);
// schedule an image for update
- void schedule_action(const std::string &global_image_id);
+ void schedule_action(const image_map::GlobalId &global_id);
void schedule_update_task();
- void schedule_update_task(const ceph::mutex &timer_lock);
+ void schedule_update_task(const ceph::mutex &timer_lock, double after);
void process_updates();
void update_image_mapping(Updates&& map_updates,
- std::set<std::string>&& map_removals);
+ image_map::GlobalIds&& map_removals);
void rebalance();
void schedule_rebalance_task();
- void notify_listener_acquire_release_images(const Updates &acquire, const Updates &release);
+ void notify_listener_acquire_release_images(const Updates &acquire,
+ const Updates &release);
void notify_listener_remove_images(const std::string &mirror_uuid,
const Updates &remove);
void update_images_added(const std::string &mirror_uuid,
- const std::set<std::string> &global_image_ids);
+ const MirrorEntities &entities);
void update_images_removed(const std::string &mirror_uuid,
- const std::set<std::string> &global_image_ids);
+ const MirrorEntities &entities);
void filter_instance_ids(const std::vector<std::string> &instance_ids,
std::vector<std::string> *filtered_instance_ids,
template <typename I>
void NamespaceReplayer<I>::handle_update(const std::string &mirror_uuid,
- ImageIds &&added_image_ids,
- ImageIds &&removed_image_ids) {
+ MirrorEntities &&added_entities,
+ MirrorEntities &&removed_entities) {
std::lock_guard locker{m_lock};
if (!m_image_map) {
}
dout(10) << "mirror_uuid=" << mirror_uuid << ", "
- << "added_count=" << added_image_ids.size() << ", "
- << "removed_count=" << removed_image_ids.size() << dendl;
+ << "added_count=" << added_entities.size() << ", "
+ << "removed_count=" << removed_entities.size() << dendl;
m_service_daemon->add_or_update_namespace_attribute(
m_local_io_ctx.get_id(), m_local_io_ctx.get_namespace(),
m_remote_pool_watcher->get_image_count());
}
- std::set<std::string> added_global_image_ids;
- for (auto& image_id : added_image_ids) {
- added_global_image_ids.insert(image_id.global_id);
- }
-
- std::set<std::string> removed_global_image_ids;
- for (auto& image_id : removed_image_ids) {
- removed_global_image_ids.insert(image_id.global_id);
- }
-
- m_image_map->update_images(mirror_uuid,
- std::move(added_global_image_ids),
- std::move(removed_global_image_ids));
+ m_image_map->update_images(mirror_uuid, std::move(added_entities),
+ std::move(removed_entities));
}
template <typename I>
}
void handle_update(const std::string &mirror_uuid,
- ImageIds &&added_image_ids,
- ImageIds &&removed_image_ids) override {
+ MirrorEntities &&added_entities,
+ MirrorEntities &&removed_entities) override {
namespace_replayer->handle_update((local ? "" : mirror_uuid),
- std::move(added_image_ids),
- std::move(removed_image_ids));
+ std::move(added_entities),
+ std::move(removed_entities));
}
};
const std::string &instance_id,
Context* on_finish) override {
namespace_replayer->handle_acquire_image(global_image_id, instance_id,
- on_finish);
+ on_finish);
}
void release_image(const std::string &global_image_id,
const std::string &instance_id,
Context* on_finish) override {
namespace_replayer->handle_release_image(global_image_id, instance_id,
- on_finish);
+ on_finish);
}
void remove_image(const std::string &mirror_uuid,
};
void handle_update(const std::string &mirror_uuid,
- ImageIds &&added_image_ids,
- ImageIds &&removed_image_ids);
+ MirrorEntities &&added_entities,
+ MirrorEntities &&removed_entities);
int init_rados(const std::string &cluster_name,
const std::string &client_name,
#include "librbd/api/Mirror.h"
#include "librbd/asio/ContextWQ.h"
#include "tools/rbd_mirror/Threads.h"
-#include "tools/rbd_mirror/pool_watcher/RefreshImagesRequest.h"
+#include "tools/rbd_mirror/pool_watcher/RefreshEntitiesRequest.h"
+
+#include <numeric>
#define dout_context g_ceph_context
#define dout_subsys ceph_subsys_rbd_mirror
void handle_mode_updated(cls::rbd::MirrorMode mirror_mode) override {
// invalidate all image state and refresh the pool contents
- m_pool_watcher->schedule_refresh_images(5);
+ m_pool_watcher->schedule_refresh_entities(5);
}
void handle_image_updated(cls::rbd::MirrorImageState state,
return m_blocklisted;
}
+template <typename I>
+size_t PoolWatcher<I>::get_image_count() const {
+ std::lock_guard locker{m_lock};
+ return std::accumulate(m_entities.begin(), m_entities.end(), 0,
+ [](size_t count,
+ const std::pair<MirrorEntity, std::string> &p) {
+ return count + p.first.count;
+ });
+}
+
template <typename I>
void PoolWatcher<I>::init(Context *on_finish) {
dout(5) << dendl;
void PoolWatcher<I>::register_watcher() {
{
std::lock_guard locker{m_lock};
- ceph_assert(m_image_ids_invalid);
+ ceph_assert(m_entities_invalid);
ceph_assert(m_refresh_in_progress);
}
// if the watch registration is in-flight, let the watcher
// handle the transition -- only (re-)register if it's not registered
if (!m_mirroring_watcher->is_unregistered()) {
- refresh_images();
+ refresh_entities();
return;
}
{
std::lock_guard locker{m_lock};
- ceph_assert(m_image_ids_invalid);
+ ceph_assert(m_entities_invalid);
ceph_assert(m_refresh_in_progress);
if (r < 0) {
m_refresh_in_progress = false;
Context *on_init_finish = nullptr;
if (r >= 0) {
- refresh_images();
+ refresh_entities();
} else if (r == -EBLOCKLISTED) {
dout(0) << "detected client is blocklisted" << dendl;
std::swap(on_init_finish, m_on_init_finish);
}
- schedule_refresh_images(30);
+ schedule_refresh_entities(30);
} else {
derr << "unexpected error registering mirroring directory watch: "
<< cpp_strerror(r) << dendl;
- schedule_refresh_images(10);
+ schedule_refresh_entities(10);
}
m_async_op_tracker.finish_op();
}
template <typename I>
-void PoolWatcher<I>::refresh_images() {
+void PoolWatcher<I>::refresh_entities() {
dout(5) << dendl;
{
std::lock_guard locker{m_lock};
- ceph_assert(m_image_ids_invalid);
+ ceph_assert(m_entities_invalid);
ceph_assert(m_refresh_in_progress);
// clear all pending notification events since we need to perform
- // a full image list refresh
- m_pending_added_image_ids.clear();
- m_pending_removed_image_ids.clear();
+ // a full entity list refresh
+ m_pending_added_entities.clear();
+ m_pending_removed_entities.clear();
}
m_async_op_tracker.start_op();
- m_refresh_image_ids.clear();
+ m_refresh_entities.clear();
Context *ctx = create_context_callback<
- PoolWatcher, &PoolWatcher<I>::handle_refresh_images>(this);
- auto req = pool_watcher::RefreshImagesRequest<I>::create(m_io_ctx,
- &m_refresh_image_ids,
- ctx);
+ PoolWatcher, &PoolWatcher<I>::handle_refresh_entities>(this);
+ auto req = pool_watcher::RefreshEntitiesRequest<I>::create(
+ m_io_ctx, &m_refresh_entities, ctx);
req->send();
}
template <typename I>
-void PoolWatcher<I>::handle_refresh_images(int r) {
+void PoolWatcher<I>::handle_refresh_entities(int r) {
dout(5) << "r=" << r << dendl;
bool deferred_refresh = false;
Context *on_init_finish = nullptr;
{
std::lock_guard locker{m_lock};
- ceph_assert(m_image_ids_invalid);
+ ceph_assert(m_entities_invalid);
ceph_assert(m_refresh_in_progress);
m_refresh_in_progress = false;
if (r == -ENOENT) {
dout(5) << "mirroring directory not found" << dendl;
r = 0;
- m_refresh_image_ids.clear();
+ m_refresh_entities.clear();
}
if (m_deferred_refresh) {
// need to refresh -- skip the notification
deferred_refresh = true;
} else if (r >= 0) {
- m_pending_image_ids = std::move(m_refresh_image_ids);
- m_image_ids_invalid = false;
+ m_pending_entities = std::move(m_refresh_entities);
+ m_entities_invalid = false;
std::swap(on_init_finish, m_on_init_finish);
schedule_listener();
} else if (r == -EBLOCKLISTED) {
- dout(0) << "detected client is blocklisted during image refresh" << dendl;
+ dout(0) << "detected client is blocklisted during entity refresh" << dendl;
m_blocklisted = true;
std::swap(on_init_finish, m_on_init_finish);
if (deferred_refresh) {
dout(5) << "scheduling deferred refresh" << dendl;
- schedule_refresh_images(0);
+ schedule_refresh_entities(0);
} else if (retry_refresh) {
derr << "failed to retrieve mirroring directory: " << cpp_strerror(r)
<< dendl;
- schedule_refresh_images(10);
+ schedule_refresh_entities(10);
}
m_async_op_tracker.finish_op();
}
template <typename I>
-void PoolWatcher<I>::schedule_refresh_images(double interval) {
+void PoolWatcher<I>::schedule_refresh_entities(double interval) {
std::scoped_lock locker{m_threads->timer_lock, m_lock};
if (m_shutting_down || m_refresh_in_progress || m_timer_ctx != nullptr) {
if (m_refresh_in_progress && !m_deferred_refresh) {
return;
}
- m_image_ids_invalid = true;
+ m_entities_invalid = true;
m_timer_ctx = m_threads->timer->add_event_after(
interval,
new LambdaContext([this](int r) {
- process_refresh_images();
+ process_refresh_entities();
}));
}
<< cpp_strerror(r) << dendl;
}
- schedule_refresh_images(5);
+ schedule_refresh_entities(5);
}
template <typename I>
<< "enabled=" << enabled << dendl;
std::lock_guard locker{m_lock};
- ImageId image_id(global_image_id, id);
- m_pending_added_image_ids.erase(image_id);
- m_pending_removed_image_ids.erase(image_id);
+ MirrorEntity entity(MIRROR_ENTITY_TYPE_IMAGE, global_image_id, 1);
+ m_pending_added_entities.erase(entity);
+ m_pending_removed_entities.erase(entity);
if (enabled) {
- m_pending_added_image_ids.insert(image_id);
+ m_pending_added_entities.insert({entity, id});
schedule_listener();
} else {
- m_pending_removed_image_ids.insert(image_id);
+ m_pending_removed_entities.insert({entity, id});
schedule_listener();
}
}
}
template <typename I>
-void PoolWatcher<I>::process_refresh_images() {
+void PoolWatcher<I>::process_refresh_entities() {
ceph_assert(ceph_mutex_is_locked(m_threads->timer_lock));
ceph_assert(m_timer_ctx != nullptr);
m_timer_ctx = nullptr;
void PoolWatcher<I>::schedule_listener() {
ceph_assert(ceph_mutex_is_locked(m_lock));
m_pending_updates = true;
- if (m_shutting_down || m_image_ids_invalid || m_notify_listener_in_progress) {
+ if (m_shutting_down || m_entities_invalid || m_notify_listener_in_progress) {
return;
}
dout(10) << dendl;
std::string mirror_uuid;
- ImageIds added_image_ids;
- ImageIds removed_image_ids;
+ MirrorEntities added_entities;
+ MirrorEntities removed_entities;
{
std::lock_guard locker{m_lock};
ceph_assert(m_notify_listener_in_progress);
// if the watch failed while we didn't own the lock, we are going
// to need to perform a full refresh
- if (m_image_ids_invalid) {
+ if (m_entities_invalid) {
m_notify_listener_in_progress = false;
return;
}
- // merge add/remove notifications into pending set (a given image
+ // merge add/remove notifications into pending set (a given entity
// can only be in one set or another)
- for (auto &image_id : m_pending_removed_image_ids) {
- dout(20) << "image_id=" << image_id << dendl;
- m_pending_image_ids.erase(image_id);
+ for (auto &[entity, id] : m_pending_removed_entities) {
+ dout(20) << "removed pending entity={" << entity << "}" << dendl;
+ m_pending_entities.erase(entity);
+ auto it = m_entities.find(entity);
+ if (it != m_entities.end()) {
+ m_entities.erase(entity);
+ }
+ m_entities.insert({entity, id});
}
+ m_pending_removed_entities.clear();
- for (auto &image_id : m_pending_added_image_ids) {
- dout(20) << "image_id=" << image_id << dendl;
- m_pending_image_ids.erase(image_id);
- m_pending_image_ids.insert(image_id);
+ for (auto &[entity, id] : m_pending_added_entities) {
+ dout(20) << "added pending entity={" << entity << "}" << dendl;
+ m_pending_entities.erase(entity);
+ m_pending_entities.insert({entity, id});
}
- m_pending_added_image_ids.clear();
+ m_pending_added_entities.clear();
// compute added/removed images
- for (auto &image_id : m_image_ids) {
- auto it = m_pending_image_ids.find(image_id);
- if (it == m_pending_image_ids.end() || it->id != image_id.id) {
- removed_image_ids.insert(image_id);
+ for (auto &[entity, id] : m_entities) {
+ auto it = m_pending_entities.find(entity);
+ // If previous entity is not there in current set of entities or if
+ // their id's don't match then consider its removed
+ if (it == m_pending_entities.end() || it->second != id ||
+ it->first.count < entity.count) {
+ removed_entities.insert(entity);
}
}
- for (auto &image_id : m_pending_image_ids) {
- auto it = m_image_ids.find(image_id);
- if (it == m_image_ids.end() || it->id != image_id.id) {
- added_image_ids.insert(image_id);
+ for (auto &[entity, id] : m_pending_entities) {
+ auto it = m_entities.find(entity);
+ // If current entity is not there in previous set of entities or if
+ // their id's don't match then consider its added
+ if (it == m_entities.end() || it->second != id ||
+ it->first.count < entity.count) {
+ added_entities.insert(entity);
}
}
m_pending_updates = false;
- m_image_ids = m_pending_image_ids;
+ m_entities = m_pending_entities;
}
- m_listener.handle_update(m_mirror_uuid, std::move(added_image_ids),
- std::move(removed_image_ids));
-
+ m_listener.handle_update(m_mirror_uuid, std::move(added_entities),
+ std::move(removed_entities));
{
std::lock_guard locker{m_lock};
m_notify_listener_in_progress = false;
PoolWatcher& operator=(const PoolWatcher&) = delete;
bool is_blocklisted() const;
+ size_t get_image_count() const;
void init(Context *on_finish = nullptr);
void shut_down(Context *on_finish);
- inline uint64_t get_image_count() const {
- std::lock_guard locker{m_lock};
- return m_image_ids.size();
- }
-
private:
/**
* @verbatim
* |/--------------------------------\
* | |
* v |
- * REFRESH_IMAGES |
+ * REFRESH_ENTITIES |
* | |
* |/----------------------------\ |
* | | |
* v | |
* IDLE ---\ | |
* | | | |
- * | |\---> IMAGE_UPDATED | |
- * | | | | |
- * | | v | |
- * | | GET_IMAGE_NAME --/ |
+ * | |\---> ENTITY_UPDATED --/ |
* | | |
* | \----> WATCH_ERROR ---------/
* v
std::string m_mirror_uuid;
pool_watcher::Listener &m_listener;
- ImageIds m_refresh_image_ids;
+ std::map<MirrorEntity, std::string> m_refresh_entities;
bufferlist m_out_bl;
mutable ceph::mutex m_lock;
Context *m_on_init_finish = nullptr;
- ImageIds m_image_ids;
+ std::map<MirrorEntity, std::string> m_entities;
bool m_pending_updates = false;
bool m_notify_listener_in_progress = false;
- ImageIds m_pending_image_ids;
- ImageIds m_pending_added_image_ids;
- ImageIds m_pending_removed_image_ids;
+ std::map<MirrorEntity, std::string> m_pending_entities;
+ std::map<MirrorEntity, std::string> m_pending_added_entities;
+ std::map<MirrorEntity, std::string> m_pending_removed_entities;
MirroringWatcher *m_mirroring_watcher;
AsyncOpTracker m_async_op_tracker;
bool m_blocklisted = false;
bool m_shutting_down = false;
- bool m_image_ids_invalid = true;
+ bool m_entities_invalid = true;
bool m_refresh_in_progress = false;
bool m_deferred_refresh = false;
void handle_register_watcher(int r);
void unregister_watcher();
- void refresh_images();
- void handle_refresh_images(int r);
+ void refresh_entities();
+ void handle_refresh_entities(int r);
- void schedule_refresh_images(double interval);
- void process_refresh_images();
+ void schedule_refresh_entities(double interval);
+ void process_refresh_entities();
void handle_rewatch_complete(int r);
void handle_image_updated(const std::string &image_id,
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+#include "include/stringify.h"
#include "tools/rbd_mirror/Types.h"
namespace rbd {
namespace mirror {
-std::ostream &operator<<(std::ostream &os, const ImageId &image_id) {
- return os << "global id=" << image_id.global_id << ", "
- << "id=" << image_id.id;
+std::ostream &operator<<(std::ostream &os, const MirrorEntityType &type) {
+ switch (type) {
+ case MIRROR_ENTITY_TYPE_IMAGE:
+ os << "Image";
+ break;
+ case MIRROR_ENTITY_TYPE_GROUP:
+ os << "Group";
+ break;
+ default:
+ os << "Unknown (" << static_cast<uint32_t>(type) << ")";
+ break;
+ }
+ return os;
+}
+
+std::ostream &operator<<(std::ostream &os, const MirrorEntity &entity) {
+ return os << "type=" << entity.type << ", global_id=" << entity.global_id
+ << ", count=" << entity.count;
}
std::ostream& operator<<(std::ostream& os,
typedef std::shared_ptr<librados::IoCtx> IoCtxRef;
typedef std::shared_ptr<librbd::Image> ImageRef;
-struct ImageId {
+enum MirrorEntityType {
+ MIRROR_ENTITY_TYPE_IMAGE = 0,
+ MIRROR_ENTITY_TYPE_GROUP = 1,
+};
+
+std::ostream &operator<<(std::ostream &os, const MirrorEntityType &type);
+
+struct MirrorEntity {
+ MirrorEntityType type = MIRROR_ENTITY_TYPE_IMAGE;
std::string global_id;
- std::string id;
+ size_t count = 1;
- explicit ImageId(const std::string &global_id) : global_id(global_id) {
- }
- ImageId(const std::string &global_id, const std::string &id)
- : global_id(global_id), id(id) {
+ MirrorEntity(MirrorEntityType type, const std::string &global_id, size_t count)
+ : type(type), global_id(global_id), count(count) {
}
- inline bool operator==(const ImageId &rhs) const {
- return (global_id == rhs.global_id && id == rhs.id);
+ inline bool operator==(const MirrorEntity &rhs) const {
+ return type == rhs.type && global_id == rhs.global_id && count == rhs.count;
}
- inline bool operator<(const ImageId &rhs) const {
+ inline bool operator<(const MirrorEntity &rhs) const {
+ if (type != rhs.type) {
+ return type < rhs.type;
+ }
return global_id < rhs.global_id;
}
};
-std::ostream &operator<<(std::ostream &, const ImageId &image_id);
+std::ostream &operator<<(std::ostream &, const MirrorEntity &entity);
-typedef std::set<ImageId> ImageIds;
+typedef std::set<MirrorEntity> MirrorEntities;
struct LocalPoolMeta {
LocalPoolMeta() {}
template<typename I>
LoadRequest<I>::LoadRequest(librados::IoCtx &ioctx,
- std::map<std::string, cls::rbd::MirrorImageMap> *image_mapping,
+ std::map<GlobalId, cls::rbd::MirrorImageMap> *image_mapping,
Context *on_finish)
: m_ioctx(ioctx),
m_image_mapping(image_mapping),
return;
}
- m_image_mapping->insert(image_mapping.begin(), image_mapping.end());
+ for (auto &[global_id_str, image_map] : image_mapping) {
+ auto global_id = GlobalId(global_id_str);
+ if (global_id.type != MIRROR_ENTITY_TYPE_IMAGE &&
+ global_id.type != MIRROR_ENTITY_TYPE_GROUP) {
+ derr << ": unknown mirror entitiy type " << global_id.type << " for "
+ << global_id_str << dendl;
+ continue;
+ }
+ m_image_mapping->insert({global_id, image_map});
+ }
if (image_mapping.size() == MAX_RETURN) {
m_start_after = image_mapping.rbegin()->first;
void LoadRequest<I>::cleanup_image_map() {
dout(20) << dendl;
- std::set<std::string> map_removals;
+ std::set<GlobalId> map_removals;
auto it = m_image_mapping->begin();
while (it != m_image_mapping->end()) {
#include "cls/rbd/cls_rbd_types.h"
#include "include/rados/librados.hpp"
+#include "Types.h"
class Context;
class LoadRequest {
public:
static LoadRequest *create(librados::IoCtx &ioctx,
- std::map<std::string, cls::rbd::MirrorImageMap> *image_mapping,
+ std::map<GlobalId, cls::rbd::MirrorImageMap> *image_mapping,
Context *on_finish) {
return new LoadRequest(ioctx, image_mapping, on_finish);
}
* @endverbatim
*/
LoadRequest(librados::IoCtx &ioctx,
- std::map<std::string, cls::rbd::MirrorImageMap> *image_mapping,
+ std::map<GlobalId, cls::rbd::MirrorImageMap> *image_mapping,
Context *on_finish);
librados::IoCtx &m_ioctx;
- std::map<std::string, cls::rbd::MirrorImageMap> *m_image_mapping;
+ std::map<GlobalId, cls::rbd::MirrorImageMap> *m_image_mapping;
Context *m_on_finish;
- std::set<std::string> m_global_image_ids;
+ std::set<GlobalId> m_global_image_ids;
bufferlist m_out_bl;
std::string m_start_after;
// map should at least have once instance
std::string instance_id = stringify(ioctx.get_instance_id());
- m_map.emplace(instance_id, std::set<std::string>{});
+ m_map.emplace(instance_id, GlobalIds{});
}
void Policy::init(
- const std::map<std::string, cls::rbd::MirrorImageMap> &image_mapping) {
+ const std::map<GlobalId, cls::rbd::MirrorImageMap> &image_mapping) {
dout(20) << dendl;
std::unique_lock map_lock{m_map_lock};
auto map_result = m_map[it.second.instance_id].emplace(it.first);
ceph_assert(map_result.second);
+ PolicyData policy_data;
+ try {
+ auto iter = it.second.data.cbegin();
+ if (!iter.end()) {
+ decode(policy_data, iter);
+ }
+ } catch (const buffer::error &err) {
+ derr << "error decoding policy data: " << err.what() << dendl;
+ continue;
+ }
+
auto image_state_result = m_image_states.emplace(
- it.first, ImageState{it.second.instance_id, it.second.mapped_time});
+ it.first, ImageState{policy_data.weight, it.second.instance_id,
+ it.second.mapped_time});
ceph_assert(image_state_result.second);
// ensure we (re)send image acquire actions to the instance
}
}
-LookupInfo Policy::lookup(const std::string &global_image_id) {
- dout(20) << "global_image_id=" << global_image_id << dendl;
+LookupInfo Policy::lookup(const GlobalId &global_id) {
+ dout(20) << "global_id=" << global_id << dendl;
std::shared_lock map_lock{m_map_lock};
LookupInfo info;
- auto it = m_image_states.find(global_image_id);
+ auto it = m_image_states.find(global_id);
if (it != m_image_states.end()) {
info.instance_id = it->second.instance_id;
info.mapped_time = it->second.mapped_time;
+ info.weight = it->second.weight;
}
return info;
}
-bool Policy::add_image(const std::string &global_image_id) {
- dout(5) << "global_image_id=" << global_image_id << dendl;
+bool Policy::add_entity(const GlobalId &global_id, uint64_t weight) {
+ dout(5) << "global_id=" << global_id << dendl;
std::unique_lock map_lock{m_map_lock};
- auto image_state_result = m_image_states.emplace(global_image_id,
- ImageState{});
+ auto image_state_result = m_image_states.emplace(global_id, ImageState{});
auto& image_state = image_state_result.first->second;
if (image_state.state == StateTransition::STATE_INITIALIZING) {
// avoid duplicate acquire notifications upon leader startup
return false;
}
+ image_state.weight = weight;
return set_state(&image_state, StateTransition::STATE_ASSOCIATING, false);
}
-bool Policy::remove_image(const std::string &global_image_id) {
- dout(5) << "global_image_id=" << global_image_id << dendl;
+bool Policy::remove_entity(const GlobalId &global_id) {
+ dout(5) << "global_id=" << global_id << dendl;
std::unique_lock map_lock{m_map_lock};
- auto it = m_image_states.find(global_image_id);
+ auto it = m_image_states.find(global_id);
if (it == m_image_states.end()) {
return false;
}
}
void Policy::add_instances(const InstanceIds &instance_ids,
- GlobalImageIds* global_image_ids) {
+ GlobalIds* global_ids) {
dout(5) << "instance_ids=" << instance_ids << dendl;
std::unique_lock map_lock{m_map_lock};
for (auto& instance : instance_ids) {
ceph_assert(!instance.empty());
- m_map.emplace(instance, std::set<std::string>{});
+ m_map.emplace(instance, GlobalIds{});
}
// post-failover, remove any dead instances and re-shuffle their images
}
if (!dead_instances.empty()) {
- remove_instances(m_map_lock, dead_instances, global_image_ids);
+ remove_instances(m_map_lock, dead_instances, global_ids);
}
}
- GlobalImageIds shuffle_global_image_ids;
- do_shuffle_add_instances(m_map, m_image_states.size(), &shuffle_global_image_ids);
- dout(5) << "shuffling global_image_ids=[" << shuffle_global_image_ids
- << "]" << dendl;
- for (auto& global_image_id : shuffle_global_image_ids) {
- auto it = m_image_states.find(global_image_id);
+ GlobalIds shuffle_global_ids;
+ size_t image_count =
+ std::accumulate(m_image_states.begin(), m_image_states.end(), 0,
+ [](size_t count,
+ const std::pair<GlobalId, ImageState> &p) {
+ return count + p.second.weight;
+ });
+
+ do_shuffle_add_instances(m_map, image_count, &shuffle_global_ids);
+ dout(5) << "shuffling global_ids=[" << shuffle_global_ids << "]" << dendl;
+
+ for (auto &global_id : shuffle_global_ids) {
+ auto it = m_image_states.find(global_id);
ceph_assert(it != m_image_states.end());
auto& image_state = it->second;
if (set_state(&image_state, StateTransition::STATE_SHUFFLING, false)) {
- global_image_ids->emplace(global_image_id);
+ global_ids->emplace(global_id);
}
}
}
void Policy::remove_instances(const InstanceIds &instance_ids,
- GlobalImageIds* global_image_ids) {
+ GlobalIds* global_ids) {
std::unique_lock map_lock{m_map_lock};
- remove_instances(m_map_lock, instance_ids, global_image_ids);
+ remove_instances(m_map_lock, instance_ids, global_ids);
}
void Policy::remove_instances(const ceph::shared_mutex& lock,
const InstanceIds &instance_ids,
- GlobalImageIds* global_image_ids) {
+ GlobalIds* global_ids) {
ceph_assert(ceph_mutex_is_wlocked(m_map_lock));
dout(5) << "instance_ids=" << instance_ids << dendl;
continue;
}
- auto& instance_global_image_ids = map_it->second;
- if (instance_global_image_ids.empty()) {
+ auto& instance_global_ids = map_it->second;
+ if (instance_global_ids.empty()) {
m_map.erase(map_it);
continue;
}
m_dead_instances.insert(instance_id);
dout(5) << "force shuffling: instance_id=" << instance_id << ", "
- << "global_image_ids=[" << instance_global_image_ids << "]"<< dendl;
- for (auto& global_image_id : instance_global_image_ids) {
- auto it = m_image_states.find(global_image_id);
+ << "global_ids=[" << instance_global_ids << "]"<< dendl;
+ for (auto& global_id : instance_global_ids) {
+ auto it = m_image_states.find(global_id);
ceph_assert(it != m_image_states.end());
auto& image_state = it->second;
}
if (set_state(&image_state, StateTransition::STATE_SHUFFLING, true)) {
- global_image_ids->emplace(global_image_id);
+ global_ids->emplace(global_id);
}
}
}
}
-ActionType Policy::start_action(const std::string &global_image_id) {
+ActionType Policy::start_action(const GlobalId &global_id) {
std::unique_lock map_lock{m_map_lock};
- auto it = m_image_states.find(global_image_id);
+ auto it = m_image_states.find(global_id);
ceph_assert(it != m_image_states.end());
auto& image_state = it->second;
auto& transition = image_state.transition;
ceph_assert(transition.action_type != ACTION_TYPE_NONE);
- dout(5) << "global_image_id=" << global_image_id << ", "
+ dout(5) << "global_id=" << global_id << ", "
<< "state=" << image_state.state << ", "
<< "action_type=" << transition.action_type << dendl;
if (transition.start_policy_action) {
- execute_policy_action(global_image_id, &image_state,
+ execute_policy_action(global_id, &image_state,
*transition.start_policy_action);
transition.start_policy_action = boost::none;
}
return transition.action_type;
}
-bool Policy::finish_action(const std::string &global_image_id, int r) {
+bool Policy::finish_action(const GlobalId &global_id, int r) {
std::unique_lock map_lock{m_map_lock};
- auto it = m_image_states.find(global_image_id);
+ auto it = m_image_states.find(global_id);
ceph_assert(it != m_image_states.end());
auto& image_state = it->second;
auto& transition = image_state.transition;
- dout(5) << "global_image_id=" << global_image_id << ", "
+ dout(5) << "global_id=" << global_id << ", "
<< "state=" << image_state.state << ", "
<< "action_type=" << transition.action_type << ", "
<< "r=" << r << dendl;
// image state may get purged in execute_policy_action()
bool pending_action = image_state.transition.action_type != ACTION_TYPE_NONE;
if (finish_policy_action) {
- execute_policy_action(global_image_id, &image_state, *finish_policy_action);
+ execute_policy_action(global_id, &image_state, *finish_policy_action);
}
return pending_action;
}
void Policy::execute_policy_action(
- const std::string& global_image_id, ImageState* image_state,
+ const GlobalId &global_id, ImageState *image_state,
StateTransition::PolicyAction policy_action) {
- dout(5) << "global_image_id=" << global_image_id << ", "
+ dout(5) << "global_id=" << global_id << ", "
<< "policy_action=" << policy_action << dendl;
switch (policy_action) {
case StateTransition::POLICY_ACTION_MAP:
- map(global_image_id, image_state);
+ map(global_id, image_state);
break;
case StateTransition::POLICY_ACTION_UNMAP:
- unmap(global_image_id, image_state);
+ unmap(global_id, image_state);
break;
case StateTransition::POLICY_ACTION_REMOVE:
if (image_state->state == StateTransition::STATE_UNASSOCIATED) {
ceph_assert(image_state->instance_id == UNMAPPED_INSTANCE_ID);
ceph_assert(!image_state->next_state);
- m_image_states.erase(global_image_id);
+ m_image_states.erase(global_id);
}
break;
}
}
-void Policy::map(const std::string& global_image_id, ImageState* image_state) {
+void Policy::map(const GlobalId &global_id, ImageState *image_state) {
ceph_assert(ceph_mutex_is_wlocked(m_map_lock));
std::string instance_id = image_state->instance_id;
return;
}
if (is_dead_instance(instance_id)) {
- unmap(global_image_id, image_state);
+ unmap(global_id, image_state);
}
- instance_id = do_map(m_map, global_image_id);
+ instance_id = do_map(m_map, global_id);
ceph_assert(!instance_id.empty());
- dout(5) << "global_image_id=" << global_image_id << ", "
+ dout(5) << "global_id=" << global_id << ", "
<< "instance_id=" << instance_id << dendl;
image_state->instance_id = instance_id;
image_state->mapped_time = ceph_clock_now();
- auto ins = m_map[instance_id].emplace(global_image_id);
+ auto ins = m_map[instance_id].emplace(global_id);
ceph_assert(ins.second);
}
-void Policy::unmap(const std::string &global_image_id,
- ImageState* image_state) {
+void Policy::unmap(const GlobalId &global_id, ImageState* image_state) {
ceph_assert(ceph_mutex_is_wlocked(m_map_lock));
std::string instance_id = image_state->instance_id;
return;
}
- dout(5) << "global_image_id=" << global_image_id << ", "
- << "instance_id=" << instance_id << dendl;
+ dout(5) << "global_id=" << global_id << ", " << "instance_id=" << instance_id
+ << dendl;
ceph_assert(!instance_id.empty());
- m_map[instance_id].erase(global_image_id);
+ m_map[instance_id].erase(global_id);
image_state->instance_id = UNMAPPED_INSTANCE_ID;
image_state->mapped_time = {};
}
}
-bool Policy::is_image_shuffling(const std::string &global_image_id) {
+bool Policy::is_entity_shuffling(const GlobalId &global_id) const {
ceph_assert(ceph_mutex_is_locked(m_map_lock));
- auto it = m_image_states.find(global_image_id);
+ auto it = m_image_states.find(global_id);
ceph_assert(it != m_image_states.end());
auto& image_state = it->second;
// avoid attempting to re-shuffle a pending shuffle
auto result = is_state_scheduled(image_state,
StateTransition::STATE_SHUFFLING);
- dout(20) << "global_image_id=" << global_image_id << ", "
+ dout(20) << "global_id=" << global_id << ", "
<< "result=" << result << dendl;
return result;
}
-bool Policy::can_shuffle_image(const std::string &global_image_id) {
+bool Policy::can_shuffle_entity(const GlobalId &global_id) const {
ceph_assert(ceph_mutex_is_locked(m_map_lock));
CephContext *cct = reinterpret_cast<CephContext *>(m_ioctx.cct());
int migration_throttle = cct->_conf.get_val<uint64_t>(
"rbd_mirror_image_policy_migration_throttle");
- auto it = m_image_states.find(global_image_id);
+ auto it = m_image_states.find(global_id);
ceph_assert(it != m_image_states.end());
auto& image_state = it->second;
auto result = (StateTransition::is_idle(image_state.state) &&
((migration_throttle <= 0) ||
(now - last_shuffled_time >= migration_throttle)));
- dout(10) << "global_image_id=" << global_image_id << ", "
+ dout(10) << "global_id=" << global_id << ", "
<< "migration_throttle=" << migration_throttle << ", "
<< "last_shuffled_time=" << last_shuffled_time << ", "
<< "result=" << result << dendl;
return result;
}
+uint64_t Policy::get_weight(const GlobalId &global_id) const {
+ ceph_assert(ceph_mutex_is_locked(m_map_lock));
+
+ auto it = m_image_states.find(global_id);
+ ceph_assert(it != m_image_states.end());
+
+ return it->second.weight;
+}
+
bool Policy::set_state(ImageState* image_state, StateTransition::State state,
bool ignore_current_state) {
if (!ignore_current_state && image_state->state == state) {
}
// init -- called during initialization
- void init(
- const std::map<std::string, cls::rbd::MirrorImageMap> &image_mapping);
+ void init(const std::map<GlobalId, cls::rbd::MirrorImageMap> &image_mapping);
// lookup an image from the map
- LookupInfo lookup(const std::string &global_image_id);
+ LookupInfo lookup(const GlobalId &global_id);
// add, remove
- bool add_image(const std::string &global_image_id);
- bool remove_image(const std::string &global_image_id);
+ bool add_entity(const GlobalId &global_id, uint64_t weight);
+ bool remove_entity(const GlobalId &global_id);
// shuffle images when instances are added/removed
- void add_instances(const InstanceIds &instance_ids,
- GlobalImageIds* global_image_ids);
- void remove_instances(const InstanceIds &instance_ids,
- GlobalImageIds* global_image_ids);
+ void add_instances(const InstanceIds &instance_ids, GlobalIds* global_ids);
+ void remove_instances(const InstanceIds &instance_ids, GlobalIds* global_ids);
- ActionType start_action(const std::string &global_image_id);
- bool finish_action(const std::string &global_image_id, int r);
+ ActionType start_action(const GlobalId &global_id);
+ bool finish_action(const GlobalId &global_id, int r);
protected:
- typedef std::map<std::string, std::set<std::string> > InstanceToImageMap;
+ typedef std::map<std::string, GlobalIds> InstanceToImageMap;
- bool is_dead_instance(const std::string instance_id) {
+ bool is_dead_instance(const std::string instance_id) const {
ceph_assert(ceph_mutex_is_locked(m_map_lock));
return m_dead_instances.find(instance_id) != m_dead_instances.end();
}
- bool is_image_shuffling(const std::string &global_image_id);
- bool can_shuffle_image(const std::string &global_image_id);
+ bool is_entity_shuffling(const GlobalId &global_id) const;
+ bool can_shuffle_entity(const GlobalId &global_id) const;
+ uint64_t get_weight(const GlobalId &global_id) const;
- // map an image (global image id) to an instance
+ // map an entity (global id) to an instance
virtual std::string do_map(const InstanceToImageMap& map,
- const std::string &global_image_id) = 0;
+ const GlobalId &global_id) = 0;
// shuffle images when instances are added/removed
virtual void do_shuffle_add_instances(
const InstanceToImageMap& map, size_t image_count,
- std::set<std::string> *remap_global_image_ids) = 0;
+ GlobalIds *remap_global_ids) = 0;
private:
struct ImageState {
+ uint64_t weight = 1;
std::string instance_id = UNMAPPED_INSTANCE_ID;
utime_t mapped_time;
ImageState() {}
- ImageState(const std::string& instance_id, const utime_t& mapped_time)
- : instance_id(instance_id), mapped_time(mapped_time) {
+ ImageState(uint64_t weight, const std::string& instance_id,
+ const utime_t& mapped_time)
+ : weight(weight), instance_id(instance_id), mapped_time(mapped_time) {
}
// active state and action
boost::optional<StateTransition::State> next_state = boost::none;
};
- typedef std::map<std::string, ImageState> ImageStates;
+ typedef std::map<GlobalId, ImageState> ImageStates;
librados::IoCtx &m_ioctx;
void remove_instances(const ceph::shared_mutex& lock,
const InstanceIds &instance_ids,
- GlobalImageIds* global_image_ids);
+ GlobalIds* global_ids);
bool set_state(ImageState* image_state, StateTransition::State state,
bool ignore_current_state);
- void execute_policy_action(const std::string& global_image_id,
- ImageState* image_state,
+ void execute_policy_action(const GlobalId& global_id, ImageState* image_state,
StateTransition::PolicyAction policy_action);
- void map(const std::string& global_image_id, ImageState* image_state);
- void unmap(const std::string &global_image_id, ImageState* image_state);
+ void map(const GlobalId &global_id, ImageState* image_state);
+ void unmap(const GlobalId &global_id, ImageState* image_state);
bool is_state_scheduled(const ImageState& image_state,
StateTransition::State state) const;
void SimplePolicy::do_shuffle_add_instances(
const InstanceToImageMap& map, size_t image_count,
- std::set<std::string> *remap_global_image_ids) {
+ GlobalIds *remap_global_ids) {
uint64_t images_per_instance = calc_images_per_instance(map, image_count);
dout(5) << "images per instance=" << images_per_instance << dendl;
for (auto const &instance : map) {
- if (instance.second.size() <= images_per_instance) {
+ uint64_t instance_image_count =
+ std::accumulate(instance.second.begin(), instance.second.end(), 0,
+ [this](uint64_t count, const GlobalId &global_id) {
+ return count + get_weight(global_id);
+ });
+
+ if (instance_image_count <= images_per_instance) {
continue;
}
auto it = instance.second.begin();
- uint64_t cut_off = instance.second.size() - images_per_instance;
+ uint64_t cut_off = instance_image_count - images_per_instance;
+
+ // TODO: improve for weight > 1: find the best entity(ies) to cut off
while (it != instance.second.end() && cut_off > 0) {
- if (Policy::is_image_shuffling(*it)) {
- --cut_off;
- } else if (Policy::can_shuffle_image(*it)) {
- --cut_off;
- remap_global_image_ids->emplace(*it);
+ auto weight = get_weight(*it);
+ if (weight <= cut_off) {
+ if (Policy::is_entity_shuffling(*it)) {
+ cut_off -= weight;
+ } else if (Policy::can_shuffle_entity(*it)) {
+ cut_off -= weight;
+ remap_global_ids->emplace(*it);
+ }
}
-
++it;
}
}
}
std::string SimplePolicy::do_map(const InstanceToImageMap& map,
- const std::string &global_image_id) {
+ const GlobalId &global_id) {
auto min_it = map.end();
+ uint64_t min_image_count = UINT64_MAX;
for (auto it = map.begin(); it != map.end(); ++it) {
- ceph_assert(it->second.find(global_image_id) == it->second.end());
+ ceph_assert(it->second.find(global_id) == it->second.end());
if (Policy::is_dead_instance(it->first)) {
continue;
- } else if (min_it == map.end()) {
- min_it = it;
- } else if (it->second.size() < min_it->second.size()) {
+ }
+ uint64_t image_count =
+ std::accumulate(it->second.begin(), it->second.end(), 0,
+ [this](uint64_t count, const GlobalId &global_id) {
+ return count + get_weight(global_id);
+ });
+ if (image_count < min_image_count) {
min_it = it;
+ min_image_count = image_count;
}
}
ceph_assert(min_it != map.end());
- dout(20) << "global_image_id=" << global_image_id << " maps to instance_id="
+ dout(20) << "global_id=" << global_id << " maps to instance_id="
<< min_it->first << dendl;
return min_it->first;
}
protected:
SimplePolicy(librados::IoCtx &ioctx);
- std::string do_map(const InstanceToImageMap& map,
- const std::string &global_image_id) override;
+ std::string do_map(const InstanceToImageMap &map,
+ const GlobalId &global_id) override;
void do_shuffle_add_instances(
const InstanceToImageMap& map, size_t image_count,
- std::set<std::string> *remap_global_image_ids) override;
+ GlobalIds *remap_global_ids) override;
private:
size_t calc_images_per_instance(const InstanceToImageMap& map,
} // anonymous namespace
+GlobalId::GlobalId(const std::string &global_id) {
+ size_t pos = 0;
+ if (global_id.size() > 1 && global_id[1] == ':') {
+ ceph_assert(global_id[0] >= '0');
+ type = static_cast<MirrorEntityType>(global_id[0] - '0');
+ pos = 2;
+ }
+ id = global_id.substr(pos);
+}
+
+std::string GlobalId::to_str() const {
+ if (type == MIRROR_ENTITY_TYPE_IMAGE) {
+ return id;
+ }
+
+ return stringify(static_cast<int>(type)) + ":" + id;
+}
+
+std::ostream &operator<<(std::ostream &os, const GlobalId &global_id) {
+ return os << "{" << global_id.type << ", " << global_id.id << "}";
+}
+
PolicyMetaType PolicyData::get_policy_meta_type() const {
return std::visit(GetTypeVisitor<PolicyMetaType>(), policy_meta);
}
void PolicyData::encode(bufferlist& bl) const {
- ENCODE_START(1, 1, bl);
+ ENCODE_START(2, 1, bl);
std::visit(EncodeVisitor(bl), policy_meta);
+ encode(weight, bl);
ENCODE_FINISH(bl);
}
void PolicyData::decode(bufferlist::const_iterator& it) {
- DECODE_START(1, it);
+ DECODE_START(2, it);
uint32_t policy_meta_type;
decode(policy_meta_type, it);
}
std::visit(DecodeVisitor(struct_v, it), policy_meta);
+ if (struct_v >= 2) {
+ decode(weight, it);
+ }
DECODE_FINISH(it);
}
}
void PolicyData::generate_test_instances(std::list<PolicyData *> &o) {
- o.push_back(new PolicyData(PolicyMetaNone()));
+ o.push_back(new PolicyData(1, PolicyMetaNone()));
}
std::ostream &operator<<(std::ostream &os, const ActionType& action_type) {
struct LookupInfo {
std::string instance_id = UNMAPPED_INSTANCE_ID;
utime_t mapped_time;
+ uint64_t weight = 1;
};
enum ActionType {
ACTION_TYPE_RELEASE
};
+struct GlobalId {
+ MirrorEntityType type = MIRROR_ENTITY_TYPE_IMAGE;
+ std::string id;
+
+ GlobalId(MirrorEntityType type, const std::string &id) : type(type), id(id) {
+ }
+ GlobalId(const std::string &global_id);
+
+ std::string to_str() const;
+
+ inline bool operator==(const GlobalId &rhs) const {
+ return type == rhs.type && id == rhs.id;
+ }
+ inline bool operator<(const GlobalId &rhs) const {
+ if (type != rhs.type) {
+ return type < rhs.type;
+ }
+ return id < rhs.id;
+ }
+};
+
+std::ostream &operator<<(std::ostream &os, const GlobalId &global_id);
+
typedef std::vector<std::string> InstanceIds;
-typedef std::set<std::string> GlobalImageIds;
+typedef std::set<GlobalId> GlobalIds;
typedef std::map<std::string, ActionType> ImageActionTypes;
enum PolicyMetaType {
PolicyData()
: policy_meta(PolicyMetaUnknown()) {
}
- PolicyData(const PolicyMeta &policy_meta)
- : policy_meta(policy_meta) {
+ PolicyData(uint64_t weight, const PolicyMeta &policy_meta)
+ : weight(weight), policy_meta(policy_meta) {
}
+ uint64_t weight = 1;
PolicyMeta policy_meta;
PolicyMetaType get_policy_meta_type() const;
template <typename I>
UpdateRequest<I>::UpdateRequest(librados::IoCtx &ioctx,
- std::map<std::string, cls::rbd::MirrorImageMap> &&update_mapping,
- std::set<std::string> &&remove_global_image_ids, Context *on_finish)
+ std::map<GlobalId, cls::rbd::MirrorImageMap> &&update_mapping,
+ GlobalIds &&remove_global_ids, Context *on_finish)
: m_ioctx(ioctx),
m_update_mapping(update_mapping),
- m_remove_global_image_ids(remove_global_image_ids),
+ m_remove_global_ids(remove_global_ids),
m_on_finish(on_finish) {
}
void UpdateRequest<I>::update_image_map() {
dout(20) << dendl;
- if (m_update_mapping.empty() && m_remove_global_image_ids.empty()) {
+ if (m_update_mapping.empty() && m_remove_global_ids.empty()) {
finish(0);
return;
}
auto it1 = m_update_mapping.begin();
while (it1 != m_update_mapping.end() && nr_updates++ < MAX_UPDATE) {
- librbd::cls_client::mirror_image_map_update(&op, it1->first, it1->second);
+ librbd::cls_client::mirror_image_map_update(&op, it1->first.to_str(), it1->second);
it1 = m_update_mapping.erase(it1);
}
- auto it2 = m_remove_global_image_ids.begin();
- while (it2 != m_remove_global_image_ids.end() && nr_updates++ < MAX_UPDATE) {
- librbd::cls_client::mirror_image_map_remove(&op, *it2);
- it2 = m_remove_global_image_ids.erase(it2);
+ auto it2 = m_remove_global_ids.begin();
+ while (it2 != m_remove_global_ids.end() && nr_updates++ < MAX_UPDATE) {
+ librbd::cls_client::mirror_image_map_remove(&op, it2->to_str());
+ it2 = m_remove_global_ids.erase(it2);
}
librados::AioCompletion *aio_comp = create_rados_callback<
#include "cls/rbd/cls_rbd_types.h"
#include "include/rados/librados.hpp"
+#include "Types.h"
class Context;
// accepts an image map for updation and a collection of
// global image ids to purge.
static UpdateRequest *create(librados::IoCtx &ioctx,
- std::map<std::string, cls::rbd::MirrorImageMap> &&update_mapping,
- std::set<std::string> &&remove_global_image_ids, Context *on_finish) {
- return new UpdateRequest(ioctx, std::move(update_mapping), std::move(remove_global_image_ids),
+ std::map<GlobalId, cls::rbd::MirrorImageMap> &&update_mapping,
+ GlobalIds &&remove_global_ids, Context *on_finish) {
+ return new UpdateRequest(ioctx, std::move(update_mapping), std::move(remove_global_ids),
on_finish);
}
* @endverbatim
*/
UpdateRequest(librados::IoCtx &ioctx,
- std::map<std::string, cls::rbd::MirrorImageMap> &&update_mapping,
- std::set<std::string> &&remove_global_image_ids, Context *on_finish);
+ std::map<GlobalId, cls::rbd::MirrorImageMap> &&update_mapping,
+ GlobalIds &&remove_global_ids, Context *on_finish);
librados::IoCtx &m_ioctx;
- std::map<std::string, cls::rbd::MirrorImageMap> m_update_mapping;
- std::set<std::string> m_remove_global_image_ids;
+ std::map<GlobalId, cls::rbd::MirrorImageMap> m_update_mapping;
+ GlobalIds m_remove_global_ids;
Context *m_on_finish;
void update_image_map();
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "tools/rbd_mirror/pool_watcher/RefreshEntitiesRequest.h"
+#include "common/debug.h"
+#include "common/errno.h"
+#include "cls/rbd/cls_rbd_client.h"
+#include "librbd/Utils.h"
+#include <map>
+
+#define dout_context g_ceph_context
+#define dout_subsys ceph_subsys_rbd_mirror
+#undef dout_prefix
+#define dout_prefix *_dout << "rbd::mirror::pool_watcher::RefreshEntitiesRequest " \
+ << this << " " << __func__ << ": "
+
+namespace rbd {
+namespace mirror {
+namespace pool_watcher {
+
+static const uint32_t MAX_RETURN = 1024;
+
+using librbd::util::create_rados_callback;
+
+template <typename I>
+void RefreshEntitiesRequest<I>::send() {
+ m_entities->clear();
+ mirror_image_list();
+}
+
+template <typename I>
+void RefreshEntitiesRequest<I>::mirror_image_list() {
+ dout(10) << dendl;
+
+ librados::ObjectReadOperation op;
+ librbd::cls_client::mirror_image_list_start(&op, m_start_after, MAX_RETURN,
+ false);
+ m_out_bl.clear();
+ librados::AioCompletion *aio_comp = create_rados_callback<
+ RefreshEntitiesRequest<I>,
+ &RefreshEntitiesRequest<I>::handle_mirror_image_list>(this);
+ int r = m_remote_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl);
+ ceph_assert(r == 0);
+ aio_comp->release();
+}
+
+template <typename I>
+void RefreshEntitiesRequest<I>::handle_mirror_image_list(int r) {
+ dout(10) << "r=" << r << dendl;
+
+ std::map<std::string, std::string> ids;
+ if (r == 0) {
+ auto it = m_out_bl.cbegin();
+ r = librbd::cls_client::mirror_image_list_finish(&it, &ids);
+ }
+
+ if (r < 0 && r != -ENOENT) {
+ derr << "failed to list mirrored images: " << cpp_strerror(r) << dendl;
+ finish(r);
+ return;
+ }
+
+ for (auto &[image_id, global_image_id] : ids) {
+ m_entities->insert(
+ {{MIRROR_ENTITY_TYPE_IMAGE, global_image_id, 1}, image_id});
+ }
+
+ if (ids.size() == MAX_RETURN) {
+ m_start_after = ids.rbegin()->first;
+ mirror_image_list();
+ return;
+ }
+
+ finish(0);
+}
+
+template <typename I>
+void RefreshEntitiesRequest<I>::finish(int r) {
+ dout(10) << "r=" << r << dendl;
+
+ m_on_finish->complete(r);
+ delete this;
+}
+
+} // namespace pool_watcher
+} // namespace mirror
+} // namespace rbd
+
+template class rbd::mirror::pool_watcher::RefreshEntitiesRequest<librbd::ImageCtx>;
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_RBD_MIRROR_POOL_WATCHER_REFRESH_IMAGES_REQUEST_H
+#define CEPH_RBD_MIRROR_POOL_WATCHER_REFRESH_IMAGES_REQUEST_H
+
+#include "include/buffer.h"
+#include "include/rados/librados.hpp"
+#include "tools/rbd_mirror/Types.h"
+#include <string>
+
+struct Context;
+
+namespace librbd { struct ImageCtx; }
+
+namespace rbd {
+namespace mirror {
+namespace pool_watcher {
+
+template <typename ImageCtxT = librbd::ImageCtx>
+class RefreshEntitiesRequest {
+public:
+ static RefreshEntitiesRequest *create(librados::IoCtx &remote_io_ctx,
+ std::map<MirrorEntity,
+ std::string> *entities,
+ Context *on_finish) {
+ return new RefreshEntitiesRequest(remote_io_ctx, entities, on_finish);
+ }
+
+ RefreshEntitiesRequest(librados::IoCtx &remote_io_ctx,
+ std::map<MirrorEntity,
+ std::string> *entities,
+ Context *on_finish)
+ : m_remote_io_ctx(remote_io_ctx), m_entities(entities),
+ m_on_finish(on_finish) {
+ }
+
+ void send();
+
+private:
+ /**
+ * @verbatim
+ *
+ * <start>
+ * |
+ * | /-------------\
+ * | | |
+ * v v | (more images)
+ * MIRROR_IMAGE_LIST ---/
+ * |
+ * v
+ * <finish>
+ *
+ * @endverbatim
+ */
+
+ librados::IoCtx &m_remote_io_ctx;
+ std::map<MirrorEntity, std::string> *m_entities;
+ Context *m_on_finish;
+
+ bufferlist m_out_bl;
+ std::string m_start_after;
+
+ void mirror_image_list();
+ void handle_mirror_image_list(int r);
+
+ void finish(int r);
+
+};
+
+} // namespace pool_watcher
+} // namespace mirror
+} // namespace rbd
+
+extern template class rbd::mirror::pool_watcher::RefreshEntitiesRequest<librbd::ImageCtx>;
+
+#endif // CEPH_RBD_MIRROR_POOL_WATCHER_REFRESH_IMAGES_REQUEST_H
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "tools/rbd_mirror/pool_watcher/RefreshImagesRequest.h"
-#include "common/debug.h"
-#include "common/errno.h"
-#include "cls/rbd/cls_rbd_client.h"
-#include "librbd/Utils.h"
-#include <map>
-
-#define dout_context g_ceph_context
-#define dout_subsys ceph_subsys_rbd_mirror
-#undef dout_prefix
-#define dout_prefix *_dout << "rbd::mirror::pool_watcher::RefreshImagesRequest " \
- << this << " " << __func__ << ": "
-
-namespace rbd {
-namespace mirror {
-namespace pool_watcher {
-
-static const uint32_t MAX_RETURN = 1024;
-
-using librbd::util::create_rados_callback;
-
-template <typename I>
-void RefreshImagesRequest<I>::send() {
- m_image_ids->clear();
- mirror_image_list();
-}
-
-template <typename I>
-void RefreshImagesRequest<I>::mirror_image_list() {
- dout(10) << dendl;
-
- librados::ObjectReadOperation op;
- librbd::cls_client::mirror_image_list_start(&op, m_start_after, MAX_RETURN,
- false);
- m_out_bl.clear();
- librados::AioCompletion *aio_comp = create_rados_callback<
- RefreshImagesRequest<I>,
- &RefreshImagesRequest<I>::handle_mirror_image_list>(this);
- int r = m_remote_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl);
- ceph_assert(r == 0);
- aio_comp->release();
-}
-
-template <typename I>
-void RefreshImagesRequest<I>::handle_mirror_image_list(int r) {
- dout(10) << "r=" << r << dendl;
-
- std::map<std::string, std::string> ids;
- if (r == 0) {
- auto it = m_out_bl.cbegin();
- r = librbd::cls_client::mirror_image_list_finish(&it, &ids);
- }
-
- if (r < 0 && r != -ENOENT) {
- derr << "failed to list mirrored images: " << cpp_strerror(r) << dendl;
- finish(r);
- return;
- }
-
- // store as global -> local image ids
- for (auto &id : ids) {
- m_image_ids->emplace(id.second, id.first);
- }
-
- if (ids.size() == MAX_RETURN) {
- m_start_after = ids.rbegin()->first;
- mirror_image_list();
- return;
- }
-
- finish(0);
-}
-
-template <typename I>
-void RefreshImagesRequest<I>::finish(int r) {
- dout(10) << "r=" << r << dendl;
-
- m_on_finish->complete(r);
- delete this;
-}
-
-} // namespace pool_watcher
-} // namespace mirror
-} // namespace rbd
-
-template class rbd::mirror::pool_watcher::RefreshImagesRequest<librbd::ImageCtx>;
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#ifndef CEPH_RBD_MIRROR_POOL_WATCHER_REFRESH_IMAGES_REQUEST_H
-#define CEPH_RBD_MIRROR_POOL_WATCHER_REFRESH_IMAGES_REQUEST_H
-
-#include "include/buffer.h"
-#include "include/rados/librados.hpp"
-#include "tools/rbd_mirror/Types.h"
-#include <string>
-
-struct Context;
-
-namespace librbd { struct ImageCtx; }
-
-namespace rbd {
-namespace mirror {
-namespace pool_watcher {
-
-template <typename ImageCtxT = librbd::ImageCtx>
-class RefreshImagesRequest {
-public:
- static RefreshImagesRequest *create(librados::IoCtx &remote_io_ctx,
- ImageIds *image_ids, Context *on_finish) {
- return new RefreshImagesRequest(remote_io_ctx, image_ids, on_finish);
- }
-
- RefreshImagesRequest(librados::IoCtx &remote_io_ctx, ImageIds *image_ids,
- Context *on_finish)
- : m_remote_io_ctx(remote_io_ctx), m_image_ids(image_ids),
- m_on_finish(on_finish) {
- }
-
- void send();
-
-private:
- /**
- * @verbatim
- *
- * <start>
- * |
- * | /-------------\
- * | | |
- * v v | (more images)
- * MIRROR_IMAGE_LIST ---/
- * |
- * v
- * <finish>
- *
- * @endverbatim
- */
-
- librados::IoCtx &m_remote_io_ctx;
- ImageIds *m_image_ids;
- Context *m_on_finish;
-
- bufferlist m_out_bl;
- std::string m_start_after;
-
- void mirror_image_list();
- void handle_mirror_image_list(int r);
-
- void finish(int r);
-
-};
-
-} // namespace pool_watcher
-} // namespace mirror
-} // namespace rbd
-
-extern template class rbd::mirror::pool_watcher::RefreshImagesRequest<librbd::ImageCtx>;
-
-#endif // CEPH_RBD_MIRROR_POOL_WATCHER_REFRESH_IMAGES_REQUEST_H
}
virtual void handle_update(const std::string &mirror_uuid,
- ImageIds &&added_image_ids,
- ImageIds &&removed_image_ids) = 0;
+ MirrorEntities &&added_entities,
+ MirrorEntities &&removed_entities) = 0;
};
} // namespace pool_watcher