@@ -467,7 +467,7 @@ struct Database {
467
467
}
468
468
}
469
469
470
- bool HasPriorityWork () {
470
+ bool HasPriorityWork () const {
471
471
return priorityWork_ > 0 ;
472
472
}
473
473
@@ -521,8 +521,7 @@ struct BaseIterator {
521
521
gt_(gt),
522
522
gte_(gte),
523
523
limit_(limit),
524
- count_(0 ),
525
- eof_(false ) {
524
+ count_(0 ) {
526
525
options_ = new leveldb::ReadOptions ();
527
526
options_->fill_cache = fillCache;
528
527
options_->snapshot = database->NewSnapshot ();
@@ -588,40 +587,22 @@ struct BaseIterator {
588
587
didSeek_ = true ;
589
588
590
589
if (OutOfRange (target)) {
591
- if (reverse_) {
592
- dbIterator_->SeekToFirst ();
593
- dbIterator_->Prev ();
594
- } else {
595
- dbIterator_->SeekToLast ();
596
- dbIterator_->Next ();
597
- }
598
-
599
- return ;
590
+ return SeekToEnd ();
600
591
}
601
592
602
593
dbIterator_->Seek (target);
603
594
604
595
if (dbIterator_->Valid ()) {
605
596
int cmp = dbIterator_->key ().compare (target);
606
- if (cmp > 0 && reverse_) {
607
- dbIterator_->Prev ();
608
- } else if (cmp < 0 && !reverse_) {
609
- dbIterator_->Next ();
597
+ if (reverse_ ? cmp > 0 : cmp < 0 ) {
598
+ Next ();
610
599
}
611
600
} else {
612
- if (reverse_) {
613
- dbIterator_->SeekToLast ();
614
- } else {
615
- dbIterator_->SeekToFirst ();
616
- }
601
+ SeekToFirst ();
617
602
if (dbIterator_->Valid ()) {
618
603
int cmp = dbIterator_->key ().compare (target);
619
- if (cmp > 0 && reverse_) {
620
- dbIterator_->SeekToFirst ();
621
- dbIterator_->Prev ();
622
- } else if (cmp < 0 && !reverse_) {
623
- dbIterator_->SeekToLast ();
624
- dbIterator_->Next ();
604
+ if (reverse_ ? cmp > 0 : cmp < 0 ) {
605
+ SeekToEnd ();
625
606
}
626
607
}
627
608
}
@@ -636,24 +617,34 @@ struct BaseIterator {
636
617
}
637
618
}
638
619
639
- bool ReadOne () {
640
- if (eof_ || !dbIterator_->Valid ()) {
641
- return false ;
642
- }
643
-
644
- if ((limit_ >= 0 && ++count_ > limit_) || OutOfRange (dbIterator_->key ())) {
645
- eof_ = true ;
646
- return false ;
647
- }
620
+ bool Valid () const {
621
+ return dbIterator_->Valid () && !OutOfRange (dbIterator_->key ());
622
+ }
648
623
649
- return true ;
624
+ bool Increment () {
625
+ return limit_ < 0 || ++count_ <= limit_;
650
626
}
651
627
652
- void Advance () {
628
+ void Next () {
653
629
if (reverse_) dbIterator_->Prev ();
654
630
else dbIterator_->Next ();
655
631
}
656
632
633
+ void SeekToFirst () {
634
+ if (reverse_) dbIterator_->SeekToLast ();
635
+ else dbIterator_->SeekToFirst ();
636
+ }
637
+
638
+ void SeekToLast () {
639
+ if (reverse_) dbIterator_->SeekToFirst ();
640
+ else dbIterator_->SeekToLast ();
641
+ }
642
+
643
+ void SeekToEnd () {
644
+ SeekToLast ();
645
+ Next ();
646
+ }
647
+
657
648
leveldb::Slice CurrentKey () const {
658
649
return dbIterator_->key ();
659
650
}
@@ -666,7 +657,13 @@ struct BaseIterator {
666
657
return dbIterator_->status ();
667
658
}
668
659
669
- bool OutOfRange (const leveldb::Slice& target) {
660
+ bool OutOfRange (const leveldb::Slice& target) const {
661
+ // TODO: benchmark to see if this is worth it
662
+ // if (upperBoundOnly && !reverse_) {
663
+ // return ((lt_ != NULL && target.compare(*lt_) >= 0) ||
664
+ // (lte_ != NULL && target.compare(*lte_) > 0));
665
+ // }
666
+
670
667
return ((lt_ != NULL && target.compare (*lt_) >= 0 ) ||
671
668
(lte_ != NULL && target.compare (*lte_) > 0 ) ||
672
669
(gt_ != NULL && target.compare (*gt_) <= 0 ) ||
@@ -686,7 +683,6 @@ struct BaseIterator {
686
683
std::string* gte_;
687
684
int limit_;
688
685
int count_;
689
- bool eof_;
690
686
leveldb::ReadOptions* options_;
691
687
};
692
688
@@ -734,33 +730,36 @@ struct Iterator final : public BaseIterator {
734
730
if (ref_ != NULL ) napi_delete_reference (env, ref_);
735
731
}
736
732
737
- bool ReadMany (uint32_t size, std::vector<std::pair<std::string, std::string>>& result) {
733
+ bool ReadMany (uint32_t size) {
734
+ cache_.clear ();
738
735
size_t bytesRead = 0 ;
739
736
740
- while (ReadOne ()) {
741
- std::string key, value;
737
+ while (true ) {
738
+ if (landed_) Next ();
739
+ if (!Valid () || !Increment ()) break ;
742
740
743
741
if (keys_) {
744
742
leveldb::Slice slice = CurrentKey ();
745
- key.assign (slice.data (), slice.size ());
746
- bytesRead += key.size ();
743
+ cache_.emplace_back (slice.data (), slice.size ());
744
+ bytesRead += slice.size ();
745
+ } else {
746
+ cache_.emplace_back (" " );
747
747
}
748
748
749
749
if (values_) {
750
750
leveldb::Slice slice = CurrentValue ();
751
- value.assign (slice.data (), slice.size ());
752
- bytesRead += value.size ();
751
+ cache_.emplace_back (slice.data (), slice.size ());
752
+ bytesRead += slice.size ();
753
+ } else {
754
+ cache_.emplace_back (" " );
753
755
}
754
756
755
- Advance ();
756
- result.push_back (std::make_pair (key, value));
757
-
758
757
if (!landed_) {
759
758
landed_ = true ;
760
759
return true ;
761
760
}
762
761
763
- if (bytesRead > highWaterMark_ || result .size () >= size) {
762
+ if (bytesRead > highWaterMark_ || cache_ .size () >= size * 2 ) {
764
763
return true ;
765
764
}
766
765
}
@@ -778,6 +777,7 @@ struct Iterator final : public BaseIterator {
778
777
bool nexting_;
779
778
bool isEnding_;
780
779
BaseWorker* endWorker_;
780
+ std::vector<std::string> cache_;
781
781
782
782
private:
783
783
napi_ref ref_;
@@ -1136,18 +1136,18 @@ struct ClearWorker final : public PriorityWorker {
1136
1136
std::string* gt,
1137
1137
std::string* gte)
1138
1138
: PriorityWorker(env, database, callback, " leveldown.db.clear" ) {
1139
- baseIterator_ = new BaseIterator (database, reverse, lt, lte, gt, gte, limit, false );
1139
+ iterator_ = new BaseIterator (database, reverse, lt, lte, gt, gte, limit, false );
1140
1140
writeOptions_ = new leveldb::WriteOptions ();
1141
1141
writeOptions_->sync = false ;
1142
1142
}
1143
1143
1144
1144
~ClearWorker () {
1145
- delete baseIterator_ ;
1145
+ delete iterator_ ;
1146
1146
delete writeOptions_;
1147
1147
}
1148
1148
1149
1149
void DoExecute () override {
1150
- baseIterator_ ->SeekToRange ();
1150
+ iterator_ ->SeekToRange ();
1151
1151
1152
1152
// TODO: add option
1153
1153
uint32_t hwm = 16 * 1024 ;
@@ -1156,14 +1156,14 @@ struct ClearWorker final : public PriorityWorker {
1156
1156
while (true ) {
1157
1157
size_t bytesRead = 0 ;
1158
1158
1159
- while (bytesRead < hwm && baseIterator_-> ReadOne ()) {
1160
- leveldb::Slice key = baseIterator_ ->CurrentKey ();
1159
+ while (bytesRead <= hwm && iterator_-> Valid () && iterator_-> Increment ()) {
1160
+ leveldb::Slice key = iterator_ ->CurrentKey ();
1161
1161
batch.Delete (key);
1162
1162
bytesRead += key.size ();
1163
- baseIterator_-> Advance ();
1163
+ iterator_-> Next ();
1164
1164
}
1165
1165
1166
- if (!SetStatus (baseIterator_ ->Status ()) || bytesRead == 0 ) {
1166
+ if (!SetStatus (iterator_ ->Status ()) || bytesRead == 0 ) {
1167
1167
break ;
1168
1168
}
1169
1169
@@ -1174,11 +1174,11 @@ struct ClearWorker final : public PriorityWorker {
1174
1174
batch.Clear ();
1175
1175
}
1176
1176
1177
- baseIterator_ ->End ();
1177
+ iterator_ ->End ();
1178
1178
}
1179
1179
1180
1180
private:
1181
- BaseIterator* baseIterator_ ;
1181
+ BaseIterator* iterator_ ;
1182
1182
leveldb::WriteOptions* writeOptions_;
1183
1183
};
1184
1184
@@ -1536,22 +1536,21 @@ struct NextWorker final : public BaseWorker {
1536
1536
1537
1537
// Limit the size of the cache to prevent starving the event loop
1538
1538
// in JS-land while we're recursively calling process.nextTick().
1539
- ok_ = iterator_->ReadMany (1000 , result_ );
1539
+ ok_ = iterator_->ReadMany (1000 );
1540
1540
1541
1541
if (!ok_) {
1542
1542
SetStatus (iterator_->Status ());
1543
1543
}
1544
1544
}
1545
1545
1546
1546
void HandleOKCallback (napi_env env, napi_value callback) override {
1547
- size_t arraySize = result_ .size () * 2 ;
1547
+ size_t arraySize = iterator_-> cache_ .size ();
1548
1548
napi_value jsArray;
1549
1549
napi_create_array_with_length (env, arraySize, &jsArray);
1550
1550
1551
- for (size_t idx = 0 ; idx < result_.size (); ++idx) {
1552
- std::pair<std::string, std::string> row = result_[idx];
1553
- std::string key = row.first ;
1554
- std::string value = row.second ;
1551
+ for (size_t idx = 0 ; idx < iterator_->cache_ .size (); idx += 2 ) {
1552
+ std::string key = iterator_->cache_ [idx];
1553
+ std::string value = iterator_->cache_ [idx + 1 ];
1555
1554
1556
1555
napi_value returnKey;
1557
1556
if (iterator_->keyAsBuffer_ ) {
@@ -1568,8 +1567,8 @@ struct NextWorker final : public BaseWorker {
1568
1567
}
1569
1568
1570
1569
// put the key & value in a descending order, so that they can be .pop:ed in javascript-land
1571
- napi_set_element (env, jsArray, static_cast <int >(arraySize - idx * 2 - 1 ), returnKey);
1572
- napi_set_element (env, jsArray, static_cast <int >(arraySize - idx * 2 - 2 ), returnValue);
1570
+ napi_set_element (env, jsArray, static_cast <int >(arraySize - idx - 1 ), returnKey);
1571
+ napi_set_element (env, jsArray, static_cast <int >(arraySize - idx - 2 ), returnValue);
1573
1572
}
1574
1573
1575
1574
napi_value argv[3 ];
@@ -1592,7 +1591,6 @@ struct NextWorker final : public BaseWorker {
1592
1591
}
1593
1592
1594
1593
Iterator* iterator_;
1595
- std::vector<std::pair<std::string, std::string> > result_;
1596
1594
bool ok_;
1597
1595
};
1598
1596
0 commit comments