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; } |