// 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