|
|
@ -35,303 +35,30 @@ class BaseDeltaIterator : public Iterator { |
|
|
|
public: |
|
|
|
public: |
|
|
|
BaseDeltaIterator(Iterator* base_iterator, WBWIIterator* delta_iterator, |
|
|
|
BaseDeltaIterator(Iterator* base_iterator, WBWIIterator* delta_iterator, |
|
|
|
const Comparator* comparator, |
|
|
|
const Comparator* comparator, |
|
|
|
const ReadOptions* read_options = nullptr) |
|
|
|
const ReadOptions* read_options = nullptr); |
|
|
|
: forward_(true), |
|
|
|
|
|
|
|
current_at_base_(true), |
|
|
|
|
|
|
|
equal_keys_(false), |
|
|
|
|
|
|
|
status_(Status::OK()), |
|
|
|
|
|
|
|
base_iterator_(base_iterator), |
|
|
|
|
|
|
|
delta_iterator_(delta_iterator), |
|
|
|
|
|
|
|
comparator_(comparator), |
|
|
|
|
|
|
|
iterate_upper_bound_(read_options ? read_options->iterate_upper_bound |
|
|
|
|
|
|
|
: nullptr) {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~BaseDeltaIterator() override {} |
|
|
|
~BaseDeltaIterator() override {} |
|
|
|
|
|
|
|
|
|
|
|
bool Valid() const override { |
|
|
|
bool Valid() const override; |
|
|
|
return status_.ok() ? (current_at_base_ ? BaseValid() : DeltaValid()) |
|
|
|
void SeekToFirst() override; |
|
|
|
: false; |
|
|
|
void SeekToLast() override; |
|
|
|
} |
|
|
|
void Seek(const Slice& k) override; |
|
|
|
|
|
|
|
void SeekForPrev(const Slice& k) override; |
|
|
|
void SeekToFirst() override { |
|
|
|
void Next() override; |
|
|
|
forward_ = true; |
|
|
|
void Prev() override; |
|
|
|
base_iterator_->SeekToFirst(); |
|
|
|
Slice key() const override; |
|
|
|
delta_iterator_->SeekToFirst(); |
|
|
|
Slice value() const override; |
|
|
|
UpdateCurrent(); |
|
|
|
Status status() const override; |
|
|
|
} |
|
|
|
void Invalidate(Status s); |
|
|
|
|
|
|
|
|
|
|
|
void SeekToLast() override { |
|
|
|
|
|
|
|
forward_ = false; |
|
|
|
|
|
|
|
base_iterator_->SeekToLast(); |
|
|
|
|
|
|
|
delta_iterator_->SeekToLast(); |
|
|
|
|
|
|
|
UpdateCurrent(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Seek(const Slice& k) override { |
|
|
|
|
|
|
|
forward_ = true; |
|
|
|
|
|
|
|
base_iterator_->Seek(k); |
|
|
|
|
|
|
|
delta_iterator_->Seek(k); |
|
|
|
|
|
|
|
UpdateCurrent(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void SeekForPrev(const Slice& k) override { |
|
|
|
|
|
|
|
forward_ = false; |
|
|
|
|
|
|
|
base_iterator_->SeekForPrev(k); |
|
|
|
|
|
|
|
delta_iterator_->SeekForPrev(k); |
|
|
|
|
|
|
|
UpdateCurrent(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Next() override { |
|
|
|
|
|
|
|
if (!Valid()) { |
|
|
|
|
|
|
|
status_ = Status::NotSupported("Next() on invalid iterator"); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!forward_) { |
|
|
|
|
|
|
|
// Need to change direction
|
|
|
|
|
|
|
|
// if our direction was backward and we're not equal, we have two states:
|
|
|
|
|
|
|
|
// * both iterators are valid: we're already in a good state (current
|
|
|
|
|
|
|
|
// shows to smaller)
|
|
|
|
|
|
|
|
// * only one iterator is valid: we need to advance that iterator
|
|
|
|
|
|
|
|
forward_ = true; |
|
|
|
|
|
|
|
equal_keys_ = false; |
|
|
|
|
|
|
|
if (!BaseValid()) { |
|
|
|
|
|
|
|
assert(DeltaValid()); |
|
|
|
|
|
|
|
base_iterator_->SeekToFirst(); |
|
|
|
|
|
|
|
} else if (!DeltaValid()) { |
|
|
|
|
|
|
|
delta_iterator_->SeekToFirst(); |
|
|
|
|
|
|
|
} else if (current_at_base_) { |
|
|
|
|
|
|
|
// Change delta from larger than base to smaller
|
|
|
|
|
|
|
|
AdvanceDelta(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// Change base from larger than delta to smaller
|
|
|
|
|
|
|
|
AdvanceBase(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (DeltaValid() && BaseValid()) { |
|
|
|
|
|
|
|
if (comparator_->Equal(delta_iterator_->Entry().key, |
|
|
|
|
|
|
|
base_iterator_->key())) { |
|
|
|
|
|
|
|
equal_keys_ = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Advance(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Prev() override { |
|
|
|
|
|
|
|
if (!Valid()) { |
|
|
|
|
|
|
|
status_ = Status::NotSupported("Prev() on invalid iterator"); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (forward_) { |
|
|
|
|
|
|
|
// Need to change direction
|
|
|
|
|
|
|
|
// if our direction was backward and we're not equal, we have two states:
|
|
|
|
|
|
|
|
// * both iterators are valid: we're already in a good state (current
|
|
|
|
|
|
|
|
// shows to smaller)
|
|
|
|
|
|
|
|
// * only one iterator is valid: we need to advance that iterator
|
|
|
|
|
|
|
|
forward_ = false; |
|
|
|
|
|
|
|
equal_keys_ = false; |
|
|
|
|
|
|
|
if (!BaseValid()) { |
|
|
|
|
|
|
|
assert(DeltaValid()); |
|
|
|
|
|
|
|
base_iterator_->SeekToLast(); |
|
|
|
|
|
|
|
} else if (!DeltaValid()) { |
|
|
|
|
|
|
|
delta_iterator_->SeekToLast(); |
|
|
|
|
|
|
|
} else if (current_at_base_) { |
|
|
|
|
|
|
|
// Change delta from less advanced than base to more advanced
|
|
|
|
|
|
|
|
AdvanceDelta(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// Change base from less advanced than delta to more advanced
|
|
|
|
|
|
|
|
AdvanceBase(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (DeltaValid() && BaseValid()) { |
|
|
|
|
|
|
|
if (comparator_->Equal(delta_iterator_->Entry().key, |
|
|
|
|
|
|
|
base_iterator_->key())) { |
|
|
|
|
|
|
|
equal_keys_ = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Advance(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Slice key() const override { |
|
|
|
|
|
|
|
return current_at_base_ ? base_iterator_->key() |
|
|
|
|
|
|
|
: delta_iterator_->Entry().key; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Slice value() const override { |
|
|
|
|
|
|
|
return current_at_base_ ? base_iterator_->value() |
|
|
|
|
|
|
|
: delta_iterator_->Entry().value; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status status() const override { |
|
|
|
|
|
|
|
if (!status_.ok()) { |
|
|
|
|
|
|
|
return status_; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!base_iterator_->status().ok()) { |
|
|
|
|
|
|
|
return base_iterator_->status(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return delta_iterator_->status(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Invalidate(Status s) { status_ = s; } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
private: |
|
|
|
void AssertInvariants() { |
|
|
|
void AssertInvariants(); |
|
|
|
#ifndef NDEBUG |
|
|
|
void Advance(); |
|
|
|
bool not_ok = false; |
|
|
|
void AdvanceDelta(); |
|
|
|
if (!base_iterator_->status().ok()) { |
|
|
|
void AdvanceBase(); |
|
|
|
assert(!base_iterator_->Valid()); |
|
|
|
bool BaseValid() const; |
|
|
|
not_ok = true; |
|
|
|
bool DeltaValid() const; |
|
|
|
} |
|
|
|
void UpdateCurrent(); |
|
|
|
if (!delta_iterator_->status().ok()) { |
|
|
|
|
|
|
|
assert(!delta_iterator_->Valid()); |
|
|
|
|
|
|
|
not_ok = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (not_ok) { |
|
|
|
|
|
|
|
assert(!Valid()); |
|
|
|
|
|
|
|
assert(!status().ok()); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!Valid()) { |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!BaseValid()) { |
|
|
|
|
|
|
|
assert(!current_at_base_ && delta_iterator_->Valid()); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!DeltaValid()) { |
|
|
|
|
|
|
|
assert(current_at_base_ && base_iterator_->Valid()); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// we don't support those yet
|
|
|
|
|
|
|
|
assert(delta_iterator_->Entry().type != kMergeRecord && |
|
|
|
|
|
|
|
delta_iterator_->Entry().type != kLogDataRecord); |
|
|
|
|
|
|
|
int compare = comparator_->Compare(delta_iterator_->Entry().key, |
|
|
|
|
|
|
|
base_iterator_->key()); |
|
|
|
|
|
|
|
if (forward_) { |
|
|
|
|
|
|
|
// current_at_base -> compare < 0
|
|
|
|
|
|
|
|
assert(!current_at_base_ || compare < 0); |
|
|
|
|
|
|
|
// !current_at_base -> compare <= 0
|
|
|
|
|
|
|
|
assert(current_at_base_ && compare >= 0); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// current_at_base -> compare > 0
|
|
|
|
|
|
|
|
assert(!current_at_base_ || compare > 0); |
|
|
|
|
|
|
|
// !current_at_base -> compare <= 0
|
|
|
|
|
|
|
|
assert(current_at_base_ && compare <= 0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// equal_keys_ <=> compare == 0
|
|
|
|
|
|
|
|
assert((equal_keys_ || compare != 0) && (!equal_keys_ || compare == 0)); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Advance() { |
|
|
|
|
|
|
|
if (equal_keys_) { |
|
|
|
|
|
|
|
assert(BaseValid() && DeltaValid()); |
|
|
|
|
|
|
|
AdvanceBase(); |
|
|
|
|
|
|
|
AdvanceDelta(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (current_at_base_) { |
|
|
|
|
|
|
|
assert(BaseValid()); |
|
|
|
|
|
|
|
AdvanceBase(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
assert(DeltaValid()); |
|
|
|
|
|
|
|
AdvanceDelta(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
UpdateCurrent(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void AdvanceDelta() { |
|
|
|
|
|
|
|
if (forward_) { |
|
|
|
|
|
|
|
delta_iterator_->Next(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
delta_iterator_->Prev(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
void AdvanceBase() { |
|
|
|
|
|
|
|
if (forward_) { |
|
|
|
|
|
|
|
base_iterator_->Next(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
base_iterator_->Prev(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
bool BaseValid() const { return base_iterator_->Valid(); } |
|
|
|
|
|
|
|
bool DeltaValid() const { return delta_iterator_->Valid(); } |
|
|
|
|
|
|
|
void UpdateCurrent() { |
|
|
|
|
|
|
|
// Suppress false positive clang analyzer warnings.
|
|
|
|
|
|
|
|
#ifndef __clang_analyzer__ |
|
|
|
|
|
|
|
status_ = Status::OK(); |
|
|
|
|
|
|
|
while (true) { |
|
|
|
|
|
|
|
WriteEntry delta_entry; |
|
|
|
|
|
|
|
if (DeltaValid()) { |
|
|
|
|
|
|
|
assert(delta_iterator_->status().ok()); |
|
|
|
|
|
|
|
delta_entry = delta_iterator_->Entry(); |
|
|
|
|
|
|
|
} else if (!delta_iterator_->status().ok()) { |
|
|
|
|
|
|
|
// Expose the error status and stop.
|
|
|
|
|
|
|
|
current_at_base_ = false; |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
equal_keys_ = false; |
|
|
|
|
|
|
|
if (!BaseValid()) { |
|
|
|
|
|
|
|
if (!base_iterator_->status().ok()) { |
|
|
|
|
|
|
|
// Expose the error status and stop.
|
|
|
|
|
|
|
|
current_at_base_ = true; |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Base has finished.
|
|
|
|
|
|
|
|
if (!DeltaValid()) { |
|
|
|
|
|
|
|
// Finished
|
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (iterate_upper_bound_) { |
|
|
|
|
|
|
|
if (comparator_->Compare(delta_entry.key, *iterate_upper_bound_) >= |
|
|
|
|
|
|
|
0) { |
|
|
|
|
|
|
|
// out of upper bound -> finished.
|
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (delta_entry.type == kDeleteRecord || |
|
|
|
|
|
|
|
delta_entry.type == kSingleDeleteRecord) { |
|
|
|
|
|
|
|
AdvanceDelta(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
current_at_base_ = false; |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if (!DeltaValid()) { |
|
|
|
|
|
|
|
// Delta has finished.
|
|
|
|
|
|
|
|
current_at_base_ = true; |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
int compare = |
|
|
|
|
|
|
|
(forward_ ? 1 : -1) * |
|
|
|
|
|
|
|
comparator_->Compare(delta_entry.key, base_iterator_->key()); |
|
|
|
|
|
|
|
if (compare <= 0) { // delta bigger or equal
|
|
|
|
|
|
|
|
if (compare == 0) { |
|
|
|
|
|
|
|
equal_keys_ = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (delta_entry.type != kDeleteRecord && |
|
|
|
|
|
|
|
delta_entry.type != kSingleDeleteRecord) { |
|
|
|
|
|
|
|
current_at_base_ = false; |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Delta is less advanced and is delete.
|
|
|
|
|
|
|
|
AdvanceDelta(); |
|
|
|
|
|
|
|
if (equal_keys_) { |
|
|
|
|
|
|
|
AdvanceBase(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
current_at_base_ = true; |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AssertInvariants(); |
|
|
|
|
|
|
|
#endif // __clang_analyzer__
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool forward_; |
|
|
|
bool forward_; |
|
|
|
bool current_at_base_; |
|
|
|
bool current_at_base_; |
|
|
|