thin-provisioning-tools/persistent-data/block.h

197 lines
4.8 KiB
C
Raw Normal View History

2011-12-16 00:04:31 +05:30
// Copyright (C) 2011 Red Hat, Inc. All rights reserved.
2011-12-06 19:23:05 +05:30
//
2011-12-06 19:13:56 +05:30
// 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
// <http://www.gnu.org/licenses/>.
#ifndef BLOCK_H
#define BLOCK_H
#include "block-cache/block_cache.h"
2014-07-25 15:05:04 +05:30
#include "block-cache/buffer.h"
2011-10-24 22:34:19 +05:30
#include <stdint.h>
#include <map>
#include <vector>
#include <boost/noncopyable.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
2013-01-23 17:58:00 +05:30
#include <string>
//----------------------------------------------------------------
namespace persistent_data {
2014-07-25 15:05:04 +05:30
using namespace bcache;
2013-01-23 17:58:00 +05:30
uint32_t const MD_BLOCK_SIZE = 4096;
template <uint32_t BlockSize = MD_BLOCK_SIZE>
class block_manager : private boost::noncopyable {
public:
typedef boost::shared_ptr<block_manager> ptr;
2013-01-12 01:46:40 +05:30
enum mode {
READ_ONLY,
READ_WRITE,
CREATE
2013-01-12 01:46:40 +05:30
};
2011-10-24 22:34:19 +05:30
block_manager(std::string const &path,
block_address nr_blocks,
unsigned max_concurrent_locks,
mode m);
enum block_type {
BT_SUPERBLOCK,
BT_NORMAL
};
2014-07-25 15:05:04 +05:30
// FIXME: eventually this will disappear to be replaced with block_cache::block
struct block : private boost::noncopyable {
2011-07-13 19:39:33 +05:30
typedef boost::shared_ptr<block> ptr;
2014-07-25 15:05:04 +05:30
block(block_cache &bc,
2011-10-24 22:34:19 +05:30
block_address location,
block_type bt,
2014-07-25 19:16:51 +05:30
typename bcache::validator::ptr v,
2011-10-24 22:34:19 +05:30
bool zero = false);
~block();
void check_read_lockable() const {
// FIXME: finish
}
2011-10-24 22:34:19 +05:30
void check_write_lockable() const {
// FIXME: finish
}
block_type get_type() const;
uint64_t get_location() const;
2014-07-25 19:16:51 +05:30
void const *get_data() const;
void *get_data();
void mark_dirty();
void unlock();
private:
void check_not_unlocked() const;
2014-07-25 15:05:04 +05:30
block_cache &bc_;
block_cache::block *internal_;
block_type bt_;
2011-10-24 22:34:19 +05:30
bool dirty_;
bool unlocked_;
};
class read_ref {
public:
static uint32_t const BLOCK_SIZE = BlockSize;
2011-10-24 22:34:19 +05:30
read_ref(block_manager<BlockSize> const &bm,
typename block::ptr b);
2011-10-24 22:34:19 +05:30
read_ref(read_ref const &rhs);
virtual ~read_ref();
read_ref const &operator =(read_ref const &rhs);
block_address get_location() const;
2014-07-25 19:16:51 +05:30
void const * data() const;
protected:
block_manager<BlockSize> const *bm_;
typename block::ptr block_;
2011-10-24 22:34:19 +05:30
unsigned *holders_;
};
// Inherited from read_ref, since you can read a block that's write
// locked.
class write_ref : public read_ref {
public:
2011-10-24 22:34:19 +05:30
write_ref(block_manager<BlockSize> const &bm,
typename block::ptr b);
2011-06-27 15:15:30 +05:30
using read_ref::data;
2014-07-25 19:16:51 +05:30
void *data();
};
// Locking methods
read_ref
2011-06-27 15:15:30 +05:30
read_lock(block_address location,
typename validator::ptr v =
2014-07-25 19:16:51 +05:30
typename validator::ptr(new bcache::noop_validator())) const;
write_ref
2011-06-27 15:15:30 +05:30
write_lock(block_address location,
typename validator::ptr v =
2014-07-25 19:16:51 +05:30
typename validator::ptr(new bcache::noop_validator()));
write_ref
2011-06-27 15:15:30 +05:30
write_lock_zero(block_address location,
typename validator::ptr v =
2014-07-25 19:16:51 +05:30
typename validator::ptr(new bcache::noop_validator()));
// The super block is the one that should be written last.
// Unlocking this block triggers the following events:
//
// i) synchronous write of all dirty blocks _except_ the
// superblock.
//
// ii) synchronous write of superblock
//
// If any locks are held at the time of the superblock
// being unlocked then an exception will be thrown.
write_ref superblock(block_address b,
typename validator::ptr v =
2014-07-25 19:16:51 +05:30
typename validator::ptr(new bcache::noop_validator()));
write_ref superblock_zero(block_address b,
typename validator::ptr v =
2014-07-25 19:16:51 +05:30
typename validator::ptr(new bcache::noop_validator()));
2011-07-22 20:39:56 +05:30
block_address get_nr_blocks() const;
2011-10-24 22:34:19 +05:30
void flush() const;
// This is just for unit tests, don't call in application
// code.
bool is_locked(block_address b) const;
private:
2011-07-13 19:39:33 +05:30
void check(block_address b) const;
void write_block(typename block::ptr b) const;
int fd_;
2014-07-25 15:05:04 +05:30
// FIXME: the mutable is a fudge to allow flush() to be const, which I'm not sure is necc.
mutable block_cache bc_;
};
// A little utility to help build validators
2014-07-25 19:16:51 +05:30
inline bcache::validator::ptr
mk_validator(bcache::validator *v) {
return bcache::validator::ptr(v);
}
}
2011-06-27 15:15:30 +05:30
#include "block.tcc"
//----------------------------------------------------------------
#endif