Format all files IAW the Google C++ Style Guide.
Use clang-format to correct formatting to be in agreement with the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html). Doing this simplifies the process of accepting changes. Also fixed a few warnings flagged by clang-tidy. PiperOrigin-RevId: 246350737
This commit is contained in:
parent
3724030179
commit
297e66afc1
18
.clang-format
Normal file
18
.clang-format
Normal file
@ -0,0 +1,18 @@
|
||||
# Run manually to reformat a file:
|
||||
# clang-format -i --style=file <file>
|
||||
# find . -iname '*.cc' -o -iname '*.h' -o -iname '*.h.in' | xargs clang-format -i --style=file
|
||||
BasedOnStyle: Google
|
||||
DerivePointerAlignment: false
|
||||
|
||||
# Public headers are in a different location in the internal Google repository.
|
||||
# Order them so that when imported to the authoritative repository they will be
|
||||
# in correct alphabetical order.
|
||||
IncludeCategories:
|
||||
- Regex: '^(<|"(db|helpers)/)'
|
||||
Priority: 1
|
||||
- Regex: '^"(leveldb)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(issues|port|table|third_party|util)/)'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
Priority: 4
|
@ -86,6 +86,14 @@ Contribution requirements:
|
||||
3. **Tests**: All changes must be accompanied by a new (or changed) test, or
|
||||
a sufficient explanation as to why a new (or changed) test is not required.
|
||||
|
||||
4. **Consistent Style**: This project conforms to the
|
||||
[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html).
|
||||
To ensure your changes are properly formatted please run:
|
||||
|
||||
```
|
||||
clang-format -i --style=file <file>
|
||||
```
|
||||
|
||||
## Submitting a Pull Request
|
||||
|
||||
Before any pull request will be accepted the author must first sign a
|
||||
|
@ -2,9 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include "leveldb/db.h"
|
||||
#include "db/db_impl.h"
|
||||
#include "leveldb/cache.h"
|
||||
#include "leveldb/db.h"
|
||||
#include "util/testharness.h"
|
||||
#include "util/testutil.h"
|
||||
|
||||
@ -81,16 +81,15 @@ void AutoCompactTest::DoReads(int n) {
|
||||
ASSERT_LT(read, 100) << "Taking too long to compact";
|
||||
Iterator* iter = db_->NewIterator(ReadOptions());
|
||||
for (iter->SeekToFirst();
|
||||
iter->Valid() && iter->key().ToString() < limit_key;
|
||||
iter->Next()) {
|
||||
iter->Valid() && iter->key().ToString() < limit_key; iter->Next()) {
|
||||
// Drop data
|
||||
}
|
||||
delete iter;
|
||||
// Wait a little bit to allow any triggered compactions to complete.
|
||||
Env::Default()->SleepForMicroseconds(1000000);
|
||||
uint64_t size = Size(Key(0), Key(n));
|
||||
fprintf(stderr, "iter %3d => %7.3f MB [other %7.3f MB]\n",
|
||||
read+1, size/1048576.0, Size(Key(n), Key(kCount))/1048576.0);
|
||||
fprintf(stderr, "iter %3d => %7.3f MB [other %7.3f MB]\n", read + 1,
|
||||
size / 1048576.0, Size(Key(n), Key(kCount)) / 1048576.0);
|
||||
if (size <= initial_size / 10) {
|
||||
break;
|
||||
}
|
||||
@ -103,16 +102,10 @@ void AutoCompactTest::DoReads(int n) {
|
||||
ASSERT_GE(final_other_size, initial_other_size / 5 - 1048576);
|
||||
}
|
||||
|
||||
TEST(AutoCompactTest, ReadAll) {
|
||||
DoReads(kCount);
|
||||
}
|
||||
TEST(AutoCompactTest, ReadAll) { DoReads(kCount); }
|
||||
|
||||
TEST(AutoCompactTest, ReadHalf) {
|
||||
DoReads(kCount/2);
|
||||
}
|
||||
TEST(AutoCompactTest, ReadHalf) { DoReads(kCount / 2); }
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
#include "db/builder.h"
|
||||
|
||||
#include "db/filename.h"
|
||||
#include "db/dbformat.h"
|
||||
#include "db/filename.h"
|
||||
#include "db/table_cache.h"
|
||||
#include "db/version_edit.h"
|
||||
#include "leveldb/db.h"
|
||||
@ -14,12 +14,8 @@
|
||||
|
||||
namespace leveldb {
|
||||
|
||||
Status BuildTable(const std::string& dbname,
|
||||
Env* env,
|
||||
const Options& options,
|
||||
TableCache* table_cache,
|
||||
Iterator* iter,
|
||||
FileMetaData* meta) {
|
||||
Status BuildTable(const std::string& dbname, Env* env, const Options& options,
|
||||
TableCache* table_cache, Iterator* iter, FileMetaData* meta) {
|
||||
Status s;
|
||||
meta->file_size = 0;
|
||||
iter->SeekToFirst();
|
||||
@ -60,8 +56,7 @@ Status BuildTable(const std::string& dbname,
|
||||
|
||||
if (s.ok()) {
|
||||
// Verify that the table is usable
|
||||
Iterator* it = table_cache->NewIterator(ReadOptions(),
|
||||
meta->number,
|
||||
Iterator* it = table_cache->NewIterator(ReadOptions(), meta->number,
|
||||
meta->file_size);
|
||||
s = it->status();
|
||||
delete it;
|
||||
|
@ -22,12 +22,8 @@ class VersionEdit;
|
||||
// *meta will be filled with metadata about the generated table.
|
||||
// If no data is present in *iter, meta->file_size will be set to
|
||||
// zero, and no Table file will be produced.
|
||||
Status BuildTable(const std::string& dbname,
|
||||
Env* env,
|
||||
const Options& options,
|
||||
TableCache* table_cache,
|
||||
Iterator* iter,
|
||||
FileMetaData* meta);
|
||||
Status BuildTable(const std::string& dbname, Env* env, const Options& options,
|
||||
TableCache* table_cache, Iterator* iter, FileMetaData* meta);
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
|
283
db/c.cc
283
db/c.cc
@ -5,6 +5,7 @@
|
||||
#include "leveldb/c.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "leveldb/cache.h"
|
||||
#include "leveldb/comparator.h"
|
||||
#include "leveldb/db.h"
|
||||
@ -42,40 +43,60 @@ using leveldb::WriteOptions;
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct leveldb_t { DB* rep; };
|
||||
struct leveldb_iterator_t { Iterator* rep; };
|
||||
struct leveldb_writebatch_t { WriteBatch rep; };
|
||||
struct leveldb_snapshot_t { const Snapshot* rep; };
|
||||
struct leveldb_readoptions_t { ReadOptions rep; };
|
||||
struct leveldb_writeoptions_t { WriteOptions rep; };
|
||||
struct leveldb_options_t { Options rep; };
|
||||
struct leveldb_cache_t { Cache* rep; };
|
||||
struct leveldb_seqfile_t { SequentialFile* rep; };
|
||||
struct leveldb_randomfile_t { RandomAccessFile* rep; };
|
||||
struct leveldb_writablefile_t { WritableFile* rep; };
|
||||
struct leveldb_logger_t { Logger* rep; };
|
||||
struct leveldb_filelock_t { FileLock* rep; };
|
||||
struct leveldb_t {
|
||||
DB* rep;
|
||||
};
|
||||
struct leveldb_iterator_t {
|
||||
Iterator* rep;
|
||||
};
|
||||
struct leveldb_writebatch_t {
|
||||
WriteBatch rep;
|
||||
};
|
||||
struct leveldb_snapshot_t {
|
||||
const Snapshot* rep;
|
||||
};
|
||||
struct leveldb_readoptions_t {
|
||||
ReadOptions rep;
|
||||
};
|
||||
struct leveldb_writeoptions_t {
|
||||
WriteOptions rep;
|
||||
};
|
||||
struct leveldb_options_t {
|
||||
Options rep;
|
||||
};
|
||||
struct leveldb_cache_t {
|
||||
Cache* rep;
|
||||
};
|
||||
struct leveldb_seqfile_t {
|
||||
SequentialFile* rep;
|
||||
};
|
||||
struct leveldb_randomfile_t {
|
||||
RandomAccessFile* rep;
|
||||
};
|
||||
struct leveldb_writablefile_t {
|
||||
WritableFile* rep;
|
||||
};
|
||||
struct leveldb_logger_t {
|
||||
Logger* rep;
|
||||
};
|
||||
struct leveldb_filelock_t {
|
||||
FileLock* rep;
|
||||
};
|
||||
|
||||
struct leveldb_comparator_t : public Comparator {
|
||||
void* state_;
|
||||
void (*destructor_)(void*);
|
||||
int (*compare_)(
|
||||
void*,
|
||||
const char* a, size_t alen,
|
||||
const char* b, size_t blen);
|
||||
int (*compare_)(void*, const char* a, size_t alen, const char* b,
|
||||
size_t blen);
|
||||
const char* (*name_)(void*);
|
||||
|
||||
virtual ~leveldb_comparator_t() {
|
||||
(*destructor_)(state_);
|
||||
}
|
||||
virtual ~leveldb_comparator_t() { (*destructor_)(state_); }
|
||||
|
||||
virtual int Compare(const Slice& a, const Slice& b) const {
|
||||
return (*compare_)(state_, a.data(), a.size(), b.data(), b.size());
|
||||
}
|
||||
|
||||
virtual const char* Name() const {
|
||||
return (*name_)(state_);
|
||||
}
|
||||
virtual const char* Name() const { return (*name_)(state_); }
|
||||
|
||||
// No-ops since the C binding does not support key shortening methods.
|
||||
virtual void FindShortestSeparator(std::string*, const Slice&) const {}
|
||||
@ -86,23 +107,15 @@ struct leveldb_filterpolicy_t : public FilterPolicy {
|
||||
void* state_;
|
||||
void (*destructor_)(void*);
|
||||
const char* (*name_)(void*);
|
||||
char* (*create_)(
|
||||
void*,
|
||||
const char* const* key_array, const size_t* key_length_array,
|
||||
int num_keys,
|
||||
char* (*create_)(void*, const char* const* key_array,
|
||||
const size_t* key_length_array, int num_keys,
|
||||
size_t* filter_length);
|
||||
unsigned char (*key_match_)(
|
||||
void*,
|
||||
const char* key, size_t length,
|
||||
unsigned char (*key_match_)(void*, const char* key, size_t length,
|
||||
const char* filter, size_t filter_length);
|
||||
|
||||
virtual ~leveldb_filterpolicy_t() {
|
||||
(*destructor_)(state_);
|
||||
}
|
||||
virtual ~leveldb_filterpolicy_t() { (*destructor_)(state_); }
|
||||
|
||||
virtual const char* Name() const {
|
||||
return (*name_)(state_);
|
||||
}
|
||||
virtual const char* Name() const { return (*name_)(state_); }
|
||||
|
||||
virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
|
||||
std::vector<const char*> key_pointers(n);
|
||||
@ -118,8 +131,8 @@ struct leveldb_filterpolicy_t : public FilterPolicy {
|
||||
}
|
||||
|
||||
virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const {
|
||||
return (*key_match_)(state_, key.data(), key.size(),
|
||||
filter.data(), filter.size());
|
||||
return (*key_match_)(state_, key.data(), key.size(), filter.data(),
|
||||
filter.size());
|
||||
}
|
||||
};
|
||||
|
||||
@ -148,9 +161,7 @@ static char* CopyString(const std::string& str) {
|
||||
return result;
|
||||
}
|
||||
|
||||
leveldb_t* leveldb_open(
|
||||
const leveldb_options_t* options,
|
||||
const char* name,
|
||||
leveldb_t* leveldb_open(const leveldb_options_t* options, const char* name,
|
||||
char** errptr) {
|
||||
DB* db;
|
||||
if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) {
|
||||
@ -166,38 +177,25 @@ void leveldb_close(leveldb_t* db) {
|
||||
delete db;
|
||||
}
|
||||
|
||||
void leveldb_put(
|
||||
leveldb_t* db,
|
||||
const leveldb_writeoptions_t* options,
|
||||
const char* key, size_t keylen,
|
||||
const char* val, size_t vallen,
|
||||
void leveldb_put(leveldb_t* db, const leveldb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr,
|
||||
db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void leveldb_delete(
|
||||
leveldb_t* db,
|
||||
const leveldb_writeoptions_t* options,
|
||||
const char* key, size_t keylen,
|
||||
char** errptr) {
|
||||
void leveldb_delete(leveldb_t* db, const leveldb_writeoptions_t* options,
|
||||
const char* key, size_t keylen, char** errptr) {
|
||||
SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen)));
|
||||
}
|
||||
|
||||
|
||||
void leveldb_write(
|
||||
leveldb_t* db,
|
||||
const leveldb_writeoptions_t* options,
|
||||
leveldb_writebatch_t* batch,
|
||||
char** errptr) {
|
||||
void leveldb_write(leveldb_t* db, const leveldb_writeoptions_t* options,
|
||||
leveldb_writebatch_t* batch, char** errptr) {
|
||||
SaveError(errptr, db->rep->Write(options->rep, &batch->rep));
|
||||
}
|
||||
|
||||
char* leveldb_get(
|
||||
leveldb_t* db,
|
||||
const leveldb_readoptions_t* options,
|
||||
const char* key, size_t keylen,
|
||||
size_t* vallen,
|
||||
char* leveldb_get(leveldb_t* db, const leveldb_readoptions_t* options,
|
||||
const char* key, size_t keylen, size_t* vallen,
|
||||
char** errptr) {
|
||||
char* result = nullptr;
|
||||
std::string tmp;
|
||||
@ -215,30 +213,25 @@ char* leveldb_get(
|
||||
}
|
||||
|
||||
leveldb_iterator_t* leveldb_create_iterator(
|
||||
leveldb_t* db,
|
||||
const leveldb_readoptions_t* options) {
|
||||
leveldb_t* db, const leveldb_readoptions_t* options) {
|
||||
leveldb_iterator_t* result = new leveldb_iterator_t;
|
||||
result->rep = db->rep->NewIterator(options->rep);
|
||||
return result;
|
||||
}
|
||||
|
||||
const leveldb_snapshot_t* leveldb_create_snapshot(
|
||||
leveldb_t* db) {
|
||||
const leveldb_snapshot_t* leveldb_create_snapshot(leveldb_t* db) {
|
||||
leveldb_snapshot_t* result = new leveldb_snapshot_t;
|
||||
result->rep = db->rep->GetSnapshot();
|
||||
return result;
|
||||
}
|
||||
|
||||
void leveldb_release_snapshot(
|
||||
leveldb_t* db,
|
||||
void leveldb_release_snapshot(leveldb_t* db,
|
||||
const leveldb_snapshot_t* snapshot) {
|
||||
db->rep->ReleaseSnapshot(snapshot->rep);
|
||||
delete snapshot;
|
||||
}
|
||||
|
||||
char* leveldb_property_value(
|
||||
leveldb_t* db,
|
||||
const char* propname) {
|
||||
char* leveldb_property_value(leveldb_t* db, const char* propname) {
|
||||
std::string tmp;
|
||||
if (db->rep->GetProperty(Slice(propname), &tmp)) {
|
||||
// We use strdup() since we expect human readable output.
|
||||
@ -248,11 +241,11 @@ char* leveldb_property_value(
|
||||
}
|
||||
}
|
||||
|
||||
void leveldb_approximate_sizes(
|
||||
leveldb_t* db,
|
||||
int num_ranges,
|
||||
const char* const* range_start_key, const size_t* range_start_key_len,
|
||||
const char* const* range_limit_key, const size_t* range_limit_key_len,
|
||||
void leveldb_approximate_sizes(leveldb_t* db, int num_ranges,
|
||||
const char* const* range_start_key,
|
||||
const size_t* range_start_key_len,
|
||||
const char* const* range_limit_key,
|
||||
const size_t* range_limit_key_len,
|
||||
uint64_t* sizes) {
|
||||
Range* ranges = new Range[num_ranges];
|
||||
for (int i = 0; i < num_ranges; i++) {
|
||||
@ -263,10 +256,9 @@ void leveldb_approximate_sizes(
|
||||
delete[] ranges;
|
||||
}
|
||||
|
||||
void leveldb_compact_range(
|
||||
leveldb_t* db,
|
||||
const char* start_key, size_t start_key_len,
|
||||
const char* limit_key, size_t limit_key_len) {
|
||||
void leveldb_compact_range(leveldb_t* db, const char* start_key,
|
||||
size_t start_key_len, const char* limit_key,
|
||||
size_t limit_key_len) {
|
||||
Slice a, b;
|
||||
db->rep->CompactRange(
|
||||
// Pass null Slice if corresponding "const char*" is null
|
||||
@ -274,16 +266,12 @@ void leveldb_compact_range(
|
||||
(limit_key ? (b = Slice(limit_key, limit_key_len), &b) : nullptr));
|
||||
}
|
||||
|
||||
void leveldb_destroy_db(
|
||||
const leveldb_options_t* options,
|
||||
const char* name,
|
||||
void leveldb_destroy_db(const leveldb_options_t* options, const char* name,
|
||||
char** errptr) {
|
||||
SaveError(errptr, DestroyDB(name, options->rep));
|
||||
}
|
||||
|
||||
void leveldb_repair_db(
|
||||
const leveldb_options_t* options,
|
||||
const char* name,
|
||||
void leveldb_repair_db(const leveldb_options_t* options, const char* name,
|
||||
char** errptr) {
|
||||
SaveError(errptr, RepairDB(name, options->rep));
|
||||
}
|
||||
@ -309,13 +297,9 @@ void leveldb_iter_seek(leveldb_iterator_t* iter, const char* k, size_t klen) {
|
||||
iter->rep->Seek(Slice(k, klen));
|
||||
}
|
||||
|
||||
void leveldb_iter_next(leveldb_iterator_t* iter) {
|
||||
iter->rep->Next();
|
||||
}
|
||||
void leveldb_iter_next(leveldb_iterator_t* iter) { iter->rep->Next(); }
|
||||
|
||||
void leveldb_iter_prev(leveldb_iterator_t* iter) {
|
||||
iter->rep->Prev();
|
||||
}
|
||||
void leveldb_iter_prev(leveldb_iterator_t* iter) { iter->rep->Prev(); }
|
||||
|
||||
const char* leveldb_iter_key(const leveldb_iterator_t* iter, size_t* klen) {
|
||||
Slice s = iter->rep->key();
|
||||
@ -337,32 +321,25 @@ leveldb_writebatch_t* leveldb_writebatch_create() {
|
||||
return new leveldb_writebatch_t;
|
||||
}
|
||||
|
||||
void leveldb_writebatch_destroy(leveldb_writebatch_t* b) {
|
||||
delete b;
|
||||
}
|
||||
void leveldb_writebatch_destroy(leveldb_writebatch_t* b) { delete b; }
|
||||
|
||||
void leveldb_writebatch_clear(leveldb_writebatch_t* b) {
|
||||
b->rep.Clear();
|
||||
}
|
||||
void leveldb_writebatch_clear(leveldb_writebatch_t* b) { b->rep.Clear(); }
|
||||
|
||||
void leveldb_writebatch_put(
|
||||
leveldb_writebatch_t* b,
|
||||
const char* key, size_t klen,
|
||||
const char* val, size_t vlen) {
|
||||
void leveldb_writebatch_put(leveldb_writebatch_t* b, const char* key,
|
||||
size_t klen, const char* val, size_t vlen) {
|
||||
b->rep.Put(Slice(key, klen), Slice(val, vlen));
|
||||
}
|
||||
|
||||
void leveldb_writebatch_delete(
|
||||
leveldb_writebatch_t* b,
|
||||
const char* key, size_t klen) {
|
||||
void leveldb_writebatch_delete(leveldb_writebatch_t* b, const char* key,
|
||||
size_t klen) {
|
||||
b->rep.Delete(Slice(key, klen));
|
||||
}
|
||||
|
||||
void leveldb_writebatch_iterate(
|
||||
const leveldb_writebatch_t* b,
|
||||
void* state,
|
||||
void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen),
|
||||
void (*deleted)(void*, const char* k, size_t klen)) {
|
||||
void leveldb_writebatch_iterate(const leveldb_writebatch_t* b, void* state,
|
||||
void (*put)(void*, const char* k, size_t klen,
|
||||
const char* v, size_t vlen),
|
||||
void (*deleted)(void*, const char* k,
|
||||
size_t klen)) {
|
||||
class H : public WriteBatch::Handler {
|
||||
public:
|
||||
void* state_;
|
||||
@ -387,38 +364,32 @@ void leveldb_writebatch_append(leveldb_writebatch_t *destination,
|
||||
destination->rep.Append(source->rep);
|
||||
}
|
||||
|
||||
leveldb_options_t* leveldb_options_create() {
|
||||
return new leveldb_options_t;
|
||||
}
|
||||
leveldb_options_t* leveldb_options_create() { return new leveldb_options_t; }
|
||||
|
||||
void leveldb_options_destroy(leveldb_options_t* options) {
|
||||
delete options;
|
||||
}
|
||||
void leveldb_options_destroy(leveldb_options_t* options) { delete options; }
|
||||
|
||||
void leveldb_options_set_comparator(
|
||||
leveldb_options_t* opt,
|
||||
void leveldb_options_set_comparator(leveldb_options_t* opt,
|
||||
leveldb_comparator_t* cmp) {
|
||||
opt->rep.comparator = cmp;
|
||||
}
|
||||
|
||||
void leveldb_options_set_filter_policy(
|
||||
leveldb_options_t* opt,
|
||||
void leveldb_options_set_filter_policy(leveldb_options_t* opt,
|
||||
leveldb_filterpolicy_t* policy) {
|
||||
opt->rep.filter_policy = policy;
|
||||
}
|
||||
|
||||
void leveldb_options_set_create_if_missing(
|
||||
leveldb_options_t* opt, unsigned char v) {
|
||||
void leveldb_options_set_create_if_missing(leveldb_options_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.create_if_missing = v;
|
||||
}
|
||||
|
||||
void leveldb_options_set_error_if_exists(
|
||||
leveldb_options_t* opt, unsigned char v) {
|
||||
void leveldb_options_set_error_if_exists(leveldb_options_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.error_if_exists = v;
|
||||
}
|
||||
|
||||
void leveldb_options_set_paranoid_checks(
|
||||
leveldb_options_t* opt, unsigned char v) {
|
||||
void leveldb_options_set_paranoid_checks(leveldb_options_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.paranoid_checks = v;
|
||||
}
|
||||
|
||||
@ -459,12 +430,9 @@ void leveldb_options_set_compression(leveldb_options_t* opt, int t) {
|
||||
}
|
||||
|
||||
leveldb_comparator_t* leveldb_comparator_create(
|
||||
void* state,
|
||||
void (*destructor)(void*),
|
||||
int (*compare)(
|
||||
void*,
|
||||
const char* a, size_t alen,
|
||||
const char* b, size_t blen),
|
||||
void* state, void (*destructor)(void*),
|
||||
int (*compare)(void*, const char* a, size_t alen, const char* b,
|
||||
size_t blen),
|
||||
const char* (*name)(void*)) {
|
||||
leveldb_comparator_t* result = new leveldb_comparator_t;
|
||||
result->state_ = state;
|
||||
@ -474,21 +442,14 @@ leveldb_comparator_t* leveldb_comparator_create(
|
||||
return result;
|
||||
}
|
||||
|
||||
void leveldb_comparator_destroy(leveldb_comparator_t* cmp) {
|
||||
delete cmp;
|
||||
}
|
||||
void leveldb_comparator_destroy(leveldb_comparator_t* cmp) { delete cmp; }
|
||||
|
||||
leveldb_filterpolicy_t* leveldb_filterpolicy_create(
|
||||
void* state,
|
||||
void (*destructor)(void*),
|
||||
char* (*create_filter)(
|
||||
void*,
|
||||
const char* const* key_array, const size_t* key_length_array,
|
||||
int num_keys,
|
||||
void* state, void (*destructor)(void*),
|
||||
char* (*create_filter)(void*, const char* const* key_array,
|
||||
const size_t* key_length_array, int num_keys,
|
||||
size_t* filter_length),
|
||||
unsigned char (*key_may_match)(
|
||||
void*,
|
||||
const char* key, size_t length,
|
||||
unsigned char (*key_may_match)(void*, const char* key, size_t length,
|
||||
const char* filter, size_t filter_length),
|
||||
const char* (*name)(void*)) {
|
||||
leveldb_filterpolicy_t* result = new leveldb_filterpolicy_t;
|
||||
@ -531,23 +492,19 @@ leveldb_readoptions_t* leveldb_readoptions_create() {
|
||||
return new leveldb_readoptions_t;
|
||||
}
|
||||
|
||||
void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) {
|
||||
delete opt;
|
||||
}
|
||||
void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) { delete opt; }
|
||||
|
||||
void leveldb_readoptions_set_verify_checksums(
|
||||
leveldb_readoptions_t* opt,
|
||||
void leveldb_readoptions_set_verify_checksums(leveldb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.verify_checksums = v;
|
||||
}
|
||||
|
||||
void leveldb_readoptions_set_fill_cache(
|
||||
leveldb_readoptions_t* opt, unsigned char v) {
|
||||
void leveldb_readoptions_set_fill_cache(leveldb_readoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.fill_cache = v;
|
||||
}
|
||||
|
||||
void leveldb_readoptions_set_snapshot(
|
||||
leveldb_readoptions_t* opt,
|
||||
void leveldb_readoptions_set_snapshot(leveldb_readoptions_t* opt,
|
||||
const leveldb_snapshot_t* snap) {
|
||||
opt->rep.snapshot = (snap ? snap->rep : nullptr);
|
||||
}
|
||||
@ -556,12 +513,10 @@ leveldb_writeoptions_t* leveldb_writeoptions_create() {
|
||||
return new leveldb_writeoptions_t;
|
||||
}
|
||||
|
||||
void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) {
|
||||
delete opt;
|
||||
}
|
||||
void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) { delete opt; }
|
||||
|
||||
void leveldb_writeoptions_set_sync(
|
||||
leveldb_writeoptions_t* opt, unsigned char v) {
|
||||
void leveldb_writeoptions_set_sync(leveldb_writeoptions_t* opt,
|
||||
unsigned char v) {
|
||||
opt->rep.sync = v;
|
||||
}
|
||||
|
||||
@ -600,16 +555,10 @@ char* leveldb_env_get_test_directory(leveldb_env_t* env) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void leveldb_free(void* ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
void leveldb_free(void* ptr) { free(ptr); }
|
||||
|
||||
int leveldb_major_version() {
|
||||
return kMajorVersion;
|
||||
}
|
||||
int leveldb_major_version() { return kMajorVersion; }
|
||||
|
||||
int leveldb_minor_version() {
|
||||
return kMinorVersion;
|
||||
}
|
||||
int leveldb_minor_version() { return kMinorVersion; }
|
||||
|
||||
} // end extern "C"
|
||||
|
@ -2,16 +2,16 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include "leveldb/db.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "leveldb/cache.h"
|
||||
#include "leveldb/table.h"
|
||||
#include "leveldb/write_batch.h"
|
||||
|
||||
#include "db/db_impl.h"
|
||||
#include "db/filename.h"
|
||||
#include "db/log_format.h"
|
||||
#include "db/version_set.h"
|
||||
#include "leveldb/cache.h"
|
||||
#include "leveldb/db.h"
|
||||
#include "leveldb/table.h"
|
||||
#include "leveldb/write_batch.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/testharness.h"
|
||||
#include "util/testutil.h"
|
||||
@ -52,9 +52,7 @@ class CorruptionTest {
|
||||
return DB::Open(options_, dbname_, &db_);
|
||||
}
|
||||
|
||||
void Reopen() {
|
||||
ASSERT_OK(TryReopen());
|
||||
}
|
||||
void Reopen() { ASSERT_OK(TryReopen()); }
|
||||
|
||||
void RepairDB() {
|
||||
delete db_;
|
||||
@ -95,8 +93,7 @@ class CorruptionTest {
|
||||
// Ignore boundary keys.
|
||||
continue;
|
||||
}
|
||||
if (!ConsumeDecimalNumber(&in, &key) ||
|
||||
!in.empty() ||
|
||||
if (!ConsumeDecimalNumber(&in, &key) || !in.empty() ||
|
||||
key < next_expected) {
|
||||
bad_keys++;
|
||||
continue;
|
||||
@ -127,8 +124,7 @@ class CorruptionTest {
|
||||
std::string fname;
|
||||
int picked_number = -1;
|
||||
for (size_t i = 0; i < filenames.size(); i++) {
|
||||
if (ParseFileName(filenames[i], &number, &type) &&
|
||||
type == filetype &&
|
||||
if (ParseFileName(filenames[i], &number, &type) && type == filetype &&
|
||||
int(number) > picked_number) { // Pick latest file
|
||||
fname = dbname_ + "/" + filenames[i];
|
||||
picked_number = number;
|
||||
@ -361,6 +357,4 @@ TEST(CorruptionTest, UnrelatedKeys) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -2,9 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "leveldb/cache.h"
|
||||
#include "leveldb/db.h"
|
||||
#include "leveldb/env.h"
|
||||
@ -55,8 +56,7 @@ static const char* FLAGS_benchmarks =
|
||||
"fill100K,"
|
||||
"crc32c,"
|
||||
"snappycomp,"
|
||||
"snappyuncomp,"
|
||||
;
|
||||
"snappyuncomp,";
|
||||
|
||||
// Number of key/values to place in database
|
||||
static int FLAGS_num = 1000000;
|
||||
@ -214,9 +214,7 @@ class Stats {
|
||||
seconds_ = (finish_ - start_) * 1e-6;
|
||||
}
|
||||
|
||||
void AddMessage(Slice msg) {
|
||||
AppendWithSpace(&message_, msg);
|
||||
}
|
||||
void AddMessage(Slice msg) { AppendWithSpace(&message_, msg); }
|
||||
|
||||
void FinishedSingleOp() {
|
||||
if (FLAGS_histogram) {
|
||||
@ -232,21 +230,26 @@ class Stats {
|
||||
|
||||
done_++;
|
||||
if (done_ >= next_report_) {
|
||||
if (next_report_ < 1000) next_report_ += 100;
|
||||
else if (next_report_ < 5000) next_report_ += 500;
|
||||
else if (next_report_ < 10000) next_report_ += 1000;
|
||||
else if (next_report_ < 50000) next_report_ += 5000;
|
||||
else if (next_report_ < 100000) next_report_ += 10000;
|
||||
else if (next_report_ < 500000) next_report_ += 50000;
|
||||
else next_report_ += 100000;
|
||||
if (next_report_ < 1000)
|
||||
next_report_ += 100;
|
||||
else if (next_report_ < 5000)
|
||||
next_report_ += 500;
|
||||
else if (next_report_ < 10000)
|
||||
next_report_ += 1000;
|
||||
else if (next_report_ < 50000)
|
||||
next_report_ += 5000;
|
||||
else if (next_report_ < 100000)
|
||||
next_report_ += 10000;
|
||||
else if (next_report_ < 500000)
|
||||
next_report_ += 50000;
|
||||
else
|
||||
next_report_ += 100000;
|
||||
fprintf(stderr, "... finished %d ops%30s\r", done_, "");
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void AddBytes(int64_t n) {
|
||||
bytes_ += n;
|
||||
}
|
||||
void AddBytes(int64_t n) { bytes_ += n; }
|
||||
|
||||
void Report(const Slice& name) {
|
||||
// Pretend at least one op was done in case we are running a benchmark
|
||||
@ -265,11 +268,8 @@ class Stats {
|
||||
}
|
||||
AppendWithSpace(&extra, message_);
|
||||
|
||||
fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n",
|
||||
name.ToString().c_str(),
|
||||
seconds_ * 1e6 / done_,
|
||||
(extra.empty() ? "" : " "),
|
||||
extra.c_str());
|
||||
fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", name.ToString().c_str(),
|
||||
seconds_ * 1e6 / done_, (extra.empty() ? "" : " "), extra.c_str());
|
||||
if (FLAGS_histogram) {
|
||||
fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str());
|
||||
}
|
||||
@ -330,20 +330,20 @@ class Benchmark {
|
||||
static_cast<int>(FLAGS_value_size * FLAGS_compression_ratio + 0.5));
|
||||
fprintf(stdout, "Entries: %d\n", num_);
|
||||
fprintf(stdout, "RawSize: %.1f MB (estimated)\n",
|
||||
((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_)
|
||||
/ 1048576.0));
|
||||
((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_) /
|
||||
1048576.0));
|
||||
fprintf(stdout, "FileSize: %.1f MB (estimated)\n",
|
||||
(((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_)
|
||||
/ 1048576.0));
|
||||
(((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_) /
|
||||
1048576.0));
|
||||
PrintWarnings();
|
||||
fprintf(stdout, "------------------------------------------------\n");
|
||||
}
|
||||
|
||||
void PrintWarnings() {
|
||||
#if defined(__GNUC__) && !defined(__OPTIMIZE__)
|
||||
fprintf(stdout,
|
||||
"WARNING: Optimization is disabled: benchmarks unnecessarily slow\n"
|
||||
);
|
||||
fprintf(
|
||||
stdout,
|
||||
"WARNING: Optimization is disabled: benchmarks unnecessarily slow\n");
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
fprintf(stdout,
|
||||
@ -361,8 +361,8 @@ class Benchmark {
|
||||
}
|
||||
|
||||
void PrintEnvironment() {
|
||||
fprintf(stderr, "LevelDB: version %d.%d\n",
|
||||
kMajorVersion, kMinorVersion);
|
||||
fprintf(stderr, "LevelDB: version %d.%d\n", kMajorVersion,
|
||||
kMinorVersion);
|
||||
|
||||
#if defined(__linux)
|
||||
time_t now = time(nullptr);
|
||||
@ -516,7 +516,7 @@ class Benchmark {
|
||||
} else if (name == Slice("sstables")) {
|
||||
PrintStats("leveldb.sstables");
|
||||
} else {
|
||||
if (name != Slice()) { // No error message for empty name
|
||||
if (!name.empty()) { // No error message for empty name
|
||||
fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str());
|
||||
}
|
||||
}
|
||||
@ -706,13 +706,9 @@ class Benchmark {
|
||||
}
|
||||
}
|
||||
|
||||
void WriteSeq(ThreadState* thread) {
|
||||
DoWrite(thread, true);
|
||||
}
|
||||
void WriteSeq(ThreadState* thread) { DoWrite(thread, true); }
|
||||
|
||||
void WriteRandom(ThreadState* thread) {
|
||||
DoWrite(thread, false);
|
||||
}
|
||||
void WriteRandom(ThreadState* thread) { DoWrite(thread, false); }
|
||||
|
||||
void DoWrite(ThreadState* thread, bool seq) {
|
||||
if (num_ != FLAGS_num) {
|
||||
@ -852,13 +848,9 @@ class Benchmark {
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteSeq(ThreadState* thread) {
|
||||
DoDelete(thread, true);
|
||||
}
|
||||
void DeleteSeq(ThreadState* thread) { DoDelete(thread, true); }
|
||||
|
||||
void DeleteRandom(ThreadState* thread) {
|
||||
DoDelete(thread, false);
|
||||
}
|
||||
void DeleteRandom(ThreadState* thread) { DoDelete(thread, false); }
|
||||
|
||||
void ReadWhileWriting(ThreadState* thread) {
|
||||
if (thread->tid > 0) {
|
||||
@ -890,9 +882,7 @@ class Benchmark {
|
||||
}
|
||||
}
|
||||
|
||||
void Compact(ThreadState* thread) {
|
||||
db_->CompactRange(nullptr, nullptr);
|
||||
}
|
||||
void Compact(ThreadState* thread) { db_->CompactRange(nullptr, nullptr); }
|
||||
|
||||
void PrintStats(const char* key) {
|
||||
std::string stats;
|
||||
|
127
db/db_impl.cc
127
db/db_impl.cc
@ -268,8 +268,7 @@ void DBImpl::DeleteObsoleteFiles() {
|
||||
if (type == kTableFile) {
|
||||
table_cache_->Evict(number);
|
||||
}
|
||||
Log(options_.info_log, "Delete type=%d #%lld\n",
|
||||
static_cast<int>(type),
|
||||
Log(options_.info_log, "Delete type=%d #%lld\n", static_cast<int>(type),
|
||||
static_cast<unsigned long long>(number));
|
||||
env_->DeleteFile(dbname_ + "/" + filenames[i]);
|
||||
}
|
||||
@ -302,8 +301,8 @@ Status DBImpl::Recover(VersionEdit* edit, bool *save_manifest) {
|
||||
}
|
||||
} else {
|
||||
if (options_.error_if_exists) {
|
||||
return Status::InvalidArgument(
|
||||
dbname_, "exists (error_if_exists is true)");
|
||||
return Status::InvalidArgument(dbname_,
|
||||
"exists (error_if_exists is true)");
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,8 +377,8 @@ Status DBImpl::RecoverLogFile(uint64_t log_number, bool last_log,
|
||||
Status* status; // null if options_.paranoid_checks==false
|
||||
virtual void Corruption(size_t bytes, const Status& s) {
|
||||
Log(info_log, "%s%s: dropping %d bytes; %s",
|
||||
(this->status == nullptr ? "(ignoring error) " : ""),
|
||||
fname, static_cast<int>(bytes), s.ToString().c_str());
|
||||
(this->status == nullptr ? "(ignoring error) " : ""), fname,
|
||||
static_cast<int>(bytes), s.ToString().c_str());
|
||||
if (this->status != nullptr && this->status->ok()) *this->status = s;
|
||||
}
|
||||
};
|
||||
@ -405,8 +404,7 @@ Status DBImpl::RecoverLogFile(uint64_t log_number, bool last_log,
|
||||
// paranoid_checks==false so that corruptions cause entire commits
|
||||
// to be skipped instead of propagating bad information (like overly
|
||||
// large sequence numbers).
|
||||
log::Reader reader(file, &reporter, true/*checksum*/,
|
||||
0/*initial_offset*/);
|
||||
log::Reader reader(file, &reporter, true /*checksum*/, 0 /*initial_offset*/);
|
||||
Log(options_.info_log, "Recovering log #%llu",
|
||||
(unsigned long long)log_number);
|
||||
|
||||
@ -416,11 +414,10 @@ Status DBImpl::RecoverLogFile(uint64_t log_number, bool last_log,
|
||||
WriteBatch batch;
|
||||
int compactions = 0;
|
||||
MemTable* mem = nullptr;
|
||||
while (reader.ReadRecord(&record, &scratch) &&
|
||||
status.ok()) {
|
||||
while (reader.ReadRecord(&record, &scratch) && status.ok()) {
|
||||
if (record.size() < 12) {
|
||||
reporter.Corruption(
|
||||
record.size(), Status::Corruption("log record too small"));
|
||||
reporter.Corruption(record.size(),
|
||||
Status::Corruption("log record too small"));
|
||||
continue;
|
||||
}
|
||||
WriteBatchInternal::SetContents(&batch, record);
|
||||
@ -434,8 +431,7 @@ Status DBImpl::RecoverLogFile(uint64_t log_number, bool last_log,
|
||||
if (!status.ok()) {
|
||||
break;
|
||||
}
|
||||
const SequenceNumber last_seq =
|
||||
WriteBatchInternal::Sequence(&batch) +
|
||||
const SequenceNumber last_seq = WriteBatchInternal::Sequence(&batch) +
|
||||
WriteBatchInternal::Count(&batch) - 1;
|
||||
if (last_seq > *max_sequence) {
|
||||
*max_sequence = last_seq;
|
||||
@ -510,13 +506,11 @@ Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit,
|
||||
}
|
||||
|
||||
Log(options_.info_log, "Level-0 table #%llu: %lld bytes %s",
|
||||
(unsigned long long) meta.number,
|
||||
(unsigned long long) meta.file_size,
|
||||
(unsigned long long)meta.number, (unsigned long long)meta.file_size,
|
||||
s.ToString().c_str());
|
||||
delete iter;
|
||||
pending_outputs_.erase(meta.number);
|
||||
|
||||
|
||||
// Note that if file_size is zero, the file has been deleted and
|
||||
// should not be added to the manifest.
|
||||
int level = 0;
|
||||
@ -526,8 +520,8 @@ Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit,
|
||||
if (base != nullptr) {
|
||||
level = base->PickLevelForMemTableOutput(min_user_key, max_user_key);
|
||||
}
|
||||
edit->AddFile(level, meta.number, meta.file_size,
|
||||
meta.smallest, meta.largest);
|
||||
edit->AddFile(level, meta.number, meta.file_size, meta.smallest,
|
||||
meta.largest);
|
||||
}
|
||||
|
||||
CompactionStats stats;
|
||||
@ -658,8 +652,7 @@ void DBImpl::MaybeScheduleCompaction() {
|
||||
// DB is being deleted; no more background compactions
|
||||
} else if (!bg_error_.ok()) {
|
||||
// Already got an error; no more changes
|
||||
} else if (imm_ == nullptr &&
|
||||
manual_compaction_ == nullptr &&
|
||||
} else if (imm_ == nullptr && manual_compaction_ == nullptr &&
|
||||
!versions_->NeedsCompaction()) {
|
||||
// No work to be done
|
||||
} else {
|
||||
@ -711,8 +704,7 @@ void DBImpl::BackgroundCompaction() {
|
||||
}
|
||||
Log(options_.info_log,
|
||||
"Manual compaction at level-%d from %s .. %s; will stop at %s\n",
|
||||
m->level,
|
||||
(m->begin ? m->begin->DebugString().c_str() : "(begin)"),
|
||||
m->level, (m->begin ? m->begin->DebugString().c_str() : "(begin)"),
|
||||
(m->end ? m->end->DebugString().c_str() : "(end)"),
|
||||
(m->done ? "(end)" : manual_end.DebugString().c_str()));
|
||||
} else {
|
||||
@ -727,19 +719,17 @@ void DBImpl::BackgroundCompaction() {
|
||||
assert(c->num_input_files(0) == 1);
|
||||
FileMetaData* f = c->input(0, 0);
|
||||
c->edit()->DeleteFile(c->level(), f->number);
|
||||
c->edit()->AddFile(c->level() + 1, f->number, f->file_size,
|
||||
f->smallest, f->largest);
|
||||
c->edit()->AddFile(c->level() + 1, f->number, f->file_size, f->smallest,
|
||||
f->largest);
|
||||
status = versions_->LogAndApply(c->edit(), &mutex_);
|
||||
if (!status.ok()) {
|
||||
RecordBackgroundError(status);
|
||||
}
|
||||
VersionSet::LevelSummaryStorage tmp;
|
||||
Log(options_.info_log, "Moved #%lld to level-%d %lld bytes %s: %s\n",
|
||||
static_cast<unsigned long long>(f->number),
|
||||
c->level() + 1,
|
||||
static_cast<unsigned long long>(f->number), c->level() + 1,
|
||||
static_cast<unsigned long long>(f->file_size),
|
||||
status.ToString().c_str(),
|
||||
versions_->LevelSummary(&tmp));
|
||||
status.ToString().c_str(), versions_->LevelSummary(&tmp));
|
||||
} else {
|
||||
CompactionState* compact = new CompactionState(c);
|
||||
status = DoCompactionWork(compact);
|
||||
@ -757,8 +747,7 @@ void DBImpl::BackgroundCompaction() {
|
||||
} else if (shutting_down_.load(std::memory_order_acquire)) {
|
||||
// Ignore compaction errors found during shutting down
|
||||
} else {
|
||||
Log(options_.info_log,
|
||||
"Compaction error: %s", status.ToString().c_str());
|
||||
Log(options_.info_log, "Compaction error: %s", status.ToString().c_str());
|
||||
}
|
||||
|
||||
if (is_manual) {
|
||||
@ -853,16 +842,13 @@ Status DBImpl::FinishCompactionOutputFile(CompactionState* compact,
|
||||
|
||||
if (s.ok() && current_entries > 0) {
|
||||
// Verify that the table is usable
|
||||
Iterator* iter = table_cache_->NewIterator(ReadOptions(),
|
||||
output_number,
|
||||
current_bytes);
|
||||
Iterator* iter =
|
||||
table_cache_->NewIterator(ReadOptions(), output_number, current_bytes);
|
||||
s = iter->status();
|
||||
delete iter;
|
||||
if (s.ok()) {
|
||||
Log(options_.info_log,
|
||||
"Generated table #%llu@%d: %lld keys, %lld bytes",
|
||||
(unsigned long long) output_number,
|
||||
compact->compaction->level(),
|
||||
Log(options_.info_log, "Generated table #%llu@%d: %lld keys, %lld bytes",
|
||||
(unsigned long long)output_number, compact->compaction->level(),
|
||||
(unsigned long long)current_entries,
|
||||
(unsigned long long)current_bytes);
|
||||
}
|
||||
@ -870,14 +856,11 @@ Status DBImpl::FinishCompactionOutputFile(CompactionState* compact,
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
Status DBImpl::InstallCompactionResults(CompactionState* compact) {
|
||||
mutex_.AssertHeld();
|
||||
Log(options_.info_log, "Compacted %d@%d + %d@%d files => %lld bytes",
|
||||
compact->compaction->num_input_files(0),
|
||||
compact->compaction->level(),
|
||||
compact->compaction->num_input_files(1),
|
||||
compact->compaction->level() + 1,
|
||||
compact->compaction->num_input_files(0), compact->compaction->level(),
|
||||
compact->compaction->num_input_files(1), compact->compaction->level() + 1,
|
||||
static_cast<long long>(compact->total_bytes));
|
||||
|
||||
// Add compaction outputs
|
||||
@ -885,9 +868,8 @@ Status DBImpl::InstallCompactionResults(CompactionState* compact) {
|
||||
const int level = compact->compaction->level();
|
||||
for (size_t i = 0; i < compact->outputs.size(); i++) {
|
||||
const CompactionState::Output& out = compact->outputs[i];
|
||||
compact->compaction->edit()->AddFile(
|
||||
level + 1,
|
||||
out.number, out.file_size, out.smallest, out.largest);
|
||||
compact->compaction->edit()->AddFile(level + 1, out.number, out.file_size,
|
||||
out.smallest, out.largest);
|
||||
}
|
||||
return versions_->LogAndApply(compact->compaction->edit(), &mutex_);
|
||||
}
|
||||
@ -897,8 +879,7 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
|
||||
int64_t imm_micros = 0; // Micros spent doing imm_ compactions
|
||||
|
||||
Log(options_.info_log, "Compacting %d@%d + %d@%d files",
|
||||
compact->compaction->num_input_files(0),
|
||||
compact->compaction->level(),
|
||||
compact->compaction->num_input_files(0), compact->compaction->level(),
|
||||
compact->compaction->num_input_files(1),
|
||||
compact->compaction->level() + 1);
|
||||
|
||||
@ -953,8 +934,8 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
|
||||
last_sequence_for_key = kMaxSequenceNumber;
|
||||
} else {
|
||||
if (!has_current_user_key ||
|
||||
user_comparator()->Compare(ikey.user_key,
|
||||
Slice(current_user_key)) != 0) {
|
||||
user_comparator()->Compare(ikey.user_key, Slice(current_user_key)) !=
|
||||
0) {
|
||||
// First occurrence of this user key
|
||||
current_user_key.assign(ikey.user_key.data(), ikey.user_key.size());
|
||||
has_current_user_key = true;
|
||||
@ -1049,8 +1030,7 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
|
||||
RecordBackgroundError(status);
|
||||
}
|
||||
VersionSet::LevelSummaryStorage tmp;
|
||||
Log(options_.info_log,
|
||||
"compacted to: %s", versions_->LevelSummary(&tmp));
|
||||
Log(options_.info_log, "compacted to: %s", versions_->LevelSummary(&tmp));
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1116,8 +1096,7 @@ int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes() {
|
||||
return versions_->MaxNextLevelOverlappingBytes();
|
||||
}
|
||||
|
||||
Status DBImpl::Get(const ReadOptions& options,
|
||||
const Slice& key,
|
||||
Status DBImpl::Get(const ReadOptions& options, const Slice& key,
|
||||
std::string* value) {
|
||||
Status s;
|
||||
MutexLock l(&mutex_);
|
||||
@ -1168,10 +1147,10 @@ Iterator* DBImpl::NewIterator(const ReadOptions& options) {
|
||||
SequenceNumber latest_snapshot;
|
||||
uint32_t seed;
|
||||
Iterator* iter = NewInternalIterator(options, &latest_snapshot, &seed);
|
||||
return NewDBIterator(
|
||||
this, user_comparator(), iter,
|
||||
return NewDBIterator(this, user_comparator(), iter,
|
||||
(options.snapshot != nullptr
|
||||
? static_cast<const SnapshotImpl*>(options.snapshot)->sequence_number()
|
||||
? static_cast<const SnapshotImpl*>(options.snapshot)
|
||||
->sequence_number()
|
||||
: latest_snapshot),
|
||||
seed);
|
||||
}
|
||||
@ -1202,9 +1181,9 @@ Status DBImpl::Delete(const WriteOptions& options, const Slice& key) {
|
||||
return DB::Delete(options, key);
|
||||
}
|
||||
|
||||
Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
|
||||
Status DBImpl::Write(const WriteOptions& options, WriteBatch* updates) {
|
||||
Writer w(&mutex_);
|
||||
w.batch = my_batch;
|
||||
w.batch = updates;
|
||||
w.sync = options.sync;
|
||||
w.done = false;
|
||||
|
||||
@ -1218,10 +1197,10 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
|
||||
}
|
||||
|
||||
// May temporarily unlock and wait.
|
||||
Status status = MakeRoomForWrite(my_batch == nullptr);
|
||||
Status status = MakeRoomForWrite(updates == nullptr);
|
||||
uint64_t last_sequence = versions_->LastSequence();
|
||||
Writer* last_writer = &w;
|
||||
if (status.ok() && my_batch != nullptr) { // nullptr batch is for compactions
|
||||
if (status.ok() && updates != nullptr) { // nullptr batch is for compactions
|
||||
WriteBatch* updates = BuildBatchGroup(&last_writer);
|
||||
WriteBatchInternal::SetSequence(updates, last_sequence + 1);
|
||||
last_sequence += WriteBatchInternal::Count(updates);
|
||||
@ -1337,9 +1316,8 @@ Status DBImpl::MakeRoomForWrite(bool force) {
|
||||
// Yield previous error
|
||||
s = bg_error_;
|
||||
break;
|
||||
} else if (
|
||||
allow_delay &&
|
||||
versions_->NumLevelFiles(0) >= config::kL0_SlowdownWritesTrigger) {
|
||||
} else if (allow_delay && versions_->NumLevelFiles(0) >=
|
||||
config::kL0_SlowdownWritesTrigger) {
|
||||
// We are getting close to hitting a hard limit on the number of
|
||||
// L0 files. Rather than delaying a single write by several
|
||||
// seconds when we hit the hard limit, start delaying each
|
||||
@ -1417,18 +1395,13 @@ bool DBImpl::GetProperty(const Slice& property, std::string* value) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
" Compactions\n"
|
||||
"Level Files Size(MB) Time(sec) Read(MB) Write(MB)\n"
|
||||
"--------------------------------------------------\n"
|
||||
);
|
||||
"--------------------------------------------------\n");
|
||||
value->append(buf);
|
||||
for (int level = 0; level < config::kNumLevels; level++) {
|
||||
int files = versions_->NumLevelFiles(level);
|
||||
if (stats_[level].micros > 0 || files > 0) {
|
||||
snprintf(
|
||||
buf, sizeof(buf),
|
||||
"%3d %8d %8.0f %9.0f %8.0f %9.0f\n",
|
||||
level,
|
||||
files,
|
||||
versions_->NumLevelBytes(level) / 1048576.0,
|
||||
snprintf(buf, sizeof(buf), "%3d %8d %8.0f %9.0f %8.0f %9.0f\n", level,
|
||||
files, versions_->NumLevelBytes(level) / 1048576.0,
|
||||
stats_[level].micros / 1e6,
|
||||
stats_[level].bytes_read / 1048576.0,
|
||||
stats_[level].bytes_written / 1048576.0);
|
||||
@ -1457,9 +1430,7 @@ bool DBImpl::GetProperty(const Slice& property, std::string* value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void DBImpl::GetApproximateSizes(
|
||||
const Range* range, int n,
|
||||
uint64_t* sizes) {
|
||||
void DBImpl::GetApproximateSizes(const Range* range, int n, uint64_t* sizes) {
|
||||
// TODO(opt): better implementation
|
||||
Version* v;
|
||||
{
|
||||
@ -1499,8 +1470,7 @@ Status DB::Delete(const WriteOptions& opt, const Slice& key) {
|
||||
|
||||
DB::~DB() {}
|
||||
|
||||
Status DB::Open(const Options& options, const std::string& dbname,
|
||||
DB** dbptr) {
|
||||
Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) {
|
||||
*dbptr = nullptr;
|
||||
|
||||
DBImpl* impl = new DBImpl(options, dbname);
|
||||
@ -1543,8 +1513,7 @@ Status DB::Open(const Options& options, const std::string& dbname,
|
||||
return s;
|
||||
}
|
||||
|
||||
Snapshot::~Snapshot() {
|
||||
}
|
||||
Snapshot::~Snapshot() {}
|
||||
|
||||
Status DestroyDB(const std::string& dbname, const Options& options) {
|
||||
Env* env = options.env;
|
||||
|
@ -35,8 +35,7 @@ class DBImpl : public DB {
|
||||
virtual Status Put(const WriteOptions&, const Slice& key, const Slice& value);
|
||||
virtual Status Delete(const WriteOptions&, const Slice& key);
|
||||
virtual Status Write(const WriteOptions& options, WriteBatch* updates);
|
||||
virtual Status Get(const ReadOptions& options,
|
||||
const Slice& key,
|
||||
virtual Status Get(const ReadOptions& options, const Slice& key,
|
||||
std::string* value);
|
||||
virtual Iterator* NewIterator(const ReadOptions&);
|
||||
virtual const Snapshot* GetSnapshot();
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||
#include "db/db_iter.h"
|
||||
|
||||
#include "db/filename.h"
|
||||
#include "db/db_impl.h"
|
||||
#include "db/dbformat.h"
|
||||
#include "db/filename.h"
|
||||
#include "leveldb/env.h"
|
||||
#include "leveldb/iterator.h"
|
||||
#include "port/port.h"
|
||||
@ -43,10 +43,7 @@ class DBIter: public Iterator {
|
||||
// the exact entry that yields this->key(), this->value()
|
||||
// (2) When moving backwards, the internal iterator is positioned
|
||||
// just before all entries whose user key == this->key().
|
||||
enum Direction {
|
||||
kForward,
|
||||
kReverse
|
||||
};
|
||||
enum Direction { kForward, kReverse };
|
||||
|
||||
DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s,
|
||||
uint32_t seed)
|
||||
@ -57,11 +54,8 @@ class DBIter: public Iterator {
|
||||
direction_(kForward),
|
||||
valid_(false),
|
||||
rnd_(seed),
|
||||
bytes_until_read_sampling_(RandomCompactionPeriod()) {
|
||||
}
|
||||
virtual ~DBIter() {
|
||||
delete iter_;
|
||||
}
|
||||
bytes_until_read_sampling_(RandomCompactionPeriod()) {}
|
||||
virtual ~DBIter() { delete iter_; }
|
||||
virtual bool Valid() const { return valid_; }
|
||||
virtual Slice key() const {
|
||||
assert(valid_);
|
||||
@ -221,8 +215,8 @@ void DBIter::Prev() {
|
||||
ClearSavedValue();
|
||||
return;
|
||||
}
|
||||
if (user_comparator_->Compare(ExtractUserKey(iter_->key()),
|
||||
saved_key_) < 0) {
|
||||
if (user_comparator_->Compare(ExtractUserKey(iter_->key()), saved_key_) <
|
||||
0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -278,8 +272,8 @@ void DBIter::Seek(const Slice& target) {
|
||||
direction_ = kForward;
|
||||
ClearSavedValue();
|
||||
saved_key_.clear();
|
||||
AppendInternalKey(
|
||||
&saved_key_, ParsedInternalKey(target, sequence_, kValueTypeForSeek));
|
||||
AppendInternalKey(&saved_key_,
|
||||
ParsedInternalKey(target, sequence_, kValueTypeForSeek));
|
||||
iter_->Seek(saved_key_);
|
||||
if (iter_->Valid()) {
|
||||
FindNextUserEntry(false, &saved_key_ /* temporary storage */);
|
||||
@ -308,11 +302,8 @@ void DBIter::SeekToLast() {
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
Iterator* NewDBIterator(
|
||||
DBImpl* db,
|
||||
const Comparator* user_key_comparator,
|
||||
Iterator* internal_iter,
|
||||
SequenceNumber sequence,
|
||||
Iterator* NewDBIterator(DBImpl* db, const Comparator* user_key_comparator,
|
||||
Iterator* internal_iter, SequenceNumber sequence,
|
||||
uint32_t seed) {
|
||||
return new DBIter(db, user_key_comparator, internal_iter, sequence, seed);
|
||||
}
|
||||
|
@ -6,8 +6,9 @@
|
||||
#define STORAGE_LEVELDB_DB_DB_ITER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "leveldb/db.h"
|
||||
|
||||
#include "db/dbformat.h"
|
||||
#include "leveldb/db.h"
|
||||
|
||||
namespace leveldb {
|
||||
|
||||
@ -16,10 +17,8 @@ class DBImpl;
|
||||
// Return a new iterator that converts internal keys (yielded by
|
||||
// "*internal_iter") that were live at the specified "sequence" number
|
||||
// into appropriate user keys.
|
||||
Iterator* NewDBIterator(DBImpl* db,
|
||||
const Comparator* user_key_comparator,
|
||||
Iterator* internal_iter,
|
||||
SequenceNumber sequence,
|
||||
Iterator* NewDBIterator(DBImpl* db, const Comparator* user_key_comparator,
|
||||
Iterator* internal_iter, SequenceNumber sequence,
|
||||
uint32_t seed);
|
||||
|
||||
} // namespace leveldb
|
||||
|
125
db/db_test.cc
125
db/db_test.cc
@ -2,17 +2,18 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include "leveldb/db.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
|
||||
#include "leveldb/db.h"
|
||||
#include "leveldb/filter_policy.h"
|
||||
#include "db/db_impl.h"
|
||||
#include "db/filename.h"
|
||||
#include "db/version_set.h"
|
||||
#include "db/write_batch_internal.h"
|
||||
#include "leveldb/cache.h"
|
||||
#include "leveldb/env.h"
|
||||
#include "leveldb/filter_policy.h"
|
||||
#include "leveldb/table.h"
|
||||
#include "port/port.h"
|
||||
#include "port/thread_annotations.h"
|
||||
@ -31,8 +32,8 @@ static std::string RandomString(Random* rnd, int len) {
|
||||
}
|
||||
|
||||
static std::string RandomKey(Random* rnd) {
|
||||
int len = (rnd->OneIn(3)
|
||||
? 1 // Short sometimes to encourage collisions
|
||||
int len =
|
||||
(rnd->OneIn(3) ? 1 // Short sometimes to encourage collisions
|
||||
: (rnd->OneIn(100) ? rnd->Skewed(10) : rnd->Uniform(10)));
|
||||
return test::RandomKey(rnd, len);
|
||||
}
|
||||
@ -42,11 +43,10 @@ class AtomicCounter {
|
||||
private:
|
||||
port::Mutex mu_;
|
||||
int count_ GUARDED_BY(mu_);
|
||||
|
||||
public:
|
||||
AtomicCounter() : count_(0) {}
|
||||
void Increment() {
|
||||
IncrementBy(1);
|
||||
}
|
||||
void Increment() { IncrementBy(1); }
|
||||
void IncrementBy(int count) LOCKS_EXCLUDED(mu_) {
|
||||
MutexLock l(&mu_);
|
||||
count_ += count;
|
||||
@ -120,15 +120,15 @@ class SpecialEnv : public EnvWrapper {
|
||||
bool count_random_reads_;
|
||||
AtomicCounter random_read_counter_;
|
||||
|
||||
explicit SpecialEnv(Env* base) : EnvWrapper(base),
|
||||
explicit SpecialEnv(Env* base)
|
||||
: EnvWrapper(base),
|
||||
delay_data_sync_(false),
|
||||
data_sync_error_(false),
|
||||
no_space_(false),
|
||||
non_writable_(false),
|
||||
manifest_sync_error_(false),
|
||||
manifest_write_error_(false),
|
||||
count_random_reads_(false) {
|
||||
}
|
||||
count_random_reads_(false) {}
|
||||
|
||||
Status NewWritableFile(const std::string& f, WritableFile** r) {
|
||||
class DataFile : public WritableFile {
|
||||
@ -137,10 +137,7 @@ class SpecialEnv : public EnvWrapper {
|
||||
WritableFile* const base_;
|
||||
|
||||
public:
|
||||
DataFile(SpecialEnv* env, WritableFile* base)
|
||||
: env_(env),
|
||||
base_(base) {
|
||||
}
|
||||
DataFile(SpecialEnv* env, WritableFile* base) : env_(env), base_(base) {}
|
||||
~DataFile() { delete base_; }
|
||||
Status Append(const Slice& data) {
|
||||
if (env_->no_space_.load(std::memory_order_acquire)) {
|
||||
@ -166,6 +163,7 @@ class SpecialEnv : public EnvWrapper {
|
||||
private:
|
||||
SpecialEnv* env_;
|
||||
WritableFile* base_;
|
||||
|
||||
public:
|
||||
ManifestFile(SpecialEnv* env, WritableFile* b) : env_(env), base_(b) {}
|
||||
~ManifestFile() { delete base_; }
|
||||
@ -208,10 +206,10 @@ class SpecialEnv : public EnvWrapper {
|
||||
private:
|
||||
RandomAccessFile* target_;
|
||||
AtomicCounter* counter_;
|
||||
|
||||
public:
|
||||
CountingFile(RandomAccessFile* target, AtomicCounter* counter)
|
||||
: target_(target), counter_(counter) {
|
||||
}
|
||||
: target_(target), counter_(counter) {}
|
||||
virtual ~CountingFile() { delete target_; }
|
||||
virtual Status Read(uint64_t offset, size_t n, Slice* result,
|
||||
char* scratch) const {
|
||||
@ -233,13 +231,7 @@ class DBTest {
|
||||
const FilterPolicy* filter_policy_;
|
||||
|
||||
// Sequence of option configurations to try
|
||||
enum OptionConfig {
|
||||
kDefault,
|
||||
kReuse,
|
||||
kFilter,
|
||||
kUncompressed,
|
||||
kEnd
|
||||
};
|
||||
enum OptionConfig { kDefault, kReuse, kFilter, kUncompressed, kEnd };
|
||||
int option_config_;
|
||||
|
||||
public:
|
||||
@ -249,8 +241,7 @@ class DBTest {
|
||||
|
||||
Options last_options_;
|
||||
|
||||
DBTest() : option_config_(kDefault),
|
||||
env_(new SpecialEnv(Env::Default())) {
|
||||
DBTest() : option_config_(kDefault), env_(new SpecialEnv(Env::Default())) {
|
||||
filter_policy_ = NewBloomFilterPolicy(10);
|
||||
dbname_ = test::TmpDir() + "/db_test";
|
||||
DestroyDB(dbname_, Options());
|
||||
@ -297,13 +288,9 @@ class DBTest {
|
||||
return options;
|
||||
}
|
||||
|
||||
DBImpl* dbfull() {
|
||||
return reinterpret_cast<DBImpl*>(db_);
|
||||
}
|
||||
DBImpl* dbfull() { return reinterpret_cast<DBImpl*>(db_); }
|
||||
|
||||
void Reopen(Options* options = nullptr) {
|
||||
ASSERT_OK(TryReopen(options));
|
||||
}
|
||||
void Reopen(Options* options = nullptr) { ASSERT_OK(TryReopen(options)); }
|
||||
|
||||
void Close() {
|
||||
delete db_;
|
||||
@ -336,9 +323,7 @@ class DBTest {
|
||||
return db_->Put(WriteOptions(), k, v);
|
||||
}
|
||||
|
||||
Status Delete(const std::string& k) {
|
||||
return db_->Delete(WriteOptions(), k);
|
||||
}
|
||||
Status Delete(const std::string& k) { return db_->Delete(WriteOptions(), k); }
|
||||
|
||||
std::string Get(const std::string& k, const Snapshot* snapshot = nullptr) {
|
||||
ReadOptions options;
|
||||
@ -424,9 +409,8 @@ class DBTest {
|
||||
|
||||
int NumTableFilesAtLevel(int level) {
|
||||
std::string property;
|
||||
ASSERT_TRUE(
|
||||
db_->GetProperty("leveldb.num-files-at-level" + NumberToString(level),
|
||||
&property));
|
||||
ASSERT_TRUE(db_->GetProperty(
|
||||
"leveldb.num-files-at-level" + NumberToString(level), &property));
|
||||
return std::stoi(property);
|
||||
}
|
||||
|
||||
@ -491,9 +475,9 @@ class DBTest {
|
||||
|
||||
void DumpFileCounts(const char* label) {
|
||||
fprintf(stderr, "---\n%s:\n", label);
|
||||
fprintf(stderr, "maxoverlap: %lld\n",
|
||||
static_cast<long long>(
|
||||
dbfull()->TEST_MaxNextLevelOverlappingBytes()));
|
||||
fprintf(
|
||||
stderr, "maxoverlap: %lld\n",
|
||||
static_cast<long long>(dbfull()->TEST_MaxNextLevelOverlappingBytes()));
|
||||
for (int level = 0; level < config::kNumLevels; level++) {
|
||||
int num = NumTableFilesAtLevel(level);
|
||||
if (num > 0) {
|
||||
@ -760,8 +744,7 @@ TEST(DBTest, GetEncountersEmptyLevel) {
|
||||
|
||||
// Step 1: First place sstables in levels 0 and 2
|
||||
int compaction_count = 0;
|
||||
while (NumTableFilesAtLevel(0) == 0 ||
|
||||
NumTableFilesAtLevel(2) == 0) {
|
||||
while (NumTableFilesAtLevel(0) == 0 || NumTableFilesAtLevel(2) == 0) {
|
||||
ASSERT_LE(compaction_count, 100) << "could not fill levels 0 and 2";
|
||||
compaction_count++;
|
||||
Put("a", "begin");
|
||||
@ -1179,8 +1162,7 @@ static bool Between(uint64_t val, uint64_t low, uint64_t high) {
|
||||
bool result = (val >= low) && (val <= high);
|
||||
if (!result) {
|
||||
fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n",
|
||||
(unsigned long long)(val),
|
||||
(unsigned long long)(low),
|
||||
(unsigned long long)(val), (unsigned long long)(low),
|
||||
(unsigned long long)(high));
|
||||
}
|
||||
return result;
|
||||
@ -1225,7 +1207,8 @@ TEST(DBTest, ApproximateSizes) {
|
||||
for (int compact_start = 0; compact_start < N; compact_start += 10) {
|
||||
for (int i = 0; i < N; i += 10) {
|
||||
ASSERT_TRUE(Between(Size("", Key(i)), S1 * i, S2 * i));
|
||||
ASSERT_TRUE(Between(Size("", Key(i)+".suffix"), S1*(i+1), S2*(i+1)));
|
||||
ASSERT_TRUE(Between(Size("", Key(i) + ".suffix"), S1 * (i + 1),
|
||||
S2 * (i + 1)));
|
||||
ASSERT_TRUE(Between(Size(Key(i), Key(i + 10)), S1 * 10, S2 * 10));
|
||||
}
|
||||
ASSERT_TRUE(Between(Size("", Key(50)), S1 * 50, S2 * 50));
|
||||
@ -1428,7 +1411,8 @@ TEST(DBTest, OverlapInLevel0) {
|
||||
do {
|
||||
ASSERT_EQ(config::kMaxMemCompactLevel, 2) << "Fix test to match config";
|
||||
|
||||
// Fill levels 1 and 2 to disable the pushing of new memtables to levels > 0.
|
||||
// Fill levels 1 and 2 to disable the pushing of new memtables to levels >
|
||||
// 0.
|
||||
ASSERT_OK(Put("100", "v100"));
|
||||
ASSERT_OK(Put("999", "v999"));
|
||||
dbfull()->TEST_CompactMemTable();
|
||||
@ -1554,6 +1538,7 @@ TEST(DBTest, CustomComparator) {
|
||||
virtual void FindShortSuccessor(std::string* key) const {
|
||||
ToNumber(*key); // Check format
|
||||
}
|
||||
|
||||
private:
|
||||
static int ToNumber(const Slice& x) {
|
||||
// Check that there are no extra characters.
|
||||
@ -1809,8 +1794,7 @@ TEST(DBTest, ManifestWriteError) {
|
||||
// We iterate twice. In the second iteration, everything is the
|
||||
// same except the log record never makes it to the MANIFEST file.
|
||||
for (int iter = 0; iter < 2; iter++) {
|
||||
std::atomic<bool>* error_type = (iter == 0)
|
||||
? &env_->manifest_sync_error_
|
||||
std::atomic<bool>* error_type = (iter == 0) ? &env_->manifest_sync_error_
|
||||
: &env_->manifest_write_error_;
|
||||
|
||||
// Insert foo=>bar mapping
|
||||
@ -1854,8 +1838,7 @@ TEST(DBTest, MissingSSTFile) {
|
||||
options.paranoid_checks = true;
|
||||
Status s = TryReopen(&options);
|
||||
ASSERT_TRUE(!s.ok());
|
||||
ASSERT_TRUE(s.ToString().find("issing") != std::string::npos)
|
||||
<< s.ToString();
|
||||
ASSERT_TRUE(s.ToString().find("issing") != std::string::npos) << s.ToString();
|
||||
}
|
||||
|
||||
TEST(DBTest, StillReadSST) {
|
||||
@ -1970,8 +1953,8 @@ static void MTThreadBody(void* arg) {
|
||||
if (rnd.OneIn(2)) {
|
||||
// Write values of the form <key, my id, counter>.
|
||||
// We add some padding for force compactions.
|
||||
snprintf(valbuf, sizeof(valbuf), "%d.%d.%-1000d",
|
||||
key, id, static_cast<int>(counter));
|
||||
snprintf(valbuf, sizeof(valbuf), "%d.%d.%-1000d", key, id,
|
||||
static_cast<int>(counter));
|
||||
ASSERT_OK(db->Put(WriteOptions(), Slice(keybuf), Slice(valbuf)));
|
||||
} else {
|
||||
// Read a value and verify that it matches the pattern written above.
|
||||
@ -2048,8 +2031,8 @@ class ModelDB: public DB {
|
||||
virtual Status Delete(const WriteOptions& o, const Slice& key) {
|
||||
return DB::Delete(o, key);
|
||||
}
|
||||
virtual Status Get(const ReadOptions& options,
|
||||
const Slice& key, std::string* value) {
|
||||
virtual Status Get(const ReadOptions& options, const Slice& key,
|
||||
std::string* value) {
|
||||
assert(false); // Not implemented
|
||||
return Status::NotFound(key);
|
||||
}
|
||||
@ -2080,9 +2063,7 @@ class ModelDB: public DB {
|
||||
virtual void Put(const Slice& key, const Slice& value) {
|
||||
(*map_)[key.ToString()] = value.ToString();
|
||||
}
|
||||
virtual void Delete(const Slice& key) {
|
||||
map_->erase(key.ToString());
|
||||
}
|
||||
virtual void Delete(const Slice& key) { map_->erase(key.ToString()); }
|
||||
};
|
||||
Handler handler;
|
||||
handler.map_ = &map_;
|
||||
@ -2097,15 +2078,13 @@ class ModelDB: public DB {
|
||||
sizes[i] = 0;
|
||||
}
|
||||
}
|
||||
virtual void CompactRange(const Slice* start, const Slice* end) {
|
||||
}
|
||||
virtual void CompactRange(const Slice* start, const Slice* end) {}
|
||||
|
||||
private:
|
||||
class ModelIter : public Iterator {
|
||||
public:
|
||||
ModelIter(const KVMap* map, bool owned)
|
||||
: map_(map), owned_(owned), iter_(map_->end()) {
|
||||
}
|
||||
: map_(map), owned_(owned), iter_(map_->end()) {}
|
||||
~ModelIter() {
|
||||
if (owned_) delete map_;
|
||||
}
|
||||
@ -2136,9 +2115,7 @@ class ModelDB: public DB {
|
||||
KVMap map_;
|
||||
};
|
||||
|
||||
static bool CompareIterators(int step,
|
||||
DB* model,
|
||||
DB* db,
|
||||
static bool CompareIterators(int step, DB* model, DB* db,
|
||||
const Snapshot* model_snap,
|
||||
const Snapshot* db_snap) {
|
||||
ReadOptions options;
|
||||
@ -2149,12 +2126,10 @@ static bool CompareIterators(int step,
|
||||
bool ok = true;
|
||||
int count = 0;
|
||||
for (miter->SeekToFirst(), dbiter->SeekToFirst();
|
||||
ok && miter->Valid() && dbiter->Valid();
|
||||
miter->Next(), dbiter->Next()) {
|
||||
ok && miter->Valid() && dbiter->Valid(); miter->Next(), dbiter->Next()) {
|
||||
count++;
|
||||
if (miter->key().compare(dbiter->key()) != 0) {
|
||||
fprintf(stderr, "step %d: Key mismatch: '%s' vs. '%s'\n",
|
||||
step,
|
||||
fprintf(stderr, "step %d: Key mismatch: '%s' vs. '%s'\n", step,
|
||||
EscapeString(miter->key()).c_str(),
|
||||
EscapeString(dbiter->key()).c_str());
|
||||
ok = false;
|
||||
@ -2163,8 +2138,7 @@ static bool CompareIterators(int step,
|
||||
|
||||
if (miter->value().compare(dbiter->value()) != 0) {
|
||||
fprintf(stderr, "step %d: Value mismatch for key '%s': '%s' vs. '%s'\n",
|
||||
step,
|
||||
EscapeString(miter->key()).c_str(),
|
||||
step, EscapeString(miter->key()).c_str(),
|
||||
EscapeString(miter->value()).c_str(),
|
||||
EscapeString(miter->value()).c_str());
|
||||
ok = false;
|
||||
@ -2200,10 +2174,8 @@ TEST(DBTest, Randomized) {
|
||||
int p = rnd.Uniform(100);
|
||||
if (p < 45) { // Put
|
||||
k = RandomKey(&rnd);
|
||||
v = RandomString(&rnd,
|
||||
rnd.OneIn(20)
|
||||
? 100 + rnd.Uniform(100)
|
||||
: rnd.Uniform(8));
|
||||
v = RandomString(
|
||||
&rnd, rnd.OneIn(20) ? 100 + rnd.Uniform(100) : rnd.Uniform(8));
|
||||
ASSERT_OK(model.Put(WriteOptions(), k, v));
|
||||
ASSERT_OK(db_->Put(WriteOptions(), k, v));
|
||||
|
||||
@ -2212,7 +2184,6 @@ TEST(DBTest, Randomized) {
|
||||
ASSERT_OK(model.Delete(WriteOptions(), k));
|
||||
ASSERT_OK(db_->Delete(WriteOptions(), k));
|
||||
|
||||
|
||||
} else { // Multi-element batch
|
||||
WriteBatch b;
|
||||
const int num = rnd.Uniform(8);
|
||||
@ -2309,8 +2280,8 @@ void BM_LogAndApply(int iters, int num_base_files) {
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%d", num_base_files);
|
||||
fprintf(stderr,
|
||||
"BM_LogAndApply/%-6s %8d iters : %9u us (%7.0f us / iter)\n",
|
||||
buf, iters, us, ((float)us) / iters);
|
||||
"BM_LogAndApply/%-6s %8d iters : %9u us (%7.0f us / iter)\n", buf,
|
||||
iters, us, ((float)us) / iters);
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
|
@ -2,8 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include <stdio.h>
|
||||
#include "db/dbformat.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "port/port.h"
|
||||
#include "util/coding.h"
|
||||
|
||||
@ -22,8 +24,7 @@ void AppendInternalKey(std::string* result, const ParsedInternalKey& key) {
|
||||
|
||||
std::string ParsedInternalKey::DebugString() const {
|
||||
char buf[50];
|
||||
snprintf(buf, sizeof(buf), "' @ %llu : %d",
|
||||
(unsigned long long) sequence,
|
||||
snprintf(buf, sizeof(buf), "' @ %llu : %d", (unsigned long long)sequence,
|
||||
int(type));
|
||||
std::string result = "'";
|
||||
result += EscapeString(user_key.ToString());
|
||||
@ -65,8 +66,7 @@ int InternalKeyComparator::Compare(const Slice& akey, const Slice& bkey) const {
|
||||
return r;
|
||||
}
|
||||
|
||||
void InternalKeyComparator::FindShortestSeparator(
|
||||
std::string* start,
|
||||
void InternalKeyComparator::FindShortestSeparator(std::string* start,
|
||||
const Slice& limit) const {
|
||||
// Attempt to shorten the user portion of the key
|
||||
Slice user_start = ExtractUserKey(*start);
|
||||
@ -77,7 +77,8 @@ void InternalKeyComparator::FindShortestSeparator(
|
||||
user_comparator_->Compare(user_start, tmp) < 0) {
|
||||
// User key has become shorter physically, but larger logically.
|
||||
// Tack on the earliest possible number to the shortened user key.
|
||||
PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek));
|
||||
PutFixed64(&tmp,
|
||||
PackSequenceAndType(kMaxSequenceNumber, kValueTypeForSeek));
|
||||
assert(this->Compare(*start, tmp) < 0);
|
||||
assert(this->Compare(tmp, limit) < 0);
|
||||
start->swap(tmp);
|
||||
@ -92,15 +93,14 @@ void InternalKeyComparator::FindShortSuccessor(std::string* key) const {
|
||||
user_comparator_->Compare(user_key, tmp) < 0) {
|
||||
// User key has become shorter physically, but larger logically.
|
||||
// Tack on the earliest possible number to the shortened user key.
|
||||
PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek));
|
||||
PutFixed64(&tmp,
|
||||
PackSequenceAndType(kMaxSequenceNumber, kValueTypeForSeek));
|
||||
assert(this->Compare(*key, tmp) < 0);
|
||||
key->swap(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
const char* InternalFilterPolicy::Name() const {
|
||||
return user_policy_->Name();
|
||||
}
|
||||
const char* InternalFilterPolicy::Name() const { return user_policy_->Name(); }
|
||||
|
||||
void InternalFilterPolicy::CreateFilter(const Slice* keys, int n,
|
||||
std::string* dst) const {
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define STORAGE_LEVELDB_DB_DBFORMAT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "leveldb/comparator.h"
|
||||
#include "leveldb/db.h"
|
||||
#include "leveldb/filter_policy.h"
|
||||
@ -48,10 +49,7 @@ class InternalKey;
|
||||
// Value types encoded as the last component of internal keys.
|
||||
// DO NOT CHANGE THESE ENUM VALUES: they are embedded in the on-disk
|
||||
// data structures.
|
||||
enum ValueType {
|
||||
kTypeDeletion = 0x0,
|
||||
kTypeValue = 0x1
|
||||
};
|
||||
enum ValueType { kTypeDeletion = 0x0, kTypeValue = 0x1 };
|
||||
// kValueTypeForSeek defines the ValueType that should be passed when
|
||||
// constructing a ParsedInternalKey object for seeking to a particular
|
||||
// sequence number (since we sort sequence numbers in decreasing order
|
||||
@ -64,8 +62,7 @@ typedef uint64_t SequenceNumber;
|
||||
|
||||
// We leave eight bits empty at the bottom so a type and sequence#
|
||||
// can be packed together into 64-bits.
|
||||
static const SequenceNumber kMaxSequenceNumber =
|
||||
((0x1ull << 56) - 1);
|
||||
static const SequenceNumber kMaxSequenceNumber = ((0x1ull << 56) - 1);
|
||||
|
||||
struct ParsedInternalKey {
|
||||
Slice user_key;
|
||||
@ -103,12 +100,12 @@ inline Slice ExtractUserKey(const Slice& internal_key) {
|
||||
class InternalKeyComparator : public Comparator {
|
||||
private:
|
||||
const Comparator* user_comparator_;
|
||||
|
||||
public:
|
||||
explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) {}
|
||||
virtual const char* Name() const;
|
||||
virtual int Compare(const Slice& a, const Slice& b) const;
|
||||
virtual void FindShortestSeparator(
|
||||
std::string* start,
|
||||
virtual void FindShortestSeparator(std::string* start,
|
||||
const Slice& limit) const;
|
||||
virtual void FindShortSuccessor(std::string* key) const;
|
||||
|
||||
@ -121,6 +118,7 @@ class InternalKeyComparator : public Comparator {
|
||||
class InternalFilterPolicy : public FilterPolicy {
|
||||
private:
|
||||
const FilterPolicy* const user_policy_;
|
||||
|
||||
public:
|
||||
explicit InternalFilterPolicy(const FilterPolicy* p) : user_policy_(p) {}
|
||||
virtual const char* Name() const;
|
||||
@ -134,6 +132,7 @@ class InternalFilterPolicy : public FilterPolicy {
|
||||
class InternalKey {
|
||||
private:
|
||||
std::string rep_;
|
||||
|
||||
public:
|
||||
InternalKey() {} // Leave rep_ as empty to indicate it is invalid
|
||||
InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) {
|
||||
@ -158,8 +157,8 @@ class InternalKey {
|
||||
std::string DebugString() const;
|
||||
};
|
||||
|
||||
inline int InternalKeyComparator::Compare(
|
||||
const InternalKey& a, const InternalKey& b) const {
|
||||
inline int InternalKeyComparator::Compare(const InternalKey& a,
|
||||
const InternalKey& b) const {
|
||||
return Compare(a.Encode(), b.Encode());
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,7 @@
|
||||
|
||||
namespace leveldb {
|
||||
|
||||
static std::string IKey(const std::string& user_key,
|
||||
uint64_t seq,
|
||||
static std::string IKey(const std::string& user_key, uint64_t seq,
|
||||
ValueType vt) {
|
||||
std::string encoded;
|
||||
AppendInternalKey(&encoded, ParsedInternalKey(user_key, seq, vt));
|
||||
@ -28,9 +27,7 @@ static std::string ShortSuccessor(const std::string& s) {
|
||||
return result;
|
||||
}
|
||||
|
||||
static void TestKey(const std::string& key,
|
||||
uint64_t seq,
|
||||
ValueType vt) {
|
||||
static void TestKey(const std::string& key, uint64_t seq, ValueType vt) {
|
||||
std::string encoded = IKey(key, seq, vt);
|
||||
|
||||
Slice in(encoded);
|
||||
@ -48,12 +45,18 @@ class FormatTest { };
|
||||
|
||||
TEST(FormatTest, InternalKey_EncodeDecode) {
|
||||
const char* keys[] = {"", "k", "hello", "longggggggggggggggggggggg"};
|
||||
const uint64_t seq[] = {
|
||||
1, 2, 3,
|
||||
(1ull << 8) - 1, 1ull << 8, (1ull << 8) + 1,
|
||||
(1ull << 16) - 1, 1ull << 16, (1ull << 16) + 1,
|
||||
(1ull << 32) - 1, 1ull << 32, (1ull << 32) + 1
|
||||
};
|
||||
const uint64_t seq[] = {1,
|
||||
2,
|
||||
3,
|
||||
(1ull << 8) - 1,
|
||||
1ull << 8,
|
||||
(1ull << 8) + 1,
|
||||
(1ull << 16) - 1,
|
||||
1ull << 16,
|
||||
(1ull << 16) + 1,
|
||||
(1ull << 32) - 1,
|
||||
1ull << 32,
|
||||
(1ull << 32) + 1};
|
||||
for (int k = 0; k < sizeof(keys) / sizeof(keys[0]); k++) {
|
||||
for (int s = 0; s < sizeof(seq) / sizeof(seq[0]); s++) {
|
||||
TestKey(keys[k], seq[s], kTypeValue);
|
||||
@ -65,37 +68,35 @@ TEST(FormatTest, InternalKey_EncodeDecode) {
|
||||
TEST(FormatTest, InternalKeyShortSeparator) {
|
||||
// When user keys are same
|
||||
ASSERT_EQ(IKey("foo", 100, kTypeValue),
|
||||
Shorten(IKey("foo", 100, kTypeValue),
|
||||
IKey("foo", 99, kTypeValue)));
|
||||
ASSERT_EQ(IKey("foo", 100, kTypeValue),
|
||||
Shorten(IKey("foo", 100, kTypeValue),
|
||||
IKey("foo", 101, kTypeValue)));
|
||||
ASSERT_EQ(IKey("foo", 100, kTypeValue),
|
||||
Shorten(IKey("foo", 100, kTypeValue),
|
||||
IKey("foo", 100, kTypeValue)));
|
||||
ASSERT_EQ(IKey("foo", 100, kTypeValue),
|
||||
Shorten(IKey("foo", 100, kTypeValue),
|
||||
IKey("foo", 100, kTypeDeletion)));
|
||||
Shorten(IKey("foo", 100, kTypeValue), IKey("foo", 99, kTypeValue)));
|
||||
ASSERT_EQ(
|
||||
IKey("foo", 100, kTypeValue),
|
||||
Shorten(IKey("foo", 100, kTypeValue), IKey("foo", 101, kTypeValue)));
|
||||
ASSERT_EQ(
|
||||
IKey("foo", 100, kTypeValue),
|
||||
Shorten(IKey("foo", 100, kTypeValue), IKey("foo", 100, kTypeValue)));
|
||||
ASSERT_EQ(
|
||||
IKey("foo", 100, kTypeValue),
|
||||
Shorten(IKey("foo", 100, kTypeValue), IKey("foo", 100, kTypeDeletion)));
|
||||
|
||||
// When user keys are misordered
|
||||
ASSERT_EQ(IKey("foo", 100, kTypeValue),
|
||||
Shorten(IKey("foo", 100, kTypeValue),
|
||||
IKey("bar", 99, kTypeValue)));
|
||||
Shorten(IKey("foo", 100, kTypeValue), IKey("bar", 99, kTypeValue)));
|
||||
|
||||
// When user keys are different, but correctly ordered
|
||||
ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek),
|
||||
Shorten(IKey("foo", 100, kTypeValue),
|
||||
IKey("hello", 200, kTypeValue)));
|
||||
ASSERT_EQ(
|
||||
IKey("g", kMaxSequenceNumber, kValueTypeForSeek),
|
||||
Shorten(IKey("foo", 100, kTypeValue), IKey("hello", 200, kTypeValue)));
|
||||
|
||||
// When start user key is prefix of limit user key
|
||||
ASSERT_EQ(IKey("foo", 100, kTypeValue),
|
||||
Shorten(IKey("foo", 100, kTypeValue),
|
||||
IKey("foobar", 200, kTypeValue)));
|
||||
ASSERT_EQ(
|
||||
IKey("foo", 100, kTypeValue),
|
||||
Shorten(IKey("foo", 100, kTypeValue), IKey("foobar", 200, kTypeValue)));
|
||||
|
||||
// When limit user key is prefix of start user key
|
||||
ASSERT_EQ(IKey("foobar", 100, kTypeValue),
|
||||
Shorten(IKey("foobar", 100, kTypeValue),
|
||||
IKey("foo", 200, kTypeValue)));
|
||||
ASSERT_EQ(
|
||||
IKey("foobar", 100, kTypeValue),
|
||||
Shorten(IKey("foobar", 100, kTypeValue), IKey("foo", 200, kTypeValue)));
|
||||
}
|
||||
|
||||
TEST(FormatTest, InternalKeyShortestSuccessor) {
|
||||
@ -107,6 +108,4 @@ TEST(FormatTest, InternalKeyShortestSuccessor) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -90,7 +90,6 @@ class WriteBatchItemPrinter : public WriteBatch::Handler {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Called on every log record (each one of which is a WriteBatch)
|
||||
// found in a kLogFile.
|
||||
static void WriteBatchPrinter(uint64_t pos, Slice record, WritableFile* dst) {
|
||||
@ -216,9 +215,12 @@ Status DumpFile(Env* env, const std::string& fname, WritableFile* dst) {
|
||||
return Status::InvalidArgument(fname + ": unknown file type");
|
||||
}
|
||||
switch (ftype) {
|
||||
case kLogFile: return DumpLog(env, fname, dst);
|
||||
case kDescriptorFile: return DumpDescriptor(env, fname, dst);
|
||||
case kTableFile: return DumpTable(env, fname, dst);
|
||||
case kLogFile:
|
||||
return DumpLog(env, fname, dst);
|
||||
case kDescriptorFile:
|
||||
return DumpDescriptor(env, fname, dst);
|
||||
case kTableFile:
|
||||
return DumpTable(env, fname, dst);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -9,12 +9,12 @@
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "leveldb/db.h"
|
||||
#include "db/db_impl.h"
|
||||
#include "db/filename.h"
|
||||
#include "db/log_format.h"
|
||||
#include "db/version_set.h"
|
||||
#include "leveldb/cache.h"
|
||||
#include "leveldb/db.h"
|
||||
#include "leveldb/env.h"
|
||||
#include "leveldb/table.h"
|
||||
#include "leveldb/write_batch.h"
|
||||
@ -56,8 +56,7 @@ Status Truncate(const std::string& filename, uint64_t length) {
|
||||
|
||||
SequentialFile* orig_file;
|
||||
Status s = env->NewSequentialFile(filename, &orig_file);
|
||||
if (!s.ok())
|
||||
return s;
|
||||
if (!s.ok()) return s;
|
||||
|
||||
char* scratch = new char[length];
|
||||
leveldb::Slice result;
|
||||
@ -108,8 +107,7 @@ struct FileState {
|
||||
// is written to or sync'ed.
|
||||
class TestWritableFile : public WritableFile {
|
||||
public:
|
||||
TestWritableFile(const FileState& state,
|
||||
WritableFile* f,
|
||||
TestWritableFile(const FileState& state, WritableFile* f,
|
||||
FaultInjectionTestEnv* env);
|
||||
virtual ~TestWritableFile();
|
||||
virtual Status Append(const Slice& data);
|
||||
@ -165,13 +163,9 @@ class FaultInjectionTestEnv : public EnvWrapper {
|
||||
bool filesystem_active_ GUARDED_BY(mutex_); // Record flushes, syncs, writes
|
||||
};
|
||||
|
||||
TestWritableFile::TestWritableFile(const FileState& state,
|
||||
WritableFile* f,
|
||||
TestWritableFile::TestWritableFile(const FileState& state, WritableFile* f,
|
||||
FaultInjectionTestEnv* env)
|
||||
: state_(state),
|
||||
target_(f),
|
||||
writable_file_opened_(true),
|
||||
env_(env) {
|
||||
: state_(state), target_(f), writable_file_opened_(true), env_(env) {
|
||||
assert(f != nullptr);
|
||||
}
|
||||
|
||||
@ -395,9 +389,7 @@ class FaultInjectionTest {
|
||||
delete env_;
|
||||
}
|
||||
|
||||
void ReuseLogs(bool reuse) {
|
||||
options_.reuse_logs = reuse;
|
||||
}
|
||||
void ReuseLogs(bool reuse) { options_.reuse_logs = reuse; }
|
||||
|
||||
void Build(int start_idx, int num_vals) {
|
||||
std::string key_space, value_space;
|
||||
@ -497,18 +489,17 @@ class FaultInjectionTest {
|
||||
}
|
||||
|
||||
void PartialCompactTestReopenWithFault(ResetMethod reset_method,
|
||||
int num_pre_sync,
|
||||
int num_post_sync) {
|
||||
int num_pre_sync, int num_post_sync) {
|
||||
env_->SetFilesystemActive(false);
|
||||
CloseDB();
|
||||
ResetDBState(reset_method);
|
||||
ASSERT_OK(OpenDB());
|
||||
ASSERT_OK(Verify(0, num_pre_sync, FaultInjectionTest::VAL_EXPECT_NO_ERROR));
|
||||
ASSERT_OK(Verify(num_pre_sync, num_post_sync, FaultInjectionTest::VAL_EXPECT_ERROR));
|
||||
ASSERT_OK(Verify(num_pre_sync, num_post_sync,
|
||||
FaultInjectionTest::VAL_EXPECT_ERROR));
|
||||
}
|
||||
|
||||
void NoWriteTestPreFault() {
|
||||
}
|
||||
void NoWriteTestPreFault() {}
|
||||
|
||||
void NoWriteTestReopenWithFault(ResetMethod reset_method) {
|
||||
CloseDB();
|
||||
@ -524,8 +515,7 @@ class FaultInjectionTest {
|
||||
int num_post_sync = rnd.Uniform(kMaxNumValues);
|
||||
|
||||
PartialCompactTestPreFault(num_pre_sync, num_post_sync);
|
||||
PartialCompactTestReopenWithFault(RESET_DROP_UNSYNCED_DATA,
|
||||
num_pre_sync,
|
||||
PartialCompactTestReopenWithFault(RESET_DROP_UNSYNCED_DATA, num_pre_sync,
|
||||
num_post_sync);
|
||||
|
||||
NoWriteTestPreFault();
|
||||
@ -535,8 +525,7 @@ class FaultInjectionTest {
|
||||
// No new files created so we expect all values since no files will be
|
||||
// dropped.
|
||||
PartialCompactTestReopenWithFault(RESET_DELETE_UNSYNCED_FILES,
|
||||
num_pre_sync + num_post_sync,
|
||||
0);
|
||||
num_pre_sync + num_post_sync, 0);
|
||||
|
||||
NoWriteTestPreFault();
|
||||
NoWriteTestReopenWithFault(RESET_DELETE_UNSYNCED_FILES);
|
||||
@ -556,6 +545,4 @@ TEST(FaultInjectionTest, FaultTestWithLogReuse) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -2,9 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include "db/filename.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include "db/filename.h"
|
||||
|
||||
#include "db/dbformat.h"
|
||||
#include "leveldb/env.h"
|
||||
#include "util/logging.h"
|
||||
@ -19,8 +21,7 @@ static std::string MakeFileName(const std::string& dbname, uint64_t number,
|
||||
const char* suffix) {
|
||||
char buf[100];
|
||||
snprintf(buf, sizeof(buf), "/%06llu.%s",
|
||||
static_cast<unsigned long long>(number),
|
||||
suffix);
|
||||
static_cast<unsigned long long>(number), suffix);
|
||||
return dbname + buf;
|
||||
}
|
||||
|
||||
@ -51,9 +52,7 @@ std::string CurrentFileName(const std::string& dbname) {
|
||||
return dbname + "/CURRENT";
|
||||
}
|
||||
|
||||
std::string LockFileName(const std::string& dbname) {
|
||||
return dbname + "/LOCK";
|
||||
}
|
||||
std::string LockFileName(const std::string& dbname) { return dbname + "/LOCK"; }
|
||||
|
||||
std::string TempFileName(const std::string& dbname, uint64_t number) {
|
||||
assert(number > 0);
|
||||
@ -69,7 +68,6 @@ std::string OldInfoLogFileName(const std::string& dbname) {
|
||||
return dbname + "/LOG.old";
|
||||
}
|
||||
|
||||
|
||||
// Owned filenames have the form:
|
||||
// dbname/CURRENT
|
||||
// dbname/LOCK
|
||||
@ -77,8 +75,7 @@ std::string OldInfoLogFileName(const std::string& dbname) {
|
||||
// dbname/LOG.old
|
||||
// dbname/MANIFEST-[0-9]+
|
||||
// dbname/[0-9]+.(log|sst|ldb)
|
||||
bool ParseFileName(const std::string& filename,
|
||||
uint64_t* number,
|
||||
bool ParseFileName(const std::string& filename, uint64_t* number,
|
||||
FileType* type) {
|
||||
Slice rest(filename);
|
||||
if (rest == "CURRENT") {
|
||||
|
@ -8,7 +8,9 @@
|
||||
#define STORAGE_LEVELDB_DB_FILENAME_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "leveldb/slice.h"
|
||||
#include "leveldb/status.h"
|
||||
#include "port/port.h"
|
||||
@ -69,8 +71,7 @@ std::string OldInfoLogFileName(const std::string& dbname);
|
||||
// If filename is a leveldb file, store the type of the file in *type.
|
||||
// The number encoded in the filename is stored in *number. If the
|
||||
// filename was successfully parsed, returns true. Else return false.
|
||||
bool ParseFileName(const std::string& filename,
|
||||
uint64_t* number,
|
||||
bool ParseFileName(const std::string& filename, uint64_t* number,
|
||||
FileType* type);
|
||||
|
||||
// Make the CURRENT file point to the descriptor file with the
|
||||
|
@ -44,8 +44,7 @@ TEST(FileNameTest, Parse) {
|
||||
}
|
||||
|
||||
// Errors
|
||||
static const char* errors[] = {
|
||||
"",
|
||||
static const char* errors[] = {"",
|
||||
"foo",
|
||||
"foo-dx-100.log",
|
||||
".log",
|
||||
@ -66,8 +65,7 @@ TEST(FileNameTest, Parse) {
|
||||
"184467440737095516150.log",
|
||||
"100",
|
||||
"100.",
|
||||
"100.lop"
|
||||
};
|
||||
"100.lop"};
|
||||
for (int i = 0; i < sizeof(errors) / sizeof(errors[0]); i++) {
|
||||
std::string f = errors[i];
|
||||
ASSERT_TRUE(!ParseFileName(f, &number, &type)) << f;
|
||||
@ -130,6 +128,4 @@ TEST(FileNameTest, Construction) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "leveldb/dumpfile.h"
|
||||
#include "leveldb/env.h"
|
||||
#include "leveldb/status.h"
|
||||
@ -38,11 +39,9 @@ bool HandleDumpCommand(Env* env, char** files, int num) {
|
||||
} // namespace leveldb
|
||||
|
||||
static void Usage() {
|
||||
fprintf(
|
||||
stderr,
|
||||
fprintf(stderr,
|
||||
"Usage: leveldbutil command...\n"
|
||||
" dump files... -- dump contents of specified files\n"
|
||||
);
|
||||
" dump files... -- dump contents of specified files\n");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "db/log_reader.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "leveldb/env.h"
|
||||
#include "util/coding.h"
|
||||
#include "util/crc32c.h"
|
||||
@ -12,8 +13,7 @@
|
||||
namespace leveldb {
|
||||
namespace log {
|
||||
|
||||
Reader::Reporter::~Reporter() {
|
||||
}
|
||||
Reader::Reporter::~Reporter() {}
|
||||
|
||||
Reader::Reader(SequentialFile* file, Reporter* reporter, bool checksum,
|
||||
uint64_t initial_offset)
|
||||
@ -26,12 +26,9 @@ Reader::Reader(SequentialFile* file, Reporter* reporter, bool checksum,
|
||||
last_record_offset_(0),
|
||||
end_of_buffer_offset_(0),
|
||||
initial_offset_(initial_offset),
|
||||
resyncing_(initial_offset > 0) {
|
||||
}
|
||||
resyncing_(initial_offset > 0) {}
|
||||
|
||||
Reader::~Reader() {
|
||||
delete[] backing_store_;
|
||||
}
|
||||
Reader::~Reader() { delete[] backing_store_; }
|
||||
|
||||
bool Reader::SkipToInitialBlock() {
|
||||
const size_t offset_in_block = initial_offset_ % kBlockSize;
|
||||
@ -176,9 +173,7 @@ bool Reader::ReadRecord(Slice* record, std::string* scratch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t Reader::LastRecordOffset() {
|
||||
return last_record_offset_;
|
||||
}
|
||||
uint64_t Reader::LastRecordOffset() { return last_record_offset_; }
|
||||
|
||||
void Reader::ReportCorruption(uint64_t bytes, const char* reason) {
|
||||
ReportDrop(bytes, Status::Corruption(reason));
|
||||
|
@ -113,11 +113,11 @@ class LogTest {
|
||||
static int num_initial_offset_records_;
|
||||
|
||||
public:
|
||||
LogTest() : reading_(false),
|
||||
LogTest()
|
||||
: reading_(false),
|
||||
writer_(new Writer(&dest_)),
|
||||
reader_(new Reader(&source_, &report_, true /*checksum*/,
|
||||
0/*initial_offset*/)) {
|
||||
}
|
||||
0 /*initial_offset*/)) {}
|
||||
|
||||
~LogTest() {
|
||||
delete writer_;
|
||||
@ -134,9 +134,7 @@ class LogTest {
|
||||
writer_->AddRecord(Slice(msg));
|
||||
}
|
||||
|
||||
size_t WrittenBytes() const {
|
||||
return dest_.contents_.size();
|
||||
}
|
||||
size_t WrittenBytes() const { return dest_.contents_.size(); }
|
||||
|
||||
std::string Read() {
|
||||
if (!reading_) {
|
||||
@ -171,17 +169,11 @@ class LogTest {
|
||||
EncodeFixed32(&dest_.contents_[header_offset], crc);
|
||||
}
|
||||
|
||||
void ForceError() {
|
||||
source_.force_error_ = true;
|
||||
}
|
||||
void ForceError() { source_.force_error_ = true; }
|
||||
|
||||
size_t DroppedBytes() const {
|
||||
return report_.dropped_bytes_;
|
||||
}
|
||||
size_t DroppedBytes() const { return report_.dropped_bytes_; }
|
||||
|
||||
std::string ReportMessage() const {
|
||||
return report_.message_;
|
||||
}
|
||||
std::string ReportMessage() const { return report_.message_; }
|
||||
|
||||
// Returns OK iff recorded error message contains "msg"
|
||||
std::string MatchError(const std::string& msg) const {
|
||||
@ -222,8 +214,8 @@ class LogTest {
|
||||
WriteInitialOffsetLog();
|
||||
reading_ = true;
|
||||
source_.contents_ = Slice(dest_.contents_);
|
||||
Reader* offset_reader = new Reader(&source_, &report_, true/*checksum*/,
|
||||
initial_offset);
|
||||
Reader* offset_reader =
|
||||
new Reader(&source_, &report_, true /*checksum*/, initial_offset);
|
||||
|
||||
// Read all records from expected_record_offset through the last one.
|
||||
ASSERT_LT(expected_record_offset, num_initial_offset_records_);
|
||||
@ -242,8 +234,8 @@ class LogTest {
|
||||
}
|
||||
};
|
||||
|
||||
size_t LogTest::initial_offset_record_sizes_[] =
|
||||
{10000, // Two sizable records in first block
|
||||
size_t LogTest::initial_offset_record_sizes_[] = {
|
||||
10000, // Two sizable records in first block
|
||||
10000,
|
||||
2 * log::kBlockSize - 1000, // Span three blocks
|
||||
1,
|
||||
@ -251,15 +243,13 @@ size_t LogTest::initial_offset_record_sizes_[] =
|
||||
log::kBlockSize - kHeaderSize, // Consume the entirety of block 4.
|
||||
};
|
||||
|
||||
uint64_t LogTest::initial_offset_last_record_offsets_[] =
|
||||
{0,
|
||||
uint64_t LogTest::initial_offset_last_record_offsets_[] = {
|
||||
0,
|
||||
kHeaderSize + 10000,
|
||||
2 * (kHeaderSize + 10000),
|
||||
2 * (kHeaderSize + 10000) +
|
||||
(2 * log::kBlockSize - 1000) + 3 * kHeaderSize,
|
||||
2 * (kHeaderSize + 10000) +
|
||||
(2 * log::kBlockSize - 1000) + 3 * kHeaderSize
|
||||
+ kHeaderSize + 1,
|
||||
2 * (kHeaderSize + 10000) + (2 * log::kBlockSize - 1000) + 3 * kHeaderSize,
|
||||
2 * (kHeaderSize + 10000) + (2 * log::kBlockSize - 1000) + 3 * kHeaderSize +
|
||||
kHeaderSize + 1,
|
||||
3 * log::kBlockSize,
|
||||
};
|
||||
|
||||
@ -267,9 +257,7 @@ uint64_t LogTest::initial_offset_last_record_offsets_[] =
|
||||
int LogTest::num_initial_offset_records_ =
|
||||
sizeof(LogTest::initial_offset_last_record_offsets_) / sizeof(uint64_t);
|
||||
|
||||
TEST(LogTest, Empty) {
|
||||
ASSERT_EQ("EOF", Read());
|
||||
}
|
||||
TEST(LogTest, Empty) { ASSERT_EQ("EOF", Read()); }
|
||||
|
||||
TEST(LogTest, ReadWrite) {
|
||||
Write("foo");
|
||||
@ -525,33 +513,19 @@ TEST(LogTest, ErrorJoinsRecords) {
|
||||
ASSERT_GE(dropped, 2 * kBlockSize);
|
||||
}
|
||||
|
||||
TEST(LogTest, ReadStart) {
|
||||
CheckInitialOffsetRecord(0, 0);
|
||||
}
|
||||
TEST(LogTest, ReadStart) { CheckInitialOffsetRecord(0, 0); }
|
||||
|
||||
TEST(LogTest, ReadSecondOneOff) {
|
||||
CheckInitialOffsetRecord(1, 1);
|
||||
}
|
||||
TEST(LogTest, ReadSecondOneOff) { CheckInitialOffsetRecord(1, 1); }
|
||||
|
||||
TEST(LogTest, ReadSecondTenThousand) {
|
||||
CheckInitialOffsetRecord(10000, 1);
|
||||
}
|
||||
TEST(LogTest, ReadSecondTenThousand) { CheckInitialOffsetRecord(10000, 1); }
|
||||
|
||||
TEST(LogTest, ReadSecondStart) {
|
||||
CheckInitialOffsetRecord(10007, 1);
|
||||
}
|
||||
TEST(LogTest, ReadSecondStart) { CheckInitialOffsetRecord(10007, 1); }
|
||||
|
||||
TEST(LogTest, ReadThirdOneOff) {
|
||||
CheckInitialOffsetRecord(10008, 2);
|
||||
}
|
||||
TEST(LogTest, ReadThirdOneOff) { CheckInitialOffsetRecord(10008, 2); }
|
||||
|
||||
TEST(LogTest, ReadThirdStart) {
|
||||
CheckInitialOffsetRecord(20014, 2);
|
||||
}
|
||||
TEST(LogTest, ReadThirdStart) { CheckInitialOffsetRecord(20014, 2); }
|
||||
|
||||
TEST(LogTest, ReadFourthOneOff) {
|
||||
CheckInitialOffsetRecord(20015, 3);
|
||||
}
|
||||
TEST(LogTest, ReadFourthOneOff) { CheckInitialOffsetRecord(20015, 3); }
|
||||
|
||||
TEST(LogTest, ReadFourthFirstBlockTrailer) {
|
||||
CheckInitialOffsetRecord(log::kBlockSize - 4, 3);
|
||||
@ -575,17 +549,11 @@ TEST(LogTest, ReadInitialOffsetIntoBlockPadding) {
|
||||
CheckInitialOffsetRecord(3 * log::kBlockSize - 3, 5);
|
||||
}
|
||||
|
||||
TEST(LogTest, ReadEnd) {
|
||||
CheckOffsetPastEndReturnsNoRecords(0);
|
||||
}
|
||||
TEST(LogTest, ReadEnd) { CheckOffsetPastEndReturnsNoRecords(0); }
|
||||
|
||||
TEST(LogTest, ReadPastEnd) {
|
||||
CheckOffsetPastEndReturnsNoRecords(5);
|
||||
}
|
||||
TEST(LogTest, ReadPastEnd) { CheckOffsetPastEndReturnsNoRecords(5); }
|
||||
|
||||
} // namespace log
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "db/log_writer.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "leveldb/env.h"
|
||||
#include "util/coding.h"
|
||||
#include "util/crc32c.h"
|
||||
@ -19,9 +20,7 @@ static void InitTypeCrc(uint32_t* type_crc) {
|
||||
}
|
||||
}
|
||||
|
||||
Writer::Writer(WritableFile* dest)
|
||||
: dest_(dest),
|
||||
block_offset_(0) {
|
||||
Writer::Writer(WritableFile* dest) : dest_(dest), block_offset_(0) {
|
||||
InitTypeCrc(type_crc_);
|
||||
}
|
||||
|
||||
@ -30,8 +29,7 @@ Writer::Writer(WritableFile* dest, uint64_t dest_length)
|
||||
InitTypeCrc(type_crc_);
|
||||
}
|
||||
|
||||
Writer::~Writer() {
|
||||
}
|
||||
Writer::~Writer() {}
|
||||
|
||||
Status Writer::AddRecord(const Slice& slice) {
|
||||
const char* ptr = slice.data();
|
||||
@ -49,7 +47,7 @@ Status Writer::AddRecord(const Slice& slice) {
|
||||
// Switch to a new block
|
||||
if (leftover > 0) {
|
||||
// Fill the trailer (literal below relies on kHeaderSize being 7)
|
||||
assert(kHeaderSize == 7);
|
||||
static_assert(kHeaderSize == 7, "");
|
||||
dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover));
|
||||
}
|
||||
block_offset_ = 0;
|
||||
@ -81,30 +79,31 @@ Status Writer::AddRecord(const Slice& slice) {
|
||||
return s;
|
||||
}
|
||||
|
||||
Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr, size_t n) {
|
||||
assert(n <= 0xffff); // Must fit in two bytes
|
||||
assert(block_offset_ + kHeaderSize + n <= kBlockSize);
|
||||
Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr,
|
||||
size_t length) {
|
||||
assert(length <= 0xffff); // Must fit in two bytes
|
||||
assert(block_offset_ + kHeaderSize + length <= kBlockSize);
|
||||
|
||||
// Format the header
|
||||
char buf[kHeaderSize];
|
||||
buf[4] = static_cast<char>(n & 0xff);
|
||||
buf[5] = static_cast<char>(n >> 8);
|
||||
buf[4] = static_cast<char>(length & 0xff);
|
||||
buf[5] = static_cast<char>(length >> 8);
|
||||
buf[6] = static_cast<char>(t);
|
||||
|
||||
// Compute the crc of the record type and the payload.
|
||||
uint32_t crc = crc32c::Extend(type_crc_[t], ptr, n);
|
||||
uint32_t crc = crc32c::Extend(type_crc_[t], ptr, length);
|
||||
crc = crc32c::Mask(crc); // Adjust for storage
|
||||
EncodeFixed32(buf, crc);
|
||||
|
||||
// Write the header and the payload
|
||||
Status s = dest_->Append(Slice(buf, kHeaderSize));
|
||||
if (s.ok()) {
|
||||
s = dest_->Append(Slice(ptr, n));
|
||||
s = dest_->Append(Slice(ptr, length));
|
||||
if (s.ok()) {
|
||||
s = dest_->Flush();
|
||||
}
|
||||
}
|
||||
block_offset_ += kHeaderSize + n;
|
||||
block_offset_ += kHeaderSize + length;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define STORAGE_LEVELDB_DB_LOG_WRITER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "db/log_format.h"
|
||||
#include "leveldb/slice.h"
|
||||
#include "leveldb/status.h"
|
||||
|
@ -18,20 +18,15 @@ static Slice GetLengthPrefixedSlice(const char* data) {
|
||||
return Slice(p, len);
|
||||
}
|
||||
|
||||
MemTable::MemTable(const InternalKeyComparator& cmp)
|
||||
: comparator_(cmp),
|
||||
refs_(0),
|
||||
table_(comparator_, &arena_) {
|
||||
}
|
||||
MemTable::MemTable(const InternalKeyComparator& comparator)
|
||||
: comparator_(comparator), refs_(0), table_(comparator_, &arena_) {}
|
||||
|
||||
MemTable::~MemTable() {
|
||||
assert(refs_ == 0);
|
||||
}
|
||||
MemTable::~MemTable() { assert(refs_ == 0); }
|
||||
|
||||
size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); }
|
||||
|
||||
int MemTable::KeyComparator::operator()(const char* aptr, const char* bptr)
|
||||
const {
|
||||
int MemTable::KeyComparator::operator()(const char* aptr,
|
||||
const char* bptr) const {
|
||||
// Internal keys are encoded as length-prefixed strings.
|
||||
Slice a = GetLengthPrefixedSlice(aptr);
|
||||
Slice b = GetLengthPrefixedSlice(bptr);
|
||||
@ -75,12 +70,9 @@ class MemTableIterator: public Iterator {
|
||||
void operator=(const MemTableIterator&);
|
||||
};
|
||||
|
||||
Iterator* MemTable::NewIterator() {
|
||||
return new MemTableIterator(&table_);
|
||||
}
|
||||
Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); }
|
||||
|
||||
void MemTable::Add(SequenceNumber s, ValueType type,
|
||||
const Slice& key,
|
||||
void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key,
|
||||
const Slice& value) {
|
||||
// Format of an entry is concatenation of:
|
||||
// key_size : varint32 of internal_key.size()
|
||||
@ -90,9 +82,9 @@ void MemTable::Add(SequenceNumber s, ValueType type,
|
||||
size_t key_size = key.size();
|
||||
size_t val_size = value.size();
|
||||
size_t internal_key_size = key_size + 8;
|
||||
const size_t encoded_len =
|
||||
VarintLength(internal_key_size) + internal_key_size +
|
||||
VarintLength(val_size) + val_size;
|
||||
const size_t encoded_len = VarintLength(internal_key_size) +
|
||||
internal_key_size + VarintLength(val_size) +
|
||||
val_size;
|
||||
char* buf = arena_.Allocate(encoded_len);
|
||||
char* p = EncodeVarint32(buf, internal_key_size);
|
||||
memcpy(p, key.data(), key_size);
|
||||
@ -123,8 +115,7 @@ bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
|
||||
uint32_t key_length;
|
||||
const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length);
|
||||
if (comparator_.comparator.user_comparator()->Compare(
|
||||
Slice(key_ptr, key_length - 8),
|
||||
key.user_key()) == 0) {
|
||||
Slice(key_ptr, key_length - 8), key.user_key()) == 0) {
|
||||
// Correct user key
|
||||
const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8);
|
||||
switch (static_cast<ValueType>(tag & 0xff)) {
|
||||
|
@ -6,9 +6,10 @@
|
||||
#define STORAGE_LEVELDB_DB_MEMTABLE_H_
|
||||
|
||||
#include <string>
|
||||
#include "leveldb/db.h"
|
||||
|
||||
#include "db/dbformat.h"
|
||||
#include "db/skiplist.h"
|
||||
#include "leveldb/db.h"
|
||||
#include "util/arena.h"
|
||||
|
||||
namespace leveldb {
|
||||
@ -49,8 +50,7 @@ class MemTable {
|
||||
// Add an entry into memtable that maps key to value at the
|
||||
// specified sequence number and with the specified type.
|
||||
// Typically value will be empty if type==kTypeDeletion.
|
||||
void Add(SequenceNumber seq, ValueType type,
|
||||
const Slice& key,
|
||||
void Add(SequenceNumber seq, ValueType type, const Slice& key,
|
||||
const Slice& value);
|
||||
|
||||
// If memtable contains a value for key, store it in *value and return true.
|
||||
|
@ -92,9 +92,7 @@ class RecoveryTest {
|
||||
return dbname_ + "/" + current;
|
||||
}
|
||||
|
||||
std::string LogName(uint64_t number) {
|
||||
return LogFileName(dbname_, number);
|
||||
}
|
||||
std::string LogName(uint64_t number) { return LogFileName(dbname_, number); }
|
||||
|
||||
size_t DeleteLogFiles() {
|
||||
// Linux allows unlinking open files, but Windows does not.
|
||||
@ -107,13 +105,9 @@ class RecoveryTest {
|
||||
return logs.size();
|
||||
}
|
||||
|
||||
void DeleteManifestFile() {
|
||||
ASSERT_OK(env_->DeleteFile(ManifestFileName()));
|
||||
}
|
||||
void DeleteManifestFile() { ASSERT_OK(env_->DeleteFile(ManifestFileName())); }
|
||||
|
||||
uint64_t FirstLogFile() {
|
||||
return GetFiles(kLogFile)[0];
|
||||
}
|
||||
uint64_t FirstLogFile() { return GetFiles(kLogFile)[0]; }
|
||||
|
||||
std::vector<uint64_t> GetFiles(FileType t) {
|
||||
std::vector<std::string> filenames;
|
||||
@ -129,13 +123,9 @@ class RecoveryTest {
|
||||
return result;
|
||||
}
|
||||
|
||||
int NumLogs() {
|
||||
return GetFiles(kLogFile).size();
|
||||
}
|
||||
int NumLogs() { return GetFiles(kLogFile).size(); }
|
||||
|
||||
int NumTables() {
|
||||
return GetFiles(kTableFile).size();
|
||||
}
|
||||
int NumTables() { return GetFiles(kTableFile).size(); }
|
||||
|
||||
uint64_t FileSize(const std::string& fname) {
|
||||
uint64_t result;
|
||||
@ -143,9 +133,7 @@ class RecoveryTest {
|
||||
return result;
|
||||
}
|
||||
|
||||
void CompactMemTable() {
|
||||
dbfull()->TEST_CompactMemTable();
|
||||
}
|
||||
void CompactMemTable() { dbfull()->TEST_CompactMemTable(); }
|
||||
|
||||
// Directly construct a log file that sets key to val.
|
||||
void MakeLogFile(uint64_t lognum, SequenceNumber seq, Slice key, Slice val) {
|
||||
@ -339,6 +327,4 @@ TEST(RecoveryTest, ManifestMissing) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
39
db/repair.cc
39
db/repair.cc
@ -84,9 +84,7 @@ class Repairer {
|
||||
"recovered %d files; %llu bytes. "
|
||||
"Some data may have been lost. "
|
||||
"****",
|
||||
dbname_.c_str(),
|
||||
static_cast<int>(tables_.size()),
|
||||
bytes);
|
||||
dbname_.c_str(), static_cast<int>(tables_.size()), bytes);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -152,8 +150,7 @@ class Repairer {
|
||||
Status status = ConvertLogToTable(logs_[i]);
|
||||
if (!status.ok()) {
|
||||
Log(options_.info_log, "Log #%llu: ignoring conversion error: %s",
|
||||
(unsigned long long) logs_[i],
|
||||
status.ToString().c_str());
|
||||
(unsigned long long)logs_[i], status.ToString().c_str());
|
||||
}
|
||||
ArchiveFile(logname);
|
||||
}
|
||||
@ -167,8 +164,7 @@ class Repairer {
|
||||
virtual void Corruption(size_t bytes, const Status& s) {
|
||||
// We print error messages for corruption, but continue repairing.
|
||||
Log(info_log, "Log #%llu: dropping %d bytes; %s",
|
||||
(unsigned long long) lognum,
|
||||
static_cast<int>(bytes),
|
||||
(unsigned long long)lognum, static_cast<int>(bytes),
|
||||
s.ToString().c_str());
|
||||
}
|
||||
};
|
||||
@ -202,8 +198,8 @@ class Repairer {
|
||||
int counter = 0;
|
||||
while (reader.ReadRecord(&record, &scratch)) {
|
||||
if (record.size() < 12) {
|
||||
reporter.Corruption(
|
||||
record.size(), Status::Corruption("log record too small"));
|
||||
reporter.Corruption(record.size(),
|
||||
Status::Corruption("log record too small"));
|
||||
continue;
|
||||
}
|
||||
WriteBatchInternal::SetContents(&batch, record);
|
||||
@ -212,8 +208,7 @@ class Repairer {
|
||||
counter += WriteBatchInternal::Count(&batch);
|
||||
} else {
|
||||
Log(options_.info_log, "Log #%llu: ignoring %s",
|
||||
(unsigned long long) log,
|
||||
status.ToString().c_str());
|
||||
(unsigned long long)log, status.ToString().c_str());
|
||||
status = Status::OK(); // Keep going with rest of file
|
||||
}
|
||||
}
|
||||
@ -234,9 +229,7 @@ class Repairer {
|
||||
}
|
||||
}
|
||||
Log(options_.info_log, "Log #%llu: %d ops saved to Table #%llu %s",
|
||||
(unsigned long long) log,
|
||||
counter,
|
||||
(unsigned long long) meta.number,
|
||||
(unsigned long long)log, counter, (unsigned long long)meta.number,
|
||||
status.ToString().c_str());
|
||||
return status;
|
||||
}
|
||||
@ -272,8 +265,7 @@ class Repairer {
|
||||
ArchiveFile(TableFileName(dbname_, number));
|
||||
ArchiveFile(SSTTableFileName(dbname_, number));
|
||||
Log(options_.info_log, "Table #%llu: dropped: %s",
|
||||
(unsigned long long) t.meta.number,
|
||||
status.ToString().c_str());
|
||||
(unsigned long long)t.meta.number, status.ToString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -287,8 +279,7 @@ class Repairer {
|
||||
Slice key = iter->key();
|
||||
if (!ParseInternalKey(key, &parsed)) {
|
||||
Log(options_.info_log, "Table #%llu: unparsable key %s",
|
||||
(unsigned long long) t.meta.number,
|
||||
EscapeString(key).c_str());
|
||||
(unsigned long long)t.meta.number, EscapeString(key).c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -307,9 +298,7 @@ class Repairer {
|
||||
}
|
||||
delete iter;
|
||||
Log(options_.info_log, "Table #%llu: %d entries %s",
|
||||
(unsigned long long) t.meta.number,
|
||||
counter,
|
||||
status.ToString().c_str());
|
||||
(unsigned long long)t.meta.number, counter, status.ToString().c_str());
|
||||
|
||||
if (status.ok()) {
|
||||
tables_.push_back(t);
|
||||
@ -395,8 +384,8 @@ class Repairer {
|
||||
for (size_t i = 0; i < tables_.size(); i++) {
|
||||
// TODO(opt): separate out into multiple levels
|
||||
const TableInfo& t = tables_[i];
|
||||
edit_.AddFile(0, t.meta.number, t.meta.file_size,
|
||||
t.meta.smallest, t.meta.largest);
|
||||
edit_.AddFile(0, t.meta.number, t.meta.file_size, t.meta.smallest,
|
||||
t.meta.largest);
|
||||
}
|
||||
|
||||
// fprintf(stderr, "NewDescriptor:\n%s\n", edit_.DebugString().c_str());
|
||||
@ -447,8 +436,8 @@ class Repairer {
|
||||
new_file.append("/");
|
||||
new_file.append((slash == nullptr) ? fname.c_str() : slash + 1);
|
||||
Status s = env_->RenameFile(fname, new_file);
|
||||
Log(options_.info_log, "Archiving %s: %s\n",
|
||||
fname.c_str(), s.ToString().c_str());
|
||||
Log(options_.info_log, "Archiving %s: %s\n", fname.c_str(),
|
||||
s.ToString().c_str());
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
@ -180,8 +180,8 @@ struct SkipList<Key, Comparator>::Node {
|
||||
};
|
||||
|
||||
template <typename Key, class Comparator>
|
||||
typename SkipList<Key, Comparator>::Node*
|
||||
SkipList<Key, Comparator>::NewNode(const Key& key, int height) {
|
||||
typename SkipList<Key, Comparator>::Node* SkipList<Key, Comparator>::NewNode(
|
||||
const Key& key, int height) {
|
||||
char* const node_memory = arena_->AllocateAligned(
|
||||
sizeof(Node) + sizeof(std::atomic<Node*>) * (height - 1));
|
||||
return new (node_memory) Node(key);
|
||||
|
@ -117,8 +117,7 @@ TEST(SkipTest, InsertAndLookup) {
|
||||
|
||||
// Compare against model iterator
|
||||
for (std::set<Key>::reverse_iterator model_iter = keys.rbegin();
|
||||
model_iter != keys.rend();
|
||||
++model_iter) {
|
||||
model_iter != keys.rend(); ++model_iter) {
|
||||
ASSERT_TRUE(iter.Valid());
|
||||
ASSERT_EQ(*model_iter, iter.key());
|
||||
iter.Prev();
|
||||
@ -165,7 +164,7 @@ class ConcurrentTest {
|
||||
}
|
||||
|
||||
static Key MakeKey(uint64_t k, uint64_t g) {
|
||||
assert(sizeof(Key) == sizeof(uint64_t));
|
||||
static_assert(sizeof(Key) == sizeof(uint64_t), "");
|
||||
assert(k <= K); // We sometimes pass K to seek to the end of the skiplist
|
||||
assert(g <= 0xffffffffu);
|
||||
return ((k << 40) | (g << 8) | (HashNumbers(k, g) & 0xff));
|
||||
@ -195,9 +194,7 @@ class ConcurrentTest {
|
||||
void Set(int k, int v) {
|
||||
generation[k].store(v, std::memory_order_release);
|
||||
}
|
||||
int Get(int k) {
|
||||
return generation[k].load(std::memory_order_acquire);
|
||||
}
|
||||
int Get(int k) { return generation[k].load(std::memory_order_acquire); }
|
||||
|
||||
State() {
|
||||
for (int k = 0; k < K; k++) {
|
||||
@ -255,11 +252,9 @@ class ConcurrentTest {
|
||||
// Note that generation 0 is never inserted, so it is ok if
|
||||
// <*,0,*> is missing.
|
||||
ASSERT_TRUE((gen(pos) == 0) ||
|
||||
(gen(pos) > static_cast<Key>(initial_state.Get(key(pos))))
|
||||
) << "key: " << key(pos)
|
||||
<< "; gen: " << gen(pos)
|
||||
<< "; initgen: "
|
||||
<< initial_state.Get(key(pos));
|
||||
(gen(pos) > static_cast<Key>(initial_state.Get(key(pos)))))
|
||||
<< "key: " << key(pos) << "; gen: " << gen(pos)
|
||||
<< "; initgen: " << initial_state.Get(key(pos));
|
||||
|
||||
// Advance to next key in the valid key space
|
||||
if (key(pos) < key(current)) {
|
||||
@ -305,17 +300,10 @@ class TestState {
|
||||
int seed_;
|
||||
std::atomic<bool> quit_flag_;
|
||||
|
||||
enum ReaderState {
|
||||
STARTING,
|
||||
RUNNING,
|
||||
DONE
|
||||
};
|
||||
enum ReaderState { STARTING, RUNNING, DONE };
|
||||
|
||||
explicit TestState(int s)
|
||||
: seed_(s),
|
||||
quit_flag_(false),
|
||||
state_(STARTING),
|
||||
state_cv_(&mu_) {}
|
||||
: seed_(s), quit_flag_(false), state_(STARTING), state_cv_(&mu_) {}
|
||||
|
||||
void Wait(ReaderState s) LOCKS_EXCLUDED(mu_) {
|
||||
mu_.Lock();
|
||||
@ -378,6 +366,4 @@ TEST(SkipTest, Concurrent5) { RunConcurrent(5); }
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -44,8 +44,14 @@ class SnapshotList {
|
||||
}
|
||||
|
||||
bool empty() const { return head_.next_ == &head_; }
|
||||
SnapshotImpl* oldest() const { assert(!empty()); return head_.next_; }
|
||||
SnapshotImpl* newest() const { assert(!empty()); return head_.prev_; }
|
||||
SnapshotImpl* oldest() const {
|
||||
assert(!empty());
|
||||
return head_.next_;
|
||||
}
|
||||
SnapshotImpl* newest() const {
|
||||
assert(!empty());
|
||||
return head_.prev_;
|
||||
}
|
||||
|
||||
// Creates a SnapshotImpl and appends it to the end of the list.
|
||||
SnapshotImpl* New(SequenceNumber sequence_number) {
|
||||
|
@ -29,18 +29,14 @@ static void UnrefEntry(void* arg1, void* arg2) {
|
||||
cache->Release(h);
|
||||
}
|
||||
|
||||
TableCache::TableCache(const std::string& dbname,
|
||||
const Options& options,
|
||||
TableCache::TableCache(const std::string& dbname, const Options& options,
|
||||
int entries)
|
||||
: env_(options.env),
|
||||
dbname_(dbname),
|
||||
options_(options),
|
||||
cache_(NewLRUCache(entries)) {
|
||||
}
|
||||
cache_(NewLRUCache(entries)) {}
|
||||
|
||||
TableCache::~TableCache() {
|
||||
delete cache_;
|
||||
}
|
||||
TableCache::~TableCache() { delete cache_; }
|
||||
|
||||
Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
|
||||
Cache::Handle** handle) {
|
||||
@ -80,8 +76,7 @@ Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
|
||||
}
|
||||
|
||||
Iterator* TableCache::NewIterator(const ReadOptions& options,
|
||||
uint64_t file_number,
|
||||
uint64_t file_size,
|
||||
uint64_t file_number, uint64_t file_size,
|
||||
Table** tableptr) {
|
||||
if (tableptr != nullptr) {
|
||||
*tableptr = nullptr;
|
||||
@ -102,17 +97,15 @@ Iterator* TableCache::NewIterator(const ReadOptions& options,
|
||||
return result;
|
||||
}
|
||||
|
||||
Status TableCache::Get(const ReadOptions& options,
|
||||
uint64_t file_number,
|
||||
uint64_t file_size,
|
||||
const Slice& k,
|
||||
void* arg,
|
||||
void (*saver)(void*, const Slice&, const Slice&)) {
|
||||
Status TableCache::Get(const ReadOptions& options, uint64_t file_number,
|
||||
uint64_t file_size, const Slice& k, void* arg,
|
||||
void (*handle_result)(void*, const Slice&,
|
||||
const Slice&)) {
|
||||
Cache::Handle* handle = nullptr;
|
||||
Status s = FindTable(file_number, file_size, &handle);
|
||||
if (s.ok()) {
|
||||
Table* t = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
|
||||
s = t->InternalGet(options, k, arg, saver);
|
||||
s = t->InternalGet(options, k, arg, handle_result);
|
||||
cache_->Release(handle);
|
||||
}
|
||||
return s;
|
||||
|
@ -7,8 +7,10 @@
|
||||
#ifndef STORAGE_LEVELDB_DB_TABLE_CACHE_H_
|
||||
#define STORAGE_LEVELDB_DB_TABLE_CACHE_H_
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "db/dbformat.h"
|
||||
#include "leveldb/cache.h"
|
||||
#include "leveldb/table.h"
|
||||
@ -30,18 +32,13 @@ class TableCache {
|
||||
// underlies the returned iterator. The returned "*tableptr" object is owned
|
||||
// by the cache and should not be deleted, and is valid for as long as the
|
||||
// returned iterator is live.
|
||||
Iterator* NewIterator(const ReadOptions& options,
|
||||
uint64_t file_number,
|
||||
uint64_t file_size,
|
||||
Table** tableptr = nullptr);
|
||||
Iterator* NewIterator(const ReadOptions& options, uint64_t file_number,
|
||||
uint64_t file_size, Table** tableptr = nullptr);
|
||||
|
||||
// If a seek to internal key "k" in specified file finds an entry,
|
||||
// call (*handle_result)(arg, found_key, found_value).
|
||||
Status Get(const ReadOptions& options,
|
||||
uint64_t file_number,
|
||||
uint64_t file_size,
|
||||
const Slice& k,
|
||||
void* arg,
|
||||
Status Get(const ReadOptions& options, uint64_t file_number,
|
||||
uint64_t file_size, const Slice& k, void* arg,
|
||||
void (*handle_result)(void*, const Slice&, const Slice&));
|
||||
|
||||
// Evict any entry for the specified file number
|
||||
|
@ -67,8 +67,7 @@ void VersionEdit::EncodeTo(std::string* dst) const {
|
||||
}
|
||||
|
||||
for (DeletedFileSet::const_iterator iter = deleted_files_.begin();
|
||||
iter != deleted_files_.end();
|
||||
++iter) {
|
||||
iter != deleted_files_.end(); ++iter) {
|
||||
PutVarint32(dst, kDeletedFile);
|
||||
PutVarint32(dst, iter->first); // level
|
||||
PutVarint64(dst, iter->second); // file number
|
||||
@ -97,8 +96,7 @@ static bool GetInternalKey(Slice* input, InternalKey* dst) {
|
||||
|
||||
static bool GetLevel(Slice* input, int* level) {
|
||||
uint32_t v;
|
||||
if (GetVarint32(input, &v) &&
|
||||
v < config::kNumLevels) {
|
||||
if (GetVarint32(input, &v) && v < config::kNumLevels) {
|
||||
*level = v;
|
||||
return true;
|
||||
} else {
|
||||
@ -163,8 +161,7 @@ Status VersionEdit::DecodeFrom(const Slice& src) {
|
||||
break;
|
||||
|
||||
case kCompactPointer:
|
||||
if (GetLevel(&input, &level) &&
|
||||
GetInternalKey(&input, &key)) {
|
||||
if (GetLevel(&input, &level) && GetInternalKey(&input, &key)) {
|
||||
compact_pointers_.push_back(std::make_pair(level, key));
|
||||
} else {
|
||||
msg = "compaction pointer";
|
||||
@ -172,8 +169,7 @@ Status VersionEdit::DecodeFrom(const Slice& src) {
|
||||
break;
|
||||
|
||||
case kDeletedFile:
|
||||
if (GetLevel(&input, &level) &&
|
||||
GetVarint64(&input, &number)) {
|
||||
if (GetLevel(&input, &level) && GetVarint64(&input, &number)) {
|
||||
deleted_files_.insert(std::make_pair(level, number));
|
||||
} else {
|
||||
msg = "deleted file";
|
||||
@ -181,8 +177,7 @@ Status VersionEdit::DecodeFrom(const Slice& src) {
|
||||
break;
|
||||
|
||||
case kNewFile:
|
||||
if (GetLevel(&input, &level) &&
|
||||
GetVarint64(&input, &f.number) &&
|
||||
if (GetLevel(&input, &level) && GetVarint64(&input, &f.number) &&
|
||||
GetVarint64(&input, &f.file_size) &&
|
||||
GetInternalKey(&input, &f.smallest) &&
|
||||
GetInternalKey(&input, &f.largest)) {
|
||||
@ -239,8 +234,7 @@ std::string VersionEdit::DebugString() const {
|
||||
r.append(compact_pointers_[i].second.DebugString());
|
||||
}
|
||||
for (DeletedFileSet::const_iterator iter = deleted_files_.begin();
|
||||
iter != deleted_files_.end();
|
||||
++iter) {
|
||||
iter != deleted_files_.end(); ++iter) {
|
||||
r.append("\n DeleteFile: ");
|
||||
AppendNumberTo(&r, iter->first);
|
||||
r.append(" ");
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "db/dbformat.h"
|
||||
|
||||
namespace leveldb {
|
||||
@ -59,10 +60,8 @@ class VersionEdit {
|
||||
// Add the specified file at the specified number.
|
||||
// REQUIRES: This version has not been saved (see VersionSet::SaveTo)
|
||||
// REQUIRES: "smallest" and "largest" are smallest and largest keys in file
|
||||
void AddFile(int level, uint64_t file,
|
||||
uint64_t file_size,
|
||||
const InternalKey& smallest,
|
||||
const InternalKey& largest) {
|
||||
void AddFile(int level, uint64_t file, uint64_t file_size,
|
||||
const InternalKey& smallest, const InternalKey& largest) {
|
||||
FileMetaData f;
|
||||
f.number = file;
|
||||
f.file_size = file_size;
|
||||
|
@ -41,6 +41,4 @@ TEST(VersionEditTest, EncodeDecode) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -4,8 +4,10 @@
|
||||
|
||||
#include "db/version_set.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "db/filename.h"
|
||||
#include "db/log_reader.h"
|
||||
#include "db/log_writer.h"
|
||||
@ -84,8 +86,7 @@ Version::~Version() {
|
||||
}
|
||||
|
||||
int FindFile(const InternalKeyComparator& icmp,
|
||||
const std::vector<FileMetaData*>& files,
|
||||
const Slice& key) {
|
||||
const std::vector<FileMetaData*>& files, const Slice& key) {
|
||||
uint32_t left = 0;
|
||||
uint32_t right = files.size();
|
||||
while (left < right) {
|
||||
@ -104,22 +105,21 @@ int FindFile(const InternalKeyComparator& icmp,
|
||||
return right;
|
||||
}
|
||||
|
||||
static bool AfterFile(const Comparator* ucmp,
|
||||
const Slice* user_key, const FileMetaData* f) {
|
||||
static bool AfterFile(const Comparator* ucmp, const Slice* user_key,
|
||||
const FileMetaData* f) {
|
||||
// null user_key occurs before all keys and is therefore never after *f
|
||||
return (user_key != nullptr &&
|
||||
ucmp->Compare(*user_key, f->largest.user_key()) > 0);
|
||||
}
|
||||
|
||||
static bool BeforeFile(const Comparator* ucmp,
|
||||
const Slice* user_key, const FileMetaData* f) {
|
||||
static bool BeforeFile(const Comparator* ucmp, const Slice* user_key,
|
||||
const FileMetaData* f) {
|
||||
// null user_key occurs after all keys and is therefore never before *f
|
||||
return (user_key != nullptr &&
|
||||
ucmp->Compare(*user_key, f->smallest.user_key()) < 0);
|
||||
}
|
||||
|
||||
bool SomeFileOverlapsRange(
|
||||
const InternalKeyComparator& icmp,
|
||||
bool SomeFileOverlapsRange(const InternalKeyComparator& icmp,
|
||||
bool disjoint_sorted_files,
|
||||
const std::vector<FileMetaData*>& files,
|
||||
const Slice* smallest_user_key,
|
||||
@ -143,7 +143,8 @@ bool SomeFileOverlapsRange(
|
||||
uint32_t index = 0;
|
||||
if (smallest_user_key != nullptr) {
|
||||
// Find the earliest possible internal key for smallest_user_key
|
||||
InternalKey small_key(*smallest_user_key, kMaxSequenceNumber,kValueTypeForSeek);
|
||||
InternalKey small_key(*smallest_user_key, kMaxSequenceNumber,
|
||||
kValueTypeForSeek);
|
||||
index = FindFile(icmp, files, small_key.Encode());
|
||||
}
|
||||
|
||||
@ -164,13 +165,9 @@ class Version::LevelFileNumIterator : public Iterator {
|
||||
public:
|
||||
LevelFileNumIterator(const InternalKeyComparator& icmp,
|
||||
const std::vector<FileMetaData*>* flist)
|
||||
: icmp_(icmp),
|
||||
flist_(flist),
|
||||
index_(flist->size()) { // Marks as invalid
|
||||
}
|
||||
virtual bool Valid() const {
|
||||
return index_ < flist_->size();
|
||||
: icmp_(icmp), flist_(flist), index_(flist->size()) { // Marks as invalid
|
||||
}
|
||||
virtual bool Valid() const { return index_ < flist_->size(); }
|
||||
virtual void Seek(const Slice& target) {
|
||||
index_ = FindFile(icmp_, *flist_, target);
|
||||
}
|
||||
@ -201,6 +198,7 @@ class Version::LevelFileNumIterator : public Iterator {
|
||||
return Slice(value_buf_, sizeof(value_buf_));
|
||||
}
|
||||
virtual Status status() const { return Status::OK(); }
|
||||
|
||||
private:
|
||||
const InternalKeyComparator icmp_;
|
||||
const std::vector<FileMetaData*>* const flist_;
|
||||
@ -210,16 +208,14 @@ class Version::LevelFileNumIterator : public Iterator {
|
||||
mutable char value_buf_[16];
|
||||
};
|
||||
|
||||
static Iterator* GetFileIterator(void* arg,
|
||||
const ReadOptions& options,
|
||||
static Iterator* GetFileIterator(void* arg, const ReadOptions& options,
|
||||
const Slice& file_value) {
|
||||
TableCache* cache = reinterpret_cast<TableCache*>(arg);
|
||||
if (file_value.size() != 16) {
|
||||
return NewErrorIterator(
|
||||
Status::Corruption("FileReader invoked with unexpected value"));
|
||||
} else {
|
||||
return cache->NewIterator(options,
|
||||
DecodeFixed64(file_value.data()),
|
||||
return cache->NewIterator(options, DecodeFixed64(file_value.data()),
|
||||
DecodeFixed64(file_value.data() + 8));
|
||||
}
|
||||
}
|
||||
@ -227,16 +223,15 @@ static Iterator* GetFileIterator(void* arg,
|
||||
Iterator* Version::NewConcatenatingIterator(const ReadOptions& options,
|
||||
int level) const {
|
||||
return NewTwoLevelIterator(
|
||||
new LevelFileNumIterator(vset_->icmp_, &files_[level]),
|
||||
&GetFileIterator, vset_->table_cache_, options);
|
||||
new LevelFileNumIterator(vset_->icmp_, &files_[level]), &GetFileIterator,
|
||||
vset_->table_cache_, options);
|
||||
}
|
||||
|
||||
void Version::AddIterators(const ReadOptions& options,
|
||||
std::vector<Iterator*>* iters) {
|
||||
// Merge all level zero files together since they may overlap
|
||||
for (size_t i = 0; i < files_[0].size(); i++) {
|
||||
iters->push_back(
|
||||
vset_->table_cache_->NewIterator(
|
||||
iters->push_back(vset_->table_cache_->NewIterator(
|
||||
options, files_[0][i]->number, files_[0][i]->file_size));
|
||||
}
|
||||
|
||||
@ -264,7 +259,7 @@ struct Saver {
|
||||
Slice user_key;
|
||||
std::string* value;
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
static void SaveValue(void* arg, const Slice& ikey, const Slice& v) {
|
||||
Saver* s = reinterpret_cast<Saver*>(arg);
|
||||
ParsedInternalKey parsed_key;
|
||||
@ -284,8 +279,7 @@ static bool NewestFirst(FileMetaData* a, FileMetaData* b) {
|
||||
return a->number > b->number;
|
||||
}
|
||||
|
||||
void Version::ForEachOverlapping(Slice user_key, Slice internal_key,
|
||||
void* arg,
|
||||
void Version::ForEachOverlapping(Slice user_key, Slice internal_key, void* arg,
|
||||
bool (*func)(void*, int, FileMetaData*)) {
|
||||
// TODO(sanjay): Change Version::Get() to use this function.
|
||||
const Comparator* ucmp = vset_->icmp_.user_comparator();
|
||||
@ -329,10 +323,8 @@ void Version::ForEachOverlapping(Slice user_key, Slice internal_key,
|
||||
}
|
||||
}
|
||||
|
||||
Status Version::Get(const ReadOptions& options,
|
||||
const LookupKey& k,
|
||||
std::string* value,
|
||||
GetStats* stats) {
|
||||
Status Version::Get(const ReadOptions& options, const LookupKey& k,
|
||||
std::string* value, GetStats* stats) {
|
||||
Slice ikey = k.internal_key();
|
||||
Slice user_key = k.user_key();
|
||||
const Comparator* ucmp = vset_->icmp_.user_comparator();
|
||||
@ -405,8 +397,8 @@ Status Version::Get(const ReadOptions& options,
|
||||
saver.ucmp = ucmp;
|
||||
saver.user_key = user_key;
|
||||
saver.value = value;
|
||||
s = vset_->table_cache_->Get(options, f->number, f->file_size,
|
||||
ikey, &saver, SaveValue);
|
||||
s = vset_->table_cache_->Get(options, f->number, f->file_size, ikey,
|
||||
&saver, SaveValue);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
@ -479,9 +471,7 @@ bool Version::RecordReadSample(Slice internal_key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Version::Ref() {
|
||||
++refs_;
|
||||
}
|
||||
void Version::Ref() { ++refs_; }
|
||||
|
||||
void Version::Unref() {
|
||||
assert(this != &vset_->dummy_versions_);
|
||||
@ -492,15 +482,13 @@ void Version::Unref() {
|
||||
}
|
||||
}
|
||||
|
||||
bool Version::OverlapInLevel(int level,
|
||||
const Slice* smallest_user_key,
|
||||
bool Version::OverlapInLevel(int level, const Slice* smallest_user_key,
|
||||
const Slice* largest_user_key) {
|
||||
return SomeFileOverlapsRange(vset_->icmp_, (level > 0), files_[level],
|
||||
smallest_user_key, largest_user_key);
|
||||
}
|
||||
|
||||
int Version::PickLevelForMemTableOutput(
|
||||
const Slice& smallest_user_key,
|
||||
int Version::PickLevelForMemTableOutput(const Slice& smallest_user_key,
|
||||
const Slice& largest_user_key) {
|
||||
int level = 0;
|
||||
if (!OverlapInLevel(0, &smallest_user_key, &largest_user_key)) {
|
||||
@ -528,9 +516,7 @@ int Version::PickLevelForMemTableOutput(
|
||||
}
|
||||
|
||||
// Store in "*inputs" all files in "level" that overlap [begin,end]
|
||||
void Version::GetOverlappingInputs(
|
||||
int level,
|
||||
const InternalKey* begin,
|
||||
void Version::GetOverlappingInputs(int level, const InternalKey* begin,
|
||||
const InternalKey* end,
|
||||
std::vector<FileMetaData*>* inputs) {
|
||||
assert(level >= 0);
|
||||
@ -561,8 +547,8 @@ void Version::GetOverlappingInputs(
|
||||
user_begin = file_start;
|
||||
inputs->clear();
|
||||
i = 0;
|
||||
} else if (end != nullptr && user_cmp->Compare(file_limit,
|
||||
user_end) > 0) {
|
||||
} else if (end != nullptr &&
|
||||
user_cmp->Compare(file_limit, user_end) > 0) {
|
||||
user_end = file_limit;
|
||||
inputs->clear();
|
||||
i = 0;
|
||||
@ -630,9 +616,7 @@ class VersionSet::Builder {
|
||||
|
||||
public:
|
||||
// Initialize a builder with the files from *base and other info from *vset
|
||||
Builder(VersionSet* vset, Version* base)
|
||||
: vset_(vset),
|
||||
base_(base) {
|
||||
Builder(VersionSet* vset, Version* base) : vset_(vset), base_(base) {
|
||||
base_->Ref();
|
||||
BySmallestKey cmp;
|
||||
cmp.internal_comparator = &vset_->icmp_;
|
||||
@ -646,8 +630,8 @@ class VersionSet::Builder {
|
||||
const FileSet* added = levels_[level].added_files;
|
||||
std::vector<FileMetaData*> to_unref;
|
||||
to_unref.reserve(added->size());
|
||||
for (FileSet::const_iterator it = added->begin();
|
||||
it != added->end(); ++it) {
|
||||
for (FileSet::const_iterator it = added->begin(); it != added->end();
|
||||
++it) {
|
||||
to_unref.push_back(*it);
|
||||
}
|
||||
delete added;
|
||||
@ -674,8 +658,7 @@ class VersionSet::Builder {
|
||||
// Delete files
|
||||
const VersionEdit::DeletedFileSet& del = edit->deleted_files_;
|
||||
for (VersionEdit::DeletedFileSet::const_iterator iter = del.begin();
|
||||
iter != del.end();
|
||||
++iter) {
|
||||
iter != del.end(); ++iter) {
|
||||
const int level = iter->first;
|
||||
const uint64_t number = iter->second;
|
||||
levels_[level].deleted_files.insert(number);
|
||||
@ -721,13 +704,11 @@ class VersionSet::Builder {
|
||||
const FileSet* added = levels_[level].added_files;
|
||||
v->files_[level].reserve(base_files.size() + added->size());
|
||||
for (FileSet::const_iterator added_iter = added->begin();
|
||||
added_iter != added->end();
|
||||
++added_iter) {
|
||||
added_iter != added->end(); ++added_iter) {
|
||||
// Add all smaller files listed in base_
|
||||
for (std::vector<FileMetaData*>::const_iterator bpos
|
||||
= std::upper_bound(base_iter, base_end, *added_iter, cmp);
|
||||
base_iter != bpos;
|
||||
++base_iter) {
|
||||
for (std::vector<FileMetaData*>::const_iterator bpos =
|
||||
std::upper_bound(base_iter, base_end, *added_iter, cmp);
|
||||
base_iter != bpos; ++base_iter) {
|
||||
MaybeAddFile(v, level, *base_iter);
|
||||
}
|
||||
|
||||
@ -773,8 +754,7 @@ class VersionSet::Builder {
|
||||
}
|
||||
};
|
||||
|
||||
VersionSet::VersionSet(const std::string& dbname,
|
||||
const Options* options,
|
||||
VersionSet::VersionSet(const std::string& dbname, const Options* options,
|
||||
TableCache* table_cache,
|
||||
const InternalKeyComparator* cmp)
|
||||
: env_(options->env),
|
||||
@ -927,8 +907,8 @@ Status VersionSet::Recover(bool *save_manifest) {
|
||||
s = env_->NewSequentialFile(dscname, &file);
|
||||
if (!s.ok()) {
|
||||
if (s.IsNotFound()) {
|
||||
return Status::Corruption(
|
||||
"CURRENT points to a non-existent file", s.ToString());
|
||||
return Status::Corruption("CURRENT points to a non-existent file",
|
||||
s.ToString());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -946,7 +926,8 @@ Status VersionSet::Recover(bool *save_manifest) {
|
||||
{
|
||||
LogReporter reporter;
|
||||
reporter.status = &s;
|
||||
log::Reader reader(file, &reporter, true/*checksum*/, 0/*initial_offset*/);
|
||||
log::Reader reader(file, &reporter, true /*checksum*/,
|
||||
0 /*initial_offset*/);
|
||||
Slice record;
|
||||
std::string scratch;
|
||||
while (reader.ReadRecord(&record, &scratch) && s.ok()) {
|
||||
@ -1142,16 +1123,12 @@ int VersionSet::NumLevelFiles(int level) const {
|
||||
|
||||
const char* VersionSet::LevelSummary(LevelSummaryStorage* scratch) const {
|
||||
// Update code if kNumLevels changes
|
||||
assert(config::kNumLevels == 7);
|
||||
static_assert(config::kNumLevels == 7, "");
|
||||
snprintf(scratch->buffer, sizeof(scratch->buffer),
|
||||
"files[ %d %d %d %d %d %d %d ]",
|
||||
int(current_->files_[0].size()),
|
||||
int(current_->files_[1].size()),
|
||||
int(current_->files_[2].size()),
|
||||
int(current_->files_[3].size()),
|
||||
int(current_->files_[4].size()),
|
||||
int(current_->files_[5].size()),
|
||||
int(current_->files_[6].size()));
|
||||
"files[ %d %d %d %d %d %d %d ]", int(current_->files_[0].size()),
|
||||
int(current_->files_[1].size()), int(current_->files_[2].size()),
|
||||
int(current_->files_[3].size()), int(current_->files_[4].size()),
|
||||
int(current_->files_[5].size()), int(current_->files_[6].size()));
|
||||
return scratch->buffer;
|
||||
}
|
||||
|
||||
@ -1188,8 +1165,7 @@ uint64_t VersionSet::ApproximateOffsetOf(Version* v, const InternalKey& ikey) {
|
||||
}
|
||||
|
||||
void VersionSet::AddLiveFiles(std::set<uint64_t>* live) {
|
||||
for (Version* v = dummy_versions_.next_;
|
||||
v != &dummy_versions_;
|
||||
for (Version* v = dummy_versions_.next_; v != &dummy_versions_;
|
||||
v = v->next_) {
|
||||
for (int level = 0; level < config::kNumLevels; level++) {
|
||||
const std::vector<FileMetaData*>& files = v->files_[level];
|
||||
@ -1227,8 +1203,7 @@ int64_t VersionSet::MaxNextLevelOverlappingBytes() {
|
||||
// *smallest, *largest.
|
||||
// REQUIRES: inputs is not empty
|
||||
void VersionSet::GetRange(const std::vector<FileMetaData*>& inputs,
|
||||
InternalKey* smallest,
|
||||
InternalKey* largest) {
|
||||
InternalKey* smallest, InternalKey* largest) {
|
||||
assert(!inputs.empty());
|
||||
smallest->Clear();
|
||||
largest->Clear();
|
||||
@ -1253,8 +1228,7 @@ void VersionSet::GetRange(const std::vector<FileMetaData*>& inputs,
|
||||
// REQUIRES: inputs is not empty
|
||||
void VersionSet::GetRange2(const std::vector<FileMetaData*>& inputs1,
|
||||
const std::vector<FileMetaData*>& inputs2,
|
||||
InternalKey* smallest,
|
||||
InternalKey* largest) {
|
||||
InternalKey* smallest, InternalKey* largest) {
|
||||
std::vector<FileMetaData*> all = inputs1;
|
||||
all.insert(all.end(), inputs2.begin(), inputs2.end());
|
||||
GetRange(all, smallest, largest);
|
||||
@ -1276,8 +1250,8 @@ Iterator* VersionSet::MakeInputIterator(Compaction* c) {
|
||||
if (c->level() + which == 0) {
|
||||
const std::vector<FileMetaData*>& files = c->inputs_[which];
|
||||
for (size_t i = 0; i < files.size(); i++) {
|
||||
list[num++] = table_cache_->NewIterator(
|
||||
options, files[i]->number, files[i]->file_size);
|
||||
list[num++] = table_cache_->NewIterator(options, files[i]->number,
|
||||
files[i]->file_size);
|
||||
}
|
||||
} else {
|
||||
// Create concatenating iterator for the files from this level
|
||||
@ -1433,7 +1407,8 @@ void VersionSet::SetupOtherInputs(Compaction* c) {
|
||||
AddBoundaryInputs(icmp_, current_->files_[level], &c->inputs_[0]);
|
||||
GetRange(c->inputs_[0], &smallest, &largest);
|
||||
|
||||
current_->GetOverlappingInputs(level+1, &smallest, &largest, &c->inputs_[1]);
|
||||
current_->GetOverlappingInputs(level + 1, &smallest, &largest,
|
||||
&c->inputs_[1]);
|
||||
|
||||
// Get entire range covered by compaction
|
||||
InternalKey all_start, all_limit;
|
||||
@ -1459,13 +1434,9 @@ void VersionSet::SetupOtherInputs(Compaction* c) {
|
||||
if (expanded1.size() == c->inputs_[1].size()) {
|
||||
Log(options_->info_log,
|
||||
"Expanding@%d %d+%d (%ld+%ld bytes) to %d+%d (%ld+%ld bytes)\n",
|
||||
level,
|
||||
int(c->inputs_[0].size()),
|
||||
int(c->inputs_[1].size()),
|
||||
long(inputs0_size), long(inputs1_size),
|
||||
int(expanded0.size()),
|
||||
int(expanded1.size()),
|
||||
long(expanded0_size), long(inputs1_size));
|
||||
level, int(c->inputs_[0].size()), int(c->inputs_[1].size()),
|
||||
long(inputs0_size), long(inputs1_size), int(expanded0.size()),
|
||||
int(expanded1.size()), long(expanded0_size), long(inputs1_size));
|
||||
smallest = new_start;
|
||||
largest = new_limit;
|
||||
c->inputs_[0] = expanded0;
|
||||
@ -1490,9 +1461,7 @@ void VersionSet::SetupOtherInputs(Compaction* c) {
|
||||
c->edit_.SetCompactPointer(level, largest);
|
||||
}
|
||||
|
||||
Compaction* VersionSet::CompactRange(
|
||||
int level,
|
||||
const InternalKey* begin,
|
||||
Compaction* VersionSet::CompactRange(int level, const InternalKey* begin,
|
||||
const InternalKey* end) {
|
||||
std::vector<FileMetaData*> inputs;
|
||||
current_->GetOverlappingInputs(level, begin, end, &inputs);
|
||||
@ -1588,7 +1557,8 @@ bool Compaction::ShouldStopBefore(const Slice& internal_key) {
|
||||
const InternalKeyComparator* icmp = &vset->icmp_;
|
||||
while (grandparent_index_ < grandparents_.size() &&
|
||||
icmp->Compare(internal_key,
|
||||
grandparents_[grandparent_index_]->largest.Encode()) > 0) {
|
||||
grandparents_[grandparent_index_]->largest.Encode()) >
|
||||
0) {
|
||||
if (seen_key_) {
|
||||
overlapped_bytes_ += grandparents_[grandparent_index_]->file_size;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "db/dbformat.h"
|
||||
#include "db/version_edit.h"
|
||||
#include "port/port.h"
|
||||
@ -25,7 +26,9 @@
|
||||
|
||||
namespace leveldb {
|
||||
|
||||
namespace log { class Writer; }
|
||||
namespace log {
|
||||
class Writer;
|
||||
}
|
||||
|
||||
class Compaction;
|
||||
class Iterator;
|
||||
@ -40,8 +43,7 @@ class WritableFile;
|
||||
// Return files.size() if there is no such file.
|
||||
// REQUIRES: "files" contains a sorted list of non-overlapping files.
|
||||
int FindFile(const InternalKeyComparator& icmp,
|
||||
const std::vector<FileMetaData*>& files,
|
||||
const Slice& key);
|
||||
const std::vector<FileMetaData*>& files, const Slice& key);
|
||||
|
||||
// Returns true iff some file in "files" overlaps the user key range
|
||||
// [*smallest,*largest].
|
||||
@ -98,8 +100,7 @@ class Version {
|
||||
// some part of [*smallest_user_key,*largest_user_key].
|
||||
// smallest_user_key==nullptr represents a key smaller than all the DB's keys.
|
||||
// largest_user_key==nullptr represents a key largest than all the DB's keys.
|
||||
bool OverlapInLevel(int level,
|
||||
const Slice* smallest_user_key,
|
||||
bool OverlapInLevel(int level, const Slice* smallest_user_key,
|
||||
const Slice* largest_user_key);
|
||||
|
||||
// Return the level at which we should place a new memtable compaction
|
||||
@ -124,8 +125,7 @@ class Version {
|
||||
// false, makes no more calls.
|
||||
//
|
||||
// REQUIRES: user portion of internal_key == user_key.
|
||||
void ForEachOverlapping(Slice user_key, Slice internal_key,
|
||||
void* arg,
|
||||
void ForEachOverlapping(Slice user_key, Slice internal_key, void* arg,
|
||||
bool (*func)(void*, int, FileMetaData*));
|
||||
|
||||
VersionSet* vset_; // VersionSet to which this Version belongs
|
||||
@ -147,12 +147,14 @@ class Version {
|
||||
int compaction_level_;
|
||||
|
||||
explicit Version(VersionSet* vset)
|
||||
: vset_(vset), next_(this), prev_(this), refs_(0),
|
||||
: vset_(vset),
|
||||
next_(this),
|
||||
prev_(this),
|
||||
refs_(0),
|
||||
file_to_compact_(nullptr),
|
||||
file_to_compact_level_(-1),
|
||||
compaction_score_(-1),
|
||||
compaction_level_(-1) {
|
||||
}
|
||||
compaction_level_(-1) {}
|
||||
|
||||
~Version();
|
||||
|
||||
@ -163,10 +165,8 @@ class Version {
|
||||
|
||||
class VersionSet {
|
||||
public:
|
||||
VersionSet(const std::string& dbname,
|
||||
const Options* options,
|
||||
TableCache* table_cache,
|
||||
const InternalKeyComparator*);
|
||||
VersionSet(const std::string& dbname, const Options* options,
|
||||
TableCache* table_cache, const InternalKeyComparator*);
|
||||
~VersionSet();
|
||||
|
||||
// Apply *edit to the current version to form a new descriptor that
|
||||
@ -233,9 +233,7 @@ class VersionSet {
|
||||
// the specified level. Returns nullptr if there is nothing in that
|
||||
// level that overlaps the specified range. Caller should delete
|
||||
// the result.
|
||||
Compaction* CompactRange(
|
||||
int level,
|
||||
const InternalKey* begin,
|
||||
Compaction* CompactRange(int level, const InternalKey* begin,
|
||||
const InternalKey* end);
|
||||
|
||||
// Return the maximum overlapping data (in bytes) at next level for any
|
||||
@ -277,14 +275,12 @@ class VersionSet {
|
||||
|
||||
void Finalize(Version* v);
|
||||
|
||||
void GetRange(const std::vector<FileMetaData*>& inputs,
|
||||
InternalKey* smallest,
|
||||
void GetRange(const std::vector<FileMetaData*>& inputs, InternalKey* smallest,
|
||||
InternalKey* largest);
|
||||
|
||||
void GetRange2(const std::vector<FileMetaData*>& inputs1,
|
||||
const std::vector<FileMetaData*>& inputs2,
|
||||
InternalKey* smallest,
|
||||
InternalKey* largest);
|
||||
InternalKey* smallest, InternalKey* largest);
|
||||
|
||||
void SetupOtherInputs(Compaction* c);
|
||||
|
||||
|
@ -86,7 +86,6 @@ TEST(FindFileTest, Single) {
|
||||
ASSERT_TRUE(Overlaps(nullptr, nullptr));
|
||||
}
|
||||
|
||||
|
||||
TEST(FindFileTest, Multiple) {
|
||||
Add("150", "200");
|
||||
Add("200", "250");
|
||||
|
@ -15,10 +15,10 @@
|
||||
|
||||
#include "leveldb/write_batch.h"
|
||||
|
||||
#include "leveldb/db.h"
|
||||
#include "db/dbformat.h"
|
||||
#include "db/memtable.h"
|
||||
#include "db/write_batch_internal.h"
|
||||
#include "leveldb/db.h"
|
||||
#include "util/coding.h"
|
||||
|
||||
namespace leveldb {
|
||||
@ -26,9 +26,7 @@ namespace leveldb {
|
||||
// WriteBatch header has an 8-byte sequence number followed by a 4-byte count.
|
||||
static const size_t kHeader = 12;
|
||||
|
||||
WriteBatch::WriteBatch() {
|
||||
Clear();
|
||||
}
|
||||
WriteBatch::WriteBatch() { Clear(); }
|
||||
|
||||
WriteBatch::~WriteBatch() {}
|
||||
|
||||
@ -39,9 +37,7 @@ void WriteBatch::Clear() {
|
||||
rep_.resize(kHeader);
|
||||
}
|
||||
|
||||
size_t WriteBatch::ApproximateSize() const {
|
||||
return rep_.size();
|
||||
}
|
||||
size_t WriteBatch::ApproximateSize() const { return rep_.size(); }
|
||||
|
||||
Status WriteBatch::Iterate(Handler* handler) const {
|
||||
Slice input(rep_);
|
||||
@ -133,8 +129,7 @@ class MemTableInserter : public WriteBatch::Handler {
|
||||
};
|
||||
} // namespace
|
||||
|
||||
Status WriteBatchInternal::InsertInto(const WriteBatch* b,
|
||||
MemTable* memtable) {
|
||||
Status WriteBatchInternal::InsertInto(const WriteBatch* b, MemTable* memtable) {
|
||||
MemTableInserter inserter;
|
||||
inserter.sequence_ = WriteBatchInternal::Sequence(b);
|
||||
inserter.mem_ = memtable;
|
||||
|
@ -29,13 +29,9 @@ class WriteBatchInternal {
|
||||
// this batch.
|
||||
static void SetSequence(WriteBatch* batch, SequenceNumber seq);
|
||||
|
||||
static Slice Contents(const WriteBatch* batch) {
|
||||
return Slice(batch->rep_);
|
||||
}
|
||||
static Slice Contents(const WriteBatch* batch) { return Slice(batch->rep_); }
|
||||
|
||||
static size_t ByteSize(const WriteBatch* batch) {
|
||||
return batch->rep_.size();
|
||||
}
|
||||
static size_t ByteSize(const WriteBatch* batch) { return batch->rep_.size(); }
|
||||
|
||||
static void SetContents(WriteBatch* batch, const Slice& contents);
|
||||
|
||||
@ -46,5 +42,4 @@ class WriteBatchInternal {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
|
||||
#endif // STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_
|
||||
|
@ -68,7 +68,8 @@ TEST(WriteBatchTest, Multiple) {
|
||||
WriteBatchInternal::SetSequence(&batch, 100);
|
||||
ASSERT_EQ(100, WriteBatchInternal::Sequence(&batch));
|
||||
ASSERT_EQ(3, WriteBatchInternal::Count(&batch));
|
||||
ASSERT_EQ("Put(baz, boo)@102"
|
||||
ASSERT_EQ(
|
||||
"Put(baz, boo)@102"
|
||||
"Delete(box)@101"
|
||||
"Put(foo, bar)@100",
|
||||
PrintContents(&batch));
|
||||
@ -82,7 +83,8 @@ TEST(WriteBatchTest, Corruption) {
|
||||
Slice contents = WriteBatchInternal::Contents(&batch);
|
||||
WriteBatchInternal::SetContents(&batch,
|
||||
Slice(contents.data(), contents.size() - 1));
|
||||
ASSERT_EQ("Put(foo, bar)@200"
|
||||
ASSERT_EQ(
|
||||
"Put(foo, bar)@200"
|
||||
"ParseError()",
|
||||
PrintContents(&batch));
|
||||
}
|
||||
@ -92,21 +94,21 @@ TEST(WriteBatchTest, Append) {
|
||||
WriteBatchInternal::SetSequence(&b1, 200);
|
||||
WriteBatchInternal::SetSequence(&b2, 300);
|
||||
b1.Append(b2);
|
||||
ASSERT_EQ("",
|
||||
PrintContents(&b1));
|
||||
ASSERT_EQ("", PrintContents(&b1));
|
||||
b2.Put("a", "va");
|
||||
b1.Append(b2);
|
||||
ASSERT_EQ("Put(a, va)@200",
|
||||
PrintContents(&b1));
|
||||
ASSERT_EQ("Put(a, va)@200", PrintContents(&b1));
|
||||
b2.Clear();
|
||||
b2.Put("b", "vb");
|
||||
b1.Append(b2);
|
||||
ASSERT_EQ("Put(a, va)@200"
|
||||
ASSERT_EQ(
|
||||
"Put(a, va)@200"
|
||||
"Put(b, vb)@201",
|
||||
PrintContents(&b1));
|
||||
b2.Delete("foo");
|
||||
b1.Append(b2);
|
||||
ASSERT_EQ("Put(a, va)@200"
|
||||
ASSERT_EQ(
|
||||
"Put(a, va)@200"
|
||||
"Put(b, vb)@202"
|
||||
"Put(b, vb)@201"
|
||||
"Delete(foo)@203",
|
||||
@ -132,6 +134,4 @@ TEST(WriteBatchTest, ApproximateSize) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -2,9 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "util/histogram.h"
|
||||
#include "util/random.h"
|
||||
#include "util/testutil.h"
|
||||
@ -38,8 +39,7 @@ static const char* FLAGS_benchmarks =
|
||||
"fillrand100K,"
|
||||
"fillseq100K,"
|
||||
"readseq,"
|
||||
"readrand100K,"
|
||||
;
|
||||
"readrand100K,";
|
||||
|
||||
// Number of key/values to place in database
|
||||
static int FLAGS_num = 1000000;
|
||||
@ -78,8 +78,7 @@ static bool FLAGS_WAL_enabled = true;
|
||||
// Use the db with the following name.
|
||||
static const char* FLAGS_db = nullptr;
|
||||
|
||||
inline
|
||||
static void ExecErrorCheck(int status, char *err_msg) {
|
||||
inline static void ExecErrorCheck(int status, char* err_msg) {
|
||||
if (status != SQLITE_OK) {
|
||||
fprintf(stderr, "SQL error: %s\n", err_msg);
|
||||
sqlite3_free(err_msg);
|
||||
@ -87,24 +86,21 @@ static void ExecErrorCheck(int status, char *err_msg) {
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
static void StepErrorCheck(int status) {
|
||||
inline static void StepErrorCheck(int status) {
|
||||
if (status != SQLITE_DONE) {
|
||||
fprintf(stderr, "SQL step error: status = %d\n", status);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
static void ErrorCheck(int status) {
|
||||
inline static void ErrorCheck(int status) {
|
||||
if (status != SQLITE_OK) {
|
||||
fprintf(stderr, "sqlite3 error: status = %d\n", status);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
static void WalCheckpoint(sqlite3* db_) {
|
||||
inline static void WalCheckpoint(sqlite3* db_) {
|
||||
// Flush all writes to disk
|
||||
if (FLAGS_WAL_enabled) {
|
||||
sqlite3_wal_checkpoint_v2(db_, nullptr, SQLITE_CHECKPOINT_FULL, nullptr,
|
||||
@ -186,17 +182,17 @@ class Benchmark {
|
||||
fprintf(stdout, "Values: %d bytes each\n", FLAGS_value_size);
|
||||
fprintf(stdout, "Entries: %d\n", num_);
|
||||
fprintf(stdout, "RawSize: %.1f MB (estimated)\n",
|
||||
((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_)
|
||||
/ 1048576.0));
|
||||
((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_) /
|
||||
1048576.0));
|
||||
PrintWarnings();
|
||||
fprintf(stdout, "------------------------------------------------\n");
|
||||
}
|
||||
|
||||
void PrintWarnings() {
|
||||
#if defined(__GNUC__) && !defined(__OPTIMIZE__)
|
||||
fprintf(stdout,
|
||||
"WARNING: Optimization is disabled: benchmarks unnecessarily slow\n"
|
||||
);
|
||||
fprintf(
|
||||
stdout,
|
||||
"WARNING: Optimization is disabled: benchmarks unnecessarily slow\n");
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
fprintf(stdout,
|
||||
@ -262,13 +258,20 @@ class Benchmark {
|
||||
|
||||
done_++;
|
||||
if (done_ >= next_report_) {
|
||||
if (next_report_ < 1000) next_report_ += 100;
|
||||
else if (next_report_ < 5000) next_report_ += 500;
|
||||
else if (next_report_ < 10000) next_report_ += 1000;
|
||||
else if (next_report_ < 50000) next_report_ += 5000;
|
||||
else if (next_report_ < 100000) next_report_ += 10000;
|
||||
else if (next_report_ < 500000) next_report_ += 50000;
|
||||
else next_report_ += 100000;
|
||||
if (next_report_ < 1000)
|
||||
next_report_ += 100;
|
||||
else if (next_report_ < 5000)
|
||||
next_report_ += 500;
|
||||
else if (next_report_ < 10000)
|
||||
next_report_ += 1000;
|
||||
else if (next_report_ < 50000)
|
||||
next_report_ += 5000;
|
||||
else if (next_report_ < 100000)
|
||||
next_report_ += 10000;
|
||||
else if (next_report_ < 500000)
|
||||
next_report_ += 50000;
|
||||
else
|
||||
next_report_ += 100000;
|
||||
fprintf(stderr, "... finished %d ops%30s\r", done_, "");
|
||||
fflush(stderr);
|
||||
}
|
||||
@ -292,10 +295,8 @@ class Benchmark {
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n",
|
||||
name.ToString().c_str(),
|
||||
(finish - start_) * 1e6 / done_,
|
||||
(message_.empty() ? "" : " "),
|
||||
fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", name.ToString().c_str(),
|
||||
(finish - start_) * 1e6 / done_, (message_.empty() ? "" : " "),
|
||||
message_.c_str());
|
||||
if (FLAGS_histogram) {
|
||||
fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str());
|
||||
@ -304,14 +305,8 @@ class Benchmark {
|
||||
}
|
||||
|
||||
public:
|
||||
enum Order {
|
||||
SEQUENTIAL,
|
||||
RANDOM
|
||||
};
|
||||
enum DBState {
|
||||
FRESH,
|
||||
EXISTING
|
||||
};
|
||||
enum Order { SEQUENTIAL, RANDOM };
|
||||
enum DBState { FRESH, EXISTING };
|
||||
|
||||
Benchmark()
|
||||
: db_(nullptr),
|
||||
@ -426,10 +421,8 @@ class Benchmark {
|
||||
// Open database
|
||||
std::string tmp_dir;
|
||||
Env::Default()->GetTestDirectory(&tmp_dir);
|
||||
snprintf(file_name, sizeof(file_name),
|
||||
"%s/dbbench_sqlite3-%d.db",
|
||||
tmp_dir.c_str(),
|
||||
db_num_);
|
||||
snprintf(file_name, sizeof(file_name), "%s/dbbench_sqlite3-%d.db",
|
||||
tmp_dir.c_str(), db_num_);
|
||||
status = sqlite3_open(file_name, &db_);
|
||||
if (status) {
|
||||
fprintf(stderr, "open error: %s\n", sqlite3_errmsg(db_));
|
||||
@ -460,8 +453,8 @@ class Benchmark {
|
||||
std::string WAL_checkpoint = "PRAGMA wal_autocheckpoint = 4096";
|
||||
status = sqlite3_exec(db_, WAL_stmt.c_str(), nullptr, nullptr, &err_msg);
|
||||
ExecErrorCheck(status, err_msg);
|
||||
status = sqlite3_exec(db_, WAL_checkpoint.c_str(), nullptr, nullptr,
|
||||
&err_msg);
|
||||
status =
|
||||
sqlite3_exec(db_, WAL_checkpoint.c_str(), nullptr, nullptr, &err_msg);
|
||||
ExecErrorCheck(status, err_msg);
|
||||
}
|
||||
|
||||
@ -472,14 +465,14 @@ class Benchmark {
|
||||
std::string stmt_array[] = {locking_stmt, create_stmt};
|
||||
int stmt_array_length = sizeof(stmt_array) / sizeof(std::string);
|
||||
for (int i = 0; i < stmt_array_length; i++) {
|
||||
status = sqlite3_exec(db_, stmt_array[i].c_str(), nullptr, nullptr,
|
||||
&err_msg);
|
||||
status =
|
||||
sqlite3_exec(db_, stmt_array[i].c_str(), nullptr, nullptr, &err_msg);
|
||||
ExecErrorCheck(status, err_msg);
|
||||
}
|
||||
}
|
||||
|
||||
void Write(bool write_sync, Order order, DBState state,
|
||||
int num_entries, int value_size, int entries_per_batch) {
|
||||
void Write(bool write_sync, Order order, DBState state, int num_entries,
|
||||
int value_size, int entries_per_batch) {
|
||||
// Create new database if state == FRESH
|
||||
if (state == FRESH) {
|
||||
if (FLAGS_use_existing_db) {
|
||||
@ -507,20 +500,20 @@ class Benchmark {
|
||||
std::string end_trans_str = "END TRANSACTION;";
|
||||
|
||||
// Check for synchronous flag in options
|
||||
std::string sync_stmt = (write_sync) ? "PRAGMA synchronous = FULL" :
|
||||
"PRAGMA synchronous = OFF";
|
||||
std::string sync_stmt =
|
||||
(write_sync) ? "PRAGMA synchronous = FULL" : "PRAGMA synchronous = OFF";
|
||||
status = sqlite3_exec(db_, sync_stmt.c_str(), nullptr, nullptr, &err_msg);
|
||||
ExecErrorCheck(status, err_msg);
|
||||
|
||||
// Preparing sqlite3 statements
|
||||
status = sqlite3_prepare_v2(db_, replace_str.c_str(), -1,
|
||||
&replace_stmt, nullptr);
|
||||
status = sqlite3_prepare_v2(db_, replace_str.c_str(), -1, &replace_stmt,
|
||||
nullptr);
|
||||
ErrorCheck(status);
|
||||
status = sqlite3_prepare_v2(db_, begin_trans_str.c_str(), -1,
|
||||
&begin_trans_stmt, nullptr);
|
||||
ErrorCheck(status);
|
||||
status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1,
|
||||
&end_trans_stmt, nullptr);
|
||||
status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1, &end_trans_stmt,
|
||||
nullptr);
|
||||
ErrorCheck(status);
|
||||
|
||||
bool transaction = (entries_per_batch > 1);
|
||||
@ -538,16 +531,16 @@ class Benchmark {
|
||||
const char* value = gen_.Generate(value_size).data();
|
||||
|
||||
// Create values for key-value pair
|
||||
const int k = (order == SEQUENTIAL) ? i + j :
|
||||
(rand_.Next() % num_entries);
|
||||
const int k =
|
||||
(order == SEQUENTIAL) ? i + j : (rand_.Next() % num_entries);
|
||||
char key[100];
|
||||
snprintf(key, sizeof(key), "%016d", k);
|
||||
|
||||
// Bind KV values into replace_stmt
|
||||
status = sqlite3_bind_blob(replace_stmt, 1, key, 16, SQLITE_STATIC);
|
||||
ErrorCheck(status);
|
||||
status = sqlite3_bind_blob(replace_stmt, 2, value,
|
||||
value_size, SQLITE_STATIC);
|
||||
status = sqlite3_bind_blob(replace_stmt, 2, value, value_size,
|
||||
SQLITE_STATIC);
|
||||
ErrorCheck(status);
|
||||
|
||||
// Execute replace_stmt
|
||||
@ -593,8 +586,8 @@ class Benchmark {
|
||||
status = sqlite3_prepare_v2(db_, begin_trans_str.c_str(), -1,
|
||||
&begin_trans_stmt, nullptr);
|
||||
ErrorCheck(status);
|
||||
status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1,
|
||||
&end_trans_stmt, nullptr);
|
||||
status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1, &end_trans_stmt,
|
||||
nullptr);
|
||||
ErrorCheck(status);
|
||||
status = sqlite3_prepare_v2(db_, read_str.c_str(), -1, &read_stmt, nullptr);
|
||||
ErrorCheck(status);
|
||||
@ -621,7 +614,8 @@ class Benchmark {
|
||||
ErrorCheck(status);
|
||||
|
||||
// Execute read statement
|
||||
while ((status = sqlite3_step(read_stmt)) == SQLITE_ROW) {}
|
||||
while ((status = sqlite3_step(read_stmt)) == SQLITE_ROW) {
|
||||
}
|
||||
StepErrorCheck(status);
|
||||
|
||||
// Reset SQLite statement for another use
|
||||
@ -664,7 +658,6 @@ class Benchmark {
|
||||
status = sqlite3_finalize(pStmt);
|
||||
ErrorCheck(status);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace leveldb
|
||||
|
@ -2,9 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include <kcpolydb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <kcpolydb.h>
|
||||
|
||||
#include "util/histogram.h"
|
||||
#include "util/random.h"
|
||||
#include "util/testutil.h"
|
||||
@ -34,8 +35,7 @@ static const char* FLAGS_benchmarks =
|
||||
"fillrand100K,"
|
||||
"fillseq100K,"
|
||||
"readseq100K,"
|
||||
"readrand100K,"
|
||||
;
|
||||
"readrand100K,";
|
||||
|
||||
// Number of key/values to place in database
|
||||
static int FLAGS_num = 1000000;
|
||||
@ -71,9 +71,7 @@ static bool FLAGS_compression = true;
|
||||
// Use the db with the following name.
|
||||
static const char* FLAGS_db = nullptr;
|
||||
|
||||
inline
|
||||
static void DBSynchronize(kyotocabinet::TreeDB* db_)
|
||||
{
|
||||
inline static void DBSynchronize(kyotocabinet::TreeDB* db_) {
|
||||
// Synchronize will flush writes to disk
|
||||
if (!db_->synchronize()) {
|
||||
fprintf(stderr, "synchronize error: %s\n", db_->error().name());
|
||||
@ -157,20 +155,20 @@ class Benchmark {
|
||||
static_cast<int>(FLAGS_value_size * FLAGS_compression_ratio + 0.5));
|
||||
fprintf(stdout, "Entries: %d\n", num_);
|
||||
fprintf(stdout, "RawSize: %.1f MB (estimated)\n",
|
||||
((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_)
|
||||
/ 1048576.0));
|
||||
((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_) /
|
||||
1048576.0));
|
||||
fprintf(stdout, "FileSize: %.1f MB (estimated)\n",
|
||||
(((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_)
|
||||
/ 1048576.0));
|
||||
(((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_) /
|
||||
1048576.0));
|
||||
PrintWarnings();
|
||||
fprintf(stdout, "------------------------------------------------\n");
|
||||
}
|
||||
|
||||
void PrintWarnings() {
|
||||
#if defined(__GNUC__) && !defined(__OPTIMIZE__)
|
||||
fprintf(stdout,
|
||||
"WARNING: Optimization is disabled: benchmarks unnecessarily slow\n"
|
||||
);
|
||||
fprintf(
|
||||
stdout,
|
||||
"WARNING: Optimization is disabled: benchmarks unnecessarily slow\n");
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
fprintf(stdout,
|
||||
@ -237,13 +235,20 @@ class Benchmark {
|
||||
|
||||
done_++;
|
||||
if (done_ >= next_report_) {
|
||||
if (next_report_ < 1000) next_report_ += 100;
|
||||
else if (next_report_ < 5000) next_report_ += 500;
|
||||
else if (next_report_ < 10000) next_report_ += 1000;
|
||||
else if (next_report_ < 50000) next_report_ += 5000;
|
||||
else if (next_report_ < 100000) next_report_ += 10000;
|
||||
else if (next_report_ < 500000) next_report_ += 50000;
|
||||
else next_report_ += 100000;
|
||||
if (next_report_ < 1000)
|
||||
next_report_ += 100;
|
||||
else if (next_report_ < 5000)
|
||||
next_report_ += 500;
|
||||
else if (next_report_ < 10000)
|
||||
next_report_ += 1000;
|
||||
else if (next_report_ < 50000)
|
||||
next_report_ += 5000;
|
||||
else if (next_report_ < 100000)
|
||||
next_report_ += 10000;
|
||||
else if (next_report_ < 500000)
|
||||
next_report_ += 50000;
|
||||
else
|
||||
next_report_ += 100000;
|
||||
fprintf(stderr, "... finished %d ops%30s\r", done_, "");
|
||||
fflush(stderr);
|
||||
}
|
||||
@ -267,10 +272,8 @@ class Benchmark {
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n",
|
||||
name.ToString().c_str(),
|
||||
(finish - start_) * 1e6 / done_,
|
||||
(message_.empty() ? "" : " "),
|
||||
fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", name.ToString().c_str(),
|
||||
(finish - start_) * 1e6 / done_, (message_.empty() ? "" : " "),
|
||||
message_.c_str());
|
||||
if (FLAGS_histogram) {
|
||||
fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str());
|
||||
@ -279,14 +282,8 @@ class Benchmark {
|
||||
}
|
||||
|
||||
public:
|
||||
enum Order {
|
||||
SEQUENTIAL,
|
||||
RANDOM
|
||||
};
|
||||
enum DBState {
|
||||
FRESH,
|
||||
EXISTING
|
||||
};
|
||||
enum Order { SEQUENTIAL, RANDOM };
|
||||
enum DBState { FRESH, EXISTING };
|
||||
|
||||
Benchmark()
|
||||
: db_(nullptr),
|
||||
@ -395,16 +392,14 @@ class Benchmark {
|
||||
db_num_++;
|
||||
std::string test_dir;
|
||||
Env::Default()->GetTestDirectory(&test_dir);
|
||||
snprintf(file_name, sizeof(file_name),
|
||||
"%s/dbbench_polyDB-%d.kct",
|
||||
test_dir.c_str(),
|
||||
db_num_);
|
||||
snprintf(file_name, sizeof(file_name), "%s/dbbench_polyDB-%d.kct",
|
||||
test_dir.c_str(), db_num_);
|
||||
|
||||
// Create tuning options and open the database
|
||||
int open_options = kyotocabinet::PolyDB::OWRITER |
|
||||
kyotocabinet::PolyDB::OCREATE;
|
||||
int tune_options = kyotocabinet::TreeDB::TSMALL |
|
||||
kyotocabinet::TreeDB::TLINEAR;
|
||||
int open_options =
|
||||
kyotocabinet::PolyDB::OWRITER | kyotocabinet::PolyDB::OCREATE;
|
||||
int tune_options =
|
||||
kyotocabinet::TreeDB::TSMALL | kyotocabinet::TreeDB::TLINEAR;
|
||||
if (FLAGS_compression) {
|
||||
tune_options |= kyotocabinet::TreeDB::TCOMPRESS;
|
||||
db_->tune_compressor(&comp_);
|
||||
@ -421,8 +416,8 @@ class Benchmark {
|
||||
}
|
||||
}
|
||||
|
||||
void Write(bool sync, Order order, DBState state,
|
||||
int num_entries, int value_size, int entries_per_batch) {
|
||||
void Write(bool sync, Order order, DBState state, int num_entries,
|
||||
int value_size, int entries_per_batch) {
|
||||
// Create new database if state == FRESH
|
||||
if (state == FRESH) {
|
||||
if (FLAGS_use_existing_db) {
|
||||
@ -442,8 +437,7 @@ class Benchmark {
|
||||
}
|
||||
|
||||
// Write to database
|
||||
for (int i = 0; i < num_entries; i++)
|
||||
{
|
||||
for (int i = 0; i < num_entries; i++) {
|
||||
const int k = (order == SEQUENTIAL) ? i : (rand_.Next() % num_entries);
|
||||
char key[100];
|
||||
snprintf(key, sizeof(key), "%016d", k);
|
||||
|
@ -134,9 +134,7 @@ class FileState {
|
||||
|
||||
private:
|
||||
// Private since only Unref() should be used to delete it.
|
||||
~FileState() {
|
||||
Truncate();
|
||||
}
|
||||
~FileState() { Truncate(); }
|
||||
|
||||
// No copying allowed.
|
||||
FileState(const FileState&);
|
||||
@ -158,9 +156,7 @@ class SequentialFileImpl : public SequentialFile {
|
||||
file_->Ref();
|
||||
}
|
||||
|
||||
~SequentialFileImpl() {
|
||||
file_->Unref();
|
||||
}
|
||||
~SequentialFileImpl() { file_->Unref(); }
|
||||
|
||||
virtual Status Read(size_t n, Slice* result, char* scratch) {
|
||||
Status s = file_->Read(pos_, n, result, scratch);
|
||||
@ -189,13 +185,9 @@ class SequentialFileImpl : public SequentialFile {
|
||||
|
||||
class RandomAccessFileImpl : public RandomAccessFile {
|
||||
public:
|
||||
explicit RandomAccessFileImpl(FileState* file) : file_(file) {
|
||||
file_->Ref();
|
||||
}
|
||||
explicit RandomAccessFileImpl(FileState* file) : file_(file) { file_->Ref(); }
|
||||
|
||||
~RandomAccessFileImpl() {
|
||||
file_->Unref();
|
||||
}
|
||||
~RandomAccessFileImpl() { file_->Unref(); }
|
||||
|
||||
virtual Status Read(uint64_t offset, size_t n, Slice* result,
|
||||
char* scratch) const {
|
||||
@ -208,17 +200,11 @@ class RandomAccessFileImpl : public RandomAccessFile {
|
||||
|
||||
class WritableFileImpl : public WritableFile {
|
||||
public:
|
||||
WritableFileImpl(FileState* file) : file_(file) {
|
||||
file_->Ref();
|
||||
}
|
||||
WritableFileImpl(FileState* file) : file_(file) { file_->Ref(); }
|
||||
|
||||
~WritableFileImpl() {
|
||||
file_->Unref();
|
||||
}
|
||||
~WritableFileImpl() { file_->Unref(); }
|
||||
|
||||
virtual Status Append(const Slice& data) {
|
||||
return file_->Append(data);
|
||||
}
|
||||
virtual Status Append(const Slice& data) { return file_->Append(data); }
|
||||
|
||||
virtual Status Close() { return Status::OK(); }
|
||||
virtual Status Flush() { return Status::OK(); }
|
||||
@ -238,7 +224,8 @@ class InMemoryEnv : public EnvWrapper {
|
||||
explicit InMemoryEnv(Env* base_env) : EnvWrapper(base_env) {}
|
||||
|
||||
virtual ~InMemoryEnv() {
|
||||
for (FileSystem::iterator i = file_map_.begin(); i != file_map_.end(); ++i){
|
||||
for (FileSystem::iterator i = file_map_.begin(); i != file_map_.end();
|
||||
++i) {
|
||||
i->second->Unref();
|
||||
}
|
||||
}
|
||||
@ -311,7 +298,8 @@ class InMemoryEnv : public EnvWrapper {
|
||||
MutexLock lock(&mutex_);
|
||||
result->clear();
|
||||
|
||||
for (FileSystem::iterator i = file_map_.begin(); i != file_map_.end(); ++i){
|
||||
for (FileSystem::iterator i = file_map_.begin(); i != file_map_.end();
|
||||
++i) {
|
||||
const std::string& filename = i->first;
|
||||
|
||||
if (filename.size() >= dir.size() + 1 && filename[dir.size()] == '/' &&
|
||||
@ -343,13 +331,9 @@ class InMemoryEnv : public EnvWrapper {
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
virtual Status CreateDir(const std::string& dirname) {
|
||||
return Status::OK();
|
||||
}
|
||||
virtual Status CreateDir(const std::string& dirname) { return Status::OK(); }
|
||||
|
||||
virtual Status DeleteDir(const std::string& dirname) {
|
||||
return Status::OK();
|
||||
}
|
||||
virtual Status DeleteDir(const std::string& dirname) { return Status::OK(); }
|
||||
|
||||
virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) {
|
||||
MutexLock lock(&mutex_);
|
||||
@ -361,8 +345,7 @@ class InMemoryEnv : public EnvWrapper {
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
virtual Status RenameFile(const std::string& src,
|
||||
const std::string& target) {
|
||||
virtual Status RenameFile(const std::string& src, const std::string& target) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (file_map_.find(src) == file_map_.end()) {
|
||||
return Status::IOError(src, "File not found");
|
||||
@ -403,8 +386,6 @@ class InMemoryEnv : public EnvWrapper {
|
||||
|
||||
} // namespace
|
||||
|
||||
Env* NewMemEnv(Env* base_env) {
|
||||
return new InMemoryEnv(base_env);
|
||||
}
|
||||
Env* NewMemEnv(Env* base_env) { return new InMemoryEnv(base_env); }
|
||||
|
||||
} // namespace leveldb
|
||||
|
@ -4,12 +4,13 @@
|
||||
|
||||
#include "helpers/memenv/memenv.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "db/db_impl.h"
|
||||
#include "leveldb/db.h"
|
||||
#include "leveldb/env.h"
|
||||
#include "util/testharness.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace leveldb {
|
||||
|
||||
@ -17,12 +18,8 @@ class MemEnvTest {
|
||||
public:
|
||||
Env* env_;
|
||||
|
||||
MemEnvTest()
|
||||
: env_(NewMemEnv(Env::Default())) {
|
||||
}
|
||||
~MemEnvTest() {
|
||||
delete env_;
|
||||
}
|
||||
MemEnvTest() : env_(NewMemEnv(Env::Default())) {}
|
||||
~MemEnvTest() { delete env_; }
|
||||
};
|
||||
|
||||
TEST(MemEnvTest, Basics) {
|
||||
@ -259,6 +256,4 @@ TEST(MemEnvTest, DBTest) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -47,6 +47,7 @@ extern "C" {
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "leveldb/export.h"
|
||||
|
||||
/* Exported types */
|
||||
@ -189,10 +190,7 @@ LEVELDB_EXPORT void leveldb_options_set_block_restart_interval(
|
||||
LEVELDB_EXPORT void leveldb_options_set_max_file_size(leveldb_options_t*,
|
||||
size_t);
|
||||
|
||||
enum {
|
||||
leveldb_no_compression = 0,
|
||||
leveldb_snappy_compression = 1
|
||||
};
|
||||
enum { leveldb_no_compression = 0, leveldb_snappy_compression = 1 };
|
||||
LEVELDB_EXPORT void leveldb_options_set_compression(leveldb_options_t*, int);
|
||||
|
||||
/* Comparator */
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define STORAGE_LEVELDB_INCLUDE_CACHE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "leveldb/export.h"
|
||||
#include "leveldb/slice.h"
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "leveldb/export.h"
|
||||
|
||||
namespace leveldb {
|
||||
@ -44,8 +45,7 @@ class LEVELDB_EXPORT Comparator {
|
||||
// If *start < limit, changes *start to a short string in [start,limit).
|
||||
// Simple comparator implementations may return with *start unchanged,
|
||||
// i.e., an implementation of this method that does nothing is correct.
|
||||
virtual void FindShortestSeparator(
|
||||
std::string* start,
|
||||
virtual void FindShortestSeparator(std::string* start,
|
||||
const Slice& limit) const = 0;
|
||||
|
||||
// Changes *key to a short string >= *key.
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "leveldb/export.h"
|
||||
#include "leveldb/iterator.h"
|
||||
#include "leveldb/options.h"
|
||||
@ -49,8 +50,7 @@ class LEVELDB_EXPORT DB {
|
||||
// OK on success.
|
||||
// Stores nullptr in *dbptr and returns a non-OK status on error.
|
||||
// Caller should delete *dbptr when it is no longer needed.
|
||||
static Status Open(const Options& options,
|
||||
const std::string& name,
|
||||
static Status Open(const Options& options, const std::string& name,
|
||||
DB** dbptr);
|
||||
|
||||
DB() = default;
|
||||
@ -63,8 +63,7 @@ class LEVELDB_EXPORT DB {
|
||||
// Set the database entry for "key" to "value". Returns OK on success,
|
||||
// and a non-OK status on error.
|
||||
// Note: consider setting options.sync = true.
|
||||
virtual Status Put(const WriteOptions& options,
|
||||
const Slice& key,
|
||||
virtual Status Put(const WriteOptions& options, const Slice& key,
|
||||
const Slice& value) = 0;
|
||||
|
||||
// Remove the database entry (if any) for "key". Returns OK on
|
||||
@ -85,8 +84,8 @@ class LEVELDB_EXPORT DB {
|
||||
// a status for which Status::IsNotFound() returns true.
|
||||
//
|
||||
// May return some other Status on an error.
|
||||
virtual Status Get(const ReadOptions& options,
|
||||
const Slice& key, std::string* value) = 0;
|
||||
virtual Status Get(const ReadOptions& options, const Slice& key,
|
||||
std::string* value) = 0;
|
||||
|
||||
// Return a heap-allocated iterator over the contents of the database.
|
||||
// The result of NewIterator() is initially invalid (caller must
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "leveldb/env.h"
|
||||
#include "leveldb/export.h"
|
||||
#include "leveldb/status.h"
|
||||
|
@ -15,8 +15,10 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "leveldb/export.h"
|
||||
#include "leveldb/status.h"
|
||||
|
||||
@ -164,9 +166,7 @@ class LEVELDB_EXPORT Env {
|
||||
// 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;
|
||||
virtual void Schedule(void (*function)(void* arg), void* arg) = 0;
|
||||
|
||||
// Start a new thread, invoking "function(arg)" within the new thread.
|
||||
// When "function(arg)" returns, the thread will be destroyed.
|
||||
@ -364,9 +364,7 @@ class LEVELDB_EXPORT EnvWrapper : public Env {
|
||||
Status NewLogger(const std::string& fname, Logger** result) override {
|
||||
return target_->NewLogger(fname, result);
|
||||
}
|
||||
uint64_t NowMicros() override {
|
||||
return target_->NowMicros();
|
||||
}
|
||||
uint64_t NowMicros() override { return target_->NowMicros(); }
|
||||
void SleepForMicroseconds(int micros) override {
|
||||
target_->SleepForMicroseconds(micros);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "leveldb/export.h"
|
||||
|
||||
namespace leveldb {
|
||||
@ -39,8 +40,8 @@ class LEVELDB_EXPORT FilterPolicy {
|
||||
//
|
||||
// Warning: do not change the initial contents of *dst. Instead,
|
||||
// append the newly constructed filter to *dst.
|
||||
virtual void CreateFilter(const Slice* keys, int n, std::string* dst)
|
||||
const = 0;
|
||||
virtual void CreateFilter(const Slice* keys, int n,
|
||||
std::string* dst) const = 0;
|
||||
|
||||
// "filter" contains the data appended by a preceding call to
|
||||
// CreateFilter() on this class. This method must return true if
|
||||
|
@ -93,7 +93,10 @@ class LEVELDB_EXPORT Iterator {
|
||||
// True if the node is not used. Only head nodes might be unused.
|
||||
bool IsEmpty() const { return function == nullptr; }
|
||||
// Invokes the cleanup function.
|
||||
void Run() { assert(function != nullptr); (*function)(arg1, arg2); }
|
||||
void Run() {
|
||||
assert(function != nullptr);
|
||||
(*function)(arg1, arg2);
|
||||
}
|
||||
};
|
||||
CleanupNode cleanup_head_;
|
||||
};
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define STORAGE_LEVELDB_INCLUDE_OPTIONS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "leveldb/export.h"
|
||||
|
||||
namespace leveldb {
|
||||
|
@ -18,7 +18,9 @@
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "leveldb/export.h"
|
||||
|
||||
namespace leveldb {
|
||||
@ -58,7 +60,10 @@ class LEVELDB_EXPORT Slice {
|
||||
}
|
||||
|
||||
// Change this slice to refer to an empty array
|
||||
void clear() { data_ = ""; size_ = 0; }
|
||||
void clear() {
|
||||
data_ = "";
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
// Drop the first "n" bytes from this slice.
|
||||
void remove_prefix(size_t n) {
|
||||
@ -78,8 +83,7 @@ class LEVELDB_EXPORT Slice {
|
||||
|
||||
// Return true iff "x" is a prefix of "*this"
|
||||
bool starts_with(const Slice& x) const {
|
||||
return ((size_ >= x.size_) &&
|
||||
(memcmp(data_, x.data_, x.size_) == 0));
|
||||
return ((size_ >= x.size_) && (memcmp(data_, x.data_, x.size_) == 0));
|
||||
}
|
||||
|
||||
private:
|
||||
@ -92,21 +96,20 @@ inline bool operator==(const Slice& x, const Slice& y) {
|
||||
(memcmp(x.data(), y.data(), x.size()) == 0));
|
||||
}
|
||||
|
||||
inline bool operator!=(const Slice& x, const Slice& y) {
|
||||
return !(x == y);
|
||||
}
|
||||
inline bool operator!=(const Slice& x, const Slice& y) { return !(x == y); }
|
||||
|
||||
inline int Slice::compare(const Slice& b) const {
|
||||
const size_t min_len = (size_ < b.size_) ? size_ : b.size_;
|
||||
int r = memcmp(data_, b.data_, min_len);
|
||||
if (r == 0) {
|
||||
if (size_ < b.size_) r = -1;
|
||||
else if (size_ > b.size_) r = +1;
|
||||
if (size_ < b.size_)
|
||||
r = -1;
|
||||
else if (size_ > b.size_)
|
||||
r = +1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
|
||||
#endif // STORAGE_LEVELDB_INCLUDE_SLICE_H_
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "leveldb/export.h"
|
||||
#include "leveldb/slice.h"
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define STORAGE_LEVELDB_INCLUDE_TABLE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "leveldb/export.h"
|
||||
#include "leveldb/iterator.h"
|
||||
|
||||
@ -36,10 +37,8 @@ class LEVELDB_EXPORT Table {
|
||||
// for the duration of the returned table's lifetime.
|
||||
//
|
||||
// *file must remain live while this Table is in use.
|
||||
static Status Open(const Options& options,
|
||||
RandomAccessFile* file,
|
||||
uint64_t file_size,
|
||||
Table** table);
|
||||
static Status Open(const Options& options, RandomAccessFile* file,
|
||||
uint64_t file_size, Table** table);
|
||||
|
||||
Table(const Table&) = delete;
|
||||
void operator=(const Table&) = delete;
|
||||
@ -70,11 +69,9 @@ class LEVELDB_EXPORT Table {
|
||||
// to Seek(key). May not make such a call if filter policy says
|
||||
// that key is not present.
|
||||
friend class TableCache;
|
||||
Status InternalGet(
|
||||
const ReadOptions&, const Slice& key,
|
||||
void* arg,
|
||||
void (*handle_result)(void* arg, const Slice& k, const Slice& v));
|
||||
|
||||
Status InternalGet(const ReadOptions&, const Slice& key, void* arg,
|
||||
void (*handle_result)(void* arg, const Slice& k,
|
||||
const Slice& v));
|
||||
|
||||
void ReadMeta(const Footer& footer);
|
||||
void ReadFilter(const Slice& filter_handle_value);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "leveldb/export.h"
|
||||
#include "leveldb/options.h"
|
||||
#include "leveldb/status.h"
|
||||
|
@ -22,6 +22,7 @@
|
||||
#define STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "leveldb/export.h"
|
||||
#include "leveldb/status.h"
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
// Test for issue 178: a manual compaction causes deleted data to reappear.
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "leveldb/db.h"
|
||||
#include "leveldb/write_batch.h"
|
||||
@ -21,9 +21,7 @@ std::string Key1(int i) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
std::string Key2(int i) {
|
||||
return Key1(i) + "_xxx";
|
||||
}
|
||||
std::string Key2(int i) { return Key1(i) + "_xxx"; }
|
||||
|
||||
class Issue178 {};
|
||||
|
||||
@ -87,6 +85,4 @@ TEST(Issue178, Test) {
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -54,6 +54,4 @@ TEST(Issue200, Test) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -30,9 +30,9 @@
|
||||
#endif // HAVE_SNAPPY
|
||||
|
||||
#include <cassert>
|
||||
#include <condition_variable> // NOLINT
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <condition_variable> // NOLINT
|
||||
#include <mutex> // NOLINT
|
||||
#include <string>
|
||||
|
||||
@ -79,6 +79,7 @@ class CondVar {
|
||||
}
|
||||
void Signal() { cv_.notify_one(); }
|
||||
void SignalAll() { cv_.notify_all(); }
|
||||
|
||||
private:
|
||||
std::condition_variable cv_;
|
||||
Mutex* const mu_;
|
||||
@ -94,7 +95,9 @@ inline bool Snappy_Compress(const char* input, size_t length,
|
||||
return true;
|
||||
#else
|
||||
// Silence compiler warnings about unused arguments.
|
||||
(void)input; (void)length; (void)output;
|
||||
(void)input;
|
||||
(void)length;
|
||||
(void)output;
|
||||
#endif // HAVE_SNAPPY
|
||||
|
||||
return false;
|
||||
@ -106,7 +109,9 @@ inline bool Snappy_GetUncompressedLength(const char* input, size_t length,
|
||||
return snappy::GetUncompressedLength(input, length, result);
|
||||
#else
|
||||
// Silence compiler warnings about unused arguments.
|
||||
(void)input; (void)length; (void)result;
|
||||
(void)input;
|
||||
(void)length;
|
||||
(void)result;
|
||||
return false;
|
||||
#endif // HAVE_SNAPPY
|
||||
}
|
||||
@ -116,14 +121,17 @@ inline bool Snappy_Uncompress(const char* input, size_t length, char* output) {
|
||||
return snappy::RawUncompress(input, length, output);
|
||||
#else
|
||||
// Silence compiler warnings about unused arguments.
|
||||
(void)input; (void)length; (void)output;
|
||||
(void)input;
|
||||
(void)length;
|
||||
(void)output;
|
||||
return false;
|
||||
#endif // HAVE_SNAPPY
|
||||
}
|
||||
|
||||
inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) {
|
||||
// Silence compiler warnings about unused arguments.
|
||||
(void)func; (void)arg;
|
||||
(void)func;
|
||||
(void)arg;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -132,7 +140,9 @@ inline uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size) {
|
||||
return ::crc32c::Extend(crc, reinterpret_cast<const uint8_t*>(buf), size);
|
||||
#else
|
||||
// Silence compiler warnings about unused arguments.
|
||||
(void)crc; (void)buf; (void)size;
|
||||
(void)crc;
|
||||
(void)buf;
|
||||
(void)size;
|
||||
return 0;
|
||||
#endif // HAVE_CRC32C
|
||||
}
|
||||
|
@ -54,18 +54,15 @@
|
||||
#endif
|
||||
|
||||
#ifndef LOCK_RETURNED
|
||||
#define LOCK_RETURNED(x) \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
|
||||
#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
|
||||
#endif
|
||||
|
||||
#ifndef LOCKABLE
|
||||
#define LOCKABLE \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(lockable)
|
||||
#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable)
|
||||
#endif
|
||||
|
||||
#ifndef SCOPED_LOCKABLE
|
||||
#define SCOPED_LOCKABLE \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
||||
#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
|
||||
#endif
|
||||
|
||||
#ifndef EXCLUSIVE_LOCK_FUNCTION
|
||||
|
@ -6,8 +6,9 @@
|
||||
|
||||
#include "table/block.h"
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "leveldb/comparator.h"
|
||||
#include "table/format.h"
|
||||
#include "util/coding.h"
|
||||
@ -51,8 +52,7 @@ Block::~Block() {
|
||||
// If any errors are detected, returns nullptr. Otherwise, returns a
|
||||
// pointer to the key delta (just past the three decoded values).
|
||||
static inline const char* DecodeEntry(const char* p, const char* limit,
|
||||
uint32_t* shared,
|
||||
uint32_t* non_shared,
|
||||
uint32_t* shared, uint32_t* non_shared,
|
||||
uint32_t* value_length) {
|
||||
if (limit - p < 3) return nullptr;
|
||||
*shared = reinterpret_cast<const unsigned char*>(p)[0];
|
||||
@ -112,9 +112,7 @@ class Block::Iter : public Iterator {
|
||||
}
|
||||
|
||||
public:
|
||||
Iter(const Comparator* comparator,
|
||||
const char* data,
|
||||
uint32_t restarts,
|
||||
Iter(const Comparator* comparator, const char* data, uint32_t restarts,
|
||||
uint32_t num_restarts)
|
||||
: comparator_(comparator),
|
||||
data_(data),
|
||||
@ -171,9 +169,9 @@ class Block::Iter : public Iterator {
|
||||
uint32_t mid = (left + right + 1) / 2;
|
||||
uint32_t region_offset = GetRestartPoint(mid);
|
||||
uint32_t shared, non_shared, value_length;
|
||||
const char* key_ptr = DecodeEntry(data_ + region_offset,
|
||||
data_ + restarts_,
|
||||
&shared, &non_shared, &value_length);
|
||||
const char* key_ptr =
|
||||
DecodeEntry(data_ + region_offset, data_ + restarts_, &shared,
|
||||
&non_shared, &value_length);
|
||||
if (key_ptr == nullptr || (shared != 0)) {
|
||||
CorruptionError();
|
||||
return;
|
||||
@ -253,7 +251,7 @@ class Block::Iter : public Iterator {
|
||||
}
|
||||
};
|
||||
|
||||
Iterator* Block::NewIterator(const Comparator* cmp) {
|
||||
Iterator* Block::NewIterator(const Comparator* comparator) {
|
||||
if (size_ < sizeof(uint32_t)) {
|
||||
return NewErrorIterator(Status::Corruption("bad block contents"));
|
||||
}
|
||||
@ -261,7 +259,7 @@ Iterator* Block::NewIterator(const Comparator* cmp) {
|
||||
if (num_restarts == 0) {
|
||||
return NewEmptyIterator();
|
||||
} else {
|
||||
return new Iter(cmp, data_, restart_offset_, num_restarts);
|
||||
return new Iter(comparator, data_, restart_offset_, num_restarts);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "leveldb/iterator.h"
|
||||
|
||||
namespace leveldb {
|
||||
|
@ -28,8 +28,10 @@
|
||||
|
||||
#include "table/block_builder.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "leveldb/comparator.h"
|
||||
#include "leveldb/table_builder.h"
|
||||
#include "util/coding.h"
|
||||
@ -37,10 +39,7 @@
|
||||
namespace leveldb {
|
||||
|
||||
BlockBuilder::BlockBuilder(const Options* options)
|
||||
: options_(options),
|
||||
restarts_(),
|
||||
counter_(0),
|
||||
finished_(false) {
|
||||
: options_(options), restarts_(), counter_(0), finished_(false) {
|
||||
assert(options->block_restart_interval >= 1);
|
||||
restarts_.push_back(0); // First restart point is at offset 0
|
||||
}
|
||||
|
@ -5,9 +5,10 @@
|
||||
#ifndef STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_
|
||||
#define STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <stdint.h>
|
||||
#include "leveldb/slice.h"
|
||||
|
||||
namespace leveldb {
|
||||
@ -35,9 +36,7 @@ class BlockBuilder {
|
||||
size_t CurrentSizeEstimate() const;
|
||||
|
||||
// Return true iff no entries have been added since the last Reset()
|
||||
bool empty() const {
|
||||
return buffer_.empty();
|
||||
}
|
||||
bool empty() const { return buffer_.empty(); }
|
||||
|
||||
private:
|
||||
const Options* options_;
|
||||
|
@ -16,8 +16,7 @@ static const size_t kFilterBaseLg = 11;
|
||||
static const size_t kFilterBase = 1 << kFilterBaseLg;
|
||||
|
||||
FilterBlockBuilder::FilterBlockBuilder(const FilterPolicy* policy)
|
||||
: policy_(policy) {
|
||||
}
|
||||
: policy_(policy) {}
|
||||
|
||||
void FilterBlockBuilder::StartBlock(uint64_t block_offset) {
|
||||
uint64_t filter_index = (block_offset / kFilterBase);
|
||||
@ -77,11 +76,7 @@ void FilterBlockBuilder::GenerateFilter() {
|
||||
|
||||
FilterBlockReader::FilterBlockReader(const FilterPolicy* policy,
|
||||
const Slice& contents)
|
||||
: policy_(policy),
|
||||
data_(nullptr),
|
||||
offset_(nullptr),
|
||||
num_(0),
|
||||
base_lg_(0) {
|
||||
: policy_(policy), data_(nullptr), offset_(nullptr), num_(0), base_lg_(0) {
|
||||
size_t n = contents.size();
|
||||
if (n < 5) return; // 1 byte for base_lg_ and 4 for start of offset array
|
||||
base_lg_ = contents[n - 1];
|
||||
@ -108,4 +103,4 @@ bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) {
|
||||
return true; // Errors are treated as potential matches
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace leveldb
|
||||
|
@ -11,8 +11,10 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "leveldb/slice.h"
|
||||
#include "util/hash.h"
|
||||
|
||||
@ -63,6 +65,6 @@ class FilterBlockReader {
|
||||
size_t base_lg_; // Encoding parameter (see kFilterBaseLg in .cc file)
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace leveldb
|
||||
|
||||
#endif // STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_
|
||||
|
@ -16,9 +16,7 @@ namespace leveldb {
|
||||
// For testing: emit an array with one hash value per key
|
||||
class TestHashFilter : public FilterPolicy {
|
||||
public:
|
||||
virtual const char* Name() const {
|
||||
return "TestHashFilter";
|
||||
}
|
||||
virtual const char* Name() const { return "TestHashFilter"; }
|
||||
|
||||
virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
|
||||
for (int i = 0; i < n; i++) {
|
||||
@ -123,6 +121,4 @@ TEST(FilterBlockTest, MultiChunk) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -21,8 +21,7 @@ void BlockHandle::EncodeTo(std::string* dst) const {
|
||||
}
|
||||
|
||||
Status BlockHandle::DecodeFrom(Slice* input) {
|
||||
if (GetVarint64(input, &offset_) &&
|
||||
GetVarint64(input, &size_)) {
|
||||
if (GetVarint64(input, &offset_) && GetVarint64(input, &size_)) {
|
||||
return Status::OK();
|
||||
} else {
|
||||
return Status::Corruption("bad block handle");
|
||||
@ -62,10 +61,8 @@ Status Footer::DecodeFrom(Slice* input) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Status ReadBlock(RandomAccessFile* file,
|
||||
const ReadOptions& options,
|
||||
const BlockHandle& handle,
|
||||
BlockContents* result) {
|
||||
Status ReadBlock(RandomAccessFile* file, const ReadOptions& options,
|
||||
const BlockHandle& handle, BlockContents* result) {
|
||||
result->data = Slice();
|
||||
result->cachable = false;
|
||||
result->heap_allocated = false;
|
||||
|
@ -5,8 +5,10 @@
|
||||
#ifndef STORAGE_LEVELDB_TABLE_FORMAT_H_
|
||||
#define STORAGE_LEVELDB_TABLE_FORMAT_H_
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "leveldb/slice.h"
|
||||
#include "leveldb/status.h"
|
||||
#include "leveldb/table_builder.h"
|
||||
@ -53,12 +55,8 @@ class Footer {
|
||||
void set_metaindex_handle(const BlockHandle& h) { metaindex_handle_ = h; }
|
||||
|
||||
// The block handle for the index block of the table
|
||||
const BlockHandle& index_handle() const {
|
||||
return index_handle_;
|
||||
}
|
||||
void set_index_handle(const BlockHandle& h) {
|
||||
index_handle_ = h;
|
||||
}
|
||||
const BlockHandle& index_handle() const { return index_handle_; }
|
||||
void set_index_handle(const BlockHandle& h) { index_handle_ = h; }
|
||||
|
||||
void EncodeTo(std::string* dst) const;
|
||||
Status DecodeFrom(Slice* input);
|
||||
@ -66,9 +64,7 @@ class Footer {
|
||||
// Encoded length of a Footer. Note that the serialization of a
|
||||
// Footer will always occupy exactly this many bytes. It consists
|
||||
// of two block handles and a magic number.
|
||||
enum {
|
||||
kEncodedLength = 2*BlockHandle::kMaxEncodedLength + 8
|
||||
};
|
||||
enum { kEncodedLength = 2 * BlockHandle::kMaxEncodedLength + 8 };
|
||||
|
||||
private:
|
||||
BlockHandle metaindex_handle_;
|
||||
@ -91,17 +87,13 @@ struct BlockContents {
|
||||
|
||||
// Read the block identified by "handle" from "file". On failure
|
||||
// return non-OK. On success fill *result and return OK.
|
||||
Status ReadBlock(RandomAccessFile* file,
|
||||
const ReadOptions& options,
|
||||
const BlockHandle& handle,
|
||||
BlockContents* result);
|
||||
Status ReadBlock(RandomAccessFile* file, const ReadOptions& options,
|
||||
const BlockHandle& handle, BlockContents* result);
|
||||
|
||||
// Implementation details follow. Clients should ignore,
|
||||
|
||||
inline BlockHandle::BlockHandle()
|
||||
: offset_(~static_cast<uint64_t>(0)),
|
||||
size_(~static_cast<uint64_t>(0)) {
|
||||
}
|
||||
: offset_(~static_cast<uint64_t>(0)), size_(~static_cast<uint64_t>(0)) {}
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
|
@ -51,8 +51,14 @@ class EmptyIterator : public Iterator {
|
||||
void SeekToLast() override {}
|
||||
void Next() override { assert(false); }
|
||||
void Prev() override { assert(false); }
|
||||
Slice key() const override { assert(false); return Slice(); }
|
||||
Slice value() const override { assert(false); return Slice(); }
|
||||
Slice key() const override {
|
||||
assert(false);
|
||||
return Slice();
|
||||
}
|
||||
Slice value() const override {
|
||||
assert(false);
|
||||
return Slice();
|
||||
}
|
||||
Status status() const override { return status_; }
|
||||
|
||||
private:
|
||||
@ -61,9 +67,7 @@ class EmptyIterator : public Iterator {
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
Iterator* NewEmptyIterator() {
|
||||
return new EmptyIterator(Status::OK());
|
||||
}
|
||||
Iterator* NewEmptyIterator() { return new EmptyIterator(Status::OK()); }
|
||||
|
||||
Iterator* NewErrorIterator(const Status& status) {
|
||||
return new EmptyIterator(status);
|
||||
|
@ -17,9 +17,7 @@ namespace leveldb {
|
||||
class IteratorWrapper {
|
||||
public:
|
||||
IteratorWrapper() : iter_(nullptr), valid_(false) {}
|
||||
explicit IteratorWrapper(Iterator* iter): iter_(nullptr) {
|
||||
Set(iter);
|
||||
}
|
||||
explicit IteratorWrapper(Iterator* iter) : iter_(nullptr) { Set(iter); }
|
||||
~IteratorWrapper() { delete iter_; }
|
||||
Iterator* iter() const { return iter_; }
|
||||
|
||||
@ -35,18 +33,46 @@ class IteratorWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Iterator interface methods
|
||||
bool Valid() const { return valid_; }
|
||||
Slice key() const { assert(Valid()); return key_; }
|
||||
Slice value() const { assert(Valid()); return iter_->value(); }
|
||||
Slice key() const {
|
||||
assert(Valid());
|
||||
return key_;
|
||||
}
|
||||
Slice value() const {
|
||||
assert(Valid());
|
||||
return iter_->value();
|
||||
}
|
||||
// Methods below require iter() != nullptr
|
||||
Status status() const { assert(iter_); return iter_->status(); }
|
||||
void Next() { assert(iter_); iter_->Next(); Update(); }
|
||||
void Prev() { assert(iter_); iter_->Prev(); Update(); }
|
||||
void Seek(const Slice& k) { assert(iter_); iter_->Seek(k); Update(); }
|
||||
void SeekToFirst() { assert(iter_); iter_->SeekToFirst(); Update(); }
|
||||
void SeekToLast() { assert(iter_); iter_->SeekToLast(); Update(); }
|
||||
Status status() const {
|
||||
assert(iter_);
|
||||
return iter_->status();
|
||||
}
|
||||
void Next() {
|
||||
assert(iter_);
|
||||
iter_->Next();
|
||||
Update();
|
||||
}
|
||||
void Prev() {
|
||||
assert(iter_);
|
||||
iter_->Prev();
|
||||
Update();
|
||||
}
|
||||
void Seek(const Slice& k) {
|
||||
assert(iter_);
|
||||
iter_->Seek(k);
|
||||
Update();
|
||||
}
|
||||
void SeekToFirst() {
|
||||
assert(iter_);
|
||||
iter_->SeekToFirst();
|
||||
Update();
|
||||
}
|
||||
void SeekToLast() {
|
||||
assert(iter_);
|
||||
iter_->SeekToLast();
|
||||
Update();
|
||||
}
|
||||
|
||||
private:
|
||||
void Update() {
|
||||
|
@ -24,13 +24,9 @@ class MergingIterator : public Iterator {
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~MergingIterator() {
|
||||
delete[] children_;
|
||||
}
|
||||
virtual ~MergingIterator() { delete[] children_; }
|
||||
|
||||
virtual bool Valid() const {
|
||||
return (current_ != nullptr);
|
||||
}
|
||||
virtual bool Valid() const { return (current_ != nullptr); }
|
||||
|
||||
virtual void SeekToFirst() {
|
||||
for (int i = 0; i < n_; i++) {
|
||||
@ -145,10 +141,7 @@ class MergingIterator : public Iterator {
|
||||
IteratorWrapper* current_;
|
||||
|
||||
// Which direction is the iterator moving?
|
||||
enum Direction {
|
||||
kForward,
|
||||
kReverse
|
||||
};
|
||||
enum Direction { kForward, kReverse };
|
||||
Direction direction_;
|
||||
};
|
||||
|
||||
@ -183,14 +176,15 @@ void MergingIterator::FindLargest() {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Iterator* NewMergingIterator(const Comparator* cmp, Iterator** list, int n) {
|
||||
Iterator* NewMergingIterator(const Comparator* comparator, Iterator** children,
|
||||
int n) {
|
||||
assert(n >= 0);
|
||||
if (n == 0) {
|
||||
return NewEmptyIterator();
|
||||
} else if (n == 1) {
|
||||
return list[0];
|
||||
return children[0];
|
||||
} else {
|
||||
return new MergingIterator(cmp, list, n);
|
||||
return new MergingIterator(comparator, children, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,8 @@ class Iterator;
|
||||
// key is present in K child iterators, it will be yielded K times.
|
||||
//
|
||||
// REQUIRES: n >= 0
|
||||
Iterator* NewMergingIterator(
|
||||
const Comparator* comparator, Iterator** children, int n);
|
||||
Iterator* NewMergingIterator(const Comparator* comparator, Iterator** children,
|
||||
int n);
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
|
@ -35,10 +35,8 @@ struct Table::Rep {
|
||||
Block* index_block;
|
||||
};
|
||||
|
||||
Status Table::Open(const Options& options,
|
||||
RandomAccessFile* file,
|
||||
uint64_t size,
|
||||
Table** table) {
|
||||
Status Table::Open(const Options& options, RandomAccessFile* file,
|
||||
uint64_t size, Table** table) {
|
||||
*table = nullptr;
|
||||
if (size < Footer::kEncodedLength) {
|
||||
return Status::Corruption("file is too short to be an sstable");
|
||||
@ -135,9 +133,7 @@ void Table::ReadFilter(const Slice& filter_handle_value) {
|
||||
rep_->filter = new FilterBlockReader(rep_->options.filter_policy, block.data);
|
||||
}
|
||||
|
||||
Table::~Table() {
|
||||
delete rep_;
|
||||
}
|
||||
Table::~Table() { delete rep_; }
|
||||
|
||||
static void DeleteBlock(void* arg, void* ignored) {
|
||||
delete reinterpret_cast<Block*>(arg);
|
||||
@ -156,8 +152,7 @@ static void ReleaseBlock(void* arg, void* h) {
|
||||
|
||||
// Convert an index iterator value (i.e., an encoded BlockHandle)
|
||||
// into an iterator over the contents of the corresponding block.
|
||||
Iterator* Table::BlockReader(void* arg,
|
||||
const ReadOptions& options,
|
||||
Iterator* Table::BlockReader(void* arg, const ReadOptions& options,
|
||||
const Slice& index_value) {
|
||||
Table* table = reinterpret_cast<Table*>(arg);
|
||||
Cache* block_cache = table->rep_->options.block_cache;
|
||||
@ -185,8 +180,8 @@ Iterator* Table::BlockReader(void* arg,
|
||||
if (s.ok()) {
|
||||
block = new Block(contents);
|
||||
if (contents.cachable && options.fill_cache) {
|
||||
cache_handle = block_cache->Insert(
|
||||
key, block, block->size(), &DeleteCachedBlock);
|
||||
cache_handle = block_cache->Insert(key, block, block->size(),
|
||||
&DeleteCachedBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -218,9 +213,9 @@ Iterator* Table::NewIterator(const ReadOptions& options) const {
|
||||
&Table::BlockReader, const_cast<Table*>(this), options);
|
||||
}
|
||||
|
||||
Status Table::InternalGet(const ReadOptions& options, const Slice& k,
|
||||
void* arg,
|
||||
void (*saver)(void*, const Slice&, const Slice&)) {
|
||||
Status Table::InternalGet(const ReadOptions& options, const Slice& k, void* arg,
|
||||
void (*handle_result)(void*, const Slice&,
|
||||
const Slice&)) {
|
||||
Status s;
|
||||
Iterator* iiter = rep_->index_block->NewIterator(rep_->options.comparator);
|
||||
iiter->Seek(k);
|
||||
@ -228,15 +223,14 @@ Status Table::InternalGet(const ReadOptions& options, const Slice& k,
|
||||
Slice handle_value = iiter->value();
|
||||
FilterBlockReader* filter = rep_->filter;
|
||||
BlockHandle handle;
|
||||
if (filter != nullptr &&
|
||||
handle.DecodeFrom(&handle_value).ok() &&
|
||||
if (filter != nullptr && handle.DecodeFrom(&handle_value).ok() &&
|
||||
!filter->KeyMayMatch(handle.offset(), k)) {
|
||||
// Not found
|
||||
} else {
|
||||
Iterator* block_iter = BlockReader(this, options, iiter->value());
|
||||
block_iter->Seek(k);
|
||||
if (block_iter->Valid()) {
|
||||
(*saver)(arg, block_iter->key(), block_iter->value());
|
||||
(*handle_result)(arg, block_iter->key(), block_iter->value());
|
||||
}
|
||||
s = block_iter->status();
|
||||
delete block_iter;
|
||||
@ -249,7 +243,6 @@ Status Table::InternalGet(const ReadOptions& options, const Slice& k,
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
uint64_t Table::ApproximateOffsetOf(const Slice& key) const {
|
||||
Iterator* index_iter =
|
||||
rep_->index_block->NewIterator(rep_->options.comparator);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "leveldb/table_builder.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "leveldb/comparator.h"
|
||||
#include "leveldb/env.h"
|
||||
#include "leveldb/filter_policy.h"
|
||||
@ -53,7 +54,8 @@ struct TableBuilder::Rep {
|
||||
index_block(&index_block_options),
|
||||
num_entries(0),
|
||||
closed(false),
|
||||
filter_block(opt.filter_policy == nullptr ? nullptr
|
||||
filter_block(opt.filter_policy == nullptr
|
||||
? nullptr
|
||||
: new FilterBlockBuilder(opt.filter_policy)),
|
||||
pending_index_entry(false) {
|
||||
index_block_options.block_restart_interval = 1;
|
||||
@ -173,8 +175,7 @@ void TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) {
|
||||
}
|
||||
|
||||
void TableBuilder::WriteRawBlock(const Slice& block_contents,
|
||||
CompressionType type,
|
||||
BlockHandle* handle) {
|
||||
CompressionType type, BlockHandle* handle) {
|
||||
Rep* r = rep_;
|
||||
handle->set_offset(r->offset);
|
||||
handle->set_size(block_contents.size());
|
||||
@ -192,9 +193,7 @@ void TableBuilder::WriteRawBlock(const Slice& block_contents,
|
||||
}
|
||||
}
|
||||
|
||||
Status TableBuilder::status() const {
|
||||
return rep_->status;
|
||||
}
|
||||
Status TableBuilder::status() const { return rep_->status; }
|
||||
|
||||
Status TableBuilder::Finish() {
|
||||
Rep* r = rep_;
|
||||
@ -259,12 +258,8 @@ void TableBuilder::Abandon() {
|
||||
r->closed = true;
|
||||
}
|
||||
|
||||
uint64_t TableBuilder::NumEntries() const {
|
||||
return rep_->num_entries;
|
||||
}
|
||||
uint64_t TableBuilder::NumEntries() const { return rep_->num_entries; }
|
||||
|
||||
uint64_t TableBuilder::FileSize() const {
|
||||
return rep_->offset;
|
||||
}
|
||||
uint64_t TableBuilder::FileSize() const { return rep_->offset; }
|
||||
|
||||
} // namespace leveldb
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "db/dbformat.h"
|
||||
#include "db/memtable.h"
|
||||
#include "db/write_batch_internal.h"
|
||||
@ -27,8 +28,8 @@ namespace leveldb {
|
||||
static std::string Reverse(const Slice& key) {
|
||||
std::string str(key.ToString());
|
||||
std::string rev("");
|
||||
for (std::string::reverse_iterator rit = str.rbegin();
|
||||
rit != str.rend(); ++rit) {
|
||||
for (std::string::reverse_iterator rit = str.rbegin(); rit != str.rend();
|
||||
++rit) {
|
||||
rev.push_back(*rit);
|
||||
}
|
||||
return rev;
|
||||
@ -45,8 +46,7 @@ class ReverseKeyComparator : public Comparator {
|
||||
return BytewiseComparator()->Compare(Reverse(a), Reverse(b));
|
||||
}
|
||||
|
||||
virtual void FindShortestSeparator(
|
||||
std::string* start,
|
||||
virtual void FindShortestSeparator(std::string* start,
|
||||
const Slice& limit) const {
|
||||
std::string s = Reverse(*start);
|
||||
std::string l = Reverse(limit);
|
||||
@ -106,12 +106,10 @@ class StringSink: public WritableFile {
|
||||
std::string contents_;
|
||||
};
|
||||
|
||||
|
||||
class StringSource : public RandomAccessFile {
|
||||
public:
|
||||
StringSource(const Slice& contents)
|
||||
: contents_(contents.data(), contents.size()) {
|
||||
}
|
||||
: contents_(contents.data(), contents.size()) {}
|
||||
|
||||
virtual ~StringSource() {}
|
||||
|
||||
@ -150,14 +148,11 @@ class Constructor {
|
||||
// Finish constructing the data structure with all the keys that have
|
||||
// been added so far. Returns the keys in sorted order in "*keys"
|
||||
// and stores the key/value pairs in "*kvmap"
|
||||
void Finish(const Options& options,
|
||||
std::vector<std::string>* keys,
|
||||
void Finish(const Options& options, std::vector<std::string>* keys,
|
||||
KVMap* kvmap) {
|
||||
*kvmap = data_;
|
||||
keys->clear();
|
||||
for (KVMap::const_iterator it = data_.begin();
|
||||
it != data_.end();
|
||||
++it) {
|
||||
for (KVMap::const_iterator it = data_.begin(); it != data_.end(); ++it) {
|
||||
keys->push_back(it->first);
|
||||
}
|
||||
data_.clear();
|
||||
@ -181,20 +176,14 @@ class Constructor {
|
||||
class BlockConstructor : public Constructor {
|
||||
public:
|
||||
explicit BlockConstructor(const Comparator* cmp)
|
||||
: Constructor(cmp),
|
||||
comparator_(cmp),
|
||||
block_(nullptr) { }
|
||||
~BlockConstructor() {
|
||||
delete block_;
|
||||
}
|
||||
: Constructor(cmp), comparator_(cmp), block_(nullptr) {}
|
||||
~BlockConstructor() { delete block_; }
|
||||
virtual Status FinishImpl(const Options& options, const KVMap& data) {
|
||||
delete block_;
|
||||
block_ = nullptr;
|
||||
BlockBuilder builder(&options);
|
||||
|
||||
for (KVMap::const_iterator it = data.begin();
|
||||
it != data.end();
|
||||
++it) {
|
||||
for (KVMap::const_iterator it = data.begin(); it != data.end(); ++it) {
|
||||
builder.Add(it->first, it->second);
|
||||
}
|
||||
// Open the block
|
||||
@ -221,20 +210,14 @@ class BlockConstructor: public Constructor {
|
||||
class TableConstructor : public Constructor {
|
||||
public:
|
||||
TableConstructor(const Comparator* cmp)
|
||||
: Constructor(cmp),
|
||||
source_(nullptr), table_(nullptr) {
|
||||
}
|
||||
~TableConstructor() {
|
||||
Reset();
|
||||
}
|
||||
: Constructor(cmp), source_(nullptr), table_(nullptr) {}
|
||||
~TableConstructor() { Reset(); }
|
||||
virtual Status FinishImpl(const Options& options, const KVMap& data) {
|
||||
Reset();
|
||||
StringSink sink;
|
||||
TableBuilder builder(options, &sink);
|
||||
|
||||
for (KVMap::const_iterator it = data.begin();
|
||||
it != data.end();
|
||||
++it) {
|
||||
for (KVMap::const_iterator it = data.begin(); it != data.end(); ++it) {
|
||||
builder.Add(it->first, it->second);
|
||||
ASSERT_TRUE(builder.status().ok());
|
||||
}
|
||||
@ -316,22 +299,17 @@ class KeyConvertingIterator: public Iterator {
|
||||
class MemTableConstructor : public Constructor {
|
||||
public:
|
||||
explicit MemTableConstructor(const Comparator* cmp)
|
||||
: Constructor(cmp),
|
||||
internal_comparator_(cmp) {
|
||||
: Constructor(cmp), internal_comparator_(cmp) {
|
||||
memtable_ = new MemTable(internal_comparator_);
|
||||
memtable_->Ref();
|
||||
}
|
||||
~MemTableConstructor() {
|
||||
memtable_->Unref();
|
||||
}
|
||||
~MemTableConstructor() { memtable_->Unref(); }
|
||||
virtual Status FinishImpl(const Options& options, const KVMap& data) {
|
||||
memtable_->Unref();
|
||||
memtable_ = new MemTable(internal_comparator_);
|
||||
memtable_->Ref();
|
||||
int seq = 1;
|
||||
for (KVMap::const_iterator it = data.begin();
|
||||
it != data.end();
|
||||
++it) {
|
||||
for (KVMap::const_iterator it = data.begin(); it != data.end(); ++it) {
|
||||
memtable_->Add(seq, kTypeValue, it->first, it->second);
|
||||
seq++;
|
||||
}
|
||||
@ -349,21 +327,16 @@ class MemTableConstructor: public Constructor {
|
||||
class DBConstructor : public Constructor {
|
||||
public:
|
||||
explicit DBConstructor(const Comparator* cmp)
|
||||
: Constructor(cmp),
|
||||
comparator_(cmp) {
|
||||
: Constructor(cmp), comparator_(cmp) {
|
||||
db_ = nullptr;
|
||||
NewDB();
|
||||
}
|
||||
~DBConstructor() {
|
||||
delete db_;
|
||||
}
|
||||
~DBConstructor() { delete db_; }
|
||||
virtual Status FinishImpl(const Options& options, const KVMap& data) {
|
||||
delete db_;
|
||||
db_ = nullptr;
|
||||
NewDB();
|
||||
for (KVMap::const_iterator it = data.begin();
|
||||
it != data.end();
|
||||
++it) {
|
||||
for (KVMap::const_iterator it = data.begin(); it != data.end(); ++it) {
|
||||
WriteBatch batch;
|
||||
batch.Put(it->first, it->second);
|
||||
ASSERT_TRUE(db_->Write(WriteOptions(), &batch).ok());
|
||||
@ -396,12 +369,7 @@ class DBConstructor: public Constructor {
|
||||
DB* db_;
|
||||
};
|
||||
|
||||
enum TestType {
|
||||
TABLE_TEST,
|
||||
BLOCK_TEST,
|
||||
MEMTABLE_TEST,
|
||||
DB_TEST
|
||||
};
|
||||
enum TestType { TABLE_TEST, BLOCK_TEST, MEMTABLE_TEST, DB_TEST };
|
||||
|
||||
struct TestArgs {
|
||||
TestType type;
|
||||
@ -466,9 +434,7 @@ class Harness {
|
||||
}
|
||||
}
|
||||
|
||||
~Harness() {
|
||||
delete constructor_;
|
||||
}
|
||||
~Harness() { delete constructor_; }
|
||||
|
||||
void Add(const std::string& key, const std::string& value) {
|
||||
constructor_->Add(key, value);
|
||||
@ -490,8 +456,7 @@ class Harness {
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
iter->SeekToFirst();
|
||||
for (KVMap::const_iterator model_iter = data.begin();
|
||||
model_iter != data.end();
|
||||
++model_iter) {
|
||||
model_iter != data.end(); ++model_iter) {
|
||||
ASSERT_EQ(ToString(data, model_iter), ToString(iter));
|
||||
iter->Next();
|
||||
}
|
||||
@ -505,8 +470,7 @@ class Harness {
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
iter->SeekToLast();
|
||||
for (KVMap::const_reverse_iterator model_iter = data.rbegin();
|
||||
model_iter != data.rend();
|
||||
++model_iter) {
|
||||
model_iter != data.rend(); ++model_iter) {
|
||||
ASSERT_EQ(ToString(data, model_iter), ToString(iter));
|
||||
iter->Prev();
|
||||
}
|
||||
@ -514,8 +478,7 @@ class Harness {
|
||||
delete iter;
|
||||
}
|
||||
|
||||
void TestRandomAccess(Random* rnd,
|
||||
const std::vector<std::string>& keys,
|
||||
void TestRandomAccess(Random* rnd, const std::vector<std::string>& keys,
|
||||
const KVMap& data) {
|
||||
static const bool kVerbose = false;
|
||||
Iterator* iter = constructor_->NewIterator();
|
||||
@ -546,8 +509,8 @@ class Harness {
|
||||
case 2: {
|
||||
std::string key = PickRandomKey(rnd, keys);
|
||||
model_iter = data.lower_bound(key);
|
||||
if (kVerbose) fprintf(stderr, "Seek '%s'\n",
|
||||
EscapeString(key).c_str());
|
||||
if (kVerbose)
|
||||
fprintf(stderr, "Seek '%s'\n", EscapeString(key).c_str());
|
||||
iter->Seek(Slice(key));
|
||||
ASSERT_EQ(ToString(data, model_iter), ToString(iter));
|
||||
break;
|
||||
@ -621,7 +584,7 @@ class Harness {
|
||||
break;
|
||||
case 1: {
|
||||
// Attempt to return something smaller than an existing key
|
||||
if (result.size() > 0 && result[result.size()-1] > '\0') {
|
||||
if (!result.empty() && result[result.size() - 1] > '\0') {
|
||||
result[result.size() - 1]--;
|
||||
}
|
||||
break;
|
||||
@ -720,8 +683,8 @@ TEST(Harness, Randomized) {
|
||||
for (int num_entries = 0; num_entries < 2000;
|
||||
num_entries += (num_entries < 50 ? 1 : 200)) {
|
||||
if ((num_entries % 10) == 0) {
|
||||
fprintf(stderr, "case %d of %d: num_entries = %d\n",
|
||||
(i + 1), int(kNumTestArgs), num_entries);
|
||||
fprintf(stderr, "case %d of %d: num_entries = %d\n", (i + 1),
|
||||
int(kNumTestArgs), num_entries);
|
||||
}
|
||||
for (int e = 0; e < num_entries; e++) {
|
||||
std::string v;
|
||||
@ -774,8 +737,7 @@ TEST(MemTableTest, Simple) {
|
||||
Iterator* iter = memtable->NewIterator();
|
||||
iter->SeekToFirst();
|
||||
while (iter->Valid()) {
|
||||
fprintf(stderr, "key: '%s' -> '%s'\n",
|
||||
iter->key().ToString().c_str(),
|
||||
fprintf(stderr, "key: '%s' -> '%s'\n", iter->key().ToString().c_str(),
|
||||
iter->value().ToString().c_str());
|
||||
iter->Next();
|
||||
}
|
||||
@ -788,8 +750,7 @@ static bool Between(uint64_t val, uint64_t low, uint64_t high) {
|
||||
bool result = (val >= low) && (val <= high);
|
||||
if (!result) {
|
||||
fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n",
|
||||
(unsigned long long)(val),
|
||||
(unsigned long long)(low),
|
||||
(unsigned long long)(val), (unsigned long long)(low),
|
||||
(unsigned long long)(high));
|
||||
}
|
||||
return result;
|
||||
@ -824,7 +785,6 @@ TEST(TableTest, ApproximateOffsetOfPlain) {
|
||||
ASSERT_TRUE(Between(c.ApproximateOffsetOf("k06"), 510000, 511000));
|
||||
ASSERT_TRUE(Between(c.ApproximateOffsetOf("k07"), 510000, 511000));
|
||||
ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 610000, 612000));
|
||||
|
||||
}
|
||||
|
||||
static bool SnappyCompressionSupported() {
|
||||
@ -871,6 +831,4 @@ TEST(TableTest, ApproximateOffsetOfCompressed) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -17,11 +17,8 @@ typedef Iterator* (*BlockFunction)(void*, const ReadOptions&, const Slice&);
|
||||
|
||||
class TwoLevelIterator : public Iterator {
|
||||
public:
|
||||
TwoLevelIterator(
|
||||
Iterator* index_iter,
|
||||
BlockFunction block_function,
|
||||
void* arg,
|
||||
const ReadOptions& options);
|
||||
TwoLevelIterator(Iterator* index_iter, BlockFunction block_function,
|
||||
void* arg, const ReadOptions& options);
|
||||
|
||||
virtual ~TwoLevelIterator();
|
||||
|
||||
@ -31,9 +28,7 @@ class TwoLevelIterator: public Iterator {
|
||||
virtual void Next();
|
||||
virtual void Prev();
|
||||
|
||||
virtual bool Valid() const {
|
||||
return data_iter_.Valid();
|
||||
}
|
||||
virtual bool Valid() const { return data_iter_.Valid(); }
|
||||
virtual Slice key() const {
|
||||
assert(Valid());
|
||||
return data_iter_.key();
|
||||
@ -73,20 +68,16 @@ class TwoLevelIterator: public Iterator {
|
||||
std::string data_block_handle_;
|
||||
};
|
||||
|
||||
TwoLevelIterator::TwoLevelIterator(
|
||||
Iterator* index_iter,
|
||||
BlockFunction block_function,
|
||||
void* arg,
|
||||
TwoLevelIterator::TwoLevelIterator(Iterator* index_iter,
|
||||
BlockFunction block_function, void* arg,
|
||||
const ReadOptions& options)
|
||||
: block_function_(block_function),
|
||||
arg_(arg),
|
||||
options_(options),
|
||||
index_iter_(index_iter),
|
||||
data_iter_(nullptr) {
|
||||
}
|
||||
data_iter_(nullptr) {}
|
||||
|
||||
TwoLevelIterator::~TwoLevelIterator() {
|
||||
}
|
||||
TwoLevelIterator::~TwoLevelIterator() {}
|
||||
|
||||
void TwoLevelIterator::Seek(const Slice& target) {
|
||||
index_iter_.Seek(target);
|
||||
@ -121,7 +112,6 @@ void TwoLevelIterator::Prev() {
|
||||
SkipEmptyDataBlocksBackward();
|
||||
}
|
||||
|
||||
|
||||
void TwoLevelIterator::SkipEmptyDataBlocksForward() {
|
||||
while (data_iter_.iter() == nullptr || !data_iter_.Valid()) {
|
||||
// Move to next block
|
||||
@ -158,7 +148,8 @@ void TwoLevelIterator::InitDataBlock() {
|
||||
SetDataIterator(nullptr);
|
||||
} else {
|
||||
Slice handle = index_iter_.value();
|
||||
if (data_iter_.iter() != nullptr && handle.compare(data_block_handle_) == 0) {
|
||||
if (data_iter_.iter() != nullptr &&
|
||||
handle.compare(data_block_handle_) == 0) {
|
||||
// data_iter_ is already constructed with this iterator, so
|
||||
// no need to change anything
|
||||
} else {
|
||||
@ -171,10 +162,8 @@ void TwoLevelIterator::InitDataBlock() {
|
||||
|
||||
} // namespace
|
||||
|
||||
Iterator* NewTwoLevelIterator(
|
||||
Iterator* index_iter,
|
||||
BlockFunction block_function,
|
||||
void* arg,
|
||||
Iterator* NewTwoLevelIterator(Iterator* index_iter,
|
||||
BlockFunction block_function, void* arg,
|
||||
const ReadOptions& options) {
|
||||
return new TwoLevelIterator(index_iter, block_function, arg, options);
|
||||
}
|
||||
|
@ -22,12 +22,9 @@ struct ReadOptions;
|
||||
// an iterator over the contents of the corresponding block.
|
||||
Iterator* NewTwoLevelIterator(
|
||||
Iterator* index_iter,
|
||||
Iterator* (*block_function)(
|
||||
void* arg,
|
||||
const ReadOptions& options,
|
||||
Iterator* (*block_function)(void* arg, const ReadOptions& options,
|
||||
const Slice& index_value),
|
||||
void* arg,
|
||||
const ReadOptions& options);
|
||||
void* arg, const ReadOptions& options);
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
|
@ -39,7 +39,8 @@ char* Arena::AllocateFallback(size_t bytes) {
|
||||
|
||||
char* Arena::AllocateAligned(size_t bytes) {
|
||||
const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8;
|
||||
assert((align & (align-1)) == 0); // Pointer size should be a power of 2
|
||||
static_assert((align & (align - 1)) == 0,
|
||||
"Pointer size should be a power of 2");
|
||||
size_t current_mod = reinterpret_cast<uintptr_t>(alloc_ptr_) & (align - 1);
|
||||
size_t slop = (current_mod == 0 ? 0 : align - current_mod);
|
||||
size_t needed = bytes + slop;
|
||||
|
@ -11,9 +11,7 @@ namespace leveldb {
|
||||
|
||||
class ArenaTest {};
|
||||
|
||||
TEST(ArenaTest, Empty) {
|
||||
Arena arena;
|
||||
}
|
||||
TEST(ArenaTest, Empty) { Arena arena; }
|
||||
|
||||
TEST(ArenaTest, Simple) {
|
||||
std::vector<std::pair<size_t, char*> > allocated;
|
||||
@ -26,8 +24,9 @@ TEST(ArenaTest, Simple) {
|
||||
if (i % (N / 10) == 0) {
|
||||
s = i;
|
||||
} else {
|
||||
s = rnd.OneIn(4000) ? rnd.Uniform(6000) :
|
||||
(rnd.OneIn(10) ? rnd.Uniform(100) : rnd.Uniform(20));
|
||||
s = rnd.OneIn(4000)
|
||||
? rnd.Uniform(6000)
|
||||
: (rnd.OneIn(10) ? rnd.Uniform(100) : rnd.Uniform(20));
|
||||
}
|
||||
if (s == 0) {
|
||||
// Our arena disallows size 0 allocations.
|
||||
@ -63,6 +62,4 @@ TEST(ArenaTest, Simple) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -20,17 +20,14 @@ class BloomFilterPolicy : public FilterPolicy {
|
||||
size_t k_;
|
||||
|
||||
public:
|
||||
explicit BloomFilterPolicy(int bits_per_key)
|
||||
: bits_per_key_(bits_per_key) {
|
||||
explicit BloomFilterPolicy(int bits_per_key) : bits_per_key_(bits_per_key) {
|
||||
// We intentionally round down to reduce probing cost a little bit
|
||||
k_ = static_cast<size_t>(bits_per_key * 0.69); // 0.69 =~ ln(2)
|
||||
if (k_ < 1) k_ = 1;
|
||||
if (k_ > 30) k_ = 30;
|
||||
}
|
||||
|
||||
virtual const char* Name() const {
|
||||
return "leveldb.BuiltinBloomFilter2";
|
||||
}
|
||||
virtual const char* Name() const { return "leveldb.BuiltinBloomFilter2"; }
|
||||
|
||||
virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
|
||||
// Compute bloom filter size (in both bits and bytes)
|
||||
@ -86,7 +83,7 @@ class BloomFilterPolicy : public FilterPolicy {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
const FilterPolicy* NewBloomFilterPolicy(int bits_per_key) {
|
||||
return new BloomFilterPolicy(bits_per_key);
|
||||
|
@ -27,18 +27,14 @@ class BloomTest {
|
||||
public:
|
||||
BloomTest() : policy_(NewBloomFilterPolicy(10)) {}
|
||||
|
||||
~BloomTest() {
|
||||
delete policy_;
|
||||
}
|
||||
~BloomTest() { delete policy_; }
|
||||
|
||||
void Reset() {
|
||||
keys_.clear();
|
||||
filter_.clear();
|
||||
}
|
||||
|
||||
void Add(const Slice& s) {
|
||||
keys_.push_back(s.ToString());
|
||||
}
|
||||
void Add(const Slice& s) { keys_.push_back(s.ToString()); }
|
||||
|
||||
void Build() {
|
||||
std::vector<Slice> key_slices;
|
||||
@ -52,9 +48,7 @@ class BloomTest {
|
||||
if (kVerbose >= 2) DumpFilter();
|
||||
}
|
||||
|
||||
size_t FilterSize() const {
|
||||
return filter_.size();
|
||||
}
|
||||
size_t FilterSize() const { return filter_.size(); }
|
||||
|
||||
void DumpFilter() {
|
||||
fprintf(stderr, "F(");
|
||||
@ -143,12 +137,14 @@ TEST(BloomTest, VaryingLengths) {
|
||||
rate * 100.0, length, static_cast<int>(FilterSize()));
|
||||
}
|
||||
ASSERT_LE(rate, 0.02); // Must not be over 2%
|
||||
if (rate > 0.0125) mediocre_filters++; // Allowed, but not too often
|
||||
else good_filters++;
|
||||
if (rate > 0.0125)
|
||||
mediocre_filters++; // Allowed, but not too often
|
||||
else
|
||||
good_filters++;
|
||||
}
|
||||
if (kVerbose >= 1) {
|
||||
fprintf(stderr, "Filters: %d good, %d mediocre\n",
|
||||
good_filters, mediocre_filters);
|
||||
fprintf(stderr, "Filters: %d good, %d mediocre\n", good_filters,
|
||||
mediocre_filters);
|
||||
}
|
||||
ASSERT_LE(mediocre_filters, good_filters / 5);
|
||||
}
|
||||
@ -157,6 +153,4 @@ TEST(BloomTest, VaryingLengths) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -14,8 +14,7 @@
|
||||
|
||||
namespace leveldb {
|
||||
|
||||
Cache::~Cache() {
|
||||
}
|
||||
Cache::~Cache() {}
|
||||
|
||||
namespace {
|
||||
|
||||
@ -114,8 +113,7 @@ class HandleTable {
|
||||
// pointer to the trailing slot in the corresponding linked list.
|
||||
LRUHandle** FindPointer(const Slice& key, uint32_t hash) {
|
||||
LRUHandle** ptr = &list_[hash & (length_ - 1)];
|
||||
while (*ptr != nullptr &&
|
||||
((*ptr)->hash != hash || key != (*ptr)->key())) {
|
||||
while (*ptr != nullptr && ((*ptr)->hash != hash || key != (*ptr)->key())) {
|
||||
ptr = &(*ptr)->next_hash;
|
||||
}
|
||||
return ptr;
|
||||
@ -158,8 +156,8 @@ class LRUCache {
|
||||
void SetCapacity(size_t capacity) { capacity_ = capacity; }
|
||||
|
||||
// Like Cache methods, but with an extra "hash" parameter.
|
||||
Cache::Handle* Insert(const Slice& key, uint32_t hash,
|
||||
void* value, size_t charge,
|
||||
Cache::Handle* Insert(const Slice& key, uint32_t hash, void* value,
|
||||
size_t charge,
|
||||
void (*deleter)(const Slice& key, void* value));
|
||||
Cache::Handle* Lookup(const Slice& key, uint32_t hash);
|
||||
void Release(Cache::Handle* handle);
|
||||
@ -265,13 +263,14 @@ void LRUCache::Release(Cache::Handle* handle) {
|
||||
Unref(reinterpret_cast<LRUHandle*>(handle));
|
||||
}
|
||||
|
||||
Cache::Handle* LRUCache::Insert(
|
||||
const Slice& key, uint32_t hash, void* value, size_t charge,
|
||||
void (*deleter)(const Slice& key, void* value)) {
|
||||
Cache::Handle* LRUCache::Insert(const Slice& key, uint32_t hash, void* value,
|
||||
size_t charge,
|
||||
void (*deleter)(const Slice& key,
|
||||
void* value)) {
|
||||
MutexLock l(&mutex_);
|
||||
|
||||
LRUHandle* e = reinterpret_cast<LRUHandle*>(
|
||||
malloc(sizeof(LRUHandle)-1 + key.size()));
|
||||
LRUHandle* e =
|
||||
reinterpret_cast<LRUHandle*>(malloc(sizeof(LRUHandle) - 1 + key.size()));
|
||||
e->value = value;
|
||||
e->deleter = deleter;
|
||||
e->charge = charge;
|
||||
@ -346,13 +345,10 @@ class ShardedLRUCache : public Cache {
|
||||
return Hash(s.data(), s.size(), 0);
|
||||
}
|
||||
|
||||
static uint32_t Shard(uint32_t hash) {
|
||||
return hash >> (32 - kNumShardBits);
|
||||
}
|
||||
static uint32_t Shard(uint32_t hash) { return hash >> (32 - kNumShardBits); }
|
||||
|
||||
public:
|
||||
explicit ShardedLRUCache(size_t capacity)
|
||||
: last_id_(0) {
|
||||
explicit ShardedLRUCache(size_t capacity) : last_id_(0) {
|
||||
const size_t per_shard = (capacity + (kNumShards - 1)) / kNumShards;
|
||||
for (int s = 0; s < kNumShards; s++) {
|
||||
shard_[s].SetCapacity(per_shard);
|
||||
@ -399,8 +395,6 @@ class ShardedLRUCache : public Cache {
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
Cache* NewLRUCache(size_t capacity) {
|
||||
return new ShardedLRUCache(capacity);
|
||||
}
|
||||
Cache* NewLRUCache(size_t capacity) { return new ShardedLRUCache(capacity); }
|
||||
|
||||
} // namespace leveldb
|
||||
|
@ -37,13 +37,9 @@ class CacheTest {
|
||||
std::vector<int> deleted_values_;
|
||||
Cache* cache_;
|
||||
|
||||
CacheTest() : cache_(NewLRUCache(kCacheSize)) {
|
||||
current_ = this;
|
||||
}
|
||||
CacheTest() : cache_(NewLRUCache(kCacheSize)) { current_ = this; }
|
||||
|
||||
~CacheTest() {
|
||||
delete cache_;
|
||||
}
|
||||
~CacheTest() { delete cache_; }
|
||||
|
||||
int Lookup(int key) {
|
||||
Cache::Handle* handle = cache_->Lookup(EncodeKey(key));
|
||||
@ -64,9 +60,7 @@ class CacheTest {
|
||||
&CacheTest::Deleter);
|
||||
}
|
||||
|
||||
void Erase(int key) {
|
||||
cache_->Erase(EncodeKey(key));
|
||||
}
|
||||
void Erase(int key) { cache_->Erase(EncodeKey(key)); }
|
||||
};
|
||||
CacheTest* CacheTest::current_;
|
||||
|
||||
@ -229,6 +223,4 @@ TEST(CacheTest, ZeroSizeCache) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -6,29 +6,29 @@
|
||||
|
||||
namespace leveldb {
|
||||
|
||||
void EncodeFixed32(char* buf, uint32_t value) {
|
||||
void EncodeFixed32(char* dst, uint32_t value) {
|
||||
if (port::kLittleEndian) {
|
||||
memcpy(buf, &value, sizeof(value));
|
||||
memcpy(dst, &value, sizeof(value));
|
||||
} else {
|
||||
buf[0] = value & 0xff;
|
||||
buf[1] = (value >> 8) & 0xff;
|
||||
buf[2] = (value >> 16) & 0xff;
|
||||
buf[3] = (value >> 24) & 0xff;
|
||||
dst[0] = value & 0xff;
|
||||
dst[1] = (value >> 8) & 0xff;
|
||||
dst[2] = (value >> 16) & 0xff;
|
||||
dst[3] = (value >> 24) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void EncodeFixed64(char* buf, uint64_t value) {
|
||||
void EncodeFixed64(char* dst, uint64_t value) {
|
||||
if (port::kLittleEndian) {
|
||||
memcpy(buf, &value, sizeof(value));
|
||||
memcpy(dst, &value, sizeof(value));
|
||||
} else {
|
||||
buf[0] = value & 0xff;
|
||||
buf[1] = (value >> 8) & 0xff;
|
||||
buf[2] = (value >> 16) & 0xff;
|
||||
buf[3] = (value >> 24) & 0xff;
|
||||
buf[4] = (value >> 32) & 0xff;
|
||||
buf[5] = (value >> 40) & 0xff;
|
||||
buf[6] = (value >> 48) & 0xff;
|
||||
buf[7] = (value >> 56) & 0xff;
|
||||
dst[0] = value & 0xff;
|
||||
dst[1] = (value >> 8) & 0xff;
|
||||
dst[2] = (value >> 16) & 0xff;
|
||||
dst[3] = (value >> 24) & 0xff;
|
||||
dst[4] = (value >> 32) & 0xff;
|
||||
dst[5] = (value >> 40) & 0xff;
|
||||
dst[6] = (value >> 48) & 0xff;
|
||||
dst[7] = (value >> 56) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,8 +109,7 @@ int VarintLength(uint64_t v) {
|
||||
return len;
|
||||
}
|
||||
|
||||
const char* GetVarint32PtrFallback(const char* p,
|
||||
const char* limit,
|
||||
const char* GetVarint32PtrFallback(const char* p, const char* limit,
|
||||
uint32_t* value) {
|
||||
uint32_t result = 0;
|
||||
for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) {
|
||||
@ -181,8 +180,7 @@ const char* GetLengthPrefixedSlice(const char* p, const char* limit,
|
||||
|
||||
bool GetLengthPrefixedSlice(Slice* input, Slice* result) {
|
||||
uint32_t len;
|
||||
if (GetVarint32(input, &len) &&
|
||||
input->size() >= len) {
|
||||
if (GetVarint32(input, &len) && input->size() >= len) {
|
||||
*result = Slice(input->data(), len);
|
||||
input->remove_prefix(len);
|
||||
return true;
|
||||
|
@ -64,10 +64,10 @@ inline uint32_t DecodeFixed32(const char* ptr) {
|
||||
memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load
|
||||
return result;
|
||||
} else {
|
||||
return ((static_cast<uint32_t>(static_cast<unsigned char>(ptr[0])))
|
||||
| (static_cast<uint32_t>(static_cast<unsigned char>(ptr[1])) << 8)
|
||||
| (static_cast<uint32_t>(static_cast<unsigned char>(ptr[2])) << 16)
|
||||
| (static_cast<uint32_t>(static_cast<unsigned char>(ptr[3])) << 24));
|
||||
return ((static_cast<uint32_t>(static_cast<unsigned char>(ptr[0]))) |
|
||||
(static_cast<uint32_t>(static_cast<unsigned char>(ptr[1])) << 8) |
|
||||
(static_cast<uint32_t>(static_cast<unsigned char>(ptr[2])) << 16) |
|
||||
(static_cast<uint32_t>(static_cast<unsigned char>(ptr[3])) << 24));
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,11 +85,9 @@ inline uint64_t DecodeFixed64(const char* ptr) {
|
||||
}
|
||||
|
||||
// Internal routine for use by fallback path of GetVarint32Ptr
|
||||
const char* GetVarint32PtrFallback(const char* p,
|
||||
const char* limit,
|
||||
const char* GetVarint32PtrFallback(const char* p, const char* limit,
|
||||
uint32_t* value);
|
||||
inline const char* GetVarint32Ptr(const char* p,
|
||||
const char* limit,
|
||||
inline const char* GetVarint32Ptr(const char* p, const char* limit,
|
||||
uint32_t* value) {
|
||||
if (p < limit) {
|
||||
uint32_t result = *(reinterpret_cast<const unsigned char*>(p));
|
||||
|
@ -134,8 +134,8 @@ TEST(Coding, Varint64) {
|
||||
TEST(Coding, Varint32Overflow) {
|
||||
uint32_t result;
|
||||
std::string input("\x81\x82\x83\x84\x85\x11");
|
||||
ASSERT_TRUE(GetVarint32Ptr(input.data(), input.data() + input.size(), &result)
|
||||
== nullptr);
|
||||
ASSERT_TRUE(GetVarint32Ptr(input.data(), input.data() + input.size(),
|
||||
&result) == nullptr);
|
||||
}
|
||||
|
||||
TEST(Coding, Varint32Truncation) {
|
||||
@ -146,16 +146,16 @@ TEST(Coding, Varint32Truncation) {
|
||||
for (size_t len = 0; len < s.size() - 1; len++) {
|
||||
ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + len, &result) == nullptr);
|
||||
}
|
||||
ASSERT_TRUE(
|
||||
GetVarint32Ptr(s.data(), s.data() + s.size(), &result) != nullptr);
|
||||
ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + s.size(), &result) !=
|
||||
nullptr);
|
||||
ASSERT_EQ(large_value, result);
|
||||
}
|
||||
|
||||
TEST(Coding, Varint64Overflow) {
|
||||
uint64_t result;
|
||||
std::string input("\x81\x82\x83\x84\x85\x81\x82\x83\x84\x85\x11");
|
||||
ASSERT_TRUE(GetVarint64Ptr(input.data(), input.data() + input.size(), &result)
|
||||
== nullptr);
|
||||
ASSERT_TRUE(GetVarint64Ptr(input.data(), input.data() + input.size(),
|
||||
&result) == nullptr);
|
||||
}
|
||||
|
||||
TEST(Coding, Varint64Truncation) {
|
||||
@ -166,8 +166,8 @@ TEST(Coding, Varint64Truncation) {
|
||||
for (size_t len = 0; len < s.size() - 1; len++) {
|
||||
ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + len, &result) == nullptr);
|
||||
}
|
||||
ASSERT_TRUE(
|
||||
GetVarint64Ptr(s.data(), s.data() + s.size(), &result) != nullptr);
|
||||
ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + s.size(), &result) !=
|
||||
nullptr);
|
||||
ASSERT_EQ(large_value, result);
|
||||
}
|
||||
|
||||
@ -193,6 +193,4 @@ TEST(Coding, Strings) {
|
||||
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
@ -20,16 +20,13 @@ class BytewiseComparatorImpl : public Comparator {
|
||||
public:
|
||||
BytewiseComparatorImpl() {}
|
||||
|
||||
virtual const char* Name() const {
|
||||
return "leveldb.BytewiseComparator";
|
||||
}
|
||||
virtual const char* Name() const { return "leveldb.BytewiseComparator"; }
|
||||
|
||||
virtual int Compare(const Slice& a, const Slice& b) const {
|
||||
return a.compare(b);
|
||||
}
|
||||
|
||||
virtual void FindShortestSeparator(
|
||||
std::string* start,
|
||||
virtual void FindShortestSeparator(std::string* start,
|
||||
const Slice& limit) const {
|
||||
// Find length of common prefix
|
||||
size_t min_length = std::min(start->size(), limit.size());
|
||||
|
@ -256,8 +256,8 @@ inline uint32_t ReadUint32LE(const uint8_t* buffer) {
|
||||
template <int N>
|
||||
constexpr inline const uint8_t* RoundUp(const uint8_t* pointer) {
|
||||
return reinterpret_cast<uint8_t*>(
|
||||
(reinterpret_cast<uintptr_t>(pointer) + (N - 1))
|
||||
& ~static_cast<uintptr_t>(N - 1));
|
||||
(reinterpret_cast<uintptr_t>(pointer) + (N - 1)) &
|
||||
~static_cast<uintptr_t>(N - 1));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -273,14 +273,14 @@ static bool CanAccelerateCRC32C() {
|
||||
return port::AcceleratedCRC32C(0, kTestCRCBuffer, kBufSize) == kTestCRCValue;
|
||||
}
|
||||
|
||||
uint32_t Extend(uint32_t crc, const char* buf, size_t size) {
|
||||
uint32_t Extend(uint32_t crc, const char* data, size_t n) {
|
||||
static bool accelerate = CanAccelerateCRC32C();
|
||||
if (accelerate) {
|
||||
return port::AcceleratedCRC32C(crc, buf, size);
|
||||
return port::AcceleratedCRC32C(crc, data, n);
|
||||
}
|
||||
|
||||
const uint8_t* p = reinterpret_cast<const uint8_t*>(buf);
|
||||
const uint8_t* e = p + size;
|
||||
const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
|
||||
const uint8_t* e = p + n;
|
||||
uint32_t l = crc ^ kCRC32Xor;
|
||||
|
||||
// Process one byte at a time.
|
||||
|
@ -17,9 +17,7 @@ namespace crc32c {
|
||||
uint32_t Extend(uint32_t init_crc, const char* data, size_t n);
|
||||
|
||||
// Return the crc32c of data[0,n-1]
|
||||
inline uint32_t Value(const char* data, size_t n) {
|
||||
return Extend(0, data, n);
|
||||
}
|
||||
inline uint32_t Value(const char* data, size_t n) { return Extend(0, data, n); }
|
||||
|
||||
static const uint32_t kMaskDelta = 0xa282ead8ul;
|
||||
|
||||
|
@ -31,29 +31,18 @@ TEST(CRC, StandardResults) {
|
||||
ASSERT_EQ(0x113fdb5c, Value(buf, sizeof(buf)));
|
||||
|
||||
unsigned char data[48] = {
|
||||
0x01, 0xc0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x14,
|
||||
0x00, 0x00, 0x00, 0x18,
|
||||
0x28, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x28, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
ASSERT_EQ(0xd9963a56, Value(reinterpret_cast<char*>(data), sizeof(data)));
|
||||
}
|
||||
|
||||
TEST(CRC, Values) {
|
||||
ASSERT_NE(Value("a", 1), Value("foo", 3));
|
||||
}
|
||||
TEST(CRC, Values) { ASSERT_NE(Value("a", 1), Value("foo", 3)); }
|
||||
|
||||
TEST(CRC, Extend) {
|
||||
ASSERT_EQ(Value("hello world", 11),
|
||||
Extend(Value("hello ", 6), "world", 5));
|
||||
ASSERT_EQ(Value("hello world", 11), Extend(Value("hello ", 6), "world", 5));
|
||||
}
|
||||
|
||||
TEST(CRC, Mask) {
|
||||
@ -67,6 +56,4 @@ TEST(CRC, Mask) {
|
||||
} // namespace crc32c
|
||||
} // namespace leveldb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return leveldb::test::RunAllTests();
|
||||
}
|
||||
int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
|
||||
|
24
util/env.cc
24
util/env.cc
@ -6,27 +6,21 @@
|
||||
|
||||
namespace leveldb {
|
||||
|
||||
Env::~Env() {
|
||||
}
|
||||
Env::~Env() {}
|
||||
|
||||
Status Env::NewAppendableFile(const std::string& fname, WritableFile** result) {
|
||||
return Status::NotSupported("NewAppendableFile", fname);
|
||||
}
|
||||
|
||||
SequentialFile::~SequentialFile() {
|
||||
}
|
||||
SequentialFile::~SequentialFile() {}
|
||||
|
||||
RandomAccessFile::~RandomAccessFile() {
|
||||
}
|
||||
RandomAccessFile::~RandomAccessFile() {}
|
||||
|
||||
WritableFile::~WritableFile() {
|
||||
}
|
||||
WritableFile::~WritableFile() {}
|
||||
|
||||
Logger::~Logger() {
|
||||
}
|
||||
Logger::~Logger() {}
|
||||
|
||||
FileLock::~FileLock() {
|
||||
}
|
||||
FileLock::~FileLock() {}
|
||||
|
||||
void Log(Logger* info_log, const char* format, ...) {
|
||||
if (info_log != nullptr) {
|
||||
@ -38,8 +32,7 @@ void Log(Logger* info_log, const char* format, ...) {
|
||||
}
|
||||
|
||||
static Status DoWriteStringToFile(Env* env, const Slice& data,
|
||||
const std::string& fname,
|
||||
bool should_sync) {
|
||||
const std::string& fname, bool should_sync) {
|
||||
WritableFile* file;
|
||||
Status s = env->NewWritableFile(fname, &file);
|
||||
if (!s.ok()) {
|
||||
@ -94,7 +87,6 @@ Status ReadFileToString(Env* env, const std::string& fname, std::string* data) {
|
||||
return s;
|
||||
}
|
||||
|
||||
EnvWrapper::~EnvWrapper() {
|
||||
}
|
||||
EnvWrapper::~EnvWrapper() {}
|
||||
|
||||
} // namespace leveldb
|
||||
|
@ -32,8 +32,8 @@
|
||||
#include "leveldb/status.h"
|
||||
#include "port/port.h"
|
||||
#include "port/thread_annotations.h"
|
||||
#include "util/posix_logger.h"
|
||||
#include "util/env_posix_test_helper.h"
|
||||
#include "util/posix_logger.h"
|
||||
|
||||
namespace leveldb {
|
||||
|
||||
@ -76,8 +76,7 @@ class Limiter {
|
||||
int old_acquires_allowed =
|
||||
acquires_allowed_.fetch_sub(1, std::memory_order_relaxed);
|
||||
|
||||
if (old_acquires_allowed > 0)
|
||||
return true;
|
||||
if (old_acquires_allowed > 0) return true;
|
||||
|
||||
acquires_allowed_.fetch_add(1, std::memory_order_relaxed);
|
||||
return false;
|
||||
@ -85,9 +84,7 @@ class Limiter {
|
||||
|
||||
// Release a resource acquired by a previous call to Acquire() that returned
|
||||
// true.
|
||||
void Release() {
|
||||
acquires_allowed_.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); }
|
||||
|
||||
private:
|
||||
// The number of available resources.
|
||||
@ -214,7 +211,9 @@ class PosixMmapReadableFile final : public RandomAccessFile {
|
||||
// instance is destroyed.
|
||||
PosixMmapReadableFile(std::string filename, char* mmap_base, size_t length,
|
||||
Limiter* mmap_limiter)
|
||||
: mmap_base_(mmap_base), length_(length), mmap_limiter_(mmap_limiter),
|
||||
: mmap_base_(mmap_base),
|
||||
length_(length),
|
||||
mmap_limiter_(mmap_limiter),
|
||||
filename_(std::move(filename)) {}
|
||||
|
||||
~PosixMmapReadableFile() override {
|
||||
@ -243,8 +242,11 @@ class PosixMmapReadableFile final : public RandomAccessFile {
|
||||
class PosixWritableFile final : public WritableFile {
|
||||
public:
|
||||
PosixWritableFile(std::string filename, int fd)
|
||||
: pos_(0), fd_(fd), is_manifest_(IsManifest(filename)),
|
||||
filename_(std::move(filename)), dirname_(Dirname(filename_)) {}
|
||||
: pos_(0),
|
||||
fd_(fd),
|
||||
is_manifest_(IsManifest(filename)),
|
||||
filename_(std::move(filename)),
|
||||
dirname_(Dirname(filename_)) {}
|
||||
|
||||
~PosixWritableFile() override {
|
||||
if (fd_ >= 0) {
|
||||
@ -292,9 +294,7 @@ class PosixWritableFile final : public WritableFile {
|
||||
return status;
|
||||
}
|
||||
|
||||
Status Flush() override {
|
||||
return FlushBuffer();
|
||||
}
|
||||
Status Flush() override { return FlushBuffer(); }
|
||||
|
||||
Status Sync() override {
|
||||
// Ensure new files referred to by the manifest are in the filesystem.
|
||||
@ -517,12 +517,12 @@ class PosixEnv : public Env {
|
||||
uint64_t file_size;
|
||||
Status status = GetFileSize(filename, &file_size);
|
||||
if (status.ok()) {
|
||||
void* mmap_base = ::mmap(/*addr=*/nullptr, file_size, PROT_READ,
|
||||
MAP_SHARED, fd, 0);
|
||||
void* mmap_base =
|
||||
::mmap(/*addr=*/nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (mmap_base != MAP_FAILED) {
|
||||
*result = new PosixMmapReadableFile(
|
||||
filename, reinterpret_cast<char*>(mmap_base), file_size,
|
||||
&mmap_limiter_);
|
||||
*result = new PosixMmapReadableFile(filename,
|
||||
reinterpret_cast<char*>(mmap_base),
|
||||
file_size, &mmap_limiter_);
|
||||
} else {
|
||||
status = PosixError(filename, errno);
|
||||
}
|
||||
@ -691,9 +691,7 @@ class PosixEnv : public Env {
|
||||
return static_cast<uint64_t>(tv.tv_sec) * kUsecondsPerSecond + tv.tv_usec;
|
||||
}
|
||||
|
||||
void SleepForMicroseconds(int micros) override {
|
||||
::usleep(micros);
|
||||
}
|
||||
void SleepForMicroseconds(int micros) override { ::usleep(micros); }
|
||||
|
||||
private:
|
||||
void BackgroundThreadMain();
|
||||
@ -716,7 +714,6 @@ class PosixEnv : public Env {
|
||||
void* const arg;
|
||||
};
|
||||
|
||||
|
||||
port::Mutex background_work_mutex_;
|
||||
port::CondVar background_work_cv_ GUARDED_BY(background_work_mutex_);
|
||||
bool started_background_thread_ GUARDED_BY(background_work_mutex_);
|
||||
@ -730,9 +727,7 @@ class PosixEnv : public Env {
|
||||
};
|
||||
|
||||
// Return the maximum number of concurrent mmaps.
|
||||
int MaxMmaps() {
|
||||
return g_mmap_limit;
|
||||
}
|
||||
int MaxMmaps() { return g_mmap_limit; }
|
||||
|
||||
// Return the maximum number of read-only files to keep open.
|
||||
int MaxOpenFiles() {
|
||||
@ -758,8 +753,7 @@ PosixEnv::PosixEnv()
|
||||
: background_work_cv_(&background_work_mutex_),
|
||||
started_background_thread_(false),
|
||||
mmap_limiter_(MaxMmaps()),
|
||||
fd_limiter_(MaxOpenFiles()) {
|
||||
}
|
||||
fd_limiter_(MaxOpenFiles()) {}
|
||||
|
||||
void PosixEnv::Schedule(
|
||||
void (*background_work_function)(void* background_work_arg),
|
||||
@ -792,8 +786,7 @@ void PosixEnv::BackgroundThreadMain() {
|
||||
}
|
||||
|
||||
assert(!background_work_queue_.empty());
|
||||
auto background_work_function =
|
||||
background_work_queue_.front().function;
|
||||
auto background_work_function = background_work_queue_.front().function;
|
||||
void* background_work_arg = background_work_queue_.front().arg;
|
||||
background_work_queue_.pop();
|
||||
|
||||
|
@ -3,14 +3,12 @@
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include "leveldb/env.h"
|
||||
|
||||
#include "port/port.h"
|
||||
#include "util/testharness.h"
|
||||
#include "util/env_posix_test_helper.h"
|
||||
#include "util/testharness.h"
|
||||
|
||||
namespace leveldb {
|
||||
|
||||
static const int kDelayMicros = 100000;
|
||||
static const int kReadOnlyFileLimit = 4;
|
||||
static const int kMMapLimit = 4;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user