|
|
@ -6,45 +6,61 @@ |
|
|
|
#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; |
|
|
|
//TODO:打开fieldDB
|
|
|
|
Status FieldDB::OpenFieldDB(const Options& options,const std::string& name,DB** dbptr) { |
|
|
|
Status FieldDB::OpenFieldDB(const Options& options, |
|
|
|
const std::string& name, FieldDB** dbptr) { |
|
|
|
// options.env->CreateDir("./abc")
|
|
|
|
*dbptr = new FieldDB(options,name); |
|
|
|
return Status::OK(); |
|
|
|
} |
|
|
|
|
|
|
|
Status FieldDB::Recover() { |
|
|
|
|
|
|
|
} |
|
|
|
if(*dbptr == nullptr){ |
|
|
|
return Status::NotSupported(name, "new a fieldDb first\n"); |
|
|
|
} |
|
|
|
|
|
|
|
FieldDB::FieldDB(const Options& options,const std::string& name) { |
|
|
|
//
|
|
|
|
Status status; |
|
|
|
status = Open(options, name+"_indexDB", &indexDB); |
|
|
|
if(!status.ok()) return; |
|
|
|
status = Open(options, name+"_kvDB", &kvDB); |
|
|
|
if(!status.ok()) return; |
|
|
|
status = Open(options, name+"_metaDB", &metaDB); |
|
|
|
if(!status.ok()) return; |
|
|
|
|
|
|
|
Recover(); |
|
|
|
DB *indexdb, *kvdb, *metadb; |
|
|
|
status = Open(options, name+"_indexDB", &indexdb); |
|
|
|
if(!status.ok()) return status; |
|
|
|
|
|
|
|
status = Open(options, name+"_kvDB", &kvdb); |
|
|
|
if(!status.ok()) return status; |
|
|
|
status = Open(options, name+"_metaDB", &metadb); |
|
|
|
if(!status.ok()) return status; |
|
|
|
|
|
|
|
(*dbptr)->indexDB_ = indexdb; |
|
|
|
(*dbptr)->kvDB_ = kvdb; |
|
|
|
(*dbptr)->metaDB_ = metadb; |
|
|
|
(*dbptr)->dbname_ = name; |
|
|
|
|
|
|
|
status = (*dbptr)->Recover(); |
|
|
|
return status; |
|
|
|
} |
|
|
|
|
|
|
|
// todo
|
|
|
|
Status FieldDB::Recover() { |
|
|
|
//
|
|
|
|
return Status::OK(); |
|
|
|
} |
|
|
|
|
|
|
|
Status FieldDB::Put(const WriteOptions &options, const Slice &key, const Slice &value) { |
|
|
|
return kvDB->Put(options, key, 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::PutFields(const WriteOptions &Options, |
|
|
|
const Slice &key, const FieldArray &fields) { |
|
|
|
//
|
|
|
|
return kvDB_->PutFields(Options, key, fields); |
|
|
|
} |
|
|
|
|
|
|
|
// todo: 删除有索引的key时indexdb也要同步
|
|
|
|
Status FieldDB::Delete(const WriteOptions &options, const Slice &key) { |
|
|
|
return kvDB->Delete(options, key); |
|
|
|
//
|
|
|
|
return kvDB_->Delete(options, key); |
|
|
|
} |
|
|
|
// TODO:根据updates里面的东西,要对是否需要更新index进行分别处理
|
|
|
|
Status FieldDB::Write(const WriteOptions &options, WriteBatch *updates) { |
|
|
@ -52,56 +68,127 @@ Status FieldDB::Write(const WriteOptions &options, WriteBatch *updates) { |
|
|
|
} |
|
|
|
|
|
|
|
Status FieldDB::Get(const ReadOptions &options, const Slice &key, std::string *value) { |
|
|
|
return kvDB->Get(options, key, 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; |
|
|
|
return kvDB_->GetFields(options, key, fields); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
std::vector<std::string> FieldDB::FindKeysByField(Field &field) { |
|
|
|
std::vector<std::string> result; |
|
|
|
auto iter = kvDB->NewIterator(ReadOptions()); |
|
|
|
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()); |
|
|
|
if(fields.HasField(field)) { |
|
|
|
result.push_back(iter->key().ToString()); |
|
|
|
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); |
|
|
|
return kvDB_->NewIterator(options); |
|
|
|
} |
|
|
|
|
|
|
|
// TODO:使用统一seq进行snapshot管理
|
|
|
|
const Snapshot * FieldDB::GetSnapshot() { |
|
|
|
return kvDB->GetSnapshot(); |
|
|
|
return kvDB_->GetSnapshot(); |
|
|
|
} |
|
|
|
// TODO:同上
|
|
|
|
void FieldDB::ReleaseSnapshot(const Snapshot *snapshot) { |
|
|
|
kvDB->ReleaseSnapshot(snapshot); |
|
|
|
kvDB_->ReleaseSnapshot(snapshot); |
|
|
|
} |
|
|
|
|
|
|
|
bool FieldDB::GetProperty(const Slice &property, std::string *value) { |
|
|
|
return kvDB->GetProperty(property, value) | indexDB->GetProperty(property, 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); |
|
|
|
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); |
|
|
|
kvDB_->CompactRange(begin, end); |
|
|
|
} |
|
|
|
|
|
|
|
} // end of namespace
|