TFS的官方文档里面提到:在TFS中,将大量的小文件(实际数据文件)合并成为一个大文件,这个大文件称为块(Block), 每个Block拥有在集群内唯一的编号(Block Id), Block Id在NameServer在创建Block的时候分配。
对此有如下疑问:
DataServer在初始化的时候就已经将所有的block全部建立出来了,nameServer在什么时候来通知DataServer来分配block呢。
我们先来看看DataServer初始化的时候会做了哪些事情:
1、通过BlockFileManager的format_block_file_system函数来初始化存储空间,将存储空间划分为多个block,同时建立相应的索引文件
2、DataServer在上报心跳的时候,上报自身的存储信息已经已有的block信息。
4、当Client调用Open时,NameServer会给Client选择一个blockId,供Client写入
5、当DataServer收到NewBlockMessage消息,则新建BlockId,同时缓存,并持久化到硬盘(源码步骤很详细,不细说明)
对此有如下疑问:
DataServer在初始化的时候就已经将所有的block全部建立出来了,nameServer在什么时候来通知DataServer来分配block呢。
我们先来看看DataServer初始化的时候会做了哪些事情:
1、通过BlockFileManager的format_block_file_system函数来初始化存储空间,将存储空间划分为多个block,同时建立相应的索引文件
int BlockFileManager::format_block_file_system(const SysParam::FileSystemParam& fs_param)
{
............................................
// 3. create super block file
//该函数会在存储空间新建一个super索引文件,以后服务启动的时候会通过该文件加载DataServer里的所有Block信息
ret = create_fs_super_blk();
if (TFS_SUCCESS != ret)
return ret;
............................................
return TFS_SUCCESS;
}
2、DataServer在上报心跳的时候,上报自身的存储信息已经已有的block信息。
//节点的状态信息,NameServer根据状态信息,选举合适的DataServer新建Block(待确定,还没有找到相关的实现代码)
struct DataServerStatInfo
{
uint64_t id_;
int64_t use_capacity_;
int64_t total_capacity_;
int32_t current_load_;
int32_t block_count_;
int32_t last_update_time_;
int32_t startup_time_;
Throughput total_tp_;
int32_t current_time_;
DataServerLiveStatus status_;
};
//用来标识该DataServer包含有哪些block
typedef std::vector<BlockInfo> BLOCK_INFO_LIST
4、当Client调用Open时,NameServer会给Client选择一个blockId,供Client写入
int MetaManager::write_block_info(uint32_t& block_id, int32_t mode, uint32_t& lease_id, int32_t& version,
VUINT64& ds_list)
{
..............................................................
//nameserver assign a new write block
if ((block_id == 0)
&& (mode & BLOCK_CREATE))
{
VINT64 fail_ds;
//选择一个合适的block id
block_id = elect_write_block(fail_ds);
if (block_id == 0)
{
TBSYS_LOG(ERROR, "elect write block faild...");
return EXIT_NO_BLOCK;
}
}
BlockChunkPtr ptr = meta_mgr_.get_block_chunk(block_id);
ptr->mutex_.rdlock();
BlockCollect* block_collect = ptr->find(block_id);
// create block in slave nameserver.
if ((mode & BLOCK_NEWBLK))
{
if (block_collect == NULL)
{
ptr->mutex_.unlock();
//如果block id 不存在,则通知DataServer新建
block_collect = add_new_block(block_id);
if (block_collect == NULL)
{
TBSYS_LOG(ERROR, "add new block(%u) failed, dataserver not found", block_id);
return EXIT_NO_DATASERVER;
}
ptr->mutex_.rdlock();
TBSYS_LOG(DEBUG, "block(%u), not found meta data, add new(%p)", block_id, block_collect);
}
............................................................
}
......................................................................
return TFS_SUCCESS;
}
//通知DataServer新建一个block
BlockCollect* MetaManager::add_new_block(uint32_t& block_id, const uint64_t ds_id)
{
.....................................................................
for (uint32_t i = 0; i < elect_ds_list.size(); ++i)
{
TBSYS_LOG(DEBUG, "dataserver(%s)", tbsys::CNetUtil::addrToString(elect_ds_list[i]).c_str());
NewBlockMessage nbmsg;
nbmsg.add_new_id(new_block_id);
//给DataServer发送NewBlockMessage消息,通知DataServer新建Block(阻塞模式)
if (send_message_to_server(elect_ds_list[i], &nbmsg, NULL) == TFS_SUCCESS)
{
add_success_ds_list.push_back(elect_ds_list[i]);
TBSYS_LOG(INFO, "add block:%u on server:%s succeed", new_block_id, tbsys::CNetUtil::addrToString(
elect_ds_list[i]).c_str());
}
else
{
TBSYS_LOG(INFO, "add block:%u on server:%s failed", new_block_id, tbsys::CNetUtil::addrToString(
elect_ds_list[i]).c_str());
}
}
......................................................
return block_collect;
}
5、当DataServer收到NewBlockMessage消息,则新建BlockId,同时缓存,并持久化到硬盘(源码步骤很详细,不细说明)
int BlockFileManager::new_block(const uint32_t logic_block_id, uint32_t& physical_block_id,
const BlockType block_type)
{
}