コード例 #1
0
ファイル: SFDSFile.cpp プロジェクト: xmulyj/SFDS
bool File::_send_file_to_chunk(string &local_file, string &fid, string &chunk_addr, int chunk_port, FileInfo &fileinfo)
{
	int32_t chunk_fd = Socket::Connect(chunk_port, chunk_addr.c_str());
	if(chunk_fd == -1)
	{
		LOG_ERROR(logger, "connect chunk failed.");
		return false;
	}

	//1. 获取文件大小
	FILE *fd = fopen(local_file.c_str(), "rb");
	if(fd == NULL)
	{
		LOG_ERROR(logger, "open file error.");
		Socket::Close(chunk_fd);
		return false;
	}
	struct stat file_stat;
	if(fstat(fileno(fd), &file_stat) == -1)
	{
		LOG_ERROR(logger, "stat file error. errno="<<errno<<","<<strerror(errno));
		fclose(fd);
		Socket::Close(chunk_fd);
		return false;
	}

	//发送文件
	string filename = local_file.substr(local_file.find_last_of('/')+1);
	uint32_t filesize = file_stat.st_size;
	bool result = true;

	ByteBuffer byte_buffer(10240);
	KVData kvdata(true);

	//1 发送开始协议
	FileData file_data;
	file_data.fid = fid;
	file_data.name = filename;
	file_data.filesize = filesize;

	file_data.flag = FileData::FLAG_START;
	kvdata.SetValue(KEY_PROTOCOL_TYPE, PROTOCOL_FILE);
	kvdata.SetValue(KEY_FILEDATA_FID, file_data.fid);
	kvdata.SetValue(KEY_FILEDATA_FILE_NAME, file_data.name);
	kvdata.SetValue(KEY_FILEDATA_FILE_SIZE, file_data.filesize);
	kvdata.SetValue(KEY_FILEDATA_FLAG, file_data.flag);

	if(SendData(chunk_fd, kvdata) == false)
	{
		LOG_ERROR(logger, "send file data start to chunk failed.");
		fclose(fd);
		Socket::Close(chunk_fd);
		return false;
	}
	if(RecvData(chunk_fd, byte_buffer, kvdata) == false)
	{
		LOG_ERROR(logger, "recv data to chunk failed.");
		fclose(fd);
		Socket::Close(chunk_fd);
		return false;
	}

	FileSaveResult save_result;
	int32_t protocol_type;
	if(kvdata.GetValue(KEY_PROTOCOL_TYPE, protocol_type)==false
		|| kvdata.GetValue(KEY_FILEDATA_RESULT, save_result.status)==false
		|| kvdata.GetValue(KEY_FILEDATA_FID, save_result.fid)==false)
	{
		LOG_ERROR(logger, "get protocol data failed.");
		fclose(fd);
		Socket::Close(chunk_fd);
		return false;
	}

	if(protocol_type!=PROTOCOL_FILE_SAVE_RESULT)
	{
		LOG_ERROR(logger, "protocol type invalid.");
		fclose(fd);
		Socket::Close(chunk_fd);
		return false;
	}

	if(save_result.status == FileSaveResult::CREATE_FAILED) //存储失败
	{
		LOG_ERROR(logger, "chunk create file failed. fid="<<fid);
		fclose(fd);
		Socket::Close(chunk_fd);
		return false;
	}

	int seg_size = 0;
	//2 发送分片
	file_data.index = 0;
	file_data.offset = 0;

	int READ_SIZE = 4096;
	char buffer[5000];
	while(file_data.offset < filesize)
	{
		seg_size = filesize-file_data.offset;
		if(seg_size > READ_SIZE)
			seg_size = READ_SIZE;

		file_data.size = seg_size;
		file_data.flag = FileData::FLAG_SEG;

		int32_t read_size = fread(buffer, 1, file_data.size, fd);
		if(read_size != file_data.size)
		{
			LOG_ERROR(logger, "read file error. read_size="<<read_size<<",expect_size="<<file_data.size<<",cur_offset="<<file_data.offset<<",filesize="<<filesize<<",error="<<strerror(errno));
			fclose(fd);
			Socket::Close(chunk_fd);
			return false;
		}

		kvdata.Clear();
		kvdata.SetValue(KEY_PROTOCOL_TYPE, PROTOCOL_FILE);
		kvdata.SetValue(KEY_FILEDATA_FID, file_data.fid);
		kvdata.SetValue(KEY_FILEDATA_FILE_NAME, file_data.name);
		kvdata.SetValue(KEY_FILEDATA_FILE_SIZE, file_data.filesize);
		kvdata.SetValue(KEY_FILEDATA_FLAG, file_data.flag);
		kvdata.SetValue(KEY_FILEDATA_INDEX, file_data.index);
		kvdata.SetValue(KEY_FILEDATA_SEG_SIZE, file_data.size);
		kvdata.SetValue(KEY_FILEDATA_OFFSET, file_data.offset);
		kvdata.SetValue(KEY_FILEDATA_DATA, buffer, file_data.size);

		if(SendData(chunk_fd, kvdata) == false)
		{
			LOG_ERROR(logger, "send file data failed.");
			fclose(fd);
			Socket::Close(chunk_fd);
			return false;
		}

		if(RecvData(chunk_fd, byte_buffer, kvdata) == false)
		{
			LOG_ERROR(logger, "recv file data rsp failed.");
			fclose(fd);
			Socket::Close(chunk_fd);
			return false;
		}

		if(!kvdata.GetValue(KEY_PROTOCOL_TYPE, protocol_type) || protocol_type!=PROTOCOL_FILE_SAVE_RESULT)
		{
			LOG_ERROR(logger, "recv file data rsp protocol_type invalid.");
			fclose(fd);
			Socket::Close(chunk_fd);
			return false;
		}

		FileSaveResult save_result;
		if(!kvdata.GetValue(KEY_FILEDATA_RESULT, save_result.status)
			|| !kvdata.GetValue(KEY_FILEDATA_FID, save_result.fid)
			|| !kvdata.GetValue(KEY_FILEDATA_INDEX, save_result.index))
		{
			LOG_ERROR(logger, "file data rsp:get param failed.");
			fclose(fd);
			Socket::Close(chunk_fd);
			return false;
		}

		if(save_result.status==FileSaveResult::DATA_SAVE_FAILED || save_result.fid!=file_data.fid)
		{
			LOG_ERROR(logger, "save file data failed or fid invalid.cur fid="<<file_data.fid<<",recv fid="<<save_result.fid);
			fclose(fd);
			Socket::Close(chunk_fd);
			return false;
		}

		LOG_DEBUG(logger, "save file_data_seg succ. fid="<<file_data.fid<<",index="<<file_data.index);
		++file_data.index;
		file_data.offset += seg_size;
	}
	fclose(fd);

	file_data.flag = FileData::FLAG_END;
	kvdata.Clear();
	kvdata.SetValue(KEY_PROTOCOL_TYPE, PROTOCOL_FILE);
	kvdata.SetValue(KEY_FILEDATA_FLAG, file_data.flag);
	kvdata.SetValue(KEY_FILEDATA_FID, file_data.fid);
	kvdata.SetValue(KEY_FILEDATA_FILE_NAME, file_data.name);
	kvdata.SetValue(KEY_FILEDATA_FILE_SIZE, file_data.filesize);
	if(SendData(chunk_fd, kvdata) == false)
	{
		LOG_ERROR(logger, "send file data end to chunk failed.");
		Socket::Close(chunk_fd);
		return false;
	}

	//等待chunk回复file_info信息
	if(RecvData(chunk_fd, byte_buffer, kvdata) == false)
	{
		LOG_ERROR(logger, "recv file info from chunk failed.");
		fclose(fd);
		Socket::Close(chunk_fd);
		return false;
	}

	if(!kvdata.GetValue(KEY_PROTOCOL_TYPE, protocol_type) || protocol_type!=PROTOCOL_FILE_INFO)
	{
		LOG_ERROR(logger, "recv file info from chunk failed. invalid protocol_type");
		Socket::Close(chunk_fd);
		return false;
	}
	if(!kvdata.GetValue(KEY_FILEINFO_RSP_RESULT, fileinfo.result))
	{
		LOG_ERROR(logger, "recv file info from chunk failed. get result failed");
		Socket::Close(chunk_fd);
		return false;
	}
	if(!kvdata.GetValue(KEY_FILEINFO_RSP_FID, fileinfo.fid))
	{
		LOG_ERROR(logger, "recv file info from chunk failed. get fid failed");
		Socket::Close(chunk_fd);
		return false;
	}

	if(fileinfo.result == FileInfo::RESULT_SUCC || fileinfo.result==FileInfo::RESULT_CHUNK)
	{
		kvdata.GetValue(KEY_FILEINFO_RSP_FILE_NAME, fileinfo.name);
		kvdata.GetValue(KEY_FILEINFO_RSP_FILE_SIZE, fileinfo.size);

		uint32_t chunk_count;
		if(!kvdata.GetValue(KEY_FILEINFO_RSP_CHUNK_NUM, chunk_count) || chunk_count<=0)
		{
			Socket::Close(chunk_fd);
			return false;
		}
		for(int i=0; i<chunk_count; ++i)
		{
			KVData kv_chunkpath(true);
			if(!kvdata.GetValue(KEY_FILEINFO_RSP_CHUNK_PATH0, kv_chunkpath))
			{
				Socket::Close(chunk_fd);
				return false;
			}

			ChunkPath chunkpath;
			kv_chunkpath.GetValue(KEY_FILEINFO_RSP_CHUNK_ID, chunkpath.id);
			kv_chunkpath.GetValue(KEY_FILEINFO_RSP_CHUNK_IP, chunkpath.ip);
			kv_chunkpath.GetValue(KEY_FILEINFO_RSP_CHUNK_PORT, chunkpath.port);
			kv_chunkpath.GetValue(KEY_FILEINFO_RSP_CHUNK_INDEX, chunkpath.index);
			kv_chunkpath.GetValue(KEY_FILEINFO_RSP_CHUNK_OFFSET, chunkpath.offset);

			fileinfo.AddChunkPath(chunkpath);
		}
	}

	Socket::Close(chunk_fd);
	return true;
}
コード例 #2
0
ファイル: SFDSFile.cpp プロジェクト: xmulyj/SFDS
bool File::_get_file_info(string &fid, bool query_chunk, FileInfo &fileinfo)
{
	//连接master
	int master_fd = Socket::Connect(m_master_port, m_master_addr.c_str());
	if(master_fd == -1)
		return false;

	//协议数据
	FileInfoReq fileinfo_req;
	fileinfo_req.fid = fid;
	fileinfo_req.query_chunkpath = query_chunk?1:0;

	KVData kvdata(true);
	kvdata.SetValue(KEY_PROTOCOL_TYPE, PROTOCOL_FILE_INFO_REQ);
	kvdata.SetValue(KEY_FILEINFO_REQ_FID, fileinfo_req.fid);
	kvdata.SetValue(KEY_FILEINFO_REQ_CHUNKPATH, fileinfo_req.query_chunkpath);

	if(SendData(master_fd, kvdata) == false)
	{
		LOG_ERROR(logger, "send data to master failed.");
		Socket::Close(master_fd);
		return false;
	}

	ByteBuffer byte_buffer(10240);
	if(RecvData(master_fd, byte_buffer, kvdata) == false)
	{
		LOG_ERROR(logger, "recv data from master failed.");
		return false;
	}

	uint32_t protocol_type;
	if(!kvdata.GetValue(KEY_PROTOCOL_TYPE, protocol_type) || protocol_type!=PROTOCOL_FILE_INFO)
	{
		Socket::Close(master_fd);
		return false;
	}
	if(!kvdata.GetValue(KEY_FILEINFO_RSP_RESULT, fileinfo.result))
	{
		Socket::Close(master_fd);
		return false;
	}
	if(!kvdata.GetValue(KEY_FILEINFO_RSP_FID, fileinfo.fid))
	{
		Socket::Close(master_fd);
		return false;
	}

	if(fileinfo.result == FileInfo::RESULT_SUCC || fileinfo.result==FileInfo::RESULT_CHUNK)
	{
		kvdata.GetValue(KEY_FILEINFO_RSP_FILE_NAME, fileinfo.name);
		kvdata.GetValue(KEY_FILEINFO_RSP_FILE_SIZE, fileinfo.size);

		uint32_t chunk_count;
		if(!kvdata.GetValue(KEY_FILEINFO_RSP_CHUNK_NUM, chunk_count) || chunk_count<=0)
		{
			Socket::Close(master_fd);
			return false;
		}
		for(int i=0; i<chunk_count; ++i)
		{
			KVData kv_chunkpath(true);
			if(!kvdata.GetValue(KEY_FILEINFO_RSP_CHUNK_PATH0, kv_chunkpath))
			{
				Socket::Close(master_fd);
				return false;
			}

			ChunkPath chunkpath;
			kv_chunkpath.GetValue(KEY_FILEINFO_RSP_CHUNK_ID, chunkpath.id);
			kv_chunkpath.GetValue(KEY_FILEINFO_RSP_CHUNK_IP, chunkpath.ip);
			kv_chunkpath.GetValue(KEY_FILEINFO_RSP_CHUNK_PORT, chunkpath.port);
			kv_chunkpath.GetValue(KEY_FILEINFO_RSP_CHUNK_INDEX, chunkpath.index);
			kv_chunkpath.GetValue(KEY_FILEINFO_RSP_CHUNK_OFFSET, chunkpath.offset);

			fileinfo.AddChunkPath(chunkpath);
		}
	}

	Socket::Close(master_fd);
	return true;
}