Fixed bug with seek compactions on Level 0

Summary: Due to how the code handled compactions in Level 0 in `PickCompaction()` it could be the case that two compactions on level 0 ran that produced tables in level 1 that overlap. However, this case seems like it would only occur on a seek compaction which is unlikely on level 0. Furthermore, level 0 and level 1 had to have a certain arrangement of files.

Test Plan:
make check

Reviewers: dhruba, vamsi

Reviewed By: dhruba

CC: leveldb, sheki

Differential Revision: https://reviews.facebook.net/D7923
This commit is contained in:
Kosie van der Merwe 2013-01-15 12:43:09 -08:00
parent 8ce418cd79
commit 28fe86c48a
2 changed files with 13 additions and 11 deletions

View File

@ -1936,10 +1936,14 @@ Compaction* VersionSet::PickCompaction() {
// Find compactions needed by seeks
if (c == NULL && (current_->file_to_compact_ != NULL)) {
level = current_->file_to_compact_level_;
// Only allow one level 0 compaction at a time.
if (level != 0 || compactions_in_progress_[0].empty()) {
c = new Compaction(level, MaxFileSizeForLevel(level),
MaxGrandParentOverlapBytes(level), NumberLevels(), true);
c->inputs_[0].push_back(current_->file_to_compact_);
}
}
if (c == NULL) {
return NULL;
@ -1949,26 +1953,22 @@ Compaction* VersionSet::PickCompaction() {
c->input_version_->Ref();
// Files in level 0 may overlap each other, so pick up all overlapping ones
// Two level 0 compaction won't run at the same time, so don't need to worry
// about files on level 0 being compacted.
if (level == 0) {
assert(compactions_in_progress_[0].empty());
InternalKey smallest, largest;
GetRange(c->inputs_[0], &smallest, &largest);
// Note that the next call will discard the file we placed in
// c->inputs_[0] earlier and replace it with an overlapping set
// which will include the picked file.
c->inputs_[0].clear();
std::vector<FileMetaData*> more;
current_->GetOverlappingInputs(0, &smallest, &largest, &more);
current_->GetOverlappingInputs(0, &smallest, &largest, &c->inputs_[0]);
if (ParentRangeInCompaction(&smallest, &largest,
level, &c->parent_index_)) {
delete c;
return NULL;
}
for (unsigned int i = 0; i < more.size(); i++) {
FileMetaData* f = more[i];
if (!f->being_compacted) {
c->inputs_[0].push_back(f);
}
}
assert(!c->inputs_[0].empty());
}

View File

@ -345,6 +345,8 @@ class VersionSet {
// For the specfied level, pick a compaction.
// Returns NULL if there is no compaction to be done.
// If level is 0 and there is already a compaction on that level, this
// function will return NULL.
Compaction* PickCompactionBySize(int level, double score);
// Free up the files that were participated in a compaction