BlobStore handles unique_ref<Blob> instead of unique_ptr<Blob>

This commit is contained in:
Sebastian Meßmer 2015-06-18 12:45:37 +02:00
parent c4f55f081a
commit 5039205cd2
7 changed files with 61 additions and 34 deletions

View File

@ -12,10 +12,15 @@
using std::unique_ptr; using std::unique_ptr;
using std::make_unique; using std::make_unique;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using blockstore::BlockStore; using blockstore::BlockStore;
using blockstore::parallelaccess::ParallelAccessBlockStore; using blockstore::parallelaccess::ParallelAccessBlockStore;
using blockstore::Key; using blockstore::Key;
using cpputils::dynamic_pointer_move; using cpputils::dynamic_pointer_move;
using boost::optional;
using boost::none;
namespace blobstore { namespace blobstore {
namespace onblocks { namespace onblocks {
@ -31,19 +36,19 @@ BlobStoreOnBlocks::BlobStoreOnBlocks(unique_ptr<BlockStore> blockStore, uint32_t
BlobStoreOnBlocks::~BlobStoreOnBlocks() { BlobStoreOnBlocks::~BlobStoreOnBlocks() {
} }
unique_ptr<Blob> BlobStoreOnBlocks::create() { unique_ref<Blob> BlobStoreOnBlocks::create() {
return make_unique<BlobOnBlocks>(_dataTreeStore->createNewTree()); return make_unique_ref<BlobOnBlocks>(_dataTreeStore->createNewTree());
} }
unique_ptr<Blob> BlobStoreOnBlocks::load(const Key &key) { optional<unique_ref<Blob>> BlobStoreOnBlocks::load(const Key &key) {
auto tree = _dataTreeStore->load(key); auto tree = _dataTreeStore->load(key);
if (tree == nullptr) { if (tree == nullptr) {
return nullptr; return none;
} }
return make_unique<BlobOnBlocks>(std::move(tree)); return optional<unique_ref<Blob>>(make_unique_ref<BlobOnBlocks>(std::move(tree)));
} }
void BlobStoreOnBlocks::remove(unique_ptr<Blob> blob) { void BlobStoreOnBlocks::remove(unique_ref<Blob> blob) {
auto _blob = dynamic_pointer_move<BlobOnBlocks>(blob); auto _blob = dynamic_pointer_move<BlobOnBlocks>(blob);
_dataTreeStore->remove(_blob->releaseTree()); _dataTreeStore->remove(_blob->releaseTree());
} }

View File

@ -18,10 +18,10 @@ public:
BlobStoreOnBlocks(std::unique_ptr<blockstore::BlockStore> blockStore, uint32_t blocksizeBytes); BlobStoreOnBlocks(std::unique_ptr<blockstore::BlockStore> blockStore, uint32_t blocksizeBytes);
virtual ~BlobStoreOnBlocks(); virtual ~BlobStoreOnBlocks();
std::unique_ptr<Blob> create() override; cpputils::unique_ref<Blob> create() override;
std::unique_ptr<Blob> load(const blockstore::Key &key) override; boost::optional<cpputils::unique_ref<Blob>> load(const blockstore::Key &key) override;
void remove(std::unique_ptr<Blob> blob) override; void remove(cpputils::unique_ref<Blob> blob) override;
private: private:
std::unique_ptr<parallelaccessdatatreestore::ParallelAccessDataTreeStore> _dataTreeStore; std::unique_ptr<parallelaccessdatatreestore::ParallelAccessDataTreeStore> _dataTreeStore;

View File

@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "messmer/blockstore/utils/Key.h" #include "messmer/blockstore/utils/Key.h"
#include <messmer/cpp-utils/unique_ref.h>
namespace blobstore { namespace blobstore {
@ -14,11 +15,9 @@ class BlobStore {
public: public:
virtual ~BlobStore() {} virtual ~BlobStore() {}
virtual std::unique_ptr<Blob> create() = 0; virtual cpputils::unique_ref<Blob> create() = 0;
//TODO Use boost::optional (if key doesn't exist) virtual boost::optional<cpputils::unique_ref<Blob>> load(const blockstore::Key &key) = 0;
// Return nullptr if block with this key doesn't exists virtual void remove(cpputils::unique_ref<Blob> blob) = 0;
virtual std::unique_ptr<Blob> load(const blockstore::Key &key) = 0;
virtual void remove(std::unique_ptr<Blob> blob) = 0;
}; };
} }

View File

@ -3,7 +3,7 @@
#include <messmer/cpp-utils/data/DataFixture.h> #include <messmer/cpp-utils/data/DataFixture.h>
#include "../../../implementations/onblocks/datanodestore/DataNodeView.h" #include "../../../implementations/onblocks/datanodestore/DataNodeView.h"
using std::unique_ptr; using cpputils::unique_ref;
using ::testing::WithParamInterface; using ::testing::WithParamInterface;
using ::testing::Values; using ::testing::Values;
@ -37,7 +37,7 @@ public:
} }
Data randomData; Data randomData;
unique_ptr<Blob> blob; unique_ref<Blob> blob;
}; };
constexpr uint32_t BlobReadWriteTest::LARGE_SIZE; constexpr uint32_t BlobReadWriteTest::LARGE_SIZE;
constexpr DataNodeLayout BlobReadWriteTest::LAYOUT; constexpr DataNodeLayout BlobReadWriteTest::LAYOUT;
@ -45,14 +45,14 @@ constexpr DataNodeLayout BlobReadWriteTest::LAYOUT;
TEST_F(BlobReadWriteTest, WritingImmediatelyFlushes_SmallSize) { TEST_F(BlobReadWriteTest, WritingImmediatelyFlushes_SmallSize) {
blob->resize(5); blob->resize(5);
blob->write(randomData.data(), 0, 5); blob->write(randomData.data(), 0, 5);
auto loaded = blobStore->load(blob->key()); auto loaded = loadBlob(blob->key());
EXPECT_DATA_READS_AS(randomData, *loaded, 0, 5); EXPECT_DATA_READS_AS(randomData, *loaded, 0, 5);
} }
TEST_F(BlobReadWriteTest, WritingImmediatelyFlushes_LargeSize) { TEST_F(BlobReadWriteTest, WritingImmediatelyFlushes_LargeSize) {
blob->resize(LARGE_SIZE); blob->resize(LARGE_SIZE);
blob->write(randomData.data(), 0, LARGE_SIZE); blob->write(randomData.data(), 0, LARGE_SIZE);
auto loaded = blobStore->load(blob->key()); auto loaded = loadBlob(blob->key());
EXPECT_DATA_READS_AS(randomData, *loaded, 0, LARGE_SIZE); EXPECT_DATA_READS_AS(randomData, *loaded, 0, LARGE_SIZE);
} }
@ -127,7 +127,7 @@ TEST_P(BlobReadWriteDataTest, WriteAndReadImmediately) {
TEST_P(BlobReadWriteDataTest, WriteAndReadAfterLoading) { TEST_P(BlobReadWriteDataTest, WriteAndReadAfterLoading) {
blob->resize(GetParam().blobsize); blob->resize(GetParam().blobsize);
blob->write(this->foregroundData.data(), GetParam().offset, GetParam().count); blob->write(this->foregroundData.data(), GetParam().offset, GetParam().count);
auto loaded = blobStore->load(blob->key()); auto loaded = loadBlob(blob->key());
EXPECT_DATA_READS_AS(this->foregroundData, *loaded, GetParam().offset, GetParam().count); EXPECT_DATA_READS_AS(this->foregroundData, *loaded, GetParam().offset, GetParam().count);
EXPECT_DATA_IS_ZEROES_OUTSIDE_OF(*loaded, GetParam().offset, GetParam().count); EXPECT_DATA_IS_ZEROES_OUTSIDE_OF(*loaded, GetParam().offset, GetParam().count);

View File

@ -2,12 +2,11 @@
#include <messmer/cpp-utils/data/Data.h> #include <messmer/cpp-utils/data/Data.h>
#include <messmer/cpp-utils/data/DataFixture.h> #include <messmer/cpp-utils/data/DataFixture.h>
using std::unique_ptr;
using namespace blobstore; using namespace blobstore;
using blockstore::Key; using blockstore::Key;
using cpputils::Data; using cpputils::Data;
using cpputils::DataFixture; using cpputils::DataFixture;
using cpputils::unique_ref;
class BlobSizeTest: public BlobStoreTest { class BlobSizeTest: public BlobStoreTest {
public: public:
@ -16,7 +15,7 @@ public:
static constexpr uint32_t MEDIUM_SIZE = 5 * 1024 * 1024; static constexpr uint32_t MEDIUM_SIZE = 5 * 1024 * 1024;
static constexpr uint32_t LARGE_SIZE = 10 * 1024 * 1024; static constexpr uint32_t LARGE_SIZE = 10 * 1024 * 1024;
unique_ptr<Blob> blob; unique_ref<Blob> blob;
}; };
constexpr uint32_t BlobSizeTest::MEDIUM_SIZE; constexpr uint32_t BlobSizeTest::MEDIUM_SIZE;
constexpr uint32_t BlobSizeTest::LARGE_SIZE; constexpr uint32_t BlobSizeTest::LARGE_SIZE;
@ -66,16 +65,16 @@ TEST_F(BlobSizeTest, ResizingToItself_Large) {
TEST_F(BlobSizeTest, EmptyBlobStaysEmptyWhenLoading) { TEST_F(BlobSizeTest, EmptyBlobStaysEmptyWhenLoading) {
Key key = blob->key(); Key key = blob->key();
blob.reset(); reset(std::move(blob));
auto loaded = blobStore->load(key); auto loaded = loadBlob(key);
EXPECT_EQ(0, loaded->size()); EXPECT_EQ(0, loaded->size());
} }
TEST_F(BlobSizeTest, BlobSizeStaysIntactWhenLoading) { TEST_F(BlobSizeTest, BlobSizeStaysIntactWhenLoading) {
blob->resize(LARGE_SIZE); blob->resize(LARGE_SIZE);
Key key = blob->key(); Key key = blob->key();
blob.reset(); reset(std::move(blob));
auto loaded = blobStore->load(key); auto loaded = loadBlob(key);
EXPECT_EQ(LARGE_SIZE, loaded->size()); EXPECT_EQ(LARGE_SIZE, loaded->size());
} }
@ -114,7 +113,7 @@ TEST_F(BlobSizeTest, WritingAfterEndOfBlobGrowsBlob_NonEmpty) {
TEST_F(BlobSizeTest, ChangingSizeImmediatelyFlushes) { TEST_F(BlobSizeTest, ChangingSizeImmediatelyFlushes) {
blob->resize(LARGE_SIZE); blob->resize(LARGE_SIZE);
auto loaded = blobStore->load(blob->key()); auto loaded = loadBlob(blob->key());
EXPECT_EQ(LARGE_SIZE, loaded->size()); EXPECT_EQ(LARGE_SIZE, loaded->size());
} }
@ -143,7 +142,7 @@ TEST_F(BlobSizeDataTest, BlobIsZeroedOutAfterGrowing) {
TEST_F(BlobSizeDataTest, BlobIsZeroedOutAfterGrowingAndLoading) { TEST_F(BlobSizeDataTest, BlobIsZeroedOutAfterGrowingAndLoading) {
blob->resize(LARGE_SIZE); blob->resize(LARGE_SIZE);
auto loaded = blobStore->load(blob->key()); auto loaded = loadBlob(blob->key());
EXPECT_EQ(0, std::memcmp(readBlob(*loaded).data(), ZEROES.data(), LARGE_SIZE)); EXPECT_EQ(0, std::memcmp(readBlob(*loaded).data(), ZEROES.data(), LARGE_SIZE));
} }

View File

@ -1,16 +1,29 @@
#include "testutils/BlobStoreTest.h" #include "testutils/BlobStoreTest.h"
#include <boost/optional/optional_io.hpp>
using blockstore::Key; using blockstore::Key;
using cpputils::unique_ref;
using blobstore::Blob;
using boost::none;
//gtest/boost::optional workaround for working with optional<unique_ref<T>>
namespace boost {
std::ostream& operator<<(std::ostream& out, const unique_ref<Blob> &ref) {
out << "[" << ref->key().ToString() << "]" << ref.get();
return out;
}
}
TEST_F(BlobStoreTest, LoadNonexistingKeyOnEmptyBlobstore) { TEST_F(BlobStoreTest, LoadNonexistingKeyOnEmptyBlobstore) {
const blockstore::Key key = blockstore::Key::FromString("1491BB4932A389EE14BC7090AC772972"); const blockstore::Key key = blockstore::Key::FromString("1491BB4932A389EE14BC7090AC772972");
EXPECT_EQ(nullptr, blobStore->load(key)); EXPECT_EQ(none, blobStore->load(key));
} }
TEST_F(BlobStoreTest, LoadNonexistingKeyOnNonEmptyBlobstore) { TEST_F(BlobStoreTest, LoadNonexistingKeyOnNonEmptyBlobstore) {
blobStore->create(); blobStore->create();
const blockstore::Key key = blockstore::Key::FromString("1491BB4932A389EE14BC7090AC772972"); const blockstore::Key key = blockstore::Key::FromString("1491BB4932A389EE14BC7090AC772972");
EXPECT_EQ(nullptr, blobStore->load(key)); EXPECT_EQ(none, blobStore->load(key));
} }
TEST_F(BlobStoreTest, TwoCreatedBlobsHaveDifferentKeys) { TEST_F(BlobStoreTest, TwoCreatedBlobsHaveDifferentKeys) {
@ -23,13 +36,13 @@ TEST_F(BlobStoreTest, BlobIsNotLoadableAfterDeletion_DeleteDirectly) {
auto blob = blobStore->create(); auto blob = blobStore->create();
Key key = blob->key(); Key key = blob->key();
blobStore->remove(std::move(blob)); blobStore->remove(std::move(blob));
EXPECT_EQ(nullptr, blobStore->load(key).get()); EXPECT_FALSE((bool)blobStore->load(key));
} }
TEST_F(BlobStoreTest, BlobIsNotLoadableAfterDeletion_DeleteAfterLoading) { TEST_F(BlobStoreTest, BlobIsNotLoadableAfterDeletion_DeleteAfterLoading) {
auto blob = blobStore->create(); auto blob = blobStore->create();
Key key = blob->key(); Key key = blob->key();
blob.reset(); reset(std::move(blob));
blobStore->remove(blobStore->load(key)); blobStore->remove(loadBlob(key));
EXPECT_EQ(nullptr, blobStore->load(key).get()); EXPECT_FALSE((bool)blobStore->load(key));
} }

View File

@ -9,4 +9,15 @@ public:
static constexpr uint32_t BLOCKSIZE_BYTES = 4096; static constexpr uint32_t BLOCKSIZE_BYTES = 4096;
std::unique_ptr<blobstore::BlobStore> blobStore; std::unique_ptr<blobstore::BlobStore> blobStore;
cpputils::unique_ref<blobstore::Blob> loadBlob(const blockstore::Key &key) {
auto loaded = blobStore->load(key);
EXPECT_TRUE((bool)loaded);
return std::move(*loaded);
}
void reset(cpputils::unique_ref<blobstore::Blob> ref) {
UNUSED(ref);
//ref is moved into here and then destructed
}
}; };