diff --git a/src/blobstore/implementations/onblocks/datanodestore/DataNode.h b/src/blobstore/implementations/onblocks/datanodestore/DataNode.h index 9bfa98fc..2308fe26 100644 --- a/src/blobstore/implementations/onblocks/datanodestore/DataNode.h +++ b/src/blobstore/implementations/onblocks/datanodestore/DataNode.h @@ -26,6 +26,7 @@ protected: DataNodeView &node(); const DataNodeView &node() const; + friend class DataNodeStore; private: blockstore::Key _key; //TODO Remove this and make blockstore::Block store the key diff --git a/src/blobstore/implementations/onblocks/datanodestore/DataNodeStore.cpp b/src/blobstore/implementations/onblocks/datanodestore/DataNodeStore.cpp index 264c589f..f76239e4 100644 --- a/src/blobstore/implementations/onblocks/datanodestore/DataNodeStore.cpp +++ b/src/blobstore/implementations/onblocks/datanodestore/DataNodeStore.cpp @@ -3,6 +3,7 @@ #include "DataNodeStore.h" #include "blockstore/interface/BlockStore.h" #include "blockstore/interface/Block.h" +#include "blockstore/utils/BlockStoreUtils.h" using blockstore::BlockStore; @@ -53,6 +54,11 @@ unique_ptr DataNodeStore::load(const Key &key) { return load(_blockstore->load(key), key); } +unique_ptr DataNodeStore::createNewNodeAsCopyFrom(const DataNode &source) { + auto newBlock = blockstore::utils::copyToNewBlock(_blockstore.get(), source.node().block()); + return load(std::move(newBlock.block), newBlock.key); +} + } } } diff --git a/src/blobstore/implementations/onblocks/datanodestore/DataNodeStore.h b/src/blobstore/implementations/onblocks/datanodestore/DataNodeStore.h index 0f8d03bc..43749f73 100644 --- a/src/blobstore/implementations/onblocks/datanodestore/DataNodeStore.h +++ b/src/blobstore/implementations/onblocks/datanodestore/DataNodeStore.h @@ -30,6 +30,8 @@ public: std::unique_ptr createNewLeafNode(); std::unique_ptr createNewInnerNode(const DataNode &first_child); + std::unique_ptr createNewNodeAsCopyFrom(const DataNode &source); + private: std::unique_ptr load(std::unique_ptr block, const blockstore::Key &key); diff --git a/src/blobstore/implementations/onblocks/datanodestore/DataNodeView.h b/src/blobstore/implementations/onblocks/datanodestore/DataNodeView.h index 48e99246..97617da5 100644 --- a/src/blobstore/implementations/onblocks/datanodestore/DataNodeView.h +++ b/src/blobstore/implementations/onblocks/datanodestore/DataNodeView.h @@ -76,6 +76,10 @@ public: return std::move(_block); } + const blockstore::Block &block() const { + return *_block; + } + private: template const Type *GetOffset() const { diff --git a/src/blobstore/implementations/onblocks/datatreestore/DataTree.cpp b/src/blobstore/implementations/onblocks/datatreestore/DataTree.cpp index d4f1df0a..86441a4c 100644 --- a/src/blobstore/implementations/onblocks/datatreestore/DataTree.cpp +++ b/src/blobstore/implementations/onblocks/datatreestore/DataTree.cpp @@ -76,19 +76,13 @@ optional_ownership_ptr DataTree::createChainOfInnerNodes(unsigned int } unique_ptr DataTree::addDataLeafToFullTree() { - auto copyOfOldRoot = copyNode(*_rootNode); + auto copyOfOldRoot = _nodeStore->createNewNodeAsCopyFrom(*_rootNode); auto newRootNode = DataNode::convertToNewInnerNode(std::move(_rootNode), *copyOfOldRoot); auto newLeaf = addDataLeafAt(newRootNode.get()); _rootNode = std::move(newRootNode); return newLeaf; } -unique_ptr DataTree::copyNode(const DataNode &source) { - //TODO - assert(false); - return nullptr; -} - } diff --git a/src/blobstore/implementations/onblocks/datatreestore/DataTree.h b/src/blobstore/implementations/onblocks/datatreestore/DataTree.h index 56e2dbce..02055a86 100644 --- a/src/blobstore/implementations/onblocks/datatreestore/DataTree.h +++ b/src/blobstore/implementations/onblocks/datatreestore/DataTree.h @@ -31,7 +31,6 @@ private: std::unique_ptr addDataLeafAt(datanodestore::DataInnerNode *insertPos); fspp::ptr::optional_ownership_ptr createChainOfInnerNodes(unsigned int num, datanodestore::DataLeafNode *leaf); std::unique_ptr addDataLeafToFullTree(); - std::unique_ptr copyNode(const datanodestore::DataNode &source); DISALLOW_COPY_AND_ASSIGN(DataTree); }; diff --git a/src/test/blobstore/implementations/onblocks/datanodestore/DataInnerNodeTest.cpp b/src/test/blobstore/implementations/onblocks/datanodestore/DataInnerNodeTest.cpp index 4883a5bd..6aae7193 100644 --- a/src/test/blobstore/implementations/onblocks/datanodestore/DataInnerNodeTest.cpp +++ b/src/test/blobstore/implementations/onblocks/datanodestore/DataInnerNodeTest.cpp @@ -87,6 +87,11 @@ public: return converted->key(); } + unique_ptr CopyInnerNode(const DataInnerNode &node) { + auto copied = nodeStore->createNewNodeAsCopyFrom(node); + return dynamic_pointer_move(copied); + } + Data ZEROES; unique_ptr _blockStore; BlockStore *blockStore; @@ -169,5 +174,26 @@ TEST_F(DataInnerNodeTest, ConvertToInternalNodeZeroesOutChildrenRegion) { EXPECT_EQ(0, std::memcmp(ZEROES.data(), (uint8_t*)block->data()+DataNodeView::HEADERSIZE_BYTES+sizeof(DataInnerNode::ChildEntry), DataLeafNode::MAX_STORED_BYTES-sizeof(DataInnerNode::ChildEntry))); } +TEST_F(DataInnerNodeTest, CopyingCreatesNewNode) { + auto copied = CopyInnerNode(*node); + EXPECT_NE(node->key(), copied->key()); +} + +TEST_F(DataInnerNodeTest, CopyInnerNodeWithOneChild) { + auto copied = CopyInnerNode(*node); + + EXPECT_EQ(node->numChildren(), copied->numChildren()); + EXPECT_EQ(node->getChild(0)->key(), copied->getChild(0)->key()); +} + +TEST_F(DataInnerNodeTest, CopyInnerNodeWithTwoChildren) { + AddALeafTo(node.get()); + auto copied = CopyInnerNode(*node); + + EXPECT_EQ(node->numChildren(), copied->numChildren()); + EXPECT_EQ(node->getChild(0)->key(), copied->getChild(0)->key()); + EXPECT_EQ(node->getChild(1)->key(), copied->getChild(1)->key()); +} + //TODO TestCase for LastChild diff --git a/src/test/blobstore/implementations/onblocks/datanodestore/DataLeafNodeTest.cpp b/src/test/blobstore/implementations/onblocks/datanodestore/DataLeafNodeTest.cpp index 6c7991e6..6cda64c3 100644 --- a/src/test/blobstore/implementations/onblocks/datanodestore/DataLeafNodeTest.cpp +++ b/src/test/blobstore/implementations/onblocks/datanodestore/DataLeafNodeTest.cpp @@ -84,6 +84,11 @@ public: return converted->key(); } + unique_ptr CopyLeafNode(const DataLeafNode &node) { + auto copied = nodeStore->createNewNodeAsCopyFrom(node); + return dynamic_pointer_move(copied); + } + Data ZEROES; Data randomData; unique_ptr _blockStore; @@ -204,6 +209,24 @@ TEST_F(DataLeafNodeTest, ConvertToInternalNodeZeroesOutChildrenRegion) { EXPECT_EQ(0, std::memcmp(ZEROES.data(), (uint8_t*)block->data()+DataNodeView::HEADERSIZE_BYTES+sizeof(DataInnerNode::ChildEntry), DataLeafNode::MAX_STORED_BYTES-sizeof(DataInnerNode::ChildEntry))); } +TEST_F(DataLeafNodeTest, CopyingCreatesANewLeaf) { + auto copied = CopyLeafNode(*leaf); + EXPECT_NE(leaf->key(), copied->key()); +} + +TEST_F(DataLeafNodeTest, CopyEmptyLeaf) { + auto copied = CopyLeafNode(*leaf); + EXPECT_EQ(leaf->numBytes(), copied->numBytes()); +} + +TEST_F(DataLeafNodeTest, CopyDataLeaf) { + FillLeafBlockWithData(); + auto copied = CopyLeafNode(*leaf); + + EXPECT_EQ(leaf->numBytes(), copied->numBytes()); + EXPECT_EQ(0, std::memcmp(leaf->data(), copied->data(), leaf->numBytes())); + EXPECT_NE(leaf->data(), copied->data()); +} /* TODO * The following test cases test reading/writing part of a leaf. This doesn't make much sense,