Skip to content

Commit 299cced

Browse files
author
Gabor Cselle
committed
A number of bugfixes:
- Added DB::CompactRange() method. Changed manual compaction code so it breaks up compactions of big ranges into smaller compactions. Changed the code that pushes the output of memtable compactions to higher levels to obey the grandparent constraint: i.e., we must never have a single file in level L that overlaps too much data in level L+1 (to avoid very expensive L-1 compactions). Added code to pretty-print internal keys. - Fixed bug where we would not detect overlap with files in level-0 because we were incorrectly using binary search on an array of files with overlapping ranges. Added "leveldb.sstables" property that can be used to dump all of the sstables and ranges that make up the db state. - Removing post_write_snapshot support. Email to leveldb mailing list brought up no users, just confusion from one person about what it meant. - Fixing static_cast char to unsigned on BIG_ENDIAN platforms. Fixes Issue 35 and Issue 36. - Comment clarification to address leveldb Issue 37. - Change license in posix_logger.h to match other files. - A build problem where uint32 was used instead of uint32_t. Sync with upstream @24408625
1 parent 26db4d9 commit 299cced

18 files changed

+483
-217
lines changed

build_detect_platform

-5
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,6 @@ case `uname -s` in
3535
echo "PLATFORM_CFLAGS=-D_REENTRANT -DOS_FREEBSD" >> build_config.mk
3636
echo "PLATFORM_LDFLAGS=-lpthread" >> build_config.mk
3737
;;
38-
GNU/kFreeBSD)
39-
PLATFORM=OS_FREEBSD
40-
echo "PLATFORM_CFLAGS=-pthread -DOS_FREEBSD" >> build_config.mk
41-
echo "PLATFORM_LDFLAGS=-lpthread -lrt" >> build_config.mk
42-
;;
4338
*)
4439
echo "Unknown platform!"
4540
exit 1

