More preparations for not loading blocks in write() calls

This commit is contained in:
Sebastian Messmer 2016-07-15 21:06:41 +02:00
parent d80b95514e
commit eb792daefc
4 changed files with 62 additions and 35 deletions

View File

@ -41,7 +41,7 @@ void BlobOnBlocks::resize(uint64_t numBytes) {
_sizeCache = numBytes; _sizeCache = numBytes;
} }
void BlobOnBlocks::_traverseLeaves(uint64_t beginByte, uint64_t sizeBytes, function<void (uint64_t leafOffset, DataLeafNode *leaf, uint32_t begin, uint32_t count)> onExistingLeaf, function<Data (uint64_t beginByte, uint32_t count)> onCreateLeaf) const { void BlobOnBlocks::_traverseLeaves(uint64_t beginByte, uint64_t sizeBytes, function<void (uint64_t leafOffset, LeafHandle leaf, uint32_t begin, uint32_t count)> onExistingLeaf, function<Data (uint64_t beginByte, uint32_t count)> onCreateLeaf) const {
unique_lock<mutex> lock(_mutex); // TODO Multiple traverse calls in parallel? unique_lock<mutex> lock(_mutex); // TODO Multiple traverse calls in parallel?
uint64_t endByte = beginByte + sizeBytes; uint64_t endByte = beginByte + sizeBytes;
uint64_t maxBytesPerLeaf = _datatree->maxBytesPerLeaf(); uint64_t maxBytesPerLeaf = _datatree->maxBytesPerLeaf();
@ -49,18 +49,19 @@ void BlobOnBlocks::_traverseLeaves(uint64_t beginByte, uint64_t sizeBytes, funct
uint32_t endLeaf = utils::ceilDivision(endByte, maxBytesPerLeaf); uint32_t endLeaf = utils::ceilDivision(endByte, maxBytesPerLeaf);
bool blobIsGrowingFromThisTraversal = false; bool blobIsGrowingFromThisTraversal = false;
auto _onExistingLeaf = [&onExistingLeaf, beginByte, endByte, endLeaf, maxBytesPerLeaf, &blobIsGrowingFromThisTraversal] (uint32_t leafIndex, LeafHandle leafHandle) { auto _onExistingLeaf = [&onExistingLeaf, beginByte, endByte, endLeaf, maxBytesPerLeaf, &blobIsGrowingFromThisTraversal] (uint32_t leafIndex, LeafHandle leafHandle) {
auto leaf = leafHandle.node();
uint64_t indexOfFirstLeafByte = leafIndex * maxBytesPerLeaf; uint64_t indexOfFirstLeafByte = leafIndex * maxBytesPerLeaf;
ASSERT(endByte > indexOfFirstLeafByte, "Traversal went too far right"); ASSERT(endByte > indexOfFirstLeafByte, "Traversal went too far right");
ASSERT(leafIndex == endLeaf-1 || leaf->numBytes() == maxBytesPerLeaf, "All leafes but the rightmost one have to have maximal size");
uint32_t dataBegin = utils::maxZeroSubtraction(beginByte, indexOfFirstLeafByte); uint32_t dataBegin = utils::maxZeroSubtraction(beginByte, indexOfFirstLeafByte);
uint32_t dataEnd = std::min(maxBytesPerLeaf, endByte - indexOfFirstLeafByte); uint32_t dataEnd = std::min(maxBytesPerLeaf, endByte - indexOfFirstLeafByte);
if (leafIndex == endLeaf-1 && leaf->numBytes() < dataEnd) { if (leafIndex == endLeaf-1) {
// If we are traversing an area that didn't exist before (i.e. in the area of the last leaf that wasn't used before), then the last leaf might have a wrong size. We have to fix it. auto leaf = leafHandle.node();
leaf->resize(dataEnd); if (leaf->numBytes() < dataEnd) {
blobIsGrowingFromThisTraversal = true; // If we are traversing an area that didn't exist before (i.e. in the area of the last leaf that wasn't used before), then the last leaf might have a wrong size. We have to fix it.
leaf->resize(dataEnd);
blobIsGrowingFromThisTraversal = true;
}
} }
onExistingLeaf(indexOfFirstLeafByte, leaf, dataBegin, dataEnd-dataBegin); onExistingLeaf(indexOfFirstLeafByte, std::move(leafHandle), dataBegin, dataEnd-dataBegin);
}; };
auto _onCreateLeaf = [&onCreateLeaf, maxBytesPerLeaf, beginByte, firstLeaf, endByte, endLeaf, &blobIsGrowingFromThisTraversal] (uint32_t leafIndex) -> Data { auto _onCreateLeaf = [&onCreateLeaf, maxBytesPerLeaf, beginByte, firstLeaf, endByte, endLeaf, &blobIsGrowingFromThisTraversal] (uint32_t leafIndex) -> Data {
blobIsGrowingFromThisTraversal = true; blobIsGrowingFromThisTraversal = true;
@ -111,10 +112,10 @@ uint64_t BlobOnBlocks::tryRead(void *target, uint64_t offset, uint64_t count) co
} }
void BlobOnBlocks::_read(void *target, uint64_t offset, uint64_t count) const { void BlobOnBlocks::_read(void *target, uint64_t offset, uint64_t count) const {
auto onExistingLeaf = [target, offset, count] (uint64_t indexOfFirstLeafByte, const DataLeafNode *leaf, uint32_t leafDataOffset, uint32_t leafDataSize) { auto onExistingLeaf = [target, offset, count] (uint64_t indexOfFirstLeafByte, LeafHandle leaf, uint32_t leafDataOffset, uint32_t leafDataSize) {
ASSERT(indexOfFirstLeafByte+leafDataOffset>=offset && indexOfFirstLeafByte-offset+leafDataOffset <= count && indexOfFirstLeafByte-offset+leafDataOffset+leafDataSize <= count, "Writing to target out of bounds"); ASSERT(indexOfFirstLeafByte+leafDataOffset>=offset && indexOfFirstLeafByte-offset+leafDataOffset <= count && indexOfFirstLeafByte-offset+leafDataOffset+leafDataSize <= count, "Writing to target out of bounds");
//TODO Simplify formula, make it easier to understand //TODO Simplify formula, make it easier to understand
leaf->read((uint8_t*)target + indexOfFirstLeafByte - offset + leafDataOffset, leafDataOffset, leafDataSize); leaf.node()->read((uint8_t*)target + indexOfFirstLeafByte - offset + leafDataOffset, leafDataOffset, leafDataSize);
}; };
auto onCreateLeaf = [] (uint64_t /*beginByte*/, uint32_t /*count*/) -> Data { auto onCreateLeaf = [] (uint64_t /*beginByte*/, uint32_t /*count*/) -> Data {
ASSERT(false, "Reading shouldn't create new leaves."); ASSERT(false, "Reading shouldn't create new leaves.");
@ -123,10 +124,10 @@ void BlobOnBlocks::_read(void *target, uint64_t offset, uint64_t count) const {
} }
void BlobOnBlocks::write(const void *source, uint64_t offset, uint64_t count) { void BlobOnBlocks::write(const void *source, uint64_t offset, uint64_t count) {
auto onExistingLeaf = [source, offset, count] (uint64_t indexOfFirstLeafByte, DataLeafNode *leaf, uint32_t leafDataOffset, uint32_t leafDataSize) { auto onExistingLeaf = [source, offset, count] (uint64_t indexOfFirstLeafByte, LeafHandle leaf, uint32_t leafDataOffset, uint32_t leafDataSize) {
ASSERT(indexOfFirstLeafByte+leafDataOffset>=offset && indexOfFirstLeafByte-offset+leafDataOffset <= count && indexOfFirstLeafByte-offset+leafDataOffset+leafDataSize <= count, "Reading from source out of bounds"); ASSERT(indexOfFirstLeafByte+leafDataOffset>=offset && indexOfFirstLeafByte-offset+leafDataOffset <= count && indexOfFirstLeafByte-offset+leafDataOffset+leafDataSize <= count, "Reading from source out of bounds");
//TODO Simplify formula, make it easier to understand //TODO Simplify formula, make it easier to understand
leaf->write((uint8_t*)source + indexOfFirstLeafByte - offset + leafDataOffset, leafDataOffset, leafDataSize); leaf.node()->write((uint8_t*)source + indexOfFirstLeafByte - offset + leafDataOffset, leafDataOffset, leafDataSize);
}; };
auto onCreateLeaf = [source, offset, count] (uint64_t beginByte, uint32_t numBytes) -> Data { auto onCreateLeaf = [source, offset, count] (uint64_t beginByte, uint32_t numBytes) -> Data {
ASSERT(beginByte >= offset && beginByte-offset <= count && beginByte-offset+numBytes <= count, "Reading from source out of bounds"); ASSERT(beginByte >= offset && beginByte-offset <= count && beginByte-offset+numBytes <= count, "Reading from source out of bounds");

View File

@ -3,6 +3,7 @@
#define MESSMER_BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_BLOBONBLOCKS_H_ #define MESSMER_BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_BLOBONBLOCKS_H_
#include "../../interface/Blob.h" #include "../../interface/Blob.h"
#include "datatreestore/LeafHandle.h"
#include <memory> #include <memory>
#include <boost/optional.hpp> #include <boost/optional.hpp>
@ -38,7 +39,7 @@ public:
private: private:
void _read(void *target, uint64_t offset, uint64_t count) const; void _read(void *target, uint64_t offset, uint64_t count) const;
void _traverseLeaves(uint64_t offsetBytes, uint64_t sizeBytes, std::function<void (uint64_t leafOffset, datanodestore::DataLeafNode *leaf, uint32_t begin, uint32_t count)> onExistingLeaf, std::function<cpputils::Data (uint64_t beginByte, uint32_t count)> onCreateLeaf) const; void _traverseLeaves(uint64_t offsetBytes, uint64_t sizeBytes, std::function<void (uint64_t leafOffset, datatreestore::LeafHandle leaf, uint32_t begin, uint32_t count)> onExistingLeaf, std::function<cpputils::Data (uint64_t beginByte, uint32_t count)> onCreateLeaf) const;
cpputils::unique_ref<parallelaccessdatatreestore::DataTreeRef> _datatree; cpputils::unique_ref<parallelaccessdatatreestore::DataTreeRef> _datatree;
mutable boost::optional<uint64_t> _sizeCache; mutable boost::optional<uint64_t> _sizeCache;

View File

@ -1 +1,40 @@
#include "LeafHandle.h" #include "LeafHandle.h"
#include "../datanodestore/DataLeafNode.h"
#include "../datanodestore/DataNodeStore.h"
using cpputils::WithOwnership;
using cpputils::WithoutOwnership;
using boost::none;
using cpputils::dynamic_pointer_move;
using blobstore::onblocks::datanodestore::DataLeafNode;
using blobstore::onblocks::datanodestore::DataNodeStore;
using blockstore::Key;
namespace blobstore {
namespace onblocks {
namespace datatreestore {
LeafHandle::LeafHandle(DataNodeStore *nodeStore, const Key &key)
: _nodeStore(nodeStore), _key(key), _leaf(cpputils::null<DataLeafNode>()) {
}
LeafHandle::LeafHandle(DataNodeStore *nodeStore, DataLeafNode *node)
: _nodeStore(nodeStore), _key(node->key()),
_leaf(WithoutOwnership<DataLeafNode>(node)) {
}
DataLeafNode *LeafHandle::node() {
if (_leaf.get() == nullptr) {
auto loaded = _nodeStore->load(_key);
ASSERT(loaded != none, "Leaf not found");
auto leaf = dynamic_pointer_move<DataLeafNode>(*loaded);
ASSERT(leaf != none, "Loaded leaf is not leaf node");
_leaf = WithOwnership(std::move(*leaf));
}
return _leaf.get();
}
}
}
}

View File

@ -4,41 +4,27 @@
#include <cpp-utils/macros.h> #include <cpp-utils/macros.h>
#include <cpp-utils/pointer/optional_ownership_ptr.h> #include <cpp-utils/pointer/optional_ownership_ptr.h>
#include "blobstore/implementations/onblocks/datanodestore/DataNodeStore.h" #include <blockstore/utils/Key.h>
#include "blobstore/implementations/onblocks/datanodestore/DataLeafNode.h"
namespace blobstore { namespace blobstore {
namespace onblocks { namespace onblocks {
namespace datanodestore {
class DataNodeStore;
class DataLeafNode;
}
namespace datatreestore { namespace datatreestore {
class LeafHandle final { class LeafHandle final {
public: public:
LeafHandle(datanodestore::DataNodeStore *nodeStore, const blockstore::Key &key) LeafHandle(datanodestore::DataNodeStore *nodeStore, const blockstore::Key &key);
:_nodeStore(nodeStore), _key(key), _leaf(cpputils::null<datanodestore::DataLeafNode>()) { LeafHandle(datanodestore::DataNodeStore *nodeStore, datanodestore::DataLeafNode *node);
}
LeafHandle(datanodestore::DataNodeStore *nodeStore, datanodestore::DataLeafNode *node)
: _nodeStore(nodeStore), _key(node->key()), _leaf(cpputils::WithoutOwnership<datanodestore::DataLeafNode>(node)) {
}
LeafHandle(LeafHandle &&rhs) = default; LeafHandle(LeafHandle &&rhs) = default;
const blockstore::Key &key() { const blockstore::Key &key() {
return _key; return _key;
} }
datanodestore::DataLeafNode *node() { datanodestore::DataLeafNode *node();
if (_leaf.get() == nullptr) {
auto loaded = _nodeStore->load(_key);
ASSERT(loaded != boost::none, "Leaf not found");
auto leaf = cpputils::dynamic_pointer_move<datanodestore::DataLeafNode>(*loaded);
ASSERT(leaf != boost::none, "Loaded leaf is not leaf node");
_leaf = cpputils::WithOwnership(std::move(*leaf));
}
return _leaf.get();
}
private: private:
datanodestore::DataNodeStore *_nodeStore; datanodestore::DataNodeStore *_nodeStore;