@nxtedition/rocksdb 5.2.30 → 5.2.35
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
|
@@ -30,6 +30,23 @@ class NullLogger : public rocksdb::Logger {
|
|
|
30
30
|
struct Database;
|
|
31
31
|
struct Iterator;
|
|
32
32
|
|
|
33
|
+
#define NAPI_STATUS_RETURN(call) \
|
|
34
|
+
{ \
|
|
35
|
+
const auto status = (call); \
|
|
36
|
+
if (status != napi_ok) { \
|
|
37
|
+
return status; \
|
|
38
|
+
} \
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
#define NAPI_PENDING_EXCEPTION() \
|
|
42
|
+
{ \
|
|
43
|
+
bool result; \
|
|
44
|
+
NAPI_STATUS_THROWS(napi_is_exception_pending(env, &result)); \
|
|
45
|
+
if (result) { \
|
|
46
|
+
return nullptr; \
|
|
47
|
+
} \
|
|
48
|
+
}
|
|
49
|
+
|
|
33
50
|
#define NAPI_DB_CONTEXT() \
|
|
34
51
|
Database* database = nullptr; \
|
|
35
52
|
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], (void**)&database));
|
|
@@ -60,21 +77,15 @@ static bool IsObject(napi_env env, napi_value value) {
|
|
|
60
77
|
return type == napi_object;
|
|
61
78
|
}
|
|
62
79
|
|
|
63
|
-
static napi_value CreateError(napi_env env, const std::string_view&
|
|
64
|
-
napi_value
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return error;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
static napi_value CreateCodeError(napi_env env, const std::string_view& code, const std::string_view& msg) {
|
|
72
|
-
napi_value codeValue;
|
|
73
|
-
napi_create_string_utf8(env, code.data(), code.size(), &codeValue);
|
|
80
|
+
static napi_value CreateError(napi_env env, const std::optional<std::string_view>& code, const std::string_view& msg) {
|
|
81
|
+
napi_value codeValue = nullptr;
|
|
82
|
+
if (code) {
|
|
83
|
+
NAPI_STATUS_THROWS(napi_create_string_utf8(env, code->data(), code->size(), &codeValue));
|
|
84
|
+
}
|
|
74
85
|
napi_value msgValue;
|
|
75
|
-
napi_create_string_utf8(env, msg.data(), msg.size(), &msgValue);
|
|
86
|
+
NAPI_STATUS_THROWS(napi_create_string_utf8(env, msg.data(), msg.size(), &msgValue));
|
|
76
87
|
napi_value error;
|
|
77
|
-
napi_create_error(env, codeValue, msgValue, &error);
|
|
88
|
+
NAPI_STATUS_THROWS(napi_create_error(env, codeValue, msgValue, &error));
|
|
78
89
|
return error;
|
|
79
90
|
}
|
|
80
91
|
|
|
@@ -177,18 +188,10 @@ static std::optional<std::string> RangeOption(napi_env env, napi_value opts, con
|
|
|
177
188
|
}
|
|
178
189
|
|
|
179
190
|
static napi_status CallFunction(napi_env env, napi_value callback, const int argc, napi_value* argv) {
|
|
180
|
-
napi_status status;
|
|
181
191
|
napi_value global;
|
|
182
192
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
return status;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
status = napi_call_function(env, global, callback, argc, argv, nullptr);
|
|
189
|
-
if (status != napi_ok) {
|
|
190
|
-
return status;
|
|
191
|
-
}
|
|
193
|
+
NAPI_STATUS_RETURN(napi_get_global(env, &global));
|
|
194
|
+
NAPI_STATUS_RETURN(napi_call_function(env, global, callback, argc, argv, nullptr));
|
|
192
195
|
|
|
193
196
|
return napi_ok;
|
|
194
197
|
}
|
|
@@ -201,28 +204,35 @@ static napi_value ToError(napi_env env, const rocksdb::Status& status) {
|
|
|
201
204
|
const auto msg = status.ToString();
|
|
202
205
|
|
|
203
206
|
if (status.IsNotFound()) {
|
|
204
|
-
return
|
|
207
|
+
return CreateError(env, "LEVEL_NOT_FOUND", msg);
|
|
205
208
|
} else if (status.IsCorruption()) {
|
|
206
|
-
return
|
|
209
|
+
return CreateError(env, "LEVEL_CORRUPTION", msg);
|
|
207
210
|
} else if (status.IsIOError()) {
|
|
208
211
|
if (msg.find("IO error: lock ") != std::string::npos) { // env_posix.cc
|
|
209
|
-
return
|
|
212
|
+
return CreateError(env, "LEVEL_LOCKED", msg);
|
|
210
213
|
} else if (msg.find("IO error: LockFile ") != std::string::npos) { // env_win.cc
|
|
211
|
-
return
|
|
214
|
+
return CreateError(env, "LEVEL_LOCKED", msg);
|
|
212
215
|
} else if (msg.find("IO error: While lock file") != std::string::npos) { // env_mac.cc
|
|
213
|
-
return
|
|
216
|
+
return CreateError(env, "LEVEL_LOCKED", msg);
|
|
214
217
|
} else {
|
|
215
|
-
return
|
|
218
|
+
return CreateError(env, "LEVEL_IO_ERROR", msg);
|
|
216
219
|
}
|
|
217
220
|
}
|
|
218
221
|
|
|
219
|
-
return CreateError(env, msg);
|
|
222
|
+
return CreateError(env, {}, msg);
|
|
220
223
|
}
|
|
221
224
|
|
|
222
225
|
template <typename T>
|
|
223
|
-
|
|
226
|
+
static void Finalize(napi_env env, void* data, void* hint) {
|
|
227
|
+
if (hint) {
|
|
228
|
+
delete reinterpret_cast<T*>(hint);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
napi_status Convert(napi_env env, std::string s, bool asBuffer, napi_value& result) {
|
|
224
233
|
if (asBuffer) {
|
|
225
|
-
|
|
234
|
+
auto ptr = new std::string(std::move(s));
|
|
235
|
+
return napi_create_external_buffer(env, ptr->size(), ptr->data(), Finalize<std::string>, ptr, &result);
|
|
226
236
|
} else {
|
|
227
237
|
return napi_create_string_utf8(env, s.data(), s.size(), &result);
|
|
228
238
|
}
|
|
@@ -231,7 +241,7 @@ napi_status Convert(napi_env env, const T& s, bool asBuffer, napi_value& result)
|
|
|
231
241
|
struct NapiSlice : public rocksdb::Slice {
|
|
232
242
|
NapiSlice(napi_env env, napi_value from) {
|
|
233
243
|
if (IsString(env, from)) {
|
|
234
|
-
napi_get_value_string_utf8(env, from, nullptr, 0, &size_);
|
|
244
|
+
NAPI_STATUS_THROWS_VOID(napi_get_value_string_utf8(env, from, nullptr, 0, &size_));
|
|
235
245
|
char* data;
|
|
236
246
|
if (size_ + 1 < stack_.size()) {
|
|
237
247
|
data = stack_.data();
|
|
@@ -240,17 +250,17 @@ struct NapiSlice : public rocksdb::Slice {
|
|
|
240
250
|
data = heap_.get();
|
|
241
251
|
}
|
|
242
252
|
data[size_] = 0;
|
|
243
|
-
napi_get_value_string_utf8(env, from, data, size_ + 1, &size_);
|
|
253
|
+
NAPI_STATUS_THROWS_VOID(napi_get_value_string_utf8(env, from, data, size_ + 1, &size_));
|
|
244
254
|
data_ = data;
|
|
245
255
|
} else if (IsBuffer(env, from)) {
|
|
246
256
|
void* data;
|
|
247
|
-
napi_get_buffer_info(env, from, &data, &size_);
|
|
257
|
+
NAPI_STATUS_THROWS_VOID(napi_get_buffer_info(env, from, &data, &size_));
|
|
248
258
|
data_ = static_cast<char*>(data);
|
|
249
259
|
}
|
|
250
260
|
}
|
|
251
261
|
|
|
252
262
|
std::unique_ptr<char[]> heap_;
|
|
253
|
-
std::array<char,
|
|
263
|
+
std::array<char, 1024> stack_;
|
|
254
264
|
};
|
|
255
265
|
|
|
256
266
|
/**
|
|
@@ -263,13 +273,12 @@ struct NapiSlice : public rocksdb::Slice {
|
|
|
263
273
|
* - Destroy (main thread): do cleanup regardless of success
|
|
264
274
|
*/
|
|
265
275
|
struct Worker {
|
|
266
|
-
Worker(napi_env env, Database* database, napi_value callback, const std::string& resourceName)
|
|
267
|
-
: database_(database) {
|
|
276
|
+
Worker(napi_env env, Database* database, napi_value callback, const std::string& resourceName) : database_(database) {
|
|
268
277
|
NAPI_STATUS_THROWS_VOID(napi_create_reference(env, callback, 1, &callbackRef_));
|
|
269
278
|
napi_value asyncResourceName;
|
|
270
279
|
NAPI_STATUS_THROWS_VOID(napi_create_string_utf8(env, resourceName.data(), resourceName.size(), &asyncResourceName));
|
|
271
|
-
NAPI_STATUS_THROWS_VOID(
|
|
272
|
-
|
|
280
|
+
NAPI_STATUS_THROWS_VOID(
|
|
281
|
+
napi_create_async_work(env, callback, asyncResourceName, Worker::Execute, Worker::Complete, this, &asyncWork_));
|
|
273
282
|
}
|
|
274
283
|
|
|
275
284
|
virtual ~Worker() {}
|
|
@@ -282,6 +291,8 @@ struct Worker {
|
|
|
282
291
|
static void Complete(napi_env env, napi_status status, void* data) {
|
|
283
292
|
auto self = reinterpret_cast<Worker*>(data);
|
|
284
293
|
|
|
294
|
+
// TODO (fix): napi status handling...
|
|
295
|
+
|
|
285
296
|
napi_value callback;
|
|
286
297
|
napi_get_reference_value(env, self->callbackRef_, &callback);
|
|
287
298
|
|
|
@@ -301,13 +312,15 @@ struct Worker {
|
|
|
301
312
|
|
|
302
313
|
virtual rocksdb::Status Execute(Database& database) = 0;
|
|
303
314
|
|
|
304
|
-
virtual
|
|
315
|
+
virtual napi_status OnOk(napi_env env, napi_value callback) {
|
|
305
316
|
napi_value argv;
|
|
306
|
-
napi_get_null(env, &argv);
|
|
307
|
-
CallFunction(env, callback, 1, &argv);
|
|
317
|
+
NAPI_STATUS_RETURN(napi_get_null(env, &argv));
|
|
318
|
+
return CallFunction(env, callback, 1, &argv);
|
|
308
319
|
}
|
|
309
320
|
|
|
310
|
-
virtual
|
|
321
|
+
virtual napi_status OnError(napi_env env, napi_value callback, napi_value err) {
|
|
322
|
+
return CallFunction(env, callback, 1, &err);
|
|
323
|
+
}
|
|
311
324
|
|
|
312
325
|
virtual void Destroy(napi_env env) {}
|
|
313
326
|
|
|
@@ -322,20 +335,6 @@ struct Worker {
|
|
|
322
335
|
};
|
|
323
336
|
|
|
324
337
|
struct Database {
|
|
325
|
-
rocksdb::Status Open(const rocksdb::Options& options, const bool readOnly, const char* location) {
|
|
326
|
-
if (readOnly) {
|
|
327
|
-
rocksdb::DB* db = nullptr;
|
|
328
|
-
const auto status = rocksdb::DB::OpenForReadOnly(options, location, &db);
|
|
329
|
-
db_.reset(db);
|
|
330
|
-
return status;
|
|
331
|
-
} else {
|
|
332
|
-
rocksdb::DB* db = nullptr;
|
|
333
|
-
const auto status = rocksdb::DB::Open(options, location, &db);
|
|
334
|
-
db_.reset(db);
|
|
335
|
-
return status;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
338
|
void AttachIterator(napi_env env, Iterator* iterator) {
|
|
340
339
|
iterators_.insert(iterator);
|
|
341
340
|
IncrementPriorityWork(env);
|
|
@@ -346,10 +345,10 @@ struct Database {
|
|
|
346
345
|
DecrementPriorityWork(env);
|
|
347
346
|
}
|
|
348
347
|
|
|
349
|
-
void IncrementPriorityWork(napi_env env) { napi_reference_ref(env,
|
|
348
|
+
void IncrementPriorityWork(napi_env env) { napi_reference_ref(env, priorityRef_, &priorityWork_); }
|
|
350
349
|
|
|
351
350
|
void DecrementPriorityWork(napi_env env) {
|
|
352
|
-
napi_reference_unref(env,
|
|
351
|
+
napi_reference_unref(env, priorityRef_, &priorityWork_);
|
|
353
352
|
|
|
354
353
|
if (priorityWork_ == 0 && pendingCloseWorker_) {
|
|
355
354
|
pendingCloseWorker_->Queue(env);
|
|
@@ -362,7 +361,7 @@ struct Database {
|
|
|
362
361
|
std::unique_ptr<rocksdb::DB> db_;
|
|
363
362
|
Worker* pendingCloseWorker_;
|
|
364
363
|
std::set<Iterator*> iterators_;
|
|
365
|
-
napi_ref
|
|
364
|
+
napi_ref priorityRef_;
|
|
366
365
|
|
|
367
366
|
private:
|
|
368
367
|
uint32_t priorityWork_ = 0;
|
|
@@ -378,33 +377,40 @@ struct BaseIterator {
|
|
|
378
377
|
const int limit,
|
|
379
378
|
const bool fillCache)
|
|
380
379
|
: database_(database),
|
|
381
|
-
lt_(!lte ? lt : *lte + '\0'),
|
|
382
|
-
gte_(gte ? gte : (gt ? std::optional<std::string>(*gt + '\0') : std::nullopt)),
|
|
383
380
|
snapshot_(database_->db_->GetSnapshot(),
|
|
384
381
|
[this](const rocksdb::Snapshot* ptr) { database_->db_->ReleaseSnapshot(ptr); }),
|
|
385
|
-
iterator_(database->db_->NewIterator([&] {
|
|
386
|
-
rocksdb::ReadOptions options;
|
|
387
|
-
if (lt_) {
|
|
388
|
-
upper_bound_ = rocksdb::Slice(lt_->data(), lt_->size());
|
|
389
|
-
options.iterate_upper_bound = &upper_bound_;
|
|
390
|
-
}
|
|
391
|
-
if (gte_) {
|
|
392
|
-
lower_bound_ = rocksdb::Slice(gte_->data(), gte_->size());
|
|
393
|
-
options.iterate_lower_bound = &lower_bound_;
|
|
394
|
-
}
|
|
395
|
-
options.fill_cache = fillCache;
|
|
396
|
-
options.snapshot = snapshot_.get();
|
|
397
|
-
return options;
|
|
398
|
-
}())),
|
|
399
382
|
reverse_(reverse),
|
|
400
|
-
limit_(limit)
|
|
383
|
+
limit_(limit),
|
|
384
|
+
fillCache_(fillCache) {
|
|
385
|
+
if (lte) {
|
|
386
|
+
upper_bound_ = std::make_unique<rocksdb::PinnableSlice>();
|
|
387
|
+
*upper_bound_->GetSelf() = std::move(*lte) + '\0';
|
|
388
|
+
upper_bound_->PinSelf();
|
|
389
|
+
} else if (lt) {
|
|
390
|
+
upper_bound_ = std::make_unique<rocksdb::PinnableSlice>();
|
|
391
|
+
*upper_bound_->GetSelf() = std::move(*lt);
|
|
392
|
+
upper_bound_->PinSelf();
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (gte) {
|
|
396
|
+
lower_bound_ = std::make_unique<rocksdb::PinnableSlice>();
|
|
397
|
+
*lower_bound_->GetSelf() = std::move(*gte);
|
|
398
|
+
lower_bound_->PinSelf();
|
|
399
|
+
} else if (gt) {
|
|
400
|
+
lower_bound_ = std::make_unique<rocksdb::PinnableSlice>();
|
|
401
|
+
*lower_bound_->GetSelf() = std::move(*gt) + '\0';
|
|
402
|
+
lower_bound_->PinSelf();
|
|
403
|
+
}
|
|
404
|
+
}
|
|
401
405
|
|
|
402
406
|
virtual ~BaseIterator() { assert(!iterator_); }
|
|
403
407
|
|
|
404
|
-
bool DidSeek() const { return
|
|
408
|
+
bool DidSeek() const { return iterator_ != nullptr; }
|
|
405
409
|
|
|
406
410
|
void SeekToRange() {
|
|
407
|
-
|
|
411
|
+
if (!iterator_) {
|
|
412
|
+
Init();
|
|
413
|
+
}
|
|
408
414
|
|
|
409
415
|
if (reverse_) {
|
|
410
416
|
iterator_->SeekToLast();
|
|
@@ -413,10 +419,12 @@ struct BaseIterator {
|
|
|
413
419
|
}
|
|
414
420
|
}
|
|
415
421
|
|
|
416
|
-
void Seek(const
|
|
417
|
-
|
|
422
|
+
void Seek(const rocksdb::Slice& target) {
|
|
423
|
+
if (!iterator_) {
|
|
424
|
+
Init();
|
|
425
|
+
}
|
|
418
426
|
|
|
419
|
-
if ((
|
|
427
|
+
if ((upper_bound_ && target.compare(*upper_bound_) >= 0) || (lower_bound_ && target.compare(*lower_bound_) < 0)) {
|
|
420
428
|
// TODO (fix): Why is this required? Seek should handle it?
|
|
421
429
|
// https://github.com/facebook/rocksdb/issues/9904
|
|
422
430
|
iterator_->SeekToLast();
|
|
@@ -455,16 +463,28 @@ struct BaseIterator {
|
|
|
455
463
|
Database* database_;
|
|
456
464
|
|
|
457
465
|
private:
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
466
|
+
void Init() {
|
|
467
|
+
rocksdb::ReadOptions options;
|
|
468
|
+
if (upper_bound_) {
|
|
469
|
+
options.iterate_upper_bound = &*upper_bound_;
|
|
470
|
+
}
|
|
471
|
+
if (lower_bound_) {
|
|
472
|
+
options.iterate_lower_bound = &*lower_bound_;
|
|
473
|
+
}
|
|
474
|
+
options.fill_cache = fillCache_;
|
|
475
|
+
options.snapshot = snapshot_.get();
|
|
476
|
+
|
|
477
|
+
iterator_.reset(database_->db_->NewIterator(options));
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
std::unique_ptr<rocksdb::PinnableSlice> lower_bound_;
|
|
481
|
+
std::unique_ptr<rocksdb::PinnableSlice> upper_bound_;
|
|
462
482
|
std::shared_ptr<const rocksdb::Snapshot> snapshot_;
|
|
463
483
|
std::unique_ptr<rocksdb::Iterator> iterator_;
|
|
464
|
-
bool didSeek_ = false;
|
|
465
484
|
const bool reverse_;
|
|
466
485
|
const int limit_;
|
|
467
486
|
int count_ = 0;
|
|
487
|
+
const bool fillCache_;
|
|
468
488
|
};
|
|
469
489
|
|
|
470
490
|
struct Iterator final : public BaseIterator {
|
|
@@ -543,8 +563,8 @@ static void FinalizeDatabase(napi_env env, void* data, void* hint) {
|
|
|
543
563
|
if (data) {
|
|
544
564
|
auto database = reinterpret_cast<Database*>(data);
|
|
545
565
|
napi_remove_env_cleanup_hook(env, env_cleanup_hook, database);
|
|
546
|
-
if (database->
|
|
547
|
-
napi_delete_reference(env, database->
|
|
566
|
+
if (database->priorityRef_)
|
|
567
|
+
napi_delete_reference(env, database->priorityRef_);
|
|
548
568
|
delete database;
|
|
549
569
|
}
|
|
550
570
|
}
|
|
@@ -556,7 +576,7 @@ NAPI_METHOD(db_init) {
|
|
|
556
576
|
napi_value result;
|
|
557
577
|
NAPI_STATUS_THROWS(napi_create_external(env, database, FinalizeDatabase, nullptr, &result));
|
|
558
578
|
|
|
559
|
-
NAPI_STATUS_THROWS(napi_create_reference(env, result, 0, &database->
|
|
579
|
+
NAPI_STATUS_THROWS(napi_create_reference(env, result, 0, &database->priorityRef_));
|
|
560
580
|
|
|
561
581
|
return result;
|
|
562
582
|
}
|
|
@@ -566,71 +586,22 @@ struct OpenWorker final : public Worker {
|
|
|
566
586
|
Database* database,
|
|
567
587
|
napi_value callback,
|
|
568
588
|
const std::string& location,
|
|
569
|
-
|
|
570
|
-
const bool errorIfExists,
|
|
571
|
-
const bool compression,
|
|
572
|
-
const uint32_t writeBufferSize,
|
|
573
|
-
const uint32_t blockSize,
|
|
574
|
-
const uint32_t maxOpenFiles,
|
|
575
|
-
const uint32_t blockRestartInterval,
|
|
576
|
-
const uint32_t maxFileSize,
|
|
577
|
-
const uint32_t cacheSize,
|
|
578
|
-
const std::string& infoLogLevel,
|
|
589
|
+
rocksdb::Options options,
|
|
579
590
|
const bool readOnly)
|
|
580
|
-
: Worker(env, database, callback, "leveldown.db.open"),
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
if (infoLogLevel == "debug")
|
|
593
|
-
lvl = rocksdb::InfoLogLevel::DEBUG_LEVEL;
|
|
594
|
-
else if (infoLogLevel == "info")
|
|
595
|
-
lvl = rocksdb::InfoLogLevel::INFO_LEVEL;
|
|
596
|
-
else if (infoLogLevel == "warn")
|
|
597
|
-
lvl = rocksdb::InfoLogLevel::WARN_LEVEL;
|
|
598
|
-
else if (infoLogLevel == "error")
|
|
599
|
-
lvl = rocksdb::InfoLogLevel::ERROR_LEVEL;
|
|
600
|
-
else if (infoLogLevel == "fatal")
|
|
601
|
-
lvl = rocksdb::InfoLogLevel::FATAL_LEVEL;
|
|
602
|
-
else if (infoLogLevel == "header")
|
|
603
|
-
lvl = rocksdb::InfoLogLevel::HEADER_LEVEL;
|
|
604
|
-
else
|
|
605
|
-
napi_throw_error(env, nullptr, "invalid log level");
|
|
606
|
-
|
|
607
|
-
options_.info_log_level = lvl;
|
|
608
|
-
} else {
|
|
609
|
-
// In some places RocksDB checks this option to see if it should prepare
|
|
610
|
-
// debug information (ahead of logging), so set it to the highest level.
|
|
611
|
-
options_.info_log_level = rocksdb::InfoLogLevel::HEADER_LEVEL;
|
|
612
|
-
options_.info_log.reset(new NullLogger());
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
rocksdb::BlockBasedTableOptions tableOptions;
|
|
616
|
-
|
|
617
|
-
if (cacheSize) {
|
|
618
|
-
tableOptions.block_cache = rocksdb::NewLRUCache(cacheSize);
|
|
619
|
-
} else {
|
|
620
|
-
tableOptions.no_block_cache = true;
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
tableOptions.block_size = blockSize;
|
|
624
|
-
tableOptions.block_restart_interval = blockRestartInterval;
|
|
625
|
-
tableOptions.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10));
|
|
626
|
-
tableOptions.format_version = 5;
|
|
627
|
-
tableOptions.checksum = rocksdb::kxxHash64;
|
|
628
|
-
|
|
629
|
-
options_.table_factory.reset(rocksdb::NewBlockBasedTableFactory(tableOptions));
|
|
591
|
+
: Worker(env, database, callback, "leveldown.db.open"),
|
|
592
|
+
options_(options),
|
|
593
|
+
readOnly_(readOnly),
|
|
594
|
+
location_(location) {}
|
|
595
|
+
|
|
596
|
+
rocksdb::Status Execute(Database& database) override {
|
|
597
|
+
rocksdb::DB* db;
|
|
598
|
+
const auto status = readOnly_
|
|
599
|
+
? rocksdb::DB::OpenForReadOnly(options_, location_, &db)
|
|
600
|
+
: rocksdb::DB::Open(options_, location_, &db);
|
|
601
|
+
database.db_.reset(db);
|
|
602
|
+
return status;
|
|
630
603
|
}
|
|
631
604
|
|
|
632
|
-
rocksdb::Status Execute(Database& database) override { return database.Open(options_, readOnly_, location_.c_str()); }
|
|
633
|
-
|
|
634
605
|
rocksdb::Options options_;
|
|
635
606
|
const bool readOnly_;
|
|
636
607
|
const std::string location_;
|
|
@@ -640,27 +611,71 @@ NAPI_METHOD(db_open) {
|
|
|
640
611
|
NAPI_ARGV(4);
|
|
641
612
|
NAPI_DB_CONTEXT();
|
|
642
613
|
|
|
614
|
+
rocksdb::Options options;
|
|
615
|
+
|
|
616
|
+
options.IncreaseParallelism(Uint32Property(env, argv[2], "parallelism", 4));
|
|
617
|
+
|
|
643
618
|
const auto location = ToString(env, argv[1]);
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
619
|
+
options.create_if_missing = BooleanProperty(env, argv[2], "createIfMissing", true);
|
|
620
|
+
options.error_if_exists = BooleanProperty(env, argv[2], "errorIfExists", false);
|
|
621
|
+
options.compression =
|
|
622
|
+
BooleanProperty(env, argv[2], "compression", true) ? rocksdb::kSnappyCompression : rocksdb::kNoCompression;
|
|
623
|
+
options.max_open_files = Uint32Property(env, argv[2], "maxOpenFiles", 1000);
|
|
624
|
+
options.max_log_file_size = Uint32Property(env, argv[2], "maxFileSize", 2 << 20);
|
|
625
|
+
options.write_buffer_size = Uint32Property(env, argv[2], "writeBufferSize", 4 << 20);
|
|
626
|
+
options.use_adaptive_mutex = true;
|
|
627
|
+
|
|
628
|
+
const auto infoLogLevel = StringProperty(env, argv[2], "infoLogLevel");
|
|
629
|
+
if (infoLogLevel.size() > 0) {
|
|
630
|
+
rocksdb::InfoLogLevel lvl = {};
|
|
631
|
+
|
|
632
|
+
if (infoLogLevel == "debug")
|
|
633
|
+
lvl = rocksdb::InfoLogLevel::DEBUG_LEVEL;
|
|
634
|
+
else if (infoLogLevel == "info")
|
|
635
|
+
lvl = rocksdb::InfoLogLevel::INFO_LEVEL;
|
|
636
|
+
else if (infoLogLevel == "warn")
|
|
637
|
+
lvl = rocksdb::InfoLogLevel::WARN_LEVEL;
|
|
638
|
+
else if (infoLogLevel == "error")
|
|
639
|
+
lvl = rocksdb::InfoLogLevel::ERROR_LEVEL;
|
|
640
|
+
else if (infoLogLevel == "fatal")
|
|
641
|
+
lvl = rocksdb::InfoLogLevel::FATAL_LEVEL;
|
|
642
|
+
else if (infoLogLevel == "header")
|
|
643
|
+
lvl = rocksdb::InfoLogLevel::HEADER_LEVEL;
|
|
644
|
+
else
|
|
645
|
+
napi_throw_error(env, nullptr, "invalid log level");
|
|
646
|
+
|
|
647
|
+
options.info_log_level = lvl;
|
|
648
|
+
} else {
|
|
649
|
+
// In some places RocksDB checks this option to see if it should prepare
|
|
650
|
+
// debug information (ahead of logging), so set it to the highest level.
|
|
651
|
+
options.info_log_level = rocksdb::InfoLogLevel::HEADER_LEVEL;
|
|
652
|
+
options.info_log.reset(new NullLogger());
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
const auto readOnly = BooleanProperty(env, argv[2], "readOnly", false);
|
|
656
|
+
const auto cacheSize = Uint32Property(env, argv[2], "cacheSize", 8 << 20);
|
|
657
|
+
|
|
658
|
+
rocksdb::BlockBasedTableOptions tableOptions;
|
|
659
|
+
|
|
660
|
+
if (cacheSize) {
|
|
661
|
+
tableOptions.block_cache = rocksdb::NewLRUCache(cacheSize);
|
|
662
|
+
} else {
|
|
663
|
+
tableOptions.no_block_cache = true;
|
|
664
|
+
}
|
|
649
665
|
|
|
650
|
-
|
|
666
|
+
tableOptions.block_size = Uint32Property(env, argv[2], "blockSize", 4096);
|
|
667
|
+
tableOptions.block_restart_interval = Uint32Property(env, argv[2], "blockRestartInterval", 16);
|
|
668
|
+
tableOptions.filter_policy.reset(rocksdb::NewBloomFilterPolicy(10));
|
|
669
|
+
tableOptions.format_version = 5;
|
|
670
|
+
tableOptions.checksum = rocksdb::kxxHash64;
|
|
651
671
|
|
|
652
|
-
|
|
653
|
-
const auto writeBufferSize = Uint32Property(env, options, "writeBufferSize", 4 << 20);
|
|
654
|
-
const auto blockSize = Uint32Property(env, options, "blockSize", 4096);
|
|
655
|
-
const auto maxOpenFiles = Uint32Property(env, options, "maxOpenFiles", 1000);
|
|
656
|
-
const auto blockRestartInterval = Uint32Property(env, options, "blockRestartInterval", 16);
|
|
657
|
-
const auto maxFileSize = Uint32Property(env, options, "maxFileSize", 2 << 20);
|
|
672
|
+
options.table_factory.reset(rocksdb::NewBlockBasedTableFactory(tableOptions));
|
|
658
673
|
|
|
659
674
|
const auto callback = argv[3];
|
|
660
675
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
676
|
+
NAPI_PENDING_EXCEPTION();
|
|
677
|
+
|
|
678
|
+
auto worker = new OpenWorker(env, database, callback, location, options, readOnly);
|
|
664
679
|
worker->Queue(env);
|
|
665
680
|
|
|
666
681
|
return 0;
|
|
@@ -698,11 +713,13 @@ NAPI_METHOD(db_put) {
|
|
|
698
713
|
NAPI_ARGV(4);
|
|
699
714
|
NAPI_DB_CONTEXT();
|
|
700
715
|
|
|
701
|
-
const auto key =
|
|
702
|
-
const auto
|
|
716
|
+
const auto key = NapiSlice(env, argv[1]);
|
|
717
|
+
const auto val = NapiSlice(env, argv[2]);
|
|
718
|
+
|
|
719
|
+
NAPI_PENDING_EXCEPTION();
|
|
703
720
|
|
|
704
721
|
rocksdb::WriteOptions options;
|
|
705
|
-
return ToError(env, database->db_->Put(options, key,
|
|
722
|
+
return ToError(env, database->db_->Put(options, key, val));
|
|
706
723
|
}
|
|
707
724
|
|
|
708
725
|
struct GetWorker final : public Worker {
|
|
@@ -726,17 +743,19 @@ struct GetWorker final : public Worker {
|
|
|
726
743
|
options.fill_cache = fillCache_;
|
|
727
744
|
options.snapshot = snapshot_.get();
|
|
728
745
|
|
|
729
|
-
auto status = database.db_->Get(options,
|
|
746
|
+
auto status = database.db_->Get(options, key_, &value_);
|
|
747
|
+
|
|
748
|
+
key_.clear();
|
|
730
749
|
snapshot_ = nullptr;
|
|
731
750
|
|
|
732
751
|
return status;
|
|
733
752
|
}
|
|
734
753
|
|
|
735
|
-
|
|
754
|
+
napi_status OnOk(napi_env env, napi_value callback) override {
|
|
736
755
|
napi_value argv[2];
|
|
737
|
-
napi_get_null(env, &argv[0]);
|
|
738
|
-
Convert(env, std::move(value_), asBuffer_, argv[1]);
|
|
739
|
-
CallFunction(env, callback, 2, argv);
|
|
756
|
+
NAPI_STATUS_RETURN(napi_get_null(env, &argv[0]));
|
|
757
|
+
NAPI_STATUS_RETURN(Convert(env, std::move(value_), asBuffer_, argv[1]));
|
|
758
|
+
return CallFunction(env, callback, 2, argv);
|
|
740
759
|
}
|
|
741
760
|
|
|
742
761
|
void Destroy(napi_env env) override {
|
|
@@ -745,8 +764,8 @@ struct GetWorker final : public Worker {
|
|
|
745
764
|
}
|
|
746
765
|
|
|
747
766
|
private:
|
|
748
|
-
|
|
749
|
-
|
|
767
|
+
std::string key_;
|
|
768
|
+
std::string value_;
|
|
750
769
|
const bool asBuffer_;
|
|
751
770
|
const bool fillCache_;
|
|
752
771
|
std::shared_ptr<const rocksdb::Snapshot> snapshot_;
|
|
@@ -762,6 +781,8 @@ NAPI_METHOD(db_get) {
|
|
|
762
781
|
const auto fillCache = BooleanProperty(env, options, "fillCache", true);
|
|
763
782
|
const auto callback = argv[3];
|
|
764
783
|
|
|
784
|
+
NAPI_PENDING_EXCEPTION();
|
|
785
|
+
|
|
765
786
|
auto worker = new GetWorker(env, database, callback, key, asBuffer, fillCache);
|
|
766
787
|
worker->Queue(env);
|
|
767
788
|
|
|
@@ -790,6 +811,8 @@ struct GetManyWorker final : public Worker {
|
|
|
790
811
|
options.snapshot = snapshot_.get();
|
|
791
812
|
|
|
792
813
|
status_ = database.db_->MultiGet(options, std::vector<rocksdb::Slice>(keys_.begin(), keys_.end()), &values_);
|
|
814
|
+
|
|
815
|
+
keys_.clear();
|
|
793
816
|
snapshot_ = nullptr;
|
|
794
817
|
|
|
795
818
|
for (auto status : status_) {
|
|
@@ -801,26 +824,29 @@ struct GetManyWorker final : public Worker {
|
|
|
801
824
|
return rocksdb::Status::OK();
|
|
802
825
|
}
|
|
803
826
|
|
|
804
|
-
|
|
827
|
+
napi_status OnOk(napi_env env, napi_value callback) override {
|
|
805
828
|
const auto size = values_.size();
|
|
806
829
|
|
|
807
830
|
napi_value array;
|
|
808
|
-
napi_create_array_with_length(env, size, &array);
|
|
831
|
+
NAPI_STATUS_RETURN(napi_create_array_with_length(env, size, &array));
|
|
809
832
|
|
|
810
833
|
for (size_t idx = 0; idx < size; idx++) {
|
|
811
834
|
napi_value element;
|
|
812
835
|
if (status_[idx].ok()) {
|
|
813
|
-
Convert(env, values_[idx], valueAsBuffer_, element);
|
|
836
|
+
NAPI_STATUS_RETURN(Convert(env, std::move(values_[idx]), valueAsBuffer_, element));
|
|
814
837
|
} else {
|
|
815
|
-
napi_get_undefined(env, &element);
|
|
838
|
+
NAPI_STATUS_RETURN(napi_get_undefined(env, &element));
|
|
816
839
|
}
|
|
817
|
-
napi_set_element(env, array, static_cast<uint32_t>(idx), element);
|
|
840
|
+
NAPI_STATUS_RETURN(napi_set_element(env, array, static_cast<uint32_t>(idx), element));
|
|
818
841
|
}
|
|
819
842
|
|
|
843
|
+
values_.clear();
|
|
844
|
+
status_.clear();
|
|
845
|
+
|
|
820
846
|
napi_value argv[2];
|
|
821
|
-
napi_get_null(env, &argv[0]);
|
|
847
|
+
NAPI_STATUS_RETURN(napi_get_null(env, &argv[0]));
|
|
822
848
|
argv[1] = array;
|
|
823
|
-
CallFunction(env, callback, 2, argv);
|
|
849
|
+
return CallFunction(env, callback, 2, argv);
|
|
824
850
|
}
|
|
825
851
|
|
|
826
852
|
void Destroy(napi_env env) override {
|
|
@@ -829,7 +855,7 @@ struct GetManyWorker final : public Worker {
|
|
|
829
855
|
}
|
|
830
856
|
|
|
831
857
|
private:
|
|
832
|
-
|
|
858
|
+
std::vector<std::string> keys_;
|
|
833
859
|
std::vector<std::string> values_;
|
|
834
860
|
std::vector<rocksdb::Status> status_;
|
|
835
861
|
const bool valueAsBuffer_;
|
|
@@ -861,6 +887,8 @@ NAPI_METHOD(db_get_many) {
|
|
|
861
887
|
const bool fillCache = BooleanProperty(env, options, "fillCache", true);
|
|
862
888
|
const auto callback = argv[3];
|
|
863
889
|
|
|
890
|
+
NAPI_PENDING_EXCEPTION();
|
|
891
|
+
|
|
864
892
|
auto worker = new GetManyWorker(env, database, keys, callback, asBuffer, fillCache);
|
|
865
893
|
worker->Queue(env);
|
|
866
894
|
|
|
@@ -871,7 +899,9 @@ NAPI_METHOD(db_del) {
|
|
|
871
899
|
NAPI_ARGV(3);
|
|
872
900
|
NAPI_DB_CONTEXT();
|
|
873
901
|
|
|
874
|
-
const auto key =
|
|
902
|
+
const auto key = NapiSlice(env, argv[1]);
|
|
903
|
+
|
|
904
|
+
NAPI_PENDING_EXCEPTION();
|
|
875
905
|
|
|
876
906
|
rocksdb::WriteOptions options;
|
|
877
907
|
return ToError(env, database->db_->Delete(options, key));
|
|
@@ -889,6 +919,8 @@ NAPI_METHOD(db_clear) {
|
|
|
889
919
|
const auto gt = RangeOption(env, argv[1], "gt");
|
|
890
920
|
const auto gte = RangeOption(env, argv[1], "gte");
|
|
891
921
|
|
|
922
|
+
NAPI_PENDING_EXCEPTION();
|
|
923
|
+
|
|
892
924
|
// TODO (perf): Use DeleteRange.
|
|
893
925
|
|
|
894
926
|
BaseIterator it(database, reverse, lt, lte, gt, gte, limit, false);
|
|
@@ -934,23 +966,19 @@ NAPI_METHOD(db_get_property) {
|
|
|
934
966
|
NAPI_ARGV(2);
|
|
935
967
|
NAPI_DB_CONTEXT();
|
|
936
968
|
|
|
937
|
-
const auto property =
|
|
969
|
+
const auto property = NapiSlice(env, argv[1]);
|
|
970
|
+
|
|
971
|
+
NAPI_PENDING_EXCEPTION();
|
|
938
972
|
|
|
939
973
|
std::string value;
|
|
940
974
|
database->db_->GetProperty(property, &value);
|
|
941
975
|
|
|
942
976
|
napi_value result;
|
|
943
|
-
napi_create_string_utf8(env, value.data(), value.size(), &result);
|
|
977
|
+
NAPI_STATUS_THROWS(napi_create_string_utf8(env, value.data(), value.size(), &result));
|
|
944
978
|
|
|
945
979
|
return result;
|
|
946
980
|
}
|
|
947
981
|
|
|
948
|
-
static void FinalizeIterator(napi_env env, void* data, void* hint) {
|
|
949
|
-
if (data) {
|
|
950
|
-
delete reinterpret_cast<Iterator*>(data);
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
|
|
954
982
|
NAPI_METHOD(iterator_init) {
|
|
955
983
|
NAPI_ARGV(2);
|
|
956
984
|
NAPI_DB_CONTEXT();
|
|
@@ -970,15 +998,17 @@ NAPI_METHOD(iterator_init) {
|
|
|
970
998
|
const auto gt = RangeOption(env, options, "gt");
|
|
971
999
|
const auto gte = RangeOption(env, options, "gte");
|
|
972
1000
|
|
|
973
|
-
|
|
1001
|
+
NAPI_PENDING_EXCEPTION();
|
|
1002
|
+
|
|
1003
|
+
auto iterator = std::make_unique<Iterator>(database, reverse, keys, values, limit, lt, lte, gt, gte, fillCache, keyAsBuffer,
|
|
974
1004
|
valueAsBuffer, highWaterMarkBytes);
|
|
975
|
-
napi_value result;
|
|
976
1005
|
|
|
977
|
-
|
|
1006
|
+
napi_value result;
|
|
1007
|
+
NAPI_STATUS_THROWS(napi_create_external(env, iterator.get(), Finalize<Iterator>, iterator.get(), &result));
|
|
978
1008
|
|
|
979
1009
|
// Prevent GC of JS object before the iterator is closed (explicitly or on
|
|
980
1010
|
// db close) and keep track of non-closed iterators to end them on db close.
|
|
981
|
-
iterator->Attach(env, result);
|
|
1011
|
+
iterator.release()->Attach(env, result);
|
|
982
1012
|
|
|
983
1013
|
return result;
|
|
984
1014
|
}
|
|
@@ -987,39 +1017,22 @@ NAPI_METHOD(iterator_seek) {
|
|
|
987
1017
|
NAPI_ARGV(2);
|
|
988
1018
|
NAPI_ITERATOR_CONTEXT();
|
|
989
1019
|
|
|
990
|
-
const auto target =
|
|
1020
|
+
const auto target = NapiSlice(env, argv[1]);
|
|
1021
|
+
|
|
1022
|
+
NAPI_PENDING_EXCEPTION();
|
|
1023
|
+
|
|
991
1024
|
iterator->first_ = true;
|
|
992
1025
|
iterator->Seek(target);
|
|
993
1026
|
|
|
994
1027
|
return 0;
|
|
995
1028
|
}
|
|
996
1029
|
|
|
997
|
-
struct CloseIteratorWorker final : public Worker {
|
|
998
|
-
CloseIteratorWorker(napi_env env, Iterator* iterator, napi_value callback)
|
|
999
|
-
: Worker(env, iterator->database_, callback, "leveldown.iterator.end"), iterator_(iterator) {}
|
|
1000
|
-
|
|
1001
|
-
rocksdb::Status Execute(Database& database) override {
|
|
1002
|
-
iterator_->Close();
|
|
1003
|
-
return rocksdb::Status::OK();
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
void Destroy(napi_env env) override {
|
|
1007
|
-
iterator_->Detach(env);
|
|
1008
|
-
Worker::Destroy(env);
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
private:
|
|
1012
|
-
Iterator* iterator_;
|
|
1013
|
-
};
|
|
1014
|
-
|
|
1015
1030
|
NAPI_METHOD(iterator_close) {
|
|
1016
|
-
NAPI_ARGV(
|
|
1031
|
+
NAPI_ARGV(1);
|
|
1017
1032
|
NAPI_ITERATOR_CONTEXT();
|
|
1018
1033
|
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
auto worker = new CloseIteratorWorker(env, iterator, callback);
|
|
1022
|
-
worker->Queue(env);
|
|
1034
|
+
iterator->Detach(env);
|
|
1035
|
+
iterator->Close();
|
|
1023
1036
|
|
|
1024
1037
|
return 0;
|
|
1025
1038
|
}
|
|
@@ -1033,9 +1046,6 @@ struct NextWorker final : public Worker {
|
|
|
1033
1046
|
iterator_->SeekToRange();
|
|
1034
1047
|
}
|
|
1035
1048
|
|
|
1036
|
-
// Limit the size of the cache to prevent starving the event loop
|
|
1037
|
-
// in JS-land while we're recursively calling process.nextTick().
|
|
1038
|
-
|
|
1039
1049
|
cache_.reserve(size_ * 2);
|
|
1040
1050
|
size_t bytesRead = 0;
|
|
1041
1051
|
|
|
@@ -1075,29 +1085,29 @@ struct NextWorker final : public Worker {
|
|
|
1075
1085
|
return iterator_->Status();
|
|
1076
1086
|
}
|
|
1077
1087
|
|
|
1078
|
-
|
|
1088
|
+
napi_status OnOk(napi_env env, napi_value callback) override {
|
|
1079
1089
|
const auto size = cache_.size();
|
|
1080
1090
|
napi_value result;
|
|
1081
|
-
napi_create_array_with_length(env, size, &result);
|
|
1091
|
+
NAPI_STATUS_RETURN(napi_create_array_with_length(env, size, &result));
|
|
1082
1092
|
|
|
1083
1093
|
for (size_t idx = 0; idx < cache_.size(); idx += 2) {
|
|
1084
1094
|
napi_value key;
|
|
1085
1095
|
napi_value val;
|
|
1086
1096
|
|
|
1087
|
-
Convert(env, cache_[idx + 0], iterator_->keyAsBuffer_, key);
|
|
1088
|
-
Convert(env, cache_[idx + 1], iterator_->valueAsBuffer_, val);
|
|
1097
|
+
NAPI_STATUS_RETURN(Convert(env, std::move(cache_[idx + 0]), iterator_->keyAsBuffer_, key));
|
|
1098
|
+
NAPI_STATUS_RETURN(Convert(env, std::move(cache_[idx + 1]), iterator_->valueAsBuffer_, val));
|
|
1089
1099
|
|
|
1090
|
-
napi_set_element(env, result, static_cast<int>(idx + 0), key);
|
|
1091
|
-
napi_set_element(env, result, static_cast<int>(idx + 1), val);
|
|
1100
|
+
NAPI_STATUS_RETURN(napi_set_element(env, result, static_cast<int>(idx + 0), key));
|
|
1101
|
+
NAPI_STATUS_RETURN(napi_set_element(env, result, static_cast<int>(idx + 1), val));
|
|
1092
1102
|
}
|
|
1093
1103
|
|
|
1094
1104
|
cache_.clear();
|
|
1095
1105
|
|
|
1096
1106
|
napi_value argv[3];
|
|
1097
|
-
napi_get_null(env, &argv[0]);
|
|
1107
|
+
NAPI_STATUS_RETURN(napi_get_null(env, &argv[0]));
|
|
1098
1108
|
argv[1] = result;
|
|
1099
|
-
napi_get_boolean(env, !finished_, &argv[2]);
|
|
1100
|
-
CallFunction(env, callback, 3, argv);
|
|
1109
|
+
NAPI_STATUS_RETURN(napi_get_boolean(env, !finished_, &argv[2]));
|
|
1110
|
+
return CallFunction(env, callback, 3, argv);
|
|
1101
1111
|
}
|
|
1102
1112
|
|
|
1103
1113
|
private:
|
|
@@ -1113,8 +1123,6 @@ NAPI_METHOD(iterator_nextv) {
|
|
|
1113
1123
|
|
|
1114
1124
|
uint32_t size;
|
|
1115
1125
|
NAPI_STATUS_THROWS(napi_get_value_uint32(env, argv[1], &size));
|
|
1116
|
-
if (size == 0)
|
|
1117
|
-
size = 1;
|
|
1118
1126
|
|
|
1119
1127
|
const auto callback = argv[2];
|
|
1120
1128
|
|
|
@@ -1164,16 +1172,12 @@ NAPI_METHOD(batch_do) {
|
|
|
1164
1172
|
}
|
|
1165
1173
|
}
|
|
1166
1174
|
|
|
1175
|
+
NAPI_PENDING_EXCEPTION();
|
|
1176
|
+
|
|
1167
1177
|
rocksdb::WriteOptions options;
|
|
1168
1178
|
return ToError(env, database->db_->Write(options, &batch));
|
|
1169
1179
|
}
|
|
1170
1180
|
|
|
1171
|
-
static void FinalizeBatch(napi_env env, void* data, void* hint) {
|
|
1172
|
-
if (data) {
|
|
1173
|
-
delete reinterpret_cast<rocksdb::WriteBatch*>(data);
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
1181
|
NAPI_METHOD(batch_init) {
|
|
1178
1182
|
NAPI_ARGV(1);
|
|
1179
1183
|
NAPI_DB_CONTEXT();
|
|
@@ -1181,7 +1185,7 @@ NAPI_METHOD(batch_init) {
|
|
|
1181
1185
|
auto batch = new rocksdb::WriteBatch();
|
|
1182
1186
|
|
|
1183
1187
|
napi_value result;
|
|
1184
|
-
NAPI_STATUS_THROWS(napi_create_external(env, batch,
|
|
1188
|
+
NAPI_STATUS_THROWS(napi_create_external(env, batch, Finalize<rocksdb::WriteBatch>, batch, &result));
|
|
1185
1189
|
return result;
|
|
1186
1190
|
}
|
|
1187
1191
|
|
|
@@ -1190,9 +1194,11 @@ NAPI_METHOD(batch_put) {
|
|
|
1190
1194
|
NAPI_BATCH_CONTEXT();
|
|
1191
1195
|
|
|
1192
1196
|
const auto key = NapiSlice(env, argv[1]);
|
|
1193
|
-
const auto
|
|
1197
|
+
const auto val = NapiSlice(env, argv[2]);
|
|
1198
|
+
|
|
1199
|
+
NAPI_PENDING_EXCEPTION();
|
|
1194
1200
|
|
|
1195
|
-
batch->Put(key,
|
|
1201
|
+
batch->Put(key, val);
|
|
1196
1202
|
|
|
1197
1203
|
return 0;
|
|
1198
1204
|
}
|
|
@@ -1203,6 +1209,8 @@ NAPI_METHOD(batch_del) {
|
|
|
1203
1209
|
|
|
1204
1210
|
const auto key = NapiSlice(env, argv[1]);
|
|
1205
1211
|
|
|
1212
|
+
NAPI_PENDING_EXCEPTION();
|
|
1213
|
+
|
|
1206
1214
|
batch->Delete(key);
|
|
1207
1215
|
|
|
1208
1216
|
return 0;
|
package/iterator.js
CHANGED
|
@@ -103,7 +103,7 @@ class Iterator extends AbstractIterator {
|
|
|
103
103
|
this[kCache] = empty
|
|
104
104
|
this[kCallback] = null
|
|
105
105
|
|
|
106
|
-
binding.iterator_close(this[kContext]
|
|
106
|
+
process.nextTick(callback, binding.iterator_close(this[kContext]))
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
_end (callback) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/rocksdb",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.35",
|
|
4
4
|
"description": "A low-level Node.js RocksDB binding",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "index.js",
|
|
@@ -12,17 +12,17 @@
|
|
|
12
12
|
"test-prebuild": "cross-env PREBUILDS_ONLY=1 npm t",
|
|
13
13
|
"coverage": "nyc report -r lcovonly",
|
|
14
14
|
"rebuild": "npm run install --build-from-source",
|
|
15
|
-
"prebuild": "prebuildify -t
|
|
15
|
+
"prebuild": "prebuildify -t -t 17.8.0 --napi --strip",
|
|
16
16
|
"download-prebuilds": "prebuildify-ci download",
|
|
17
17
|
"hallmark": "hallmark --fix",
|
|
18
18
|
"dependency-check": "dependency-check --no-dev -i napi-macros . test/*.js",
|
|
19
19
|
"prepublishOnly": "npm run dependency-check",
|
|
20
|
-
"prebuild-linux-arm": "prebuildify-cross -i linux-armv6 -i linux-armv7 -i linux-arm64 -t
|
|
21
|
-
"prebuild-android-arm": "prebuildify-cross -i android-armv7 -i android-arm64 -t
|
|
22
|
-
"prebuild-linux-x64": "prebuildify-cross -i centos7-devtoolset7 -i alpine -t
|
|
23
|
-
"prebuild-darwin-x64+arm64": "prebuildify -t
|
|
24
|
-
"prebuild-win32-x86": "prebuildify -t
|
|
25
|
-
"prebuild-win32-x64": "prebuildify -t
|
|
20
|
+
"prebuild-linux-arm": "prebuildify-cross -i linux-armv6 -i linux-armv7 -i linux-arm64 -t -t 17.8.0 --napi --strip",
|
|
21
|
+
"prebuild-android-arm": "prebuildify-cross -i android-armv7 -i android-arm64 -t -t 17.8.0 --napi --strip",
|
|
22
|
+
"prebuild-linux-x64": "prebuildify-cross -i centos7-devtoolset7 -i alpine -t -t 17.8.0 --napi --strip",
|
|
23
|
+
"prebuild-darwin-x64+arm64": "prebuildify -t -t 17.8.0 --napi --strip --arch x64+arm64",
|
|
24
|
+
"prebuild-win32-x86": "prebuildify -t -t 17.8.0 --napi --strip",
|
|
25
|
+
"prebuild-win32-x64": "prebuildify -t -t 17.8.0 --napi --strip"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"abstract-level": "^1.0.2",
|
|
Binary file
|
|
Binary file
|
|
index 6a452a6..ff525bf 100755
|
|
|
Binary file
|