local->cct()));
replayer = new rbd::mirror::ImageReplayer<>(threads, local, remote, client_id,
local_pool_id, remote_pool_id,
- remote_image_id);
+ remote_image_id,
+ "global image id");
replayer->start(&start_cond, &bootstap_params);
r = start_cond.wait();
m_replayer = new ImageReplayerT(m_threads,
rbd::mirror::RadosRef(new librados::Rados(m_local_ioctx)),
rbd::mirror::RadosRef(new librados::Rados(m_remote_ioctx)),
- m_client_id, m_local_ioctx.get_id(), m_remote_pool_id, m_remote_image_id);
+ m_client_id, m_local_ioctx.get_id(), m_remote_pool_id, m_remote_image_id,
+ "global image id");
}
void start(rbd::mirror::ImageReplayer<>::BootstrapParams *bootstap_params =
ImageReplayer(rbd::mirror::Threads *threads,
rbd::mirror::RadosRef local, rbd::mirror::RadosRef remote,
const std::string &client_id, int64_t local_pool_id,
- int64_t remote_pool_id, const std::string &remote_image_id)
+ int64_t remote_pool_id, const std::string &remote_image_id,
+ const std::string &global_image_id)
: rbd::mirror::ImageReplayer<>(threads, local, remote, client_id,
local_pool_id, remote_pool_id,
- remote_image_id)
+ remote_image_id, global_image_id)
{}
void set_error(const std::string &state, int r) {
librbd::RBD rbd;
rbd.open(ioctx, image, name.c_str());
image.mirror_image_enable();
+
+ librbd::mirror_image_info_t mirror_image_info;
+ ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image_info,
+ sizeof(mirror_image_info)));
image.close();
- m_mirrored_images[ioctx.get_id()].insert(get_image_id(&ioctx, name));
+
+ m_mirrored_images[ioctx.get_id()].insert(PoolWatcher::ImageIds(
+ get_image_id(&ioctx, name), mirror_image_info.global_id));
}
if (image_name != nullptr)
*image_name = name;
librbd::RBD rbd;
rbd.open(cioctx, image, name.c_str());
image.mirror_image_enable();
+
+ librbd::mirror_image_info_t mirror_image_info;
+ ASSERT_EQ(0, image.mirror_image_get_info(&mirror_image_info,
+ sizeof(mirror_image_info)));
image.close();
- m_mirrored_images[cioctx.get_id()].insert(get_image_id(&cioctx, name));
+
+ m_mirrored_images[cioctx.get_id()].insert(PoolWatcher::ImageIds(
+ get_image_id(&cioctx, name), mirror_image_info.global_id));
}
if (image_name != nullptr)
*image_name = name;
unique_ptr<PoolWatcher> m_pool_watcher;
set<string> m_pools;
- std::map<int64_t, std::set<std::string> > m_mirrored_images;
+ PoolWatcher::PoolImageIds m_mirrored_images;
uint64_t m_image_number;
uint64_t m_snap_number;
librbd::MockImageReplayerImageCtx **local_image_ctx,
const std::string &local_image_name,
const std::string &remote_image_id,
+ const std::string &global_image_id,
ContextWQ *work_queue, SafeTimer *timer,
Mutex *timer_lock,
const std::string &mirror_uuid,
const std::string &mirror_uuid,
int64_t local_pool_id,
int64_t remote_pool_id,
- const std::string &remote_image_id) :
+ const std::string &remote_image_id,
+ const std::string &global_image_id) :
m_threads(threads),
m_local(local),
m_remote(remote),
m_remote_pool_id(remote_pool_id),
m_local_pool_id(local_pool_id),
m_remote_image_id(remote_image_id),
+ m_global_image_id(global_image_id),
m_name(stringify(remote_pool_id) + "/" + remote_image_id),
m_lock("rbd::mirror::ImageReplayer " + stringify(remote_pool_id) + " " +
remote_image_id),
ImageReplayer, &ImageReplayer<I>::handle_bootstrap>(this);
BootstrapRequest<I> *request = BootstrapRequest<I>::create(
m_local_ioctx, m_remote_ioctx, &m_local_image_ctx,
- m_local_image_name, m_remote_image_id, m_threads->work_queue,
- m_threads->timer, &m_threads->timer_lock, m_mirror_uuid, m_remote_journaler,
- &m_client_meta, ctx);
+ m_local_image_name, m_remote_image_id, m_global_image_id,
+ m_threads->work_queue, m_threads->timer, &m_threads->timer_lock,
+ m_mirror_uuid, m_remote_journaler, &m_client_meta, ctx);
request->send();
}
ImageReplayer(Threads *threads, RadosRef local, RadosRef remote,
const std::string &mirror_uuid, int64_t local_pool_id,
- int64_t remote_pool_id, const std::string &remote_image_id);
+ int64_t remote_pool_id, const std::string &remote_image_id,
+ const std::string &global_image_id);
virtual ~ImageReplayer();
ImageReplayer(const ImageReplayer&) = delete;
ImageReplayer& operator=(const ImageReplayer&) = delete;
RadosRef m_local, m_remote;
std::string m_mirror_uuid;
int64_t m_remote_pool_id, m_local_pool_id;
- std::string m_remote_image_id, m_local_image_id;
+ std::string m_remote_image_id, m_local_image_id, m_global_image_id;
std::string m_local_image_name;
std::string m_name;
Mutex m_lock;
#define dout_prefix *_dout << "rbd-mirror: PoolWatcher::" << __func__ << ": "
using std::list;
-using std::map;
-using std::set;
using std::string;
using std::unique_ptr;
using std::vector;
m_timer.shutdown();
}
-const map<int64_t, set<string> >& PoolWatcher::get_images() const
+const PoolWatcher::PoolImageIds& PoolWatcher::get_images() const
{
assert(m_lock.is_locked());
return m_images;
void PoolWatcher::refresh_images(bool reschedule)
{
dout(20) << "enter" << dendl;
- map<int64_t, set<string> > images;
+ PoolImageIds images;
list<pair<int64_t, string> > pools;
int r = m_cluster->pool_list2(pools);
if (r < 0) {
continue;
}
- std::set<std::string> image_ids;
+ std::set<ImageIds> image_ids;
std::string last_read = "";
int max_read = 1024;
do {
continue;
}
for (auto it = mirror_images.begin(); it != mirror_images.end(); ++it) {
- image_ids.insert(it->first);
+ image_ids.insert(ImageIds(it->first, it->second));
}
if (!mirror_images.empty()) {
last_read = mirror_images.rbegin()->first;
*/
class PoolWatcher {
public:
+ struct ImageIds {
+ std::string id;
+ std::string global_id;
+
+ ImageIds(const std::string &id, const std::string &global_id = "")
+ : id(id), global_id(global_id) {
+ }
+
+ inline bool operator==(const ImageIds &rhs) const {
+ return (id == rhs.id && global_id == rhs.global_id);
+ }
+ inline bool operator<(const ImageIds &rhs) const {
+ return id < rhs.id;
+ }
+ };
+ typedef std::map<int64_t, std::set<ImageIds> > PoolImageIds;
+
PoolWatcher(RadosRef cluster, double interval_seconds,
Mutex &lock, Cond &cond);
~PoolWatcher();
PoolWatcher(const PoolWatcher&) = delete;
PoolWatcher& operator=(const PoolWatcher&) = delete;
- const std::map<int64_t, std::set<std::string> >& get_images() const;
+
+ const PoolImageIds& get_images() const;
void refresh_images(bool reschedule=true);
private:
RadosRef m_cluster;
SafeTimer m_timer;
double m_interval;
- // pool id -> image id
- std::map<int64_t, std::set<std::string> > m_images;
+
+ PoolImageIds m_images;
};
} // namespace mirror
}
// Stopping
- map<int64_t, set<string> > empty_sources;
+ PoolImageIds empty_sources;
while (true) {
Mutex::Locker l(m_lock);
set_sources(empty_sources);
}
}
-void Replayer::set_sources(const map<int64_t, set<string> > &images)
+void Replayer::set_sources(const PoolImageIds &pool_image_ids)
{
dout(20) << "enter" << dendl;
for (auto it = m_images.begin(); it != m_images.end();) {
int64_t pool_id = it->first;
auto &pool_images = it->second;
- if (images.find(pool_id) == images.end()) {
+
+ // pool has no mirrored images
+ if (pool_image_ids.find(pool_id) == pool_image_ids.end()) {
for (auto images_it = pool_images.begin();
images_it != pool_images.end();) {
if (stop_image_replayer(images_it->second)) {
}
continue;
}
+
+ // shut down replayers for non-mirrored images
for (auto images_it = pool_images.begin();
images_it != pool_images.end();) {
- if (images.at(pool_id).find(images_it->first) ==
- images.at(pool_id).end()) {
+ auto &image_ids = pool_image_ids.at(pool_id);
+ if (image_ids.find(ImageIds(images_it->first)) == image_ids.end()) {
if (stop_image_replayer(images_it->second)) {
pool_images.erase(images_it++);
}
++it;
}
- for (const auto &kv : images) {
+ // (re)start new image replayers
+ for (const auto &kv : pool_image_ids) {
int64_t pool_id = kv.first;
// TODO: clean up once remote peer -> image replayer refactored
// create entry for pool if it doesn't exist
auto &pool_replayers = m_images[pool_id];
for (const auto &image_id : kv.second) {
- auto it = pool_replayers.find(image_id);
+ auto it = pool_replayers.find(image_id.id);
if (it == pool_replayers.end()) {
unique_ptr<ImageReplayer<> > image_replayer(new ImageReplayer<>(
m_threads, m_local, m_remote, mirror_uuid, local_ioctx.get_id(),
- pool_id, image_id));
+ pool_id, image_id.id, image_id.global_id));
it = pool_replayers.insert(
- std::make_pair(image_id, std::move(image_replayer))).first;
+ std::make_pair(image_id.id, std::move(image_replayer))).first;
}
start_image_replayer(it->second);
}
void flush();
private:
- void set_sources(const std::map<int64_t, std::set<std::string> > &images);
+ typedef PoolWatcher::ImageIds ImageIds;
+ typedef PoolWatcher::PoolImageIds PoolImageIds;
+
+ void set_sources(const PoolImageIds &pool_image_ids);
void start_image_replayer(unique_ptr<ImageReplayer<> > &image_replayer);
bool stop_image_replayer(unique_ptr<ImageReplayer<> > &image_replayer);
template <typename I>
struct C_CreateImage : public Context {
librados::IoCtx &local_io_ctx;
+ std::string global_image_id;
std::string local_image_name;
I *remote_image_ctx;
Context *on_finish;
C_CreateImage(librados::IoCtx &local_io_ctx,
+ const std::string &global_image_id,
const std::string &local_image_name, I *remote_image_ctx,
Context *on_finish)
- : local_io_ctx(local_io_ctx), local_image_name(local_image_name),
- remote_image_ctx(remote_image_ctx), on_finish(on_finish) {
+ : local_io_ctx(local_io_ctx), global_image_id(global_image_id),
+ local_image_name(local_image_name), remote_image_ctx(remote_image_ctx),
+ on_finish(on_finish) {
}
virtual void finish(int r) override {
remote_image_ctx->stripe_unit,
remote_image_ctx->stripe_count,
journal_order, journal_splay_width, journal_pool,
- "global-image-id");
+ global_image_id);
on_finish->complete(r);
}
};
I **local_image_ctx,
const std::string &local_image_name,
const std::string &remote_image_id,
+ const std::string &global_image_id,
ContextWQ *work_queue, SafeTimer *timer,
Mutex *timer_lock,
const std::string &mirror_uuid,
Context *on_finish)
: m_local_io_ctx(local_io_ctx), m_remote_io_ctx(remote_io_ctx),
m_local_image_ctx(local_image_ctx), m_local_image_name(local_image_name),
- m_remote_image_id(remote_image_id), m_work_queue(work_queue),
- m_timer(timer), m_timer_lock(timer_lock), m_mirror_uuid(mirror_uuid),
- m_journaler(journaler), m_client_meta(client_meta), m_on_finish(on_finish) {
+ m_remote_image_id(remote_image_id), m_global_image_id(global_image_id),
+ m_work_queue(work_queue), m_timer(timer), m_timer_lock(timer_lock),
+ m_mirror_uuid(mirror_uuid), m_journaler(journaler),
+ m_client_meta(client_meta), m_on_finish(on_finish) {
}
template <typename I>
Context *ctx = create_context_callback<
BootstrapRequest<I>, &BootstrapRequest<I>::handle_create_local_image>(
this);
- m_work_queue->queue(new C_CreateImage<I>(m_local_io_ctx, m_local_image_name,
+ m_work_queue->queue(new C_CreateImage<I>(m_local_io_ctx, m_global_image_id,
+ m_local_image_name,
m_remote_image_ctx, ctx), 0);
}
ImageCtxT **local_image_ctx,
const std::string &local_image_name,
const std::string &remote_image_id,
+ const std::string &global_image_id,
ContextWQ *work_queue, SafeTimer *timer,
Mutex *timer_lock,
const std::string &mirror_uuid,
MirrorPeerClientMeta *client_meta,
Context *on_finish) {
return new BootstrapRequest(local_io_ctx, remote_io_ctx, local_image_ctx,
- local_image_name, remote_image_id, work_queue,
- timer, timer_lock, mirror_uuid, journaler,
- client_meta, on_finish);
+ local_image_name, remote_image_id,
+ global_image_id, work_queue, timer, timer_lock,
+ mirror_uuid, journaler, client_meta, on_finish);
}
BootstrapRequest(librados::IoCtx &local_io_ctx,
librados::IoCtx &remote_io_ctx,
ImageCtxT **local_image_ctx,
const std::string &local_image_name,
- const std::string &remote_image_id, ContextWQ *work_queue,
+ const std::string &remote_image_id,
+ const std::string &global_image_id, ContextWQ *work_queue,
SafeTimer *timer, Mutex *timer_lock,
const std::string &mirror_uuid, Journaler *journaler,
MirrorPeerClientMeta *client_meta, Context *on_finish);
std::string m_local_image_name;
std::string m_local_image_id;
std::string m_remote_image_id;
+ std::string m_global_image_id;
ContextWQ *m_work_queue;
SafeTimer *m_timer;
Mutex *m_timer_lock;