@nxtedition/rocksdb 13.0.3 → 13.1.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/binding.cc CHANGED
@@ -431,7 +431,8 @@ class Iterator final : public BaseIterator {
431
431
  values_(values),
432
432
  highWaterMarkBytes_(highWaterMarkBytes),
433
433
  keyEncoding_(keyEncoding),
434
- valueEncoding_(valueEncoding) {}
434
+ valueEncoding_(valueEncoding) {
435
+ }
435
436
 
436
437
  void Seek(const rocksdb::Slice& target) override {
437
438
  first_ = true;
@@ -504,18 +505,18 @@ class Iterator final : public BaseIterator {
504
505
  readOptions.ignore_range_deletions = false;
505
506
  NAPI_STATUS_THROWS(GetProperty(env, options, "ignoreRangeDeletions", readOptions.ignore_range_deletions));
506
507
 
507
- uint32_t timeout = 0;
508
- NAPI_STATUS_THROWS(GetProperty(env, options, "timeout", timeout));
508
+ // uint32_t timeout = 0;
509
+ // NAPI_STATUS_THROWS(GetProperty(env, options, "timeout", timeout));
509
510
 
510
- readOptions.deadline = timeout
511
- ? std::chrono::microseconds(database->db->GetEnv()->NowMicros() + timeout * 1000)
512
- : std::chrono::microseconds::zero();
511
+ // readOptions.deadline = timeout
512
+ // ? std::chrono::microseconds(database->db->GetEnv()->NowMicros() + timeout * 1000)
513
+ // : std::chrono::microseconds::zero();
513
514
 
514
515
  return std::make_unique<Iterator>(database, column, reverse, keys, values, limit, lt, lte, gt, gte,
515
516
  highWaterMarkBytes, keyEncoding, valueEncoding, readOptions);
516
517
  }
517
518
 
518
- napi_value nextv(napi_env env, uint32_t count, napi_value callback) {
519
+ napi_value nextv(napi_env env, uint32_t count, uint32_t timeout, napi_value callback) {
519
520
  struct State {
520
521
  std::vector<rocksdb::PinnableSlice> keys;
521
522
  std::vector<rocksdb::PinnableSlice> values;
@@ -528,18 +529,18 @@ class Iterator final : public BaseIterator {
528
529
  state.keys.reserve(count);
529
530
  state.values.reserve(count);
530
531
 
532
+ const auto deadline = timeout
533
+ ? database_->db->GetEnv()->NowMicros() + timeout * 1000
534
+ : 0;
535
+
531
536
  size_t bytesRead = 0;
532
- while (true) {
537
+ for (int n = 0; n < count; n++) {
533
538
  if (!first_) {
534
539
  Next();
535
540
  } else {
536
541
  first_ = false;
537
542
  }
538
543
 
539
- if (Status().IsTimedOut()) {
540
- break;
541
- }
542
-
543
544
  ROCKS_STATUS_RETURN(Status());
544
545
 
545
546
  if (!Valid() || !Increment()) {
@@ -550,30 +551,30 @@ class Iterator final : public BaseIterator {
550
551
  if (keys_ && values_) {
551
552
  rocksdb::PinnableSlice k;
552
553
  k.PinSelf(CurrentKey());
553
- bytesRead += k.size();
554
554
  state.keys.push_back(std::move(k));
555
555
 
556
556
  rocksdb::PinnableSlice v;
557
557
  v.PinSelf(CurrentValue());
558
- bytesRead += v.size();
559
558
  state.values.push_back(std::move(v));
560
559
  } else if (keys_) {
561
560
  rocksdb::PinnableSlice k;
562
561
  k.PinSelf(CurrentKey());
563
- bytesRead += k.size();
564
562
  state.keys.push_back(std::move(k));
565
563
  } else if (values_) {
566
564
  rocksdb::PinnableSlice v;
567
565
  v.PinSelf(CurrentValue());
568
- bytesRead += v.size();
569
566
  state.values.push_back(std::move(v));
570
567
  } else {
571
568
  assert(false);
572
569
  }
573
-
574
570
  state.count += 1;
575
571
 
576
- if (bytesRead > highWaterMarkBytes_ || state.count >= count) {
572
+ bytesRead += CurrentKey().size() + CurrentValue().size();
573
+ if (bytesRead > highWaterMarkBytes_) {
574
+ break;
575
+ }
576
+
577
+ if (deadline > 0 && database_->db->GetEnv()->NowMicros() > deadline) {
577
578
  break;
578
579
  }
579
580
  }
@@ -620,26 +621,26 @@ class Iterator final : public BaseIterator {
620
621
  return 0;
621
622
  }
622
623
 
623
- napi_value nextv(napi_env env, uint32_t count) {
624
+ napi_value nextv(napi_env env, uint32_t count, uint32_t timeout = 0) {
624
625
  napi_value finished;
625
626
  NAPI_STATUS_THROWS(napi_get_boolean(env, false, &finished));
626
627
 
627
628
  napi_value rows;
628
629
  NAPI_STATUS_THROWS(napi_create_array(env, &rows));
629
630
 
631
+ const auto deadline = timeout
632
+ ? database_->db->GetEnv()->NowMicros() + timeout * 1000
633
+ : 0;
634
+
630
635
  size_t idx = 0;
631
636
  size_t bytesRead = 0;
632
- while (true) {
637
+ for (int n = 0; n < count; n++) {
633
638
  if (!first_) {
634
639
  Next();
635
640
  } else {
636
641
  first_ = false;
637
642
  }
638
643
 
639
- if (Status().IsTimedOut()) {
640
- break;
641
- }
642
-
643
644
  ROCKS_STATUS_THROWS_NAPI(Status());
644
645
 
645
646
  if (!Valid() || !Increment()) {
@@ -655,17 +656,14 @@ class Iterator final : public BaseIterator {
655
656
  const auto v = CurrentValue();
656
657
  NAPI_STATUS_THROWS(Convert(env, &k, keyEncoding_, key));
657
658
  NAPI_STATUS_THROWS(Convert(env, &v, valueEncoding_, val));
658
- bytesRead += k.size() + v.size();
659
659
  } else if (keys_) {
660
660
  const auto k = CurrentKey();
661
661
  NAPI_STATUS_THROWS(Convert(env, &k, keyEncoding_, key));
662
662
  NAPI_STATUS_THROWS(napi_get_undefined(env, &val));
663
- bytesRead += k.size();
664
663
  } else if (values_) {
665
664
  const auto v = CurrentValue();
666
665
  NAPI_STATUS_THROWS(napi_get_undefined(env, &key));
667
666
  NAPI_STATUS_THROWS(Convert(env, &v, valueEncoding_, val));
668
- bytesRead += v.size();
669
667
  } else {
670
668
  assert(false);
671
669
  }
@@ -673,7 +671,12 @@ class Iterator final : public BaseIterator {
673
671
  NAPI_STATUS_THROWS(napi_set_element(env, rows, idx++, key));
674
672
  NAPI_STATUS_THROWS(napi_set_element(env, rows, idx++, val));
675
673
 
676
- if (bytesRead > highWaterMarkBytes_ || idx / 2 >= count) {
674
+ bytesRead += CurrentKey().size() + CurrentValue().size();
675
+ if (bytesRead > highWaterMarkBytes_) {
676
+ break;
677
+ }
678
+
679
+ if (deadline > 0 && database_->db->GetEnv()->NowMicros() > deadline) {
677
680
  break;
678
681
  }
679
682
  }
@@ -776,7 +779,12 @@ NAPI_METHOD(db_get_location) {
776
779
  NAPI_METHOD(db_query) {
777
780
  NAPI_ARGV(2);
778
781
 
779
- return Iterator::create(env, argv[0], argv[1])->nextv(env, std::numeric_limits<uint32_t>::max());
782
+ try {
783
+ return Iterator::create(env, argv[0], argv[1])->nextv(env, std::numeric_limits<uint32_t>::max());
784
+ } catch (const std::exception& e) {
785
+ napi_throw_error(env, nullptr, e.what());
786
+ return nullptr;
787
+ }
780
788
  }
781
789
 
782
790
  template <typename T, typename U>
@@ -786,50 +794,50 @@ napi_status InitOptions(napi_env env, T& columnOptions, const U& options) {
786
794
  uint64_t memtable_memory_budget = 256 * 1024 * 1024;
787
795
  NAPI_STATUS_RETURN(GetProperty(env, options, "memtableMemoryBudget", memtable_memory_budget));
788
796
 
789
- std::optional<std::string> compactionOpt;
790
- NAPI_STATUS_RETURN(GetProperty(env, options, "compaction", compactionOpt));
791
- if (compactionOpt) {
792
- if (*compactionOpt == "universal") {
793
- columnOptions.write_buffer_size = memtable_memory_budget / 4;
794
- // merge two memtables when flushing to L0
795
- columnOptions.min_write_buffer_number_to_merge = 2;
796
- // this means we'll use 50% extra memory in the worst case, but will reduce
797
- // write stalls.
798
- columnOptions.max_write_buffer_number = 6;
799
- // universal style compaction
800
- columnOptions.compaction_style = rocksdb::kCompactionStyleUniversal;
801
- columnOptions.compaction_options_universal.compression_size_percent = 80;
802
- } else if (*compactionOpt == "level") {
803
- columnOptions.write_buffer_size = static_cast<size_t>(memtable_memory_budget / 4);
804
- // merge two memtables when flushing to L0
805
- columnOptions.min_write_buffer_number_to_merge = 2;
806
- // this means we'll use 50% extra memory in the worst case, but will reduce
807
- // write stalls.
808
- columnOptions.max_write_buffer_number = 6;
809
- // start flushing L0->L1 as soon as possible. each file on level0 is
810
- // (memtable_memory_budget / 2). This will flush level 0 when it's bigger than
811
- // memtable_memory_budget.
812
- columnOptions.level0_file_num_compaction_trigger = 2;
813
- // doesn't really matter much, but we don't want to create too many files
814
- columnOptions.target_file_size_base = memtable_memory_budget / 8;
815
- // make Level1 size equal to Level0 size, so that L0->L1 compactions are fast
816
- columnOptions.max_bytes_for_level_base = memtable_memory_budget;
817
-
818
- // level style compaction
819
- columnOptions.compaction_style = rocksdb::kCompactionStyleLevel;
820
-
821
- // only compress levels >= 2
822
- columnOptions.compression_per_level.resize(columnOptions.num_levels);
823
- for (int i = 0; i < columnOptions.num_levels; ++i) {
824
- if (i < 2) {
825
- columnOptions.compression_per_level[i] = rocksdb::kNoCompression;
826
- } else {
827
- columnOptions.compression_per_level[i] = rocksdb::kZSTD;
828
- }
797
+ std::string compaction;
798
+ NAPI_STATUS_RETURN(GetProperty(env, options, "compaction", compaction));
799
+ if (compaction == "") {
800
+ // Do nothing...
801
+ } else if (compaction == "universal") {
802
+ columnOptions.write_buffer_size = memtable_memory_budget / 4;
803
+ // merge two memtables when flushing to L0
804
+ columnOptions.min_write_buffer_number_to_merge = 2;
805
+ // this means we'll use 50% extra memory in the worst case, but will reduce
806
+ // write stalls.
807
+ columnOptions.max_write_buffer_number = 6;
808
+ // universal style compaction
809
+ columnOptions.compaction_style = rocksdb::kCompactionStyleUniversal;
810
+ columnOptions.compaction_options_universal.compression_size_percent = 80;
811
+ } else if (compaction == "level") {
812
+ columnOptions.write_buffer_size = static_cast<size_t>(memtable_memory_budget / 4);
813
+ // merge two memtables when flushing to L0
814
+ columnOptions.min_write_buffer_number_to_merge = 2;
815
+ // this means we'll use 50% extra memory in the worst case, but will reduce
816
+ // write stalls.
817
+ columnOptions.max_write_buffer_number = 6;
818
+ // start flushing L0->L1 as soon as possible. each file on level0 is
819
+ // (memtable_memory_budget / 2). This will flush level 0 when it's bigger than
820
+ // memtable_memory_budget.
821
+ columnOptions.level0_file_num_compaction_trigger = 2;
822
+ // doesn't really matter much, but we don't want to create too many files
823
+ columnOptions.target_file_size_base = memtable_memory_budget / 8;
824
+ // make Level1 size equal to Level0 size, so that L0->L1 compactions are fast
825
+ columnOptions.max_bytes_for_level_base = memtable_memory_budget;
826
+
827
+ // level style compaction
828
+ columnOptions.compaction_style = rocksdb::kCompactionStyleLevel;
829
+
830
+ // only compress levels >= 2
831
+ columnOptions.compression_per_level.resize(columnOptions.num_levels);
832
+ for (int i = 0; i < columnOptions.num_levels; ++i) {
833
+ if (i < 2) {
834
+ columnOptions.compression_per_level[i] = rocksdb::kNoCompression;
835
+ } else {
836
+ columnOptions.compression_per_level[i] = rocksdb::kZSTD;
829
837
  }
830
- } else {
831
- return napi_invalid_arg;
832
838
  }
839
+ } else {
840
+ return napi_invalid_arg;
833
841
  }
834
842
 
835
843
  bool compression = true;
@@ -888,15 +896,17 @@ napi_status InitOptions(napi_env env, T& columnOptions, const U& options) {
888
896
  columnOptions.optimize_filters_for_hits = false;
889
897
  NAPI_STATUS_RETURN(GetProperty(env, options, "optimizeFiltersForHits", columnOptions.optimize_filters_for_hits));
890
898
 
891
- uint32_t cacheSize = 8 << 20;
892
- NAPI_STATUS_RETURN(GetProperty(env, options, "cacheSize", cacheSize));
893
-
894
899
  rocksdb::BlockBasedTableOptions tableOptions;
895
900
 
896
- if (cacheSize) {
897
- tableOptions.block_cache = rocksdb::HyperClockCacheOptions(cacheSize, 0).MakeSharedCache();
898
- } else {
899
- tableOptions.no_block_cache = true;
901
+ {
902
+ uint32_t cacheSize = 8 << 20;
903
+ NAPI_STATUS_RETURN(GetProperty(env, options, "cacheSize", cacheSize));
904
+
905
+ if (cacheSize) {
906
+ tableOptions.block_cache = rocksdb::HyperClockCacheOptions(cacheSize, 0).MakeSharedCache();
907
+ } else {
908
+ tableOptions.no_block_cache = true;
909
+ }
900
910
  }
901
911
 
902
912
  std::string optimize = "";
@@ -915,11 +925,11 @@ napi_status InitOptions(napi_env env, T& columnOptions, const U& options) {
915
925
  tableOptions.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10));
916
926
  }
917
927
 
918
- std::optional<std::string> filterPolicyOpt;
919
- NAPI_STATUS_RETURN(GetProperty(env, options, "filterPolicy", filterPolicyOpt));
920
- if (filterPolicyOpt) {
928
+ std::string filterPolicy;
929
+ NAPI_STATUS_RETURN(GetProperty(env, options, "filterPolicy", filterPolicy));
930
+ if (filterPolicy != "") {
921
931
  ROCKS_STATUS_RETURN_NAPI(
922
- rocksdb::FilterPolicy::CreateFromString(configOptions, *filterPolicyOpt, &tableOptions.filter_policy));
932
+ rocksdb::FilterPolicy::CreateFromString(configOptions, filterPolicy, &tableOptions.filter_policy));
923
933
  }
924
934
 
925
935
  tableOptions.block_size = 4 * 1024;
@@ -1469,11 +1479,16 @@ NAPI_METHOD(db_get_latest_sequence) {
1469
1479
  NAPI_METHOD(iterator_init) {
1470
1480
  NAPI_ARGV(2);
1471
1481
 
1472
- auto iterator = Iterator::create(env, argv[0], argv[1]);
1473
-
1474
1482
  napi_value result;
1475
- NAPI_STATUS_THROWS(napi_create_external(env, iterator.get(), Finalize<Iterator>, iterator.get(), &result));
1476
- iterator.release();
1483
+ try {
1484
+ auto iterator = Iterator::create(env, argv[0], argv[1]);
1485
+
1486
+ NAPI_STATUS_THROWS(napi_create_external(env, iterator.get(), Finalize<Iterator>, iterator.get(), &result));
1487
+ iterator.release();
1488
+ } catch (const std::exception& e) {
1489
+ napi_throw_error(env, nullptr, e.what());
1490
+ return nullptr;
1491
+ }
1477
1492
 
1478
1493
  return result;
1479
1494
  }
@@ -1481,13 +1496,18 @@ NAPI_METHOD(iterator_init) {
1481
1496
  NAPI_METHOD(iterator_seek) {
1482
1497
  NAPI_ARGV(2);
1483
1498
 
1484
- Iterator* iterator;
1485
- NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&iterator)));
1499
+ try {
1500
+ Iterator* iterator;
1501
+ NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&iterator)));
1486
1502
 
1487
- rocksdb::PinnableSlice target;
1488
- NAPI_STATUS_THROWS(GetValue(env, argv[1], target));
1503
+ rocksdb::PinnableSlice target;
1504
+ NAPI_STATUS_THROWS(GetValue(env, argv[1], target));
1489
1505
 
1490
- iterator->Seek(target);
1506
+ iterator->Seek(target);
1507
+ } catch (const std::exception& e) {
1508
+ napi_throw_error(env, nullptr, e.what());
1509
+ return nullptr;
1510
+ }
1491
1511
 
1492
1512
  return 0;
1493
1513
  }
@@ -1495,36 +1515,57 @@ NAPI_METHOD(iterator_seek) {
1495
1515
  NAPI_METHOD(iterator_close) {
1496
1516
  NAPI_ARGV(1);
1497
1517
 
1498
- Iterator* iterator;
1499
- NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&iterator)));
1518
+ try {
1519
+ Iterator* iterator;
1520
+ NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&iterator)));
1500
1521
 
1501
- ROCKS_STATUS_THROWS_NAPI(iterator->Close());
1522
+ ROCKS_STATUS_THROWS_NAPI(iterator->Close());
1523
+ } catch (const std::exception& e) {
1524
+ napi_throw_error(env, nullptr, e.what());
1525
+ return nullptr;
1526
+ }
1502
1527
 
1503
1528
  return 0;
1504
1529
  }
1505
1530
 
1506
1531
  NAPI_METHOD(iterator_nextv) {
1507
- NAPI_ARGV(3);
1532
+ NAPI_ARGV(4);
1508
1533
 
1509
- Iterator* iterator;
1510
- NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&iterator)));
1534
+ try {
1535
+ Iterator* iterator;
1536
+ NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&iterator)));
1511
1537
 
1512
- uint32_t count;
1513
- NAPI_STATUS_THROWS(napi_get_value_uint32(env, argv[1], &count));
1538
+ uint32_t count = 1024;
1539
+ NAPI_STATUS_THROWS(GetValue(env, argv[1], count));
1540
+
1541
+ uint32_t timeout = 0;
1542
+ NAPI_STATUS_THROWS(GetProperty(env, argv[2], "timeout", timeout));
1514
1543
 
1515
- return iterator->nextv(env, count, argv[2]);
1544
+ return iterator->nextv(env, count, timeout, argv[3]);
1545
+ } catch (const std::exception& e) {
1546
+ napi_throw_error(env, nullptr, e.what());
1547
+ return nullptr;
1548
+ }
1516
1549
  }
1517
1550
 
1518
1551
  NAPI_METHOD(iterator_nextv_sync) {
1519
- NAPI_ARGV(2);
1552
+ NAPI_ARGV(3);
1520
1553
 
1521
- Iterator* iterator;
1522
- NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&iterator)));
1554
+ try {
1555
+ Iterator* iterator;
1556
+ NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&iterator)));
1523
1557
 
1524
- uint32_t count;
1525
- NAPI_STATUS_THROWS(napi_get_value_uint32(env, argv[1], &count));
1558
+ uint32_t count = 1024;
1559
+ NAPI_STATUS_THROWS(GetValue(env, argv[1], count));
1526
1560
 
1527
- return iterator->nextv(env, count);
1561
+ uint32_t timeout = 0;
1562
+ NAPI_STATUS_THROWS(GetProperty(env, argv[2], "timeout", timeout));
1563
+
1564
+ return iterator->nextv(env, count, timeout);
1565
+ } catch (const std::exception& e) {
1566
+ napi_throw_error(env, nullptr, e.what());
1567
+ return nullptr;
1568
+ }
1528
1569
  }
