diff --git a/db/db_impl.cc b/db/db_impl.cc index 1061c48804..c5caec068f 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -2523,9 +2523,9 @@ Status DBImpl::ProcessKeyValueCompaction( Status status; std::string compaction_filter_value; ParsedInternalKey ikey; - std::string current_user_key; + IterKey current_user_key; bool has_current_user_key = false; - std::vector delete_key; // for compaction filter + IterKey delete_key; SequenceNumber last_sequence_for_key __attribute__((unused)) = kMaxSequenceNumber; SequenceNumber visible_in_snapshot = kMaxSequenceNumber; @@ -2589,16 +2589,16 @@ Status DBImpl::ProcessKeyValueCompaction( // Do not hide error keys // TODO: error key stays in db forever? Figure out the intention/rationale // v10 error v8 : we cannot hide v8 even though it's pretty obvious. - current_user_key.clear(); + current_user_key.Clear(); has_current_user_key = false; last_sequence_for_key = kMaxSequenceNumber; visible_in_snapshot = kMaxSequenceNumber; } else { if (!has_current_user_key || cfd->user_comparator()->Compare(ikey.user_key, - Slice(current_user_key)) != 0) { + current_user_key.GetKey()) != 0) { // First occurrence of this user key - current_user_key.assign(ikey.user_key.data(), ikey.user_key.size()); + current_user_key.SetUserKey(ikey.user_key); has_current_user_key = true; last_sequence_for_key = kMaxSequenceNumber; visible_in_snapshot = kMaxSequenceNumber; @@ -2617,13 +2617,11 @@ Status DBImpl::ProcessKeyValueCompaction( compact->compaction->level(), ikey.user_key, value, &compaction_filter_value, &value_changed); if (to_delete) { - // make a copy of the original key - delete_key.assign(key.data(), key.data() + key.size()); - // convert it to a delete - UpdateInternalKey(&delete_key[0], delete_key.size(), - ikey.sequence, kTypeDeletion); + // make a copy of the original key and convert it to a delete + delete_key.SetInternalKey(ExtractUserKey(key), ikey.sequence, + kTypeDeletion); // anchor the key again - key = Slice(&delete_key[0], delete_key.size()); + key = delete_key.GetKey(); // needed because ikey is backed by key ParseInternalKey(key, &ikey); // no value associated with delete diff --git a/db/dbformat.h b/db/dbformat.h index 6ac53074a0..99925d2845 100644 --- a/db/dbformat.h +++ b/db/dbformat.h @@ -242,47 +242,17 @@ class IterKey { public: IterKey() : key_(space_), buf_size_(sizeof(space_)), key_size_(0) {} - ~IterKey() { Clear(); } + ~IterKey() { ResetBuffer(); } - Slice GetKey() const { - if (key_ != nullptr) { - return Slice(key_, key_size_); - } else { - return Slice(); - } - } + Slice GetKey() const { return Slice(key_, key_size_); } - bool Valid() const { return key_ != nullptr; } - - void Clear() { - if (key_ != nullptr && key_ != space_) { - delete[] key_; - } - key_ = space_; - buf_size_ = sizeof(buf_size_); - } - - // Enlarge the buffer size if needed based on key_size. - // By default, static allocated buffer is used. Once there is a key - // larger than the static allocated buffer, another buffer is dynamically - // allocated, until a larger key buffer is requested. In that case, we - // reallocate buffer and delete the old one. - void EnlargeBufferIfNeeded(size_t key_size) { - // If size is smaller than buffer size, continue using current buffer, - // or the static allocated one, as default - if (key_size > buf_size_) { - // Need to enlarge the buffer. - Clear(); - key_ = new char[key_size]; - buf_size_ = key_size; - } - key_size_ = key_size; - } + void Clear() { key_size_ = 0; } void SetUserKey(const Slice& user_key) { size_t size = user_key.size(); EnlargeBufferIfNeeded(size); memcpy(key_, user_key.data(), size); + key_size_ = size; } void SetInternalKey(const Slice& user_key, SequenceNumber s, @@ -291,6 +261,7 @@ class IterKey { EnlargeBufferIfNeeded(usize + sizeof(uint64_t)); memcpy(key_, user_key.data(), usize); EncodeFixed64(key_ + usize, PackSequenceAndType(s, value_type)); + key_size_ = usize + sizeof(uint64_t); } void SetInternalKey(const ParsedInternalKey& parsed_key) { @@ -303,6 +274,31 @@ class IterKey { size_t key_size_; char space_[32]; // Avoid allocation for short keys + void ResetBuffer() { + if (key_ != nullptr && key_ != space_) { + delete[] key_; + } + key_ = space_; + buf_size_ = sizeof(buf_size_); + key_size_ = 0; + } + + // Enlarge the buffer size if needed based on key_size. + // By default, static allocated buffer is used. Once there is a key + // larger than the static allocated buffer, another buffer is dynamically + // allocated, until a larger key buffer is requested. In that case, we + // reallocate buffer and delete the old one. + void EnlargeBufferIfNeeded(size_t key_size) { + // If size is smaller than buffer size, continue using current buffer, + // or the static allocated one, as default + if (key_size > buf_size_) { + // Need to enlarge the buffer. + ResetBuffer(); + key_ = new char[key_size]; + buf_size_ = key_size; + } + } + // No copying allowed IterKey(const IterKey&) = delete; void operator=(const IterKey&) = delete;