|
@ -8,6 +8,7 @@ |
|
|
#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 "include/leveldb/write_batch.h"
|
|
|
|
|
|
|
|
|
namespace leveldb { |
|
|
namespace leveldb { |
|
|
|
|
|
|
|
@ -99,40 +100,107 @@ void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key, |
|
|
table_.Insert(buf); |
|
|
table_.Insert(buf); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) { //燕改
|
|
|
|
|
|
// Slice memkey = key.memtable_key();
|
|
|
|
|
|
// Table::Iterator iter(&table_);
|
|
|
|
|
|
// iter.Seek(memkey.data());
|
|
|
|
|
|
// if (iter.Valid()) {// 获取跳表项的内容
|
|
|
|
|
|
// // entry format is:
|
|
|
|
|
|
// // klength varint32
|
|
|
|
|
|
// // userkey char[klength]
|
|
|
|
|
|
// // tag uint64
|
|
|
|
|
|
// // vlength varint32
|
|
|
|
|
|
// // value char[vlength]
|
|
|
|
|
|
// // Check that it belongs to same user key. We do not check the
|
|
|
|
|
|
// // sequence number since the Seek() call above should have skipped
|
|
|
|
|
|
// // all entries with overly large sequence numbers.
|
|
|
|
|
|
// const char* entry = iter.key();
|
|
|
|
|
|
// uint32_t key_length;
|
|
|
|
|
|
// const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length);
|
|
|
|
|
|
// if (comparator_.comparator.user_comparator()->Compare(// 比较键值
|
|
|
|
|
|
// Slice(key_ptr, key_length - 8), key.user_key()) == 0) {
|
|
|
|
|
|
// // Correct user key
|
|
|
|
|
|
// const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8);
|
|
|
|
|
|
// switch (static_cast<ValueType>(tag & 0xff)) {
|
|
|
|
|
|
// case kTypeValue: {
|
|
|
|
|
|
// // Slice v = GetLengthPrefixedSlice(key_ptr + key_length);
|
|
|
|
|
|
// // value->assign(v.data(), v.size());
|
|
|
|
|
|
// // return true;
|
|
|
|
|
|
|
|
|
|
|
|
// // 获取过期时间戳,燕改
|
|
|
|
|
|
// Slice v = GetLengthPrefixedSlice(key_ptr + key_length);
|
|
|
|
|
|
// uint64_t expire_time = DecodeFixed64(v.data() + v.size() - sizeof(uint64_t));
|
|
|
|
|
|
|
|
|
|
|
|
// // 检查是否已过期
|
|
|
|
|
|
// uint64_t current_time = Env::Default()->NowMicros() / 1000000; // 当前时间(秒)
|
|
|
|
|
|
// if (expire_time > 0 && expire_time < current_time) {
|
|
|
|
|
|
// *s = Status::NotFound("Key has expired"); // 已过期
|
|
|
|
|
|
// return false;
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// // 未过期,返回值
|
|
|
|
|
|
// value->assign(v.data() + 8, v.size() - 8); // 去除前8字节的时间戳
|
|
|
|
|
|
// return true;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// case kTypeDeletion:
|
|
|
|
|
|
// *s = Status::NotFound(Slice());
|
|
|
|
|
|
// return true;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// return false;
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
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(); |
|
|
|
|
|
Table::Iterator iter(&table_); |
|
|
|
|
|
iter.Seek(memkey.data()); |
|
|
|
|
|
if (iter.Valid()) { |
|
|
|
|
|
// entry format is:
|
|
|
|
|
|
// klength varint32
|
|
|
|
|
|
// userkey char[klength]
|
|
|
|
|
|
// tag uint64
|
|
|
|
|
|
// vlength varint32
|
|
|
|
|
|
// value char[vlength]
|
|
|
|
|
|
// Check that it belongs to same user key. We do not check the
|
|
|
|
|
|
// sequence number since the Seek() call above should have skipped
|
|
|
|
|
|
// all entries with overly large sequence numbers.
|
|
|
|
|
|
const char* entry = iter.key(); |
|
|
|
|
|
uint32_t key_length; |
|
|
|
|
|
const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length); |
|
|
|
|
|
if (comparator_.comparator.user_comparator()->Compare( |
|
|
|
|
|
Slice(key_ptr, key_length - 8), key.user_key()) == 0) { |
|
|
|
|
|
// Correct user key
|
|
|
|
|
|
const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); |
|
|
|
|
|
switch (static_cast<ValueType>(tag & 0xff)) { |
|
|
|
|
|
case kTypeValue: { |
|
|
|
|
|
Slice v = GetLengthPrefixedSlice(key_ptr + key_length); |
|
|
|
|
|
value->assign(v.data(), v.size()); |
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
Slice memkey = key.memtable_key(); |
|
|
|
|
|
Table::Iterator iter(&table_); |
|
|
|
|
|
iter.Seek(memkey.data()); |
|
|
|
|
|
|
|
|
|
|
|
if (iter.Valid()) { // 获取跳表项的内容
|
|
|
|
|
|
const char* entry = iter.key(); |
|
|
|
|
|
uint32_t key_length; |
|
|
|
|
|
const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length); |
|
|
|
|
|
|
|
|
|
|
|
if (comparator_.comparator.user_comparator()->Compare( |
|
|
|
|
|
Slice(key_ptr, key_length - 8), key.user_key()) == 0) { |
|
|
|
|
|
const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); |
|
|
|
|
|
switch (static_cast<ValueType>(tag & 0xff)) { |
|
|
|
|
|
case kTypeValue: { |
|
|
|
|
|
// 获取存储的值和时间戳
|
|
|
|
|
|
Slice v = GetLengthPrefixedSlice(key_ptr + key_length); |
|
|
|
|
|
std::string combined_str(v.data(), v.size()); |
|
|
|
|
|
|
|
|
|
|
|
// 根据存储格式分离原始值和时间戳
|
|
|
|
|
|
std::string actual_value = combined_str.substr(0, combined_str.size() - 20); |
|
|
|
|
|
std::string time_str = combined_str.substr(combined_str.size() - 19, 19); |
|
|
|
|
|
|
|
|
|
|
|
// 获取当前时间(字符串格式)
|
|
|
|
|
|
auto now = std::chrono::system_clock::now(); |
|
|
|
|
|
auto now_time_t = std::chrono::system_clock::to_time_t(now); |
|
|
|
|
|
std::tm* now_tm = std::localtime(&now_time_t); |
|
|
|
|
|
char buffer[20]; |
|
|
|
|
|
std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", now_tm); |
|
|
|
|
|
std::string current_time_str(buffer); |
|
|
|
|
|
|
|
|
|
|
|
// 检查过期
|
|
|
|
|
|
if (time_str <= current_time_str) { |
|
|
|
|
|
*s = Status::NotFound("Key has expired"); // 已过期
|
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 未过期,返回实际值
|
|
|
|
|
|
value->assign(actual_value); |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
case kTypeDeletion: |
|
|
|
|
|
*s = Status::NotFound(Slice()); |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
case kTypeDeletion: |
|
|
|
|
|
*s = Status::NotFound(Slice()); |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace leveldb
|
|
|
} // namespace leveldb
|