rocksdb-native 1.0.0 → 1.2.0

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.c CHANGED
@@ -45,14 +45,20 @@ typedef struct {
45
45
  js_ref_t *on_close;
46
46
  } rocksdb_native_close_t;
47
47
 
48
+ typedef struct {
49
+ rocksdb_delete_range_t handle;
50
+
51
+ js_env_t *env;
52
+ js_ref_t *ctx;
53
+ js_ref_t *on_status;
54
+ } rocksdb_native_delete_range_t;
55
+
48
56
  typedef struct {
49
57
  rocksdb_iterator_t handle;
50
58
 
51
59
  rocksdb_slice_t *keys;
52
60
  rocksdb_slice_t *values;
53
61
 
54
- size_t capacity;
55
-
56
62
  js_env_t *env;
57
63
  js_ref_t *ctx;
58
64
  js_ref_t *on_open;
@@ -280,6 +286,101 @@ rocksdb_native_close (js_env_t *env, js_callback_info_t *info) {
280
286
  return handle;
281
287
  }
282
288
 
289
+ static void
290
+ rocksdb_native__on_delete_range (rocksdb_delete_range_t *handle, int status) {
291
+ int err;
292
+
293
+ assert(status == 0);
294
+
295
+ rocksdb_native_delete_range_t *req = (rocksdb_native_delete_range_t *) handle->data;
296
+
297
+ js_env_t *env = req->env;
298
+
299
+ js_handle_scope_t *scope;
300
+ err = js_open_handle_scope(env, &scope);
301
+ assert(err == 0);
302
+
303
+ js_value_t *ctx;
304
+ err = js_get_reference_value(env, req->ctx, &ctx);
305
+ assert(err == 0);
306
+
307
+ js_value_t *cb;
308
+ err = js_get_reference_value(env, req->on_status, &cb);
309
+ assert(err == 0);
310
+
311
+ js_value_t *error;
312
+
313
+ if (req->handle.error) {
314
+ err = js_create_string_utf8(env, (utf8_t *) req->handle.error, -1, &error);
315
+ assert(err == 0);
316
+ } else {
317
+ err = js_get_null(env, &error);
318
+ assert(err == 0);
319
+ }
320
+
321
+ js_call_function(env, ctx, cb, 1, (js_value_t *[]){error}, NULL);
322
+
323
+ err = js_close_handle_scope(env, scope);
324
+ assert(err == 0);
325
+
326
+ err = js_delete_reference(env, req->on_status);
327
+ assert(err == 0);
328
+
329
+ err = js_delete_reference(env, req->ctx);
330
+ assert(err == 0);
331
+ }
332
+
333
+ static js_value_t *
334
+ rocksdb_native_delete_range (js_env_t *env, js_callback_info_t *info) {
335
+ int err;
336
+
337
+ size_t argc = 7;
338
+ js_value_t *argv[7];
339
+
340
+ err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
341
+ assert(err == 0);
342
+
343
+ assert(argc == 7);
344
+
345
+ rocksdb_native_t *db;
346
+ err = js_get_arraybuffer_info(env, argv[0], (void **) &db, NULL);
347
+ assert(err == 0);
348
+
349
+ js_value_t *handle;
350
+
351
+ rocksdb_native_delete_range_t *req;
352
+ err = js_create_arraybuffer(env, sizeof(rocksdb_native_delete_range_t), (void **) &req, &handle);
353
+ assert(err == 0);
354
+
355
+ req->env = env;
356
+ req->handle.data = (void *) req;
357
+
358
+ rocksdb_range_t range;
359
+
360
+ err = js_get_typedarray_info(env, argv[1], NULL, (void **) &range.gt.data, &range.gt.len, NULL, NULL);
361
+ assert(err == 0);
362
+
363
+ err = js_get_typedarray_info(env, argv[2], NULL, (void **) &range.gte.data, &range.gte.len, NULL, NULL);
364
+ assert(err == 0);
365
+
366
+ err = js_get_typedarray_info(env, argv[3], NULL, (void **) &range.lt.data, &range.lt.len, NULL, NULL);
367
+ assert(err == 0);
368
+
369
+ err = js_get_typedarray_info(env, argv[4], NULL, (void **) &range.lte.data, &range.lte.len, NULL, NULL);
370
+ assert(err == 0);
371
+
372
+ err = js_create_reference(env, argv[5], 1, &req->ctx);
373
+ assert(err == 0);
374
+
375
+ err = js_create_reference(env, argv[6], 1, &req->on_status);
376
+ assert(err == 0);
377
+
378
+ err = rocksdb_delete_range(&db->handle, &req->handle, range, rocksdb_native__on_delete_range);
379
+ assert(err == 0);
380
+
381
+ return handle;
382
+ }
383
+
283
384
  static js_value_t *
284
385
  rocksdb_native_iterator_init (js_env_t *env, js_callback_info_t *info) {
285
386
  int err;
@@ -349,8 +450,6 @@ rocksdb_native_iterator_buffer (js_env_t *env, js_callback_info_t *info) {
349
450
  err = js_create_arraybuffer(env, 2 * capacity * sizeof(rocksdb_slice_t), (void **) &data, &handle);
350
451
  assert(err == 0);
351
452
 
352
- iterator->capacity = capacity;
353
-
354
453
  size_t offset = 0;
355
454
 
356
455
  iterator->keys = (rocksdb_slice_t *) &data[offset];
@@ -404,27 +503,37 @@ static js_value_t *
404
503
  rocksdb_native_iterator_open (js_env_t *env, js_callback_info_t *info) {
405
504
  int err;
406
505
 
407
- size_t argc = 3;
408
- js_value_t *argv[3];
506
+ size_t argc = 6;
507
+ js_value_t *argv[6];
409
508
 
410
509
  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
411
510
  assert(err == 0);
412
511
 
413
- assert(argc == 3);
512
+ assert(argc == 6);
414
513
 
415
514
  rocksdb_native_iterator_t *iterator;
416
515
  err = js_get_arraybuffer_info(env, argv[0], (void **) &iterator, NULL);
417
516
  assert(err == 0);
418
517
 
419
- rocksdb_slice_t start;
420
- err = js_get_typedarray_info(env, argv[1], NULL, (void **) &start.data, &start.len, NULL, NULL);
518
+ rocksdb_range_t range;
519
+
520
+ err = js_get_typedarray_info(env, argv[1], NULL, (void **) &range.gt.data, &range.gt.len, NULL, NULL);
521
+ assert(err == 0);
522
+
523
+ err = js_get_typedarray_info(env, argv[2], NULL, (void **) &range.gte.data, &range.gte.len, NULL, NULL);
524
+ assert(err == 0);
525
+
526
+ err = js_get_typedarray_info(env, argv[3], NULL, (void **) &range.lt.data, &range.lt.len, NULL, NULL);
527
+ assert(err == 0);
528
+
529
+ err = js_get_typedarray_info(env, argv[4], NULL, (void **) &range.lte.data, &range.lte.len, NULL, NULL);
421
530
  assert(err == 0);
422
531
 
423
- rocksdb_slice_t end;
424
- err = js_get_typedarray_info(env, argv[2], NULL, (void **) &end.data, &end.len, NULL, NULL);
532
+ bool reverse;
533
+ err = js_get_value_bool(env, argv[5], &reverse);
425
534
  assert(err == 0);
426
535
 
427
- err = rocksdb_iterator_open(&iterator->handle, start, end, rocksdb_native__on_iterator_open);
536
+ err = rocksdb_iterator_open(&iterator->handle, range, reverse, rocksdb_native__on_iterator_open);
428
537
  assert(err == 0);
429
538
 
430
539
  return NULL;
@@ -562,19 +671,23 @@ static js_value_t *
562
671
  rocksdb_native_iterator_read (js_env_t *env, js_callback_info_t *info) {
563
672
  int err;
564
673
 
565
- size_t argc = 1;
566
- js_value_t *argv[1];
674
+ size_t argc = 2;
675
+ js_value_t *argv[2];
567
676
 
568
677
  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
569
678
  assert(err == 0);
570
679
 
571
- assert(argc == 1);
680
+ assert(argc == 2);
572
681
 
573
682
  rocksdb_native_iterator_t *iterator;
574
683
  err = js_get_arraybuffer_info(env, argv[0], (void **) &iterator, NULL);
575
684
  assert(err == 0);
576
685
 
577
- err = rocksdb_iterator_read(&iterator->handle, iterator->keys, iterator->values, iterator->capacity, rocksdb_native__on_iterator_read);
686
+ uint32_t capacity;
687
+ err = js_get_value_uint32(env, argv[1], &capacity);
688
+ assert(err == 0);
689
+
690
+ err = rocksdb_iterator_read(&iterator->handle, iterator->keys, iterator->values, capacity, rocksdb_native__on_iterator_read);
578
691
  assert(err == 0);
579
692
 
580
693
  return NULL;
@@ -856,6 +969,7 @@ rocksdb_native_exports (js_env_t *env, js_value_t *exports) {
856
969
  V("init", rocksdb_native_init)
857
970
  V("open", rocksdb_native_open)
858
971
  V("close", rocksdb_native_close)
972
+ V("deleteRange", rocksdb_native_delete_range)
859
973
 
860
974
  V("iteratorInit", rocksdb_native_iterator_init)
861
975
  V("iteratorBuffer", rocksdb_native_iterator_buffer)
package/index.js CHANGED
@@ -1,9 +1,12 @@
1
1
  /* global Bare */
2
2
  const ReadyResource = require('ready-resource')
3
+ const b4a = require('b4a')
3
4
  const binding = require('./binding')
4
5
  const Batch = require('./lib/batch')
5
6
  const Iterator = require('./lib/iterator')
6
7
 
8
+ const empty = b4a.alloc(0)
9
+
7
10
  const RocksDB = module.exports = class RocksDB extends ReadyResource {
8
11
  constructor (path, {
9
12
  // default options, https://github.com/facebook/rocksdb/wiki/Setup-Options-and-Basic-Tuning
@@ -101,6 +104,42 @@ const RocksDB = module.exports = class RocksDB extends ReadyResource {
101
104
  }
102
105
  }
103
106
 
107
+ async deleteRange (start, end, opts = {}) {
108
+ if (typeof start === 'string') start = b4a.from(start)
109
+ if (typeof end === 'string') end = b4a.from(end)
110
+
111
+ if (start && !b4a.isBuffer(start)) {
112
+ opts = start
113
+ start = empty
114
+ } else if (end && !b4a.isBuffer(end)) {
115
+ opts = end
116
+ end = empty
117
+ }
118
+
119
+ const {
120
+ gt = empty,
121
+ gte = start,
122
+ lt = end,
123
+ lte = empty
124
+ } = opts
125
+
126
+ const req = { resolve: null, reject: null, handle: null }
127
+
128
+ const promise = new Promise((resolve, reject) => {
129
+ req.resolve = resolve
130
+ req.reject = reject
131
+ })
132
+
133
+ req.handle = binding.deleteRange(this._handle, gt, gte, lt, lte, req, onstatus)
134
+
135
+ return promise
136
+
137
+ function onstatus (err) {
138
+ if (err) req.reject(new Error(err))
139
+ else req.resolve()
140
+ }
141
+ }
142
+
104
143
  batch (opts) {
105
144
  return new Batch(this, opts)
106
145
  }
package/lib/iterator.js CHANGED
@@ -9,28 +9,43 @@ module.exports = class RocksDBIterator extends Readable {
9
9
  if (typeof start === 'string') start = b4a.from(start)
10
10
  if (typeof end === 'string') end = b4a.from(end)
11
11
 
12
- if (end && !Buffer.isBuffer(end)) {
12
+ if (start && !b4a.isBuffer(start)) {
13
+ opts = start
14
+ start = empty
15
+ } else if (end && !b4a.isBuffer(end)) {
13
16
  opts = end
14
17
  end = empty
15
18
  }
16
19
 
17
20
  const {
21
+ gt = empty,
22
+ gte = start,
23
+ lt = end,
24
+ lte = empty,
25
+ reverse = false,
26
+ limit = Infinity,
18
27
  capacity = 8
19
28
  } = opts
20
29
 
21
30
  super()
22
31
 
23
32
  this._db = db
24
- this._start = start
25
- this._end = end || empty
33
+
34
+ this._gt = toBuffer(gt) || empty
35
+ this._gte = toBuffer(gte) || empty
36
+ this._lt = toBuffer(lt) || empty
37
+ this._lte = toBuffer(lte) || empty
38
+
39
+ this._reverse = reverse
40
+ this._limit = limit
26
41
  this._capacity = capacity
27
42
 
28
43
  this._pendingOpen = null
29
44
  this._pendingRead = null
30
45
  this._pendingDestroy = null
31
46
 
32
- this._handle = null
33
47
  this._buffer = null
48
+ this._handle = null
34
49
 
35
50
  if (db.opened === true) this.ready()
36
51
  }
@@ -48,6 +63,8 @@ module.exports = class RocksDBIterator extends Readable {
48
63
 
49
64
  const n = keys.length
50
65
 
66
+ this._limit -= n
67
+
51
68
  for (let i = 0; i < n; i++) {
52
69
  this.push({ key: b4a.from(keys[i]), value: b4a.from(values[i]) })
53
70
  }
@@ -88,13 +105,13 @@ module.exports = class RocksDBIterator extends Readable {
88
105
 
89
106
  this._pendingOpen = cb
90
107
 
91
- binding.iteratorOpen(this._handle, this._start, this._end)
108
+ binding.iteratorOpen(this._handle, this._gt, this._gte, this._lt, this._lte, this._reverse)
92
109
  }
93
110
 
94
111
  _read (cb) {
95
112
  this._pendingRead = cb
96
113
 
97
- binding.iteratorRead(this._handle)
114
+ binding.iteratorRead(this._handle, Math.min(this._capacity, this._limit))
98
115
  }
99
116
 
100
117
  async _destroy (cb) {
@@ -105,3 +122,7 @@ module.exports = class RocksDBIterator extends Readable {
105
122
  binding.iteratorClose(this._handle)
106
123
  }
107
124
  }
125
+
126
+ function toBuffer (data) {
127
+ return typeof data === 'string' ? b4a.from(data) : data
128
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rocksdb-native",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "librocksdb bindings for JavaScript",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -13,6 +13,7 @@ typedef struct rocksdb_options_s rocksdb_options_t;
13
13
  typedef struct rocksdb_open_s rocksdb_open_t;
14
14
  typedef struct rocksdb_close_s rocksdb_close_t;
15
15
  typedef struct rocksdb_slice_s rocksdb_slice_t;
16
+ typedef struct rocksdb_range_s rocksdb_range_t;
16
17
  typedef struct rocksdb_read_range_s rocksdb_read_range_t;
17
18
  typedef struct rocksdb_delete_range_s rocksdb_delete_range_t;
18
19
  typedef struct rocksdb_iterator_s rocksdb_iterator_t;
@@ -107,13 +108,21 @@ struct rocksdb_slice_s {
107
108
  size_t len;
108
109
  };
109
110
 
111
+ struct rocksdb_range_s {
112
+ rocksdb_slice_t gt;
113
+ rocksdb_slice_t gte;
114
+
115
+ rocksdb_slice_t lt;
116
+ rocksdb_slice_t lte;
117
+ };
118
+
110
119
  struct rocksdb_read_range_s {
111
120
  uv_work_t worker;
112
121
 
113
122
  rocksdb_t *db;
114
123
 
115
- rocksdb_slice_t start;
116
- rocksdb_slice_t end;
124
+ rocksdb_range_t range;
125
+ bool reverse;
117
126
 
118
127
  size_t len;
119
128
  size_t capacity;
@@ -133,8 +142,7 @@ struct rocksdb_delete_range_s {
133
142
 
134
143
  rocksdb_t *db;
135
144
 
136
- rocksdb_slice_t start;
137
- rocksdb_slice_t end;
145
+ rocksdb_range_t range;
138
146
 
139
147
  char *error;
140
148
 
@@ -150,8 +158,8 @@ struct rocksdb_iterator_s {
150
158
 
151
159
  void *handle; // Opaque iterator pointer
152
160
 
153
- rocksdb_slice_t start;
154
- rocksdb_slice_t end;
161
+ rocksdb_range_t range;
162
+ bool reverse;
155
163
 
156
164
  size_t len;
157
165
  size_t capacity;
@@ -214,22 +222,22 @@ rocksdb_slice_t
214
222
  rocksdb_slice_empty (void);
215
223
 
216
224
  int
217
- rocksdb_read_range (rocksdb_t *db, rocksdb_read_range_t *req, rocksdb_slice_t start, rocksdb_slice_t end, rocksdb_slice_t *keys, rocksdb_slice_t *values, size_t capacity, rocksdb_read_range_cb cb);
225
+ rocksdb_read_range (rocksdb_t *db, rocksdb_read_range_t *req, rocksdb_range_t range, bool reverse, rocksdb_slice_t *keys, rocksdb_slice_t *values, size_t capacity, rocksdb_read_range_cb cb);
218
226
 
219
227
  int
220
- rocksdb_delete_range (rocksdb_t *db, rocksdb_delete_range_t *req, rocksdb_slice_t start, rocksdb_slice_t end, rocksdb_delete_range_cb cb);
228
+ rocksdb_delete_range (rocksdb_t *db, rocksdb_delete_range_t *req, rocksdb_range_t range, rocksdb_delete_range_cb cb);
221
229
 
222
230
  int
223
231
  rocksdb_iterator_init (rocksdb_t *db, rocksdb_iterator_t *iterator);
224
232
 
225
233
  int
226
- rocksdb_iterator_open (rocksdb_iterator_t *iterator, rocksdb_slice_t start, rocksdb_slice_t end, rocksdb_iterator_cb cb);
234
+ rocksdb_iterator_open (rocksdb_iterator_t *iterator, rocksdb_range_t range, bool reverse, rocksdb_iterator_cb cb);
227
235
 
228
236
  int
229
237
  rocksdb_iterator_close (rocksdb_iterator_t *iterator, rocksdb_iterator_cb cb);
230
238
 
231
239
  int
232
- rocksdb_iterator_refresh (rocksdb_iterator_t *iterator, rocksdb_slice_t start, rocksdb_slice_t end, rocksdb_iterator_cb cb);
240
+ rocksdb_iterator_refresh (rocksdb_iterator_t *iterator, rocksdb_range_t range, bool reverse, rocksdb_iterator_cb cb);
233
241
 
234
242
  int
235
243
  rocksdb_iterator_read (rocksdb_iterator_t *iterator, rocksdb_slice_t *keys, rocksdb_slice_t *values, size_t capacity, rocksdb_iterator_cb cb);
@@ -36,7 +36,7 @@ static const rocksdb_options_t rocksdb__default_options = {
36
36
  template <auto rocksdb_options_t::*P, typename T>
37
37
  static inline T
38
38
  rocksdb__option (const rocksdb_options_t *options, int min_version, T fallback = T(rocksdb__default_options.*P)) {
39
- return T(options->version >= min_version ? options->*P : fallback);
39
+ return options->version >= min_version ? T(options->*P) : fallback;
40
40
  }
41
41
 
42
42
  extern "C" int
@@ -202,45 +202,170 @@ rocksdb__slice_copy (const Slice &slice) {
202
202
  return {.data = data, .len = len};
203
203
  }
204
204
 
205
+ static inline const Slice &
206
+ rocksdb__slice_cast (const rocksdb_slice_t &slice) {
207
+ return reinterpret_cast<const Slice &>(slice);
208
+ }
209
+
210
+ static inline const rocksdb_slice_t &
211
+ rocksdb__slice_cast (const Slice &slice) {
212
+ return reinterpret_cast<const rocksdb_slice_t &>(slice);
213
+ }
214
+
215
+ static inline void
216
+ rocksdb__iterator_seek_first (Iterator *iterator, const rocksdb_range_t &range) {
217
+ if (range.gte.len) {
218
+ auto gte = rocksdb__slice_cast(range.gte);
219
+
220
+ iterator->Seek(gte);
221
+ } else if (range.gt.len) {
222
+ auto gt = rocksdb__slice_cast(range.gt);
223
+
224
+ iterator->Seek(gt);
225
+
226
+ if (iterator->Valid() && iterator->key().compare(gt) == 0) {
227
+ iterator->Next();
228
+ }
229
+ } else {
230
+ iterator->SeekToFirst();
231
+ }
232
+ }
233
+
234
+ static inline void
235
+ rocksdb__iterator_seek_last (Iterator *iterator, const rocksdb_range_t &range) {
236
+ if (range.lte.len) {
237
+ auto lte = rocksdb__slice_cast(range.lte);
238
+
239
+ iterator->Seek(lte);
240
+
241
+ if (iterator->Valid()) {
242
+ if (iterator->key().compare(lte) > 0) iterator->Prev();
243
+ } else {
244
+ iterator->SeekToLast();
245
+ }
246
+ } else if (range.lt.len) {
247
+
248
+ auto lt = rocksdb__slice_cast(range.lt);
249
+
250
+ iterator->Seek(lt);
251
+
252
+ if (iterator->Valid()) {
253
+ if (iterator->key().compare(lt) >= 0) iterator->Prev();
254
+ } else {
255
+ iterator->SeekToLast();
256
+ }
257
+ } else {
258
+ iterator->SeekToLast();
259
+ }
260
+ }
261
+
262
+ template <bool reverse>
263
+ static inline void
264
+ rocksdb__iterator_seek (Iterator *iterator, const rocksdb_range_t &range) {
265
+ if (reverse) {
266
+ rocksdb__iterator_seek_last(iterator, range);
267
+ } else {
268
+ rocksdb__iterator_seek_first(iterator, range);
269
+ }
270
+ }
271
+
205
272
  template <typename T>
206
273
  static inline void
207
274
  rocksdb__iterator_seek (Iterator *iterator, T *req) {
208
- iterator->Seek(reinterpret_cast<const Slice &>(req->start));
275
+ const auto &range = req->range;
276
+
277
+ if (req->reverse) {
278
+ rocksdb__iterator_seek<true>(iterator, range);
279
+ } else {
280
+ rocksdb__iterator_seek<false>(iterator, range);
281
+ }
282
+ }
283
+
284
+ template <bool reverse = false>
285
+ static inline void
286
+ rocksdb__iterator_next (Iterator *iterator) {
287
+ if (reverse) {
288
+ iterator->Prev();
289
+ } else {
290
+ iterator->Next();
291
+ }
209
292
  }
210
293
 
211
294
  template <typename T>
212
- static inline Iterator *
213
- rocksdb__iterator_open (T *req) {
214
- auto db = reinterpret_cast<DB *>(req->db->handle);
295
+ static inline void
296
+ rocksdb__iterator_next (Iterator *iterator, T *req) {
297
+ if (req->reverse) {
298
+ rocksdb__iterator_next<true>(iterator);
299
+ } else {
300
+ rocksdb__iterator_next<false>(iterator);
301
+ }
302
+ }
303
+
304
+ static inline bool
305
+ rocksdb__iterator_valid (Iterator *iterator, const rocksdb_range_t &range) {
306
+ if (!iterator->Valid()) return false;
307
+
308
+ auto key = iterator->key();
215
309
 
310
+ return (
311
+ (range.lt.len == 0 || key.compare(rocksdb__slice_cast(range.lt)) < 0) &&
312
+ (range.lte.len == 0 || key.compare(rocksdb__slice_cast(range.lte)) <= 0) &&
313
+ (range.gt.len == 0 || key.compare(rocksdb__slice_cast(range.gt)) > 0) &&
314
+ (range.gte.len == 0 || key.compare(rocksdb__slice_cast(range.gte)) >= 0)
315
+ );
316
+ }
317
+
318
+ template <typename T>
319
+ static inline bool
320
+ rocksdb__iterator_valid (Iterator *iterator, T *req) {
321
+ return rocksdb__iterator_valid(iterator, req->range);
322
+ }
323
+
324
+ template <bool reverse = false>
325
+ static inline Iterator *
326
+ rocksdb__iterator_open (DB *db, const rocksdb_range_t &range) {
216
327
  auto iterator = db->NewIterator(ReadOptions());
217
328
 
218
- rocksdb__iterator_seek(iterator, req);
329
+ rocksdb__iterator_seek<reverse>(iterator, range);
219
330
 
220
331
  return iterator;
221
332
  }
222
333
 
223
334
  template <typename T>
224
- static inline void
225
- rocksdb__iterator_read (Iterator *iterator, T *req) {
226
- while (iterator->Valid() && req->len < req->capacity) {
227
- auto key = iterator->key();
335
+ static inline Iterator *
336
+ rocksdb__iterator_open (T *req) {
337
+ auto db = reinterpret_cast<DB *>(req->db->handle);
228
338
 
229
- if (req->end.len && key.compare(reinterpret_cast<const Slice &>(req->end)) >= 0) {
230
- break;
231
- }
339
+ const auto &range = req->range;
232
340
 
233
- auto value = iterator->value();
341
+ if (req->reverse) {
342
+ return rocksdb__iterator_open<true>(db, range);
343
+ } else {
344
+ return rocksdb__iterator_open<false>(db, range);
345
+ }
346
+ }
234
347
 
235
- req->keys[req->len] = rocksdb__slice_copy(key);
236
- req->values[req->len] = rocksdb__slice_copy(value);
348
+ template <typename T>
349
+ static inline void
350
+ rocksdb__iterator_read (Iterator *iterator, T *req) {
351
+ while (rocksdb__iterator_valid(iterator, req) && req->len < req->capacity) {
352
+ auto i = req->len++;
237
353
 
238
- req->len++;
354
+ req->keys[i] = rocksdb__slice_copy(iterator->key());
355
+ req->values[i] = rocksdb__slice_copy(iterator->value());
239
356
 
240
- iterator->Next();
357
+ rocksdb__iterator_next(iterator, req);
241
358
  }
242
359
  }
243
360
 
361
+ template <typename T>
362
+ static inline void
363
+ rocksdb__iterator_refresh (Iterator *iterator, T *req) {
364
+ iterator->Refresh();
365
+
366
+ rocksdb__iterator_seek(iterator, req);
367
+ }
368
+
244
369
  static void
245
370
  rocksdb__on_after_read_range (uv_work_t *handle, int status) {
246
371
  auto req = reinterpret_cast<rocksdb_read_range_t *>(handle->data);
@@ -272,10 +397,10 @@ rocksdb__on_read_range (uv_work_t *handle) {
272
397
  }
273
398
 
274
399
  extern "C" int
275
- rocksdb_read_range (rocksdb_t *db, rocksdb_read_range_t *req, rocksdb_slice_t start, rocksdb_slice_t end, rocksdb_slice_t *keys, rocksdb_slice_t *values, size_t capacity, rocksdb_read_range_cb cb) {
400
+ rocksdb_read_range (rocksdb_t *db, rocksdb_read_range_t *req, rocksdb_range_t range, bool reverse, rocksdb_slice_t *keys, rocksdb_slice_t *values, size_t capacity, rocksdb_read_range_cb cb) {
276
401
  req->db = db;
277
- req->start = start;
278
- req->end = end;
402
+ req->range = range;
403
+ req->reverse = reverse;
279
404
  req->keys = keys;
280
405
  req->values = values;
281
406
  req->len = 0;
@@ -304,20 +429,40 @@ rocksdb__on_delete_range (uv_work_t *handle) {
304
429
 
305
430
  auto db = reinterpret_cast<DB *>(req->db->handle);
306
431
 
307
- auto status = db->DeleteRange(WriteOptions(), reinterpret_cast<const Slice &>(req->start), reinterpret_cast<const Slice &>(req->end));
432
+ const auto &range = req->range;
308
433
 
309
- if (status.ok()) {
310
- req->error = nullptr;
434
+ if (range.gte.len && range.lt.len) {
435
+ auto status = db->DeleteRange(WriteOptions(), rocksdb__slice_cast(range.gte), rocksdb__slice_cast(range.lt));
436
+
437
+ if (status.ok()) {
438
+ req->error = nullptr;
439
+ } else {
440
+ req->error = strdup(status.getState());
441
+ }
311
442
  } else {
312
- req->error = strdup(status.getState());
443
+ auto iterator = rocksdb__iterator_open(db, req->range);
444
+
445
+ req->error = nullptr;
446
+
447
+ while (rocksdb__iterator_valid(iterator, req->range)) {
448
+ auto status = db->Delete(WriteOptions(), iterator->key());
449
+
450
+ if (status.ok()) {
451
+ rocksdb__iterator_next(iterator);
452
+ } else {
453
+ req->error = strdup(status.getState());
454
+ break;
455
+ }
456
+ }
457
+
458
+ delete iterator;
313
459
  }
314
460
  }
315
461
 
316
462
  extern "C" int
317
- rocksdb_delete_range (rocksdb_t *db, rocksdb_delete_range_t *req, rocksdb_slice_t start, rocksdb_slice_t end, rocksdb_delete_range_cb cb) {
463
+ rocksdb_delete_range (rocksdb_t *db, rocksdb_delete_range_t *req, rocksdb_range_t range, rocksdb_delete_range_cb cb) {
318
464
  req->db = db;
319
- req->start = start;
320
- req->end = end;
465
+ req->range = range;
321
466
  req->cb = cb;
322
467
 
323
468
  req->worker.data = static_cast<void *>(req);
@@ -363,9 +508,9 @@ rocksdb__on_iterator_open (uv_work_t *handle) {
363
508
  }
364
509
 
365
510
  extern "C" int
366
- rocksdb_iterator_open (rocksdb_iterator_t *iterator, rocksdb_slice_t start, rocksdb_slice_t end, rocksdb_iterator_cb cb) {
367
- iterator->start = start;
368
- iterator->end = end;
511
+ rocksdb_iterator_open (rocksdb_iterator_t *iterator, rocksdb_range_t range, bool reverse, rocksdb_iterator_cb cb) {
512
+ iterator->range = range;
513
+ iterator->reverse = reverse;
369
514
  iterator->cb = cb;
370
515
 
371
516
  return uv_queue_work(iterator->db->loop, &iterator->worker, rocksdb__on_iterator_open, rocksdb__on_after_iterator);
@@ -393,9 +538,7 @@ rocksdb__on_iterator_refresh (uv_work_t *handle) {
393
538
 
394
539
  auto iterator = reinterpret_cast<Iterator *>(req->handle);
395
540
 
396
- iterator->Refresh();
397
-
398
- rocksdb__iterator_seek(iterator, req);
541
+ rocksdb__iterator_refresh(iterator, req);
399
542
 
400
543
  auto status = iterator->status();
401
544
 
@@ -407,9 +550,9 @@ rocksdb__on_iterator_refresh (uv_work_t *handle) {
407
550
  }
408
551
 
409
552
  extern "C" int
410
- rocksdb_iterator_refresh (rocksdb_iterator_t *iterator, rocksdb_slice_t start, rocksdb_slice_t end, rocksdb_iterator_cb cb) {
411
- iterator->start = end;
412
- iterator->end = end;
553
+ rocksdb_iterator_refresh (rocksdb_iterator_t *iterator, rocksdb_range_t range, bool reverse, rocksdb_iterator_cb cb) {
554
+ iterator->range = range;
555
+ iterator->reverse = reverse;
413
556
  iterator->cb = cb;
414
557
 
415
558
  return uv_queue_work(iterator->db->loop, &iterator->worker, rocksdb__on_iterator_close, rocksdb__on_after_iterator);