@nxtedition/rocksdb 11.0.4 → 11.0.6

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
@@ -307,12 +307,15 @@ struct BaseIterator : public Closable {
307
307
  }
308
308
 
309
309
  rocksdb::ReadOptions readOptions;
310
+
310
311
  if (upper_bound_) {
311
312
  readOptions.iterate_upper_bound = &*upper_bound_;
312
313
  }
314
+
313
315
  if (lower_bound_) {
314
316
  readOptions.iterate_lower_bound = &*lower_bound_;
315
317
  }
318
+
316
319
  readOptions.fill_cache = fillCache;
317
320
  readOptions.async_io = true;
318
321
  readOptions.adaptive_readahead = true;
@@ -329,9 +332,15 @@ struct BaseIterator : public Closable {
329
332
  database_->Attach(this);
330
333
  }
331
334
 
332
- virtual ~BaseIterator() { assert(!iterator_); }
335
+ virtual ~BaseIterator() {
336
+ if (iterator_) {
337
+ database_->Detach(this);
338
+ }
339
+ }
333
340
 
334
341
  virtual void Seek(const rocksdb::Slice& target) {
342
+ assert(iterator_);
343
+
335
344
  if ((upper_bound_ && target.compare(*upper_bound_) >= 0) || (lower_bound_ && target.compare(*lower_bound_) < 0)) {
336
345
  // TODO (fix): Why is this required? Seek should handle it?
337
346
  // https://github.com/facebook/rocksdb/issues/9904
@@ -347,8 +356,10 @@ struct BaseIterator : public Closable {
347
356
  }
348
357
 
349
358
  virtual rocksdb::Status Close() override {
350
- iterator_.reset();
351
- database_->Detach(this);
359
+ if (iterator_) {
360
+ iterator_.reset();
361
+ database_->Detach(this);
362
+ }
352
363
  return rocksdb::Status::OK();
353
364
  }
354
365
 
@@ -632,7 +643,6 @@ NAPI_METHOD(db_get_location) {
632
643
  return result;
633
644
  }
634
645
 
635
-
636
646
  NAPI_METHOD(db_query) {
637
647
  NAPI_ARGV(2);
638
648
 
@@ -986,7 +996,7 @@ NAPI_METHOD(db_close) {
986
996
  return 0;
987
997
  }
988
998
 
989
- NAPI_METHOD(db_get_many) {
999
+ NAPI_METHOD(db_get_many_sync) {
990
1000
  NAPI_ARGV(3);
991
1001
 
992
1002
  Database* database;
@@ -1028,9 +1038,6 @@ NAPI_METHOD(db_get_many) {
1028
1038
  napi_value rows;
1029
1039
  NAPI_STATUS_THROWS(napi_create_array_with_length(env, count, &rows));
1030
1040
 
1031
- napi_value finished;
1032
- NAPI_STATUS_THROWS(napi_get_boolean(env, true, &finished));
1033
-
1034
1041
  for (auto n = 0; n < count; n++) {
1035
1042
  napi_value row;
1036
1043
  if (statuses[n].IsNotFound()) {
@@ -1044,11 +1051,88 @@ NAPI_METHOD(db_get_many) {
1044
1051
  NAPI_STATUS_THROWS(napi_set_element(env, rows, n, row));
1045
1052
  }
1046
1053
 
1047
- napi_value ret;
1048
- NAPI_STATUS_THROWS(napi_create_object(env, &ret));
1049
- NAPI_STATUS_THROWS(napi_set_named_property(env, ret, "rows", rows));
1050
- NAPI_STATUS_THROWS(napi_set_named_property(env, ret, "finished", finished));
1051
- return ret;
1054
+ return rows;
1055
+ }
1056
+
1057
+ NAPI_METHOD(db_get_many) {
1058
+ NAPI_ARGV(4);
1059
+
1060
+ Database* database;
1061
+ NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
1062
+
1063
+ uint32_t count;
1064
+ NAPI_STATUS_THROWS(napi_get_array_length(env, argv[1], &count));
1065
+
1066
+ bool fillCache = true;
1067
+ NAPI_STATUS_THROWS(GetProperty(env, argv[2], "fillCache", fillCache));
1068
+
1069
+ rocksdb::ColumnFamilyHandle* column = database->db->DefaultColumnFamily();
1070
+ NAPI_STATUS_THROWS(GetProperty(env, argv[2], "column", column));
1071
+
1072
+ Encoding valueEncoding = Encoding::Buffer;
1073
+ NAPI_STATUS_THROWS(GetProperty(env, argv[2], "valueEncoding", valueEncoding));
1074
+
1075
+ int32_t highWaterMarkBytes = std::numeric_limits<int32_t>::max();
1076
+ NAPI_STATUS_THROWS(GetProperty(env, argv[2], "highWaterMarkBytes", highWaterMarkBytes));
1077
+
1078
+ auto callback = argv[3];
1079
+
1080
+ std::vector<rocksdb::PinnableSlice> keys{count};
1081
+
1082
+ for (uint32_t n = 0; n < count; n++) {
1083
+ napi_value element;
1084
+ NAPI_STATUS_THROWS(napi_get_element(env, argv[1], n, &element));
1085
+ NAPI_STATUS_THROWS(GetValue(env, element, keys[n]));
1086
+ }
1087
+
1088
+ struct State {
1089
+ std::vector<rocksdb::Status> statuses;
1090
+ std::vector<rocksdb::PinnableSlice> values;
1091
+ };
1092
+
1093
+ runAsync<State>(
1094
+ "leveldown.get_many", env, callback,
1095
+ [=, keys = std::move(keys)](auto& state) {
1096
+ std::vector<rocksdb::Slice> keys2{count};
1097
+ for (uint32_t n = 0; n < count; n++) {
1098
+ keys2[n] = keys[n];
1099
+ }
1100
+
1101
+ rocksdb::ReadOptions readOptions;
1102
+ readOptions.fill_cache = fillCache;
1103
+ readOptions.async_io = true;
1104
+ readOptions.optimize_multiget_for_io = true;
1105
+ readOptions.value_size_soft_limit = highWaterMarkBytes;
1106
+
1107
+ state.statuses.resize(count);
1108
+ state.values.resize(count);
1109
+
1110
+ database->db->MultiGet(readOptions, column, count, keys2.data(), state.values.data(), state.statuses.data());
1111
+
1112
+ return rocksdb::Status::OK();
1113
+ },
1114
+ [=](auto& state, auto env, auto& argv) {
1115
+ argv.resize(2);
1116
+
1117
+ NAPI_STATUS_RETURN(napi_create_array_with_length(env, count, &argv[1]));
1118
+
1119
+ for (auto n = 0; n < count; n++) {
1120
+ napi_value row;
1121
+ if (state.statuses[n].IsNotFound()) {
1122
+ NAPI_STATUS_RETURN(napi_get_undefined(env, &row));
1123
+ } else if (state.statuses[n].IsAborted()) {
1124
+ NAPI_STATUS_RETURN(napi_get_null(env, &row));
1125
+ } else {
1126
+ ROCKS_STATUS_RETURN_NAPI(state.statuses[n]);
1127
+ NAPI_STATUS_RETURN(Convert(env, &state.values[n], valueEncoding, row));
1128
+ }
1129
+ NAPI_STATUS_RETURN(napi_set_element(env, argv[1], n, row));
1130
+ }
1131
+
1132
+ return napi_ok;
1133
+ });
1134
+
1135
+ return 0;
1052
1136
  }
1053
1137
 
1054
1138
  NAPI_METHOD(db_clear) {
@@ -1253,10 +1337,8 @@ NAPI_METHOD(batch_put) {
1253
1337
  rocksdb::Slice val;
1254
1338
  NAPI_STATUS_THROWS(GetValue(env, argv[2], val));
1255
1339
 
1256
- const auto options = argv[3];
1257
-
1258
1340
  rocksdb::ColumnFamilyHandle* column = nullptr;
1259
- NAPI_STATUS_THROWS(GetProperty(env, options, "column", column));
1341
+ NAPI_STATUS_THROWS(GetProperty(env, argv[3], "column", column));
1260
1342
 
1261
1343
  if (column) {
1262
1344
  ROCKS_STATUS_THROWS_NAPI(batch->Put(column, key, val));
@@ -1276,10 +1358,8 @@ NAPI_METHOD(batch_del) {
1276
1358
  rocksdb::Slice key;
1277
1359
  NAPI_STATUS_THROWS(GetValue(env, argv[1], key));
1278
1360
 
1279
- const auto options = argv[2];
1280
-
1281
1361
  rocksdb::ColumnFamilyHandle* column = nullptr;
1282
- NAPI_STATUS_THROWS(GetProperty(env, options, "column", column));
1362
+ NAPI_STATUS_THROWS(GetProperty(env, argv[2], "column", column));
1283
1363
 
1284
1364
  if (column) {
1285
1365
  ROCKS_STATUS_THROWS_NAPI(batch->Delete(column, key));
@@ -1302,10 +1382,8 @@ NAPI_METHOD(batch_merge) {
1302
1382
  rocksdb::Slice val;
1303
1383
  NAPI_STATUS_THROWS(GetValue(env, argv[2], val));
1304
1384
 
1305
- const auto options = argv[3];
1306
-
1307
1385
  rocksdb::ColumnFamilyHandle* column = nullptr;
1308
- NAPI_STATUS_THROWS(GetProperty(env, options, "column", column));
1386
+ NAPI_STATUS_THROWS(GetProperty(env, argv[3], "column", column));
1309
1387
 
1310
1388
  if (column) {
1311
1389
  ROCKS_STATUS_THROWS_NAPI(batch->Merge(column, key, val));
@@ -1328,7 +1406,7 @@ NAPI_METHOD(batch_clear) {
1328
1406
  }
1329
1407
 
1330
1408
  NAPI_METHOD(batch_write) {
1331
- NAPI_ARGV(4);
1409
+ NAPI_ARGV(3);
1332
1410
 
1333
1411
  Database* database;
1334
1412
  NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
@@ -1336,14 +1414,11 @@ NAPI_METHOD(batch_write) {
1336
1414
  rocksdb::WriteBatch* batch;
1337
1415
  NAPI_STATUS_THROWS(napi_get_value_external(env, argv[1], reinterpret_cast<void**>(&batch)));
1338
1416
 
1339
- auto options = argv[2];
1340
- auto callback = argv[3];
1341
-
1342
1417
  bool sync = false;
1343
- NAPI_STATUS_THROWS(GetProperty(env, options, "sync", sync));
1418
+ NAPI_STATUS_THROWS(GetProperty(env, argv[2], "sync", sync));
1344
1419
 
1345
1420
  bool lowPriority = false;
1346
- NAPI_STATUS_THROWS(GetProperty(env, options, "lowPriority", lowPriority));
1421
+ NAPI_STATUS_THROWS(GetProperty(env, argv[2], "lowPriority", lowPriority));
1347
1422
 
1348
1423
  rocksdb::WriteOptions writeOptions;
1349
1424
  writeOptions.sync = sync;
@@ -1410,6 +1485,7 @@ NAPI_INIT() {
1410
1485
  NAPI_EXPORT_FUNCTION(db_get_location);
1411
1486
  NAPI_EXPORT_FUNCTION(db_close);
1412
1487
  NAPI_EXPORT_FUNCTION(db_get_many);
1488
+ NAPI_EXPORT_FUNCTION(db_get_many_sync);
1413
1489
  NAPI_EXPORT_FUNCTION(db_clear);
1414
1490
  NAPI_EXPORT_FUNCTION(db_get_property);
1415
1491
  NAPI_EXPORT_FUNCTION(db_get_latest_sequence);
package/index.js CHANGED
@@ -152,11 +152,14 @@ class RocksLevel extends AbstractLevel {
152
152
  }
153
153
 
154
154
  _getMany (keys, options, callback) {
155
+ if (keys.some(key => typeof key === 'string')) {
156
+ keys = keys.map(key => typeof key === 'string' ? Buffer.from(key) : key)
157
+ }
158
+
155
159
  callback = fromCallback(callback, kPromise)
156
160
 
157
161
  try {
158
- // TODO (fix): highWaterMark and limit with async between...
159
- process.nextTick(callback, null, this._getManySync(keys, options ?? kEmpty))
162
+ binding.db_get_many(this[kContext], keys, options ?? kEmpty, callback)
160
163
  } catch (err) {
161
164
  process.nextTick(callback, err)
162
165
  }
@@ -169,9 +172,7 @@ class RocksLevel extends AbstractLevel {
169
172
  keys = keys.map(key => typeof key === 'string' ? Buffer.from(key) : key)
170
173
  }
171
174
 
172
- const { rows, finished } = binding.db_get_many(this[kContext], keys, options ?? kEmpty)
173
- assert(finished)
174
- return rows
175
+ return binding.db_get_many_sync(this[kContext], keys, options ?? kEmpty)
175
176
  }
176
177
 
177
178
  _del (key, options, callback) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/rocksdb",
3
- "version": "11.0.4",
3
+ "version": "11.0.6",
4
4
  "description": "A low-level Node.js RocksDB binding",
5
5
  "license": "MIT",
6
6
  "main": "index.js",