@nxtedition/rocksdb 7.1.34 → 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 -154
- 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/index.js +0 -192
- package/package.json +2 -4
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.node +0 -0
- package/common.js +0 -7
- 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
|
|
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
|
+
- `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 {
|
|
@@ -38,7 +37,6 @@ class NullLogger : public rocksdb::Logger {
|
|
|
38
37
|
|
|
39
38
|
struct Database;
|
|
40
39
|
struct Iterator;
|
|
41
|
-
struct Updates;
|
|
42
40
|
|
|
43
41
|
struct ColumnFamily {
|
|
44
42
|
napi_ref ref;
|
|
@@ -254,48 +252,6 @@ struct BatchIterator : public rocksdb::WriteBatch::Handler {
|
|
|
254
252
|
std::vector<BatchEntry> cache_;
|
|
255
253
|
};
|
|
256
254
|
|
|
257
|
-
struct Updates : public BatchIterator, public Closable {
|
|
258
|
-
Updates(Database* database,
|
|
259
|
-
const int64_t seqNumber,
|
|
260
|
-
const bool keys,
|
|
261
|
-
const bool values,
|
|
262
|
-
const bool data,
|
|
263
|
-
const rocksdb::ColumnFamilyHandle* column,
|
|
264
|
-
const Encoding keyEncoding,
|
|
265
|
-
const Encoding valueEncoding)
|
|
266
|
-
: BatchIterator(database, keys, values, data, column, keyEncoding, valueEncoding),
|
|
267
|
-
database_(database),
|
|
268
|
-
start_(seqNumber) {}
|
|
269
|
-
|
|
270
|
-
virtual ~Updates() { assert(!iterator_); }
|
|
271
|
-
|
|
272
|
-
rocksdb::Status Close() override {
|
|
273
|
-
iterator_.reset();
|
|
274
|
-
return rocksdb::Status::OK();
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
napi_status Attach(napi_env env, napi_value context) {
|
|
278
|
-
NAPI_STATUS_RETURN(napi_create_reference(env, context, 1, &ref_));
|
|
279
|
-
database_->closables.insert(this);
|
|
280
|
-
return napi_ok;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
napi_status Detach(napi_env env) {
|
|
284
|
-
database_->closables.erase(this);
|
|
285
|
-
if (ref_) {
|
|
286
|
-
NAPI_STATUS_RETURN(napi_delete_reference(env, ref_));
|
|
287
|
-
}
|
|
288
|
-
return napi_ok;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
Database* database_;
|
|
292
|
-
int64_t start_;
|
|
293
|
-
std::unique_ptr<rocksdb::TransactionLogIterator> iterator_;
|
|
294
|
-
|
|
295
|
-
private:
|
|
296
|
-
napi_ref ref_ = nullptr;
|
|
297
|
-
};
|
|
298
|
-
|
|
299
255
|
struct BaseIterator : public Closable {
|
|
300
256
|
BaseIterator(Database* database,
|
|
301
257
|
rocksdb::ColumnFamilyHandle* column,
|
|
@@ -600,12 +556,8 @@ napi_status InitOptions(napi_env env, T& columnOptions, const U& options) {
|
|
|
600
556
|
std::optional<std::string> mergeOperatorOpt;
|
|
601
557
|
NAPI_STATUS_RETURN(GetProperty(env, options, "mergeOperator", mergeOperatorOpt));
|
|
602
558
|
if (mergeOperatorOpt) {
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
} else {
|
|
606
|
-
ROCKS_STATUS_RETURN_NAPI(
|
|
607
|
-
rocksdb::MergeOperator::CreateFromString(configOptions, *mergeOperatorOpt, &columnOptions.merge_operator));
|
|
608
|
-
}
|
|
559
|
+
ROCKS_STATUS_RETURN_NAPI(
|
|
560
|
+
rocksdb::MergeOperator::CreateFromString(configOptions, *mergeOperatorOpt, &columnOptions.merge_operator));
|
|
609
561
|
}
|
|
610
562
|
|
|
611
563
|
std::optional<std::string> compactionPriority;
|
|
@@ -850,106 +802,6 @@ NAPI_METHOD(db_close) {
|
|
|
850
802
|
return 0;
|
|
851
803
|
}
|
|
852
804
|
|
|
853
|
-
NAPI_METHOD(updates_init) {
|
|
854
|
-
NAPI_ARGV(2);
|
|
855
|
-
|
|
856
|
-
Database* database;
|
|
857
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
|
|
858
|
-
|
|
859
|
-
const auto options = argv[1];
|
|
860
|
-
|
|
861
|
-
int64_t since = 0;
|
|
862
|
-
NAPI_STATUS_THROWS(GetProperty(env, options, "since", since));
|
|
863
|
-
|
|
864
|
-
bool keys = true;
|
|
865
|
-
NAPI_STATUS_THROWS(GetProperty(env, options, "keys", keys));
|
|
866
|
-
|
|
867
|
-
bool values = true;
|
|
868
|
-
NAPI_STATUS_THROWS(GetProperty(env, options, "values", values));
|
|
869
|
-
|
|
870
|
-
bool data = true;
|
|
871
|
-
NAPI_STATUS_THROWS(GetProperty(env, options, "data", data));
|
|
872
|
-
|
|
873
|
-
Encoding keyEncoding = Encoding::String;
|
|
874
|
-
NAPI_STATUS_THROWS(GetProperty(env, options, "keyEncoding", keyEncoding));
|
|
875
|
-
|
|
876
|
-
Encoding valueEncoding = Encoding::String;
|
|
877
|
-
NAPI_STATUS_THROWS(GetProperty(env, options, "valueEncoding", valueEncoding));
|
|
878
|
-
|
|
879
|
-
rocksdb::ColumnFamilyHandle* column = nullptr;
|
|
880
|
-
NAPI_STATUS_THROWS(GetProperty(env, options, "column", column));
|
|
881
|
-
|
|
882
|
-
auto updates =
|
|
883
|
-
std::unique_ptr<Updates>(new Updates(database, since, keys, values, data, column, keyEncoding, valueEncoding));
|
|
884
|
-
|
|
885
|
-
napi_value result;
|
|
886
|
-
NAPI_STATUS_THROWS(napi_create_external(env, updates.get(), Finalize<Updates>, updates.get(), &result));
|
|
887
|
-
|
|
888
|
-
// Prevent GC of JS object before the iterator is closed (explicitly or on
|
|
889
|
-
// db close) and keep track of non-closed iterators to end them on db close.
|
|
890
|
-
NAPI_STATUS_THROWS(updates.release()->Attach(env, result));
|
|
891
|
-
|
|
892
|
-
return result;
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
NAPI_METHOD(updates_next) {
|
|
896
|
-
NAPI_ARGV(2);
|
|
897
|
-
|
|
898
|
-
Updates* updates;
|
|
899
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&updates)));
|
|
900
|
-
|
|
901
|
-
auto callback = argv[1];
|
|
902
|
-
|
|
903
|
-
runAsync<rocksdb::BatchResult>(
|
|
904
|
-
"leveldown.updates.next", env, callback,
|
|
905
|
-
[=](auto& batchResult) {
|
|
906
|
-
if (!updates->iterator_) {
|
|
907
|
-
rocksdb::TransactionLogIterator::ReadOptions options;
|
|
908
|
-
const auto status = updates->database_->db->GetUpdatesSince(updates->start_, &updates->iterator_, options);
|
|
909
|
-
if (!status.ok()) {
|
|
910
|
-
return status;
|
|
911
|
-
}
|
|
912
|
-
} else if (updates->iterator_->Valid()) {
|
|
913
|
-
updates->iterator_->Next();
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
if (!updates->iterator_->Valid() || !updates->iterator_->status().ok()) {
|
|
917
|
-
return updates->iterator_->status();
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
batchResult = updates->iterator_->GetBatch();
|
|
921
|
-
|
|
922
|
-
return rocksdb::Status::OK();
|
|
923
|
-
},
|
|
924
|
-
[=](auto& batchResult, auto env, auto& argv) {
|
|
925
|
-
if (!batchResult.writeBatchPtr) {
|
|
926
|
-
return napi_ok;
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
argv.resize(5);
|
|
930
|
-
NAPI_STATUS_RETURN(updates->Iterate(env, *batchResult.writeBatchPtr, &argv[1]));
|
|
931
|
-
NAPI_STATUS_RETURN(napi_create_int64(env, batchResult.sequence, &argv[2]));
|
|
932
|
-
NAPI_STATUS_RETURN(napi_create_int64(env, batchResult.writeBatchPtr->Count(), &argv[3]));
|
|
933
|
-
NAPI_STATUS_RETURN(napi_create_int64(env, updates->start_, &argv[4]));
|
|
934
|
-
|
|
935
|
-
return napi_ok;
|
|
936
|
-
});
|
|
937
|
-
|
|
938
|
-
return 0;
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
NAPI_METHOD(updates_close) {
|
|
942
|
-
NAPI_ARGV(1);
|
|
943
|
-
|
|
944
|
-
Updates* updates;
|
|
945
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&updates)));
|
|
946
|
-
|
|
947
|
-
ROCKS_STATUS_THROWS_NAPI(updates->Close());
|
|
948
|
-
NAPI_STATUS_THROWS(updates->Detach(env));
|
|
949
|
-
|
|
950
|
-
return 0;
|
|
951
|
-
}
|
|
952
|
-
|
|
953
805
|
NAPI_METHOD(db_get_many) {
|
|
954
806
|
NAPI_ARGV(4);
|
|
955
807
|
|
|
@@ -1731,10 +1583,6 @@ NAPI_INIT() {
|
|
|
1731
1583
|
NAPI_EXPORT_FUNCTION(iterator_nextv);
|
|
1732
1584
|
NAPI_EXPORT_FUNCTION(iterator_get_sequence);
|
|
1733
1585
|
|
|
1734
|
-
NAPI_EXPORT_FUNCTION(updates_init);
|
|
1735
|
-
NAPI_EXPORT_FUNCTION(updates_close);
|
|
1736
|
-
NAPI_EXPORT_FUNCTION(updates_next);
|
|
1737
|
-
|
|
1738
1586
|
NAPI_EXPORT_FUNCTION(batch_do);
|
|
1739
1587
|
NAPI_EXPORT_FUNCTION(batch_init);
|
|
1740
1588
|
NAPI_EXPORT_FUNCTION(batch_put);
|
|
@@ -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;
|