Write factory methods in DataNode and write more test cases
This commit is contained in:
parent
1201823b68
commit
eebe8a4b75
@ -14,7 +14,7 @@ DataInnerNode::DataInnerNode(DataNodeView view)
|
|||||||
DataInnerNode::~DataInnerNode() {
|
DataInnerNode::~DataInnerNode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataInnerNode::InitializeNewInnerNode() {
|
void DataInnerNode::InitializeNewNode() {
|
||||||
*_node.MagicNumber() = _node.magicNumberNodeWithChildren;
|
*_node.MagicNumber() = _node.magicNumberNodeWithChildren;
|
||||||
*_node.Size() = 0;
|
*_node.Size() = 0;
|
||||||
}
|
}
|
||||||
|
@ -9,23 +9,23 @@ namespace onblocks {
|
|||||||
|
|
||||||
class DataInnerNode: public DataNode {
|
class DataInnerNode: public DataNode {
|
||||||
public:
|
public:
|
||||||
//TODO Creation of node objects should be in DataNode class (factory)
|
|
||||||
DataInnerNode(DataNodeView block);
|
DataInnerNode(DataNodeView block);
|
||||||
virtual ~DataInnerNode();
|
virtual ~DataInnerNode();
|
||||||
|
|
||||||
|
void InitializeNewNode();
|
||||||
|
|
||||||
struct ChildEntry {
|
struct ChildEntry {
|
||||||
uint32_t numBlocksInThisAndLeftwardNodes;
|
uint32_t numBlocksInThisAndLeftwardNodes;
|
||||||
uint8_t key[Key::KEYLENGTH_BINARY];
|
uint8_t key[Key::KEYLENGTH_BINARY];
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitializeNewInnerNode();
|
|
||||||
|
|
||||||
void read(off_t offset, size_t count, blockstore::Data *result) override;
|
void read(off_t offset, size_t count, blockstore::Data *result) override;
|
||||||
void write(off_t offset, size_t count, const blockstore::Data &data) override;
|
void write(off_t offset, size_t count, const blockstore::Data &data) override;
|
||||||
|
|
||||||
uint64_t numBytesInThisNode() override;
|
uint64_t numBytesInThisNode() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ChildEntry *ChildrenBegin();
|
ChildEntry *ChildrenBegin();
|
||||||
ChildEntry *ChildrenEnd();
|
ChildEntry *ChildrenEnd();
|
||||||
ChildEntry *ChildrenLast();
|
ChildEntry *ChildrenLast();
|
||||||
|
@ -26,7 +26,7 @@ void DataLeafNode::write(off_t offset, size_t count, const Data &data) {
|
|||||||
std::memcpy(_node.DataBegin<unsigned char>()+offset, data.data(), count);
|
std::memcpy(_node.DataBegin<unsigned char>()+offset, data.data(), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataLeafNode::InitializeNewLeafNode() {
|
void DataLeafNode::InitializeNewNode() {
|
||||||
*_node.MagicNumber() = _node.magicNumberLeaf;
|
*_node.MagicNumber() = _node.magicNumberLeaf;
|
||||||
*_node.Size() = 0;
|
*_node.Size() = 0;
|
||||||
}
|
}
|
||||||
|
@ -9,16 +9,14 @@ namespace onblocks {
|
|||||||
|
|
||||||
class DataLeafNode: public DataNode {
|
class DataLeafNode: public DataNode {
|
||||||
public:
|
public:
|
||||||
//TODO Creation of node objects should be in DataNode class (factory)
|
|
||||||
DataLeafNode(DataNodeView block);
|
DataLeafNode(DataNodeView block);
|
||||||
virtual ~DataLeafNode();
|
virtual ~DataLeafNode();
|
||||||
|
|
||||||
|
void InitializeNewNode();
|
||||||
|
|
||||||
void read(off_t offset, size_t count, blockstore::Data *result) override;
|
void read(off_t offset, size_t count, blockstore::Data *result) override;
|
||||||
void write(off_t offset, size_t count, const blockstore::Data &data) override;
|
void write(off_t offset, size_t count, const blockstore::Data &data) override;
|
||||||
|
|
||||||
//TODO This should then also only be accessible for the DataNode class in its factory methods (we can override a general Initialize() method here)
|
|
||||||
void InitializeNewLeafNode();
|
|
||||||
|
|
||||||
uint64_t numBytesInThisNode() override;
|
uint64_t numBytesInThisNode() override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -23,27 +23,26 @@ unique_ptr<DataNode> DataNode::load(unique_ptr<Block> block) {
|
|||||||
DataNodeView node(std::move(block));
|
DataNodeView node(std::move(block));
|
||||||
|
|
||||||
if (*node.MagicNumber() == node.magicNumberNodeWithChildren) {
|
if (*node.MagicNumber() == node.magicNumberNodeWithChildren) {
|
||||||
return make_unique<DataInnerNode>(std::move(node));
|
return unique_ptr<DataInnerNode>(new DataInnerNode(std::move(node)));
|
||||||
} else if (*node.MagicNumber() == node.magicNumberLeaf) {
|
} else if (*node.MagicNumber() == node.magicNumberLeaf) {
|
||||||
return make_unique<DataLeafNode>(std::move(node));
|
return unique_ptr<DataLeafNode>(new DataLeafNode(std::move(node)));
|
||||||
} else {
|
} else {
|
||||||
//TODO Better exception
|
//TODO Better exception
|
||||||
throw runtime_error("Invalid node magic number");
|
throw runtime_error("Invalid node magic number");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
unique_ptr<DataNode> DataNode::createNewInnerNode(unique_ptr<Block> block) {
|
||||||
unique_ptr<DataInnerNode> DataNodeView::initializeNewInnerNode(unique_ptr<Block> block) {
|
auto newNode = unique_ptr<DataInnerNode>(new DataInnerNode(std::move(block)));
|
||||||
auto newNode = make_unique<DataInnerNode>(std::move(block));
|
newNode->InitializeNewNode();
|
||||||
newNode->InitializeEmptyInnerNode();
|
return std::move(newNode);
|
||||||
return newNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<DataLeafNode> DataNodeView::initializeNewLeafNode(unique_ptr<Block> block) {
|
unique_ptr<DataNode> DataNode::createNewLeafNode(unique_ptr<Block> block) {
|
||||||
auto newNode = make_unique<DataLeafNode>(std::move(block));
|
auto newNode = unique_ptr<DataLeafNode>(new DataLeafNode(std::move(block)));
|
||||||
newNode->InitializeEmptyLeaf();
|
newNode->InitializeNewNode();
|
||||||
return newNode;
|
return std::move(newNode);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ public:
|
|||||||
virtual uint64_t numBytesInThisNode() = 0;
|
virtual uint64_t numBytesInThisNode() = 0;
|
||||||
|
|
||||||
static std::unique_ptr<DataNode> load(std::unique_ptr<blockstore::Block> block);
|
static std::unique_ptr<DataNode> load(std::unique_ptr<blockstore::Block> block);
|
||||||
|
static std::unique_ptr<DataNode> createNewLeafNode(std::unique_ptr<blockstore::Block> block);
|
||||||
|
static std::unique_ptr<DataNode> createNewInnerNode(std::unique_ptr<blockstore::Block> block);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DataNode(DataNodeView block);
|
DataNode(DataNodeView block);
|
||||||
|
@ -19,6 +19,8 @@ using blockstore::inmemory::InMemoryBlockStore;
|
|||||||
using namespace blobstore;
|
using namespace blobstore;
|
||||||
using namespace blobstore::onblocks;
|
using namespace blobstore::onblocks;
|
||||||
|
|
||||||
|
#define EXPECT_IS_PTR_TYPE(Type, ptr) EXPECT_NE(nullptr, dynamic_cast<Type*>(ptr)) << "Given pointer cannot be cast to the given type"
|
||||||
|
|
||||||
class DataLeafNodeTest: public Test {
|
class DataLeafNodeTest: public Test {
|
||||||
public:
|
public:
|
||||||
unique_ptr<BlockStore> blockStore = make_unique<InMemoryBlockStore>();
|
unique_ptr<BlockStore> blockStore = make_unique<InMemoryBlockStore>();
|
||||||
@ -31,14 +33,15 @@ public:
|
|||||||
|
|
||||||
Key WriteDataToNewLeafBlockAndReturnKey() {
|
Key WriteDataToNewLeafBlockAndReturnKey() {
|
||||||
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
|
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
|
||||||
DataLeafNode leaf(DataNodeView(std::move(block.block)));
|
auto leaf = DataNode::createNewLeafNode(std::move(block.block));
|
||||||
leaf.write(0, randomData.size(), randomData);
|
leaf->write(0, randomData.size(), randomData);
|
||||||
return block.key;
|
return block.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadDataFromLeafBlock(Key key, Data *data) {
|
void ReadDataFromLeafBlock(Key key, Data *data) {
|
||||||
DataLeafNode leaf(DataNodeView(blockStore->load(key)));
|
auto leaf = DataNode::load(blockStore->load(key));
|
||||||
leaf.read(0, data->size(), data);
|
EXPECT_IS_PTR_TYPE(DataLeafNode, leaf.get());
|
||||||
|
leaf->read(0, data->size(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Data randomData;
|
Data randomData;
|
||||||
@ -46,11 +49,11 @@ public:
|
|||||||
|
|
||||||
TEST_F(DataLeafNodeTest, ReadWrittenDataImmediately) {
|
TEST_F(DataLeafNodeTest, ReadWrittenDataImmediately) {
|
||||||
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
|
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
|
||||||
DataLeafNode leaf(DataNodeView(std::move(block.block)));
|
auto leaf = DataNode::createNewLeafNode(std::move(block.block));
|
||||||
leaf.write(0, randomData.size(), randomData);
|
leaf->write(0, randomData.size(), randomData);
|
||||||
|
|
||||||
Data read(DataNodeView::DATASIZE_BYTES);
|
Data read(DataNodeView::DATASIZE_BYTES);
|
||||||
leaf.read(0, read.size(), &read);
|
leaf->read(0, read.size(), &read);
|
||||||
EXPECT_EQ(0, std::memcmp(randomData.data(), read.data(), randomData.size()));
|
EXPECT_EQ(0, std::memcmp(randomData.data(), read.data(), randomData.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,5 +66,21 @@ TEST_F(DataLeafNodeTest, ReadWrittenDataAfterReloadingBLock) {
|
|||||||
EXPECT_EQ(0, std::memcmp(randomData.data(), data.data(), randomData.size()));
|
EXPECT_EQ(0, std::memcmp(randomData.data(), data.data(), randomData.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DataLeafNodeTest, NewLeafNodeHasSizeZero) {
|
||||||
|
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
|
||||||
|
auto leaf = DataNode::createNewLeafNode(std::move(block.block));
|
||||||
|
EXPECT_EQ(0u, leaf->numBytesInThisNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DataLeafNodeTest, NewLeafNodeHasSizeZero_AfterLoading) {
|
||||||
|
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
|
||||||
|
{
|
||||||
|
DataNode::createNewLeafNode(std::move(block.block));
|
||||||
|
}
|
||||||
|
auto leaf = DataNode::load(blockStore->load(block.key));
|
||||||
|
|
||||||
|
EXPECT_EQ(0u, leaf->numBytesInThisNode());
|
||||||
|
}
|
||||||
|
|
||||||
//TODO Write tests that only read part of the data
|
//TODO Write tests that only read part of the data
|
||||||
//TODO Test numBytesInThisNode()
|
//TODO Test numBytesInThisNode()
|
||||||
|
@ -24,11 +24,23 @@ public:
|
|||||||
|
|
||||||
#define EXPECT_IS_PTR_TYPE(Type, ptr) EXPECT_NE(nullptr, dynamic_cast<Type*>(ptr)) << "Given pointer cannot be cast to the given type"
|
#define EXPECT_IS_PTR_TYPE(Type, ptr) EXPECT_NE(nullptr, dynamic_cast<Type*>(ptr)) << "Given pointer cannot be cast to the given type"
|
||||||
|
|
||||||
|
TEST_F(DataNodeTest, CreateLeafNodeCreatesLeafNode) {
|
||||||
|
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
|
||||||
|
auto node = DataNode::createNewLeafNode(std::move(block.block));
|
||||||
|
EXPECT_IS_PTR_TYPE(DataLeafNode, node.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DataNodeTest, CreateInnerNodeCreatesInnerNode) {
|
||||||
|
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
|
||||||
|
auto node = DataNode::createNewInnerNode(std::move(block.block));
|
||||||
|
EXPECT_IS_PTR_TYPE(DataInnerNode, node.get());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(DataNodeTest, LeafNodeIsRecognizedAfterStoreAndLoad) {
|
TEST_F(DataNodeTest, LeafNodeIsRecognizedAfterStoreAndLoad) {
|
||||||
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
|
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
|
||||||
Key key = block.key;
|
Key key = block.key;
|
||||||
{
|
{
|
||||||
DataLeafNode(std::move(block.block)).InitializeNewLeafNode();
|
DataNode::createNewLeafNode(std::move(block.block));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto loaded_node = DataNode::load(blockStore->load(key));
|
auto loaded_node = DataNode::load(blockStore->load(key));
|
||||||
@ -40,7 +52,7 @@ TEST_F(DataNodeTest, InnerNodeIsRecognizedAfterStoreAndLoad) {
|
|||||||
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
|
auto block = blockStore->create(BlobStoreOnBlocks::BLOCKSIZE);
|
||||||
Key key = block.key;
|
Key key = block.key;
|
||||||
{
|
{
|
||||||
DataInnerNode(std::move(block.block)).InitializeNewInnerNode();
|
DataNode::createNewInnerNode(std::move(block.block));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto loaded_node = DataNode::load(blockStore->load(key));
|
auto loaded_node = DataNode::load(blockStore->load(key));
|
||||||
|
Loading…
Reference in New Issue
Block a user