|
@ -96,35 +96,35 @@ class TestEnv : public EnvWrapper { |
|
|
// Special Env used to delay background operations
|
|
|
// Special Env used to delay background operations
|
|
|
class SpecialEnv : public EnvWrapper { |
|
|
class SpecialEnv : public EnvWrapper { |
|
|
public: |
|
|
public: |
|
|
// sstable/log Sync() calls are blocked while this pointer is non-NULL.
|
|
|
|
|
|
|
|
|
// sstable/log Sync() calls are blocked while this pointer is non-null.
|
|
|
port::AtomicPointer delay_data_sync_; |
|
|
port::AtomicPointer delay_data_sync_; |
|
|
|
|
|
|
|
|
// sstable/log Sync() calls return an error.
|
|
|
// sstable/log Sync() calls return an error.
|
|
|
port::AtomicPointer data_sync_error_; |
|
|
port::AtomicPointer data_sync_error_; |
|
|
|
|
|
|
|
|
// Simulate no-space errors while this pointer is non-NULL.
|
|
|
|
|
|
|
|
|
// Simulate no-space errors while this pointer is non-null.
|
|
|
port::AtomicPointer no_space_; |
|
|
port::AtomicPointer no_space_; |
|
|
|
|
|
|
|
|
// Simulate non-writable file system while this pointer is non-NULL
|
|
|
|
|
|
|
|
|
// Simulate non-writable file system while this pointer is non-null.
|
|
|
port::AtomicPointer non_writable_; |
|
|
port::AtomicPointer non_writable_; |
|
|
|
|
|
|
|
|
// Force sync of manifest files to fail while this pointer is non-NULL
|
|
|
|
|
|
|
|
|
// Force sync of manifest files to fail while this pointer is non-null.
|
|
|
port::AtomicPointer manifest_sync_error_; |
|
|
port::AtomicPointer manifest_sync_error_; |
|
|
|
|
|
|
|
|
// Force write to manifest files to fail while this pointer is non-NULL
|
|
|
|
|
|
|
|
|
// Force write to manifest files to fail while this pointer is non-null.
|
|
|
port::AtomicPointer manifest_write_error_; |
|
|
port::AtomicPointer manifest_write_error_; |
|
|
|
|
|
|
|
|
bool count_random_reads_; |
|
|
bool count_random_reads_; |
|
|
AtomicCounter random_read_counter_; |
|
|
AtomicCounter random_read_counter_; |
|
|
|
|
|
|
|
|
explicit SpecialEnv(Env* base) : EnvWrapper(base) { |
|
|
explicit SpecialEnv(Env* base) : EnvWrapper(base) { |
|
|
delay_data_sync_.Release_Store(NULL); |
|
|
|
|
|
data_sync_error_.Release_Store(NULL); |
|
|
|
|
|
no_space_.Release_Store(NULL); |
|
|
|
|
|
non_writable_.Release_Store(NULL); |
|
|
|
|
|
|
|
|
delay_data_sync_.Release_Store(nullptr); |
|
|
|
|
|
data_sync_error_.Release_Store(nullptr); |
|
|
|
|
|
no_space_.Release_Store(nullptr); |
|
|
|
|
|
non_writable_.Release_Store(nullptr); |
|
|
count_random_reads_ = false; |
|
|
count_random_reads_ = false; |
|
|
manifest_sync_error_.Release_Store(NULL); |
|
|
|
|
|
manifest_write_error_.Release_Store(NULL); |
|
|
|
|
|
|
|
|
manifest_sync_error_.Release_Store(nullptr); |
|
|
|
|
|
manifest_write_error_.Release_Store(nullptr); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Status NewWritableFile(const std::string& f, WritableFile** r) { |
|
|
Status NewWritableFile(const std::string& f, WritableFile** r) { |
|
@ -140,7 +140,7 @@ class SpecialEnv : public EnvWrapper { |
|
|
} |
|
|
} |
|
|
~DataFile() { delete base_; } |
|
|
~DataFile() { delete base_; } |
|
|
Status Append(const Slice& data) { |
|
|
Status Append(const Slice& data) { |
|
|
if (env_->no_space_.Acquire_Load() != NULL) { |
|
|
|
|
|
|
|
|
if (env_->no_space_.Acquire_Load() != nullptr) { |
|
|
// Drop writes on the floor
|
|
|
// Drop writes on the floor
|
|
|
return Status::OK(); |
|
|
return Status::OK(); |
|
|
} else { |
|
|
} else { |
|
@ -150,10 +150,10 @@ class SpecialEnv : public EnvWrapper { |
|
|
Status Close() { return base_->Close(); } |
|
|
Status Close() { return base_->Close(); } |
|
|
Status Flush() { return base_->Flush(); } |
|
|
Status Flush() { return base_->Flush(); } |
|
|
Status Sync() { |
|
|
Status Sync() { |
|
|
if (env_->data_sync_error_.Acquire_Load() != NULL) { |
|
|
|
|
|
|
|
|
if (env_->data_sync_error_.Acquire_Load() != nullptr) { |
|
|
return Status::IOError("simulated data sync error"); |
|
|
return Status::IOError("simulated data sync error"); |
|
|
} |
|
|
} |
|
|
while (env_->delay_data_sync_.Acquire_Load() != NULL) { |
|
|
|
|
|
|
|
|
while (env_->delay_data_sync_.Acquire_Load() != nullptr) { |
|
|
DelayMilliseconds(100); |
|
|
DelayMilliseconds(100); |
|
|
} |
|
|
} |
|
|
return base_->Sync(); |
|
|
return base_->Sync(); |
|
@ -167,7 +167,7 @@ class SpecialEnv : public EnvWrapper { |
|
|
ManifestFile(SpecialEnv* env, WritableFile* b) : env_(env), base_(b) { } |
|
|
ManifestFile(SpecialEnv* env, WritableFile* b) : env_(env), base_(b) { } |
|
|
~ManifestFile() { delete base_; } |
|
|
~ManifestFile() { delete base_; } |
|
|
Status Append(const Slice& data) { |
|
|
Status Append(const Slice& data) { |
|
|
if (env_->manifest_write_error_.Acquire_Load() != NULL) { |
|
|
|
|
|
|
|
|
if (env_->manifest_write_error_.Acquire_Load() != nullptr) { |
|
|
return Status::IOError("simulated writer error"); |
|
|
return Status::IOError("simulated writer error"); |
|
|
} else { |
|
|
} else { |
|
|
return base_->Append(data); |
|
|
return base_->Append(data); |
|
@ -176,7 +176,7 @@ class SpecialEnv : public EnvWrapper { |
|
|
Status Close() { return base_->Close(); } |
|
|
Status Close() { return base_->Close(); } |
|
|
Status Flush() { return base_->Flush(); } |
|
|
Status Flush() { return base_->Flush(); } |
|
|
Status Sync() { |
|
|
Status Sync() { |
|
|
if (env_->manifest_sync_error_.Acquire_Load() != NULL) { |
|
|
|
|
|
|
|
|
if (env_->manifest_sync_error_.Acquire_Load() != nullptr) { |
|
|
return Status::IOError("simulated sync error"); |
|
|
return Status::IOError("simulated sync error"); |
|
|
} else { |
|
|
} else { |
|
|
return base_->Sync(); |
|
|
return base_->Sync(); |
|
@ -184,16 +184,16 @@ class SpecialEnv : public EnvWrapper { |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
if (non_writable_.Acquire_Load() != NULL) { |
|
|
|
|
|
|
|
|
if (non_writable_.Acquire_Load() != nullptr) { |
|
|
return Status::IOError("simulated write error"); |
|
|
return Status::IOError("simulated write error"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Status s = target()->NewWritableFile(f, r); |
|
|
Status s = target()->NewWritableFile(f, r); |
|
|
if (s.ok()) { |
|
|
if (s.ok()) { |
|
|
if (strstr(f.c_str(), ".ldb") != NULL || |
|
|
|
|
|
strstr(f.c_str(), ".log") != NULL) { |
|
|
|
|
|
|
|
|
if (strstr(f.c_str(), ".ldb") != nullptr || |
|
|
|
|
|
strstr(f.c_str(), ".log") != nullptr) { |
|
|
*r = new DataFile(this, *r); |
|
|
*r = new DataFile(this, *r); |
|
|
} else if (strstr(f.c_str(), "MANIFEST") != NULL) { |
|
|
|
|
|
|
|
|
} else if (strstr(f.c_str(), "MANIFEST") != nullptr) { |
|
|
*r = new ManifestFile(this, *r); |
|
|
*r = new ManifestFile(this, *r); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -251,7 +251,7 @@ class DBTest { |
|
|
filter_policy_ = NewBloomFilterPolicy(10); |
|
|
filter_policy_ = NewBloomFilterPolicy(10); |
|
|
dbname_ = test::TmpDir() + "/db_test"; |
|
|
dbname_ = test::TmpDir() + "/db_test"; |
|
|
DestroyDB(dbname_, Options()); |
|
|
DestroyDB(dbname_, Options()); |
|
|
db_ = NULL; |
|
|
|
|
|
|
|
|
db_ = nullptr; |
|
|
Reopen(); |
|
|
Reopen(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -298,27 +298,27 @@ class DBTest { |
|
|
return reinterpret_cast<DBImpl*>(db_); |
|
|
return reinterpret_cast<DBImpl*>(db_); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void Reopen(Options* options = NULL) { |
|
|
|
|
|
|
|
|
void Reopen(Options* options = nullptr) { |
|
|
ASSERT_OK(TryReopen(options)); |
|
|
ASSERT_OK(TryReopen(options)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void Close() { |
|
|
void Close() { |
|
|
delete db_; |
|
|
delete db_; |
|
|
db_ = NULL; |
|
|
|
|
|
|
|
|
db_ = nullptr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void DestroyAndReopen(Options* options = NULL) { |
|
|
|
|
|
|
|
|
void DestroyAndReopen(Options* options = nullptr) { |
|
|
delete db_; |
|
|
delete db_; |
|
|
db_ = NULL; |
|
|
|
|
|
|
|
|
db_ = nullptr; |
|
|
DestroyDB(dbname_, Options()); |
|
|
DestroyDB(dbname_, Options()); |
|
|
ASSERT_OK(TryReopen(options)); |
|
|
ASSERT_OK(TryReopen(options)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Status TryReopen(Options* options) { |
|
|
Status TryReopen(Options* options) { |
|
|
delete db_; |
|
|
delete db_; |
|
|
db_ = NULL; |
|
|
|
|
|
|
|
|
db_ = nullptr; |
|
|
Options opts; |
|
|
Options opts; |
|
|
if (options != NULL) { |
|
|
|
|
|
|
|
|
if (options != nullptr) { |
|
|
opts = *options; |
|
|
opts = *options; |
|
|
} else { |
|
|
} else { |
|
|
opts = CurrentOptions(); |
|
|
opts = CurrentOptions(); |
|
@ -337,7 +337,7 @@ class DBTest { |
|
|
return db_->Delete(WriteOptions(), k); |
|
|
return db_->Delete(WriteOptions(), k); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
std::string Get(const std::string& k, const Snapshot* snapshot = NULL) { |
|
|
|
|
|
|
|
|
std::string Get(const std::string& k, const Snapshot* snapshot = nullptr) { |
|
|
ReadOptions options; |
|
|
ReadOptions options; |
|
|
options.snapshot = snapshot; |
|
|
options.snapshot = snapshot; |
|
|
std::string result; |
|
|
std::string result; |
|
@ -549,7 +549,7 @@ class DBTest { |
|
|
|
|
|
|
|
|
TEST(DBTest, Empty) { |
|
|
TEST(DBTest, Empty) { |
|
|
do { |
|
|
do { |
|
|
ASSERT_TRUE(db_ != NULL); |
|
|
|
|
|
|
|
|
ASSERT_TRUE(db_ != nullptr); |
|
|
ASSERT_EQ("NOT_FOUND", Get("foo")); |
|
|
ASSERT_EQ("NOT_FOUND", Get("foo")); |
|
|
} while (ChangeOptions()); |
|
|
} while (ChangeOptions()); |
|
|
} |
|
|
} |
|
@ -590,7 +590,7 @@ TEST(DBTest, GetFromImmutableLayer) { |
|
|
Put("k1", std::string(100000, 'x')); // Fill memtable
|
|
|
Put("k1", std::string(100000, 'x')); // Fill memtable
|
|
|
Put("k2", std::string(100000, 'y')); // Trigger compaction
|
|
|
Put("k2", std::string(100000, 'y')); // Trigger compaction
|
|
|
ASSERT_EQ("v1", Get("foo")); |
|
|
ASSERT_EQ("v1", Get("foo")); |
|
|
env_->delay_data_sync_.Release_Store(NULL); // Release sync calls
|
|
|
|
|
|
|
|
|
env_->delay_data_sync_.Release_Store(nullptr); // Release sync calls
|
|
|
} while (ChangeOptions()); |
|
|
} while (ChangeOptions()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -695,7 +695,7 @@ TEST(DBTest, GetEncountersEmptyLevel) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Step 2: clear level 1 if necessary.
|
|
|
// Step 2: clear level 1 if necessary.
|
|
|
dbfull()->TEST_CompactRange(1, NULL, NULL); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(1, nullptr, nullptr); |
|
|
ASSERT_EQ(NumTableFilesAtLevel(0), 1); |
|
|
ASSERT_EQ(NumTableFilesAtLevel(0), 1); |
|
|
ASSERT_EQ(NumTableFilesAtLevel(1), 0); |
|
|
ASSERT_EQ(NumTableFilesAtLevel(1), 0); |
|
|
ASSERT_EQ(NumTableFilesAtLevel(2), 1); |
|
|
ASSERT_EQ(NumTableFilesAtLevel(2), 1); |
|
@ -1032,7 +1032,7 @@ TEST(DBTest, CompactionsGenerateMultipleFiles) { |
|
|
|
|
|
|
|
|
// Reopening moves updates to level-0
|
|
|
// Reopening moves updates to level-0
|
|
|
Reopen(&options); |
|
|
Reopen(&options); |
|
|
dbfull()->TEST_CompactRange(0, NULL, NULL); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(0, nullptr, nullptr); |
|
|
|
|
|
|
|
|
ASSERT_EQ(NumTableFilesAtLevel(0), 0); |
|
|
ASSERT_EQ(NumTableFilesAtLevel(0), 0); |
|
|
ASSERT_GT(NumTableFilesAtLevel(1), 1); |
|
|
ASSERT_GT(NumTableFilesAtLevel(1), 1); |
|
@ -1083,7 +1083,7 @@ TEST(DBTest, SparseMerge) { |
|
|
} |
|
|
} |
|
|
Put("C", "vc"); |
|
|
Put("C", "vc"); |
|
|
dbfull()->TEST_CompactMemTable(); |
|
|
dbfull()->TEST_CompactMemTable(); |
|
|
dbfull()->TEST_CompactRange(0, NULL, NULL); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(0, nullptr, nullptr); |
|
|
|
|
|
|
|
|
// Make sparse update
|
|
|
// Make sparse update
|
|
|
Put("A", "va2"); |
|
|
Put("A", "va2"); |
|
@ -1094,9 +1094,9 @@ TEST(DBTest, SparseMerge) { |
|
|
// Compactions should not cause us to create a situation where
|
|
|
// Compactions should not cause us to create a situation where
|
|
|
// a file overlaps too much data at the next level.
|
|
|
// a file overlaps too much data at the next level.
|
|
|
ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); |
|
|
ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); |
|
|
dbfull()->TEST_CompactRange(0, NULL, NULL); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(0, nullptr, nullptr); |
|
|
ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); |
|
|
ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); |
|
|
dbfull()->TEST_CompactRange(1, NULL, NULL); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(1, nullptr, nullptr); |
|
|
ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); |
|
|
ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -1207,7 +1207,7 @@ TEST(DBTest, ApproximateSizes_MixOfSmallAndLarge) { |
|
|
|
|
|
|
|
|
ASSERT_TRUE(Between(Size(Key(3), Key(5)), 110000, 111000)); |
|
|
ASSERT_TRUE(Between(Size(Key(3), Key(5)), 110000, 111000)); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(0, NULL, NULL); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(0, nullptr, nullptr); |
|
|
} |
|
|
} |
|
|
} while (ChangeOptions()); |
|
|
} while (ChangeOptions()); |
|
|
} |
|
|
} |
|
@ -1283,11 +1283,11 @@ TEST(DBTest, HiddenValuesAreRemoved) { |
|
|
db_->ReleaseSnapshot(snapshot); |
|
|
db_->ReleaseSnapshot(snapshot); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ tiny, " + big + " ]"); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ tiny, " + big + " ]"); |
|
|
Slice x("x"); |
|
|
Slice x("x"); |
|
|
dbfull()->TEST_CompactRange(0, NULL, &x); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(0, nullptr, &x); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]"); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]"); |
|
|
ASSERT_EQ(NumTableFilesAtLevel(0), 0); |
|
|
ASSERT_EQ(NumTableFilesAtLevel(0), 0); |
|
|
ASSERT_GE(NumTableFilesAtLevel(1), 1); |
|
|
ASSERT_GE(NumTableFilesAtLevel(1), 1); |
|
|
dbfull()->TEST_CompactRange(1, NULL, &x); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(1, nullptr, &x); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]"); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]"); |
|
|
|
|
|
|
|
|
ASSERT_TRUE(Between(Size("", "pastfoo"), 0, 1000)); |
|
|
ASSERT_TRUE(Between(Size("", "pastfoo"), 0, 1000)); |
|
@ -1313,11 +1313,11 @@ TEST(DBTest, DeletionMarkers1) { |
|
|
ASSERT_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2
|
|
|
ASSERT_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2
|
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]"); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]"); |
|
|
Slice z("z"); |
|
|
Slice z("z"); |
|
|
dbfull()->TEST_CompactRange(last-2, NULL, &z); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(last-2, nullptr, &z); |
|
|
// DEL eliminated, but v1 remains because we aren't compacting that level
|
|
|
// DEL eliminated, but v1 remains because we aren't compacting that level
|
|
|
// (DEL can be eliminated because v2 hides v1).
|
|
|
// (DEL can be eliminated because v2 hides v1).
|
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ v2, v1 ]"); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ v2, v1 ]"); |
|
|
dbfull()->TEST_CompactRange(last-1, NULL, NULL); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(last-1, nullptr, nullptr); |
|
|
// Merging last-1 w/ last, so we are the base level for "foo", so
|
|
|
// Merging last-1 w/ last, so we are the base level for "foo", so
|
|
|
// DEL is removed. (as is v1).
|
|
|
// DEL is removed. (as is v1).
|
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ v2 ]"); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ v2 ]"); |
|
@ -1340,10 +1340,10 @@ TEST(DBTest, DeletionMarkers2) { |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); |
|
|
ASSERT_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2
|
|
|
ASSERT_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2
|
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); |
|
|
dbfull()->TEST_CompactRange(last-2, NULL, NULL); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(last-2, nullptr, nullptr); |
|
|
// DEL kept: "last" file overlaps
|
|
|
// DEL kept: "last" file overlaps
|
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); |
|
|
dbfull()->TEST_CompactRange(last-1, NULL, NULL); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(last-1, nullptr, nullptr); |
|
|
// Merging last-1 w/ last, so we are the base level for "foo", so
|
|
|
// Merging last-1 w/ last, so we are the base level for "foo", so
|
|
|
// DEL is removed. (as is v1).
|
|
|
// DEL is removed. (as is v1).
|
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ ]"); |
|
|
ASSERT_EQ(AllEntriesFor("foo"), "[ ]"); |
|
@ -1376,8 +1376,8 @@ TEST(DBTest, OverlapInLevel0) { |
|
|
ASSERT_EQ("2,1,1", FilesPerLevel()); |
|
|
ASSERT_EQ("2,1,1", FilesPerLevel()); |
|
|
|
|
|
|
|
|
// Compact away the placeholder files we created initially
|
|
|
// Compact away the placeholder files we created initially
|
|
|
dbfull()->TEST_CompactRange(1, NULL, NULL); |
|
|
|
|
|
dbfull()->TEST_CompactRange(2, NULL, NULL); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(1, nullptr, nullptr); |
|
|
|
|
|
dbfull()->TEST_CompactRange(2, nullptr, nullptr); |
|
|
ASSERT_EQ("2", FilesPerLevel()); |
|
|
ASSERT_EQ("2", FilesPerLevel()); |
|
|
|
|
|
|
|
|
// Do a memtable compaction. Before bug-fix, the compaction would
|
|
|
// Do a memtable compaction. Before bug-fix, the compaction would
|
|
@ -1437,7 +1437,7 @@ TEST(DBTest, Fflush_Issue474) { |
|
|
static const int kNum = 100000; |
|
|
static const int kNum = 100000; |
|
|
Random rnd(test::RandomSeed()); |
|
|
Random rnd(test::RandomSeed()); |
|
|
for (int i = 0; i < kNum; i++) { |
|
|
for (int i = 0; i < kNum; i++) { |
|
|
fflush(NULL); |
|
|
|
|
|
|
|
|
fflush(nullptr); |
|
|
ASSERT_OK(Put(RandomKey(&rnd), RandomString(&rnd, 100))); |
|
|
ASSERT_OK(Put(RandomKey(&rnd), RandomString(&rnd, 100))); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -1495,7 +1495,7 @@ TEST(DBTest, CustomComparator) { |
|
|
Options new_options = CurrentOptions(); |
|
|
Options new_options = CurrentOptions(); |
|
|
new_options.create_if_missing = true; |
|
|
new_options.create_if_missing = true; |
|
|
new_options.comparator = &cmp; |
|
|
new_options.comparator = &cmp; |
|
|
new_options.filter_policy = NULL; // Cannot use bloom filters
|
|
|
|
|
|
|
|
|
new_options.filter_policy = nullptr; // Cannot use bloom filters
|
|
|
new_options.write_buffer_size = 1000; // Compact more often
|
|
|
new_options.write_buffer_size = 1000; // Compact more often
|
|
|
DestroyAndReopen(&new_options); |
|
|
DestroyAndReopen(&new_options); |
|
|
ASSERT_OK(Put("[10]", "ten")); |
|
|
ASSERT_OK(Put("[10]", "ten")); |
|
@ -1550,7 +1550,7 @@ TEST(DBTest, ManualCompaction) { |
|
|
// Compact all
|
|
|
// Compact all
|
|
|
MakeTables(1, "a", "z"); |
|
|
MakeTables(1, "a", "z"); |
|
|
ASSERT_EQ("0,1,2", FilesPerLevel()); |
|
|
ASSERT_EQ("0,1,2", FilesPerLevel()); |
|
|
db_->CompactRange(NULL, NULL); |
|
|
|
|
|
|
|
|
db_->CompactRange(nullptr, nullptr); |
|
|
ASSERT_EQ("0,0,1", FilesPerLevel()); |
|
|
ASSERT_EQ("0,0,1", FilesPerLevel()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -1559,38 +1559,38 @@ TEST(DBTest, DBOpen_Options) { |
|
|
DestroyDB(dbname, Options()); |
|
|
DestroyDB(dbname, Options()); |
|
|
|
|
|
|
|
|
// Does not exist, and create_if_missing == false: error
|
|
|
// Does not exist, and create_if_missing == false: error
|
|
|
DB* db = NULL; |
|
|
|
|
|
|
|
|
DB* db = nullptr; |
|
|
Options opts; |
|
|
Options opts; |
|
|
opts.create_if_missing = false; |
|
|
opts.create_if_missing = false; |
|
|
Status s = DB::Open(opts, dbname, &db); |
|
|
Status s = DB::Open(opts, dbname, &db); |
|
|
ASSERT_TRUE(strstr(s.ToString().c_str(), "does not exist") != NULL); |
|
|
|
|
|
ASSERT_TRUE(db == NULL); |
|
|
|
|
|
|
|
|
ASSERT_TRUE(strstr(s.ToString().c_str(), "does not exist") != nullptr); |
|
|
|
|
|
ASSERT_TRUE(db == nullptr); |
|
|
|
|
|
|
|
|
// Does not exist, and create_if_missing == true: OK
|
|
|
// Does not exist, and create_if_missing == true: OK
|
|
|
opts.create_if_missing = true; |
|
|
opts.create_if_missing = true; |
|
|
s = DB::Open(opts, dbname, &db); |
|
|
s = DB::Open(opts, dbname, &db); |
|
|
ASSERT_OK(s); |
|
|
ASSERT_OK(s); |
|
|
ASSERT_TRUE(db != NULL); |
|
|
|
|
|
|
|
|
ASSERT_TRUE(db != nullptr); |
|
|
|
|
|
|
|
|
delete db; |
|
|
delete db; |
|
|
db = NULL; |
|
|
|
|
|
|
|
|
db = nullptr; |
|
|
|
|
|
|
|
|
// Does exist, and error_if_exists == true: error
|
|
|
// Does exist, and error_if_exists == true: error
|
|
|
opts.create_if_missing = false; |
|
|
opts.create_if_missing = false; |
|
|
opts.error_if_exists = true; |
|
|
opts.error_if_exists = true; |
|
|
s = DB::Open(opts, dbname, &db); |
|
|
s = DB::Open(opts, dbname, &db); |
|
|
ASSERT_TRUE(strstr(s.ToString().c_str(), "exists") != NULL); |
|
|
|
|
|
ASSERT_TRUE(db == NULL); |
|
|
|
|
|
|
|
|
ASSERT_TRUE(strstr(s.ToString().c_str(), "exists") != nullptr); |
|
|
|
|
|
ASSERT_TRUE(db == nullptr); |
|
|
|
|
|
|
|
|
// Does exist, and error_if_exists == false: OK
|
|
|
// Does exist, and error_if_exists == false: OK
|
|
|
opts.create_if_missing = true; |
|
|
opts.create_if_missing = true; |
|
|
opts.error_if_exists = false; |
|
|
opts.error_if_exists = false; |
|
|
s = DB::Open(opts, dbname, &db); |
|
|
s = DB::Open(opts, dbname, &db); |
|
|
ASSERT_OK(s); |
|
|
ASSERT_OK(s); |
|
|
ASSERT_TRUE(db != NULL); |
|
|
|
|
|
|
|
|
ASSERT_TRUE(db != nullptr); |
|
|
|
|
|
|
|
|
delete db; |
|
|
delete db; |
|
|
db = NULL; |
|
|
|
|
|
|
|
|
db = nullptr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
TEST(DBTest, DestroyEmptyDir) { |
|
|
TEST(DBTest, DestroyEmptyDir) { |
|
@ -1628,9 +1628,9 @@ TEST(DBTest, DestroyOpenDB) { |
|
|
|
|
|
|
|
|
Options opts; |
|
|
Options opts; |
|
|
opts.create_if_missing = true; |
|
|
opts.create_if_missing = true; |
|
|
DB* db = NULL; |
|
|
|
|
|
|
|
|
DB* db = nullptr; |
|
|
ASSERT_OK(DB::Open(opts, dbname, &db)); |
|
|
ASSERT_OK(DB::Open(opts, dbname, &db)); |
|
|
ASSERT_TRUE(db != NULL); |
|
|
|
|
|
|
|
|
ASSERT_TRUE(db != nullptr); |
|
|
|
|
|
|
|
|
// Must fail to destroy an open db.
|
|
|
// Must fail to destroy an open db.
|
|
|
ASSERT_TRUE(env_->FileExists(dbname)); |
|
|
ASSERT_TRUE(env_->FileExists(dbname)); |
|
@ -1638,7 +1638,7 @@ TEST(DBTest, DestroyOpenDB) { |
|
|
ASSERT_TRUE(env_->FileExists(dbname)); |
|
|
ASSERT_TRUE(env_->FileExists(dbname)); |
|
|
|
|
|
|
|
|
delete db; |
|
|
delete db; |
|
|
db = NULL; |
|
|
|
|
|
|
|
|
db = nullptr; |
|
|
|
|
|
|
|
|
// Should succeed destroying a closed db.
|
|
|
// Should succeed destroying a closed db.
|
|
|
ASSERT_OK(DestroyDB(dbname, Options())); |
|
|
ASSERT_OK(DestroyDB(dbname, Options())); |
|
@ -1646,7 +1646,7 @@ TEST(DBTest, DestroyOpenDB) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
TEST(DBTest, Locking) { |
|
|
TEST(DBTest, Locking) { |
|
|
DB* db2 = NULL; |
|
|
|
|
|
|
|
|
DB* db2 = nullptr; |
|
|
Status s = DB::Open(CurrentOptions(), dbname_, &db2); |
|
|
Status s = DB::Open(CurrentOptions(), dbname_, &db2); |
|
|
ASSERT_TRUE(!s.ok()) << "Locking did not prevent re-opening db"; |
|
|
ASSERT_TRUE(!s.ok()) << "Locking did not prevent re-opening db"; |
|
|
} |
|
|
} |
|
@ -1664,10 +1664,10 @@ TEST(DBTest, NoSpace) { |
|
|
env_->no_space_.Release_Store(env_); // Force out-of-space errors
|
|
|
env_->no_space_.Release_Store(env_); // Force out-of-space errors
|
|
|
for (int i = 0; i < 10; i++) { |
|
|
for (int i = 0; i < 10; i++) { |
|
|
for (int level = 0; level < config::kNumLevels-1; level++) { |
|
|
for (int level = 0; level < config::kNumLevels-1; level++) { |
|
|
dbfull()->TEST_CompactRange(level, NULL, NULL); |
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(level, nullptr, nullptr); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
env_->no_space_.Release_Store(NULL); |
|
|
|
|
|
|
|
|
env_->no_space_.Release_Store(nullptr); |
|
|
ASSERT_LT(CountFiles(), num_files + 3); |
|
|
ASSERT_LT(CountFiles(), num_files + 3); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -1688,7 +1688,7 @@ TEST(DBTest, NonWritableFileSystem) { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
ASSERT_GT(errors, 0); |
|
|
ASSERT_GT(errors, 0); |
|
|
env_->non_writable_.Release_Store(NULL); |
|
|
|
|
|
|
|
|
env_->non_writable_.Release_Store(nullptr); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
TEST(DBTest, WriteSyncError) { |
|
|
TEST(DBTest, WriteSyncError) { |
|
@ -1712,7 +1712,7 @@ TEST(DBTest, WriteSyncError) { |
|
|
ASSERT_EQ("NOT_FOUND", Get("k2")); |
|
|
ASSERT_EQ("NOT_FOUND", Get("k2")); |
|
|
|
|
|
|
|
|
// (d) make sync behave normally
|
|
|
// (d) make sync behave normally
|
|
|
env_->data_sync_error_.Release_Store(NULL); |
|
|
|
|
|
|
|
|
env_->data_sync_error_.Release_Store(nullptr); |
|
|
|
|
|
|
|
|
// (e) Do a non-sync write; should fail
|
|
|
// (e) Do a non-sync write; should fail
|
|
|
w.sync = false; |
|
|
w.sync = false; |
|
@ -1753,11 +1753,11 @@ TEST(DBTest, ManifestWriteError) { |
|
|
|
|
|
|
|
|
// Merging compaction (will fail)
|
|
|
// Merging compaction (will fail)
|
|
|
error_type->Release_Store(env_); |
|
|
error_type->Release_Store(env_); |
|
|
dbfull()->TEST_CompactRange(last, NULL, NULL); // Should fail
|
|
|
|
|
|
|
|
|
dbfull()->TEST_CompactRange(last, nullptr, nullptr); // Should fail
|
|
|
ASSERT_EQ("bar", Get("foo")); |
|
|
ASSERT_EQ("bar", Get("foo")); |
|
|
|
|
|
|
|
|
// Recovery: should not lose data
|
|
|
// Recovery: should not lose data
|
|
|
error_type->Release_Store(NULL); |
|
|
|
|
|
|
|
|
error_type->Release_Store(nullptr); |
|
|
Reopen(&options); |
|
|
Reopen(&options); |
|
|
ASSERT_EQ("bar", Get("foo")); |
|
|
ASSERT_EQ("bar", Get("foo")); |
|
|
} |
|
|
} |
|
@ -1849,7 +1849,7 @@ TEST(DBTest, BloomFilter) { |
|
|
fprintf(stderr, "%d missing => %d reads\n", N, reads); |
|
|
fprintf(stderr, "%d missing => %d reads\n", N, reads); |
|
|
ASSERT_LE(reads, 3*N/100); |
|
|
ASSERT_LE(reads, 3*N/100); |
|
|
|
|
|
|
|
|
env_->delay_data_sync_.Release_Store(NULL); |
|
|
|
|
|
|
|
|
env_->delay_data_sync_.Release_Store(nullptr); |
|
|
Close(); |
|
|
Close(); |
|
|
delete options.block_cache; |
|
|
delete options.block_cache; |
|
|
delete options.filter_policy; |
|
|
delete options.filter_policy; |
|
@ -1883,7 +1883,7 @@ static void MTThreadBody(void* arg) { |
|
|
Random rnd(1000 + id); |
|
|
Random rnd(1000 + id); |
|
|
std::string value; |
|
|
std::string value; |
|
|
char valbuf[1500]; |
|
|
char valbuf[1500]; |
|
|
while (t->state->stop.Acquire_Load() == NULL) { |
|
|
|
|
|
|
|
|
while (t->state->stop.Acquire_Load() == nullptr) { |
|
|
t->state->counter[id].Release_Store(reinterpret_cast<void*>(counter)); |
|
|
t->state->counter[id].Release_Store(reinterpret_cast<void*>(counter)); |
|
|
|
|
|
|
|
|
int key = rnd.Uniform(kNumKeys); |
|
|
int key = rnd.Uniform(kNumKeys); |
|
@ -1946,7 +1946,7 @@ TEST(DBTest, MultiThreaded) { |
|
|
// Stop the threads and wait for them to finish
|
|
|
// Stop the threads and wait for them to finish
|
|
|
mt.stop.Release_Store(&mt); |
|
|
mt.stop.Release_Store(&mt); |
|
|
for (int id = 0; id < kNumThreads; id++) { |
|
|
for (int id = 0; id < kNumThreads; id++) { |
|
|
while (mt.thread_done[id].Acquire_Load() == NULL) { |
|
|
|
|
|
|
|
|
while (mt.thread_done[id].Acquire_Load() == nullptr) { |
|
|
DelayMilliseconds(100); |
|
|
DelayMilliseconds(100); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -1978,7 +1978,7 @@ class ModelDB: public DB { |
|
|
return Status::NotFound(key); |
|
|
return Status::NotFound(key); |
|
|
} |
|
|
} |
|
|
virtual Iterator* NewIterator(const ReadOptions& options) { |
|
|
virtual Iterator* NewIterator(const ReadOptions& options) { |
|
|
if (options.snapshot == NULL) { |
|
|
|
|
|
|
|
|
if (options.snapshot == nullptr) { |
|
|
KVMap* saved = new KVMap; |
|
|
KVMap* saved = new KVMap; |
|
|
*saved = map_; |
|
|
*saved = map_; |
|
|
return new ModelIter(saved, true); |
|
|
return new ModelIter(saved, true); |
|
@ -2112,8 +2112,8 @@ TEST(DBTest, Randomized) { |
|
|
do { |
|
|
do { |
|
|
ModelDB model(CurrentOptions()); |
|
|
ModelDB model(CurrentOptions()); |
|
|
const int N = 10000; |
|
|
const int N = 10000; |
|
|
const Snapshot* model_snap = NULL; |
|
|
|
|
|
const Snapshot* db_snap = NULL; |
|
|
|
|
|
|
|
|
const Snapshot* model_snap = nullptr; |
|
|
|
|
|
const Snapshot* db_snap = nullptr; |
|
|
std::string k, v; |
|
|
std::string k, v; |
|
|
for (int step = 0; step < N; step++) { |
|
|
for (int step = 0; step < N; step++) { |
|
|
if (step % 100 == 0) { |
|
|
if (step % 100 == 0) { |
|
@ -2158,23 +2158,23 @@ TEST(DBTest, Randomized) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ((step % 100) == 0) { |
|
|
if ((step % 100) == 0) { |
|
|
ASSERT_TRUE(CompareIterators(step, &model, db_, NULL, NULL)); |
|
|
|
|
|
|
|
|
ASSERT_TRUE(CompareIterators(step, &model, db_, nullptr, nullptr)); |
|
|
ASSERT_TRUE(CompareIterators(step, &model, db_, model_snap, db_snap)); |
|
|
ASSERT_TRUE(CompareIterators(step, &model, db_, model_snap, db_snap)); |
|
|
// Save a snapshot from each DB this time that we'll use next
|
|
|
// Save a snapshot from each DB this time that we'll use next
|
|
|
// time we compare things, to make sure the current state is
|
|
|
// time we compare things, to make sure the current state is
|
|
|
// preserved with the snapshot
|
|
|
// preserved with the snapshot
|
|
|
if (model_snap != NULL) model.ReleaseSnapshot(model_snap); |
|
|
|
|
|
if (db_snap != NULL) db_->ReleaseSnapshot(db_snap); |
|
|
|
|
|
|
|
|
if (model_snap != nullptr) model.ReleaseSnapshot(model_snap); |
|
|
|
|
|
if (db_snap != nullptr) db_->ReleaseSnapshot(db_snap); |
|
|
|
|
|
|
|
|
Reopen(); |
|
|
Reopen(); |
|
|
ASSERT_TRUE(CompareIterators(step, &model, db_, NULL, NULL)); |
|
|
|
|
|
|
|
|
ASSERT_TRUE(CompareIterators(step, &model, db_, nullptr, nullptr)); |
|
|
|
|
|
|
|
|
model_snap = model.GetSnapshot(); |
|
|
model_snap = model.GetSnapshot(); |
|
|
db_snap = db_->GetSnapshot(); |
|
|
db_snap = db_->GetSnapshot(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
if (model_snap != NULL) model.ReleaseSnapshot(model_snap); |
|
|
|
|
|
if (db_snap != NULL) db_->ReleaseSnapshot(db_snap); |
|
|
|
|
|
|
|
|
if (model_snap != nullptr) model.ReleaseSnapshot(model_snap); |
|
|
|
|
|
if (db_snap != nullptr) db_->ReleaseSnapshot(db_snap); |
|
|
} while (ChangeOptions()); |
|
|
} while (ChangeOptions()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -2188,15 +2188,15 @@ void BM_LogAndApply(int iters, int num_base_files) { |
|
|
std::string dbname = test::TmpDir() + "/leveldb_test_benchmark"; |
|
|
std::string dbname = test::TmpDir() + "/leveldb_test_benchmark"; |
|
|
DestroyDB(dbname, Options()); |
|
|
DestroyDB(dbname, Options()); |
|
|
|
|
|
|
|
|
DB* db = NULL; |
|
|
|
|
|
|
|
|
DB* db = nullptr; |
|
|
Options opts; |
|
|
Options opts; |
|
|
opts.create_if_missing = true; |
|
|
opts.create_if_missing = true; |
|
|
Status s = DB::Open(opts, dbname, &db); |
|
|
Status s = DB::Open(opts, dbname, &db); |
|
|
ASSERT_OK(s); |
|
|
ASSERT_OK(s); |
|
|
ASSERT_TRUE(db != NULL); |
|
|
|
|
|
|
|
|
ASSERT_TRUE(db != nullptr); |
|
|
|
|
|
|
|
|
delete db; |
|
|
delete db; |
|
|
db = NULL; |
|
|
|
|
|
|
|
|
db = nullptr; |
|
|
|
|
|
|
|
|
Env* env = Env::Default(); |
|
|
Env* env = Env::Default(); |
|
|
|
|
|
|
|
@ -2205,7 +2205,7 @@ void BM_LogAndApply(int iters, int num_base_files) { |
|
|
|
|
|
|
|
|
InternalKeyComparator cmp(BytewiseComparator()); |
|
|
InternalKeyComparator cmp(BytewiseComparator()); |
|
|
Options options; |
|
|
Options options; |
|
|
VersionSet vset(dbname, &options, NULL, &cmp); |
|
|
|
|
|
|
|
|
VersionSet vset(dbname, &options, nullptr, &cmp); |
|
|
bool save_manifest; |
|
|
bool save_manifest; |
|
|
ASSERT_OK(vset.Recover(&save_manifest)); |
|
|
ASSERT_OK(vset.Recover(&save_manifest)); |
|
|
VersionEdit vbase; |
|
|
VersionEdit vbase; |
|
|