@nxtedition/rocksdb 7.0.44 → 7.0.45
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 +344 -391
- package/chained-batch.js +70 -21
- package/index.js +33 -7
- package/package.json +2 -2
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
package/binding.cc
CHANGED
|
@@ -249,7 +249,7 @@ napi_status Convert(napi_env env, T&& s, bool asBuffer, napi_value& result) {
|
|
|
249
249
|
if (!s) {
|
|
250
250
|
return napi_get_null(env, &result);
|
|
251
251
|
} else if (asBuffer) {
|
|
252
|
-
using Y = typename std::
|
|
252
|
+
using Y = typename std::decay<decltype(*s)>::type;
|
|
253
253
|
auto ptr = new Y(std::move(*s));
|
|
254
254
|
return napi_create_external_buffer(env, ptr->size(), const_cast<char*>(ptr->data()), Finalize<Y>, ptr, &result);
|
|
255
255
|
} else {
|
|
@@ -329,6 +329,13 @@ struct Worker {
|
|
|
329
329
|
rocksdb::Status status_;
|
|
330
330
|
};
|
|
331
331
|
|
|
332
|
+
struct ColumnFamily {
|
|
333
|
+
napi_ref ref;
|
|
334
|
+
napi_value val;
|
|
335
|
+
rocksdb::ColumnFamilyHandle* handle;
|
|
336
|
+
rocksdb::ColumnFamilyDescriptor descriptor;
|
|
337
|
+
};
|
|
338
|
+
|
|
332
339
|
struct Database {
|
|
333
340
|
void AttachIterator(napi_env env, Iterator* iterator) {
|
|
334
341
|
iterators_.insert(iterator);
|
|
@@ -367,13 +374,228 @@ struct Database {
|
|
|
367
374
|
Worker* pendingCloseWorker_;
|
|
368
375
|
std::set<Iterator*> iterators_;
|
|
369
376
|
std::set<Updates*> updates_;
|
|
370
|
-
std::
|
|
377
|
+
std::map<int32_t, ColumnFamily> columns_;
|
|
371
378
|
napi_ref priorityRef_;
|
|
372
379
|
|
|
373
380
|
private:
|
|
374
381
|
uint32_t priorityWork_ = 0;
|
|
375
382
|
};
|
|
376
383
|
|
|
384
|
+
enum BatchOp { Empty, Put, Delete, Merge, Data };
|
|
385
|
+
|
|
386
|
+
struct BatchEntry {
|
|
387
|
+
BatchOp op = BatchOp::Empty;
|
|
388
|
+
std::optional<std::string> key;
|
|
389
|
+
std::optional<std::string> val;
|
|
390
|
+
std::optional<ColumnFamily> column;
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
struct BatchIterator : public rocksdb::WriteBatch::Handler {
|
|
394
|
+
BatchIterator(Database* database,
|
|
395
|
+
bool keys = true,
|
|
396
|
+
bool values = true,
|
|
397
|
+
bool data = true,
|
|
398
|
+
const rocksdb::ColumnFamilyHandle* column = nullptr,
|
|
399
|
+
bool keyAsBuffer = false,
|
|
400
|
+
bool valueAsBuffer = false)
|
|
401
|
+
: database_(database),
|
|
402
|
+
keys_(keys),
|
|
403
|
+
values_(values),
|
|
404
|
+
data_(data),
|
|
405
|
+
column_(column),
|
|
406
|
+
keyAsBuffer_(keyAsBuffer),
|
|
407
|
+
valueAsBuffer_(valueAsBuffer) {}
|
|
408
|
+
|
|
409
|
+
napi_status Iterate(napi_env env, const rocksdb::WriteBatch& batch, napi_value* result) {
|
|
410
|
+
cache_.reserve(batch.Count());
|
|
411
|
+
batch.Iterate(this); // TODO (fix): Error?
|
|
412
|
+
|
|
413
|
+
napi_value putStr;
|
|
414
|
+
NAPI_STATUS_RETURN(napi_create_string_utf8(env, "put", NAPI_AUTO_LENGTH, &putStr));
|
|
415
|
+
|
|
416
|
+
napi_value delStr;
|
|
417
|
+
NAPI_STATUS_RETURN(napi_create_string_utf8(env, "del", NAPI_AUTO_LENGTH, &delStr));
|
|
418
|
+
|
|
419
|
+
napi_value mergeStr;
|
|
420
|
+
NAPI_STATUS_RETURN(napi_create_string_utf8(env, "merge", NAPI_AUTO_LENGTH, &mergeStr));
|
|
421
|
+
|
|
422
|
+
napi_value dataStr;
|
|
423
|
+
NAPI_STATUS_RETURN(napi_create_string_utf8(env, "data", NAPI_AUTO_LENGTH, &dataStr));
|
|
424
|
+
|
|
425
|
+
napi_value nullVal;
|
|
426
|
+
NAPI_STATUS_RETURN(napi_get_null(env, &nullVal));
|
|
427
|
+
|
|
428
|
+
NAPI_STATUS_RETURN(napi_create_array_with_length(env, cache_.size() * 4, result));
|
|
429
|
+
for (size_t n = 0; n < cache_.size(); ++n) {
|
|
430
|
+
napi_value op;
|
|
431
|
+
if (cache_[n].op == BatchOp::Put) {
|
|
432
|
+
op = putStr;
|
|
433
|
+
} else if (cache_[n].op == BatchOp::Delete) {
|
|
434
|
+
op = delStr;
|
|
435
|
+
} else if (cache_[n].op == BatchOp::Merge) {
|
|
436
|
+
op = mergeStr;
|
|
437
|
+
} else if (cache_[n].op == BatchOp::Data) {
|
|
438
|
+
op = dataStr;
|
|
439
|
+
} else {
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
NAPI_STATUS_RETURN(napi_set_element(env, *result, n * 4 + 0, op));
|
|
444
|
+
|
|
445
|
+
napi_value key;
|
|
446
|
+
NAPI_STATUS_RETURN(Convert(env, cache_[n].key, keyAsBuffer_, key));
|
|
447
|
+
NAPI_STATUS_RETURN(napi_set_element(env, *result, n * 4 + 1, key));
|
|
448
|
+
|
|
449
|
+
napi_value val;
|
|
450
|
+
NAPI_STATUS_RETURN(Convert(env, cache_[n].val, valueAsBuffer_, val));
|
|
451
|
+
NAPI_STATUS_RETURN(napi_set_element(env, *result, n * 4 + 2, val));
|
|
452
|
+
|
|
453
|
+
// TODO (fix)
|
|
454
|
+
// napi_value column = cache_[n].column ? cache_[n].column->val : nullVal;
|
|
455
|
+
NAPI_STATUS_RETURN(napi_set_element(env, *result, n * 4 + 3, nullVal));
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return napi_ok;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
rocksdb::Status PutCF(uint32_t column_family_id, const rocksdb::Slice& key, const rocksdb::Slice& value) override {
|
|
462
|
+
if (column_ && column_->GetID() != column_family_id) {
|
|
463
|
+
return rocksdb::Status::OK();
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
BatchEntry entry;
|
|
467
|
+
|
|
468
|
+
entry.op = BatchOp::Put;
|
|
469
|
+
|
|
470
|
+
if (keys_) {
|
|
471
|
+
entry.key = key.ToStringView();
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (values_) {
|
|
475
|
+
entry.val = value.ToStringView();
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// if (database_ && database_->columns_.find(column_family_id) != database_->columns_.end()) {
|
|
479
|
+
// entry.column = database_->columns_[column_family_id];
|
|
480
|
+
// }
|
|
481
|
+
|
|
482
|
+
cache_.push_back(entry);
|
|
483
|
+
|
|
484
|
+
return rocksdb::Status::OK();
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
rocksdb::Status DeleteCF(uint32_t column_family_id, const rocksdb::Slice& key) override {
|
|
488
|
+
if (column_ && column_->GetID() != column_family_id) {
|
|
489
|
+
return rocksdb::Status::OK();
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
BatchEntry entry;
|
|
493
|
+
|
|
494
|
+
entry.op = BatchOp::Delete;
|
|
495
|
+
|
|
496
|
+
if (keys_) {
|
|
497
|
+
entry.key = key.ToStringView();
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// if (database_ && database_->columns_.find(column_family_id) != database_->columns_.end()) {
|
|
501
|
+
// entry.column = database_->columns_[column_family_id];
|
|
502
|
+
// }
|
|
503
|
+
|
|
504
|
+
cache_.push_back(entry);
|
|
505
|
+
|
|
506
|
+
return rocksdb::Status::OK();
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
rocksdb::Status MergeCF(uint32_t column_family_id, const rocksdb::Slice& key, const rocksdb::Slice& value) override {
|
|
510
|
+
if (column_ && column_->GetID() != column_family_id) {
|
|
511
|
+
return rocksdb::Status::OK();
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
BatchEntry entry;
|
|
515
|
+
|
|
516
|
+
entry.op = BatchOp::Merge;
|
|
517
|
+
|
|
518
|
+
if (keys_) {
|
|
519
|
+
entry.key = key.ToStringView();
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if (values_) {
|
|
523
|
+
entry.val = value.ToStringView();
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// if (database_ && database_->columns_.find(column_family_id) != database_->columns_.end()) {
|
|
527
|
+
// entry.column = database_->columns_[column_family_id];
|
|
528
|
+
// }
|
|
529
|
+
|
|
530
|
+
cache_.push_back(entry);
|
|
531
|
+
|
|
532
|
+
return rocksdb::Status::OK();
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
void LogData(const rocksdb::Slice& data) override {
|
|
536
|
+
if (!data_) {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
BatchEntry entry;
|
|
541
|
+
|
|
542
|
+
entry.op = BatchOp::Data;
|
|
543
|
+
|
|
544
|
+
entry.val = data.ToStringView();
|
|
545
|
+
|
|
546
|
+
cache_.push_back(entry);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
bool Continue() override { return true; }
|
|
550
|
+
|
|
551
|
+
private:
|
|
552
|
+
Database* database_;
|
|
553
|
+
bool keys_;
|
|
554
|
+
bool values_;
|
|
555
|
+
bool data_;
|
|
556
|
+
const rocksdb::ColumnFamilyHandle* column_;
|
|
557
|
+
bool keyAsBuffer_;
|
|
558
|
+
bool valueAsBuffer_;
|
|
559
|
+
std::vector<BatchEntry> cache_;
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
struct Updates : public BatchIterator {
|
|
563
|
+
Updates(Database* database,
|
|
564
|
+
int64_t seqNumber,
|
|
565
|
+
bool keys,
|
|
566
|
+
bool values,
|
|
567
|
+
bool data,
|
|
568
|
+
const rocksdb::ColumnFamilyHandle* column,
|
|
569
|
+
bool keyAsBuffer,
|
|
570
|
+
bool valueAsBuffer)
|
|
571
|
+
: BatchIterator(database, keys, values, data, column, keyAsBuffer, valueAsBuffer),
|
|
572
|
+
database_(database),
|
|
573
|
+
sequence_(seqNumber),
|
|
574
|
+
start_(seqNumber) {}
|
|
575
|
+
|
|
576
|
+
void Close() { iterator_.reset(); }
|
|
577
|
+
|
|
578
|
+
void Attach(napi_env env, napi_value context) {
|
|
579
|
+
napi_create_reference(env, context, 1, &ref_);
|
|
580
|
+
database_->AttachUpdates(env, this);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
void Detach(napi_env env) {
|
|
584
|
+
database_->DetachUpdates(env, this);
|
|
585
|
+
if (ref_) {
|
|
586
|
+
napi_delete_reference(env, ref_);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
Database* database_;
|
|
591
|
+
int64_t sequence_;
|
|
592
|
+
int64_t start_;
|
|
593
|
+
std::unique_ptr<rocksdb::TransactionLogIterator> iterator_;
|
|
594
|
+
|
|
595
|
+
private:
|
|
596
|
+
napi_ref ref_ = nullptr;
|
|
597
|
+
};
|
|
598
|
+
|
|
377
599
|
struct BaseIterator {
|
|
378
600
|
BaseIterator(Database* database,
|
|
379
601
|
rocksdb::ColumnFamilyHandle* column,
|
|
@@ -562,53 +784,10 @@ struct Iterator final : public BaseIterator {
|
|
|
562
784
|
napi_ref ref_ = nullptr;
|
|
563
785
|
};
|
|
564
786
|
|
|
565
|
-
struct Updates {
|
|
566
|
-
Updates(Database* database,
|
|
567
|
-
int64_t seqNumber,
|
|
568
|
-
bool keys,
|
|
569
|
-
bool values,
|
|
570
|
-
bool data,
|
|
571
|
-
const rocksdb::ColumnFamilyHandle* column)
|
|
572
|
-
: database_(database),
|
|
573
|
-
sequence_(seqNumber),
|
|
574
|
-
start_(seqNumber),
|
|
575
|
-
keys_(keys),
|
|
576
|
-
values_(values),
|
|
577
|
-
data_(data),
|
|
578
|
-
column_(column) {}
|
|
579
|
-
|
|
580
|
-
void Close() { iterator_.reset(); }
|
|
581
|
-
|
|
582
|
-
void Attach(napi_env env, napi_value context) {
|
|
583
|
-
napi_create_reference(env, context, 1, &ref_);
|
|
584
|
-
database_->AttachUpdates(env, this);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
void Detach(napi_env env) {
|
|
588
|
-
database_->DetachUpdates(env, this);
|
|
589
|
-
if (ref_) {
|
|
590
|
-
napi_delete_reference(env, ref_);
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
Database* database_;
|
|
595
|
-
int64_t sequence_;
|
|
596
|
-
int64_t start_;
|
|
597
|
-
std::unique_ptr<rocksdb::TransactionLogIterator> iterator_;
|
|
598
|
-
bool keys_;
|
|
599
|
-
bool values_;
|
|
600
|
-
bool data_;
|
|
601
|
-
const rocksdb::ColumnFamilyHandle* column_;
|
|
602
|
-
|
|
603
|
-
private:
|
|
604
|
-
napi_ref ref_ = nullptr;
|
|
605
|
-
};
|
|
606
|
-
|
|
607
787
|
static napi_status GetColumnFamily(Database* database,
|
|
608
788
|
napi_env env,
|
|
609
789
|
napi_value options,
|
|
610
|
-
rocksdb::ColumnFamilyHandle** column
|
|
611
|
-
bool fallback = true) {
|
|
790
|
+
rocksdb::ColumnFamilyHandle** column) {
|
|
612
791
|
bool hasColumn = false;
|
|
613
792
|
NAPI_STATUS_RETURN(napi_has_named_property(env, options, "column", &hasColumn));
|
|
614
793
|
|
|
@@ -616,7 +795,7 @@ static napi_status GetColumnFamily(Database* database,
|
|
|
616
795
|
napi_value value = nullptr;
|
|
617
796
|
NAPI_STATUS_RETURN(napi_get_named_property(env, options, "column", &value));
|
|
618
797
|
NAPI_STATUS_RETURN(napi_get_value_external(env, value, reinterpret_cast<void**>(column)));
|
|
619
|
-
} else if (
|
|
798
|
+
} else if (database) {
|
|
620
799
|
*column = database->db_->DefaultColumnFamily();
|
|
621
800
|
} else {
|
|
622
801
|
*column = nullptr;
|
|
@@ -641,18 +820,18 @@ static void env_cleanup_hook(void* arg) {
|
|
|
641
820
|
// following code must be a safe noop if called before db_open() or after
|
|
642
821
|
// db_close().
|
|
643
822
|
if (database && database->db_) {
|
|
644
|
-
for (auto it : database->iterators_) {
|
|
823
|
+
for (auto& it : database->iterators_) {
|
|
645
824
|
// TODO: does not do `napi_delete_reference`. Problem?
|
|
646
825
|
it->Close();
|
|
647
826
|
}
|
|
648
827
|
|
|
649
|
-
for (auto it : database->updates_) {
|
|
828
|
+
for (auto& it : database->updates_) {
|
|
650
829
|
// TODO: does not do `napi_delete_reference`. Problem?
|
|
651
830
|
it->Close();
|
|
652
831
|
}
|
|
653
832
|
|
|
654
|
-
for (auto it : database->columns_) {
|
|
655
|
-
database->db_->DestroyColumnFamilyHandle(it);
|
|
833
|
+
for (auto& it : database->columns_) {
|
|
834
|
+
database->db_->DestroyColumnFamilyHandle(it.second.handle);
|
|
656
835
|
}
|
|
657
836
|
|
|
658
837
|
// Having closed the iterators (and released snapshots) we can safely close.
|
|
@@ -666,6 +845,9 @@ static void FinalizeDatabase(napi_env env, void* data, void* hint) {
|
|
|
666
845
|
napi_remove_env_cleanup_hook(env, env_cleanup_hook, database);
|
|
667
846
|
if (database->priorityRef_)
|
|
668
847
|
napi_delete_reference(env, database->priorityRef_);
|
|
848
|
+
for (auto& it : database->columns_) {
|
|
849
|
+
napi_delete_reference(env, it.second.ref);
|
|
850
|
+
}
|
|
669
851
|
delete database;
|
|
670
852
|
}
|
|
671
853
|
}
|
|
@@ -688,17 +870,16 @@ struct OpenWorker final : public Worker {
|
|
|
688
870
|
napi_value callback,
|
|
689
871
|
const std::string& location,
|
|
690
872
|
const rocksdb::Options& options,
|
|
691
|
-
std::vector<rocksdb::ColumnFamilyDescriptor>
|
|
873
|
+
std::vector<rocksdb::ColumnFamilyDescriptor> descriptors)
|
|
692
874
|
: Worker(env, database, callback, "leveldown.db.open"),
|
|
693
875
|
options_(options),
|
|
694
876
|
location_(location),
|
|
695
|
-
|
|
877
|
+
descriptors_(std::move(descriptors)) {}
|
|
696
878
|
|
|
697
879
|
rocksdb::Status Execute(Database& database) override {
|
|
698
880
|
rocksdb::DB* db = nullptr;
|
|
699
|
-
const auto status =
|
|
700
|
-
|
|
701
|
-
: rocksdb::DB::Open(options_, location_, column_families_, &database.columns_, &db);
|
|
881
|
+
const auto status = descriptors_.empty() ? rocksdb::DB::Open(options_, location_, &db)
|
|
882
|
+
: rocksdb::DB::Open(options_, location_, descriptors_, &handles_, &db);
|
|
702
883
|
database.db_.reset(db);
|
|
703
884
|
return status;
|
|
704
885
|
}
|
|
@@ -707,13 +888,19 @@ struct OpenWorker final : public Worker {
|
|
|
707
888
|
napi_value argv[2];
|
|
708
889
|
NAPI_STATUS_RETURN(napi_get_null(env, &argv[0]));
|
|
709
890
|
|
|
710
|
-
const auto size =
|
|
891
|
+
const auto size = handles_.size();
|
|
711
892
|
NAPI_STATUS_RETURN(napi_create_object(env, &argv[1]));
|
|
712
893
|
|
|
713
894
|
for (size_t n = 0; n < size; ++n) {
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
895
|
+
ColumnFamily column;
|
|
896
|
+
column.handle = handles_[n];
|
|
897
|
+
column.descriptor = descriptors_[n];
|
|
898
|
+
NAPI_STATUS_RETURN(napi_create_external(env, column.handle, nullptr, nullptr, &column.val));
|
|
899
|
+
NAPI_STATUS_RETURN(napi_create_reference(env, column.val, 1, &column.ref));
|
|
900
|
+
|
|
901
|
+
NAPI_STATUS_RETURN(napi_set_named_property(env, argv[1], descriptors_[n].name.c_str(), column.val));
|
|
902
|
+
|
|
903
|
+
database_->columns_[column.handle->GetID()] = column;
|
|
717
904
|
}
|
|
718
905
|
|
|
719
906
|
return CallFunction(env, callback, 2, argv);
|
|
@@ -721,7 +908,8 @@ struct OpenWorker final : public Worker {
|
|
|
721
908
|
|
|
722
909
|
rocksdb::Options options_;
|
|
723
910
|
const std::string location_;
|
|
724
|
-
std::vector<rocksdb::ColumnFamilyDescriptor>
|
|
911
|
+
std::vector<rocksdb::ColumnFamilyDescriptor> descriptors_;
|
|
912
|
+
std::vector<rocksdb::ColumnFamilyHandle*> handles_;
|
|
725
913
|
};
|
|
726
914
|
|
|
727
915
|
template <typename T, typename U>
|
|
@@ -940,8 +1128,8 @@ struct CloseWorker final : public Worker {
|
|
|
940
1128
|
: Worker(env, database, callback, "leveldown.db.close") {}
|
|
941
1129
|
|
|
942
1130
|
rocksdb::Status Execute(Database& database) override {
|
|
943
|
-
for (auto it : database.columns_) {
|
|
944
|
-
database.db_->DestroyColumnFamilyHandle(it);
|
|
1131
|
+
for (auto& it : database.columns_) {
|
|
1132
|
+
database.db_->DestroyColumnFamilyHandle(it.second.handle);
|
|
945
1133
|
}
|
|
946
1134
|
|
|
947
1135
|
return database.db_->Close();
|
|
@@ -969,7 +1157,7 @@ NAPI_METHOD(db_close) {
|
|
|
969
1157
|
return 0;
|
|
970
1158
|
}
|
|
971
1159
|
|
|
972
|
-
struct UpdatesNextWorker final : public
|
|
1160
|
+
struct UpdatesNextWorker final : public Worker {
|
|
973
1161
|
UpdatesNextWorker(napi_env env, Updates* updates, napi_value callback)
|
|
974
1162
|
: Worker(env, updates->database_, callback, "rocks_level.db.get"), updates_(updates) {
|
|
975
1163
|
database_->IncrementPriorityWork(env);
|
|
@@ -994,10 +1182,10 @@ struct UpdatesNextWorker final : public rocksdb::WriteBatch::Handler, public Wor
|
|
|
994
1182
|
|
|
995
1183
|
updates_->sequence_ = batch.sequence;
|
|
996
1184
|
|
|
997
|
-
|
|
998
|
-
|
|
1185
|
+
batch_ = std::move(batch.writeBatchPtr);
|
|
1186
|
+
count_ = batch_->Count();
|
|
999
1187
|
|
|
1000
|
-
return
|
|
1188
|
+
return rocksdb::Status::OK();
|
|
1001
1189
|
}
|
|
1002
1190
|
|
|
1003
1191
|
napi_status OnOk(napi_env env, napi_value callback) override {
|
|
@@ -1009,12 +1197,7 @@ struct UpdatesNextWorker final : public rocksdb::WriteBatch::Handler, public Wor
|
|
|
1009
1197
|
return CallFunction(env, callback, 1, argv);
|
|
1010
1198
|
}
|
|
1011
1199
|
|
|
1012
|
-
NAPI_STATUS_RETURN(
|
|
1013
|
-
for (size_t idx = 0; idx < cache_.size(); idx++) {
|
|
1014
|
-
napi_value val;
|
|
1015
|
-
NAPI_STATUS_RETURN(Convert(env, cache_[idx], false, val));
|
|
1016
|
-
NAPI_STATUS_RETURN(napi_set_element(env, argv[1], idx, val));
|
|
1017
|
-
}
|
|
1200
|
+
NAPI_STATUS_RETURN(updates_->Iterate(env, *batch_, &argv[1]));
|
|
1018
1201
|
|
|
1019
1202
|
NAPI_STATUS_RETURN(napi_create_int64(env, updates_->sequence_, &argv[2]));
|
|
1020
1203
|
|
|
@@ -1030,110 +1213,9 @@ struct UpdatesNextWorker final : public rocksdb::WriteBatch::Handler, public Wor
|
|
|
1030
1213
|
Worker::Destroy(env);
|
|
1031
1214
|
}
|
|
1032
1215
|
|
|
1033
|
-
std::optional<std::string> GetColumnName(uint32_t column_family_id) {
|
|
1034
|
-
if (column_family_id == 0) {
|
|
1035
|
-
return "default";
|
|
1036
|
-
}
|
|
1037
|
-
auto columns = database_->columns_;
|
|
1038
|
-
auto columnIt = std::find_if(columns.begin(), columns.end(),
|
|
1039
|
-
[&](const auto& handle) { return handle->GetID() == column_family_id; });
|
|
1040
|
-
return columnIt == columns.end() ? std::nullopt : std::optional<std::string>((*columnIt)->GetName());
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
rocksdb::Status PutCF(uint32_t column_family_id, const rocksdb::Slice& key, const rocksdb::Slice& value) override {
|
|
1044
|
-
if (updates_->column_ && updates_->column_->GetID() != column_family_id) {
|
|
1045
|
-
return rocksdb::Status::OK();
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
cache_.emplace_back("put");
|
|
1049
|
-
|
|
1050
|
-
if (updates_->keys_) {
|
|
1051
|
-
cache_.emplace_back(key.ToStringView());
|
|
1052
|
-
} else {
|
|
1053
|
-
cache_.emplace_back(std::nullopt);
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
if (updates_->values_) {
|
|
1057
|
-
cache_.emplace_back(value.ToStringView());
|
|
1058
|
-
} else {
|
|
1059
|
-
cache_.emplace_back(std::nullopt);
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
if (!updates_->column_) {
|
|
1063
|
-
cache_.emplace_back(GetColumnName(column_family_id));
|
|
1064
|
-
} else {
|
|
1065
|
-
cache_.emplace_back(std::nullopt);
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
return rocksdb::Status::OK();
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
rocksdb::Status DeleteCF(uint32_t column_family_id, const rocksdb::Slice& key) override {
|
|
1072
|
-
if (updates_->column_ && updates_->column_->GetID() != column_family_id) {
|
|
1073
|
-
return rocksdb::Status::OK();
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
cache_.emplace_back("del");
|
|
1077
|
-
|
|
1078
|
-
if (updates_->keys_) {
|
|
1079
|
-
cache_.emplace_back(key.ToStringView());
|
|
1080
|
-
} else {
|
|
1081
|
-
cache_.emplace_back(std::nullopt);
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
cache_.emplace_back(std::nullopt);
|
|
1085
|
-
|
|
1086
|
-
if (!updates_->column_) {
|
|
1087
|
-
cache_.emplace_back(GetColumnName(column_family_id));
|
|
1088
|
-
} else {
|
|
1089
|
-
cache_.emplace_back(std::nullopt);
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
return rocksdb::Status::OK();
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
|
-
rocksdb::Status MergeCF(uint32_t column_family_id, const rocksdb::Slice& key, const rocksdb::Slice& value) override {
|
|
1096
|
-
if (updates_->column_ && updates_->column_->GetID() != column_family_id) {
|
|
1097
|
-
return rocksdb::Status::OK();
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
cache_.emplace_back("merge");
|
|
1101
|
-
|
|
1102
|
-
if (updates_->keys_) {
|
|
1103
|
-
cache_.emplace_back(key.ToStringView());
|
|
1104
|
-
} else {
|
|
1105
|
-
cache_.emplace_back(std::nullopt);
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
if (updates_->values_) {
|
|
1109
|
-
cache_.emplace_back(value.ToStringView());
|
|
1110
|
-
} else {
|
|
1111
|
-
cache_.emplace_back(std::nullopt);
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
|
-
if (!updates_->column_) {
|
|
1115
|
-
cache_.emplace_back(GetColumnName(column_family_id));
|
|
1116
|
-
} else {
|
|
1117
|
-
cache_.emplace_back(std::nullopt);
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
return rocksdb::Status::OK();
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
void LogData(const rocksdb::Slice& data) override {
|
|
1124
|
-
if (updates_->data_) {
|
|
1125
|
-
cache_.emplace_back("data");
|
|
1126
|
-
cache_.emplace_back(std::nullopt);
|
|
1127
|
-
cache_.emplace_back(data.ToStringView());
|
|
1128
|
-
cache_.emplace_back(std::nullopt);
|
|
1129
|
-
}
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
|
-
bool Continue() override { return true; }
|
|
1133
|
-
|
|
1134
1216
|
private:
|
|
1135
1217
|
int64_t count_ = -1;
|
|
1136
|
-
std::
|
|
1218
|
+
std::unique_ptr<rocksdb::WriteBatch> batch_;
|
|
1137
1219
|
Updates* updates_;
|
|
1138
1220
|
};
|
|
1139
1221
|
|
|
@@ -1163,11 +1245,13 @@ NAPI_METHOD(updates_init) {
|
|
|
1163
1245
|
NAPI_STATUS_THROWS(napi_get_named_property(env, argv[1], "data", &dataProperty));
|
|
1164
1246
|
NAPI_STATUS_THROWS(napi_get_value_bool(env, dataProperty, &data));
|
|
1165
1247
|
|
|
1166
|
-
|
|
1248
|
+
const bool keyAsBuffer = EncodingIsBuffer(env, argv[1], "keyEncoding");
|
|
1249
|
+
const bool valueAsBuffer = EncodingIsBuffer(env, argv[1], "valueEncoding");
|
|
1250
|
+
|
|
1167
1251
|
rocksdb::ColumnFamilyHandle* column;
|
|
1168
|
-
NAPI_STATUS_THROWS(GetColumnFamily(
|
|
1252
|
+
NAPI_STATUS_THROWS(GetColumnFamily(nullptr, env, argv[1], &column));
|
|
1169
1253
|
|
|
1170
|
-
auto updates = std::make_unique<Updates>(database, since, keys, values, data, column);
|
|
1254
|
+
auto updates = std::make_unique<Updates>(database, since, keys, values, data, column, keyAsBuffer, valueAsBuffer);
|
|
1171
1255
|
|
|
1172
1256
|
napi_value result;
|
|
1173
1257
|
NAPI_STATUS_THROWS(napi_create_external(env, updates.get(), Finalize<Updates>, updates.get(), &result));
|
|
@@ -1203,102 +1287,6 @@ NAPI_METHOD(updates_close) {
|
|
|
1203
1287
|
return 0;
|
|
1204
1288
|
}
|
|
1205
1289
|
|
|
1206
|
-
NAPI_METHOD(db_put) {
|
|
1207
|
-
NAPI_ARGV(4);
|
|
1208
|
-
|
|
1209
|
-
Database* database;
|
|
1210
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
|
|
1211
|
-
|
|
1212
|
-
rocksdb::PinnableSlice key;
|
|
1213
|
-
NAPI_STATUS_THROWS(ToString(env, argv[1], key));
|
|
1214
|
-
|
|
1215
|
-
rocksdb::PinnableSlice val;
|
|
1216
|
-
NAPI_STATUS_THROWS(ToString(env, argv[2], val));
|
|
1217
|
-
|
|
1218
|
-
rocksdb::ColumnFamilyHandle* column;
|
|
1219
|
-
NAPI_STATUS_THROWS(GetColumnFamily(database, env, argv[3], &column));
|
|
1220
|
-
|
|
1221
|
-
rocksdb::WriteOptions writeOptions;
|
|
1222
|
-
ROCKS_STATUS_THROWS(database->db_->Put(writeOptions, column, key, val));
|
|
1223
|
-
|
|
1224
|
-
return 0;
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
struct GetWorker final : public Worker {
|
|
1228
|
-
GetWorker(napi_env env,
|
|
1229
|
-
Database* database,
|
|
1230
|
-
rocksdb::ColumnFamilyHandle* column,
|
|
1231
|
-
napi_value callback,
|
|
1232
|
-
const std::string& key,
|
|
1233
|
-
const bool asBuffer,
|
|
1234
|
-
const bool fillCache)
|
|
1235
|
-
: Worker(env, database, callback, "rocks_level.db.get"),
|
|
1236
|
-
column_(column),
|
|
1237
|
-
key_(key),
|
|
1238
|
-
asBuffer_(asBuffer),
|
|
1239
|
-
fillCache_(fillCache),
|
|
1240
|
-
snapshot_(database_->db_->GetSnapshot(),
|
|
1241
|
-
[this](const rocksdb::Snapshot* ptr) { database_->db_->ReleaseSnapshot(ptr); }) {
|
|
1242
|
-
database_->IncrementPriorityWork(env);
|
|
1243
|
-
}
|
|
1244
|
-
|
|
1245
|
-
rocksdb::Status Execute(Database& database) override {
|
|
1246
|
-
rocksdb::ReadOptions readOptions;
|
|
1247
|
-
readOptions.fill_cache = fillCache_;
|
|
1248
|
-
readOptions.snapshot = snapshot_.get();
|
|
1249
|
-
|
|
1250
|
-
auto status = database.db_->Get(readOptions, column_, key_, &value_);
|
|
1251
|
-
|
|
1252
|
-
key_.clear();
|
|
1253
|
-
snapshot_ = nullptr;
|
|
1254
|
-
|
|
1255
|
-
return status;
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
napi_status OnOk(napi_env env, napi_value callback) override {
|
|
1259
|
-
napi_value argv[2];
|
|
1260
|
-
NAPI_STATUS_RETURN(napi_get_null(env, &argv[0]));
|
|
1261
|
-
|
|
1262
|
-
NAPI_STATUS_RETURN(Convert(env, &value_, asBuffer_, argv[1]));
|
|
1263
|
-
|
|
1264
|
-
return CallFunction(env, callback, 2, argv);
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
void Destroy(napi_env env) override {
|
|
1268
|
-
database_->DecrementPriorityWork(env);
|
|
1269
|
-
Worker::Destroy(env);
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
private:
|
|
1273
|
-
rocksdb::ColumnFamilyHandle* column_;
|
|
1274
|
-
std::string key_;
|
|
1275
|
-
rocksdb::PinnableSlice value_;
|
|
1276
|
-
const bool asBuffer_;
|
|
1277
|
-
const bool fillCache_;
|
|
1278
|
-
std::shared_ptr<const rocksdb::Snapshot> snapshot_;
|
|
1279
|
-
};
|
|
1280
|
-
|
|
1281
|
-
NAPI_METHOD(db_get) {
|
|
1282
|
-
NAPI_ARGV(4);
|
|
1283
|
-
|
|
1284
|
-
Database* database;
|
|
1285
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
|
|
1286
|
-
|
|
1287
|
-
std::string key;
|
|
1288
|
-
NAPI_STATUS_THROWS(ToString(env, argv[1], key));
|
|
1289
|
-
|
|
1290
|
-
const auto asBuffer = EncodingIsBuffer(env, argv[2], "valueEncoding");
|
|
1291
|
-
const auto fillCache = BooleanProperty(env, argv[2], "fillCache").value_or(true);
|
|
1292
|
-
|
|
1293
|
-
rocksdb::ColumnFamilyHandle* column;
|
|
1294
|
-
NAPI_STATUS_THROWS(GetColumnFamily(database, env, argv[2], &column));
|
|
1295
|
-
|
|
1296
|
-
auto worker = new GetWorker(env, database, column, argv[3], key, asBuffer, fillCache);
|
|
1297
|
-
worker->Queue(env);
|
|
1298
|
-
|
|
1299
|
-
return 0;
|
|
1300
|
-
}
|
|
1301
|
-
|
|
1302
1290
|
struct GetManyWorker final : public Worker {
|
|
1303
1291
|
GetManyWorker(napi_env env,
|
|
1304
1292
|
Database* database,
|
|
@@ -1388,50 +1376,6 @@ struct GetManyWorker final : public Worker {
|
|
|
1388
1376
|
const rocksdb::Snapshot* snapshot_;
|
|
1389
1377
|
};
|
|
1390
1378
|
|
|
1391
|
-
typedef std::vector<std::string> Vector;
|
|
1392
|
-
|
|
1393
|
-
NAPI_METHOD(vector_init) {
|
|
1394
|
-
auto vector = new Vector();
|
|
1395
|
-
|
|
1396
|
-
napi_value result;
|
|
1397
|
-
NAPI_STATUS_THROWS(napi_create_external(env, vector, Finalize<Vector>, vector, &result));
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
NAPI_METHOD(vector_push) {
|
|
1401
|
-
NAPI_ARGV(2);
|
|
1402
|
-
|
|
1403
|
-
Vector* vector;
|
|
1404
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&vector)));
|
|
1405
|
-
|
|
1406
|
-
std::string value;
|
|
1407
|
-
NAPI_STATUS_THROWS(ToString(env, argv[1], value));
|
|
1408
|
-
|
|
1409
|
-
vector->push_back(std::move(value));
|
|
1410
|
-
}
|
|
1411
|
-
|
|
1412
|
-
NAPI_METHOD(db_get_many2) {
|
|
1413
|
-
NAPI_ARGV(4);
|
|
1414
|
-
|
|
1415
|
-
Database* database;
|
|
1416
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
|
|
1417
|
-
|
|
1418
|
-
Vector* vector;
|
|
1419
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[1], reinterpret_cast<void**>(&vector)));
|
|
1420
|
-
|
|
1421
|
-
const bool asBuffer = EncodingIsBuffer(env, argv[2], "valueEncoding");
|
|
1422
|
-
const bool fillCache = BooleanProperty(env, argv[2], "fillCache").value_or(true);
|
|
1423
|
-
const bool ignoreRangeDeletions = BooleanProperty(env, argv[2], "ignoreRangeDeletions").value_or(false);
|
|
1424
|
-
|
|
1425
|
-
rocksdb::ColumnFamilyHandle* column;
|
|
1426
|
-
NAPI_STATUS_THROWS(GetColumnFamily(database, env, argv[2], &column));
|
|
1427
|
-
|
|
1428
|
-
auto worker =
|
|
1429
|
-
new GetManyWorker(env, database, column, std::move(*vector), argv[3], asBuffer, fillCache, ignoreRangeDeletions);
|
|
1430
|
-
worker->Queue(env);
|
|
1431
|
-
|
|
1432
|
-
return 0;
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
1379
|
NAPI_METHOD(db_get_many) {
|
|
1436
1380
|
NAPI_ARGV(4);
|
|
1437
1381
|
|
|
@@ -1465,24 +1409,6 @@ NAPI_METHOD(db_get_many) {
|
|
|
1465
1409
|
return 0;
|
|
1466
1410
|
}
|
|
1467
1411
|
|
|
1468
|
-
NAPI_METHOD(db_del) {
|
|
1469
|
-
NAPI_ARGV(3);
|
|
1470
|
-
|
|
1471
|
-
Database* database;
|
|
1472
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
|
|
1473
|
-
|
|
1474
|
-
rocksdb::PinnableSlice key;
|
|
1475
|
-
NAPI_STATUS_THROWS(ToString(env, argv[1], key));
|
|
1476
|
-
|
|
1477
|
-
rocksdb::ColumnFamilyHandle* column;
|
|
1478
|
-
NAPI_STATUS_THROWS(GetColumnFamily(database, env, argv[2], &column));
|
|
1479
|
-
|
|
1480
|
-
rocksdb::WriteOptions writeOptions;
|
|
1481
|
-
ROCKS_STATUS_THROWS(database->db_->Delete(writeOptions, column, key));
|
|
1482
|
-
|
|
1483
|
-
return 0;
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
1412
|
NAPI_METHOD(db_clear) {
|
|
1487
1413
|
NAPI_ARGV(2);
|
|
1488
1414
|
|
|
@@ -1851,11 +1777,6 @@ NAPI_METHOD(batch_do) {
|
|
|
1851
1777
|
}
|
|
1852
1778
|
|
|
1853
1779
|
NAPI_METHOD(batch_init) {
|
|
1854
|
-
NAPI_ARGV(1);
|
|
1855
|
-
|
|
1856
|
-
Database* database;
|
|
1857
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
|
|
1858
|
-
|
|
1859
1780
|
auto batch = new rocksdb::WriteBatch();
|
|
1860
1781
|
|
|
1861
1782
|
napi_value result;
|
|
@@ -1865,53 +1786,79 @@ NAPI_METHOD(batch_init) {
|
|
|
1865
1786
|
}
|
|
1866
1787
|
|
|
1867
1788
|
NAPI_METHOD(batch_put) {
|
|
1868
|
-
NAPI_ARGV(
|
|
1869
|
-
|
|
1870
|
-
Database* database;
|
|
1871
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
|
|
1789
|
+
NAPI_ARGV(4);
|
|
1872
1790
|
|
|
1873
1791
|
rocksdb::WriteBatch* batch;
|
|
1874
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[
|
|
1792
|
+
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], (void**)(&batch)));
|
|
1875
1793
|
|
|
1876
1794
|
rocksdb::PinnableSlice key;
|
|
1877
|
-
NAPI_STATUS_THROWS(ToString(env, argv[
|
|
1795
|
+
NAPI_STATUS_THROWS(ToString(env, argv[1], key));
|
|
1878
1796
|
|
|
1879
1797
|
rocksdb::PinnableSlice val;
|
|
1880
|
-
NAPI_STATUS_THROWS(ToString(env, argv[
|
|
1798
|
+
NAPI_STATUS_THROWS(ToString(env, argv[2], val));
|
|
1881
1799
|
|
|
1882
1800
|
rocksdb::ColumnFamilyHandle* column;
|
|
1883
|
-
NAPI_STATUS_THROWS(GetColumnFamily(
|
|
1801
|
+
NAPI_STATUS_THROWS(GetColumnFamily(nullptr, env, argv[3], &column));
|
|
1884
1802
|
|
|
1885
|
-
|
|
1803
|
+
if (column) {
|
|
1804
|
+
ROCKS_STATUS_THROWS(batch->Put(column, key, val));
|
|
1805
|
+
} else {
|
|
1806
|
+
ROCKS_STATUS_THROWS(batch->Put(key, val));
|
|
1807
|
+
}
|
|
1886
1808
|
|
|
1887
1809
|
return 0;
|
|
1888
1810
|
}
|
|
1889
1811
|
|
|
1890
1812
|
NAPI_METHOD(batch_del) {
|
|
1891
|
-
NAPI_ARGV(
|
|
1813
|
+
NAPI_ARGV(3);
|
|
1892
1814
|
|
|
1893
|
-
|
|
1894
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&
|
|
1815
|
+
rocksdb::WriteBatch* batch;
|
|
1816
|
+
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&batch)));
|
|
1817
|
+
|
|
1818
|
+
rocksdb::PinnableSlice key;
|
|
1819
|
+
NAPI_STATUS_THROWS(ToString(env, argv[1], key));
|
|
1820
|
+
|
|
1821
|
+
rocksdb::ColumnFamilyHandle* column;
|
|
1822
|
+
NAPI_STATUS_THROWS(GetColumnFamily(nullptr, env, argv[2], &column));
|
|
1823
|
+
|
|
1824
|
+
if (column) {
|
|
1825
|
+
ROCKS_STATUS_THROWS(batch->Delete(column, key));
|
|
1826
|
+
} else {
|
|
1827
|
+
ROCKS_STATUS_THROWS(batch->Delete(key));
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
return 0;
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
NAPI_METHOD(batch_merge) {
|
|
1834
|
+
NAPI_ARGV(4);
|
|
1895
1835
|
|
|
1896
1836
|
rocksdb::WriteBatch* batch;
|
|
1897
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[
|
|
1837
|
+
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], (void**)(&batch)));
|
|
1898
1838
|
|
|
1899
1839
|
rocksdb::PinnableSlice key;
|
|
1900
|
-
NAPI_STATUS_THROWS(ToString(env, argv[
|
|
1840
|
+
NAPI_STATUS_THROWS(ToString(env, argv[1], key));
|
|
1841
|
+
|
|
1842
|
+
rocksdb::PinnableSlice val;
|
|
1843
|
+
NAPI_STATUS_THROWS(ToString(env, argv[2], val));
|
|
1901
1844
|
|
|
1902
1845
|
rocksdb::ColumnFamilyHandle* column;
|
|
1903
|
-
NAPI_STATUS_THROWS(GetColumnFamily(
|
|
1846
|
+
NAPI_STATUS_THROWS(GetColumnFamily(nullptr, env, argv[3], &column));
|
|
1904
1847
|
|
|
1905
|
-
|
|
1848
|
+
if (column) {
|
|
1849
|
+
ROCKS_STATUS_THROWS(batch->Merge(column, key, val));
|
|
1850
|
+
} else {
|
|
1851
|
+
ROCKS_STATUS_THROWS(batch->Merge(key, val));
|
|
1852
|
+
}
|
|
1906
1853
|
|
|
1907
1854
|
return 0;
|
|
1908
1855
|
}
|
|
1909
1856
|
|
|
1910
1857
|
NAPI_METHOD(batch_clear) {
|
|
1911
|
-
NAPI_ARGV(
|
|
1858
|
+
NAPI_ARGV(1);
|
|
1912
1859
|
|
|
1913
1860
|
rocksdb::WriteBatch* batch;
|
|
1914
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[
|
|
1861
|
+
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&batch)));
|
|
1915
1862
|
|
|
1916
1863
|
batch->Clear();
|
|
1917
1864
|
|
|
@@ -1934,53 +1881,65 @@ NAPI_METHOD(batch_write) {
|
|
|
1934
1881
|
}
|
|
1935
1882
|
|
|
1936
1883
|
NAPI_METHOD(batch_put_log_data) {
|
|
1937
|
-
NAPI_ARGV(
|
|
1938
|
-
|
|
1939
|
-
Database* database;
|
|
1940
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
|
|
1884
|
+
NAPI_ARGV(3);
|
|
1941
1885
|
|
|
1942
1886
|
rocksdb::WriteBatch* batch;
|
|
1943
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[
|
|
1887
|
+
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&batch)));
|
|
1944
1888
|
|
|
1945
1889
|
rocksdb::PinnableSlice logData;
|
|
1946
|
-
NAPI_STATUS_THROWS(ToString(env, argv[
|
|
1890
|
+
NAPI_STATUS_THROWS(ToString(env, argv[1], logData));
|
|
1947
1891
|
|
|
1948
1892
|
ROCKS_STATUS_THROWS(batch->PutLogData(logData));
|
|
1949
1893
|
|
|
1950
1894
|
return 0;
|
|
1951
1895
|
}
|
|
1952
1896
|
|
|
1953
|
-
NAPI_METHOD(
|
|
1954
|
-
NAPI_ARGV(
|
|
1897
|
+
NAPI_METHOD(batch_count) {
|
|
1898
|
+
NAPI_ARGV(1);
|
|
1899
|
+
|
|
1900
|
+
rocksdb::WriteBatch* batch;
|
|
1901
|
+
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&batch)));
|
|
1902
|
+
|
|
1903
|
+
napi_value result;
|
|
1904
|
+
NAPI_STATUS_THROWS(napi_create_int64(env, batch->Count(), &result));
|
|
1905
|
+
|
|
1906
|
+
return result;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
NAPI_METHOD(batch_iterate) {
|
|
1910
|
+
NAPI_ARGV(3);
|
|
1955
1911
|
|
|
1956
1912
|
Database* database;
|
|
1957
1913
|
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
|
|
1958
1914
|
|
|
1959
1915
|
rocksdb::WriteBatch* batch;
|
|
1960
|
-
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[1],
|
|
1961
|
-
|
|
1962
|
-
rocksdb::PinnableSlice key;
|
|
1963
|
-
NAPI_STATUS_THROWS(ToString(env, argv[2], key));
|
|
1964
|
-
|
|
1965
|
-
rocksdb::PinnableSlice val;
|
|
1966
|
-
NAPI_STATUS_THROWS(ToString(env, argv[3], val));
|
|
1916
|
+
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[1], reinterpret_cast<void**>(&batch)));
|
|
1967
1917
|
|
|
1968
|
-
|
|
1969
|
-
|
|
1918
|
+
napi_value keysProperty;
|
|
1919
|
+
bool keys;
|
|
1920
|
+
NAPI_STATUS_THROWS(napi_get_named_property(env, argv[2], "keys", &keysProperty));
|
|
1921
|
+
NAPI_STATUS_THROWS(napi_get_value_bool(env, keysProperty, &keys));
|
|
1970
1922
|
|
|
1971
|
-
|
|
1923
|
+
napi_value valuesProperty;
|
|
1924
|
+
bool values;
|
|
1925
|
+
NAPI_STATUS_THROWS(napi_get_named_property(env, argv[2], "values", &valuesProperty));
|
|
1926
|
+
NAPI_STATUS_THROWS(napi_get_value_bool(env, valuesProperty, &values));
|
|
1972
1927
|
|
|
1973
|
-
|
|
1974
|
-
|
|
1928
|
+
napi_value dataProperty;
|
|
1929
|
+
bool data;
|
|
1930
|
+
NAPI_STATUS_THROWS(napi_get_named_property(env, argv[2], "data", &dataProperty));
|
|
1931
|
+
NAPI_STATUS_THROWS(napi_get_value_bool(env, dataProperty, &data));
|
|
1975
1932
|
|
|
1976
|
-
|
|
1977
|
-
|
|
1933
|
+
const bool keyAsBuffer = EncodingIsBuffer(env, argv[1], "keyEncoding");
|
|
1934
|
+
const bool valueAsBuffer = EncodingIsBuffer(env, argv[1], "valueEncoding");
|
|
1978
1935
|
|
|
1979
|
-
rocksdb::
|
|
1980
|
-
NAPI_STATUS_THROWS(
|
|
1936
|
+
rocksdb::ColumnFamilyHandle* column;
|
|
1937
|
+
NAPI_STATUS_THROWS(GetColumnFamily(nullptr, env, argv[2], &column));
|
|
1981
1938
|
|
|
1982
1939
|
napi_value result;
|
|
1983
|
-
|
|
1940
|
+
BatchIterator iterator(nullptr, keys, values, data, column, keyAsBuffer, valueAsBuffer);
|
|
1941
|
+
|
|
1942
|
+
NAPI_STATUS_THROWS(iterator.Iterate(env, *batch, &result));
|
|
1984
1943
|
|
|
1985
1944
|
return result;
|
|
1986
1945
|
}
|
|
@@ -2065,10 +2024,7 @@ NAPI_INIT() {
|
|
|
2065
2024
|
NAPI_EXPORT_FUNCTION(db_init);
|
|
2066
2025
|
NAPI_EXPORT_FUNCTION(db_open);
|
|
2067
2026
|
NAPI_EXPORT_FUNCTION(db_close);
|
|
2068
|
-
NAPI_EXPORT_FUNCTION(db_put);
|
|
2069
|
-
NAPI_EXPORT_FUNCTION(db_get);
|
|
2070
2027
|
NAPI_EXPORT_FUNCTION(db_get_many);
|
|
2071
|
-
NAPI_EXPORT_FUNCTION(db_del);
|
|
2072
2028
|
NAPI_EXPORT_FUNCTION(db_clear);
|
|
2073
2029
|
NAPI_EXPORT_FUNCTION(db_get_property);
|
|
2074
2030
|
NAPI_EXPORT_FUNCTION(db_get_latest_sequence);
|
|
@@ -2096,8 +2052,5 @@ NAPI_INIT() {
|
|
|
2096
2052
|
NAPI_EXPORT_FUNCTION(batch_put_log_data);
|
|
2097
2053
|
NAPI_EXPORT_FUNCTION(batch_merge);
|
|
2098
2054
|
NAPI_EXPORT_FUNCTION(batch_count);
|
|
2099
|
-
|
|
2100
|
-
NAPI_EXPORT_FUNCTION(vector_init);
|
|
2101
|
-
NAPI_EXPORT_FUNCTION(vector_push);
|
|
2102
|
-
NAPI_EXPORT_FUNCTION(db_get_many2);
|
|
2055
|
+
NAPI_EXPORT_FUNCTION(batch_iterate);
|
|
2103
2056
|
}
|
package/chained-batch.js
CHANGED
|
@@ -2,55 +2,104 @@
|
|
|
2
2
|
|
|
3
3
|
const { AbstractChainedBatch } = require('abstract-level')
|
|
4
4
|
const binding = require('./binding')
|
|
5
|
+
const ModuleError = require('module-error')
|
|
6
|
+
const kWrite = Symbol('write')
|
|
7
|
+
const kBatchContext = Symbol('batchContext')
|
|
8
|
+
const kDbContext = Symbol('dbContext')
|
|
5
9
|
|
|
6
|
-
const
|
|
7
|
-
const
|
|
10
|
+
const NOOP = () => {}
|
|
11
|
+
const EMPTY = {}
|
|
8
12
|
|
|
9
13
|
class ChainedBatch extends AbstractChainedBatch {
|
|
10
|
-
constructor (db, context) {
|
|
14
|
+
constructor (db, context, write) {
|
|
11
15
|
super(db)
|
|
12
16
|
|
|
17
|
+
this[kWrite] = write
|
|
13
18
|
this[kDbContext] = context
|
|
14
|
-
this[kBatchContext] = binding.batch_init(
|
|
19
|
+
this[kBatchContext] = binding.batch_init()
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
_put (key, value, options) {
|
|
18
|
-
|
|
23
|
+
if (key === null || key === undefined) {
|
|
24
|
+
throw new ModuleError('Key cannot be null or undefined', {
|
|
25
|
+
code: 'LEVEL_INVALID_KEY'
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (value === null || value === undefined) {
|
|
30
|
+
throw new ModuleError('value cannot be null or undefined', {
|
|
31
|
+
code: 'LEVEL_INVALID_VALUE'
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
binding.batch_put(this[kBatchContext], key, value, options ?? EMPTY)
|
|
19
36
|
}
|
|
20
37
|
|
|
21
38
|
_del (key, options) {
|
|
22
|
-
|
|
39
|
+
if (key === null || key === undefined) {
|
|
40
|
+
throw new ModuleError('Key cannot be null or undefined', {
|
|
41
|
+
code: 'LEVEL_INVALID_KEY'
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
binding.batch_del(this[kBatchContext], key, options ?? EMPTY)
|
|
23
46
|
}
|
|
24
47
|
|
|
25
48
|
_clear () {
|
|
26
|
-
binding.batch_clear(this[
|
|
49
|
+
binding.batch_clear(this[kBatchContext])
|
|
27
50
|
}
|
|
28
51
|
|
|
29
52
|
_write (options, callback) {
|
|
30
|
-
|
|
31
|
-
binding.batch_write(this[kDbContext], this[kBatchContext], options)
|
|
32
|
-
process.nextTick(callback, null)
|
|
33
|
-
} catch (err) {
|
|
34
|
-
process.nextTick(callback, err)
|
|
35
|
-
}
|
|
53
|
+
this[kWrite](this, this[kBatchContext], options ?? EMPTY, callback ?? NOOP)
|
|
36
54
|
}
|
|
37
55
|
|
|
38
56
|
_close (callback) {
|
|
39
57
|
process.nextTick(callback)
|
|
40
58
|
}
|
|
41
59
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
60
|
+
get length () {
|
|
61
|
+
return binding.batch_count(this[kBatchContext])
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
_putLogData (value, options) {
|
|
65
|
+
if (value === null || value === undefined) {
|
|
66
|
+
throw new ModuleError('value cannot be null or undefined', {
|
|
67
|
+
code: 'LEVEL_INVALID_VALUE'
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
binding.batch_put_log_data(this[kBatchContext], value, options ?? EMPTY)
|
|
45
72
|
}
|
|
46
73
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
74
|
+
_merge (key, value, options) {
|
|
75
|
+
if (key === null || key === undefined) {
|
|
76
|
+
throw new ModuleError('Key cannot be null or undefined', {
|
|
77
|
+
code: 'LEVEL_INVALID_KEY'
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (value === null || value === undefined) {
|
|
82
|
+
throw new ModuleError('value cannot be null or undefined', {
|
|
83
|
+
code: 'LEVEL_INVALID_VALUE'
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
binding.batch_merge(this[kBatchContext], key, value, options ?? EMPTY)
|
|
50
88
|
}
|
|
51
89
|
|
|
52
|
-
|
|
53
|
-
|
|
90
|
+
* [Symbol.iterator] () {
|
|
91
|
+
const rows = binding.batch_iterate(this[kDbContext], this[kBatchContext], {
|
|
92
|
+
keys: true,
|
|
93
|
+
values: true,
|
|
94
|
+
data: true
|
|
95
|
+
})
|
|
96
|
+
for (let n = 0; n < rows.length; n += 4) {
|
|
97
|
+
yield {
|
|
98
|
+
type: rows[n + 0],
|
|
99
|
+
key: rows[n + 1],
|
|
100
|
+
value: rows[n + 2]
|
|
101
|
+
}
|
|
102
|
+
}
|
|
54
103
|
}
|
|
55
104
|
}
|
|
56
105
|
|
package/index.js
CHANGED
|
@@ -96,25 +96,41 @@ class RocksLevel extends AbstractLevel {
|
|
|
96
96
|
|
|
97
97
|
_put (key, value, options, callback) {
|
|
98
98
|
try {
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
const batch = this.batch()
|
|
100
|
+
batch.put(key, value, options)
|
|
101
|
+
batch.write(callback)
|
|
101
102
|
} catch (err) {
|
|
102
103
|
process.nextTick(callback, err)
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
_get (key, options, callback) {
|
|
107
|
-
|
|
108
|
+
this._getMany([key], options, (err, val) => {
|
|
109
|
+
if (err) {
|
|
110
|
+
callback(err)
|
|
111
|
+
} else if (val[0] === undefined) {
|
|
112
|
+
callback(Object.assign(new Error('not found'), {
|
|
113
|
+
code: 'LEVEL_NOT_FOUND'
|
|
114
|
+
}))
|
|
115
|
+
} else {
|
|
116
|
+
callback(null, val[0])
|
|
117
|
+
}
|
|
118
|
+
})
|
|
108
119
|
}
|
|
109
120
|
|
|
110
121
|
_getMany (keys, options, callback) {
|
|
111
|
-
|
|
122
|
+
try {
|
|
123
|
+
binding.db_get_many(this[kContext], keys, options, callback)
|
|
124
|
+
} catch (err) {
|
|
125
|
+
process.nextTick(callback, err)
|
|
126
|
+
}
|
|
112
127
|
}
|
|
113
128
|
|
|
114
129
|
_del (key, options, callback) {
|
|
115
130
|
try {
|
|
116
|
-
|
|
117
|
-
|
|
131
|
+
const batch = this.batch()
|
|
132
|
+
batch.del(key, options)
|
|
133
|
+
batch.write(callback)
|
|
118
134
|
} catch (err) {
|
|
119
135
|
process.nextTick(callback, err)
|
|
120
136
|
}
|
|
@@ -122,6 +138,7 @@ class RocksLevel extends AbstractLevel {
|
|
|
122
138
|
|
|
123
139
|
_clear (options, callback) {
|
|
124
140
|
try {
|
|
141
|
+
// TODO (fix): Use batch + DeleteRange...
|
|
125
142
|
binding.db_clear(this[kContext], options)
|
|
126
143
|
process.nextTick(callback, null)
|
|
127
144
|
} catch (err) {
|
|
@@ -130,7 +147,16 @@ class RocksLevel extends AbstractLevel {
|
|
|
130
147
|
}
|
|
131
148
|
|
|
132
149
|
_chainedBatch () {
|
|
133
|
-
return new ChainedBatch(this, this[kContext])
|
|
150
|
+
return new ChainedBatch(this, this[kContext], (batch, context, options, callback) => {
|
|
151
|
+
try {
|
|
152
|
+
const seq = this.sequence
|
|
153
|
+
binding.batch_write(this[kContext], context, options)
|
|
154
|
+
this.emit('write', batch, seq + 1)
|
|
155
|
+
process.nextTick(callback, null)
|
|
156
|
+
} catch (err) {
|
|
157
|
+
process.nextTick(callback, err)
|
|
158
|
+
}
|
|
159
|
+
})
|
|
134
160
|
}
|
|
135
161
|
|
|
136
162
|
_batch (operations, options, callback) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/rocksdb",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.45",
|
|
4
4
|
"description": "A low-level Node.js RocksDB binding",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"abstract-level": "^1.0.2",
|
|
15
|
-
"module-error": "^1.0.
|
|
15
|
+
"module-error": "^1.0.2",
|
|
16
16
|
"napi-macros": "~2.0.0",
|
|
17
17
|
"node-gyp-build": "^4.3.0"
|
|
18
18
|
},
|
|
Binary file
|