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; }
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; }