libcryfs/implementations/onblocks/BlobOnBlocks.cpp

77 lines
2.6 KiB
C++
Raw Normal View History

2015-02-17 00:40:34 +01:00
#include "BlobOnBlocks.h"
#include "datatreestore/DataTree.h"
#include "datanodestore/DataLeafNode.h"
#include "utils/Math.h"
#include <cmath>
2014-12-09 17:56:48 +01:00
using std::unique_ptr;
using std::function;
using blobstore::onblocks::datanodestore::DataLeafNode;
using blobstore::onblocks::datanodestore::DataNodeLayout;
2015-02-27 00:18:26 +01:00
using blockstore::Key;
2014-12-09 17:56:48 +01:00
namespace blobstore {
namespace onblocks {
using datatreestore::DataTree;
BlobOnBlocks::BlobOnBlocks(unique_ptr<DataTree> datatree)
: _datatree(std::move(datatree)) {
2014-12-09 17:56:48 +01:00
}
BlobOnBlocks::~BlobOnBlocks() {
2014-12-09 17:56:48 +01:00
}
uint64_t BlobOnBlocks::size() const {
2015-02-25 23:09:48 +01:00
return _datatree->numStoredBytes();
2014-12-09 17:56:48 +01:00
}
void BlobOnBlocks::resize(uint64_t numBytes) {
_datatree->resizeNumBytes(numBytes);
}
void BlobOnBlocks::traverseLeaves(uint64_t beginByte, uint64_t sizeBytes, function<void (uint64_t, DataLeafNode *leaf, uint32_t, uint32_t)> func) const {
uint64_t endByte = beginByte + sizeBytes;
assert(endByte <= size());
uint32_t firstLeaf = beginByte / _datatree->maxBytesPerLeaf();
uint32_t endLeaf = utils::ceilDivision(endByte, _datatree->maxBytesPerLeaf());
_datatree->traverseLeaves(firstLeaf, endLeaf, [&func, beginByte, endByte](DataLeafNode *leaf, uint32_t leafIndex) {
uint64_t indexOfFirstLeafByte = leafIndex * leaf->maxStoreableBytes();
uint32_t dataBegin = utils::maxZeroSubtraction(beginByte, indexOfFirstLeafByte);
uint32_t dataEnd = std::min((uint64_t)leaf->maxStoreableBytes(), endByte - indexOfFirstLeafByte);
func(indexOfFirstLeafByte, leaf, dataBegin, dataEnd-dataBegin);
});
}
void BlobOnBlocks::read(void *target, uint64_t offset, uint64_t size) const {
traverseLeaves(offset, size, [target] (uint64_t indexOfFirstLeafByte, const DataLeafNode *leaf, uint32_t leafDataOffset, uint32_t leafDataSize) {
leaf->read((uint8_t*)target + indexOfFirstLeafByte + leafDataOffset, leafDataOffset, leafDataSize);
});
}
void BlobOnBlocks::write(const void *source, uint64_t offset, uint64_t size) {
resizeIfSmallerThan(offset + size);
traverseLeaves(offset, size, [source] (uint64_t indexOfFirstLeafByte, DataLeafNode *leaf, uint32_t leafDataOffset, uint32_t leafDataSize) {
leaf->write((uint8_t*)source + indexOfFirstLeafByte + leafDataOffset, leafDataOffset, leafDataSize);
});
}
void BlobOnBlocks::resizeIfSmallerThan(uint64_t neededSize) {
//TODO This is inefficient, because size() and resizeNumBytes() both traverse the tree. Better: _datatree->ensureMinSize(x)
if (neededSize > size()) {
_datatree->resizeNumBytes(neededSize);
}
}
2015-02-27 00:18:26 +01:00
Key BlobOnBlocks::key() const {
return _datatree->key();
}
unique_ptr<DataTree> BlobOnBlocks::releaseTree() {
return std::move(_datatree);
}
}
}