Squashed 'src/leveldb/' changes from aca1ffc..ae6c262
ae6c262 Merge branch 'leveldb' into ripple-fork 28fa222 Looks like a bit more delay is needed to smooth the latency. a18f3e6 Tidy up JobQueue, add ripple_core module ab82e57 Release leveldb 1.12 02c6259 Release leveldb 1.11 5bbb544 Rate limit compactions with a 25ms pause after each complete file. 8c29c47 LevelDB issue 178 fix: cannot resize a level 0 compaction set 18b245c Added GNU/kFreeBSD kernel name (TARGET_OS) 8be9d12 CondVar::SignalAll was broken, leading to deadlocks on Windows builds. http://code.google.com/p/leveldb/issues/detail?id=149 c9fc070 Upgrade LevelDB to 1.10.0, mostly for better write stall logging. 8215b15 Tweak to variable name to support unity build git-subtree-dir: src/leveldb git-subtree-split: ae6c2620b2ef3d5c69e63dc0eda865d6a39fa061
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
namespace leveldb {
|
||||
|
||||
inline uint32_t Block::NumRestarts() const {
|
||||
assert(size_ >= 2*sizeof(uint32_t));
|
||||
assert(size_ >= sizeof(uint32_t));
|
||||
return DecodeFixed32(data_ + size_ - sizeof(uint32_t));
|
||||
}
|
||||
|
||||
@@ -27,11 +27,12 @@ Block::Block(const BlockContents& contents)
|
||||
if (size_ < sizeof(uint32_t)) {
|
||||
size_ = 0; // Error marker
|
||||
} else {
|
||||
restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t);
|
||||
if (restart_offset_ > size_ - sizeof(uint32_t)) {
|
||||
// The size is too small for NumRestarts() and therefore
|
||||
// restart_offset_ wrapped around.
|
||||
size_t max_restarts_allowed = (size_-sizeof(uint32_t)) / sizeof(uint32_t);
|
||||
if (NumRestarts() > max_restarts_allowed) {
|
||||
// The size is too small for NumRestarts()
|
||||
size_ = 0;
|
||||
} else {
|
||||
restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -253,7 +254,7 @@ class Block::Iter : public Iterator {
|
||||
};
|
||||
|
||||
Iterator* Block::NewIterator(const Comparator* cmp) {
|
||||
if (size_ < 2*sizeof(uint32_t)) {
|
||||
if (size_ < sizeof(uint32_t)) {
|
||||
return NewErrorIterator(Status::Corruption("bad block contents"));
|
||||
}
|
||||
const uint32_t num_restarts = NumRestarts();
|
||||
|
||||
@@ -228,7 +228,6 @@ Status Table::InternalGet(const ReadOptions& options, const Slice& k,
|
||||
!filter->KeyMayMatch(handle.offset(), k)) {
|
||||
// Not found
|
||||
} else {
|
||||
Slice handle = iiter->value();
|
||||
Iterator* block_iter = BlockReader(this, options, iiter->value());
|
||||
block_iter->Seek(k);
|
||||
if (block_iter->Valid()) {
|
||||
|
||||
@@ -644,6 +644,36 @@ class Harness {
|
||||
Constructor* constructor_;
|
||||
};
|
||||
|
||||
// Test empty table/block.
|
||||
TEST(Harness, Empty) {
|
||||
for (int i = 0; i < kNumTestArgs; i++) {
|
||||
Init(kTestArgList[i]);
|
||||
Random rnd(test::RandomSeed() + 1);
|
||||
Test(&rnd);
|
||||
}
|
||||
}
|
||||
|
||||
// Special test for a block with no restart entries. The C++ leveldb
|
||||
// code never generates such blocks, but the Java version of leveldb
|
||||
// seems to.
|
||||
TEST(Harness, ZeroRestartPointsInBlock) {
|
||||
char data[sizeof(uint32_t)];
|
||||
memset(data, 0, sizeof(data));
|
||||
BlockContents contents;
|
||||
contents.data = Slice(data, sizeof(data));
|
||||
contents.cachable = false;
|
||||
contents.heap_allocated = false;
|
||||
Block block(contents);
|
||||
Iterator* iter = block.NewIterator(BytewiseComparator());
|
||||
iter->SeekToFirst();
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
iter->SeekToLast();
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
iter->Seek("foo");
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
delete iter;
|
||||
}
|
||||
|
||||
// Test the empty key
|
||||
TEST(Harness, SimpleEmptyKey) {
|
||||
for (int i = 0; i < kNumTestArgs; i++) {
|
||||
|
||||
Reference in New Issue
Block a user