Kaynağa Gözat

Now can pass ReadTTL

main
kevinyao0901 1 ay önce
ebeveyn
işleme
5c8871b1cc
4 değiştirilmiş dosya ile 57 ekleme ve 10 silme
  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 Dosyayı Görüntüle

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

+ 1
- 0
db/db_test.cc Dosyayı Görüntüle

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

+ 19
- 0
db/memtable.cc Dosyayı Görüntüle

@ -73,6 +73,8 @@ 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) {
// Format of an entry is concatenation of: // Format of an entry is concatenation of:
@ -124,6 +126,23 @@ bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
case kTypeValue: { case kTypeValue: {
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());
// 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; return true;
} }
case kTypeDeletion: case kTypeDeletion:

+ 32
- 5
test/ttl_test.cc Dosyayı Görüntüle

@ -4,7 +4,7 @@
#include "leveldb/env.h" #include "leveldb/env.h"
#include "leveldb/db.h" #include "leveldb/db.h"
#include <unordered_set>
using namespace leveldb; using namespace leveldb;
@ -20,14 +20,28 @@ Status OpenDB(std::string dbName, DB **db) {
void InsertData(DB *db, uint64_t ttl/* second */) { void InsertData(DB *db, uint64_t ttl/* second */) {
WriteOptions writeOptions; WriteOptions writeOptions;
int key_num = data_size / value_size; 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++) { for (int i = 0; i < key_num; i++) {
int key_ = rand() % key_num+1; int key_ = rand() % key_num+1;
std::string key = std::to_string(key_); std::string key = std::to_string(key_);
std::string value(value_size, 'a'); 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)) { 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; int key_num = data_size / value_size;
// 点查 // 点查
srand(static_cast<unsigned int>(time(0)));
srand(42);
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
int key_ = rand() % key_num+1; int key_ = rand() % key_num+1;
std::string key = std::to_string(key_); std::string key = std::to_string(key_);
@ -58,12 +72,18 @@ TEST(TestTTL, ReadTTL) {
ReadOptions readOptions; ReadOptions readOptions;
Status status; Status status;
int key_num = data_size / value_size; int key_num = data_size / value_size;
srand(static_cast<unsigned int>(time(0)));
srand(42);
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
int key_ = rand() % key_num+1; int key_ = rand() % key_num+1;
std::string key = std::to_string(key_); std::string key = std::to_string(key_);
std::string value; std::string value;
status = db->Get(readOptions, key, &value); status = db->Get(readOptions, key, &value);
// 检查 status 并打印出失败的状态信息
if (!status.ok()) {
std::cerr << "Key: " << key << ", Status: " << status.ToString() << std::endl;
}
ASSERT_TRUE(status.ok()); ASSERT_TRUE(status.ok());
} }
@ -74,6 +94,12 @@ TEST(TestTTL, ReadTTL) {
std::string key = std::to_string(key_); std::string key = std::to_string(key_);
std::string value; std::string value;
status = db->Get(readOptions, key, &value); status = db->Get(readOptions, key, &value);
// 检查 status 并打印出失败的状态信息
if (status.ok()) {
std::cerr << "Key: " << key << ", Status: " << status.ToString() << std::endl;
}
ASSERT_FALSE(status.ok()); ASSERT_FALSE(status.ok());
} }
} }
@ -106,6 +132,7 @@ TEST(TestTTL, CompactionTTL) {
int main(int argc, char** argv) { int main(int argc, char** argv) {
srand(42);
// All tests currently run with the same read-only file limits. // All tests currently run with the same read-only file limits.
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();

Yükleniyor…
İptal
Kaydet