#include "fielddb/request.h" #include #include "leveldb/slice.h" #include "leveldb/status.h" #include "leveldb/write_batch.h" #include "util/mutexlock.h" #include "util/serialize_value.h" #include "fielddb/encode_index.h" #include "fielddb/field_db.h" #include "fielddb/meta.h" namespace fielddb { using namespace leveldb; //为虚函数提供最基本的实现 void Request::PendReq(Request *req) { assert(0); } //为虚函数提供最基本的实现 void Request::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, WriteBatch &MetaBatch,fielddb::FieldDB *DB) { assert(0); } void Request::Prepare(FieldDB *DB) { assert(0); } void Request::Finalize(FieldDB *DB) { assert(0); } //为虚函数提供最基本的实现 bool Request::isPending() { //pending中的请求的parent会指向所等待的请求(iCreate/iDelete) return parent != this; } /*******FieldsReq*******/ void FieldsReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, WriteBatch &MetaBatch,fielddb::FieldDB *DB) { KVBatch.Put(Slice(*Key), Slice(SerializeValue(*Fields))); bool HasIndex = false; { // MutexLock L(&DB->index_mu); //互斥访问索引状态表 DB->index_mu.AssertHeld(); //1.将存在冲突的put 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 == FieldDB::Creating || index_status == FieldDB::Deleting) { parent_req->PendReq(this); return; } else if(index_status == FieldDB::Exist) { HasIndex = true; } assert(0); } } //2.对于没有冲突但含有索引操作的put,构建metaKV,这里直接将KV对简单编码后写入metaDB if(HasIndex) { Slice MetaKey,MetaValue; std::string serialized = SerializeValue(*Fields); MetaKV MKV = MetaKV(Key,&serialized); MKV.Trans(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()); } } } } /*******DeleteReq*******/ void DeleteReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, WriteBatch &MetaBatch,fielddb::FieldDB *DB) { //TODO: //1. 读取当前的最新的键值对,判断是否存在含有键值对的field //2.1 如果无,则正常构造delete //2.2 如果是有的field的索引状态都是exist,则在meta中写KV_Deleting类型的记录 //在kvDB和metaDB中写入对应的delete //2.3 如果存在field的索引状态是Creating或者Deleting,那么在那个队列上面进行等待 } /*******iCreateReq*******/ void iCreateReq::Prepare(FieldDB *DB) { //在index_中完成索引状态更新,在这里可以避免重复创建 DB->index_mu.AssertHeld(); if(DB->index_.count(*Field)) { auto [istatus,parent] = DB->index_[*Field]; if(istatus == FieldDB::Exist) { //如果已经完成建立索引,则返回成功 done = true; s = Status::OK(); } else { //如果正在创建或删除,那么进行等待 parent->PendReq(this); } return; } //如果索引状态表中没有,则表示尚未创建,更新相应的状态 //这里将done设置为true表示在taskqueue中需要完成的部分已经完成,不需要pend DB->index_[*Field] = {FieldDB::Creating,this}; done = true; } void iCreateReq::ConstructBatch(WriteBatch &KVBatch,WriteBatch &IndexBatch, WriteBatch &MetaBatch,fielddb::FieldDB *DB) { //TODO:遍历数据库,构建二级索引到indexbatch,并且更新metaDB中的元数据为Index类型的(Field,Creating) //这里或许不需要在metaDB中先写一遍? } void iCreateReq::Finalize(FieldDB *DB) { //TODO: //1. 写入完成后,更新index状态表,并将metaDB的值改为Index类型的(Field,Existing) //2. 将所有的pendinglist重新入队 } }