libcryfs/implementations/caching/NewBlock.cpp

69 lines
1.6 KiB
C++

#include "NewBlock.h"
#include "CachingBlockStore.h"
using std::unique_ptr;
using cpputils::Data;
namespace blockstore {
namespace caching {
NewBlock::NewBlock(const Key &key, Data data, CachingBlockStore *blockStore)
:Block(key),
_blockStore(blockStore),
_data(std::move(data)),
_baseBlock(nullptr),
_dataChanged(true) {
}
NewBlock::~NewBlock() {
writeToBaseBlockIfChanged();
}
const void *NewBlock::data() const {
return _data.data();
}
void NewBlock::write(const void *source, uint64_t offset, uint64_t size) {
assert(offset <= _data.size() && offset + size <= _data.size());
std::memcpy((uint8_t*)_data.data()+offset, source, size);
_dataChanged = true;
}
void NewBlock::writeToBaseBlockIfChanged() {
if (_dataChanged) {
if (_baseBlock.get() == nullptr) {
//TODO _data.copy() necessary?
auto newBase = _blockStore->tryCreateInBaseStore(key(), _data.copy());
assert(newBase != boost::none); //TODO What if tryCreate fails due to a duplicate key? We should ensure we don't use duplicate keys.
//TODO Don't use to_unique_ptr but make _baseBlock a unique_ref
_baseBlock = cpputils::to_unique_ptr(std::move(*newBase));
} else {
_baseBlock->write(_data.data(), 0, _data.size());
}
_dataChanged = false;
}
}
void NewBlock::remove() {
if (_baseBlock.get() != nullptr) {
_blockStore->removeFromBaseStore(std::move(_baseBlock));
}
_dataChanged = false;
}
void NewBlock::flush() {
writeToBaseBlockIfChanged();
_baseBlock->flush();
}
size_t NewBlock::size() const {
return _data.size();
}
bool NewBlock::alreadyExistsInBaseStore() const {
return _baseBlock.get() != nullptr;
}
}
}