ASSERT_TRUE(info.instance_id == UNMAPPED_INSTANCE_ID);
}
+TEST_F(TestImageMapPolicy, InitialInstanceUpdate) {
+ const std::string global_image_id = "global id 1";
+
+ m_policy->init({{global_image_id, {"9876", {}, {}}}});
+
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_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);
+
+ ASSERT_EQ(0U, shuffle_global_image_ids.size());
+ ASSERT_TRUE(m_policy->finish_action(global_image_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_MAP_UPDATE, m_policy->start_action(global_image_id));
+ ASSERT_TRUE(m_policy->finish_action(global_image_id, 0));
+
+ ASSERT_EQ(ACTION_TYPE_ACQUIRE, m_policy->start_action(global_image_id));
+ ASSERT_FALSE(m_policy->finish_action(global_image_id, 0));
+}
+
} // namespace image_map
} // namespace mirror
} // namespace rbd
&peer_ack_ctxs);
wait_for_scheduled_task();
+ auto local_instance_id = stringify(m_local_io_ctx.get_instance_id());
+ mock_image_map->update_instances_added({local_instance_id});
+
std::set<std::string> shuffled_global_image_ids;
// RELEASE+UPDATE_MAPPING+ACQUIRE
&peer_ack_ctxs);
wait_for_scheduled_task();
+ auto local_instance_id = stringify(m_local_io_ctx.get_instance_id());
+ mock_image_map->update_instances_added({local_instance_id});
+
std::set<std::string> shuffled_global_image_ids;
// RELEASE+UPDATE_MAPPING+ACQUIRE
mock_image_map->init(&cond);
ASSERT_EQ(0, cond.wait());
+ mock_image_map->update_instances_added({local_instance_id});
+
std::set<std::string> global_image_ids_ack(global_image_ids);
// remote peer ACKs image acquire request -- completing action
&peer_ack_ctxs);
wait_for_scheduled_task();
+ auto local_instance_id = stringify(m_local_io_ctx.get_instance_id());
+ mock_image_map->update_instances_added({local_instance_id});
+
std::set<std::string> shuffled_global_image_ids;
// RELEASE+UPDATE_MAPPING+ACQUIRE
mock_image_map->init(&cond);
ASSERT_EQ(0, cond.wait());
+ auto local_instance_id = stringify(m_local_io_ctx.get_instance_id());
+ mock_image_map->update_instances_added({local_instance_id});
+
std::set<std::string> global_image_ids{
"global id 1", "global id 2", "global id 3", "remote id 4",
};
m_map.emplace(instance, std::set<std::string>{});
}
+ // post-failover, remove any dead instances and re-shuffle their images
+ if (m_initial_update) {
+ dout(5) << "initial instance update" << dendl;
+ m_initial_update = false;
+
+ std::set<std::string> alive_instances(instance_ids.begin(),
+ instance_ids.end());
+ InstanceIds dead_instances;
+ for (auto& map_pair : m_map) {
+ if (alive_instances.find(map_pair.first) == alive_instances.end()) {
+ dead_instances.push_back(map_pair.first);
+ }
+ }
+
+ if (!dead_instances.empty()) {
+ remove_instances(m_map_lock, dead_instances, global_image_ids);
+ }
+ }
+
GlobalImageIds shuffle_global_image_ids;
do_shuffle_add_instances(m_map, m_image_states.size(), instance_ids,
&shuffle_global_image_ids);
void Policy::remove_instances(const InstanceIds &instance_ids,
GlobalImageIds* global_image_ids) {
+ RWLock::WLocker map_lock(m_map_lock);
+ remove_instances(m_map_lock, instance_ids, global_image_ids);
+}
+
+void Policy::remove_instances(const RWLock& lock,
+ const InstanceIds &instance_ids,
+ GlobalImageIds* global_image_ids) {
+ assert(m_map_lock.is_wlocked());
dout(5) << "instance_ids=" << instance_ids << dendl;
- RWLock::WLocker map_lock(m_map_lock);
for (auto& instance_id : instance_ids) {
auto map_it = m_map.find(instance_id);
if (map_it != m_map.end()) {
ImageStates m_image_states;
std::set<std::string> m_dead_instances;
+ bool m_initial_update = true;
+
+ void remove_instances(const RWLock& lock, const InstanceIds &instance_ids,
+ GlobalImageIds* global_image_ids);
+
bool set_state(ImageState* image_state, StateTransition::State state,
bool ignore_current_state);