mirror of
https://github.com/facebook/rocksdb.git
synced 2026-07-08 15:15:23 +08:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aad2110823 | |||
| a143ef9b38 | |||
| b3ed08129b | |||
| 854d236361 | |||
| 200c05a23f | |||
| fa798e9e28 | |||
| 658a3ce2fa | |||
| 6b34021fc2 | |||
| 71046971f0 | |||
| 861f6e48e4 | |||
| 7edb92b843 | |||
| 22bb7c754b | |||
| 8eb552bf4d | |||
| 0c4040681a | |||
| 08740b15a4 | |||
| e0aa19a94e | |||
| f1a60e5c3e | |||
| 87d6eb2f6b | |||
| 9262061b0d | |||
| 5e9f3a9aa7 | |||
| 433541823c | |||
| 4734dbb742 | |||
| 72fcbf055d | |||
| 5b76338c01 | |||
| 11c65021fb | |||
| 1d8c57db23 | |||
| 5f2c136c32 | |||
| 8866448001 | |||
| 4012ca1c7b | |||
| e2a093a6c3 | |||
| eeb90c7ee9 | |||
| 5e73c4d4ad | |||
| 1565dab809 | |||
| 0e422308aa |
@@ -1,6 +1,6 @@
|
||||
rocksdb: A persistent key-value store for flash storage
|
||||
Authors: * The Facebook Database Engineering Team
|
||||
* Build on earlier work on leveldb by Sanjay Ghemawat
|
||||
* Build on earlier work on leveldb by Sanjay Ghemawat
|
||||
(sanjay@google.com) and Jeff Dean (jeff@google.com)
|
||||
|
||||
This code is a library that forms the core building block for a fast
|
||||
@@ -19,64 +19,64 @@ persistent key/value store.
|
||||
See doc/index.html for more explanation.
|
||||
See doc/impl.html for a brief overview of the implementation.
|
||||
|
||||
The public interface is in include/*.h. Callers should not include or
|
||||
The public interface is in include/*. Callers should not include or
|
||||
rely on the details of any other header files in this package. Those
|
||||
internal APIs may be changed without warning.
|
||||
|
||||
Guide to header files:
|
||||
|
||||
include/db.h
|
||||
include/rocksdb/db.h
|
||||
Main interface to the DB: Start here
|
||||
|
||||
include/options.h
|
||||
include/rocksdb/options.h
|
||||
Control over the behavior of an entire database, and also
|
||||
control over the behavior of individual reads and writes.
|
||||
|
||||
include/comparator.h
|
||||
include/rocksdb/comparator.h
|
||||
Abstraction for user-specified comparison function. If you want
|
||||
just bytewise comparison of keys, you can use the default comparator,
|
||||
but clients can write their own comparator implementations if they
|
||||
want custom ordering (e.g. to handle different character
|
||||
encodings, etc.)
|
||||
|
||||
include/iterator.h
|
||||
include/rocksdb/iterator.h
|
||||
Interface for iterating over data. You can get an iterator
|
||||
from a DB object.
|
||||
|
||||
include/write_batch.h
|
||||
include/rocksdb/write_batch.h
|
||||
Interface for atomically applying multiple updates to a database.
|
||||
|
||||
include/slice.h
|
||||
include/rocksdb/slice.h
|
||||
A simple module for maintaining a pointer and a length into some
|
||||
other byte array.
|
||||
|
||||
include/status.h
|
||||
include/rocksdb/status.h
|
||||
Status is returned from many of the public interfaces and is used
|
||||
to report success and various kinds of errors.
|
||||
|
||||
include/env.h
|
||||
include/rocksdb/env.h
|
||||
Abstraction of the OS environment. A posix implementation of
|
||||
this interface is in util/env_posix.cc
|
||||
|
||||
include/table_builder.h
|
||||
include/rocksdb/table_builder.h
|
||||
Lower-level modules that most clients probably won't use directly
|
||||
|
||||
include/cache.h
|
||||
include/rocksdb/cache.h
|
||||
An API for the block cache.
|
||||
|
||||
include/compaction_filter.h
|
||||
include/rocksdb/compaction_filter.h
|
||||
An API for a application filter invoked on every compaction.
|
||||
|
||||
include/filter_policy.h
|
||||
include/rocksdb/filter_policy.h
|
||||
An API for configuring a bloom filter.
|
||||
|
||||
include/memtablerep.h
|
||||
include/rocksdb/memtablerep.h
|
||||
An API for implementing a memtable.
|
||||
|
||||
include/statistics.h
|
||||
include/rocksdb/statistics.h
|
||||
An API to retrieve various database statistics.
|
||||
|
||||
include/transaction_log_iterator.h
|
||||
include/rocksdb/transaction_log.h
|
||||
An API to retrieve transaction logs from a database.
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
* Detailed instructions on how to compile using fbcode and jemalloc
|
||||
|
||||
* Latest release is 2.3.fb
|
||||
* Latest release is 2.4.fb
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@
|
||||
#include "rocksdb/iterator.h"
|
||||
#include "util/stop_watch.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
Status BuildTable(const std::string& dbname,
|
||||
Env* env,
|
||||
@@ -204,4 +204,4 @@ Status BuildTable(const std::string& dbname,
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@
|
||||
#include "rocksdb/status.h"
|
||||
#include "rocksdb/types.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
struct Options;
|
||||
struct FileMetaData;
|
||||
@@ -36,6 +36,6 @@ extern Status BuildTable(const std::string& dbname,
|
||||
const SequenceNumber newest_snapshot,
|
||||
const SequenceNumber earliest_seqno_in_memtable);
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_BUILDER_H_
|
||||
|
||||
@@ -16,28 +16,28 @@
|
||||
#include "rocksdb/status.h"
|
||||
#include "rocksdb/write_batch.h"
|
||||
|
||||
using leveldb::Cache;
|
||||
using leveldb::Comparator;
|
||||
using leveldb::CompressionType;
|
||||
using leveldb::DB;
|
||||
using leveldb::Env;
|
||||
using leveldb::FileLock;
|
||||
using leveldb::FilterPolicy;
|
||||
using leveldb::Iterator;
|
||||
using leveldb::Logger;
|
||||
using leveldb::NewBloomFilterPolicy;
|
||||
using leveldb::NewLRUCache;
|
||||
using leveldb::Options;
|
||||
using leveldb::RandomAccessFile;
|
||||
using leveldb::Range;
|
||||
using leveldb::ReadOptions;
|
||||
using leveldb::SequentialFile;
|
||||
using leveldb::Slice;
|
||||
using leveldb::Snapshot;
|
||||
using leveldb::Status;
|
||||
using leveldb::WritableFile;
|
||||
using leveldb::WriteBatch;
|
||||
using leveldb::WriteOptions;
|
||||
using rocksdb::Cache;
|
||||
using rocksdb::Comparator;
|
||||
using rocksdb::CompressionType;
|
||||
using rocksdb::DB;
|
||||
using rocksdb::Env;
|
||||
using rocksdb::FileLock;
|
||||
using rocksdb::FilterPolicy;
|
||||
using rocksdb::Iterator;
|
||||
using rocksdb::Logger;
|
||||
using rocksdb::NewBloomFilterPolicy;
|
||||
using rocksdb::NewLRUCache;
|
||||
using rocksdb::Options;
|
||||
using rocksdb::RandomAccessFile;
|
||||
using rocksdb::Range;
|
||||
using rocksdb::ReadOptions;
|
||||
using rocksdb::SequentialFile;
|
||||
using rocksdb::Slice;
|
||||
using rocksdb::Snapshot;
|
||||
using rocksdb::Status;
|
||||
using rocksdb::WritableFile;
|
||||
using rocksdb::WriteBatch;
|
||||
using rocksdb::WriteOptions;
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "util/testharness.h"
|
||||
#include "util/testutil.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
static const int kValueSize = 1000;
|
||||
|
||||
@@ -68,7 +68,7 @@ class CorruptionTest {
|
||||
void RepairDB() {
|
||||
delete db_;
|
||||
db_ = nullptr;
|
||||
ASSERT_OK(::leveldb::RepairDB(dbname_, options_));
|
||||
ASSERT_OK(::rocksdb::RepairDB(dbname_, options_));
|
||||
}
|
||||
|
||||
void Build(int n) {
|
||||
@@ -354,8 +354,8 @@ TEST(CorruptionTest, UnrelatedKeys) {
|
||||
ASSERT_EQ(Value(1000, &tmp2).ToString(), v);
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
return rocksdb::test::RunAllTests();
|
||||
}
|
||||
|
||||
+143
-58
@@ -13,6 +13,7 @@
|
||||
#include "rocksdb/cache.h"
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "rocksdb/memtablerep.h"
|
||||
#include "rocksdb/write_batch.h"
|
||||
#include "rocksdb/statistics.h"
|
||||
#include "port/port.h"
|
||||
@@ -79,6 +80,7 @@ static const char* FLAGS_benchmarks =
|
||||
"snappycomp,"
|
||||
"snappyuncomp,"
|
||||
"acquireload,"
|
||||
"fillfromstdin,"
|
||||
;
|
||||
// the maximum size of key in bytes
|
||||
static const int MAX_KEY_SIZE = 128;
|
||||
@@ -151,15 +153,21 @@ static int FLAGS_min_write_buffer_number_to_merge = 0;
|
||||
static int FLAGS_max_background_compactions = 0;
|
||||
|
||||
// style of compaction: level-based vs universal
|
||||
static leveldb::CompactionStyle FLAGS_compaction_style = leveldb::kCompactionStyleLevel;
|
||||
static rocksdb::CompactionStyle FLAGS_compaction_style = rocksdb::kCompactionStyleLevel;
|
||||
|
||||
// Percentage flexibility while comparing file size
|
||||
// (for universal compaction only).
|
||||
static int FLAGS_universal_size_ratio = 1;
|
||||
static int FLAGS_universal_size_ratio = 0;
|
||||
|
||||
// The minimum number of files in a single compaction run
|
||||
// (for universal compaction only).
|
||||
static int FLAGS_compaction_universal_min_merge_width = 2;
|
||||
static int FLAGS_universal_min_merge_width = 0;
|
||||
|
||||
// The max number of files to compact in universal style compaction
|
||||
static unsigned int FLAGS_universal_max_merge_width = 0;
|
||||
|
||||
// The max size amplification for universal style compaction
|
||||
static unsigned int FLAGS_universal_max_size_amplification_percent = 0;
|
||||
|
||||
// Number of bytes to use as a cache of uncompressed data.
|
||||
// Negative means use default settings.
|
||||
@@ -193,7 +201,7 @@ static bool FLAGS_verify_checksum = false;
|
||||
|
||||
// Database statistics
|
||||
static bool FLAGS_statistics = false;
|
||||
static class std::shared_ptr<leveldb::Statistics> dbstats;
|
||||
static class std::shared_ptr<rocksdb::Statistics> dbstats;
|
||||
|
||||
// Number of write operations to do. If negative, do FLAGS_num reads.
|
||||
static long FLAGS_writes = -1;
|
||||
@@ -271,8 +279,8 @@ static int FLAGS_disable_seek_compaction = false;
|
||||
static uint64_t FLAGS_delete_obsolete_files_period_micros = 0;
|
||||
|
||||
// Algorithm used to compress the database
|
||||
static enum leveldb::CompressionType FLAGS_compression_type =
|
||||
leveldb::kSnappyCompression;
|
||||
static enum rocksdb::CompressionType FLAGS_compression_type =
|
||||
rocksdb::kSnappyCompression;
|
||||
|
||||
// If non-negative, compression starts from this level. Levels with number
|
||||
// < FLAGS_min_level_to_compress are not compressed.
|
||||
@@ -282,7 +290,7 @@ static int FLAGS_min_level_to_compress = -1;
|
||||
static int FLAGS_table_cache_numshardbits = 4;
|
||||
|
||||
// posix or hdfs environment
|
||||
static leveldb::Env* FLAGS_env = leveldb::Env::Default();
|
||||
static rocksdb::Env* FLAGS_env = rocksdb::Env::Default();
|
||||
|
||||
// Stats are reported every N operations when this is greater
|
||||
// than zero. When 0 the interval grows over time.
|
||||
@@ -331,11 +339,11 @@ static bool FLAGS_use_mmap_writes;
|
||||
|
||||
// Advise random access on table file open
|
||||
static bool FLAGS_advise_random_on_open =
|
||||
leveldb::Options().advise_random_on_open;
|
||||
rocksdb::Options().advise_random_on_open;
|
||||
|
||||
// Access pattern advice when a file is compacted
|
||||
static auto FLAGS_compaction_fadvice =
|
||||
leveldb::Options().access_hint_on_compaction_start;
|
||||
rocksdb::Options().access_hint_on_compaction_start;
|
||||
|
||||
// Use multiget to access a series of keys instead of get
|
||||
static bool FLAGS_use_multiget = false;
|
||||
@@ -350,13 +358,13 @@ static bool FLAGS_warn_missing_keys = true;
|
||||
|
||||
// Use adaptive mutex
|
||||
static auto FLAGS_use_adaptive_mutex =
|
||||
leveldb::Options().use_adaptive_mutex;
|
||||
rocksdb::Options().use_adaptive_mutex;
|
||||
|
||||
// Allows OS to incrementally sync files to disk while they are being
|
||||
// written, in the background. Issue one request for every bytes_per_sync
|
||||
// written. 0 turns it off.
|
||||
static auto FLAGS_bytes_per_sync =
|
||||
leveldb::Options().bytes_per_sync;
|
||||
rocksdb::Options().bytes_per_sync;
|
||||
|
||||
// On true, deletes use bloom-filter and drop the delete if key not present
|
||||
static bool FLAGS_filter_deletes = false;
|
||||
@@ -378,7 +386,10 @@ static enum RepFactory FLAGS_rep_factory;
|
||||
// The possible merge operators are defined in utilities/merge_operators.h
|
||||
static std::string FLAGS_merge_operator = "";
|
||||
|
||||
namespace leveldb {
|
||||
static auto FLAGS_purge_log_after_memtable_flush =
|
||||
rocksdb::Options().purge_log_after_memtable_flush;
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
// Helper for quickly generating random data.
|
||||
class RandomGenerator {
|
||||
@@ -680,16 +691,16 @@ class Benchmark {
|
||||
fprintf(stdout, "Write rate limit: %d\n", FLAGS_writes_per_second);
|
||||
|
||||
switch (FLAGS_compression_type) {
|
||||
case leveldb::kNoCompression:
|
||||
case rocksdb::kNoCompression:
|
||||
fprintf(stdout, "Compression: none\n");
|
||||
break;
|
||||
case leveldb::kSnappyCompression:
|
||||
case rocksdb::kSnappyCompression:
|
||||
fprintf(stdout, "Compression: snappy\n");
|
||||
break;
|
||||
case leveldb::kZlibCompression:
|
||||
case rocksdb::kZlibCompression:
|
||||
fprintf(stdout, "Compression: zlib\n");
|
||||
break;
|
||||
case leveldb::kBZip2Compression:
|
||||
case rocksdb::kBZip2Compression:
|
||||
fprintf(stdout, "Compression: bzip2\n");
|
||||
break;
|
||||
}
|
||||
@@ -724,7 +735,7 @@ class Benchmark {
|
||||
"WARNING: Assertions are enabled; benchmarks unnecessarily slow\n");
|
||||
#endif
|
||||
|
||||
if (FLAGS_compression_type != leveldb::kNoCompression) {
|
||||
if (FLAGS_compression_type != rocksdb::kNoCompression) {
|
||||
// The test string should not be too small.
|
||||
const int len = FLAGS_block_size;
|
||||
char* text = (char*) malloc(len+1);
|
||||
@@ -897,6 +908,9 @@ class Benchmark {
|
||||
} else if (name == Slice("fillrandom")) {
|
||||
fresh_db = true;
|
||||
method = &Benchmark::WriteRandom;
|
||||
} else if (name == Slice("fillfromstdin")) {
|
||||
fresh_db = true;
|
||||
method = &Benchmark::WriteFromStdin;
|
||||
} else if (name == Slice("filluniquerandom")) {
|
||||
fresh_db = true;
|
||||
if (num_threads > 1) {
|
||||
@@ -1182,9 +1196,6 @@ class Benchmark {
|
||||
FLAGS_min_write_buffer_number_to_merge;
|
||||
options.max_background_compactions = FLAGS_max_background_compactions;
|
||||
options.compaction_style = FLAGS_compaction_style;
|
||||
options.compaction_options_universal.size_ratio = FLAGS_universal_size_ratio;
|
||||
options.compaction_options_universal.min_merge_width =
|
||||
FLAGS_compaction_universal_min_merge_width;
|
||||
options.block_size = FLAGS_block_size;
|
||||
options.filter_policy = filter_policy_;
|
||||
options.prefix_extractor = FLAGS_use_prefix_blooms ? prefix_extractor_
|
||||
@@ -1226,6 +1237,7 @@ class Benchmark {
|
||||
);
|
||||
break;
|
||||
}
|
||||
options.purge_log_after_memtable_flush = FLAGS_purge_log_after_memtable_flush;
|
||||
if (FLAGS_max_bytes_for_level_multiplier_additional.size() > 0) {
|
||||
if (FLAGS_max_bytes_for_level_multiplier_additional.size() !=
|
||||
(unsigned int)FLAGS_num_levels) {
|
||||
@@ -1286,6 +1298,24 @@ class Benchmark {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// set universal style compaction configurations, if applicable
|
||||
if (FLAGS_universal_size_ratio != 0) {
|
||||
options.compaction_options_universal.size_ratio =
|
||||
FLAGS_universal_size_ratio;
|
||||
}
|
||||
if (FLAGS_universal_min_merge_width != 0) {
|
||||
options.compaction_options_universal.min_merge_width =
|
||||
FLAGS_universal_min_merge_width;
|
||||
}
|
||||
if (FLAGS_universal_max_merge_width != 0) {
|
||||
options.compaction_options_universal.max_merge_width =
|
||||
FLAGS_universal_max_merge_width;
|
||||
}
|
||||
if (FLAGS_universal_max_size_amplification_percent != 0) {
|
||||
options.compaction_options_universal.max_size_amplification_percent =
|
||||
FLAGS_universal_max_size_amplification_percent;
|
||||
}
|
||||
|
||||
Status s;
|
||||
if(FLAGS_read_only) {
|
||||
s = DB::OpenForReadOnly(options, FLAGS_db, &db_);
|
||||
@@ -1317,6 +1347,54 @@ class Benchmark {
|
||||
DoWrite(thread, UNIQUE_RANDOM);
|
||||
}
|
||||
|
||||
void writeOrFail(WriteBatch& batch) {
|
||||
Status s = db_->Write(write_options_, &batch);
|
||||
if (!s.ok()) {
|
||||
fprintf(stderr, "put error: %s\n", s.ToString().c_str());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteFromStdin(ThreadState* thread) {
|
||||
size_t count = 0;
|
||||
WriteBatch batch;
|
||||
const size_t bufferLen = 32 << 20;
|
||||
unique_ptr<char[]> line = unique_ptr<char[]>(new char[bufferLen]);
|
||||
char* linep = line.get();
|
||||
const int batchSize = 100 << 10;
|
||||
const char columnSeparator = '\t';
|
||||
const char lineSeparator = '\n';
|
||||
|
||||
while (fgets(linep, bufferLen, stdin) != nullptr) {
|
||||
++count;
|
||||
char* tab = std::find(linep, linep + bufferLen, columnSeparator);
|
||||
if (tab == linep + bufferLen) {
|
||||
fprintf(stderr, "[Error] No Key delimiter TAB at line %ld\n", count);
|
||||
continue;
|
||||
}
|
||||
Slice key(linep, tab - linep);
|
||||
tab++;
|
||||
char* endLine = std::find(tab, linep + bufferLen, lineSeparator);
|
||||
if (endLine == linep + bufferLen) {
|
||||
fprintf(stderr, "[Error] No ENTER at end of line # %ld\n", count);
|
||||
continue;
|
||||
}
|
||||
Slice value(tab, endLine - tab);
|
||||
thread->stats.FinishedSingleOp(db_);
|
||||
thread->stats.AddBytes(endLine - linep - 1);
|
||||
|
||||
if (batch.Count() < batchSize) {
|
||||
batch.Put(key, value);
|
||||
continue;
|
||||
}
|
||||
writeOrFail(batch);
|
||||
batch.Clear();
|
||||
}
|
||||
if (batch.Count() > 0) {
|
||||
writeOrFail(batch);
|
||||
}
|
||||
}
|
||||
|
||||
void DoWrite(ThreadState* thread, WriteMode write_mode) {
|
||||
const int test_duration = write_mode == RANDOM ? FLAGS_duration : 0;
|
||||
const int num_ops = writes_ == 0 ? num_ : writes_ ;
|
||||
@@ -2225,28 +2303,24 @@ class Benchmark {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
leveldb::InstallStackTraceHandler();
|
||||
rocksdb::InstallStackTraceHandler();
|
||||
|
||||
FLAGS_write_buffer_size = leveldb::Options().write_buffer_size;
|
||||
FLAGS_max_write_buffer_number = leveldb::Options().max_write_buffer_number;
|
||||
FLAGS_write_buffer_size = rocksdb::Options().write_buffer_size;
|
||||
FLAGS_max_write_buffer_number = rocksdb::Options().max_write_buffer_number;
|
||||
FLAGS_min_write_buffer_number_to_merge =
|
||||
leveldb::Options().min_write_buffer_number_to_merge;
|
||||
FLAGS_open_files = leveldb::Options().max_open_files;
|
||||
rocksdb::Options().min_write_buffer_number_to_merge;
|
||||
FLAGS_open_files = rocksdb::Options().max_open_files;
|
||||
FLAGS_max_background_compactions =
|
||||
leveldb::Options().max_background_compactions;
|
||||
FLAGS_compaction_style = leveldb::Options().compaction_style;
|
||||
FLAGS_universal_size_ratio =
|
||||
leveldb::Options().compaction_options_universal.size_ratio;
|
||||
FLAGS_compaction_universal_min_merge_width =
|
||||
leveldb::Options().compaction_options_universal.min_merge_width;
|
||||
rocksdb::Options().max_background_compactions;
|
||||
FLAGS_compaction_style = rocksdb::Options().compaction_style;
|
||||
// Compression test code above refers to FLAGS_block_size
|
||||
FLAGS_block_size = leveldb::Options().block_size;
|
||||
FLAGS_use_os_buffer = leveldb::EnvOptions().use_os_buffer;
|
||||
FLAGS_use_mmap_reads = leveldb::EnvOptions().use_mmap_reads;
|
||||
FLAGS_use_mmap_writes = leveldb::EnvOptions().use_mmap_writes;
|
||||
FLAGS_block_size = rocksdb::Options().block_size;
|
||||
FLAGS_use_os_buffer = rocksdb::EnvOptions().use_os_buffer;
|
||||
FLAGS_use_mmap_reads = rocksdb::EnvOptions().use_mmap_reads;
|
||||
FLAGS_use_mmap_writes = rocksdb::EnvOptions().use_mmap_writes;
|
||||
|
||||
std::string default_db_path;
|
||||
|
||||
@@ -2259,7 +2333,7 @@ int main(int argc, char** argv) {
|
||||
char buf[2048];
|
||||
char str[512];
|
||||
|
||||
if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) {
|
||||
if (rocksdb::Slice(argv[i]).starts_with("--benchmarks=")) {
|
||||
FLAGS_benchmarks = argv[i] + strlen("--benchmarks=");
|
||||
} else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) {
|
||||
FLAGS_compression_ratio = d;
|
||||
@@ -2299,8 +2373,8 @@ int main(int argc, char** argv) {
|
||||
} else {
|
||||
FLAGS_key_size = n;
|
||||
}
|
||||
} else if (sscanf(argv[i], "--write_buffer_size=%d%c", &n, &junk) == 1) {
|
||||
FLAGS_write_buffer_size = n;
|
||||
} else if (sscanf(argv[i], "--write_buffer_size=%lld%c", &ll, &junk) == 1) {
|
||||
FLAGS_write_buffer_size = ll;
|
||||
} else if (sscanf(argv[i], "--max_write_buffer_number=%d%c", &n, &junk) == 1) {
|
||||
FLAGS_max_write_buffer_number = n;
|
||||
} else if (sscanf(argv[i], "--min_write_buffer_number_to_merge=%d%c",
|
||||
@@ -2310,12 +2384,7 @@ int main(int argc, char** argv) {
|
||||
== 1) {
|
||||
FLAGS_max_background_compactions = n;
|
||||
} else if (sscanf(argv[i], "--compaction_style=%d%c", &n, &junk) == 1) {
|
||||
FLAGS_compaction_style = (leveldb::CompactionStyle)n;
|
||||
} else if (sscanf(argv[i], "--universal_size_ratio=%d%c", &n, &junk) == 1) {
|
||||
FLAGS_universal_size_ratio = n;
|
||||
} else if (sscanf(argv[i], "--universal_min_merge_width=%d%c",
|
||||
&n, &junk) == 1) {
|
||||
FLAGS_compaction_universal_min_merge_width = n;
|
||||
FLAGS_compaction_style = (rocksdb::CompactionStyle)n;
|
||||
} else if (sscanf(argv[i], "--cache_size=%ld%c", &l, &junk) == 1) {
|
||||
FLAGS_cache_size = l;
|
||||
} else if (sscanf(argv[i], "--block_size=%d%c", &n, &junk) == 1) {
|
||||
@@ -2355,7 +2424,7 @@ int main(int argc, char** argv) {
|
||||
} else if (sscanf(argv[i], "--statistics=%d%c", &n, &junk) == 1 &&
|
||||
(n == 0 || n == 1)) {
|
||||
if (n == 1) {
|
||||
dbstats = leveldb::CreateDBStatistics();
|
||||
dbstats = rocksdb::CreateDBStatistics();
|
||||
FLAGS_statistics = true;
|
||||
}
|
||||
} else if (sscanf(argv[i], "--writes=%lld%c", &ll, &junk) == 1) {
|
||||
@@ -2387,7 +2456,7 @@ int main(int argc, char** argv) {
|
||||
(n == 0 || n == 1)) {
|
||||
FLAGS_get_approx = n;
|
||||
} else if (sscanf(argv[i], "--hdfs=%s", buf) == 1) {
|
||||
FLAGS_env = new leveldb::HdfsEnv(buf);
|
||||
FLAGS_env = new rocksdb::HdfsEnv(buf);
|
||||
} else if (sscanf(argv[i], "--num_levels=%d%c",
|
||||
&n, &junk) == 1) {
|
||||
FLAGS_num_levels = n;
|
||||
@@ -2409,7 +2478,7 @@ int main(int argc, char** argv) {
|
||||
} else if (sscanf(argv[i],
|
||||
"--max_bytes_for_level_multiplier_additional=%s%c",
|
||||
str, &junk) == 1) {
|
||||
std::vector<std::string> fanout = leveldb::stringSplit(str, ',');
|
||||
std::vector<std::string> fanout = rocksdb::stringSplit(str, ',');
|
||||
for (unsigned int j= 0; j < fanout.size(); j++) {
|
||||
FLAGS_max_bytes_for_level_multiplier_additional.push_back(
|
||||
std::stoi(fanout[j]));
|
||||
@@ -2423,13 +2492,13 @@ int main(int argc, char** argv) {
|
||||
} else if (strncmp(argv[i], "--compression_type=", 19) == 0) {
|
||||
const char* ctype = argv[i] + 19;
|
||||
if (!strcasecmp(ctype, "none"))
|
||||
FLAGS_compression_type = leveldb::kNoCompression;
|
||||
FLAGS_compression_type = rocksdb::kNoCompression;
|
||||
else if (!strcasecmp(ctype, "snappy"))
|
||||
FLAGS_compression_type = leveldb::kSnappyCompression;
|
||||
FLAGS_compression_type = rocksdb::kSnappyCompression;
|
||||
else if (!strcasecmp(ctype, "zlib"))
|
||||
FLAGS_compression_type = leveldb::kZlibCompression;
|
||||
FLAGS_compression_type = rocksdb::kZlibCompression;
|
||||
else if (!strcasecmp(ctype, "bzip2"))
|
||||
FLAGS_compression_type = leveldb::kBZip2Compression;
|
||||
FLAGS_compression_type = rocksdb::kBZip2Compression;
|
||||
else {
|
||||
fprintf(stdout, "Cannot parse %s\n", argv[i]);
|
||||
}
|
||||
@@ -2492,13 +2561,13 @@ int main(int argc, char** argv) {
|
||||
FLAGS_advise_random_on_open = n;
|
||||
} else if (sscanf(argv[i], "--compaction_fadvice=%s", buf) == 1) {
|
||||
if (!strcasecmp(buf, "NONE"))
|
||||
FLAGS_compaction_fadvice = leveldb::Options::NONE;
|
||||
FLAGS_compaction_fadvice = rocksdb::Options::NONE;
|
||||
else if (!strcasecmp(buf, "NORMAL"))
|
||||
FLAGS_compaction_fadvice = leveldb::Options::NORMAL;
|
||||
FLAGS_compaction_fadvice = rocksdb::Options::NORMAL;
|
||||
else if (!strcasecmp(buf, "SEQUENTIAL"))
|
||||
FLAGS_compaction_fadvice = leveldb::Options::SEQUENTIAL;
|
||||
FLAGS_compaction_fadvice = rocksdb::Options::SEQUENTIAL;
|
||||
else if (!strcasecmp(buf, "WILLNEED"))
|
||||
FLAGS_compaction_fadvice = leveldb::Options::WILLNEED;
|
||||
FLAGS_compaction_fadvice = rocksdb::Options::WILLNEED;
|
||||
else {
|
||||
fprintf(stdout, "Unknown compaction fadvice:%s\n", buf);
|
||||
}
|
||||
@@ -2518,6 +2587,22 @@ int main(int argc, char** argv) {
|
||||
FLAGS_filter_deletes = n;
|
||||
} else if (sscanf(argv[i], "--merge_operator=%s", buf) == 1) {
|
||||
FLAGS_merge_operator = buf;
|
||||
} else if (sscanf(argv[i], "--purge_log_after_memtable_flush=%d%c", &n, &junk)
|
||||
== 1 && (n == 0 || n ==1 )) {
|
||||
FLAGS_purge_log_after_memtable_flush = n;
|
||||
} else if (sscanf(argv[i], "--universal_size_ratio=%d%c",
|
||||
&n, &junk) == 1) {
|
||||
FLAGS_universal_size_ratio = n;
|
||||
} else if (sscanf(argv[i], "--universal_min_merge_width=%d%c",
|
||||
&n, &junk) == 1) {
|
||||
FLAGS_universal_min_merge_width = n;
|
||||
} else if (sscanf(argv[i], "--universal_max_merge_width=%d%c",
|
||||
&n, &junk) == 1) {
|
||||
FLAGS_universal_max_merge_width = n;
|
||||
} else if (sscanf(argv[i],
|
||||
"--universal_max_size_amplification_percent=%d%c",
|
||||
&n, &junk) == 1) {
|
||||
FLAGS_universal_max_size_amplification_percent = n;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid flag '%s'\n", argv[i]);
|
||||
exit(1);
|
||||
@@ -2530,12 +2615,12 @@ int main(int argc, char** argv) {
|
||||
|
||||
// Choose a location for the test database if none given with --db=<path>
|
||||
if (FLAGS_db == nullptr) {
|
||||
leveldb::Env::Default()->GetTestDirectory(&default_db_path);
|
||||
rocksdb::Env::Default()->GetTestDirectory(&default_db_path);
|
||||
default_db_path += "/dbbench";
|
||||
FLAGS_db = default_db_path.c_str();
|
||||
}
|
||||
|
||||
leveldb::Benchmark benchmark;
|
||||
rocksdb::Benchmark benchmark;
|
||||
benchmark.Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
+11
-8
@@ -13,7 +13,7 @@
|
||||
#include "port/port.h"
|
||||
#include "util/mutexlock.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
Status DBImpl::DisableFileDeletions() {
|
||||
MutexLock l(&mutex_);
|
||||
@@ -30,16 +30,19 @@ Status DBImpl::EnableFileDeletions() {
|
||||
}
|
||||
|
||||
Status DBImpl::GetLiveFiles(std::vector<std::string>& ret,
|
||||
uint64_t* manifest_file_size) {
|
||||
uint64_t* manifest_file_size,
|
||||
bool flush_memtable) {
|
||||
|
||||
*manifest_file_size = 0;
|
||||
|
||||
// flush all dirty data to disk.
|
||||
Status status = Flush(FlushOptions());
|
||||
if (!status.ok()) {
|
||||
Log(options_.info_log, "Cannot Flush data %s\n",
|
||||
status.ToString().c_str());
|
||||
return status;
|
||||
if (flush_memtable) {
|
||||
// flush all dirty data to disk.
|
||||
Status status = Flush(FlushOptions());
|
||||
if (!status.ok()) {
|
||||
Log(options_.info_log, "Cannot Flush data %s\n",
|
||||
status.ToString().c_str());
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
MutexLock l(&mutex_);
|
||||
|
||||
+129
-42
@@ -47,7 +47,7 @@
|
||||
#include "util/mutexlock.h"
|
||||
#include "util/stop_watch.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
void dumpLeveldbBuildVersion(Logger * log);
|
||||
|
||||
@@ -169,12 +169,14 @@ Options SanitizeOptions(const std::string& dbname,
|
||||
// function.
|
||||
auto factory = dynamic_cast<PrefixHashRepFactory*>(
|
||||
result.memtable_factory.get());
|
||||
if (factory != nullptr &&
|
||||
if (factory &&
|
||||
factory->GetTransform() != result.prefix_extractor) {
|
||||
Log(result.info_log, "A prefix hash representation factory was supplied "
|
||||
"whose prefix extractor does not match options.prefix_extractor. "
|
||||
"Falling back to skip list representation factory");
|
||||
result.memtable_factory = std::make_shared<SkipListFactory>();
|
||||
} else if (factory) {
|
||||
Log(result.info_log, "Prefix hash memtable rep is in use.");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -198,6 +200,7 @@ DBImpl::DBImpl(const Options& options, const std::string& dbname)
|
||||
logfile_number_(0),
|
||||
tmp_batch_(),
|
||||
bg_compaction_scheduled_(0),
|
||||
bg_flush_scheduled_(0),
|
||||
bg_logstats_scheduled_(false),
|
||||
manual_compaction_(nullptr),
|
||||
logger_(nullptr),
|
||||
@@ -265,7 +268,9 @@ DBImpl::~DBImpl() {
|
||||
}
|
||||
mutex_.Lock();
|
||||
shutting_down_.Release_Store(this); // Any non-nullptr value is ok
|
||||
while (bg_compaction_scheduled_ || bg_logstats_scheduled_) {
|
||||
while (bg_compaction_scheduled_ ||
|
||||
bg_flush_scheduled_ ||
|
||||
bg_logstats_scheduled_) {
|
||||
bg_cv_.Wait();
|
||||
}
|
||||
mutex_.Unlock();
|
||||
@@ -285,13 +290,17 @@ void DBImpl::TEST_Destroy_DBImpl() {
|
||||
|
||||
// wait till all background compactions are done.
|
||||
mutex_.Lock();
|
||||
while (bg_compaction_scheduled_ || bg_logstats_scheduled_) {
|
||||
while (bg_compaction_scheduled_ ||
|
||||
bg_flush_scheduled_ ||
|
||||
bg_logstats_scheduled_) {
|
||||
bg_cv_.Wait();
|
||||
}
|
||||
|
||||
// Prevent new compactions from occuring.
|
||||
bg_work_gate_closed_ = true;
|
||||
const int LargeNumber = 10000000;
|
||||
bg_compaction_scheduled_ += LargeNumber;
|
||||
|
||||
mutex_.Unlock();
|
||||
|
||||
// force release the lock file.
|
||||
@@ -420,6 +429,26 @@ void DBImpl::FindObsoleteFiles(DeletionState& deletion_state) {
|
||||
deletion_state.prevlognumber = versions_->PrevLogNumber();
|
||||
}
|
||||
|
||||
Status DBImpl::DeleteLogFile(uint64_t number) {
|
||||
Status s;
|
||||
auto filename = LogFileName(dbname_, number);
|
||||
if (options_.WAL_ttl_seconds > 0) {
|
||||
s = env_->RenameFile(filename,
|
||||
ArchivedLogFileName(dbname_, number));
|
||||
|
||||
if (!s.ok()) {
|
||||
Log(options_.info_log, "RenameFile logfile #%lu FAILED", number);
|
||||
}
|
||||
} else {
|
||||
s = env_->DeleteFile(filename);
|
||||
if(!s.ok()) {
|
||||
Log(options_.info_log, "Delete logfile #%lu FAILED", number);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
// Diffs the files listed in filenames and those that do not
|
||||
// belong to live files are posibly removed. If the removed file
|
||||
// is a sst file, then it returns the file number in files_to_evict.
|
||||
@@ -474,19 +503,9 @@ void DBImpl::PurgeObsoleteFiles(DeletionState& state) {
|
||||
state.files_to_evict.push_back(number);
|
||||
}
|
||||
Log(options_.info_log, "Delete type=%d #%lu", int(type), number);
|
||||
if (type == kLogFile && options_.WAL_ttl_seconds > 0) {
|
||||
Status st = env_->RenameFile(
|
||||
LogFileName(dbname_, number),
|
||||
ArchivedLogFileName(dbname_, number)
|
||||
);
|
||||
|
||||
if (!st.ok()) {
|
||||
Log(
|
||||
options_.info_log, "RenameFile type=%d #%lu FAILED",
|
||||
int(type),
|
||||
number
|
||||
);
|
||||
}
|
||||
if (type == kLogFile) {
|
||||
DeleteLogFile(number);
|
||||
} else {
|
||||
Status st = env_->DeleteFile(dbname_ + "/" + state.allfiles[i]);
|
||||
if (!st.ok()) {
|
||||
@@ -499,7 +518,7 @@ void DBImpl::PurgeObsoleteFiles(DeletionState& state) {
|
||||
}
|
||||
}
|
||||
|
||||
// Delete old log files.
|
||||
// Delete old info log files.
|
||||
size_t old_log_file_count = old_log_files.size();
|
||||
// NOTE: Currently we only support log purge when options_.db_log_dir is
|
||||
// located in `dbname` directory.
|
||||
@@ -904,7 +923,6 @@ Status DBImpl::CompactMemTable(bool* madeProgress) {
|
||||
}
|
||||
|
||||
// Save the contents of the earliest memtable as a new Table
|
||||
// This will release and re-acquire the mutex.
|
||||
uint64_t file_number;
|
||||
std::vector<MemTable*> mems;
|
||||
imm_.PickMemtablesToFlush(&mems);
|
||||
@@ -918,8 +936,10 @@ Status DBImpl::CompactMemTable(bool* madeProgress) {
|
||||
MemTable* m = mems[0];
|
||||
VersionEdit* edit = m->GetEdits();
|
||||
edit->SetPrevLogNumber(0);
|
||||
edit->SetLogNumber(m->GetLogNumber()); // Earlier logs no longer needed
|
||||
edit->SetLogNumber(m->GetNextLogNumber()); // Earlier logs no longer needed
|
||||
auto to_delete = m->GetLogNumber();
|
||||
|
||||
// This will release and re-acquire the mutex.
|
||||
Status s = WriteLevel0Table(mems, edit, &file_number);
|
||||
|
||||
if (s.ok() && shutting_down_.Acquire_Load()) {
|
||||
@@ -937,10 +957,19 @@ Status DBImpl::CompactMemTable(bool* madeProgress) {
|
||||
if (madeProgress) {
|
||||
*madeProgress = 1;
|
||||
}
|
||||
|
||||
MaybeScheduleLogDBDeployStats();
|
||||
// we could have deleted obsolete files here, but it is not
|
||||
// absolutely necessary because it could be also done as part
|
||||
// of other background compaction
|
||||
// TODO: if log deletion failed for any reason, we probably
|
||||
// should store the file number in the shared state, and retry
|
||||
// However, for now, PurgeObsoleteFiles will take care of that
|
||||
// anyways.
|
||||
if (options_.purge_log_after_memtable_flush &&
|
||||
!disable_delete_obsolete_files_ &&
|
||||
to_delete > 0) {
|
||||
mutex_.Unlock();
|
||||
DeleteLogFile(to_delete);
|
||||
mutex_.Lock();
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -997,10 +1026,10 @@ void DBImpl::ReFitLevel(int level, int target_level) {
|
||||
|
||||
// wait for all background threads to stop
|
||||
bg_work_gate_closed_ = true;
|
||||
while (bg_compaction_scheduled_ > 0) {
|
||||
while (bg_compaction_scheduled_ > 0 || bg_flush_scheduled_) {
|
||||
Log(options_.info_log,
|
||||
"RefitLevel: waiting for background threads to stop: %d",
|
||||
bg_compaction_scheduled_);
|
||||
"RefitLevel: waiting for background threads to stop: %d %d",
|
||||
bg_compaction_scheduled_, bg_flush_scheduled_);
|
||||
bg_cv_.Wait();
|
||||
}
|
||||
|
||||
@@ -1063,6 +1092,7 @@ SequenceNumber DBImpl::GetLatestSequenceNumber() {
|
||||
Status DBImpl::GetUpdatesSince(SequenceNumber seq,
|
||||
unique_ptr<TransactionLogIterator>* iter) {
|
||||
|
||||
RecordTick(options_.statistics, GET_UPDATES_SINCE_CALLS);
|
||||
if (seq > last_flushed_sequence_) {
|
||||
return Status::IOError("Requested sequence not yet written in the db");
|
||||
}
|
||||
@@ -1351,7 +1381,8 @@ Status DBImpl::TEST_WaitForCompactMemTable() {
|
||||
Status DBImpl::TEST_WaitForCompact() {
|
||||
// Wait until the compaction completes
|
||||
MutexLock l(&mutex_);
|
||||
while (bg_compaction_scheduled_ && bg_error_.ok()) {
|
||||
while ((bg_compaction_scheduled_ || bg_flush_scheduled_) &&
|
||||
bg_error_.ok()) {
|
||||
bg_cv_.Wait();
|
||||
}
|
||||
return bg_error_;
|
||||
@@ -1361,29 +1392,80 @@ void DBImpl::MaybeScheduleCompaction() {
|
||||
mutex_.AssertHeld();
|
||||
if (bg_work_gate_closed_) {
|
||||
// gate closed for backgrond work
|
||||
} else if (bg_compaction_scheduled_ >= options_.max_background_compactions) {
|
||||
// Already scheduled
|
||||
} else if (shutting_down_.Acquire_Load()) {
|
||||
// DB is being deleted; no more background compactions
|
||||
} else if (!imm_.IsFlushPending(options_.min_write_buffer_number_to_merge) &&
|
||||
manual_compaction_ == nullptr &&
|
||||
!versions_->NeedsCompaction()) {
|
||||
// No work to be done
|
||||
} else {
|
||||
bg_compaction_scheduled_++;
|
||||
env_->Schedule(&DBImpl::BGWork, this);
|
||||
bool is_flush_pending =
|
||||
imm_.IsFlushPending(options_.min_write_buffer_number_to_merge);
|
||||
if (is_flush_pending &&
|
||||
(bg_flush_scheduled_ < options_.max_background_flushes)) {
|
||||
// memtable flush needed
|
||||
bg_flush_scheduled_++;
|
||||
env_->Schedule(&DBImpl::BGWorkFlush, this, Env::Priority::HIGH);
|
||||
}
|
||||
|
||||
if ((manual_compaction_ ||
|
||||
versions_->NeedsCompaction() ||
|
||||
(is_flush_pending && (options_.max_background_flushes <= 0))) &&
|
||||
bg_compaction_scheduled_ < options_.max_background_compactions) {
|
||||
// compaction needed, or memtable flush needed but HIGH pool not enabled.
|
||||
bg_compaction_scheduled_++;
|
||||
env_->Schedule(&DBImpl::BGWorkCompaction, this, Env::Priority::LOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DBImpl::BGWork(void* db) {
|
||||
reinterpret_cast<DBImpl*>(db)->BackgroundCall();
|
||||
void DBImpl::BGWorkFlush(void* db) {
|
||||
reinterpret_cast<DBImpl*>(db)->BackgroundCallFlush();
|
||||
}
|
||||
|
||||
void DBImpl::BGWorkCompaction(void* db) {
|
||||
reinterpret_cast<DBImpl*>(db)->BackgroundCallCompaction();
|
||||
}
|
||||
|
||||
Status DBImpl::BackgroundFlush() {
|
||||
Status stat;
|
||||
while (stat.ok() &&
|
||||
imm_.IsFlushPending(options_.min_write_buffer_number_to_merge)) {
|
||||
Log(options_.info_log,
|
||||
"BackgroundCallFlush doing CompactMemTable, flush slots available %d",
|
||||
options_.max_background_flushes - bg_flush_scheduled_);
|
||||
stat = CompactMemTable();
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
void DBImpl::BackgroundCallFlush() {
|
||||
assert(bg_flush_scheduled_);
|
||||
MutexLock l(&mutex_);
|
||||
|
||||
if (!shutting_down_.Acquire_Load()) {
|
||||
Status s = BackgroundFlush();
|
||||
if (!s.ok()) {
|
||||
// Wait a little bit before retrying background compaction in
|
||||
// case this is an environmental problem and we do not want to
|
||||
// chew up resources for failed compactions for the duration of
|
||||
// the problem.
|
||||
bg_cv_.SignalAll(); // In case a waiter can proceed despite the error
|
||||
Log(options_.info_log, "Waiting after background flush error: %s",
|
||||
s.ToString().c_str());
|
||||
mutex_.Unlock();
|
||||
env_->SleepForMicroseconds(1000000);
|
||||
mutex_.Lock();
|
||||
}
|
||||
}
|
||||
|
||||
bg_flush_scheduled_--;
|
||||
|
||||
bg_cv_.SignalAll();
|
||||
}
|
||||
|
||||
|
||||
void DBImpl::TEST_PurgeObsoleteteWAL() {
|
||||
PurgeObsoleteWALFiles();
|
||||
}
|
||||
|
||||
void DBImpl::BackgroundCall() {
|
||||
void DBImpl::BackgroundCallCompaction() {
|
||||
bool madeProgress = false;
|
||||
DeletionState deletion_state;
|
||||
|
||||
@@ -1436,6 +1518,7 @@ Status DBImpl::BackgroundCompaction(bool* madeProgress,
|
||||
*madeProgress = false;
|
||||
mutex_.AssertHeld();
|
||||
|
||||
// TODO: remove memtable flush from formal compaction
|
||||
while (imm_.IsFlushPending(options_.min_write_buffer_number_to_merge)) {
|
||||
Log(options_.info_log,
|
||||
"BackgroundCompaction doing CompactMemTable, compaction slots available %d",
|
||||
@@ -1812,6 +1895,7 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
|
||||
}
|
||||
for (; input->Valid() && !shutting_down_.Acquire_Load(); ) {
|
||||
// Prioritize immutable compaction work
|
||||
// TODO: remove memtable flush from normal compaction work
|
||||
if (imm_.imm_flush_needed.NoBarrier_Load() != nullptr) {
|
||||
const uint64_t imm_start = env_->NowMicros();
|
||||
mutex_.Lock();
|
||||
@@ -2108,7 +2192,7 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
|
||||
}
|
||||
|
||||
mutex_.Lock();
|
||||
stats_[compact->compaction->level() + 1].Add(stats);
|
||||
stats_[compact->compaction->output_level()].Add(stats);
|
||||
|
||||
// if there were any unused file number (mostly in case of
|
||||
// compaction error), free up the entry from pending_putputs
|
||||
@@ -2478,10 +2562,12 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
|
||||
throw std::runtime_error("In memory WriteBatch corruption!");
|
||||
}
|
||||
SetTickerCount(options_.statistics, SEQUENCE_NUMBER, last_sequence);
|
||||
}
|
||||
mutex_.Lock();
|
||||
if (status.ok()) {
|
||||
versions_->SetLastSequence(last_sequence);
|
||||
last_flushed_sequence_ = current_sequence;
|
||||
}
|
||||
mutex_.Lock();
|
||||
}
|
||||
if (updates == &tmp_batch_) tmp_batch_.Clear();
|
||||
}
|
||||
@@ -2743,7 +2829,7 @@ Status DBImpl::MakeRoomForWrite(bool force) {
|
||||
lfile->SetPreallocationBlockSize(1.1 * options_.write_buffer_size);
|
||||
logfile_number_ = new_log_number;
|
||||
log_.reset(new log::Writer(std::move(lfile)));
|
||||
mem_->SetLogNumber(logfile_number_);
|
||||
mem_->SetNextLogNumber(logfile_number_);
|
||||
imm_.Add(mem_);
|
||||
if (force) {
|
||||
imm_.FlushRequested();
|
||||
@@ -2751,6 +2837,7 @@ Status DBImpl::MakeRoomForWrite(bool force) {
|
||||
mem_ = new MemTable(internal_comparator_, mem_rep_factory_,
|
||||
NumberLevels(), options_);
|
||||
mem_->Ref();
|
||||
mem_->SetLogNumber(logfile_number_);
|
||||
force = false; // Do not force another compaction if have room
|
||||
MaybeScheduleCompaction();
|
||||
}
|
||||
@@ -3113,6 +3200,7 @@ Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) {
|
||||
s = impl->versions_->LogAndApply(&edit, &impl->mutex_);
|
||||
}
|
||||
if (s.ok()) {
|
||||
impl->mem_->SetLogNumber(impl->logfile_number_);
|
||||
impl->DeleteObsoleteFiles();
|
||||
impl->MaybeScheduleCompaction();
|
||||
impl->MaybeScheduleLogDBDeployStats();
|
||||
@@ -3121,7 +3209,6 @@ Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) {
|
||||
impl->mutex_.Unlock();
|
||||
|
||||
if (options.compaction_style == kCompactionStyleUniversal) {
|
||||
std::string property;
|
||||
int num_files;
|
||||
for (int i = 1; i < impl->NumberLevels(); i++) {
|
||||
num_files = impl->versions_->NumLevelFiles(i);
|
||||
@@ -3207,4 +3294,4 @@ void dumpLeveldbBuildVersion(Logger * log) {
|
||||
leveldb_build_compile_time, leveldb_build_compile_date);
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+14
-5
@@ -24,7 +24,7 @@
|
||||
#include "scribe/scribe_logger.h"
|
||||
#endif
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class MemTable;
|
||||
class TableCache;
|
||||
@@ -72,7 +72,8 @@ class DBImpl : public DB {
|
||||
virtual Status DisableFileDeletions();
|
||||
virtual Status EnableFileDeletions();
|
||||
virtual Status GetLiveFiles(std::vector<std::string>&,
|
||||
uint64_t* manifest_file_size);
|
||||
uint64_t* manifest_file_size,
|
||||
bool flush_memtable = true);
|
||||
virtual Status GetSortedWalFiles(VectorLogPtr& files);
|
||||
virtual Status DeleteWalFiles(const VectorLogPtr& files);
|
||||
virtual SequenceNumber GetLatestSequenceNumber();
|
||||
@@ -187,9 +188,12 @@ class DBImpl : public DB {
|
||||
void LogDBDeployStats();
|
||||
|
||||
void MaybeScheduleCompaction();
|
||||
static void BGWork(void* db);
|
||||
void BackgroundCall();
|
||||
static void BGWorkCompaction(void* db);
|
||||
static void BGWorkFlush(void* db);
|
||||
void BackgroundCallCompaction();
|
||||
void BackgroundCallFlush();
|
||||
Status BackgroundCompaction(bool* madeProgress,DeletionState& deletion_state);
|
||||
Status BackgroundFlush();
|
||||
void CleanupCompaction(CompactionState* compact);
|
||||
Status DoCompactionWork(CompactionState* compact);
|
||||
|
||||
@@ -212,6 +216,8 @@ class DBImpl : public DB {
|
||||
// Removes the file listed in files_to_evict from the table_cache
|
||||
void EvictObsoleteFiles(DeletionState& deletion_state);
|
||||
|
||||
Status DeleteLogFile(uint64_t number);
|
||||
|
||||
void PurgeObsoleteWALFiles();
|
||||
|
||||
Status AppendSortedWalsOfType(const std::string& path,
|
||||
@@ -281,6 +287,9 @@ class DBImpl : public DB {
|
||||
// count how many background compaction been scheduled or is running?
|
||||
int bg_compaction_scheduled_;
|
||||
|
||||
// number of background memtable flush jobs, submitted to the HIGH pool
|
||||
int bg_flush_scheduled_;
|
||||
|
||||
// Has a background stats log thread scheduled?
|
||||
bool bg_logstats_scheduled_;
|
||||
|
||||
@@ -435,6 +444,6 @@ extern Options SanitizeOptions(const std::string& db,
|
||||
const InternalFilterPolicy* ipolicy,
|
||||
const Options& src);
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_DB_IMPL_H_
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include "util/logging.h"
|
||||
#include "util/build_version.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
DBImplReadOnly::DBImplReadOnly(const Options& options,
|
||||
const std::string& dbname)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "scribe/scribe_logger.h"
|
||||
#endif
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class DBImplReadOnly : public DBImpl {
|
||||
public:
|
||||
@@ -60,7 +60,8 @@ public:
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
virtual Status GetLiveFiles(std::vector<std::string>&,
|
||||
uint64_t* manifest_file_size) {
|
||||
uint64_t* manifest_file_size,
|
||||
bool flush_memtable = true) {
|
||||
return Status::NotSupported("Not supported operation in read only mode.");
|
||||
}
|
||||
virtual Status Flush(const FlushOptions& options) {
|
||||
|
||||
+5
-2
@@ -15,8 +15,9 @@
|
||||
#include "port/port.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/mutexlock.h"
|
||||
#include "util/perf_context_imp.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
#if 0
|
||||
static void DumpInternalIter(Iterator* iter) {
|
||||
@@ -197,6 +198,7 @@ void DBIter::FindNextUserEntry(bool skipping) {
|
||||
if (skipping &&
|
||||
user_comparator_->Compare(ikey.user_key, saved_key_) <= 0) {
|
||||
num_skipped++; // skip this entry
|
||||
BumpPerfCount(&perf_context.internal_key_skipped_count);
|
||||
} else {
|
||||
skipping = false;
|
||||
switch (ikey.type) {
|
||||
@@ -206,6 +208,7 @@ void DBIter::FindNextUserEntry(bool skipping) {
|
||||
SaveKey(ikey.user_key, &saved_key_);
|
||||
skipping = true;
|
||||
num_skipped = 0;
|
||||
BumpPerfCount(&perf_context.internal_delete_skipped_count);
|
||||
break;
|
||||
case kTypeValue:
|
||||
valid_ = true;
|
||||
@@ -468,4 +471,4 @@ Iterator* NewDBIterator(
|
||||
internal_iter, sequence);
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@
|
||||
#include "rocksdb/db.h"
|
||||
#include "db/dbformat.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
// Return a new iterator that converts internal keys (yielded by
|
||||
// "*internal_iter") that were live at the specified "sequence" number
|
||||
@@ -22,6 +22,6 @@ extern Iterator* NewDBIterator(
|
||||
Iterator* internal_iter,
|
||||
const SequenceNumber& sequence);
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_DB_ITER_H_
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
#include "util/mutexlock.h"
|
||||
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class DBStatistics: public Statistics {
|
||||
public:
|
||||
@@ -59,6 +59,6 @@ std::shared_ptr<Statistics> CreateDBStatistics() {
|
||||
return std::make_shared<DBStatistics>();
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // LEVELDB_STORAGE_DB_DB_STATISTICS_H_
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "port/port.h"
|
||||
#include "util/mutexlock.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
void DBImpl::MaybeScheduleLogDBDeployStats() {
|
||||
|
||||
|
||||
+129
-20
@@ -23,7 +23,7 @@
|
||||
#include "util/testutil.h"
|
||||
#include "utilities/merge_operators.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
static bool SnappyCompressionSupported(const CompressionOptions& options) {
|
||||
std::string out;
|
||||
@@ -335,7 +335,7 @@ class DBTest {
|
||||
options.memtable_factory.reset(new UnsortedRepFactory);
|
||||
break;
|
||||
case kVectorRep:
|
||||
options.memtable_factory.reset(new VectorRepFactory);
|
||||
options.memtable_factory.reset(new VectorRepFactory(100));
|
||||
break;
|
||||
case kUniversalCompaction:
|
||||
options.compaction_style = kCompactionStyleUniversal;
|
||||
@@ -831,7 +831,7 @@ TEST(DBTest, KeyMayExist) {
|
||||
std::string value;
|
||||
Options options = CurrentOptions();
|
||||
options.filter_policy = NewBloomFilterPolicy(20);
|
||||
options.statistics = leveldb::CreateDBStatistics();
|
||||
options.statistics = rocksdb::CreateDBStatistics();
|
||||
Reopen(&options);
|
||||
|
||||
ASSERT_TRUE(!db_->KeyMayExist(ropts, "a", &value));
|
||||
@@ -892,7 +892,7 @@ TEST(DBTest, NonBlockingIteration) {
|
||||
do {
|
||||
ReadOptions non_blocking_opts, regular_opts;
|
||||
Options options = CurrentOptions();
|
||||
options.statistics = leveldb::CreateDBStatistics();
|
||||
options.statistics = rocksdb::CreateDBStatistics();
|
||||
non_blocking_opts.read_tier = kBlockCacheTier;
|
||||
Reopen(&options);
|
||||
|
||||
@@ -1140,7 +1140,7 @@ TEST(DBTest, IterReseek) {
|
||||
Options options = CurrentOptions();
|
||||
options.max_sequential_skip_in_iterations = 3;
|
||||
options.create_if_missing = true;
|
||||
options.statistics = leveldb::CreateDBStatistics();
|
||||
options.statistics = rocksdb::CreateDBStatistics();
|
||||
DestroyAndReopen(&options);
|
||||
|
||||
// insert two keys with same userkey and verify that
|
||||
@@ -1283,6 +1283,44 @@ TEST(DBTest, IterMultiWithDelete) {
|
||||
} while (ChangeOptions());
|
||||
}
|
||||
|
||||
TEST(DBTest, IterWithSnapshot) {
|
||||
do {
|
||||
ASSERT_OK(Put("key1", "val1"));
|
||||
ASSERT_OK(Put("key2", "val2"));
|
||||
ASSERT_OK(Put("key3", "val3"));
|
||||
ASSERT_OK(Put("key4", "val4"));
|
||||
ASSERT_OK(Put("key5", "val5"));
|
||||
|
||||
const Snapshot *snapshot = db_->GetSnapshot();
|
||||
ReadOptions options;
|
||||
options.snapshot = snapshot;
|
||||
Iterator* iter = db_->NewIterator(options);
|
||||
|
||||
// Put more values after the snapshot
|
||||
ASSERT_OK(Put("key100", "val100"));
|
||||
ASSERT_OK(Put("key101", "val101"));
|
||||
|
||||
iter->Seek("key5");
|
||||
ASSERT_EQ(IterStatus(iter), "key5->val5");
|
||||
if (!CurrentOptions().merge_operator) {
|
||||
// TODO: merge operator does not support backward iteration yet
|
||||
iter->Prev();
|
||||
ASSERT_EQ(IterStatus(iter), "key4->val4");
|
||||
iter->Prev();
|
||||
ASSERT_EQ(IterStatus(iter), "key3->val3");
|
||||
|
||||
iter->Next();
|
||||
ASSERT_EQ(IterStatus(iter), "key4->val4");
|
||||
iter->Next();
|
||||
ASSERT_EQ(IterStatus(iter), "key5->val5");
|
||||
iter->Next();
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
}
|
||||
db_->ReleaseSnapshot(snapshot);
|
||||
delete iter;
|
||||
} while (ChangeOptions());
|
||||
}
|
||||
|
||||
TEST(DBTest, Recover) {
|
||||
do {
|
||||
ASSERT_OK(Put("foo", "v1"));
|
||||
@@ -1599,8 +1637,8 @@ TEST(DBTest, UniversalCompactionTrigger) {
|
||||
Options options = CurrentOptions();
|
||||
options.compaction_style = kCompactionStyleUniversal;
|
||||
options.write_buffer_size = 100<<10; //100KB
|
||||
// trigger compaction if there are > 3 files
|
||||
options.level0_file_num_compaction_trigger = 3;
|
||||
// trigger compaction if there are >= 4 files
|
||||
options.level0_file_num_compaction_trigger = 4;
|
||||
Reopen(&options);
|
||||
|
||||
Random rnd(301);
|
||||
@@ -1610,7 +1648,7 @@ TEST(DBTest, UniversalCompactionTrigger) {
|
||||
// Generate a set of files at level 0, but don't trigger level-0
|
||||
// compaction.
|
||||
for (int num = 0;
|
||||
num < options.level0_file_num_compaction_trigger;
|
||||
num < options.level0_file_num_compaction_trigger-1;
|
||||
num++) {
|
||||
// Write 120KB (12 values, each 10K)
|
||||
for (int i = 0; i < 12; i++) {
|
||||
@@ -1645,7 +1683,7 @@ TEST(DBTest, UniversalCompactionTrigger) {
|
||||
// data amount).
|
||||
dbfull()->Flush(FlushOptions());
|
||||
for (int num = 0;
|
||||
num < options.level0_file_num_compaction_trigger-2;
|
||||
num < options.level0_file_num_compaction_trigger-3;
|
||||
num++) {
|
||||
// Write 120KB (12 values, each 10K)
|
||||
for (int i = 0; i < 12; i++) {
|
||||
@@ -1674,7 +1712,7 @@ TEST(DBTest, UniversalCompactionTrigger) {
|
||||
// Now we have 2 files at level 0, with size 4 and 2.4. Continue
|
||||
// generating new files at level 0.
|
||||
for (int num = 0;
|
||||
num < options.level0_file_num_compaction_trigger-2;
|
||||
num < options.level0_file_num_compaction_trigger-3;
|
||||
num++) {
|
||||
// Write 120KB (12 values, each 10K)
|
||||
for (int i = 0; i < 12; i++) {
|
||||
@@ -1728,6 +1766,76 @@ TEST(DBTest, UniversalCompactionTrigger) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DBTest, UniversalCompactionSizeAmplification) {
|
||||
Options options = CurrentOptions();
|
||||
options.compaction_style = kCompactionStyleUniversal;
|
||||
options.write_buffer_size = 100<<10; //100KB
|
||||
options.level0_file_num_compaction_trigger = 3;
|
||||
|
||||
// Trigger compaction if size amplification exceeds 110%
|
||||
options.compaction_options_universal.
|
||||
max_size_amplification_percent = 110;
|
||||
Reopen(&options);
|
||||
|
||||
Random rnd(301);
|
||||
int key_idx = 0;
|
||||
|
||||
// Generate two files in Level 0. Both files are approx the same size.
|
||||
for (int num = 0;
|
||||
num < options.level0_file_num_compaction_trigger-1;
|
||||
num++) {
|
||||
// Write 120KB (12 values, each 10K)
|
||||
for (int i = 0; i < 12; i++) {
|
||||
ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
|
||||
key_idx++;
|
||||
}
|
||||
dbfull()->TEST_WaitForCompactMemTable();
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), num + 1);
|
||||
}
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 2);
|
||||
|
||||
// Flush whatever is remaining in memtable. This is typically
|
||||
// small, which should not trigger size ratio based compaction
|
||||
// but will instead trigger size amplification.
|
||||
dbfull()->Flush(FlushOptions());
|
||||
|
||||
// Verify that size amplification did occur
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 1);
|
||||
}
|
||||
|
||||
TEST(DBTest, UniversalCompactionOptions) {
|
||||
Options options = CurrentOptions();
|
||||
options.compaction_style = kCompactionStyleUniversal;
|
||||
options.write_buffer_size = 100<<10; //100KB
|
||||
options.level0_file_num_compaction_trigger = 4;
|
||||
options.num_levels = 1;
|
||||
Reopen(&options);
|
||||
|
||||
Random rnd(301);
|
||||
int key_idx = 0;
|
||||
|
||||
for (int num = 0;
|
||||
num < options.level0_file_num_compaction_trigger;
|
||||
num++) {
|
||||
// Write 120KB (12 values, each 10K)
|
||||
for (int i = 0; i < 12; i++) {
|
||||
ASSERT_OK(Put(Key(key_idx), RandomString(&rnd, 10000)));
|
||||
key_idx++;
|
||||
}
|
||||
dbfull()->TEST_WaitForCompactMemTable();
|
||||
|
||||
if (num < options.level0_file_num_compaction_trigger - 1) {
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), num + 1);
|
||||
}
|
||||
}
|
||||
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 1);
|
||||
for (int i = 1; i < options.num_levels ; i++) {
|
||||
ASSERT_EQ(NumTableFilesAtLevel(i), 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DBTest, ConvertCompactionStyle) {
|
||||
Random rnd(301);
|
||||
int max_key_level_insert = 200;
|
||||
@@ -3750,7 +3858,7 @@ class ModelDB: public DB {
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual Status Flush(const leveldb::FlushOptions& options) {
|
||||
virtual Status Flush(const rocksdb::FlushOptions& options) {
|
||||
Status ret;
|
||||
return ret;
|
||||
}
|
||||
@@ -3761,7 +3869,8 @@ class ModelDB: public DB {
|
||||
virtual Status EnableFileDeletions() {
|
||||
return Status::OK();
|
||||
}
|
||||
virtual Status GetLiveFiles(std::vector<std::string>&, uint64_t* size) {
|
||||
virtual Status GetLiveFiles(std::vector<std::string>&, uint64_t* size,
|
||||
bool flush_memtable = true) {
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
@@ -3776,8 +3885,8 @@ class ModelDB: public DB {
|
||||
virtual SequenceNumber GetLatestSequenceNumber() {
|
||||
return 0;
|
||||
}
|
||||
virtual Status GetUpdatesSince(leveldb::SequenceNumber,
|
||||
unique_ptr<leveldb::TransactionLogIterator>*) {
|
||||
virtual Status GetUpdatesSince(rocksdb::SequenceNumber,
|
||||
unique_ptr<rocksdb::TransactionLogIterator>*) {
|
||||
return Status::NotSupported("Not supported in Model DB");
|
||||
}
|
||||
|
||||
@@ -4194,16 +4303,16 @@ void BM_LogAndApply(int iters, int num_base_files) {
|
||||
buf, iters, us, ((float)us) / iters);
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc > 1 && std::string(argv[1]) == "--benchmark") {
|
||||
leveldb::BM_LogAndApply(1000, 1);
|
||||
leveldb::BM_LogAndApply(1000, 100);
|
||||
leveldb::BM_LogAndApply(1000, 10000);
|
||||
leveldb::BM_LogAndApply(100, 100000);
|
||||
rocksdb::BM_LogAndApply(1000, 1);
|
||||
rocksdb::BM_LogAndApply(1000, 100);
|
||||
rocksdb::BM_LogAndApply(1000, 10000);
|
||||
rocksdb::BM_LogAndApply(100, 100000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return leveldb::test::RunAllTests();
|
||||
return rocksdb::test::RunAllTests();
|
||||
}
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@
|
||||
#include "util/coding.h"
|
||||
#include "util/perf_context_imp.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
static uint64_t PackSequenceAndType(uint64_t seq, ValueType t) {
|
||||
assert(seq <= kMaxSequenceNumber);
|
||||
@@ -139,4 +139,4 @@ LookupKey::LookupKey(const Slice& user_key, SequenceNumber s) {
|
||||
end_ = dst;
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@
|
||||
#include "util/coding.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class InternalKey;
|
||||
|
||||
@@ -223,6 +223,6 @@ inline LookupKey::~LookupKey() {
|
||||
if (start_ != space_) delete[] start_;
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_FORMAT_H_
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@
|
||||
#include "util/logging.h"
|
||||
#include "util/testharness.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
static std::string IKey(const std::string& user_key,
|
||||
uint64_t seq,
|
||||
@@ -105,8 +105,8 @@ TEST(FormatTest, InternalKeyShortestSuccessor) {
|
||||
ShortSuccessor(IKey("\xff\xff", 100, kTypeValue)));
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
return rocksdb::test::RunAllTests();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <map>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class DeleteFileTest {
|
||||
public:
|
||||
@@ -180,9 +180,9 @@ TEST(DeleteFileTest, DeleteFileWithIterator) {
|
||||
delete it;
|
||||
CloseDB();
|
||||
}
|
||||
} //namespace leveldb
|
||||
} //namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
return rocksdb::test::RunAllTests();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@
|
||||
#include "rocksdb/env.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
// Given a path, flatten the path name by replacing all chars not in
|
||||
// {[0-9,a-z,A-Z,-,_,.]} with _. And append '\0' at the end.
|
||||
@@ -218,4 +218,4 @@ Status SetCurrentFile(Env* env, const std::string& dbname,
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@
|
||||
#include "rocksdb/status.h"
|
||||
#include "port/port.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Env;
|
||||
|
||||
@@ -92,6 +92,6 @@ extern Status SetCurrentFile(Env* env, const std::string& dbname,
|
||||
uint64_t descriptor_number);
|
||||
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_FILENAME_H_
|
||||
|
||||
+3
-3
@@ -9,7 +9,7 @@
|
||||
#include "util/logging.h"
|
||||
#include "util/testharness.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class FileNameTest { };
|
||||
|
||||
@@ -128,8 +128,8 @@ TEST(FileNameTest, Construction) {
|
||||
ASSERT_EQ(kMetaDatabase, type);
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
return rocksdb::test::RunAllTests();
|
||||
}
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@
|
||||
#ifndef STORAGE_LEVELDB_DB_LOG_FORMAT_H_
|
||||
#define STORAGE_LEVELDB_DB_LOG_FORMAT_H_
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
namespace log {
|
||||
|
||||
enum RecordType {
|
||||
@@ -30,6 +30,6 @@ static const unsigned int kBlockSize = 32768;
|
||||
static const int kHeaderSize = 4 + 1 + 2;
|
||||
|
||||
} // namespace log
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_LOG_FORMAT_H_
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@
|
||||
#include "util/coding.h"
|
||||
#include "util/crc32c.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
namespace log {
|
||||
|
||||
Reader::Reporter::~Reporter() {
|
||||
@@ -256,4 +256,4 @@ unsigned int Reader::ReadPhysicalRecord(Slice* result) {
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@
|
||||
#include "rocksdb/slice.h"
|
||||
#include "rocksdb/status.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class SequentialFile;
|
||||
using std::unique_ptr;
|
||||
@@ -118,6 +118,6 @@ class Reader {
|
||||
};
|
||||
|
||||
} // namespace log
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_LOG_READER_H_
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@
|
||||
#include "util/random.h"
|
||||
#include "util/testharness.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
namespace log {
|
||||
|
||||
// Construct a string of the specified length made out of the supplied
|
||||
@@ -516,8 +516,8 @@ TEST(LogTest, ReadPastEnd) {
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
return rocksdb::test::RunAllTests();
|
||||
}
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@
|
||||
#include "util/coding.h"
|
||||
#include "util/crc32c.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
namespace log {
|
||||
|
||||
Writer::Writer(unique_ptr<WritableFile>&& dest)
|
||||
@@ -100,4 +100,4 @@ Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr, size_t n) {
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@
|
||||
#include "rocksdb/slice.h"
|
||||
#include "rocksdb/status.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class WritableFile;
|
||||
|
||||
@@ -49,6 +49,6 @@ class Writer {
|
||||
};
|
||||
|
||||
} // namespace log
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_LOG_WRITER_H_
|
||||
|
||||
+3
-2
@@ -14,7 +14,7 @@
|
||||
#include "util/coding.h"
|
||||
#include "util/murmurhash.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
MemTable::MemTable(const InternalKeyComparator& cmp,
|
||||
std::shared_ptr<MemTableRepFactory> table_factory,
|
||||
@@ -29,6 +29,7 @@ MemTable::MemTable(const InternalKeyComparator& cmp,
|
||||
file_number_(0),
|
||||
edit_(numlevel),
|
||||
first_seqno_(0),
|
||||
mem_next_logfile_number_(0),
|
||||
mem_logfile_number_(0) { }
|
||||
|
||||
MemTable::~MemTable() {
|
||||
@@ -237,4 +238,4 @@ bool MemTable::Get(const LookupKey& key, std::string* value, Status* s,
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+14
-2
@@ -15,7 +15,7 @@
|
||||
#include "rocksdb/memtablerep.h"
|
||||
#include "util/arena_impl.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Mutex;
|
||||
class MemTableIterator;
|
||||
@@ -92,6 +92,14 @@ class MemTable {
|
||||
// into the memtable
|
||||
SequenceNumber GetFirstSequenceNumber() { return first_seqno_; }
|
||||
|
||||
// Returns the next active logfile number when this memtable is about to
|
||||
// be flushed to storage
|
||||
uint64_t GetNextLogNumber() { return mem_next_logfile_number_; }
|
||||
|
||||
// Sets the next active logfile number when this memtable is about to
|
||||
// be flushed to storage
|
||||
void SetNextLogNumber(uint64_t num) { mem_next_logfile_number_ = num; }
|
||||
|
||||
// Returns the logfile number that can be safely deleted when this
|
||||
// memstore is flushed to storage
|
||||
uint64_t GetLogNumber() { return mem_logfile_number_; }
|
||||
@@ -127,6 +135,10 @@ class MemTable {
|
||||
SequenceNumber first_seqno_;
|
||||
|
||||
// The log files earlier than this number can be deleted.
|
||||
uint64_t mem_next_logfile_number_;
|
||||
|
||||
// The log file that backs this memtable (to be deleted when
|
||||
// memtable flush is done)
|
||||
uint64_t mem_logfile_number_;
|
||||
|
||||
// No copying allowed
|
||||
@@ -134,6 +146,6 @@ class MemTable {
|
||||
void operator=(const MemTable&);
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_MEMTABLE_H_
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@
|
||||
#include "rocksdb/iterator.h"
|
||||
#include "util/coding.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class InternalKeyComparator;
|
||||
class Mutex;
|
||||
@@ -210,4 +210,4 @@ void MemTableList::GetMemTables(std::vector<MemTable*>* output) {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@
|
||||
#include "db/skiplist.h"
|
||||
#include "memtable.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class InternalKeyComparator;
|
||||
class Mutex;
|
||||
@@ -99,6 +99,6 @@ class MemTableList {
|
||||
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_MEMTABLELIST_H_
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
// PRE: iter points to the first merge type entry
|
||||
// POST: iter points to the first entry beyond the merge process (or the end)
|
||||
@@ -189,4 +189,4 @@ void MergeHelper::MergeUntil(Iterator* iter, SequenceNumber stop_before,
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@
|
||||
#include <string>
|
||||
#include <deque>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Comparator;
|
||||
class Iterator;
|
||||
@@ -93,6 +93,6 @@ class MergeHelper {
|
||||
bool success_;
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "rocksdb/merge_operator.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
// Given a "real" merge from the library, call the user's
|
||||
// associative merge function one-by-one on each of the operands.
|
||||
@@ -48,4 +48,4 @@ bool AssociativeMergeOperator::PartialMerge(
|
||||
return Merge(key, &left_operand, right_operand, new_value, logger);
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
#include "utilities/utility_db.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace leveldb;
|
||||
using namespace rocksdb;
|
||||
|
||||
|
||||
std::shared_ptr<DB> OpenDb(const string& dbname, const bool ttl = false) {
|
||||
|
||||
+220
-29
@@ -1,5 +1,7 @@
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "/usr/include/valgrind/callgrind.h"
|
||||
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/perf_context.h"
|
||||
@@ -8,16 +10,43 @@
|
||||
#include "util/testharness.h"
|
||||
|
||||
|
||||
namespace leveldb {
|
||||
bool FLAGS_random_key = false;
|
||||
bool FLAGS_use_set_based_memetable = false;
|
||||
int FLAGS_total_keys = 100;
|
||||
int FLAGS_write_buffer_size = 1000000000;
|
||||
int FLAGS_max_write_buffer_number = 8;
|
||||
int FLAGS_min_write_buffer_number_to_merge = 7;
|
||||
|
||||
// Path to the database on file system
|
||||
const std::string kDbName = test::TmpDir() + "/perf_context_test";
|
||||
const std::string kDbName = rocksdb::test::TmpDir() + "/perf_context_test";
|
||||
|
||||
std::shared_ptr<DB> OpenDb(size_t write_buffer_size) {
|
||||
void SeekToFirst(rocksdb::Iterator* iter) {
|
||||
// std::cout << "Press a key to continue:";
|
||||
// std::string s;
|
||||
// std::cin >> s;
|
||||
iter->SeekToFirst();
|
||||
// std::cout << "Press a key to continue:";
|
||||
// std::string s2;
|
||||
// std::cin >> s2;
|
||||
}
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
std::shared_ptr<DB> OpenDb() {
|
||||
DB* db;
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
options.write_buffer_size = write_buffer_size;
|
||||
options.write_buffer_size = FLAGS_write_buffer_size;
|
||||
options.max_write_buffer_number = FLAGS_max_write_buffer_number;
|
||||
options.min_write_buffer_number_to_merge =
|
||||
FLAGS_min_write_buffer_number_to_merge;
|
||||
|
||||
if (FLAGS_use_set_based_memetable) {
|
||||
auto prefix_extractor = rocksdb::NewFixedPrefixTransform(0);
|
||||
options.memtable_factory =
|
||||
std::make_shared<rocksdb::PrefixHashRepFactory>(prefix_extractor);
|
||||
}
|
||||
|
||||
Status s = DB::Open(options, kDbName, &db);
|
||||
ASSERT_OK(s);
|
||||
return std::shared_ptr<DB>(db);
|
||||
@@ -25,7 +54,85 @@ std::shared_ptr<DB> OpenDb(size_t write_buffer_size) {
|
||||
|
||||
class PerfContextTest { };
|
||||
|
||||
int kTotalKeys = 100;
|
||||
TEST(PerfContextTest, SeekIntoDeletion) {
|
||||
DestroyDB(kDbName, Options());
|
||||
auto db = OpenDb();
|
||||
WriteOptions write_options;
|
||||
ReadOptions read_options;
|
||||
|
||||
for (int i = 0; i < FLAGS_total_keys; ++i) {
|
||||
std::string key = "k" + std::to_string(i);
|
||||
std::string value = "v" + std::to_string(i);
|
||||
|
||||
db->Put(write_options, key, value);
|
||||
}
|
||||
|
||||
for (int i = 0; i < FLAGS_total_keys -1 ; ++i) {
|
||||
std::string key = "k" + std::to_string(i);
|
||||
db->Delete(write_options, key);
|
||||
}
|
||||
|
||||
HistogramImpl hist_get;
|
||||
HistogramImpl hist_get_time;
|
||||
for (int i = 0; i < FLAGS_total_keys - 1; ++i) {
|
||||
std::string key = "k" + std::to_string(i);
|
||||
std::string value;
|
||||
|
||||
perf_context.Reset();
|
||||
StopWatchNano timer(Env::Default(), true);
|
||||
auto status = db->Get(read_options, key, &value);
|
||||
auto elapsed_nanos = timer.ElapsedNanos();
|
||||
ASSERT_TRUE(status.IsNotFound());
|
||||
hist_get.Add(perf_context.user_key_comparison_count);
|
||||
hist_get_time.Add(elapsed_nanos);
|
||||
}
|
||||
|
||||
std::cout << "Get uesr key comparison: \n" << hist_get.ToString()
|
||||
<< "Get time: \n" << hist_get_time.ToString();
|
||||
|
||||
HistogramImpl hist_seek_to_first;
|
||||
std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
|
||||
|
||||
perf_context.Reset();
|
||||
StopWatchNano timer(Env::Default(), true);
|
||||
//CALLGRIND_ZERO_STATS;
|
||||
SeekToFirst(iter.get());
|
||||
//iter->SeekToFirst();
|
||||
//CALLGRIND_DUMP_STATS;
|
||||
hist_seek_to_first.Add(perf_context.user_key_comparison_count);
|
||||
auto elapsed_nanos = timer.ElapsedNanos();
|
||||
|
||||
std::cout << "SeekToFirst uesr key comparison: \n" << hist_seek_to_first.ToString()
|
||||
<< "ikey skipped: " << perf_context.internal_key_skipped_count << "\n"
|
||||
<< "idelete skipped: " << perf_context.internal_delete_skipped_count << "\n"
|
||||
<< "elapsed: " << elapsed_nanos << "\n";
|
||||
|
||||
HistogramImpl hist_seek;
|
||||
for (int i = 0; i < FLAGS_total_keys; ++i) {
|
||||
std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
|
||||
std::string key = "k" + std::to_string(i);
|
||||
|
||||
perf_context.Reset();
|
||||
StopWatchNano timer(Env::Default(), true);
|
||||
iter->Seek(key);
|
||||
auto elapsed_nanos = timer.ElapsedNanos();
|
||||
hist_seek.Add(perf_context.user_key_comparison_count);
|
||||
std::cout << "seek cmp: " << perf_context.user_key_comparison_count
|
||||
<< " ikey skipped " << perf_context.internal_key_skipped_count
|
||||
<< " idelete skipped " << perf_context.internal_delete_skipped_count
|
||||
<< " elapsed: " << elapsed_nanos << "ns\n";
|
||||
|
||||
perf_context.Reset();
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
StopWatchNano timer2(Env::Default(), true);
|
||||
iter->Next();
|
||||
auto elapsed_nanos2 = timer2.ElapsedNanos();
|
||||
std::cout << "next cmp: " << perf_context.user_key_comparison_count
|
||||
<< "elapsed: " << elapsed_nanos2 << "ns\n";
|
||||
}
|
||||
|
||||
std::cout << "Seek uesr key comparison: \n" << hist_seek.ToString();
|
||||
}
|
||||
|
||||
TEST(PerfContextTest, StopWatchNanoOverhead) {
|
||||
// profile the timer cost by itself!
|
||||
@@ -68,62 +175,146 @@ TEST(PerfContextTest, StopWatchOverhead) {
|
||||
void ProfileKeyComparison() {
|
||||
DestroyDB(kDbName, Options()); // Start this test with a fresh DB
|
||||
|
||||
auto db = OpenDb(1000000000);
|
||||
auto db = OpenDb();
|
||||
|
||||
WriteOptions write_options;
|
||||
ReadOptions read_options;
|
||||
|
||||
uint64_t total_user_key_comparison_get = 0;
|
||||
uint64_t total_user_key_comparison_put = 0;
|
||||
uint64_t max_user_key_comparison_get = 0;
|
||||
HistogramImpl hist_put;
|
||||
HistogramImpl hist_get;
|
||||
|
||||
std::cout << "Inserting " << kTotalKeys << " key/value pairs\n...\n";
|
||||
std::cout << "Inserting " << FLAGS_total_keys << " key/value pairs\n...\n";
|
||||
|
||||
for (int i = 0; i < kTotalKeys; ++i) {
|
||||
std::vector<int> keys;
|
||||
for (int i = 0; i < FLAGS_total_keys; ++i) {
|
||||
keys.push_back(i);
|
||||
}
|
||||
|
||||
if (FLAGS_random_key) {
|
||||
std::random_shuffle(keys.begin(), keys.end());
|
||||
}
|
||||
|
||||
for (const int i : keys) {
|
||||
std::string key = "k" + std::to_string(i);
|
||||
std::string value = "v" + std::to_string(i);
|
||||
|
||||
perf_context.Reset();
|
||||
db->Put(write_options, key, value);
|
||||
total_user_key_comparison_put += perf_context.user_key_comparison_count;
|
||||
hist_put.Add(perf_context.user_key_comparison_count);
|
||||
|
||||
perf_context.Reset();
|
||||
db->Get(read_options, key, &value);
|
||||
total_user_key_comparison_get += perf_context.user_key_comparison_count;
|
||||
max_user_key_comparison_get =
|
||||
std::max(max_user_key_comparison_get,
|
||||
perf_context.user_key_comparison_count);
|
||||
hist_get.Add(perf_context.user_key_comparison_count);
|
||||
}
|
||||
|
||||
std::cout << "total user key comparison get: "
|
||||
<< total_user_key_comparison_get << "\n"
|
||||
<< "total user key comparison put: "
|
||||
<< total_user_key_comparison_put << "\n"
|
||||
<< "max user key comparison get: "
|
||||
<< max_user_key_comparison_get << "\n"
|
||||
<< "avg user key comparison get:"
|
||||
<< total_user_key_comparison_get/kTotalKeys << "\n";
|
||||
std::cout << "Put uesr key comparison: \n" << hist_put.ToString()
|
||||
<< "Get uesr key comparison: \n" << hist_get.ToString();
|
||||
|
||||
}
|
||||
|
||||
TEST(PerfContextTest, KeyComparisonCount) {
|
||||
SetPerfLevel(kDisable);
|
||||
SetPerfLevel(kEnableCount);
|
||||
ProfileKeyComparison();
|
||||
|
||||
SetPerfLevel(kEnableCount);
|
||||
SetPerfLevel(kDisable);
|
||||
ProfileKeyComparison();
|
||||
|
||||
SetPerfLevel(kEnableTime);
|
||||
ProfileKeyComparison();
|
||||
}
|
||||
|
||||
// make perf_context_test
|
||||
// export LEVELDB_TESTS=PerfContextTest.SeekKeyComparison
|
||||
// For one memtable:
|
||||
// ./perf_context_test --write_buffer_size=500000 --total_keys=10000
|
||||
// For two memtables:
|
||||
// ./perf_context_test --write_buffer_size=250000 --total_keys=10000
|
||||
// Specify --random_key=1 to shuffle the key before insertion
|
||||
// Results show that, for sequential insertion, worst-case Seek Key comparison
|
||||
// is close to the total number of keys (linear), when there is only one
|
||||
// memtable. When there are two memtables, even the avg Seek Key comparison
|
||||
// starts to become linear to the input size.
|
||||
|
||||
TEST(PerfContextTest, SeekKeyComparison) {
|
||||
DestroyDB(kDbName, Options());
|
||||
auto db = OpenDb();
|
||||
WriteOptions write_options;
|
||||
ReadOptions read_options;
|
||||
|
||||
std::cout << "Inserting " << FLAGS_total_keys << " key/value pairs\n...\n";
|
||||
|
||||
std::vector<int> keys;
|
||||
for (int i = 0; i < FLAGS_total_keys; ++i) {
|
||||
keys.push_back(i);
|
||||
}
|
||||
|
||||
if (FLAGS_random_key) {
|
||||
std::random_shuffle(keys.begin(), keys.end());
|
||||
}
|
||||
|
||||
for (const int i : keys) {
|
||||
std::string key = "k" + std::to_string(i);
|
||||
std::string value = "v" + std::to_string(i);
|
||||
|
||||
db->Put(write_options, key, value);
|
||||
}
|
||||
|
||||
HistogramImpl hist_seek;
|
||||
HistogramImpl hist_next;
|
||||
|
||||
for (int i = 0; i < FLAGS_total_keys; ++i) {
|
||||
std::string key = "k" + std::to_string(i);
|
||||
std::string value = "v" + std::to_string(i);
|
||||
|
||||
std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
|
||||
perf_context.Reset();
|
||||
iter->Seek(key);
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->value().ToString(), value);
|
||||
hist_seek.Add(perf_context.user_key_comparison_count);
|
||||
}
|
||||
|
||||
std::unique_ptr<Iterator> iter(db->NewIterator(read_options));
|
||||
for (iter->SeekToFirst(); iter->Valid();) {
|
||||
perf_context.Reset();
|
||||
iter->Next();
|
||||
hist_next.Add(perf_context.user_key_comparison_count);
|
||||
}
|
||||
|
||||
std::cout << "Seek:\n" << hist_seek.ToString()
|
||||
<< "Next:\n" << hist_next.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
if (argc > 1) {
|
||||
leveldb::kTotalKeys = std::stoi(argv[1]);
|
||||
for (int i = 1; i < argc; i++) {
|
||||
int n;
|
||||
char junk;
|
||||
|
||||
if (sscanf(argv[i], "--write_buffer_size=%d%c", &n, &junk) == 1) {
|
||||
FLAGS_write_buffer_size = n;
|
||||
}
|
||||
|
||||
if (sscanf(argv[i], "--total_keys=%d%c", &n, &junk) == 1) {
|
||||
FLAGS_total_keys = n;
|
||||
}
|
||||
|
||||
if (sscanf(argv[i], "--random_key=%d%c", &n, &junk) == 1 &&
|
||||
(n == 0 || n == 1)) {
|
||||
FLAGS_random_key = n;
|
||||
}
|
||||
|
||||
if (sscanf(argv[i], "--use_set_based_memetable=%d%c", &n, &junk) == 1 &&
|
||||
(n == 0 || n == 1)) {
|
||||
FLAGS_use_set_based_memetable = n;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
leveldb::test::RunAllTests();
|
||||
std::cout << kDbName << "\n";
|
||||
|
||||
rocksdb::test::RunAllTests();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include "rocksdb/iterator.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class PrefixFilterIterator : public Iterator {
|
||||
private:
|
||||
@@ -71,6 +71,6 @@ class PrefixFilterIterator : public Iterator {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/env.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -383,4 +383,4 @@ Status RepairDB(const std::string& dbname, const Options& options) {
|
||||
return repairer.Run();
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+12
-2
@@ -33,7 +33,7 @@
|
||||
#include "port/port.h"
|
||||
#include "util/random.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
template<typename Key, class Comparator>
|
||||
class SkipList {
|
||||
@@ -107,6 +107,7 @@ class SkipList {
|
||||
|
||||
// Used for optimizing sequential insert patterns
|
||||
Node* prev_[kMaxHeight];
|
||||
int prev_height_;
|
||||
|
||||
inline int GetMaxHeight() const {
|
||||
return static_cast<int>(
|
||||
@@ -267,6 +268,10 @@ typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOr
|
||||
Node* x = prev[0];
|
||||
Node* next = x->Next(0);
|
||||
if ((x == head_) || KeyIsAfterNode(key, x)) {
|
||||
// Adjust all relevant insertion points to the previous entry
|
||||
for (int i = 1; i < prev_height_; i++) {
|
||||
prev[i] = x;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
}
|
||||
@@ -275,6 +280,9 @@ typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOr
|
||||
int level = GetMaxHeight() - 1;
|
||||
while (true) {
|
||||
Node* next = x->Next(level);
|
||||
// Make sure the lists are sorted.
|
||||
// If x points to head_ or next points nullptr, it is trivially satisfied.
|
||||
assert((x == head_) || (next == nullptr) || KeyIsAfterNode(next->key, x));
|
||||
if (KeyIsAfterNode(key, next)) {
|
||||
// Keep searching in this list
|
||||
x = next;
|
||||
@@ -337,6 +345,7 @@ SkipList<Key,Comparator>::SkipList(Comparator cmp, Arena* arena)
|
||||
arena_(arena),
|
||||
head_(NewNode(0 /* any key will do */, kMaxHeight)),
|
||||
max_height_(reinterpret_cast<void*>(1)),
|
||||
prev_height_(1),
|
||||
rnd_(0xdeadbeef) {
|
||||
for (int i = 0; i < kMaxHeight; i++) {
|
||||
head_->SetNext(i, nullptr);
|
||||
@@ -378,6 +387,7 @@ void SkipList<Key,Comparator>::Insert(const Key& key) {
|
||||
prev_[i]->SetNext(i, x);
|
||||
}
|
||||
prev_[0] = x;
|
||||
prev_height_ = height;
|
||||
}
|
||||
|
||||
template<typename Key, class Comparator>
|
||||
@@ -390,6 +400,6 @@ bool SkipList<Key,Comparator>::Contains(const Key& key) const {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_SKIPLIST_H_
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@
|
||||
#include "util/random.h"
|
||||
#include "util/testharness.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
typedef uint64_t Key;
|
||||
|
||||
@@ -371,8 +371,8 @@ TEST(SkipTest, Concurrent3) { RunConcurrent(3); }
|
||||
TEST(SkipTest, Concurrent4) { RunConcurrent(4); }
|
||||
TEST(SkipTest, Concurrent5) { RunConcurrent(5); }
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
return rocksdb::test::RunAllTests();
|
||||
}
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "rocksdb/db.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class SnapshotList;
|
||||
|
||||
@@ -80,6 +80,6 @@ class SnapshotList {
|
||||
SnapshotImpl list_;
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_SNAPSHOT_H_
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@
|
||||
#include "util/coding.h"
|
||||
#include "util/stop_watch.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
static void DeleteEntry(const Slice& key, void* value) {
|
||||
Table* table = reinterpret_cast<Table*>(value);
|
||||
@@ -160,4 +160,4 @@ void TableCache::Evict(uint64_t file_number) {
|
||||
cache_->Erase(Slice(buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@
|
||||
#include "port/port.h"
|
||||
#include "table/table.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Env;
|
||||
|
||||
@@ -72,6 +72,6 @@ class TableCache {
|
||||
const bool no_io = false);
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_TABLE_CACHE_H_
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "db/transaction_log_impl.h"
|
||||
#include "db/write_batch_internal.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
TransactionLogIteratorImpl::TransactionLogIteratorImpl(
|
||||
const std::string& dbname,
|
||||
@@ -168,4 +168,4 @@ Status TransactionLogIteratorImpl::OpenLogReader(const LogFile* logFile) {
|
||||
);
|
||||
return Status::OK();
|
||||
}
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "db/log_reader.h"
|
||||
#include "db/filename.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
struct LogReporter : public log::Reader::Reporter {
|
||||
Env* env;
|
||||
@@ -99,5 +99,5 @@ class TransactionLogIteratorImpl : public TransactionLogIterator {
|
||||
|
||||
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
#endif // STORAGE_LEVELDB_INCLUDE_WRITES_ITERATOR_IMPL_H_
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@
|
||||
#include "db/version_set.h"
|
||||
#include "util/coding.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
// Tag numbers for serialized VersionEdit. These numbers are written to
|
||||
// disk and should not be changed.
|
||||
@@ -293,4 +293,4 @@ std::string VersionEdit::DebugString(bool hex_key) const {
|
||||
return r;
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@
|
||||
#include <vector>
|
||||
#include "db/dbformat.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class VersionSet;
|
||||
|
||||
@@ -122,6 +122,6 @@ class VersionEdit {
|
||||
std::vector< std::pair<int, FileMetaData> > new_files_;
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_VERSION_EDIT_H_
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "db/version_edit.h"
|
||||
#include "util/testharness.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
static void TestEncodeDecode(const VersionEdit& edit) {
|
||||
std::string encoded, encoded2;
|
||||
@@ -41,8 +41,8 @@ TEST(VersionEditTest, EncodeDecode) {
|
||||
TestEncodeDecode(edit);
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
return rocksdb::test::RunAllTests();
|
||||
}
|
||||
|
||||
+224
-121
@@ -21,7 +21,7 @@
|
||||
#include "util/logging.h"
|
||||
#include "util/stop_watch.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
static uint64_t TotalFileSize(const std::vector<FileMetaData*>& files) {
|
||||
uint64_t sum = 0;
|
||||
@@ -2159,17 +2159,215 @@ void VersionSet::SizeBeingCompacted(std::vector<uint64_t>& sizes) {
|
||||
}
|
||||
}
|
||||
|
||||
Compaction* VersionSet::PickCompactionUniversal(int level, double score) {
|
||||
//
|
||||
// Look at overall size amplification. If size amplification
|
||||
// exceeeds the configured value, then do a compaction
|
||||
// of the candidate files all the way upto the earliest
|
||||
// base file (overrides configured values of file-size ratios,
|
||||
// min_merge_width and max_merge_width).
|
||||
//
|
||||
Compaction* VersionSet::PickCompactionUniversalSizeAmp(
|
||||
int level, double score) {
|
||||
assert (level == 0);
|
||||
|
||||
// percentage flexibilty while comparing file sizes
|
||||
uint64_t ratio = options_->compaction_options_universal.size_ratio;
|
||||
// percentage flexibilty while reducing size amplification
|
||||
uint64_t ratio = options_->compaction_options_universal.
|
||||
max_size_amplification_percent;
|
||||
|
||||
// The files are sorted from newest first to oldest last.
|
||||
std::vector<int>& file_by_time = current_->files_by_size_[level];
|
||||
assert(file_by_time.size() == current_->files_[level].size());
|
||||
|
||||
unsigned int candidate_count = 0;
|
||||
uint64_t candidate_size = 0;
|
||||
unsigned int start_index = 0;
|
||||
FileMetaData* f = nullptr;
|
||||
|
||||
// Skip files that are already being compacted
|
||||
for (unsigned int loop = 0; loop < file_by_time.size() - 1; loop++) {
|
||||
int index = file_by_time[loop];
|
||||
f = current_->files_[level][index];
|
||||
if (!f->being_compacted) {
|
||||
start_index = loop; // Consider this as the first candidate.
|
||||
break;
|
||||
}
|
||||
Log(options_->info_log, "Universal: skipping file %ld[%d] compacted %s",
|
||||
f->number, loop, " cannot be a candidate to reduce size amp.\n");
|
||||
f = nullptr;
|
||||
}
|
||||
if (f == nullptr) {
|
||||
return nullptr; // no candidate files
|
||||
}
|
||||
|
||||
Log(options_->info_log, "Universal: First candidate file %ld[%d] %s",
|
||||
f->number, start_index, " to reduce size amp.\n");
|
||||
|
||||
// keep adding up all the remaining files
|
||||
for (unsigned int loop = start_index; loop < file_by_time.size() - 1;
|
||||
loop++) {
|
||||
int index = file_by_time[loop];
|
||||
f = current_->files_[level][index];
|
||||
if (f->being_compacted) {
|
||||
Log(options_->info_log,
|
||||
"Universal: Possible candidate file %ld[%d] %s.", f->number, loop,
|
||||
" is already being compacted. No size amp reduction possible.\n");
|
||||
return nullptr;
|
||||
}
|
||||
candidate_size += f->file_size;
|
||||
candidate_count++;
|
||||
}
|
||||
if (candidate_count == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// size of earliest file
|
||||
int index = file_by_time[file_by_time.size() - 1];
|
||||
uint64_t earliest_file_size = current_->files_[level][index]->file_size;
|
||||
|
||||
// size amplification = percentage of additional size
|
||||
if (candidate_size * 100 < ratio * earliest_file_size) {
|
||||
Log(options_->info_log,
|
||||
"Universal: size amp not needed. newer-files-total-size %ld "
|
||||
"earliest-file-size %ld",
|
||||
candidate_size, earliest_file_size);
|
||||
return nullptr;
|
||||
} else {
|
||||
Log(options_->info_log,
|
||||
"Universal: size amp needed. newer-files-total-size %ld "
|
||||
"earliest-file-size %ld",
|
||||
candidate_size, earliest_file_size);
|
||||
}
|
||||
assert(start_index >= 0 && start_index < file_by_time.size() - 1);
|
||||
|
||||
// create a compaction request
|
||||
Compaction* c = new Compaction(level, level, MaxFileSizeForLevel(level),
|
||||
LLONG_MAX, NumberLevels());
|
||||
c->score_ = score;
|
||||
for (unsigned int loop = start_index; loop < file_by_time.size(); loop++) {
|
||||
int index = file_by_time[loop];
|
||||
f = current_->files_[level][index];
|
||||
c->inputs_[0].push_back(f);
|
||||
Log(options_->info_log,
|
||||
"Universal: size amp picking file %ld[%d] with size %ld",
|
||||
f->number, index, f->file_size);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
//
|
||||
// Consider compaction files based on their size differences with
|
||||
// the next file in time order.
|
||||
//
|
||||
Compaction* VersionSet::PickCompactionUniversalReadAmp(
|
||||
int level, double score, unsigned int ratio,
|
||||
unsigned int max_number_of_files_to_compact) {
|
||||
|
||||
unsigned int min_merge_width =
|
||||
options_->compaction_options_universal.min_merge_width;
|
||||
unsigned int max_merge_width =
|
||||
options_->compaction_options_universal.max_merge_width;
|
||||
|
||||
if ((current_->files_[level].size() <=
|
||||
// The files are sorted from newest first to oldest last.
|
||||
std::vector<int>& file_by_time = current_->files_by_size_[level];
|
||||
FileMetaData* f = nullptr;
|
||||
bool done = false;
|
||||
int start_index = 0;
|
||||
unsigned int candidate_count;
|
||||
assert(file_by_time.size() == current_->files_[level].size());
|
||||
|
||||
unsigned int max_files_to_compact = std::min(max_merge_width,
|
||||
max_number_of_files_to_compact);
|
||||
min_merge_width = std::max(min_merge_width, 2U);
|
||||
|
||||
// Considers a candidate file only if it is smaller than the
|
||||
// total size accumulated so far.
|
||||
for (unsigned int loop = 0; loop < file_by_time.size(); loop++) {
|
||||
|
||||
candidate_count = 0;
|
||||
|
||||
// Skip files that are already being compacted
|
||||
for (f = nullptr; loop < file_by_time.size(); loop++) {
|
||||
int index = file_by_time[loop];
|
||||
f = current_->files_[level][index];
|
||||
|
||||
if (!f->being_compacted) {
|
||||
candidate_count = 1;
|
||||
break;
|
||||
}
|
||||
Log(options_->info_log,
|
||||
"Universal: file %ld[%d] being compacted, skipping",
|
||||
f->number, loop);
|
||||
f = nullptr;
|
||||
}
|
||||
|
||||
// This file is not being compacted. Consider it as the
|
||||
// first candidate to be compacted.
|
||||
uint64_t candidate_size = f != nullptr? f->file_size : 0;
|
||||
if (f != nullptr) {
|
||||
Log(options_->info_log, "Universal: Possible candidate file %ld[%d].",
|
||||
f->number, loop);
|
||||
}
|
||||
|
||||
// Check if the suceeding files need compaction.
|
||||
for (unsigned int i = loop+1;
|
||||
candidate_count < max_files_to_compact && i < file_by_time.size();
|
||||
i++) {
|
||||
int index = file_by_time[i];
|
||||
FileMetaData* f = current_->files_[level][index];
|
||||
if (f->being_compacted) {
|
||||
break;
|
||||
}
|
||||
// pick files if the total candidate file size (increased by the
|
||||
// specified ratio) is still larger than the next candidate file.
|
||||
uint64_t sz = (candidate_size * (100L + ratio)) /100;
|
||||
if (sz < f->file_size) {
|
||||
break;
|
||||
}
|
||||
candidate_count++;
|
||||
candidate_size += f->file_size;
|
||||
}
|
||||
|
||||
// Found a series of consecutive files that need compaction.
|
||||
if (candidate_count >= (unsigned int)min_merge_width) {
|
||||
start_index = loop;
|
||||
done = true;
|
||||
break;
|
||||
} else {
|
||||
for (unsigned int i = loop;
|
||||
i < loop + candidate_count && i < file_by_time.size(); i++) {
|
||||
int index = file_by_time[i];
|
||||
FileMetaData* f = current_->files_[level][index];
|
||||
Log(options_->info_log,
|
||||
"Universal: Skipping file %ld[%d] with size %ld %d\n",
|
||||
f->number, i, f->file_size, f->being_compacted);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!done || candidate_count <= 1) {
|
||||
return nullptr;
|
||||
}
|
||||
Compaction* c = new Compaction(level, level, MaxFileSizeForLevel(level),
|
||||
LLONG_MAX, NumberLevels());
|
||||
c->score_ = score;
|
||||
|
||||
for (unsigned int i = start_index; i < start_index + candidate_count; i++) {
|
||||
int index = file_by_time[i];
|
||||
FileMetaData* f = current_->files_[level][index];
|
||||
c->inputs_[0].push_back(f);
|
||||
Log(options_->info_log, "Universal: Picking file %ld[%d] with size %ld\n",
|
||||
f->number, i, f->file_size);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
//
|
||||
// Universal style of compaction. Pick files that are contiguous in
|
||||
// time-range to compact.
|
||||
//
|
||||
Compaction* VersionSet::PickCompactionUniversal(int level, double score) {
|
||||
assert (level == 0);
|
||||
|
||||
if ((current_->files_[level].size() <
|
||||
(unsigned int)options_->level0_file_num_compaction_trigger)) {
|
||||
Log(options_->info_log, "Universal: nothing to do\n");
|
||||
return nullptr;
|
||||
@@ -2179,127 +2377,29 @@ Compaction* VersionSet::PickCompactionUniversal(int level, double score) {
|
||||
current_->files_[level].size(),
|
||||
LevelFileSummary(&tmp, 0));
|
||||
|
||||
Compaction* c = nullptr;
|
||||
c = new Compaction(level, level, MaxFileSizeForLevel(level),
|
||||
LLONG_MAX, NumberLevels());
|
||||
c->score_ = score;
|
||||
// Check for size amplification first.
|
||||
Compaction* c = PickCompactionUniversalSizeAmp(level, score);
|
||||
if (c == nullptr) {
|
||||
|
||||
// The files are sorted from newest first to oldest last.
|
||||
std::vector<int>& file_by_time = current_->files_by_size_[level];
|
||||
FileMetaData* f = nullptr;
|
||||
bool done = false;
|
||||
assert(file_by_time.size() == current_->files_[level].size());
|
||||
// Size amplification is within limits. Try reducing read
|
||||
// amplification while maintaining file size ratios.
|
||||
unsigned int ratio = options_->compaction_options_universal.size_ratio;
|
||||
c = PickCompactionUniversalReadAmp(level, score, ratio, UINT_MAX);
|
||||
|
||||
unsigned int max_files_to_compact = std::min(max_merge_width, UINT_MAX);
|
||||
|
||||
// Make two pass. The first pass considers a candidate file
|
||||
// only if it is smaller than the total size accumulated so far.
|
||||
// The second pass does not look at the slope of the
|
||||
// file-size curve to decide what to pick for compaction.
|
||||
for (int iter = 0; !done && iter < 2; iter++) {
|
||||
|
||||
for (unsigned int loop = 0; loop < file_by_time.size(); ) {
|
||||
|
||||
// Skip files that are already being compacted
|
||||
for (f = nullptr; loop < file_by_time.size(); loop++) {
|
||||
int index = file_by_time[loop];
|
||||
f = current_->files_[level][index];
|
||||
|
||||
if (!f->being_compacted) {
|
||||
break;
|
||||
}
|
||||
Log(options_->info_log, "Universal: file %ld[%d] being compacted, skipping",
|
||||
f->number, loop);
|
||||
f = nullptr;
|
||||
}
|
||||
|
||||
// This file is not being compacted. Consider it as the
|
||||
// first candidate to be compacted.
|
||||
unsigned int candidate_count = 1;
|
||||
uint64_t candidate_size = f != nullptr? f->file_size : 0;
|
||||
if (f != nullptr) {
|
||||
Log(options_->info_log, "Universal: Possible candidate file %ld[%d] %s.",
|
||||
f->number, loop, iter == 0? "" : "forced ");
|
||||
}
|
||||
|
||||
// Check if the suceeding files need compaction.
|
||||
for (unsigned int i = loop+1;
|
||||
candidate_count < max_files_to_compact && i < file_by_time.size();
|
||||
i++) {
|
||||
int index = file_by_time[i];
|
||||
FileMetaData* f = current_->files_[level][index];
|
||||
if (f->being_compacted) {
|
||||
break;
|
||||
}
|
||||
// If this is the first iteration, then we pick files if the
|
||||
// total candidate file size (increased by the specified ratio)
|
||||
// is still larger than the next candidate file.
|
||||
if (iter == 0) {
|
||||
uint64_t sz = (candidate_size * (100 + ratio)) /100;
|
||||
if (sz < f->file_size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
candidate_count++;
|
||||
candidate_size += f->file_size;
|
||||
}
|
||||
|
||||
// Found a series of consecutive files that need compaction.
|
||||
if (candidate_count >= (unsigned int)min_merge_width) {
|
||||
for (unsigned int i = loop; i < loop + candidate_count; i++) {
|
||||
int index = file_by_time[i];
|
||||
FileMetaData* f = current_->files_[level][index];
|
||||
c->inputs_[0].push_back(f);
|
||||
Log(options_->info_log, "Universal: Picking file %ld[%d] with size %ld %s",
|
||||
f->number, i, f->file_size,
|
||||
(iter == 0 ? "" : "forced"));
|
||||
}
|
||||
done = true;
|
||||
break;
|
||||
} else {
|
||||
for (unsigned int i = loop;
|
||||
i < loop + candidate_count && i < file_by_time.size(); i++) {
|
||||
int index = file_by_time[i];
|
||||
FileMetaData* f = current_->files_[level][index];
|
||||
Log(options_->info_log, "Universal: Skipping file %ld[%d] with size %ld %d %s",
|
||||
f->number, i, f->file_size, f->being_compacted,
|
||||
(iter == 0 ? "" : "forced"));
|
||||
}
|
||||
}
|
||||
loop += candidate_count;
|
||||
}
|
||||
assert(done || c->inputs_[0].size() == 0);
|
||||
|
||||
// If we are unable to find a normal compaction run and we are still
|
||||
// above the compaction threshold, iterate again to pick compaction
|
||||
// candidates, this time without considering their size differences.
|
||||
if (!done) {
|
||||
int files_not_in_compaction = 0;
|
||||
for (unsigned int i = 0; i < current_->files_[level].size(); i++) {
|
||||
f = current_->files_[level][i];
|
||||
if (!f->being_compacted) {
|
||||
files_not_in_compaction++;
|
||||
}
|
||||
}
|
||||
int expected_num_files = files_not_in_compaction +
|
||||
compactions_in_progress_[level].size();
|
||||
if (expected_num_files <=
|
||||
options_->level0_file_num_compaction_trigger + 1) {
|
||||
done = true; // nothing more to do
|
||||
} else {
|
||||
max_files_to_compact = std::min((int)max_merge_width,
|
||||
expected_num_files - options_->level0_file_num_compaction_trigger);
|
||||
Log(options_->info_log, "Universal: second loop with maxfiles %d",
|
||||
max_files_to_compact);
|
||||
}
|
||||
// Size amplification and file size ratios are within configured limits.
|
||||
// If max read amplification is exceeding configured limits, then force
|
||||
// compaction without looking at filesize ratios and try to reduce
|
||||
// the number of files to fewer than level0_file_num_compaction_trigger.
|
||||
if (c == nullptr) {
|
||||
unsigned int num_files = current_->files_[level].size() -
|
||||
options_->level0_file_num_compaction_trigger;
|
||||
c = PickCompactionUniversalReadAmp(level, score, UINT_MAX, num_files);
|
||||
}
|
||||
}
|
||||
if (c->inputs_[0].size() <= 1) {
|
||||
Log(options_->info_log, "Universal: only %ld files, nothing to do.\n",
|
||||
c->inputs_[0].size());
|
||||
delete c;
|
||||
if (c == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
assert(c->inputs_[0].size() > 1);
|
||||
|
||||
// validate that all the chosen files are non overlapping in time
|
||||
FileMetaData* newerfile __attribute__((unused)) = nullptr;
|
||||
@@ -2311,6 +2411,9 @@ Compaction* VersionSet::PickCompactionUniversal(int level, double score) {
|
||||
newerfile = f;
|
||||
}
|
||||
|
||||
// The files are sorted from newest first to oldest last.
|
||||
std::vector<int>& file_by_time = current_->files_by_size_[level];
|
||||
|
||||
// Is the earliest file part of this compaction?
|
||||
int last_index = file_by_time[file_by_time.size()-1];
|
||||
FileMetaData* last_file = current_->files_[level][last_index];
|
||||
@@ -2952,4 +3055,4 @@ void Compaction::Summary(char* output, int len) {
|
||||
level_low_summary, level_up_summary);
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
+9
-2
@@ -25,7 +25,7 @@
|
||||
#include "port/port.h"
|
||||
#include "db/table_cache.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
namespace log { class Writer; }
|
||||
|
||||
@@ -383,6 +383,13 @@ class VersionSet {
|
||||
// Pick files to compact in Universal mode
|
||||
Compaction* PickCompactionUniversal(int level, double score);
|
||||
|
||||
// Pick Universal compaction to limit read amplification
|
||||
Compaction* PickCompactionUniversalReadAmp(int level, double score,
|
||||
unsigned int ratio, unsigned int num_files);
|
||||
|
||||
// Pick Universal compaction to limit space amplification.
|
||||
Compaction* PickCompactionUniversalSizeAmp(int level, double score);
|
||||
|
||||
// Free up the files that were participated in a compaction
|
||||
void ReleaseCompactionFiles(Compaction* c, Status status);
|
||||
|
||||
@@ -620,6 +627,6 @@ class Compaction {
|
||||
void ResetNextCompactionIndex();
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_VERSION_SET_H_
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "db/log_writer.h"
|
||||
#include "util/logging.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
Status VersionSet::ReduceNumberOfLevels(int new_levels, port::Mutex* mu) {
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "util/testharness.h"
|
||||
#include "util/testutil.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class FindFileTest {
|
||||
public:
|
||||
@@ -172,8 +172,8 @@ TEST(FindFileTest, OverlappingFiles) {
|
||||
ASSERT_TRUE(Overlaps("600", "700"));
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
return rocksdb::test::RunAllTests();
|
||||
}
|
||||
|
||||
+2
-2
@@ -26,7 +26,7 @@
|
||||
#include "util/coding.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
// WriteBatch header has an 8-byte sequence number followed by a 4-byte count.
|
||||
static const size_t kHeader = 12;
|
||||
@@ -227,4 +227,4 @@ void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) {
|
||||
dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader);
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/options.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class MemTable;
|
||||
|
||||
@@ -51,7 +51,7 @@ class WriteBatchInternal {
|
||||
static void Append(WriteBatch* dst, const WriteBatch* src);
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "util/logging.h"
|
||||
#include "util/testharness.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
static std::string PrintContents(WriteBatch* b) {
|
||||
InternalKeyComparator cmp(BytewiseComparator());
|
||||
@@ -221,8 +221,8 @@ TEST(WriteBatchTest, Continue) {
|
||||
handler.seen);
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
return rocksdb::test::RunAllTests();
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ static void WalCheckpoint(sqlite3* db_) {
|
||||
}
|
||||
}
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
// Helper for quickly generating random data.
|
||||
namespace {
|
||||
@@ -664,7 +664,7 @@ class Benchmark {
|
||||
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::string default_db_path;
|
||||
@@ -672,7 +672,7 @@ int main(int argc, char** argv) {
|
||||
double d;
|
||||
int n;
|
||||
char junk;
|
||||
if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) {
|
||||
if (rocksdb::Slice(argv[i]).starts_with("--benchmarks=")) {
|
||||
FLAGS_benchmarks = argv[i] + strlen("--benchmarks=");
|
||||
} else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 &&
|
||||
(n == 0 || n == 1)) {
|
||||
@@ -688,7 +688,7 @@ int main(int argc, char** argv) {
|
||||
FLAGS_reads = n;
|
||||
} else if (sscanf(argv[i], "--value_size=%d%c", &n, &junk) == 1) {
|
||||
FLAGS_value_size = n;
|
||||
} else if (leveldb::Slice(argv[i]) == leveldb::Slice("--no_transaction")) {
|
||||
} else if (rocksdb::Slice(argv[i]) == rocksdb::Slice("--no_transaction")) {
|
||||
FLAGS_transaction = false;
|
||||
} else if (sscanf(argv[i], "--page_size=%d%c", &n, &junk) == 1) {
|
||||
FLAGS_page_size = n;
|
||||
@@ -707,12 +707,12 @@ int main(int argc, char** argv) {
|
||||
|
||||
// Choose a location for the test database if none given with --db=<path>
|
||||
if (FLAGS_db == NULL) {
|
||||
leveldb::Env::Default()->GetTestDirectory(&default_db_path);
|
||||
rocksdb::Env::Default()->GetTestDirectory(&default_db_path);
|
||||
default_db_path += "/dbbench";
|
||||
FLAGS_db = default_db_path.c_str();
|
||||
}
|
||||
|
||||
leveldb::Benchmark benchmark;
|
||||
rocksdb::Benchmark benchmark;
|
||||
benchmark.Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ static void DBSynchronize(kyotocabinet::TreeDB* db_)
|
||||
}
|
||||
}
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
// Helper for quickly generating random data.
|
||||
namespace {
|
||||
@@ -479,7 +479,7 @@ class Benchmark {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::string default_db_path;
|
||||
@@ -487,7 +487,7 @@ int main(int argc, char** argv) {
|
||||
double d;
|
||||
int n;
|
||||
char junk;
|
||||
if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) {
|
||||
if (rocksdb::Slice(argv[i]).starts_with("--benchmarks=")) {
|
||||
FLAGS_benchmarks = argv[i] + strlen("--benchmarks=");
|
||||
} else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) {
|
||||
FLAGS_compression_ratio = d;
|
||||
@@ -517,12 +517,12 @@ int main(int argc, char** argv) {
|
||||
|
||||
// Choose a location for the test database if none given with --db=<path>
|
||||
if (FLAGS_db == NULL) {
|
||||
leveldb::Env::Default()->GetTestDirectory(&default_db_path);
|
||||
rocksdb::Env::Default()->GetTestDirectory(&default_db_path);
|
||||
default_db_path += "/dbbench";
|
||||
FLAGS_db = default_db_path.c_str();
|
||||
}
|
||||
|
||||
leveldb::Benchmark benchmark;
|
||||
rocksdb::Benchmark benchmark;
|
||||
benchmark.Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
+52
-52
@@ -25,27 +25,27 @@ creating it if necessary:
|
||||
#include <assert>
|
||||
#include "leveldb/db.h"
|
||||
|
||||
leveldb::DB* db;
|
||||
leveldb::Options options;
|
||||
rocksdb::DB* db;
|
||||
rocksdb::Options options;
|
||||
options.create_if_missing = true;
|
||||
leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db);
|
||||
rocksdb::Status status = rocksdb::DB::Open(options, "/tmp/testdb", &db);
|
||||
assert(status.ok());
|
||||
...
|
||||
</pre>
|
||||
If you want to raise an error if the database already exists, add
|
||||
the following line before the <code>leveldb::DB::Open</code> call:
|
||||
the following line before the <code>rocksdb::DB::Open</code> call:
|
||||
<pre>
|
||||
options.error_if_exists = true;
|
||||
</pre>
|
||||
<h1>Status</h1>
|
||||
<p>
|
||||
You may have noticed the <code>leveldb::Status</code> type above. Values of this
|
||||
You may have noticed the <code>rocksdb::Status</code> type above. Values of this
|
||||
type are returned by most functions in <code>leveldb</code> that may encounter an
|
||||
error. You can check if such a result is ok, and also print an
|
||||
associated error message:
|
||||
<p>
|
||||
<pre>
|
||||
leveldb::Status s = ...;
|
||||
rocksdb::Status s = ...;
|
||||
if (!s.ok()) cerr << s.ToString() << endl;
|
||||
</pre>
|
||||
<h1>Closing A Database</h1>
|
||||
@@ -65,9 +65,9 @@ modify/query the database. For example, the following code
|
||||
moves the value stored under key1 to key2.
|
||||
<pre>
|
||||
std::string value;
|
||||
leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
|
||||
if (s.ok()) s = db->Put(leveldb::WriteOptions(), key2, value);
|
||||
if (s.ok()) s = db->Delete(leveldb::WriteOptions(), key1);
|
||||
rocksdb::Status s = db->Get(rocksdb::ReadOptions(), key1, &value);
|
||||
if (s.ok()) s = db->Put(rocksdb::WriteOptions(), key2, value);
|
||||
if (s.ok()) s = db->Delete(rocksdb::WriteOptions(), key1);
|
||||
</pre>
|
||||
|
||||
<h1>Atomic Updates</h1>
|
||||
@@ -81,12 +81,12 @@ atomically apply a set of updates:
|
||||
#include "leveldb/write_batch.h"
|
||||
...
|
||||
std::string value;
|
||||
leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
|
||||
rocksdb::Status s = db->Get(rocksdb::ReadOptions(), key1, &value);
|
||||
if (s.ok()) {
|
||||
leveldb::WriteBatch batch;
|
||||
rocksdb::WriteBatch batch;
|
||||
batch.Delete(key1);
|
||||
batch.Put(key2, value);
|
||||
s = db->Write(leveldb::WriteOptions(), &batch);
|
||||
s = db->Write(rocksdb::WriteOptions(), &batch);
|
||||
}
|
||||
</pre>
|
||||
The <code>WriteBatch</code> holds a sequence of edits to be made to the database,
|
||||
@@ -109,7 +109,7 @@ persistent storage. (On Posix systems, this is implemented by calling
|
||||
either <code>fsync(...)</code> or <code>fdatasync(...)</code> or
|
||||
<code>msync(..., MS_SYNC)</code> before the write operation returns.)
|
||||
<pre>
|
||||
leveldb::WriteOptions write_options;
|
||||
rocksdb::WriteOptions write_options;
|
||||
write_options.sync = true;
|
||||
db->Put(write_options, ...);
|
||||
</pre>
|
||||
@@ -144,7 +144,7 @@ the batch.
|
||||
A database may only be opened by one process at a time.
|
||||
The <code>leveldb</code> implementation acquires a lock from the
|
||||
operating system to prevent misuse. Within a single process, the
|
||||
same <code>leveldb::DB</code> object may be safely shared by multiple
|
||||
same <code>rocksdb::DB</code> object may be safely shared by multiple
|
||||
concurrent threads. I.e., different threads may write into or fetch
|
||||
iterators or call <code>Get</code> on the same database without any
|
||||
external synchronization (the leveldb implementation will
|
||||
@@ -160,7 +160,7 @@ The following example demonstrates how to print all key,value pairs
|
||||
in a database.
|
||||
<p>
|
||||
<pre>
|
||||
leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
|
||||
rocksdb::Iterator* it = db->NewIterator(rocksdb::ReadOptions());
|
||||
for (it->SeekToFirst(); it->Valid(); it->Next()) {
|
||||
cout << it->key().ToString() << ": " << it->value().ToString() << endl;
|
||||
}
|
||||
@@ -196,10 +196,10 @@ implicit snapshot of the current state.
|
||||
Snapshots are created by the DB::GetSnapshot() method:
|
||||
<p>
|
||||
<pre>
|
||||
leveldb::ReadOptions options;
|
||||
rocksdb::ReadOptions options;
|
||||
options.snapshot = db->GetSnapshot();
|
||||
... apply some updates to db ...
|
||||
leveldb::Iterator* iter = db->NewIterator(options);
|
||||
rocksdb::Iterator* iter = db->NewIterator(options);
|
||||
... read using iter to view the state when the snapshot was created ...
|
||||
delete iter;
|
||||
db->ReleaseSnapshot(options.snapshot);
|
||||
@@ -211,7 +211,7 @@ support reading as of that snapshot.
|
||||
<h1>Slice</h1>
|
||||
<p>
|
||||
The return value of the <code>it->key()</code> and <code>it->value()</code> calls above
|
||||
are instances of the <code>leveldb::Slice</code> type. <code>Slice</code> is a simple
|
||||
are instances of the <code>rocksdb::Slice</code> type. <code>Slice</code> is a simple
|
||||
structure that contains a length and a pointer to an external byte
|
||||
array. Returning a <code>Slice</code> is a cheaper alternative to returning a
|
||||
<code>std::string</code> since we do not need to copy potentially large keys and
|
||||
@@ -223,10 +223,10 @@ C++ strings and null-terminated C-style strings can be easily converted
|
||||
to a Slice:
|
||||
<p>
|
||||
<pre>
|
||||
leveldb::Slice s1 = "hello";
|
||||
rocksdb::Slice s1 = "hello";
|
||||
|
||||
std::string str("world");
|
||||
leveldb::Slice s2 = str;
|
||||
rocksdb::Slice s2 = str;
|
||||
</pre>
|
||||
A Slice can be easily converted back to a C++ string:
|
||||
<pre>
|
||||
@@ -238,7 +238,7 @@ the external byte array into which the Slice points remains live while
|
||||
the Slice is in use. For example, the following is buggy:
|
||||
<p>
|
||||
<pre>
|
||||
leveldb::Slice slice;
|
||||
rocksdb::Slice slice;
|
||||
if (...) {
|
||||
std::string str = ...;
|
||||
slice = str;
|
||||
@@ -255,16 +255,16 @@ which orders bytes lexicographically. You can however supply a custom
|
||||
comparator when opening a database. For example, suppose each
|
||||
database key consists of two numbers and we should sort by the first
|
||||
number, breaking ties by the second number. First, define a proper
|
||||
subclass of <code>leveldb::Comparator</code> that expresses these rules:
|
||||
subclass of <code>rocksdb::Comparator</code> that expresses these rules:
|
||||
<p>
|
||||
<pre>
|
||||
class TwoPartComparator : public leveldb::Comparator {
|
||||
class TwoPartComparator : public rocksdb::Comparator {
|
||||
public:
|
||||
// Three-way comparison function:
|
||||
// if a < b: negative result
|
||||
// if a > b: positive result
|
||||
// else: zero result
|
||||
int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const {
|
||||
int Compare(const rocksdb::Slice& a, const rocksdb::Slice& b) const {
|
||||
int a1, a2, b1, b2;
|
||||
ParseKey(a, &a1, &a2);
|
||||
ParseKey(b, &b1, &b2);
|
||||
@@ -277,7 +277,7 @@ subclass of <code>leveldb::Comparator</code> that expresses these rules:
|
||||
|
||||
// Ignore the following methods for now:
|
||||
const char* Name() const { return "TwoPartComparator"; }
|
||||
void FindShortestSeparator(std::string*, const leveldb::Slice&) const { }
|
||||
void FindShortestSeparator(std::string*, const rocksdb::Slice&) const { }
|
||||
void FindShortSuccessor(std::string*) const { }
|
||||
};
|
||||
</pre>
|
||||
@@ -285,18 +285,18 @@ Now create a database using this custom comparator:
|
||||
<p>
|
||||
<pre>
|
||||
TwoPartComparator cmp;
|
||||
leveldb::DB* db;
|
||||
leveldb::Options options;
|
||||
rocksdb::DB* db;
|
||||
rocksdb::Options options;
|
||||
options.create_if_missing = true;
|
||||
options.comparator = &cmp;
|
||||
leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db);
|
||||
rocksdb::Status status = rocksdb::DB::Open(options, "/tmp/testdb", &db);
|
||||
...
|
||||
</pre>
|
||||
<h2>Backwards compatibility</h2>
|
||||
<p>
|
||||
The result of the comparator's <code>Name</code> method is attached to the
|
||||
database when it is created, and is checked on every subsequent
|
||||
database open. If the name changes, the <code>leveldb::DB::Open</code> call will
|
||||
database open. If the name changes, the <code>rocksdb::DB::Open</code> call will
|
||||
fail. Therefore, change the name if and only if the new key format
|
||||
and comparison function are incompatible with existing databases, and
|
||||
it is ok to discard the contents of all existing databases.
|
||||
@@ -339,9 +339,9 @@ compression entirely, but should only do so if benchmarks show a
|
||||
performance improvement:
|
||||
<p>
|
||||
<pre>
|
||||
leveldb::Options options;
|
||||
options.compression = leveldb::kNoCompression;
|
||||
... leveldb::DB::Open(options, name, ...) ....
|
||||
rocksdb::Options options;
|
||||
options.compression = rocksdb::kNoCompression;
|
||||
... rocksdb::DB::Open(options, name, ...) ....
|
||||
</pre>
|
||||
<h2>Cache</h2>
|
||||
<p>
|
||||
@@ -353,10 +353,10 @@ uncompressed block contents.
|
||||
<pre>
|
||||
#include "leveldb/cache.h"
|
||||
|
||||
leveldb::Options options;
|
||||
options.cache = leveldb::NewLRUCache(100 * 1048576); // 100MB cache
|
||||
leveldb::DB* db;
|
||||
leveldb::DB::Open(options, name, &db);
|
||||
rocksdb::Options options;
|
||||
options.cache = rocksdb::NewLRUCache(100 * 1048576); // 100MB cache
|
||||
rocksdb::DB* db;
|
||||
rocksdb::DB::Open(options, name, &db);
|
||||
... use the db ...
|
||||
delete db
|
||||
delete options.cache;
|
||||
@@ -373,9 +373,9 @@ displacing most of the cached contents. A per-iterator option can be
|
||||
used to achieve this:
|
||||
<p>
|
||||
<pre>
|
||||
leveldb::ReadOptions options;
|
||||
rocksdb::ReadOptions options;
|
||||
options.fill_cache = false;
|
||||
leveldb::Iterator* it = db->NewIterator(options);
|
||||
rocksdb::Iterator* it = db->NewIterator(options);
|
||||
for (it->SeekToFirst(); it->Valid(); it->Next()) {
|
||||
...
|
||||
}
|
||||
@@ -407,10 +407,10 @@ a single <code>Get()</code> call may involve multiple reads from disk.
|
||||
The optional <code>FilterPolicy</code> mechanism can be used to reduce
|
||||
the number of disk reads substantially.
|
||||
<pre>
|
||||
leveldb::Options options;
|
||||
rocksdb::Options options;
|
||||
options.filter_policy = NewBloomFilter(10);
|
||||
leveldb::DB* db;
|
||||
leveldb::DB::Open(options, "/tmp/testdb", &db);
|
||||
rocksdb::DB* db;
|
||||
rocksdb::DB::Open(options, "/tmp/testdb", &db);
|
||||
... use the database ...
|
||||
delete db;
|
||||
delete options.filter_policy;
|
||||
@@ -434,7 +434,7 @@ consider a comparator that ignores trailing spaces when comparing keys.
|
||||
Instead, the application should provide a custom filter policy that
|
||||
also ignores trailing spaces. For example:
|
||||
<pre>
|
||||
class CustomFilterPolicy : public leveldb::FilterPolicy {
|
||||
class CustomFilterPolicy : public rocksdb::FilterPolicy {
|
||||
private:
|
||||
FilterPolicy* builtin_policy_;
|
||||
public:
|
||||
@@ -484,7 +484,7 @@ checksums are verified:
|
||||
parts of its persistent storage have been corrupted.
|
||||
<p>
|
||||
If a database is corrupted (perhaps it cannot be opened when
|
||||
paranoid checking is turned on), the <code>leveldb::RepairDB</code> function
|
||||
paranoid checking is turned on), the <code>rocksdb::RepairDB</code> function
|
||||
may be used to recover as much of the data as possible
|
||||
<p>
|
||||
</ul>
|
||||
@@ -494,11 +494,11 @@ The <code>GetApproximateSizes</code> method can used to get the approximate
|
||||
number of bytes of file system space used by one or more key ranges.
|
||||
<p>
|
||||
<pre>
|
||||
leveldb::Range ranges[2];
|
||||
ranges[0] = leveldb::Range("a", "c");
|
||||
ranges[1] = leveldb::Range("x", "z");
|
||||
rocksdb::Range ranges[2];
|
||||
ranges[0] = rocksdb::Range("a", "c");
|
||||
ranges[1] = rocksdb::Range("x", "z");
|
||||
uint64_t sizes[2];
|
||||
leveldb::Status s = db->GetApproximateSizes(ranges, 2, sizes);
|
||||
rocksdb::Status s = db->GetApproximateSizes(ranges, 2, sizes);
|
||||
</pre>
|
||||
The preceding call will set <code>sizes[0]</code> to the approximate number of
|
||||
bytes of file system space used by the key range <code>[a..c)</code> and
|
||||
@@ -508,21 +508,21 @@ bytes of file system space used by the key range <code>[a..c)</code> and
|
||||
<h1>Environment</h1>
|
||||
<p>
|
||||
All file operations (and other operating system calls) issued by the
|
||||
<code>leveldb</code> implementation are routed through a <code>leveldb::Env</code> object.
|
||||
<code>leveldb</code> implementation are routed through a <code>rocksdb::Env</code> object.
|
||||
Sophisticated clients may wish to provide their own <code>Env</code>
|
||||
implementation to get better control. For example, an application may
|
||||
introduce artificial delays in the file IO paths to limit the impact
|
||||
of <code>leveldb</code> on other activities in the system.
|
||||
<p>
|
||||
<pre>
|
||||
class SlowEnv : public leveldb::Env {
|
||||
class SlowEnv : public rocksdb::Env {
|
||||
.. implementation of the Env interface ...
|
||||
};
|
||||
|
||||
SlowEnv env;
|
||||
leveldb::Options options;
|
||||
rocksdb::Options options;
|
||||
options.env = &env;
|
||||
Status s = leveldb::DB::Open(options, ...);
|
||||
Status s = rocksdb::DB::Open(options, ...);
|
||||
</pre>
|
||||
<h1>Porting</h1>
|
||||
<p>
|
||||
@@ -531,7 +531,7 @@ specific implementations of the types/methods/functions exported by
|
||||
<code>leveldb/port/port.h</code>. See <code>leveldb/port/port_example.h</code> for more
|
||||
details.
|
||||
<p>
|
||||
In addition, the new platform may need a new default <code>leveldb::Env</code>
|
||||
In addition, the new platform may need a new default <code>rocksdb::Env</code>
|
||||
implementation. See <code>leveldb/util/env_posix.h</code> for an example.
|
||||
|
||||
<h1>Other Information</h1>
|
||||
|
||||
+11
-9
@@ -31,7 +31,7 @@
|
||||
#ifdef USE_HDFS
|
||||
#include "hdfs/hdfs.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
static const std::string kProto = "hdfs://";
|
||||
static const std::string pathsep = "/";
|
||||
@@ -107,8 +107,9 @@ class HdfsEnv : public Env {
|
||||
|
||||
virtual Status NewLogger(const std::string& fname, Logger** result);
|
||||
|
||||
virtual void Schedule( void (*function)(void* arg), void* arg) {
|
||||
posixEnv->Schedule(function, arg);
|
||||
virtual void Schedule(void (*function)(void* arg), void* arg,
|
||||
Priority pri = LOW) {
|
||||
posixEnv->Schedule(function, arg, pri);
|
||||
}
|
||||
|
||||
virtual void StartThread(void (*function)(void* arg), void* arg) {
|
||||
@@ -140,8 +141,8 @@ class HdfsEnv : public Env {
|
||||
return posixEnv->GetAbsolutePath(db_path, output_path);
|
||||
}
|
||||
|
||||
virtual void SetBackgroundThreads(int number) {
|
||||
posixEnv->SetBackgroundThreads(number);
|
||||
virtual void SetBackgroundThreads(int number, Priority pri = LOW) {
|
||||
posixEnv->SetBackgroundThreads(number, pri);
|
||||
}
|
||||
|
||||
virtual std::string TimeToString(uint64_t number) {
|
||||
@@ -213,12 +214,12 @@ class HdfsEnv : public Env {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#else // USE_HDFS
|
||||
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
static const Status notsup;
|
||||
|
||||
@@ -279,7 +280,8 @@ class HdfsEnv : public Env {
|
||||
virtual Status NewLogger(const std::string& fname,
|
||||
shared_ptr<Logger>* result){return notsup;}
|
||||
|
||||
virtual void Schedule( void (*function)(void* arg), void* arg) {}
|
||||
virtual void Schedule(void (*function)(void* arg), void* arg,
|
||||
Priority pri = LOW) {}
|
||||
|
||||
virtual void StartThread(void (*function)(void* arg), void* arg) {}
|
||||
|
||||
@@ -296,7 +298,7 @@ class HdfsEnv : public Env {
|
||||
virtual Status GetAbsolutePath(const std::string& db_path,
|
||||
std::string* outputpath) {return notsup;}
|
||||
|
||||
virtual void SetBackgroundThreads(int number) {}
|
||||
virtual void SetBackgroundThreads(int number, Priority pri = LOW) {}
|
||||
|
||||
virtual std::string TimeToString(uint64_t number) { return "";}
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -383,4 +383,4 @@ Env* NewMemEnv(Env* base_env) {
|
||||
return new InMemoryEnv(base_env);
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#ifndef STORAGE_ROCKSDB_HELPERS_MEMENV_MEMENV_H_
|
||||
#define STORAGE_ROCKSDB_HELPERS_MEMENV_MEMENV_H_
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Env;
|
||||
|
||||
@@ -14,6 +14,6 @@ class Env;
|
||||
// *base_env must remain live while the result is in use.
|
||||
Env* NewMemEnv(Env* base_env);
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // STORAGE_ROCKSDB_HELPERS_MEMENV_MEMENV_H_
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class MemEnvTest {
|
||||
public:
|
||||
@@ -226,8 +226,8 @@ TEST(MemEnvTest, DBTest) {
|
||||
delete db;
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
return rocksdb::test::RunAllTests();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Arena {
|
||||
public:
|
||||
@@ -36,6 +36,8 @@ class Arena {
|
||||
void operator=(const Arena&);
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_ARENA_H_
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <stdint.h>
|
||||
#include "rocksdb/slice.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
@@ -101,6 +101,8 @@ class Cache {
|
||||
void operator=(const Cache&);
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_UTIL_CACHE_H_
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Slice;
|
||||
|
||||
@@ -66,6 +66,8 @@ class DefaultCompactionFilterFactory : public CompactionFilterFactory {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_COMPACTION_FILTER_H_
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Slice;
|
||||
|
||||
@@ -58,6 +58,8 @@ class Comparator {
|
||||
// must not be deleted.
|
||||
extern const Comparator* BytewiseComparator();
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_COMPARATOR_H_
|
||||
|
||||
+12
-3
@@ -14,7 +14,7 @@
|
||||
#include "rocksdb/types.h"
|
||||
#include "rocksdb/transaction_log.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
@@ -244,8 +244,15 @@ class DB {
|
||||
// manifest file is returned in manifest_file_size. The manifest file is an
|
||||
// ever growing file, but only the portion specified by manifest_file_size is
|
||||
// valid for this snapshot.
|
||||
// Setting flush_memtable to true does Flush before recording the live files.
|
||||
// Setting flush_memtable to false is useful when we don't want to wait for
|
||||
// flush which may have to wait for compaction to complete taking an
|
||||
// indeterminate time. But this will have to use GetSortedWalFiles after
|
||||
// GetLiveFiles to compensate for memtables missed in this snapshot due to the
|
||||
// absence of Flush, by WAL files to recover the database consistently later
|
||||
virtual Status GetLiveFiles(std::vector<std::string>&,
|
||||
uint64_t* manifest_file_size) = 0;
|
||||
uint64_t* manifest_file_size,
|
||||
bool flush_memtable = true) = 0;
|
||||
|
||||
// Retrieve the sorted list of all wal files with earliest file first
|
||||
virtual Status GetSortedWalFiles(VectorLogPtr& files) = 0;
|
||||
@@ -299,6 +306,8 @@ Status DestroyDB(const std::string& name, const Options& options);
|
||||
// on a database that contains important information.
|
||||
Status RepairDB(const std::string& dbname, const Options& options);
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_DB_H_
|
||||
|
||||
+42
-13
@@ -20,7 +20,7 @@
|
||||
#include <stdint.h>
|
||||
#include "rocksdb/status.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class FileLock;
|
||||
class Logger;
|
||||
@@ -41,7 +41,7 @@ struct EnvOptions {
|
||||
EnvOptions();
|
||||
|
||||
// construct from Options
|
||||
EnvOptions(const Options& options);
|
||||
explicit EnvOptions(const Options& options);
|
||||
|
||||
// If true, then allow caching of data in environment buffers
|
||||
bool use_os_buffer;
|
||||
@@ -162,15 +162,20 @@ class Env {
|
||||
// REQUIRES: lock has not already been unlocked.
|
||||
virtual Status UnlockFile(FileLock* lock) = 0;
|
||||
|
||||
// Arrange to run "(*function)(arg)" once in a background thread.
|
||||
//
|
||||
enum Priority { LOW, HIGH, TOTAL };
|
||||
|
||||
// Arrange to run "(*function)(arg)" once in a background thread, in
|
||||
// the thread pool specified by pri. By default, jobs go to the 'LOW'
|
||||
// priority thread pool.
|
||||
|
||||
// "function" may run in an unspecified thread. Multiple functions
|
||||
// added to the same Env may run concurrently in different threads.
|
||||
// I.e., the caller may not assume that background work items are
|
||||
// serialized.
|
||||
virtual void Schedule(
|
||||
void (*function)(void* arg),
|
||||
void* arg) = 0;
|
||||
void* arg,
|
||||
Priority pri = LOW) = 0;
|
||||
|
||||
// Start a new thread, invoking "function(arg)" within the new thread.
|
||||
// When "function(arg)" returns, the thread will be destroyed.
|
||||
@@ -210,9 +215,10 @@ class Env {
|
||||
virtual Status GetAbsolutePath(const std::string& db_path,
|
||||
std::string* output_path) = 0;
|
||||
|
||||
// The number of background worker threads for this environment.
|
||||
// default: 1
|
||||
virtual void SetBackgroundThreads(int number) = 0;
|
||||
// The number of background worker threads of a specific thread pool
|
||||
// for this environment. 'LOW' is the default pool.
|
||||
// default number: 1
|
||||
virtual void SetBackgroundThreads(int number, Priority pri = LOW) = 0;
|
||||
|
||||
// Converts seconds-since-Jan-01-1970 to a printable string
|
||||
virtual std::string TimeToString(uint64_t time) = 0;
|
||||
@@ -247,6 +253,13 @@ class SequentialFile {
|
||||
//
|
||||
// REQUIRES: External synchronization
|
||||
virtual Status Skip(uint64_t n) = 0;
|
||||
|
||||
// Remove any kind of caching of data from the offset to offset+length
|
||||
// of this file. If the length is 0, then it refers to the end of file.
|
||||
// If the system is not caching the file contents, then this is a noop.
|
||||
virtual Status InvalidateCache(size_t offset, size_t length) {
|
||||
return Status::NotSupported("InvalidateCache not supported.");
|
||||
}
|
||||
};
|
||||
|
||||
// A file abstraction for randomly reading the contents of a file.
|
||||
@@ -292,6 +305,12 @@ class RandomAccessFile {
|
||||
|
||||
virtual void Hint(AccessPattern pattern) {}
|
||||
|
||||
// Remove any kind of caching of data from the offset to offset+length
|
||||
// of this file. If the length is 0, then it refers to the end of file.
|
||||
// If the system is not caching the file contents, then this is a noop.
|
||||
virtual Status InvalidateCache(size_t offset, size_t length) {
|
||||
return Status::NotSupported("InvalidateCache not supported.");
|
||||
}
|
||||
};
|
||||
|
||||
// A file abstraction for sequential writing. The implementation
|
||||
@@ -341,6 +360,14 @@ class WritableFile {
|
||||
*block_size = preallocation_block_size_;
|
||||
}
|
||||
|
||||
// Remove any kind of caching of data from the offset to offset+length
|
||||
// of this file. If the length is 0, then it refers to the end of file.
|
||||
// If the system is not caching the file contents, then this is a noop.
|
||||
// This call has no effect on dirty pages in the cache.
|
||||
virtual Status InvalidateCache(size_t offset, size_t length) {
|
||||
return Status::NotSupported("InvalidateCache not supported.");
|
||||
}
|
||||
|
||||
protected:
|
||||
// PrepareWrite performs any necessary preparation for a write
|
||||
// before the write actually occurs. This allows for pre-allocation
|
||||
@@ -496,8 +523,8 @@ class EnvWrapper : public Env {
|
||||
return target_->LockFile(f, l);
|
||||
}
|
||||
Status UnlockFile(FileLock* l) { return target_->UnlockFile(l); }
|
||||
void Schedule(void (*f)(void*), void* a) {
|
||||
return target_->Schedule(f, a);
|
||||
void Schedule(void (*f)(void*), void* a, Priority pri) {
|
||||
return target_->Schedule(f, a, pri);
|
||||
}
|
||||
void StartThread(void (*f)(void*), void* a) {
|
||||
return target_->StartThread(f, a);
|
||||
@@ -525,8 +552,8 @@ class EnvWrapper : public Env {
|
||||
std::string* output_path) {
|
||||
return target_->GetAbsolutePath(db_path, output_path);
|
||||
}
|
||||
void SetBackgroundThreads(int num) {
|
||||
return target_->SetBackgroundThreads(num);
|
||||
void SetBackgroundThreads(int num, Priority pri) {
|
||||
return target_->SetBackgroundThreads(num, pri);
|
||||
}
|
||||
std::string TimeToString(uint64_t time) {
|
||||
return target_->TimeToString(time);
|
||||
@@ -536,6 +563,8 @@ class EnvWrapper : public Env {
|
||||
Env* target_;
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_ENV_H_
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Slice;
|
||||
|
||||
@@ -66,5 +66,6 @@ class FilterPolicy {
|
||||
extern const FilterPolicy* NewBloomFilterPolicy(int bits_per_key);
|
||||
|
||||
}
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_FILTER_POLICY_H_
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "rocksdb/slice.h"
|
||||
#include "rocksdb/status.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Iterator {
|
||||
public:
|
||||
@@ -97,6 +97,8 @@ extern Iterator* NewEmptyIterator();
|
||||
// Return an empty iterator with the specified status.
|
||||
extern Iterator* NewErrorIterator(const Status& status);
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_ITERATOR_H_
|
||||
|
||||
@@ -3,12 +3,18 @@
|
||||
#define STORAGE_ROCKSDB_INCLUDE_LDB_TOOL_H
|
||||
#include "rocksdb/options.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class LDBTool {
|
||||
public:
|
||||
void Run(int argc, char** argv, Options = Options());
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
namespace leveldb = rocksdb;
|
||||
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_LDB_TOOL_H
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include "rocksdb/slice.h"
|
||||
#include "rocksdb/slice_transform.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class MemTableRep {
|
||||
public:
|
||||
@@ -143,6 +143,7 @@ class MemTableRepFactory {
|
||||
virtual ~MemTableRepFactory() { };
|
||||
virtual std::shared_ptr<MemTableRep> CreateMemTableRep(
|
||||
MemTableRep::KeyComparator&, Arena*) = 0;
|
||||
virtual const char* Name() const = 0;
|
||||
};
|
||||
|
||||
// This creates MemTableReps that are backed by an std::vector. On iteration,
|
||||
@@ -152,13 +153,16 @@ class MemTableRepFactory {
|
||||
// Parameters:
|
||||
// count: Passed to the constructor of the underlying std::vector of each
|
||||
// VectorRep. On initialization, the underlying array will be at least count
|
||||
// size.
|
||||
// bytes reserved for usage.
|
||||
class VectorRepFactory : public MemTableRepFactory {
|
||||
const size_t count_;
|
||||
public:
|
||||
explicit VectorRepFactory(size_t count = 0) : count_(count) { }
|
||||
virtual std::shared_ptr<MemTableRep> CreateMemTableRep(
|
||||
MemTableRep::KeyComparator&, Arena*) override;
|
||||
virtual const char* Name() const override {
|
||||
return "VectorRepFactory";
|
||||
}
|
||||
};
|
||||
|
||||
// This uses a skip list to store keys. It is the default.
|
||||
@@ -166,6 +170,9 @@ class SkipListFactory : public MemTableRepFactory {
|
||||
public:
|
||||
virtual std::shared_ptr<MemTableRep> CreateMemTableRep(
|
||||
MemTableRep::KeyComparator&, Arena*) override;
|
||||
virtual const char* Name() const override {
|
||||
return "SkipListFactory";
|
||||
}
|
||||
};
|
||||
|
||||
// TransformReps are backed by an unordered map of buffers to buckets. When
|
||||
@@ -201,6 +208,10 @@ class TransformRepFactory : public MemTableRepFactory {
|
||||
virtual std::shared_ptr<MemTableRep> CreateMemTableRep(
|
||||
MemTableRep::KeyComparator&, Arena*) override;
|
||||
|
||||
virtual const char* Name() const override {
|
||||
return "TransformRepFactory";
|
||||
}
|
||||
|
||||
const SliceTransform* GetTransform() { return transform_; }
|
||||
|
||||
protected:
|
||||
@@ -219,6 +230,9 @@ public:
|
||||
: TransformRepFactory(NewNoopTransform(),
|
||||
bucket_count,
|
||||
num_locks) { }
|
||||
virtual const char* Name() const override {
|
||||
return "UnsortedRepFactory";
|
||||
}
|
||||
};
|
||||
|
||||
// PrefixHashReps bin user keys based on a fixed-size prefix. This optimizes for
|
||||
@@ -234,8 +248,14 @@ public:
|
||||
|
||||
virtual std::shared_ptr<MemTableRep> CreateMemTableRep(
|
||||
MemTableRep::KeyComparator&, Arena*) override;
|
||||
|
||||
virtual const char* Name() const override {
|
||||
return "PrefixHashRepFactory";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_DB_MEMTABLEREP_H_
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <deque>
|
||||
#include "rocksdb/slice.h" // TODO: Remove this when migration is done;
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Slice;
|
||||
class Logger;
|
||||
@@ -142,6 +142,8 @@ class AssociativeMergeOperator : public MergeOperator {
|
||||
Logger* logger) const override;
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_MERGE_OPERATOR_H_
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "rocksdb/memtablerep.h"
|
||||
#include "rocksdb/slice_transform.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Cache;
|
||||
class Comparator;
|
||||
@@ -369,10 +369,23 @@ struct Options {
|
||||
// every compaction run.
|
||||
uint64_t delete_obsolete_files_period_micros;
|
||||
|
||||
// Maximum number of concurrent background compactions.
|
||||
// Maximum number of concurrent background jobs, submitted to
|
||||
// the default LOW priority thread pool
|
||||
// Default: 1
|
||||
int max_background_compactions;
|
||||
|
||||
// Maximum number of concurrent background memtable flush jobs, submitted to
|
||||
// the HIGH priority thread pool.
|
||||
// By default, all background jobs (major compaction and memtable flush) go
|
||||
// to the LOW priority pool. If this option is set to a positive number,
|
||||
// memtable flush jobs will be submitted to the HIGH priority pool.
|
||||
// It is important when the same Env is shared by multiple db instances.
|
||||
// Without a separate pool, long running major compaction jobs could
|
||||
// potentially block memtable flush jobs of other db instances, leading to
|
||||
// unnecessary Put stalls.
|
||||
// Default: 0
|
||||
int max_background_flushes;
|
||||
|
||||
// Specify the maximal size of the info log file. If the log file
|
||||
// is larger than `max_log_file_size`, a new info log file will
|
||||
// be created.
|
||||
@@ -548,6 +561,11 @@ struct Options {
|
||||
// an application to modify/delete a key-value during background compaction.
|
||||
// Default: a factory that doesn't provide any object
|
||||
std::shared_ptr<CompactionFilterFactory> compaction_filter_factory;
|
||||
|
||||
// Remove the log file immediately after the corresponding memtable is flushed
|
||||
// to data file.
|
||||
// Default: true
|
||||
bool purge_log_after_memtable_flush;
|
||||
};
|
||||
|
||||
//
|
||||
@@ -655,6 +673,8 @@ struct FlushOptions {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_OPTIONS_H_
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
enum PerfLevel {
|
||||
kDisable = 0, // disable perf stats
|
||||
@@ -28,11 +28,14 @@ struct PerfContext {
|
||||
uint64_t block_read_time;
|
||||
uint64_t block_checksum_time;
|
||||
uint64_t block_decompress_time;
|
||||
uint64_t internal_key_skipped_count;
|
||||
uint64_t internal_delete_skipped_count;
|
||||
};
|
||||
|
||||
extern __thread PerfContext perf_context;
|
||||
|
||||
}
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright (c) 2013 Facebook.
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// This is for backward compatibility with applications that use the
|
||||
// 'leveldb' namespace. This file will be deleted in a future release.
|
||||
//
|
||||
namespace leveldb = rocksdb;
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Slice {
|
||||
public:
|
||||
@@ -117,6 +117,8 @@ inline int Slice::compare(const Slice& b) const {
|
||||
return r;
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_SLICE_H_
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Slice;
|
||||
|
||||
@@ -40,4 +40,6 @@ extern const SliceTransform* NewNoopTransform();
|
||||
|
||||
}
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_SLICE_TRANSFORM_H_
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
/**
|
||||
* Keep adding ticker's here.
|
||||
@@ -23,58 +23,64 @@ namespace leveldb {
|
||||
* And incrementing TICKER_ENUM_MAX.
|
||||
*/
|
||||
enum Tickers {
|
||||
BLOCK_CACHE_MISS = 0,
|
||||
BLOCK_CACHE_HIT = 1,
|
||||
BLOOM_FILTER_USEFUL = 2, // no. of times bloom filter has avoided file reads.
|
||||
BLOCK_CACHE_MISS,
|
||||
BLOCK_CACHE_HIT,
|
||||
BLOOM_FILTER_USEFUL, // no. of times bloom filter has avoided file reads.
|
||||
|
||||
/**
|
||||
* COMPACTION_KEY_DROP_* count the reasons for key drop during compaction
|
||||
* There are 3 reasons currently.
|
||||
*/
|
||||
COMPACTION_KEY_DROP_NEWER_ENTRY = 3, // key was written with a newer value.
|
||||
COMPACTION_KEY_DROP_OBSOLETE = 4, // The key is obsolete.
|
||||
COMPACTION_KEY_DROP_USER = 5, // user compaction function has dropped the key.
|
||||
// Number of keys written to the database via the Put and Write call's
|
||||
NUMBER_KEYS_WRITTEN = 6,
|
||||
// Number of Keys read,
|
||||
NUMBER_KEYS_READ = 7,
|
||||
// Bytes written / read
|
||||
BYTES_WRITTEN = 8,
|
||||
BYTES_READ = 9,
|
||||
NO_FILE_CLOSES = 10,
|
||||
NO_FILE_OPENS = 11,
|
||||
NO_FILE_ERRORS = 12,
|
||||
// Time system had to wait to do LO-L1 compactions
|
||||
STALL_L0_SLOWDOWN_MICROS = 13,
|
||||
// Time system had to wait to move memtable to L1.
|
||||
STALL_MEMTABLE_COMPACTION_MICROS = 14,
|
||||
// write throttle because of too many files in L0
|
||||
STALL_L0_NUM_FILES_MICROS = 15,
|
||||
RATE_LIMIT_DELAY_MILLIS = 16,
|
||||
COMPACTION_KEY_DROP_NEWER_ENTRY, // key was written with a newer value.
|
||||
COMPACTION_KEY_DROP_OBSOLETE, // The key is obsolete.
|
||||
COMPACTION_KEY_DROP_USER, // user compaction function has dropped the key.
|
||||
|
||||
NO_ITERATORS = 17, // number of iterators currently open
|
||||
// Number of keys written to the database via the Put and Write call's
|
||||
NUMBER_KEYS_WRITTEN,
|
||||
// Number of Keys read,
|
||||
NUMBER_KEYS_READ,
|
||||
// Bytes written / read
|
||||
BYTES_WRITTEN,
|
||||
BYTES_READ,
|
||||
NO_FILE_CLOSES,
|
||||
NO_FILE_OPENS,
|
||||
NO_FILE_ERRORS,
|
||||
// Time system had to wait to do LO-L1 compactions
|
||||
STALL_L0_SLOWDOWN_MICROS,
|
||||
// Time system had to wait to move memtable to L1.
|
||||
STALL_MEMTABLE_COMPACTION_MICROS,
|
||||
// write throttle because of too many files in L0
|
||||
STALL_L0_NUM_FILES_MICROS,
|
||||
RATE_LIMIT_DELAY_MILLIS,
|
||||
|
||||
NO_ITERATORS, // number of iterators currently open
|
||||
|
||||
// Number of MultiGet calls, keys read, and bytes read
|
||||
NUMBER_MULTIGET_CALLS = 18,
|
||||
NUMBER_MULTIGET_KEYS_READ = 19,
|
||||
NUMBER_MULTIGET_BYTES_READ = 20,
|
||||
NUMBER_MULTIGET_CALLS,
|
||||
NUMBER_MULTIGET_KEYS_READ,
|
||||
NUMBER_MULTIGET_BYTES_READ,
|
||||
|
||||
// Number of deletes records that were not required to be
|
||||
// written to storage because key does not exist
|
||||
NUMBER_FILTERED_DELETES = 21,
|
||||
NUMBER_MERGE_FAILURES = 22,
|
||||
SEQUENCE_NUMBER = 23,
|
||||
NUMBER_FILTERED_DELETES,
|
||||
NUMBER_MERGE_FAILURES,
|
||||
SEQUENCE_NUMBER,
|
||||
|
||||
// number of times bloom was checked before creating iterator on a
|
||||
// file, and the number of times the check was useful in avoiding
|
||||
// iterator creation (and thus likely IOPs).
|
||||
BLOOM_FILTER_PREFIX_CHECKED = 24,
|
||||
BLOOM_FILTER_PREFIX_USEFUL = 25,
|
||||
BLOOM_FILTER_PREFIX_CHECKED,
|
||||
BLOOM_FILTER_PREFIX_USEFUL,
|
||||
|
||||
// Number of times we had to reseek inside an iteration to skip
|
||||
// over large number of keys with same userkey.
|
||||
NUMBER_OF_RESEEKS_IN_ITERATION = 26,
|
||||
NUMBER_OF_RESEEKS_IN_ITERATION,
|
||||
|
||||
TICKER_ENUM_MAX = 27
|
||||
// Record the number of calls to GetUpadtesSince. Useful to keep track of
|
||||
// transaction log iterator refreshes
|
||||
GET_UPDATES_SINCE_CALLS,
|
||||
|
||||
TICKER_ENUM_MAX
|
||||
};
|
||||
|
||||
// The order of items listed in Tickers should be the same as
|
||||
@@ -106,7 +112,8 @@ const std::vector<std::pair<Tickers, std::string>> TickersNameMap = {
|
||||
{ SEQUENCE_NUMBER, "rocksdb.sequence.number" },
|
||||
{ BLOOM_FILTER_PREFIX_CHECKED, "rocksdb.bloom.filter.prefix.checked" },
|
||||
{ BLOOM_FILTER_PREFIX_USEFUL, "rocksdb.bloom.filter.prefix.useful" },
|
||||
{ NUMBER_OF_RESEEKS_IN_ITERATION, "rocksdb.number.reseeks.iteration" }
|
||||
{ NUMBER_OF_RESEEKS_IN_ITERATION, "rocksdb.number.reseeks.iteration" },
|
||||
{ GET_UPDATES_SINCE_CALLS, "rocksdb.getupdatessince.calls" }
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -117,27 +124,27 @@ const std::vector<std::pair<Tickers, std::string>> TickersNameMap = {
|
||||
* And increment HISTOGRAM_ENUM_MAX
|
||||
*/
|
||||
enum Histograms {
|
||||
DB_GET = 0,
|
||||
DB_WRITE = 1,
|
||||
COMPACTION_TIME = 2,
|
||||
TABLE_SYNC_MICROS = 3,
|
||||
COMPACTION_OUTFILE_SYNC_MICROS = 4,
|
||||
WAL_FILE_SYNC_MICROS = 5,
|
||||
MANIFEST_FILE_SYNC_MICROS = 6,
|
||||
DB_GET,
|
||||
DB_WRITE,
|
||||
COMPACTION_TIME,
|
||||
TABLE_SYNC_MICROS,
|
||||
COMPACTION_OUTFILE_SYNC_MICROS,
|
||||
WAL_FILE_SYNC_MICROS,
|
||||
MANIFEST_FILE_SYNC_MICROS,
|
||||
// TIME SPENT IN IO DURING TABLE OPEN
|
||||
TABLE_OPEN_IO_MICROS = 7,
|
||||
DB_MULTIGET = 8,
|
||||
READ_BLOCK_COMPACTION_MICROS = 9,
|
||||
READ_BLOCK_GET_MICROS = 10,
|
||||
WRITE_RAW_BLOCK_MICROS = 11,
|
||||
TABLE_OPEN_IO_MICROS,
|
||||
DB_MULTIGET,
|
||||
READ_BLOCK_COMPACTION_MICROS,
|
||||
READ_BLOCK_GET_MICROS,
|
||||
WRITE_RAW_BLOCK_MICROS,
|
||||
|
||||
STALL_L0_SLOWDOWN_COUNT = 12,
|
||||
STALL_MEMTABLE_COMPACTION_COUNT = 13,
|
||||
STALL_L0_NUM_FILES_COUNT = 14,
|
||||
HARD_RATE_LIMIT_DELAY_COUNT = 15,
|
||||
SOFT_RATE_LIMIT_DELAY_COUNT = 16,
|
||||
NUM_FILES_IN_SINGLE_COMPACTION = 17,
|
||||
HISTOGRAM_ENUM_MAX = 18
|
||||
STALL_L0_SLOWDOWN_COUNT,
|
||||
STALL_MEMTABLE_COMPACTION_COUNT,
|
||||
STALL_L0_NUM_FILES_COUNT,
|
||||
HARD_RATE_LIMIT_DELAY_COUNT,
|
||||
SOFT_RATE_LIMIT_DELAY_COUNT,
|
||||
NUM_FILES_IN_SINGLE_COMPACTION,
|
||||
HISTOGRAM_ENUM_MAX
|
||||
};
|
||||
|
||||
const std::vector<std::pair<Histograms, std::string>> HistogramsNameMap = {
|
||||
@@ -251,6 +258,8 @@ inline void SetTickerCount(std::shared_ptr<Statistics> statistics,
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_STATISTICS_H_
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <string>
|
||||
#include "rocksdb/slice.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Status {
|
||||
public:
|
||||
@@ -121,6 +121,8 @@ inline void Status::operator=(const Status& s) {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_STATUS_H_
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "rocksdb/options.h"
|
||||
#include "rocksdb/status.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class BlockBuilder;
|
||||
class BlockHandle;
|
||||
@@ -90,6 +90,8 @@ class TableBuilder {
|
||||
void operator=(const TableBuilder&);
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_TABLE_BUILDER_H_
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "rocksdb/types.h"
|
||||
#include "rocksdb/write_batch.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class LogFile;
|
||||
typedef std::vector<std::unique_ptr<LogFile>> VectorLogPtr;
|
||||
@@ -76,6 +76,8 @@ class TransactionLogIterator {
|
||||
// ONLY use if Valid() is true and status() is OK.
|
||||
virtual BatchResult GetBatch() = 0;
|
||||
};
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_TRANSACTION_LOG_ITERATOR_H_
|
||||
|
||||
@@ -3,12 +3,15 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
// Define all public custom types here.
|
||||
|
||||
// Represents a sequence number in a WAL file.
|
||||
typedef uint64_t SequenceNumber;
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_TYPES_H_
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "rocksdb/slice.h"
|
||||
#include "rocksdb/statistics.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
//
|
||||
// Algorithm used to make a compaction request stop picking new files
|
||||
@@ -36,9 +36,21 @@ class CompactionOptionsUniversal {
|
||||
// The minimum number of files in a single compaction run. Default: 2
|
||||
unsigned int min_merge_width;
|
||||
|
||||
// The maximum number of files in a single compaction run. Default: INT_MAX
|
||||
// The maximum number of files in a single compaction run. Default: UINT_MAX
|
||||
unsigned int max_merge_width;
|
||||
|
||||
// The size amplification is defined as the amount (in percentage) of
|
||||
// additional storage needed to store a single byte of data in the database.
|
||||
// For example, a size amplification of 2% means that a database that
|
||||
// contains 100 bytes of user-data may occupy upto 102 bytes of
|
||||
// physical storage. By this definition, a fully compacted database has
|
||||
// a size amplification of 0%. Rocksdb uses the following heuristic
|
||||
// to calculate size amplification: it assumes that all files excluding
|
||||
// the earliest file contribute to the size amplification.
|
||||
// Default: 200, which means that a 100 byte database could require upto
|
||||
// 300 bytes of storage.
|
||||
unsigned int max_size_amplification_percent;
|
||||
|
||||
// The algorithm used to stop picking files into a single compaction run
|
||||
// Default: kCompactionStopStyleTotalSize
|
||||
CompactionStopStyle stop_style;
|
||||
@@ -48,10 +60,13 @@ class CompactionOptionsUniversal {
|
||||
size_ratio(1),
|
||||
min_merge_width(2),
|
||||
max_merge_width(UINT_MAX),
|
||||
max_size_amplification_percent(200),
|
||||
stop_style(kCompactionStopStyleTotalSize) {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_UNIVERSAL_COMPACTION_OPTIONS_H
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <string>
|
||||
#include "rocksdb/status.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
class Slice;
|
||||
|
||||
@@ -94,6 +94,8 @@ class WriteBatch {
|
||||
// Intentionally copyable
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#include "rocksdb/rocksdb_to_leveldb.h"
|
||||
|
||||
#endif // STORAGE_ROCKSDB_INCLUDE_WRITE_BATCH_H_
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "rocksdb/db.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
// This class contains APIs to stack rocksdb wrappers.Eg. Stack TTL over base d
|
||||
class StackableDB : public DB {
|
||||
@@ -133,9 +133,9 @@ class StackableDB : public DB {
|
||||
return sdb_->EnableFileDeletions();
|
||||
}
|
||||
|
||||
virtual Status GetLiveFiles(std::vector<std::string>& vec, uint64_t* mfs)
|
||||
override {
|
||||
return sdb_->GetLiveFiles(vec, mfs);
|
||||
virtual Status GetLiveFiles(std::vector<std::string>& vec, uint64_t* mfs,
|
||||
bool flush_memtable = true) override {
|
||||
return sdb_->GetLiveFiles(vec, mfs, flush_memtable);
|
||||
}
|
||||
|
||||
virtual SequenceNumber GetLatestSequenceNumber() override {
|
||||
@@ -160,6 +160,6 @@ class StackableDB : public DB {
|
||||
StackableDB* sdb_;
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // LEVELDB_INCLUDE_UTILITIES_STACKABLE_DB_H_
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "stackable_db.h"
|
||||
|
||||
namespace leveldb {
|
||||
namespace rocksdb {
|
||||
|
||||
// This class contains APIs to open leveldb with specific support eg. TTL
|
||||
class UtilityDB {
|
||||
@@ -49,6 +49,6 @@ class UtilityDB {
|
||||
bool read_only = false);
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // LEVELDB_INCLUDE_UTILITIES_UTILITY_DB_H_
|
||||
|
||||
+3
-3
@@ -39,19 +39,19 @@ import static org.fusesource.hawtjni.runtime.ClassFlag.CPP;
|
||||
import static org.fusesource.hawtjni.runtime.MethodFlag.CPP_DELETE;
|
||||
|
||||
/**
|
||||
* Provides a java interface to the C++ leveldb::Cache class.
|
||||
* Provides a java interface to the C++ rocksdb::Cache class.
|
||||
*
|
||||
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
|
||||
*/
|
||||
public class NativeCache extends NativeObject {
|
||||
|
||||
@JniClass(name="leveldb::Cache", flags={CPP})
|
||||
@JniClass(name="rocksdb::Cache", flags={CPP})
|
||||
private static class CacheJNI {
|
||||
static {
|
||||
NativeDB.LIBRARY.load();
|
||||
}
|
||||
|
||||
@JniMethod(cast="leveldb::Cache *", accessor="leveldb::NewLRUCache")
|
||||
@JniMethod(cast="rocksdb::Cache *", accessor="rocksdb::NewLRUCache")
|
||||
public static final native long NewLRUCache(
|
||||
@JniArg(cast="size_t") long capacity);
|
||||
|
||||
|
||||
+2
-2
@@ -40,7 +40,7 @@ import static org.fusesource.hawtjni.runtime.ClassFlag.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Provides a java interface to the C++ leveldb::Comparator class.
|
||||
* Provides a java interface to the C++ rocksdb::Comparator class.
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
|
||||
@@ -85,7 +85,7 @@ public abstract class NativeComparator extends NativeObject {
|
||||
@JniField(flags={CONSTANT}, accessor="sizeof(struct JNIComparator)")
|
||||
static int SIZEOF;
|
||||
|
||||
@JniField(flags={CONSTANT}, cast="const Comparator*", accessor="leveldb::BytewiseComparator()")
|
||||
@JniField(flags={CONSTANT}, cast="const Comparator*", accessor="rocksdb::BytewiseComparator()")
|
||||
private static long BYTEWISE_COMPARATOR;
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@
|
||||
package org.fusesource.leveldbjni.internal;
|
||||
|
||||
/**
|
||||
* Provides a java interface to the C++ leveldb::CompressionType enum.
|
||||
* Provides a java interface to the C++ rocksdb::CompressionType enum.
|
||||
*
|
||||
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
|
||||
*/
|
||||
|
||||
+14
-14
@@ -52,7 +52,7 @@ public class NativeDB extends NativeObject {
|
||||
|
||||
public static final Library LIBRARY = new Library("leveldbjni", NativeDB.class);
|
||||
|
||||
@JniClass(name="leveldb::DB", flags={CPP})
|
||||
@JniClass(name="rocksdb::DB", flags={CPP})
|
||||
static class DBJNI {
|
||||
static {
|
||||
NativeDB.LIBRARY.load();
|
||||
@@ -79,13 +79,13 @@ public class NativeDB extends NativeObject {
|
||||
long self
|
||||
);
|
||||
|
||||
@JniMethod(copy="leveldb::Status", accessor = "leveldb::DB::Open")
|
||||
@JniMethod(copy="rocksdb::Status", accessor = "rocksdb::DB::Open")
|
||||
static final native long Open(
|
||||
@JniArg(flags={BY_VALUE, NO_OUT}) NativeOptions options,
|
||||
@JniArg(cast="const char*") String path,
|
||||
@JniArg(cast="leveldb::DB**") long[] self);
|
||||
@JniArg(cast="rocksdb::DB**") long[] self);
|
||||
|
||||
@JniMethod(copy="leveldb::Status", flags={CPP_METHOD})
|
||||
@JniMethod(copy="rocksdb::Status", flags={CPP_METHOD})
|
||||
static final native long Put(
|
||||
long self,
|
||||
@JniArg(flags={BY_VALUE, NO_OUT}) NativeWriteOptions options,
|
||||
@@ -93,21 +93,21 @@ public class NativeDB extends NativeObject {
|
||||
@JniArg(flags={BY_VALUE, NO_OUT}) NativeSlice value
|
||||
);
|
||||
|
||||
@JniMethod(copy="leveldb::Status", flags={CPP_METHOD})
|
||||
@JniMethod(copy="rocksdb::Status", flags={CPP_METHOD})
|
||||
static final native long Delete(
|
||||
long self,
|
||||
@JniArg(flags={BY_VALUE, NO_OUT}) NativeWriteOptions options,
|
||||
@JniArg(flags={BY_VALUE, NO_OUT}) NativeSlice key
|
||||
);
|
||||
|
||||
@JniMethod(copy="leveldb::Status", flags={CPP_METHOD})
|
||||
@JniMethod(copy="rocksdb::Status", flags={CPP_METHOD})
|
||||
static final native long Write(
|
||||
long self,
|
||||
@JniArg(flags={BY_VALUE}) NativeWriteOptions options,
|
||||
@JniArg(cast="leveldb::WriteBatch *") long updates
|
||||
@JniArg(cast="rocksdb::WriteBatch *") long updates
|
||||
);
|
||||
|
||||
@JniMethod(copy="leveldb::Status", flags={CPP_METHOD})
|
||||
@JniMethod(copy="rocksdb::Status", flags={CPP_METHOD})
|
||||
static final native long Get(
|
||||
long self,
|
||||
@JniArg(flags={NO_OUT, BY_VALUE}) NativeReadOptions options,
|
||||
@@ -115,26 +115,26 @@ public class NativeDB extends NativeObject {
|
||||
@JniArg(cast="std::string *") long value
|
||||
);
|
||||
|
||||
@JniMethod(cast="leveldb::Iterator *", flags={CPP_METHOD})
|
||||
@JniMethod(cast="rocksdb::Iterator *", flags={CPP_METHOD})
|
||||
static final native long NewIterator(
|
||||
long self,
|
||||
@JniArg(flags={NO_OUT, BY_VALUE}) NativeReadOptions options
|
||||
);
|
||||
|
||||
@JniMethod(cast="leveldb::Snapshot *", flags={CPP_METHOD})
|
||||
@JniMethod(cast="rocksdb::Snapshot *", flags={CPP_METHOD})
|
||||
static final native long GetSnapshot(
|
||||
long self);
|
||||
|
||||
@JniMethod(flags={CPP_METHOD})
|
||||
static final native void ReleaseSnapshot(
|
||||
long self,
|
||||
@JniArg(cast="const leveldb::Snapshot *") long snapshot
|
||||
@JniArg(cast="const rocksdb::Snapshot *") long snapshot
|
||||
);
|
||||
|
||||
@JniMethod(flags={CPP_METHOD})
|
||||
static final native void GetApproximateSizes(
|
||||
long self,
|
||||
@JniArg(cast="const leveldb::Range *") long range,
|
||||
@JniArg(cast="const rocksdb::Range *") long range,
|
||||
int n,
|
||||
@JniArg(cast="uint64_t*") long[] sizes
|
||||
);
|
||||
@@ -146,12 +146,12 @@ public class NativeDB extends NativeObject {
|
||||
@JniArg(cast="std::string *") long value
|
||||
);
|
||||
|
||||
@JniMethod(copy="leveldb::Status", accessor = "leveldb::DestroyDB")
|
||||
@JniMethod(copy="rocksdb::Status", accessor = "rocksdb::DestroyDB")
|
||||
static final native long DestroyDB(
|
||||
@JniArg(cast="const char*") String path,
|
||||
@JniArg(flags={BY_VALUE, NO_OUT}) NativeOptions options);
|
||||
|
||||
@JniMethod(copy="leveldb::Status", accessor = "leveldb::RepairDB")
|
||||
@JniMethod(copy="rocksdb::Status", accessor = "rocksdb::RepairDB")
|
||||
static final native long RepairDB(
|
||||
@JniArg(cast="const char*") String path,
|
||||
@JniArg(flags={BY_VALUE, NO_OUT}) NativeOptions options);
|
||||
|
||||
+5
-5
@@ -38,13 +38,13 @@ import static org.fusesource.hawtjni.runtime.ArgFlag.*;
|
||||
import static org.fusesource.hawtjni.runtime.ClassFlag.*;
|
||||
|
||||
/**
|
||||
* Provides a java interface to the C++ leveldb::Iterator class.
|
||||
* Provides a java interface to the C++ rocksdb::Iterator class.
|
||||
*
|
||||
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
|
||||
*/
|
||||
public class NativeIterator extends NativeObject {
|
||||
|
||||
@JniClass(name="leveldb::Iterator", flags={CPP})
|
||||
@JniClass(name="rocksdb::Iterator", flags={CPP})
|
||||
private static class IteratorJNI {
|
||||
static {
|
||||
NativeDB.LIBRARY.load();
|
||||
@@ -86,17 +86,17 @@ public class NativeIterator extends NativeObject {
|
||||
long self
|
||||
);
|
||||
|
||||
@JniMethod(copy="leveldb::Slice", flags={CPP_METHOD})
|
||||
@JniMethod(copy="rocksdb::Slice", flags={CPP_METHOD})
|
||||
static final native long key(
|
||||
long self
|
||||
);
|
||||
|
||||
@JniMethod(copy="leveldb::Slice", flags={CPP_METHOD})
|
||||
@JniMethod(copy="rocksdb::Slice", flags={CPP_METHOD})
|
||||
static final native long value(
|
||||
long self
|
||||
);
|
||||
|
||||
@JniMethod(copy="leveldb::Status", flags={CPP_METHOD})
|
||||
@JniMethod(copy="rocksdb::Status", flags={CPP_METHOD})
|
||||
static final native long status(
|
||||
long self
|
||||
);
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ import static org.fusesource.hawtjni.runtime.MethodFlag.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Provides a java interface to the C++ leveldb::Logger class.
|
||||
* Provides a java interface to the C++ rocksdb::Logger class.
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
|
||||
|
||||
+8
-8
@@ -42,11 +42,11 @@ import static org.fusesource.hawtjni.runtime.FieldFlag.FIELD_SKIP;
|
||||
import static org.fusesource.hawtjni.runtime.MethodFlag.CONSTANT_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Provides a java interface to the C++ leveldb::Options class.
|
||||
* Provides a java interface to the C++ rocksdb::Options class.
|
||||
*
|
||||
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
|
||||
*/
|
||||
@JniClass(name="leveldb::Options", flags={STRUCT, CPP})
|
||||
@JniClass(name="rocksdb::Options", flags={STRUCT, CPP})
|
||||
public class NativeOptions {
|
||||
|
||||
static {
|
||||
@@ -57,7 +57,7 @@ public class NativeOptions {
|
||||
@JniMethod(flags={CONSTANT_INITIALIZER})
|
||||
private static final native void init();
|
||||
|
||||
@JniField(flags={CONSTANT}, cast="Env*", accessor="leveldb::Env::Default()")
|
||||
@JniField(flags={CONSTANT}, cast="Env*", accessor="rocksdb::Env::Default()")
|
||||
private static long DEFAULT_ENV;
|
||||
|
||||
private boolean create_if_missing = false;
|
||||
@@ -83,7 +83,7 @@ public class NativeOptions {
|
||||
|
||||
@JniField(flags={FIELD_SKIP})
|
||||
private NativeComparator comparatorObject = NativeComparator.BYTEWISE_COMPARATOR;
|
||||
@JniField(cast="const leveldb::Comparator*")
|
||||
@JniField(cast="const rocksdb::Comparator*")
|
||||
private long comparator = comparatorObject.pointer();
|
||||
|
||||
@JniField(cast="uint64_t")
|
||||
@@ -110,17 +110,17 @@ public class NativeOptions {
|
||||
|
||||
@JniField(flags={FIELD_SKIP})
|
||||
private NativeLogger infoLogObject = null;
|
||||
@JniField(cast="leveldb::Logger*")
|
||||
@JniField(cast="rocksdb::Logger*")
|
||||
private long info_log = 0;
|
||||
|
||||
@JniField(cast="leveldb::Env*")
|
||||
@JniField(cast="rocksdb::Env*")
|
||||
private long env = DEFAULT_ENV;
|
||||
@JniField(cast="leveldb::Cache*")
|
||||
@JniField(cast="rocksdb::Cache*")
|
||||
private long block_cache = 0;
|
||||
@JniField(flags={FIELD_SKIP})
|
||||
private NativeCache cache;
|
||||
|
||||
@JniField(cast="leveldb::CompressionType")
|
||||
@JniField(cast="rocksdb::CompressionType")
|
||||
private int compression = NativeCompressionType.kSnappyCompression.value;
|
||||
|
||||
public NativeOptions createIfMissing(boolean value) {
|
||||
|
||||
+3
-3
@@ -41,13 +41,13 @@ import static org.fusesource.hawtjni.runtime.FieldFlag.FIELD_SKIP;
|
||||
import static org.fusesource.hawtjni.runtime.MethodFlag.CONSTANT_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Provides a java interface to the C++ leveldb::ReadOptions class.
|
||||
* Provides a java interface to the C++ rocksdb::ReadOptions class.
|
||||
*
|
||||
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
|
||||
*/
|
||||
public class NativeRange {
|
||||
|
||||
@JniClass(name="leveldb::Range", flags={STRUCT, CPP})
|
||||
@JniClass(name="rocksdb::Range", flags={STRUCT, CPP})
|
||||
static public class RangeJNI {
|
||||
|
||||
static {
|
||||
@@ -69,7 +69,7 @@ public class NativeRange {
|
||||
@JniMethod(flags={CONSTANT_INITIALIZER})
|
||||
private static final native void init();
|
||||
|
||||
@JniField(flags={CONSTANT}, accessor="sizeof(struct leveldb::Range)")
|
||||
@JniField(flags={CONSTANT}, accessor="sizeof(struct rocksdb::Range)")
|
||||
static int SIZEOF;
|
||||
|
||||
@JniField
|
||||
|
||||
+3
-3
@@ -38,11 +38,11 @@ import static org.fusesource.hawtjni.runtime.ClassFlag.CPP;
|
||||
import static org.fusesource.hawtjni.runtime.ClassFlag.STRUCT;
|
||||
|
||||
/**
|
||||
* Provides a java interface to the C++ leveldb::ReadOptions class.
|
||||
* Provides a java interface to the C++ rocksdb::ReadOptions class.
|
||||
*
|
||||
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
|
||||
*/
|
||||
@JniClass(name="leveldb::ReadOptions", flags={STRUCT, CPP})
|
||||
@JniClass(name="rocksdb::ReadOptions", flags={STRUCT, CPP})
|
||||
public class NativeReadOptions {
|
||||
|
||||
@JniField
|
||||
@@ -51,7 +51,7 @@ public class NativeReadOptions {
|
||||
@JniField
|
||||
private boolean fill_cache = true;
|
||||
|
||||
@JniField(cast="const leveldb::Snapshot*")
|
||||
@JniField(cast="const rocksdb::Snapshot*")
|
||||
private long snapshot=0;
|
||||
|
||||
public boolean fillCache() {
|
||||
|
||||
+4
-4
@@ -41,14 +41,14 @@ import static org.fusesource.hawtjni.runtime.MethodFlag.CONSTANT_INITIALIZER;
|
||||
import static org.fusesource.hawtjni.runtime.MethodFlag.CPP_DELETE;
|
||||
|
||||
/**
|
||||
* Provides a java interface to the C++ leveldb::Slice class.
|
||||
* Provides a java interface to the C++ rocksdb::Slice class.
|
||||
*
|
||||
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
|
||||
*/
|
||||
@JniClass(name="leveldb::Slice", flags={STRUCT, CPP})
|
||||
@JniClass(name="rocksdb::Slice", flags={STRUCT, CPP})
|
||||
class NativeSlice {
|
||||
|
||||
@JniClass(name="leveldb::Slice", flags={CPP})
|
||||
@JniClass(name="rocksdb::Slice", flags={CPP})
|
||||
static class SliceJNI {
|
||||
static {
|
||||
NativeDB.LIBRARY.load();
|
||||
@@ -74,7 +74,7 @@ class NativeSlice {
|
||||
@JniMethod(flags={CONSTANT_INITIALIZER})
|
||||
private static final native void init();
|
||||
|
||||
@JniField(flags={CONSTANT}, accessor="sizeof(struct leveldb::Slice)")
|
||||
@JniField(flags={CONSTANT}, accessor="sizeof(struct rocksdb::Slice)")
|
||||
static int SIZEOF;
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user