TFS文件系统数据服务器启动加载分析
来源:互联网 发布:酒神文化知乎 编辑:程序博客网 时间:2024/05/18 14:44
TFS文件系统数据服务器启动加载分析
TFS文件系统的数据服务器在启动时会有加载超级块,加载文件块的操作,可以对照代码,
做下分析.
(1). 启动加载
int BlockFileManager::bootstrap(const SysParam::FileSystemParam& fs_param)
{
//装载超级块
int ret = load_super_blk(fs_param);
if (TFS_SUCCESS != ret){
return ret;
}
//装载块文件
return load_block_file();
}
(2). 装载超级块
//加载超级块
int BlockFileManager::load_super_blk(const SysParam::FileSystemParam& fs_param)
{
bool fs_init_status = true;
//reserve:储备,mount:安装
TBSYS_LOG(INFO, "read super block. mount name: %s, offset: %d/n", fs_param.mount_name_.c_str(),fs_param.super_block_reserve_offset_);
//会去读取超级块存成的文件
super_block_impl_ = new SuperBlockImpl(fs_param.mount_name_, fs_param.super_block_reserve_offset_);
int ret = super_block_impl_->read_super_blk(super_block_);
if (TFS_SUCCESS != ret)
{
TBSYS_LOG(ERROR, "read super block error. ret: %d, desc: %s/n", ret, strerror(errno));
return ret;
}
//在检查超级块的状态:是否是DEV_TAG="TAOBAO"
if (!super_block_impl_->check_status(DEV_TAG, super_block_))
{
fs_init_status = false;
}
//接上面的判断是否进行了文件系统格式化
if (!fs_init_status)
{
TBSYS_LOG(ERROR, "file system not inited. please format it first./n");
return EXIT_FS_NOTINIT_ERROR;
}
//假定主块是,扩展块是,在接着依据这个条件展开
//计算项目个数=主块数+扩展块数+1=9+3+1=13
unsigned item_count = super_block_.main_block_count_ + super_block_.extend_block_count_ + 1;
TBSYS_LOG(INFO, "file system bitmap size: %u/n", item_count);
normal_bit_map_ = new BitMap(item_count);
error_bit_map_ = new BitMap(item_count);
//那么这个时候bit_map_size_=2
bit_map_size_ = normal_bit_map_->get_slot_count();
//假定分配个字节的缓冲
char* tmp_bit_map_buf = new char[4 * bit_map_size_];
memset(tmp_bit_map_buf, 0, 4 * bit_map_size_);
ret = super_block_impl_->read_bit_map(tmp_bit_map_buf, 4 * bit_map_size_);
if (TFS_SUCCESS != ret)
{
tbsys::gDeleteA(tmp_bit_map_buf);
return ret;
}
// 连续对前面四个小段进行比较:因为是* bit_map_size_
// 先比较前面两个,在比较后面两个
if (memcmp(tmp_bit_map_buf, tmp_bit_map_buf + bit_map_size_, bit_map_size_) != 0)
{
tbsys::gDeleteA(tmp_bit_map_buf);
TBSYS_LOG(ERROR, "normal bitmap conflict"); //位图有冲突
return EXIT_BITMAP_CONFLICT_ERROR;
}
if (memcmp(tmp_bit_map_buf + 2 * bit_map_size_, tmp_bit_map_buf + 3 * bit_map_size_, bit_map_size_) != 0)
{
tbsys::gDeleteA(tmp_bit_map_buf);
TBSYS_LOG(ERROR, "error bitmap conflict");
return EXIT_BITMAP_CONFLICT_ERROR;
}
//在装载位图:bit_map_size_=2 tmp_bit_map_buf=4*2=8,分两段,前面一段是普通位图,后面一段是错误位图
normal_bit_map_->copy(bit_map_size_, tmp_bit_map_buf);
error_bit_map_->copy(bit_map_size_, tmp_bit_map_buf + 2 * bit_map_size_);
//计算位图使用的个数
TBSYS_LOG(DEBUG, "bitmap used count: %u, error: %u", normal_bit_map_->get_set_count(),error_bit_map_->get_set_count());
tbsys::gDeleteA(tmp_bit_map_buf);
return TFS_SUCCESS;
}
(3)SuperBlockImpl类
//flag默认值是true,slave:附件
SuperBlockImpl::SuperBlockImpl(const std::string& mount_name, const int32_t super_start_offset, const bool flag) :
super_reserve_offset_(super_start_offset)
{
//dir
if (true == flag)
{
//比如mount_name=/data/tfs1,那么super_block_file_=/data/tfs1/fs_super
super_block_file_ = mount_name + SUPERBLOCK_NAME; ///SUPERBLOCK_NAME: /fs_super
}
else
{
super_block_file_ = mount_name;
}
//bitmap起始偏移量=超级快存储偏移量+2个超级块大小+一个整形大小
bitmap_start_offset_ = super_reserve_offset_ + 2 * sizeof(SuperBlock) + sizeof(int);
//superblock file is already exist
//已经确定了超级块的文件名
file_op_ = new FileOperation(super_block_file_, O_RDWR | O_SYNC);
if (NULL == file_op_)
{
assert(false);
}
}
int SuperBlockImpl::read_super_blk(SuperBlock& super_block) const
{
memset(&super_block, 0, sizeof(SuperBlock));
//super_reserve_offset_:读位置的偏移量
return file_op_->pread_file((char*) (&super_block), sizeof(SuperBlock), super_reserve_offset_);
}
int SuperBlockImpl::write_super_blk(const SuperBlock& super_block)
{
//内存拷贝两个超级块
char* tmp_buf = new char[2 * sizeof(SuperBlock)];
memcpy(tmp_buf, &super_block, sizeof(SuperBlock));
memcpy(tmp_buf + sizeof(SuperBlock), &super_block, sizeof(SuperBlock));
int ret = file_op_->pwrite_file(tmp_buf, 2 * sizeof(SuperBlock), super_reserve_offset_);
tbsys::gDeleteA(tmp_buf);
if (ret)
{
TBSYS_LOG(ERROR, "write super block error. ret: %d, desc: %s", ret, strerror(errno));
return ret;
}
return TFS_SUCCESS;
}
(3). 装载块文件
//加载块文件
int BlockFileManager::load_block_file()
{
//construct logic block and corresponding physicblock list according to bitmap
PhysicalBlockMapIter pit;
bool conflict_flag = false;
PhysicalBlock* t_physical_block = NULL;
PhysicalBlock* ext_physical_block = NULL;
LogicBlock* t_logic_block = NULL;
int ret = TFS_SUCCESS;
//从pos=1开始做循环
for (uint32_t pos = 1; pos <= static_cast<uint32_t> (super_block_.main_block_count_); ++pos)
{
//init every loop
t_physical_block = NULL;
t_logic_block = NULL;
ext_physical_block = NULL;
//如果在普通位图里面找到
if (normal_bit_map_->test(pos))
{
t_physical_block = new PhysicalBlock(pos, super_block_.mount_point_, super_block_.main_block_size_,C_MAIN_BLOCK);
//从块文件中读取物理块前缀
ret = t_physical_block->load_block_prefix();
if (TFS_SUCCESS != ret)
{
TBSYS_LOG(ERROR, "init physical block fail. fatal error! pos: %d, file: %s", pos, super_block_.mount_point_);
break;
}
BlockPrefix block_prefix;
t_physical_block->get_block_prefix(block_prefix);
// not inited, error
if (0 == block_prefix.logic_blockid_)
{
tbsys::gDelete(t_physical_block);
TBSYS_LOG(ERROR, "block prefix illegal! logic blockid: %u, physical pos: %u.", block_prefix.logic_blockid_,
pos);
normal_bit_map_->reset(pos);
super_block_impl_->write_bit_map(normal_bit_map_, error_bit_map_);
continue;
}
//在生成逻辑块,并且打开/data/tfs1/index/逻辑块blockid映射文件
t_logic_block = new LogicBlock(block_prefix.logic_blockid_, pos, super_block_.mount_point_);
t_logic_block->add_physic_block(t_physical_block);
//record physical block id
uint32_t logic_block_id = block_prefix.logic_blockid_;
TBSYS_LOG(
DEBUG,
"load logic block. per block size: %u, logic block id: %u, physic prev blockid: %u, physic next blockid: %u, physical blockid: %u.",
super_block_.main_block_size_, logic_block_id, block_prefix.prev_physic_blockid_,
block_prefix.next_physic_blockid_, pos);
//先判断是否已经在physcial_blocks_中了
pit = physcial_blocks_.find(pos);
if (pit != physcial_blocks_.end())
{
ret = EXIT_PHYSIC_UNEXPECT_FOUND_ERROR;
TBSYS_LOG(ERROR, "logic blockid: %u, physical blockid: %u is repetitive. fatal error! ret: %d",
logic_block_id, pos, EXIT_PHYSIC_UNEXPECT_FOUND_ERROR);
break;
}
LogicBlockMapIter mit = logic_blocks_.find(logic_block_id);
if (mit != logic_blocks_.end())
{
TBSYS_LOG(INFO, "logic blockid: %u, map blockid: %u already exist", logic_block_id, mit->first);
mit = compact_logic_blocks_.find(logic_block_id);
if (mit != compact_logic_blocks_.end())
{
TBSYS_LOG(INFO, "logic blockid: %u already exist in compact block map", logic_block_id);
ret = del_block(logic_block_id, C_COMPACT_BLOCK);
if (TFS_SUCCESS != ret)
{
break;
}
}
compact_logic_blocks_.insert(LogicBlockMap::value_type(logic_block_id, t_logic_block));
}
else
{
//将逻辑块号,逻辑块对象指针插入到logic_blocks_这个map中
logic_blocks_.insert(LogicBlockMap::value_type(logic_block_id, t_logic_block));
}
//将位置,物理块指针插入到physcial_blocks_这个map中
physcial_blocks_.insert(PhysicalBlockMap::value_type(pos, t_physical_block));
uint32_t ext_pos = pos;
//在加入扩展逻辑块
while (0 != block_prefix.next_physic_blockid_)
{
ext_physical_block = NULL;
//将物理块位置设置为前一个块id
uint32_t prev_block_id = ext_pos;
//把扩展块位置赋值为下一个物理块设置
ext_pos = block_prefix.next_physic_blockid_;
//bitmap is not set
//program exit
if (!normal_bit_map_->test(ext_pos))
{
TBSYS_LOG(ERROR, "ext next physicblock and bitmap conflicted! logic blockid: %u, physical blockid: %u.",
logic_block_id, ext_pos);
ret = EXIT_BLOCKID_CONFLICT_ERROR;
break;
}
//新生成扩展物理块
PhysicalBlock* ext_physical_block = new PhysicalBlock(ext_pos, super_block_.mount_point_,super_block_.extend_block_size_, C_EXT_BLOCK);
ret = ext_physical_block->load_block_prefix();
if (TFS_SUCCESS != ret)
{
TBSYS_LOG(ERROR, "init physical block fail. fatal error! pos: %u, mount point: %s", pos,
super_block_.mount_point_);
break;
}
memset(&block_prefix, 0, sizeof(BlockPrefix));
ext_physical_block->get_block_prefix(block_prefix);
if (prev_block_id != block_prefix.prev_physic_blockid_)
{
TBSYS_LOG(ERROR, "read prev blockid conflict! prev blockid: %u. block prefix's physic prev blockid: %u",
prev_block_id, block_prefix.prev_physic_blockid_);
//release
normal_bit_map_->reset(pos);
super_block_impl_->write_bit_map(normal_bit_map_, error_bit_map_);
conflict_flag = true;
break;
}
TBSYS_LOG(
DEBUG,
"read blockprefix! ext physical blockid pos: %u. prev blockid: %u. blockprefix's physic prev blockid: %u, next physic blockid: %u, logic blockid :%u",
ext_pos, prev_block_id, block_prefix.prev_physic_blockid_, block_prefix.next_physic_blockid_,
block_prefix.logic_blockid_);
pit = physcial_blocks_.find(ext_pos);
if (pit != physcial_blocks_.end())
{
ret = EXIT_PHYSIC_UNEXPECT_FOUND_ERROR;
TBSYS_LOG(ERROR, "logic blockid: %u, physical blockid: %u is repetitive. fatal error!", logic_block_id,
ext_pos);
break;
}
//同样将扩展物理块加入到逻辑块列表中
t_logic_block->add_physic_block(ext_physical_block);
physcial_blocks_.insert(PhysicalBlockMap::value_type(ext_pos, ext_physical_block));
}
if (TFS_SUCCESS != ret)
{
break;
}
if (conflict_flag)
{
TBSYS_LOG(ERROR, "delete load conflict block. logic blockid: %u", logic_block_id);
del_block(logic_block_id, C_CONFUSE_BLOCK);
continue;
}
//逻辑块加载块文件
ret = t_logic_block->load_block_file(super_block_.hash_slot_size_, super_block_.mmap_option_);
//if these error happened when load block, program should exit
if (TFS_SUCCESS != ret && EXIT_COMPACT_BLOCK_ERROR != ret && EXIT_BLOCKID_ZERO_ERROR != ret)
{
TBSYS_LOG(ERROR, "logicblock load error! logic blockid: %u. ret: %d", logic_block_id, ret);
break;
}
else if (TFS_SUCCESS != ret) // ret == EXIT_COMPACT_BLOCK_ERROR || ret == EXIT_BLOCKID_ZERO_ERROR
{
//roll back
//can not make sure the type of this block, so add to confuse type
del_block(logic_block_id, C_CONFUSE_BLOCK);
ret = TFS_SUCCESS;
}
}
conflict_flag = false;
}
if (TFS_SUCCESS != ret)
{
tbsys::gDelete(t_physical_block);
tbsys::gDelete(t_logic_block);
tbsys::gDelete(ext_physical_block);
}
return ret;
}
(4).涉及到的IndexHandle类的方法:
IndexHandle::IndexHandle(const std::string& base_path, const uint32_t main_block_id)
{
//create file_op handle
std::stringstream tmp_stream;
//tmp_stream=/data/tfs1/index/物理块blockid
tmp_stream << base_path << INDEX_DIR_PREFIX << main_block_id;
std::string index_path;
tmp_stream >> index_path;
//创建一个映射到文件的指针
file_op_ = new MMapFileOperation(index_path, O_RDWR | O_LARGEFILE | O_CREAT);
is_load_ = false;
}
//创建索引,并且映射到文件中
//在t_logic_block->init_block_file()里被调用
int IndexHandle::create(const uint32_t logic_block_id, const int32_t cfg_bucket_size, const MMapOption map_option,
const DirtyFlag dirty_flag)
{
TBSYS_LOG(
DEBUG,
"index create block: %u index. bucket size: %d, max mmap size: %d, first mmap size: %d, per mmap size: %d, dirty flag: %d",
logic_block_id, cfg_bucket_size, map_option.max_mmap_size_, map_option.first_mmap_size_,
map_option.per_mmap_size_, dirty_flag);
if (is_load_)
{
return EXIT_INDEX_ALREADY_LOADED_ERROR;
}
int ret = TFS_SUCCESS;
int64_t file_size = file_op_->get_file_size();
if (file_size < 0)
{
return TFS_ERROR;
}
else if (file_size == 0) // empty file
{
IndexHeader i_header;
i_header.block_info_.block_id_ = logic_block_id;
i_header.block_info_.seq_no_ = 1;
//cfg_bucket_size: 每个Block中hash槽(桶)的个数
i_header.index_file_size_ = sizeof(IndexHeader) + cfg_bucket_size * sizeof(int32_t);
i_header.bucket_size_ = cfg_bucket_size;
i_header.flag_ = dirty_flag;
// index header + total buckets 索引头结构+总的桶尺寸大小
char* init_data = new char[i_header.index_file_size_];
memcpy(init_data, &i_header, sizeof(IndexHeader));
memset(init_data + sizeof(IndexHeader), 0, i_header.index_file_size_ - sizeof(IndexHeader));
//写入索引头结构以及桶结构数组到文件,这个时候还并没有映射到文件,因此是直接写文件
ret = file_op_->pwrite_file(init_data, i_header.index_file_size_, 0);
delete[] init_data;
init_data = NULL;
if (TFS_SUCCESS != ret)
return ret;
}
else //file size > 0, index already exist
{
return EXIT_INDEX_UNEXPECT_EXIST_ERROR;
}
//在进行映射文件操作
ret = file_op_->mmap_file(map_option);
if (TFS_SUCCESS != ret) //mmap fail
return ret;
is_load_ = true;
TBSYS_LOG(
INFO,
"init blockid: %u index successful. data file size: %d, index file size: %d, bucket size: %d, free head offset: %d, seqno: %d, size: %d, filecount: %d, del_size: %d, del_file_count: %d version: %d",
logic_block_id, index_header()->data_file_offset_, index_header()->index_file_size_,
index_header()->bucket_size_, index_header()->free_head_offset_, block_info()->seq_no_, block_info()->size_,
block_info()->file_count_, block_info()->del_size_, block_info()->del_file_count_, block_info()->version_);
return TFS_SUCCESS;
}
int IndexHandle::load(const uint32_t logic_block_id, const int32_t cfg_bucket_size, const MMapOption map_option)
{
if (is_load_)
{
return EXIT_INDEX_ALREADY_LOADED_ERROR;
}
int ret = TFS_SUCCESS;
int file_size = file_op_->get_file_size();
if (file_size < 0)
{
return file_size;
}
else if (file_size == 0) // empty file
{
return EXIT_INDEX_EMPTY_ERROR;
}
//重新设置内存映射文件大小
MMapOption tmp_map_option = map_option;
if (file_size > tmp_map_option.first_mmap_size_ && file_size <= tmp_map_option.max_mmap_size_)
{
tmp_map_option.first_mmap_size_ = file_size;
}
//进行内存文件映射
ret = file_op_->mmap_file(tmp_map_option);
if (TFS_SUCCESS != ret)
return ret;
//从内存映射文件中取值,比较桶大小
if (cfg_bucket_size != bucket_size())
{
TBSYS_LOG(ERROR, "Index configure error. old bucket size: %u, new bucket size: %d", bucket_size(),
cfg_bucket_size);
return EXIT_BUCKET_CONFIGURE_ERROR;
}
// check block_id
if (logic_block_id != block_info()->block_id_)
{
TBSYS_LOG(ERROR, "block id conflict. blockid: %d, index blockid: %d", logic_block_id, block_info()->block_id_);
return EXIT_BLOCKID_CONFLICT_ERROR;
}
// check flag
if (C_DATA_COMPACT == index_header()->flag_)
{
//unfinish compact block
TBSYS_LOG(ERROR, "It is a unfinish compact block. blockid: %d", logic_block_id);
return EXIT_COMPACT_BLOCK_ERROR;
}
if (C_DATA_CLEAN == index_header()->flag_)
{
//do nothing
}
is_load_ = true;
TBSYS_LOG(
INFO,
"load blockid: %u index successful. data file offset: %d, index file size: %d, bucket size: %d, free head offset: %d, seqno: %d, size: %d, filecount: %d, del size: %d, del file count: %d version: %d",
logic_block_id, index_header()->data_file_offset_, index_header()->index_file_size_, bucket_size(),
index_header()->free_head_offset_, block_info()->seq_no_, block_info()->size_, block_info()->file_count_,
block_info()->del_size_, block_info()->del_file_count_, block_info()->version_);
return TFS_SUCCESS;
}
//生成文件内部id号(key值)
int IndexHandle::find_avail_key(uint64_t& key)
{
if (0 == key)
{
key = block_info()->seq_no_;
} // continue test
int32_t offset = 0, slot = 0;
int ret = TFS_SUCCESS;
MetaInfo meta_info;
int retry_times = MAX_RETRY_TIMES;
bool found = false;
do
{
slot = static_cast<uint32_t> (key) % bucket_size();
//首先找到第一个元文件结点
offset = bucket_slot()[slot];
//如果是,说明还没有该桶的第一个元文件存在,直接返回,key值取: key = block_info()->seq_no_
if (0 == offset)
{
found = true;
break;
}
//从桶列表里面去查找
for (; offset != 0;)
{
ret = file_op_->pread_file(reinterpret_cast<char*> (&meta_info), META_INFO_SIZE, offset);
if (TFS_SUCCESS != ret)
return ret;
// 如果发现有相同的key值,那么++key,退出循环,否则找下一个元数据文件
if (static_cast<uint32_t> (key) == static_cast<uint32_t> (meta_info.get_key()))
{
++key;
break;
}
offset = meta_info.get_next_meta_offset();
}
if (0 == offset)
{
found = true;
break;
}
}
while (retry_times--);
//更新seq_no_值,给下一个桶生成key做准备
block_info()->seq_no_ = key + 1;
if (!found)
{
TBSYS_LOG(ERROR, "blockid: %u, find avail key fail. new key: %" PRI64_PREFIX "u", block_info()->block_id_, key);
return EXIT_CREATE_FILEID_ERROR;
}
TBSYS_LOG(DEBUG, "blockid: %u, get key: %" PRI64_PREFIX "u, seqno: %u", block_info()->block_id_, key,
block_info()->seq_no_);
return TFS_SUCCESS;
}
//将元数据写入段
int IndexHandle::write_segment_meta(const uint64_t key, const RawMeta& meta)
{
int32_t current_offset = 0, previous_offset = 0;
int ret = hash_find(key, current_offset, previous_offset);
if (TFS_SUCCESS == ret) // check not exists
{
return EXIT_META_UNEXPECT_FOUND_ERROR;
}
else if (EXIT_META_NOT_FOUND_ERROR != ret)
{
return ret;
}
//查找不到,哈希插入操作
int32_t slot = static_cast<uint32_t> (key) % bucket_size();
return hash_insert(slot, previous_offset, meta);
}
//参数:内部文件id号
int IndexHandle::read_segment_meta(const uint64_t key, RawMeta& meta)
{
//find
int32_t current_offset = 0, previous_offset = 0;
int ret = hash_find(key, current_offset, previous_offset);
if (TFS_SUCCESS == ret) //exist
{
//如果查找成功,从当前偏移量开始读取
ret = file_op_->pread_file(reinterpret_cast<char*> (&meta), RAW_META_SIZE, current_offset);
if (TFS_SUCCESS != ret)
return ret;
}
else
{
return ret;
}
return TFS_SUCCESS;
}
//在块中查找内部文件号key
int IndexHandle::hash_find(const uint64_t key, int32_t& current_offset, int32_t& previous_offset)
{
//首先确定槽
int32_t slot = static_cast<uint32_t> (key) % bucket_size(); //取余数
previous_offset = 0;
MetaInfo meta_info;
int ret = TFS_SUCCESS;
//首先查询桶列表数组,初始写入文件时全是,因此需要在此判断不为
for (int32_t pos = bucket_slot()[slot]; pos != 0;)
{
ret = file_op_->pread_file(reinterpret_cast<char*> (&meta_info), META_INFO_SIZE, pos);
if (TFS_SUCCESS != ret)
return ret;
if (hash_compare(key, meta_info.get_key()))
{
current_offset = pos;
return TFS_SUCCESS;
}
previous_offset = pos;
//取下一偏移量位置
pos = meta_info.get_next_meta_offset();
}
return EXIT_META_NOT_FOUND_ERROR;
}
//插入元数据到桶的链表尾部
//索引文件的格式: IndexHeader(头结构)+桶的偏移数组(记录桶中第一个元素的地址)+实际的元数据结构偏移量
int IndexHandle::hash_insert(const int32_t slot, const int32_t previous_offset, const RawMeta& meta)
{
int ret = TFS_SUCCESS;
MetaInfo tmp_meta_info;
int32_t current_offset = 0;
//插入操作时首先取空闲的index_header()->free_head_offset_
if (0 != index_header()->free_head_offset_)
{
ret = file_op_->pread_file(reinterpret_cast<char*> (&tmp_meta_info), META_INFO_SIZE,index_header()->free_head_offset_);
if (TFS_SUCCESS != ret)
return ret;
//得到这个空闲的偏移量位置
current_offset = index_header()->free_head_offset_;
//得到下一个空闲元素的位置作为空闲头部偏移量
//只是占用写入已经被释放元数据的位置,跟key值映射到相同的桶里面没有关系,桶链表还是
//具有相同桶值的链表
index_header()->free_head_offset_ = tmp_meta_info.get_next_meta_offset();
}
else
{
//初始插入时free_head_offset_=0
current_offset = index_header()->index_file_size_;
index_header()->index_file_size_ += META_INFO_SIZE;
}
MetaInfo meta_info(meta);
ret = file_op_->pwrite_file(reinterpret_cast<const char*> (&meta_info), META_INFO_SIZE, current_offset);
if (TFS_SUCCESS != ret)
return ret;
//构造current_offset,previous_offset形成这样的关系,元数据构成偏移量的这种关系
if (0 != previous_offset)
{
//先读出前面的元素,修改它的next_meta_offset_属性,指向当前元素,在保存
ret = file_op_->pread_file(reinterpret_cast<char*> (&tmp_meta_info), META_INFO_SIZE, previous_offset);
if (TFS_SUCCESS != ret)
return ret;
tmp_meta_info.set_next_meta_offset(current_offset);
ret = file_op_->pwrite_file(reinterpret_cast<const char*> (&tmp_meta_info), META_INFO_SIZE, previous_offset);
if (TFS_SUCCESS != ret)
return ret;
}
else
{
//如果是桶的第一个元素,previous_offset=0时,那么将当前偏移量直接赋值给桶的第一个元素
bucket_slot()[slot] = current_offset;
}
return TFS_SUCCESS;
}
//删除指定key值的索引
int IndexHandle::delete_segment_meta(const uint64_t key)
{
//首先定位key值的current_offset,previous_offset
int32_t current_offset = 0, previous_offset = 0;
int ret = hash_find(key, current_offset, previous_offset);
if (TFS_SUCCESS != ret)
return ret;
//通过current_offset在索引文件中取出meta_info
MetaInfo meta_info;
ret = file_op_->pread_file(reinterpret_cast<char*> (&meta_info), META_INFO_SIZE, current_offset);
if (TFS_SUCCESS != ret)
return ret;
//得到该值的下一个元数据的位置偏移量
int32_t tmp_pos = meta_info.get_next_meta_offset();
int32_t slot = static_cast<uint32_t> (key) % bucket_size();
//相当于对链表进行删除结点的操作
if (0 == previous_offset)
{
//如果是首节点,那么指向该节点的下一个结点
bucket_slot()[slot] = tmp_pos;
}
else
{
//否者更新前一个结点的next_meta_offset,指向删除结点的下一个结点的位置
MetaInfo pre_meta_info;
ret = file_op_->pread_file(reinterpret_cast<char*> (&pre_meta_info), META_INFO_SIZE, previous_offset);
if (TFS_SUCCESS != ret)
return ret;
pre_meta_info.set_next_meta_offset(tmp_pos);
ret = file_op_->pwrite_file(reinterpret_cast<const char*> (&pre_meta_info), META_INFO_SIZE, previous_offset);
if (TFS_SUCCESS != ret)
return ret;
}
//并不是删除该节点,而是设置下一个结点是index_header()->free_head_offset_
meta_info.set_next_meta_offset(index_header()->free_head_offset_);
ret = file_op_->pwrite_file(reinterpret_cast<const char*> (&meta_info), META_INFO_SIZE, current_offset);
if (TFS_SUCCESS != ret)
return ret;
//释放的头结点的偏移指向current_offset
//可以看出,这里形成了一个构造删除结点的链表
index_header()->free_head_offset_ = current_offset;
return TFS_SUCCESS;
}
- TFS文件系统数据服务器启动加载分析
- TFS文件系统格式化分析
- TFS文件系统策略分析
- TFS文件系统写文件分析
- TFS文件系统
- TFS数据块同步推送分析
- nginx启动配置加载性能分析(一)-作为http服务器
- 关于监听器的使用(服务器启动时加载数据)
- tfs文件系统笔记
- TFS集群文件系统
- tfs--淘宝文件系统扩容
- TFS淘宝文件系统原理
- TFS文件系统 安装
- 淘宝分布式文件系统TFS
- 根文件系统的启动分析
- Android 根文件系统启动分析
- qtopia 文件系统启动过程分析
- Android 根文件系统启动分析
- 搜索引擎都有哪几种类型?
- sudo命令的使用说明
- 40岁的系统分析员出路在哪里呢?
- TFS文件系统格式化分析
- linux内核编译过程中出现两个错误的解决方法~!
- TFS文件系统数据服务器启动加载分析
- 贝子你能回来吗?
- the connection to the VMware USB Arbitration Service was unsuccessful.Please check the status of this service in the Microsogt M
- TFS文件系统写文件分析
- 将二维矩阵0元素所在行列都标记为0
- 自由软件之父
- magento -- 推荐插件 -- 按字母过滤列表页产品 --alphabates
- 持续进步
- PDM 四阶段成熟度模型