kevinyao0901 пре 3 недеља
родитељ
комит
5c8871b1cc
4 измењених фајлова са 57 додато и 10 уклоњено
  1. +5
    -5
      db/db_impl.cc
  2. +1
    -0
      db/db_test.cc
  3. +19
    -0
      db/memtable.cc
  4. +32
    -5
      test/ttl_test.cc

+ 5
- 5
db/db_impl.cc Прегледај датотеку

@ -42,7 +42,7 @@ const int kNumNonTableCacheFiles = 10;
//TTL ToDo : add func for TTL Put
void AppendExpirationTime(std::string* value, uint64_t expiration_time) {
// 将过期时间戳(64位整数)附加到值的前面
// 直接小端序的过期时间戳(64位整数)附加到值的前面
value->append(reinterpret_cast<const char*>(&expiration_time), sizeof(expiration_time));
}
@ -53,11 +53,11 @@ uint64_t GetCurrentTime() {
// 解析过期时间戳
uint64_t ParseExpirationTime(const std::string& value) {
// 假设过期时间戳在值的前 8 字节,以大端序存储
// 假设过期时间戳在值的前 8 字节
assert(value.size() >= sizeof(uint64_t));
uint64_t expiration_time;
memcpy(&expiration_time, value.data(), sizeof(uint64_t));
return expiration_time;
return expiration_time; // 直接返回小端序的值
}
// 解析出实际的值(去掉前面的过期时间戳部分)
@ -1207,14 +1207,14 @@ Status DBImpl::Get(const ReadOptions& options, const Slice& key,
// 如果当前时间已经超过过期时间,则认为数据过期,返回 NotFound
if (current_time > expiration_time) {
s = Status::NotFound("Key expired");
s = Status::NotFound(Slice());
} else {
// 数据未过期,解析出实际的值
*value = ParseActualValue(*value);
}
}
//finish modify
// //finish modify
if (have_stat_update && current->UpdateStats(stats)) {
MaybeScheduleCompaction();

+ 1
- 0
db/db_test.cc Прегледај датотеку

@ -348,6 +348,7 @@ class DBTest : public testing::Test {
Status Put(const std::string& k, const std::string& v) {
return db_->Put(WriteOptions(), k, v);
}
Status Delete(const std::string& k) { return db_->Delete(WriteOptions(), k); }

+ 19
- 0
db/memtable.cc Прегледај датотеку

@ -73,6 +73,8 @@ class MemTableIterator : public Iterator {
Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); }
void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key,
const Slice& value) {
// Format of an entry is concatenation of:
@ -124,6 +126,23 @@ bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
case kTypeValue: {
Slice v = GetLengthPrefixedSlice(key_ptr + key_length);
value->assign(v.data(), v.size());
// TTL ToDo :检查:从 value 中解析出过期时间戳并与当前时间比较
assert(value->size() >= sizeof(uint64_t));
uint64_t expiration_time;
memcpy(&expiration_time, value->data(), sizeof(uint64_t)); // 解析出过期时间戳
uint64_t current_time = static_cast<uint64_t>(time(nullptr)); // 获取当前时间
// 如果当前时间已超过过期时间,设置状态为 NotFound 表示数据过期
if (current_time > expiration_time) {
*s = Status::NotFound(Slice());
return true;
} else {
// 数据未过期,解析出实际的值部分,去掉过期时间戳
*value = value->substr(sizeof(uint64_t));
}
//finish modify
return true;
}
case kTypeDeletion:

+ 32
- 5
test/ttl_test.cc Прегледај датотеку

@ -4,7 +4,7 @@
#include "leveldb/env.h"
#include "leveldb/db.h"
#include <unordered_set>
using namespace leveldb;
@ -20,14 +20,28 @@ Status OpenDB(std::string dbName, DB **db) {
void InsertData(DB *db, uint64_t ttl/* second */) {
WriteOptions writeOptions;
int key_num = data_size / value_size;
srand(static_cast<unsigned int>(time(0)));
srand(42);
// 用于存储成功写入的唯一键
std::unordered_set<std::string> unique_keys;
for (int i = 0; i < key_num; i++) {
int key_ = rand() % key_num+1;
std::string key = std::to_string(key_);
std::string value(value_size, 'a');
db->Put(writeOptions, key, value, ttl);
Status status = db->Put(writeOptions, key, value, ttl);
if (!status.ok()) {
// 输出失败的状态信息并退出循环
std::cerr << "Failed to write key: " << key
<< ", Status: " << status.ToString() << std::endl;
}else{
std::cerr << "Success to write key: " << key << std::endl;
unique_keys.insert(key); // 插入集合中,如果已经存在则不会重复插入
}
}
// 打印成功写入的唯一键的数量
std::cout << "Total unique keys successfully written: " << unique_keys.size() << std::endl;
}
void GetData(DB *db, int size = (1 << 30)) {
@ -35,7 +49,7 @@ void GetData(DB *db, int size = (1 << 30)) {
int key_num = data_size / value_size;
// 点查
srand(static_cast<unsigned int>(time(0)));
srand(42);
for (int i = 0; i < 100; i++) {
int key_ = rand() % key_num+1;
std::string key = std::to_string(key_);
@ -58,12 +72,18 @@ TEST(TestTTL, ReadTTL) {
ReadOptions readOptions;
Status status;
int key_num = data_size / value_size;
srand(static_cast<unsigned int>(time(0)));
srand(42);
for (int i = 0; i < 100; i++) {
int key_ = rand() % key_num+1;
std::string key = std::to_string(key_);
std::string value;
status = db->Get(readOptions, key, &value);
// 检查 status 并打印出失败的状态信息
if (!status.ok()) {
std::cerr << "Key: " << key << ", Status: " << status.ToString() << std::endl;
}
ASSERT_TRUE(status.ok());
}
@ -74,6 +94,12 @@ TEST(TestTTL, ReadTTL) {
std::string key = std::to_string(key_);
std::string value;
status = db->Get(readOptions, key, &value);
// 检查 status 并打印出失败的状态信息
if (status.ok()) {
std::cerr << "Key: " << key << ", Status: " << status.ToString() << std::endl;
}
ASSERT_FALSE(status.ok());
}
}
@ -106,6 +132,7 @@ TEST(TestTTL, CompactionTTL) {
int main(int argc, char** argv) {
srand(42);
// All tests currently run with the same read-only file limits.
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();

Loading…
Откажи
Сачувај