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;

}

3SuperBlockImpl

//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: 每个Blockhash()的个数

                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;

}

 

原创粉丝点击