Skip to content

Commit 02c6259

Browse files
davidsgroganvinniefalco
authored andcommitted
Release leveldb 1.11
Fixes issues 161 174 178 As well as the issue reported by edouarda14@gmail.com about MissingSSTFile unit test failing on windows. Conflicts: Makefile
1 parent 5bbb544 commit 02c6259

File tree

9 files changed

+159
-23
lines changed

9 files changed

+159
-23
lines changed

Makefile

+5-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ TESTS = \
4242
env_test \
4343
filename_test \
4444
filter_block_test \
45+
issue178_test \
4546
log_test \
4647
memenv_test \
4748
skiplist_test \
@@ -69,7 +70,7 @@ SHARED = $(SHARED1)
6970
else
7071
# Update db.h if you change these.
7172
SHARED_MAJOR = 1
72-
SHARED_MINOR = 9
73+
SHARED_MINOR = 11
7374
SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT)
7475
SHARED2 = $(SHARED1).$(SHARED_MAJOR)
7576
SHARED3 = $(SHARED1).$(SHARED_MAJOR).$(SHARED_MINOR)
@@ -146,6 +147,9 @@ filename_test: db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS)
146147
filter_block_test: table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS)
147148
$(CXX) $(LDFLAGS) table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
148149

150+
issue178_test: issues/issue178_test.o $(LIBOBJECTS) $(TESTHARNESS)
151+
$(CXX) $(LDFLAGS) issues/issue178_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
152+
149153
log_test: db/log_test.o $(LIBOBJECTS) $(TESTHARNESS)
150154
$(CXX) $(LDFLAGS) db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
151155

db/db_impl.cc

+15-6
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535

