int TfsFile::tfs_open(const char *file_name, const char *suffix, const int32_t mode)
{
mode_ = mode;
//利用文件名计算得到block_id和file_id
conv_name(file_name, suffix);
int32_t iret = tfs_open(block_id_, file_id_, mode_);
if (iret != TFS_SUCCESS)
{
return iret;
}
FSName fsname;
fsname.set_cluster_id(session_->get_cluster_id());
fsname.set_block_id(block_id_);
fsname.set_file_id(file_id_);
//这个有什么用
fsname.set_prefix(suffix);
file_id_ = fsname.get_file_id();
strcpy(file_name_, fsname.get_name());
return TFS_SUCCESS;
}
int TfsFile::tfs_open(const uint32_t block_id, const uint64_t file_id, const int32_t mode)
{
if (session_ == NULL)
{
snprintf(error_message_, ERR_MSG_SIZE, "not set session, session is null");
return TFS_ERROR;
}
//读模式的话,必须指明block_id
if ((block_id == 0) && (mode == READ_MODE || mode == UNLINK_MODE))
{
snprintf(error_message_, ERR_MSG_SIZE, "%s no block, block_id(%u) file_id(%" PRI64_PREFIX "u)",
file_name_, block_id, file_id);
return TFS_ERROR;
}
mode_ = mode;
block_id_ = block_id;
file_id_ = file_id;
ds_list_.clear();
if (mode == READ_MODE)
{
//跟NameServer通信,主要是获取ds_list信息,主要是调用
//TfsSession::get_block_info_ex()函数,加上查询cache的信息
if (session_->get_block_info(block_id_, ds_list_) != TFS_SUCCESS)
{
//没有可读的DS,返回错误
if (ds_list_.size() == 0)
{
snprintf(error_message_, ERR_MSG_SIZE, "tfs open fail, block(%u) no exist in nameserver", block_id_);
return TFS_ERROR;
}
}
}
else if (mode == UNLINK_MODE)
{
if (session_->get_unlink_block_info(block_id_, ds_list_) != TFS_SUCCESS)
{
snprintf(error_message_, ERR_MSG_SIZE, "tfs open fail, block(%u) no exist in nameserver", block_id_);
return TFS_ERROR;
}
}
//写模式
else
{
uint32_t current_block_id = block_id_;
int32_t flag = BLOCK_WRITE | BLOCK_CREATE;
if ((mode_ & NEWBLK_MODE))
{
flag |= BLOCK_NEWBLK;
}
if ((mode_ & NOLEASE_MODE))
{
flag |= BLOCK_NOLEASE;
}
//这里也调用TfsSession::get_block_info_ex,如果对应的文件不存在,则
//NameServer会找到一个可用的block_id返回
if (session_->create_block_info(current_block_id, ds_list_, flag, fail_servers_) != TFS_SUCCESS)
{
if (ds_list_.size() == 0 || current_block_id == 0)
{
snprintf(error_message_, ERR_MSG_SIZE, "create block(%u) fail in nameserver", block_id_);
return TFS_ERROR;
}
}
//这里的APPED_MODE是如何来判断的,跟block_id==0有什么关系
if (block_id_ == 0)
{
block_id_ = current_block_id;
mode_ |= APPEND_MODE;
}
}
if (block_id_ == 0 || ds_list_.size() == 0)
{
snprintf(error_message_, ERR_MSG_SIZE, "block(%u),is invalid, dataserver size(%u)", block_id_,
static_cast<uint32_t> (ds_list_.size()));
return TFS_ERROR;
}
if ((mode_ & READ_MODE))
{
if (file_id_ == 0)
{
//TBSYS_LOG(WARN, "blockId(%u) read fileid is 0.", block_id_);
}
//读模式通过这个方法来选择DS
pri_ds_index_ = static_cast<int32_t> (file_id_ % ds_list_.size());
}
else
{
pri_ds_index_ = 0;
}
//尝试连接ds_list中的DS,并且选出第一个可连接的DS作为primary DS
if (connect_ds() != TFS_SUCCESS)
{
snprintf(error_message_, ERR_MSG_SIZE, "connect to dataserver fail.");
if ((mode_ & APPEND_MODE))
{
fail_servers_.push_back(ds_list_[0]);
}
return TFS_ERROR;
}
fail_servers_.clear();
if ((mode_ & WRITE_MODE))
{
//这个函数调用client_->call(CreateFileMessage),经过上面connect_ds()的调用,
//client_是连到primary DS的客户端,所以这个消息不是发送给NS的
//通过此消息,去primary DS上获取file_number
int32_t ret = create_filename();
if (ret != TFS_SUCCESS)
{
CLIENT_POOL.release_client(client_);
TBSYS_LOG(ERROR, "create file name faile(%d)", ret);
return ret;
}
if (file_id_ == 0)
{
snprintf(error_message_, ERR_MSG_SIZE, "create file name fail,fileid == 0");
CLIENT_POOL.release_client(client_);
return TFS_ERROR;
}
}
offset_ = 0;
eof_ = TFS_FILE_EOF_FLAG_NO;
crc_ = 0;
is_open_flag_ = TFS_FILE_OPEN_FLAG_YES;
return TFS_SUCCESS;
} |