|
@ -8,6 +8,8 @@ |
|
|
#include "leveldb/env.h"
|
|
|
#include "leveldb/env.h"
|
|
|
#include "leveldb/iterator.h"
|
|
|
#include "leveldb/iterator.h"
|
|
|
#include "util/coding.h"
|
|
|
#include "util/coding.h"
|
|
|
|
|
|
#include "ctime"
|
|
|
|
|
|
#include "iostream"
|
|
|
|
|
|
|
|
|
namespace leveldb { |
|
|
namespace leveldb { |
|
|
|
|
|
|
|
@ -74,16 +76,24 @@ class MemTableIterator : public Iterator { |
|
|
Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); } |
|
|
Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); } |
|
|
|
|
|
|
|
|
void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key, |
|
|
void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key, |
|
|
const Slice& value) { |
|
|
|
|
|
|
|
|
const Slice& value, uint64_t deadTime) { |
|
|
// Format of an entry is concatenation of:
|
|
|
// Format of an entry is concatenation of:
|
|
|
// key_size : varint32 of internal_key.size()
|
|
|
// key_size : varint32 of internal_key.size()
|
|
|
// key bytes : char[internal_key.size()]
|
|
|
// key bytes : char[internal_key.size()]
|
|
|
// tag : uint64((sequence << 8) | type)
|
|
|
// tag : uint64((sequence << 8) | type)
|
|
|
// value_size : varint32 of value.size()
|
|
|
// value_size : varint32 of value.size()
|
|
|
// value bytes : char[value.size()]
|
|
|
// value bytes : char[value.size()]
|
|
|
|
|
|
//变成
|
|
|
|
|
|
// key_size : varint32 of internal_key.size()
|
|
|
|
|
|
// key bytes : char[internal_key.size()]
|
|
|
|
|
|
// (deadTime) : uint64(可能有)
|
|
|
|
|
|
// tag : uint64((sequence << 8) | havettl << 1 | type)
|
|
|
|
|
|
// value_size : varint32 of value.size()
|
|
|
|
|
|
// value bytes : char[value.size()]
|
|
|
size_t key_size = key.size(); |
|
|
size_t key_size = key.size(); |
|
|
size_t val_size = value.size(); |
|
|
size_t val_size = value.size(); |
|
|
size_t internal_key_size = key_size + 8; |
|
|
size_t internal_key_size = key_size + 8; |
|
|
|
|
|
if(deadTime != 0) internal_key_size += 8; |
|
|
const size_t encoded_len = VarintLength(internal_key_size) + |
|
|
const size_t encoded_len = VarintLength(internal_key_size) + |
|
|
internal_key_size + VarintLength(val_size) + |
|
|
internal_key_size + VarintLength(val_size) + |
|
|
val_size; |
|
|
val_size; |
|
@ -91,22 +101,33 @@ void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key, |
|
|
char* p = EncodeVarint32(buf, internal_key_size); |
|
|
char* p = EncodeVarint32(buf, internal_key_size); |
|
|
std::memcpy(p, key.data(), key_size); |
|
|
std::memcpy(p, key.data(), key_size); |
|
|
p += key_size; |
|
|
p += key_size; |
|
|
EncodeFixed64(p, (s << 8) | type); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(deadTime == 0){ |
|
|
|
|
|
EncodeFixed64(p, (s << 8) | type); |
|
|
|
|
|
} else { |
|
|
|
|
|
EncodeFixed64(p, deadTime); |
|
|
|
|
|
p += 8; |
|
|
|
|
|
EncodeFixed64(p, (s << 8) | 0b10 | type); |
|
|
|
|
|
} |
|
|
p += 8; |
|
|
p += 8; |
|
|
|
|
|
|
|
|
p = EncodeVarint32(p, val_size); |
|
|
p = EncodeVarint32(p, val_size); |
|
|
std::memcpy(p, value.data(), val_size); |
|
|
std::memcpy(p, value.data(), val_size); |
|
|
assert(p + val_size == buf + encoded_len); |
|
|
assert(p + val_size == buf + encoded_len); |
|
|
table_.Insert(buf); |
|
|
table_.Insert(buf); |
|
|
|
|
|
std::cout << "insert:" << key.ToString() << std::endl; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) { |
|
|
bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) { |
|
|
Slice memkey = key.memtable_key(); |
|
|
Slice memkey = key.memtable_key(); |
|
|
Table::Iterator iter(&table_); |
|
|
Table::Iterator iter(&table_); |
|
|
iter.Seek(memkey.data()); |
|
|
iter.Seek(memkey.data()); |
|
|
|
|
|
std::cout << "search:" << key.user_key().ToString() << " valid?" << iter.Valid(); |
|
|
if (iter.Valid()) { |
|
|
if (iter.Valid()) { |
|
|
// entry format is:
|
|
|
// entry format is:
|
|
|
// klength varint32
|
|
|
// klength varint32
|
|
|
// userkey char[klength]
|
|
|
// userkey char[klength]
|
|
|
|
|
|
// (deadTime) uint64
|
|
|
// tag uint64
|
|
|
// tag uint64
|
|
|
// vlength varint32
|
|
|
// vlength varint32
|
|
|
// value char[vlength]
|
|
|
// value char[vlength]
|
|
@ -116,12 +137,26 @@ bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) { |
|
|
const char* entry = iter.key(); |
|
|
const char* entry = iter.key(); |
|
|
uint32_t key_length; |
|
|
uint32_t key_length; |
|
|
const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length); |
|
|
const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length); |
|
|
|
|
|
|
|
|
|
|
|
std::cout << " get:" << ExtractUserKey(Slice(key_ptr, key_length)).ToString(); |
|
|
if (comparator_.comparator.user_comparator()->Compare( |
|
|
if (comparator_.comparator.user_comparator()->Compare( |
|
|
Slice(key_ptr, key_length - 8), key.user_key()) == 0) { |
|
|
|
|
|
|
|
|
ExtractUserKey(Slice(key_ptr, key_length)), key.user_key()) == 0) { |
|
|
// Correct user key
|
|
|
// Correct user key
|
|
|
const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); |
|
|
const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); |
|
|
switch (static_cast<ValueType>(tag & 0xff)) { |
|
|
|
|
|
|
|
|
switch (static_cast<ValueType>(tag & 0x01)) { |
|
|
case kTypeValue: { |
|
|
case kTypeValue: { |
|
|
|
|
|
uint8_t havettl = (tag & 0xff) >> 1; |
|
|
|
|
|
if(havettl){ |
|
|
|
|
|
time_t nowTime; |
|
|
|
|
|
time(&nowTime); |
|
|
|
|
|
assert(nowTime > 0); |
|
|
|
|
|
const uint64_t deadTime = DecodeFixed64(key_ptr + key_length - 16); |
|
|
|
|
|
if(static_cast<uint64_t>(nowTime) > deadTime){ //过期了
|
|
|
|
|
|
std::cout << nowTime << "dead:" << deadTime << std::endl; |
|
|
|
|
|
*s = Status::NotFound(Slice()); |
|
|
|
|
|
return true; //todo:之前有没过期的key
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
Slice v = GetLengthPrefixedSlice(key_ptr + key_length); |
|
|
Slice v = GetLengthPrefixedSlice(key_ptr + key_length); |
|
|
value->assign(v.data(), v.size()); |
|
|
value->assign(v.data(), v.size()); |
|
|
return true; |
|
|
return true; |
|
|