3636
namespace leveldb {
3737

38+
const int kNumNonTableCacheFiles = 10;
39+
3840
// Information kept for every waiting writer
3941
struct DBImpl::Writer {
4042
Status status;
@@ -92,9 +94,9 @@ Options SanitizeOptions(const std::string& dbname,
9294
Options result = src;
9395
result.comparator = icmp;
9496
result.filter_policy = (src.filter_policy != NULL) ? ipolicy : NULL;
95-
ClipToRange(&result.max_open_files, 20, 50000);
96-
ClipToRange(&result.write_buffer_size, 64<<10, 1<<30);
97-
ClipToRange(&result.block_size, 1<<10, 4<<20);
97+
ClipToRange(&result.max_open_files, 64 + kNumNonTableCacheFiles, 50000);
98+
ClipToRange(&result.write_buffer_size, 64<<10, 1<<30);
99+
ClipToRange(&result.block_size, 1<<10, 4<<20);
98100
if (result.info_log == NULL) {
99101
// Open a log file in the same directory as the db
100102
src.env->CreateDir(dbname); // In case it does not exist
@@ -130,12 +132,13 @@ DBImpl::DBImpl(const Options& options, const std::string& dbname)
130132
log_(NULL),
131133
tmp_batch_(new WriteBatch),
132134
bg_compaction_scheduled_(false),
133-
manual_compaction_(NULL) {
135+
manual_compaction_(NULL),
136+
consecutive_compaction_errors_(0) {
134137
mem_->Ref();
135138
has_imm_.Release_Store(NULL);
136139

137140
// Reserve ten files or so for other uses and give the rest to TableCache.
138-
const int table_cache_size = options.max_open_files - 10;
141+
const int table_cache_size = options.max_open_files - kNumNonTableCacheFiles;
139142
table_cache_ = new TableCache(dbname_, &options_, table_cache_size);
140143

141144
versions_ = new VersionSet(dbname_, &options_, table_cache_,
@@ -619,6 +622,7 @@ void DBImpl::BackgroundCall() {
619622
Status s = BackgroundCompaction();
620623
if (s.ok()) {
621624
// Success
625+
consecutive_compaction_errors_ = 0;
622626
} else if (shutting_down_.Acquire_Load()) {
623627
// Error most likely due to shutdown; do not wait
624628
} else {
@@ -630,7 +634,12 @@ void DBImpl::BackgroundCall() {
630634
Log(options_.info_log, "Waiting after background compaction error: %s",
631635
s.ToString().c_str());
632636
mutex_.Unlock();
633-
env_->SleepForMicroseconds(1000000);
637+
++consecutive_compaction_errors_;
638+
int seconds_to_sleep = 1;
639+
for (int i = 0; i < 3 && i < consecutive_compaction_errors_ - 1; ++i) {
640+
seconds_to_sleep *= 2;
641+
}
642+
env_->SleepForMicroseconds(seconds_to_sleep * 1000000);
634643
mutex_.Lock();
635644
}
636645
}

db/db_impl.h

+1
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ class DBImpl : public DB {
163163

164164
// Have we encountered a background error in paranoid mode?
165165
Status bg_error_;
166+
int consecutive_compaction_errors_;
166167

167168
// Per level compaction stats. stats_[level] stores the stats for
168169
// compactions that produced data for the specified "level".

db/db_test.cc

+44-10
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ class AtomicCounter {
3333
public:
3434
AtomicCounter() : count_(0) { }
3535
void Increment() {
36+
IncrementBy(1);
37+
}
38+
void IncrementBy(int count) {
3639
MutexLock l(&mu_);
37-
count_++;
40+
count_ += count;
3841
}
3942
int Read() {
4043
MutexLock l(&mu_);
@@ -45,6 +48,10 @@ class AtomicCounter {
4548
count_ = 0;
4649
}
4750
};
51+
52+
void DelayMilliseconds(int millis) {
53+
Env::Default()->SleepForMicroseconds(millis * 1000);
54+
}
4855
}
4956

5057
// Special Env used to delay background operations
@@ -69,6 +76,7 @@ class SpecialEnv : public EnvWrapper {
6976
AtomicCounter random_read_counter_;
7077

7178
AtomicCounter sleep_counter_;
79+
AtomicCounter sleep_time_counter_;
7280

7381
explicit SpecialEnv(Env* base) : EnvWrapper(base) {
7482
delay_sstable_sync_.Release_Store(NULL);
@@ -103,7 +111,7 @@ class SpecialEnv : public EnvWrapper {
103111
Status Flush() { return base_->Flush(); }
104112
Status Sync() {
105113
while (env_->delay_sstable_sync_.Acquire_Load() != NULL) {
106-
env_->SleepForMicroseconds(100000);
114+
DelayMilliseconds(100);
107115
}
108116
return base_->Sync();
109117
}
@@ -174,8 +182,9 @@ class SpecialEnv : public EnvWrapper {
174182

175183
virtual void SleepForMicroseconds(int micros) {
176184
sleep_counter_.Increment();
177-
target()->SleepForMicroseconds(micros);
185+
sleep_time_counter_.IncrementBy(micros);
178186
}
187+
179188
};
180189

181190
class DBTest {
@@ -625,7 +634,7 @@ TEST(DBTest, GetEncountersEmptyLevel) {
625634
}
626635

627636
// Step 4: Wait for compaction to finish
628-
env_->SleepForMicroseconds(1000000);
637+
DelayMilliseconds(1000);
629638

630639
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
631640
} while (ChangeOptions());
@@ -1309,7 +1318,7 @@ TEST(DBTest, L0_CompactionBug_Issue44_a) {
13091318
Reopen();
13101319
Reopen();
13111320
ASSERT_EQ("(a->v)", Contents());
1312-
env_->SleepForMicroseconds(1000000); // Wait for compaction to finish
1321+
DelayMilliseconds(1000); // Wait for compaction to finish
13131322
ASSERT_EQ("(a->v)", Contents());
13141323
}
13151324

@@ -1325,7 +1334,7 @@ TEST(DBTest, L0_CompactionBug_Issue44_b) {
13251334
Put("","");
13261335
Reopen();
13271336
Put("","");
1328-
env_->SleepForMicroseconds(1000000); // Wait for compaction to finish
1337+
DelayMilliseconds(1000); // Wait for compaction to finish
13291338
Reopen();
13301339
Put("d","dv");
13311340
Reopen();
@@ -1335,7 +1344,7 @@ TEST(DBTest, L0_CompactionBug_Issue44_b) {
13351344
Delete("b");
13361345
Reopen();
13371346
ASSERT_EQ("(->)(c->cv)", Contents());
1338-
env_->SleepForMicroseconds(1000000); // Wait for compaction to finish
1347+
DelayMilliseconds(1000); // Wait for compaction to finish
13391348
ASSERT_EQ("(->)(c->cv)", Contents());
13401349
}
13411350

@@ -1520,6 +1529,30 @@ TEST(DBTest, NoSpace) {
15201529
ASSERT_GE(env_->sleep_counter_.Read(), 5);
15211530
}
15221531

1532+
TEST(DBTest, ExponentialBackoff) {
1533+
Options options = CurrentOptions();
1534+
options.env = env_;
1535+
Reopen(&options);
1536+
1537+
ASSERT_OK(Put("foo", "v1"));
1538+
ASSERT_EQ("v1", Get("foo"));
1539+
Compact("a", "z");
1540+
env_->non_writable_.Release_Store(env_); // Force errors for new files
1541+
env_->sleep_counter_.Reset();
1542+
env_->sleep_time_counter_.Reset();
1543+
for (int i = 0; i < 5; i++) {
1544+
dbfull()->TEST_CompactRange(2, NULL, NULL);
1545+
}
1546+
env_->non_writable_.Release_Store(NULL);
1547+
1548+
// Wait for compaction to finish
1549+
DelayMilliseconds(1000);
1550+
1551+
ASSERT_GE(env_->sleep_counter_.Read(), 5);
1552+
ASSERT_LT(env_->sleep_counter_.Read(), 10);
1553+
ASSERT_GE(env_->sleep_time_counter_.Read(), 10e6);
1554+
}
1555+
15231556
TEST(DBTest, NonWritableFileSystem) {
15241557
Options options = CurrentOptions();
15251558
options.write_buffer_size = 1000;
@@ -1533,7 +1566,7 @@ TEST(DBTest, NonWritableFileSystem) {
15331566
fprintf(stderr, "iter %d; errors %d\n", i, errors);
15341567
if (!Put("foo", big).ok()) {
15351568
errors++;
1536-
env_->SleepForMicroseconds(100000);
1569+
DelayMilliseconds(100);
15371570
}
15381571
}
15391572
ASSERT_GT(errors, 0);
@@ -1589,6 +1622,7 @@ TEST(DBTest, MissingSSTFile) {
15891622
dbfull()->TEST_CompactMemTable();
15901623
ASSERT_EQ("bar", Get("foo"));
15911624

1625+
Close();
15921626
ASSERT_TRUE(DeleteAnSSTFile());
15931627
Options options = CurrentOptions();
15941628
options.paranoid_checks = true;
@@ -1742,13 +1776,13 @@ TEST(DBTest, MultiThreaded) {
17421776
}
17431777

17441778
// Let them run for a while
1745-
env_->SleepForMicroseconds(kTestSeconds * 1000000);
1779+
DelayMilliseconds(kTestSeconds * 1000);
17461780

17471781
// Stop the threads and wait for them to finish
17481782
mt.stop.Release_Store(&mt);
17491783
for (int id = 0; id < kNumThreads; id++) {
17501784
while (mt.thread_done[id].Acquire_Load() == NULL) {
1751-
env_->SleepForMicroseconds(100000);
1785+
DelayMilliseconds(100);
17521786
}
17531787
}
17541788
} while (ChangeOptions());

db/filename_test.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ TEST(FileNameTest, Parse) {
7070
for (int i = 0; i < sizeof(errors) / sizeof(errors[0]); i++) {
7171
std::string f = errors[i];
7272
ASSERT_TRUE(!ParseFileName(f, &number, &type)) << f;
73-
};
73+
}
7474
}
7575

7676
TEST(FileNameTest, Construction) {

include/leveldb/db.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace leveldb {
1414

1515
// Update Makefile if you change these
1616
static const int kMajorVersion = 1;
17-
static const int kMinorVersion = 10;
17+
static const int kMinorVersion = 11;
1818

1919
struct Options;
2020
struct ReadOptions;

issues/issue178_test.cc

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Test for issue 178: a manual compaction causes deleted data to reappear.
2+
#include <iostream>
3+
#include <sstream>
4+
#include <cstdlib>
5+
6+
#include "leveldb/db.h"
7+
#include "leveldb/write_batch.h"
8+
#include "util/testharness.h"
9+
10+
namespace {
11+
12+
const int kNumKeys = 1100000;
13+
14+
std::string Key1(int i) {
15+
char buf[100];
16+
snprintf(buf, sizeof(buf), "my_key_%d", i);
17+
return buf;
18+
}
19+
20+
std::string Key2(int i) {
21+
return Key1(i) + "_xxx";
22+
}
23+
24+
class Issue178 { };
25+
26+
TEST(Issue178, Test) {
27+
// Get rid of any state from an old run.
28+
std::string dbpath = leveldb::test::TmpDir() + "/leveldb_cbug_test";
29+
DestroyDB(dbpath, leveldb::Options());
30+
31+
// Open database. Disable compression since it affects the creation
32+
// of layers and the code below is trying to test against a very
33+
// specific scenario.
34+
leveldb::DB* db;
35+
leveldb::Options db_options;
36+
db_options.create_if_missing = true;
37+
db_options.compression = leveldb::kNoCompression;
38+
ASSERT_OK(leveldb::DB::Open(db_options, dbpath, &db));
39+
40+
// create first key range
41+
leveldb::WriteBatch batch;
42+
for (size_t i = 0; i < kNumKeys; i++) {
43+
batch.Put(Key1(i), "value for range 1 key");
44+
}
45+
ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
46+
47+
// create second key range
48+
batch.Clear();
49+
for (size_t i = 0; i < kNumKeys; i++) {
50+
batch.Put(Key2(i), "value for range 2 key");
51+
}
52+
ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
53+
54+
// delete second key range
55+
batch.Clear();
56+
for (size_t i = 0; i < kNumKeys; i++) {
57+
batch.Delete(Key2(i));
58+
}
59+
ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
60+
61+
// compact database
62+
std::string start_key = Key1(0);
63+
std::string end_key = Key1(kNumKeys - 1);
64+
leveldb::Slice least(start_key.data(), start_key.size());
65+
leveldb::Slice greatest(end_key.data(), end_key.size());
66+
67+
// commenting out the line below causes the example to work correctly
68+
db->CompactRange(&least, &greatest);
69+
70+
// count the keys
71+
leveldb::Iterator* iter = db->NewIterator(leveldb::ReadOptions());
72+
size_t num_keys = 0;
73+
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
74+
num_keys++;
75+
}
76+
delete iter;
77+
ASSERT_EQ(kNumKeys, num_keys) << "Bad number of keys";
78+
79+
// close database
80+
delete db;
81+
DestroyDB(dbpath, leveldb::Options());
82+
}
83+
84+
} // anonymous namespace
85+
86+
int main(int argc, char** argv) {
87+
return leveldb::test::RunAllTests();
88+
}

util/coding_test.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ TEST(Coding, Varint64) {
109109
values.push_back(power);
110110
values.push_back(power-1);
111111
values.push_back(power+1);
112-
};
112+
}
113113

114114
std::string s;
115115
for (int i = 0; i < values.size(); i++) {

util/env_posix.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -467,23 +467,23 @@ class PosixEnv : public Env {
467467
result = IOError(fname, errno);
468468
}
469469
return result;
470-
};
470+
}
471471

472472
virtual Status CreateDir(const std::string& name) {
473473
Status result;
474474
if (mkdir(name.c_str(), 0755) != 0) {
475475
result = IOError(name, errno);
476476
}
477477
return result;
478-
};
478+
}
479479

480480
virtual Status DeleteDir(const std::string& name) {
481481
Status result;
482482
if (rmdir(name.c_str()) != 0) {
483483
result = IOError(name, errno);
484484
}
485485
return result;
486-
};
486+
}
487487

488488
virtual Status GetFileSize(const std::string& fname, uint64_t* size) {
489489
Status s;

0 commit comments

Comments
 (0)