From 730de90449ede5f3a59a8a5dec7f38ee42571d8a Mon Sep 17 00:00:00 2001 From: alexfisher <1823748191@qq.com> Date: Sun, 17 Nov 2024 01:58:53 +0800 Subject: [PATCH] basic function roughly complete --- CMakeLists.txt | 4 +++ db/db_impl.cc | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++-- db/db_impl.h | 12 +++++++ db/db_iter.cc | 12 +++++-- include/leveldb/db.h | 15 +++++++++ test/test.cpp | 62 +++++++++++++++++++++++++++++++++++ 6 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 test/test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fda9e01..ec151f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -517,3 +517,7 @@ if(LEVELDB_INSTALL) DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" ) endif(LEVELDB_INSTALL) +add_executable(db_test1 +"${PROJECT_SOURCE_DIR}/test/test.cpp" + ) +target_link_libraries(db_test1 PRIVATE leveldb gtest) \ No newline at end of file diff --git a/db/db_impl.cc b/db/db_impl.cc index f96d245..3f1ea16 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -11,7 +11,8 @@ #include #include #include - +#include +#include #include "db/builder.h" #include "db/db_iter.h" #include "db/dbformat.h" @@ -1161,6 +1162,18 @@ Status DBImpl::Get(const ReadOptions& options, const Slice& key, mem->Unref(); if (imm != nullptr) imm->Unref(); current->Unref(); + std::ifstream inFile("tmp.txt", std::ios::in | std::ios::binary); + if (!inFile.is_open()) { + std::cerr << "Failed to open file for writing!" << std::endl; + return Status::Corruption("Failed to open file for writing!"); + } + uint64_t value_offset=*(uint64_t*)(value->c_str()); + size_t value_size=*(size_t*)(value->c_str()+sizeof(uint64_t)); + inFile.seekg(value_offset); + char value_buf[value_size]; + inFile.read(value_buf,value_size); + inFile.close(); + *value=std::string(value_buf,value_size); return s; } @@ -1198,6 +1211,67 @@ Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { return DB::Put(o, key, val); } +std::string DB::SerializeValue(const FieldArray& fields){ + std::string res_=""; + PutVarint64(&res_,(uint64_t)fields.size()); + for(auto pr:fields){ + PutLengthPrefixedSlice(&res_, pr.first); + PutLengthPrefixedSlice(&res_, pr.second); + } + return res_; +} + + // 反序列化为字段数组 +void DB::ParseValue(const std::string& value_str,FieldArray* res){ + Slice slice=Slice(value_str.c_str()); + uint64_t siz; + bool tmpres=GetVarint64(&slice,&siz); + assert(tmpres); + res->clear(); + for(int i=0;iemplace_back(value_name,value); + } +} + +Status DB::Put_with_fields(const WriteOptions& op, const Slice& key,const FieldArray& fields){ + auto value=SerializeValue(fields); + return Put(op,key,value); +} +Status DB::Get_with_fields(const ReadOptions& options, const Slice& key,FieldArray* fields){ + std::string* value; + auto status=Get(options,key,value); + if(!status.ok())return status; + ParseValue(*value,fields); + return status; +} +Status DB::Get_keys_by_field(const ReadOptions& options, const Field field,std::vector *keys){ + auto it=NewIterator(options); + it->SeekToFirst(); + keys->clear(); + while(it->Valid()){ + auto val=it->value(); + FieldArray arr; + auto str_val=std::string(val.data(),val.size()); + ParseValue(str_val,&arr); + for(auto pr:arr){ + if(pr.first==field.first&&pr.second==field.second){ + Slice key=it->key(); + keys->push_back(std::string(key.data(),key.size())); + break; + } + } + it->Next(); + } + delete it; + return Status::OK(); +} + Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { return DB::Delete(options, key); } @@ -1487,7 +1561,20 @@ void DBImpl::GetApproximateSizes(const Range* range, int n, uint64_t* sizes) { // can call if they wish Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { WriteBatch batch; - batch.Put(key, value); + std::ofstream valueFile("tmp.txt", std::ios::app | std::ios::binary); + if (!valueFile.is_open()) { + std::cerr << "Failed to open file for writing!" << std::endl; + return Status::Corruption("Failed to open file for writing!"); + } + uint64_t offset=valueFile.tellp(); + valueFile.write(value.data(),value.size()); + valueFile.close(); + auto value_len=value.size(); + char *new_value_buf=new char[sizeof(uint64_t)+sizeof(size_t)]; + memcpy(new_value_buf,(void*)(&offset),sizeof(uint64_t)); + memcpy(new_value_buf+sizeof(uint64_t),(void*)(&value_len),sizeof(size_t)); + Slice new_value=Slice(new_value_buf,sizeof(uint64_t)+sizeof(size_t)); + batch.Put(key, new_value); return Write(opt, &batch); } diff --git a/db/db_impl.h b/db/db_impl.h index c7b0172..1bd02b2 100644 --- a/db/db_impl.h +++ b/db/db_impl.h @@ -35,6 +35,18 @@ class DBImpl : public DB { ~DBImpl() override; + // // 序列化为字符串 + // std::string SerializeValue(const FieldArray& fields)override; + + // // 反序列化为字段数组 + // FieldArray ParseValue(const std::string& value_str)override; + + // Status Put_with_fields(const WriteOptions& options, const Slice& key,const FieldArray& fields)override; + + // Status Get_with_fields(const ReadOptions& options, const Slice& key, + // FieldArray* fields)override; + + // Implementations of the DB interface Status Put(const WriteOptions&, const Slice& key, const Slice& value) override; diff --git a/db/db_iter.cc b/db/db_iter.cc index 532c2db..a7ce298 100644 --- a/db/db_iter.cc +++ b/db/db_iter.cc @@ -1,7 +1,8 @@ // Copyright (c) 2011 The LevelDB Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. See the AUTHORS file for names of contributors. - +#include +#include #include "db/db_iter.h" #include "db/db_impl.h" @@ -67,7 +68,14 @@ class DBIter : public Iterator { } Slice value() const override { assert(valid_); - return (direction_ == kForward) ? iter_->value() : saved_value_; + auto tmp_value= (direction_ == kForward) ? iter_->value() : saved_value_; + std::ifstream inFile("tmp.txt", std::ios::in | std::ios::binary); + uint64_t value_offset=*(uint64_t*)(tmp_value.data()); + size_t value_size=*(size_t*)(tmp_value.data()+sizeof(uint64_t)); + inFile.seekg(value_offset); + char *value_buf=new char[value_size]; + inFile.read(value_buf,value_size); + return Slice(value_buf,value_size); } Status status() const override { if (status_.ok()) { diff --git a/include/leveldb/db.h b/include/leveldb/db.h index a13d147..4db4883 100644 --- a/include/leveldb/db.h +++ b/include/leveldb/db.h @@ -11,12 +11,15 @@ #include "leveldb/export.h" #include "leveldb/iterator.h" #include "leveldb/options.h" +#include namespace leveldb { // Update CMakeLists.txt if you change these static const int kMajorVersion = 1; static const int kMinorVersion = 23; +using Field=std::pair; +using FieldArray=std::vector>; struct Options; struct ReadOptions; @@ -87,6 +90,18 @@ class LEVELDB_EXPORT DB { virtual Status Get(const ReadOptions& options, const Slice& key, std::string* value) = 0; + virtual std::string SerializeValue(const FieldArray& fields); + + // 反序列化为字段数组 + virtual void ParseValue(const std::string& value_str,FieldArray* res); + + virtual Status Put_with_fields(const WriteOptions& options, const Slice& key,const FieldArray& fields); + + virtual Status Get_with_fields(const ReadOptions& options, const Slice& key, + FieldArray* fields); + + virtual Status Get_keys_by_field(const ReadOptions& options, const Field field,std::vector *keys); + // Return a heap-allocated iterator over the contents of the database. // The result of NewIterator() is initially invalid (caller must // call one of the Seek methods on the iterator before using it). diff --git a/test/test.cpp b/test/test.cpp new file mode 100644 index 0000000..ead36ef --- /dev/null +++ b/test/test.cpp @@ -0,0 +1,62 @@ +#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); +} + +TEST(TestTTL, OurTTL) { + DB *db; + WriteOptions writeOptions; + ReadOptions readOptions; + if(OpenDB("testdb_for_XOY", &db).ok() == false) { + std::cerr << "open db failed" << std::endl; + abort(); + } + std::string key = "k_1"; + + std::string key1 = "k_2"; + + FieldArray fields = { + {"name", "Customer#000000001"}, + {"address", "IVhzIApeRb"}, + {"phone", "25-989-741-2988"} + }; + + FieldArray fields1 = { + {"name", "Customer#000000001"}, + {"address", "abc"}, + {"phone", "def"} + }; + + db->Put_with_fields(WriteOptions(), key, fields); + + db->Put_with_fields(WriteOptions(), key1, fields1); + + // 读取并反序列化 + FieldArray value_ret; + db->Get_with_fields(ReadOptions(), key, &value_ret);; + for(auto pr:value_ret){ + std::cout< v; + db->Get_keys_by_field(ReadOptions(),fields[0],&v); + for(auto s:v)std::cout<