mirror of
https://github.com/facebook/rocksdb.git
synced 2024-11-30 22:41:48 +00:00
485ee4f45c
Summary: Follow-up to https://github.com/facebook/rocksdb/issues/13106 which revealed that some SST file readers (in addition to blob files) were being essentially leaked in TableCache (until DB::Close() time). Patched sources of leaks: * Flush that is not committed (builder.cc) * Various obsolete SST files picked up by directory scan but not caught by SubcompactionState::Cleanup() cleaning up from some failed compactions. Dozens of unit tests fail without the "backstop" TableCache::Evict() call in PurgeObsoleteFiles(). We also needed to adjust the check for leaks as follows: * Ok if DB::Open never finished (see comment) * Ok if deletions are disabled (see comment) * Allow "quarantined" files to be in table_cache because (presumably) they might become live again. * Get live files from all live Versions. Suggested follow-up: * Potentially delete more obsolete files sooner with a FIXME in db_impl_files.cc. This could potentially be high value because it seems to gate deletion of any/all newer obsolete files on all older compactions finishing. * Try to catch obsolete files in more places using the VersionSet::obsolete_files_ pipeline rather than relying on them being picked up with directory scan, or deleting them outside of normal mechanisms. Pull Request resolved: https://github.com/facebook/rocksdb/pull/13117 Test Plan: updated check used in most all unit tests in ASAN build Reviewed By: hx235 Differential Revision: D65502988 Pulled By: pdillinger fbshipit-source-id: aa0795a8a09d9ec578d25183fe43e2a35849209c
114 lines
3.8 KiB
C++
114 lines
3.8 KiB
C++
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
//
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
//
|
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
|
|
#include "db/compaction/subcompaction_state.h"
|
|
|
|
#include "rocksdb/sst_partitioner.h"
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
void SubcompactionState::AggregateCompactionOutputStats(
|
|
InternalStats::CompactionStatsFull& compaction_stats) const {
|
|
compaction_stats.stats.Add(compaction_outputs_.stats_);
|
|
if (HasPenultimateLevelOutputs()) {
|
|
compaction_stats.has_penultimate_level_output = true;
|
|
compaction_stats.penultimate_level_stats.Add(
|
|
penultimate_level_outputs_.stats_);
|
|
}
|
|
}
|
|
|
|
OutputIterator SubcompactionState::GetOutputs() const {
|
|
return OutputIterator(penultimate_level_outputs_.outputs_,
|
|
compaction_outputs_.outputs_);
|
|
}
|
|
|
|
void SubcompactionState::Cleanup(Cache* cache) {
|
|
penultimate_level_outputs_.Cleanup();
|
|
compaction_outputs_.Cleanup();
|
|
|
|
if (!status.ok()) {
|
|
for (const auto& out : GetOutputs()) {
|
|
// If this file was inserted into the table cache then remove it here
|
|
// because this compaction was not committed. This is not strictly
|
|
// required because of a backstop TableCache::Evict() in
|
|
// PurgeObsoleteFiles() but is our opportunity to apply
|
|
// uncache_aggressiveness. TODO: instead, put these files into the
|
|
// VersionSet::obsolete_files_ pipeline so that they don't have to
|
|
// be picked up by scanning the DB directory.
|
|
TableCache::ReleaseObsolete(
|
|
cache, out.meta.fd.GetNumber(), nullptr /*handle*/,
|
|
compaction->mutable_cf_options()->uncache_aggressiveness);
|
|
}
|
|
}
|
|
// TODO: sub_compact.io_status is not checked like status. Not sure if thats
|
|
// intentional. So ignoring the io_status as of now.
|
|
io_status.PermitUncheckedError();
|
|
}
|
|
|
|
Slice SubcompactionState::SmallestUserKey() const {
|
|
if (has_penultimate_level_outputs_) {
|
|
Slice a = compaction_outputs_.SmallestUserKey();
|
|
Slice b = penultimate_level_outputs_.SmallestUserKey();
|
|
if (a.empty()) {
|
|
return b;
|
|
}
|
|
if (b.empty()) {
|
|
return a;
|
|
}
|
|
const Comparator* user_cmp =
|
|
compaction->column_family_data()->user_comparator();
|
|
if (user_cmp->Compare(a, b) > 0) {
|
|
return b;
|
|
} else {
|
|
return a;
|
|
}
|
|
} else {
|
|
return compaction_outputs_.SmallestUserKey();
|
|
}
|
|
}
|
|
|
|
Slice SubcompactionState::LargestUserKey() const {
|
|
if (has_penultimate_level_outputs_) {
|
|
Slice a = compaction_outputs_.LargestUserKey();
|
|
Slice b = penultimate_level_outputs_.LargestUserKey();
|
|
if (a.empty()) {
|
|
return b;
|
|
}
|
|
if (b.empty()) {
|
|
return a;
|
|
}
|
|
const Comparator* user_cmp =
|
|
compaction->column_family_data()->user_comparator();
|
|
if (user_cmp->Compare(a, b) < 0) {
|
|
return b;
|
|
} else {
|
|
return a;
|
|
}
|
|
} else {
|
|
return compaction_outputs_.LargestUserKey();
|
|
}
|
|
}
|
|
|
|
Status SubcompactionState::AddToOutput(
|
|
const CompactionIterator& iter,
|
|
const CompactionFileOpenFunc& open_file_func,
|
|
const CompactionFileCloseFunc& close_file_func) {
|
|
// update target output first
|
|
is_current_penultimate_level_ = iter.output_to_penultimate_level();
|
|
current_outputs_ = is_current_penultimate_level_ ? &penultimate_level_outputs_
|
|
: &compaction_outputs_;
|
|
if (is_current_penultimate_level_) {
|
|
has_penultimate_level_outputs_ = true;
|
|
}
|
|
|
|
return Current().AddToOutput(iter, open_file_func, close_file_func);
|
|
}
|
|
|
|
} // namespace ROCKSDB_NAMESPACE
|