文章目录

  • 1 索引处理类的头文件定义
  • 2 构造函数和析构函数
  • 3 create方法实现
  • 4 load方法实现
  • 5 remove和flush方法的实现
  • 6 索引初始化测试
  • 7 写入文件实现
    • 7.1 哈希查找实现
    • 7.2 哈希插入实现
    • 7.3 更新块信息
    • 7.4 写入文件测试
  • 8 读文件实现
    • 8.1 读MetaInfo
    • 8.2 读流程实现
  • 9 删除文件实现
    • 9.1 删除MetaInfo
    • 9.2 删除文件流程实现

1 索引处理类的头文件定义

#ifndef QINIU_LARGEFILE_INDEX_HANDLE_H_
#define QINIU_LARGEFILE_INDEX_HANDLE_H_#include "common.h"
#include "mmap_file_op.h"namespace qiniu
{namespace largefile{struct IndexHeader{public:IndexHeader(){memset(this, 0, sizeof(IndexHeader));}BlockInfo block_info_;        //meta block infoint32_t     bucket_size_;      //hash bucket sizeint32_t     data_file_offset_; //offset to write next data in blockint32_t     index_file_size_;  //offset after: index_header + all bucketsint32_t     free_head_offset_;// free meta node  list, for reuse};class IndexHandle{public:IndexHandle( const std::string& base_path, const uint32_t main_block_id);~IndexHandle();int create(const uint32_t logic_block_id, const int32_t bucket_size, const MMapOption map_option);int load(const uint32_t logic_block_id, const int32_t bucket_size, const MMapOption map_option);//remove index: unmmap and unlink fileint remove(const uint32_t logic_block_id);int flush();IndexHeader * index_header(){return  reinterpret_cast<IndexHeader *>(file_op_->get_map_data());}int update_block_info(const OperType oper_type, const uint32_t modify_size);BlockInfo* block_info(){return reinterpret_cast<BlockInfo*> (file_op_->get_map_data());}int32_t* bucket_slot(){return reinterpret_cast<int32_t*> (reinterpret_cast<char*>(file_op_->get_map_data()) + sizeof(IndexHeader));}int32_t bucket_size() const {return reinterpret_cast<IndexHeader *>(file_op_->get_map_data())->bucket_size_;}int32_t get_block_data_offset() const{return reinterpret_cast<IndexHeader*>(file_op_->get_map_data())->data_file_offset_;}int32_t free_head_offset() const {return reinterpret_cast<IndexHeader*>(file_op_->get_map_data())->free_head_offset_;}void commit_block_data_offset(const int file_size){reinterpret_cast<IndexHeader*>(file_op_->get_map_data())->data_file_offset_ += file_size;}int32_t write_segment_meta(const uint64_t key, MetaInfo &meta);int32_t read_segment_meta(const uint64_t key, MetaInfo &meta);int32_t delete_segment_meta(const uint64_t key);int32_t hash_find(const uint64_t key, int32_t& current_offset, int32_t&  previous_offset);int32_t hash_insert(const uint64_t key, int32_t previous_offset, MetaInfo &meta);private:bool hash_compare(const uint64_t left_key, const uint64_t right_key){return (left_key == right_key);}MMapFileOperation* file_op_;bool is_load_;};}
}
#endif  //QINIU_LARGEFILE_INDEX_HANDLE_H_

2 构造函数和析构函数

IndexHandle::IndexHandle(const std::string& base_path, const uint32_t main_block_id){//create file_op_ handle objectstd::stringstream tmp_stream;tmp_stream << base_path<< INDEX_DIR_PREFIX<< main_block_id;           //    /root/martin/index/1std::string index_path;tmp_stream>>index_path;file_op_ = new MMapFileOperation(index_path,  O_CREAT | O_RDWR | O_LARGEFILE);is_load_ = false;}IndexHandle::~IndexHandle(){if(file_op_){delete file_op_;file_op_ = NULL;}}

3 create方法实现

int IndexHandle::create(const uint32_t logic_block_id, const int32_t bucket_size, const MMapOption map_option)
{int ret = TFS_SUCCESS;if(debug) printf(" create index , block id: %u , bucket size: %d, max_mmap_size: %d, first mmap size: %d,  per mmap size: %d\n",logic_block_id, bucket_size,  map_option.max_mmap_size_, map_option.first_mmap_size_, map_option.per_mmap_size_);if(is_load_){return EXIT_INDEX_ALREADY_LOADED_ERROR;}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;i_header.bucket_size_ = bucket_size;i_header.index_file_size_ = sizeof(IndexHeader) + bucket_size * sizeof(int32_t);//index header + total bucketschar * 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));//write index header and buckets into index file ret = file_op_->pwrite_file(init_data, i_header.index_file_size_, 0);delete[] init_data;init_data = NULL;if(ret != TFS_SUCCESS ){return ret;}ret = file_op_->flush_file();if(ret != TFS_SUCCESS ){return ret;}}else //file size > 0 , index already exist{return EXIT_META_UNEXPECT_FOUND_ERROR;}ret = file_op_->mmap_file(map_option);if(ret != TFS_SUCCESS){return ret;}is_load_ = true;if(debug) printf("init blockid:  %d 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\n",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;
}

4 load方法实现

int IndexHandle::load(const uint32_t logic_block_id, const int32_t _bucket_size, const MMapOption map_option)
{int ret = TFS_SUCCESS;if(is_load_){return EXIT_INDEX_ALREADY_LOADED_ERROR;}int64_t file_size = file_op_->get_file_size();if(file_size <0){return file_size;}else if(file_size == 0)//empty file {return  EXIT_INDEX_CORRUPT_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( ret != TFS_SUCCESS){return ret;}if(debug) printf("IndexHandle::load - bucket_size(): %d, index_header()->bucket_size_: %d,  block id: %d\n", bucket_size(), index_header()->bucket_size_, block_info()->block_id_);if(0 == bucket_size() || 0 == block_info()->block_id_){fprintf(stderr, "Index corrupt error. blockid: %u, bucket size: %d\n", block_info()->block_id_, bucket_size());return EXIT_INDEX_CORRUPT_ERROR;}//check file sizeint32_t index_file_size = sizeof(IndexHeader) + bucket_size() * sizeof(int32_t);if(file_size < index_file_size){fprintf(stderr, "Index corrupt error,blockid: %u, bucket size: %d, file size: %ld, index file size: %d\n", block_info()->block_id_, bucket_size(), file_size,index_file_size);return EXIT_INDEX_CORRUPT_ERROR;}//check block id if(logic_block_id != block_info()->block_id_){fprintf(stderr, "block id conflict. blockid: %u, index blockid: %u\n", logic_block_id, block_info()->block_id_);return EXIT_BLOCKID_CONFLICT_ERROR;}//check bucket_sizeif(_bucket_size != bucket_size()){fprintf(stderr, "Index configure error, old bucket size: %d, new bucket size: %d\n", bucket_size(), _bucket_size);return EXIT_BUCKET_CONFIGURE_ERROR;}is_load_ = true;if(debug) printf("load blockid:  %d 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\n",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;
}

5 remove和flush方法的实现

int IndexHandle::remove(const uint32_t logic_block_id)
{if(is_load_){if(logic_block_id != block_info()->block_id_){fprintf(stderr, "block id conflict. bolckid: %d, index blokid: %d\n", logic_block_id,  block_info()->block_id_);return EXIT_BLOCKID_CONFLICT_ERROR;}}int ret = file_op_->munmap_file();if( TFS_SUCCESS != ret){return ret;}ret = file_op_->unlink_file();return ret;
}int IndexHandle::flush()
{int  ret = file_op_->flush_file();if(TFS_SUCCESS != ret){fprintf(stderr, "index flush fail , ret: %d error desc: %s\n", ret, strerror(errno));}return ret;
}

6 索引初始化测试

先来看一下块初始化的流程:

测试代码如下:

#include "common.h"
#include "file_op.h"
#include "index_handle.h"
#include <sstream>using namespace qiniu;
using namespace std;const static largefile::MMapOption mmap_option = {1024000, 4096, 4096};  //内存映射的参数
const static uint32_t main_blocksize = 1024*1024*64;  //主块文件的大小
const static uint32_t bucket_size = 1000;  //哈希桶的大小
static int32_t block_id = 1;static int debug = 1;int main(int argc, char **argv)   //argv[0]="rm"  argv[1]="-f"  argv[2] ="a.out"
{std::string mainblock_path;std::string index_path;int32_t ret = largefile::TFS_SUCCESS;cout<<" Type your bockid :"<<endl;cin>> block_id;if(block_id < 1){cerr<<" Invalid blockid, exit."<<endl;exit(-1);}//1. 创建索引文件largefile::IndexHandle *index_handle = new largefile::IndexHandle(".", block_id);  //索引文件句柄if(debug)  printf("Init index ...\n");ret = index_handle->create(block_id, bucket_size, mmap_option);if(ret != largefile::TFS_SUCCESS){fprintf(stderr, "create index %d failed.\n", block_id);//delete mainblock;delete index_handle;exit(-3);}//2. 生成主块文件std::stringstream tmp_stream;tmp_stream<< "." << largefile::MAINBLOCK_DIR_PREFIX << block_id;tmp_stream >> mainblock_path;largefile::FileOperation *mainblock = new largefile::FileOperation(mainblock_path, O_RDWR | O_LARGEFILE | O_CREAT);ret = mainblock->ftruncate_file(main_blocksize);if(ret != 0){fprintf(stderr, "create main block %s failed. reason: %s\n", mainblock_path.c_str(), strerror(errno));delete mainblock;index_handle->remove(block_id);exit(-2);}//其他操作mainblock->close_file();index_handle->flush();delete mainblock;delete index_handle;return 0;
}

7 写入文件实现

写入文件的流程如下:

7.1 哈希查找实现

int IndexHandle::hash_find(const uint64_t key, int32_t& current_offset, int32_t&  previous_offset)
{int ret = TFS_SUCCESS;MetaInfo meta_info;current_offset = 0;previous_offset = 0;//1.确定key 存放的桶(slot)的位置int32_t slot = static_cast<uint32_t>(key)  % bucket_size();//2.读取桶首节点存储的第一个节点的偏移量,如果偏移量为零,直接返回 EXIT_META_NOT_FOUND_ERROR//3.根据偏移量读取存储的metainfo //4.与key进行比较,相等则设置current_offset 和previous_offset 并返回TFS_SUCCESS,否则继续执行5//5. 从metainfo 中取得下一个节点的在文件中的偏移量,如果偏移量为零,直接返回 EXIT_META_NOT_FOUND_ERROR,//    否则,跳转至3继续循环执行int32_t pos = bucket_slot()[slot];for(;pos != 0; ){ret = file_op_->pread_file(reinterpret_cast<char*>(&meta_info), sizeof(MetaInfo), 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;}

7.2 哈希插入实现

int32_t IndexHandle::hash_insert(const uint64_t key, int32_t previous_offset, MetaInfo &meta)
{int  ret = TFS_SUCCESS;MetaInfo tmp_meta_info;int32_t current_offset = 0;//1.确定key 存放的桶(slot)的位置int32_t slot = static_cast<uint32_t>(key) % bucket_size();//2.确定meta 节点存储在文件中的偏移量if(free_head_offset() != 0){ret = file_op_->pread_file(reinterpret_cast<char*>(&tmp_meta_info), sizeof(MetaInfo), free_head_offset());if( TFS_SUCCESS != ret){return ret;}current_offset = index_header()->free_head_offset_;if(debug) printf("reuse metainfo, current_offset: %d\n", current_offset);index_header()->free_head_offset_ = tmp_meta_info.get_next_meta_offset();}else {current_offset = index_header()->index_file_size_;index_header()->index_file_size_ += sizeof(MetaInfo);}//3.将meta 节点写入索引文件中meta.set_next_meta_offset(0);ret = file_op_->pwrite_file( reinterpret_cast<const char*>(&meta), sizeof(MetaInfo), current_offset);if( TFS_SUCCESS != ret){index_header()->index_file_size_ -= sizeof(MetaInfo);return ret;}//4. 将meta 节点插入到哈希链表中//当前一个节点已经存在if( 0 != previous_offset){ret = file_op_->pread_file(reinterpret_cast<char*>(&tmp_meta_info), sizeof(MetaInfo), previous_offset);if( TFS_SUCCESS != ret){index_header()->index_file_size_ -= sizeof(MetaInfo);return ret;}tmp_meta_info.set_next_meta_offset(current_offset);ret = file_op_->pwrite_file( reinterpret_cast<const char*>(&tmp_meta_info), sizeof(MetaInfo), previous_offset);if( TFS_SUCCESS != ret){index_header()->index_file_size_ -= sizeof(MetaInfo);return ret;}}else  { //不存在前一个节点的情况bucket_slot()[slot] = current_offset;}return TFS_SUCCESS;
}

7.3 更新块信息

int IndexHandle::write_segment_meta(const uint64_t key, MetaInfo &meta)
{int32_t  current_offset = 0, previous_offset = 0;//思考? key  存在吗? 存在=>处理? 不存在=>处理?//1.从文件哈希表中查找key 是否存在  hash_find(key, current_offset, previous_offset);int ret = hash_find(key, current_offset, previous_offset);if( TFS_SUCCESS == ret){return EXIT_META_UNEXPECT_FOUND_ERROR;}else if( EXIT_META_NOT_FOUND_ERROR != ret){return ret;}//2.不存在就写入meta 到文件哈希表中  hash_insert(key, previous_offset, meta);ret = hash_insert(key,  previous_offset, meta);return ret;
}int IndexHandle::update_block_info(const OperType oper_type, const uint32_t modify_size)
{if( block_info()->block_id_ == 0){return EXIT_BLOCKID_ZERO_ERROR;}if( oper_type  == C_OPER_INSERT ){++block_info()->version_;++block_info()->file_count_;++block_info()->seq_no_;block_info()->size_ += modify_size;}else if( oper_type == C_OPER_DELETE ){++block_info()->version_;--block_info()->file_count_;block_info()->size_ -= modify_size;++block_info()->del_file_count_;block_info()->del_size_ += modify_size;}if(debug) printf("update block info. blockid: %u, version: %u, file count: %u, size: %u, del file count: %u, del size: %u, seq no: %u, oper type: %d\n",block_info()->block_id_, block_info()->version_, block_info()->file_count_, block_info()->size_,block_info()->del_file_count_, block_info()->del_size_, block_info()->seq_no_, oper_type);return TFS_SUCCESS;
}

7.4 写入文件测试

#include "common.h"
#include "file_op.h"
#include "index_handle.h"
#include <sstream>using namespace qiniu;
using namespace std;const static largefile::MMapOption mmap_option = {1024000, 4096, 4096};  //内存映射的参数
const static uint32_t main_blocksize = 1024*1024*64;  //主块文件的大小
const static uint32_t bucket_size = 1000;  //哈希桶的大小
static int32_t block_id = 1;static int debug = 1;int main(int argc, char **argv)   //argv[0]="rm"  argv[1]="-f"  argv[2] ="a.out"
{std::string mainblock_path;std::string index_path;int32_t ret = largefile::TFS_SUCCESS;cout<<" Type your bockid :"<<endl;cin>> block_id;if(block_id < 1){cerr<<" Invalid blockid, exit."<<endl;exit(-1);}//1. 加载索引文件largefile::IndexHandle *index_handle = new largefile::IndexHandle(".", block_id);  //索引文件句柄if(debug)  printf("load index ...\n");ret = index_handle->load(block_id, bucket_size, mmap_option);if(ret != largefile::TFS_SUCCESS){fprintf(stderr, "load index %d failed.\n", block_id);//delete mainblock;delete index_handle;exit(-2);}//2. 写入文件到主块文件中std::stringstream tmp_stream;tmp_stream<< "." << largefile::MAINBLOCK_DIR_PREFIX << block_id;tmp_stream >> mainblock_path;largefile::FileOperation *mainblock = new largefile::FileOperation(mainblock_path, O_RDWR | O_LARGEFILE | O_CREAT);char buffer[4096];memset(buffer, '6', sizeof(buffer));int32_t data_offset = index_handle->get_block_data_offset();uint32_t file_no = index_handle->block_info()->seq_no_;if( (ret = mainblock->pwrite_file(buffer, sizeof(buffer), data_offset)) !=  largefile::TFS_SUCCESS){fprintf(stderr, "write to main block failed. ret: %d, reason: %s\n", ret, strerror(errno));mainblock->close_file();delete mainblock;delete index_handle;exit(-3);}//3. 索引文件中写入Metainfolargefile::MetaInfo meta;meta.set_file_id( file_no );meta.set_offset( data_offset );meta.set_size( sizeof(buffer) );ret = index_handle->write_segment_meta(meta.get_key(), meta);if(ret == largefile::TFS_SUCCESS){//1.更新索引头部信息index_handle->commit_block_data_offset( sizeof(buffer) );//2. 更新块信息index_handle->update_block_info(largefile::C_OPER_INSERT, sizeof(buffer) );ret = index_handle->flush();if(ret != largefile::TFS_SUCCESS){fprintf(stderr, "flush mainblock %d failed. file no: %u \n", block_id, file_no);}}else {fprintf(stderr, "write_segement_meta - mainblock %d failed. file no: %u\n", block_id, file_no);}if(ret !=  largefile::TFS_SUCCESS){fprintf(stderr,"write to mainblock %d  failed. file no: %u\n", block_id, file_no);}else {if(debug) printf("write successfully. file_no : %u , block_id: %d\n", file_no, block_id);}mainblock->close_file();delete mainblock;delete index_handle;return 0;
}

8 读文件实现

8.1 读MetaInfo

int32_t IndexHandle::read_segment_meta(const uint64_t key, MetaInfo &meta)
{int32_t  current_offset = 0, previous_offset = 0;//1.确定key 存放的桶(slot)的位置//int32_t slot = static_cast<uint32_t>(key)  % bucket_size();int32_t ret = hash_find(key,  current_offset, previous_offset);if( TFS_SUCCESS == ret) //exist{ret = file_op_->pread_file(reinterpret_cast<char *> (&meta), sizeof(MetaInfo), current_offset);return ret;}else {return ret;}
}

8.2 读流程实现

#include "common.h"
#include "file_op.h"
#include "index_handle.h"
#include <sstream>using namespace qiniu;
using namespace std;const static largefile::MMapOption mmap_option = {1024000, 4096, 4096};  //内存映射的参数
const static uint32_t main_blocksize = 1024*1024*64;  //主块文件的大小
const static uint32_t bucket_size = 1000;  //哈希桶的大小
static int32_t block_id = 1;static int debug = 1;int main(int argc, char **argv)   //argv[0]="rm"  argv[1]="-f"  argv[2] ="a.out"
{std::string mainblock_path;std::string index_path;int32_t ret = largefile::TFS_SUCCESS;cout<<" Type your bockid :"<<endl;cin>> block_id;if(block_id < 1){cerr<<" Invalid blockid, exit."<<endl;exit(-1);}//1. 加载索引文件largefile::IndexHandle *index_handle = new largefile::IndexHandle(".", block_id);  //索引文件句柄if(debug)  printf("load index ...\n");ret = index_handle->load(block_id, bucket_size, mmap_option);if(ret != largefile::TFS_SUCCESS){fprintf(stderr, "load index %d failed.\n", block_id);//delete mainblock;delete index_handle;exit(-2);}//2.  读取文件的meta info.uint64_t file_id = 0;cout<<" Type your file_id :"<<endl;cin>> file_id;if(file_id < 1){cerr<<" Invalid fileid, exit."<<endl;exit(-2);}largefile::MetaInfo meta;ret = index_handle->read_segment_meta( file_id, meta);if(ret != largefile::TFS_SUCCESS){fprintf(stderr, "read_segment_meta error. file_id: %lu, ret: %d\n", file_id, ret);exit(-3);}//3. 根据meta info 读取文件std::stringstream tmp_stream;tmp_stream<< "." << largefile::MAINBLOCK_DIR_PREFIX << block_id;tmp_stream >> mainblock_path;largefile::FileOperation *mainblock = new largefile::FileOperation(mainblock_path, O_RDWR );char *buffer = new char[meta.get_size() + 1];ret = mainblock->pread_file(buffer, meta.get_size(), meta.get_offset());if(ret != largefile::TFS_SUCCESS){fprintf(stderr, "read from main block failed. ret: %d, reason: %s\n", ret, strerror(errno));mainblock->close_file();delete mainblock;delete index_handle;exit(-3);}buffer[meta.get_size()] = '\0';printf("read size %d, content: %s\n", meta.get_size(), buffer);mainblock->close_file();delete mainblock;delete index_handle;return 0;
}

9 删除文件实现

9.1 删除MetaInfo

int32_t IndexHandle::delete_segment_meta(const uint64_t key)
{int32_t  current_offset = 0, previous_offset = 0;int32_t ret = hash_find(key,  current_offset, previous_offset);if( ret != TFS_SUCCESS ){return ret;}MetaInfo meta_info;ret = file_op_->pread_file(reinterpret_cast<char *>(&meta_info), sizeof(MetaInfo), current_offset);if ( TFS_SUCCESS != ret ){return ret;}int32_t next_pos = meta_info.get_next_meta_offset();if(previous_offset == 0){int32_t slot = static_cast<uint32_t> (key) % bucket_size();bucket_slot()[slot] = next_pos;}else {MetaInfo pre_meta_info;ret = file_op_->pread_file(reinterpret_cast<char *>(&pre_meta_info), sizeof(MetaInfo), previous_offset);if ( TFS_SUCCESS != ret ){return ret;}pre_meta_info.set_next_meta_offset(next_pos);ret = file_op_->pwrite_file(reinterpret_cast<char *>(&pre_meta_info), sizeof(MetaInfo), previous_offset);if ( TFS_SUCCESS != ret ){return ret;}}//把删除节点加入可重用节点链表(下一个小节实现)meta_info.set_next_meta_offset(free_head_offset());// index_header()->free_head_offset_;ret = file_op_->pwrite_file(reinterpret_cast<char *>(&meta_info), sizeof(MetaInfo),  current_offset);if( TFS_SUCCESS != ret ){return  ret;}index_header()->free_head_offset_ = current_offset;if(debug) printf("delete_segment_meta - reuse metainfo, current_offset: %d\n", current_offset);update_block_info(C_OPER_DELETE, meta_info.get_size());return TFS_SUCCESS;}

9.2 删除文件流程实现

#include "common.h"
#include "file_op.h"
#include "index_handle.h"
#include <sstream>using namespace qiniu;
using namespace std;const static largefile::MMapOption mmap_option = {1024000, 4096, 4096};  //内存映射的参数
const static uint32_t main_blocksize = 1024*1024*64;  //主块文件的大小
const static uint32_t bucket_size = 1000;  //哈希桶的大小
static int32_t block_id = 1;static int debug = 1;int main(int argc, char **argv)   //argv[0]="rm"  argv[1]="-f"  argv[2] ="a.out"
{std::string mainblock_path;std::string index_path;int32_t ret = largefile::TFS_SUCCESS;cout<<" Type your bockid :"<<endl;cin>> block_id;if(block_id < 1){cerr<<" Invalid blockid, exit."<<endl;exit(-1);}//1. 加载索引文件largefile::IndexHandle *index_handle = new largefile::IndexHandle(".", block_id);  //索引文件句柄if(debug)  printf("load index ...\n");ret = index_handle->load(block_id, bucket_size, mmap_option);if(ret != largefile::TFS_SUCCESS){fprintf(stderr, "load index %d failed.\n", block_id);//delete mainblock;delete index_handle;exit(-2);}//2.  删除指定文件的meta info.uint64_t file_id = 0;cout<<" Type your file_id :"<<endl;cin>> file_id;if(file_id < 1){cerr<<" Invalid fileid, exit."<<endl;exit(-3);}ret = index_handle->delete_segment_meta(file_id);if(ret != largefile::TFS_SUCCESS){fprintf(stderr, "delete index failed. file_id: %lu, ret: %d\n", file_id, ret);}ret = index_handle->flush();if(ret != largefile::TFS_SUCCESS){fprintf(stderr, "flush mainblock %d failed. file no: %lu \n", block_id, file_id);exit(-4);}printf("delete successfully!\n");delete index_handle;return 0;
}

参考资料:

  1. C/C++从入门到精通-高级程序员之路【奇牛学院】

索引处理类的设计与实现相关推荐

  1. java 重启线程_java 可重启线程及线程池类的设计(详解)

    了解JAVA多线程编程的人都知道,要产生一个线程有两种方法,一是类直接继承Thread类并实现其run()方法:二是类实现Runnable接口并实现其run()方法,然后新建一个以该类为构造方法参数的 ...

  2. 第 08 章_索引的创建与设计原则

    第 08 章_索引的创建与设计原则 1. 索引的声明与使用 1. 1 索引的分类 MySQL的索引包括普通索引.唯一性索引.全文索引.单列索引.多列索引和空间索引等. 从功能逻辑上说,索引主要有 4 ...

  3. 转:软件设计漫谈之三:30分钟掌握面向对象类的设计原则

    转自:http://blog.csdn.net/yunhua_lee/article/details/5105524 30分钟掌握面向对象类的设计原则 看过设计模式的人不少,但看过Martin的面向对 ...

  4. VS 2010 通过 Architecture创建UML类图设计

    [赛迪网报道]类是对应用领域或应用解决方案中概念的描述.类图以类为中心进行组织,类图中的其他元素或属于某个类,或与类相关联.类也是对象的集合,展示了对象的结构及与系统交互的行为,其目的是显示建模系统的 ...

  5. 一文讲透非标品的商品类目设计

    www.pmcaff.com 本文为作者 百转 于社区发布 只要做电商,商品类目设计就是绕不开的一环.好的类目设计能让供需双方更快.更好定义或找到所关心的商品,是整个电商体系的地基,是构建并链接各个模 ...

  6. Java黑皮书课后题第10章:*10.10(Queue类)10.6节给出一个Stock类。设计一个名为Queue的类用于存储整数。像栈一样,队列保存元素。在栈中,元素后进先出。队列中元素先进先出

    10.10(Queue类)10.6节给出一个Stock类,设计一个名为Queue的类用于存储整数 题目 程序 破题 代码 Test10.java Test10_Queue.java UML 题目 程序 ...

  7. Java黑皮书课后题第10章:10.4(MyPoint类)设计一个名为MyPoint的类,代表一个以x坐标和y坐标表示的点

    10.4(MyPoint类)设计一个名为MyPoint的类,代表一个以x坐标和y坐标表示的点 题目 程序 代码 Test4.java Test4_MyPoint.java 运行实例 UML 题目 程序 ...

  8. Java黑皮书课后题第10章:10.3(MyInteger类)设计一个名为MyInteger的类

    10.3(MyInteger类)设计一个名为MyInteger的类 题目 程序说明 代码 Test3.java Test3_MyInteger.java 运行实例 UML 题目 程序说明 测试程序:T ...

  9. Java黑皮书课后题第9章:**9.13(Location类)设计一个名为Location的类,定位二维数组中的最大值及其位置。

    Java黑皮书课后题第9章:**9.13(Location类)设计一个名为Location的类,定位二维数组中的最大值及其位置 题目 破题 代码 Test13 Test13_Location 运行结果 ...

最新文章

  1. Redis的rdb格式学习
  2. Redis键命令(查找键、判断键值是否存在、查看键值类型、删除键值、设置过期时间、查看键值有效时间)
  3. 如何监控impala的数据_CDH秘籍(两):cloudera Manager存储监控数据
  4. 基本数据类型之间的运算
  5. CSS实现三列图片等宽等间距布局
  6. P7293-[USACO21JAN]Sum of Distances P【统计,bfs】
  7. tensorflow1、2会话、变量、feed、fetch、最小二乘法
  8. c++ 类与默认函数、包括构造函数和析构函数的特点
  9. refprop物性库_REFPROP下载-REFPROP官方版下载[制冷剂物性查询]-天极下载
  10. matlab simulink 六自由度机械臂模糊控制pid
  11. BLE_BQB Test_Modulation Characteristics, LE Coded (S=8)_RF-PHY/TRM/BV-13-C
  12. 阿里云 mysql 导出数据库_阿里云服务器如何操作导出数据库
  13. PyCharm设置背景颜色为白色
  14. Microsemi Libero免费版License申请教程(2022年)
  15. Visual Studio 2019背景美化(背景透明化+自定义背景图片)
  16. 树莓派程序开机自启(尝试过很多终于成了)
  17. SQLZOO练习答案(一):SELECT names/zh
  18. 如何用JAVA制作一个漂亮的表格
  19. 3D中的方位和角位移(1)
  20. 信息系统项目管理:软件开发生命周期模型的选择比较

热门文章

  1. android 点击图片事件,android图文混排点击事件
  2. 06540计算机网络考试大纲,2020年自考06540计算机网络基本原理复习资料(7)
  3. 【控制】傅里叶系列(二)傅里叶变换的推导
  4. copy_to_user和copy_from_user
  5. Matlab篇(五)clc,close,close all,clear,clear all 的作用(转)
  6. BCH虫洞项目有多安全以及WHC究竟能干什么?
  7. 第一课-并行编程的几个概念
  8. 第四届中国国际大数据大会务实推进应用落地
  9. Android GIS开发系列-- 入门季(11) Callout气泡的显示
  10. 和FBI杠上了 苹果聘前亚马逊信息安全副总裁