Fix traversing bug and add test case for it

This commit is contained in:
Sebastian Messmer 2015-09-30 15:33:09 +02:00
parent faa4b0c6f8
commit e07ddaa289
2 changed files with 12 additions and 4 deletions

View File

@ -36,11 +36,12 @@ void BlobOnBlocks::traverseLeaves(uint64_t beginByte, uint64_t sizeBytes, functi
uint64_t endByte = beginByte + sizeBytes; uint64_t endByte = beginByte + sizeBytes;
uint32_t firstLeaf = beginByte / _datatree->maxBytesPerLeaf(); uint32_t firstLeaf = beginByte / _datatree->maxBytesPerLeaf();
uint32_t endLeaf = utils::ceilDivision(endByte, _datatree->maxBytesPerLeaf()); uint32_t endLeaf = utils::ceilDivision(endByte, _datatree->maxBytesPerLeaf());
_datatree->traverseLeaves(firstLeaf, endLeaf, [&func, beginByte, endByte, endLeaf](DataLeafNode *leaf, uint32_t leafIndex) { bool writingOutside = size() < endByte; // TODO Calling size() is slow because it has to traverse the tree
_datatree->traverseLeaves(firstLeaf, endLeaf, [&func, beginByte, endByte, endLeaf, writingOutside](DataLeafNode *leaf, uint32_t leafIndex) {
uint64_t indexOfFirstLeafByte = leafIndex * leaf->maxStoreableBytes(); uint64_t indexOfFirstLeafByte = leafIndex * leaf->maxStoreableBytes();
uint32_t dataBegin = utils::maxZeroSubtraction(beginByte, indexOfFirstLeafByte); uint32_t dataBegin = utils::maxZeroSubtraction(beginByte, indexOfFirstLeafByte);
uint32_t dataEnd = std::min((uint64_t)leaf->maxStoreableBytes(), endByte - indexOfFirstLeafByte); uint32_t dataEnd = std::min((uint64_t)leaf->maxStoreableBytes(), endByte - indexOfFirstLeafByte);
if (leafIndex == endLeaf-1 && leaf->numBytes() < dataEnd) { if (leafIndex == endLeaf-1 && writingOutside) {
// If we are traversing an area that didn't exist before, then the last leaf was just created with a wrong size. We have to fix it. // If we are traversing an area that didn't exist before, then the last leaf was just created with a wrong size. We have to fix it.
leaf->resize(dataEnd); leaf->resize(dataEnd);
} }
@ -64,8 +65,8 @@ uint64_t BlobOnBlocks::tryRead(void *target, uint64_t offset, uint64_t count) co
return realCount; return realCount;
} }
void BlobOnBlocks::write(const void *source, uint64_t offset, uint64_t size) { void BlobOnBlocks::write(const void *source, uint64_t offset, uint64_t count) {
traverseLeaves(offset, size, [source, offset] (uint64_t indexOfFirstLeafByte, DataLeafNode *leaf, uint32_t leafDataOffset, uint32_t leafDataSize) { traverseLeaves(offset, count, [source, offset] (uint64_t indexOfFirstLeafByte, DataLeafNode *leaf, uint32_t leafDataOffset, uint32_t leafDataSize) {
//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->write((uint8_t*)source + indexOfFirstLeafByte - offset + leafDataOffset, leafDataOffset, leafDataSize);
}); });

View File

@ -56,6 +56,13 @@ TEST_F(BlobReadWriteTest, WritingImmediatelyFlushes_LargeSize) {
EXPECT_DATA_READS_AS(randomData, *loaded, 0, LARGE_SIZE); EXPECT_DATA_READS_AS(randomData, *loaded, 0, LARGE_SIZE);
} }
// Regression test for a strange bug we had
TEST_F(BlobReadWriteTest, WritingCloseTo16ByteLimitDoesntDestroySize) {
blob->resize(1);
blob->write(randomData.data(), 32776, 4);
EXPECT_EQ(32780, blob->size());
}
struct DataRange { struct DataRange {
size_t blobsize; size_t blobsize;
off_t offset; off_t offset;