Add more tests to ASSERT_STATUS_CHECKED (4) (#7718)
Summary: Fourth batch of adding more tests to ASSERT_STATUS_CHECKED. * db_range_del_test * db_write_test * random_access_file_reader_test * merge_test * external_sst_file_test * write_buffer_manager_test * stringappend_test * deletefile_test Pull Request resolved: https://github.com/facebook/rocksdb/pull/7718 Reviewed By: pdillinger Differential Revision: D25671608 fbshipit-source-id: 687a794e98a9e0cd5428ead9898ef05ced987c31
This commit is contained in:
parent
41ff125a8a
commit
81592d9ffa
8
Makefile
8
Makefile
@ -606,9 +606,13 @@ ifdef ASSERT_STATUS_CHECKED
|
|||||||
db_wal_test \
|
db_wal_test \
|
||||||
db_with_timestamp_basic_test \
|
db_with_timestamp_basic_test \
|
||||||
db_with_timestamp_compaction_test \
|
db_with_timestamp_compaction_test \
|
||||||
|
db_write_test \
|
||||||
db_options_test \
|
db_options_test \
|
||||||
db_properties_test \
|
db_properties_test \
|
||||||
|
db_range_del_test \
|
||||||
db_secondary_test \
|
db_secondary_test \
|
||||||
|
deletefile_test \
|
||||||
|
external_sst_file_test \
|
||||||
options_file_test \
|
options_file_test \
|
||||||
defer_test \
|
defer_test \
|
||||||
filename_test \
|
filename_test \
|
||||||
@ -631,6 +635,7 @@ ifdef ASSERT_STATUS_CHECKED
|
|||||||
iostats_context_test \
|
iostats_context_test \
|
||||||
ldb_cmd_test \
|
ldb_cmd_test \
|
||||||
memkind_kmem_allocator_test \
|
memkind_kmem_allocator_test \
|
||||||
|
merge_test \
|
||||||
merger_test \
|
merger_test \
|
||||||
mock_env_test \
|
mock_env_test \
|
||||||
object_registry_test \
|
object_registry_test \
|
||||||
@ -643,6 +648,7 @@ ifdef ASSERT_STATUS_CHECKED
|
|||||||
options_settable_test \
|
options_settable_test \
|
||||||
options_test \
|
options_test \
|
||||||
point_lock_manager_test \
|
point_lock_manager_test \
|
||||||
|
random_access_file_reader_test \
|
||||||
random_test \
|
random_test \
|
||||||
range_del_aggregator_test \
|
range_del_aggregator_test \
|
||||||
sst_file_reader_test \
|
sst_file_reader_test \
|
||||||
@ -654,6 +660,7 @@ ifdef ASSERT_STATUS_CHECKED
|
|||||||
sst_dump_test \
|
sst_dump_test \
|
||||||
statistics_test \
|
statistics_test \
|
||||||
stats_history_test \
|
stats_history_test \
|
||||||
|
stringappend_test \
|
||||||
thread_local_test \
|
thread_local_test \
|
||||||
trace_analyzer_test \
|
trace_analyzer_test \
|
||||||
transaction_test \
|
transaction_test \
|
||||||
@ -671,6 +678,7 @@ ifdef ASSERT_STATUS_CHECKED
|
|||||||
version_builder_test \
|
version_builder_test \
|
||||||
version_edit_test \
|
version_edit_test \
|
||||||
work_queue_test \
|
work_queue_test \
|
||||||
|
write_buffer_manager_test \
|
||||||
write_controller_test \
|
write_controller_test \
|
||||||
write_prepared_transaction_test \
|
write_prepared_transaction_test \
|
||||||
write_unprepared_transaction_test \
|
write_unprepared_transaction_test \
|
||||||
|
@ -1449,9 +1449,8 @@ Status CompactionJob::FinishCompactionOutputFile(
|
|||||||
} else {
|
} else {
|
||||||
sub_compact->builder->Abandon();
|
sub_compact->builder->Abandon();
|
||||||
}
|
}
|
||||||
IOStatus io_s = sub_compact->builder->io_status();
|
|
||||||
if (s.ok()) {
|
if (s.ok()) {
|
||||||
s = io_s;
|
s = sub_compact->builder->io_status();
|
||||||
}
|
}
|
||||||
const uint64_t current_bytes = sub_compact->builder->FileSize();
|
const uint64_t current_bytes = sub_compact->builder->FileSize();
|
||||||
if (s.ok()) {
|
if (s.ok()) {
|
||||||
@ -1462,6 +1461,7 @@ Status CompactionJob::FinishCompactionOutputFile(
|
|||||||
sub_compact->total_bytes += current_bytes;
|
sub_compact->total_bytes += current_bytes;
|
||||||
|
|
||||||
// Finish and check for file errors
|
// Finish and check for file errors
|
||||||
|
IOStatus io_s;
|
||||||
if (s.ok()) {
|
if (s.ok()) {
|
||||||
StopWatch sw(env_, stats_, COMPACTION_OUTFILE_SYNC_MICROS);
|
StopWatch sw(env_, stats_, COMPACTION_OUTFILE_SYNC_MICROS);
|
||||||
io_s = sub_compact->outfile->Sync(db_options_.use_fsync);
|
io_s = sub_compact->outfile->Sync(db_options_.use_fsync);
|
||||||
@ -1500,7 +1500,18 @@ Status CompactionJob::FinishCompactionOutputFile(
|
|||||||
std::string fname =
|
std::string fname =
|
||||||
TableFileName(sub_compact->compaction->immutable_cf_options()->cf_paths,
|
TableFileName(sub_compact->compaction->immutable_cf_options()->cf_paths,
|
||||||
meta->fd.GetNumber(), meta->fd.GetPathId());
|
meta->fd.GetNumber(), meta->fd.GetPathId());
|
||||||
env_->DeleteFile(fname);
|
|
||||||
|
// TODO(AR) it is not clear if there are any larger implications if
|
||||||
|
// DeleteFile fails here
|
||||||
|
Status ds = env_->DeleteFile(fname);
|
||||||
|
if (!ds.ok()) {
|
||||||
|
ROCKS_LOG_WARN(
|
||||||
|
db_options_.info_log,
|
||||||
|
"[%s] [JOB %d] Unable to remove SST file for table #%" PRIu64
|
||||||
|
" at bottom level%s",
|
||||||
|
cfd->GetName().c_str(), job_id_, output_number,
|
||||||
|
meta->marked_for_compaction ? " (need compaction)" : "");
|
||||||
|
}
|
||||||
|
|
||||||
// Also need to remove the file from outputs, or it will be added to the
|
// Also need to remove the file from outputs, or it will be added to the
|
||||||
// VersionEdit.
|
// VersionEdit.
|
||||||
|
@ -3483,7 +3483,6 @@ Status DBImpl::DeleteFile(std::string name) {
|
|||||||
return Status::InvalidArgument("Invalid file name");
|
return Status::InvalidArgument("Invalid file name");
|
||||||
}
|
}
|
||||||
|
|
||||||
Status status;
|
|
||||||
if (type == kWalFile) {
|
if (type == kWalFile) {
|
||||||
// Only allow deleting archived log files
|
// Only allow deleting archived log files
|
||||||
if (log_type != kArchivedLogFile) {
|
if (log_type != kArchivedLogFile) {
|
||||||
@ -3492,7 +3491,7 @@ Status DBImpl::DeleteFile(std::string name) {
|
|||||||
name.c_str());
|
name.c_str());
|
||||||
return Status::NotSupported("Delete only supported for archived logs");
|
return Status::NotSupported("Delete only supported for archived logs");
|
||||||
}
|
}
|
||||||
status = wal_manager_.DeleteFile(name, number);
|
Status status = wal_manager_.DeleteFile(name, number);
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
ROCKS_LOG_ERROR(immutable_db_options_.info_log,
|
ROCKS_LOG_ERROR(immutable_db_options_.info_log,
|
||||||
"DeleteFile %s failed -- %s.\n", name.c_str(),
|
"DeleteFile %s failed -- %s.\n", name.c_str(),
|
||||||
@ -3501,6 +3500,7 @@ Status DBImpl::DeleteFile(std::string name) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status status;
|
||||||
int level;
|
int level;
|
||||||
FileMetaData* metadata;
|
FileMetaData* metadata;
|
||||||
ColumnFamilyData* cfd;
|
ColumnFamilyData* cfd;
|
||||||
@ -4354,7 +4354,7 @@ Status DBImpl::IngestExternalFiles(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Ingest multiple external SST files atomically.
|
// Ingest multiple external SST files atomically.
|
||||||
size_t num_cfs = args.size();
|
const size_t num_cfs = args.size();
|
||||||
for (size_t i = 0; i != num_cfs; ++i) {
|
for (size_t i = 0; i != num_cfs; ++i) {
|
||||||
if (args[i].external_files.empty()) {
|
if (args[i].external_files.empty()) {
|
||||||
char err_msg[128] = {0};
|
char err_msg[128] = {0};
|
||||||
@ -4395,10 +4395,7 @@ Status DBImpl::IngestExternalFiles(
|
|||||||
env_, versions_.get(), cfd, immutable_db_options_, file_options_,
|
env_, versions_.get(), cfd, immutable_db_options_, file_options_,
|
||||||
&snapshots_, arg.options, &directories_, &event_logger_, io_tracer_);
|
&snapshots_, arg.options, &directories_, &event_logger_, io_tracer_);
|
||||||
}
|
}
|
||||||
std::vector<std::pair<bool, Status>> exec_results;
|
|
||||||
for (size_t i = 0; i != num_cfs; ++i) {
|
|
||||||
exec_results.emplace_back(false, Status::OK());
|
|
||||||
}
|
|
||||||
// TODO(yanqin) maybe make jobs run in parallel
|
// TODO(yanqin) maybe make jobs run in parallel
|
||||||
uint64_t start_file_number = next_file_number;
|
uint64_t start_file_number = next_file_number;
|
||||||
for (size_t i = 1; i != num_cfs; ++i) {
|
for (size_t i = 1; i != num_cfs; ++i) {
|
||||||
@ -4406,10 +4403,13 @@ Status DBImpl::IngestExternalFiles(
|
|||||||
auto* cfd =
|
auto* cfd =
|
||||||
static_cast<ColumnFamilyHandleImpl*>(args[i].column_family)->cfd();
|
static_cast<ColumnFamilyHandleImpl*>(args[i].column_family)->cfd();
|
||||||
SuperVersion* super_version = cfd->GetReferencedSuperVersion(this);
|
SuperVersion* super_version = cfd->GetReferencedSuperVersion(this);
|
||||||
exec_results[i].second = ingestion_jobs[i].Prepare(
|
Status es = ingestion_jobs[i].Prepare(
|
||||||
args[i].external_files, args[i].files_checksums,
|
args[i].external_files, args[i].files_checksums,
|
||||||
args[i].files_checksum_func_names, start_file_number, super_version);
|
args[i].files_checksum_func_names, start_file_number, super_version);
|
||||||
exec_results[i].first = true;
|
// capture first error only
|
||||||
|
if (!es.ok() && status.ok()) {
|
||||||
|
status = es;
|
||||||
|
}
|
||||||
CleanupSuperVersion(super_version);
|
CleanupSuperVersion(super_version);
|
||||||
}
|
}
|
||||||
TEST_SYNC_POINT("DBImpl::IngestExternalFiles:BeforeLastJobPrepare:0");
|
TEST_SYNC_POINT("DBImpl::IngestExternalFiles:BeforeLastJobPrepare:0");
|
||||||
@ -4418,24 +4418,18 @@ Status DBImpl::IngestExternalFiles(
|
|||||||
auto* cfd =
|
auto* cfd =
|
||||||
static_cast<ColumnFamilyHandleImpl*>(args[0].column_family)->cfd();
|
static_cast<ColumnFamilyHandleImpl*>(args[0].column_family)->cfd();
|
||||||
SuperVersion* super_version = cfd->GetReferencedSuperVersion(this);
|
SuperVersion* super_version = cfd->GetReferencedSuperVersion(this);
|
||||||
exec_results[0].second = ingestion_jobs[0].Prepare(
|
Status es = ingestion_jobs[0].Prepare(
|
||||||
args[0].external_files, args[0].files_checksums,
|
args[0].external_files, args[0].files_checksums,
|
||||||
args[0].files_checksum_func_names, next_file_number, super_version);
|
args[0].files_checksum_func_names, next_file_number, super_version);
|
||||||
exec_results[0].first = true;
|
if (!es.ok()) {
|
||||||
|
status = es;
|
||||||
|
}
|
||||||
CleanupSuperVersion(super_version);
|
CleanupSuperVersion(super_version);
|
||||||
}
|
}
|
||||||
for (const auto& exec_result : exec_results) {
|
|
||||||
if (!exec_result.second.ok()) {
|
|
||||||
status = exec_result.second;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
for (size_t i = 0; i != num_cfs; ++i) {
|
for (size_t i = 0; i != num_cfs; ++i) {
|
||||||
if (exec_results[i].first) {
|
|
||||||
ingestion_jobs[i].Cleanup(status);
|
ingestion_jobs[i].Cleanup(status);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
InstrumentedMutexLock l(&mutex_);
|
InstrumentedMutexLock l(&mutex_);
|
||||||
ReleaseFileNumberFromPendingOutputs(pending_output_elem);
|
ReleaseFileNumberFromPendingOutputs(pending_output_elem);
|
||||||
return status;
|
return status;
|
||||||
|
@ -566,7 +566,12 @@ Status DBImpl::PipelinedWriteImpl(const WriteOptions& write_options,
|
|||||||
write_thread_.ExitAsBatchGroupLeader(wal_write_group, w.status);
|
write_thread_.ExitAsBatchGroupLeader(wal_write_group, w.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: the memtable_write_group is declared before the following
|
||||||
|
// `if` statement because its lifetime needs to be longer
|
||||||
|
// that the inner context of the `if` as a reference to it
|
||||||
|
// may be used further below within the outer _write_thread
|
||||||
WriteThread::WriteGroup memtable_write_group;
|
WriteThread::WriteGroup memtable_write_group;
|
||||||
|
|
||||||
if (w.state == WriteThread::STATE_MEMTABLE_WRITER_LEADER) {
|
if (w.state == WriteThread::STATE_MEMTABLE_WRITER_LEADER) {
|
||||||
PERF_TIMER_GUARD(write_memtable_time);
|
PERF_TIMER_GUARD(write_memtable_time);
|
||||||
assert(w.ShouldWriteToMemtable());
|
assert(w.ShouldWriteToMemtable());
|
||||||
@ -583,6 +588,10 @@ Status DBImpl::PipelinedWriteImpl(const WriteOptions& write_options,
|
|||||||
versions_->SetLastSequence(memtable_write_group.last_sequence);
|
versions_->SetLastSequence(memtable_write_group.last_sequence);
|
||||||
write_thread_.ExitAsMemTableWriter(&w, memtable_write_group);
|
write_thread_.ExitAsMemTableWriter(&w, memtable_write_group);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// NOTE: the memtable_write_group is never really used,
|
||||||
|
// so we need to set its status to pass ASSERT_STATUS_CHECKED
|
||||||
|
memtable_write_group.status.PermitUncheckedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w.state == WriteThread::STATE_PARALLEL_MEMTABLE_WRITER) {
|
if (w.state == WriteThread::STATE_PARALLEL_MEMTABLE_WRITER) {
|
||||||
|
@ -56,7 +56,7 @@ TEST_F(DBRangeDelTest, EndSameAsStartCoversNothing) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DBRangeDelTest, EndComesBeforeStartInvalidArgument) {
|
TEST_F(DBRangeDelTest, EndComesBeforeStartInvalidArgument) {
|
||||||
db_->Put(WriteOptions(), "b", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "b", "val"));
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "b", "a")
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "b", "a")
|
||||||
.IsInvalidArgument());
|
.IsInvalidArgument());
|
||||||
@ -82,13 +82,14 @@ TEST_F(DBRangeDelTest, CompactionOutputHasOnlyRangeTombstone) {
|
|||||||
|
|
||||||
// snapshot protects range tombstone from dropping due to becoming obsolete.
|
// snapshot protects range tombstone from dropping due to becoming obsolete.
|
||||||
const Snapshot* snapshot = db_->GetSnapshot();
|
const Snapshot* snapshot = db_->GetSnapshot();
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z");
|
ASSERT_OK(
|
||||||
db_->Flush(FlushOptions());
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
||||||
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
|
|
||||||
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
||||||
dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
|
ASSERT_OK(dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
|
||||||
true /* disallow_trivial_move */);
|
true /* disallow_trivial_move */));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
||||||
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
||||||
ASSERT_EQ(0, TestGetTickerCount(opts, COMPACTION_RANGE_DEL_DROP_OBSOLETE));
|
ASSERT_EQ(0, TestGetTickerCount(opts, COMPACTION_RANGE_DEL_DROP_OBSOLETE));
|
||||||
@ -118,7 +119,8 @@ TEST_F(DBRangeDelTest, CompactionOutputFilesExactlyFilled) {
|
|||||||
|
|
||||||
// snapshot protects range tombstone from dropping due to becoming obsolete.
|
// snapshot protects range tombstone from dropping due to becoming obsolete.
|
||||||
const Snapshot* snapshot = db_->GetSnapshot();
|
const Snapshot* snapshot = db_->GetSnapshot();
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0), Key(1));
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0),
|
||||||
|
Key(1)));
|
||||||
|
|
||||||
Random rnd(301);
|
Random rnd(301);
|
||||||
for (int i = 0; i < kNumFiles; ++i) {
|
for (int i = 0; i < kNumFiles; ++i) {
|
||||||
@ -128,18 +130,18 @@ TEST_F(DBRangeDelTest, CompactionOutputFilesExactlyFilled) {
|
|||||||
values.push_back(rnd.RandomString(3 << 10));
|
values.push_back(rnd.RandomString(3 << 10));
|
||||||
ASSERT_OK(Put(Key(i * kNumPerFile + j), values[j]));
|
ASSERT_OK(Put(Key(i * kNumPerFile + j), values[j]));
|
||||||
if (j == 0 && i > 0) {
|
if (j == 0 && i > 0) {
|
||||||
dbfull()->TEST_WaitForFlushMemTable();
|
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// put extra key to trigger final flush
|
// put extra key to trigger final flush
|
||||||
ASSERT_OK(Put("", ""));
|
ASSERT_OK(Put("", ""));
|
||||||
dbfull()->TEST_WaitForFlushMemTable();
|
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
|
||||||
ASSERT_EQ(kNumFiles, NumTableFilesAtLevel(0));
|
ASSERT_EQ(kNumFiles, NumTableFilesAtLevel(0));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
||||||
|
|
||||||
dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
|
ASSERT_OK(dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
|
||||||
true /* disallow_trivial_move */);
|
true /* disallow_trivial_move */));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
||||||
ASSERT_EQ(2, NumTableFilesAtLevel(1));
|
ASSERT_EQ(2, NumTableFilesAtLevel(1));
|
||||||
db_->ReleaseSnapshot(snapshot);
|
db_->ReleaseSnapshot(snapshot);
|
||||||
@ -178,12 +180,12 @@ TEST_F(DBRangeDelTest, MaxCompactionBytesCutsOutputFiles) {
|
|||||||
}
|
}
|
||||||
// extra entry to trigger SpecialSkipListFactory's flush
|
// extra entry to trigger SpecialSkipListFactory's flush
|
||||||
ASSERT_OK(Put(GetNumericStr(kNumPerFile), ""));
|
ASSERT_OK(Put(GetNumericStr(kNumPerFile), ""));
|
||||||
dbfull()->TEST_WaitForFlushMemTable();
|
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
|
||||||
ASSERT_EQ(i + 1, NumTableFilesAtLevel(0));
|
ASSERT_EQ(i + 1, NumTableFilesAtLevel(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
|
ASSERT_OK(dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
|
||||||
true /* disallow_trivial_move */);
|
true /* disallow_trivial_move */));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
||||||
ASSERT_GE(NumTableFilesAtLevel(1), 2);
|
ASSERT_GE(NumTableFilesAtLevel(1), 2);
|
||||||
|
|
||||||
@ -221,10 +223,10 @@ TEST_F(DBRangeDelTest, SentinelsOmittedFromOutputFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DBRangeDelTest, FlushRangeDelsSameStartKey) {
|
TEST_F(DBRangeDelTest, FlushRangeDelsSameStartKey) {
|
||||||
db_->Put(WriteOptions(), "b1", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "b1", "val"));
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "c"));
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "c"));
|
||||||
db_->Put(WriteOptions(), "b2", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "b2", "val"));
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "b"));
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "b"));
|
||||||
// first iteration verifies query correctness in memtable, second verifies
|
// first iteration verifies query correctness in memtable, second verifies
|
||||||
@ -241,8 +243,9 @@ TEST_F(DBRangeDelTest, FlushRangeDelsSameStartKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DBRangeDelTest, CompactRangeDelsSameStartKey) {
|
TEST_F(DBRangeDelTest, CompactRangeDelsSameStartKey) {
|
||||||
db_->Put(WriteOptions(), "unused", "val"); // prevents empty after compaction
|
ASSERT_OK(db_->Put(WriteOptions(), "unused",
|
||||||
db_->Put(WriteOptions(), "b1", "val");
|
"val")); // prevents empty after compaction
|
||||||
|
ASSERT_OK(db_->Put(WriteOptions(), "b1", "val"));
|
||||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "c"));
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "c"));
|
||||||
@ -254,8 +257,8 @@ TEST_F(DBRangeDelTest, CompactRangeDelsSameStartKey) {
|
|||||||
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
|
ASSERT_OK(dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
|
||||||
true /* disallow_trivial_move */);
|
true /* disallow_trivial_move */));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
||||||
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
||||||
}
|
}
|
||||||
@ -279,12 +282,13 @@ TEST_F(DBRangeDelTest, FlushRemovesCoveredKeys) {
|
|||||||
if (i == kNum / 3) {
|
if (i == kNum / 3) {
|
||||||
snapshot = db_->GetSnapshot();
|
snapshot = db_->GetSnapshot();
|
||||||
} else if (i == 2 * kNum / 3) {
|
} else if (i == 2 * kNum / 3) {
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
||||||
GetNumericStr(kRangeBegin), GetNumericStr(kRangeEnd));
|
GetNumericStr(kRangeBegin),
|
||||||
|
GetNumericStr(kRangeEnd)));
|
||||||
}
|
}
|
||||||
db_->Put(WriteOptions(), GetNumericStr(i), "val");
|
ASSERT_OK(db_->Put(WriteOptions(), GetNumericStr(i), "val"));
|
||||||
}
|
}
|
||||||
db_->Flush(FlushOptions());
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
|
|
||||||
for (int i = 0; i < kNum; ++i) {
|
for (int i = 0; i < kNum; ++i) {
|
||||||
ReadOptions read_opts;
|
ReadOptions read_opts;
|
||||||
@ -314,24 +318,27 @@ TEST_F(DBRangeDelTest, CompactionRemovesCoveredKeys) {
|
|||||||
for (int i = 0; i < kNumFiles; ++i) {
|
for (int i = 0; i < kNumFiles; ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
// range tombstone covers first half of the previous file
|
// range tombstone covers first half of the previous file
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
ASSERT_OK(db_->DeleteRange(
|
||||||
|
WriteOptions(), db_->DefaultColumnFamily(),
|
||||||
GetNumericStr((i - 1) * kNumPerFile),
|
GetNumericStr((i - 1) * kNumPerFile),
|
||||||
GetNumericStr((i - 1) * kNumPerFile + kNumPerFile / 2));
|
GetNumericStr((i - 1) * kNumPerFile + kNumPerFile / 2)));
|
||||||
}
|
}
|
||||||
// Make sure a given key appears in each file so compaction won't be able to
|
// Make sure a given key appears in each file so compaction won't be able to
|
||||||
// use trivial move, which would happen if the ranges were non-overlapping.
|
// use trivial move, which would happen if the ranges were non-overlapping.
|
||||||
// Also, we need an extra element since flush is only triggered when the
|
// Also, we need an extra element since flush is only triggered when the
|
||||||
// number of keys is one greater than SpecialSkipListFactory's limit.
|
// number of keys is one greater than SpecialSkipListFactory's limit.
|
||||||
// We choose a key outside the key-range used by the test to avoid conflict.
|
// We choose a key outside the key-range used by the test to avoid conflict.
|
||||||
db_->Put(WriteOptions(), GetNumericStr(kNumPerFile * kNumFiles), "val");
|
ASSERT_OK(db_->Put(WriteOptions(), GetNumericStr(kNumPerFile * kNumFiles),
|
||||||
|
"val"));
|
||||||
|
|
||||||
for (int j = 0; j < kNumPerFile; ++j) {
|
for (int j = 0; j < kNumPerFile; ++j) {
|
||||||
db_->Put(WriteOptions(), GetNumericStr(i * kNumPerFile + j), "val");
|
ASSERT_OK(
|
||||||
|
db_->Put(WriteOptions(), GetNumericStr(i * kNumPerFile + j), "val"));
|
||||||
}
|
}
|
||||||
dbfull()->TEST_WaitForFlushMemTable();
|
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
|
||||||
ASSERT_EQ(i + 1, NumTableFilesAtLevel(0));
|
ASSERT_EQ(i + 1, NumTableFilesAtLevel(0));
|
||||||
}
|
}
|
||||||
db_->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
||||||
ASSERT_GT(NumTableFilesAtLevel(1), 0);
|
ASSERT_GT(NumTableFilesAtLevel(1), 0);
|
||||||
ASSERT_EQ((kNumFiles - 1) * kNumPerFile / 2,
|
ASSERT_EQ((kNumFiles - 1) * kNumPerFile / 2,
|
||||||
@ -373,8 +380,8 @@ TEST_F(DBRangeDelTest, ValidLevelSubcompactionBoundaries) {
|
|||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
// delete [95,105) in two files, [295,305) in next two
|
// delete [95,105) in two files, [295,305) in next two
|
||||||
int mid = (j + (1 - j % 2)) * kNumPerFile;
|
int mid = (j + (1 - j % 2)) * kNumPerFile;
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
||||||
Key(mid - 5), Key(mid + 5));
|
Key(mid - 5), Key(mid + 5)));
|
||||||
}
|
}
|
||||||
std::vector<std::string> values;
|
std::vector<std::string> values;
|
||||||
// Write 100KB (100 values, each 1K)
|
// Write 100KB (100 values, each 1K)
|
||||||
@ -384,7 +391,7 @@ TEST_F(DBRangeDelTest, ValidLevelSubcompactionBoundaries) {
|
|||||||
}
|
}
|
||||||
// put extra key to trigger flush
|
// put extra key to trigger flush
|
||||||
ASSERT_OK(Put("", ""));
|
ASSERT_OK(Put("", ""));
|
||||||
dbfull()->TEST_WaitForFlushMemTable();
|
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
|
||||||
if (j < kNumFiles - 1) {
|
if (j < kNumFiles - 1) {
|
||||||
// background compaction may happen early for kNumFiles'th file
|
// background compaction may happen early for kNumFiles'th file
|
||||||
ASSERT_EQ(NumTableFilesAtLevel(0), j + 1);
|
ASSERT_EQ(NumTableFilesAtLevel(0), j + 1);
|
||||||
@ -400,7 +407,7 @@ TEST_F(DBRangeDelTest, ValidLevelSubcompactionBoundaries) {
|
|||||||
// oversized L0 (relative to base_level) causes the compaction to run
|
// oversized L0 (relative to base_level) causes the compaction to run
|
||||||
// earlier.
|
// earlier.
|
||||||
ASSERT_OK(db_->EnableAutoCompaction({db_->DefaultColumnFamily()}));
|
ASSERT_OK(db_->EnableAutoCompaction({db_->DefaultColumnFamily()}));
|
||||||
dbfull()->TEST_WaitForCompact();
|
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||||
ASSERT_OK(db_->SetOptions(db_->DefaultColumnFamily(),
|
ASSERT_OK(db_->SetOptions(db_->DefaultColumnFamily(),
|
||||||
{{"disable_auto_compactions", "true"}}));
|
{{"disable_auto_compactions", "true"}}));
|
||||||
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
|
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
|
||||||
@ -433,8 +440,8 @@ TEST_F(DBRangeDelTest, ValidUniversalSubcompactionBoundaries) {
|
|||||||
// insert range deletions [95,105) in two files, [295,305) in next two
|
// insert range deletions [95,105) in two files, [295,305) in next two
|
||||||
// to prepare L1 for later manual compaction.
|
// to prepare L1 for later manual compaction.
|
||||||
int mid = (j + (1 - j % 2)) * kNumPerFile;
|
int mid = (j + (1 - j % 2)) * kNumPerFile;
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
||||||
Key(mid - 5), Key(mid + 5));
|
Key(mid - 5), Key(mid + 5)));
|
||||||
}
|
}
|
||||||
std::vector<std::string> values;
|
std::vector<std::string> values;
|
||||||
// Write 100KB (100 values, each 1K)
|
// Write 100KB (100 values, each 1K)
|
||||||
@ -444,13 +451,13 @@ TEST_F(DBRangeDelTest, ValidUniversalSubcompactionBoundaries) {
|
|||||||
}
|
}
|
||||||
// put extra key to trigger flush
|
// put extra key to trigger flush
|
||||||
ASSERT_OK(Put("", ""));
|
ASSERT_OK(Put("", ""));
|
||||||
dbfull()->TEST_WaitForFlushMemTable();
|
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
|
||||||
if (j < kFilesPerLevel - 1) {
|
if (j < kFilesPerLevel - 1) {
|
||||||
// background compaction may happen early for kFilesPerLevel'th file
|
// background compaction may happen early for kFilesPerLevel'th file
|
||||||
ASSERT_EQ(NumTableFilesAtLevel(0), j + 1);
|
ASSERT_EQ(NumTableFilesAtLevel(0), j + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbfull()->TEST_WaitForCompact();
|
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||||
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
|
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
|
||||||
ASSERT_GT(NumTableFilesAtLevel(kNumLevels - 1 - i), kFilesPerLevel - 1);
|
ASSERT_GT(NumTableFilesAtLevel(kNumLevels - 1 - i), kFilesPerLevel - 1);
|
||||||
}
|
}
|
||||||
@ -483,17 +490,17 @@ TEST_F(DBRangeDelTest, CompactionRemovesCoveredMergeOperands) {
|
|||||||
for (int i = 0; i <= kNumFiles * kNumPerFile; ++i) {
|
for (int i = 0; i <= kNumFiles * kNumPerFile; ++i) {
|
||||||
if (i % kNumPerFile == 0 && i / kNumPerFile == kNumFiles - 1) {
|
if (i % kNumPerFile == 0 && i / kNumPerFile == kNumFiles - 1) {
|
||||||
// Delete merge operands from all but the last file
|
// Delete merge operands from all but the last file
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "key",
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
||||||
"key_");
|
"key", "key_"));
|
||||||
}
|
}
|
||||||
std::string val;
|
std::string val;
|
||||||
PutFixed64(&val, i);
|
PutFixed64(&val, i);
|
||||||
db_->Merge(WriteOptions(), "key", val);
|
ASSERT_OK(db_->Merge(WriteOptions(), "key", val));
|
||||||
// we need to prevent trivial move using Puts so compaction will actually
|
// we need to prevent trivial move using Puts so compaction will actually
|
||||||
// process the merge operands.
|
// process the merge operands.
|
||||||
db_->Put(WriteOptions(), "prevent_trivial_move", "");
|
ASSERT_OK(db_->Put(WriteOptions(), "prevent_trivial_move", ""));
|
||||||
if (i > 0 && i % kNumPerFile == 0) {
|
if (i > 0 && i % kNumPerFile == 0) {
|
||||||
dbfull()->TEST_WaitForFlushMemTable();
|
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,7 +511,7 @@ TEST_F(DBRangeDelTest, CompactionRemovesCoveredMergeOperands) {
|
|||||||
PutFixed64(&expected, 45); // 1+2+...+9
|
PutFixed64(&expected, 45); // 1+2+...+9
|
||||||
ASSERT_EQ(expected, actual);
|
ASSERT_EQ(expected, actual);
|
||||||
|
|
||||||
db_->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
|
|
||||||
expected.clear();
|
expected.clear();
|
||||||
ASSERT_OK(db_->Get(read_opts, "key", &actual));
|
ASSERT_OK(db_->Get(read_opts, "key", &actual));
|
||||||
@ -550,19 +557,19 @@ TEST_F(DBRangeDelTest, ObsoleteTombstoneCleanup) {
|
|||||||
opts.statistics = CreateDBStatistics();
|
opts.statistics = CreateDBStatistics();
|
||||||
Reopen(opts);
|
Reopen(opts);
|
||||||
|
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "dr1",
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "dr1",
|
||||||
"dr10"); // obsolete after compaction
|
"dr10")); // obsolete after compaction
|
||||||
db_->Put(WriteOptions(), "key", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "key", "val"));
|
||||||
db_->Flush(FlushOptions());
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
const Snapshot* snapshot = db_->GetSnapshot();
|
const Snapshot* snapshot = db_->GetSnapshot();
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "dr2",
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "dr2",
|
||||||
"dr20"); // protected by snapshot
|
"dr20")); // protected by snapshot
|
||||||
db_->Put(WriteOptions(), "key", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "key", "val"));
|
||||||
db_->Flush(FlushOptions());
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
|
|
||||||
ASSERT_EQ(2, NumTableFilesAtLevel(0));
|
ASSERT_EQ(2, NumTableFilesAtLevel(0));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
||||||
db_->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
||||||
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
||||||
ASSERT_EQ(1, TestGetTickerCount(opts, COMPACTION_RANGE_DEL_DROP_OBSOLETE));
|
ASSERT_EQ(1, TestGetTickerCount(opts, COMPACTION_RANGE_DEL_DROP_OBSOLETE));
|
||||||
@ -609,22 +616,24 @@ TEST_F(DBRangeDelTest, TableEvictedDuringScan) {
|
|||||||
// to bottommost level (i.e., L1).
|
// to bottommost level (i.e., L1).
|
||||||
const Snapshot* snapshot = db_->GetSnapshot();
|
const Snapshot* snapshot = db_->GetSnapshot();
|
||||||
for (int i = 0; i < kNum; ++i) {
|
for (int i = 0; i < kNum; ++i) {
|
||||||
db_->Put(WriteOptions(), GetNumericStr(i), "val");
|
ASSERT_OK(db_->Put(WriteOptions(), GetNumericStr(i), "val"));
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
dbfull()->TEST_WaitForFlushMemTable();
|
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
|
||||||
}
|
}
|
||||||
if (i >= kNum / 2 && i < kNum / 2 + kNumRanges) {
|
if (i >= kNum / 2 && i < kNum / 2 + kNumRanges) {
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
||||||
GetNumericStr(kRangeBegin), GetNumericStr(kRangeEnd));
|
GetNumericStr(kRangeBegin),
|
||||||
|
GetNumericStr(kRangeEnd)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Must be > 1 so the first L1 file can be closed before scan finishes
|
// Must be > 1 so the first L1 file can be closed before scan finishes
|
||||||
dbfull()->TEST_WaitForCompact();
|
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||||
ASSERT_GT(NumTableFilesAtLevel(1), 1);
|
ASSERT_GT(NumTableFilesAtLevel(1), 1);
|
||||||
std::vector<uint64_t> file_numbers = ListTableFiles(env_, dbname_);
|
std::vector<uint64_t> file_numbers = ListTableFiles(env_, dbname_);
|
||||||
|
|
||||||
ReadOptions read_opts;
|
ReadOptions read_opts;
|
||||||
auto* iter = db_->NewIterator(read_opts);
|
auto* iter = db_->NewIterator(read_opts);
|
||||||
|
ASSERT_OK(iter->status());
|
||||||
int expected = kRangeEnd;
|
int expected = kRangeEnd;
|
||||||
iter->SeekToFirst();
|
iter->SeekToFirst();
|
||||||
for (auto file_number : file_numbers) {
|
for (auto file_number : file_numbers) {
|
||||||
@ -647,7 +656,7 @@ TEST_F(DBRangeDelTest, TableEvictedDuringScan) {
|
|||||||
TEST_F(DBRangeDelTest, GetCoveredKeyFromMutableMemtable) {
|
TEST_F(DBRangeDelTest, GetCoveredKeyFromMutableMemtable) {
|
||||||
do {
|
do {
|
||||||
DestroyAndReopen(CurrentOptions());
|
DestroyAndReopen(CurrentOptions());
|
||||||
db_->Put(WriteOptions(), "key", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "key", "val"));
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
||||||
|
|
||||||
@ -669,10 +678,10 @@ TEST_F(DBRangeDelTest, GetCoveredKeyFromImmutableMemtable) {
|
|||||||
opts.memtable_factory.reset(new SpecialSkipListFactory(1));
|
opts.memtable_factory.reset(new SpecialSkipListFactory(1));
|
||||||
DestroyAndReopen(opts);
|
DestroyAndReopen(opts);
|
||||||
|
|
||||||
db_->Put(WriteOptions(), "key", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "key", "val"));
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
||||||
db_->Put(WriteOptions(), "blah", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "blah", "val"));
|
||||||
|
|
||||||
ReadOptions read_opts;
|
ReadOptions read_opts;
|
||||||
std::string value;
|
std::string value;
|
||||||
@ -683,7 +692,7 @@ TEST_F(DBRangeDelTest, GetCoveredKeyFromImmutableMemtable) {
|
|||||||
TEST_F(DBRangeDelTest, GetCoveredKeyFromSst) {
|
TEST_F(DBRangeDelTest, GetCoveredKeyFromSst) {
|
||||||
do {
|
do {
|
||||||
DestroyAndReopen(CurrentOptions());
|
DestroyAndReopen(CurrentOptions());
|
||||||
db_->Put(WriteOptions(), "key", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "key", "val"));
|
||||||
// snapshot prevents key from being deleted during flush
|
// snapshot prevents key from being deleted during flush
|
||||||
const Snapshot* snapshot = db_->GetSnapshot();
|
const Snapshot* snapshot = db_->GetSnapshot();
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
@ -706,11 +715,11 @@ TEST_F(DBRangeDelTest, GetCoveredMergeOperandFromMemtable) {
|
|||||||
for (int i = 0; i < kNumMergeOps; ++i) {
|
for (int i = 0; i < kNumMergeOps; ++i) {
|
||||||
std::string val;
|
std::string val;
|
||||||
PutFixed64(&val, i);
|
PutFixed64(&val, i);
|
||||||
db_->Merge(WriteOptions(), "key", val);
|
ASSERT_OK(db_->Merge(WriteOptions(), "key", val));
|
||||||
if (i == kNumMergeOps / 2) {
|
if (i == kNumMergeOps / 2) {
|
||||||
// deletes [0, 5]
|
// deletes [0, 5]
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "key",
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
||||||
"key_");
|
"key", "key_"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,16 +743,16 @@ TEST_F(DBRangeDelTest, GetIgnoresRangeDeletions) {
|
|||||||
opts.memtable_factory.reset(new SpecialSkipListFactory(1));
|
opts.memtable_factory.reset(new SpecialSkipListFactory(1));
|
||||||
Reopen(opts);
|
Reopen(opts);
|
||||||
|
|
||||||
db_->Put(WriteOptions(), "sst_key", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "sst_key", "val"));
|
||||||
// snapshot prevents key from being deleted during flush
|
// snapshot prevents key from being deleted during flush
|
||||||
const Snapshot* snapshot = db_->GetSnapshot();
|
const Snapshot* snapshot = db_->GetSnapshot();
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
||||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
db_->Put(WriteOptions(), "imm_key", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "imm_key", "val"));
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
||||||
db_->Put(WriteOptions(), "mem_key", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "mem_key", "val"));
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
||||||
|
|
||||||
@ -768,13 +777,15 @@ TEST_F(DBRangeDelTest, IteratorRemovesCoveredKeys) {
|
|||||||
// should be deleted.
|
// should be deleted.
|
||||||
for (int i = 0; i < kNum; ++i) {
|
for (int i = 0; i < kNum; ++i) {
|
||||||
if (i == kNum / 2) {
|
if (i == kNum / 2) {
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
||||||
GetNumericStr(kRangeBegin), GetNumericStr(kRangeEnd));
|
GetNumericStr(kRangeBegin),
|
||||||
|
GetNumericStr(kRangeEnd)));
|
||||||
}
|
}
|
||||||
db_->Put(WriteOptions(), GetNumericStr(i), "val");
|
ASSERT_OK(db_->Put(WriteOptions(), GetNumericStr(i), "val"));
|
||||||
}
|
}
|
||||||
ReadOptions read_opts;
|
ReadOptions read_opts;
|
||||||
auto* iter = db_->NewIterator(read_opts);
|
auto* iter = db_->NewIterator(read_opts);
|
||||||
|
ASSERT_OK(iter->status());
|
||||||
|
|
||||||
int expected = 0;
|
int expected = 0;
|
||||||
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
@ -802,14 +813,16 @@ TEST_F(DBRangeDelTest, IteratorOverUserSnapshot) {
|
|||||||
for (int i = 0; i < kNum; ++i) {
|
for (int i = 0; i < kNum; ++i) {
|
||||||
if (i == kNum / 2) {
|
if (i == kNum / 2) {
|
||||||
snapshot = db_->GetSnapshot();
|
snapshot = db_->GetSnapshot();
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
||||||
GetNumericStr(kRangeBegin), GetNumericStr(kRangeEnd));
|
GetNumericStr(kRangeBegin),
|
||||||
|
GetNumericStr(kRangeEnd)));
|
||||||
}
|
}
|
||||||
db_->Put(WriteOptions(), GetNumericStr(i), "val");
|
ASSERT_OK(db_->Put(WriteOptions(), GetNumericStr(i), "val"));
|
||||||
}
|
}
|
||||||
ReadOptions read_opts;
|
ReadOptions read_opts;
|
||||||
read_opts.snapshot = snapshot;
|
read_opts.snapshot = snapshot;
|
||||||
auto* iter = db_->NewIterator(read_opts);
|
auto* iter = db_->NewIterator(read_opts);
|
||||||
|
ASSERT_OK(iter->status());
|
||||||
|
|
||||||
int expected = 0;
|
int expected = 0;
|
||||||
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
@ -828,22 +841,23 @@ TEST_F(DBRangeDelTest, IteratorIgnoresRangeDeletions) {
|
|||||||
opts.memtable_factory.reset(new SpecialSkipListFactory(1));
|
opts.memtable_factory.reset(new SpecialSkipListFactory(1));
|
||||||
Reopen(opts);
|
Reopen(opts);
|
||||||
|
|
||||||
db_->Put(WriteOptions(), "sst_key", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "sst_key", "val"));
|
||||||
// snapshot prevents key from being deleted during flush
|
// snapshot prevents key from being deleted during flush
|
||||||
const Snapshot* snapshot = db_->GetSnapshot();
|
const Snapshot* snapshot = db_->GetSnapshot();
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
||||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
db_->Put(WriteOptions(), "imm_key", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "imm_key", "val"));
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
||||||
db_->Put(WriteOptions(), "mem_key", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "mem_key", "val"));
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
|
||||||
|
|
||||||
ReadOptions read_opts;
|
ReadOptions read_opts;
|
||||||
read_opts.ignore_range_deletions = true;
|
read_opts.ignore_range_deletions = true;
|
||||||
auto* iter = db_->NewIterator(read_opts);
|
auto* iter = db_->NewIterator(read_opts);
|
||||||
|
ASSERT_OK(iter->status());
|
||||||
int i = 0;
|
int i = 0;
|
||||||
std::string expected[] = {"imm_key", "mem_key", "sst_key"};
|
std::string expected[] = {"imm_key", "mem_key", "sst_key"};
|
||||||
for (iter->SeekToFirst(); iter->Valid(); iter->Next(), ++i) {
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next(), ++i) {
|
||||||
@ -857,7 +871,7 @@ TEST_F(DBRangeDelTest, IteratorIgnoresRangeDeletions) {
|
|||||||
|
|
||||||
#ifndef ROCKSDB_UBSAN_RUN
|
#ifndef ROCKSDB_UBSAN_RUN
|
||||||
TEST_F(DBRangeDelTest, TailingIteratorRangeTombstoneUnsupported) {
|
TEST_F(DBRangeDelTest, TailingIteratorRangeTombstoneUnsupported) {
|
||||||
db_->Put(WriteOptions(), "key", "val");
|
ASSERT_OK(db_->Put(WriteOptions(), "key", "val"));
|
||||||
// snapshot prevents key from being deleted during flush
|
// snapshot prevents key from being deleted during flush
|
||||||
const Snapshot* snapshot = db_->GetSnapshot();
|
const Snapshot* snapshot = db_->GetSnapshot();
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
@ -873,6 +887,7 @@ TEST_F(DBRangeDelTest, TailingIteratorRangeTombstoneUnsupported) {
|
|||||||
iter->SeekToFirst();
|
iter->SeekToFirst();
|
||||||
}
|
}
|
||||||
ASSERT_TRUE(iter->status().IsNotSupported());
|
ASSERT_TRUE(iter->status().IsNotSupported());
|
||||||
|
|
||||||
delete iter;
|
delete iter;
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
@ -882,7 +897,6 @@ TEST_F(DBRangeDelTest, TailingIteratorRangeTombstoneUnsupported) {
|
|||||||
}
|
}
|
||||||
db_->ReleaseSnapshot(snapshot);
|
db_->ReleaseSnapshot(snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !ROCKSDB_UBSAN_RUN
|
#endif // !ROCKSDB_UBSAN_RUN
|
||||||
|
|
||||||
TEST_F(DBRangeDelTest, SubcompactionHasEmptyDedicatedRangeDelFile) {
|
TEST_F(DBRangeDelTest, SubcompactionHasEmptyDedicatedRangeDelFile) {
|
||||||
@ -926,8 +940,8 @@ TEST_F(DBRangeDelTest, SubcompactionHasEmptyDedicatedRangeDelFile) {
|
|||||||
ASSERT_EQ(kNumFiles, NumTableFilesAtLevel(0));
|
ASSERT_EQ(kNumFiles, NumTableFilesAtLevel(0));
|
||||||
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
||||||
|
|
||||||
db_->EnableAutoCompaction({db_->DefaultColumnFamily()});
|
ASSERT_OK(db_->EnableAutoCompaction({db_->DefaultColumnFamily()}));
|
||||||
dbfull()->TEST_WaitForCompact();
|
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||||
db_->ReleaseSnapshot(snapshot);
|
db_->ReleaseSnapshot(snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -949,7 +963,7 @@ TEST_F(DBRangeDelTest, MemtableBloomFilter) {
|
|||||||
for (int i = 0; i < kNumKeys; ++i) {
|
for (int i = 0; i < kNumKeys; ++i) {
|
||||||
ASSERT_OK(Put(Key(i), "val"));
|
ASSERT_OK(Put(Key(i), "val"));
|
||||||
}
|
}
|
||||||
Flush();
|
ASSERT_OK(Flush());
|
||||||
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0),
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0),
|
||||||
Key(kNumKeys)));
|
Key(kNumKeys)));
|
||||||
for (int i = 0; i < kNumKeys; ++i) {
|
for (int i = 0; i < kNumKeys; ++i) {
|
||||||
@ -987,8 +1001,8 @@ TEST_F(DBRangeDelTest, CompactionTreatsSplitInputLevelDeletionAtomically) {
|
|||||||
|
|
||||||
// snapshot protects range tombstone from dropping due to becoming obsolete.
|
// snapshot protects range tombstone from dropping due to becoming obsolete.
|
||||||
const Snapshot* snapshot = db_->GetSnapshot();
|
const Snapshot* snapshot = db_->GetSnapshot();
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0),
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
||||||
Key(2 * kNumFilesPerLevel));
|
Key(0), Key(2 * kNumFilesPerLevel)));
|
||||||
|
|
||||||
Random rnd(301);
|
Random rnd(301);
|
||||||
std::string value = rnd.RandomString(kValueBytes);
|
std::string value = rnd.RandomString(kValueBytes);
|
||||||
@ -997,14 +1011,14 @@ TEST_F(DBRangeDelTest, CompactionTreatsSplitInputLevelDeletionAtomically) {
|
|||||||
ASSERT_OK(Put(Key(j), value));
|
ASSERT_OK(Put(Key(j), value));
|
||||||
ASSERT_OK(Put(Key(2 * kNumFilesPerLevel - 1 - j), value));
|
ASSERT_OK(Put(Key(2 * kNumFilesPerLevel - 1 - j), value));
|
||||||
if (j > 0) {
|
if (j > 0) {
|
||||||
dbfull()->TEST_WaitForFlushMemTable();
|
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
|
||||||
ASSERT_EQ(j, NumTableFilesAtLevel(0));
|
ASSERT_EQ(j, NumTableFilesAtLevel(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// put extra key to trigger final flush
|
// put extra key to trigger final flush
|
||||||
ASSERT_OK(Put("", ""));
|
ASSERT_OK(Put("", ""));
|
||||||
dbfull()->TEST_WaitForFlushMemTable();
|
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable());
|
||||||
dbfull()->TEST_WaitForCompact();
|
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
||||||
ASSERT_EQ(kNumFilesPerLevel, NumTableFilesAtLevel(1));
|
ASSERT_EQ(kNumFilesPerLevel, NumTableFilesAtLevel(1));
|
||||||
|
|
||||||
@ -1022,7 +1036,7 @@ TEST_F(DBRangeDelTest, CompactionTreatsSplitInputLevelDeletionAtomically) {
|
|||||||
} else if (i == 2) {
|
} else if (i == 2) {
|
||||||
ASSERT_OK(db_->SetOptions(db_->DefaultColumnFamily(),
|
ASSERT_OK(db_->SetOptions(db_->DefaultColumnFamily(),
|
||||||
{{"max_bytes_for_level_base", "10000"}}));
|
{{"max_bytes_for_level_base", "10000"}}));
|
||||||
dbfull()->TEST_WaitForCompact();
|
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||||
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
||||||
}
|
}
|
||||||
ASSERT_GT(NumTableFilesAtLevel(2), 0);
|
ASSERT_GT(NumTableFilesAtLevel(2), 0);
|
||||||
@ -1056,8 +1070,8 @@ TEST_F(DBRangeDelTest, RangeTombstoneEndKeyAsSstableUpperBound) {
|
|||||||
// A snapshot protects the range tombstone from dropping due to
|
// A snapshot protects the range tombstone from dropping due to
|
||||||
// becoming obsolete.
|
// becoming obsolete.
|
||||||
const Snapshot* snapshot = db_->GetSnapshot();
|
const Snapshot* snapshot = db_->GetSnapshot();
|
||||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0),
|
||||||
Key(0), Key(2 * kNumFilesPerLevel));
|
Key(2 * kNumFilesPerLevel)));
|
||||||
|
|
||||||
// Create 2 additional sstables in L0. Note that the first sstable
|
// Create 2 additional sstables in L0. Note that the first sstable
|
||||||
// contains the range tombstone.
|
// contains the range tombstone.
|
||||||
@ -1096,7 +1110,7 @@ TEST_F(DBRangeDelTest, RangeTombstoneEndKeyAsSstableUpperBound) {
|
|||||||
ASSERT_EQ(value, Get(Key(2)));
|
ASSERT_EQ(value, Get(Key(2)));
|
||||||
auto begin_str = Key(3);
|
auto begin_str = Key(3);
|
||||||
const ROCKSDB_NAMESPACE::Slice begin = begin_str;
|
const ROCKSDB_NAMESPACE::Slice begin = begin_str;
|
||||||
dbfull()->TEST_CompactRange(1, &begin, nullptr);
|
ASSERT_OK(dbfull()->TEST_CompactRange(1, &begin, nullptr));
|
||||||
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
||||||
ASSERT_EQ(2, NumTableFilesAtLevel(2));
|
ASSERT_EQ(2, NumTableFilesAtLevel(2));
|
||||||
ASSERT_EQ(value, Get(Key(2)));
|
ASSERT_EQ(value, Get(Key(2)));
|
||||||
@ -1115,7 +1129,7 @@ TEST_F(DBRangeDelTest, RangeTombstoneEndKeyAsSstableUpperBound) {
|
|||||||
// [key000002#6,1, key000004#72057594037927935,15]
|
// [key000002#6,1, key000004#72057594037927935,15]
|
||||||
auto begin_str = Key(0);
|
auto begin_str = Key(0);
|
||||||
const ROCKSDB_NAMESPACE::Slice begin = begin_str;
|
const ROCKSDB_NAMESPACE::Slice begin = begin_str;
|
||||||
dbfull()->TEST_CompactRange(1, &begin, &begin);
|
ASSERT_OK(dbfull()->TEST_CompactRange(1, &begin, &begin));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
||||||
ASSERT_EQ(3, NumTableFilesAtLevel(2));
|
ASSERT_EQ(3, NumTableFilesAtLevel(2));
|
||||||
}
|
}
|
||||||
@ -1216,9 +1230,9 @@ TEST_F(DBRangeDelTest, KeyAtOverlappingEndpointReappears) {
|
|||||||
std::string value;
|
std::string value;
|
||||||
ASSERT_TRUE(db_->Get(ReadOptions(), "key", &value).IsNotFound());
|
ASSERT_TRUE(db_->Get(ReadOptions(), "key", &value).IsNotFound());
|
||||||
|
|
||||||
dbfull()->TEST_CompactRange(0 /* level */, nullptr /* begin */,
|
ASSERT_OK(dbfull()->TEST_CompactRange(
|
||||||
nullptr /* end */, nullptr /* column_family */,
|
0 /* level */, nullptr /* begin */, nullptr /* end */,
|
||||||
true /* disallow_trivial_move */);
|
nullptr /* column_family */, true /* disallow_trivial_move */));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
||||||
// Now we have multiple files at L1 all containing a single user key, thus
|
// Now we have multiple files at L1 all containing a single user key, thus
|
||||||
// guaranteeing overlap in the file endpoints.
|
// guaranteeing overlap in the file endpoints.
|
||||||
@ -1229,9 +1243,9 @@ TEST_F(DBRangeDelTest, KeyAtOverlappingEndpointReappears) {
|
|||||||
|
|
||||||
// Compact and verify again. It's worthwhile because now the files have
|
// Compact and verify again. It's worthwhile because now the files have
|
||||||
// tighter endpoints, so we can verify that doesn't mess anything up.
|
// tighter endpoints, so we can verify that doesn't mess anything up.
|
||||||
dbfull()->TEST_CompactRange(1 /* level */, nullptr /* begin */,
|
ASSERT_OK(dbfull()->TEST_CompactRange(
|
||||||
nullptr /* end */, nullptr /* column_family */,
|
1 /* level */, nullptr /* begin */, nullptr /* end */,
|
||||||
true /* disallow_trivial_move */);
|
nullptr /* column_family */, true /* disallow_trivial_move */));
|
||||||
ASSERT_GT(NumTableFilesAtLevel(2), 1);
|
ASSERT_GT(NumTableFilesAtLevel(2), 1);
|
||||||
ASSERT_TRUE(db_->Get(ReadOptions(), "key", &value).IsNotFound());
|
ASSERT_TRUE(db_->Get(ReadOptions(), "key", &value).IsNotFound());
|
||||||
|
|
||||||
@ -1307,6 +1321,7 @@ TEST_F(DBRangeDelTest, UntruncatedTombstoneDoesNotDeleteNewerKey) {
|
|||||||
|
|
||||||
auto get_key_count = [this]() -> int {
|
auto get_key_count = [this]() -> int {
|
||||||
auto* iter = db_->NewIterator(ReadOptions());
|
auto* iter = db_->NewIterator(ReadOptions());
|
||||||
|
assert(iter->status().ok());
|
||||||
iter->SeekToFirst();
|
iter->SeekToFirst();
|
||||||
int keys_found = 0;
|
int keys_found = 0;
|
||||||
for (; iter->Valid(); iter->Next()) {
|
for (; iter->Valid(); iter->Next()) {
|
||||||
@ -1409,6 +1424,7 @@ TEST_F(DBRangeDelTest, DeletedMergeOperandReappearsIterPrev) {
|
|||||||
ASSERT_GT(NumTableFilesAtLevel(1), 1);
|
ASSERT_GT(NumTableFilesAtLevel(1), 1);
|
||||||
|
|
||||||
auto* iter = db_->NewIterator(ReadOptions());
|
auto* iter = db_->NewIterator(ReadOptions());
|
||||||
|
ASSERT_OK(iter->status());
|
||||||
iter->SeekToLast();
|
iter->SeekToLast();
|
||||||
int keys_found = 0;
|
int keys_found = 0;
|
||||||
for (; iter->Valid(); iter->Prev()) {
|
for (; iter->Valid(); iter->Prev()) {
|
||||||
@ -1435,11 +1451,12 @@ TEST_F(DBRangeDelTest, SnapshotPreventsDroppedKeys) {
|
|||||||
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0),
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0),
|
||||||
Key(10)));
|
Key(10)));
|
||||||
|
|
||||||
db_->Flush(FlushOptions());
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
|
|
||||||
ReadOptions read_opts;
|
ReadOptions read_opts;
|
||||||
read_opts.snapshot = snapshot;
|
read_opts.snapshot = snapshot;
|
||||||
auto* iter = db_->NewIterator(read_opts);
|
auto* iter = db_->NewIterator(read_opts);
|
||||||
|
ASSERT_OK(iter->status());
|
||||||
|
|
||||||
iter->SeekToFirst();
|
iter->SeekToFirst();
|
||||||
ASSERT_TRUE(iter->Valid());
|
ASSERT_TRUE(iter->Valid());
|
||||||
@ -1482,6 +1499,7 @@ TEST_F(DBRangeDelTest, SnapshotPreventsDroppedKeysInImmMemTables) {
|
|||||||
ReadOptions read_opts;
|
ReadOptions read_opts;
|
||||||
read_opts.snapshot = snapshot.get();
|
read_opts.snapshot = snapshot.get();
|
||||||
std::unique_ptr<Iterator> iter(db_->NewIterator(read_opts));
|
std::unique_ptr<Iterator> iter(db_->NewIterator(read_opts));
|
||||||
|
ASSERT_OK(iter->status());
|
||||||
|
|
||||||
TEST_SYNC_POINT("SnapshotPreventsDroppedKeysInImmMemTables:AfterNewIterator");
|
TEST_SYNC_POINT("SnapshotPreventsDroppedKeysInImmMemTables:AfterNewIterator");
|
||||||
|
|
||||||
@ -1519,7 +1537,7 @@ TEST_F(DBRangeDelTest, RangeTombstoneWrittenToMinimalSsts) {
|
|||||||
std::string value = rnd.RandomString(kValueBytes);
|
std::string value = rnd.RandomString(kValueBytes);
|
||||||
ASSERT_OK(Put(key, value));
|
ASSERT_OK(Put(key, value));
|
||||||
}
|
}
|
||||||
db_->Flush(FlushOptions());
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
MoveFilesToLevel(2);
|
MoveFilesToLevel(2);
|
||||||
}
|
}
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
||||||
@ -1538,7 +1556,7 @@ TEST_F(DBRangeDelTest, RangeTombstoneWrittenToMinimalSsts) {
|
|||||||
// TODO(ajkr): remove this `Put` after file cutting accounts for range
|
// TODO(ajkr): remove this `Put` after file cutting accounts for range
|
||||||
// tombstones (#3977).
|
// tombstones (#3977).
|
||||||
ASSERT_OK(Put("c" + Key(1), "value"));
|
ASSERT_OK(Put("c" + Key(1), "value"));
|
||||||
db_->Flush(FlushOptions());
|
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||||
|
|
||||||
// Ensure manual L0->L1 compaction cuts the outputs before the range tombstone
|
// Ensure manual L0->L1 compaction cuts the outputs before the range tombstone
|
||||||
// and the range tombstone is only placed in the second SST.
|
// and the range tombstone is only placed in the second SST.
|
||||||
@ -1546,9 +1564,9 @@ TEST_F(DBRangeDelTest, RangeTombstoneWrittenToMinimalSsts) {
|
|||||||
Slice begin_key(begin_key_storage);
|
Slice begin_key(begin_key_storage);
|
||||||
std::string end_key_storage("d");
|
std::string end_key_storage("d");
|
||||||
Slice end_key(end_key_storage);
|
Slice end_key(end_key_storage);
|
||||||
dbfull()->TEST_CompactRange(0 /* level */, &begin_key /* begin */,
|
ASSERT_OK(dbfull()->TEST_CompactRange(
|
||||||
&end_key /* end */, nullptr /* column_family */,
|
0 /* level */, &begin_key /* begin */, &end_key /* end */,
|
||||||
true /* disallow_trivial_move */);
|
nullptr /* column_family */, true /* disallow_trivial_move */));
|
||||||
ASSERT_EQ(2, NumTableFilesAtLevel(1));
|
ASSERT_EQ(2, NumTableFilesAtLevel(1));
|
||||||
|
|
||||||
std::vector<LiveFileMetaData> all_metadata;
|
std::vector<LiveFileMetaData> all_metadata;
|
||||||
@ -1613,15 +1631,15 @@ TEST_F(DBRangeDelTest, OverlappedTombstones) {
|
|||||||
|
|
||||||
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
||||||
|
|
||||||
dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
|
ASSERT_OK(dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
|
||||||
true /* disallow_trivial_move */);
|
true /* disallow_trivial_move */));
|
||||||
|
|
||||||
// The tombstone range is not broken up into multiple SSTs which may incur a
|
// The tombstone range is not broken up into multiple SSTs which may incur a
|
||||||
// large compaction with L2.
|
// large compaction with L2.
|
||||||
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
||||||
std::vector<std::vector<FileMetaData>> files;
|
std::vector<std::vector<FileMetaData>> files;
|
||||||
dbfull()->TEST_CompactRange(1, nullptr, nullptr, nullptr,
|
ASSERT_OK(dbfull()->TEST_CompactRange(1, nullptr, nullptr, nullptr,
|
||||||
true /* disallow_trivial_move */);
|
true /* disallow_trivial_move */));
|
||||||
ASSERT_EQ(1, NumTableFilesAtLevel(2));
|
ASSERT_EQ(1, NumTableFilesAtLevel(2));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
||||||
}
|
}
|
||||||
@ -1654,13 +1672,13 @@ TEST_F(DBRangeDelTest, OverlappedKeys) {
|
|||||||
|
|
||||||
// The key range is broken up into three SSTs to avoid a future big compaction
|
// The key range is broken up into three SSTs to avoid a future big compaction
|
||||||
// with the grandparent
|
// with the grandparent
|
||||||
dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
|
ASSERT_OK(dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
|
||||||
true /* disallow_trivial_move */);
|
true /* disallow_trivial_move */));
|
||||||
ASSERT_EQ(3, NumTableFilesAtLevel(1));
|
ASSERT_EQ(3, NumTableFilesAtLevel(1));
|
||||||
|
|
||||||
std::vector<std::vector<FileMetaData>> files;
|
std::vector<std::vector<FileMetaData>> files;
|
||||||
dbfull()->TEST_CompactRange(1, nullptr, nullptr, nullptr,
|
ASSERT_OK(dbfull()->TEST_CompactRange(1, nullptr, nullptr, nullptr,
|
||||||
true /* disallow_trivial_move */);
|
true /* disallow_trivial_move */));
|
||||||
ASSERT_EQ(1, NumTableFilesAtLevel(2));
|
ASSERT_EQ(1, NumTableFilesAtLevel(2));
|
||||||
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
||||||
}
|
}
|
||||||
|
@ -60,14 +60,15 @@ TEST_P(DBWriteTest, WriteStallRemoveNoSlowdownWrite) {
|
|||||||
std::string key = "foo" + std::to_string(a);
|
std::string key = "foo" + std::to_string(a);
|
||||||
WriteOptions wo;
|
WriteOptions wo;
|
||||||
wo.no_slowdown = false;
|
wo.no_slowdown = false;
|
||||||
dbfull()->Put(wo, key, "bar");
|
ASSERT_OK(dbfull()->Put(wo, key, "bar"));
|
||||||
};
|
};
|
||||||
std::function<void()> write_no_slowdown_func = [&]() {
|
std::function<void()> write_no_slowdown_func = [&]() {
|
||||||
int a = thread_num.fetch_add(1);
|
int a = thread_num.fetch_add(1);
|
||||||
std::string key = "foo" + std::to_string(a);
|
std::string key = "foo" + std::to_string(a);
|
||||||
WriteOptions wo;
|
WriteOptions wo;
|
||||||
wo.no_slowdown = true;
|
wo.no_slowdown = true;
|
||||||
dbfull()->Put(wo, key, "bar");
|
Status s = dbfull()->Put(wo, key, "bar");
|
||||||
|
ASSERT_TRUE(s.ok() || s.IsIncomplete());
|
||||||
};
|
};
|
||||||
std::function<void(void*)> unblock_main_thread_func = [&](void*) {
|
std::function<void(void*)> unblock_main_thread_func = [&](void*) {
|
||||||
mutex.Lock();
|
mutex.Lock();
|
||||||
@ -77,13 +78,13 @@ TEST_P(DBWriteTest, WriteStallRemoveNoSlowdownWrite) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create 3 L0 files and schedule 4th without waiting
|
// Create 3 L0 files and schedule 4th without waiting
|
||||||
Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar");
|
ASSERT_OK(Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar"));
|
||||||
Flush();
|
ASSERT_OK(Flush());
|
||||||
Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar");
|
ASSERT_OK(Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar"));
|
||||||
Flush();
|
ASSERT_OK(Flush());
|
||||||
Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar");
|
ASSERT_OK(Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar"));
|
||||||
Flush();
|
ASSERT_OK(Flush());
|
||||||
Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar");
|
ASSERT_OK(Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar"));
|
||||||
|
|
||||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||||
"WriteThread::JoinBatchGroup:Start", unblock_main_thread_func);
|
"WriteThread::JoinBatchGroup:Start", unblock_main_thread_func);
|
||||||
@ -104,7 +105,7 @@ TEST_P(DBWriteTest, WriteStallRemoveNoSlowdownWrite) {
|
|||||||
// write_thread
|
// write_thread
|
||||||
FlushOptions fopt;
|
FlushOptions fopt;
|
||||||
fopt.wait = false;
|
fopt.wait = false;
|
||||||
dbfull()->Flush(fopt);
|
ASSERT_OK(dbfull()->Flush(fopt));
|
||||||
|
|
||||||
// Create a mix of slowdown/no_slowdown write threads
|
// Create a mix of slowdown/no_slowdown write threads
|
||||||
mutex.Lock();
|
mutex.Lock();
|
||||||
@ -145,7 +146,7 @@ TEST_P(DBWriteTest, WriteStallRemoveNoSlowdownWrite) {
|
|||||||
mutex.Unlock();
|
mutex.Unlock();
|
||||||
|
|
||||||
TEST_SYNC_POINT("DBWriteTest::WriteStallRemoveNoSlowdownWrite:1");
|
TEST_SYNC_POINT("DBWriteTest::WriteStallRemoveNoSlowdownWrite:1");
|
||||||
dbfull()->TEST_WaitForFlushMemTable(nullptr);
|
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable(nullptr));
|
||||||
// This would have triggered a write stall. Unblock the write group leader
|
// This would have triggered a write stall. Unblock the write group leader
|
||||||
TEST_SYNC_POINT("DBWriteTest::WriteStallRemoveNoSlowdownWrite:2");
|
TEST_SYNC_POINT("DBWriteTest::WriteStallRemoveNoSlowdownWrite:2");
|
||||||
// The leader is going to create missing newer links. When the leader
|
// The leader is going to create missing newer links. When the leader
|
||||||
@ -178,14 +179,15 @@ TEST_P(DBWriteTest, WriteThreadHangOnWriteStall) {
|
|||||||
std::string key = "foo" + std::to_string(a);
|
std::string key = "foo" + std::to_string(a);
|
||||||
WriteOptions wo;
|
WriteOptions wo;
|
||||||
wo.no_slowdown = false;
|
wo.no_slowdown = false;
|
||||||
dbfull()->Put(wo, key, "bar");
|
ASSERT_OK(dbfull()->Put(wo, key, "bar"));
|
||||||
};
|
};
|
||||||
std::function<void()> write_no_slowdown_func = [&]() {
|
std::function<void()> write_no_slowdown_func = [&]() {
|
||||||
int a = thread_num.fetch_add(1);
|
int a = thread_num.fetch_add(1);
|
||||||
std::string key = "foo" + std::to_string(a);
|
std::string key = "foo" + std::to_string(a);
|
||||||
WriteOptions wo;
|
WriteOptions wo;
|
||||||
wo.no_slowdown = true;
|
wo.no_slowdown = true;
|
||||||
dbfull()->Put(wo, key, "bar");
|
Status s = dbfull()->Put(wo, key, "bar");
|
||||||
|
ASSERT_TRUE(s.ok() || s.IsIncomplete());
|
||||||
};
|
};
|
||||||
std::function<void(void *)> unblock_main_thread_func = [&](void *) {
|
std::function<void(void *)> unblock_main_thread_func = [&](void *) {
|
||||||
mutex.Lock();
|
mutex.Lock();
|
||||||
@ -195,13 +197,13 @@ TEST_P(DBWriteTest, WriteThreadHangOnWriteStall) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create 3 L0 files and schedule 4th without waiting
|
// Create 3 L0 files and schedule 4th without waiting
|
||||||
Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar");
|
ASSERT_OK(Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar"));
|
||||||
Flush();
|
ASSERT_OK(Flush());
|
||||||
Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar");
|
ASSERT_OK(Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar"));
|
||||||
Flush();
|
ASSERT_OK(Flush());
|
||||||
Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar");
|
ASSERT_OK(Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar"));
|
||||||
Flush();
|
ASSERT_OK(Flush());
|
||||||
Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar");
|
ASSERT_OK(Put("foo" + std::to_string(thread_num.fetch_add(1)), "bar"));
|
||||||
|
|
||||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
|
||||||
"WriteThread::JoinBatchGroup:Start", unblock_main_thread_func);
|
"WriteThread::JoinBatchGroup:Start", unblock_main_thread_func);
|
||||||
@ -222,7 +224,7 @@ TEST_P(DBWriteTest, WriteThreadHangOnWriteStall) {
|
|||||||
// write_thread
|
// write_thread
|
||||||
FlushOptions fopt;
|
FlushOptions fopt;
|
||||||
fopt.wait = false;
|
fopt.wait = false;
|
||||||
dbfull()->Flush(fopt);
|
ASSERT_OK(dbfull()->Flush(fopt));
|
||||||
|
|
||||||
// Create a mix of slowdown/no_slowdown write threads
|
// Create a mix of slowdown/no_slowdown write threads
|
||||||
mutex.Lock();
|
mutex.Lock();
|
||||||
@ -243,7 +245,7 @@ TEST_P(DBWriteTest, WriteThreadHangOnWriteStall) {
|
|||||||
mutex.Unlock();
|
mutex.Unlock();
|
||||||
|
|
||||||
TEST_SYNC_POINT("DBWriteTest::WriteThreadHangOnWriteStall:1");
|
TEST_SYNC_POINT("DBWriteTest::WriteThreadHangOnWriteStall:1");
|
||||||
dbfull()->TEST_WaitForFlushMemTable(nullptr);
|
ASSERT_OK(dbfull()->TEST_WaitForFlushMemTable(nullptr));
|
||||||
// This would have triggered a write stall. Unblock the write group leader
|
// This would have triggered a write stall. Unblock the write group leader
|
||||||
TEST_SYNC_POINT("DBWriteTest::WriteThreadHangOnWriteStall:2");
|
TEST_SYNC_POINT("DBWriteTest::WriteThreadHangOnWriteStall:2");
|
||||||
// The leader is going to create missing newer links. When the leader finishes,
|
// The leader is going to create missing newer links. When the leader finishes,
|
||||||
@ -307,6 +309,11 @@ TEST_P(DBWriteTest, IOErrorOnWALWritePropagateToWriteThreadFollower) {
|
|||||||
threads[i].join();
|
threads[i].join();
|
||||||
}
|
}
|
||||||
ASSERT_EQ(1, leader_count);
|
ASSERT_EQ(1, leader_count);
|
||||||
|
|
||||||
|
// The Failed PUT operations can cause a BG error to be set.
|
||||||
|
// Mark it as Checked for the ASSERT_STATUS_CHECKED
|
||||||
|
dbfull()->Resume().PermitUncheckedError();
|
||||||
|
|
||||||
// Close before mock_env destruct.
|
// Close before mock_env destruct.
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
@ -351,7 +358,9 @@ TEST_P(DBWriteTest, IOErrorOnWALWriteTriggersReadOnlyMode) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if (!options.manual_wal_flush) {
|
if (!options.manual_wal_flush) {
|
||||||
ASSERT_FALSE(res.ok());
|
ASSERT_NOK(res);
|
||||||
|
} else {
|
||||||
|
ASSERT_OK(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Close before mock_env destruct.
|
// Close before mock_env destruct.
|
||||||
@ -423,13 +432,14 @@ TEST_P(DBWriteTest, ConcurrentlyDisabledWAL) {
|
|||||||
ROCKSDB_NAMESPACE::WriteOptions write_option_default;
|
ROCKSDB_NAMESPACE::WriteOptions write_option_default;
|
||||||
std::string no_wal_key = no_wal_key_prefix + std::to_string(t) +
|
std::string no_wal_key = no_wal_key_prefix + std::to_string(t) +
|
||||||
"_" + std::to_string(i);
|
"_" + std::to_string(i);
|
||||||
this->Put(no_wal_key, no_wal_value, write_option_disable);
|
ASSERT_OK(
|
||||||
|
this->Put(no_wal_key, no_wal_value, write_option_disable));
|
||||||
std::string wal_key =
|
std::string wal_key =
|
||||||
wal_key_prefix + std::to_string(i) + "_" + std::to_string(i);
|
wal_key_prefix + std::to_string(i) + "_" + std::to_string(i);
|
||||||
this->Put(wal_key, wal_value, write_option_default);
|
ASSERT_OK(this->Put(wal_key, wal_value, write_option_default));
|
||||||
dbfull()->SyncWAL();
|
ASSERT_OK(dbfull()->SyncWAL());
|
||||||
}
|
}
|
||||||
return 0;
|
return;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (auto& t: threads) {
|
for (auto& t: threads) {
|
||||||
|
@ -40,7 +40,7 @@ class DeleteFileTest : public DBTestBase {
|
|||||||
wal_dir_(dbname_ + "/wal_files") {}
|
wal_dir_(dbname_ + "/wal_files") {}
|
||||||
|
|
||||||
void SetOptions(Options* options) {
|
void SetOptions(Options* options) {
|
||||||
assert(options);
|
ASSERT_NE(options, nullptr);
|
||||||
options->delete_obsolete_files_period_micros = 0; // always do full purge
|
options->delete_obsolete_files_period_micros = 0; // always do full purge
|
||||||
options->enable_thread_tracking = true;
|
options->enable_thread_tracking = true;
|
||||||
options->write_buffer_size = 1024 * 1024 * 1000;
|
options->write_buffer_size = 1024 * 1024 * 1000;
|
||||||
@ -105,7 +105,7 @@ class DeleteFileTest : public DBTestBase {
|
|||||||
void CheckFileTypeCounts(const std::string& dir, int required_log,
|
void CheckFileTypeCounts(const std::string& dir, int required_log,
|
||||||
int required_sst, int required_manifest) {
|
int required_sst, int required_manifest) {
|
||||||
std::vector<std::string> filenames;
|
std::vector<std::string> filenames;
|
||||||
env_->GetChildren(dir, &filenames);
|
ASSERT_OK(env_->GetChildren(dir, &filenames));
|
||||||
|
|
||||||
int log_cnt = 0, sst_cnt = 0, manifest_cnt = 0;
|
int log_cnt = 0, sst_cnt = 0, manifest_cnt = 0;
|
||||||
for (auto file : filenames) {
|
for (auto file : filenames) {
|
||||||
@ -180,7 +180,8 @@ TEST_F(DeleteFileTest, AddKeysAndQueryLevels) {
|
|||||||
ASSERT_TRUE(status.IsInvalidArgument());
|
ASSERT_TRUE(status.IsInvalidArgument());
|
||||||
|
|
||||||
// Lowest level file deletion should succeed.
|
// Lowest level file deletion should succeed.
|
||||||
ASSERT_OK(db_->DeleteFile(level2file));
|
status = db_->DeleteFile(level2file);
|
||||||
|
ASSERT_OK(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DeleteFileTest, PurgeObsoleteFilesTest) {
|
TEST_F(DeleteFileTest, PurgeObsoleteFilesTest) {
|
||||||
@ -201,7 +202,7 @@ TEST_F(DeleteFileTest, PurgeObsoleteFilesTest) {
|
|||||||
compact_options.change_level = true;
|
compact_options.change_level = true;
|
||||||
compact_options.target_level = 2;
|
compact_options.target_level = 2;
|
||||||
Slice first_slice(first), last_slice(last);
|
Slice first_slice(first), last_slice(last);
|
||||||
db_->CompactRange(compact_options, &first_slice, &last_slice);
|
ASSERT_OK(db_->CompactRange(compact_options, &first_slice, &last_slice));
|
||||||
// 1 sst after compaction
|
// 1 sst after compaction
|
||||||
CheckFileTypeCounts(dbname_, 0, 1, 1);
|
CheckFileTypeCounts(dbname_, 0, 1, 1);
|
||||||
|
|
||||||
@ -210,7 +211,9 @@ TEST_F(DeleteFileTest, PurgeObsoleteFilesTest) {
|
|||||||
Iterator *itr = nullptr;
|
Iterator *itr = nullptr;
|
||||||
CreateTwoLevels();
|
CreateTwoLevels();
|
||||||
itr = db_->NewIterator(ReadOptions());
|
itr = db_->NewIterator(ReadOptions());
|
||||||
db_->CompactRange(compact_options, &first_slice, &last_slice);
|
ASSERT_OK(itr->status());
|
||||||
|
ASSERT_OK(db_->CompactRange(compact_options, &first_slice, &last_slice));
|
||||||
|
ASSERT_OK(itr->status());
|
||||||
// 3 sst after compaction with live iterator
|
// 3 sst after compaction with live iterator
|
||||||
CheckFileTypeCounts(dbname_, 0, 3, 1);
|
CheckFileTypeCounts(dbname_, 0, 3, 1);
|
||||||
delete itr;
|
delete itr;
|
||||||
@ -237,7 +240,8 @@ TEST_F(DeleteFileTest, BackgroundPurgeIteratorTest) {
|
|||||||
ReadOptions read_options;
|
ReadOptions read_options;
|
||||||
read_options.background_purge_on_iterator_cleanup = true;
|
read_options.background_purge_on_iterator_cleanup = true;
|
||||||
itr = db_->NewIterator(read_options);
|
itr = db_->NewIterator(read_options);
|
||||||
db_->CompactRange(compact_options, &first_slice, &last_slice);
|
ASSERT_OK(itr->status());
|
||||||
|
ASSERT_OK(db_->CompactRange(compact_options, &first_slice, &last_slice));
|
||||||
// 3 sst after compaction with live iterator
|
// 3 sst after compaction with live iterator
|
||||||
CheckFileTypeCounts(dbname_, 0, 3, 1);
|
CheckFileTypeCounts(dbname_, 0, 3, 1);
|
||||||
test::SleepingBackgroundTask sleeping_task_before;
|
test::SleepingBackgroundTask sleeping_task_before;
|
||||||
@ -344,11 +348,12 @@ TEST_F(DeleteFileTest, BackgroundPurgeCopyOptions) {
|
|||||||
ReadOptions read_options;
|
ReadOptions read_options;
|
||||||
read_options.background_purge_on_iterator_cleanup = true;
|
read_options.background_purge_on_iterator_cleanup = true;
|
||||||
itr = db_->NewIterator(read_options);
|
itr = db_->NewIterator(read_options);
|
||||||
|
ASSERT_OK(itr->status());
|
||||||
// ReadOptions is deleted, but iterator cleanup function should not be
|
// ReadOptions is deleted, but iterator cleanup function should not be
|
||||||
// affected
|
// affected
|
||||||
}
|
}
|
||||||
|
|
||||||
db_->CompactRange(compact_options, &first_slice, &last_slice);
|
ASSERT_OK(db_->CompactRange(compact_options, &first_slice, &last_slice));
|
||||||
// 3 sst after compaction with live iterator
|
// 3 sst after compaction with live iterator
|
||||||
CheckFileTypeCounts(dbname_, 0, 3, 1);
|
CheckFileTypeCounts(dbname_, 0, 3, 1);
|
||||||
delete itr;
|
delete itr;
|
||||||
@ -382,9 +387,11 @@ TEST_F(DeleteFileTest, BackgroundPurgeTestMultipleJobs) {
|
|||||||
ReadOptions read_options;
|
ReadOptions read_options;
|
||||||
read_options.background_purge_on_iterator_cleanup = true;
|
read_options.background_purge_on_iterator_cleanup = true;
|
||||||
Iterator* itr1 = db_->NewIterator(read_options);
|
Iterator* itr1 = db_->NewIterator(read_options);
|
||||||
|
ASSERT_OK(itr1->status());
|
||||||
CreateTwoLevels();
|
CreateTwoLevels();
|
||||||
Iterator* itr2 = db_->NewIterator(read_options);
|
Iterator* itr2 = db_->NewIterator(read_options);
|
||||||
db_->CompactRange(compact_options, &first_slice, &last_slice);
|
ASSERT_OK(itr2->status());
|
||||||
|
ASSERT_OK(db_->CompactRange(compact_options, &first_slice, &last_slice));
|
||||||
// 5 sst files after 2 compactions with 2 live iterators
|
// 5 sst files after 2 compactions with 2 live iterators
|
||||||
CheckFileTypeCounts(dbname_, 0, 5, 1);
|
CheckFileTypeCounts(dbname_, 0, 5, 1);
|
||||||
|
|
||||||
@ -417,6 +424,7 @@ TEST_F(DeleteFileTest, DeleteFileWithIterator) {
|
|||||||
CreateTwoLevels();
|
CreateTwoLevels();
|
||||||
ReadOptions read_options;
|
ReadOptions read_options;
|
||||||
Iterator* it = db_->NewIterator(read_options);
|
Iterator* it = db_->NewIterator(read_options);
|
||||||
|
ASSERT_OK(it->status());
|
||||||
std::vector<LiveFileMetaData> metadata;
|
std::vector<LiveFileMetaData> metadata;
|
||||||
db_->GetLiveFilesMetaData(&metadata);
|
db_->GetLiveFilesMetaData(&metadata);
|
||||||
|
|
||||||
@ -432,7 +440,7 @@ TEST_F(DeleteFileTest, DeleteFileWithIterator) {
|
|||||||
Status status = db_->DeleteFile(level2file);
|
Status status = db_->DeleteFile(level2file);
|
||||||
fprintf(stdout, "Deletion status %s: %s\n",
|
fprintf(stdout, "Deletion status %s: %s\n",
|
||||||
level2file.c_str(), status.ToString().c_str());
|
level2file.c_str(), status.ToString().c_str());
|
||||||
ASSERT_TRUE(status.ok());
|
ASSERT_OK(status);
|
||||||
it->SeekToFirst();
|
it->SeekToFirst();
|
||||||
int numKeysIterated = 0;
|
int numKeysIterated = 0;
|
||||||
while(it->Valid()) {
|
while(it->Valid()) {
|
||||||
@ -452,7 +460,7 @@ TEST_F(DeleteFileTest, DeleteLogFiles) {
|
|||||||
|
|
||||||
AddKeys(10, 0);
|
AddKeys(10, 0);
|
||||||
VectorLogPtr logfiles;
|
VectorLogPtr logfiles;
|
||||||
db_->GetSortedWalFiles(logfiles);
|
ASSERT_OK(db_->GetSortedWalFiles(logfiles));
|
||||||
ASSERT_GT(logfiles.size(), 0UL);
|
ASSERT_GT(logfiles.size(), 0UL);
|
||||||
// Take the last log file which is expected to be alive and try to delete it
|
// Take the last log file which is expected to be alive and try to delete it
|
||||||
// Should not succeed because live logs are not allowed to be deleted
|
// Should not succeed because live logs are not allowed to be deleted
|
||||||
@ -461,7 +469,7 @@ TEST_F(DeleteFileTest, DeleteLogFiles) {
|
|||||||
ASSERT_OK(env_->FileExists(wal_dir_ + "/" + alive_log->PathName()));
|
ASSERT_OK(env_->FileExists(wal_dir_ + "/" + alive_log->PathName()));
|
||||||
fprintf(stdout, "Deleting alive log file %s\n",
|
fprintf(stdout, "Deleting alive log file %s\n",
|
||||||
alive_log->PathName().c_str());
|
alive_log->PathName().c_str());
|
||||||
ASSERT_TRUE(!db_->DeleteFile(alive_log->PathName()).ok());
|
ASSERT_NOK(db_->DeleteFile(alive_log->PathName()));
|
||||||
ASSERT_OK(env_->FileExists(wal_dir_ + "/" + alive_log->PathName()));
|
ASSERT_OK(env_->FileExists(wal_dir_ + "/" + alive_log->PathName()));
|
||||||
logfiles.clear();
|
logfiles.clear();
|
||||||
|
|
||||||
@ -469,10 +477,10 @@ TEST_F(DeleteFileTest, DeleteLogFiles) {
|
|||||||
// Call Flush again to flush out memtable and move alive log to archived log
|
// Call Flush again to flush out memtable and move alive log to archived log
|
||||||
// and try to delete the archived log file
|
// and try to delete the archived log file
|
||||||
FlushOptions fopts;
|
FlushOptions fopts;
|
||||||
db_->Flush(fopts);
|
ASSERT_OK(db_->Flush(fopts));
|
||||||
AddKeys(10, 0);
|
AddKeys(10, 0);
|
||||||
db_->Flush(fopts);
|
ASSERT_OK(db_->Flush(fopts));
|
||||||
db_->GetSortedWalFiles(logfiles);
|
ASSERT_OK(db_->GetSortedWalFiles(logfiles));
|
||||||
ASSERT_GT(logfiles.size(), 0UL);
|
ASSERT_GT(logfiles.size(), 0UL);
|
||||||
std::unique_ptr<LogFile> archived_log = std::move(logfiles.front());
|
std::unique_ptr<LogFile> archived_log = std::move(logfiles.front());
|
||||||
ASSERT_EQ(archived_log->Type(), kArchivedLogFile);
|
ASSERT_EQ(archived_log->Type(), kArchivedLogFile);
|
||||||
@ -480,8 +488,8 @@ TEST_F(DeleteFileTest, DeleteLogFiles) {
|
|||||||
fprintf(stdout, "Deleting archived log file %s\n",
|
fprintf(stdout, "Deleting archived log file %s\n",
|
||||||
archived_log->PathName().c_str());
|
archived_log->PathName().c_str());
|
||||||
ASSERT_OK(db_->DeleteFile(archived_log->PathName()));
|
ASSERT_OK(db_->DeleteFile(archived_log->PathName()));
|
||||||
ASSERT_EQ(Status::NotFound(),
|
ASSERT_TRUE(
|
||||||
env_->FileExists(wal_dir_ + "/" + archived_log->PathName()));
|
env_->FileExists(wal_dir_ + "/" + archived_log->PathName()).IsNotFound());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DeleteFileTest, DeleteNonDefaultColumnFamily) {
|
TEST_F(DeleteFileTest, DeleteNonDefaultColumnFamily) {
|
||||||
@ -520,6 +528,7 @@ TEST_F(DeleteFileTest, DeleteNonDefaultColumnFamily) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::unique_ptr<Iterator> itr(db_->NewIterator(ReadOptions(), handles_[1]));
|
std::unique_ptr<Iterator> itr(db_->NewIterator(ReadOptions(), handles_[1]));
|
||||||
|
ASSERT_OK(itr->status());
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (itr->SeekToFirst(); itr->Valid(); itr->Next()) {
|
for (itr->SeekToFirst(); itr->Valid(); itr->Next()) {
|
||||||
ASSERT_OK(itr->status());
|
ASSERT_OK(itr->status());
|
||||||
|
@ -47,8 +47,8 @@ class ExternSSTFileLinkFailFallbackTest
|
|||||||
: DBTestBase("/external_sst_file_test", /*env_do_fsync=*/true),
|
: DBTestBase("/external_sst_file_test", /*env_do_fsync=*/true),
|
||||||
test_env_(new ExternalSSTTestEnv(env_, true)) {
|
test_env_(new ExternalSSTTestEnv(env_, true)) {
|
||||||
sst_files_dir_ = dbname_ + "/sst_files/";
|
sst_files_dir_ = dbname_ + "/sst_files/";
|
||||||
DestroyDir(env_, sst_files_dir_);
|
EXPECT_EQ(DestroyDir(env_, sst_files_dir_), Status::OK());
|
||||||
env_->CreateDir(sst_files_dir_);
|
EXPECT_EQ(env_->CreateDir(sst_files_dir_), Status::OK());
|
||||||
options_ = CurrentOptions();
|
options_ = CurrentOptions();
|
||||||
options_.disable_auto_compactions = true;
|
options_.disable_auto_compactions = true;
|
||||||
options_.env = test_env_;
|
options_.env = test_env_;
|
||||||
@ -79,8 +79,8 @@ class ExternalSSTFileTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DestroyAndRecreateExternalSSTFilesDir() {
|
void DestroyAndRecreateExternalSSTFilesDir() {
|
||||||
DestroyDir(env_, sst_files_dir_);
|
ASSERT_OK(DestroyDir(env_, sst_files_dir_));
|
||||||
env_->CreateDir(sst_files_dir_);
|
ASSERT_OK(env_->CreateDir(sst_files_dir_));
|
||||||
}
|
}
|
||||||
|
|
||||||
Status GenerateOneExternalFile(
|
Status GenerateOneExternalFile(
|
||||||
@ -116,7 +116,7 @@ class ExternalSSTFileTest
|
|||||||
for (const auto& entry : data) {
|
for (const auto& entry : data) {
|
||||||
s = sst_file_writer.Put(entry.first, entry.second);
|
s = sst_file_writer.Put(entry.first, entry.second);
|
||||||
if (!s.ok()) {
|
if (!s.ok()) {
|
||||||
sst_file_writer.Finish();
|
sst_file_writer.Finish().PermitUncheckedError();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,7 +171,7 @@ class ExternalSSTFileTest
|
|||||||
for (auto& entry : data) {
|
for (auto& entry : data) {
|
||||||
s = sst_file_writer.Put(entry.first, entry.second);
|
s = sst_file_writer.Put(entry.first, entry.second);
|
||||||
if (!s.ok()) {
|
if (!s.ok()) {
|
||||||
sst_file_writer.Finish();
|
sst_file_writer.Finish().PermitUncheckedError();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,11 +213,10 @@ class ExternalSSTFileTest
|
|||||||
size_t num_cfs = column_families.size();
|
size_t num_cfs = column_families.size();
|
||||||
assert(ifos.size() == num_cfs);
|
assert(ifos.size() == num_cfs);
|
||||||
assert(data.size() == num_cfs);
|
assert(data.size() == num_cfs);
|
||||||
Status s;
|
|
||||||
std::vector<IngestExternalFileArg> args(num_cfs);
|
std::vector<IngestExternalFileArg> args(num_cfs);
|
||||||
for (size_t i = 0; i != num_cfs; ++i) {
|
for (size_t i = 0; i != num_cfs; ++i) {
|
||||||
std::string external_file_path;
|
std::string external_file_path;
|
||||||
s = GenerateOneExternalFile(
|
Status s = GenerateOneExternalFile(
|
||||||
options, column_families[i], data[i], file_id, sort_data,
|
options, column_families[i], data[i], file_id, sort_data,
|
||||||
&external_file_path,
|
&external_file_path,
|
||||||
true_data.size() == num_cfs ? &true_data[i] : nullptr);
|
true_data.size() == num_cfs ? &true_data[i] : nullptr);
|
||||||
@ -230,8 +229,7 @@ class ExternalSSTFileTest
|
|||||||
args[i].external_files.push_back(external_file_path);
|
args[i].external_files.push_back(external_file_path);
|
||||||
args[i].options = ifos[i];
|
args[i].options = ifos[i];
|
||||||
}
|
}
|
||||||
s = db_->IngestExternalFiles(args);
|
return db_->IngestExternalFiles(args);
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status GenerateAndAddExternalFile(
|
Status GenerateAndAddExternalFile(
|
||||||
@ -282,7 +280,9 @@ class ExternalSSTFileTest
|
|||||||
return db_->IngestExternalFile(files, opts);
|
return db_->IngestExternalFile(files, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ExternalSSTFileTest() override { DestroyDir(env_, sst_files_dir_); }
|
~ExternalSSTFileTest() override {
|
||||||
|
DestroyDir(env_, sst_files_dir_).PermitUncheckedError();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int last_file_id_ = 0;
|
int last_file_id_ = 0;
|
||||||
@ -305,8 +305,7 @@ TEST_F(ExternalSSTFileTest, Basic) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
||||||
}
|
}
|
||||||
ExternalSstFileInfo file1_info;
|
ExternalSstFileInfo file1_info;
|
||||||
Status s = sst_file_writer.Finish(&file1_info);
|
ASSERT_OK(sst_file_writer.Finish(&file1_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
|
|
||||||
// Current file size should be non-zero after success write.
|
// Current file size should be non-zero after success write.
|
||||||
ASSERT_GT(sst_file_writer.FileSize(), 0);
|
ASSERT_GT(sst_file_writer.FileSize(), 0);
|
||||||
@ -319,8 +318,7 @@ TEST_F(ExternalSSTFileTest, Basic) {
|
|||||||
ASSERT_EQ(file1_info.smallest_range_del_key, "");
|
ASSERT_EQ(file1_info.smallest_range_del_key, "");
|
||||||
ASSERT_EQ(file1_info.largest_range_del_key, "");
|
ASSERT_EQ(file1_info.largest_range_del_key, "");
|
||||||
// sst_file_writer already finished, cannot add this value
|
// sst_file_writer already finished, cannot add this value
|
||||||
s = sst_file_writer.Put(Key(100), "bad_val");
|
ASSERT_NOK(sst_file_writer.Put(Key(100), "bad_val"));
|
||||||
ASSERT_FALSE(s.ok()) << s.ToString();
|
|
||||||
|
|
||||||
// file2.sst (100 => 199)
|
// file2.sst (100 => 199)
|
||||||
std::string file2 = sst_files_dir_ + "file2.sst";
|
std::string file2 = sst_files_dir_ + "file2.sst";
|
||||||
@ -329,11 +327,9 @@ TEST_F(ExternalSSTFileTest, Basic) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
||||||
}
|
}
|
||||||
// Cannot add this key because it's not after last added key
|
// Cannot add this key because it's not after last added key
|
||||||
s = sst_file_writer.Put(Key(99), "bad_val");
|
ASSERT_NOK(sst_file_writer.Put(Key(99), "bad_val"));
|
||||||
ASSERT_FALSE(s.ok()) << s.ToString();
|
|
||||||
ExternalSstFileInfo file2_info;
|
ExternalSstFileInfo file2_info;
|
||||||
s = sst_file_writer.Finish(&file2_info);
|
ASSERT_OK(sst_file_writer.Finish(&file2_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file2_info.file_path, file2);
|
ASSERT_EQ(file2_info.file_path, file2);
|
||||||
ASSERT_EQ(file2_info.num_entries, 100);
|
ASSERT_EQ(file2_info.num_entries, 100);
|
||||||
ASSERT_EQ(file2_info.smallest_key, Key(100));
|
ASSERT_EQ(file2_info.smallest_key, Key(100));
|
||||||
@ -347,9 +343,8 @@ TEST_F(ExternalSSTFileTest, Basic) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val_overlap"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val_overlap"));
|
||||||
}
|
}
|
||||||
ExternalSstFileInfo file3_info;
|
ExternalSstFileInfo file3_info;
|
||||||
s = sst_file_writer.Finish(&file3_info);
|
ASSERT_OK(sst_file_writer.Finish(&file3_info));
|
||||||
|
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
// Current file size should be non-zero after success finish.
|
// Current file size should be non-zero after success finish.
|
||||||
ASSERT_GT(sst_file_writer.FileSize(), 0);
|
ASSERT_GT(sst_file_writer.FileSize(), 0);
|
||||||
ASSERT_EQ(file3_info.file_path, file3);
|
ASSERT_EQ(file3_info.file_path, file3);
|
||||||
@ -365,8 +360,7 @@ TEST_F(ExternalSSTFileTest, Basic) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val_overlap"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val_overlap"));
|
||||||
}
|
}
|
||||||
ExternalSstFileInfo file4_info;
|
ExternalSstFileInfo file4_info;
|
||||||
s = sst_file_writer.Finish(&file4_info);
|
ASSERT_OK(sst_file_writer.Finish(&file4_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file4_info.file_path, file4);
|
ASSERT_EQ(file4_info.file_path, file4);
|
||||||
ASSERT_EQ(file4_info.num_entries, 10);
|
ASSERT_EQ(file4_info.num_entries, 10);
|
||||||
ASSERT_EQ(file4_info.smallest_key, Key(30));
|
ASSERT_EQ(file4_info.smallest_key, Key(30));
|
||||||
@ -379,8 +373,7 @@ TEST_F(ExternalSSTFileTest, Basic) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
||||||
}
|
}
|
||||||
ExternalSstFileInfo file5_info;
|
ExternalSstFileInfo file5_info;
|
||||||
s = sst_file_writer.Finish(&file5_info);
|
ASSERT_OK(sst_file_writer.Finish(&file5_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file5_info.file_path, file5);
|
ASSERT_EQ(file5_info.file_path, file5);
|
||||||
ASSERT_EQ(file5_info.num_entries, 100);
|
ASSERT_EQ(file5_info.num_entries, 100);
|
||||||
ASSERT_EQ(file5_info.smallest_key, Key(400));
|
ASSERT_EQ(file5_info.smallest_key, Key(400));
|
||||||
@ -389,10 +382,9 @@ TEST_F(ExternalSSTFileTest, Basic) {
|
|||||||
// file6.sst (delete 400 => 500)
|
// file6.sst (delete 400 => 500)
|
||||||
std::string file6 = sst_files_dir_ + "file6.sst";
|
std::string file6 = sst_files_dir_ + "file6.sst";
|
||||||
ASSERT_OK(sst_file_writer.Open(file6));
|
ASSERT_OK(sst_file_writer.Open(file6));
|
||||||
sst_file_writer.DeleteRange(Key(400), Key(500));
|
ASSERT_OK(sst_file_writer.DeleteRange(Key(400), Key(500)));
|
||||||
ExternalSstFileInfo file6_info;
|
ExternalSstFileInfo file6_info;
|
||||||
s = sst_file_writer.Finish(&file6_info);
|
ASSERT_OK(sst_file_writer.Finish(&file6_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file6_info.file_path, file6);
|
ASSERT_EQ(file6_info.file_path, file6);
|
||||||
ASSERT_EQ(file6_info.num_entries, 0);
|
ASSERT_EQ(file6_info.num_entries, 0);
|
||||||
ASSERT_EQ(file6_info.smallest_key, "");
|
ASSERT_EQ(file6_info.smallest_key, "");
|
||||||
@ -404,17 +396,16 @@ TEST_F(ExternalSSTFileTest, Basic) {
|
|||||||
// file7.sst (delete 500 => 570, put 520 => 599 divisible by 2)
|
// file7.sst (delete 500 => 570, put 520 => 599 divisible by 2)
|
||||||
std::string file7 = sst_files_dir_ + "file7.sst";
|
std::string file7 = sst_files_dir_ + "file7.sst";
|
||||||
ASSERT_OK(sst_file_writer.Open(file7));
|
ASSERT_OK(sst_file_writer.Open(file7));
|
||||||
sst_file_writer.DeleteRange(Key(500), Key(550));
|
ASSERT_OK(sst_file_writer.DeleteRange(Key(500), Key(550)));
|
||||||
for (int k = 520; k < 560; k += 2) {
|
for (int k = 520; k < 560; k += 2) {
|
||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
||||||
}
|
}
|
||||||
sst_file_writer.DeleteRange(Key(525), Key(575));
|
ASSERT_OK(sst_file_writer.DeleteRange(Key(525), Key(575)));
|
||||||
for (int k = 560; k < 600; k += 2) {
|
for (int k = 560; k < 600; k += 2) {
|
||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
||||||
}
|
}
|
||||||
ExternalSstFileInfo file7_info;
|
ExternalSstFileInfo file7_info;
|
||||||
s = sst_file_writer.Finish(&file7_info);
|
ASSERT_OK(sst_file_writer.Finish(&file7_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file7_info.file_path, file7);
|
ASSERT_EQ(file7_info.file_path, file7);
|
||||||
ASSERT_EQ(file7_info.num_entries, 40);
|
ASSERT_EQ(file7_info.num_entries, 40);
|
||||||
ASSERT_EQ(file7_info.smallest_key, Key(520));
|
ASSERT_EQ(file7_info.smallest_key, Key(520));
|
||||||
@ -426,10 +417,9 @@ TEST_F(ExternalSSTFileTest, Basic) {
|
|||||||
// file8.sst (delete 600 => 700)
|
// file8.sst (delete 600 => 700)
|
||||||
std::string file8 = sst_files_dir_ + "file8.sst";
|
std::string file8 = sst_files_dir_ + "file8.sst";
|
||||||
ASSERT_OK(sst_file_writer.Open(file8));
|
ASSERT_OK(sst_file_writer.Open(file8));
|
||||||
sst_file_writer.DeleteRange(Key(600), Key(700));
|
ASSERT_OK(sst_file_writer.DeleteRange(Key(600), Key(700)));
|
||||||
ExternalSstFileInfo file8_info;
|
ExternalSstFileInfo file8_info;
|
||||||
s = sst_file_writer.Finish(&file8_info);
|
ASSERT_OK(sst_file_writer.Finish(&file8_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file8_info.file_path, file8);
|
ASSERT_EQ(file8_info.file_path, file8);
|
||||||
ASSERT_EQ(file8_info.num_entries, 0);
|
ASSERT_EQ(file8_info.num_entries, 0);
|
||||||
ASSERT_EQ(file8_info.smallest_key, "");
|
ASSERT_EQ(file8_info.smallest_key, "");
|
||||||
@ -441,13 +431,11 @@ TEST_F(ExternalSSTFileTest, Basic) {
|
|||||||
// Cannot create an empty sst file
|
// Cannot create an empty sst file
|
||||||
std::string file_empty = sst_files_dir_ + "file_empty.sst";
|
std::string file_empty = sst_files_dir_ + "file_empty.sst";
|
||||||
ExternalSstFileInfo file_empty_info;
|
ExternalSstFileInfo file_empty_info;
|
||||||
s = sst_file_writer.Finish(&file_empty_info);
|
ASSERT_NOK(sst_file_writer.Finish(&file_empty_info));
|
||||||
ASSERT_NOK(s);
|
|
||||||
|
|
||||||
DestroyAndReopen(options);
|
DestroyAndReopen(options);
|
||||||
// Add file using file path
|
// Add file using file path
|
||||||
s = DeprecatedAddFile({file1});
|
ASSERT_OK(DeprecatedAddFile({file1}));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(db_->GetLatestSequenceNumber(), 0U);
|
ASSERT_EQ(db_->GetLatestSequenceNumber(), 0U);
|
||||||
for (int k = 0; k < 100; k++) {
|
for (int k = 0; k < 100; k++) {
|
||||||
ASSERT_EQ(Get(Key(k)), Key(k) + "_val");
|
ASSERT_EQ(Get(Key(k)), Key(k) + "_val");
|
||||||
@ -468,12 +456,10 @@ TEST_F(ExternalSSTFileTest, Basic) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This file has overlapping values with the existing data
|
// This file has overlapping values with the existing data
|
||||||
s = DeprecatedAddFile({file3});
|
ASSERT_NOK(DeprecatedAddFile({file3}));
|
||||||
ASSERT_FALSE(s.ok()) << s.ToString();
|
|
||||||
|
|
||||||
// This file has overlapping values with the existing data
|
// This file has overlapping values with the existing data
|
||||||
s = DeprecatedAddFile({file4});
|
ASSERT_NOK(DeprecatedAddFile({file4}));
|
||||||
ASSERT_FALSE(s.ok()) << s.ToString();
|
|
||||||
|
|
||||||
// Overwrite values of keys divisible by 5
|
// Overwrite values of keys divisible by 5
|
||||||
for (int k = 0; k < 200; k += 5) {
|
for (int k = 0; k < 200; k += 5) {
|
||||||
@ -485,8 +471,7 @@ TEST_F(ExternalSSTFileTest, Basic) {
|
|||||||
ASSERT_OK(DeprecatedAddFile({file5}));
|
ASSERT_OK(DeprecatedAddFile({file5}));
|
||||||
|
|
||||||
// This file has overlapping values with the existing data
|
// This file has overlapping values with the existing data
|
||||||
s = DeprecatedAddFile({file6});
|
ASSERT_NOK(DeprecatedAddFile({file6}));
|
||||||
ASSERT_FALSE(s.ok()) << s.ToString();
|
|
||||||
|
|
||||||
// Key range of file7 (500 => 598) don't overlap with any keys in DB
|
// Key range of file7 (500 => 598) don't overlap with any keys in DB
|
||||||
ASSERT_OK(DeprecatedAddFile({file7}));
|
ASSERT_OK(DeprecatedAddFile({file7}));
|
||||||
@ -614,15 +599,13 @@ TEST_F(ExternalSSTFileTest, AddList) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
||||||
}
|
}
|
||||||
ExternalSstFileInfo file1_info;
|
ExternalSstFileInfo file1_info;
|
||||||
Status s = sst_file_writer.Finish(&file1_info);
|
ASSERT_OK(sst_file_writer.Finish(&file1_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file1_info.file_path, file1);
|
ASSERT_EQ(file1_info.file_path, file1);
|
||||||
ASSERT_EQ(file1_info.num_entries, 100);
|
ASSERT_EQ(file1_info.num_entries, 100);
|
||||||
ASSERT_EQ(file1_info.smallest_key, Key(0));
|
ASSERT_EQ(file1_info.smallest_key, Key(0));
|
||||||
ASSERT_EQ(file1_info.largest_key, Key(99));
|
ASSERT_EQ(file1_info.largest_key, Key(99));
|
||||||
// sst_file_writer already finished, cannot add this value
|
// sst_file_writer already finished, cannot add this value
|
||||||
s = sst_file_writer.Put(Key(100), "bad_val");
|
ASSERT_NOK(sst_file_writer.Put(Key(100), "bad_val"));
|
||||||
ASSERT_FALSE(s.ok()) << s.ToString();
|
|
||||||
|
|
||||||
// file2.sst (100 => 199)
|
// file2.sst (100 => 199)
|
||||||
std::string file2 = sst_files_dir_ + "file2.sst";
|
std::string file2 = sst_files_dir_ + "file2.sst";
|
||||||
@ -631,11 +614,9 @@ TEST_F(ExternalSSTFileTest, AddList) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
||||||
}
|
}
|
||||||
// Cannot add this key because it's not after last added key
|
// Cannot add this key because it's not after last added key
|
||||||
s = sst_file_writer.Put(Key(99), "bad_val");
|
ASSERT_NOK(sst_file_writer.Put(Key(99), "bad_val"));
|
||||||
ASSERT_FALSE(s.ok()) << s.ToString();
|
|
||||||
ExternalSstFileInfo file2_info;
|
ExternalSstFileInfo file2_info;
|
||||||
s = sst_file_writer.Finish(&file2_info);
|
ASSERT_OK(sst_file_writer.Finish(&file2_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file2_info.file_path, file2);
|
ASSERT_EQ(file2_info.file_path, file2);
|
||||||
ASSERT_EQ(file2_info.num_entries, 100);
|
ASSERT_EQ(file2_info.num_entries, 100);
|
||||||
ASSERT_EQ(file2_info.smallest_key, Key(100));
|
ASSERT_EQ(file2_info.smallest_key, Key(100));
|
||||||
@ -649,8 +630,7 @@ TEST_F(ExternalSSTFileTest, AddList) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val_overlap"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val_overlap"));
|
||||||
}
|
}
|
||||||
ExternalSstFileInfo file3_info;
|
ExternalSstFileInfo file3_info;
|
||||||
s = sst_file_writer.Finish(&file3_info);
|
ASSERT_OK(sst_file_writer.Finish(&file3_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file3_info.file_path, file3);
|
ASSERT_EQ(file3_info.file_path, file3);
|
||||||
ASSERT_EQ(file3_info.num_entries, 5);
|
ASSERT_EQ(file3_info.num_entries, 5);
|
||||||
ASSERT_EQ(file3_info.smallest_key, Key(195));
|
ASSERT_EQ(file3_info.smallest_key, Key(195));
|
||||||
@ -664,8 +644,7 @@ TEST_F(ExternalSSTFileTest, AddList) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val_overlap"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val_overlap"));
|
||||||
}
|
}
|
||||||
ExternalSstFileInfo file4_info;
|
ExternalSstFileInfo file4_info;
|
||||||
s = sst_file_writer.Finish(&file4_info);
|
ASSERT_OK(sst_file_writer.Finish(&file4_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file4_info.file_path, file4);
|
ASSERT_EQ(file4_info.file_path, file4);
|
||||||
ASSERT_EQ(file4_info.num_entries, 10);
|
ASSERT_EQ(file4_info.num_entries, 10);
|
||||||
ASSERT_EQ(file4_info.smallest_key, Key(30));
|
ASSERT_EQ(file4_info.smallest_key, Key(30));
|
||||||
@ -678,8 +657,7 @@ TEST_F(ExternalSSTFileTest, AddList) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
||||||
}
|
}
|
||||||
ExternalSstFileInfo file5_info;
|
ExternalSstFileInfo file5_info;
|
||||||
s = sst_file_writer.Finish(&file5_info);
|
ASSERT_OK(sst_file_writer.Finish(&file5_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file5_info.file_path, file5);
|
ASSERT_EQ(file5_info.file_path, file5);
|
||||||
ASSERT_EQ(file5_info.num_entries, 100);
|
ASSERT_EQ(file5_info.num_entries, 100);
|
||||||
ASSERT_EQ(file5_info.smallest_key, Key(200));
|
ASSERT_EQ(file5_info.smallest_key, Key(200));
|
||||||
@ -691,8 +669,7 @@ TEST_F(ExternalSSTFileTest, AddList) {
|
|||||||
ASSERT_OK(sst_file_writer.DeleteRange(Key(0), Key(75)));
|
ASSERT_OK(sst_file_writer.DeleteRange(Key(0), Key(75)));
|
||||||
ASSERT_OK(sst_file_writer.DeleteRange(Key(25), Key(100)));
|
ASSERT_OK(sst_file_writer.DeleteRange(Key(25), Key(100)));
|
||||||
ExternalSstFileInfo file6_info;
|
ExternalSstFileInfo file6_info;
|
||||||
s = sst_file_writer.Finish(&file6_info);
|
ASSERT_OK(sst_file_writer.Finish(&file6_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file6_info.file_path, file6);
|
ASSERT_EQ(file6_info.file_path, file6);
|
||||||
ASSERT_EQ(file6_info.num_entries, 0);
|
ASSERT_EQ(file6_info.num_entries, 0);
|
||||||
ASSERT_EQ(file6_info.smallest_key, "");
|
ASSERT_EQ(file6_info.smallest_key, "");
|
||||||
@ -706,8 +683,7 @@ TEST_F(ExternalSSTFileTest, AddList) {
|
|||||||
ASSERT_OK(sst_file_writer.Open(file7));
|
ASSERT_OK(sst_file_writer.Open(file7));
|
||||||
ASSERT_OK(sst_file_writer.DeleteRange(Key(99), Key(201)));
|
ASSERT_OK(sst_file_writer.DeleteRange(Key(99), Key(201)));
|
||||||
ExternalSstFileInfo file7_info;
|
ExternalSstFileInfo file7_info;
|
||||||
s = sst_file_writer.Finish(&file7_info);
|
ASSERT_OK(sst_file_writer.Finish(&file7_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file7_info.file_path, file7);
|
ASSERT_EQ(file7_info.file_path, file7);
|
||||||
ASSERT_EQ(file7_info.num_entries, 0);
|
ASSERT_EQ(file7_info.num_entries, 0);
|
||||||
ASSERT_EQ(file7_info.smallest_key, "");
|
ASSERT_EQ(file7_info.smallest_key, "");
|
||||||
@ -727,17 +703,13 @@ TEST_F(ExternalSSTFileTest, AddList) {
|
|||||||
DestroyAndReopen(options);
|
DestroyAndReopen(options);
|
||||||
|
|
||||||
// These lists of files have key ranges that overlap with each other
|
// These lists of files have key ranges that overlap with each other
|
||||||
s = DeprecatedAddFile(file_list1);
|
ASSERT_NOK(DeprecatedAddFile(file_list1));
|
||||||
ASSERT_FALSE(s.ok()) << s.ToString();
|
|
||||||
// Both of the following overlap on the range deletion tombstone.
|
// Both of the following overlap on the range deletion tombstone.
|
||||||
s = DeprecatedAddFile(file_list4);
|
ASSERT_NOK(DeprecatedAddFile(file_list4));
|
||||||
ASSERT_FALSE(s.ok()) << s.ToString();
|
ASSERT_NOK(DeprecatedAddFile(file_list5));
|
||||||
s = DeprecatedAddFile(file_list5);
|
|
||||||
ASSERT_FALSE(s.ok()) << s.ToString();
|
|
||||||
|
|
||||||
// Add files using file path list
|
// Add files using file path list
|
||||||
s = DeprecatedAddFile(file_list0);
|
ASSERT_OK(DeprecatedAddFile(file_list0));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(db_->GetLatestSequenceNumber(), 0U);
|
ASSERT_EQ(db_->GetLatestSequenceNumber(), 0U);
|
||||||
for (int k = 0; k < 200; k++) {
|
for (int k = 0; k < 200; k++) {
|
||||||
ASSERT_EQ(Get(Key(k)), Key(k) + "_val");
|
ASSERT_EQ(Get(Key(k)), Key(k) + "_val");
|
||||||
@ -778,8 +750,7 @@ TEST_F(ExternalSSTFileTest, AddList) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This file list has overlapping values with the existing data
|
// This file list has overlapping values with the existing data
|
||||||
s = DeprecatedAddFile(file_list3);
|
ASSERT_NOK(DeprecatedAddFile(file_list3));
|
||||||
ASSERT_FALSE(s.ok()) << s.ToString();
|
|
||||||
|
|
||||||
// Overwrite values of keys divisible by 5
|
// Overwrite values of keys divisible by 5
|
||||||
for (int k = 0; k < 200; k += 5) {
|
for (int k = 0; k < 200; k += 5) {
|
||||||
@ -847,16 +818,14 @@ TEST_F(ExternalSSTFileTest, AddListAtomicity) {
|
|||||||
for (int k = i * 100; k < (i + 1) * 100; k++) {
|
for (int k = i * 100; k < (i + 1) * 100; k++) {
|
||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
||||||
}
|
}
|
||||||
Status s = sst_file_writer.Finish(&files_info[i]);
|
ASSERT_OK(sst_file_writer.Finish(&files_info[i]));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(files_info[i].file_path, files[i]);
|
ASSERT_EQ(files_info[i].file_path, files[i]);
|
||||||
ASSERT_EQ(files_info[i].num_entries, 100);
|
ASSERT_EQ(files_info[i].num_entries, 100);
|
||||||
ASSERT_EQ(files_info[i].smallest_key, Key(i * 100));
|
ASSERT_EQ(files_info[i].smallest_key, Key(i * 100));
|
||||||
ASSERT_EQ(files_info[i].largest_key, Key((i + 1) * 100 - 1));
|
ASSERT_EQ(files_info[i].largest_key, Key((i + 1) * 100 - 1));
|
||||||
}
|
}
|
||||||
files.push_back(sst_files_dir_ + "file" + std::to_string(n) + ".sst");
|
files.push_back(sst_files_dir_ + "file" + std::to_string(n) + ".sst");
|
||||||
auto s = DeprecatedAddFile(files);
|
ASSERT_NOK(DeprecatedAddFile(files));
|
||||||
ASSERT_NOK(s) << s.ToString();
|
|
||||||
for (int k = 0; k < n * 100; k++) {
|
for (int k = 0; k < n * 100; k++) {
|
||||||
ASSERT_EQ("NOT_FOUND", Get(Key(k)));
|
ASSERT_EQ("NOT_FOUND", Get(Key(k)));
|
||||||
}
|
}
|
||||||
@ -878,17 +847,14 @@ TEST_F(ExternalSSTFileTest, PurgeObsoleteFilesBug) {
|
|||||||
|
|
||||||
// file1.sst (0 => 500)
|
// file1.sst (0 => 500)
|
||||||
std::string sst_file_path = sst_files_dir_ + "file1.sst";
|
std::string sst_file_path = sst_files_dir_ + "file1.sst";
|
||||||
Status s = sst_file_writer.Open(sst_file_path);
|
ASSERT_OK(sst_file_writer.Open(sst_file_path));
|
||||||
ASSERT_OK(s);
|
|
||||||
for (int i = 0; i < 500; i++) {
|
for (int i = 0; i < 500; i++) {
|
||||||
std::string k = Key(i);
|
std::string k = Key(i);
|
||||||
s = sst_file_writer.Put(k, k + "_val");
|
ASSERT_OK(sst_file_writer.Put(k, k + "_val"));
|
||||||
ASSERT_OK(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalSstFileInfo sst_file_info;
|
ExternalSstFileInfo sst_file_info;
|
||||||
s = sst_file_writer.Finish(&sst_file_info);
|
ASSERT_OK(sst_file_writer.Finish(&sst_file_info));
|
||||||
ASSERT_OK(s);
|
|
||||||
|
|
||||||
options.delete_obsolete_files_period_micros = 0;
|
options.delete_obsolete_files_period_micros = 0;
|
||||||
options.disable_auto_compactions = true;
|
options.disable_auto_compactions = true;
|
||||||
@ -900,12 +866,11 @@ TEST_F(ExternalSSTFileTest, PurgeObsoleteFilesBug) {
|
|||||||
ASSERT_OK(Flush());
|
ASSERT_OK(Flush());
|
||||||
ASSERT_OK(Put("aaa", "xxx"));
|
ASSERT_OK(Put("aaa", "xxx"));
|
||||||
ASSERT_OK(Flush());
|
ASSERT_OK(Flush());
|
||||||
db_->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
});
|
});
|
||||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
|
||||||
|
|
||||||
s = DeprecatedAddFile({sst_file_path});
|
ASSERT_OK(DeprecatedAddFile({sst_file_path}));
|
||||||
ASSERT_OK(s);
|
|
||||||
|
|
||||||
for (int i = 0; i < 500; i++) {
|
for (int i = 0; i < 500; i++) {
|
||||||
std::string k = Key(i);
|
std::string k = Key(i);
|
||||||
@ -928,8 +893,7 @@ TEST_F(ExternalSSTFileTest, SkipSnapshot) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
||||||
}
|
}
|
||||||
ExternalSstFileInfo file1_info;
|
ExternalSstFileInfo file1_info;
|
||||||
Status s = sst_file_writer.Finish(&file1_info);
|
ASSERT_OK(sst_file_writer.Finish(&file1_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file1_info.file_path, file1);
|
ASSERT_EQ(file1_info.file_path, file1);
|
||||||
ASSERT_EQ(file1_info.num_entries, 100);
|
ASSERT_EQ(file1_info.num_entries, 100);
|
||||||
ASSERT_EQ(file1_info.smallest_key, Key(0));
|
ASSERT_EQ(file1_info.smallest_key, Key(0));
|
||||||
@ -942,8 +906,7 @@ TEST_F(ExternalSSTFileTest, SkipSnapshot) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
||||||
}
|
}
|
||||||
ExternalSstFileInfo file2_info;
|
ExternalSstFileInfo file2_info;
|
||||||
s = sst_file_writer.Finish(&file2_info);
|
ASSERT_OK(sst_file_writer.Finish(&file2_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file2_info.file_path, file2);
|
ASSERT_EQ(file2_info.file_path, file2);
|
||||||
ASSERT_EQ(file2_info.num_entries, 200);
|
ASSERT_EQ(file2_info.num_entries, 200);
|
||||||
ASSERT_EQ(file2_info.smallest_key, Key(100));
|
ASSERT_EQ(file2_info.smallest_key, Key(100));
|
||||||
@ -972,8 +935,7 @@ TEST_F(ExternalSSTFileTest, SkipSnapshot) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k) + "_val"));
|
||||||
}
|
}
|
||||||
ExternalSstFileInfo file3_info;
|
ExternalSstFileInfo file3_info;
|
||||||
s = sst_file_writer.Finish(&file3_info);
|
ASSERT_OK(sst_file_writer.Finish(&file3_info));
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
ASSERT_EQ(file3_info.file_path, file3);
|
ASSERT_EQ(file3_info.file_path, file3);
|
||||||
ASSERT_EQ(file3_info.num_entries, 100);
|
ASSERT_EQ(file3_info.num_entries, 100);
|
||||||
ASSERT_EQ(file3_info.smallest_key, Key(300));
|
ASSERT_EQ(file3_info.smallest_key, Key(300));
|
||||||
@ -1019,8 +981,7 @@ TEST_F(ExternalSSTFileTest, MultiThreaded) {
|
|||||||
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k)));
|
ASSERT_OK(sst_file_writer.Put(Key(k), Key(k)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Status s = sst_file_writer.Finish();
|
ASSERT_OK(sst_file_writer.Finish());
|
||||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
|
||||||
};
|
};
|
||||||
// Write num_files files in parallel
|
// Write num_files files in parallel
|
||||||
std::vector<port::Thread> sst_writer_threads;
|
std::vector<port::Thread> sst_writer_threads;
|
||||||
@ -1082,8 +1043,7 @@ TEST_F(ExternalSSTFileTest, MultiThreaded) {
|
|||||||
// Overwrite values of keys divisible by 100
|
// Overwrite values of keys divisible by 100
|
||||||
for (int k = 0; k < num_files * keys_per_file; k += 100) {
|
for (int k = 0; k < num_files * keys_per_file; k += 100) {
|
||||||
std::string key = Key(k);
|
std::string key = Key(k);
|
||||||
Status s = Put(key, key + "_new");
|
ASSERT_OK(Put(key, key + "_new"));
|
||||||
ASSERT_TRUE(s.ok());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
@ -1167,7 +1127,8 @@ TEST_F(ExternalSSTFileTest, OverlappingRanges) {
|
|||||||
|
|
||||||
// Generate the file containing the range
|
// Generate the file containing the range
|
||||||
std::string file_name = sst_files_dir_ + env_->GenerateUniqueId();
|
std::string file_name = sst_files_dir_ + env_->GenerateUniqueId();
|
||||||
ASSERT_OK(sst_file_writer.Open(file_name));
|
s = sst_file_writer.Open(file_name);
|
||||||
|
ASSERT_OK(s);
|
||||||
for (int k = range_start; k <= range_end; k++) {
|
for (int k = range_start; k <= range_end; k++) {
|
||||||
s = sst_file_writer.Put(Key(k), range_val);
|
s = sst_file_writer.Put(Key(k), range_val);
|
||||||
ASSERT_OK(s);
|
ASSERT_OK(s);
|
||||||
@ -1212,10 +1173,10 @@ TEST_F(ExternalSSTFileTest, OverlappingRanges) {
|
|||||||
|
|
||||||
// Flush / Compact the DB
|
// Flush / Compact the DB
|
||||||
if (i && i % 50 == 0) {
|
if (i && i % 50 == 0) {
|
||||||
Flush();
|
ASSERT_OK(Flush());
|
||||||
}
|
}
|
||||||
if (i && i % 75 == 0) {
|
if (i && i % 75 == 0) {
|
||||||
db_->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1293,7 +1254,7 @@ TEST_P(ExternalSSTFileTest, PickedLevel) {
|
|||||||
// Hold compaction from finishing
|
// Hold compaction from finishing
|
||||||
TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevel:2");
|
TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevel:2");
|
||||||
|
|
||||||
dbfull()->TEST_WaitForCompact();
|
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||||
EXPECT_EQ(FilesPerLevel(), "1,1,1,2");
|
EXPECT_EQ(FilesPerLevel(), "1,1,1,2");
|
||||||
|
|
||||||
size_t kcnt = 0;
|
size_t kcnt = 0;
|
||||||
@ -1380,7 +1341,7 @@ TEST_F(ExternalSSTFileTest, PickedLevelBug) {
|
|||||||
ASSERT_OK(bg_addfile_status);
|
ASSERT_OK(bg_addfile_status);
|
||||||
ASSERT_OK(bg_compact_status);
|
ASSERT_OK(bg_compact_status);
|
||||||
|
|
||||||
dbfull()->TEST_WaitForCompact();
|
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||||
|
|
||||||
int total_keys = 0;
|
int total_keys = 0;
|
||||||
Iterator* iter = db_->NewIterator(ReadOptions());
|
Iterator* iter = db_->NewIterator(ReadOptions());
|
||||||
@ -1417,7 +1378,7 @@ TEST_F(ExternalSSTFileTest, IngestNonExistingFile) {
|
|||||||
|
|
||||||
// After full compaction, there should be only 1 file.
|
// After full compaction, there should be only 1 file.
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
env_->GetChildren(dbname_, &files);
|
ASSERT_OK(env_->GetChildren(dbname_, &files));
|
||||||
int num_sst_files = 0;
|
int num_sst_files = 0;
|
||||||
for (auto& f : files) {
|
for (auto& f : files) {
|
||||||
uint64_t number;
|
uint64_t number;
|
||||||
@ -1539,7 +1500,7 @@ TEST_F(ExternalSSTFileTest, PickedLevelDynamic) {
|
|||||||
TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevelDynamic:2");
|
TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevelDynamic:2");
|
||||||
|
|
||||||
// Output of the compaction will go to L3
|
// Output of the compaction will go to L3
|
||||||
dbfull()->TEST_WaitForCompact();
|
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||||
EXPECT_EQ(FilesPerLevel(), "1,0,0,2");
|
EXPECT_EQ(FilesPerLevel(), "1,0,0,2");
|
||||||
|
|
||||||
Close();
|
Close();
|
||||||
@ -1681,7 +1642,7 @@ TEST_F(ExternalSSTFileTest, AddFileTrivialMoveBug) {
|
|||||||
cro.exclusive_manual_compaction = false;
|
cro.exclusive_manual_compaction = false;
|
||||||
ASSERT_OK(db_->CompactRange(cro, nullptr, nullptr));
|
ASSERT_OK(db_->CompactRange(cro, nullptr, nullptr));
|
||||||
|
|
||||||
dbfull()->TEST_WaitForCompact();
|
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||||
|
|
||||||
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
|
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
|
||||||
}
|
}
|
||||||
@ -1733,9 +1694,9 @@ TEST_F(ExternalSSTFileTest, WithUnorderedWrite) {
|
|||||||
Options options = CurrentOptions();
|
Options options = CurrentOptions();
|
||||||
options.unordered_write = true;
|
options.unordered_write = true;
|
||||||
DestroyAndReopen(options);
|
DestroyAndReopen(options);
|
||||||
Put("foo", "v1");
|
ASSERT_OK(Put("foo", "v1"));
|
||||||
SyncPoint::GetInstance()->EnableProcessing();
|
SyncPoint::GetInstance()->EnableProcessing();
|
||||||
port::Thread writer([&]() { Put("bar", "v2"); });
|
port::Thread writer([&]() { ASSERT_OK(Put("bar", "v2")); });
|
||||||
|
|
||||||
TEST_SYNC_POINT("ExternalSSTFileTest::WithUnorderedWrite:WaitWriteWAL");
|
TEST_SYNC_POINT("ExternalSSTFileTest::WithUnorderedWrite:WaitWriteWAL");
|
||||||
ASSERT_OK(GenerateAndAddExternalFile(options, {{"bar", "v3"}}, -1,
|
ASSERT_OK(GenerateAndAddExternalFile(options, {{"bar", "v3"}}, -1,
|
||||||
@ -1784,7 +1745,7 @@ TEST_P(ExternalSSTFileTest, IngestFileWithGlobalSeqnoRandomized) {
|
|||||||
}
|
}
|
||||||
size_t kcnt = 0;
|
size_t kcnt = 0;
|
||||||
VerifyDBFromMap(true_data, &kcnt, false);
|
VerifyDBFromMap(true_data, &kcnt, false);
|
||||||
db_->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
VerifyDBFromMap(true_data, &kcnt, false);
|
VerifyDBFromMap(true_data, &kcnt, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1868,8 +1829,8 @@ TEST_P(ExternalSSTFileTest, IngestFileWithGlobalSeqnoMemtableFlush) {
|
|||||||
ASSERT_OK(Put(Key(k), "memtable"));
|
ASSERT_OK(Put(Key(k), "memtable"));
|
||||||
true_data[Key(k)] = "memtable";
|
true_data[Key(k)] = "memtable";
|
||||||
}
|
}
|
||||||
db_->GetIntProperty(DB::Properties::kNumEntriesActiveMemTable,
|
ASSERT_TRUE(db_->GetIntProperty(DB::Properties::kNumEntriesActiveMemTable,
|
||||||
&entries_in_memtable);
|
&entries_in_memtable));
|
||||||
ASSERT_GE(entries_in_memtable, 1);
|
ASSERT_GE(entries_in_memtable, 1);
|
||||||
|
|
||||||
bool write_global_seqno = std::get<0>(GetParam());
|
bool write_global_seqno = std::get<0>(GetParam());
|
||||||
@ -1878,40 +1839,40 @@ TEST_P(ExternalSSTFileTest, IngestFileWithGlobalSeqnoMemtableFlush) {
|
|||||||
ASSERT_OK(GenerateAndAddExternalFile(
|
ASSERT_OK(GenerateAndAddExternalFile(
|
||||||
options, {90, 100, 110}, -1, true, write_global_seqno,
|
options, {90, 100, 110}, -1, true, write_global_seqno,
|
||||||
verify_checksums_before_ingest, false, false, &true_data));
|
verify_checksums_before_ingest, false, false, &true_data));
|
||||||
db_->GetIntProperty(DB::Properties::kNumEntriesActiveMemTable,
|
ASSERT_TRUE(db_->GetIntProperty(DB::Properties::kNumEntriesActiveMemTable,
|
||||||
&entries_in_memtable);
|
&entries_in_memtable));
|
||||||
ASSERT_GE(entries_in_memtable, 1);
|
ASSERT_GE(entries_in_memtable, 1);
|
||||||
|
|
||||||
// This file will flush the memtable
|
// This file will flush the memtable
|
||||||
ASSERT_OK(GenerateAndAddExternalFile(
|
ASSERT_OK(GenerateAndAddExternalFile(
|
||||||
options, {19, 20, 21}, -1, true, write_global_seqno,
|
options, {19, 20, 21}, -1, true, write_global_seqno,
|
||||||
verify_checksums_before_ingest, false, false, &true_data));
|
verify_checksums_before_ingest, false, false, &true_data));
|
||||||
db_->GetIntProperty(DB::Properties::kNumEntriesActiveMemTable,
|
ASSERT_TRUE(db_->GetIntProperty(DB::Properties::kNumEntriesActiveMemTable,
|
||||||
&entries_in_memtable);
|
&entries_in_memtable));
|
||||||
ASSERT_EQ(entries_in_memtable, 0);
|
ASSERT_EQ(entries_in_memtable, 0);
|
||||||
|
|
||||||
for (int k : {200, 201, 205, 206}) {
|
for (int k : {200, 201, 205, 206}) {
|
||||||
ASSERT_OK(Put(Key(k), "memtable"));
|
ASSERT_OK(Put(Key(k), "memtable"));
|
||||||
true_data[Key(k)] = "memtable";
|
true_data[Key(k)] = "memtable";
|
||||||
}
|
}
|
||||||
db_->GetIntProperty(DB::Properties::kNumEntriesActiveMemTable,
|
ASSERT_TRUE(db_->GetIntProperty(DB::Properties::kNumEntriesActiveMemTable,
|
||||||
&entries_in_memtable);
|
&entries_in_memtable));
|
||||||
ASSERT_GE(entries_in_memtable, 1);
|
ASSERT_GE(entries_in_memtable, 1);
|
||||||
|
|
||||||
// No need for flush, this file keys fit between the memtable keys
|
// No need for flush, this file keys fit between the memtable keys
|
||||||
ASSERT_OK(GenerateAndAddExternalFile(
|
ASSERT_OK(GenerateAndAddExternalFile(
|
||||||
options, {202, 203, 204}, -1, true, write_global_seqno,
|
options, {202, 203, 204}, -1, true, write_global_seqno,
|
||||||
verify_checksums_before_ingest, false, false, &true_data));
|
verify_checksums_before_ingest, false, false, &true_data));
|
||||||
db_->GetIntProperty(DB::Properties::kNumEntriesActiveMemTable,
|
ASSERT_TRUE(db_->GetIntProperty(DB::Properties::kNumEntriesActiveMemTable,
|
||||||
&entries_in_memtable);
|
&entries_in_memtable));
|
||||||
ASSERT_GE(entries_in_memtable, 1);
|
ASSERT_GE(entries_in_memtable, 1);
|
||||||
|
|
||||||
// This file will flush the memtable
|
// This file will flush the memtable
|
||||||
ASSERT_OK(GenerateAndAddExternalFile(
|
ASSERT_OK(GenerateAndAddExternalFile(
|
||||||
options, {206, 207}, -1, true, write_global_seqno,
|
options, {206, 207}, -1, true, write_global_seqno,
|
||||||
verify_checksums_before_ingest, false, false, &true_data));
|
verify_checksums_before_ingest, false, false, &true_data));
|
||||||
db_->GetIntProperty(DB::Properties::kNumEntriesActiveMemTable,
|
ASSERT_TRUE(db_->GetIntProperty(DB::Properties::kNumEntriesActiveMemTable,
|
||||||
&entries_in_memtable);
|
&entries_in_memtable));
|
||||||
ASSERT_EQ(entries_in_memtable, 0);
|
ASSERT_EQ(entries_in_memtable, 0);
|
||||||
|
|
||||||
size_t kcnt = 0;
|
size_t kcnt = 0;
|
||||||
@ -2309,7 +2270,7 @@ TEST_P(ExternalSSTFileTest, IngestBehind) {
|
|||||||
ASSERT_OK(Put(Key(i), "memtable"));
|
ASSERT_OK(Put(Key(i), "memtable"));
|
||||||
true_data[Key(i)] = "memtable";
|
true_data[Key(i)] = "memtable";
|
||||||
}
|
}
|
||||||
db_->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
// Universal picker should go at second from the bottom level
|
// Universal picker should go at second from the bottom level
|
||||||
ASSERT_EQ("0,1", FilesPerLevel());
|
ASSERT_EQ("0,1", FilesPerLevel());
|
||||||
ASSERT_OK(GenerateAndAddExternalFile(
|
ASSERT_OK(GenerateAndAddExternalFile(
|
||||||
@ -2323,7 +2284,7 @@ TEST_P(ExternalSSTFileTest, IngestBehind) {
|
|||||||
verify_checksums_before_ingest, true /*ingest_behind*/,
|
verify_checksums_before_ingest, true /*ingest_behind*/,
|
||||||
false /*sort_data*/, &true_data));
|
false /*sort_data*/, &true_data));
|
||||||
ASSERT_EQ("0,1,1", FilesPerLevel());
|
ASSERT_EQ("0,1,1", FilesPerLevel());
|
||||||
db_->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
// bottom level should be empty
|
// bottom level should be empty
|
||||||
ASSERT_EQ("0,1", FilesPerLevel());
|
ASSERT_EQ("0,1", FilesPerLevel());
|
||||||
|
|
||||||
@ -2471,9 +2432,8 @@ TEST_P(ExternalSSTFileTest, IngestFilesIntoMultipleColumnFamilies_Success) {
|
|||||||
// Resize the true_data vector upon construction to avoid re-alloc
|
// Resize the true_data vector upon construction to avoid re-alloc
|
||||||
std::vector<std::map<std::string, std::string>> true_data(
|
std::vector<std::map<std::string, std::string>> true_data(
|
||||||
column_families.size());
|
column_families.size());
|
||||||
Status s = GenerateAndAddExternalFiles(options, column_families, ifos, data,
|
ASSERT_OK(GenerateAndAddExternalFiles(options, column_families, ifos, data,
|
||||||
-1, true, true_data);
|
-1, true, true_data));
|
||||||
ASSERT_OK(s);
|
|
||||||
Close();
|
Close();
|
||||||
ReopenWithColumnFamilies({kDefaultColumnFamilyName, "pikachu", "eevee"},
|
ReopenWithColumnFamilies({kDefaultColumnFamilyName, "pikachu", "eevee"},
|
||||||
options);
|
options);
|
||||||
@ -2654,9 +2614,8 @@ TEST_P(ExternalSSTFileTest, IngestFilesIntoMultipleColumnFamilies_PrepareFail) {
|
|||||||
std::vector<std::map<std::string, std::string>> true_data(
|
std::vector<std::map<std::string, std::string>> true_data(
|
||||||
column_families.size());
|
column_families.size());
|
||||||
port::Thread ingest_thread([&]() {
|
port::Thread ingest_thread([&]() {
|
||||||
Status s = GenerateAndAddExternalFiles(options, column_families, ifos, data,
|
ASSERT_NOK(GenerateAndAddExternalFiles(options, column_families, ifos, data,
|
||||||
-1, true, true_data);
|
-1, true, true_data));
|
||||||
ASSERT_NOK(s);
|
|
||||||
});
|
});
|
||||||
TEST_SYNC_POINT(
|
TEST_SYNC_POINT(
|
||||||
"ExternalSSTFileTest::IngestFilesIntoMultipleColumnFamilies_PrepareFail:"
|
"ExternalSSTFileTest::IngestFilesIntoMultipleColumnFamilies_PrepareFail:"
|
||||||
@ -2724,9 +2683,8 @@ TEST_P(ExternalSSTFileTest, IngestFilesIntoMultipleColumnFamilies_CommitFail) {
|
|||||||
std::vector<std::map<std::string, std::string>> true_data(
|
std::vector<std::map<std::string, std::string>> true_data(
|
||||||
column_families.size());
|
column_families.size());
|
||||||
port::Thread ingest_thread([&]() {
|
port::Thread ingest_thread([&]() {
|
||||||
Status s = GenerateAndAddExternalFiles(options, column_families, ifos, data,
|
ASSERT_NOK(GenerateAndAddExternalFiles(options, column_families, ifos, data,
|
||||||
-1, true, true_data);
|
-1, true, true_data));
|
||||||
ASSERT_NOK(s);
|
|
||||||
});
|
});
|
||||||
TEST_SYNC_POINT(
|
TEST_SYNC_POINT(
|
||||||
"ExternalSSTFileTest::IngestFilesIntoMultipleColumnFamilies_CommitFail:"
|
"ExternalSSTFileTest::IngestFilesIntoMultipleColumnFamilies_CommitFail:"
|
||||||
@ -2799,9 +2757,8 @@ TEST_P(ExternalSSTFileTest,
|
|||||||
std::vector<std::map<std::string, std::string>> true_data(
|
std::vector<std::map<std::string, std::string>> true_data(
|
||||||
column_families.size());
|
column_families.size());
|
||||||
port::Thread ingest_thread([&]() {
|
port::Thread ingest_thread([&]() {
|
||||||
Status s = GenerateAndAddExternalFiles(options, column_families, ifos, data,
|
ASSERT_NOK(GenerateAndAddExternalFiles(options, column_families, ifos, data,
|
||||||
-1, true, true_data);
|
-1, true, true_data));
|
||||||
ASSERT_NOK(s);
|
|
||||||
});
|
});
|
||||||
TEST_SYNC_POINT(
|
TEST_SYNC_POINT(
|
||||||
"ExternalSSTFileTest::IngestFilesIntoMultipleColumnFamilies_"
|
"ExternalSSTFileTest::IngestFilesIntoMultipleColumnFamilies_"
|
||||||
@ -2812,7 +2769,7 @@ TEST_P(ExternalSSTFileTest,
|
|||||||
"PartialManifestWriteFail:1");
|
"PartialManifestWriteFail:1");
|
||||||
ingest_thread.join();
|
ingest_thread.join();
|
||||||
|
|
||||||
fault_injection_env->DropUnsyncedFileData();
|
ASSERT_OK(fault_injection_env->DropUnsyncedFileData());
|
||||||
fault_injection_env->SetFilesystemActive(true);
|
fault_injection_env->SetFilesystemActive(true);
|
||||||
Close();
|
Close();
|
||||||
ReopenWithColumnFamilies({kDefaultColumnFamilyName, "pikachu", "eevee"},
|
ReopenWithColumnFamilies({kDefaultColumnFamilyName, "pikachu", "eevee"},
|
||||||
@ -2847,7 +2804,7 @@ TEST_P(ExternalSSTFileTest, IngestFilesTriggerFlushingWithTwoWriteQueue) {
|
|||||||
// sure that it won't enter the 2nd writer queue for the second time.
|
// sure that it won't enter the 2nd writer queue for the second time.
|
||||||
std::vector<std::pair<std::string, std::string>> data;
|
std::vector<std::pair<std::string, std::string>> data;
|
||||||
data.push_back(std::make_pair("1001", "v2"));
|
data.push_back(std::make_pair("1001", "v2"));
|
||||||
GenerateAndAddExternalFile(options, data);
|
ASSERT_OK(GenerateAndAddExternalFile(options, data, -1, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(ExternalSSTFileTest, DeltaEncodingWhileGlobalSeqnoPresent) {
|
TEST_P(ExternalSSTFileTest, DeltaEncodingWhileGlobalSeqnoPresent) {
|
||||||
|
@ -244,6 +244,12 @@ ForwardIterator::ForwardIterator(DBImpl* db, const ReadOptions& read_options,
|
|||||||
if (sv_) {
|
if (sv_) {
|
||||||
RebuildIterators(false);
|
RebuildIterators(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// immutable_status_ is a local aggregation of the
|
||||||
|
// status of the immutable Iterators.
|
||||||
|
// We have to PermitUncheckedError in case it is never
|
||||||
|
// used, otherwise it will fail ASSERT_STATUS_CHECKED.
|
||||||
|
immutable_status_.PermitUncheckedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
ForwardIterator::~ForwardIterator() {
|
ForwardIterator::~ForwardIterator() {
|
||||||
|
@ -80,8 +80,8 @@ std::shared_ptr<DB> OpenDb(const std::string& dbname, const bool ttl = false,
|
|||||||
options.create_if_missing = true;
|
options.create_if_missing = true;
|
||||||
options.merge_operator = std::make_shared<CountMergeOperator>();
|
options.merge_operator = std::make_shared<CountMergeOperator>();
|
||||||
options.max_successive_merges = max_successive_merges;
|
options.max_successive_merges = max_successive_merges;
|
||||||
|
EXPECT_OK(DestroyDB(dbname, Options()));
|
||||||
Status s;
|
Status s;
|
||||||
DestroyDB(dbname, Options());
|
|
||||||
// DBWithTTL is not supported in ROCKSDB_LITE
|
// DBWithTTL is not supported in ROCKSDB_LITE
|
||||||
#ifndef ROCKSDB_LITE
|
#ifndef ROCKSDB_LITE
|
||||||
if (ttl) {
|
if (ttl) {
|
||||||
@ -95,10 +95,8 @@ std::shared_ptr<DB> OpenDb(const std::string& dbname, const bool ttl = false,
|
|||||||
assert(!ttl);
|
assert(!ttl);
|
||||||
s = DB::Open(options, dbname, &db);
|
s = DB::Open(options, dbname, &db);
|
||||||
#endif // !ROCKSDB_LITE
|
#endif // !ROCKSDB_LITE
|
||||||
if (!s.ok()) {
|
EXPECT_OK(s);
|
||||||
std::cerr << s.ToString() << std::endl;
|
assert(s.ok());
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
return std::shared_ptr<DB>(db);
|
return std::shared_ptr<DB>(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,21 +256,25 @@ void testCounters(Counters& counters, DB* db, bool test_compaction) {
|
|||||||
|
|
||||||
counters.assert_set("a", 1);
|
counters.assert_set("a", 1);
|
||||||
|
|
||||||
if (test_compaction) db->Flush(o);
|
if (test_compaction) {
|
||||||
|
ASSERT_OK(db->Flush(o));
|
||||||
|
}
|
||||||
|
|
||||||
assert(counters.assert_get("a") == 1);
|
ASSERT_EQ(counters.assert_get("a"), 1);
|
||||||
|
|
||||||
counters.assert_remove("b");
|
counters.assert_remove("b");
|
||||||
|
|
||||||
// defaut value is 0 if non-existent
|
// defaut value is 0 if non-existent
|
||||||
assert(counters.assert_get("b") == 0);
|
ASSERT_EQ(counters.assert_get("b"), 0);
|
||||||
|
|
||||||
counters.assert_add("a", 2);
|
counters.assert_add("a", 2);
|
||||||
|
|
||||||
if (test_compaction) db->Flush(o);
|
if (test_compaction) {
|
||||||
|
ASSERT_OK(db->Flush(o));
|
||||||
|
}
|
||||||
|
|
||||||
// 1+2 = 3
|
// 1+2 = 3
|
||||||
assert(counters.assert_get("a")== 3);
|
ASSERT_EQ(counters.assert_get("a"), 3);
|
||||||
|
|
||||||
dumpDb(db);
|
dumpDb(db);
|
||||||
|
|
||||||
@ -282,19 +284,19 @@ void testCounters(Counters& counters, DB* db, bool test_compaction) {
|
|||||||
counters.assert_add("b", i);
|
counters.assert_add("b", i);
|
||||||
sum += i;
|
sum += i;
|
||||||
}
|
}
|
||||||
assert(counters.assert_get("b") == sum);
|
ASSERT_EQ(counters.assert_get("b"), sum);
|
||||||
|
|
||||||
dumpDb(db);
|
dumpDb(db);
|
||||||
|
|
||||||
if (test_compaction) {
|
if (test_compaction) {
|
||||||
db->Flush(o);
|
ASSERT_OK(db->Flush(o));
|
||||||
|
|
||||||
db->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
|
|
||||||
dumpDb(db);
|
dumpDb(db);
|
||||||
|
|
||||||
assert(counters.assert_get("a")== 3);
|
ASSERT_EQ(counters.assert_get("a"), 3);
|
||||||
assert(counters.assert_get("b") == sum);
|
ASSERT_EQ(counters.assert_get("b"), sum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,14 +402,14 @@ void testSuccessiveMerge(Counters& counters, size_t max_num_merges,
|
|||||||
sum += i;
|
sum += i;
|
||||||
|
|
||||||
if (i % (max_num_merges + 1) == 0) {
|
if (i % (max_num_merges + 1) == 0) {
|
||||||
assert(num_merge_operator_calls == max_num_merges + 1);
|
ASSERT_EQ(num_merge_operator_calls, max_num_merges + 1);
|
||||||
} else {
|
} else {
|
||||||
assert(num_merge_operator_calls == 0);
|
ASSERT_EQ(num_merge_operator_calls, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
resetNumMergeOperatorCalls();
|
resetNumMergeOperatorCalls();
|
||||||
assert(counters.assert_get("z") == sum);
|
ASSERT_EQ(counters.assert_get("z"), sum);
|
||||||
assert(num_merge_operator_calls == i % (max_num_merges + 1));
|
ASSERT_EQ(num_merge_operator_calls, i % (max_num_merges + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,8 +426,8 @@ void testPartialMerge(Counters* counters, DB* db, size_t max_merge,
|
|||||||
counters->assert_add("b", i);
|
counters->assert_add("b", i);
|
||||||
tmp_sum += i;
|
tmp_sum += i;
|
||||||
}
|
}
|
||||||
db->Flush(o);
|
ASSERT_OK(db->Flush(o));
|
||||||
db->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
ASSERT_EQ(tmp_sum, counters->assert_get("b"));
|
ASSERT_EQ(tmp_sum, counters->assert_get("b"));
|
||||||
if (count > max_merge) {
|
if (count > max_merge) {
|
||||||
// in this case, FullMerge should be called instead.
|
// in this case, FullMerge should be called instead.
|
||||||
@ -438,20 +440,20 @@ void testPartialMerge(Counters* counters, DB* db, size_t max_merge,
|
|||||||
// Test case 2: partial merge should not be called when a put is found.
|
// Test case 2: partial merge should not be called when a put is found.
|
||||||
resetNumPartialMergeCalls();
|
resetNumPartialMergeCalls();
|
||||||
tmp_sum = 0;
|
tmp_sum = 0;
|
||||||
db->Put(ROCKSDB_NAMESPACE::WriteOptions(), "c", "10");
|
ASSERT_OK(db->Put(ROCKSDB_NAMESPACE::WriteOptions(), "c", "10"));
|
||||||
for (size_t i = 1; i <= count; i++) {
|
for (size_t i = 1; i <= count; i++) {
|
||||||
counters->assert_add("c", i);
|
counters->assert_add("c", i);
|
||||||
tmp_sum += i;
|
tmp_sum += i;
|
||||||
}
|
}
|
||||||
db->Flush(o);
|
ASSERT_OK(db->Flush(o));
|
||||||
db->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
ASSERT_EQ(tmp_sum, counters->assert_get("c"));
|
ASSERT_EQ(tmp_sum, counters->assert_get("c"));
|
||||||
ASSERT_EQ(num_partial_merge_calls, 0U);
|
ASSERT_EQ(num_partial_merge_calls, 0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSingleBatchSuccessiveMerge(DB* db, size_t max_num_merges,
|
void testSingleBatchSuccessiveMerge(DB* db, size_t max_num_merges,
|
||||||
size_t num_merges) {
|
size_t num_merges) {
|
||||||
assert(num_merges > max_num_merges);
|
ASSERT_GT(num_merges, max_num_merges);
|
||||||
|
|
||||||
Slice key("BatchSuccessiveMerge");
|
Slice key("BatchSuccessiveMerge");
|
||||||
uint64_t merge_value = 1;
|
uint64_t merge_value = 1;
|
||||||
@ -462,15 +464,12 @@ void testSingleBatchSuccessiveMerge(DB* db, size_t max_num_merges,
|
|||||||
// Create the batch
|
// Create the batch
|
||||||
WriteBatch batch;
|
WriteBatch batch;
|
||||||
for (size_t i = 0; i < num_merges; ++i) {
|
for (size_t i = 0; i < num_merges; ++i) {
|
||||||
batch.Merge(key, merge_value_slice);
|
ASSERT_OK(batch.Merge(key, merge_value_slice));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply to memtable and count the number of merges
|
// Apply to memtable and count the number of merges
|
||||||
resetNumMergeOperatorCalls();
|
resetNumMergeOperatorCalls();
|
||||||
{
|
ASSERT_OK(db->Write(WriteOptions(), &batch));
|
||||||
Status s = db->Write(WriteOptions(), &batch);
|
|
||||||
assert(s.ok());
|
|
||||||
}
|
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
num_merge_operator_calls,
|
num_merge_operator_calls,
|
||||||
static_cast<size_t>(num_merges - (num_merges % (max_num_merges + 1))));
|
static_cast<size_t>(num_merges - (num_merges % (max_num_merges + 1))));
|
||||||
@ -478,10 +477,7 @@ void testSingleBatchSuccessiveMerge(DB* db, size_t max_num_merges,
|
|||||||
// Get the value
|
// Get the value
|
||||||
resetNumMergeOperatorCalls();
|
resetNumMergeOperatorCalls();
|
||||||
std::string get_value_str;
|
std::string get_value_str;
|
||||||
{
|
ASSERT_OK(db->Get(ReadOptions(), key, &get_value_str));
|
||||||
Status s = db->Get(ReadOptions(), key, &get_value_str);
|
|
||||||
assert(s.ok());
|
|
||||||
}
|
|
||||||
assert(get_value_str.size() == sizeof(uint64_t));
|
assert(get_value_str.size() == sizeof(uint64_t));
|
||||||
uint64_t get_value = DecodeFixed64(&get_value_str[0]);
|
uint64_t get_value = DecodeFixed64(&get_value_str[0]);
|
||||||
ASSERT_EQ(get_value, num_merges * merge_value);
|
ASSERT_EQ(get_value, num_merges * merge_value);
|
||||||
@ -505,7 +501,7 @@ void runTest(const std::string& dbname, const bool use_ttl = false) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DestroyDB(dbname, Options());
|
ASSERT_OK(DestroyDB(dbname, Options()));
|
||||||
|
|
||||||
{
|
{
|
||||||
size_t max_merge = 5;
|
size_t max_merge = 5;
|
||||||
@ -514,7 +510,8 @@ void runTest(const std::string& dbname, const bool use_ttl = false) {
|
|||||||
testCounters(counters, db.get(), use_compression);
|
testCounters(counters, db.get(), use_compression);
|
||||||
testSuccessiveMerge(counters, max_merge, max_merge * 2);
|
testSuccessiveMerge(counters, max_merge, max_merge * 2);
|
||||||
testSingleBatchSuccessiveMerge(db.get(), 5, 7);
|
testSingleBatchSuccessiveMerge(db.get(), 5, 7);
|
||||||
DestroyDB(dbname, Options());
|
ASSERT_OK(db->Close());
|
||||||
|
ASSERT_OK(DestroyDB(dbname, Options()));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -525,14 +522,16 @@ void runTest(const std::string& dbname, const bool use_ttl = false) {
|
|||||||
auto db = OpenDb(dbname, use_ttl, max_merge);
|
auto db = OpenDb(dbname, use_ttl, max_merge);
|
||||||
MergeBasedCounters counters(db, 0);
|
MergeBasedCounters counters(db, 0);
|
||||||
testPartialMerge(&counters, db.get(), max_merge, min_merge, count);
|
testPartialMerge(&counters, db.get(), max_merge, min_merge, count);
|
||||||
DestroyDB(dbname, Options());
|
ASSERT_OK(db->Close());
|
||||||
|
ASSERT_OK(DestroyDB(dbname, Options()));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto db = OpenDb(dbname, use_ttl, max_merge);
|
auto db = OpenDb(dbname, use_ttl, max_merge);
|
||||||
MergeBasedCounters counters(db, 0);
|
MergeBasedCounters counters(db, 0);
|
||||||
testPartialMerge(&counters, db.get(), max_merge, min_merge,
|
testPartialMerge(&counters, db.get(), max_merge, min_merge,
|
||||||
min_merge * 10);
|
min_merge * 10);
|
||||||
DestroyDB(dbname, Options());
|
ASSERT_OK(db->Close());
|
||||||
|
ASSERT_OK(DestroyDB(dbname, Options()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,15 +542,15 @@ void runTest(const std::string& dbname, const bool use_ttl = false) {
|
|||||||
counters.add("test-key", 1);
|
counters.add("test-key", 1);
|
||||||
counters.add("test-key", 1);
|
counters.add("test-key", 1);
|
||||||
counters.add("test-key", 1);
|
counters.add("test-key", 1);
|
||||||
db->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
DB* reopen_db;
|
DB* reopen_db;
|
||||||
ASSERT_OK(DB::Open(Options(), dbname, &reopen_db));
|
ASSERT_OK(DB::Open(Options(), dbname, &reopen_db));
|
||||||
std::string value;
|
std::string value;
|
||||||
ASSERT_TRUE(!(reopen_db->Get(ReadOptions(), "test-key", &value).ok()));
|
ASSERT_NOK(reopen_db->Get(ReadOptions(), "test-key", &value));
|
||||||
delete reopen_db;
|
delete reopen_db;
|
||||||
DestroyDB(dbname, Options());
|
ASSERT_OK(DestroyDB(dbname, Options()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Temporary remove this test
|
/* Temporary remove this test
|
||||||
@ -591,7 +590,7 @@ TEST_F(MergeTest, MergeWithCompactionAndFlush) {
|
|||||||
testCountersWithFlushAndCompaction(counters, db.get());
|
testCountersWithFlushAndCompaction(counters, db.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DestroyDB(dbname, Options());
|
ASSERT_OK(DestroyDB(dbname, Options()));
|
||||||
}
|
}
|
||||||
#endif // !ROCKSDB_LITE
|
#endif // !ROCKSDB_LITE
|
||||||
|
|
||||||
|
@ -221,11 +221,19 @@ Status RandomAccessFileReader::MultiRead(const IOOptions& opts,
|
|||||||
aligned_reqs.reserve(num_reqs);
|
aligned_reqs.reserve(num_reqs);
|
||||||
// Align and merge the read requests.
|
// Align and merge the read requests.
|
||||||
size_t alignment = file_->GetRequiredBufferAlignment();
|
size_t alignment = file_->GetRequiredBufferAlignment();
|
||||||
aligned_reqs.push_back(Align(read_reqs[0], alignment));
|
for (size_t i = 0; i < num_reqs; i++) {
|
||||||
for (size_t i = 1; i < num_reqs; i++) {
|
|
||||||
const auto& r = Align(read_reqs[i], alignment);
|
const auto& r = Align(read_reqs[i], alignment);
|
||||||
if (!TryMerge(&aligned_reqs.back(), r)) {
|
if (i == 0) {
|
||||||
|
// head
|
||||||
aligned_reqs.push_back(r);
|
aligned_reqs.push_back(r);
|
||||||
|
|
||||||
|
} else if (!TryMerge(&aligned_reqs.back(), r)) {
|
||||||
|
// head + n
|
||||||
|
aligned_reqs.push_back(r);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// unused
|
||||||
|
r.status.PermitUncheckedError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TEST_SYNC_POINT_CALLBACK("RandomAccessFileReader::MultiRead:AlignedReqs",
|
TEST_SYNC_POINT_CALLBACK("RandomAccessFileReader::MultiRead:AlignedReqs",
|
||||||
|
@ -145,6 +145,7 @@ TEST_F(RandomAccessFileReaderTest, MultiReadDirectIO) {
|
|||||||
// Reads the first page internally.
|
// Reads the first page internally.
|
||||||
ASSERT_EQ(aligned_reqs.size(), 1);
|
ASSERT_EQ(aligned_reqs.size(), 1);
|
||||||
const FSReadRequest& aligned_r = aligned_reqs[0];
|
const FSReadRequest& aligned_r = aligned_reqs[0];
|
||||||
|
ASSERT_OK(aligned_r.status);
|
||||||
ASSERT_EQ(aligned_r.offset, 0);
|
ASSERT_EQ(aligned_r.offset, 0);
|
||||||
ASSERT_EQ(aligned_r.len, page_size);
|
ASSERT_EQ(aligned_r.len, page_size);
|
||||||
}
|
}
|
||||||
@ -189,6 +190,7 @@ TEST_F(RandomAccessFileReaderTest, MultiReadDirectIO) {
|
|||||||
// Reads the first two pages in one request internally.
|
// Reads the first two pages in one request internally.
|
||||||
ASSERT_EQ(aligned_reqs.size(), 1);
|
ASSERT_EQ(aligned_reqs.size(), 1);
|
||||||
const FSReadRequest& aligned_r = aligned_reqs[0];
|
const FSReadRequest& aligned_r = aligned_reqs[0];
|
||||||
|
ASSERT_OK(aligned_r.status);
|
||||||
ASSERT_EQ(aligned_r.offset, 0);
|
ASSERT_EQ(aligned_r.offset, 0);
|
||||||
ASSERT_EQ(aligned_r.len, 2 * page_size);
|
ASSERT_EQ(aligned_r.len, 2 * page_size);
|
||||||
}
|
}
|
||||||
@ -233,6 +235,7 @@ TEST_F(RandomAccessFileReaderTest, MultiReadDirectIO) {
|
|||||||
// Reads the first 3 pages in one request internally.
|
// Reads the first 3 pages in one request internally.
|
||||||
ASSERT_EQ(aligned_reqs.size(), 1);
|
ASSERT_EQ(aligned_reqs.size(), 1);
|
||||||
const FSReadRequest& aligned_r = aligned_reqs[0];
|
const FSReadRequest& aligned_r = aligned_reqs[0];
|
||||||
|
ASSERT_OK(aligned_r.status);
|
||||||
ASSERT_EQ(aligned_r.offset, 0);
|
ASSERT_EQ(aligned_r.offset, 0);
|
||||||
ASSERT_EQ(aligned_r.len, 3 * page_size);
|
ASSERT_EQ(aligned_r.len, 3 * page_size);
|
||||||
}
|
}
|
||||||
@ -270,8 +273,10 @@ TEST_F(RandomAccessFileReaderTest, MultiReadDirectIO) {
|
|||||||
ASSERT_EQ(aligned_reqs.size(), 2);
|
ASSERT_EQ(aligned_reqs.size(), 2);
|
||||||
const FSReadRequest& aligned_r0 = aligned_reqs[0];
|
const FSReadRequest& aligned_r0 = aligned_reqs[0];
|
||||||
const FSReadRequest& aligned_r1 = aligned_reqs[1];
|
const FSReadRequest& aligned_r1 = aligned_reqs[1];
|
||||||
|
ASSERT_OK(aligned_r0.status);
|
||||||
ASSERT_EQ(aligned_r0.offset, 0);
|
ASSERT_EQ(aligned_r0.offset, 0);
|
||||||
ASSERT_EQ(aligned_r0.len, page_size);
|
ASSERT_EQ(aligned_r0.len, page_size);
|
||||||
|
ASSERT_OK(aligned_r1.status);
|
||||||
ASSERT_EQ(aligned_r1.offset, 2 * page_size);
|
ASSERT_EQ(aligned_r1.offset, 2 * page_size);
|
||||||
ASSERT_EQ(aligned_r1.len, page_size);
|
ASSERT_EQ(aligned_r1.len, page_size);
|
||||||
}
|
}
|
||||||
@ -287,8 +292,11 @@ TEST(FSReadRequest, Align) {
|
|||||||
r.offset = 2000;
|
r.offset = 2000;
|
||||||
r.len = 2000;
|
r.len = 2000;
|
||||||
r.scratch = nullptr;
|
r.scratch = nullptr;
|
||||||
|
ASSERT_OK(r.status);
|
||||||
|
|
||||||
FSReadRequest aligned_r = Align(r, 1024);
|
FSReadRequest aligned_r = Align(r, 1024);
|
||||||
|
ASSERT_OK(r.status);
|
||||||
|
ASSERT_OK(aligned_r.status);
|
||||||
ASSERT_EQ(aligned_r.offset, 1024);
|
ASSERT_EQ(aligned_r.offset, 1024);
|
||||||
ASSERT_EQ(aligned_r.len, 3072);
|
ASSERT_EQ(aligned_r.len, 3072);
|
||||||
}
|
}
|
||||||
@ -303,14 +311,20 @@ TEST(FSReadRequest, TryMerge) {
|
|||||||
dest.offset = 0;
|
dest.offset = 0;
|
||||||
dest.len = 10;
|
dest.len = 10;
|
||||||
dest.scratch = nullptr;
|
dest.scratch = nullptr;
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
|
||||||
FSReadRequest src;
|
FSReadRequest src;
|
||||||
src.offset = 15;
|
src.offset = 15;
|
||||||
src.len = 10;
|
src.len = 10;
|
||||||
src.scratch = nullptr;
|
src.scratch = nullptr;
|
||||||
|
ASSERT_OK(src.status);
|
||||||
|
|
||||||
if (reverse) std::swap(dest, src);
|
if (reverse) {
|
||||||
|
std::swap(dest, src);
|
||||||
|
}
|
||||||
ASSERT_FALSE(TryMerge(&dest, src));
|
ASSERT_FALSE(TryMerge(&dest, src));
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
ASSERT_OK(src.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -320,16 +334,22 @@ TEST(FSReadRequest, TryMerge) {
|
|||||||
dest.offset = 0;
|
dest.offset = 0;
|
||||||
dest.len = 10;
|
dest.len = 10;
|
||||||
dest.scratch = nullptr;
|
dest.scratch = nullptr;
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
|
||||||
FSReadRequest src;
|
FSReadRequest src;
|
||||||
src.offset = 10;
|
src.offset = 10;
|
||||||
src.len = 10;
|
src.len = 10;
|
||||||
src.scratch = nullptr;
|
src.scratch = nullptr;
|
||||||
|
ASSERT_OK(src.status);
|
||||||
|
|
||||||
if (reverse) std::swap(dest, src);
|
if (reverse) {
|
||||||
|
std::swap(dest, src);
|
||||||
|
}
|
||||||
ASSERT_TRUE(TryMerge(&dest, src));
|
ASSERT_TRUE(TryMerge(&dest, src));
|
||||||
ASSERT_EQ(dest.offset, 0);
|
ASSERT_EQ(dest.offset, 0);
|
||||||
ASSERT_EQ(dest.len, 20);
|
ASSERT_EQ(dest.len, 20);
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
ASSERT_OK(src.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -339,16 +359,22 @@ TEST(FSReadRequest, TryMerge) {
|
|||||||
dest.offset = 0;
|
dest.offset = 0;
|
||||||
dest.len = 10;
|
dest.len = 10;
|
||||||
dest.scratch = nullptr;
|
dest.scratch = nullptr;
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
|
||||||
FSReadRequest src;
|
FSReadRequest src;
|
||||||
src.offset = 5;
|
src.offset = 5;
|
||||||
src.len = 10;
|
src.len = 10;
|
||||||
src.scratch = nullptr;
|
src.scratch = nullptr;
|
||||||
|
ASSERT_OK(src.status);
|
||||||
|
|
||||||
if (reverse) std::swap(dest, src);
|
if (reverse) {
|
||||||
|
std::swap(dest, src);
|
||||||
|
}
|
||||||
ASSERT_TRUE(TryMerge(&dest, src));
|
ASSERT_TRUE(TryMerge(&dest, src));
|
||||||
ASSERT_EQ(dest.offset, 0);
|
ASSERT_EQ(dest.offset, 0);
|
||||||
ASSERT_EQ(dest.len, 15);
|
ASSERT_EQ(dest.len, 15);
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
ASSERT_OK(src.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -358,16 +384,22 @@ TEST(FSReadRequest, TryMerge) {
|
|||||||
dest.offset = 0;
|
dest.offset = 0;
|
||||||
dest.len = 10;
|
dest.len = 10;
|
||||||
dest.scratch = nullptr;
|
dest.scratch = nullptr;
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
|
||||||
FSReadRequest src;
|
FSReadRequest src;
|
||||||
src.offset = 5;
|
src.offset = 5;
|
||||||
src.len = 5;
|
src.len = 5;
|
||||||
src.scratch = nullptr;
|
src.scratch = nullptr;
|
||||||
|
ASSERT_OK(src.status);
|
||||||
|
|
||||||
if (reverse) std::swap(dest, src);
|
if (reverse) {
|
||||||
|
std::swap(dest, src);
|
||||||
|
}
|
||||||
ASSERT_TRUE(TryMerge(&dest, src));
|
ASSERT_TRUE(TryMerge(&dest, src));
|
||||||
ASSERT_EQ(dest.offset, 0);
|
ASSERT_EQ(dest.offset, 0);
|
||||||
ASSERT_EQ(dest.len, 10);
|
ASSERT_EQ(dest.len, 10);
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
ASSERT_OK(src.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -377,16 +409,20 @@ TEST(FSReadRequest, TryMerge) {
|
|||||||
dest.offset = 0;
|
dest.offset = 0;
|
||||||
dest.len = 10;
|
dest.len = 10;
|
||||||
dest.scratch = nullptr;
|
dest.scratch = nullptr;
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
|
||||||
FSReadRequest src;
|
FSReadRequest src;
|
||||||
src.offset = 5;
|
src.offset = 5;
|
||||||
src.len = 1;
|
src.len = 1;
|
||||||
src.scratch = nullptr;
|
src.scratch = nullptr;
|
||||||
|
ASSERT_OK(src.status);
|
||||||
|
|
||||||
if (reverse) std::swap(dest, src);
|
if (reverse) std::swap(dest, src);
|
||||||
ASSERT_TRUE(TryMerge(&dest, src));
|
ASSERT_TRUE(TryMerge(&dest, src));
|
||||||
ASSERT_EQ(dest.offset, 0);
|
ASSERT_EQ(dest.offset, 0);
|
||||||
ASSERT_EQ(dest.len, 10);
|
ASSERT_EQ(dest.len, 10);
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
ASSERT_OK(src.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -396,16 +432,20 @@ TEST(FSReadRequest, TryMerge) {
|
|||||||
dest.offset = 0;
|
dest.offset = 0;
|
||||||
dest.len = 10;
|
dest.len = 10;
|
||||||
dest.scratch = nullptr;
|
dest.scratch = nullptr;
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
|
||||||
FSReadRequest src;
|
FSReadRequest src;
|
||||||
src.offset = 0;
|
src.offset = 0;
|
||||||
src.len = 10;
|
src.len = 10;
|
||||||
src.scratch = nullptr;
|
src.scratch = nullptr;
|
||||||
|
ASSERT_OK(src.status);
|
||||||
|
|
||||||
if (reverse) std::swap(dest, src);
|
if (reverse) std::swap(dest, src);
|
||||||
ASSERT_TRUE(TryMerge(&dest, src));
|
ASSERT_TRUE(TryMerge(&dest, src));
|
||||||
ASSERT_EQ(dest.offset, 0);
|
ASSERT_EQ(dest.offset, 0);
|
||||||
ASSERT_EQ(dest.len, 10);
|
ASSERT_EQ(dest.len, 10);
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
ASSERT_OK(src.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -415,16 +455,20 @@ TEST(FSReadRequest, TryMerge) {
|
|||||||
dest.offset = 0;
|
dest.offset = 0;
|
||||||
dest.len = 10;
|
dest.len = 10;
|
||||||
dest.scratch = nullptr;
|
dest.scratch = nullptr;
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
|
||||||
FSReadRequest src;
|
FSReadRequest src;
|
||||||
src.offset = 0;
|
src.offset = 0;
|
||||||
src.len = 5;
|
src.len = 5;
|
||||||
src.scratch = nullptr;
|
src.scratch = nullptr;
|
||||||
|
ASSERT_OK(src.status);
|
||||||
|
|
||||||
if (reverse) std::swap(dest, src);
|
if (reverse) std::swap(dest, src);
|
||||||
ASSERT_TRUE(TryMerge(&dest, src));
|
ASSERT_TRUE(TryMerge(&dest, src));
|
||||||
ASSERT_EQ(dest.offset, 0);
|
ASSERT_EQ(dest.offset, 0);
|
||||||
ASSERT_EQ(dest.len, 10);
|
ASSERT_EQ(dest.len, 10);
|
||||||
|
ASSERT_OK(dest.status);
|
||||||
|
ASSERT_OK(src.status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,8 @@ class StringAppendOperatorTest : public testing::Test,
|
|||||||
public ::testing::WithParamInterface<bool> {
|
public ::testing::WithParamInterface<bool> {
|
||||||
public:
|
public:
|
||||||
StringAppendOperatorTest() {
|
StringAppendOperatorTest() {
|
||||||
DestroyDB(kDbName, Options()); // Start each test with a fresh DB
|
DestroyDB(kDbName, Options())
|
||||||
|
.PermitUncheckedError(); // Start each test with a fresh DB
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
@ -253,9 +254,7 @@ TEST_P(StringAppendOperatorTest, SimpleTest) {
|
|||||||
slists.Append("k1", "v3");
|
slists.Append("k1", "v3");
|
||||||
|
|
||||||
std::string res;
|
std::string res;
|
||||||
bool status = slists.Get("k1", &res);
|
ASSERT_TRUE(slists.Get("k1", &res));
|
||||||
|
|
||||||
ASSERT_TRUE(status);
|
|
||||||
ASSERT_EQ(res, "v1,v2,v3");
|
ASSERT_EQ(res, "v1,v2,v3");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +267,7 @@ TEST_P(StringAppendOperatorTest, SimpleDelimiterTest) {
|
|||||||
slists.Append("k1", "v3");
|
slists.Append("k1", "v3");
|
||||||
|
|
||||||
std::string res;
|
std::string res;
|
||||||
slists.Get("k1", &res);
|
ASSERT_TRUE(slists.Get("k1", &res));
|
||||||
ASSERT_EQ(res, "v1|v2|v3");
|
ASSERT_EQ(res, "v1|v2|v3");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +278,7 @@ TEST_P(StringAppendOperatorTest, OneValueNoDelimiterTest) {
|
|||||||
slists.Append("random_key", "single_val");
|
slists.Append("random_key", "single_val");
|
||||||
|
|
||||||
std::string res;
|
std::string res;
|
||||||
slists.Get("random_key", &res);
|
ASSERT_TRUE(slists.Get("random_key", &res));
|
||||||
ASSERT_EQ(res, "single_val");
|
ASSERT_EQ(res, "single_val");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,9 +423,9 @@ TEST_P(StringAppendOperatorTest, PersistentVariousKeys) {
|
|||||||
slists.Append("c", "asdasd");
|
slists.Append("c", "asdasd");
|
||||||
|
|
||||||
std::string a, b, c;
|
std::string a, b, c;
|
||||||
slists.Get("a", &a);
|
ASSERT_TRUE(slists.Get("a", &a));
|
||||||
slists.Get("b", &b);
|
ASSERT_TRUE(slists.Get("b", &b));
|
||||||
slists.Get("c", &c);
|
ASSERT_TRUE(slists.Get("c", &c));
|
||||||
|
|
||||||
ASSERT_EQ(a, "x\nt\nr");
|
ASSERT_EQ(a, "x\nt\nr");
|
||||||
ASSERT_EQ(b, "y\n2");
|
ASSERT_EQ(b, "y\n2");
|
||||||
@ -450,9 +449,9 @@ TEST_P(StringAppendOperatorTest, PersistentVariousKeys) {
|
|||||||
// The most recent changes should be in memory (MemTable)
|
// The most recent changes should be in memory (MemTable)
|
||||||
// Hence, this will test both Get() paths.
|
// Hence, this will test both Get() paths.
|
||||||
std::string a, b, c;
|
std::string a, b, c;
|
||||||
slists.Get("a", &a);
|
ASSERT_TRUE(slists.Get("a", &a));
|
||||||
slists.Get("b", &b);
|
ASSERT_TRUE(slists.Get("b", &b));
|
||||||
slists.Get("c", &c);
|
ASSERT_TRUE(slists.Get("c", &c));
|
||||||
|
|
||||||
ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
|
ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
|
||||||
ASSERT_EQ(b, "y\n2\ndf\nl;");
|
ASSERT_EQ(b, "y\n2\ndf\nl;");
|
||||||
@ -466,9 +465,9 @@ TEST_P(StringAppendOperatorTest, PersistentVariousKeys) {
|
|||||||
|
|
||||||
// All changes should be on disk. This will test VersionSet Get()
|
// All changes should be on disk. This will test VersionSet Get()
|
||||||
std::string a, b, c;
|
std::string a, b, c;
|
||||||
slists.Get("a", &a);
|
ASSERT_TRUE(slists.Get("a", &a));
|
||||||
slists.Get("b", &b);
|
ASSERT_TRUE(slists.Get("b", &b));
|
||||||
slists.Get("c", &c);
|
ASSERT_TRUE(slists.Get("c", &c));
|
||||||
|
|
||||||
ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
|
ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
|
||||||
ASSERT_EQ(b, "y\n2\ndf\nl;");
|
ASSERT_EQ(b, "y\n2\ndf\nl;");
|
||||||
@ -482,41 +481,34 @@ TEST_P(StringAppendOperatorTest, PersistentFlushAndCompaction) {
|
|||||||
auto db = OpenDb('\n');
|
auto db = OpenDb('\n');
|
||||||
StringLists slists(db);
|
StringLists slists(db);
|
||||||
std::string a, b, c;
|
std::string a, b, c;
|
||||||
bool success;
|
|
||||||
|
|
||||||
// Append, Flush, Get
|
// Append, Flush, Get
|
||||||
slists.Append("c", "asdasd");
|
slists.Append("c", "asdasd");
|
||||||
db->Flush(ROCKSDB_NAMESPACE::FlushOptions());
|
ASSERT_OK(db->Flush(ROCKSDB_NAMESPACE::FlushOptions()));
|
||||||
success = slists.Get("c", &c);
|
ASSERT_TRUE(slists.Get("c", &c));
|
||||||
ASSERT_TRUE(success);
|
|
||||||
ASSERT_EQ(c, "asdasd");
|
ASSERT_EQ(c, "asdasd");
|
||||||
|
|
||||||
// Append, Flush, Append, Get
|
// Append, Flush, Append, Get
|
||||||
slists.Append("a", "x");
|
slists.Append("a", "x");
|
||||||
slists.Append("b", "y");
|
slists.Append("b", "y");
|
||||||
db->Flush(ROCKSDB_NAMESPACE::FlushOptions());
|
ASSERT_OK(db->Flush(ROCKSDB_NAMESPACE::FlushOptions()));
|
||||||
slists.Append("a", "t");
|
slists.Append("a", "t");
|
||||||
slists.Append("a", "r");
|
slists.Append("a", "r");
|
||||||
slists.Append("b", "2");
|
slists.Append("b", "2");
|
||||||
|
|
||||||
success = slists.Get("a", &a);
|
ASSERT_TRUE(slists.Get("a", &a));
|
||||||
assert(success == true);
|
|
||||||
ASSERT_EQ(a, "x\nt\nr");
|
ASSERT_EQ(a, "x\nt\nr");
|
||||||
|
|
||||||
success = slists.Get("b", &b);
|
ASSERT_TRUE(slists.Get("b", &b));
|
||||||
assert(success == true);
|
|
||||||
ASSERT_EQ(b, "y\n2");
|
ASSERT_EQ(b, "y\n2");
|
||||||
|
|
||||||
// Append, Get
|
// Append, Get
|
||||||
success = slists.Append("c", "asdasd");
|
ASSERT_TRUE(slists.Append("c", "asdasd"));
|
||||||
assert(success);
|
ASSERT_TRUE(slists.Append("b", "monkey"));
|
||||||
success = slists.Append("b", "monkey");
|
|
||||||
assert(success);
|
|
||||||
|
|
||||||
// I omit the "assert(success)" checks here.
|
ASSERT_TRUE(slists.Get("a", &a));
|
||||||
slists.Get("a", &a);
|
ASSERT_TRUE(slists.Get("b", &b));
|
||||||
slists.Get("b", &b);
|
ASSERT_TRUE(slists.Get("c", &c));
|
||||||
slists.Get("c", &c);
|
|
||||||
|
|
||||||
ASSERT_EQ(a, "x\nt\nr");
|
ASSERT_EQ(a, "x\nt\nr");
|
||||||
ASSERT_EQ(b, "y\n2\nmonkey");
|
ASSERT_EQ(b, "y\n2\nmonkey");
|
||||||
@ -530,17 +522,17 @@ TEST_P(StringAppendOperatorTest, PersistentFlushAndCompaction) {
|
|||||||
std::string a, b, c;
|
std::string a, b, c;
|
||||||
|
|
||||||
// Get (Quick check for persistence of previous database)
|
// Get (Quick check for persistence of previous database)
|
||||||
slists.Get("a", &a);
|
ASSERT_TRUE(slists.Get("a", &a));
|
||||||
ASSERT_EQ(a, "x\nt\nr");
|
ASSERT_EQ(a, "x\nt\nr");
|
||||||
|
|
||||||
//Append, Compact, Get
|
//Append, Compact, Get
|
||||||
slists.Append("c", "bbnagnagsx");
|
slists.Append("c", "bbnagnagsx");
|
||||||
slists.Append("a", "sa");
|
slists.Append("a", "sa");
|
||||||
slists.Append("b", "df");
|
slists.Append("b", "df");
|
||||||
db->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
slists.Get("a", &a);
|
ASSERT_TRUE(slists.Get("a", &a));
|
||||||
slists.Get("b", &b);
|
ASSERT_TRUE(slists.Get("b", &b));
|
||||||
slists.Get("c", &c);
|
ASSERT_TRUE(slists.Get("c", &c));
|
||||||
ASSERT_EQ(a, "x\nt\nr\nsa");
|
ASSERT_EQ(a, "x\nt\nr\nsa");
|
||||||
ASSERT_EQ(b, "y\n2\nmonkey\ndf");
|
ASSERT_EQ(b, "y\n2\nmonkey\ndf");
|
||||||
ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx");
|
ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx");
|
||||||
@ -550,24 +542,24 @@ TEST_P(StringAppendOperatorTest, PersistentFlushAndCompaction) {
|
|||||||
slists.Append("a", "jk");
|
slists.Append("a", "jk");
|
||||||
slists.Append("b", "l;");
|
slists.Append("b", "l;");
|
||||||
slists.Append("c", "rogosh");
|
slists.Append("c", "rogosh");
|
||||||
slists.Get("a", &a);
|
ASSERT_TRUE(slists.Get("a", &a));
|
||||||
slists.Get("b", &b);
|
ASSERT_TRUE(slists.Get("b", &b));
|
||||||
slists.Get("c", &c);
|
ASSERT_TRUE(slists.Get("c", &c));
|
||||||
ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
|
ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
|
||||||
ASSERT_EQ(b, "y\n2\nmonkey\ndf\nl;");
|
ASSERT_EQ(b, "y\n2\nmonkey\ndf\nl;");
|
||||||
ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx\nrogosh");
|
ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx\nrogosh");
|
||||||
|
|
||||||
// Compact, Get
|
// Compact, Get
|
||||||
db->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
|
ASSERT_EQ(a, "x\nt\nr\nsa\ngh\njk");
|
||||||
ASSERT_EQ(b, "y\n2\nmonkey\ndf\nl;");
|
ASSERT_EQ(b, "y\n2\nmonkey\ndf\nl;");
|
||||||
ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx\nrogosh");
|
ASSERT_EQ(c, "asdasd\nasdasd\nbbnagnagsx\nrogosh");
|
||||||
|
|
||||||
// Append, Flush, Compact, Get
|
// Append, Flush, Compact, Get
|
||||||
slists.Append("b", "afcg");
|
slists.Append("b", "afcg");
|
||||||
db->Flush(ROCKSDB_NAMESPACE::FlushOptions());
|
ASSERT_OK(db->Flush(ROCKSDB_NAMESPACE::FlushOptions()));
|
||||||
db->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
ASSERT_OK(db->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||||
slists.Get("b", &b);
|
ASSERT_TRUE(slists.Get("b", &b));
|
||||||
ASSERT_EQ(b, "y\n2\nmonkey\ndf\nl;\nafcg");
|
ASSERT_EQ(b, "y\n2\nmonkey\ndf\nl;\nafcg");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -581,17 +573,16 @@ TEST_P(StringAppendOperatorTest, SimpleTestNullDelimiter) {
|
|||||||
slists.Append("k1", "v3");
|
slists.Append("k1", "v3");
|
||||||
|
|
||||||
std::string res;
|
std::string res;
|
||||||
bool status = slists.Get("k1", &res);
|
ASSERT_TRUE(slists.Get("k1", &res));
|
||||||
ASSERT_TRUE(status);
|
|
||||||
|
|
||||||
// Construct the desired string. Default constructor doesn't like '\0' chars.
|
// Construct the desired string. Default constructor doesn't like '\0' chars.
|
||||||
std::string checker("v1,v2,v3"); // Verify that the string is right size.
|
std::string checker("v1,v2,v3"); // Verify that the string is right size.
|
||||||
checker[2] = '\0'; // Use null delimiter instead of comma.
|
checker[2] = '\0'; // Use null delimiter instead of comma.
|
||||||
checker[5] = '\0';
|
checker[5] = '\0';
|
||||||
assert(checker.size() == 8); // Verify it is still the correct size
|
ASSERT_EQ(checker.size(), 8); // Verify it is still the correct size
|
||||||
|
|
||||||
// Check that the rocksdb result string matches the desired string
|
// Check that the rocksdb result string matches the desired string
|
||||||
assert(res.size() == checker.size());
|
ASSERT_EQ(res.size(), checker.size());
|
||||||
ASSERT_EQ(res, checker);
|
ASSERT_EQ(res, checker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ DBWithTTLImpl::DBWithTTLImpl(DB* db) : DBWithTTL(db), closed_(false) {}
|
|||||||
|
|
||||||
DBWithTTLImpl::~DBWithTTLImpl() {
|
DBWithTTLImpl::~DBWithTTLImpl() {
|
||||||
if (!closed_) {
|
if (!closed_) {
|
||||||
Close();
|
Close().PermitUncheckedError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,31 +185,32 @@ bool DBWithTTLImpl::IsStale(const Slice& value, int32_t ttl, Env* env) {
|
|||||||
|
|
||||||
// Strips the TS from the end of the slice
|
// Strips the TS from the end of the slice
|
||||||
Status DBWithTTLImpl::StripTS(PinnableSlice* pinnable_val) {
|
Status DBWithTTLImpl::StripTS(PinnableSlice* pinnable_val) {
|
||||||
Status st;
|
|
||||||
if (pinnable_val->size() < kTSLength) {
|
if (pinnable_val->size() < kTSLength) {
|
||||||
return Status::Corruption("Bad timestamp in key-value");
|
return Status::Corruption("Bad timestamp in key-value");
|
||||||
}
|
}
|
||||||
// Erasing characters which hold the TS
|
// Erasing characters which hold the TS
|
||||||
pinnable_val->remove_suffix(kTSLength);
|
pinnable_val->remove_suffix(kTSLength);
|
||||||
return st;
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strips the TS from the end of the string
|
// Strips the TS from the end of the string
|
||||||
Status DBWithTTLImpl::StripTS(std::string* str) {
|
Status DBWithTTLImpl::StripTS(std::string* str) {
|
||||||
Status st;
|
|
||||||
if (str->length() < kTSLength) {
|
if (str->length() < kTSLength) {
|
||||||
return Status::Corruption("Bad timestamp in key-value");
|
return Status::Corruption("Bad timestamp in key-value");
|
||||||
}
|
}
|
||||||
// Erasing characters which hold the TS
|
// Erasing characters which hold the TS
|
||||||
str->erase(str->length() - kTSLength, kTSLength);
|
str->erase(str->length() - kTSLength, kTSLength);
|
||||||
return st;
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status DBWithTTLImpl::Put(const WriteOptions& options,
|
Status DBWithTTLImpl::Put(const WriteOptions& options,
|
||||||
ColumnFamilyHandle* column_family, const Slice& key,
|
ColumnFamilyHandle* column_family, const Slice& key,
|
||||||
const Slice& val) {
|
const Slice& val) {
|
||||||
WriteBatch batch;
|
WriteBatch batch;
|
||||||
batch.Put(column_family, key, val);
|
Status st = batch.Put(column_family, key, val);
|
||||||
|
if (!st.ok()) {
|
||||||
|
return st;
|
||||||
|
}
|
||||||
return Write(options, &batch);
|
return Write(options, &batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,7 +263,10 @@ Status DBWithTTLImpl::Merge(const WriteOptions& options,
|
|||||||
ColumnFamilyHandle* column_family, const Slice& key,
|
ColumnFamilyHandle* column_family, const Slice& key,
|
||||||
const Slice& value) {
|
const Slice& value) {
|
||||||
WriteBatch batch;
|
WriteBatch batch;
|
||||||
batch.Merge(column_family, key, value);
|
Status st = batch.Merge(column_family, key, value);
|
||||||
|
if (!st.ok()) {
|
||||||
|
return st;
|
||||||
|
}
|
||||||
return Write(options, &batch);
|
return Write(options, &batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,34 +275,28 @@ Status DBWithTTLImpl::Write(const WriteOptions& opts, WriteBatch* updates) {
|
|||||||
public:
|
public:
|
||||||
explicit Handler(Env* env) : env_(env) {}
|
explicit Handler(Env* env) : env_(env) {}
|
||||||
WriteBatch updates_ttl;
|
WriteBatch updates_ttl;
|
||||||
Status batch_rewrite_status;
|
|
||||||
Status PutCF(uint32_t column_family_id, const Slice& key,
|
Status PutCF(uint32_t column_family_id, const Slice& key,
|
||||||
const Slice& value) override {
|
const Slice& value) override {
|
||||||
std::string value_with_ts;
|
std::string value_with_ts;
|
||||||
Status st = AppendTS(value, &value_with_ts, env_);
|
Status st = AppendTS(value, &value_with_ts, env_);
|
||||||
if (!st.ok()) {
|
if (!st.ok()) {
|
||||||
batch_rewrite_status = st;
|
return st;
|
||||||
} else {
|
|
||||||
WriteBatchInternal::Put(&updates_ttl, column_family_id, key,
|
|
||||||
value_with_ts);
|
|
||||||
}
|
}
|
||||||
return Status::OK();
|
return WriteBatchInternal::Put(&updates_ttl, column_family_id, key,
|
||||||
|
value_with_ts);
|
||||||
}
|
}
|
||||||
Status MergeCF(uint32_t column_family_id, const Slice& key,
|
Status MergeCF(uint32_t column_family_id, const Slice& key,
|
||||||
const Slice& value) override {
|
const Slice& value) override {
|
||||||
std::string value_with_ts;
|
std::string value_with_ts;
|
||||||
Status st = AppendTS(value, &value_with_ts, env_);
|
Status st = AppendTS(value, &value_with_ts, env_);
|
||||||
if (!st.ok()) {
|
if (!st.ok()) {
|
||||||
batch_rewrite_status = st;
|
return st;
|
||||||
} else {
|
}
|
||||||
WriteBatchInternal::Merge(&updates_ttl, column_family_id, key,
|
return WriteBatchInternal::Merge(&updates_ttl, column_family_id, key,
|
||||||
value_with_ts);
|
value_with_ts);
|
||||||
}
|
}
|
||||||
return Status::OK();
|
|
||||||
}
|
|
||||||
Status DeleteCF(uint32_t column_family_id, const Slice& key) override {
|
Status DeleteCF(uint32_t column_family_id, const Slice& key) override {
|
||||||
WriteBatchInternal::Delete(&updates_ttl, column_family_id, key);
|
return WriteBatchInternal::Delete(&updates_ttl, column_family_id, key);
|
||||||
return Status::OK();
|
|
||||||
}
|
}
|
||||||
void LogData(const Slice& blob) override { updates_ttl.PutLogData(blob); }
|
void LogData(const Slice& blob) override { updates_ttl.PutLogData(blob); }
|
||||||
|
|
||||||
@ -306,9 +304,9 @@ Status DBWithTTLImpl::Write(const WriteOptions& opts, WriteBatch* updates) {
|
|||||||
Env* env_;
|
Env* env_;
|
||||||
};
|
};
|
||||||
Handler handler(GetEnv());
|
Handler handler(GetEnv());
|
||||||
updates->Iterate(&handler);
|
Status st = updates->Iterate(&handler);
|
||||||
if (!handler.batch_rewrite_status.ok()) {
|
if (!st.ok()) {
|
||||||
return handler.batch_rewrite_status;
|
return st;
|
||||||
} else {
|
} else {
|
||||||
return db_->Write(opts, &(handler.updates_ttl));
|
return db_->Write(opts, &(handler.updates_ttl));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user