mock_remote_image_ctx));
}
+TEST_F(TestMockImageReplayerSnapshotReplayer, ImageNameUpdated) {
+ librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
+ librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
+
+ MockThreads mock_threads(m_threads);
+ expect_work_queue_repeatedly(mock_threads);
+
+ MockReplayerListener mock_replayer_listener;
+ expect_notification(mock_threads, mock_replayer_listener);
+
+ InSequence seq;
+
+ MockInstanceWatcher mock_instance_watcher;
+ MockImageMeta mock_image_meta;
+ MockStateBuilder mock_state_builder(mock_local_image_ctx,
+ mock_remote_image_ctx,
+ mock_image_meta);
+ MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
+ "local mirror uuid", &m_pool_meta_cache,
+ &mock_state_builder, &mock_replayer_listener};
+ m_pool_meta_cache.set_remote_pool_meta(
+ m_remote_io_ctx.get_id(),
+ {"remote mirror uuid", "remote mirror peer uuid"});
+
+ librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
+ ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
+ mock_local_image_ctx,
+ mock_remote_image_ctx,
+ mock_replayer_listener,
+ mock_image_meta,
+ &update_watch_ctx));
+
+ // change the name of the image
+ mock_local_image_ctx.name = "NEW NAME";
+
+ // idle
+ expect_load_image_meta(mock_image_meta, true, 0);
+
+ // wake-up replayer
+ update_watch_ctx->handle_notify();
+
+ // wait for sync to complete and expect replay complete
+ ASSERT_EQ(0, wait_for_notification(2));
+ auto image_spec = image_replayer::util::compute_image_spec(m_local_io_ctx,
+ "NEW NAME");
+ ASSERT_EQ(image_spec, mock_replayer.get_image_spec());
+ ASSERT_FALSE(mock_replayer.is_replaying());
+
+ // shut down
+ ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
+ mock_local_image_ctx,
+ mock_remote_image_ctx));
+}
+
} // namespace snapshot
} // namespace image_replayer
} // namespace mirror
#include <iostream>
#include <string>
-PerfCounters *g_perf_counters = nullptr;
+PerfCounters *g_journal_perf_counters = nullptr;
+PerfCounters *g_snapshot_perf_counters = nullptr;
extern void register_test_cluster_watcher();
extern void register_test_image_policy();
#define dout_prefix *_dout << "rbd::mirror::" << *this << " " \
<< __func__ << ": "
-extern PerfCounters *g_perf_counters;
-
namespace rbd {
namespace mirror {
// Performance counters
enum {
- l_rbd_mirror_first = 27000,
+ l_rbd_mirror_journal_first = 27000,
l_rbd_mirror_replay,
l_rbd_mirror_replay_bytes,
l_rbd_mirror_replay_latency,
- l_rbd_mirror_last,
+ l_rbd_mirror_journal_last,
+ l_rbd_mirror_snapshot_first,
+ l_rbd_mirror_snapshot_replay_snapshots,
+ l_rbd_mirror_snapshot_replay_snapshots_time,
+ l_rbd_mirror_snapshot_replay_bytes,
+ l_rbd_mirror_snapshot_last,
};
typedef std::shared_ptr<librados::Rados> RadosRef;
#define dout_prefix *_dout << "rbd::mirror::image_replayer::journal::" \
<< "Replayer: " << this << " " << __func__ << ": "
-extern PerfCounters *g_perf_counters;
+extern PerfCounters *g_journal_perf_counters;
namespace rbd {
namespace mirror {
}
auto latency = ceph_clock_now() - replay_start_time;
- if (g_perf_counters) {
- g_perf_counters->inc(l_rbd_mirror_replay);
- g_perf_counters->inc(l_rbd_mirror_replay_bytes, replay_bytes);
- g_perf_counters->tinc(l_rbd_mirror_replay_latency, latency);
+ if (g_journal_perf_counters) {
+ g_journal_perf_counters->inc(l_rbd_mirror_replay);
+ g_journal_perf_counters->inc(l_rbd_mirror_replay_bytes, replay_bytes);
+ g_journal_perf_counters->tinc(l_rbd_mirror_replay_latency, latency);
}
auto ctx = new LambdaContext(
auto cct = static_cast<CephContext *>(m_state_builder->local_image_ctx->cct);
auto prio = cct->_conf.get_val<int64_t>("rbd_mirror_image_perf_stats_prio");
PerfCountersBuilder plb(g_ceph_context, "rbd_mirror_image_" + m_image_spec,
- l_rbd_mirror_first, l_rbd_mirror_last);
+ l_rbd_mirror_journal_first, l_rbd_mirror_journal_last);
plb.add_u64_counter(l_rbd_mirror_replay, "replay", "Replays", "r", prio);
plb.add_u64_counter(l_rbd_mirror_replay_bytes, "replay_bytes",
"Replayed data", "rb", prio, unit_t(UNIT_BYTES));
#define dout_prefix *_dout << "rbd::mirror::image_replayer::snapshot::" \
<< "Replayer: " << this << " " << __func__ << ": "
-extern PerfCounters *g_perf_counters;
+extern PerfCounters *g_snapshot_perf_counters;
namespace rbd {
namespace mirror {
template <typename I>
Replayer<I>::~Replayer() {
dout(10) << dendl;
+
+ {
+ std::unique_lock locker{m_lock};
+ unregister_perf_counters();
+ }
+
ceph_assert(m_state == STATE_COMPLETE);
ceph_assert(m_update_watch_ctx == nullptr);
ceph_assert(m_deep_copy_handler == nullptr);
m_remote_mirror_peer_uuid = remote_pool_meta.mirror_peer_uuid;
dout(10) << "remote_mirror_peer_uuid=" << m_remote_mirror_peer_uuid << dendl;
+ {
+ auto local_image_ctx = m_state_builder->local_image_ctx;
+ std::shared_lock image_locker{local_image_ctx->image_lock};
+ m_image_spec = image_replayer::util::compute_image_spec(
+ local_image_ctx->md_ctx, local_image_ctx->name);
+ }
+
+ {
+ std::unique_lock locker{m_lock};
+ register_perf_counters();
+ }
+
ceph_assert(m_on_init_shutdown == nullptr);
m_on_init_shutdown = on_finish;
m_image_updated = false;
}
+ bool update_status = false;
+ {
+ auto local_image_ctx = m_state_builder->local_image_ctx;
+ std::shared_lock image_locker{local_image_ctx->image_lock};
+ auto image_spec = image_replayer::util::compute_image_spec(
+ local_image_ctx->md_ctx, local_image_ctx->name);
+ if (m_image_spec != image_spec) {
+ m_image_spec = image_spec;
+ update_status = true;
+ }
+ }
+ if (update_status) {
+ std::unique_lock locker{m_lock};
+ unregister_perf_counters();
+ register_perf_counters();
+ notify_status_updated();
+ }
+
ceph_assert(m_state_builder->local_image_meta != nullptr);
auto ctx = create_context_callback<
Replayer<I>, &Replayer<I>::handle_load_local_image_meta>(this);
<< "snap_seqs=" << m_local_mirror_snap_ns.snap_seqs << dendl;
m_snapshot_bytes = 0;
+ m_snapshot_replay_start = ceph_clock_now();
m_deep_copy_handler = new DeepCopyHandler(this);
auto ctx = create_context_callback<
Replayer<I>, &Replayer<I>::handle_copy_image>(this);
{
std::unique_lock locker{m_lock};
m_bytes_per_snapshot(m_snapshot_bytes);
+ auto time = ceph_clock_now() - m_snapshot_replay_start;
+ if (g_snapshot_perf_counters) {
+ g_snapshot_perf_counters->inc(l_rbd_mirror_snapshot_replay_bytes,
+ m_snapshot_bytes);
+ g_snapshot_perf_counters->inc(l_rbd_mirror_snapshot_replay_snapshots);
+ g_snapshot_perf_counters->tinc(
+ l_rbd_mirror_snapshot_replay_snapshots_time, time);
+ }
+ if (m_perf_counters) {
+ m_perf_counters->inc(l_rbd_mirror_snapshot_replay_bytes, m_snapshot_bytes);
+ m_perf_counters->inc(l_rbd_mirror_snapshot_replay_snapshots);
+ m_perf_counters->tinc(l_rbd_mirror_snapshot_replay_snapshots_time, time);
+ }
m_snapshot_bytes = 0;
}
return false;
}
+template <typename I>
+void Replayer<I>::register_perf_counters() {
+ dout(5) << dendl;
+
+ ceph_assert(ceph_mutex_is_locked_by_me(m_lock));
+ ceph_assert(m_perf_counters == nullptr);
+
+ auto cct = static_cast<CephContext *>(m_state_builder->local_image_ctx->cct);
+ auto prio = cct->_conf.get_val<int64_t>("rbd_mirror_image_perf_stats_prio");
+ PerfCountersBuilder plb(g_ceph_context,
+ "rbd_mirror_snapshot_image_" + m_image_spec,
+ l_rbd_mirror_snapshot_first,
+ l_rbd_mirror_snapshot_last);
+ plb.add_u64_counter(l_rbd_mirror_snapshot_replay_snapshots,
+ "snapshots", "Snapshots", "r", prio);
+ plb.add_time_avg(l_rbd_mirror_snapshot_replay_snapshots_time,
+ "snapshots_time", "Snapshots time", "rl", prio);
+ plb.add_u64_counter(l_rbd_mirror_snapshot_replay_bytes, "replay_bytes",
+ "Replayed data", "rb", prio, unit_t(UNIT_BYTES));
+ m_perf_counters = plb.create_perf_counters();
+ g_ceph_context->get_perfcounters_collection()->add(m_perf_counters);
+}
+
+template <typename I>
+void Replayer<I>::unregister_perf_counters() {
+ dout(5) << dendl;
+ ceph_assert(ceph_mutex_is_locked_by_me(m_lock));
+
+ PerfCounters *perf_counters = nullptr;
+ std::swap(perf_counters, m_perf_counters);
+
+ if (perf_counters != nullptr) {
+ g_ceph_context->get_perfcounters_collection()->remove(perf_counters);
+ delete perf_counters;
+ }
+}
+
} // namespace snapshot
} // namespace image_replayer
} // namespace mirror
return m_error_description;
}
+ std::string get_image_spec() const {
+ std::unique_lock locker(m_lock);
+ return m_image_spec;
+ }
+
private:
/**
* @verbatim
State m_state = STATE_INIT;
+ std::string m_image_spec;
Context* m_on_init_shutdown = nullptr;
bool m_resync_requested = false;
uint64_t, boost::accumulators::stats<
boost::accumulators::tag::rolling_mean>> m_bytes_per_snapshot{
boost::accumulators::tag::rolling_window::window_size = 2};
+ utime_t m_snapshot_replay_start;
uint32_t m_pending_snapshots = 0;
bool m_updating_sync_point = false;
bool m_sync_in_progress = false;
+ PerfCounters *m_perf_counters = nullptr;
+
void load_local_image_meta();
void handle_load_local_image_meta(int r);
bool is_replay_interrupted();
bool is_replay_interrupted(std::unique_lock<ceph::mutex>* lock);
+ void register_perf_counters();
+ void unregister_perf_counters();
};
} // namespace snapshot
#include <vector>
rbd::mirror::Mirror *mirror = nullptr;
-PerfCounters *g_perf_counters = nullptr;
+PerfCounters *g_journal_perf_counters = nullptr;
+PerfCounters *g_snapshot_perf_counters = nullptr;
void usage() {
std::cout << "usage: rbd-mirror [options...]" << std::endl;
auto prio =
g_ceph_context->_conf.get_val<int64_t>("rbd_mirror_perf_stats_prio");
- PerfCountersBuilder plb(g_ceph_context, "rbd_mirror",
- rbd::mirror::l_rbd_mirror_first,
- rbd::mirror::l_rbd_mirror_last);
- plb.add_u64_counter(rbd::mirror::l_rbd_mirror_replay, "replay", "Replays",
- "r", prio);
- plb.add_u64_counter(rbd::mirror::l_rbd_mirror_replay_bytes, "replay_bytes",
- "Replayed data", "rb", prio, unit_t(UNIT_BYTES));
- plb.add_time_avg(rbd::mirror::l_rbd_mirror_replay_latency, "replay_latency",
- "Replay latency", "rl", prio);
- g_perf_counters = plb.create_perf_counters();
- g_ceph_context->get_perfcounters_collection()->add(g_perf_counters);
+ {
+ PerfCountersBuilder plb(g_ceph_context, "rbd_mirror",
+ rbd::mirror::l_rbd_mirror_journal_first,
+ rbd::mirror::l_rbd_mirror_journal_last);
+ plb.add_u64_counter(rbd::mirror::l_rbd_mirror_replay, "replay", "Replays",
+ "r", prio);
+ plb.add_u64_counter(rbd::mirror::l_rbd_mirror_replay_bytes, "replay_bytes",
+ "Replayed data", "rb", prio, unit_t(UNIT_BYTES));
+ plb.add_time_avg(rbd::mirror::l_rbd_mirror_replay_latency, "replay_latency",
+ "Replay latency", "rl", prio);
+ g_journal_perf_counters = plb.create_perf_counters();
+ }
+ {
+ PerfCountersBuilder plb(g_ceph_context, "rbd_mirror_snapshot",
+ rbd::mirror::l_rbd_mirror_snapshot_first,
+ rbd::mirror::l_rbd_mirror_snapshot_last);
+ plb.add_u64_counter(rbd::mirror::l_rbd_mirror_snapshot_replay_snapshots,
+ "snapshots", "Snapshots", "r", prio);
+ plb.add_time_avg(rbd::mirror::l_rbd_mirror_snapshot_replay_snapshots_time,
+ "snapshots_time", "Snapshots time", "rl", prio);
+ plb.add_u64_counter(rbd::mirror::l_rbd_mirror_snapshot_replay_bytes,
+ "replay_bytes", "Replayed data", "rb", prio,
+ unit_t(UNIT_BYTES));
+ g_snapshot_perf_counters = plb.create_perf_counters();
+ }
+ g_ceph_context->get_perfcounters_collection()->add(g_journal_perf_counters);
+ g_ceph_context->get_perfcounters_collection()->add(g_snapshot_perf_counters);
mirror = new rbd::mirror::Mirror(g_ceph_context, cmd_args);
int r = mirror->init();
unregister_async_signal_handler(SIGTERM, handle_signal);
shutdown_async_signal_handler();
- g_ceph_context->get_perfcounters_collection()->remove(g_perf_counters);
+ g_ceph_context->get_perfcounters_collection()->remove(g_journal_perf_counters);
+ g_ceph_context->get_perfcounters_collection()->remove(g_snapshot_perf_counters);
delete mirror;
- delete g_perf_counters;
+ delete g_journal_perf_counters;
+ delete g_snapshot_perf_counters;
return r < 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}