소스 검색

lab2部分基础实现(没有并发和metadb)

pull/1/head
augurier 9 달 전
부모
커밋
099d818344
9개의 변경된 파일294개의 추가작업 그리고 116개의 파일을 삭제
  1. +1
    -1
      CMakeLists.txt
  2. +1
    -1
      db/db_impl.cc
  3. +37
    -0
      fielddb/encode_index.h
  4. +86
    -0
      fielddb/field_db.cpp
  5. +5
    -3
      fielddb/field_db.h
  6. +38
    -1
      test/basic_function_test.cc
  7. +17
    -1
      util/serialize_value.cc
  8. +1
    -1
      util/serialize_value.h

+ 1
- 1
CMakeLists.txt 파일 보기

@ -523,6 +523,6 @@ if(LEVELDB_INSTALL)
endif(LEVELDB_INSTALL)
add_executable(lab1_test
"${PROJECT_SOURCE_DIR}/test/lab1_test.cc"
"${PROJECT_SOURCE_DIR}/test/basic_function_test.cc"
)
target_link_libraries(lab1_test PRIVATE leveldb gtest)

+ 1
- 1
db/db_impl.cc 파일 보기

@ -1177,7 +1177,7 @@ std::vector DBImpl::FindKeysByField(Field &field){
std::vector<std::string> result;
auto iter = NewIterator(ReadOptions());
for(iter->SeekToFirst();iter->Valid();iter->Next()) {
std::string k = iter->key().ToString();
// std::string k = iter->key().ToString();
InternalFieldArray fields(iter->value());
if(fields.HasField(field)) {
result.push_back(iter->key().ToString());

+ 37
- 0
fielddb/encode_index.h 파일 보기

@ -0,0 +1,37 @@
#ifndef ENCODE_INDEX_H
#define ENCODE_INDEX_H
#include "leveldb/slice.h"
#include "util/coding.h"
namespace fielddb{
using namespace leveldb;
struct ParsedInternalIndexKey { //key : {name : val}
Slice user_key_;
Slice name_;
Slice val_;
ParsedInternalIndexKey() {} // Intentionally left uninitialized (for speed)
ParsedInternalIndexKey(const Slice& user_key, const Slice& name, const Slice& val)
: user_key_(user_key), name_(name), val_(val) {}
};
bool ParseInternalIndexKey(Slice input, ParsedInternalIndexKey* result);
void AppendIndexKey(std::string* result, const ParsedInternalIndexKey& key);
inline bool ParseInternalIndexKey(Slice input, ParsedInternalIndexKey* result){
return GetLengthPrefixedSlice(&input, &result->name_) &&
GetLengthPrefixedSlice(&input, &result->val_) &&
GetLengthPrefixedSlice(&input, &result->user_key_);
}
inline void AppendIndexKey(std::string* result, const ParsedInternalIndexKey& key){
PutLengthPrefixedSlice(result, key.name_);
PutLengthPrefixedSlice(result, key.val_);
PutLengthPrefixedSlice(result, key.user_key_);
}
}
#endif

+ 86
- 0
fielddb/field_db.cpp 파일 보기

@ -6,7 +6,9 @@
#include "leveldb/env.h"
#include "leveldb/options.h"
#include "leveldb/status.h"
#include "db/write_batch_internal.h"
#include "util/serialize_value.h"
#include "fielddb/encode_index.h"
namespace fielddb {
using namespace leveldb;
@ -18,6 +20,7 @@ Status FieldDB::OpenFieldDB(const Options& options,
return Status::NotSupported(name, "new a fieldDb first\n");
}
//
Status status;
DB *indexdb, *kvdb, *metadb;
status = Open(options, name+"_indexDB", &indexdb);
@ -77,6 +80,89 @@ std::vector FieldDB::FindKeysByField(Field &field) {
return kvDB_->FindKeysByField(field);
}
std::vector<std::pair<std::string, std::string>> FieldDB::FindKeysAndValByFieldName (
const std::string &fieldName){
std::vector<std::pair<std::string, std::string>> result;
auto iter = kvDB_->NewIterator(ReadOptions());
std::string val;
for(iter->SeekToFirst();iter->Valid();iter->Next()) {
InternalFieldArray fields(iter->value());
val = fields.ValOfName(fieldName);
if(!val.empty()) {
result.push_back(std::make_pair(iter->key().ToString(), val));
}
}
return result;
}
Status FieldDB::CreateIndexOnField(const std::string& field_name) {
//taskQueue相关
//写锁 是不是只需要给putfields设置一把锁就行
std::vector<std::pair<std::string, std::string>> keysAndVal =
FindKeysAndValByFieldName(field_name);
WriteBatch writeBatch;
Slice value = Slice();
for (auto &kvPair : keysAndVal){
std::string indexKey;
AppendIndexKey(&indexKey,
ParsedInternalIndexKey(kvPair.first, field_name, kvPair.second));
writeBatch.Put(indexKey, value);
}
Status s = indexDB_->Write(WriteOptions(), &writeBatch);
if (!s.ok()) return s;
index_[field_name] = Exist;
//唤醒taskqueue
}
Status FieldDB::DeleteIndex(const std::string &field_name) {
//taskQueue相关
//写锁
std::vector<std::pair<std::string, std::string>> keysAndVal =
FindKeysAndValByFieldName(field_name);
WriteBatch writeBatch;
for (auto &kvPair : keysAndVal){
std::string indexKey;
AppendIndexKey(&indexKey,
ParsedInternalIndexKey(kvPair.first, field_name, kvPair.second));
writeBatch.Delete(indexKey);
}
Status s = indexDB_->Write(WriteOptions(), &writeBatch);
if (!s.ok()) return s;
index_.erase(field_name);
//唤醒taskqueue
}
std::vector<std::string> FieldDB::QueryByIndex(const Field &field, Status *s) {
if (index_.count(field.first) == 0 || index_[field.first] != Exist){
*s = Status::NotFound(Slice());
return std::vector<std::string>();
}
std::string indexKey;
AppendIndexKey(&indexKey,
ParsedInternalIndexKey(Slice(), field.first, field.second));
Iterator *indexIterator = indexDB_->NewIterator(ReadOptions());
indexIterator->Seek(indexKey);
std::vector<std::string> result;
for (; indexIterator->Valid(); indexIterator->Next()) {
ParsedInternalIndexKey iterKey;
if (ParseInternalIndexKey(indexIterator->key(), &iterKey)){
if (iterKey.name_ == field.first && iterKey.val_ == field.second){
result.push_back(iterKey.user_key_.ToString());
continue; //查到说明在范围里,否则break
}
}
break;
}
*s = Status::OK();
return result;
}
Iterator * FieldDB::NewIterator(const ReadOptions &options) {
return kvDB_->NewIterator(options);
}

+ 5
- 3
fielddb/field_db.h 파일 보기

@ -36,8 +36,8 @@ public:
void CompactRange(const Slice *begin, const Slice *end) override;
/*与索引相关*/
Status CreateIndexOnField(const std::string& field_name);
Status DeleteIndex(std::string &field_name);
std::vector<std::string> QueryByIndex(Field &field, Status *s);
Status DeleteIndex(const std::string &field_name);
std::vector<std::string> QueryByIndex(const Field &field, Status *s);
static Status OpenFieldDB(const Options& options,const std::string& name,FieldDB** dbptr);
@ -57,10 +57,12 @@ private:
Deleting,
Exist
};
std::map<std::string,int> index_;
std::map<std::string, int> index_;
leveldb::port::Mutex mutex_; // mutex for taskqueue
std::deque<Request *> taskqueue_;
std::vector<std::pair<std::string, std::string>> FindKeysAndValByFieldName (
const std::string &fieldName);
};
} // end of namespace
# endif

test/lab1_test.cc → test/basic_function_test.cc 파일 보기

@ -81,7 +81,22 @@ void GetFieldData(FieldDB *db) {
void findKeysByCity(FieldDB *db) {
Field field = {"address", "Shanghai"};
std::vector<std::string> resKeys = db->FindKeysByField(field);
// std::cout << shanghaiKeys.size() << " " << resKeys.size() << std::endl;
std::cout << shanghaiKeys.size() << " " << resKeys.size() << std::endl;
for (const std::string &key : resKeys){
ASSERT_NE(std::find(shanghaiKeys.begin(), shanghaiKeys.end(), key), shanghaiKeys.end());
}
}
void findKeysByCityIndex(FieldDB *db, bool expect) {
Field field = {"address", "Shanghai"};
Status s;
std::vector<std::string> resKeys = db->QueryByIndex(field, &s);
if (expect) ASSERT_TRUE(s.ok());
else {
ASSERT_TRUE(s.IsNotFound());
return;
}
std::cout << shanghaiKeys.size() << " " << resKeys.size() << std::endl;
for (const std::string &key : resKeys){
ASSERT_NE(std::find(shanghaiKeys.begin(), shanghaiKeys.end(), key), shanghaiKeys.end());
}
@ -99,6 +114,28 @@ TEST(TestLab1, Basic) {
InsertFieldData(db);
GetFieldData(db);
findKeysByCity(db);
delete db;
}
TEST(TestLab2, Basic) {
//destroy
FieldDB *db = new FieldDB();
if(OpenDB("testdb2", &db).ok() == false) {
std::cerr << "open db failed" << std::endl;
abort();
}
// ClearDB(db);
shanghaiKeys.clear();
InsertFieldData(db);
// GetFieldData(db);
// findKeysByCity(db);
db->CreateIndexOnField("address");
findKeysByCityIndex(db, true);
db->DeleteIndex("address");
findKeysByCityIndex(db, false);
delete db;
}

+ 17
- 1
util/serialize_value.cc 파일 보기

@ -73,6 +73,22 @@ bool InternalFieldArray::HasField(const Field& field) {
return std::find(fields.begin(),fields.end(),field) != fields.end();
}
std::string InternalFieldArray::ValOfName(const std::string &name) {
if(isMapped) {
if(map.count(name)) {
return map[name];
}
return std::string();
}
for (auto iter = fields.begin(); iter != fields.end(); iter++){
if (iter->first == name) {
return iter->second;
} else if (iter->first > name) {
return std::string();
}
}
return std::string();
}
}

+ 1
- 1
util/serialize_value.h 파일 보기

@ -48,7 +48,7 @@ public:
std::string Serialize();
bool HasField(const Field& field);
std::string ValOfName(const std::string& name);
private:
bool isMapped;

불러오는 중...
취소
저장