TEST_F(TestImageDeleter, Delete_NonPrimary_Image) {
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
promote_image();
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
// there is bug in the implementation
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, "diff global id");
+ "diff global id");
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, "diff global id",
create_snapshot();
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
create_snapshot("snap2");
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
create_snapshot("snap1", true);
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
create_snapshot("snap2", true);
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
std::string clone_id = create_clone();
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
m_deleter->schedule_image_delete(_rados, m_local_pool_id, clone_id,
- "clone1", GLOBAL_CLONE_IMAGE_ID);
+ GLOBAL_CLONE_IMAGE_ID);
C_SaferCond ctx2;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_CLONE_IMAGE_ID,
mirror_image));
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
mirror_image));
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
remove_image();
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
EXPECT_EQ(0, ictx->state->open(false));
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
m_deleter->set_failed_timer_interval(2);
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
EXPECT_EQ(0, ictx->state->open(false));
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
C_SaferCond ctx;
m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
m_deleter->schedule_image_delete(_rados, m_local_pool_id, m_local_image_id,
- m_image_name, GLOBAL_IMAGE_ID);
+ GLOBAL_IMAGE_ID);
ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
image.close();
m_mirrored_images.insert(PoolWatcher::ImageId(
- get_image_id(&ioctx, name), name, mirror_image_info.global_id));
+ mirror_image_info.global_id, get_image_id(&ioctx, name), name));
}
if (image_name != nullptr)
*image_name = name;
image.close();
m_mirrored_images.insert(PoolWatcher::ImageId(
- get_image_id(&cioctx, name), name, mirror_image_info.global_id));
+ mirror_image_info.global_id, get_image_id(&cioctx, name), name));
}
if (image_name != nullptr)
*image_name = name;
void ImageDeleter::schedule_image_delete(RadosRef local_rados,
int64_t local_pool_id,
const std::string& local_image_id,
- const std::string& local_image_name,
const std::string& global_image_id) {
dout(20) << "enter" << dendl;
auto del_info = find_delete_info(local_pool_id, global_image_id);
if (del_info != nullptr) {
- dout(20) << "image " << local_image_name << " (" << global_image_id << ") "
+ dout(20) << "image " << local_image_id << " (" << global_image_id << ") "
<< "was already scheduled for deletion" << dendl;
return;
}
m_delete_queue.push_front(unique_ptr<DeleteInfo>(
new DeleteInfo(local_rados, local_pool_id, local_image_id,
- local_image_name, global_image_id)));
+ global_image_id)));
m_delete_queue_cond.Signal();
}
return;
}
+ dout(20) << "local_pool_id=" << local_pool_id << ", "
+ << "global_image_id=" << global_image_id << dendl;
+
if ((*del_info)->on_delete != nullptr) {
(*del_info)->on_delete->complete(-ESTALE);
}
librbd::NoOpProgressContext ctx;
r = librbd::remove(ioctx, "", m_active_delete->local_image_id, ctx, true);
if (r < 0 && r != -ENOENT) {
- derr << "error removing image " << m_active_delete->local_image_name
- << " from local pool: " << cpp_strerror(r) << dendl;
+ derr << "error removing image " << m_active_delete->local_image_id << " "
+ << "(" << m_active_delete->global_image_id << ") from local pool: "
+ << cpp_strerror(r) << dendl;
enqueue_failed_delete(r);
return true;
}
return true;
}
- dout(10) << "Successfully deleted image: "
- << m_active_delete->local_image_name << dendl;
+ dout(10) << "Successfully deleted image "
+ << m_active_delete->local_image_id << " "
+ << "(" << m_active_delete->global_image_id << ")" << dendl;
complete_active_delete(0);
return true;
Mutex::Locker l(m_delete_lock);
for (const auto& del_info : m_delete_queue) {
- items.push_back(del_info->local_image_name);
+ items.push_back(del_info->local_image_id);
}
return items;
Mutex::Locker l(m_delete_lock);
for (const auto& del_info : m_failed_queue) {
- items.push_back(make_pair(del_info->local_image_name,
+ items.push_back(make_pair(del_info->local_image_id,
del_info->error_code));
}
void schedule_image_delete(RadosRef local_rados,
int64_t local_pool_id,
const std::string& local_image_id,
- const std::string& local_image_name,
const std::string& global_image_id);
void wait_for_scheduled_deletion(int64_t local_pool_id,
const std::string &global_image_id,
RadosRef local_rados;
int64_t local_pool_id;
std::string local_image_id;
- std::string local_image_name;
std::string global_image_id;
int error_code;
int retries;
DeleteInfo(RadosRef local_rados, int64_t local_pool_id,
const std::string& local_image_id,
- const std::string& local_image_name,
const std::string& global_image_id) :
local_rados(local_rados), local_pool_id(local_pool_id),
- local_image_id(local_image_id), local_image_name(local_image_name),
- global_image_id(global_image_id), error_code(0), retries(0),
- notify_on_failed_retry(true), on_delete(nullptr) {
+ local_image_id(local_image_id), global_image_id(global_image_id),
+ error_code(0), retries(0), notify_on_failed_retry(true),
+ on_delete(nullptr) {
}
bool match(int64_t local_pool_id, const std::string &global_image_id) {
m_image_deleter->schedule_image_delete(m_local,
m_local_pool_id,
m_local_image_id,
- m_local_image_name,
m_global_image_id);
m_stopping_for_resync = false;
}
if (it2 != image_id_to_name.end()) {
image_name = it2->second;
}
- image_ids->insert(ImageId(it->first, image_name, it->second));
+ image_ids->insert(ImageId(it->second, it->first, image_name));
}
if (!mirror_images.empty()) {
last_read = mirror_images.rbegin()->first;
#include "common/Timer.h"
#include "include/rados/librados.hpp"
#include "types.h"
+#include <boost/optional.hpp>
namespace rbd {
namespace mirror {
class PoolWatcher {
public:
struct ImageId {
+ std::string global_id;
std::string id;
boost::optional<std::string> name;
- std::string global_id;
- ImageId(const std::string &id,
- const boost::optional<std::string> &name = boost::none,
- const std::string &global_id = "")
- : id(id), name(name), global_id(global_id) {
+ ImageId(const std::string &global_id, const std::string &id = "",
+ const boost::optional<std::string> &name = boost::none)
+ : global_id(global_id), id(id), name(name) {
}
inline bool operator==(const ImageId &rhs) const {
- return (id == rhs.id && name == rhs.name && global_id == rhs.global_id);
+ return (global_id == rhs.global_id && id == rhs.id && name == rhs.name);
}
inline bool operator<(const ImageId &rhs) const {
- return id < rhs.id;
+ return global_id < rhs.global_id;
}
};
typedef std::set<ImageId> ImageIds;
return;
}
- std::set<InitImageInfo> images;
+ ImageIds image_ids;
std::string last_read = "";
int max_read = 1024;
<< dendl;
continue;
}
- images.insert(InitImageInfo(it->second, it->first, image_name));
+ image_ids.insert(ImageId(it->second, it->first, image_name));
}
if (!mirror_images.empty()) {
last_read = mirror_images.rbegin()->first;
r = mirror_images.size();
} while (r == max_read);
- m_init_images = std::move(images);
+ m_init_image_ids = std::move(image_ids);
}
void Replayer::run()
assert(m_lock.is_locked());
- if (!m_init_images.empty() && !m_stopping.read() &&
+ if (!m_init_image_ids.empty() && !m_stopping.read() &&
m_leader_watcher->is_leader()) {
dout(20) << "scanning initial local image set" << dendl;
for (auto &remote_image : image_ids) {
- auto it = m_init_images.find(InitImageInfo(remote_image.global_id));
- if (it != m_init_images.end()) {
- m_init_images.erase(it);
+ auto it = m_init_image_ids.find(ImageId(remote_image.global_id));
+ if (it != m_init_image_ids.end()) {
+ m_init_image_ids.erase(it);
}
}
- // the remaining images in m_init_images must be deleted
- for (auto &image : m_init_images) {
+ // the remaining images in m_init_image_ids must be deleted
+ for (auto &image_id : m_init_image_ids) {
dout(20) << "scheduling the deletion of init image: "
- << image.name << dendl;
+ << image_id.global_id << " (" << image_id.id << ")" << dendl;
m_image_deleter->schedule_image_delete(m_local_rados, m_local_pool_id,
- image.id, image.name,
- image.global_id);
+ image_id.id, image_id.global_id);
}
- m_init_images.clear();
+ m_init_image_ids.clear();
}
// shut down replayers for non-mirrored images
for (auto image_it = m_image_replayers.begin();
image_it != m_image_replayers.end();) {
- if (image_ids.find(ImageId(image_it->first)) == image_ids.end()) {
+ auto image_id_it = image_ids.find(image_it->first);
+ if (image_id_it == image_ids.end() ||
+ image_id_it->id != image_it->second->get_remote_image_id()) {
if (image_it->second->is_running()) {
- dout(20) << "stop image replayer for "
+ dout(20) << "stop image replayer for remote image "
<< image_it->second->get_global_image_id() << dendl;
}
if (stop_image_replayer(image_it->second)) {
}
for (auto &image_id : image_ids) {
- auto it = m_image_replayers.find(image_id.id);
+ auto it = m_image_replayers.find(image_id.global_id);
if (it == m_image_replayers.end()) {
unique_ptr<ImageReplayer<> > image_replayer(new ImageReplayer<>(
m_threads, m_image_deleter, m_image_sync_throttler, m_local_rados,
m_remote_rados, local_mirror_uuid, remote_mirror_uuid, m_local_pool_id,
m_remote_pool_id, image_id.id, image_id.global_id));
it = m_image_replayers.insert(
- std::make_pair(image_id.id, std::move(image_replayer))).first;
+ std::make_pair(image_id.global_id, std::move(image_replayer))).first;
+ } else if (image_id.id != it->second->get_remote_image_id()) {
+ // mismatched replayer in progress of stopping
+ continue;
}
if (!it->second->is_running()) {
- dout(20) << "starting image replayer for "
- << it->second->get_global_image_id() << dendl;
+ dout(20) << "starting image replayer for remote image "
+ << image_id.global_id << dendl;
}
- start_image_replayer(it->second, image_id.id, image_id.name);
+ start_image_replayer(it->second);
}
}
-void Replayer::start_image_replayer(unique_ptr<ImageReplayer<> > &image_replayer,
- const std::string &image_id,
- const boost::optional<std::string>& image_name)
+void Replayer::start_image_replayer(unique_ptr<ImageReplayer<> > &image_replayer)
{
assert(m_lock.is_locked());
- dout(20) << "global_image_id=" << image_replayer->get_global_image_id()
- << dendl;
+
+ std::string global_image_id = image_replayer->get_global_image_id();
+ dout(20) << "global_image_id=" << global_image_id << dendl;
if (!image_replayer->is_stopped()) {
return;
return;
}
- if (image_name) {
- FunctionContext *ctx = new FunctionContext(
- [this, image_id, image_name] (int r) {
- if (r == -ESTALE || r == -ECANCELED) {
- return;
- }
+ FunctionContext *ctx = new FunctionContext(
+ [this, global_image_id] (int r) {
+ dout(20) << "image deleter result: r=" << r << ", "
+ << "global_image_id=" << global_image_id << dendl;
+ if (r == -ESTALE || r == -ECANCELED) {
+ return;
+ }
- Mutex::Locker locker(m_lock);
- auto it = m_image_replayers.find(image_id);
- if (it == m_image_replayers.end()) {
- return;
- }
+ Mutex::Locker locker(m_lock);
+ auto it = m_image_replayers.find(global_image_id);
+ if (it == m_image_replayers.end()) {
+ return;
+ }
- auto &image_replayer = it->second;
- if (r >= 0) {
- image_replayer->start();
- } else {
- start_image_replayer(image_replayer, image_id, image_name);
- }
- }
- );
+ auto &image_replayer = it->second;
+ if (r >= 0) {
+ image_replayer->start();
+ } else {
+ start_image_replayer(image_replayer);
+ }
+ }
+ );
- m_image_deleter->wait_for_scheduled_deletion(
- m_local_pool_id, image_replayer->get_global_image_id(), ctx, false);
- }
+ m_image_deleter->wait_for_scheduled_deletion(
+ m_local_pool_id, image_replayer->get_global_image_id(), ctx, false);
}
bool Replayer::stop_image_replayer(unique_ptr<ImageReplayer<> > &image_replayer)
m_local_rados,
image_replayer->get_local_pool_id(),
image_replayer->get_local_image_id(),
- image_replayer->get_local_image_name(),
image_replayer->get_global_image_id());
}
return true;
m_local_rados,
image_replayer->get_local_pool_id(),
image_replayer->get_local_image_id(),
- image_replayer->get_local_image_name(),
image_replayer->get_global_image_id());
}
}
void init_local_mirroring_images();
void set_sources(const ImageIds &image_ids);
- void start_image_replayer(unique_ptr<ImageReplayer<> > &image_replayer,
- const std::string &image_id,
- const boost::optional<std::string>& image_name);
+ void start_image_replayer(unique_ptr<ImageReplayer<> > &image_replayer);
bool stop_image_replayer(unique_ptr<ImageReplayer<> > &image_replayer);
int init_rados(const std::string &cluster_name, const std::string &client_name,
std::string m_asok_hook_name;
ReplayerAdminSocketHook *m_asok_hook;
- struct InitImageInfo {
- std::string global_id;
- std::string id;
- std::string name;
-
- InitImageInfo(const std::string& global_id, const std::string &id = "",
- const std::string &name = "")
- : global_id(global_id), id(id), name(name) {
- }
-
- inline bool operator==(const InitImageInfo &rhs) const {
- return (global_id == rhs.global_id && id == rhs.id && name == rhs.name);
- }
- inline bool operator<(const InitImageInfo &rhs) const {
- return global_id < rhs.global_id;
- }
- };
-
- std::set<InitImageInfo> m_init_images;
+ std::set<ImageId> m_init_image_ids;
class ReplayerThread : public Thread {
Replayer *m_replayer;