@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.
Files changed (105) hide show
  1. package/deps/rocksdb/rocksdb/CMakeLists.txt +1 -0
  2. package/deps/rocksdb/rocksdb/Makefile +3 -0
  3. package/deps/rocksdb/rocksdb/TARGETS +6 -0
  4. package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +12 -7
  5. package/deps/rocksdb/rocksdb/cache/cache_key.h +2 -0
  6. package/deps/rocksdb/rocksdb/cache/fast_lru_cache.cc +18 -6
  7. package/deps/rocksdb/rocksdb/cache/fast_lru_cache.h +13 -5
  8. package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +89 -0
  9. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader.cc +18 -28
  10. package/deps/rocksdb/rocksdb/db/blob/blob_source.cc +147 -2
  11. package/deps/rocksdb/rocksdb/db/blob/blob_source.h +30 -0
  12. package/deps/rocksdb/rocksdb/db/blob/blob_source_test.cc +403 -30
  13. package/deps/rocksdb/rocksdb/db/c.cc +159 -5
  14. package/deps/rocksdb/rocksdb/db/c_test.c +108 -0
  15. package/deps/rocksdb/rocksdb/db/column_family.cc +2 -1
  16. package/deps/rocksdb/rocksdb/db/column_family.h +7 -5
  17. package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +22 -0
  18. package/deps/rocksdb/rocksdb/db/compaction/compaction.h +8 -0
  19. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +6 -3
  20. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator_test.cc +15 -0
  21. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +35 -2
  22. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +55 -0
  23. package/deps/rocksdb/rocksdb/db/db_basic_test.cc +21 -19
  24. package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +60 -1
  25. package/deps/rocksdb/rocksdb/db/db_flush_test.cc +247 -6
  26. package/deps/rocksdb/rocksdb/db/db_impl/compacted_db_impl.h +10 -0
  27. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +6 -33
  28. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +10 -2
  29. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +7 -15
  30. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +17 -3
  31. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +10 -4
  32. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.h +9 -0
  33. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.h +8 -0
  34. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +32 -0
  35. package/deps/rocksdb/rocksdb/db/db_inplace_update_test.cc +54 -0
  36. package/deps/rocksdb/rocksdb/db/db_iter.cc +50 -2
  37. package/deps/rocksdb/rocksdb/db/db_iter.h +2 -0
  38. package/deps/rocksdb/rocksdb/db/db_kv_checksum_test.cc +56 -25
  39. package/deps/rocksdb/rocksdb/db/db_options_test.cc +1 -1
  40. package/deps/rocksdb/rocksdb/db/db_test.cc +9 -0
  41. package/deps/rocksdb/rocksdb/db/flush_job.cc +17 -8
  42. package/deps/rocksdb/rocksdb/db/flush_job.h +1 -1
  43. package/deps/rocksdb/rocksdb/db/log_writer.h +1 -1
  44. package/deps/rocksdb/rocksdb/db/memtable.cc +103 -93
  45. package/deps/rocksdb/rocksdb/db/memtable.h +3 -3
  46. package/deps/rocksdb/rocksdb/db/merge_helper.cc +7 -2
  47. package/deps/rocksdb/rocksdb/db/version_edit.h +1 -1
  48. package/deps/rocksdb/rocksdb/db/version_set.cc +13 -5
  49. package/deps/rocksdb/rocksdb/db/version_set_sync_and_async.h +5 -0
  50. package/deps/rocksdb/rocksdb/db/wide/db_wide_basic_test.cc +213 -0
  51. package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.cc +6 -7
  52. package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization_test.cc +16 -0
  53. package/deps/rocksdb/rocksdb/db/write_batch.cc +154 -2
  54. package/deps/rocksdb/rocksdb/db/write_batch_internal.h +3 -0
  55. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +4 -0
  56. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compaction_filter.h +8 -3
  57. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +21 -1
  58. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +31 -4
  59. package/deps/rocksdb/rocksdb/env/env_test.cc +2 -2
  60. package/deps/rocksdb/rocksdb/env/fs_remap.cc +4 -0
  61. package/deps/rocksdb/rocksdb/file/random_access_file_reader.h +1 -1
  62. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +17 -0
  63. package/deps/rocksdb/rocksdb/include/rocksdb/c.h +136 -0
  64. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +6 -0
  65. package/deps/rocksdb/rocksdb/include/rocksdb/env.h +1 -1
  66. package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +1 -1
  67. package/deps/rocksdb/rocksdb/include/rocksdb/options.h +23 -23
  68. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +7 -0
  69. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/write_batch_with_index.h +11 -0
  70. package/deps/rocksdb/rocksdb/include/rocksdb/write_batch.h +14 -0
  71. package/deps/rocksdb/rocksdb/include/rocksdb/write_batch_base.h +5 -0
  72. package/deps/rocksdb/rocksdb/options/cf_options.cc +7 -0
  73. package/deps/rocksdb/rocksdb/options/cf_options.h +19 -0
  74. package/deps/rocksdb/rocksdb/options/db_options.cc +1 -6
  75. package/deps/rocksdb/rocksdb/options/db_options.h +0 -1
  76. package/deps/rocksdb/rocksdb/options/options.cc +4 -1
  77. package/deps/rocksdb/rocksdb/options/options_helper.cc +2 -0
  78. package/deps/rocksdb/rocksdb/options/options_settable_test.cc +1 -0
  79. package/deps/rocksdb/rocksdb/options/options_test.cc +4 -4
  80. package/deps/rocksdb/rocksdb/port/win/env_win.cc +1 -1
  81. package/deps/rocksdb/rocksdb/src.mk +1 -0
  82. package/deps/rocksdb/rocksdb/table/block_based/block.cc +5 -3
  83. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +2 -2
  84. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +16 -9
  85. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +4 -2
  86. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +1 -1
  87. package/deps/rocksdb/rocksdb/table/block_based/filter_block.h +13 -7
  88. package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.cc +7 -3
  89. package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.h +4 -2
  90. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.cc +28 -17
  91. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.h +15 -9
  92. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block_test.cc +32 -16
  93. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +28 -18
  94. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.h +15 -6
  95. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +16 -7
  96. package/deps/rocksdb/rocksdb/table/block_fetcher.cc +1 -1
  97. package/deps/rocksdb/rocksdb/table/get_context.cc +27 -6
  98. package/deps/rocksdb/rocksdb/table/get_context.h +2 -0
  99. package/deps/rocksdb/rocksdb/table/table_test.cc +5 -5
  100. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +46 -0
  101. package/deps/rocksdb/rocksdb/util/filter_bench.cc +3 -1
  102. package/deps/rocksdb/rocksdb/util/mutexlock.h +1 -1
  103. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +1 -1
  104. package/package.json +1 -1
  105. 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 = SanitizeOptions(dbname, DBOptions(src), read_only);
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 = Status::Aborted("Failed to create logger");
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 or kTypeValue)
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 DbKvChecksumTest : public DBTestBase,
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
- : DBTestBase("db_kv_checksum_test", /*env_do_fsync=*/false) {
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 = GetWriteBatch(
86
- cf_handle, 8 /* protection_bytes_per_key */, op_type_);
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 = GetWriteBatch(
92
- cf_handle, 0 /* protection_bytes_per_key */, op_type_);
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
- break;
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, 8 /* protection_bytes_per_key */, op_type_);
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 DBTestBase,
350
+ : public DbKvChecksumTestBase,
327
351
  public ::testing::WithParamInterface<
