2016-02-24 20:01:51 +05:30
|
|
|
#include "base/container_of.h"
|
2015-08-24 21:25:53 +05:30
|
|
|
#include "thin-provisioning/cache_stream.h"
|
|
|
|
#include "persistent-data/file_utils.h"
|
|
|
|
|
|
|
|
using namespace thin_provisioning;
|
|
|
|
using namespace std;
|
|
|
|
using namespace persistent_data;
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
int open_file(string const &path) {
|
|
|
|
int fd = ::open(path.c_str(), O_RDONLY | O_DIRECT | O_EXCL, 0666);
|
|
|
|
if (fd < 0)
|
|
|
|
syscall_failed("open",
|
|
|
|
"Note: you cannot run this tool with these options on live metadata.");
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
|
|
|
cache_stream::cache_stream(string const &path,
|
|
|
|
block_address block_size,
|
|
|
|
size_t cache_mem)
|
|
|
|
: block_size_(block_size),
|
|
|
|
nr_blocks_(get_nr_blocks(path, block_size)),
|
|
|
|
|
|
|
|
// hack because cache uses LRU rather than MRU
|
|
|
|
cache_blocks_((cache_mem / block_size) / 2u),
|
|
|
|
fd_(open_file(path)),
|
|
|
|
v_(new bcache::noop_validator()),
|
|
|
|
cache_(new block_cache(fd_, block_size / 512, nr_blocks_, cache_mem)),
|
|
|
|
current_index_(0) {
|
2015-09-03 17:32:29 +05:30
|
|
|
|
|
|
|
rewind();
|
2015-08-24 21:25:53 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
block_address
|
2015-09-04 19:46:49 +05:30
|
|
|
cache_stream::size() const
|
2015-08-24 21:25:53 +05:30
|
|
|
{
|
2015-09-04 19:46:49 +05:30
|
|
|
return nr_blocks_ * block_size_;
|
2015-08-24 21:25:53 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
cache_stream::rewind()
|
|
|
|
{
|
2015-09-03 17:32:29 +05:30
|
|
|
current_index_ = 0;
|
|
|
|
|
|
|
|
for (block_address i = 1; i < min(cache_blocks_, nr_blocks_); i++)
|
|
|
|
cache_->prefetch(i);
|
2015-08-24 21:25:53 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-09-03 17:32:29 +05:30
|
|
|
cache_stream::next(block_address count)
|
2015-08-24 21:25:53 +05:30
|
|
|
{
|
2015-09-03 17:32:29 +05:30
|
|
|
current_index_ = min(current_index_ + count, nr_blocks_);
|
2015-08-24 21:25:53 +05:30
|
|
|
|
2015-09-03 17:32:29 +05:30
|
|
|
if (current_index_ + cache_blocks_ < nr_blocks_)
|
|
|
|
cache_->prefetch(current_index_ + cache_blocks_);
|
2015-08-24 21:25:53 +05:30
|
|
|
|
2015-09-03 17:32:29 +05:30
|
|
|
return !eof();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
cache_stream::eof() const
|
|
|
|
{
|
|
|
|
return current_index_ >= nr_blocks_;
|
2015-08-24 21:25:53 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
chunk const &
|
2015-09-03 17:32:29 +05:30
|
|
|
cache_stream::get()
|
2015-08-24 21:25:53 +05:30
|
|
|
{
|
2015-09-03 17:32:29 +05:30
|
|
|
chunk_wrapper *w = new chunk_wrapper(*this);
|
|
|
|
return w->c_;
|
2015-08-24 21:25:53 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-09-03 17:32:29 +05:30
|
|
|
cache_stream::put(chunk const &c)
|
2015-08-24 21:25:53 +05:30
|
|
|
{
|
2016-02-24 20:01:51 +05:30
|
|
|
chunk_wrapper *w = base::container_of(const_cast<chunk *>(&c), &chunk_wrapper::c_);
|
2015-09-03 17:32:29 +05:30
|
|
|
delete w;
|
|
|
|
}
|
2015-08-24 21:25:53 +05:30
|
|
|
|
2015-09-03 17:32:29 +05:30
|
|
|
cache_stream::chunk_wrapper::chunk_wrapper(cache_stream &parent)
|
|
|
|
: block_(parent.cache_->get(parent.current_index_, 0, parent.v_))
|
|
|
|
{
|
|
|
|
c_.offset_ = parent.current_index_ * parent.block_size_;
|
|
|
|
c_.len_ = parent.block_size_;
|
2015-09-04 18:18:02 +05:30
|
|
|
c_.mem_.begin = static_cast<uint8_t *>(block_.get_data());
|
|
|
|
c_.mem_.end = c_.mem_.begin + parent.block_size_;
|
2015-08-24 21:25:53 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|