@nxtedition/rocksdb 7.0.40 → 7.0.41

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/binding.cc CHANGED
@@ -24,6 +24,8 @@
24
24
  #include <thread>
25
25
  #include <vector>
26
26
 
27
+ #include "max_rev_operator.h"
28
+
27
29
  class NullLogger : public rocksdb::Logger {
28
30
  public:
29
31
  using rocksdb::Logger::Logv;
@@ -156,6 +158,37 @@ static napi_status ToString(napi_env env, napi_value from, std::string& to) {
156
158
  return napi_ok;
157
159
  }
158
160
 
161
+ void noop(void* arg1, void* arg2) {}
162
+
163
+ // TODO (fix): Should use rocksdb::Slice since "to" cannot outlive "from".
164
+ static napi_status ToString(napi_env env, napi_value from, rocksdb::PinnableSlice& to) {
165
+ napi_valuetype type;
166
+ NAPI_STATUS_RETURN(napi_typeof(env, from, &type));
167
+
168
+ if (type == napi_string) {
169
+ size_t length = 0;
170
+ NAPI_STATUS_RETURN(napi_get_value_string_utf8(env, from, nullptr, 0, &length));
171
+ to.GetSelf()->resize(length, '\0');
172
+ NAPI_STATUS_RETURN(napi_get_value_string_utf8(env, from, &(*to.GetSelf())[0], length + 1, &length));
173
+ to.PinSelf();
174
+ } else {
175
+ bool isBuffer;
176
+ NAPI_STATUS_RETURN(napi_is_buffer(env, from, &isBuffer));
177
+
178
+ if (isBuffer) {
179
+ char* buf = nullptr;
180
+ size_t length = 0;
181
+ NAPI_STATUS_RETURN(napi_get_buffer_info(env, from, reinterpret_cast<void**>(&buf), &length));
182
+
183
+ to.PinSlice(rocksdb::Slice(buf, length), noop, nullptr, nullptr);
184
+ } else {
185
+ return napi_invalid_arg;
186
+ }
187
+ }
188
+
189
+ return napi_ok;
190
+ }
191
+
159
192
  static std::optional<std::string> StringProperty(napi_env env, napi_value opts, const std::string_view& name) {
160
193
  if (HasProperty(env, opts, name)) {
161
194
  const auto property = GetProperty(env, opts, name);
@@ -215,7 +248,9 @@ napi_status Convert(napi_env env, T&& s, bool asBuffer, napi_value& result) {
215
248
  if (!s) {
216
249
  return napi_get_null(env, &result);
217
250
  } else if (asBuffer) {
218
- return napi_create_buffer_copy(env, s->size(), s->data(), NULL, &result);
251
+ using Y = typename std::remove_pointer<typename std::decay<decltype(*s)>::type>::type;
252
+ auto ptr = new Y(std::move(*s));
253
+ return napi_create_external_buffer(env, ptr->size(), const_cast<char*>(ptr->data()), Finalize<Y>, ptr, &result);
219
254
  } else {
220
255
  return napi_create_string_utf8(env, s->data(), s->size(), &result);
221
256
  }
@@ -749,8 +784,12 @@ rocksdb::Status InitOptions(napi_env env, T& columnOptions, const U& options) {
749
784
 
750
785
  const auto mergeOperatorOpt = StringProperty(env, options, "mergeOperator");
751
786
  if (mergeOperatorOpt) {
752
- ROCKS_STATUS_RETURN(
753
- rocksdb::MergeOperator::CreateFromString(configOptions, *mergeOperatorOpt, &columnOptions.merge_operator));
787
+ if (*mergeOperatorOpt == "maxRev") {
788
+ columnOptions.merge_operator = std::make_shared<MaxRevOperator>();
789
+ } else {
790
+ ROCKS_STATUS_RETURN(
791
+ rocksdb::MergeOperator::CreateFromString(configOptions, *mergeOperatorOpt, &columnOptions.merge_operator));
792
+ }
754
793
  }
755
794
 
756
795
  const auto cacheSize = Uint32Property(env, options, "cacheSize").value_or(8 << 20);
@@ -1169,10 +1208,10 @@ NAPI_METHOD(db_put) {
1169
1208
  Database* database;
1170
1209
  NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
1171
1210
 
1172
- std::string key;
1211
+ rocksdb::PinnableSlice key;
1173
1212
  NAPI_STATUS_THROWS(ToString(env, argv[1], key));
1174
1213
 
1175
- std::string val;
1214
+ rocksdb::PinnableSlice val;
1176
1215
  NAPI_STATUS_THROWS(ToString(env, argv[2], val));
1177
1216
 
1178
1217
  rocksdb::ColumnFamilyHandle* column;
@@ -1387,7 +1426,7 @@ NAPI_METHOD(db_del) {
1387
1426
  Database* database;
1388
1427
  NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
1389
1428
 
1390
- std::string key;
1429
+ rocksdb::PinnableSlice key;
1391
1430
  NAPI_STATUS_THROWS(ToString(env, argv[1], key));
1392
1431
 
1393
1432
  rocksdb::ColumnFamilyHandle* column;
@@ -1496,7 +1535,7 @@ NAPI_METHOD(db_get_property) {
1496
1535
  Database* database;
1497
1536
  NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
1498
1537
 
1499
- std::string property;
1538
+ rocksdb::PinnableSlice property;
1500
1539
  NAPI_STATUS_THROWS(ToString(env, argv[1], property));
1501
1540
 
1502
1541
  std::string value;
@@ -1568,7 +1607,7 @@ NAPI_METHOD(iterator_seek) {
1568
1607
  Iterator* iterator;
1569
1608
  NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&iterator)));
1570
1609
 
1571
- std::string target;
1610
+ rocksdb::PinnableSlice target;
1572
1611
  NAPI_STATUS_THROWS(ToString(env, argv[1], target));
1573
1612
 
1574
1613
  iterator->first_ = true;
@@ -1705,14 +1744,14 @@ NAPI_METHOD(batch_do) {
1705
1744
 
1706
1745
  rocksdb::WriteBatch batch;
1707
1746
 
1708
- std::string type;
1709
- std::string key;
1710
- std::string value;
1711
-
1712
1747
  uint32_t length;
1713
1748
  NAPI_STATUS_THROWS(napi_get_array_length(env, argv[1], &length));
1714
1749
 
1715
1750
  for (uint32_t i = 0; i < length; i++) {
1751
+ rocksdb::PinnableSlice type;
1752
+ rocksdb::PinnableSlice key;
1753
+ rocksdb::PinnableSlice value;
1754
+
1716
1755
  napi_value element;
1717
1756
  NAPI_STATUS_THROWS(napi_get_element(env, argv[1], i, &element));
1718
1757
 
@@ -1789,10 +1828,10 @@ NAPI_METHOD(batch_put) {
1789
1828
  rocksdb::WriteBatch* batch;
1790
1829
  NAPI_STATUS_THROWS(napi_get_value_external(env, argv[1], (void**)(&batch)));
1791
1830
 
1792
- std::string key;
1831
+ rocksdb::PinnableSlice key;
1793
1832
  NAPI_STATUS_THROWS(ToString(env, argv[2], key));
1794
1833
 
1795
- std::string val;
1834
+ rocksdb::PinnableSlice val;
1796
1835
  NAPI_STATUS_THROWS(ToString(env, argv[3], val));
1797
1836
 
1798
1837
  rocksdb::ColumnFamilyHandle* column;
@@ -1812,7 +1851,7 @@ NAPI_METHOD(batch_del) {
1812
1851
  rocksdb::WriteBatch* batch;
1813
1852
  NAPI_STATUS_THROWS(napi_get_value_external(env, argv[1], reinterpret_cast<void**>(&batch)));
1814
1853
 
1815
- std::string key;
1854
+ rocksdb::PinnableSlice key;
1816
1855
  NAPI_STATUS_THROWS(ToString(env, argv[2], key));
1817
1856
 
1818
1857
  rocksdb::ColumnFamilyHandle* column;
@@ -1858,7 +1897,7 @@ NAPI_METHOD(batch_put_log_data) {
1858
1897
  rocksdb::WriteBatch* batch;
1859
1898
  NAPI_STATUS_THROWS(napi_get_value_external(env, argv[1], reinterpret_cast<void**>(&batch)));
1860
1899
 
1861
- std::string logData;
1900
+ rocksdb::PinnableSlice logData;
1862
1901
  NAPI_STATUS_THROWS(ToString(env, argv[2], logData));
1863
1902
 
1864
1903
  ROCKS_STATUS_THROWS(batch->PutLogData(logData));
@@ -1875,10 +1914,10 @@ NAPI_METHOD(batch_merge) {
1875
1914
  rocksdb::WriteBatch* batch;
1876
1915
  NAPI_STATUS_THROWS(napi_get_value_external(env, argv[1], (void**)(&batch)));
1877
1916
 
1878
- std::string key;
1917
+ rocksdb::PinnableSlice key;
1879
1918
  NAPI_STATUS_THROWS(ToString(env, argv[2], key));
1880
1919
 
1881
- std::string val;
1920
+ rocksdb::PinnableSlice val;
1882
1921
  NAPI_STATUS_THROWS(ToString(env, argv[3], val));
1883
1922
 
1884
1923
  rocksdb::ColumnFamilyHandle* column;
@@ -1914,7 +1953,7 @@ NAPI_METHOD(db_flush_wal) {
1914
1953
  return 0;
1915
1954
  }
1916
1955
 
1917
- template<typename T>
1956
+ template <typename T>
1918
1957
  napi_status FromLogFile(napi_env env, const T& file, napi_value* obj) {
1919
1958
  NAPI_STATUS_RETURN(napi_create_object(env, obj));
1920
1959
 
@@ -114,6 +114,8 @@ DEFINE_uint32(
114
114
  "(-stress_cache_key) Simulated file size in MiB, for accounting purposes");
115
115
  DEFINE_uint32(sck_reopen_nfiles, 100,
116
116
  "(-stress_cache_key) Simulate DB re-open average every n files");
117
+ DEFINE_uint32(sck_newdb_nreopen, 1000,
118
+ "(-stress_cache_key) Simulate new DB average every n re-opens");
117
119
  DEFINE_uint32(sck_restarts_per_day, 24,
118
120
  "(-stress_cache_key) Average simulated process restarts per day "
119
121
  "(across DBs)");
@@ -780,7 +782,7 @@ class StressCacheKey {
780
782
 
781
783
  void RunOnce() {
782
784
  // Re-initialized simulated state
783
- const size_t db_count = FLAGS_sck_db_count;
785
+ const size_t db_count = std::max(size_t{FLAGS_sck_db_count}, size_t{1});
784
786
  dbs_.reset(new TableProperties[db_count]{});
785
787
  const size_t table_mask = (size_t{1} << FLAGS_sck_table_bits) - 1;
786
788
  table_.reset(new uint64_t[table_mask + 1]{});
@@ -797,7 +799,8 @@ class StressCacheKey {
797
799
 
798
800
  process_count_ = 0;
799
801
  session_count_ = 0;
800
- ResetProcess();
802
+ newdb_count_ = 0;
803
+ ResetProcess(/*newdbs*/ true);
801
804
 
802
805
  Random64 r{std::random_device{}()};
803
806
 
@@ -816,9 +819,9 @@ class StressCacheKey {
816
819
  }
817
820
  // Any other periodic actions before simulating next file
818
821
  if (!FLAGS_sck_footer_unique_id && r.OneIn(FLAGS_sck_reopen_nfiles)) {
819
- ResetSession(db_i);
822
+ ResetSession(db_i, /*newdb*/ r.OneIn(FLAGS_sck_newdb_nreopen));
820
823
  } else if (r.OneIn(restart_nfiles_)) {
821
- ResetProcess();
824
+ ResetProcess(/*newdbs*/ false);
822
825
  }
823
826
  // Simulate next file
824
827
  OffsetableCacheKey ock;
@@ -870,7 +873,7 @@ class StressCacheKey {
870
873
  // Our goal is to predict probability of no collisions, not expected
871
874
  // number of collisions. To make the distinction, we have to get rid
872
875
  // of observing correlated collisions, which this takes care of:
873
- ResetProcess();
876
+ ResetProcess(/*newdbs*/ false);
874
877
  } else {
875
878
  // Replace (end of lifetime for file that was in this slot)
876
879
  table_[pos] = reduced_key;
@@ -888,10 +891,11 @@ class StressCacheKey {
888
891
  }
889
892
  // Report
890
893
  printf(
891
- "%" PRIu64 " days, %" PRIu64 " proc, %" PRIu64
892
- " sess, %u coll, occ %g%%, ejected %g%% \r",
894
+ "%" PRIu64 " days, %" PRIu64 " proc, %" PRIu64 " sess, %" PRIu64
895
+ " newdb, %u coll, occ %g%%, ejected %g%% \r",
893
896
  file_count / FLAGS_sck_files_per_day, process_count_,
894
- session_count_, collisions_this_run, 100.0 * sampled_count / 1000.0,
897
+ session_count_, newdb_count_ - FLAGS_sck_db_count,
898
+ collisions_this_run, 100.0 * sampled_count / 1000.0,
895
899
  100.0 * (1.0 - sampled_count / 1000.0 * table_mask / file_count));
896
900
  fflush(stdout);
897
901
  }
@@ -899,16 +903,27 @@ class StressCacheKey {
899
903
  collisions_ += collisions_this_run;
900
904
  }
901
905
 
902
- void ResetSession(size_t i) {
906
+ void ResetSession(size_t i, bool newdb) {
903
907
  dbs_[i].db_session_id = DBImpl::GenerateDbSessionId(nullptr);
908
+ if (newdb) {
909
+ ++newdb_count_;
910
+ if (FLAGS_sck_footer_unique_id) {
911
+ // Simulate how footer id would behave
912
+ dbs_[i].db_id = "none";
913
+ } else {
914
+ // db_id might be ignored, depending on the implementation details
915
+ dbs_[i].db_id = std::to_string(newdb_count_);
916
+ dbs_[i].orig_file_number = 0;
917
+ }
918
+ }
904
919
  session_count_++;
905
920
  }
906
921
 
907
- void ResetProcess() {
922
+ void ResetProcess(bool newdbs) {
908
923
  process_count_++;
909
924
  DBImpl::TEST_ResetDbSessionIdGen();
910
925
  for (size_t i = 0; i < FLAGS_sck_db_count; ++i) {
911
- ResetSession(i);
926
+ ResetSession(i, newdbs);
912
927
  }
913
928
  if (FLAGS_sck_footer_unique_id) {
914
929
  // For footer unique ID, this tracks process-wide generated SST file
@@ -923,6 +938,7 @@ class StressCacheKey {
923
938
  std::unique_ptr<uint64_t[]> table_;
924
939
  uint64_t process_count_ = 0;
925
940
  uint64_t session_count_ = 0;
941
+ uint64_t newdb_count_ = 0;
926
942
  uint64_t collisions_ = 0;
927
943
  uint32_t restart_nfiles_ = 0;
928
944
  double multiplier_ = 0.0;