From a0786b61401cf783460459de98ac9d49ed7128ee Mon Sep 17 00:00:00 2001 From: jiyeoniya <2952095622@qq.com> Date: Tue, 29 Oct 2024 10:05:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/db_impl.cc | 11 +++++++++++ db/db_impl.h | 2 ++ db/db_test.cc | 4 ++++ db/write_batch.cc | 30 ++++++++++++++++++++++++++++++ include/leveldb/write_batch.h | 3 +++ test/ttl_test.cc | 19 ++++++++++++------- 6 files changed, 62 insertions(+), 7 deletions(-) diff --git a/db/db_impl.cc b/db/db_impl.cc index f96d245..2f66816 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -1198,6 +1198,10 @@ Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { return DB::Put(o, key, val); } +Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val, uint64_t ttl) { + return DB::Put(o, key, val, ttl); +} // 实现新的put接口,心 + Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { return DB::Delete(options, key); } @@ -1491,6 +1495,13 @@ Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { return Write(opt, &batch); } +// 假设增加一个新的Put接口,包含TTL参数, 单位(秒) +Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value, uint64_t ttl){ + WriteBatch batch; + batch.Put(key, value, ttl); + return Write(opt, &batch); +} // 这里应该是新的PUT接口的真正实现的地方,还是由本来的DB类实现,怪?心 + Status DB::Delete(const WriteOptions& opt, const Slice& key) { WriteBatch batch; batch.Delete(key); diff --git a/db/db_impl.h b/db/db_impl.h index c7b0172..bf3e310 100644 --- a/db/db_impl.h +++ b/db/db_impl.h @@ -38,6 +38,8 @@ class DBImpl : public DB { // Implementations of the DB interface Status Put(const WriteOptions&, const Slice& key, const Slice& value) override; + Status Put(const WriteOptions&, const Slice& key, + const Slice& value, uint64_t ttl) override; //实现新的put接口,心 Status Delete(const WriteOptions&, const Slice& key) override; Status Write(const WriteOptions& options, WriteBatch* updates) override; Status Get(const ReadOptions& options, const Slice& key, diff --git a/db/db_test.cc b/db/db_test.cc index a4a84cd..01abf71 100644 --- a/db/db_test.cc +++ b/db/db_test.cc @@ -2117,6 +2117,10 @@ class ModelDB : public DB { Status Put(const WriteOptions& o, const Slice& k, const Slice& v) override { return DB::Put(o, k, v); } + Status Put(const WriteOptions& o, const Slice& k, + const Slice& v, uint64_t ttl) override { + return DB::Put(o, k, v); + }// 实现的是DB里的新put接口,心 Status Delete(const WriteOptions& o, const Slice& key) override { return DB::Delete(o, key); } diff --git a/db/write_batch.cc b/db/write_batch.cc index b54313c..061c2c3 100644 --- a/db/write_batch.cc +++ b/db/write_batch.cc @@ -21,6 +21,8 @@ #include "leveldb/db.h" #include "util/coding.h" +#include // For std::ostringstream 心 +#include // 引入uint64_t类型,燕 namespace leveldb { // WriteBatch header has an 8-byte sequence number followed by a 4-byte count. @@ -102,6 +104,34 @@ void WriteBatch::Put(const Slice& key, const Slice& value) { PutLengthPrefixedSlice(&rep_, value); } +void WriteBatch::Put(const Slice& key, const Slice& value, std::uint64_t ttl) { + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); + rep_.push_back(static_cast(kTypeValue)); + PutLengthPrefixedSlice(&rep_, key); + + // 获取当前时间 + auto now = std::chrono::system_clock::now(); + + // 加上ttl + auto future_time = now + std::chrono::seconds(ttl); + + // 转换为 time_t + std::time_t future_time_t = std::chrono::system_clock::to_time_t(future_time); + + // 将 time_t 转换为 tm 结构 + std::tm* local_tm = std::localtime(&future_time_t); + + // 格式化为字符串 + char buffer[20]; // 格式化字符串的缓冲区 + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local_tm); + std::string future_time_str(buffer); + + // 拼接原本的值和时间字符串 + std::string combined_str = value.ToString() + future_time_str; + PutLengthPrefixedSlice(&rep_, Slice(combined_str)); + +} // 心 + void WriteBatch::Delete(const Slice& key) { WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); rep_.push_back(static_cast(kTypeDeletion)); diff --git a/include/leveldb/write_batch.h b/include/leveldb/write_batch.h index 94d4115..befe262 100644 --- a/include/leveldb/write_batch.h +++ b/include/leveldb/write_batch.h @@ -22,6 +22,7 @@ #define STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ #include +#include // 引入uint64_t类型,燕 #include "leveldb/export.h" #include "leveldb/status.h" @@ -50,6 +51,8 @@ class LEVELDB_EXPORT WriteBatch { // Store the mapping "key->value" in the database. void Put(const Slice& key, const Slice& value); + void Put(const Slice& key, const Slice& value, uint64_t ttl); //心 + // If the database contains a mapping for "key", erase it. Else do nothing. void Delete(const Slice& key); diff --git a/test/ttl_test.cc b/test/ttl_test.cc index 06f4cda..05ea42a 100644 --- a/test/ttl_test.cc +++ b/test/ttl_test.cc @@ -7,7 +7,7 @@ using namespace leveldb; - +// 定义了数据的大小,用于插入大数据集,燕 constexpr int value_size = 2048; constexpr int data_size = 128 << 20; @@ -23,7 +23,8 @@ void InsertData(DB *db, uint64_t ttl/* second */) { srand(static_cast(time(0))); for (int i = 0; i < key_num; i++) { - int key_ = rand() % key_num+1; + //int key_ = rand() % key_num+1; + int key_ = i % key_num+1; std::string key = std::to_string(key_); std::string value(value_size, 'a'); db->Put(writeOptions, key, value, ttl); @@ -34,10 +35,11 @@ void GetData(DB *db, int size = (1 << 30)) { ReadOptions readOptions; int key_num = data_size / value_size; - // 点查 + // 使用随机种子生成随机键进行点查(单次查询),燕 srand(static_cast(time(0))); for (int i = 0; i < 100; i++) { int key_ = rand() % key_num+1; + //int key_ = i % key_num+1; std::string key = std::to_string(key_); std::string value; db->Get(readOptions, key, &value); @@ -60,17 +62,19 @@ TEST(TestTTL, ReadTTL) { int key_num = data_size / value_size; srand(static_cast(time(0))); for (int i = 0; i < 100; i++) { - int key_ = rand() % key_num+1; + //int key_ = rand() % key_num+1; + int key_ = i % key_num+1; std::string key = std::to_string(key_); std::string value; status = db->Get(readOptions, key, &value); ASSERT_TRUE(status.ok()); } - + // 等待TTL过期,使插入的数据变为“过期”状态,燕 Env::Default()->SleepForMicroseconds(ttl * 1000000); for (int i = 0; i < 100; i++) { int key_ = rand() % key_num+1; + // int key_ = i % key_num+1; std::string key = std::to_string(key_); std::string value; status = db->Get(readOptions, key, &value); @@ -99,9 +103,10 @@ TEST(TestTTL, CompactionTTL) { db->CompactRange(nullptr, nullptr); - leveldb::Range ranges[1]; + // leveldb::Range ranges[1]; // 这里为什么要重复定义?心 ranges[0] = leveldb::Range("-", "A"); - uint64_t sizes[1]; + // uint64_t sizes[1]; // 心 + db->GetApproximateSizes(ranges, 1, sizes); ASSERT_EQ(sizes[0], 0); }