|
|
@ -19,7 +19,7 @@ void Request::PendReq(Request *req) { |
|
|
|
|
|
|
|
//为虚函数提供最基本的实现
|
|
|
|
void Request::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB) |
|
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB,std::unordered_set<std::string *> &batchKeySet) |
|
|
|
{ |
|
|
|
assert(0); |
|
|
|
} |
|
|
@ -41,10 +41,28 @@ bool Request::isPending() { |
|
|
|
|
|
|
|
/*******FieldsReq*******/ |
|
|
|
void FieldsReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB) |
|
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB,std::unordered_set<std::string *> &batchKeySet) |
|
|
|
{ |
|
|
|
if (batchKeySet.find(Key) != batchKeySet.end()){ |
|
|
|
return;//并发的被合并的put/delete请求只处理一次
|
|
|
|
} else { |
|
|
|
batchKeySet.insert(Key); |
|
|
|
} |
|
|
|
std::string val_str; |
|
|
|
Status s = DB->kvDB_->Get(ReadOptions(), *Key, &val_str); |
|
|
|
FieldArray *oldFields; |
|
|
|
if (s.IsNotFound()){ |
|
|
|
oldFields = nullptr; |
|
|
|
} else if (s.ok()) { //得到数据库之前key的fields, 判断需不需要删除其中潜在的索引
|
|
|
|
oldFields = ParseValue(val_str); |
|
|
|
} else { |
|
|
|
assert(0); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
KVBatch.Put(Slice(*Key), Slice(SerializeValue(*Fields))); |
|
|
|
bool HasIndex = false; |
|
|
|
bool HasOldIndex = false; |
|
|
|
{ |
|
|
|
// MutexLock L(&DB->index_mu); //互斥访问索引状态表
|
|
|
|
DB->index_mu.AssertHeld(); |
|
|
@ -62,39 +80,118 @@ void FieldsReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
//assert(0);
|
|
|
|
} |
|
|
|
} |
|
|
|
//冲突也可能存在于,需要删除旧数据的索引,但该索引正在创删中
|
|
|
|
if (oldFields != nullptr){ |
|
|
|
for(auto [field_name,field_value] : *oldFields) { |
|
|
|
if(field_name == "") break; |
|
|
|
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); |
|
|
|
return; |
|
|
|
} else if(index_status == IndexStatus::Exist) { |
|
|
|
HasOldIndex = true; |
|
|
|
} |
|
|
|
//assert(0);
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//2.对于没有冲突但含有索引操作的put,构建metaKV,这里直接将KV对简单编码后写入metaDB
|
|
|
|
if(HasIndex) { |
|
|
|
if(HasIndex || HasOldIndex) { |
|
|
|
Slice MetaKey,MetaValue; |
|
|
|
std::string serialized = SerializeValue(*Fields); |
|
|
|
MetaKV MKV = MetaKV(Key,&serialized); |
|
|
|
MKV.Trans(MetaKey, MetaValue); |
|
|
|
MKV.TransPut(MetaKey, MetaValue); |
|
|
|
MetaBatch.Put(MetaKey, MetaValue); |
|
|
|
//第三点是不是应该在这一分支中
|
|
|
|
//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()); |
|
|
|
|
|
|
|
|
|
|
|
//3.1对于含有索引的oldfield删除索引
|
|
|
|
if (HasOldIndex) { |
|
|
|
for(auto [field_name,field_value] : *oldFields) { |
|
|
|
if(field_name == "") continue; |
|
|
|
if(DB->index_.count(field_name)) { |
|
|
|
std::string indexKey; |
|
|
|
AppendIndexKey(&indexKey, ParsedInternalIndexKey( |
|
|
|
*Key,field_name,field_value)); |
|
|
|
IndexBatch.Delete(indexKey); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//3.2对于含有索引的field建立索引
|
|
|
|
if (HasIndex) { |
|
|
|
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()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
//优化:对于3.1,3.2中都有的索引只写一次
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*******DeleteReq*******/ |
|
|
|
void DeleteReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB) |
|
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB,std::unordered_set<std::string *> &batchKeySet) |
|
|
|
{ |
|
|
|
//TODO:
|
|
|
|
if (batchKeySet.find(Key) != batchKeySet.end()){ |
|
|
|
return;//并发的被合并的put/delete请求只处理一次
|
|
|
|
} else { |
|
|
|
batchKeySet.insert(Key); |
|
|
|
} |
|
|
|
//1. 读取当前的最新的键值对,判断是否存在含有键值对的field
|
|
|
|
//2.1 如果无,则正常构造delete
|
|
|
|
//2.2 如果是有的field的索引状态都是exist,则在meta中写KV_Deleting类型的记录
|
|
|
|
//在kvDB和metaDB中写入对应的delete
|
|
|
|
//2.3 如果存在field的索引状态是Creating或者Deleting,那么在那个队列上面进行等待
|
|
|
|
std::string val_str; |
|
|
|
DB->kvDB_->Get(ReadOptions(), *Key, &val_str); |
|
|
|
FieldArray *Fields = ParseValue(val_str); |
|
|
|
KVBatch.Delete(Slice(*Key)); |
|
|
|
bool HasIndex = false; |
|
|
|
{ |
|
|
|
// MutexLock L(&DB->index_mu); //互斥访问索引状态表
|
|
|
|
DB->index_mu.AssertHeld(); |
|
|
|
//1.将存在冲突的delete pend到对应的请求
|
|
|
|
for(auto [field_name,field_value] : *Fields) { |
|
|
|
if(field_name == "") break; |
|
|
|
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); |
|
|
|
return; |
|
|
|
} else if(index_status == IndexStatus::Exist) { |
|
|
|
HasIndex = true; |
|
|
|
} |
|
|
|
//assert(0);
|
|
|
|
} |
|
|
|
} |
|
|
|
//2.对于没有冲突但含有索引操作的delete,构建metaKV,这里直接将KV对简单编码后写入metaDB
|
|
|
|
if(HasIndex) { |
|
|
|
Slice MetaKey; |
|
|
|
MetaKV MKV = MetaKV(Key); |
|
|
|
MKV.TransDelete(MetaKey); //meta中写入一个delete不需要value
|
|
|
|
MetaBatch.Put(MetaKey, Slice()); |
|
|
|
//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.Delete(indexKey); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/*******iCreateReq*******/ |
|
|
@ -126,7 +223,7 @@ void iCreateReq::PendReq(Request *req) { |
|
|
|
} |
|
|
|
|
|
|
|
void iCreateReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB) |
|
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB,std::unordered_set<std::string *> &batchKeySet) |
|
|
|
{ |
|
|
|
//遍历数据库,构建二级索引到indexbatch,(更新metaDB中的元数据为Index类型的(Field,Creating))
|
|
|
|
//一个indexwritebatch写入,那么索引创建删除应该和metadb没有交互
|
|
|
@ -185,7 +282,7 @@ void iDeleteReq::PendReq(Request* req) { |
|
|
|
} |
|
|
|
|
|
|
|
void iDeleteReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, |
|
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB) |
|
|
|
WriteBatch &MetaBatch,fielddb::FieldDB *DB,std::unordered_set<std::string *> &batchKeySet) |
|
|
|
{ |
|
|
|
std::vector<std::pair<std::string, std::string>> keysAndVal = |
|
|
|
DB->FindKeysAndValByFieldName(*Field); |
|
|
|