|
@ -8,6 +8,7 @@ |
|
|
#include "fielddb/encode_index.h"
|
|
|
#include "fielddb/encode_index.h"
|
|
|
#include "fielddb/field_db.h"
|
|
|
#include "fielddb/field_db.h"
|
|
|
#include "fielddb/meta.h"
|
|
|
#include "fielddb/meta.h"
|
|
|
|
|
|
#include "request.h"
|
|
|
namespace fielddb { |
|
|
namespace fielddb { |
|
|
using namespace leveldb; |
|
|
using namespace leveldb; |
|
|
|
|
|
|
|
@ -52,13 +53,13 @@ void FieldsReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
if(field_name == "") break; |
|
|
if(field_name == "") break; |
|
|
if(DB->index_.count(field_name)) { |
|
|
if(DB->index_.count(field_name)) { |
|
|
auto [index_status,parent_req] = DB->index_[field_name]; |
|
|
auto [index_status,parent_req] = DB->index_[field_name]; |
|
|
if(index_status == FieldDB::Creating || index_status == FieldDB::Deleting) { |
|
|
|
|
|
|
|
|
if(index_status == IndexStatus::Creating || index_status == IndexStatus::Deleting) { |
|
|
parent_req->PendReq(this); |
|
|
parent_req->PendReq(this); |
|
|
return; |
|
|
return; |
|
|
} else if(index_status == FieldDB::Exist) { |
|
|
|
|
|
|
|
|
} else if(index_status == IndexStatus::Exist) { |
|
|
HasIndex = true; |
|
|
HasIndex = true; |
|
|
} |
|
|
} |
|
|
assert(0); |
|
|
|
|
|
|
|
|
//assert(0);
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
//2.对于没有冲突但含有索引操作的put,构建metaKV,这里直接将KV对简单编码后写入metaDB
|
|
|
//2.对于没有冲突但含有索引操作的put,构建metaKV,这里直接将KV对简单编码后写入metaDB
|
|
@ -68,15 +69,16 @@ void FieldsReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
MetaKV MKV = MetaKV(Key,&serialized); |
|
|
MetaKV MKV = MetaKV(Key,&serialized); |
|
|
MKV.Trans(MetaKey, MetaValue); |
|
|
MKV.Trans(MetaKey, MetaValue); |
|
|
MetaBatch.Put(MetaKey, MetaValue); |
|
|
MetaBatch.Put(MetaKey, MetaValue); |
|
|
} |
|
|
|
|
|
|
|
|
//第三点是不是应该在这一分支中
|
|
|
//3.对于含有索引的field建立索引
|
|
|
//3.对于含有索引的field建立索引
|
|
|
for(auto [field_name,field_value] : *Fields) { |
|
|
|
|
|
if(field_name == "") continue; |
|
|
|
|
|
if(DB->index_.count(field_name)) { |
|
|
|
|
|
std::string indexKey; |
|
|
|
|
|
AppendIndexKey(&indexKey, ParsedInternalIndexKey( |
|
|
|
|
|
*Key,field_name,field_value)); |
|
|
|
|
|
IndexBatch.Put(indexKey, Slice()); |
|
|
|
|
|
|
|
|
for(auto [field_name,field_value] : *Fields) { |
|
|
|
|
|
if(field_name == "") continue; |
|
|
|
|
|
if(DB->index_.count(field_name)) { |
|
|
|
|
|
std::string indexKey; |
|
|
|
|
|
AppendIndexKey(&indexKey, ParsedInternalIndexKey( |
|
|
|
|
|
*Key,field_name,field_value)); |
|
|
|
|
|
IndexBatch.Put(indexKey, Slice()); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -101,7 +103,7 @@ void iCreateReq::Prepare(FieldDB *DB) { |
|
|
DB->index_mu.AssertHeld(); |
|
|
DB->index_mu.AssertHeld(); |
|
|
if(DB->index_.count(*Field)) { |
|
|
if(DB->index_.count(*Field)) { |
|
|
auto [istatus,parent] = DB->index_[*Field]; |
|
|
auto [istatus,parent] = DB->index_[*Field]; |
|
|
if(istatus == FieldDB::Exist) { |
|
|
|
|
|
|
|
|
if(istatus == IndexStatus::Exist) { |
|
|
//如果已经完成建立索引,则返回成功
|
|
|
//如果已经完成建立索引,则返回成功
|
|
|
done = true; |
|
|
done = true; |
|
|
Existed = true; |
|
|
Existed = true; |
|
@ -114,22 +116,48 @@ void iCreateReq::Prepare(FieldDB *DB) { |
|
|
} |
|
|
} |
|
|
//如果索引状态表中没有,则表示尚未创建,更新相应的状态
|
|
|
//如果索引状态表中没有,则表示尚未创建,更新相应的状态
|
|
|
//这里将done设置为true表示在taskqueue中需要完成的部分已经完成,不需要pend
|
|
|
//这里将done设置为true表示在taskqueue中需要完成的部分已经完成,不需要pend
|
|
|
DB->index_[*Field] = {FieldDB::Creating,this}; |
|
|
|
|
|
|
|
|
DB->index_[*Field] = {IndexStatus::Creating,this}; |
|
|
done = true; |
|
|
done = true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void iCreateReq::PendReq(Request *req) { |
|
|
|
|
|
req->parent = this; |
|
|
|
|
|
pending_list.push_back(req); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void iCreateReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
void iCreateReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB) |
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB) |
|
|
{ |
|
|
{ |
|
|
//TODO:遍历数据库,构建二级索引到indexbatch,并且更新metaDB中的元数据为Index类型的(Field,Creating)
|
|
|
|
|
|
//这里或许不需要在metaDB中先写一遍?
|
|
|
|
|
|
|
|
|
//遍历数据库,构建二级索引到indexbatch,(更新metaDB中的元数据为Index类型的(Field,Creating))
|
|
|
|
|
|
//一个indexwritebatch写入,那么索引创建删除应该和metadb没有交互
|
|
|
|
|
|
std::vector<std::pair<std::string, std::string>> keysAndVal = |
|
|
|
|
|
DB->FindKeysAndValByFieldName(*Field); |
|
|
|
|
|
Slice value = Slice(); |
|
|
|
|
|
for (auto &kvPair : keysAndVal){ |
|
|
|
|
|
std::string indexKey; |
|
|
|
|
|
AppendIndexKey(&indexKey, |
|
|
|
|
|
ParsedInternalIndexKey(kvPair.first, *Field, kvPair.second)); |
|
|
|
|
|
IndexBatch.Put(indexKey, value); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void iCreateReq::Finalize(FieldDB *DB) { |
|
|
void iCreateReq::Finalize(FieldDB *DB) { |
|
|
//TODO:
|
|
|
|
|
|
//1. 写入完成后,更新index状态表,并将metaDB的值改为Index类型的(Field,Existing)
|
|
|
|
|
|
//2. 将所有的pendinglist重新入队
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//1. 写入完成后,更新index状态表,(并将metaDB的值改为Index类型的(Field,Existing))
|
|
|
|
|
|
MutexLock iL(&DB->index_mu); |
|
|
|
|
|
DB->index_[*Field] = {IndexStatus::Exist, nullptr}; |
|
|
|
|
|
DB->index_mu.Unlock(); |
|
|
|
|
|
|
|
|
|
|
|
if (pending_list.empty()) return; |
|
|
|
|
|
//2. 将所有的pendinglist重新入队
|
|
|
|
|
|
MutexLock L(&DB->mutex_); |
|
|
|
|
|
for (auto req : pending_list){ |
|
|
|
|
|
DB->taskqueue_.push_back(req); |
|
|
|
|
|
req->parent = req; //解绑
|
|
|
|
|
|
} |
|
|
|
|
|
if (pending_list[0] == DB->taskqueue_.front()) { |
|
|
|
|
|
pending_list[0]->cond_.Signal(); |
|
|
|
|
|
} |
|
|
|
|
|
this->s = Status::OK(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/*******iDeleteReq*******/ |
|
|
/*******iDeleteReq*******/ |
|
@ -142,8 +170,8 @@ void iDeleteReq::Prepare(FieldDB *DB) { |
|
|
return ; |
|
|
return ; |
|
|
} |
|
|
} |
|
|
auto [istatus,parent] = DB->index_[*Field]; |
|
|
auto [istatus,parent] = DB->index_[*Field]; |
|
|
if(istatus == FieldDB::Exist) { |
|
|
|
|
|
DB->index_[*Field] = {FieldDB::Creating,this}; |
|
|
|
|
|
|
|
|
if(istatus == IndexStatus::Exist) { |
|
|
|
|
|
DB->index_[*Field] = {IndexStatus::Deleting,this}; |
|
|
done = true; |
|
|
done = true; |
|
|
} else { |
|
|
} else { |
|
|
//如果正在创建或者删除,那么pend到对应的请求上
|
|
|
//如果正在创建或者删除,那么pend到对应的请求上
|
|
@ -151,14 +179,42 @@ void iDeleteReq::Prepare(FieldDB *DB) { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void iDeleteReq::PendReq(Request* req) { |
|
|
|
|
|
req->parent = this; |
|
|
|
|
|
pending_list.push_back(req); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void iDeleteReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
void iDeleteReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB) |
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB) |
|
|
{ |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
std::vector<std::pair<std::string, std::string>> keysAndVal = |
|
|
|
|
|
DB->FindKeysAndValByFieldName(*Field); |
|
|
|
|
|
Slice value = Slice(); |
|
|
|
|
|
for (auto &kvPair : keysAndVal){ |
|
|
|
|
|
std::string indexKey; |
|
|
|
|
|
AppendIndexKey(&indexKey, |
|
|
|
|
|
ParsedInternalIndexKey(kvPair.first, *Field, kvPair.second)); |
|
|
|
|
|
IndexBatch.Delete(indexKey); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void iDeleteReq::Finalize(FieldDB *DB) { |
|
|
void iDeleteReq::Finalize(FieldDB *DB) { |
|
|
|
|
|
|
|
|
|
|
|
MutexLock iL(&DB->index_mu); |
|
|
|
|
|
DB->index_.erase(*Field); |
|
|
|
|
|
DB->index_mu.Unlock(); |
|
|
|
|
|
|
|
|
|
|
|
if (pending_list.empty()) return; |
|
|
|
|
|
//2. 将所有的pendinglist重新入队
|
|
|
|
|
|
MutexLock L(&DB->mutex_); |
|
|
|
|
|
for (auto req : pending_list){ |
|
|
|
|
|
DB->taskqueue_.push_back(req); |
|
|
|
|
|
req->parent = req; //解绑
|
|
|
|
|
|
} |
|
|
|
|
|
if (pending_list[0] == DB->taskqueue_.front()) { |
|
|
|
|
|
pending_list[0]->cond_.Signal(); |
|
|
|
|
|
} |
|
|
|
|
|
this->s = Status::OK(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace fielddb
|