|
@ -16,6 +16,7 @@ |
|
|
#include "leveldb/table_builder.h" |
|
|
#include "leveldb/table_builder.h" |
|
|
#include "util/coding.h" |
|
|
#include "util/coding.h" |
|
|
#include "util/logging.h" |
|
|
#include "util/logging.h" |
|
|
|
|
|
#include "iostream" |
|
|
|
|
|
|
|
|
namespace leveldb { |
|
|
namespace leveldb { |
|
|
|
|
|
|
|
@ -69,17 +70,19 @@ static const SequenceNumber kMaxSequenceNumber = ((0x1ull << 56) - 1); |
|
|
struct ParsedInternalKey { |
|
|
struct ParsedInternalKey { |
|
|
Slice user_key; |
|
|
Slice user_key; |
|
|
SequenceNumber sequence; |
|
|
SequenceNumber sequence; |
|
|
|
|
|
uint64_t deadTime; |
|
|
ValueType type; |
|
|
ValueType type; |
|
|
|
|
|
|
|
|
ParsedInternalKey() {} // Intentionally left uninitialized (for speed) |
|
|
ParsedInternalKey() {} // Intentionally left uninitialized (for speed) |
|
|
ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t) |
|
|
|
|
|
: user_key(u), sequence(seq), type(t) {} |
|
|
|
|
|
|
|
|
ParsedInternalKey(const Slice& u, const SequenceNumber& seq, |
|
|
|
|
|
ValueType t, uint64_t d = 0) |
|
|
|
|
|
: user_key(u), sequence(seq), type(t), deadTime(d) {} |
|
|
std::string DebugString() const; |
|
|
std::string DebugString() const; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// Return the length of the encoding of "key". |
|
|
// Return the length of the encoding of "key". |
|
|
inline size_t InternalKeyEncodingLength(const ParsedInternalKey& key) { |
|
|
inline size_t InternalKeyEncodingLength(const ParsedInternalKey& key) { |
|
|
return key.user_key.size() + 8; |
|
|
|
|
|
|
|
|
return key.user_key.size() + 8 + (key.deadTime != 0) * 8; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Append the serialization of "key" to *result. |
|
|
// Append the serialization of "key" to *result. |
|
@ -94,7 +97,13 @@ bool ParseInternalKey(const Slice& internal_key, ParsedInternalKey* result); |
|
|
// Returns the user key portion of an internal key. |
|
|
// Returns the user key portion of an internal key. |
|
|
inline Slice ExtractUserKey(const Slice& internal_key) { |
|
|
inline Slice ExtractUserKey(const Slice& internal_key) { |
|
|
assert(internal_key.size() >= 8); |
|
|
assert(internal_key.size() >= 8); |
|
|
return Slice(internal_key.data(), internal_key.size() - 8); |
|
|
|
|
|
|
|
|
uint64_t num = DecodeFixed64(internal_key.data() + internal_key.size() - 8); |
|
|
|
|
|
uint8_t havettl = (num & 0b10) >> 1; |
|
|
|
|
|
uint8_t islookup = (num & 0b100) >> 2; |
|
|
|
|
|
size_t klen = internal_key.size() - 8; |
|
|
|
|
|
if(havettl || islookup) klen -= 8; |
|
|
|
|
|
Slice user_key = Slice(internal_key.data(), klen); |
|
|
|
|
|
return user_key; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// A comparator for internal keys that uses a specified comparator for |
|
|
// A comparator for internal keys that uses a specified comparator for |
|
@ -137,8 +146,9 @@ class InternalKey { |
|
|
|
|
|
|
|
|
public: |
|
|
public: |
|
|
InternalKey() {} // Leave rep_ as empty to indicate it is invalid |
|
|
InternalKey() {} // Leave rep_ as empty to indicate it is invalid |
|
|
InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) { |
|
|
|
|
|
AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t)); |
|
|
|
|
|
|
|
|
InternalKey(const Slice& user_key, SequenceNumber s, |
|
|
|
|
|
ValueType t, uint64_t deadTime = 0) { |
|
|
|
|
|
AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t, deadTime)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool DecodeFrom(const Slice& s) { |
|
|
bool DecodeFrom(const Slice& s) { |
|
@ -170,13 +180,21 @@ inline int InternalKeyComparator::Compare(const InternalKey& a, |
|
|
|
|
|
|
|
|
inline bool ParseInternalKey(const Slice& internal_key, |
|
|
inline bool ParseInternalKey(const Slice& internal_key, |
|
|
ParsedInternalKey* result) { |
|
|
ParsedInternalKey* result) { |
|
|
|
|
|
//不确定需不需要标识islookup,先没改 |
|
|
const size_t n = internal_key.size(); |
|
|
const size_t n = internal_key.size(); |
|
|
if (n < 8) return false; |
|
|
if (n < 8) return false; |
|
|
uint64_t num = DecodeFixed64(internal_key.data() + n - 8); |
|
|
|
|
|
uint8_t c = num & 0xff; |
|
|
|
|
|
result->sequence = num >> 8; |
|
|
|
|
|
result->type = static_cast<ValueType>(c); |
|
|
|
|
|
result->user_key = Slice(internal_key.data(), n - 8); |
|
|
|
|
|
|
|
|
uint64_t tag = DecodeFixed64(internal_key.data() + n - 8); |
|
|
|
|
|
uint8_t c = tag & 0xff; |
|
|
|
|
|
uint8_t havettl = (c & 0b10) >> 1; |
|
|
|
|
|
result->sequence = tag >> 8; |
|
|
|
|
|
result->type = static_cast<ValueType>(c & 0b1); |
|
|
|
|
|
if(havettl){ |
|
|
|
|
|
result->deadTime = DecodeFixed64(internal_key.data() + n - 16); |
|
|
|
|
|
result->user_key = Slice(internal_key.data(), n - 16); |
|
|
|
|
|
} else { |
|
|
|
|
|
result->deadTime = 0; |
|
|
|
|
|
result->user_key = Slice(internal_key.data(), n - 8); |
|
|
|
|
|
} |
|
|
return (c <= static_cast<uint8_t>(kTypeValue)); |
|
|
return (c <= static_cast<uint8_t>(kTypeValue)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -185,7 +203,7 @@ class LookupKey { |
|
|
public: |
|
|
public: |
|
|
// Initialize *this for looking up user_key at a snapshot with |
|
|
// Initialize *this for looking up user_key at a snapshot with |
|
|
// the specified sequence number. |
|
|
// the specified sequence number. |
|
|
LookupKey(const Slice& user_key, SequenceNumber sequence); |
|
|
|
|
|
|
|
|
LookupKey(const Slice& user_key, SequenceNumber sequence, uint64_t nowTime); |
|
|
|
|
|
|
|
|
LookupKey(const LookupKey&) = delete; |
|
|
LookupKey(const LookupKey&) = delete; |
|
|
LookupKey& operator=(const LookupKey&) = delete; |
|
|
LookupKey& operator=(const LookupKey&) = delete; |
|
@ -199,14 +217,17 @@ class LookupKey { |
|
|
Slice internal_key() const { return Slice(kstart_, end_ - kstart_); } |
|
|
Slice internal_key() const { return Slice(kstart_, end_ - kstart_); } |
|
|
|
|
|
|
|
|
// Return the user key |
|
|
// Return the user key |
|
|
Slice user_key() const { return Slice(kstart_, end_ - kstart_ - 8); } |
|
|
|
|
|
|
|
|
Slice user_key() const { return Slice(kstart_, end_ - kstart_ - 16); } |
|
|
|
|
|
|
|
|
private: |
|
|
private: |
|
|
// We construct a char array of the form: |
|
|
// We construct a char array of the form: |
|
|
// klength varint32 <-- start_ |
|
|
// klength varint32 <-- start_ |
|
|
// userkey char[klength] <-- kstart_ |
|
|
// userkey char[klength] <-- kstart_ |
|
|
// tag uint64 |
|
|
|
|
|
|
|
|
// nowTime uint64 |
|
|
|
|
|
// tag uint64 最后一个字节为0000 0101 |
|
|
// <-- end_ |
|
|
// <-- end_ |
|
|
|
|
|
// 同userkey下,原本(insert时)的比较器规则为seq优先,不考虑时间 |
|
|
|
|
|
// 新增标识位(tag倒数第三位),使比较器考虑时间 |
|
|
// The array is a suitable MemTable key. |
|
|
// The array is a suitable MemTable key. |
|
|
// The suffix starting with "userkey" can be used as an InternalKey. |
|
|
// The suffix starting with "userkey" can be used as an InternalKey. |
|
|
const char* start_; |
|
|
const char* start_; |
|
|