成员:余明阳 包亦晟
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

206 lines
5.8 KiB

#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 <sstream>
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<int, int> match;
std::unique_lock<std::mutex> 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<std::string>* 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<std::string>& 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);
}
}