@nxtedition/rocksdb 7.0.12 → 7.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deps/rocksdb/rocksdb/CMakeLists.txt +1 -0
- package/deps/rocksdb/rocksdb/Makefile +3 -0
- package/deps/rocksdb/rocksdb/TARGETS +6 -0
- package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +12 -7
- package/deps/rocksdb/rocksdb/cache/cache_key.h +2 -0
- package/deps/rocksdb/rocksdb/cache/fast_lru_cache.cc +18 -6
- package/deps/rocksdb/rocksdb/cache/fast_lru_cache.h +13 -5
- package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +89 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_file_reader.cc +18 -28
- package/deps/rocksdb/rocksdb/db/blob/blob_source.cc +147 -2
- package/deps/rocksdb/rocksdb/db/blob/blob_source.h +30 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_source_test.cc +403 -30
- package/deps/rocksdb/rocksdb/db/c.cc +159 -5
- package/deps/rocksdb/rocksdb/db/c_test.c +108 -0
- package/deps/rocksdb/rocksdb/db/column_family.cc +2 -1
- package/deps/rocksdb/rocksdb/db/column_family.h +7 -5
- package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +22 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction.h +8 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +6 -3
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator_test.cc +15 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +35 -2
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +55 -0
- package/deps/rocksdb/rocksdb/db/db_basic_test.cc +21 -19
- package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +60 -1
- package/deps/rocksdb/rocksdb/db/db_flush_test.cc +247 -6
- package/deps/rocksdb/rocksdb/db/db_impl/compacted_db_impl.h +10 -0
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +6 -33
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +10 -2
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +7 -15
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +17 -3
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +10 -4
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.h +9 -0
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.h +8 -0
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +32 -0
- package/deps/rocksdb/rocksdb/db/db_inplace_update_test.cc +54 -0
- package/deps/rocksdb/rocksdb/db/db_iter.cc +50 -2
- package/deps/rocksdb/rocksdb/db/db_iter.h +2 -0
- package/deps/rocksdb/rocksdb/db/db_kv_checksum_test.cc +56 -25
- package/deps/rocksdb/rocksdb/db/db_options_test.cc +1 -1
- package/deps/rocksdb/rocksdb/db/db_test.cc +9 -0
- package/deps/rocksdb/rocksdb/db/flush_job.cc +17 -8
- package/deps/rocksdb/rocksdb/db/flush_job.h +1 -1
- package/deps/rocksdb/rocksdb/db/log_writer.h +1 -1
- package/deps/rocksdb/rocksdb/db/memtable.cc +103 -93
- package/deps/rocksdb/rocksdb/db/memtable.h +3 -3
- package/deps/rocksdb/rocksdb/db/merge_helper.cc +7 -2
- package/deps/rocksdb/rocksdb/db/version_edit.h +1 -1
- package/deps/rocksdb/rocksdb/db/version_set.cc +13 -5
- package/deps/rocksdb/rocksdb/db/version_set_sync_and_async.h +5 -0
- package/deps/rocksdb/rocksdb/db/wide/db_wide_basic_test.cc +213 -0
- package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.cc +6 -7
- package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization_test.cc +16 -0
- package/deps/rocksdb/rocksdb/db/write_batch.cc +154 -2
- package/deps/rocksdb/rocksdb/db/write_batch_internal.h +3 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +4 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compaction_filter.h +8 -3
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +21 -1
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +31 -4
- package/deps/rocksdb/rocksdb/env/env_test.cc +2 -2
- package/deps/rocksdb/rocksdb/env/fs_remap.cc +4 -0
- package/deps/rocksdb/rocksdb/file/random_access_file_reader.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +17 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/c.h +136 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/db.h +6 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/env.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/options.h +23 -23
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +7 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/write_batch_with_index.h +11 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/write_batch.h +14 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/write_batch_base.h +5 -0
- package/deps/rocksdb/rocksdb/options/cf_options.cc +7 -0
- package/deps/rocksdb/rocksdb/options/cf_options.h +19 -0
- package/deps/rocksdb/rocksdb/options/db_options.cc +1 -6
- package/deps/rocksdb/rocksdb/options/db_options.h +0 -1
- package/deps/rocksdb/rocksdb/options/options.cc +4 -1
- package/deps/rocksdb/rocksdb/options/options_helper.cc +2 -0
- package/deps/rocksdb/rocksdb/options/options_settable_test.cc +1 -0
- package/deps/rocksdb/rocksdb/options/options_test.cc +4 -4
- package/deps/rocksdb/rocksdb/port/win/env_win.cc +1 -1
- package/deps/rocksdb/rocksdb/src.mk +1 -0
- package/deps/rocksdb/rocksdb/table/block_based/block.cc +5 -3
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +2 -2
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +16 -9
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +4 -2
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +1 -1
- package/deps/rocksdb/rocksdb/table/block_based/filter_block.h +13 -7
- package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.cc +7 -3
- package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.h +4 -2
- package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.cc +28 -17
- package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.h +15 -9
- package/deps/rocksdb/rocksdb/table/block_based/full_filter_block_test.cc +32 -16
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +28 -18
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.h +15 -6
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +16 -7
- package/deps/rocksdb/rocksdb/table/block_fetcher.cc +1 -1
- package/deps/rocksdb/rocksdb/table/get_context.cc +27 -6
- package/deps/rocksdb/rocksdb/table/get_context.h +2 -0
- package/deps/rocksdb/rocksdb/table/table_test.cc +5 -5
- package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +46 -0
- package/deps/rocksdb/rocksdb/util/filter_bench.cc +3 -1
- package/deps/rocksdb/rocksdb/util/mutexlock.h +1 -1
- package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +1 -1
- package/package.json +1 -1
- package/prebuilds/linux-x64/node.napi.node +0 -0
|
@@ -27,8 +27,9 @@
|
|
|
27
27
|
|
|
28
28
|
namespace ROCKSDB_NAMESPACE {
|
|
29
29
|
Options SanitizeOptions(const std::string& dbname, const Options& src,
|
|
30
|
-
bool read_only) {
|
|
31
|
-
auto db_options =
|
|
30
|
+
bool read_only, Status* logger_creation_s) {
|
|
31
|
+
auto db_options =
|
|
32
|
+
SanitizeOptions(dbname, DBOptions(src), read_only, logger_creation_s);
|
|
32
33
|
ImmutableDBOptions immutable_db_options(db_options);
|
|
33
34
|
auto cf_options =
|
|
34
35
|
SanitizeOptions(immutable_db_options, ColumnFamilyOptions(src));
|
|
@@ -36,7 +37,7 @@ Options SanitizeOptions(const std::string& dbname, const Options& src,
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
DBOptions SanitizeOptions(const std::string& dbname, const DBOptions& src,
|
|
39
|
-
bool read_only) {
|
|
40
|
+
bool read_only, Status* logger_creation_s) {
|
|
40
41
|
DBOptions result(src);
|
|
41
42
|
|
|
42
43
|
if (result.env == nullptr) {
|
|
@@ -59,6 +60,9 @@ DBOptions SanitizeOptions(const std::string& dbname, const DBOptions& src,
|
|
|
59
60
|
if (!s.ok()) {
|
|
60
61
|
// No place suitable for logging
|
|
61
62
|
result.info_log = nullptr;
|
|
63
|
+
if (logger_creation_s) {
|
|
64
|
+
*logger_creation_s = s;
|
|
65
|
+
}
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
|
|
@@ -1790,9 +1794,11 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
|
|
|
1790
1794
|
|
|
1791
1795
|
DBImpl* impl = new DBImpl(db_options, dbname, seq_per_batch, batch_per_txn);
|
|
1792
1796
|
if (!impl->immutable_db_options_.info_log) {
|
|
1793
|
-
s =
|
|
1797
|
+
s = impl->init_logger_creation_s_;
|
|
1794
1798
|
delete impl;
|
|
1795
1799
|
return s;
|
|
1800
|
+
} else {
|
|
1801
|
+
assert(impl->init_logger_creation_s_.ok());
|
|
1796
1802
|
}
|
|
1797
1803
|
s = impl->env_->CreateDirIfMissing(impl->immutable_db_options_.GetWalDir());
|
|
1798
1804
|
if (s.ok()) {
|
|
@@ -48,6 +48,15 @@ class DBImplReadOnly : public DBImpl {
|
|
|
48
48
|
const Slice& /*key*/, const Slice& /*value*/) override {
|
|
49
49
|
return Status::NotSupported("Not supported operation in read only mode.");
|
|
50
50
|
}
|
|
51
|
+
|
|
52
|
+
using DBImpl::PutEntity;
|
|
53
|
+
Status PutEntity(const WriteOptions& /* options */,
|
|
54
|
+
ColumnFamilyHandle* /* column_family */,
|
|
55
|
+
const Slice& /* key */,
|
|
56
|
+
const WideColumns& /* columns */) override {
|
|
57
|
+
return Status::NotSupported("Not supported operation in read only mode.");
|
|
58
|
+
}
|
|
59
|
+
|
|
51
60
|
using DBImpl::Merge;
|
|
52
61
|
virtual Status Merge(const WriteOptions& /*options*/,
|
|
53
62
|
ColumnFamilyHandle* /*column_family*/,
|
|
@@ -119,6 +119,14 @@ class DBImplSecondary : public DBImpl {
|
|
|
119
119
|
return Status::NotSupported("Not supported operation in secondary mode.");
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
using DBImpl::PutEntity;
|
|
123
|
+
Status PutEntity(const WriteOptions& /* options */,
|
|
124
|
+
ColumnFamilyHandle* /* column_family */,
|
|
125
|
+
const Slice& /* key */,
|
|
126
|
+
const WideColumns& /* columns */) override {
|
|
127
|
+
return Status::NotSupported("Not supported operation in secondary mode.");
|
|
128
|
+
}
|
|
129
|
+
|
|
122
130
|
using DBImpl::Merge;
|
|
123
131
|
Status Merge(const WriteOptions& /*options*/,
|
|
124
132
|
ColumnFamilyHandle* /*column_family*/, const Slice& /*key*/,
|
|
@@ -37,6 +37,17 @@ Status DBImpl::Put(const WriteOptions& o, ColumnFamilyHandle* column_family,
|
|
|
37
37
|
return DB::Put(o, column_family, key, ts, val);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
Status DBImpl::PutEntity(const WriteOptions& options,
|
|
41
|
+
ColumnFamilyHandle* column_family, const Slice& key,
|
|
42
|
+
const WideColumns& columns) {
|
|
43
|
+
const Status s = FailIfCfHasTs(column_family);
|
|
44
|
+
if (!s.ok()) {
|
|
45
|
+
return s;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return DB::PutEntity(options, column_family, key, columns);
|
|
49
|
+
}
|
|
50
|
+
|
|
40
51
|
Status DBImpl::Merge(const WriteOptions& o, ColumnFamilyHandle* column_family,
|
|
41
52
|
const Slice& key, const Slice& val) {
|
|
42
53
|
const Status s = FailIfCfHasTs(column_family);
|
|
@@ -2236,6 +2247,27 @@ Status DB::Put(const WriteOptions& opt, ColumnFamilyHandle* column_family,
|
|
|
2236
2247
|
return Write(opt, &batch);
|
|
2237
2248
|
}
|
|
2238
2249
|
|
|
2250
|
+
Status DB::PutEntity(const WriteOptions& options,
|
|
2251
|
+
ColumnFamilyHandle* column_family, const Slice& key,
|
|
2252
|
+
const WideColumns& columns) {
|
|
2253
|
+
const ColumnFamilyHandle* const default_cf = DefaultColumnFamily();
|
|
2254
|
+
assert(default_cf);
|
|
2255
|
+
|
|
2256
|
+
const Comparator* const default_cf_ucmp = default_cf->GetComparator();
|
|
2257
|
+
assert(default_cf_ucmp);
|
|
2258
|
+
|
|
2259
|
+
WriteBatch batch(/* reserved_bytes */ 0, /* max_bytes */ 0,
|
|
2260
|
+
options.protection_bytes_per_key,
|
|
2261
|
+
default_cf_ucmp->timestamp_size());
|
|
2262
|
+
|
|
2263
|
+
const Status s = batch.PutEntity(column_family, key, columns);
|
|
2264
|
+
if (!s.ok()) {
|
|
2265
|
+
return s;
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
return Write(options, &batch);
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2239
2271
|
Status DB::Delete(const WriteOptions& opt, ColumnFamilyHandle* column_family,
|
|
2240
2272
|
const Slice& key) {
|
|
2241
2273
|
WriteBatch batch(0 /* reserved_bytes */, 0 /* max_bytes */,
|
|
@@ -65,6 +65,60 @@ TEST_F(DBTestInPlaceUpdate, InPlaceUpdateLargeNewValue) {
|
|
|
65
65
|
} while (ChangeCompactOptions());
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
TEST_F(DBTestInPlaceUpdate, InPlaceUpdateEntitySmallerNewValue) {
|
|
69
|
+
do {
|
|
70
|
+
Options options = CurrentOptions();
|
|
71
|
+
options.create_if_missing = true;
|
|
72
|
+
options.inplace_update_support = true;
|
|
73
|
+
options.env = env_;
|
|
74
|
+
options.allow_concurrent_memtable_write = false;
|
|
75
|
+
|
|
76
|
+
Reopen(options);
|
|
77
|
+
CreateAndReopenWithCF({"pikachu"}, options);
|
|
78
|
+
|
|
79
|
+
// Update key with values of smaller size
|
|
80
|
+
constexpr int num_values = 10;
|
|
81
|
+
for (int i = num_values; i > 0; --i) {
|
|
82
|
+
constexpr char key[] = "key";
|
|
83
|
+
const std::string value = DummyString(i, 'a');
|
|
84
|
+
WideColumns wide_columns{{"attr", value}};
|
|
85
|
+
|
|
86
|
+
ASSERT_OK(db_->PutEntity(WriteOptions(), handles_[1], key, wide_columns));
|
|
87
|
+
// TODO: use Get to check entity once it's supported
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Only 1 instance for that key.
|
|
91
|
+
validateNumberOfEntries(1, 1);
|
|
92
|
+
} while (ChangeCompactOptions());
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
TEST_F(DBTestInPlaceUpdate, InPlaceUpdateEntityLargerNewValue) {
|
|
96
|
+
do {
|
|
97
|
+
Options options = CurrentOptions();
|
|
98
|
+
options.create_if_missing = true;
|
|
99
|
+
options.inplace_update_support = true;
|
|
100
|
+
options.env = env_;
|
|
101
|
+
options.allow_concurrent_memtable_write = false;
|
|
102
|
+
|
|
103
|
+
Reopen(options);
|
|
104
|
+
CreateAndReopenWithCF({"pikachu"}, options);
|
|
105
|
+
|
|
106
|
+
// Update key with values of larger size
|
|
107
|
+
constexpr int num_values = 10;
|
|
108
|
+
for (int i = 0; i < num_values; ++i) {
|
|
109
|
+
constexpr char key[] = "key";
|
|
110
|
+
const std::string value = DummyString(i, 'a');
|
|
111
|
+
WideColumns wide_columns{{"attr", value}};
|
|
112
|
+
|
|
113
|
+
ASSERT_OK(db_->PutEntity(WriteOptions(), handles_[1], key, wide_columns));
|
|
114
|
+
// TODO: use Get to check entity once it's supported
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// All 10 updates exist in the internal iterator
|
|
118
|
+
validateNumberOfEntries(num_values, 1);
|
|
119
|
+
} while (ChangeCompactOptions());
|
|
120
|
+
}
|
|
121
|
+
|
|
68
122
|
TEST_F(DBTestInPlaceUpdate, InPlaceUpdateCallbackSmallerSize) {
|
|
69
123
|
do {
|
|
70
124
|
Options options = CurrentOptions();
|
|
@@ -207,6 +207,15 @@ bool DBIter::SetBlobValueIfNeeded(const Slice& user_key,
|
|
|
207
207
|
return true;
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
+
bool DBIter::SetWideColumnValueIfNeeded(const Slice& /* wide_columns_slice */) {
|
|
211
|
+
assert(!is_blob_);
|
|
212
|
+
|
|
213
|
+
// TODO: support wide-column entities
|
|
214
|
+
status_ = Status::NotSupported("Encountered unexpected wide-column entity");
|
|
215
|
+
valid_ = false;
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
|
|
210
219
|
// PRE: saved_key_ has the current user key if skipping_saved_key
|
|
211
220
|
// POST: saved_key_ should have the next user key if valid_,
|
|
212
221
|
// if the current entry is a result of merge
|
|
@@ -341,6 +350,7 @@ bool DBIter::FindNextUserEntryInternal(bool skipping_saved_key,
|
|
|
341
350
|
break;
|
|
342
351
|
case kTypeValue:
|
|
343
352
|
case kTypeBlobIndex:
|
|
353
|
+
case kTypeWideColumnEntity:
|
|
344
354
|
if (timestamp_lb_) {
|
|
345
355
|
saved_key_.SetInternalKey(ikey_);
|
|
346
356
|
|
|
@@ -348,6 +358,10 @@ bool DBIter::FindNextUserEntryInternal(bool skipping_saved_key,
|
|
|
348
358
|
if (!SetBlobValueIfNeeded(ikey_.user_key, iter_.value())) {
|
|
349
359
|
return false;
|
|
350
360
|
}
|
|
361
|
+
} else if (ikey_.type == kTypeWideColumnEntity) {
|
|
362
|
+
if (!SetWideColumnValueIfNeeded(iter_.value())) {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
351
365
|
}
|
|
352
366
|
|
|
353
367
|
valid_ = true;
|
|
@@ -369,6 +383,10 @@ bool DBIter::FindNextUserEntryInternal(bool skipping_saved_key,
|
|
|
369
383
|
if (!SetBlobValueIfNeeded(ikey_.user_key, iter_.value())) {
|
|
370
384
|
return false;
|
|
371
385
|
}
|
|
386
|
+
} else if (ikey_.type == kTypeWideColumnEntity) {
|
|
387
|
+
if (!SetWideColumnValueIfNeeded(iter_.value())) {
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
372
390
|
}
|
|
373
391
|
|
|
374
392
|
valid_ = true;
|
|
@@ -580,6 +598,12 @@ bool DBIter::MergeValuesNewToOld() {
|
|
|
580
598
|
return false;
|
|
581
599
|
}
|
|
582
600
|
return true;
|
|
601
|
+
} else if (kTypeWideColumnEntity == ikey.type) {
|
|
602
|
+
// TODO: support wide-column entities
|
|
603
|
+
status_ = Status::NotSupported(
|
|
604
|
+
"Merge currently not supported for wide-column entities");
|
|
605
|
+
valid_ = false;
|
|
606
|
+
return false;
|
|
583
607
|
} else {
|
|
584
608
|
valid_ = false;
|
|
585
609
|
status_ = Status::Corruption(
|
|
@@ -783,7 +807,8 @@ bool DBIter::FindValueForCurrentKey() {
|
|
|
783
807
|
merge_context_.Clear();
|
|
784
808
|
current_entry_is_merged_ = false;
|
|
785
809
|
// last entry before merge (could be kTypeDeletion,
|
|
786
|
-
// kTypeDeletionWithTimestamp, kTypeSingleDeletion
|
|
810
|
+
// kTypeDeletionWithTimestamp, kTypeSingleDeletion, kTypeValue,
|
|
811
|
+
// kTypeBlobIndex, or kTypeWideColumnEntity)
|
|
787
812
|
ValueType last_not_merge_type = kTypeDeletion;
|
|
788
813
|
ValueType last_key_entry_type = kTypeDeletion;
|
|
789
814
|
|
|
@@ -831,6 +856,7 @@ bool DBIter::FindValueForCurrentKey() {
|
|
|
831
856
|
switch (last_key_entry_type) {
|
|
832
857
|
case kTypeValue:
|
|
833
858
|
case kTypeBlobIndex:
|
|
859
|
+
case kTypeWideColumnEntity:
|
|
834
860
|
if (range_del_agg_.ShouldDelete(
|
|
835
861
|
ikey, RangeDelPositioningMode::kBackwardTraversal)) {
|
|
836
862
|
last_key_entry_type = kTypeRangeDeletion;
|
|
@@ -927,6 +953,12 @@ bool DBIter::FindValueForCurrentKey() {
|
|
|
927
953
|
}
|
|
928
954
|
is_blob_ = false;
|
|
929
955
|
return true;
|
|
956
|
+
} else if (last_not_merge_type == kTypeWideColumnEntity) {
|
|
957
|
+
// TODO: support wide-column entities
|
|
958
|
+
status_ = Status::NotSupported(
|
|
959
|
+
"Merge currently not supported for wide-column entities");
|
|
960
|
+
valid_ = false;
|
|
961
|
+
return false;
|
|
930
962
|
} else {
|
|
931
963
|
assert(last_not_merge_type == kTypeValue);
|
|
932
964
|
s = Merge(&pinned_value_, saved_key_.GetUserKey());
|
|
@@ -944,6 +976,11 @@ bool DBIter::FindValueForCurrentKey() {
|
|
|
944
976
|
return false;
|
|
945
977
|
}
|
|
946
978
|
break;
|
|
979
|
+
case kTypeWideColumnEntity:
|
|
980
|
+
if (!SetWideColumnValueIfNeeded(pinned_value_)) {
|
|
981
|
+
return false;
|
|
982
|
+
}
|
|
983
|
+
break;
|
|
947
984
|
default:
|
|
948
985
|
valid_ = false;
|
|
949
986
|
status_ = Status::Corruption(
|
|
@@ -1034,13 +1071,18 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
|
|
1034
1071
|
Slice ts = ExtractTimestampFromUserKey(ikey.user_key, timestamp_size_);
|
|
1035
1072
|
saved_timestamp_.assign(ts.data(), ts.size());
|
|
1036
1073
|
}
|
|
1037
|
-
if (ikey.type == kTypeValue || ikey.type == kTypeBlobIndex
|
|
1074
|
+
if (ikey.type == kTypeValue || ikey.type == kTypeBlobIndex ||
|
|
1075
|
+
ikey.type == kTypeWideColumnEntity) {
|
|
1038
1076
|
assert(iter_.iter()->IsValuePinned());
|
|
1039
1077
|
pinned_value_ = iter_.value();
|
|
1040
1078
|
if (ikey.type == kTypeBlobIndex) {
|
|
1041
1079
|
if (!SetBlobValueIfNeeded(ikey.user_key, pinned_value_)) {
|
|
1042
1080
|
return false;
|
|
1043
1081
|
}
|
|
1082
|
+
} else if (ikey_.type == kTypeWideColumnEntity) {
|
|
1083
|
+
if (!SetWideColumnValueIfNeeded(pinned_value_)) {
|
|
1084
|
+
return false;
|
|
1085
|
+
}
|
|
1044
1086
|
}
|
|
1045
1087
|
|
|
1046
1088
|
valid_ = true;
|
|
@@ -1109,6 +1151,12 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
|
|
1109
1151
|
}
|
|
1110
1152
|
is_blob_ = false;
|
|
1111
1153
|
return true;
|
|
1154
|
+
} else if (ikey.type == kTypeWideColumnEntity) {
|
|
1155
|
+
// TODO: support wide-column entities
|
|
1156
|
+
status_ = Status::NotSupported(
|
|
1157
|
+
"Merge currently not supported for wide-column entities");
|
|
1158
|
+
valid_ = false;
|
|
1159
|
+
return false;
|
|
1112
1160
|
} else {
|
|
1113
1161
|
valid_ = false;
|
|
1114
1162
|
status_ = Status::Corruption(
|
|
@@ -298,6 +298,8 @@ class DBIter final : public Iterator {
|
|
|
298
298
|
// index when using the integrated BlobDB implementation.
|
|
299
299
|
bool SetBlobValueIfNeeded(const Slice& user_key, const Slice& blob_index);
|
|
300
300
|
|
|
301
|
+
bool SetWideColumnValueIfNeeded(const Slice& wide_columns_slice);
|
|
302
|
+
|
|
301
303
|
Status Merge(const Slice* val, const Slice& user_key);
|
|
302
304
|
|
|
303
305
|
const SliceTransform* prefix_extractor_;
|
|
@@ -15,6 +15,7 @@ enum class WriteBatchOpType {
|
|
|
15
15
|
kSingleDelete,
|
|
16
16
|
kDeleteRange,
|
|
17
17
|
kMerge,
|
|
18
|
+
kPutEntity,
|
|
18
19
|
kNum,
|
|
19
20
|
};
|
|
20
21
|
|
|
@@ -62,18 +63,38 @@ std::pair<WriteBatch, Status> GetWriteBatch(ColumnFamilyHandle* cf_handle,
|
|
|
62
63
|
case WriteBatchOpType::kMerge:
|
|
63
64
|
s = wb.Merge(cf_handle, "key", "val");
|
|
64
65
|
break;
|
|
66
|
+
case WriteBatchOpType::kPutEntity:
|
|
67
|
+
s = wb.PutEntity(cf_handle, "key",
|
|
68
|
+
{{"attr_name1", "foo"}, {"attr_name2", "bar"}});
|
|
69
|
+
break;
|
|
65
70
|
case WriteBatchOpType::kNum:
|
|
66
71
|
assert(false);
|
|
67
72
|
}
|
|
68
73
|
return {std::move(wb), std::move(s)};
|
|
69
74
|
}
|
|
70
75
|
|
|
71
|
-
class
|
|
76
|
+
class DbKvChecksumTestBase : public DBTestBase {
|
|
77
|
+
public:
|
|
78
|
+
DbKvChecksumTestBase(const std::string& path, bool env_do_fsync)
|
|
79
|
+
: DBTestBase(path, env_do_fsync) {}
|
|
80
|
+
|
|
81
|
+
ColumnFamilyHandle* GetCFHandleToUse(ColumnFamilyHandle* column_family,
|
|
82
|
+
WriteBatchOpType op_type) const {
|
|
83
|
+
// Note: PutEntity cannot be called without column family
|
|
84
|
+
if (op_type == WriteBatchOpType::kPutEntity && !column_family) {
|
|
85
|
+
return db_->DefaultColumnFamily();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return column_family;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
class DbKvChecksumTest : public DbKvChecksumTestBase,
|
|
72
93
|
public ::testing::WithParamInterface<
|
|
73
94
|
std::tuple<WriteBatchOpType, char, WriteMode>> {
|
|
74
95
|
public:
|
|
75
96
|
DbKvChecksumTest()
|
|
76
|
-
:
|
|
97
|
+
: DbKvChecksumTestBase("db_kv_checksum_test", /*env_do_fsync=*/false) {
|
|
77
98
|
op_type_ = std::get<0>(GetParam());
|
|
78
99
|
corrupt_byte_addend_ = std::get<1>(GetParam());
|
|
79
100
|
write_mode_ = std::get<2>(GetParam());
|
|
@@ -82,14 +103,16 @@ class DbKvChecksumTest : public DBTestBase,
|
|
|
82
103
|
Status ExecuteWrite(ColumnFamilyHandle* cf_handle) {
|
|
83
104
|
switch (write_mode_) {
|
|
84
105
|
case WriteMode::kWriteProtectedBatch: {
|
|
85
|
-
auto batch_and_status =
|
|
86
|
-
cf_handle,
|
|
106
|
+
auto batch_and_status =
|
|
107
|
+
GetWriteBatch(GetCFHandleToUse(cf_handle, op_type_),
|
|
108
|
+
8 /* protection_bytes_per_key */, op_type_);
|
|
87
109
|
assert(batch_and_status.second.ok());
|
|
88
110
|
return db_->Write(WriteOptions(), &batch_and_status.first);
|
|
89
111
|
}
|
|
90
112
|
case WriteMode::kWriteUnprotectedBatch: {
|
|
91
|
-
auto batch_and_status =
|
|
92
|
-
cf_handle,
|
|
113
|
+
auto batch_and_status =
|
|
114
|
+
GetWriteBatch(GetCFHandleToUse(cf_handle, op_type_),
|
|
115
|
+
0 /* protection_bytes_per_key */, op_type_);
|
|
93
116
|
assert(batch_and_status.second.ok());
|
|
94
117
|
WriteOptions write_opts;
|
|
95
118
|
write_opts.protection_bytes_per_key = 8;
|
|
@@ -135,10 +158,10 @@ std::string GetOpTypeString(const WriteBatchOpType& op_type) {
|
|
|
135
158
|
return "SingleDelete";
|
|
136
159
|
case WriteBatchOpType::kDeleteRange:
|
|
137
160
|
return "DeleteRange";
|
|
138
|
-
break;
|
|
139
161
|
case WriteBatchOpType::kMerge:
|
|
140
162
|
return "Merge";
|
|
141
|
-
|
|
163
|
+
case WriteBatchOpType::kPutEntity:
|
|
164
|
+
return "PutEntity";
|
|
142
165
|
case WriteBatchOpType::kNum:
|
|
143
166
|
assert(false);
|
|
144
167
|
}
|
|
@@ -242,7 +265,8 @@ TEST_P(DbKvChecksumTest, MemTableAddWithColumnFamilyCorrupted) {
|
|
|
242
265
|
TEST_P(DbKvChecksumTest, NoCorruptionCase) {
|
|
243
266
|
// If this test fails, we may have found a piece of malfunctioned hardware
|
|
244
267
|
auto batch_and_status =
|
|
245
|
-
GetWriteBatch(nullptr,
|
|
268
|
+
GetWriteBatch(GetCFHandleToUse(nullptr, op_type_),
|
|
269
|
+
8 /* protection_bytes_per_key */, op_type_);
|
|
246
270
|
ASSERT_OK(batch_and_status.second);
|
|
247
271
|
ASSERT_OK(batch_and_status.first.VerifyChecksum());
|
|
248
272
|
}
|
|
@@ -323,12 +347,12 @@ TEST_P(DbKvChecksumTest, WriteToWALWithColumnFamilyCorrupted) {
|
|
|
323
347
|
}
|
|
324
348
|
|
|
325
349
|
class DbKvChecksumTestMergedBatch
|
|
326
|
-
: public
|
|
350
|
+
: public DbKvChecksumTestBase,
|
|
327
351
|
public ::testing::WithParamInterface<
|
|
328
352
|
std::tuple<WriteBatchOpType, WriteBatchOpType, char>> {
|
|
329
353
|
public:
|
|
330
354
|
DbKvChecksumTestMergedBatch()
|
|
331
|
-
:
|
|
355
|
+
: DbKvChecksumTestBase("db_kv_checksum_test", /*env_do_fsync=*/false) {
|
|
332
356
|
op_type1_ = std::get<0>(GetParam());
|
|
333
357
|
op_type2_ = std::get<1>(GetParam());
|
|
334
358
|
corrupt_byte_addend_ = std::get<2>(GetParam());
|
|
@@ -349,10 +373,10 @@ void CorruptWriteBatch(Slice* content, size_t offset,
|
|
|
349
373
|
|
|
350
374
|
TEST_P(DbKvChecksumTestMergedBatch, NoCorruptionCase) {
|
|
351
375
|
// Veirfy write batch checksum after write batch append
|
|
352
|
-
auto batch1 = GetWriteBatch(nullptr
|
|
376
|
+
auto batch1 = GetWriteBatch(GetCFHandleToUse(nullptr, op_type1_),
|
|
353
377
|
8 /* protection_bytes_per_key */, op_type1_);
|
|
354
378
|
ASSERT_OK(batch1.second);
|
|
355
|
-
auto batch2 = GetWriteBatch(nullptr
|
|
379
|
+
auto batch2 = GetWriteBatch(GetCFHandleToUse(nullptr, op_type2_),
|
|
356
380
|
8 /* protection_bytes_per_key */, op_type2_);
|
|
357
381
|
ASSERT_OK(batch2.second);
|
|
358
382
|
ASSERT_OK(WriteBatchInternal::Append(&batch1.first, &batch2.first));
|
|
@@ -374,11 +398,13 @@ TEST_P(DbKvChecksumTestMergedBatch, WriteToWALCorrupted) {
|
|
|
374
398
|
options.merge_operator = MergeOperators::CreateStringAppendOperator();
|
|
375
399
|
}
|
|
376
400
|
|
|
377
|
-
auto leader_batch_and_status =
|
|
378
|
-
nullptr
|
|
401
|
+
auto leader_batch_and_status =
|
|
402
|
+
GetWriteBatch(GetCFHandleToUse(nullptr, op_type1_),
|
|
403
|
+
8 /* protection_bytes_per_key */, op_type1_);
|
|
379
404
|
ASSERT_OK(leader_batch_and_status.second);
|
|
380
|
-
auto follower_batch_and_status =
|
|
381
|
-
nullptr
|
|
405
|
+
auto follower_batch_and_status =
|
|
406
|
+
GetWriteBatch(GetCFHandleToUse(nullptr, op_type2_),
|
|
407
|
+
8 /* protection_bytes_per_key */, op_type2_);
|
|
382
408
|
size_t leader_batch_size = leader_batch_and_status.first.GetDataSize();
|
|
383
409
|
size_t total_bytes =
|
|
384
410
|
leader_batch_size + follower_batch_and_status.first.GetDataSize();
|
|
@@ -419,7 +445,7 @@ TEST_P(DbKvChecksumTestMergedBatch, WriteToWALCorrupted) {
|
|
|
419
445
|
// follower
|
|
420
446
|
follower_thread = port::Thread([&]() {
|
|
421
447
|
follower_batch_and_status =
|
|
422
|
-
GetWriteBatch(nullptr
|
|
448
|
+
GetWriteBatch(GetCFHandleToUse(nullptr, op_type2_),
|
|
423
449
|
8 /* protection_bytes_per_key */, op_type2_);
|
|
424
450
|
ASSERT_OK(follower_batch_and_status.second);
|
|
425
451
|
ASSERT_TRUE(
|
|
@@ -443,8 +469,9 @@ TEST_P(DbKvChecksumTestMergedBatch, WriteToWALCorrupted) {
|
|
|
443
469
|
Reopen(options);
|
|
444
470
|
SyncPoint::GetInstance()->EnableProcessing();
|
|
445
471
|
auto log_size_pre_write = dbfull()->TEST_total_log_size();
|
|
446
|
-
leader_batch_and_status =
|
|
447
|
-
nullptr
|
|
472
|
+
leader_batch_and_status =
|
|
473
|
+
GetWriteBatch(GetCFHandleToUse(nullptr, op_type1_),
|
|
474
|
+
8 /* protection_bytes_per_key */, op_type1_);
|
|
448
475
|
ASSERT_OK(leader_batch_and_status.second);
|
|
449
476
|
ASSERT_TRUE(db_->Write(WriteOptions(), &leader_batch_and_status.first)
|
|
450
477
|
.IsCorruption());
|
|
@@ -484,10 +511,12 @@ TEST_P(DbKvChecksumTestMergedBatch, WriteToWALWithColumnFamilyCorrupted) {
|
|
|
484
511
|
CreateAndReopenWithCF({"ramen"}, options);
|
|
485
512
|
|
|
486
513
|
auto leader_batch_and_status =
|
|
487
|
-
GetWriteBatch(handles_[1],
|
|
514
|
+
GetWriteBatch(GetCFHandleToUse(handles_[1], op_type1_),
|
|
515
|
+
8 /* protection_bytes_per_key */, op_type1_);
|
|
488
516
|
ASSERT_OK(leader_batch_and_status.second);
|
|
489
517
|
auto follower_batch_and_status =
|
|
490
|
-
GetWriteBatch(handles_[1],
|
|
518
|
+
GetWriteBatch(GetCFHandleToUse(handles_[1], op_type2_),
|
|
519
|
+
8 /* protection_bytes_per_key */, op_type2_);
|
|
491
520
|
size_t leader_batch_size = leader_batch_and_status.first.GetDataSize();
|
|
492
521
|
size_t total_bytes =
|
|
493
522
|
leader_batch_size + follower_batch_and_status.first.GetDataSize();
|
|
@@ -527,8 +556,9 @@ TEST_P(DbKvChecksumTestMergedBatch, WriteToWALWithColumnFamilyCorrupted) {
|
|
|
527
556
|
// Start the other writer thread which will join the write group as
|
|
528
557
|
// follower
|
|
529
558
|
follower_thread = port::Thread([&]() {
|
|
530
|
-
follower_batch_and_status =
|
|
531
|
-
handles_[1],
|
|
559
|
+
follower_batch_and_status =
|
|
560
|
+
GetWriteBatch(GetCFHandleToUse(handles_[1], op_type2_),
|
|
561
|
+
8 /* protection_bytes_per_key */, op_type2_);
|
|
532
562
|
ASSERT_OK(follower_batch_and_status.second);
|
|
533
563
|
ASSERT_TRUE(
|
|
534
564
|
db_->Write(WriteOptions(), &follower_batch_and_status.first)
|
|
@@ -553,7 +583,8 @@ TEST_P(DbKvChecksumTestMergedBatch, WriteToWALWithColumnFamilyCorrupted) {
|
|
|
553
583
|
SyncPoint::GetInstance()->EnableProcessing();
|
|
554
584
|
auto log_size_pre_write = dbfull()->TEST_total_log_size();
|
|
555
585
|
leader_batch_and_status =
|
|
556
|
-
GetWriteBatch(handles_[1],
|
|
586
|
+
GetWriteBatch(GetCFHandleToUse(handles_[1], op_type1_),
|
|
587
|
+
8 /* protection_bytes_per_key */, op_type1_);
|
|
557
588
|
ASSERT_OK(leader_batch_and_status.second);
|
|
558
589
|
ASSERT_TRUE(db_->Write(WriteOptions(), &leader_batch_and_status.first)
|
|
559
590
|
.IsCorruption());
|
|
@@ -453,7 +453,7 @@ TEST_F(DBOptionsTest, WritableFileMaxBufferSize) {
|
|
|
453
453
|
dbfull()->SetDBOptions({{"writable_file_max_buffer_size", "524288"}}));
|
|
454
454
|
buffer_size = 512 * 1024;
|
|
455
455
|
match_cnt = 0;
|
|
456
|
-
unmatch_cnt = 0; // SetDBOptions() will create a
|
|
456
|
+
unmatch_cnt = 0; // SetDBOptions() will create a WritableFileWriter
|
|
457
457
|
|
|
458
458
|
ASSERT_EQ(buffer_size,
|
|
459
459
|
dbfull()->GetDBOptions().writable_file_max_buffer_size);
|
|
@@ -2897,6 +2897,15 @@ class ModelDB : public DB {
|
|
|
2897
2897
|
const Slice& /*v*/) override {
|
|
2898
2898
|
return Status::NotSupported();
|
|
2899
2899
|
}
|
|
2900
|
+
|
|
2901
|
+
using DB::PutEntity;
|
|
2902
|
+
Status PutEntity(const WriteOptions& /* options */,
|
|
2903
|
+
ColumnFamilyHandle* /* column_family */,
|
|
2904
|
+
const Slice& /* key */,
|
|
2905
|
+
const WideColumns& /* columns */) override {
|
|
2906
|
+
return Status::NotSupported();
|
|
2907
|
+
}
|
|
2908
|
+
|
|
2900
2909
|
using DB::Close;
|
|
2901
2910
|
Status Close() override { return Status::OK(); }
|
|
2902
2911
|
using DB::Delete;
|
|
@@ -211,6 +211,13 @@ Status FlushJob::Run(LogsWithPrepTracker* prep_tracker, FileMetaData* file_meta,
|
|
|
211
211
|
TEST_SYNC_POINT("FlushJob::Start");
|
|
212
212
|
db_mutex_->AssertHeld();
|
|
213
213
|
assert(pick_memtable_called);
|
|
214
|
+
// Mempurge threshold can be dynamically changed.
|
|
215
|
+
// For sake of consistency, mempurge_threshold is
|
|
216
|
+
// saved locally to maintain consistency in each
|
|
217
|
+
// FlushJob::Run call.
|
|
218
|
+
double mempurge_threshold =
|
|
219
|
+
mutable_cf_options_.experimental_mempurge_threshold;
|
|
220
|
+
|
|
214
221
|
AutoThreadOperationStageUpdater stage_run(
|
|
215
222
|
ThreadStatus::STAGE_FLUSH_RUN);
|
|
216
223
|
if (mems_.empty()) {
|
|
@@ -238,9 +245,11 @@ Status FlushJob::Run(LogsWithPrepTracker* prep_tracker, FileMetaData* file_meta,
|
|
|
238
245
|
prev_cpu_read_nanos = IOSTATS(cpu_read_nanos);
|
|
239
246
|
}
|
|
240
247
|
Status mempurge_s = Status::NotFound("No MemPurge.");
|
|
241
|
-
if ((
|
|
248
|
+
if ((mempurge_threshold > 0.0) &&
|
|
242
249
|
(cfd_->GetFlushReason() == FlushReason::kWriteBufferFull) &&
|
|
243
|
-
(!mems_.empty()) && MemPurgeDecider()
|
|
250
|
+
(!mems_.empty()) && MemPurgeDecider(mempurge_threshold) &&
|
|
251
|
+
!(db_options_.atomic_flush)) {
|
|
252
|
+
cfd_->SetMempurgeUsed();
|
|
244
253
|
mempurge_s = MemPurge();
|
|
245
254
|
if (!mempurge_s.ok()) {
|
|
246
255
|
// Mempurge is typically aborted when the output
|
|
@@ -628,8 +637,7 @@ Status FlushJob::MemPurge() {
|
|
|
628
637
|
return s;
|
|
629
638
|
}
|
|
630
639
|
|
|
631
|
-
bool FlushJob::MemPurgeDecider() {
|
|
632
|
-
double threshold = db_options_.experimental_mempurge_threshold;
|
|
640
|
+
bool FlushJob::MemPurgeDecider(double threshold) {
|
|
633
641
|
// Never trigger mempurge if threshold is not a strictly positive value.
|
|
634
642
|
if (!(threshold > 0.0)) {
|
|
635
643
|
return false;
|
|
@@ -779,10 +787,11 @@ bool FlushJob::MemPurgeDecider() {
|
|
|
779
787
|
estimated_useful_payload +=
|
|
780
788
|
(mt->ApproximateMemoryUsage()) * (useful_payload * 1.0 / payload);
|
|
781
789
|
|
|
782
|
-
ROCKS_LOG_INFO(
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
790
|
+
ROCKS_LOG_INFO(db_options_.info_log,
|
|
791
|
+
"Mempurge sampling [CF %s] - found garbage ratio from "
|
|
792
|
+
"sampling: %f. Threshold is %f\n",
|
|
793
|
+
cfd_->GetName().c_str(),
|
|
794
|
+
(payload - useful_payload) * 1.0 / payload, threshold);
|
|
786
795
|
} else {
|
|
787
796
|
ROCKS_LOG_WARN(db_options_.info_log,
|
|
788
797
|
"Mempurge sampling: null payload measured, and collected "
|
|
@@ -122,7 +122,7 @@ class FlushJob {
|
|
|
122
122
|
// recommend all users not to set this flag as true given that the MemPurge
|
|
123
123
|
// process has not matured yet.
|
|
124
124
|
Status MemPurge();
|
|
125
|
-
bool MemPurgeDecider();
|
|
125
|
+
bool MemPurgeDecider(double threshold);
|
|
126
126
|
// The rate limiter priority (io_priority) is determined dynamically here.
|
|
127
127
|
Env::IOPriority GetRateLimiterPriorityForWrite();
|
|
128
128
|
#ifndef ROCKSDB_LITE
|
|
@@ -28,7 +28,7 @@ namespace log {
|
|
|
28
28
|
/**
|
|
29
29
|
* Writer is a general purpose log stream writer. It provides an append-only
|
|
30
30
|
* abstraction for writing data. The details of the how the data is written is
|
|
31
|
-
* handled by the
|
|
31
|
+
* handled by the WritableFile sub-class implementation.
|
|
32
32
|
*
|
|
33
33
|
* File format:
|
|
34
34
|
*
|