Update blob_db_test
Summary: I'm trying to improve unit test of blob db. I'm rewriting blob db test. In this patch: * Rewrite tests of basic put/write/delete operations. * Add disable_background_tasks to BlobDBOptionsImpl to allow me not running any background job for basic unit tests. * Move DestroyBlobDB out from BlobDBImpl to be a standalone function. * Remove all garbage collection related tests. Will rewrite them in following patch. * Disabled compression test since it is failing. Will fix in a followup patch. Closes https://github.com/facebook/rocksdb/pull/2446 Differential Revision: D5243306 Pulled By: yiwu-arbug fbshipit-source-id: 157c71ad3b699307cb88baa3830e9b6e74f8e939
This commit is contained in:
parent
89ad9f3adb
commit
7a380deff7
@ -104,11 +104,6 @@ class BlobDB : public StackableDB {
|
||||
public:
|
||||
using rocksdb::StackableDB::Put;
|
||||
|
||||
// This function needs to be called before destroying
|
||||
// the base DB
|
||||
static Status DestroyBlobDB(const std::string& dbname, const Options& options,
|
||||
const BlobDBOptions& bdb_options);
|
||||
|
||||
virtual Status Put(const WriteOptions& options,
|
||||
ColumnFamilyHandle* column_family, const Slice& key,
|
||||
const Slice& value) override = 0;
|
||||
@ -190,6 +185,8 @@ class BlobDB : public StackableDB {
|
||||
std::vector<ColumnFamilyHandle*>* handles,
|
||||
BlobDB** blob_db, bool no_base_db = false);
|
||||
|
||||
virtual BlobDBOptions GetBlobDBOptions() const = 0;
|
||||
|
||||
virtual ~BlobDB() {}
|
||||
|
||||
virtual Status LinkToBaseDB(DB* db_base) = 0;
|
||||
@ -198,6 +195,10 @@ class BlobDB : public StackableDB {
|
||||
explicit BlobDB(DB* db);
|
||||
};
|
||||
|
||||
// Destroy the content of the database.
|
||||
Status DestroyBlobDB(const std::string& dbname, const Options& options,
|
||||
const BlobDBOptions& bdb_options);
|
||||
|
||||
} // namespace blob_db
|
||||
} // namespace rocksdb
|
||||
#endif // ROCKSDB_LITE
|
||||
|
@ -191,34 +191,6 @@ void EvictAllVersionsCompactionListener::InternalListener::OnCompaction(
|
||||
}
|
||||
}
|
||||
|
||||
Status BlobDB::DestroyBlobDB(const std::string& dbname, const Options& options,
|
||||
const BlobDBOptions& bdb_options) {
|
||||
const ImmutableDBOptions soptions(SanitizeOptions(dbname, options));
|
||||
Env* env = soptions.env;
|
||||
|
||||
Status result;
|
||||
std::string blobdir;
|
||||
blobdir = (bdb_options.path_relative) ? dbname + "/" + bdb_options.blob_dir
|
||||
: bdb_options.blob_dir;
|
||||
|
||||
std::vector<std::string> filenames;
|
||||
Status status = env->GetChildren(blobdir, &filenames);
|
||||
|
||||
for (const auto& f : filenames) {
|
||||
uint64_t number;
|
||||
FileType type;
|
||||
if (ParseFileName(f, &number, &type) && type == kBlobFile) {
|
||||
Status del = env->DeleteFile(blobdir + "/" + f);
|
||||
if (result.ok() && !del.ok()) {
|
||||
result = del;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env->DeleteDir(blobdir);
|
||||
return result;
|
||||
}
|
||||
|
||||
BlobDBImpl::BlobDBImpl(const std::string& dbname,
|
||||
const BlobDBOptions& blob_db_options,
|
||||
const DBOptions& db_options)
|
||||
@ -287,10 +259,14 @@ Status BlobDBImpl::LinkToBaseDB(DB* db) {
|
||||
s.ToString().c_str());
|
||||
}
|
||||
|
||||
StartBackgroundTasks();
|
||||
if (!bdb_options_.disable_background_tasks) {
|
||||
StartBackgroundTasks();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
BlobDBOptions BlobDBImpl::GetBlobDBOptions() const { return bdb_options_; }
|
||||
|
||||
BlobDBImpl::BlobDBImpl(DB* db, const BlobDBOptions& blob_db_options)
|
||||
: BlobDB(db),
|
||||
db_impl_(dynamic_cast<DBImpl*>(db)),
|
||||
@ -1218,7 +1194,6 @@ std::vector<Status> BlobDBImpl::MultiGet(
|
||||
Status BlobDBImpl::CommonGet(const ColumnFamilyData* cfd, const Slice& key,
|
||||
const std::string& index_entry, std::string* value,
|
||||
SequenceNumber* sequence) {
|
||||
assert(value);
|
||||
Slice index_entry_slice(index_entry);
|
||||
BlobHandle handle;
|
||||
Status s = handle.DecodeFrom(&index_entry_slice);
|
||||
@ -2244,6 +2219,39 @@ Iterator* BlobDBImpl::NewIterator(const ReadOptions& opts,
|
||||
column_family, this);
|
||||
}
|
||||
|
||||
Status DestroyBlobDB(const std::string& dbname, const Options& options,
|
||||
const BlobDBOptions& bdb_options) {
|
||||
const ImmutableDBOptions soptions(SanitizeOptions(dbname, options));
|
||||
Env* env = soptions.env;
|
||||
|
||||
Status status;
|
||||
std::string blobdir;
|
||||
blobdir = (bdb_options.path_relative) ? dbname + "/" + bdb_options.blob_dir
|
||||
: bdb_options.blob_dir;
|
||||
|
||||
std::vector<std::string> filenames;
|
||||
env->GetChildren(blobdir, &filenames);
|
||||
|
||||
for (const auto& f : filenames) {
|
||||
uint64_t number;
|
||||
FileType type;
|
||||
if (ParseFileName(f, &number, &type) && type == kBlobFile) {
|
||||
Status del = env->DeleteFile(blobdir + "/" + f);
|
||||
if (status.ok() && !del.ok()) {
|
||||
status = del;
|
||||
}
|
||||
}
|
||||
}
|
||||
env->DeleteDir(blobdir);
|
||||
|
||||
Status destroy = DestroyDB(dbname, options);
|
||||
if (status.ok() && !destroy.ok()) {
|
||||
status = destroy;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
Status BlobDBImpl::TEST_GetSequenceNumber(const Slice& key,
|
||||
SequenceNumber* sequence) {
|
||||
|
@ -189,6 +189,8 @@ class BlobDBImpl : public BlobDB {
|
||||
|
||||
Status LinkToBaseDB(DB* db) override;
|
||||
|
||||
BlobDBOptions GetBlobDBOptions() const override;
|
||||
|
||||
BlobDBImpl(DB* db, const BlobDBOptions& bdb_options);
|
||||
|
||||
BlobDBImpl(const std::string& dbname, const BlobDBOptions& bdb_options,
|
||||
|
@ -24,7 +24,8 @@ BlobDBOptionsImpl::BlobDBOptionsImpl(const BlobDBOptions& in)
|
||||
fsync_files_period_millisecs(10 * 1000),
|
||||
reclaim_of_period_millisecs(1 * 1000),
|
||||
delete_obsf_period_millisecs(10 * 1000),
|
||||
check_seqf_period_millisecs(10 * 1000) {}
|
||||
check_seqf_period_millisecs(10 * 1000),
|
||||
disable_background_tasks(false) {}
|
||||
|
||||
BlobDBOptionsImpl::BlobDBOptionsImpl()
|
||||
: deletion_check_period_millisecs(2 * 1000),
|
||||
@ -39,7 +40,8 @@ BlobDBOptionsImpl::BlobDBOptionsImpl()
|
||||
fsync_files_period_millisecs(10 * 1000),
|
||||
reclaim_of_period_millisecs(1 * 1000),
|
||||
delete_obsf_period_millisecs(10 * 1000),
|
||||
check_seqf_period_millisecs(10 * 1000) {}
|
||||
check_seqf_period_millisecs(10 * 1000),
|
||||
disable_background_tasks(false) {}
|
||||
|
||||
BlobDBOptionsImpl& BlobDBOptionsImpl::operator=(const BlobDBOptionsImpl& in) {
|
||||
BlobDBOptions::operator=(in);
|
||||
@ -57,6 +59,7 @@ BlobDBOptionsImpl& BlobDBOptionsImpl::operator=(const BlobDBOptionsImpl& in) {
|
||||
reclaim_of_period_millisecs = in.reclaim_of_period_millisecs;
|
||||
delete_obsf_period_millisecs = in.delete_obsf_period_millisecs;
|
||||
check_seqf_period_millisecs = in.check_seqf_period_millisecs;
|
||||
disable_background_tasks = in.disable_background_tasks;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -58,6 +58,9 @@ struct BlobDBOptionsImpl : public BlobDBOptions {
|
||||
// how often to schedule check seq files period
|
||||
uint32_t check_seqf_period_millisecs;
|
||||
|
||||
// Disable all background job.
|
||||
bool disable_background_tasks;
|
||||
|
||||
// default constructor
|
||||
BlobDBOptionsImpl();
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
|
||||
#include "utilities/blob_db/blob_db.h"
|
||||
@ -19,65 +19,51 @@
|
||||
#include "utilities/blob_db/blob_db_options_impl.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
namespace blob_db {
|
||||
Random s_rnd(301);
|
||||
|
||||
void gen_random(char *s, const int len) {
|
||||
static const char alphanum[] =
|
||||
"0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
s[i] = alphanum[s_rnd.Next() % (sizeof(alphanum) - 1)];
|
||||
}
|
||||
|
||||
s[len] = 0;
|
||||
}
|
||||
|
||||
class BlobDBTest : public testing::Test {
|
||||
public:
|
||||
const int kMaxBlobSize = 1 << 14;
|
||||
|
||||
BlobDBTest() : blobdb_(nullptr) {
|
||||
dbname_ = test::TmpDir() + "/blob_db_test";
|
||||
// Reopen(BlobDBOptionsImpl());
|
||||
BlobDBTest() : dbname_(test::TmpDir() + "/blob_db_test"), blob_db_(nullptr) {
|
||||
Status s = DestroyBlobDB(dbname_, Options(), BlobDBOptions());
|
||||
assert(s.ok());
|
||||
}
|
||||
|
||||
~BlobDBTest() {
|
||||
if (blobdb_) {
|
||||
delete blobdb_;
|
||||
blobdb_ = nullptr;
|
||||
}
|
||||
~BlobDBTest() { Destroy(); }
|
||||
|
||||
void Open(BlobDBOptionsImpl bdb_options = BlobDBOptionsImpl(),
|
||||
Options options = Options()) {
|
||||
options.create_if_missing = true;
|
||||
Reopen(bdb_options, options);
|
||||
}
|
||||
|
||||
void Reopen(const BlobDBOptionsImpl &bdboptions,
|
||||
const Options &options = Options()) {
|
||||
if (blobdb_) {
|
||||
delete blobdb_;
|
||||
blobdb_ = nullptr;
|
||||
void Reopen(BlobDBOptionsImpl bdb_options = BlobDBOptionsImpl(),
|
||||
Options options = Options()) {
|
||||
if (blob_db_) {
|
||||
delete blob_db_;
|
||||
blob_db_ = nullptr;
|
||||
}
|
||||
ASSERT_OK(BlobDB::Open(options, bdb_options, dbname_, &blob_db_));
|
||||
ASSERT_TRUE(blob_db_);
|
||||
}
|
||||
|
||||
BlobDBOptionsImpl bblobdb_options = bdboptions;
|
||||
Options myoptions = options;
|
||||
BlobDB::DestroyBlobDB(dbname_, myoptions, bblobdb_options);
|
||||
|
||||
DestroyDB(dbname_, myoptions);
|
||||
|
||||
myoptions.create_if_missing = true;
|
||||
EXPECT_TRUE(
|
||||
BlobDB::Open(myoptions, bblobdb_options, dbname_, &blobdb_).ok());
|
||||
ASSERT_NE(nullptr, blobdb_);
|
||||
void Destroy() {
|
||||
if (blob_db_) {
|
||||
Options options = blob_db_->GetOptions();
|
||||
BlobDBOptions bdb_options = blob_db_->GetBlobDBOptions();
|
||||
delete blob_db_;
|
||||
ASSERT_OK(DestroyBlobDB(dbname_, options, bdb_options));
|
||||
blob_db_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PutRandomWithTTL(const std::string &key, int32_t ttl, Random *rnd,
|
||||
std::map<std::string, std::string> *data = nullptr) {
|
||||
int len = rnd->Next() % kMaxBlobSize + 1;
|
||||
std::string value = test::RandomHumanReadableString(rnd, len);
|
||||
ColumnFamilyHandle *cfh = blobdb_->DefaultColumnFamily();
|
||||
ASSERT_OK(blobdb_->PutWithTTL(WriteOptions(), cfh, Slice(key), Slice(value),
|
||||
ttl));
|
||||
ASSERT_OK(
|
||||
blob_db_->PutWithTTL(WriteOptions(), Slice(key), Slice(value), ttl));
|
||||
if (data != nullptr) {
|
||||
(*data)[key] = value;
|
||||
}
|
||||
@ -88,15 +74,29 @@ class BlobDBTest : public testing::Test {
|
||||
PutRandomWithTTL(key, -1, rnd, data);
|
||||
}
|
||||
|
||||
void Delete(const std::string &key) {
|
||||
ColumnFamilyHandle *cfh = blobdb_->DefaultColumnFamily();
|
||||
ASSERT_OK(blobdb_->Delete(WriteOptions(), cfh, key));
|
||||
void PutRandomToWriteBatch(
|
||||
const std::string &key, Random *rnd, WriteBatch *batch,
|
||||
std::map<std::string, std::string> *data = nullptr) {
|
||||
int len = rnd->Next() % kMaxBlobSize + 1;
|
||||
std::string value = test::RandomHumanReadableString(rnd, len);
|
||||
ASSERT_OK(batch->Put(key, value));
|
||||
if (data != nullptr) {
|
||||
(*data)[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void Delete(const std::string &key,
|
||||
std::map<std::string, std::string> *data = nullptr) {
|
||||
ASSERT_OK(blob_db_->Delete(WriteOptions(), key));
|
||||
if (data != nullptr) {
|
||||
data->erase(key);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify blob db contain expected data and nothing more.
|
||||
// TODO(yiwu): Verify blob files are consistent with data in LSM.
|
||||
void VerifyDB(const std::map<std::string, std::string> &data) {
|
||||
Iterator *iter = blobdb_->NewIterator(ReadOptions());
|
||||
Iterator *iter = blob_db_->NewIterator(ReadOptions());
|
||||
iter->SeekToFirst();
|
||||
for (auto &p : data) {
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
@ -124,38 +124,76 @@ class BlobDBTest : public testing::Test {
|
||||
}
|
||||
}
|
||||
|
||||
BlobDB *blobdb_;
|
||||
std::string dbname_;
|
||||
const std::string dbname_;
|
||||
BlobDB *blob_db_;
|
||||
}; // class BlobDBTest
|
||||
|
||||
TEST_F(BlobDBTest, DeleteComplex) {
|
||||
BlobDBOptionsImpl bdboptions;
|
||||
Reopen(bdboptions);
|
||||
|
||||
TEST_F(BlobDBTest, Put) {
|
||||
Random rnd(301);
|
||||
BlobDBOptionsImpl bdb_options;
|
||||
bdb_options.disable_background_tasks = true;
|
||||
Open(bdb_options);
|
||||
std::map<std::string, std::string> data;
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
PutRandom("key" + ToString(i), &rnd, nullptr);
|
||||
PutRandom("key" + ToString(i), &rnd, &data);
|
||||
}
|
||||
VerifyDB(data);
|
||||
}
|
||||
|
||||
TEST_F(BlobDBTest, WriteBatch) {
|
||||
Random rnd(301);
|
||||
BlobDBOptionsImpl bdb_options;
|
||||
bdb_options.disable_background_tasks = true;
|
||||
Open(bdb_options);
|
||||
std::map<std::string, std::string> data;
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
Delete("key" + ToString(i));
|
||||
WriteBatch batch;
|
||||
for (size_t j = 0; j < 10; j++) {
|
||||
PutRandomToWriteBatch("key" + ToString(j * 100 + i), &rnd, &batch, &data);
|
||||
}
|
||||
blob_db_->Write(WriteOptions(), &batch);
|
||||
}
|
||||
VerifyDB(data);
|
||||
}
|
||||
|
||||
TEST_F(BlobDBTest, Delete) {
|
||||
Random rnd(301);
|
||||
BlobDBOptionsImpl bdb_options;
|
||||
bdb_options.disable_background_tasks = true;
|
||||
Open(bdb_options);
|
||||
std::map<std::string, std::string> data;
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
PutRandom("key" + ToString(i), &rnd, &data);
|
||||
}
|
||||
for (size_t i = 0; i < 100; i += 5) {
|
||||
Delete("key" + ToString(i), &data);
|
||||
}
|
||||
VerifyDB(data);
|
||||
}
|
||||
|
||||
TEST_F(BlobDBTest, DeleteBatch) {
|
||||
Random rnd(301);
|
||||
BlobDBOptionsImpl bdb_options;
|
||||
bdb_options.disable_background_tasks = true;
|
||||
Open(bdb_options);
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
PutRandom("key" + ToString(i), &rnd);
|
||||
}
|
||||
WriteBatch batch;
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
batch.Delete("key" + ToString(i));
|
||||
}
|
||||
ASSERT_OK(blob_db_->Write(WriteOptions(), &batch));
|
||||
// DB should be empty.
|
||||
VerifyDB({});
|
||||
}
|
||||
|
||||
TEST_F(BlobDBTest, OverrideTest) {
|
||||
BlobDBOptionsImpl bdboptions;
|
||||
bdboptions.num_concurrent_simple_blobs = 2;
|
||||
bdboptions.blob_file_size = 876 * 1024 * 10;
|
||||
|
||||
Options options;
|
||||
options.write_buffer_size = 256 * 1024;
|
||||
|
||||
Reopen(bdboptions, options);
|
||||
|
||||
TEST_F(BlobDBTest, Override) {
|
||||
Random rnd(301);
|
||||
BlobDBOptionsImpl bdb_options;
|
||||
bdb_options.disable_background_tasks = true;
|
||||
Open(bdb_options);
|
||||
std::map<std::string, std::string> data;
|
||||
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
PutRandom("key" + ToString(i), &rnd, nullptr);
|
||||
}
|
||||
@ -166,284 +204,31 @@ TEST_F(BlobDBTest, OverrideTest) {
|
||||
VerifyDB(data);
|
||||
}
|
||||
|
||||
TEST_F(BlobDBTest, DeleteTest) {
|
||||
BlobDBOptionsImpl bdboptions;
|
||||
bdboptions.num_concurrent_simple_blobs = 1;
|
||||
bdboptions.blob_file_size = 876 * 1024;
|
||||
|
||||
Reopen(bdboptions);
|
||||
|
||||
#ifdef SNAPPY
|
||||
TEST_F(BlobDBTest, DISABLED_Compression) {
|
||||
Random rnd(301);
|
||||
BlobDBOptionsImpl bdb_options;
|
||||
bdb_options.disable_background_tasks = true;
|
||||
bdb_options.compression = CompressionType::kSnappyCompression;
|
||||
Open(bdb_options);
|
||||
std::map<std::string, std::string> data;
|
||||
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
PutRandom("key" + ToString(i), &rnd, &data);
|
||||
PutRandom("put-key" + ToString(i), &rnd, &data);
|
||||
}
|
||||
for (size_t i = 0; i < 100; i += 5) {
|
||||
Delete("key" + ToString(i));
|
||||
data.erase("key" + ToString(i));
|
||||
for (int i = 0; i < 100; i++) {
|
||||
WriteBatch batch;
|
||||
for (size_t j = 0; j < 10; j++) {
|
||||
PutRandomToWriteBatch("write-batch-key" + ToString(j * 100 + i), &rnd,
|
||||
&batch, &data);
|
||||
}
|
||||
blob_db_->Write(WriteOptions(), &batch);
|
||||
}
|
||||
VerifyDB(data);
|
||||
}
|
||||
|
||||
TEST_F(BlobDBTest, GCTestWithWrite) {
|
||||
BlobDBOptionsImpl bdboptions;
|
||||
bdboptions.ttl_range_secs = 30;
|
||||
bdboptions.gc_file_pct = 100;
|
||||
bdboptions.gc_check_period_millisecs = 20 * 1000;
|
||||
bdboptions.default_ttl_extractor = true;
|
||||
|
||||
Reopen(bdboptions);
|
||||
|
||||
WriteOptions wo;
|
||||
ReadOptions ro;
|
||||
std::string value;
|
||||
|
||||
ColumnFamilyHandle *dcfh = blobdb_->DefaultColumnFamily();
|
||||
|
||||
WriteBatch batch;
|
||||
|
||||
Random rnd(301);
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
int len = rnd.Next() % kMaxBlobSize;
|
||||
if (!len) continue;
|
||||
|
||||
int ttl = 30;
|
||||
|
||||
char *val = new char[len + BlobDB::kTTLSuffixLength];
|
||||
gen_random(val, len);
|
||||
strncpy(val + len, "ttl:", 4);
|
||||
EncodeFixed32(val + len + 4, ttl);
|
||||
|
||||
std::string key("key");
|
||||
key += std::to_string(i);
|
||||
|
||||
Slice keyslice(key);
|
||||
Slice valslice(val, len + BlobDB::kTTLSuffixLength);
|
||||
|
||||
batch.Put(dcfh, keyslice, valslice);
|
||||
delete[] val;
|
||||
}
|
||||
|
||||
ASSERT_OK(blobdb_->Write(wo, &batch));
|
||||
|
||||
// TODO(yiwu): Use sync point to properly trigger GC and check result.
|
||||
// Env::Default()->SleepForMicroseconds(120 * 1000 * 1000);
|
||||
}
|
||||
|
||||
void cb_evict(const ColumnFamilyHandle *cfh, const Slice &key,
|
||||
const Slice &val) {
|
||||
fprintf(stderr, "key evicted: %s\n", key.ToString().c_str());
|
||||
}
|
||||
|
||||
static const char *LONG_STRING =
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFJFJFJTWFNLLFKFFMFMFMFMFMFMFMFMFMFMFMFMFMMF "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJAJFJFJFJFJTWBFNMFLLWMFMFMFMWKWMFMFMFMFMFMFM "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH "
|
||||
"AJFJFJFFFFFFFFFFFFFFFFFFFJFHFHFHFHFHFHFHHFHHFHHFH ";
|
||||
|
||||
TEST_F(BlobDBTest, GetWithCompression) {
|
||||
BlobDBOptionsImpl bdboptions;
|
||||
bdboptions.gc_file_pct = 100;
|
||||
bdboptions.gc_check_period_millisecs = 20 * 1000;
|
||||
bdboptions.default_ttl_extractor = true;
|
||||
bdboptions.gc_evict_cb_fn = &cb_evict;
|
||||
bdboptions.compression = CompressionType::kLZ4Compression;
|
||||
|
||||
Reopen(bdboptions);
|
||||
|
||||
WriteOptions wo;
|
||||
ReadOptions ro;
|
||||
std::string value;
|
||||
Random rnd(301);
|
||||
|
||||
ColumnFamilyHandle *dcfh = blobdb_->DefaultColumnFamily();
|
||||
|
||||
std::string orig(LONG_STRING);
|
||||
|
||||
for (size_t i = 0; i < 10000; i++) {
|
||||
size_t len = orig.length();
|
||||
int ttl = 3000 * (rnd.Next() % 10);
|
||||
|
||||
char *val = new char[len + BlobDB::kTTLSuffixLength];
|
||||
strncpy(val, LONG_STRING, len);
|
||||
strncpy(val + len, "ttl:", 4);
|
||||
EncodeFixed32(val + len + 4, ttl);
|
||||
|
||||
std::string key("key");
|
||||
key += std::to_string(i);
|
||||
|
||||
Slice keyslice(key);
|
||||
Slice valslice(val, len + BlobDB::kTTLSuffixLength);
|
||||
|
||||
ASSERT_OK(blobdb_->Put(wo, dcfh, keyslice, valslice));
|
||||
delete[] val;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 10000; i++) {
|
||||
std::string key("key");
|
||||
key += std::to_string(i);
|
||||
|
||||
Slice keyslice(key);
|
||||
std::string val;
|
||||
Status s = blobdb_->Get(ro, dcfh, keyslice, &val);
|
||||
ASSERT_TRUE(orig == val);
|
||||
}
|
||||
|
||||
// TODO(yiwu): Use sync point to properly trigger GC and check result.
|
||||
// Env::Default()->SleepForMicroseconds(120 * 1000 * 1000);
|
||||
}
|
||||
|
||||
TEST_F(BlobDBTest, GCTestWithPutAndCompression) {
|
||||
BlobDBOptionsImpl bdboptions;
|
||||
bdboptions.ttl_range_secs = 30;
|
||||
bdboptions.gc_file_pct = 100;
|
||||
bdboptions.gc_check_period_millisecs = 20 * 1000;
|
||||
bdboptions.default_ttl_extractor = true;
|
||||
bdboptions.gc_evict_cb_fn = &cb_evict;
|
||||
bdboptions.compression = CompressionType::kLZ4Compression;
|
||||
|
||||
Reopen(bdboptions);
|
||||
|
||||
WriteOptions wo;
|
||||
ReadOptions ro;
|
||||
std::string value;
|
||||
Random rnd(301);
|
||||
|
||||
ColumnFamilyHandle *dcfh = blobdb_->DefaultColumnFamily();
|
||||
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
int len = rnd.Next() % kMaxBlobSize;
|
||||
if (!len) continue;
|
||||
|
||||
int ttl = 30;
|
||||
|
||||
char *val = new char[len + BlobDB::kTTLSuffixLength];
|
||||
gen_random(val, len);
|
||||
strncpy(val + len, "ttl:", 4);
|
||||
EncodeFixed32(val + len + 4, ttl);
|
||||
|
||||
std::string key("key");
|
||||
key += std::to_string(i);
|
||||
|
||||
Slice keyslice(key);
|
||||
Slice valslice(val, len + BlobDB::kTTLSuffixLength);
|
||||
|
||||
ASSERT_OK(blobdb_->Put(wo, dcfh, keyslice, valslice));
|
||||
delete[] val;
|
||||
}
|
||||
|
||||
// TODO(yiwu): Use sync point to properly trigger GC and check result.
|
||||
// Env::Default()->SleepForMicroseconds(120 * 1000 * 1000);
|
||||
}
|
||||
|
||||
TEST_F(BlobDBTest, GCTestWithPut) {
|
||||
BlobDBOptionsImpl bdboptions;
|
||||
bdboptions.ttl_range_secs = 30;
|
||||
bdboptions.gc_file_pct = 100;
|
||||
bdboptions.gc_check_period_millisecs = 20 * 1000;
|
||||
bdboptions.default_ttl_extractor = true;
|
||||
bdboptions.gc_evict_cb_fn = &cb_evict;
|
||||
|
||||
Reopen(bdboptions);
|
||||
|
||||
WriteOptions wo;
|
||||
ReadOptions ro;
|
||||
std::string value;
|
||||
Random rnd(301);
|
||||
|
||||
ColumnFamilyHandle *dcfh = blobdb_->DefaultColumnFamily();
|
||||
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
int len = rnd.Next() % kMaxBlobSize;
|
||||
if (!len) continue;
|
||||
|
||||
int ttl = 30;
|
||||
|
||||
char *val = new char[len + BlobDB::kTTLSuffixLength];
|
||||
gen_random(val, len);
|
||||
strncpy(val + len, "ttl:", 4);
|
||||
EncodeFixed32(val + len + 4, ttl);
|
||||
|
||||
std::string key("key");
|
||||
key += std::to_string(i);
|
||||
|
||||
Slice keyslice(key);
|
||||
Slice valslice(val, len + BlobDB::kTTLSuffixLength);
|
||||
|
||||
ASSERT_OK(blobdb_->Put(wo, dcfh, keyslice, valslice));
|
||||
delete[] val;
|
||||
}
|
||||
|
||||
// TODO(yiwu): Use sync point to properly trigger GC and check result.
|
||||
// Env::Default()->SleepForMicroseconds(120 * 1000 * 1000);
|
||||
}
|
||||
|
||||
TEST_F(BlobDBTest, GCTest) {
|
||||
BlobDBOptionsImpl bdboptions;
|
||||
bdboptions.ttl_range_secs = 30;
|
||||
bdboptions.gc_file_pct = 100;
|
||||
|
||||
Reopen(bdboptions);
|
||||
|
||||
WriteOptions wo;
|
||||
ReadOptions ro;
|
||||
std::string value;
|
||||
Random rnd(301);
|
||||
|
||||
ColumnFamilyHandle *dcfh = blobdb_->DefaultColumnFamily();
|
||||
|
||||
for (size_t i = 0; i < 100; i++) {
|
||||
int len = rnd.Next() % kMaxBlobSize;
|
||||
if (!len) continue;
|
||||
|
||||
char *val = new char[len + 1];
|
||||
gen_random(val, len);
|
||||
|
||||
std::string key("key");
|
||||
key += std::to_string(i);
|
||||
|
||||
Slice keyslice(key);
|
||||
Slice valslice(val, len + 1);
|
||||
|
||||
int ttl = 30;
|
||||
|
||||
ASSERT_OK(blobdb_->PutWithTTL(wo, dcfh, keyslice, valslice, ttl));
|
||||
delete[] val;
|
||||
}
|
||||
|
||||
// TODO(yiwu): Use sync point to properly trigger GC and check result.
|
||||
// Env::Default()->SleepForMicroseconds(240 * 1000 * 1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(BlobDBTest, DISABLED_MultipleWriters) {
|
||||
BlobDBOptionsImpl bdboptions;
|
||||
Reopen(bdboptions);
|
||||
|
||||
ASSERT_TRUE(blobdb_ != nullptr);
|
||||
Open();
|
||||
|
||||
std::vector<std::thread> workers;
|
||||
for (size_t ii = 0; ii < 10; ii++)
|
||||
@ -454,55 +239,23 @@ TEST_F(BlobDBTest, DISABLED_MultipleWriters) {
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
Env::Default()->SleepForMicroseconds(180 * 1000 * 1000);
|
||||
// ASSERT_OK(blobdb_->PutWithTTL(wo, dcfh, "bar", "v2", 60));
|
||||
// ASSERT_OK(blobdb_->Get(ro, dcfh, "foo", &value));
|
||||
// ASSERT_EQ("v1", value);
|
||||
// ASSERT_OK(blobdb_->Get(ro, dcfh, "bar", &value));
|
||||
// ASSERT_EQ("v2", value);
|
||||
}
|
||||
|
||||
TEST_F(BlobDBTest, Large) {
|
||||
BlobDBOptionsImpl bdboptions;
|
||||
Options options;
|
||||
Reopen(bdboptions, options);
|
||||
|
||||
WriteOptions wo;
|
||||
ReadOptions ro;
|
||||
std::string value1, value2, value3;
|
||||
Random rnd(301);
|
||||
ColumnFamilyHandle* dcfh = blobdb_->DefaultColumnFamily();
|
||||
|
||||
value1.assign(8999, '1');
|
||||
ASSERT_OK(blobdb_->PutWithTTL(wo, dcfh, "foo", value1, 3600));
|
||||
value2.assign(9001, '2');
|
||||
ASSERT_OK(blobdb_->PutWithTTL(wo, dcfh, "bar", value2, 3600));
|
||||
test::RandomString(&rnd, 13333, &value3);
|
||||
ASSERT_OK(blobdb_->PutWithTTL(wo, dcfh, "barfoo", value3, 3600));
|
||||
|
||||
std::string value;
|
||||
ASSERT_OK(blobdb_->Get(ro, dcfh, "foo", &value));
|
||||
ASSERT_EQ(value1, value);
|
||||
ASSERT_OK(blobdb_->Get(ro, dcfh, "bar", &value));
|
||||
ASSERT_EQ(value2, value);
|
||||
ASSERT_OK(blobdb_->Get(ro, dcfh, "barfoo", &value));
|
||||
ASSERT_EQ(value3, value);
|
||||
}
|
||||
|
||||
// Test sequence number store in blob file is correct.
|
||||
TEST_F(BlobDBTest, SequenceNumber) {
|
||||
Random rnd(223);
|
||||
Reopen(BlobDBOptionsImpl(), Options());
|
||||
SequenceNumber sequence = blobdb_->GetLatestSequenceNumber();
|
||||
BlobDBImpl *blobdb_impl = reinterpret_cast<BlobDBImpl *>(blobdb_);
|
||||
Random rnd(301);
|
||||
BlobDBOptionsImpl bdb_options;
|
||||
bdb_options.disable_background_tasks = true;
|
||||
Open(bdb_options);
|
||||
SequenceNumber sequence = blob_db_->GetLatestSequenceNumber();
|
||||
BlobDBImpl *blob_db_impl = reinterpret_cast<BlobDBImpl *>(blob_db_);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
std::string key = "key" + ToString(i);
|
||||
PutRandom(key, &rnd);
|
||||
sequence += 1;
|
||||
ASSERT_EQ(sequence, blobdb_->GetLatestSequenceNumber());
|
||||
ASSERT_EQ(sequence, blob_db_->GetLatestSequenceNumber());
|
||||
SequenceNumber actual_sequence = 0;
|
||||
ASSERT_OK(blobdb_impl->TEST_GetSequenceNumber(key, &actual_sequence));
|
||||
ASSERT_OK(blob_db_impl->TEST_GetSequenceNumber(key, &actual_sequence));
|
||||
ASSERT_EQ(sequence, actual_sequence);
|
||||
}
|
||||
for (int i = 0; i < 100; i++) {
|
||||
@ -512,15 +265,15 @@ TEST_F(BlobDBTest, SequenceNumber) {
|
||||
std::string value = test::RandomHumanReadableString(&rnd, 1000);
|
||||
ASSERT_OK(batch.Put("key" + ToString(i) + "-" + ToString(k), value));
|
||||
}
|
||||
ASSERT_OK(blobdb_->Write(WriteOptions(), &batch));
|
||||
ASSERT_OK(blob_db_->Write(WriteOptions(), &batch));
|
||||
for (size_t k = 0; k < batch_size; k++) {
|
||||
std::string key = "key" + ToString(i) + "-" + ToString(k);
|
||||
sequence++;
|
||||
SequenceNumber actual_sequence;
|
||||
ASSERT_OK(blobdb_impl->TEST_GetSequenceNumber(key, &actual_sequence));
|
||||
ASSERT_OK(blob_db_impl->TEST_GetSequenceNumber(key, &actual_sequence));
|
||||
ASSERT_EQ(sequence, actual_sequence);
|
||||
}
|
||||
ASSERT_EQ(sequence, blobdb_->GetLatestSequenceNumber());
|
||||
ASSERT_EQ(sequence, blob_db_->GetLatestSequenceNumber());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user