#include "leveldb/write_batch.h" #include "db/dbformat.h" #include "leveldb/db.h" #include "util/coding.h" #include "leveldb/my_leveldb.h" #include "unordered_map" #include namespace leveldb { //反序列化为字段数组 void MyLevelDB::ParseValue(const std::string& value_str, FieldArray& resFieldArray) { std::stringstream ss(value_str); std::string segment; // 按逗号分割字符串 while (std::getline(ss, segment, ',')) { std::string key; std::string value; std::stringstream kv(segment); if (std::getline(kv, key, ':') && std::getline(kv, value, ':')) { if (!key.empty() && !value.empty()) { resFieldArray.push_back(std::make_pair(key, value)); // std::cout << ((resFieldArray.back()).first).data() << std::endl; } else { std::cerr << "Invalid key-value pair: " << segment << std::endl; } } else { std::cerr << "Failed to parse segment: " << segment << std::endl; } } } //序列化为字符串 void MyLevelDB::SerializeValue(const FieldArray& fields, std::string& resString) { resString.clear(); for (int i = 0; i < fields.size(); i++) { const std::string& key = fields[i].first; const std::string& value = fields[i].second; resString += key + ":" +value; if (i != fields.size() - 1) { resString += ","; } } } Status MyLevelDB::PutWithFields(const WriteOptions& options,const std::string& key,const FieldArray& fields) { std::string value; SerializeValue(fields, value); auto slice_key = Slice(key.c_str()); auto slice_value = Slice(value.c_str()); Status s = _fields_db->Put(options, slice_key, slice_value); std::unordered_map match; std::unique_lock l(mutex_); for (int i = 0; i < fields.size(); i++) { for (size_t idx = 0; idx < index_list_.size(); idx++) { const auto& i_name = index_list_[idx]; if (fields[i].first == i_name) { match[i] = idx; break; } } } for (auto item : match) { std::string composed_key; composed_key += fields[item.first].second + ":" + key; s = index_db[item.second]->Put(options, composed_key, Slice()); } return s; } Status MyLevelDB::FindKeysByField(const ReadOptions& options, const Field field, std::vector* keys) { auto it = _fields_db->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 MyLevelDB::CreateIndexOnField(const std::string& field_name) { for (const auto& field : this->index_list_) { if (field == field_name) { return Status::InvalidArgument(field_name, "Index already exists for this field"); } } index_list_.push_back(field_name); Options op = _op; DB* field_db; op.index_mode = true; Status status = DB::Open(op, _db_name + "_index_" + field_name, &field_db); index_db.push_back(field_db); if (!status.ok()) { std::cerr << "Failed to open index DB: " << status.ToString() << std::endl; abort(); } return status; } Status MyLevelDB::DeleteIndex(std::string& field_name) { auto it = std::find(index_list_.begin(), index_list_.end(), field_name); if (it == index_list_.end()) { return Status::NotFound("Index not found for this field"); } // 从列表中移除该字段 index_list_.erase(it); return Status::OK(); } void MyLevelDB::QueryByIndex(const ReadOptions& options, Field& field, std::vector& keys) { int i = 0; for (; i < index_list_.size(); i++) { if (index_list_[i] == field.first) { break; } } assert(i != index_list_.size()); auto it = index_db[i]->NewIterator(options); it->SeekToFirst(); while (it->Valid()) { auto val = it->key(); auto str_val = std::string(val.data(), val.size()); std::string key; std::string value; std::stringstream kv(str_val); std::getline(kv, key, ':'); std::getline(kv, value, ':'); if (key == field.second) { keys.push_back(value); } it->Next(); } delete it; } Status MyLevelDB::Put(const WriteOptions& options, const Slice& key, const Slice& value) { return _fields_db->Put(options, key, value); } Status MyLevelDB::Delete(const WriteOptions& options, const Slice& key) { return _fields_db->Delete(options, key); } Status MyLevelDB::Write(const WriteOptions& options, WriteBatch* updates) { assert(0); return Status(); } Status MyLevelDB::Get(const ReadOptions& options, const Slice& key, std::string* value) { return _fields_db->Get(options, key, value); } Iterator* MyLevelDB::NewIterator(const ReadOptions& options) { return _fields_db->NewIterator(options); } const Snapshot* MyLevelDB::GetSnapshot() { return _fields_db->GetSnapshot(); } void MyLevelDB::ReleaseSnapshot(const Snapshot* snapshot) { return _fields_db->ReleaseSnapshot(snapshot); } bool MyLevelDB::GetProperty(const Slice& property, std::string* value) { return false; } void MyLevelDB::GetApproximateSizes(const Range* range, int n, uint64_t* sizes) { /* uint64_t temp = 0; _main_db->GetApproximateSizes(range, n, sizes); for (auto& index_db : field_db_) { index_db->GetApproximateSizes(range, n, &temp); *sizes += temp; }*/ } void MyLevelDB::CompactRange(const Slice* begin, const Slice* end) { _fields_db->CompactRange(begin, end); } }