diff --git a/fielddb/field_db.cpp b/fielddb/field_db.cpp new file mode 100644 index 0000000..1de6565 --- /dev/null +++ b/fielddb/field_db.cpp @@ -0,0 +1,88 @@ +#include "fielddb/field_db.h" +#include +#include +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/options.h" +#include "leveldb/status.h" +#include "util/serialize_value.h" + +namespace leveldb { +//TODO:打开fieldDB +static Status OpenFieldDB(const Options& options,const std::string& name,DB** dbptr) { + // options.env->CreateDir("./abc") + return Status::OK(); +} + + +Status FieldDB::Put(const WriteOptions &options, const Slice &key, const Slice &value) { + return kvDB->Put(options, key, value); +} + +// TODO:需要对是否进行index更新做处理 +Status FieldDB::PutFields(const WriteOptions &, const Slice &key, const FieldArray &fields) { + return Status::OK(); +} + +Status FieldDB::Delete(const WriteOptions &options, const Slice &key) { + return kvDB->Delete(options, key); +} +// TODO:根据updates里面的东西,要对是否需要更新index进行分别处理 +Status FieldDB::Write(const WriteOptions &options, WriteBatch *updates) { + return Status::OK(); +} + +Status FieldDB::Get(const ReadOptions &options, const Slice &key, std::string *value) { + return kvDB->Get(options, key, value); +} + +Status FieldDB::GetFields(const ReadOptions &options, const Slice &key, FieldArray *fields) { + std::string value; + Status status; + status = kvDB->Get(options, key, &value); + if(status.ok() == false) return status; + fields = ParseValue(value); + return status; +} + +std::vector FieldDB::FindKeysByField(Field &field) { + std::vector result; + auto iter = kvDB->NewIterator(ReadOptions()); + for(iter->SeekToFirst();iter->Valid();iter->Next()) { + InternalFieldArray fields(iter->value()); + if(fields.HasField(field)) { + result.push_back(iter->key().ToString()); + } + } + return result; +} + +Iterator * FieldDB::NewIterator(const ReadOptions &options) { + return kvDB->NewIterator(options); +} + +// TODO:使用统一seq进行snapshot管理 +const Snapshot * FieldDB::GetSnapshot() { + return kvDB->GetSnapshot(); +} +// TODO:同上 +void FieldDB::ReleaseSnapshot(const Snapshot *snapshot) { + kvDB->ReleaseSnapshot(snapshot); +} + +bool FieldDB::GetProperty(const Slice &property, std::string *value) { + return kvDB->GetProperty(property, value) | indexDB->GetProperty(property, value); +} + +void FieldDB::GetApproximateSizes(const Range *range, int n, uint64_t *sizes) { + uint64_t temp = 0; + kvDB->GetApproximateSizes(range, n, sizes); + indexDB->GetApproximateSizes(range, n, &temp); + *sizes += temp; +} + +void FieldDB::CompactRange(const Slice *begin, const Slice *end) { + kvDB->CompactRange(begin, end); +} + +} // end of namespace \ No newline at end of file diff --git a/fielddb/field_db.h b/fielddb/field_db.h new file mode 100644 index 0000000..23534aa --- /dev/null +++ b/fielddb/field_db.h @@ -0,0 +1,33 @@ +#include "db/db_impl.h" +#include "leveldb/db.h" +#include "leveldb/options.h" +#include "leveldb/status.h" +namespace leveldb{ +class FieldDB:leveldb::DB { +public: +/*lab1的要求*/ + Status Put(const WriteOptions &options, const Slice &key, const Slice &value) override; + Status PutFields(const WriteOptions &, const Slice &key, const FieldArray &fields) override; + Status Delete(const WriteOptions &options, const Slice &key) override; + Status Write(const WriteOptions &options, WriteBatch *updates) override; + Status Get(const ReadOptions &options, const Slice &key, std::string *value) override; + Status GetFields(const ReadOptions &options, const Slice &key, FieldArray *fields) override; + std::vector FindKeysByField(Field &field) override; + Iterator * NewIterator(const ReadOptions &options) override; + const Snapshot * GetSnapshot() override; + void ReleaseSnapshot(const Snapshot *snapshot) override; + bool GetProperty(const Slice &property, std::string *value) override; + void GetApproximateSizes(const Range *range, int n, uint64_t *sizes) override; + void CompactRange(const Slice *begin, const Slice *end) override; +/*与索引相关*/ + bool CreateIndexOnField(const std::string& field_name); + bool DeleteIndex(std::string &field_name); + std::vector QueryByIndex(Field &field); + +private: + static Status OpenFieldDB(const Options& options,const std::string& name,DB** dbptr); + + leveldb::DBImpl *indexDB; + leveldb::DBImpl *kvDB; +}; +} // end of namespace \ No newline at end of file diff --git a/util/serialize_value.cc b/util/serialize_value.cc index 28ab79a..a1bdb08 100644 --- a/util/serialize_value.cc +++ b/util/serialize_value.cc @@ -41,4 +41,38 @@ FieldArray *ParseValue(const std::string& value_str){ } return res; } + +void InternalFieldArray::Map() { + if(isMapped) return; + for(const Field& pair : fields) { + map[pair.first] = pair.second; + } + isMapped = true; +} + +std::string InternalFieldArray::Serialize() { + std::string result; + if(isMapped) { + for(auto pair : map) { + PutLengthPrefixedSlice(&result, pair.first); + PutLengthPrefixedSlice(&result, pair.second); + } + } else { + result = SerializeValue(fields); + } + return result; +} + +bool InternalFieldArray::HasField(const Field& field) { + if(isMapped) { + if(map.count(field.first) && map[field.first] == field.second) { + return true; + } + return false; + } + return std::find(fields.begin(),fields.end(),field) != fields.end(); +} + + + } \ No newline at end of file diff --git a/util/serialize_value.h b/util/serialize_value.h index 6f9fb2c..ff6e68c 100644 --- a/util/serialize_value.h +++ b/util/serialize_value.h @@ -1,13 +1,56 @@ #ifndef STORAGE_LEVELDB_UTIL_SERIALIZE_VALUE_H_ #define STORAGE_LEVELDB_UTIL_SERIALIZE_VALUE_H_ +#include #include #include +#include +#include "leveldb/slice.h" +#include "util/coding.h" namespace leveldb{ - using Field = std::pair; // field_name:field_value - using FieldArray = std::vector>; +using Field = std::pair; // field_name:field_value +using FieldArray = std::vector>; - std::string SerializeValue(const FieldArray& fields); - FieldArray *ParseValue(const std::string& value_str); +std::string SerializeValue(const FieldArray& fields); +FieldArray *ParseValue(const std::string& value_str); + +class InternalFieldArray { +public: +using FieldMap = std::map; + +InternalFieldArray(const FieldArray &fields, bool to_map = false):fields(fields),isMapped(false) { + if(to_map) Map(); +} + + +InternalFieldArray(const std::string& value_str) { + Slice valueSlice(value_str); + Slice nameSlice,valSlice; + while(GetLengthPrefixedSlice(&valueSlice, &nameSlice)) { + if(GetLengthPrefixedSlice(&valueSlice, &valueSlice)) { + map[nameSlice.ToString()] = valueSlice.ToString(); + } else { + std::cout << "name and val not match!" << std::endl; + } + nameSlice.clear(); + valSlice.clear(); + } +} + +InternalFieldArray(const Slice& slice):leveldb::InternalFieldArray(slice.ToString()) {} + +//将vector变为用map存 +void Map(); + +std::string Serialize(); + +bool HasField(const Field& field); + + +private: +bool isMapped; +const FieldArray fields; +FieldMap map; +}; } #endif \ No newline at end of file