328
352
  std::tuple<WriteBatchOpType, WriteBatchOpType, char>> {
329
353
  public:
330
354
  DbKvChecksumTestMergedBatch()
331
- : DBTestBase("db_kv_checksum_test", /*env_do_fsync=*/false) {
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 /* cf_handle */,
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 /* cf_handle */,
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 = GetWriteBatch(
378
- nullptr /* cf_handle */, 8 /* protection_bytes_per_key */, op_type1_);
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 = GetWriteBatch(
381
- nullptr /* cf_handle */, 8 /* protection_bytes_per_key */, op_type2_);
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 /* cf_handle */,
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 = GetWriteBatch(
447
- nullptr /* cf_handle */, 8 /* protection_bytes_per_key */, op_type1_);
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], 8 /* protection_bytes_per_key */, op_type1_);
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], 8 /* protection_bytes_per_key */, op_type2_);
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 = GetWriteBatch(
531
- handles_[1], 8 /* protection_bytes_per_key */, op_type2_);
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], 8 /* protection_bytes_per_key */, op_type1_);
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 WriteableFileWriter
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 ((db_options_.experimental_mempurge_threshold > 0.0) &&
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
- db_options_.info_log,
784
- "Mempurge sampling - found garbage ratio from sampling: %f.\n",
785
- (payload - useful_payload) * 1.0 / payload);
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 WriteableFile sub-class implementation.
31
+ * handled by the WritableFile sub-class implementation.
32
32
  *
33
33
  * File format:
34
34
  *