Changed Blockstore::tryCreate() to return optional<unique_ref<Block>> instead of unique_ptr<Block>

This commit is contained in:
Sebastian Messmer 2015-07-20 18:57:48 +02:00
parent dc15ac22ca
commit a945e4f0fc
25 changed files with 128 additions and 89 deletions

View File

@ -10,6 +10,10 @@ using std::unique_ptr;
using std::make_unique; using std::make_unique;
using cpputils::dynamic_pointer_move; using cpputils::dynamic_pointer_move;
using cpputils::Data; using cpputils::Data;
using boost::optional;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using boost::none;
namespace blockstore { namespace blockstore {
namespace caching { namespace caching {
@ -22,9 +26,10 @@ Key CachingBlockStore::createKey() {
return _baseBlockStore->createKey(); return _baseBlockStore->createKey();
} }
unique_ptr<Block> CachingBlockStore::tryCreate(const Key &key, Data data) { optional<unique_ref<Block>> CachingBlockStore::tryCreate(const Key &key, Data data) {
//TODO Shouldn't we return boost::none if the key already exists?
++_numNewBlocks; ++_numNewBlocks;
return make_unique<CachedBlock>(make_unique<NewBlock>(key, std::move(data), this), this); return unique_ref<Block>(make_unique_ref<CachedBlock>(make_unique<NewBlock>(key, std::move(data), this), this));
} }
unique_ptr<Block> CachingBlockStore::load(const Key &key) { unique_ptr<Block> CachingBlockStore::load(const Key &key) {
@ -64,9 +69,9 @@ void CachingBlockStore::release(unique_ptr<Block> block) {
_cache.push(key, std::move(block)); _cache.push(key, std::move(block));
} }
std::unique_ptr<Block> CachingBlockStore::tryCreateInBaseStore(const Key &key, Data data) { optional<unique_ref<Block>> CachingBlockStore::tryCreateInBaseStore(const Key &key, Data data) {
auto block = _baseBlockStore->tryCreate(key, std::move(data)); auto block = _baseBlockStore->tryCreate(key, std::move(data));
if (block.get() != nullptr) { if (block != none) {
--_numNewBlocks; --_numNewBlocks;
} }
return block; return block;

View File

@ -14,14 +14,14 @@ public:
explicit CachingBlockStore(std::unique_ptr<BlockStore> baseBlockStore); explicit CachingBlockStore(std::unique_ptr<BlockStore> baseBlockStore);
Key createKey() override; Key createKey() override;
std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) override; boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) override;
std::unique_ptr<Block> load(const Key &key) override; std::unique_ptr<Block> load(const Key &key) override;
void remove(std::unique_ptr<Block> block) override; void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override; uint64_t numBlocks() const override;
void release(std::unique_ptr<Block> block); void release(std::unique_ptr<Block> block);
std::unique_ptr<Block> tryCreateInBaseStore(const Key &key, cpputils::Data data); boost::optional<cpputils::unique_ref<Block>> tryCreateInBaseStore(const Key &key, cpputils::Data data);
void removeFromBaseStore(std::unique_ptr<Block> block); void removeFromBaseStore(std::unique_ptr<Block> block);
private: private:

View File

@ -32,9 +32,11 @@ void NewBlock::write(const void *source, uint64_t offset, uint64_t size) {
void NewBlock::writeToBaseBlockIfChanged() { void NewBlock::writeToBaseBlockIfChanged() {
if (_dataChanged) { if (_dataChanged) {
if (_baseBlock.get() == nullptr) { if (_baseBlock.get() == nullptr) {
//TODO What if tryCreate fails due to a duplicate key? We should ensure we don't use duplicate keys.
//TODO _data.copy() necessary? //TODO _data.copy() necessary?
_baseBlock = _blockStore->tryCreateInBaseStore(key(), _data.copy()); 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 { } else {
_baseBlock->write(_data.data(), 0, _data.size()); _baseBlock->write(_data.data(), 0, _data.size());
} }

View File

@ -22,7 +22,7 @@ template<class Cipher>
class EncryptedBlock: public Block { class EncryptedBlock: public Block {
public: public:
BOOST_CONCEPT_ASSERT((CipherConcept<Cipher>)); BOOST_CONCEPT_ASSERT((CipherConcept<Cipher>));
static std::unique_ptr<EncryptedBlock> TryCreateNew(BlockStore *baseBlockStore, const Key &key, cpputils::Data data, const typename Cipher::EncryptionKey &encKey); static boost::optional<cpputils::unique_ref<EncryptedBlock>> TryCreateNew(BlockStore *baseBlockStore, const Key &key, cpputils::Data data, const typename Cipher::EncryptionKey &encKey);
static std::unique_ptr<EncryptedBlock> TryDecrypt(std::unique_ptr<Block> baseBlock, const typename Cipher::EncryptionKey &key); static std::unique_ptr<EncryptedBlock> TryDecrypt(std::unique_ptr<Block> baseBlock, const typename Cipher::EncryptionKey &key);
//TODO Storing key twice (in parent class and in object pointed to). Once would be enough. //TODO Storing key twice (in parent class and in object pointed to). Once would be enough.
@ -57,16 +57,17 @@ constexpr unsigned int EncryptedBlock<Cipher>::HEADER_LENGTH;
template<class Cipher> template<class Cipher>
std::unique_ptr<EncryptedBlock<Cipher>> EncryptedBlock<Cipher>::TryCreateNew(BlockStore *baseBlockStore, const Key &key, cpputils::Data data, const typename Cipher::EncryptionKey &encKey) { boost::optional<cpputils::unique_ref<EncryptedBlock<Cipher>>> EncryptedBlock<Cipher>::TryCreateNew(BlockStore *baseBlockStore, const Key &key, cpputils::Data data, const typename Cipher::EncryptionKey &encKey) {
cpputils::Data plaintextWithHeader = _prependKeyHeaderToData(key, std::move(data)); cpputils::Data plaintextWithHeader = _prependKeyHeaderToData(key, std::move(data));
cpputils::Data encrypted = Cipher::encrypt((byte*)plaintextWithHeader.data(), plaintextWithHeader.size(), encKey); cpputils::Data encrypted = Cipher::encrypt((byte*)plaintextWithHeader.data(), plaintextWithHeader.size(), encKey);
auto baseBlock = baseBlockStore->tryCreate(key, std::move(encrypted)); auto baseBlock = baseBlockStore->tryCreate(key, std::move(encrypted));
if (baseBlock.get() == nullptr) { if (baseBlock == boost::none) {
//TODO Test this code branch //TODO Test this code branch
return nullptr; return boost::none;
} }
return std::make_unique<EncryptedBlock>(std::move(baseBlock), encKey, std::move(plaintextWithHeader)); //TODO Don't use to_unique_ptr
return cpputils::make_unique_ref<EncryptedBlock>(cpputils::to_unique_ptr(std::move(*baseBlock)), encKey, std::move(plaintextWithHeader));
} }
template<class Cipher> template<class Cipher>

View File

@ -18,7 +18,7 @@ public:
//TODO Are createKey() tests included in generic BlockStoreTest? If not, add it! //TODO Are createKey() tests included in generic BlockStoreTest? If not, add it!
Key createKey() override; Key createKey() override;
std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) override; boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) override;
std::unique_ptr<Block> load(const Key &key) override; std::unique_ptr<Block> load(const Key &key) override;
void remove(std::unique_ptr<Block> block) override; void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override; uint64_t numBlocks() const override;
@ -46,9 +46,14 @@ Key EncryptedBlockStore<Cipher>::createKey() {
} }
template<class Cipher> template<class Cipher>
std::unique_ptr<Block> EncryptedBlockStore<Cipher>::tryCreate(const Key &key, cpputils::Data data) { boost::optional<cpputils::unique_ref<Block>> EncryptedBlockStore<Cipher>::tryCreate(const Key &key, cpputils::Data data) {
//TODO Test that this returns nullptr when base blockstore returns nullptr (for all pass-through-blockstores) //TODO Test that this returns boost::none when base blockstore returns nullptr (for all pass-through-blockstores)
return EncryptedBlock<Cipher>::TryCreateNew(_baseBlockStore.get(), key, std::move(data), _encKey); //TODO Easier implementation? This is only so complicated because of the case EncryptedBlock -> Block
auto result = EncryptedBlock<Cipher>::TryCreateNew(_baseBlockStore.get(), key, std::move(data), _encKey);
if (result == boost::none) {
return boost::none;
}
return cpputils::unique_ref<Block>(std::move(*result));
} }
template<class Cipher> template<class Cipher>

View File

@ -10,6 +10,10 @@ using std::lock_guard;
using std::piecewise_construct; using std::piecewise_construct;
using std::make_tuple; using std::make_tuple;
using cpputils::Data; using cpputils::Data;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using boost::optional;
using boost::none;
namespace blockstore { namespace blockstore {
namespace inmemory { namespace inmemory {
@ -17,15 +21,15 @@ namespace inmemory {
InMemoryBlockStore::InMemoryBlockStore() InMemoryBlockStore::InMemoryBlockStore()
: _blocks() {} : _blocks() {}
unique_ptr<Block> InMemoryBlockStore::tryCreate(const Key &key, Data data) { optional<unique_ref<Block>> InMemoryBlockStore::tryCreate(const Key &key, Data data) {
auto insert_result = _blocks.emplace(piecewise_construct, make_tuple(key.ToString()), make_tuple(key, std::move(data))); auto insert_result = _blocks.emplace(piecewise_construct, make_tuple(key.ToString()), make_tuple(key, std::move(data)));
if (!insert_result.second) { if (!insert_result.second) {
return nullptr; return none;
} }
//Return a pointer to the stored InMemoryBlock //Return a pointer to the stored InMemoryBlock
return make_unique<InMemoryBlock>(insert_result.first->second); return optional<unique_ref<Block>>(make_unique_ref<InMemoryBlock>(insert_result.first->second));
} }
unique_ptr<Block> InMemoryBlockStore::load(const Key &key) { unique_ptr<Block> InMemoryBlockStore::load(const Key &key) {

View File

@ -16,7 +16,7 @@ class InMemoryBlockStore: public BlockStoreWithRandomKeys {
public: public:
InMemoryBlockStore(); InMemoryBlockStore();
std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) override; boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) override;
std::unique_ptr<Block> load(const Key &key) override; std::unique_ptr<Block> load(const Key &key) override;
void remove(std::unique_ptr<Block> block) override; void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override; uint64_t numBlocks() const override;

View File

@ -13,6 +13,10 @@ using std::ifstream;
using std::ofstream; using std::ofstream;
using std::ios; using std::ios;
using cpputils::Data; using cpputils::Data;
using cpputils::make_unique_ref;
using cpputils::unique_ref;
using boost::optional;
using boost::none;
namespace bf = boost::filesystem; namespace bf = boost::filesystem;
@ -61,15 +65,15 @@ unique_ptr<OnDiskBlock> OnDiskBlock::LoadFromDisk(const bf::path &rootdir, const
} }
} }
unique_ptr<OnDiskBlock> OnDiskBlock::CreateOnDisk(const bf::path &rootdir, const Key &key, Data data) { optional<unique_ref<OnDiskBlock>> OnDiskBlock::CreateOnDisk(const bf::path &rootdir, const Key &key, Data data) {
auto filepath = rootdir / key.ToString(); auto filepath = rootdir / key.ToString();
if (bf::exists(filepath)) { if (bf::exists(filepath)) {
return nullptr; return none;
} }
auto block = unique_ptr<OnDiskBlock>(new OnDiskBlock(key, filepath, std::move(data))); auto block = make_unique_ref<OnDiskBlock>(key, filepath, std::move(data));
block->_storeToDisk(); block->_storeToDisk();
return block; return std::move(block);
} }
void OnDiskBlock::RemoveFromDisk(const bf::path &rootdir, const Key &key) { void OnDiskBlock::RemoveFromDisk(const bf::path &rootdir, const Key &key) {

View File

@ -7,7 +7,7 @@
#include <messmer/cpp-utils/data/Data.h> #include <messmer/cpp-utils/data/Data.h>
#include <iostream> #include <iostream>
#include "messmer/cpp-utils/macros.h" #include <messmer/cpp-utils/pointer/unique_ref.h>
namespace blockstore { namespace blockstore {
namespace ondisk { namespace ondisk {
@ -15,10 +15,11 @@ class OnDiskBlockStore;
class OnDiskBlock: public Block { class OnDiskBlock: public Block {
public: public:
OnDiskBlock(const Key &key, const boost::filesystem::path &filepath, cpputils::Data data);
virtual ~OnDiskBlock(); virtual ~OnDiskBlock();
static std::unique_ptr<OnDiskBlock> LoadFromDisk(const boost::filesystem::path &rootdir, const Key &key); static std::unique_ptr<OnDiskBlock> LoadFromDisk(const boost::filesystem::path &rootdir, const Key &key);
static std::unique_ptr<OnDiskBlock> CreateOnDisk(const boost::filesystem::path &rootdir, const Key &key, cpputils::Data data); static boost::optional<cpputils::unique_ref<OnDiskBlock>> CreateOnDisk(const boost::filesystem::path &rootdir, const Key &key, cpputils::Data data);
static void RemoveFromDisk(const boost::filesystem::path &rootdir, const Key &key); static void RemoveFromDisk(const boost::filesystem::path &rootdir, const Key &key);
const void *data() const override; const void *data() const override;
@ -33,8 +34,6 @@ private:
cpputils::Data _data; cpputils::Data _data;
bool _dataChanged; bool _dataChanged;
OnDiskBlock(const Key &key, const boost::filesystem::path &filepath, cpputils::Data data);
void _fillDataWithZeroes(); void _fillDataWithZeroes();
void _storeToDisk() const; void _storeToDisk() const;

View File

@ -5,6 +5,9 @@ using std::unique_ptr;
using std::make_unique; using std::make_unique;
using std::string; using std::string;
using cpputils::Data; using cpputils::Data;
using cpputils::unique_ref;
using boost::optional;
using boost::none;
namespace bf = boost::filesystem; namespace bf = boost::filesystem;
@ -14,13 +17,13 @@ namespace ondisk {
OnDiskBlockStore::OnDiskBlockStore(const boost::filesystem::path &rootdir) OnDiskBlockStore::OnDiskBlockStore(const boost::filesystem::path &rootdir)
: _rootdir(rootdir) {} : _rootdir(rootdir) {}
unique_ptr<Block> OnDiskBlockStore::tryCreate(const Key &key, Data data) { optional<unique_ref<Block>> OnDiskBlockStore::tryCreate(const Key &key, Data data) {
auto block = OnDiskBlock::CreateOnDisk(_rootdir, key, std::move(data)); //TODO Easier implementation? This is only so complicated because of the cast OnDiskBlock -> Block
auto result = std::move(OnDiskBlock::CreateOnDisk(_rootdir, key, std::move(data)));
if (!block) { if (result == boost::none) {
return nullptr; return boost::none;
} }
return std::move(block); return unique_ref<Block>(std::move(*result));
} }
unique_ptr<Block> OnDiskBlockStore::load(const Key &key) { unique_ptr<Block> OnDiskBlockStore::load(const Key &key) {

View File

@ -14,7 +14,7 @@ class OnDiskBlockStore: public BlockStoreWithRandomKeys {
public: public:
explicit OnDiskBlockStore(const boost::filesystem::path &rootdir); explicit OnDiskBlockStore(const boost::filesystem::path &rootdir);
std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) override; boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) override;
std::unique_ptr<Block> load(const Key &key) override; std::unique_ptr<Block> load(const Key &key) override;
void remove(std::unique_ptr<Block> block) override; void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override; uint64_t numBlocks() const override;

View File

@ -15,6 +15,9 @@ using cpputils::dynamic_pointer_move;
using cpputils::make_unique_ref; using cpputils::make_unique_ref;
using boost::none; using boost::none;
using cpputils::unique_ref; using cpputils::unique_ref;
using cpputils::make_unique_ref;
using boost::optional;
using boost::none;
namespace blockstore { namespace blockstore {
namespace parallelaccess { namespace parallelaccess {
@ -27,14 +30,13 @@ Key ParallelAccessBlockStore::createKey() {
return _baseBlockStore->createKey(); return _baseBlockStore->createKey();
} }
unique_ptr<Block> ParallelAccessBlockStore::tryCreate(const Key &key, cpputils::Data data) { optional<unique_ref<Block>> ParallelAccessBlockStore::tryCreate(const Key &key, cpputils::Data data) {
//TODO Don't use nullcheck/to_unique_ptr but make blockstore use unique_ref auto block = _baseBlockStore->tryCreate(key, std::move(data));
auto block = cpputils::nullcheck(_baseBlockStore->tryCreate(key, std::move(data)));
if (block == none) { if (block == none) {
//TODO Test this code branch //TODO Test this code branch
return nullptr; return none;
} }
return cpputils::to_unique_ptr(_parallelAccessStore.add(key, std::move(*block))); return unique_ref<Block>(_parallelAccessStore.add(key, std::move(*block)));
} }
unique_ptr<Block> ParallelAccessBlockStore::load(const Key &key) { unique_ptr<Block> ParallelAccessBlockStore::load(const Key &key) {

View File

@ -16,7 +16,7 @@ public:
explicit ParallelAccessBlockStore(cpputils::unique_ref<BlockStore> baseBlockStore); explicit ParallelAccessBlockStore(cpputils::unique_ref<BlockStore> baseBlockStore);
Key createKey() override; Key createKey() override;
std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) override; boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) override;
std::unique_ptr<Block> load(const Key &key) override; std::unique_ptr<Block> load(const Key &key) override;
void remove(std::unique_ptr<Block> block) override; void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override; uint64_t numBlocks() const override;

View File

@ -8,6 +8,10 @@ using std::string;
using std::mutex; using std::mutex;
using std::lock_guard; using std::lock_guard;
using cpputils::Data; using cpputils::Data;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using boost::optional;
using boost::none;
namespace blockstore { namespace blockstore {
namespace testfake { namespace testfake {
@ -15,15 +19,16 @@ namespace testfake {
FakeBlockStore::FakeBlockStore() FakeBlockStore::FakeBlockStore()
: _blocks(), _used_dataregions_for_blocks() {} : _blocks(), _used_dataregions_for_blocks() {}
unique_ptr<Block> FakeBlockStore::tryCreate(const Key &key, Data data) { optional<unique_ref<Block>> FakeBlockStore::tryCreate(const Key &key, Data data) {
auto insert_result = _blocks.emplace(key.ToString(), std::move(data)); auto insert_result = _blocks.emplace(key.ToString(), std::move(data));
if (!insert_result.second) { if (!insert_result.second) {
return nullptr; return none;
} }
//Return a copy of the stored data //Return a copy of the stored data
return load(key); //TODO Don't use nullcheck but make load() use unique_ref
return cpputils::nullcheck(load(key));
} }
unique_ptr<Block> FakeBlockStore::load(const Key &key) { unique_ptr<Block> FakeBlockStore::load(const Key &key) {

View File

@ -31,7 +31,7 @@ class FakeBlockStore: public BlockStoreWithRandomKeys {
public: public:
FakeBlockStore(); FakeBlockStore();
std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) override; boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) override;
std::unique_ptr<Block> load(const Key &key) override; std::unique_ptr<Block> load(const Key &key) override;
void remove(std::unique_ptr<Block> block) override; void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override; uint64_t numBlocks() const override;

View File

@ -4,7 +4,8 @@
#include "Block.h" #include "Block.h"
#include <string> #include <string>
#include <memory> #include <boost/optional.hpp>
#include <messmer/cpp-utils/pointer/unique_ref.h>
#include <messmer/cpp-utils/data/Data.h> #include <messmer/cpp-utils/data/Data.h>
namespace blockstore { namespace blockstore {
@ -14,21 +15,22 @@ public:
virtual ~BlockStore() {} virtual ~BlockStore() {}
virtual Key createKey() = 0; virtual Key createKey() = 0;
//Returns nullptr if key already exists //Returns boost::none if key already exists
virtual std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) = 0; virtual boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) = 0;
//TODO Use boost::optional (if key doesn't exist) //TODO Use boost::optional (if key doesn't exist)
// Return nullptr if block with this key doesn't exists // Return nullptr if block with this key doesn't exists
virtual std::unique_ptr<Block> load(const Key &key) = 0; virtual std::unique_ptr<Block> load(const Key &key) = 0;
virtual void remove(std::unique_ptr<Block> block) = 0; virtual void remove(std::unique_ptr<Block> block) = 0;
virtual uint64_t numBlocks() const = 0; virtual uint64_t numBlocks() const = 0;
std::unique_ptr<Block> create(const cpputils::Data &data) { cpputils::unique_ref<Block> create(const cpputils::Data &data) {
std::unique_ptr<Block> block(nullptr); while(true) {
while(block.get() == nullptr) { //TODO Copy (data.copy()) necessary?
//TODO Copy necessary? auto block = tryCreate(createKey(), data.copy());
block = tryCreate(createKey(), data.copy()); if (block != boost::none) {
return std::move(*block);
}
} }
return block;
} }
}; };

View File

@ -3,6 +3,7 @@
#include "../../testutils/BlockStoreTest.h" #include "../../testutils/BlockStoreTest.h"
#include "../../testutils/BlockStoreWithRandomKeysTest.h" #include "../../testutils/BlockStoreWithRandomKeysTest.h"
#include "google/gtest/gtest.h" #include "google/gtest/gtest.h"
#include <messmer/cpp-utils/pointer/unique_ref_boost_optional_gtest_workaround.h>
using blockstore::BlockStore; using blockstore::BlockStore;

View File

@ -12,6 +12,7 @@ using std::unique_ptr;
using cpputils::Data; using cpputils::Data;
using cpputils::TempFile; using cpputils::TempFile;
using cpputils::TempDir; using cpputils::TempDir;
using cpputils::unique_ref;
using namespace blockstore; using namespace blockstore;
using namespace blockstore::ondisk; using namespace blockstore::ondisk;
@ -49,11 +50,11 @@ TEST_F(OnDiskBlockCreateTest, CreatingExistingBlockReturnsNull) {
class OnDiskBlockCreateSizeTest: public OnDiskBlockCreateTest, public WithParamInterface<size_t> { class OnDiskBlockCreateSizeTest: public OnDiskBlockCreateTest, public WithParamInterface<size_t> {
public: public:
unique_ptr<OnDiskBlock> block; unique_ref<OnDiskBlock> block;
Data ZEROES; Data ZEROES;
OnDiskBlockCreateSizeTest(): OnDiskBlockCreateSizeTest():
block(OnDiskBlock::CreateOnDisk(dir.path(), key, std::move(Data(GetParam()).FillWithZeroes()))), block(OnDiskBlock::CreateOnDisk(dir.path(), key, std::move(Data(GetParam()).FillWithZeroes())).value()),
ZEROES(block->size()) ZEROES(block->size())
{ {
ZEROES.FillWithZeroes(); ZEROES.FillWithZeroes();

View File

@ -14,6 +14,7 @@ using cpputils::Data;
using cpputils::DataFixture; using cpputils::DataFixture;
using cpputils::TempFile; using cpputils::TempFile;
using cpputils::TempDir; using cpputils::TempDir;
using cpputils::unique_ref;
using namespace blockstore; using namespace blockstore;
using namespace blockstore::ondisk; using namespace blockstore::ondisk;
@ -35,22 +36,23 @@ public:
Data randomData; Data randomData;
unique_ptr<OnDiskBlock> CreateBlockAndLoadItFromDisk() { unique_ref<OnDiskBlock> CreateBlockAndLoadItFromDisk() {
{ {
OnDiskBlock::CreateOnDisk(dir.path(), key, randomData.copy()); OnDiskBlock::CreateOnDisk(dir.path(), key, randomData.copy()).value();
} }
return OnDiskBlock::LoadFromDisk(dir.path(), key); //TODO Don't use nullcheck
return cpputils::nullcheck(OnDiskBlock::LoadFromDisk(dir.path(), key)).value();
} }
unique_ptr<OnDiskBlock> CreateBlock() { unique_ref<OnDiskBlock> CreateBlock() {
return OnDiskBlock::CreateOnDisk(dir.path(), key, randomData.copy()); return OnDiskBlock::CreateOnDisk(dir.path(), key, randomData.copy()).value();
} }
void WriteDataToBlock(const unique_ptr<OnDiskBlock> &block) { void WriteDataToBlock(const unique_ref<OnDiskBlock> &block) {
block->write(randomData.data(), 0, randomData.size()); block->write(randomData.data(), 0, randomData.size());
} }
void EXPECT_BLOCK_DATA_CORRECT(const unique_ptr<OnDiskBlock> &block) { void EXPECT_BLOCK_DATA_CORRECT(const unique_ref<OnDiskBlock> &block) {
EXPECT_EQ(randomData.size(), block->size()); EXPECT_EQ(randomData.size(), block->size());
EXPECT_EQ(0, std::memcmp(randomData.data(), block->data(), randomData.size())); EXPECT_EQ(0, std::memcmp(randomData.data(), block->data(), randomData.size()));
} }

View File

@ -15,13 +15,15 @@ using std::unique_ptr;
using std::make_unique; using std::make_unique;
using cpputils::Data; using cpputils::Data;
using cpputils::DataFixture; using cpputils::DataFixture;
using cpputils::unique_ref;
using boost::optional;
using namespace blockstore; using namespace blockstore;
class BlockStoreWithRandomKeysMock: public BlockStoreWithRandomKeys { class BlockStoreWithRandomKeysMock: public BlockStoreWithRandomKeys {
public: public:
unique_ptr<Block> tryCreate(const Key &key, Data data) { optional<unique_ref<Block>> tryCreate(const Key &key, Data data) {
return unique_ptr<Block>(do_create(key, data)); return cpputils::nullcheck(unique_ptr<Block>(do_create(key, data)));
} }
MOCK_METHOD2(do_create, Block*(const Key &, const Data &data)); MOCK_METHOD2(do_create, Block*(const Key &, const Data &data));
unique_ptr<Block> load(const Key &key) { unique_ptr<Block> load(const Key &key) {

View File

@ -60,7 +60,8 @@ TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterAddingOneBlock_AfterClosingB
TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterRemovingTheLastBlock) { TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterRemovingTheLastBlock) {
auto blockStore = this->fixture.createBlockStore(); auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->create(cpputils::Data(1)); auto block = blockStore->create(cpputils::Data(1));
blockStore->remove(std::move(block)); //TODO Don't use to_unique_ptr
blockStore->remove(cpputils::to_unique_ptr(std::move(block)));
EXPECT_EQ(0, blockStore->numBlocks()); EXPECT_EQ(0, blockStore->numBlocks());
} }
@ -96,7 +97,8 @@ TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterRemovingABlock) {
auto blockStore = this->fixture.createBlockStore(); auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->create(cpputils::Data(1)); auto block = blockStore->create(cpputils::Data(1));
blockStore->create(cpputils::Data(1)); blockStore->create(cpputils::Data(1));
blockStore->remove(std::move(block)); // TODO Don't use to_unique_ptr
blockStore->remove(cpputils::to_unique_ptr(std::move(block)));
EXPECT_EQ(1, blockStore->numBlocks()); EXPECT_EQ(1, blockStore->numBlocks());
} }

View File

@ -124,7 +124,7 @@ private:
return blockStore->load(key); return blockStore->load(key);
} }
std::unique_ptr<blockstore::Block> CreateBlock() { cpputils::unique_ref<blockstore::Block> CreateBlock() {
return blockStore->create(cpputils::Data(size)); return blockStore->create(cpputils::Data(size));
} }

View File

@ -31,46 +31,46 @@ TYPED_TEST_CASE_P(BlockStoreWithRandomKeysTest);
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSameSize) { TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSameSize) {
auto blockStore = this->fixture.createBlockStore(); auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->tryCreate(this->key, cpputils::Data(1024)); auto block = blockStore->tryCreate(this->key, cpputils::Data(1024));
block->flush(); (*block)->flush(); //TODO Ideally, flush shouldn't be necessary here.
auto block2 = blockStore->tryCreate(this->key, cpputils::Data(1024)); auto block2 = blockStore->tryCreate(this->key, cpputils::Data(1024));
EXPECT_TRUE((bool)block); EXPECT_NE(boost::none, block);
EXPECT_FALSE((bool)block2); EXPECT_EQ(boost::none, block2);
} }
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndDifferentSize) { TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndDifferentSize) {
auto blockStore = this->fixture.createBlockStore(); auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->tryCreate(this->key, cpputils::Data(1024)); auto block = blockStore->tryCreate(this->key, cpputils::Data(1024));
block->flush(); (*block)->flush(); //TODO Ideally, flush shouldn't be necessary here.
auto block2 = blockStore->tryCreate(this->key, cpputils::Data(4096)); auto block2 = blockStore->tryCreate(this->key, cpputils::Data(4096));
EXPECT_TRUE((bool)block); EXPECT_NE(boost::none, block);
EXPECT_FALSE((bool)block2); EXPECT_EQ(boost::none, block2);
} }
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndFirstNullSize) { TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndFirstNullSize) {
auto blockStore = this->fixture.createBlockStore(); auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->tryCreate(this->key, cpputils::Data(0)); auto block = blockStore->tryCreate(this->key, cpputils::Data(0));
block->flush(); (*block)->flush(); //TODO Ideally, flush shouldn't be necessary here.
auto block2 = blockStore->tryCreate(this->key, cpputils::Data(1024)); auto block2 = blockStore->tryCreate(this->key, cpputils::Data(1024));
EXPECT_TRUE((bool)block); EXPECT_NE(boost::none, block);
EXPECT_FALSE((bool)block2); EXPECT_EQ(boost::none, block2);
} }
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSecondNullSize) { TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSecondNullSize) {
auto blockStore = this->fixture.createBlockStore(); auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->tryCreate(this->key, cpputils::Data(1024)); auto block = blockStore->tryCreate(this->key, cpputils::Data(1024));
block->flush(); (*block)->flush(); //TODO Ideally, flush shouldn't be necessary here.
auto block2 = blockStore->tryCreate(this->key, cpputils::Data(0)); auto block2 = blockStore->tryCreate(this->key, cpputils::Data(0));
EXPECT_TRUE((bool)block); EXPECT_NE(boost::none, block);
EXPECT_FALSE((bool)block2); EXPECT_EQ(boost::none, block2);
} }
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndBothNullSize) { TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndBothNullSize) {
auto blockStore = this->fixture.createBlockStore(); auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->tryCreate(this->key, cpputils::Data(0)); auto block = blockStore->tryCreate(this->key, cpputils::Data(0));
block->flush(); (*block)->flush(); //TODO Ideally, flush shouldn't be necessary here.
auto block2 = blockStore->tryCreate(this->key, cpputils::Data(0)); auto block2 = blockStore->tryCreate(this->key, cpputils::Data(0));
EXPECT_TRUE((bool)block); EXPECT_NE(boost::none, block);
EXPECT_FALSE((bool)block2); EXPECT_EQ(boost::none, block2);
} }
REGISTER_TYPED_TEST_CASE_P(BlockStoreWithRandomKeysTest, REGISTER_TYPED_TEST_CASE_P(BlockStoreWithRandomKeysTest,

View File

@ -1,16 +1,15 @@
#include "../interface/BlockStore.h" #include "../interface/BlockStore.h"
#include "BlockStoreUtils.h" #include "BlockStoreUtils.h"
#include <messmer/cpp-utils/data/Data.h> #include <messmer/cpp-utils/data/Data.h>
#include <memory>
#include <cassert> #include <cassert>
using std::unique_ptr;
using cpputils::Data; using cpputils::Data;
using cpputils::unique_ref;
namespace blockstore { namespace blockstore {
namespace utils { namespace utils {
unique_ptr<Block> copyToNewBlock(BlockStore *blockStore, const Block &block) { unique_ref<Block> copyToNewBlock(BlockStore *blockStore, const Block &block) {
Data data(block.size()); Data data(block.size());
std::memcpy(data.data(), block.data(), block.size()); std::memcpy(data.data(), block.data(), block.size());
return blockStore->create(data); return blockStore->create(data);

View File

@ -2,14 +2,14 @@
#ifndef BLOCKSTORE_UTILS_BLOCKSTOREUTILS_H_ #ifndef BLOCKSTORE_UTILS_BLOCKSTOREUTILS_H_
#define BLOCKSTORE_UTILS_BLOCKSTOREUTILS_H_ #define BLOCKSTORE_UTILS_BLOCKSTOREUTILS_H_
#include <memory> #include <messmer/cpp-utils/pointer/unique_ref.h>
namespace blockstore { namespace blockstore {
class BlockStore; class BlockStore;
class Block; class Block;
namespace utils { namespace utils {
std::unique_ptr<Block> copyToNewBlock(BlockStore *blockStore, const Block &block); cpputils::unique_ref<Block> copyToNewBlock(BlockStore *blockStore, const Block &block);
void copyTo(Block *target, const Block &source); void copyTo(Block *target, const Block &source);
void fillWithZeroes(Block *target); void fillWithZeroes(Block *target);