/*
FastDFS 作者提供的客户端API都是阻塞式,现在高并发高性能的程序一般都是非阻塞的处理模式,
这里根据FastDFS协议封装读、写、删除、查询几个API。
*/
//需要包含FastDFS以下几个头文件
#include "common_define.h"
#include "tracker_proto.h"
#include "fdfs_global.h"
#include "sockopt.h"
#include "fdfs_client.h"
//这是客户端API的一个宏,原样搬过来,用来分解组名和文件名
#define DFS_SPLIT_GROUP_NAME_AND_FILENAME(file_id) \
char new_file_id[FDFS_GROUP_NAME_MAX_LEN + 128]; \
char *group_name; \
char *filename; \
char *pSeperator; \
\
snprintf(new_file_id, sizeof(new_file_id), "%s", file_id); \
pSeperator = strchr(new_file_id, FDFS_FILE_ID_SEPERATOR); \
if (pSeperator == NULL) \
{ \
return EINVAL; \
} \
\
*pSeperator = '\0'; \
group_name = new_file_id; \
filename = pSeperator + 1; \
/*
描述:发送上传文件的协议, 在上传文件内容时,先要调用些函数,把协议数据发送给storage server
参数:
file_size: 上传文件的大小
ext_name: 文件的扩展名, 可以为空
file_type: 文件类型, 0 为普通文件, 1为可追加或修改的文件
*/
int upload_file_proto(const long long file_size,
const std::string ext_name,
const int file_type)
{
char out_buff[512];
char* p = out_buff;
int store_path_index = -1;
TrackerHeader* pHeader = (TrackerHeader *)out_buff;
memset(out_buff, 0x00, sizeof(out_buff));
p = out_buff + sizeof(TrackerHeader);
*p++ = (char)store_path_index;
long2buff(file_size, p);
p += FDFS_PROTO_PKG_LEN_SIZE;
memset(p, 0x00, FDFS_FILE_EXT_NAME_MAX_LEN);
if(!ext_name.empty())
{
int file_ext_len = ext_name.size();
if (file_ext_len > FDFS_FILE_EXT_NAME_MAX_LEN)
{
file_ext_len = FDFS_FILE_EXT_NAME_MAX_LEN;
}
memcpy(p, ext_name.c_str(), file_ext_len);
}
p += FDFS_FILE_EXT_NAME_MAX_LEN;
long2buff((p - out_buff) + file_size - sizeof(TrackerHeader), pHeader->pkg_len);
pHeader->status = 0;
pHeader->cmd = STORAGE_PROTO_CMD_UPLOAD_FILE;
if(1 == file_type)
{
pHeader->cmd = STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE;
}
//发送消息到storage server
int iRet = send_header_to_fdfs(out_buff, p - out_buff);
if(0 > iRet)
{
return iRet;
}
return 0;
}
/*
描述:从FastDFS下载文件的协议, 在下载文件内容时,先要调用些函数,把协议数据发送给storage server
参数:
file_id: 文件ID, 些ID为文件上传后FastDFS返回的文件ID
read_len: 读的长度, 为0则读整个文件
offset: 文件的偏移,如果重头开始读,则为0
*/
int read_file_proto(const std::string & file_id, const long long read_len, const long long file_offset)
{
DFS_SPLIT_GROUP_NAME_AND_FILENAME(file_id.c_str())
TrackerHeader *pHeader = NULL;
char out_buff[sizeof(TrackerHeader) + FDFS_GROUP_NAME_MAX_LEN + 128];
char *p = NULL;
int out_bytes;
int filename_len;
memset(out_buff, 0, sizeof(out_buff));
pHeader = (TrackerHeader *)out_buff;
p = out_buff + sizeof(TrackerHeader);
long2buff(file_offset, p);
p += 8;
long2buff(read_len, p);
p += 8;
snprintf(p, sizeof(out_buff) - (p - out_buff), "%s", group_name);
p += FDFS_GROUP_NAME_MAX_LEN;
filename_len = snprintf(p, sizeof(out_buff) - (p - out_buff),
"%s", filename);
p += filename_len;
out_bytes = p - out_buff;
long2buff(out_bytes - sizeof(TrackerHeader), pHeader->pkg_len);
pHeader->cmd = STORAGE_PROTO_CMD_DOWNLOAD_FILE;
//
发送消息到storage server
int iRet = send_header_to_fdfs(out_buff, p - out_buff);
if(0 > iRet)
{
return iRet;
}
return 0;
}
/*
描述:从FastDFS删除文件的协议, 删除一个文件时要调用此函数,把协议数据发送给storage server
参数:
file_id: 文件ID, 些ID为文件上传后FastDFS返回的文件ID
*/
int delete_file_proto(const std::string & file_id)
{
DFS_SPLIT_GROUP_NAME_AND_FILENAME(file_id.c_str())
char out_buff[sizeof(TrackerHeader)+ FDFS_GROUP_NAME_MAX_LEN + 128];
memset(out_buff, 0, sizeof(out_buff));
snprintf(out_buff + sizeof(TrackerHeader),
sizeof(out_buff) - sizeof(TrackerHeader),
"%s",
group_name);
int filename_len = snprintf(out_buff + sizeof(TrackerHeader) + FDFS_GROUP_NAME_MAX_LEN,
sizeof(out_buff) - sizeof(TrackerHeader) - FDFS_GROUP_NAME_MAX_LEN,
"%s",
filename);
TrackerHeader* pHeader = (TrackerHeader *)out_buff;
long2buff(FDFS_GROUP_NAME_MAX_LEN + filename_len, pHeader->pkg_len);
pHeader->cmd = STORAGE_PROTO_CMD_DELETE_FILE;
//发送消息到storage server
int iRet = send_header_to_fdfs(out_buff, p - out_buff);
if(0 > iRet)
{
return iRet;
}
return 0;
}
/*
描述:从FastDFS查询文件信息的协议
参数:
file_id: 文件ID, 些ID为文件上传后FastDFS返回的文件ID
*/
int query_file_infor_proto(const std::string & file_id)
{
DFS_SPLIT_GROUP_NAME_AND_FILENAME(file_id.c_str())
TrackerHeader *pHeader;
char out_buff[sizeof(TrackerHeader) + FDFS_GROUP_NAME_MAX_LEN + 128];
int filename_len;
memset(out_buff, 0x00, sizeof(out_buff));
pHeader = (TrackerHeader *)out_buff;
snprintf(out_buff + sizeof(TrackerHeader), sizeof(out_buff) - sizeof(TrackerHeader),
"%s", group_name);
filename_len = snprintf(out_buff + sizeof(TrackerHeader) + FDFS_GROUP_NAME_MAX_LEN,
sizeof(out_buff) - sizeof(TrackerHeader) - FDFS_GROUP_NAME_MAX_LEN,
"%s",
filename);
long2buff(FDFS_GROUP_NAME_MAX_LEN + filename_len, pHeader->pkg_len);
pHeader->cmd = STORAGE_PROTO_CMD_QUERY_FILE_INFO;
pHeader->status = 0;
//发送消息到storage server
int iRet = send_header_to_fdfs(out_buff, p - out_buff);
if(0 > iRet)
{
return iRet;
}
return 0;
}
/*
描述:修改一个存储在FastDFS的文件内容的协议,
参数:
file_buf: 要修改的文件内容缓冲区
file_len: 要修改的文件内容的长度
file_offset: 要修改文件的偏移
file_id: 要修改文件的文件ID, 些ID为文件上传后FastDFS返回的文件ID
*/
int modify_file_proto(const char* file_buf,
const long long file_len,
const long long file_offset,
const std::string & file_id)
{
DFS_SPLIT_GROUP_NAME_AND_FILENAME(file_id.c_str());
TrackerHeader *pHeader;
char out_buff[512];
char *p;
int appender_filename_len = strlen(filename);
memset(out_buff, 0x00, sizeof(out_buff));
pHeader = (TrackerHeader *)out_buff;
p = out_buff + sizeof(TrackerHeader);
long2buff(appender_filename_len, p);
p += FDFS_PROTO_PKG_LEN_SIZE;
long2buff(file_offset, p);
p += FDFS_PROTO_PKG_LEN_SIZE;
long2buff(file_len, p);
p += FDFS_PROTO_PKG_LEN_SIZE;
memcpy(p, filename, appender_filename_len);
p += appender_filename_len;
long2buff((p - out_buff) + file_len - sizeof(TrackerHeader), pHeader->pkg_len);
pHeader->cmd = STORAGE_PROTO_CMD_MODIFY_FILE;
pHeader->status = 0;
//发送消息到storage server
int iRet = send_header_to_fdfs(out_buff, p - out_buff);
if(0 > iRet)
{
return iRet;
}
//发送消息到storage server
iRet = send_header_to_fdfs(file_buf, file_len);
if(0 > iRet)
{
return iRet;
}
return 0;
}