|
|
@ -1,8 +1,12 @@ |
|
|
|
#include "fielddb/request.h"
|
|
|
|
#include <cassert>
|
|
|
|
#include <deque>
|
|
|
|
#include <string>
|
|
|
|
#include <unordered_set>
|
|
|
|
#include "leveldb/slice.h"
|
|
|
|
#include "leveldb/status.h"
|
|
|
|
#include "leveldb/write_batch.h"
|
|
|
|
#include "port/port_stdcxx.h"
|
|
|
|
#include "util/mutexlock.h"
|
|
|
|
#include "util/serialize_value.h"
|
|
|
|
#include "fielddb/encode_index.h"
|
|
|
@ -56,7 +60,8 @@ void FieldsReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
if (s.IsNotFound()){ |
|
|
|
oldFields = nullptr; |
|
|
|
} else if (s.ok()) { //得到数据库之前key的fields, 判断需不需要删除其中潜在的索引
|
|
|
|
oldFields = ParseValue(val_str); |
|
|
|
oldFields = new FieldArray; |
|
|
|
oldFields = ParseValue(val_str,oldFields); |
|
|
|
} else { |
|
|
|
assert(0); |
|
|
|
} |
|
|
@ -72,7 +77,7 @@ void FieldsReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
if(DB->index_.count(field_name)) { |
|
|
|
auto [index_status,parent_req] = DB->index_[field_name]; |
|
|
|
if(index_status == IndexStatus::Creating || index_status == IndexStatus::Deleting) { |
|
|
|
parent_req->PendReq(this); |
|
|
|
parent_req->PendReq(this->parent); |
|
|
|
return; |
|
|
|
} else if(index_status == IndexStatus::Exist) { |
|
|
|
HasIndex = true; |
|
|
@ -87,7 +92,7 @@ void FieldsReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
if(DB->index_.count(field_name)) { |
|
|
|
auto [index_status,parent_req] = DB->index_[field_name]; |
|
|
|
if(index_status == IndexStatus::Creating || index_status == IndexStatus::Deleting) { |
|
|
|
parent_req->PendReq(this); |
|
|
|
parent_req->PendReq(this->parent); |
|
|
|
return; |
|
|
|
} else if(index_status == IndexStatus::Exist) { |
|
|
|
HasOldIndex = true; |
|
|
@ -100,11 +105,11 @@ void FieldsReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
KVBatch.Put(Slice(*Key), Slice(SerializeValue(*Fields))); |
|
|
|
//2.对于没有冲突但含有索引操作的put,构建metaKV,这里直接将KV对简单编码后写入metaDB
|
|
|
|
if(HasIndex || HasOldIndex) { |
|
|
|
Slice MetaKey,MetaValue; |
|
|
|
std::string MetaKey,MetaValue; |
|
|
|
std::string serialized = SerializeValue(*Fields); |
|
|
|
MetaKV MKV = MetaKV(Key,&serialized); |
|
|
|
MKV.TransPut(MetaKey, MetaValue); |
|
|
|
MetaBatch.Put(MetaKey, MetaValue); |
|
|
|
MetaBatch.Put(MetaKey, serialized); |
|
|
|
|
|
|
|
|
|
|
|
//3.1对于含有索引的oldfield删除索引
|
|
|
@ -136,6 +141,8 @@ void FieldsReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
} |
|
|
|
//优化:对于3.1,3.2中都有的索引只写一次
|
|
|
|
} |
|
|
|
|
|
|
|
if(oldFields) delete oldFields; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -157,7 +164,9 @@ void DeleteReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
std::string val_str; |
|
|
|
Status s = DB->kvDB_->Get(ReadOptions(), *Key, &val_str); |
|
|
|
if (s.IsNotFound()) return; |
|
|
|
FieldArray *Fields = ParseValue(val_str); |
|
|
|
FieldArray *Fields = new FieldArray; |
|
|
|
ParseValue(val_str,Fields); |
|
|
|
KVBatch.Delete(Slice(*Key)); |
|
|
|
bool HasIndex = false; |
|
|
|
{ |
|
|
|
// MutexLock L(&DB->index_mu); //互斥访问索引状态表
|
|
|
@ -168,7 +177,7 @@ void DeleteReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
if(DB->index_.count(field_name)) { |
|
|
|
auto [index_status,parent_req] = DB->index_[field_name]; |
|
|
|
if(index_status == IndexStatus::Creating || index_status == IndexStatus::Deleting) { |
|
|
|
parent_req->PendReq(this); |
|
|
|
parent_req->PendReq(this->parent); |
|
|
|
return; |
|
|
|
} else if(index_status == IndexStatus::Exist) { |
|
|
|
HasIndex = true; |
|
|
@ -179,7 +188,7 @@ void DeleteReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
KVBatch.Delete(Slice(*Key)); |
|
|
|
//2.对于没有冲突但含有索引操作的delete,构建metaKV,这里直接将KV对简单编码后写入metaDB
|
|
|
|
if(HasIndex) { |
|
|
|
Slice MetaKey; |
|
|
|
std::string MetaKey; |
|
|
|
MetaKV MKV = MetaKV(Key); |
|
|
|
MKV.TransDelete(MetaKey); //meta中写入一个delete不需要value
|
|
|
|
MetaBatch.Put(MetaKey, Slice()); |
|
|
@ -195,6 +204,7 @@ void DeleteReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
delete Fields; |
|
|
|
} |
|
|
|
|
|
|
|
/*******iCreateReq*******/ |
|
|
@ -210,7 +220,7 @@ void iCreateReq::Prepare(FieldDB *DB) { |
|
|
|
s = Status::OK(); |
|
|
|
} else { |
|
|
|
//如果正在创建或删除,那么进行等待
|
|
|
|
parent->PendReq(this); |
|
|
|
parent->PendReq(this->parent); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
@ -317,5 +327,67 @@ void iDeleteReq::Finalize(FieldDB *DB) { |
|
|
|
this->s = Status::OK(); |
|
|
|
} |
|
|
|
|
|
|
|
BatchReq::BatchReq(WriteBatch *Batch,port::Mutex *mu): |
|
|
|
Batch(Batch),Request(BatchReq_t, mu) { |
|
|
|
|
|
|
|
struct BatchHandler : WriteBatch::Handler { |
|
|
|
void Put(const Slice &key, const Slice &value) override { |
|
|
|
//为key和value构造存储的地方,防止由于string的析构造成可能得内存访问错误
|
|
|
|
str_buf->push_back(key.ToString()); |
|
|
|
fa_buf->push_back({{"",value.ToString()}}); |
|
|
|
sub_requests->emplace_back(new FieldsReq(&str_buf->back(),&fa_buf->back(),mu)); |
|
|
|
sub_requests->back()->parent = req; |
|
|
|
} |
|
|
|
void Delete(const Slice &key) override { |
|
|
|
str_buf->push_back(key.ToString()); |
|
|
|
sub_requests->emplace_back(new DeleteReq(&str_buf->back(),mu)); |
|
|
|
sub_requests->back()->parent = req; |
|
|
|
} |
|
|
|
|
|
|
|
BatchReq *req; |
|
|
|
port::Mutex *mu; |
|
|
|
std::deque<std::string> *str_buf; |
|
|
|
std::deque<FieldArray> *fa_buf; |
|
|
|
std::deque<Request*> *sub_requests; |
|
|
|
}; |
|
|
|
|
|
|
|
BatchHandler Handler; |
|
|
|
Handler.req = this; |
|
|
|
Handler.mu = mu; |
|
|
|
Handler.str_buf = &str_buf; |
|
|
|
Handler.fa_buf = &fa_buf; |
|
|
|
Handler.sub_requests = &sub_requests; |
|
|
|
|
|
|
|
Batch->Iterate(&Handler); |
|
|
|
} |
|
|
|
|
|
|
|
BatchReq::~BatchReq() { |
|
|
|
while(!sub_requests.empty()) { |
|
|
|
Request *req = sub_requests.front(); |
|
|
|
sub_requests.pop_front(); |
|
|
|
delete req; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void BatchReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB,std::unordered_set<std::string *> &batchKeySet) |
|
|
|
{ |
|
|
|
WriteBatch Sub_KVBatch,Sub_IndexBatch,Sub_MetaBatch; |
|
|
|
std::unordered_set<std::string *> Sub_batchKeySet; |
|
|
|
//由于batch是有顺序的,根据我们现在的一个key只处理最开始的算法,这里需要反向迭代
|
|
|
|
for(auto subreq = sub_requests.rbegin(); subreq != sub_requests.rend(); subreq++ ) { |
|
|
|
(*subreq)->ConstructBatch(Sub_KVBatch, Sub_IndexBatch, Sub_MetaBatch, DB, Sub_batchKeySet); |
|
|
|
//所有的对于pendreq的调用传入的参数被改成了this->parent,因此,对于subrequests来说,
|
|
|
|
//pendreq的传参为对应的Batchreq,因此,此处判断batchreq是否pending可以得到subreq是否有冲突
|
|
|
|
if(isPending()) { |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
KVBatch.Append(Sub_KVBatch); |
|
|
|
IndexBatch.Append(Sub_IndexBatch); |
|
|
|
MetaBatch.Append(Sub_MetaBatch); |
|
|
|
batchKeySet.insert(batchKeySet.begin(),batchKeySet.end()); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} // namespace fielddb
|