@nxtedition/rocksdb 8.0.0 → 8.0.1
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/BUILDING.md +2 -2
- package/binding.cc +2 -7
- package/deps/rocksdb/rocksdb/CMakeLists.txt +8 -8
- package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +37 -0
- package/deps/rocksdb/rocksdb/db/db_iter.cc +57 -36
- package/deps/rocksdb/rocksdb/db/db_iter.h +2 -1
- package/deps/rocksdb/rocksdb/db/memtable.cc +55 -9
- package/deps/rocksdb/rocksdb/db/merge_helper.cc +72 -102
- package/deps/rocksdb/rocksdb/db/merge_helper.h +2 -11
- package/deps/rocksdb/rocksdb/db/version_set.cc +7 -3
- package/deps/rocksdb/rocksdb/db/wide/db_wide_basic_test.cc +122 -61
- package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.cc +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/table.h +3 -0
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +2 -10
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +9 -27
- package/deps/rocksdb/rocksdb/table/block_based/block_like_traits.h +0 -39
- package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.cc +0 -1
- package/deps/rocksdb/rocksdb/table/get_context.cc +52 -11
- package/deps/rocksdb/rocksdb/util/crc32c.cc +1 -1
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.node +0 -0
- package/max_rev_operator.h +0 -100
package/BUILDING.md
CHANGED
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
- Copy `libfolly.a` to `/usr/lib/x86_64-linux-gnu`.
|
|
11
11
|
- Copy headers to `/usr/lib/x86_64-linux-gnu/include`.
|
|
12
12
|
- Copy boost headers from folly scratchpad to `/usr/lib/x86_64-linux-gnu/include`.
|
|
13
|
-
- `npx prebuildify -t 18.11.0 --napi --strip --arch x64`
|
|
13
|
+
- `JOBS=8 npx prebuildify -t 18.11.0 --napi --strip --arch x64`
|
|
14
14
|
|
|
15
15
|
# OSX
|
|
16
16
|
|
|
17
17
|
- `brew install zstd`
|
|
18
|
-
- `npx prebuildify -t 18.11.0 --napi --strip --arch arm64`
|
|
18
|
+
- `JOBS=8 npx prebuildify -t 18.11.0 --napi --strip --arch arm64`
|
package/binding.cc
CHANGED
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
#include <thread>
|
|
27
27
|
#include <vector>
|
|
28
28
|
|
|
29
|
-
#include "max_rev_operator.h"
|
|
30
29
|
#include "util.h"
|
|
31
30
|
|
|
32
31
|
class NullLogger : public rocksdb::Logger {
|
|
@@ -557,12 +556,8 @@ napi_status InitOptions(napi_env env, T& columnOptions, const U& options) {
|
|
|
557
556
|
std::optional<std::string> mergeOperatorOpt;
|
|
558
557
|
NAPI_STATUS_RETURN(GetProperty(env, options, "mergeOperator", mergeOperatorOpt));
|
|
559
558
|
if (mergeOperatorOpt) {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
} else {
|
|
563
|
-
ROCKS_STATUS_RETURN_NAPI(
|
|
564
|
-
rocksdb::MergeOperator::CreateFromString(configOptions, *mergeOperatorOpt, &columnOptions.merge_operator));
|
|
565
|
-
}
|
|
559
|
+
ROCKS_STATUS_RETURN_NAPI(
|
|
560
|
+
rocksdb::MergeOperator::CreateFromString(configOptions, *mergeOperatorOpt, &columnOptions.merge_operator));
|
|
566
561
|
}
|
|
567
562
|
|
|
568
563
|
std::optional<std::string> compactionPriority;
|
|
@@ -250,6 +250,8 @@ option(FORCE_SSE42 "force building with SSE4.2, even when PORTABLE=ON" OFF)
|
|
|
250
250
|
option(FORCE_AVX "force building with AVX, even when PORTABLE=ON" OFF)
|
|
251
251
|
option(FORCE_AVX2 "force building with AVX2, even when PORTABLE=ON" OFF)
|
|
252
252
|
if(PORTABLE)
|
|
253
|
+
add_definitions(-DROCKSDB_PORTABLE)
|
|
254
|
+
|
|
253
255
|
# MSVC does not need a separate compiler flag to enable SSE4.2; if nmmintrin.h
|
|
254
256
|
# is available, it is available by default.
|
|
255
257
|
if(FORCE_SSE42 AND NOT MSVC)
|
|
@@ -292,8 +294,7 @@ if(NOT MSVC)
|
|
|
292
294
|
set(CMAKE_REQUIRED_FLAGS "-msse4.2 -mpclmul")
|
|
293
295
|
endif()
|
|
294
296
|
|
|
295
|
-
|
|
296
|
-
CHECK_CXX_SOURCE_COMPILES("
|
|
297
|
+
CHECK_CXX_SOURCE_COMPILES("
|
|
297
298
|
#include <cstdint>
|
|
298
299
|
#include <nmmintrin.h>
|
|
299
300
|
#include <wmmintrin.h>
|
|
@@ -305,12 +306,11 @@ int main() {
|
|
|
305
306
|
auto d = _mm_cvtsi128_si64(c);
|
|
306
307
|
}
|
|
307
308
|
" HAVE_SSE42)
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
endif()
|
|
309
|
+
if(HAVE_SSE42)
|
|
310
|
+
add_definitions(-DHAVE_SSE42)
|
|
311
|
+
add_definitions(-DHAVE_PCLMUL)
|
|
312
|
+
elseif(FORCE_SSE42)
|
|
313
|
+
message(FATAL_ERROR "FORCE_SSE42=ON but unable to compile with SSE4.2 enabled")
|
|
314
314
|
endif()
|
|
315
315
|
|
|
316
316
|
# Check if -latomic is required or not
|
|
@@ -1888,6 +1888,43 @@ TEST_F(DBSecondaryCacheTest, SecondaryCacheFailureTest) {
|
|
|
1888
1888
|
Destroy(options);
|
|
1889
1889
|
}
|
|
1890
1890
|
|
|
1891
|
+
TEST_F(DBSecondaryCacheTest, TestSecondaryWithCompressedCache) {
|
|
1892
|
+
if (!Snappy_Supported()) {
|
|
1893
|
+
ROCKSDB_GTEST_SKIP("Compressed cache test requires snappy support");
|
|
1894
|
+
return;
|
|
1895
|
+
}
|
|
1896
|
+
LRUCacheOptions opts(2000 /* capacity */, 0 /* num_shard_bits */,
|
|
1897
|
+
false /* strict_capacity_limit */,
|
|
1898
|
+
0.5 /* high_pri_pool_ratio */,
|
|
1899
|
+
nullptr /* memory_allocator */, kDefaultToAdaptiveMutex,
|
|
1900
|
+
kDontChargeCacheMetadata);
|
|
1901
|
+
std::shared_ptr<TestSecondaryCache> secondary_cache(
|
|
1902
|
+
new TestSecondaryCache(2048 * 1024));
|
|
1903
|
+
opts.secondary_cache = secondary_cache;
|
|
1904
|
+
std::shared_ptr<Cache> cache = NewLRUCache(opts);
|
|
1905
|
+
BlockBasedTableOptions table_options;
|
|
1906
|
+
table_options.block_cache_compressed = cache;
|
|
1907
|
+
table_options.no_block_cache = true;
|
|
1908
|
+
table_options.block_size = 1234;
|
|
1909
|
+
Options options = GetDefaultOptions();
|
|
1910
|
+
options.compression = kSnappyCompression;
|
|
1911
|
+
options.create_if_missing = true;
|
|
1912
|
+
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
|
1913
|
+
DestroyAndReopen(options);
|
|
1914
|
+
Random rnd(301);
|
|
1915
|
+
const int N = 6;
|
|
1916
|
+
for (int i = 0; i < N; i++) {
|
|
1917
|
+
// Partly compressible
|
|
1918
|
+
std::string p_v = rnd.RandomString(507) + std::string(500, ' ');
|
|
1919
|
+
ASSERT_OK(Put(Key(i), p_v));
|
|
1920
|
+
}
|
|
1921
|
+
ASSERT_OK(Flush());
|
|
1922
|
+
for (int i = 0; i < 2 * N; i++) {
|
|
1923
|
+
std::string v = Get(Key(i % N));
|
|
1924
|
+
ASSERT_EQ(1007, v.size());
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1891
1928
|
TEST_F(LRUCacheSecondaryCacheTest, BasicWaitAllTest) {
|
|
1892
1929
|
LRUCacheOptions opts(1024 /* capacity */, 2 /* num_shard_bits */,
|
|
1893
1930
|
false /* strict_capacity_limit */,
|
|
@@ -158,6 +158,8 @@ void DBIter::Next() {
|
|
|
158
158
|
|
|
159
159
|
local_stats_.next_count_++;
|
|
160
160
|
if (ok && iter_.Valid()) {
|
|
161
|
+
ClearSavedValue();
|
|
162
|
+
|
|
161
163
|
if (prefix_same_as_start_) {
|
|
162
164
|
assert(prefix_extractor_ != nullptr);
|
|
163
165
|
const Slice prefix = prefix_.GetUserKey();
|
|
@@ -544,8 +546,7 @@ bool DBIter::MergeValuesNewToOld() {
|
|
|
544
546
|
// hit a put, merge the put value with operands and store the
|
|
545
547
|
// final result in saved_value_. We are done!
|
|
546
548
|
const Slice val = iter_.value();
|
|
547
|
-
|
|
548
|
-
if (!s.ok()) {
|
|
549
|
+
if (!Merge(&val, ikey.user_key)) {
|
|
549
550
|
return false;
|
|
550
551
|
}
|
|
551
552
|
// iter_ is positioned after put
|
|
@@ -574,8 +575,7 @@ bool DBIter::MergeValuesNewToOld() {
|
|
|
574
575
|
return false;
|
|
575
576
|
}
|
|
576
577
|
valid_ = true;
|
|
577
|
-
|
|
578
|
-
if (!s.ok()) {
|
|
578
|
+
if (!Merge(&blob_value_, ikey.user_key)) {
|
|
579
579
|
return false;
|
|
580
580
|
}
|
|
581
581
|
|
|
@@ -589,11 +589,18 @@ bool DBIter::MergeValuesNewToOld() {
|
|
|
589
589
|
}
|
|
590
590
|
return true;
|
|
591
591
|
} else if (kTypeWideColumnEntity == ikey.type) {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
592
|
+
if (!MergeEntity(iter_.value(), ikey.user_key)) {
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// iter_ is positioned after put
|
|
597
|
+
iter_.Next();
|
|
598
|
+
if (!iter_.status().ok()) {
|
|
599
|
+
valid_ = false;
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
return true;
|
|
597
604
|
} else {
|
|
598
605
|
valid_ = false;
|
|
599
606
|
status_ = Status::Corruption(
|
|
@@ -612,8 +619,7 @@ bool DBIter::MergeValuesNewToOld() {
|
|
|
612
619
|
// a deletion marker.
|
|
613
620
|
// feed null as the existing value to the merge operator, such that
|
|
614
621
|
// client can differentiate this scenario and do things accordingly.
|
|
615
|
-
|
|
616
|
-
if (!s.ok()) {
|
|
622
|
+
if (!Merge(nullptr, saved_key_.GetUserKey())) {
|
|
617
623
|
return false;
|
|
618
624
|
}
|
|
619
625
|
assert(status_.ok());
|
|
@@ -636,6 +642,8 @@ void DBIter::Prev() {
|
|
|
636
642
|
}
|
|
637
643
|
}
|
|
638
644
|
if (ok) {
|
|
645
|
+
ClearSavedValue();
|
|
646
|
+
|
|
639
647
|
Slice prefix;
|
|
640
648
|
if (prefix_same_as_start_) {
|
|
641
649
|
assert(prefix_extractor_ != nullptr);
|
|
@@ -960,8 +968,7 @@ bool DBIter::FindValueForCurrentKey() {
|
|
|
960
968
|
if (last_not_merge_type == kTypeDeletion ||
|
|
961
969
|
last_not_merge_type == kTypeSingleDeletion ||
|
|
962
970
|
last_not_merge_type == kTypeDeletionWithTimestamp) {
|
|
963
|
-
|
|
964
|
-
if (!s.ok()) {
|
|
971
|
+
if (!Merge(nullptr, saved_key_.GetUserKey())) {
|
|
965
972
|
return false;
|
|
966
973
|
}
|
|
967
974
|
return true;
|
|
@@ -976,8 +983,7 @@ bool DBIter::FindValueForCurrentKey() {
|
|
|
976
983
|
return false;
|
|
977
984
|
}
|
|
978
985
|
valid_ = true;
|
|
979
|
-
|
|
980
|
-
if (!s.ok()) {
|
|
986
|
+
if (!Merge(&blob_value_, saved_key_.GetUserKey())) {
|
|
981
987
|
return false;
|
|
982
988
|
}
|
|
983
989
|
|
|
@@ -985,15 +991,14 @@ bool DBIter::FindValueForCurrentKey() {
|
|
|
985
991
|
|
|
986
992
|
return true;
|
|
987
993
|
} else if (last_not_merge_type == kTypeWideColumnEntity) {
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
return
|
|
994
|
+
if (!MergeEntity(pinned_value_, saved_key_.GetUserKey())) {
|
|
995
|
+
return false;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
return true;
|
|
993
999
|
} else {
|
|
994
1000
|
assert(last_not_merge_type == kTypeValue);
|
|
995
|
-
|
|
996
|
-
if (!s.ok()) {
|
|
1001
|
+
if (!Merge(&pinned_value_, saved_key_.GetUserKey())) {
|
|
997
1002
|
return false;
|
|
998
1003
|
}
|
|
999
1004
|
return true;
|
|
@@ -1177,8 +1182,7 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
|
|
1177
1182
|
|
|
1178
1183
|
if (ikey.type == kTypeValue) {
|
|
1179
1184
|
const Slice val = iter_.value();
|
|
1180
|
-
|
|
1181
|
-
if (!s.ok()) {
|
|
1185
|
+
if (!Merge(&val, saved_key_.GetUserKey())) {
|
|
1182
1186
|
return false;
|
|
1183
1187
|
}
|
|
1184
1188
|
return true;
|
|
@@ -1197,8 +1201,7 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
|
|
1197
1201
|
return false;
|
|
1198
1202
|
}
|
|
1199
1203
|
valid_ = true;
|
|
1200
|
-
|
|
1201
|
-
if (!s.ok()) {
|
|
1204
|
+
if (!Merge(&blob_value_, saved_key_.GetUserKey())) {
|
|
1202
1205
|
return false;
|
|
1203
1206
|
}
|
|
1204
1207
|
|
|
@@ -1206,11 +1209,11 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
|
|
1206
1209
|
|
|
1207
1210
|
return true;
|
|
1208
1211
|
} else if (ikey.type == kTypeWideColumnEntity) {
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
return
|
|
1212
|
+
if (!MergeEntity(iter_.value(), saved_key_.GetUserKey())) {
|
|
1213
|
+
return false;
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
return true;
|
|
1214
1217
|
} else {
|
|
1215
1218
|
valid_ = false;
|
|
1216
1219
|
status_ = Status::Corruption(
|
|
@@ -1220,8 +1223,7 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
|
|
1220
1223
|
}
|
|
1221
1224
|
}
|
|
1222
1225
|
|
|
1223
|
-
|
|
1224
|
-
if (!s.ok()) {
|
|
1226
|
+
if (!Merge(nullptr, saved_key_.GetUserKey())) {
|
|
1225
1227
|
return false;
|
|
1226
1228
|
}
|
|
1227
1229
|
|
|
@@ -1244,7 +1246,7 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
|
|
1244
1246
|
return true;
|
|
1245
1247
|
}
|
|
1246
1248
|
|
|
1247
|
-
|
|
1249
|
+
bool DBIter::Merge(const Slice* val, const Slice& user_key) {
|
|
1248
1250
|
Status s = MergeHelper::TimedFullMerge(
|
|
1249
1251
|
merge_operator_, user_key, val, merge_context_.GetOperands(),
|
|
1250
1252
|
&saved_value_, logger_, statistics_, clock_, &pinned_value_,
|
|
@@ -1252,14 +1254,33 @@ Status DBIter::Merge(const Slice* val, const Slice& user_key) {
|
|
|
1252
1254
|
if (!s.ok()) {
|
|
1253
1255
|
valid_ = false;
|
|
1254
1256
|
status_ = s;
|
|
1255
|
-
return
|
|
1257
|
+
return false;
|
|
1256
1258
|
}
|
|
1257
1259
|
|
|
1258
1260
|
SetValueAndColumnsFromPlain(pinned_value_.data() ? pinned_value_
|
|
1259
1261
|
: saved_value_);
|
|
1260
1262
|
|
|
1261
1263
|
valid_ = true;
|
|
1262
|
-
return
|
|
1264
|
+
return true;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
bool DBIter::MergeEntity(const Slice& entity, const Slice& user_key) {
|
|
1268
|
+
Status s = MergeHelper::TimedFullMergeWithEntity(
|
|
1269
|
+
merge_operator_, user_key, entity, merge_context_.GetOperands(),
|
|
1270
|
+
&saved_value_, logger_, statistics_, clock_,
|
|
1271
|
+
/* update_num_ops_stats */ true);
|
|
1272
|
+
if (!s.ok()) {
|
|
1273
|
+
valid_ = false;
|
|
1274
|
+
status_ = s;
|
|
1275
|
+
return false;
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
if (!SetValueAndColumnsFromEntity(saved_value_)) {
|
|
1279
|
+
return false;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
valid_ = true;
|
|
1283
|
+
return true;
|
|
1263
1284
|
}
|
|
1264
1285
|
|
|
1265
1286
|
// Move backwards until the key smaller than saved_key_.
|
|
@@ -318,7 +318,8 @@ class DBIter final : public Iterator {
|
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
// If user-defined timestamp is enabled, `user_key` includes timestamp.
|
|
321
|
-
|
|
321
|
+
bool Merge(const Slice* val, const Slice& user_key);
|
|
322
|
+
bool MergeEntity(const Slice& entity, const Slice& user_key);
|
|
322
323
|
|
|
323
324
|
const SliceTransform* prefix_extractor_;
|
|
324
325
|
Env* const env_;
|
|
@@ -1066,11 +1066,21 @@ static bool SaveValue(void* arg, const char* entry) {
|
|
|
1066
1066
|
assert(s->do_merge);
|
|
1067
1067
|
|
|
1068
1068
|
if (s->value || s->columns) {
|
|
1069
|
+
std::string result;
|
|
1069
1070
|
*(s->status) = MergeHelper::TimedFullMerge(
|
|
1070
1071
|
merge_operator, s->key->user_key(), &v,
|
|
1071
|
-
merge_context->GetOperands(),
|
|
1072
|
-
s->
|
|
1072
|
+
merge_context->GetOperands(), &result, s->logger, s->statistics,
|
|
1073
|
+
s->clock, /* result_operand */ nullptr,
|
|
1073
1074
|
/* update_num_ops_stats */ true);
|
|
1075
|
+
|
|
1076
|
+
if (s->status->ok()) {
|
|
1077
|
+
if (s->value) {
|
|
1078
|
+
*(s->value) = std::move(result);
|
|
1079
|
+
} else {
|
|
1080
|
+
assert(s->columns);
|
|
1081
|
+
s->columns->SetPlainValue(result);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1074
1084
|
}
|
|
1075
1085
|
} else if (s->value) {
|
|
1076
1086
|
s->value->assign(v.data(), v.size());
|
|
@@ -1115,11 +1125,27 @@ static bool SaveValue(void* arg, const char* entry) {
|
|
|
1115
1125
|
} else if (*(s->merge_in_progress)) {
|
|
1116
1126
|
assert(s->do_merge);
|
|
1117
1127
|
|
|
1118
|
-
if (s->value
|
|
1128
|
+
if (s->value) {
|
|
1129
|
+
Slice value_of_default;
|
|
1130
|
+
*(s->status) = WideColumnSerialization::GetValueOfDefaultColumn(
|
|
1131
|
+
v, value_of_default);
|
|
1132
|
+
if (s->status->ok()) {
|
|
1133
|
+
*(s->status) = MergeHelper::TimedFullMerge(
|
|
1134
|
+
merge_operator, s->key->user_key(), &value_of_default,
|
|
1135
|
+
merge_context->GetOperands(), s->value, s->logger,
|
|
1136
|
+
s->statistics, s->clock, /* result_operand */ nullptr,
|
|
1137
|
+
/* update_num_ops_stats */ true);
|
|
1138
|
+
}
|
|
1139
|
+
} else if (s->columns) {
|
|
1140
|
+
std::string result;
|
|
1119
1141
|
*(s->status) = MergeHelper::TimedFullMergeWithEntity(
|
|
1120
1142
|
merge_operator, s->key->user_key(), v,
|
|
1121
|
-
merge_context->GetOperands(),
|
|
1122
|
-
s->
|
|
1143
|
+
merge_context->GetOperands(), &result, s->logger, s->statistics,
|
|
1144
|
+
s->clock, /* update_num_ops_stats */ true);
|
|
1145
|
+
|
|
1146
|
+
if (s->status->ok()) {
|
|
1147
|
+
*(s->status) = s->columns->SetWideColumnValue(result);
|
|
1148
|
+
}
|
|
1123
1149
|
}
|
|
1124
1150
|
} else if (s->value) {
|
|
1125
1151
|
Slice value_of_default;
|
|
@@ -1150,11 +1176,21 @@ static bool SaveValue(void* arg, const char* entry) {
|
|
|
1150
1176
|
case kTypeRangeDeletion: {
|
|
1151
1177
|
if (*(s->merge_in_progress)) {
|
|
1152
1178
|
if (s->value || s->columns) {
|
|
1179
|
+
std::string result;
|
|
1153
1180
|
*(s->status) = MergeHelper::TimedFullMerge(
|
|
1154
1181
|
merge_operator, s->key->user_key(), nullptr,
|
|
1155
|
-
merge_context->GetOperands(),
|
|
1156
|
-
s->
|
|
1182
|
+
merge_context->GetOperands(), &result, s->logger, s->statistics,
|
|
1183
|
+
s->clock, /* result_operand */ nullptr,
|
|
1157
1184
|
/* update_num_ops_stats */ true);
|
|
1185
|
+
|
|
1186
|
+
if (s->status->ok()) {
|
|
1187
|
+
if (s->value) {
|
|
1188
|
+
*(s->value) = std::move(result);
|
|
1189
|
+
} else {
|
|
1190
|
+
assert(s->columns);
|
|
1191
|
+
s->columns->SetPlainValue(result);
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1158
1194
|
}
|
|
1159
1195
|
} else {
|
|
1160
1196
|
*(s->status) = Status::NotFound();
|
|
@@ -1180,11 +1216,21 @@ static bool SaveValue(void* arg, const char* entry) {
|
|
|
1180
1216
|
if (s->do_merge && merge_operator->ShouldMerge(
|
|
1181
1217
|
merge_context->GetOperandsDirectionBackward())) {
|
|
1182
1218
|
if (s->value || s->columns) {
|
|
1219
|
+
std::string result;
|
|
1183
1220
|
*(s->status) = MergeHelper::TimedFullMerge(
|
|
1184
1221
|
merge_operator, s->key->user_key(), nullptr,
|
|
1185
|
-
merge_context->GetOperands(),
|
|
1186
|
-
s->
|
|
1222
|
+
merge_context->GetOperands(), &result, s->logger, s->statistics,
|
|
1223
|
+
s->clock, /* result_operand */ nullptr,
|
|
1187
1224
|
/* update_num_ops_stats */ true);
|
|
1225
|
+
|
|
1226
|
+
if (s->status->ok()) {
|
|
1227
|
+
if (s->value) {
|
|
1228
|
+
*(s->value) = std::move(result);
|
|
1229
|
+
} else {
|
|
1230
|
+
assert(s->columns);
|
|
1231
|
+
s->columns->SetPlainValue(result);
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1188
1234
|
}
|
|
1189
1235
|
|
|
1190
1236
|
*(s->found_final_value) = true;
|
|
@@ -112,44 +112,10 @@ Status MergeHelper::TimedFullMerge(const MergeOperator* merge_operator,
|
|
|
112
112
|
return Status::OK();
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
Status MergeHelper::TimedFullMerge(const MergeOperator* merge_operator,
|
|
116
|
-
const Slice& key, const Slice* base_value,
|
|
117
|
-
const std::vector<Slice>& operands,
|
|
118
|
-
std::string* value,
|
|
119
|
-
PinnableWideColumns* columns, Logger* logger,
|
|
120
|
-
Statistics* statistics, SystemClock* clock,
|
|
121
|
-
Slice* result_operand,
|
|
122
|
-
bool update_num_ops_stats) {
|
|
123
|
-
assert(value || columns);
|
|
124
|
-
assert(!value || !columns);
|
|
125
|
-
|
|
126
|
-
std::string result;
|
|
127
|
-
const Status s =
|
|
128
|
-
TimedFullMerge(merge_operator, key, base_value, operands, &result, logger,
|
|
129
|
-
statistics, clock, result_operand, update_num_ops_stats);
|
|
130
|
-
if (!s.ok()) {
|
|
131
|
-
return s;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (value) {
|
|
135
|
-
*value = std::move(result);
|
|
136
|
-
return Status::OK();
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
assert(columns);
|
|
140
|
-
columns->SetPlainValue(result);
|
|
141
|
-
|
|
142
|
-
return Status::OK();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
115
|
Status MergeHelper::TimedFullMergeWithEntity(
|
|
146
116
|
const MergeOperator* merge_operator, const Slice& key, Slice base_entity,
|
|
147
|
-
const std::vector<Slice>& operands, std::string*
|
|
148
|
-
|
|
149
|
-
SystemClock* clock, bool update_num_ops_stats) {
|
|
150
|
-
assert(value || columns);
|
|
151
|
-
assert(!value || !columns);
|
|
152
|
-
|
|
117
|
+
const std::vector<Slice>& operands, std::string* result, Logger* logger,
|
|
118
|
+
Statistics* statistics, SystemClock* clock, bool update_num_ops_stats) {
|
|
153
119
|
WideColumns base_columns;
|
|
154
120
|
|
|
155
121
|
{
|
|
@@ -168,44 +134,35 @@ Status MergeHelper::TimedFullMergeWithEntity(
|
|
|
168
134
|
value_of_default = base_columns[0].value();
|
|
169
135
|
}
|
|
170
136
|
|
|
171
|
-
std::string
|
|
137
|
+
std::string merge_result;
|
|
172
138
|
|
|
173
139
|
{
|
|
174
140
|
constexpr Slice* result_operand = nullptr;
|
|
175
141
|
|
|
176
142
|
const Status s = TimedFullMerge(
|
|
177
|
-
merge_operator, key, &value_of_default, operands, &
|
|
143
|
+
merge_operator, key, &value_of_default, operands, &merge_result, logger,
|
|
178
144
|
statistics, clock, result_operand, update_num_ops_stats);
|
|
179
145
|
if (!s.ok()) {
|
|
180
146
|
return s;
|
|
181
147
|
}
|
|
182
148
|
}
|
|
183
149
|
|
|
184
|
-
if (value) {
|
|
185
|
-
*value = std::move(result);
|
|
186
|
-
return Status::OK();
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
assert(columns);
|
|
190
|
-
|
|
191
|
-
std::string output;
|
|
192
|
-
|
|
193
150
|
if (has_default_column) {
|
|
194
|
-
base_columns[0].value() =
|
|
151
|
+
base_columns[0].value() = merge_result;
|
|
195
152
|
|
|
196
|
-
const Status s = WideColumnSerialization::Serialize(base_columns,
|
|
153
|
+
const Status s = WideColumnSerialization::Serialize(base_columns, *result);
|
|
197
154
|
if (!s.ok()) {
|
|
198
155
|
return s;
|
|
199
156
|
}
|
|
200
157
|
} else {
|
|
201
158
|
const Status s =
|
|
202
|
-
WideColumnSerialization::Serialize(
|
|
159
|
+
WideColumnSerialization::Serialize(merge_result, base_columns, *result);
|
|
203
160
|
if (!s.ok()) {
|
|
204
161
|
return s;
|
|
205
162
|
}
|
|
206
163
|
}
|
|
207
164
|
|
|
208
|
-
return
|
|
165
|
+
return Status::OK();
|
|
209
166
|
}
|
|
210
167
|
|
|
211
168
|
// PRE: iter points to the first merge type entry
|
|
@@ -333,66 +290,79 @@ Status MergeHelper::MergeUntil(InternalIterator* iter,
|
|
|
333
290
|
// (almost) silently dropping the put/delete. That's probably not what we
|
|
334
291
|
// want. Also if we're in compaction and it's a put, it would be nice to
|
|
335
292
|
// run compaction filter on it.
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
uint64_t bytes_read = 0;
|
|
362
|
-
|
|
363
|
-
assert(blob_fetcher);
|
|
364
|
-
|
|
365
|
-
s = blob_fetcher->FetchBlob(ikey.user_key, blob_index,
|
|
366
|
-
prefetch_buffer, &blob_value,
|
|
367
|
-
&bytes_read);
|
|
368
|
-
if (!s.ok()) {
|
|
369
|
-
return s;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
val_ptr = &blob_value;
|
|
373
|
-
|
|
374
|
-
if (c_iter_stats) {
|
|
375
|
-
++c_iter_stats->num_blobs_read;
|
|
376
|
-
c_iter_stats->total_blob_bytes_read += bytes_read;
|
|
377
|
-
}
|
|
378
|
-
} else {
|
|
379
|
-
val_ptr = &val;
|
|
293
|
+
std::string merge_result;
|
|
294
|
+
|
|
295
|
+
if (range_del_agg &&
|
|
296
|
+
range_del_agg->ShouldDelete(
|
|
297
|
+
ikey, RangeDelPositioningMode::kForwardTraversal)) {
|
|
298
|
+
s = TimedFullMerge(user_merge_operator_, ikey.user_key, nullptr,
|
|
299
|
+
merge_context_.GetOperands(), &merge_result, logger_,
|
|
300
|
+
stats_, clock_,
|
|
301
|
+
/* result_operand */ nullptr,
|
|
302
|
+
/* update_num_ops_stats */ false);
|
|
303
|
+
} else if (ikey.type == kTypeValue) {
|
|
304
|
+
const Slice val = iter->value();
|
|
305
|
+
|
|
306
|
+
s = TimedFullMerge(user_merge_operator_, ikey.user_key, &val,
|
|
307
|
+
merge_context_.GetOperands(), &merge_result, logger_,
|
|
308
|
+
stats_, clock_,
|
|
309
|
+
/* result_operand */ nullptr,
|
|
310
|
+
/* update_num_ops_stats */ false);
|
|
311
|
+
} else if (ikey.type == kTypeBlobIndex) {
|
|
312
|
+
BlobIndex blob_index;
|
|
313
|
+
|
|
314
|
+
s = blob_index.DecodeFrom(iter->value());
|
|
315
|
+
if (!s.ok()) {
|
|
316
|
+
return s;
|
|
380
317
|
}
|
|
318
|
+
|
|
319
|
+
FilePrefetchBuffer* prefetch_buffer =
|
|
320
|
+
prefetch_buffers ? prefetch_buffers->GetOrCreatePrefetchBuffer(
|
|
321
|
+
blob_index.file_number())
|
|
322
|
+
: nullptr;
|
|
323
|
+
|
|
324
|
+
uint64_t bytes_read = 0;
|
|
325
|
+
|
|
326
|
+
assert(blob_fetcher);
|
|
327
|
+
|
|
328
|
+
PinnableSlice blob_value;
|
|
329
|
+
s = blob_fetcher->FetchBlob(ikey.user_key, blob_index, prefetch_buffer,
|
|
330
|
+
&blob_value, &bytes_read);
|
|
331
|
+
if (!s.ok()) {
|
|
332
|
+
return s;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (c_iter_stats) {
|
|
336
|
+
++c_iter_stats->num_blobs_read;
|
|
337
|
+
c_iter_stats->total_blob_bytes_read += bytes_read;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
s = TimedFullMerge(user_merge_operator_, ikey.user_key, &blob_value,
|
|
341
|
+
merge_context_.GetOperands(), &merge_result, logger_,
|
|
342
|
+
stats_, clock_,
|
|
343
|
+
/* result_operand */ nullptr,
|
|
344
|
+
/* update_num_ops_stats */ false);
|
|
345
|
+
} else if (ikey.type == kTypeWideColumnEntity) {
|
|
346
|
+
s = TimedFullMergeWithEntity(
|
|
347
|
+
user_merge_operator_, ikey.user_key, iter->value(),
|
|
348
|
+
merge_context_.GetOperands(), &merge_result, logger_, stats_,
|
|
349
|
+
clock_, /* update_num_ops_stats */ false);
|
|
381
350
|
} else {
|
|
382
|
-
|
|
351
|
+
s = TimedFullMerge(user_merge_operator_, ikey.user_key, nullptr,
|
|
352
|
+
merge_context_.GetOperands(), &merge_result, logger_,
|
|
353
|
+
stats_, clock_,
|
|
354
|
+
/* result_operand */ nullptr,
|
|
355
|
+
/* update_num_ops_stats */ false);
|
|
383
356
|
}
|
|
384
|
-
std::string merge_result;
|
|
385
|
-
s = TimedFullMerge(
|
|
386
|
-
user_merge_operator_, ikey.user_key, val_ptr,
|
|
387
|
-
merge_context_.GetOperands(), &merge_result, logger_, stats_, clock_,
|
|
388
|
-
/* result_operand */ nullptr, /* update_num_ops_stats */ false);
|
|
389
357
|
|
|
390
358
|
// We store the result in keys_.back() and operands_.back()
|
|
391
359
|
// if nothing went wrong (i.e.: no operand corruption on disk)
|
|
392
360
|
if (s.ok()) {
|
|
393
361
|
// The original key encountered
|
|
394
362
|
original_key = std::move(keys_.back());
|
|
395
|
-
orig_ikey.type =
|
|
363
|
+
orig_ikey.type = ikey.type == kTypeWideColumnEntity
|
|
364
|
+
? kTypeWideColumnEntity
|
|
365
|
+
: kTypeValue;
|
|
396
366
|
UpdateInternalKey(&original_key, orig_ikey.sequence, orig_ikey.type);
|
|
397
367
|
keys_.clear();
|
|
398
368
|
merge_context_.Clear();
|