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 cpputils::dynamic_pointer_move;
using cpputils::Data;
using boost::optional;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using boost::none;
namespace blockstore {
namespace caching {
@ -22,9 +26,10 @@ Key CachingBlockStore::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;
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) {
@ -64,9 +69,9 @@ void CachingBlockStore::release(unique_ptr<Block> 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));
if (block.get() != nullptr) {
if (block != none) {
--_numNewBlocks;
}
return block;

View File

@ -14,14 +14,14 @@ public:
explicit CachingBlockStore(std::unique_ptr<BlockStore> baseBlockStore);
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;
void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override;
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);
private:

View File

@ -32,9 +32,11 @@ void NewBlock::write(const void *source, uint64_t offset, uint64_t size) {
void NewBlock::writeToBaseBlockIfChanged() {
if (_dataChanged) {
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?
_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 {
_baseBlock->write(_data.data(), 0, _data.size());
}

View File

@ -22,7 +22,7 @@ template<class Cipher>
class EncryptedBlock: public Block {
public:
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);
//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>
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 encrypted = Cipher::encrypt((byte*)plaintextWithHeader.data(), plaintextWithHeader.size(), encKey);
auto baseBlock = baseBlockStore->tryCreate(key, std::move(encrypted));
if (baseBlock.get() == nullptr) {
if (baseBlock == boost::none) {
//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>

View File

@ -18,7 +18,7 @@ public:
//TODO Are createKey() tests included in generic BlockStoreTest? If not, add it!
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;
void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override;
@ -46,9 +46,14 @@ Key EncryptedBlockStore<Cipher>::createKey() {
}
template<class Cipher>
std::unique_ptr<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)
return EncryptedBlock<Cipher>::TryCreateNew(_baseBlockStore.get(), key, std::move(data), _encKey);
boost::optional<cpputils::unique_ref<Block>> EncryptedBlockStore<Cipher>::tryCreate(const Key &key, cpputils::Data data) {
//TODO Test that this returns boost::none when base blockstore returns nullptr (for all pass-through-blockstores)
//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>

View File

@ -10,6 +10,10 @@ using std::lock_guard;
using std::piecewise_construct;
using std::make_tuple;
using cpputils::Data;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using boost::optional;
using boost::none;
namespace blockstore {
namespace inmemory {
@ -17,15 +21,15 @@ namespace inmemory {
InMemoryBlockStore::InMemoryBlockStore()
: _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)));
if (!insert_result.second) {
return nullptr;
return none;
}
//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) {

View File

@ -16,7 +16,7 @@ class InMemoryBlockStore: public BlockStoreWithRandomKeys {
public:
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;
void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override;

View File

@ -13,6 +13,10 @@ using std::ifstream;
using std::ofstream;
using std::ios;
using cpputils::Data;
using cpputils::make_unique_ref;
using cpputils::unique_ref;
using boost::optional;
using boost::none;
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();
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();
return block;
return std::move(block);
}
void OnDiskBlock::RemoveFromDisk(const bf::path &rootdir, const Key &key) {

View File

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

View File

@ -5,6 +5,9 @@ using std::unique_ptr;
using std::make_unique;
using std::string;
using cpputils::Data;
using cpputils::unique_ref;
using boost::optional;
using boost::none;
namespace bf = boost::filesystem;
@ -14,13 +17,13 @@ namespace ondisk {
OnDiskBlockStore::OnDiskBlockStore(const boost::filesystem::path &rootdir)
: _rootdir(rootdir) {}
unique_ptr<Block> OnDiskBlockStore::tryCreate(const Key &key, Data data) {
auto block = OnDiskBlock::CreateOnDisk(_rootdir, key, std::move(data));
if (!block) {
return nullptr;
optional<unique_ref<Block>> OnDiskBlockStore::tryCreate(const Key &key, Data 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 (result == boost::none) {
return boost::none;
}
return std::move(block);
return unique_ref<Block>(std::move(*result));
}
unique_ptr<Block> OnDiskBlockStore::load(const Key &key) {

View File

@ -14,7 +14,7 @@ class OnDiskBlockStore: public BlockStoreWithRandomKeys {
public:
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;
void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override;

View File

@ -15,6 +15,9 @@ using cpputils::dynamic_pointer_move;
using cpputils::make_unique_ref;
using boost::none;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using boost::optional;
using boost::none;
namespace blockstore {
namespace parallelaccess {
@ -27,14 +30,13 @@ Key ParallelAccessBlockStore::createKey() {
return _baseBlockStore->createKey();
}
unique_ptr<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 = cpputils::nullcheck(_baseBlockStore->tryCreate(key, std::move(data)));
optional<unique_ref<Block>> ParallelAccessBlockStore::tryCreate(const Key &key, cpputils::Data data) {
auto block = _baseBlockStore->tryCreate(key, std::move(data));
if (block == none) {
//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) {

View File

@ -16,7 +16,7 @@ public:
explicit ParallelAccessBlockStore(cpputils::unique_ref<BlockStore> baseBlockStore);
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;
void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override;

View File

@ -8,6 +8,10 @@ using std::string;
using std::mutex;
using std::lock_guard;
using cpputils::Data;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using boost::optional;
using boost::none;
namespace blockstore {
namespace testfake {
@ -15,15 +19,16 @@ namespace testfake {
FakeBlockStore::FakeBlockStore()
: _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));
if (!insert_result.second) {
return nullptr;
return none;
}
//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) {

View File

@ -31,7 +31,7 @@ class FakeBlockStore: public BlockStoreWithRandomKeys {
public:
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;
void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override;

View File

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

View File

@ -12,6 +12,7 @@ using std::unique_ptr;
using cpputils::Data;
using cpputils::TempFile;
using cpputils::TempDir;
using cpputils::unique_ref;
using namespace blockstore;
using namespace blockstore::ondisk;
@ -49,11 +50,11 @@ TEST_F(OnDiskBlockCreateTest, CreatingExistingBlockReturnsNull) {
class OnDiskBlockCreateSizeTest: public OnDiskBlockCreateTest, public WithParamInterface<size_t> {
public:
unique_ptr<OnDiskBlock> block;
unique_ref<OnDiskBlock> block;
Data ZEROES;
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.FillWithZeroes();

View File

@ -14,6 +14,7 @@ using cpputils::Data;
using cpputils::DataFixture;
using cpputils::TempFile;
using cpputils::TempDir;
using cpputils::unique_ref;
using namespace blockstore;
using namespace blockstore::ondisk;
@ -35,22 +36,23 @@ public:
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() {
return OnDiskBlock::CreateOnDisk(dir.path(), key, randomData.copy());
unique_ref<OnDiskBlock> CreateBlock() {
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());
}
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(0, std::memcmp(randomData.data(), block->data(), randomData.size()));
}

View File

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

View File

@ -60,7 +60,8 @@ TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterAddingOneBlock_AfterClosingB
TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterRemovingTheLastBlock) {
auto blockStore = this->fixture.createBlockStore();
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());
}
@ -96,7 +97,8 @@ TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterRemovingABlock) {
auto blockStore = this->fixture.createBlockStore();
auto block = 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());
}

View File

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

View File

@ -31,46 +31,46 @@ TYPED_TEST_CASE_P(BlockStoreWithRandomKeysTest);
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSameSize) {
auto blockStore = this->fixture.createBlockStore();
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));
EXPECT_TRUE((bool)block);
EXPECT_FALSE((bool)block2);
EXPECT_NE(boost::none, block);
EXPECT_EQ(boost::none, block2);
}
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndDifferentSize) {
auto blockStore = this->fixture.createBlockStore();
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));
EXPECT_TRUE((bool)block);
EXPECT_FALSE((bool)block2);
EXPECT_NE(boost::none, block);
EXPECT_EQ(boost::none, block2);
}
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndFirstNullSize) {
auto blockStore = this->fixture.createBlockStore();
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));
EXPECT_TRUE((bool)block);
EXPECT_FALSE((bool)block2);
EXPECT_NE(boost::none, block);
EXPECT_EQ(boost::none, block2);
}
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSecondNullSize) {
auto blockStore = this->fixture.createBlockStore();
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));
EXPECT_TRUE((bool)block);
EXPECT_FALSE((bool)block2);
EXPECT_NE(boost::none, block);
EXPECT_EQ(boost::none, block2);
}
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndBothNullSize) {
auto blockStore = this->fixture.createBlockStore();
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));
EXPECT_TRUE((bool)block);
EXPECT_FALSE((bool)block2);
EXPECT_NE(boost::none, block);
EXPECT_EQ(boost::none, block2);
}
REGISTER_TYPED_TEST_CASE_P(BlockStoreWithRandomKeysTest,

View File

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

View File

@ -2,14 +2,14 @@
#ifndef BLOCKSTORE_UTILS_BLOCKSTOREUTILS_H_
#define BLOCKSTORE_UTILS_BLOCKSTOREUTILS_H_
#include <memory>
#include <messmer/cpp-utils/pointer/unique_ref.h>
namespace blockstore {
class BlockStore;
class Block;
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 fillWithZeroes(Block *target);