Browse Source

basic function roughly complete

version_1
alexfisher 10 months ago
parent
commit
730de90449
6 changed files with 192 additions and 4 deletions
  1. +4
    -0
      CMakeLists.txt
  2. +89
    -2
      db/db_impl.cc
  3. +12
    -0
      db/db_impl.h
  4. +10
    -2
      db/db_iter.cc
  5. +15
    -0
      include/leveldb/db.h
  6. +62
    -0
      test/test.cpp

+ 4
- 0
CMakeLists.txt View File

@ -517,3 +517,7 @@ if(LEVELDB_INSTALL)
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
) )
endif(LEVELDB_INSTALL) endif(LEVELDB_INSTALL)
add_executable(db_test1
"${PROJECT_SOURCE_DIR}/test/test.cpp"
)
target_link_libraries(db_test1 PRIVATE leveldb gtest)

+ 89
- 2
db/db_impl.cc View File

@ -11,7 +11,8 @@
#include <set> #include <set>
#include <string> #include <string>
#include <vector> #include <vector>
#include <iostream>
#include <fstream>
#include "db/builder.h" #include "db/builder.h"
#include "db/db_iter.h" #include "db/db_iter.h"
#include "db/dbformat.h" #include "db/dbformat.h"
@ -1161,6 +1162,18 @@ Status DBImpl::Get(const ReadOptions& options, const Slice& key,
mem->Unref(); mem->Unref();
if (imm != nullptr) imm->Unref(); if (imm != nullptr) imm->Unref();
current->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; return s;
} }
@ -1198,6 +1211,67 @@ Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) {
return DB::Put(o, key, 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;i<siz;i++){
Slice value_name;
Slice value;
tmpres=GetLengthPrefixedSlice(&slice,&value_name);
assert(tmpres);
tmpres=GetLengthPrefixedSlice(&slice,&value);
assert(tmpres);
res->emplace_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<std::string> *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) { Status DBImpl::Delete(const WriteOptions& options, const Slice& key) {
return DB::Delete(options, 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 // can call if they wish
Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) {
WriteBatch batch; 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); return Write(opt, &batch);
} }

+ 12
- 0
db/db_impl.h View File

@ -35,6 +35,18 @@ class DBImpl : public DB {
~DBImpl() override; ~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 // Implementations of the DB interface
Status Put(const WriteOptions&, const Slice& key, Status Put(const WriteOptions&, const Slice& key,
const Slice& value) override; const Slice& value) override;

+ 10
- 2
db/db_iter.cc View File

@ -1,7 +1,8 @@
// Copyright (c) 2011 The LevelDB Authors. All rights reserved. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // 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. // found in the LICENSE file. See the AUTHORS file for names of contributors.
#include <iostream>
#include <fstream>
#include "db/db_iter.h" #include "db/db_iter.h"
#include "db/db_impl.h" #include "db/db_impl.h"
@ -67,7 +68,14 @@ class DBIter : public Iterator {
} }
Slice value() const override { Slice value() const override {
assert(valid_); 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 { Status status() const override {
if (status_.ok()) { if (status_.ok()) {

+ 15
- 0
include/leveldb/db.h View File

@ -11,12 +11,15 @@
#include "leveldb/export.h" #include "leveldb/export.h"
#include "leveldb/iterator.h" #include "leveldb/iterator.h"
#include "leveldb/options.h" #include "leveldb/options.h"
#include <vector>
namespace leveldb { namespace leveldb {
// Update CMakeLists.txt if you change these // Update CMakeLists.txt if you change these
static const int kMajorVersion = 1; static const int kMajorVersion = 1;
static const int kMinorVersion = 23; static const int kMinorVersion = 23;
using Field=std::pair<Slice,Slice>;
using FieldArray=std::vector<std::pair<Slice, Slice>>;
struct Options; struct Options;
struct ReadOptions; struct ReadOptions;
@ -87,6 +90,18 @@ class LEVELDB_EXPORT DB {
virtual Status Get(const ReadOptions& options, const Slice& key, virtual Status Get(const ReadOptions& options, const Slice& key,
std::string* value) = 0; 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<std::string> *keys);
// Return a heap-allocated iterator over the contents of the database. // Return a heap-allocated iterator over the contents of the database.
// The result of NewIterator() is initially invalid (caller must // The result of NewIterator() is initially invalid (caller must
// call one of the Seek methods on the iterator before using it). // call one of the Seek methods on the iterator before using it).

+ 62
- 0
test/test.cpp View File

@ -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<<std::string(pr.first.data(),pr.first.size())<<" "<<std::string(pr.second.data(),pr.second.size())<<"\n";
}
std::vector<std::string> v;
db->Get_keys_by_field(ReadOptions(),fields[0],&v);
for(auto s:v)std::cout<<s<<"\n";
delete db;
}
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();
}

Loading…
Cancel
Save