FastDFS分布式文件系统点滴记录5 -- upload上传机制剖析1
来源:互联网 发布:java和php 知乎 编辑:程序博客网 时间:2024/06/07 01:55
FastDFS 文件上传机制,涉及到cient API、tracker、storage,所以这篇文章的思路是从client 执行upload 的流程说起,逐步深入到 tracker 、storage 的内部。
fdfs_upload_file.c 是上传的一个客户端,通过调用api实现上传文件至FastDFS。
首先看一下代码内容,fdfs_upload_file.c :
- int main(int argc, char*argv[])
- {
- char *conf_filename;
- char *local_filename;
- char group_name[FDFS_GROUP_NAME_MAX_LEN+ 1];
- TrackerServerInfo *pTrackerServer;
- int result;
- int store_path_index;
- TrackerServerInfo storageServer;
- char file_id[128];
-
- if (argc< 3)
- {
- printf("Usage: %s <config_filename> <local_filename>\n", argv[0]);
- return 1;
- }
- log_init();
- g_log_context.log_level = LOG_ERR;
- conf_filename = argv[1];
- if ((result=fdfs_client_init(conf_filename))!= 0)
- {
- return result;
- }
- pTrackerServer = tracker_get_connection();
- if (pTrackerServer== NULL)
- {
- fdfs_client_destroy();
- return errno != 0? errno : ECONNREFUSED;
- }
- if ((result=tracker_query_storage_store(pTrackerServer,\
- &storageServer,&store_path_index))!= 0)
- {
- fdfs_client_destroy();
- fprintf(stderr,"tracker_query_storage fail, " \
- "error no: %d, error info: %s\n",\
- result, STRERROR(result));
- return result;
- }
- strcpy(group_name,"");
- local_filename = argv[2];
- result = storage_upload_by_filename1(pTrackerServer,\
- &storageServer, store_path_index,\
- local_filename, NULL, \
- NULL, 0, group_name, file_id);
- if (result!= 0)
- {
- fprintf(stderr,"upload file fail, " \
- "error no: %d, error info: %s\n",\
- result, STRERROR(result));
- if (storageServer.sock>= 0)
- {
- fdfs_quit(&storageServer);
- }
- tracker_disconnect_server(&storageServer);
- fdfs_quit(pTrackerServer);
- tracker_close_all_connections();
- fdfs_client_destroy();
- return result;
- }
- printf("%s\n", file_id);
- fdfs_quit(pTrackerServer);
- tracker_close_all_connections();
- fdfs_client_destroy();
- return 0;
- }
- conf_filename = argv[1];
- if ((result=fdfs_client_init(conf_filename))!= 0)
- {
- return result;
- }
1. client 调用 fdfs_client_init 读取配置文件;
2. 深入到 fdfs_client_init 的内部,会调用 fdfs_load_tracker_group_ex;
3. 而fdfs_load_tracker_group_ex,会从配置文件中解析出tracker_server字段的内容,获取tracker 服务器地址信息。
fdfs_upload_file.c 46行:
通过跟踪,我们可以进入到tracker_get_connection()内部,里面调用了 tracker_client.c 65行:
- pTrackerServer = tracker_get_connection();
- if (pTrackerServer== NULL)
- {
- fdfs_client_destroy();
- return errno != 0? errno : ECONNREFUSED;
- }
- TrackerServerInfo *tracker_get_connection_ex(TrackerServerGroup*pTrackerGroup)
- {
- TrackerServerInfo *pCurrentServer;
- TrackerServerInfo *pResult;
- TrackerServerInfo *pServer;
- TrackerServerInfo *pEnd;
- int server_index;
- server_index = pTrackerGroup->server_index;
- if (server_index>= pTrackerGroup->server_count)
- {
- server_index = 0;
- }
- pResult = NULL;
- do
- {
- pCurrentServer = pTrackerGroup->servers+ server_index;
- if (pCurrentServer->sock>= 0 ||
- tracker_connect_server(pCurrentServer)== 0)
- {
- pResult = pCurrentServer;
- break;
- }
- pEnd = pTrackerGroup->servers+ pTrackerGroup->server_count;
- for (pServer=pCurrentServer+1; pServer<pEnd; pServer++)
- {
- if (pServer->sock>= 0 || tracker_connect_server(pServer)== 0)
- {
- pResult = pServer;
- pTrackerGroup->server_index= pServer -\
- pTrackerGroup->servers;
- break;
- }
- }
- if (pResult!= NULL)
- {
- break;
- }
- for (pServer=pTrackerGroup->servers; pServer<pCurrentServer; pServer++)
- {
- if (pServer->sock>= 0 || tracker_connect_server(pServer)== 0)
- {
- pResult = pServer;
- pTrackerGroup->server_index= pServer -\
- pTrackerGroup->servers;
- break;
- }
- }
- } while(0);
- pTrackerGroup->server_index++;
- if (pTrackerGroup->server_index>= pTrackerGroup->server_count)
- {
- pTrackerGroup->server_index= 0;
- }
- return pResult;
- }
fdfs_upload_file.c 56行:
- if ((result=tracker_query_storage_store(pTrackerServer,\
- &storageServer,&store_path_index))!= 0)
- {
- fdfs_client_destroy();
- fprintf(stderr,"tracker_query_storage fail, " \
- "error no: %d, error info: %s\n",\
- result, STRERROR(result));
- return result;
- }
1. tracker_query_storage_store 是 tracker_query_storage_store_without_group的宏定义;
我们到 tracker_query_storage_store_without_group,tracker_client.c 770行:
- int tracker_query_storage_store_without_group(TrackerServerInfo*pTrackerServer,
- TrackerServerInfo *pStorageServer,int *store_path_index)
- {
- TrackerHeader header;
- char in_buff[sizeof(TrackerHeader)+ \
- TRACKER_QUERY_STORAGE_STORE_BODY_LEN];
- char *pInBuff;
- int64_t in_bytes;
- int result;
- if (pTrackerServer->sock< 0)
- {
- if ((result=tracker_connect_server(pTrackerServer))!= 0)
- {
- return result;
- }
- }
- memset(pStorageServer, 0, sizeof(TrackerServerInfo));
- pStorageServer->sock= -1;
- memset(&header, 0, sizeof(header));
- header.cmd = TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE;
- if ((result=tcpsenddata_nb(pTrackerServer->sock,&header, \
- sizeof(header), g_fdfs_network_timeout))!= 0)
- {
- logError("file: "__FILE__", line: %d, "\
- "send data to tracker server %s:%d fail, "\
- "errno: %d, error info: %s", __LINE__,\
- pTrackerServer->ip_addr,\
- pTrackerServer->port,\
- result, STRERROR(result));
- }
- else
- {
- pInBuff = in_buff;
- result = fdfs_recv_response(pTrackerServer,\
- &pInBuff, sizeof(in_buff),&in_bytes);
- }
- if (result!= 0)
- {
- close(pTrackerServer->sock);
- pTrackerServer->sock= -1;
- return result;
- }
- if (in_bytes!= TRACKER_QUERY_STORAGE_STORE_BODY_LEN)
- {
- logError("file: "__FILE__", line: %d, "\
- "tracker server %s:%d response data "\
- "length: "INT64_PRINTF_FORMAT" is invalid, "\
- "expect length: %d", __LINE__,\
- pTrackerServer->ip_addr, pTrackerServer->port,\
- in_bytes, TRACKER_QUERY_STORAGE_STORE_BODY_LEN);
- return EINVAL;
- }
- memcpy(pStorageServer->group_name, in_buff,\
- FDFS_GROUP_NAME_MAX_LEN);
- memcpy(pStorageServer->ip_addr, in_buff+ \
- FDFS_GROUP_NAME_MAX_LEN, IP_ADDRESS_SIZE-1);
- pStorageServer->port= (int)buff2long(in_buff+ \
- FDFS_GROUP_NAME_MAX_LEN + IP_ADDRESS_SIZE- 1);
- *store_path_index = *(in_buff+ FDFS_GROUP_NAME_MAX_LEN + \
- IP_ADDRESS_SIZE - 1 + FDFS_PROTO_PKG_LEN_SIZE);
- return 0;
- }
1. client 连接成功 tracker 后,会向tracker 发起 TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE 命令;
2. tracker server 处理完成后,返回client 应答信息;
3. client 解析出 group name、storage ip_addr、storage port、store_path_index等信息。
我们接着看client 的动作, fdfs_upload_file.c 64行:
- strcpy(group_name,"");
- local_filename = argv[2];
- result = storage_upload_by_filename1(pTrackerServer,\
- &storageServer, store_path_index,\
- local_filename, NULL, \
- NULL, 0, group_name, file_id);
进入storage_upload_by_filename1,它是storage_upload_by_filename1_ex 的宏定义,注意命令参数是STORAGE_PROTO_CMD_UPLOAD_FILE。这个宏定义在 storage_client1.h 34行:
- #define storage_upload_by_filename1(pTrackerServer, pStorageServer,\
- store_path_index, local_filename, file_ext_name,\
- meta_list, meta_count, group_name, file_id)\
- storage_upload_by_filename1_ex(pTrackerServer, pStorageServer,\
- store_path_index, STORAGE_PROTO_CMD_UPLOAD_FILE,\
- local_filename, file_ext_name, meta_list, meta_count,\
- group_name, file_id)
真正执行上传的函数是 storage_client.c 829行:
- int storage_do_upload_file(TrackerServerInfo*pTrackerServer,\
- TrackerServerInfo *pStorageServer,const int store_path_index,\
- const char cmd,const int upload_type,const char *file_buff,\
- void *arg,const int64_t file_size,const char *master_filename,\
- const char *prefix_name, const char *file_ext_name,\
- const FDFSMetaData *meta_list, const int meta_count,\
- char *group_name, char*remote_filename)
注意 storage_client.c 971行:
- if (upload_type== FDFS_UPLOAD_BY_FILE)
- {
- if ((result=tcpsendfile(pStorageServer->sock, file_buff, \
- file_size, g_fdfs_network_timeout,\
- &total_send_bytes))!= 0)
- {
- break;
- }
- }
fdfs_upload_file.c 88 行:
- printf("%s\n", file_id);
- fdfs_quit(pTrackerServer);
- tracker_close_all_connections();
- fdfs_client_destroy();
至此,client 流程分析完成。通过分析,client 和 tracker 交互,是通过命令TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE ,而和storage 交互,是通过命令 STORAGE_PROTO_CMD_UPLOAD_FILE 。接下来,我们逐步进入tracker 、 storage 的内部实现。
通过前几篇文章的介绍,我们知道,tracker网络接收正常后, 处理任务命令的入口在 tracker_service.c
3137行,int tracker_deal_task(struct fast_task_info *pTask) 函数;
而storage 处理任务命令的入口在storage_service.c 6456 行,int storage_deal_task(struct fast_task_info *pTask).
我们逐步展开对tracker、storage 的分析。
欢迎感兴趣的朋友一起交流研究,提出意见。
FastDFS技术交流群:164684842
- FastDFS分布式文件系统点滴记录5 -- upload上传机制剖析1
- FastDFS分布式文件系统点滴记录5 -- upload上传机制剖析1
- FastDFS分布式文件系统点滴记录5 -- upload上传机制剖析2
- FastDFS分布式文件系统点滴记录5 -- upload上传机制剖析3
- FastDFS分布式文件系统点滴记录5 -- upload上传机制剖析2
- FastDFS分布式文件系统点滴记录5 -- upload上传机制剖析3
- FastDFS分布式文件系统点滴记录6 -- download下载机制剖析
- FastDFS分布式文件系统点滴记录6 -- download下载机制剖析
- FastDFS分布式文件系统点滴记录1 -- 目录
- FastDFS分布式文件系统点滴记录1 -- 目录
- FastDFS分布式文件系统点滴记录2 -- 架构概述
- FastDFS分布式文件系统点滴记录4 -- tracker 、storage 入口分析
- FastDFS分布式文件系统点滴记录2 -- 架构概述
- FastDFS分布式文件系统点滴记录4 -- tracker 、storage 入口分析
- 分布式文件系统FastDFS架构剖析
- 分布式文件系统FastDFS架构剖析
- 分布式文件系统FastDFS架构剖析
- 分布式文件系统FastDFS架构剖析
- FastDFS分布式文件系统点滴记录4 -- tracker 、storage 入口分析
- 暴强谐音,秒杀英语单词
- VS2008编译的程序在某些机器上运行提示“由于应用程序配置不正确,应用程序未能启动”的问题
- python抓取网页图片
- 安装APK时 : Application not installed
- FastDFS分布式文件系统点滴记录5 -- upload上传机制剖析1
- ARM板子启动出现:crc error-- System halted
- FFMpeg在windows下的编译和使用
- FastDFS分布式文件系统点滴记录5 -- upload上传机制剖析2
- eclipse设定每行字符数
- 如何为嵌入式QT加入自己制作的字体
- FastDFS分布式文件系统点滴记录5 -- upload上传机制剖析3
- 4种解析xml文件
- AJAX - onreadystatechange 事件