10225501448 李度 10225101546 陈胤遒 10215501422 高宇菲
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 

134 lignes
4.6 KiB

#include "fielddb/request.h"
#include <cassert>
#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重新入队
}
}