update IterKey that can get user key and internal key explicitly
Summary: to void future bug that caused by the mix of userkey/internalkey Closes https://github.com/facebook/rocksdb/pull/2084 Differential Revision: D4825889 Pulled By: lightmark fbshipit-source-id: 28411db
This commit is contained in:
parent
e2c6c06366
commit
90cfd46458
@ -105,7 +105,7 @@ void CompactionIterator::Next() {
|
|||||||
assert(valid_key);
|
assert(valid_key);
|
||||||
// Keep current_key_ in sync.
|
// Keep current_key_ in sync.
|
||||||
current_key_.UpdateInternalKey(ikey_.sequence, ikey_.type);
|
current_key_.UpdateInternalKey(ikey_.sequence, ikey_.type);
|
||||||
key_ = current_key_.GetKey();
|
key_ = current_key_.GetInternalKey();
|
||||||
ikey_.user_key = current_key_.GetUserKey();
|
ikey_.user_key = current_key_.GetUserKey();
|
||||||
valid_ = true;
|
valid_ = true;
|
||||||
} else {
|
} else {
|
||||||
@ -151,7 +151,7 @@ void CompactionIterator::NextFromInput() {
|
|||||||
status_ = Status::Corruption("Corrupted internal key not expected.");
|
status_ = Status::Corruption("Corrupted internal key not expected.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
key_ = current_key_.SetKey(key_);
|
key_ = current_key_.SetInternalKey(key_);
|
||||||
has_current_user_key_ = false;
|
has_current_user_key_ = false;
|
||||||
current_user_key_sequence_ = kMaxSequenceNumber;
|
current_user_key_sequence_ = kMaxSequenceNumber;
|
||||||
current_user_key_snapshot_ = 0;
|
current_user_key_snapshot_ = 0;
|
||||||
@ -181,7 +181,7 @@ void CompactionIterator::NextFromInput() {
|
|||||||
!cmp_->Equal(ikey_.user_key, current_user_key_)) {
|
!cmp_->Equal(ikey_.user_key, current_user_key_)) {
|
||||||
// First occurrence of this user key
|
// First occurrence of this user key
|
||||||
// Copy key for output
|
// Copy key for output
|
||||||
key_ = current_key_.SetKey(key_, &ikey_);
|
key_ = current_key_.SetInternalKey(key_, &ikey_);
|
||||||
current_user_key_ = ikey_.user_key;
|
current_user_key_ = ikey_.user_key;
|
||||||
has_current_user_key_ = true;
|
has_current_user_key_ = true;
|
||||||
has_outputted_key_ = false;
|
has_outputted_key_ = false;
|
||||||
@ -241,7 +241,7 @@ void CompactionIterator::NextFromInput() {
|
|||||||
// Need to have the compaction filter process multiple versions
|
// Need to have the compaction filter process multiple versions
|
||||||
// if we have versions on both sides of a snapshot
|
// if we have versions on both sides of a snapshot
|
||||||
current_key_.UpdateInternalKey(ikey_.sequence, ikey_.type);
|
current_key_.UpdateInternalKey(ikey_.sequence, ikey_.type);
|
||||||
key_ = current_key_.GetKey();
|
key_ = current_key_.GetInternalKey();
|
||||||
ikey_.user_key = current_key_.GetUserKey();
|
ikey_.user_key = current_key_.GetUserKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,7 +453,7 @@ void CompactionIterator::NextFromInput() {
|
|||||||
assert(valid_key);
|
assert(valid_key);
|
||||||
// Keep current_key_ in sync.
|
// Keep current_key_ in sync.
|
||||||
current_key_.UpdateInternalKey(ikey_.sequence, ikey_.type);
|
current_key_.UpdateInternalKey(ikey_.sequence, ikey_.type);
|
||||||
key_ = current_key_.GetKey();
|
key_ = current_key_.GetInternalKey();
|
||||||
ikey_.user_key = current_key_.GetUserKey();
|
ikey_.user_key = current_key_.GetUserKey();
|
||||||
valid_ = true;
|
valid_ = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -733,7 +733,7 @@ void CompactionJob::ProcessKeyValueCompaction(SubcompactionState* sub_compact) {
|
|||||||
if (start != nullptr) {
|
if (start != nullptr) {
|
||||||
IterKey start_iter;
|
IterKey start_iter;
|
||||||
start_iter.SetInternalKey(*start, kMaxSequenceNumber, kValueTypeForSeek);
|
start_iter.SetInternalKey(*start, kMaxSequenceNumber, kValueTypeForSeek);
|
||||||
input->Seek(start_iter.GetKey());
|
input->Seek(start_iter.GetInternalKey());
|
||||||
} else {
|
} else {
|
||||||
input->SeekToFirst();
|
input->SeekToFirst();
|
||||||
}
|
}
|
||||||
|
126
db/db_iter.cc
126
db/db_iter.cc
@ -162,7 +162,7 @@ class DBIter: public Iterator {
|
|||||||
virtual bool Valid() const override { return valid_; }
|
virtual bool Valid() const override { return valid_; }
|
||||||
virtual Slice key() const override {
|
virtual Slice key() const override {
|
||||||
assert(valid_);
|
assert(valid_);
|
||||||
return saved_key_.GetKey();
|
return saved_key_.GetUserKey();
|
||||||
}
|
}
|
||||||
virtual Slice value() const override {
|
virtual Slice value() const override {
|
||||||
assert(valid_);
|
assert(valid_);
|
||||||
@ -406,7 +406,8 @@ void DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
|
|||||||
|
|
||||||
if (ikey.sequence <= sequence_) {
|
if (ikey.sequence <= sequence_) {
|
||||||
if (skipping &&
|
if (skipping &&
|
||||||
user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) <= 0) {
|
user_comparator_->Compare(ikey.user_key, saved_key_.GetUserKey()) <=
|
||||||
|
0) {
|
||||||
num_skipped++; // skip this entry
|
num_skipped++; // skip this entry
|
||||||
PERF_COUNTER_ADD(internal_key_skipped_count, 1);
|
PERF_COUNTER_ADD(internal_key_skipped_count, 1);
|
||||||
} else {
|
} else {
|
||||||
@ -416,14 +417,14 @@ void DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
|
|||||||
case kTypeSingleDeletion:
|
case kTypeSingleDeletion:
|
||||||
// Arrange to skip all upcoming entries for this key since
|
// Arrange to skip all upcoming entries for this key since
|
||||||
// they are hidden by this deletion.
|
// they are hidden by this deletion.
|
||||||
saved_key_.SetKey(
|
saved_key_.SetUserKey(
|
||||||
ikey.user_key,
|
ikey.user_key,
|
||||||
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
||||||
skipping = true;
|
skipping = true;
|
||||||
PERF_COUNTER_ADD(internal_delete_skipped_count, 1);
|
PERF_COUNTER_ADD(internal_delete_skipped_count, 1);
|
||||||
break;
|
break;
|
||||||
case kTypeValue:
|
case kTypeValue:
|
||||||
saved_key_.SetKey(
|
saved_key_.SetUserKey(
|
||||||
ikey.user_key,
|
ikey.user_key,
|
||||||
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
||||||
if (range_del_agg_.ShouldDelete(
|
if (range_del_agg_.ShouldDelete(
|
||||||
@ -440,7 +441,7 @@ void DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kTypeMerge:
|
case kTypeMerge:
|
||||||
saved_key_.SetKey(
|
saved_key_.SetUserKey(
|
||||||
ikey.user_key,
|
ikey.user_key,
|
||||||
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
||||||
if (range_del_agg_.ShouldDelete(
|
if (range_del_agg_.ShouldDelete(
|
||||||
@ -471,10 +472,11 @@ void DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
|
|||||||
|
|
||||||
// Here saved_key_ may contain some old key, or the default empty key, or
|
// Here saved_key_ may contain some old key, or the default empty key, or
|
||||||
// key assigned by some random other method. We don't care.
|
// key assigned by some random other method. We don't care.
|
||||||
if (user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) <= 0) {
|
if (user_comparator_->Compare(ikey.user_key, saved_key_.GetUserKey()) <=
|
||||||
|
0) {
|
||||||
num_skipped++;
|
num_skipped++;
|
||||||
} else {
|
} else {
|
||||||
saved_key_.SetKey(
|
saved_key_.SetUserKey(
|
||||||
ikey.user_key,
|
ikey.user_key,
|
||||||
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
||||||
skipping = false;
|
skipping = false;
|
||||||
@ -491,8 +493,8 @@ void DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
|
|||||||
// We're looking for the next user-key but all we see are the same
|
// We're looking for the next user-key but all we see are the same
|
||||||
// user-key with decreasing sequence numbers. Fast forward to
|
// user-key with decreasing sequence numbers. Fast forward to
|
||||||
// sequence number 0 and type deletion (the smallest type).
|
// sequence number 0 and type deletion (the smallest type).
|
||||||
AppendInternalKey(&last_key, ParsedInternalKey(saved_key_.GetKey(), 0,
|
AppendInternalKey(&last_key, ParsedInternalKey(saved_key_.GetUserKey(),
|
||||||
kTypeDeletion));
|
0, kTypeDeletion));
|
||||||
// Don't set skipping = false because we may still see more user-keys
|
// Don't set skipping = false because we may still see more user-keys
|
||||||
// equal to saved_key_.
|
// equal to saved_key_.
|
||||||
} else {
|
} else {
|
||||||
@ -502,7 +504,7 @@ void DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
|
|||||||
// many times since our snapshot was taken, not the case when a lot of
|
// many times since our snapshot was taken, not the case when a lot of
|
||||||
// different keys were inserted after our snapshot was taken.
|
// different keys were inserted after our snapshot was taken.
|
||||||
AppendInternalKey(&last_key,
|
AppendInternalKey(&last_key,
|
||||||
ParsedInternalKey(saved_key_.GetKey(), sequence_,
|
ParsedInternalKey(saved_key_.GetUserKey(), sequence_,
|
||||||
kValueTypeForSeek));
|
kValueTypeForSeek));
|
||||||
}
|
}
|
||||||
iter_->Seek(last_key);
|
iter_->Seek(last_key);
|
||||||
@ -543,7 +545,7 @@ void DBIter::MergeValuesNewToOld() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user_comparator_->Equal(ikey.user_key, saved_key_.GetKey())) {
|
if (!user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey())) {
|
||||||
// hit the next user key, stop right here
|
// hit the next user key, stop right here
|
||||||
break;
|
break;
|
||||||
} else if (kTypeDeletion == ikey.type || kTypeSingleDeletion == ikey.type ||
|
} else if (kTypeDeletion == ikey.type || kTypeSingleDeletion == ikey.type ||
|
||||||
@ -583,9 +585,10 @@ void DBIter::MergeValuesNewToOld() {
|
|||||||
// a deletion marker.
|
// a deletion marker.
|
||||||
// feed null as the existing value to the merge operator, such that
|
// feed null as the existing value to the merge operator, such that
|
||||||
// client can differentiate this scenario and do things accordingly.
|
// client can differentiate this scenario and do things accordingly.
|
||||||
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetKey(), nullptr,
|
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetUserKey(),
|
||||||
merge_context_.GetOperands(), &saved_value_,
|
nullptr, merge_context_.GetOperands(),
|
||||||
logger_, statistics_, env_, &pinned_value_);
|
&saved_value_, logger_, statistics_, env_,
|
||||||
|
&pinned_value_);
|
||||||
if (!s.ok()) {
|
if (!s.ok()) {
|
||||||
status_ = s;
|
status_ = s;
|
||||||
}
|
}
|
||||||
@ -612,8 +615,8 @@ void DBIter::ReverseToForward() {
|
|||||||
if (prefix_extractor_ != nullptr && !total_order_seek_) {
|
if (prefix_extractor_ != nullptr && !total_order_seek_) {
|
||||||
IterKey last_key;
|
IterKey last_key;
|
||||||
last_key.SetInternalKey(ParsedInternalKey(
|
last_key.SetInternalKey(ParsedInternalKey(
|
||||||
saved_key_.GetKey(), kMaxSequenceNumber, kValueTypeForSeek));
|
saved_key_.GetUserKey(), kMaxSequenceNumber, kValueTypeForSeek));
|
||||||
iter_->Seek(last_key.GetKey());
|
iter_->Seek(last_key.GetInternalKey());
|
||||||
}
|
}
|
||||||
FindNextUserKey();
|
FindNextUserKey();
|
||||||
direction_ = kForward;
|
direction_ = kForward;
|
||||||
@ -626,9 +629,9 @@ void DBIter::ReverseToForward() {
|
|||||||
void DBIter::ReverseToBackward() {
|
void DBIter::ReverseToBackward() {
|
||||||
if (prefix_extractor_ != nullptr && !total_order_seek_) {
|
if (prefix_extractor_ != nullptr && !total_order_seek_) {
|
||||||
IterKey last_key;
|
IterKey last_key;
|
||||||
last_key.SetInternalKey(
|
last_key.SetInternalKey(ParsedInternalKey(saved_key_.GetUserKey(), 0,
|
||||||
ParsedInternalKey(saved_key_.GetKey(), 0, kValueTypeForSeekForPrev));
|
kValueTypeForSeekForPrev));
|
||||||
iter_->SeekForPrev(last_key.GetKey());
|
iter_->SeekForPrev(last_key.GetInternalKey());
|
||||||
}
|
}
|
||||||
if (current_entry_is_merged_) {
|
if (current_entry_is_merged_) {
|
||||||
// Not placed in the same key. Need to call Prev() until finding the
|
// Not placed in the same key. Need to call Prev() until finding the
|
||||||
@ -640,7 +643,8 @@ void DBIter::ReverseToBackward() {
|
|||||||
ParsedInternalKey ikey;
|
ParsedInternalKey ikey;
|
||||||
FindParseableKey(&ikey, kReverse);
|
FindParseableKey(&ikey, kReverse);
|
||||||
while (iter_->Valid() &&
|
while (iter_->Valid() &&
|
||||||
user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) > 0) {
|
user_comparator_->Compare(ikey.user_key, saved_key_.GetUserKey()) >
|
||||||
|
0) {
|
||||||
if (ikey.sequence > sequence_) {
|
if (ikey.sequence > sequence_) {
|
||||||
PERF_COUNTER_ADD(internal_recent_skipped_count, 1);
|
PERF_COUNTER_ADD(internal_recent_skipped_count, 1);
|
||||||
} else {
|
} else {
|
||||||
@ -654,7 +658,8 @@ void DBIter::ReverseToBackward() {
|
|||||||
if (iter_->Valid()) {
|
if (iter_->Valid()) {
|
||||||
ParsedInternalKey ikey;
|
ParsedInternalKey ikey;
|
||||||
assert(ParseKey(&ikey));
|
assert(ParseKey(&ikey));
|
||||||
assert(user_comparator_->Compare(ikey.user_key, saved_key_.GetKey()) <= 0);
|
assert(user_comparator_->Compare(ikey.user_key, saved_key_.GetUserKey()) <=
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -671,7 +676,8 @@ void DBIter::PrevInternal() {
|
|||||||
ParsedInternalKey ikey;
|
ParsedInternalKey ikey;
|
||||||
|
|
||||||
while (iter_->Valid()) {
|
while (iter_->Valid()) {
|
||||||
saved_key_.SetKey(ExtractUserKey(iter_->key()),
|
saved_key_.SetUserKey(
|
||||||
|
ExtractUserKey(iter_->key()),
|
||||||
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
||||||
|
|
||||||
if (FindValueForCurrentKey()) {
|
if (FindValueForCurrentKey()) {
|
||||||
@ -680,11 +686,11 @@ void DBIter::PrevInternal() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FindParseableKey(&ikey, kReverse);
|
FindParseableKey(&ikey, kReverse);
|
||||||
if (user_comparator_->Equal(ikey.user_key, saved_key_.GetKey())) {
|
if (user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey())) {
|
||||||
FindPrevUserKey();
|
FindPrevUserKey();
|
||||||
}
|
}
|
||||||
if (valid_ && prefix_extractor_ && prefix_same_as_start_ &&
|
if (valid_ && prefix_extractor_ && prefix_same_as_start_ &&
|
||||||
prefix_extractor_->Transform(saved_key_.GetKey())
|
prefix_extractor_->Transform(saved_key_.GetUserKey())
|
||||||
.compare(prefix_start_key_) != 0) {
|
.compare(prefix_start_key_) != 0) {
|
||||||
valid_ = false;
|
valid_ = false;
|
||||||
}
|
}
|
||||||
@ -699,7 +705,7 @@ void DBIter::PrevInternal() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
FindParseableKey(&ikey, kReverse);
|
FindParseableKey(&ikey, kReverse);
|
||||||
if (user_comparator_->Equal(ikey.user_key, saved_key_.GetKey())) {
|
if (user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey())) {
|
||||||
FindPrevUserKey();
|
FindPrevUserKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -729,7 +735,7 @@ bool DBIter::FindValueForCurrentKey() {
|
|||||||
TempPinData();
|
TempPinData();
|
||||||
size_t num_skipped = 0;
|
size_t num_skipped = 0;
|
||||||
while (iter_->Valid() && ikey.sequence <= sequence_ &&
|
while (iter_->Valid() && ikey.sequence <= sequence_ &&
|
||||||
user_comparator_->Equal(ikey.user_key, saved_key_.GetKey())) {
|
user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey())) {
|
||||||
if (TooManyInternalKeysSkipped()) {
|
if (TooManyInternalKeysSkipped()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -780,7 +786,7 @@ bool DBIter::FindValueForCurrentKey() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PERF_COUNTER_ADD(internal_key_skipped_count, 1);
|
PERF_COUNTER_ADD(internal_key_skipped_count, 1);
|
||||||
assert(user_comparator_->Equal(ikey.user_key, saved_key_.GetKey()));
|
assert(user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey()));
|
||||||
iter_->Prev();
|
iter_->Prev();
|
||||||
++num_skipped;
|
++num_skipped;
|
||||||
FindParseableKey(&ikey, kReverse);
|
FindParseableKey(&ikey, kReverse);
|
||||||
@ -798,14 +804,14 @@ bool DBIter::FindValueForCurrentKey() {
|
|||||||
if (last_not_merge_type == kTypeDeletion ||
|
if (last_not_merge_type == kTypeDeletion ||
|
||||||
last_not_merge_type == kTypeSingleDeletion ||
|
last_not_merge_type == kTypeSingleDeletion ||
|
||||||
last_not_merge_type == kTypeRangeDeletion) {
|
last_not_merge_type == kTypeRangeDeletion) {
|
||||||
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetKey(),
|
s = MergeHelper::TimedFullMerge(
|
||||||
nullptr, merge_context_.GetOperands(),
|
merge_operator_, saved_key_.GetUserKey(), nullptr,
|
||||||
&saved_value_, logger_, statistics_,
|
merge_context_.GetOperands(), &saved_value_, logger_, statistics_,
|
||||||
env_, &pinned_value_);
|
env_, &pinned_value_);
|
||||||
} else {
|
} else {
|
||||||
assert(last_not_merge_type == kTypeValue);
|
assert(last_not_merge_type == kTypeValue);
|
||||||
s = MergeHelper::TimedFullMerge(
|
s = MergeHelper::TimedFullMerge(
|
||||||
merge_operator_, saved_key_.GetKey(), &pinned_value_,
|
merge_operator_, saved_key_.GetUserKey(), &pinned_value_,
|
||||||
merge_context_.GetOperands(), &saved_value_, logger_, statistics_,
|
merge_context_.GetOperands(), &saved_value_, logger_, statistics_,
|
||||||
env_, &pinned_value_);
|
env_, &pinned_value_);
|
||||||
}
|
}
|
||||||
@ -831,8 +837,8 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
|||||||
// FindValueForCurrentKeyUsingSeek()
|
// FindValueForCurrentKeyUsingSeek()
|
||||||
assert(pinned_iters_mgr_.PinningEnabled());
|
assert(pinned_iters_mgr_.PinningEnabled());
|
||||||
std::string last_key;
|
std::string last_key;
|
||||||
AppendInternalKey(&last_key, ParsedInternalKey(saved_key_.GetKey(), sequence_,
|
AppendInternalKey(&last_key, ParsedInternalKey(saved_key_.GetUserKey(),
|
||||||
kValueTypeForSeek));
|
sequence_, kValueTypeForSeek));
|
||||||
iter_->Seek(last_key);
|
iter_->Seek(last_key);
|
||||||
RecordTick(statistics_, NUMBER_OF_RESEEKS_IN_ITERATION);
|
RecordTick(statistics_, NUMBER_OF_RESEEKS_IN_ITERATION);
|
||||||
|
|
||||||
@ -859,7 +865,7 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
|||||||
merge_context_.Clear();
|
merge_context_.Clear();
|
||||||
while (
|
while (
|
||||||
iter_->Valid() &&
|
iter_->Valid() &&
|
||||||
user_comparator_->Equal(ikey.user_key, saved_key_.GetKey()) &&
|
user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey()) &&
|
||||||
ikey.type == kTypeMerge &&
|
ikey.type == kTypeMerge &&
|
||||||
!range_del_agg_.ShouldDelete(
|
!range_del_agg_.ShouldDelete(
|
||||||
ikey, RangeDelAggregator::RangePositioningMode::kBackwardTraversal)) {
|
ikey, RangeDelAggregator::RangePositioningMode::kBackwardTraversal)) {
|
||||||
@ -872,17 +878,17 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
|||||||
|
|
||||||
Status s;
|
Status s;
|
||||||
if (!iter_->Valid() ||
|
if (!iter_->Valid() ||
|
||||||
!user_comparator_->Equal(ikey.user_key, saved_key_.GetKey()) ||
|
!user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey()) ||
|
||||||
ikey.type == kTypeDeletion || ikey.type == kTypeSingleDeletion ||
|
ikey.type == kTypeDeletion || ikey.type == kTypeSingleDeletion ||
|
||||||
range_del_agg_.ShouldDelete(
|
range_del_agg_.ShouldDelete(
|
||||||
ikey, RangeDelAggregator::RangePositioningMode::kBackwardTraversal)) {
|
ikey, RangeDelAggregator::RangePositioningMode::kBackwardTraversal)) {
|
||||||
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetKey(),
|
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetUserKey(),
|
||||||
nullptr, merge_context_.GetOperands(),
|
nullptr, merge_context_.GetOperands(),
|
||||||
&saved_value_, logger_, statistics_, env_,
|
&saved_value_, logger_, statistics_, env_,
|
||||||
&pinned_value_);
|
&pinned_value_);
|
||||||
// Make iter_ valid and point to saved_key_
|
// Make iter_ valid and point to saved_key_
|
||||||
if (!iter_->Valid() ||
|
if (!iter_->Valid() ||
|
||||||
!user_comparator_->Equal(ikey.user_key, saved_key_.GetKey())) {
|
!user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey())) {
|
||||||
iter_->Seek(last_key);
|
iter_->Seek(last_key);
|
||||||
RecordTick(statistics_, NUMBER_OF_RESEEKS_IN_ITERATION);
|
RecordTick(statistics_, NUMBER_OF_RESEEKS_IN_ITERATION);
|
||||||
}
|
}
|
||||||
@ -894,9 +900,10 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Slice& val = iter_->value();
|
const Slice& val = iter_->value();
|
||||||
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetKey(), &val,
|
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetUserKey(),
|
||||||
merge_context_.GetOperands(), &saved_value_,
|
&val, merge_context_.GetOperands(),
|
||||||
logger_, statistics_, env_, &pinned_value_);
|
&saved_value_, logger_, statistics_, env_,
|
||||||
|
&pinned_value_);
|
||||||
valid_ = true;
|
valid_ = true;
|
||||||
if (!s.ok()) {
|
if (!s.ok()) {
|
||||||
status_ = s;
|
status_ = s;
|
||||||
@ -915,7 +922,7 @@ void DBIter::FindNextUserKey() {
|
|||||||
ParsedInternalKey ikey;
|
ParsedInternalKey ikey;
|
||||||
FindParseableKey(&ikey, kForward);
|
FindParseableKey(&ikey, kForward);
|
||||||
while (iter_->Valid() &&
|
while (iter_->Valid() &&
|
||||||
!user_comparator_->Equal(ikey.user_key, saved_key_.GetKey())) {
|
!user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey())) {
|
||||||
iter_->Next();
|
iter_->Next();
|
||||||
FindParseableKey(&ikey, kForward);
|
FindParseableKey(&ikey, kForward);
|
||||||
}
|
}
|
||||||
@ -930,8 +937,9 @@ void DBIter::FindPrevUserKey() {
|
|||||||
ParsedInternalKey ikey;
|
ParsedInternalKey ikey;
|
||||||
FindParseableKey(&ikey, kReverse);
|
FindParseableKey(&ikey, kReverse);
|
||||||
int cmp;
|
int cmp;
|
||||||
while (iter_->Valid() && ((cmp = user_comparator_->Compare(
|
while (iter_->Valid() &&
|
||||||
ikey.user_key, saved_key_.GetKey())) == 0 ||
|
((cmp = user_comparator_->Compare(ikey.user_key,
|
||||||
|
saved_key_.GetUserKey())) == 0 ||
|
||||||
(cmp > 0 && ikey.sequence > sequence_))) {
|
(cmp > 0 && ikey.sequence > sequence_))) {
|
||||||
if (TooManyInternalKeysSkipped()) {
|
if (TooManyInternalKeysSkipped()) {
|
||||||
return;
|
return;
|
||||||
@ -942,8 +950,8 @@ void DBIter::FindPrevUserKey() {
|
|||||||
num_skipped = 0;
|
num_skipped = 0;
|
||||||
IterKey last_key;
|
IterKey last_key;
|
||||||
last_key.SetInternalKey(ParsedInternalKey(
|
last_key.SetInternalKey(ParsedInternalKey(
|
||||||
saved_key_.GetKey(), kMaxSequenceNumber, kValueTypeForSeek));
|
saved_key_.GetUserKey(), kMaxSequenceNumber, kValueTypeForSeek));
|
||||||
iter_->Seek(last_key.GetKey());
|
iter_->Seek(last_key.GetInternalKey());
|
||||||
RecordTick(statistics_, NUMBER_OF_RESEEKS_IN_ITERATION);
|
RecordTick(statistics_, NUMBER_OF_RESEEKS_IN_ITERATION);
|
||||||
} else {
|
} else {
|
||||||
++num_skipped;
|
++num_skipped;
|
||||||
@ -991,7 +999,7 @@ void DBIter::Seek(const Slice& target) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
PERF_TIMER_GUARD(seek_internal_seek_time);
|
PERF_TIMER_GUARD(seek_internal_seek_time);
|
||||||
iter_->Seek(saved_key_.GetKey());
|
iter_->Seek(saved_key_.GetInternalKey());
|
||||||
range_del_agg_.InvalidateTombstoneMapPositions();
|
range_del_agg_.InvalidateTombstoneMapPositions();
|
||||||
}
|
}
|
||||||
RecordTick(statistics_, NUMBER_DB_SEEK);
|
RecordTick(statistics_, NUMBER_DB_SEEK);
|
||||||
@ -1001,9 +1009,6 @@ void DBIter::Seek(const Slice& target) {
|
|||||||
}
|
}
|
||||||
direction_ = kForward;
|
direction_ = kForward;
|
||||||
ClearSavedValue();
|
ClearSavedValue();
|
||||||
// convert the InternalKey to UserKey in saved_key_ before
|
|
||||||
// passed to FindNextUserEntry
|
|
||||||
saved_key_.Reserve(saved_key_.Size() - 8);
|
|
||||||
FindNextUserEntry(false /* not skipping */, prefix_same_as_start_);
|
FindNextUserEntry(false /* not skipping */, prefix_same_as_start_);
|
||||||
if (!valid_) {
|
if (!valid_) {
|
||||||
prefix_start_key_.clear();
|
prefix_start_key_.clear();
|
||||||
@ -1019,8 +1024,8 @@ void DBIter::Seek(const Slice& target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (valid_ && prefix_extractor_ && prefix_same_as_start_) {
|
if (valid_ && prefix_extractor_ && prefix_same_as_start_) {
|
||||||
prefix_start_buf_.SetKey(prefix_start_key_);
|
prefix_start_buf_.SetUserKey(prefix_start_key_);
|
||||||
prefix_start_key_ = prefix_start_buf_.GetKey();
|
prefix_start_key_ = prefix_start_buf_.GetUserKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1035,7 +1040,7 @@ void DBIter::SeekForPrev(const Slice& target) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
PERF_TIMER_GUARD(seek_internal_seek_time);
|
PERF_TIMER_GUARD(seek_internal_seek_time);
|
||||||
iter_->SeekForPrev(saved_key_.GetKey());
|
iter_->SeekForPrev(saved_key_.GetInternalKey());
|
||||||
range_del_agg_.InvalidateTombstoneMapPositions();
|
range_del_agg_.InvalidateTombstoneMapPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1060,8 +1065,8 @@ void DBIter::SeekForPrev(const Slice& target) {
|
|||||||
valid_ = false;
|
valid_ = false;
|
||||||
}
|
}
|
||||||
if (valid_ && prefix_extractor_ && prefix_same_as_start_) {
|
if (valid_ && prefix_extractor_ && prefix_same_as_start_) {
|
||||||
prefix_start_buf_.SetKey(prefix_start_key_);
|
prefix_start_buf_.SetUserKey(prefix_start_key_);
|
||||||
prefix_start_key_ = prefix_start_buf_.GetKey();
|
prefix_start_key_ = prefix_start_buf_.GetUserKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1084,7 +1089,8 @@ void DBIter::SeekToFirst() {
|
|||||||
|
|
||||||
RecordTick(statistics_, NUMBER_DB_SEEK);
|
RecordTick(statistics_, NUMBER_DB_SEEK);
|
||||||
if (iter_->Valid()) {
|
if (iter_->Valid()) {
|
||||||
saved_key_.SetKey(ExtractUserKey(iter_->key()),
|
saved_key_.SetUserKey(
|
||||||
|
ExtractUserKey(iter_->key()),
|
||||||
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
||||||
FindNextUserEntry(false /* not skipping */, false /* no prefix check */);
|
FindNextUserEntry(false /* not skipping */, false /* no prefix check */);
|
||||||
if (statistics_ != nullptr) {
|
if (statistics_ != nullptr) {
|
||||||
@ -1097,8 +1103,9 @@ void DBIter::SeekToFirst() {
|
|||||||
valid_ = false;
|
valid_ = false;
|
||||||
}
|
}
|
||||||
if (valid_ && prefix_extractor_ && prefix_same_as_start_) {
|
if (valid_ && prefix_extractor_ && prefix_same_as_start_) {
|
||||||
prefix_start_buf_.SetKey(prefix_extractor_->Transform(saved_key_.GetKey()));
|
prefix_start_buf_.SetUserKey(
|
||||||
prefix_start_key_ = prefix_start_buf_.GetKey();
|
prefix_extractor_->Transform(saved_key_.GetUserKey()));
|
||||||
|
prefix_start_key_ = prefix_start_buf_.GetUserKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1140,8 +1147,9 @@ void DBIter::SeekToLast() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (valid_ && prefix_extractor_ && prefix_same_as_start_) {
|
if (valid_ && prefix_extractor_ && prefix_same_as_start_) {
|
||||||
prefix_start_buf_.SetKey(prefix_extractor_->Transform(saved_key_.GetKey()));
|
prefix_start_buf_.SetUserKey(
|
||||||
prefix_start_key_ = prefix_start_buf_.GetKey();
|
prefix_extractor_->Transform(saved_key_.GetUserKey()));
|
||||||
|
prefix_start_key_ = prefix_start_buf_.GetUserKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,16 +303,27 @@ inline LookupKey::~LookupKey() {
|
|||||||
class IterKey {
|
class IterKey {
|
||||||
public:
|
public:
|
||||||
IterKey()
|
IterKey()
|
||||||
: buf_(space_), buf_size_(sizeof(space_)), key_(buf_), key_size_(0) {}
|
: buf_(space_),
|
||||||
|
buf_size_(sizeof(space_)),
|
||||||
|
key_(buf_),
|
||||||
|
key_size_(0),
|
||||||
|
is_user_key_(true) {}
|
||||||
|
|
||||||
~IterKey() { ResetBuffer(); }
|
~IterKey() { ResetBuffer(); }
|
||||||
|
|
||||||
Slice GetKey() const { return Slice(key_, key_size_); }
|
Slice GetInternalKey() const {
|
||||||
|
assert(!IsUserKey());
|
||||||
|
return Slice(key_, key_size_);
|
||||||
|
}
|
||||||
|
|
||||||
Slice GetUserKey() const {
|
Slice GetUserKey() const {
|
||||||
|
if (IsUserKey()) {
|
||||||
|
return Slice(key_, key_size_);
|
||||||
|
} else {
|
||||||
assert(key_size_ >= 8);
|
assert(key_size_ >= 8);
|
||||||
return Slice(key_, key_size_ - 8);
|
return Slice(key_, key_size_ - 8);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t Size() const { return key_size_; }
|
size_t Size() const { return key_size_; }
|
||||||
|
|
||||||
@ -349,27 +360,22 @@ class IterKey {
|
|||||||
key_size_ = total_size;
|
key_size_ = total_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
Slice SetKey(const Slice& key, bool copy = true) {
|
Slice SetUserKey(const Slice& key, bool copy = true) {
|
||||||
size_t size = key.size();
|
is_user_key_ = true;
|
||||||
if (copy) {
|
return SetKeyImpl(key, copy);
|
||||||
// Copy key to buf_
|
|
||||||
EnlargeBufferIfNeeded(size);
|
|
||||||
memcpy(buf_, key.data(), size);
|
|
||||||
key_ = buf_;
|
|
||||||
} else {
|
|
||||||
// Update key_ to point to external memory
|
|
||||||
key_ = key.data();
|
|
||||||
}
|
}
|
||||||
key_size_ = size;
|
|
||||||
return Slice(key_, key_size_);
|
Slice SetInternalKey(const Slice& key, bool copy = true) {
|
||||||
|
is_user_key_ = false;
|
||||||
|
return SetKeyImpl(key, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies the content of key, updates the reference to the user key in ikey
|
// Copies the content of key, updates the reference to the user key in ikey
|
||||||
// and returns a Slice referencing the new copy.
|
// and returns a Slice referencing the new copy.
|
||||||
Slice SetKey(const Slice& key, ParsedInternalKey* ikey) {
|
Slice SetInternalKey(const Slice& key, ParsedInternalKey* ikey) {
|
||||||
size_t key_n = key.size();
|
size_t key_n = key.size();
|
||||||
assert(key_n >= 8);
|
assert(key_n >= 8);
|
||||||
SetKey(key);
|
SetInternalKey(key);
|
||||||
ikey->user_key = Slice(key_, key_n - 8);
|
ikey->user_key = Slice(key_, key_n - 8);
|
||||||
return Slice(key_, key_n);
|
return Slice(key_, key_n);
|
||||||
}
|
}
|
||||||
@ -408,6 +414,7 @@ class IterKey {
|
|||||||
|
|
||||||
key_ = buf_;
|
key_ = buf_;
|
||||||
key_size_ = psize + usize + sizeof(uint64_t);
|
key_size_ = psize + usize + sizeof(uint64_t);
|
||||||
|
is_user_key_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetInternalKey(const Slice& user_key, SequenceNumber s,
|
void SetInternalKey(const Slice& user_key, SequenceNumber s,
|
||||||
@ -436,14 +443,33 @@ class IterKey {
|
|||||||
char* ptr = EncodeVarint32(buf_, static_cast<uint32_t>(size));
|
char* ptr = EncodeVarint32(buf_, static_cast<uint32_t>(size));
|
||||||
memcpy(ptr, key.data(), size);
|
memcpy(ptr, key.data(), size);
|
||||||
key_ = buf_;
|
key_ = buf_;
|
||||||
|
is_user_key_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsUserKey() const { return is_user_key_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* buf_;
|
char* buf_;
|
||||||
size_t buf_size_;
|
size_t buf_size_;
|
||||||
const char* key_;
|
const char* key_;
|
||||||
size_t key_size_;
|
size_t key_size_;
|
||||||
char space_[32]; // Avoid allocation for short keys
|
char space_[32]; // Avoid allocation for short keys
|
||||||
|
bool is_user_key_;
|
||||||
|
|
||||||
|
Slice SetKeyImpl(const Slice& key, bool copy) {
|
||||||
|
size_t size = key.size();
|
||||||
|
if (copy) {
|
||||||
|
// Copy key to buf_
|
||||||
|
EnlargeBufferIfNeeded(size);
|
||||||
|
memcpy(buf_, key.data(), size);
|
||||||
|
key_ = buf_;
|
||||||
|
} else {
|
||||||
|
// Update key_ to point to external memory
|
||||||
|
key_ = key.data();
|
||||||
|
}
|
||||||
|
key_size_ = size;
|
||||||
|
return Slice(key_, key_size_);
|
||||||
|
}
|
||||||
|
|
||||||
void ResetBuffer() {
|
void ResetBuffer() {
|
||||||
if (buf_ != space_) {
|
if (buf_ != space_) {
|
||||||
|
@ -139,36 +139,36 @@ TEST_F(FormatTest, IterKeyOperation) {
|
|||||||
const char p[] = "abcdefghijklmnopqrstuvwxyz";
|
const char p[] = "abcdefghijklmnopqrstuvwxyz";
|
||||||
const char q[] = "0123456789";
|
const char q[] = "0123456789";
|
||||||
|
|
||||||
ASSERT_EQ(std::string(k.GetKey().data(), k.GetKey().size()),
|
ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()),
|
||||||
std::string(""));
|
std::string(""));
|
||||||
|
|
||||||
k.TrimAppend(0, p, 3);
|
k.TrimAppend(0, p, 3);
|
||||||
ASSERT_EQ(std::string(k.GetKey().data(), k.GetKey().size()),
|
ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()),
|
||||||
std::string("abc"));
|
std::string("abc"));
|
||||||
|
|
||||||
k.TrimAppend(1, p, 3);
|
k.TrimAppend(1, p, 3);
|
||||||
ASSERT_EQ(std::string(k.GetKey().data(), k.GetKey().size()),
|
ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()),
|
||||||
std::string("aabc"));
|
std::string("aabc"));
|
||||||
|
|
||||||
k.TrimAppend(0, p, 26);
|
k.TrimAppend(0, p, 26);
|
||||||
ASSERT_EQ(std::string(k.GetKey().data(), k.GetKey().size()),
|
ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()),
|
||||||
std::string("abcdefghijklmnopqrstuvwxyz"));
|
std::string("abcdefghijklmnopqrstuvwxyz"));
|
||||||
|
|
||||||
k.TrimAppend(26, q, 10);
|
k.TrimAppend(26, q, 10);
|
||||||
ASSERT_EQ(std::string(k.GetKey().data(), k.GetKey().size()),
|
ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()),
|
||||||
std::string("abcdefghijklmnopqrstuvwxyz0123456789"));
|
std::string("abcdefghijklmnopqrstuvwxyz0123456789"));
|
||||||
|
|
||||||
k.TrimAppend(36, q, 1);
|
k.TrimAppend(36, q, 1);
|
||||||
ASSERT_EQ(std::string(k.GetKey().data(), k.GetKey().size()),
|
ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()),
|
||||||
std::string("abcdefghijklmnopqrstuvwxyz01234567890"));
|
std::string("abcdefghijklmnopqrstuvwxyz01234567890"));
|
||||||
|
|
||||||
k.TrimAppend(26, q, 1);
|
k.TrimAppend(26, q, 1);
|
||||||
ASSERT_EQ(std::string(k.GetKey().data(), k.GetKey().size()),
|
ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()),
|
||||||
std::string("abcdefghijklmnopqrstuvwxyz0"));
|
std::string("abcdefghijklmnopqrstuvwxyz0"));
|
||||||
|
|
||||||
// Size going up, memory allocation is triggered
|
// Size going up, memory allocation is triggered
|
||||||
k.TrimAppend(27, p, 26);
|
k.TrimAppend(27, p, 26);
|
||||||
ASSERT_EQ(std::string(k.GetKey().data(), k.GetKey().size()),
|
ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()),
|
||||||
std::string("abcdefghijklmnopqrstuvwxyz0"
|
std::string("abcdefghijklmnopqrstuvwxyz0"
|
||||||
"abcdefghijklmnopqrstuvwxyz"));
|
"abcdefghijklmnopqrstuvwxyz"));
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,7 @@ void ForwardIterator::SeekInternal(const Slice& internal_key,
|
|||||||
seek_to_first ||
|
seek_to_first ||
|
||||||
// prev_key_ > internal_key
|
// prev_key_ > internal_key
|
||||||
cfd_->internal_comparator().InternalKeyComparator::Compare(
|
cfd_->internal_comparator().InternalKeyComparator::Compare(
|
||||||
prev_key_.GetKey(), internal_key) > 0)) {
|
prev_key_.GetInternalKey(), internal_key) > 0)) {
|
||||||
// Some iterators are trimmed. Need to rebuild.
|
// Some iterators are trimmed. Need to rebuild.
|
||||||
RebuildIterators(true);
|
RebuildIterators(true);
|
||||||
// Already seeked mutable iter, so seek again
|
// Already seeked mutable iter, so seek again
|
||||||
@ -410,7 +410,7 @@ void ForwardIterator::SeekInternal(const Slice& internal_key,
|
|||||||
if (seek_to_first) {
|
if (seek_to_first) {
|
||||||
is_prev_set_ = false;
|
is_prev_set_ = false;
|
||||||
} else {
|
} else {
|
||||||
prev_key_.SetKey(internal_key);
|
prev_key_.SetInternalKey(internal_key);
|
||||||
is_prev_set_ = true;
|
is_prev_set_ = true;
|
||||||
is_prev_inclusive_ = true;
|
is_prev_inclusive_ = true;
|
||||||
}
|
}
|
||||||
@ -449,15 +449,15 @@ void ForwardIterator::Next() {
|
|||||||
if (is_prev_set_ && prefix_extractor_) {
|
if (is_prev_set_ && prefix_extractor_) {
|
||||||
// advance prev_key_ to current_ only if they share the same prefix
|
// advance prev_key_ to current_ only if they share the same prefix
|
||||||
update_prev_key =
|
update_prev_key =
|
||||||
prefix_extractor_->Transform(prev_key_.GetKey()).compare(
|
prefix_extractor_->Transform(prev_key_.GetUserKey())
|
||||||
prefix_extractor_->Transform(current_->key())) == 0;
|
.compare(prefix_extractor_->Transform(current_->key())) == 0;
|
||||||
} else {
|
} else {
|
||||||
update_prev_key = true;
|
update_prev_key = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (update_prev_key) {
|
if (update_prev_key) {
|
||||||
prev_key_.SetKey(current_->key());
|
prev_key_.SetInternalKey(current_->key());
|
||||||
is_prev_set_ = true;
|
is_prev_set_ = true;
|
||||||
is_prev_inclusive_ = false;
|
is_prev_inclusive_ = false;
|
||||||
}
|
}
|
||||||
@ -476,7 +476,7 @@ void ForwardIterator::Next() {
|
|||||||
current_ = nullptr;
|
current_ = nullptr;
|
||||||
}
|
}
|
||||||
if (update_prev_key) {
|
if (update_prev_key) {
|
||||||
mutable_iter_->Seek(prev_key_.GetKey());
|
mutable_iter_->Seek(prev_key_.GetInternalKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -776,7 +776,7 @@ bool ForwardIterator::NeedToSeekImmutable(const Slice& target) {
|
|||||||
if (!valid_ || !current_ || !is_prev_set_ || !immutable_status_.ok()) {
|
if (!valid_ || !current_ || !is_prev_set_ || !immutable_status_.ok()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Slice prev_key = prev_key_.GetKey();
|
Slice prev_key = prev_key_.GetInternalKey();
|
||||||
if (prefix_extractor_ && prefix_extractor_->Transform(target).compare(
|
if (prefix_extractor_ && prefix_extractor_->Transform(target).compare(
|
||||||
prefix_extractor_->Transform(prev_key)) != 0) {
|
prefix_extractor_->Transform(prev_key)) != 0) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -196,12 +196,12 @@ void ManagedIterator::Next() {
|
|||||||
|
|
||||||
Slice ManagedIterator::key() const {
|
Slice ManagedIterator::key() const {
|
||||||
assert(valid_);
|
assert(valid_);
|
||||||
return cached_key_.GetKey();
|
return cached_key_.GetUserKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
Slice ManagedIterator::value() const {
|
Slice ManagedIterator::value() const {
|
||||||
assert(valid_);
|
assert(valid_);
|
||||||
return cached_value_.GetKey();
|
return cached_value_.GetUserKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status ManagedIterator::status() const { return status_; }
|
Status ManagedIterator::status() const { return status_; }
|
||||||
@ -221,8 +221,8 @@ void ManagedIterator::UpdateCurrent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_ = Status::OK();
|
status_ = Status::OK();
|
||||||
cached_key_.SetKey(mutable_iter_->key());
|
cached_key_.SetUserKey(mutable_iter_->key());
|
||||||
cached_value_.SetKey(mutable_iter_->value());
|
cached_value_.SetUserKey(mutable_iter_->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManagedIterator::ReleaseIter(bool only_old) {
|
void ManagedIterator::ReleaseIter(bool only_old) {
|
||||||
|
@ -286,7 +286,7 @@ Status TableCache::Get(const ReadOptions& options,
|
|||||||
user_key.size());
|
user_key.size());
|
||||||
|
|
||||||
if (auto row_handle =
|
if (auto row_handle =
|
||||||
ioptions_.row_cache->Lookup(row_cache_key.GetKey())) {
|
ioptions_.row_cache->Lookup(row_cache_key.GetUserKey())) {
|
||||||
auto found_row_cache_entry = static_cast<const std::string*>(
|
auto found_row_cache_entry = static_cast<const std::string*>(
|
||||||
ioptions_.row_cache->Value(row_handle));
|
ioptions_.row_cache->Value(row_handle));
|
||||||
replayGetContextLog(*found_row_cache_entry, user_key, get_context);
|
replayGetContextLog(*found_row_cache_entry, user_key, get_context);
|
||||||
@ -343,7 +343,7 @@ Status TableCache::Get(const ReadOptions& options,
|
|||||||
size_t charge =
|
size_t charge =
|
||||||
row_cache_key.Size() + row_cache_entry->size() + sizeof(std::string);
|
row_cache_key.Size() + row_cache_entry->size() + sizeof(std::string);
|
||||||
void* row_ptr = new std::string(std::move(*row_cache_entry));
|
void* row_ptr = new std::string(std::move(*row_cache_entry));
|
||||||
ioptions_.row_cache->Insert(row_cache_key.GetKey(), row_ptr, charge,
|
ioptions_.row_cache->Insert(row_cache_key.GetUserKey(), row_ptr, charge,
|
||||||
&DeleteEntry<std::string>);
|
&DeleteEntry<std::string>);
|
||||||
}
|
}
|
||||||
#endif // ROCKSDB_LITE
|
#endif // ROCKSDB_LITE
|
||||||
|
@ -433,7 +433,7 @@ class HashLinkListRep : public MemTableRep {
|
|||||||
} else {
|
} else {
|
||||||
IterKey encoded_key;
|
IterKey encoded_key;
|
||||||
encoded_key.EncodeLengthPrefixedKey(k);
|
encoded_key.EncodeLengthPrefixedKey(k);
|
||||||
skip_list_iter_->Seek(encoded_key.GetKey().data());
|
skip_list_iter_->Seek(encoded_key.GetUserKey().data());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The bucket is organized as a linked list
|
// The bucket is organized as a linked list
|
||||||
|
@ -87,7 +87,7 @@ void BlockIter::Prev() {
|
|||||||
const Slice current_key(key_ptr, current_prev_entry.key_size);
|
const Slice current_key(key_ptr, current_prev_entry.key_size);
|
||||||
|
|
||||||
current_ = current_prev_entry.offset;
|
current_ = current_prev_entry.offset;
|
||||||
key_.SetKey(current_key, false /* copy */);
|
key_.SetInternalKey(current_key, false /* copy */);
|
||||||
value_ = current_prev_entry.value;
|
value_ = current_prev_entry.value;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -155,7 +155,7 @@ void BlockIter::Seek(const Slice& target) {
|
|||||||
// Linear search (within restart block) for first key >= target
|
// Linear search (within restart block) for first key >= target
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!ParseNextKey() || Compare(key_.GetKey(), target) >= 0) {
|
if (!ParseNextKey() || Compare(key_.GetInternalKey(), target) >= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -176,12 +176,12 @@ void BlockIter::SeekForPrev(const Slice& target) {
|
|||||||
SeekToRestartPoint(index);
|
SeekToRestartPoint(index);
|
||||||
// Linear search (within restart block) for first key >= target
|
// Linear search (within restart block) for first key >= target
|
||||||
|
|
||||||
while (ParseNextKey() && Compare(key_.GetKey(), target) < 0) {
|
while (ParseNextKey() && Compare(key_.GetInternalKey(), target) < 0) {
|
||||||
}
|
}
|
||||||
if (!Valid()) {
|
if (!Valid()) {
|
||||||
SeekToLast();
|
SeekToLast();
|
||||||
} else {
|
} else {
|
||||||
while (Valid() && Compare(key_.GetKey(), target) > 0) {
|
while (Valid() && Compare(key_.GetInternalKey(), target) > 0) {
|
||||||
Prev();
|
Prev();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,7 +234,7 @@ bool BlockIter::ParseNextKey() {
|
|||||||
if (shared == 0) {
|
if (shared == 0) {
|
||||||
// If this key dont share any bytes with prev key then we dont need
|
// If this key dont share any bytes with prev key then we dont need
|
||||||
// to decode it and can use it's address in the block directly.
|
// to decode it and can use it's address in the block directly.
|
||||||
key_.SetKey(Slice(p, non_shared), false /* copy */);
|
key_.SetInternalKey(Slice(p, non_shared), false /* copy */);
|
||||||
key_pinned_ = true;
|
key_pinned_ = true;
|
||||||
} else {
|
} else {
|
||||||
// This key share `shared` bytes with prev key, we need to decode it
|
// This key share `shared` bytes with prev key, we need to decode it
|
||||||
@ -246,8 +246,8 @@ bool BlockIter::ParseNextKey() {
|
|||||||
// If we are reading a file with a global sequence number we should
|
// If we are reading a file with a global sequence number we should
|
||||||
// expect that all encoded sequence numbers are zeros and all value
|
// expect that all encoded sequence numbers are zeros and all value
|
||||||
// types are kTypeValue
|
// types are kTypeValue
|
||||||
assert(GetInternalKeySeqno(key_.GetKey()) == 0);
|
assert(GetInternalKeySeqno(key_.GetInternalKey()) == 0);
|
||||||
assert(ExtractValueType(key_.GetKey()) == ValueType::kTypeValue);
|
assert(ExtractValueType(key_.GetInternalKey()) == ValueType::kTypeValue);
|
||||||
|
|
||||||
if (key_pinned_) {
|
if (key_pinned_) {
|
||||||
// TODO(tec): Investigate updating the seqno in the loaded block
|
// TODO(tec): Investigate updating the seqno in the loaded block
|
||||||
|
@ -264,7 +264,7 @@ class BlockIter : public InternalIterator {
|
|||||||
virtual Status status() const override { return status_; }
|
virtual Status status() const override { return status_; }
|
||||||
virtual Slice key() const override {
|
virtual Slice key() const override {
|
||||||
assert(Valid());
|
assert(Valid());
|
||||||
return key_.GetKey();
|
return key_.GetInternalKey();
|
||||||
}
|
}
|
||||||
virtual Slice value() const override {
|
virtual Slice value() const override {
|
||||||
assert(Valid());
|
assert(Valid());
|
||||||
|
@ -124,7 +124,7 @@ class CuckooBuilderTest : public testing::Test {
|
|||||||
std::string GetInternalKey(Slice user_key, bool zero_seqno) {
|
std::string GetInternalKey(Slice user_key, bool zero_seqno) {
|
||||||
IterKey ikey;
|
IterKey ikey;
|
||||||
ikey.SetInternalKey(user_key, zero_seqno ? 0 : 1000, kTypeValue);
|
ikey.SetInternalKey(user_key, zero_seqno ? 0 : 1000, kTypeValue);
|
||||||
return ikey.GetKey().ToString();
|
return ikey.GetInternalKey().ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t NextPowOf2(uint64_t num) {
|
uint64_t NextPowOf2(uint64_t num) {
|
||||||
|
@ -322,7 +322,7 @@ void CuckooTableIterator::PrepareKVAtCurrIdx() {
|
|||||||
curr_key_.SetInternalKey(Slice(offset, reader_->user_key_length_),
|
curr_key_.SetInternalKey(Slice(offset, reader_->user_key_length_),
|
||||||
0, kTypeValue);
|
0, kTypeValue);
|
||||||
} else {
|
} else {
|
||||||
curr_key_.SetKey(Slice(offset, reader_->key_length_));
|
curr_key_.SetInternalKey(Slice(offset, reader_->key_length_));
|
||||||
}
|
}
|
||||||
curr_value_ = Slice(offset + reader_->key_length_, reader_->value_length_);
|
curr_value_ = Slice(offset + reader_->key_length_, reader_->value_length_);
|
||||||
}
|
}
|
||||||
@ -352,7 +352,7 @@ void CuckooTableIterator::Prev() {
|
|||||||
|
|
||||||
Slice CuckooTableIterator::key() const {
|
Slice CuckooTableIterator::key() const {
|
||||||
assert(Valid());
|
assert(Valid());
|
||||||
return curr_key_.GetKey();
|
return curr_key_.GetInternalKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
Slice CuckooTableIterator::value() const {
|
Slice CuckooTableIterator::value() const {
|
||||||
|
@ -376,7 +376,7 @@ void GetKeys(uint64_t num, std::vector<std::string>* keys) {
|
|||||||
keys->clear();
|
keys->clear();
|
||||||
IterKey k;
|
IterKey k;
|
||||||
k.SetInternalKey("", 0, kTypeValue);
|
k.SetInternalKey("", 0, kTypeValue);
|
||||||
std::string internal_key_suffix = k.GetKey().ToString();
|
std::string internal_key_suffix = k.GetInternalKey().ToString();
|
||||||
ASSERT_EQ(static_cast<size_t>(8), internal_key_suffix.size());
|
ASSERT_EQ(static_cast<size_t>(8), internal_key_suffix.size());
|
||||||
for (uint64_t key_idx = 0; key_idx < num; ++key_idx) {
|
for (uint64_t key_idx = 0; key_idx < num; ++key_idx) {
|
||||||
uint64_t value = 2 * key_idx;
|
uint64_t value = 2 * key_idx;
|
||||||
|
@ -112,10 +112,10 @@ Status PlainTableKeyEncoder::AppendKey(const Slice& key,
|
|||||||
|
|
||||||
Slice prefix =
|
Slice prefix =
|
||||||
prefix_extractor_->Transform(Slice(key.data(), user_key_size));
|
prefix_extractor_->Transform(Slice(key.data(), user_key_size));
|
||||||
if (key_count_for_prefix_ == 0 || prefix != pre_prefix_.GetKey() ||
|
if (key_count_for_prefix_ == 0 || prefix != pre_prefix_.GetUserKey() ||
|
||||||
key_count_for_prefix_ % index_sparseness_ == 0) {
|
key_count_for_prefix_ % index_sparseness_ == 0) {
|
||||||
key_count_for_prefix_ = 1;
|
key_count_for_prefix_ = 1;
|
||||||
pre_prefix_.SetKey(prefix);
|
pre_prefix_.SetUserKey(prefix);
|
||||||
size_bytes_pos += EncodeSize(kFullKey, user_key_size, size_bytes);
|
size_bytes_pos += EncodeSize(kFullKey, user_key_size, size_bytes);
|
||||||
Status s = file->Append(Slice(size_bytes, size_bytes_pos));
|
Status s = file->Append(Slice(size_bytes, size_bytes_pos));
|
||||||
if (!s.ok()) {
|
if (!s.ok()) {
|
||||||
@ -128,10 +128,11 @@ Status PlainTableKeyEncoder::AppendKey(const Slice& key,
|
|||||||
// For second key within a prefix, need to encode prefix length
|
// For second key within a prefix, need to encode prefix length
|
||||||
size_bytes_pos +=
|
size_bytes_pos +=
|
||||||
EncodeSize(kPrefixFromPreviousKey,
|
EncodeSize(kPrefixFromPreviousKey,
|
||||||
static_cast<uint32_t>(pre_prefix_.GetKey().size()),
|
static_cast<uint32_t>(pre_prefix_.GetUserKey().size()),
|
||||||
size_bytes + size_bytes_pos);
|
size_bytes + size_bytes_pos);
|
||||||
}
|
}
|
||||||
uint32_t prefix_len = static_cast<uint32_t>(pre_prefix_.GetKey().size());
|
uint32_t prefix_len =
|
||||||
|
static_cast<uint32_t>(pre_prefix_.GetUserKey().size());
|
||||||
size_bytes_pos += EncodeSize(kKeySuffix, user_key_size - prefix_len,
|
size_bytes_pos += EncodeSize(kKeySuffix, user_key_size - prefix_len,
|
||||||
size_bytes + size_bytes_pos);
|
size_bytes + size_bytes_pos);
|
||||||
Status s = file->Append(Slice(size_bytes, size_bytes_pos));
|
Status s = file->Append(Slice(size_bytes, size_bytes_pos));
|
||||||
@ -315,9 +316,10 @@ Status PlainTableKeyDecoder::NextPlainEncodingKey(uint32_t start_offset,
|
|||||||
}
|
}
|
||||||
if (!file_reader_.file_info()->is_mmap_mode) {
|
if (!file_reader_.file_info()->is_mmap_mode) {
|
||||||
cur_key_.SetInternalKey(*parsed_key);
|
cur_key_.SetInternalKey(*parsed_key);
|
||||||
parsed_key->user_key = Slice(cur_key_.GetKey().data(), user_key_size);
|
parsed_key->user_key =
|
||||||
|
Slice(cur_key_.GetInternalKey().data(), user_key_size);
|
||||||
if (internal_key != nullptr) {
|
if (internal_key != nullptr) {
|
||||||
*internal_key = cur_key_.GetKey();
|
*internal_key = cur_key_.GetInternalKey();
|
||||||
}
|
}
|
||||||
} else if (internal_key != nullptr) {
|
} else if (internal_key != nullptr) {
|
||||||
if (decoded_internal_key_valid) {
|
if (decoded_internal_key_valid) {
|
||||||
@ -325,7 +327,7 @@ Status PlainTableKeyDecoder::NextPlainEncodingKey(uint32_t start_offset,
|
|||||||
} else {
|
} else {
|
||||||
// Need to copy out the internal key
|
// Need to copy out the internal key
|
||||||
cur_key_.SetInternalKey(*parsed_key);
|
cur_key_.SetInternalKey(*parsed_key);
|
||||||
*internal_key = cur_key_.GetKey();
|
*internal_key = cur_key_.GetInternalKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
@ -369,12 +371,13 @@ Status PlainTableKeyDecoder::NextPrefixEncodingKey(
|
|||||||
// users, because after reading value for the key, the key might
|
// users, because after reading value for the key, the key might
|
||||||
// be invalid.
|
// be invalid.
|
||||||
cur_key_.SetInternalKey(*parsed_key);
|
cur_key_.SetInternalKey(*parsed_key);
|
||||||
saved_user_key_ = cur_key_.GetKey();
|
saved_user_key_ = cur_key_.GetUserKey();
|
||||||
if (!file_reader_.file_info()->is_mmap_mode) {
|
if (!file_reader_.file_info()->is_mmap_mode) {
|
||||||
parsed_key->user_key = Slice(cur_key_.GetKey().data(), size);
|
parsed_key->user_key =
|
||||||
|
Slice(cur_key_.GetInternalKey().data(), size);
|
||||||
}
|
}
|
||||||
if (internal_key != nullptr) {
|
if (internal_key != nullptr) {
|
||||||
*internal_key = cur_key_.GetKey();
|
*internal_key = cur_key_.GetInternalKey();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (internal_key != nullptr) {
|
if (internal_key != nullptr) {
|
||||||
@ -421,16 +424,16 @@ Status PlainTableKeyDecoder::NextPrefixEncodingKey(
|
|||||||
cur_key_.Reserve(prefix_len_ + size);
|
cur_key_.Reserve(prefix_len_ + size);
|
||||||
cur_key_.SetInternalKey(tmp, *parsed_key);
|
cur_key_.SetInternalKey(tmp, *parsed_key);
|
||||||
parsed_key->user_key =
|
parsed_key->user_key =
|
||||||
Slice(cur_key_.GetKey().data(), prefix_len_ + size);
|
Slice(cur_key_.GetInternalKey().data(), prefix_len_ + size);
|
||||||
saved_user_key_ = cur_key_.GetKey();
|
saved_user_key_ = cur_key_.GetUserKey();
|
||||||
} else {
|
} else {
|
||||||
cur_key_.Reserve(prefix_len_ + size);
|
cur_key_.Reserve(prefix_len_ + size);
|
||||||
cur_key_.SetInternalKey(Slice(saved_user_key_.data(), prefix_len_),
|
cur_key_.SetInternalKey(Slice(saved_user_key_.data(), prefix_len_),
|
||||||
*parsed_key);
|
*parsed_key);
|
||||||
}
|
}
|
||||||
parsed_key->user_key = ExtractUserKey(cur_key_.GetKey());
|
parsed_key->user_key = cur_key_.GetUserKey();
|
||||||
if (internal_key != nullptr) {
|
if (internal_key != nullptr) {
|
||||||
*internal_key = cur_key_.GetKey();
|
*internal_key = cur_key_.GetInternalKey();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user