db/corruption_test.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ TEST(CorruptionTest, TableFile) {
229229
Build(100);
230230
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
231231
dbi->TEST_CompactMemTable();
232-
dbi->TEST_CompactRange(0, "", "~");
233-
dbi->TEST_CompactRange(1, "", "~");
232+
dbi->TEST_CompactRange(0, NULL, NULL);
233+
dbi->TEST_CompactRange(1, NULL, NULL);
234234

235235
Corrupt(kTableFile, 100, 1);
236236
Check(99, 99);
@@ -278,7 +278,7 @@ TEST(CorruptionTest, CorruptedDescriptor) {
278278
ASSERT_OK(db_->Put(WriteOptions(), "foo", "hello"));
279279
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
280280
dbi->TEST_CompactMemTable();
281-
dbi->TEST_CompactRange(0, "", "~");
281+
dbi->TEST_CompactRange(0, NULL, NULL);
282282

283283
Corrupt(kDescriptorFile, 0, 1000);
284284
Status s = TryReopen();

db/db_bench.cc

+1-14
Original file line numberDiff line numberDiff line change
@@ -796,20 +796,7 @@ class Benchmark {
796796
}
797797

798798
void Compact(ThreadState* thread) {
799-
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
800-
dbi->TEST_CompactMemTable();
801-
int max_level_with_files = 1;
802-
for (int level = 1; level < config::kNumLevels; level++) {
803-
std::string property;
804-
char name[100];
805-
snprintf(name, sizeof(name), "leveldb.num-files-at-level%d", level);
806-
if (db_->GetProperty(name, &property) && atoi(property.c_str()) > 0) {
807-
max_level_with_files = level;
808-
}
809-
}
810-
for (int level = 0; level < max_level_with_files; level++) {
811-
dbi->TEST_CompactRange(level, "", "~");
812-
}
799+
db_->CompactRange(NULL, NULL);
813800
}
814801

815802
void PrintStats() {

db/db_impl.cc

+68-30
Original file line numberDiff line numberDiff line change
@@ -454,13 +454,8 @@ Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit,
454454
if (s.ok() && meta.file_size > 0) {
455455
const Slice min_user_key = meta.smallest.user_key();
456456
const Slice max_user_key = meta.largest.user_key();
457-
if (base != NULL && !base->OverlapInLevel(0, min_user_key, max_user_key)) {
458-
// Push the new sstable to a higher level if possible to reduce
459-
// expensive manifest file ops.
460-
while (level < config::kMaxMemCompactLevel &&
461-
!base->OverlapInLevel(level + 1, min_user_key, max_user_key)) {
462-
level++;
463-
}
457+
if (base != NULL) {
458+
level = base->PickLevelForMemTableOutput(min_user_key, max_user_key);
464459
}
465460
edit->AddFile(level, meta.number, meta.file_size,
466461
meta.smallest, meta.largest);
@@ -506,25 +501,55 @@ Status DBImpl::CompactMemTable() {
506501
return s;
507502
}
508503

509-
void DBImpl::TEST_CompactRange(
510-
int level,
511-
const std::string& begin,
512-
const std::string& end) {
504+
void DBImpl::CompactRange(const Slice* begin, const Slice* end) {
505+
int max_level_with_files = 1;
506+
{
507+
MutexLock l(&mutex_);
508+
Version* base = versions_->current();
509+
for (int level = 1; level < config::kNumLevels; level++) {
510+
if (base->OverlapInLevel(level, begin, end)) {
511+
max_level_with_files = level;
512+
}
513+
}
514+
}
515+
TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap
516+
for (int level = 0; level < max_level_with_files; level++) {
517+
TEST_CompactRange(level, begin, end);
518+
}
519+
}
520+
521+
void DBImpl::TEST_CompactRange(int level, const Slice* begin,const Slice* end) {
513522
assert(level >= 0);
514523
assert(level + 1 < config::kNumLevels);
515524

516-
MutexLock l(&mutex_);
517-
while (manual_compaction_ != NULL) {
518-
bg_cv_.Wait();
519-
}
525+
InternalKey begin_storage, end_storage;
526+
520527
ManualCompaction manual;
521528
manual.level = level;
522-
manual.begin = begin;
523-
manual.end = end;
524-
manual_compaction_ = &manual;
525-
MaybeScheduleCompaction();
526-
while (manual_compaction_ == &manual) {
527-
bg_cv_.Wait();
529+
manual.done = false;
530+
if (begin == NULL) {
531+
manual.begin = NULL;
532+
} else {
533+
begin_storage = InternalKey(*begin, kMaxSequenceNumber, kValueTypeForSeek);
534+
manual.begin = &begin_storage;
535+
}
536+
if (end == NULL) {
537+
manual.end = NULL;
538+
} else {
539+
end_storage = InternalKey(*end, 0, static_cast<ValueType>(0));
540+
manual.end = &end_storage;
541+
}
542+
543+
MutexLock l(&mutex_);
544+
while (!manual.done) {
545+
while (manual_compaction_ != NULL) {
546+
bg_cv_.Wait();
547+
}
548+
manual_compaction_ = &manual;
549+
MaybeScheduleCompaction();
550+
while (manual_compaction_ == &manual) {
551+
bg_cv_.Wait();
552+
}
528553
}
529554
}
530555

@@ -590,12 +615,20 @@ void DBImpl::BackgroundCompaction() {
590615

591616
Compaction* c;
592617
bool is_manual = (manual_compaction_ != NULL);
618+
InternalKey manual_end;
593619
if (is_manual) {
594-
const ManualCompaction* m = manual_compaction_;
595-
c = versions_->CompactRange(
620+
ManualCompaction* m = manual_compaction_;
621+
c = versions_->CompactRange(m->level, m->begin, m->end);
622+
m->done = (c == NULL);
623+
if (c != NULL) {
624+
manual_end = c->input(0, c->num_input_files(0) - 1)->largest;
625+
}
626+
Log(options_.info_log,
627+
"Manual compaction at level-%d from %s .. %s; will stop at %s\n",
596628
m->level,
597-
InternalKey(m->begin, kMaxSequenceNumber, kValueTypeForSeek),
598-
InternalKey(m->end, 0, static_cast<ValueType>(0)));
629+
(m->begin ? m->begin->DebugString().c_str() : "(begin)"),
630+
(m->end ? m->end->DebugString().c_str() : "(end)"),
631+
(m->done ? "(end)" : manual_end.DebugString().c_str()));
599632
} else {
600633
c = versions_->PickCompaction();
601634
}
@@ -638,7 +671,13 @@ void DBImpl::BackgroundCompaction() {
638671
}
639672

640673
if (is_manual) {
641-
// Mark it as done
674+
ManualCompaction* m = manual_compaction_;
675+
if (!m->done) {
676+
// We only compacted part of the requested range. Update *m
677+
// to the range that is left to be compacted.
678+
m->tmp_storage = manual_end;
679+
m->begin = &m->tmp_storage;
680+
}
642681
manual_compaction_ = NULL;
643682
}
644683
}
@@ -1109,10 +1148,6 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* updates) {
11091148

11101149
versions_->SetLastSequence(last_sequence);
11111150
}
1112-
if (options.post_write_snapshot != NULL) {
1113-
*options.post_write_snapshot =
1114-
status.ok() ? snapshots_.New(last_sequence) : NULL;
1115-
}
11161151
ReleaseLoggingResponsibility(&self);
11171152
return status;
11181153
}
@@ -1225,6 +1260,9 @@ bool DBImpl::GetProperty(const Slice& property, std::string* value) {
12251260
}
12261261
}
12271262
return true;
1263+
} else if (in == "sstables") {
1264+
*value = versions_->current()->DebugString();
1265+
return true;
12281266
}
12291267

12301268
return false;

db/db_impl.h

+7-7
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,12 @@ class DBImpl : public DB {
3838
virtual void ReleaseSnapshot(const Snapshot* snapshot);
3939
virtual bool GetProperty(const Slice& property, std::string* value);
4040
virtual void GetApproximateSizes(const Range* range, int n, uint64_t* sizes);
41+
virtual void CompactRange(const Slice* begin, const Slice* end);
4142

4243
// Extra methods (for testing) that are not in the public DB interface
4344

44-
// Compact any files in the named level that overlap [begin,end]
45-
void TEST_CompactRange(
46-
int level,
47-
const std::string& begin,
48-
const std::string& end);
45+
// Compact any files in the named level that overlap [*begin,*end]
46+
void TEST_CompactRange(int level, const Slice* begin, const Slice* end);
4947

5048
// Force current memtable contents to be compacted.
5149
Status TEST_CompactMemTable();
@@ -145,8 +143,10 @@ class DBImpl : public DB {
145143
// Information for a manual compaction
146144
struct ManualCompaction {
147145
int level;
148-
std::string begin;
149-
std::string end;
146+
bool done;
147+
const InternalKey* begin; // NULL means beginning of key range
148+
const InternalKey* end; // NULL means end of key range
149+
InternalKey tmp_storage; // Used to keep track of compaction progress
150150
};
151151
ManualCompaction* manual_compaction_;
152152

0 commit comments

Comments
 (0)