// Copyright (C) 2018 Red Hat, Inc. All rights reserved. // // This file is part of the thin-provisioning-tools source. // // thin-provisioning-tools is free software: you can redistribute it // and/or modify it under the terms of the GNU General Public License // as published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. // // thin-provisioning-tools is distributed in the hope that it will be // useful, but WITHOUT ANY WARRANTY; without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with thin-provisioning-tools. If not, see // . #ifndef THIN_PROVISIONING_THIN_JOURNAL_H #define THIN_PROVISIONING_THIN_JOURNAL_H #include "persistent-data/block.h" #include //---------------------------------------------------------------- namespace thin_provisioning { uint32_t const JOURNAL_BLOCK_SIZE = 4096; uint32_t const JOURNAL_CHUNK_SIZE = 32; uint32_t const JOURNAL_NR_CHUNKS = (4096 / JOURNAL_CHUNK_SIZE); class byte_stream { public: byte_stream(persistent_data::block_manager::ptr bm); void read_bytes(uint8_t *b, uint8_t *e); private: void next_block_(); size_t read_some_(uint8_t *b, uint8_t *e); persistent_data::block_manager::ptr bm_; uint64_t current_block_; uint64_t cursor_; }; //--------------------------------- class journal_visitor; struct journal_msg { journal_msg(bool success); virtual ~journal_msg() {} virtual void visit(journal_visitor &v) const = 0; bool success_; }; struct open_journal_msg : public journal_msg { open_journal_msg(uint64_t nr_metadata_blocks); virtual void visit(journal_visitor &v) const; uint64_t nr_metadata_blocks_; }; struct close_journal_msg : public journal_msg { close_journal_msg(); virtual void visit(journal_visitor &v) const; }; struct block_msg : public journal_msg { block_msg(bool success, uint64_t index); uint64_t index_; }; struct read_lock_msg : public block_msg { read_lock_msg(bool success, uint64_t index); virtual void visit(journal_visitor &v) const; }; struct write_lock_msg : public block_msg { write_lock_msg(bool success, uint64_t index); virtual void visit(journal_visitor &v) const; }; struct zero_lock_msg : public block_msg { zero_lock_msg(bool success, uint64_t index); virtual void visit(journal_visitor &v) const; }; struct try_read_lock_msg : public block_msg { try_read_lock_msg(bool success, uint64_t index); virtual void visit(journal_visitor &v) const; }; struct delta { delta(uint32_t offset, std::vector &bytes) : offset_(offset), bytes_(bytes) { } uint32_t offset_; std::vector bytes_; }; using delta_list = std::vector; struct unlock_msg : public block_msg { unlock_msg(bool success, uint64_t index, delta_list const &deltas); virtual void visit(journal_visitor &v) const; delta_list deltas_; }; struct verify_msg : public block_msg { verify_msg(bool success, uint64_t index); virtual void visit(journal_visitor &v) const; }; struct prepare_msg : public block_msg { prepare_msg(bool success, uint64_t index); virtual void visit(journal_visitor &v) const; }; struct flush_msg : public journal_msg { flush_msg(bool success); virtual void visit(journal_visitor &v) const; }; struct flush_and_unlock_msg : public block_msg { flush_and_unlock_msg(bool success, uint64_t index, delta_list const &deltas); virtual void visit(journal_visitor &v) const; delta_list deltas_; }; struct prefetch_msg : public block_msg { prefetch_msg(bool success, uint64_t index); virtual void visit(journal_visitor &v) const; }; struct set_read_only_msg : public journal_msg { set_read_only_msg(); virtual void visit(journal_visitor &v) const; }; struct set_read_write_msg : public journal_msg { set_read_write_msg(); virtual void visit(journal_visitor &v) const; }; struct journal_visitor { public: virtual ~journal_visitor() {}; void visit(journal_msg const &msg) { msg.visit(*this); } virtual void visit(open_journal_msg const &msg) = 0; virtual void visit(close_journal_msg const &msg) = 0; virtual void visit(read_lock_msg const &msg) = 0; virtual void visit(write_lock_msg const &msg) = 0; virtual void visit(zero_lock_msg const &msg) = 0; virtual void visit(try_read_lock_msg const &msg) = 0; virtual void visit(unlock_msg const &msg) = 0; virtual void visit(verify_msg const &msg) = 0; virtual void visit(prepare_msg const &msg) = 0; virtual void visit(flush_msg const &msg) = 0; virtual void visit(flush_and_unlock_msg const &msg) = 0; virtual void visit(prefetch_msg const &msg) = 0; virtual void visit(set_read_only_msg const &msg) = 0; virtual void visit(set_read_write_msg const &msg) = 0; }; enum msg_type { MT_OPEN_JOURNAL, MT_CLOSE_JOURNAL, MT_READ_LOCK, MT_WRITE_LOCK, MT_ZERO_LOCK, MT_TRY_READ_LOCK, MT_UNLOCK, MT_VERIFY, MT_PREPARE, MT_FLUSH, MT_FLUSH_AND_UNLOCK, MT_PREFETCH, MT_SET_READ_ONLY, MT_SET_READ_WRITE, }; class journal { public: journal(persistent_data::block_manager::ptr bm); void read_journal(struct journal_visitor &v); private: bool read_delta_(delta_list &ds); delta_list read_deltas_(); bool read_one_(struct journal_visitor &v); template T read_() { T r; in_.read_bytes(reinterpret_cast(&r), reinterpret_cast(&r + 1)); return r; } byte_stream in_; }; } //---------------------------------------------------------------- #endif