From ec884a8bff1ff4fa19c79c35b75709bae0484f2a Mon Sep 17 00:00:00 2001 From: ssynn <824063458@qq.com> Date: Tue, 15 Oct 2024 15:01:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0ttl=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + CMakeLists.txt | 12 ++++++ include/leveldb/db.h | 5 +++ test/db_test2.cc | 74 +++++++++++++++++++++++++++++++++ test/ttl_test.cc | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 207 insertions(+) create mode 100644 test/db_test2.cc create mode 100644 test/ttl_test.cc diff --git a/.gitignore b/.gitignore index c4b2425..4729d86 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ # Build directory. build/ out/ +cmake-build-* +.idea \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index fda9e01..54b14a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -517,3 +517,15 @@ if(LEVELDB_INSTALL) DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) endif(LEVELDB_INSTALL) + + +add_executable(db_test2 + "${PROJECT_SOURCE_DIR}/test/db_test2.cc" +) +target_link_libraries(db_test2 PRIVATE leveldb) + + +add_executable(ttl_test + "${PROJECT_SOURCE_DIR}/test/ttl_test.cc" +) +target_link_libraries(ttl_test PRIVATE leveldb gtest) \ No newline at end of file diff --git a/include/leveldb/db.h b/include/leveldb/db.h index a13d147..bf4eec5 100644 --- a/include/leveldb/db.h +++ b/include/leveldb/db.h @@ -145,6 +145,11 @@ class LEVELDB_EXPORT DB { // Therefore the following call will compact the entire database: // db->CompactRange(nullptr, nullptr); virtual void CompactRange(const Slice* begin, const Slice* end) = 0; + + // ----------------------------For TTL----------------------------- + // 为当前key设置ttl,过期后自动失效 + virtual Status Put(const WriteOptions& options, const Slice& key, + const Slice& value, uint64_t ttl) = 0; }; // Destroy the contents of the specified database. diff --git a/test/db_test2.cc b/test/db_test2.cc new file mode 100644 index 0000000..49e26ab --- /dev/null +++ b/test/db_test2.cc @@ -0,0 +1,74 @@ +#include "leveldb/db.h" +#include "leveldb/filter_policy.h" + +#include +#include +#include + +using namespace leveldb; + +constexpr int value_size = 2048; +constexpr int data_size = 256 << 20; + +// 3. 数据管理(Manifest/创建/恢复数据库) +Status OpenDB(std::string dbName, DB **db) { + Options options; + options.create_if_missing = true; + options.filter_policy = NewBloomFilterPolicy(10); + return DB::Open(options, dbName, db); +} + +// 1. 存储(数据结构与写入) +// 4. 数据合并(Compaction) +void InsertData(DB *db) { + WriteOptions writeOptions; + int key_num = data_size / value_size; + srand(static_cast(time(0))); + + 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); + } +} + +// 2. 数据访问(如何读数据) +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; + std::string key = std::to_string(key_); + std::string value; + db->Get(readOptions, key, &value); + } + + // 范围查询 + Iterator *iter = db->NewIterator(readOptions); + iter->SeekToFirst(); + while (iter->Valid()) { + iter->Next(); + } + delete iter; +} + +int main() { + + DB *db; + if(OpenDB("testdb", &db).ok()) { + InsertData(db); + delete db; + } + + if(OpenDB("testdb", &db).ok()) { + GetData(db); + delete db; + } + + return 0; +} + diff --git a/test/ttl_test.cc b/test/ttl_test.cc new file mode 100644 index 0000000..06f4cda --- /dev/null +++ b/test/ttl_test.cc @@ -0,0 +1,114 @@ + + +#include "gtest/gtest.h" + +#include "leveldb/env.h" +#include "leveldb/db.h" + + +using namespace leveldb; + +constexpr int value_size = 2048; +constexpr int data_size = 128 << 20; + +Status OpenDB(std::string dbName, DB **db) { + Options options; + options.create_if_missing = true; + return DB::Open(options, dbName, db); +} + +void InsertData(DB *db, uint64_t ttl/* second */) { + WriteOptions writeOptions; + int key_num = data_size / value_size; + srand(static_cast(time(0))); + + 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); + } +} + +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; + std::string key = std::to_string(key_); + std::string value; + db->Get(readOptions, key, &value); + } +} + +TEST(TestTTL, ReadTTL) { + DB *db; + if(OpenDB("testdb", &db).ok() == false) { + std::cerr << "open db failed" << std::endl; + abort(); + } + + uint64_t ttl = 20; + + InsertData(db, ttl); + + ReadOptions readOptions; + Status status; + 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; + std::string key = std::to_string(key_); + std::string value; + status = db->Get(readOptions, key, &value); + ASSERT_TRUE(status.ok()); + } + + Env::Default()->SleepForMicroseconds(ttl * 1000000); + + 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); + ASSERT_FALSE(status.ok()); + } +} + +TEST(TestTTL, CompactionTTL) { + DB *db; + + if(OpenDB("testdb", &db).ok() == false) { + std::cerr << "open db failed" << std::endl; + abort(); + } + + uint64_t ttl = 20; + InsertData(db, ttl); + + leveldb::Range ranges[1]; + ranges[0] = leveldb::Range("-", "A"); + uint64_t sizes[1]; + db->GetApproximateSizes(ranges, 1, sizes); + ASSERT_GT(sizes[0], 0); + + Env::Default()->SleepForMicroseconds(ttl * 1000000); + + db->CompactRange(nullptr, nullptr); + + leveldb::Range ranges[1]; + ranges[0] = leveldb::Range("-", "A"); + uint64_t sizes[1]; + db->GetApproximateSizes(ranges, 1, sizes); + ASSERT_EQ(sizes[0], 0); +} + + +int main(int argc, char** argv) { + // All tests currently run with the same read-only file limits. + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}