return new ObjectMap(*this, snap_id);
}
- Journal *ImageCtx::create_journal() {
- return new Journal(*this);
+ Journal<ImageCtx> *ImageCtx::create_journal() {
+ return new Journal<ImageCtx>(*this);
}
}
template <typename> class ExclusiveLock;
template <typename> class ImageState;
class ImageWatcher;
- class Journal;
+ template <typename> class Journal;
class LibrbdAdminSocketHook;
class ObjectMap;
std::string snap_name;
IoCtx data_ctx, md_ctx;
ImageWatcher *image_watcher;
- Journal *journal;
+ Journal<ImageCtx> *journal;
/**
* Lock ordering:
void apply_metadata_confs();
ObjectMap *create_object_map(uint64_t snap_id);
- Journal *create_journal();
+ Journal<ImageCtx> *create_journal();
void clear_pending_completions();
};
} // anonymous namespace
-Journal::Journal(ImageCtx &image_ctx)
+template <typename I>
+std::ostream &operator<<(std::ostream &os,
+ const typename Journal<I>::State &state) {
+ switch (state) {
+ case Journal<I>::STATE_UNINITIALIZED:
+ os << "Uninitialized";
+ break;
+ case Journal<I>::STATE_INITIALIZING:
+ os << "Initializing";
+ break;
+ case Journal<I>::STATE_REPLAYING:
+ os << "Replaying";
+ break;
+ case Journal<I>::STATE_RESTARTING_REPLAY:
+ os << "RestartingReplay";
+ break;
+ case Journal<I>::STATE_READY:
+ os << "Ready";
+ break;
+ case Journal<I>::STATE_STOPPING:
+ os << "Stopping";
+ break;
+ case Journal<I>::STATE_CLOSING:
+ os << "Closing";
+ break;
+ case Journal<I>::STATE_CLOSED:
+ os << "Closed";
+ break;
+ default:
+ os << "Unknown (" << static_cast<uint32_t>(state) << ")";
+ break;
+ }
+ return os;
+}
+
+template <typename I>
+Journal<I>::Journal(I &image_ctx)
: m_image_ctx(image_ctx), m_journaler(NULL),
- m_lock("Journal::m_lock"), m_state(STATE_UNINITIALIZED),
+ m_lock("Journal<I>::m_lock"), m_state(STATE_UNINITIALIZED),
m_error_result(0), m_replay_handler(this), m_close_pending(false),
- m_event_lock("Journal::m_event_lock"), m_event_tid(0),
+ m_event_lock("Journal<I>::m_event_lock"), m_event_tid(0),
m_blocking_writes(false), m_journal_replay(NULL) {
ldout(m_image_ctx.cct, 5) << this << ": ictx=" << &m_image_ctx << dendl;
}
-Journal::~Journal() {
+template <typename I>
+Journal<I>::~Journal() {
assert(m_state == STATE_UNINITIALIZED || m_state == STATE_CLOSED);
assert(m_journaler == NULL);
assert(m_journal_replay == NULL);
assert(m_wait_for_state_contexts.empty());
}
-bool Journal::is_journal_supported(ImageCtx &image_ctx) {
+template <typename I>
+bool Journal<I>::is_journal_supported(I &image_ctx) {
assert(image_ctx.snap_lock.is_locked());
return ((image_ctx.features & RBD_FEATURE_JOURNALING) &&
!image_ctx.read_only && image_ctx.snap_id == CEPH_NOSNAP);
}
-int Journal::create(librados::IoCtx &io_ctx, const std::string &image_id,
- uint8_t order, uint8_t splay_width,
- const std::string &object_pool) {
+template <typename I>
+int Journal<I>::create(librados::IoCtx &io_ctx, const std::string &image_id,
+ uint8_t order, uint8_t splay_width,
+ const std::string &object_pool) {
CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
ldout(cct, 5) << __func__ << ": image=" << image_id << dendl;
return 0;
}
-int Journal::remove(librados::IoCtx &io_ctx, const std::string &image_id) {
+template <typename I>
+int Journal<I>::remove(librados::IoCtx &io_ctx, const std::string &image_id) {
CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
ldout(cct, 5) << __func__ << ": image=" << image_id << dendl;
return 0;
}
-int Journal::reset(librados::IoCtx &io_ctx, const std::string &image_id) {
+template <typename I>
+int Journal<I>::reset(librados::IoCtx &io_ctx, const std::string &image_id) {
CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
ldout(cct, 5) << __func__ << ": image=" << image_id << dendl;
return 0;
}
-bool Journal::is_journal_ready() const {
+template <typename I>
+bool Journal<I>::is_journal_ready() const {
Mutex::Locker locker(m_lock);
return (m_state == STATE_READY);
}
-bool Journal::is_journal_replaying() const {
+template <typename I>
+bool Journal<I>::is_journal_replaying() const {
Mutex::Locker locker(m_lock);
return (m_state == STATE_REPLAYING);
}
-void Journal::wait_for_journal_ready(Context *on_ready) {
+template <typename I>
+void Journal<I>::wait_for_journal_ready(Context *on_ready) {
on_ready = util::create_async_context_callback(m_image_ctx, on_ready);
Mutex::Locker locker(m_lock);
}
}
-void Journal::open(Context *on_finish) {
+template <typename I>
+void Journal<I>::open(Context *on_finish) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << dendl;
create_journaler();
}
-void Journal::close(Context *on_finish) {
+template <typename I>
+void Journal<I>::close(Context *on_finish) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << dendl;
wait_for_steady_state(on_finish);
}
-uint64_t Journal::append_io_event(AioCompletion *aio_comp,
- const journal::EventEntry &event_entry,
- const AioObjectRequests &requests,
- uint64_t offset, size_t length,
- bool flush_entry) {
+template <typename I>
+uint64_t Journal<I>::append_io_event(AioCompletion *aio_comp,
+ const journal::EventEntry &event_entry,
+ const AioObjectRequests &requests,
+ uint64_t offset, size_t length,
+ bool flush_entry) {
assert(m_image_ctx.owner_lock.is_locked());
bufferlist bl;
return tid;
}
-void Journal::commit_io_event(uint64_t tid, int r) {
+template <typename I>
+void Journal<I>::commit_io_event(uint64_t tid, int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": tid=" << tid << ", "
"r=" << r << dendl;
Mutex::Locker event_locker(m_event_lock);
- Events::iterator it = m_events.find(tid);
+ typename Events::iterator it = m_events.find(tid);
if (it == m_events.end()) {
return;
}
complete_event(it, r);
}
-void Journal::commit_io_event_extent(uint64_t tid, uint64_t offset,
- uint64_t length, int r) {
+template <typename I>
+void Journal<I>::commit_io_event_extent(uint64_t tid, uint64_t offset,
+ uint64_t length, int r) {
assert(length > 0);
CephContext *cct = m_image_ctx.cct;
<< "r=" << r << dendl;
Mutex::Locker event_locker(m_event_lock);
- Events::iterator it = m_events.find(tid);
+ typename Events::iterator it = m_events.find(tid);
if (it == m_events.end()) {
return;
}
complete_event(it, event.ret_val);
}
-uint64_t Journal::append_op_event(journal::EventEntry &event_entry) {
+template <typename I>
+uint64_t Journal<I>::append_op_event(journal::EventEntry &event_entry) {
assert(m_image_ctx.owner_lock.is_locked());
uint64_t tid;
return tid;
}
-void Journal::commit_op_event(uint64_t tid, int r) {
+template <typename I>
+void Journal<I>::commit_op_event(uint64_t tid, int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << this << " " << __func__ << ": tid=" << tid << dendl;
}
}
-void Journal::flush_event(uint64_t tid, Context *on_safe) {
+template <typename I>
+void Journal<I>::flush_event(uint64_t tid, Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": tid=" << tid << ", "
<< "on_safe=" << on_safe << dendl;
}
}
-void Journal::wait_event(uint64_t tid, Context *on_safe) {
+template <typename I>
+void Journal<I>::wait_event(uint64_t tid, Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": tid=" << tid << ", "
<< "on_safe=" << on_safe << dendl;
wait_event(m_lock, tid, on_safe);
}
-::journal::Future Journal::wait_event(Mutex &lock, uint64_t tid,
- Context *on_safe) {
+template <typename I>
+::journal::Future Journal<I>::wait_event(Mutex &lock, uint64_t tid,
+ Context *on_safe) {
assert(m_event_lock.is_locked());
CephContext *cct = m_image_ctx.cct;
- Events::iterator it = m_events.find(tid);
+ typename Events::iterator it = m_events.find(tid);
if (it == m_events.end() || it->second.safe) {
// journal entry already safe
ldout(cct, 20) << "journal entry already safe" << dendl;
return event.future;
}
-void Journal::create_journaler() {
+template <typename I>
+void Journal<I>::create_journaler() {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << dendl;
m_journaler->init(new C_InitJournal(this));
}
-void Journal::destroy_journaler(int r) {
+template <typename I>
+void Journal<I>::destroy_journaler(int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": r=" << r << dendl;
m_image_ctx.op_work_queue->queue(new C_DestroyJournaler(this), 0);
}
-void Journal::recreate_journaler(int r) {
+template <typename I>
+void Journal<I>::recreate_journaler(int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": r=" << r << dendl;
m_image_ctx.op_work_queue->queue(new C_DestroyJournaler(this), 0);
}
-void Journal::complete_event(Events::iterator it, int r) {
+template <typename I>
+void Journal<I>::complete_event(typename Events::iterator it, int r) {
assert(m_event_lock.is_locked());
assert(m_state == STATE_READY);
}
}
-void Journal::handle_initialized(int r) {
+template <typename I>
+void Journal<I>::handle_initialized(int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": r=" << r << dendl;
}
transition_state(STATE_REPLAYING, 0);
- m_journal_replay = new journal::Replay(m_image_ctx);
+ m_journal_replay = journal::Replay<I>::create(m_image_ctx);
m_journaler->start_replay(&m_replay_handler);
}
-void Journal::handle_replay_ready() {
+template <typename I>
+void Journal<I>::handle_replay_ready() {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << dendl;
}
}
-void Journal::handle_replay_complete(int r) {
+template <typename I>
+void Journal<I>::handle_replay_complete(int r) {
CephContext *cct = m_image_ctx.cct;
{
}
}
-void Journal::handle_recording_stopped(int r) {
+template <typename I>
+void Journal<I>::handle_recording_stopped(int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": r=" << r << dendl;
destroy_journaler(r);
}
-void Journal::handle_journal_destroyed(int r) {
+template <typename I>
+void Journal<I>::handle_journal_destroyed(int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": r=" << r << dendl;
transition_state(STATE_CLOSED, r);
}
-void Journal::handle_event_safe(int r, uint64_t tid) {
+template <typename I>
+void Journal<I>::handle_event_safe(int r, uint64_t tid) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": r=" << r << ", "
<< "tid=" << tid << dendl;
Contexts on_safe_contexts;
{
Mutex::Locker event_locker(m_event_lock);
- Events::iterator it = m_events.find(tid);
+ typename Events::iterator it = m_events.find(tid);
assert(it != m_events.end());
Event &event = it->second;
}
}
-void Journal::stop_recording() {
+template <typename I>
+void Journal<I>::stop_recording() {
assert(m_lock.is_locked());
assert(m_journaler != NULL);
m_image_ctx, new C_StopRecording(this)));
}
-void Journal::block_writes() {
+template <typename I>
+void Journal<I>::block_writes() {
assert(m_lock.is_locked());
if (!m_blocking_writes) {
m_blocking_writes = true;
}
}
-void Journal::unblock_writes() {
+template <typename I>
+void Journal<I>::unblock_writes() {
assert(m_lock.is_locked());
if (m_blocking_writes) {
m_blocking_writes = false;
}
}
-void Journal::transition_state(State state, int r) {
+template <typename I>
+void Journal<I>::transition_state(State state, int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": new state=" << state << dendl;
assert(m_lock.is_locked());
}
}
-bool Journal::is_steady_state() const {
+template <typename I>
+bool Journal<I>::is_steady_state() const {
assert(m_lock.is_locked());
switch (m_state) {
case STATE_READY:
return false;
}
-void Journal::wait_for_steady_state(Context *on_state) {
+template <typename I>
+void Journal<I>::wait_for_steady_state(Context *on_state) {
assert(m_lock.is_locked());
assert(!is_steady_state());
m_wait_for_state_contexts.push_back(on_state);
}
-std::ostream &operator<<(std::ostream &os, const Journal::State &state) {
- switch (state) {
- case Journal::STATE_UNINITIALIZED:
- os << "Uninitialized";
- break;
- case Journal::STATE_INITIALIZING:
- os << "Initializing";
- break;
- case Journal::STATE_REPLAYING:
- os << "Replaying";
- break;
- case Journal::STATE_RESTARTING_REPLAY:
- os << "RestartingReplay";
- break;
- case Journal::STATE_READY:
- os << "Ready";
- break;
- case Journal::STATE_STOPPING:
- os << "Stopping";
- break;
- case Journal::STATE_CLOSING:
- os << "Closing";
- break;
- case Journal::STATE_CLOSED:
- os << "Closed";
- break;
- default:
- os << "Unknown (" << static_cast<uint32_t>(state) << ")";
- break;
- }
- return os;
-}
-
} // namespace librbd
+
+template class librbd::Journal<librbd::ImageCtx>;
#include "journal/Future.h"
#include "journal/ReplayHandler.h"
#include <algorithm>
+#include <iosfwd>
#include <list>
#include <string>
namespace journal {
class EventEntry;
-class Replay;
+template <typename> class Replay;
}
+template <typename ImageCtxT = ImageCtx>
class Journal {
public:
- typedef std::list<AioObjectRequest *> AioObjectRequests;
-
- Journal(ImageCtx &image_ctx);
- ~Journal();
-
- static bool is_journal_supported(ImageCtx &image_ctx);
- static int create(librados::IoCtx &io_ctx, const std::string &image_id,
- uint8_t order, uint8_t splay_width,
- const std::string &object_pool);
- static int remove(librados::IoCtx &io_ctx, const std::string &image_id);
- static int reset(librados::IoCtx &io_ctx, const std::string &image_id);
-
- bool is_journal_ready() const;
- bool is_journal_replaying() const;
-
- void wait_for_journal_ready(Context *on_ready);
-
- void open(Context *on_finish);
- void close(Context *on_finish);
-
- uint64_t append_io_event(AioCompletion *aio_comp,
- const journal::EventEntry &event_entry,
- const AioObjectRequests &requests,
- uint64_t offset, size_t length,
- bool flush_entry);
- void commit_io_event(uint64_t tid, int r);
- void commit_io_event_extent(uint64_t tid, uint64_t offset, uint64_t length,
- int r);
-
- uint64_t append_op_event(journal::EventEntry &event_entry);
- void commit_op_event(uint64_t tid, int r);
-
- void flush_event(uint64_t tid, Context *on_safe);
- void wait_event(uint64_t tid, Context *on_safe);
-
-private:
- typedef std::list<Context *> Contexts;
- typedef interval_set<uint64_t> ExtentInterval;
-
/**
* @verbatim
*
STATE_CLOSED
};
+ typedef std::list<AioObjectRequest *> AioObjectRequests;
+
+ Journal(ImageCtxT &image_ctx);
+ ~Journal();
+
+ static bool is_journal_supported(ImageCtxT &image_ctx);
+ static int create(librados::IoCtx &io_ctx, const std::string &image_id,
+ uint8_t order, uint8_t splay_width,
+ const std::string &object_pool);
+ static int remove(librados::IoCtx &io_ctx, const std::string &image_id);
+ static int reset(librados::IoCtx &io_ctx, const std::string &image_id);
+
+ bool is_journal_ready() const;
+ bool is_journal_replaying() const;
+
+ void wait_for_journal_ready(Context *on_ready);
+
+ void open(Context *on_finish);
+ void close(Context *on_finish);
+
+ uint64_t append_io_event(AioCompletion *aio_comp,
+ const journal::EventEntry &event_entry,
+ const AioObjectRequests &requests,
+ uint64_t offset, size_t length,
+ bool flush_entry);
+ void commit_io_event(uint64_t tid, int r);
+ void commit_io_event_extent(uint64_t tid, uint64_t offset, uint64_t length,
+ int r);
+
+ uint64_t append_op_event(journal::EventEntry &event_entry);
+ void commit_op_event(uint64_t tid, int r);
+
+ void flush_event(uint64_t tid, Context *on_safe);
+ void wait_event(uint64_t tid, Context *on_safe);
+
+private:
+ typedef std::list<Context *> Contexts;
+ typedef interval_set<uint64_t> ExtentInterval;
+
struct Event {
::journal::Future future;
AioCompletion *aio_comp;
}
};
- ImageCtx &m_image_ctx;
+ ImageCtxT &m_image_ctx;
::journal::Journaler *m_journaler;
mutable Mutex m_lock;
bool m_blocking_writes;
- journal::Replay *m_journal_replay;
+ journal::Replay<ImageCtxT> *m_journal_replay;
::journal::Future wait_event(Mutex &lock, uint64_t tid, Context *on_safe);
void destroy_journaler(int r);
void recreate_journaler(int r);
- void complete_event(Events::iterator it, int r);
+ void complete_event(typename Events::iterator it, int r);
void handle_initialized(int r);
bool is_steady_state() const;
void wait_for_steady_state(Context *on_state);
-
- friend std::ostream &operator<<(std::ostream &os, const State &state);
};
} // namespace librbd
+extern template class librbd::Journal<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_JOURNAL_H
namespace librbd {
-class Journal;
+template <typename> class Journal;
namespace exclusive_lock {
namespace librbd {
class ImageCtx;
-class Journal;
+template <typename> class Journal;
namespace exclusive_lock {
klass, &klass::handle_v2_open_journal>(this);
// TODO need safe close
- m_journal = new Journal(m_image_ctx);
+ m_journal = m_image_ctx.create_journal();
m_journal->open(ctx);
return nullptr;
}
namespace librbd {
-template <typename> class ExclusiveLock;
class ImageCtx;
-class Journal;
-class ObjectMap;
namespace image {
goto err_remove_object_map;
}
- r = Journal::create(io_ctx, id, journal_order, journal_splay_width,
- journal_pool);
+ r = Journal<>::create(io_ctx, id, journal_order, journal_splay_width,
+ journal_pool);
if (r < 0) {
lderr(cct) << "error creating journal: " << cpp_strerror(r) << dendl;
goto err_remove_object_map;
}
features_mask |= RBD_FEATURE_EXCLUSIVE_LOCK;
- r = Journal::create(ictx->md_ctx, ictx->id, ictx->journal_order,
- ictx->journal_splay_width,
- ictx->journal_pool);
+ r = Journal<>::create(ictx->md_ctx, ictx->id, ictx->journal_order,
+ ictx->journal_splay_width,
+ ictx->journal_pool);
if (r < 0) {
lderr(cct) << "error creating image journal: " << cpp_strerror(r)
<< dendl;
disable_flags = RBD_FLAG_FAST_DIFF_INVALID;
}
if ((features & RBD_FEATURE_JOURNALING) != 0) {
- r = Journal::remove(ictx->md_ctx, ictx->id);
+ r = Journal<>::remove(ictx->md_ctx, ictx->id);
if (r < 0) {
lderr(cct) << "error removing image journal: " << cpp_strerror(r)
<< dendl;
}
}
if (!old_format) {
- r = Journal::remove(io_ctx, id);
+ r = Journal<>::remove(io_ctx, id);
if (r < 0 && r != -ENOENT) {
lderr(cct) << "error removing image journal" << dendl;
return r;
namespace librbd {
namespace journal {
-Replay::Replay(ImageCtx &image_ctx)
- : m_image_ctx(image_ctx), m_lock("Replay::m_lock"), m_ret_val(0) {
+template <typename I>
+Replay<I>::Replay(I &image_ctx)
+ : m_image_ctx(image_ctx), m_lock("Replay<I>::m_lock"), m_ret_val(0) {
}
-Replay::~Replay() {
+template <typename I>
+Replay<I>::~Replay() {
assert(m_aio_completions.empty());
}
-int Replay::process(bufferlist::iterator it, Context *on_safe) {
+template <typename I>
+int Replay<I>::process(bufferlist::iterator it, Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << dendl;
return 0;
}
-int Replay::flush() {
+template <typename I>
+int Replay<I>::flush() {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << dendl;
return m_ret_val;
}
-void Replay::handle_event(const journal::AioDiscardEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::AioDiscardEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": AIO discard event" << dendl;
event.length);
}
-void Replay::handle_event(const journal::AioWriteEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::AioWriteEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": AIO write event" << dendl;
data.c_str(), 0);
}
-void Replay::handle_event(const journal::AioFlushEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::AioFlushEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": AIO flush event" << dendl;
AioImageRequest::aio_flush(&m_image_ctx, aio_comp);
}
- void Replay::handle_event(const journal::OpFinishEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::OpFinishEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": Op finish event" << dendl;
}
-void Replay::handle_event(const journal::SnapCreateEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::SnapCreateEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": Snap create event" << dendl;
}
-void Replay::handle_event(const journal::SnapRemoveEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::SnapRemoveEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": Snap remove event" << dendl;
}
-void Replay::handle_event(const journal::SnapRenameEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::SnapRenameEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": Snap rename event" << dendl;
}
-void Replay::handle_event(const journal::SnapProtectEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::SnapProtectEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": Snap protect event" << dendl;
}
-void Replay::handle_event(const journal::SnapUnprotectEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::SnapUnprotectEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": Snap unprotect event"
<< dendl;
}
-void Replay::handle_event(const journal::SnapRollbackEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::SnapRollbackEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": Snap rollback start event"
<< dendl;
}
-void Replay::handle_event(const journal::RenameEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::RenameEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": Rename event" << dendl;
}
-void Replay::handle_event(const journal::ResizeEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::ResizeEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": Resize start event" << dendl;
}
-void Replay::handle_event(const journal::FlattenEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::FlattenEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": Flatten start event" << dendl;
}
-void Replay::handle_event(const journal::UnknownEvent &event,
- Context *on_safe) {
+template <typename I>
+void Replay<I>::handle_event(const journal::UnknownEvent &event,
+ Context *on_safe) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 20) << this << " " << __func__ << ": unknown event" << dendl;
on_safe->complete(0);
}
-AioCompletion *Replay::create_aio_completion(Context *on_safe) {
+template <typename I>
+AioCompletion *Replay<I>::create_aio_completion(Context *on_safe) {
Mutex::Locker locker(m_lock);
AioCompletion *aio_comp = AioCompletion::create(this, aio_completion_callback,
nullptr);
return aio_comp;
}
-void Replay::handle_aio_completion(AioCompletion *aio_comp) {
+template <typename I>
+void Replay<I>::handle_aio_completion(AioCompletion *aio_comp) {
Mutex::Locker locker(m_lock);
AioCompletions::iterator it = m_aio_completions.find(aio_comp);
m_cond.Signal();
}
-void Replay::aio_completion_callback(completion_t cb, void *arg) {
+template <typename I>
+void Replay<I>::aio_completion_callback(completion_t cb, void *arg) {
Replay *replay = reinterpret_cast<Replay *>(arg);
AioCompletion *aio_comp = reinterpret_cast<AioCompletion *>(cb);
} // namespace journal
} // namespace librbd
+
+template class librbd::journal::Replay<librbd::ImageCtx>;
namespace journal {
+template <typename ImageCtxT = ImageCtx>
class Replay {
public:
- Replay(ImageCtx &image_ctx);
+ static Replay *create(ImageCtxT &image_ctx) {
+ return new Replay(image_ctx);
+ }
+
~Replay();
int process(bufferlist::iterator it, Context *on_safe = NULL);
}
};
- ImageCtx &m_image_ctx;
+ ImageCtxT &m_image_ctx;
Mutex m_lock;
Cond m_cond;
AioCompletions m_aio_completions;
int m_ret_val;
+ Replay(ImageCtxT &image_ctx);
+
void handle_event(const AioDiscardEvent &event, Context *on_safe);
void handle_event(const AioWriteEvent &event, Context *on_safe);
void handle_event(const AioFlushEvent &event, Context *on_safe);
} // namespace journal
} // namespace librbd
+extern template class librbd::journal::Replay<librbd::ImageCtx>;
+
#endif // CEPH_LIBRBD_JOURNAL_REPLAY_H
librbd::journal::EventEntry event_entry(
librbd::journal::AioDiscardEvent(0, payload.size()));
- librbd::Journal::AioObjectRequests requests;
+ librbd::Journal<>::AioObjectRequests requests;
{
RWLock::RLocker owner_locker(ictx->owner_lock);
ictx->journal->append_io_event(NULL, event_entry, requests, 0, 0, true);
payload_bl.append(payload);
librbd::journal::EventEntry event_entry(
librbd::journal::AioWriteEvent(0, payload.size(), payload_bl));
- librbd::Journal::AioObjectRequests requests;
+ librbd::Journal<>::AioObjectRequests requests;
{
RWLock::RLocker owner_locker(ictx->owner_lock);
ictx->journal->append_io_event(NULL, event_entry, requests, 0, 0, true);
librbd::journal::AioFlushEvent aio_flush_event;
librbd::journal::EventEntry event_entry(aio_flush_event);
- librbd::Journal::AioObjectRequests requests;
+ librbd::Journal<>::AioObjectRequests requests;
{
RWLock::RLocker owner_locker(ictx->owner_lock);
ictx->journal->append_io_event(NULL, event_entry, requests, 0, 0, true);
}
// start an AIO write op
- librbd::Journal *journal = ictx->journal;
+ librbd::Journal<> *journal = ictx->journal;
ictx->journal = NULL;
std::string payload(m_image_size, '1');