diff --git a/CMakeLists.txt b/CMakeLists.txt index 54b14a1..f533d44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -528,4 +528,9 @@ 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 +target_link_libraries(ttl_test PRIVATE leveldb gtest) + +add_executable(db_test1 + "${PROJECT_SOURCE_DIR}/test/db_test1.cc" +) +target_link_libraries(db_test1 leveldb) \ No newline at end of file diff --git a/db/db_impl.cc b/db/db_impl.cc index f96d245..d521441 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -4,14 +4,6 @@ #include "db/db_impl.h" -#include -#include -#include -#include -#include -#include -#include - #include "db/builder.h" #include "db/db_iter.h" #include "db/dbformat.h" @@ -22,11 +14,22 @@ #include "db/table_cache.h" #include "db/version_set.h" #include "db/write_batch_internal.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "leveldb/db.h" #include "leveldb/env.h" #include "leveldb/status.h" #include "leveldb/table.h" #include "leveldb/table_builder.h" + #include "port/port.h" #include "table/block.h" #include "table/merger.h" @@ -1152,6 +1155,24 @@ Status DBImpl::Get(const ReadOptions& options, const Slice& key, s = current->Get(options, lkey, value, &stats); have_stat_update = true; } + // TTL: Get the true value and make sure the data is still living + if(!value->empty()) { + auto separator = value->find_first_of("|"); + std::string ddl_str = value->substr(0, separator); + uint64_t dead_line = std::atoll(ddl_str.c_str()); + if (dead_line != 0) { + // use TTL + if (std::time(nullptr) >= dead_line) { + *value = ""; + s = Status::NotFound("Data expired"); + } + else { + *value = value->substr(separator + 1); + } + } else { + // TTL not set + } + } mutex_.Lock(); } @@ -1198,6 +1219,11 @@ Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { return DB::Put(o, key, val); } +Status DBImpl::Put(const WriteOptions& options, const Slice& key, + const Slice& value, uint64_t ttl) { + return DB::Put(options, key, value, ttl); +} + Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { return DB::Delete(options, key); } @@ -1485,12 +1511,28 @@ void DBImpl::GetApproximateSizes(const Range* range, int n, uint64_t* sizes) { // Default implementations of convenience methods that subclasses of DB // can call if they wish +// TTL: Update TTL Encode Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { WriteBatch batch; - batch.Put(key, value); + // char * ttl_encode = new char[8]; + // EncodeFixed64(ttl_encode, 0); + std::string ttl_value = "0|" + value.ToString(); + batch.Put(key, ttl_value); return Write(opt, &batch); } +// TTL: Put methods for ttl +Status DB::Put(const WriteOptions& options, const Slice& key, + const Slice& value, uint64_t ttl) { + WriteBatch batch; + // char * ttl_encode = new char[8]; + // EncodeFixed64(ttl_encode, std::time(nullptr) + ttl); + auto dead_line = std::time(nullptr) + ttl; + std::string ttl_value = std::to_string(dead_line) + "|" + value.ToString(); + batch.Put(key, ttl_value); + return Write(options, &batch); +} + 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..6157c01 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& options, const Slice& key, const Slice& value, + uint64_t ttl) override; 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/test/db_test1.cc b/test/db_test1.cc new file mode 100644 index 0000000..373d107 --- /dev/null +++ b/test/db_test1.cc @@ -0,0 +1,28 @@ +#include "leveldb/db.h" +#include + +using namespace std; +using namespace leveldb; + +int main() { + DB* db = nullptr; + Options op; + op.create_if_missing = true; + Status status = DB::Open(op, "testdb", &db); + assert(status.ok()); + db->Put(WriteOptions(), "001", "leveldb", 20); + string s; + auto stat = db->Get(ReadOptions(), "001", &s); + + cout<Put(WriteOptions(), "002", "world"); + string s1; + db->Delete(WriteOptions(), "002"); + db->Get(ReadOptions(), "002", &s1); + cout<(time(0))); + srand(0); for (int i = 0; i < key_num; i++) { int key_ = rand() % key_num+1; @@ -35,7 +31,7 @@ void GetData(DB *db, int size = (1 << 30)) { int key_num = data_size / value_size; // 点查 - srand(static_cast(time(0))); + srand(0); for (int i = 0; i < 100; i++) { int key_ = rand() % key_num+1; std::string key = std::to_string(key_); @@ -58,7 +54,7 @@ TEST(TestTTL, ReadTTL) { ReadOptions readOptions; Status status; int key_num = data_size / value_size; - srand(static_cast(time(0))); + srand(0); for (int i = 0; i < 100; i++) { int key_ = rand() % key_num+1; std::string key = std::to_string(key_); @@ -99,11 +95,11 @@ TEST(TestTTL, CompactionTTL) { 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); + leveldb::Range ranges1[1]; + ranges1[0] = leveldb::Range("-", "A"); + uint64_t sizes1[1]; + db->GetApproximateSizes(ranges1, 1, sizes1); + ASSERT_EQ(sizes1[0], 0); } @@ -111,4 +107,4 @@ 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(); -} +} \ No newline at end of file