1529
1570
 
1530
1571
  NAPI_METHOD(batch_init) {
package/binding.gyp CHANGED
@@ -8,9 +8,13 @@
8
8
  [
9
9
  "OS == 'linux'",
10
10
  {
11
+ "direct_dependent_settings": {
12
+ "libraries": [
13
+ ],
14
+ },
11
15
  "include_dirs": [
12
- "/usr/lib/x86_64-linux-gnu/include",
13
- "/usr/lib/include",
16
+ "/usr/lib/x86_64-linux-gnu/include",
17
+ "/usr/lib/include",
14
18
  ],
15
19
  "cflags": ["-march=znver1"],
16
20
  "ccflags": ["-flto", '-march=znver1'],
@@ -22,6 +26,12 @@
22
26
  [
23
27
  "OS == 'mac'",
24
28
  {
29
+ "direct_dependent_settings": {
30
+ "libraries": [
31
+ ],
32
+ },
33
+ "include_dirs": [
34
+ ],
25
35
  "xcode_settings": {
26
36
  "WARNING_CFLAGS": [
27
37
  "-Wno-sign-compare",
package/iterator.js CHANGED
@@ -96,7 +96,7 @@ class Iterator extends AbstractIterator {
96
96
  this[kFirst] = false
97
97
 
98
98
  try {
99
- const { rows, finished } = binding.iterator_nextv_sync(this[kContext], size)
99
+ const { rows, finished } = binding.iterator_nextv_sync(this[kContext], size, null)
100
100
  this[kCache] = rows
101
101
  this[kFinished] = finished
102
102
  this[kPosition] = 0
@@ -162,7 +162,7 @@ class Iterator extends AbstractIterator {
162
162
  }
163
163
 
164
164
  this[kFirst] = false
165
- const result = binding.iterator_nextv_sync(this[kContext], size)
165
+ const result = binding.iterator_nextv_sync(this[kContext], size, options)
166
166
  this[kFinished] = result.finished
167
167
 
168
168
  return result
@@ -182,7 +182,7 @@ class Iterator extends AbstractIterator {
182
182
  this[kFirst] = false
183
183
  this[kBusy] = true
184
184
  this[kDB][kRef]()
185
- binding.iterator_nextv(this[kContext], size, (err, result) => {
185
+ binding.iterator_nextv(this[kContext], size, options, (err, result) => {
186
186
  this[kBusy] = false
187
187
  this[kDB][kUnref]()
188
188
  if (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/rocksdb",
3
- "version": "13.0.3",
3
+ "version": "13.1.1",
4
4
  "description": "A low-level Node.js RocksDB binding",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
package/util.h CHANGED
@@ -260,6 +260,10 @@ static napi_status GetValue(napi_env env, napi_value value, rocksdb::ColumnFamil
260
260
  return napi_get_value_external(env, value, reinterpret_cast<void**>(&result));
261
261
  }
262
262
 
263
+ static napi_status GetValue(napi_env env, napi_value value, std::shared_ptr<rocksdb::Cache>*& result) {
264
+ return napi_get_value_external(env, value, reinterpret_cast<void**>(&result));
265
+ }
266
+
263
267
  static napi_status GetValue(napi_env env, napi_value value, Encoding& result) {
264
268
  size_t size;
265
269
  NAPI_STATUS_RETURN(napi_get_value_string_utf8(env, value, nullptr, 0, &size));