fastdfs之report源码分析

1. report流程简介

report行为是storage向tracker注册storage,上报storage信息的行为。还需注意的是:它根据返回结果触发同步sync

其storage端的流程大概如下:

  1. main[storage/fdfs_storaged.c]函数中,初始化:tracker_report_init[storage/tracker_client_thread.c]其功能为:清空g_storage_servers,g_sorted_storages,和初始化report线程锁。【见2.1】
  2. main[storage/fdfs_storaged.c]函数中,触发创建report线程tracker_report_thread_start[storage/tracker_client_thread.c]
  3. 在tracker_report_thread_start函数中,根据配置文件的tracker配置,为每一个tracker创建一个report线程tracker_report_thread_entrance [storage/fdfs_storaged.c]。【见2.2】
  4. 在tracker_report_thread_entrance函数中,先调用tracker_report_join向tracker注册storage,再周期性上报storage status,磁盘信息等。【见2.3】
  5. 在上报信息的函数中,得到tracker的返回结果。根据返回结果触发同步sync线程。

2. storage report相关源代码分析

2.1 tracker_report_init函数

report初始化函数。其功能比较简单,清空g_storage_servers,g_sorted_storages,和初始化report线程锁。

storage/tracker_client_thread.c

int tracker_report_init()

{

       int result;

 

       // 清空g_storage_servers,保存storage信息

       memset(g_storage_servers, 0, sizeof(g_storage_servers));

       // 清空g_sorted_storages,排序

       memset(g_sorted_storages, 0, sizeof(g_sorted_storages));

 

       // 初始化report线程锁

       if ((result=init_pthread_lock(&reporter_thread_lock)) != 0)

       {

              return result;

       }

 

       return 0;

}

 

2.2 tracker_report_thread_start函数

创建report线程函数,根据配置,为每一个tracker都创建一个report线程。

storage/tracker_client_thread.c

int tracker_report_thread_start()

{

       ConnectionInfo *pTrackerServer;

       ConnectionInfo *pServerEnd;

       pthread_attr_t pattr;

       pthread_t tid;

       int result;

 

       // 线程属性

       if ((result=init_pthread_attr(&pattr, g_thread_stack_size)) != 0)

       {

              return result;

       }

 

       // 线程pthread_t

       report_tids = (pthread_t *)malloc(sizeof(pthread_t) * \

                                   g_tracker_group.server_count);

       if (report_tids == NULL)

       {

              logError("file: "__FILE__", line: %d, " \

                     "malloc %d bytes fail, " \

                     "errno: %d, error info: %s", \

                     __LINE__, (int)sizeof(pthread_t) * \

                     g_tracker_group.server_count, \

                     errno, STRERROR(errno));

              return errno != 0 ? errno : ENOMEM;

       }

       memset(report_tids, 0, sizeof(pthread_t)*g_tracker_group.server_count);

 

       // tracker server状态,由向tracker注册时返回。

       src_storage_status = (int *)malloc(sizeof(int) * \

                                   g_tracker_group.server_count);

       if (src_storage_status == NULL)

       {

              logError("file: "__FILE__", line: %d, " \

                     "malloc %d bytes fail, " \

                     "errno: %d, error info: %s", __LINE__, \

                     (int)sizeof(int) * g_tracker_group.server_count, \

                     errno, STRERROR(errno));

              return errno != 0 ? errno : ENOMEM;

       }

       memset(src_storage_status,-1,sizeof(int)*g_tracker_group.server_count);

 

       // report的状态,由向tracker注册时返回。

       my_report_status = (signed char *)malloc(sizeof(signed char) * \

                                   g_tracker_group.server_count);

       if (my_report_status == NULL)

       {

              logError("file: "__FILE__", line: %d, " \

                     "malloc %d bytes fail, " \

                     "errno: %d, error info: %s", __LINE__, \

                     (int)sizeof(signed char) * g_tracker_group.server_count, \

                     errno, STRERROR(errno));

              return errno != 0 ? errno : ENOMEM;

       }

       memset(my_report_status, -1, sizeof(char)*g_tracker_group.server_count);

      

       // 创建report线程,并记录线程总数

       g_tracker_reporter_count = 0;

       pServerEnd = g_tracker_group.servers + g_tracker_group.server_count;

       for (pTrackerServer=g_tracker_group.servers; pTrackerServer<pServerEnd; \

              pTrackerServer++)

       {

              // 创建线程,线程函数:tracker_report_thread_entrance[见2.3]

              if((result=pthread_create(&tid, &pattr, \

                     tracker_report_thread_entrance, pTrackerServer)) != 0)

              {

                     logError("file: "__FILE__", line: %d, " \

                            "create thread failed, errno: %d, " \

                            "error info: %s.", \

                            __LINE__, result, STRERROR(result));

                     return result;

              }

 

              // 更新全局变量

              if ((result=pthread_mutex_lock(&reporter_thread_lock)) != 0)

              {

                     logError("file: "__FILE__", line: %d, " \

                            "call pthread_mutex_lock fail, " \

                            "errno: %d, error info: %s", \

                            __LINE__, result, STRERROR(result));

              }

 

              report_tids[g_tracker_reporter_count] = tid;

              g_tracker_reporter_count++;

              if ((result=pthread_mutex_unlock(&reporter_thread_lock)) != 0)

              {

                     logError("file: "__FILE__", line: %d, " \

                            "call pthread_mutex_unlock fail, " \

                            "errno: %d, error info: %s", \

                            __LINE__, result, STRERROR(result));

              }

       }

 

       pthread_attr_destroy(&pattr);

 

       return 0;

}

 

2.3 tracker_report_thread_entrance函数

线程执行函数。先向tracker注册storage,再周期性上报storage相关信息。

storage/tracker_client_thread.c

static void *tracker_report_thread_entrance(void *arg)

{

       ConnectionInfo *pTrackerServer;

       char my_server_id[FDFS_STORAGE_ID_MAX_SIZE];

       char tracker_client_ip[IP_ADDRESS_SIZE];

       char szFailPrompt[36];

       bool sync_old_done;

       int stat_chg_sync_count;

       int sync_time_chg_count;

       time_t current_time;

       time_t last_df_report_time;

       time_t last_sync_report_time;

       time_t last_beat_time;

       int last_trunk_file_id;

       int result;

       int previousCode;

       int nContinuousFail;

       int tracker_index;

       int64_t last_trunk_total_free_space;

       bool bServerPortChanged;

 

       // storage 端口号是否有变化

       bServerPortChanged = (g_last_server_port != 0) && \

                            (g_server_port != g_last_server_port);

 

       // 1.获取tracker连接信息

       pTrackerServer = (ConnectionInfo *)arg;

       pTrackerServer->sock = -1;

       // tracker位置标志

       tracker_index = pTrackerServer - g_tracker_group.servers;

 

       logDebug("file: "__FILE__", line: %d, " \

              "report thread to tracker server %s:%d started", \

              __LINE__, pTrackerServer->ip_addr, pTrackerServer->port);

 

       // 同步完成标志

       sync_old_done = g_sync_old_done;

       // 等待所有线程都创建、启动

       while (g_continue_flag &&  \

              g_tracker_reporter_count < g_tracker_group.server_count)

       {

              sleep(1); //waiting for all thread started

       }

 

       result = 0;

       previousCode = 0;

       nContinuousFail = 0;

       while (g_continue_flag)

       {

              // 2.连接tracker

              if (pTrackerServer->sock >= 0)

              {

                     close(pTrackerServer->sock);

              }

              pTrackerServer->sock = socket(AF_INET, SOCK_STREAM, 0);

              if(pTrackerServer->sock < 0)

              {

                     logCrit("file: "__FILE__", line: %d, " \

                            "socket create failed, errno: %d, " \

                            "error info: %s. program exit!", \

                            __LINE__, errno, STRERROR(errno));

                     g_continue_flag = false;

                     break;

              }

 

              if (g_client_bind_addr && *g_bind_addr != '\0')

              {

                     socketBind(pTrackerServer->sock, g_bind_addr, 0);

              }

 

              tcpsetserveropt(pTrackerServer->sock, g_fdfs_network_timeout);

 

              if (tcpsetnonblockopt(pTrackerServer->sock) != 0)

              {

                     nContinuousFail++;

                     sleep(g_heart_beat_interval);

                     continue;

              }

 

              if ((result=connectserverbyip_nb(pTrackerServer->sock, \

                     pTrackerServer->ip_addr, \

                     pTrackerServer->port, g_fdfs_connect_timeout)) != 0)

              {

                     if (previousCode != result)

                     {

                            logError("file: "__FILE__", line: %d, " \

                                   "connect to tracker server %s:%d fail" \

                                   ", errno: %d, error info: %s", \

                                   __LINE__, pTrackerServer->ip_addr, \

                                   pTrackerServer->port, \

                                   result, STRERROR(result));

                            previousCode = result;

                     }

 

                     nContinuousFail++;

                     if (g_continue_flag)

                     {

                            sleep(g_heart_beat_interval);

                            continue;

                     }

                     else

                     {

                            break;

                     }

              }

 

              // 2. 获取tracker的网卡ip地址tracker_client_ip

              getSockIpaddr(pTrackerServer->sock, \

                            tracker_client_ip, IP_ADDRESS_SIZE);

 

              if (nContinuousFail == 0)

              {

                     *szFailPrompt = '\0';

              }

              else

              {

                     sprintf(szFailPrompt, ", continuous fail count: %d", \

                            nContinuousFail);

              }

              logInfo("file: "__FILE__", line: %d, " \

                     "successfully connect to tracker server %s:%d%s, " \

                     "as a tracker client, my ip is %s", \

                     __LINE__, pTrackerServer->ip_addr, \

                     pTrackerServer->port, szFailPrompt, tracker_client_ip);

 

              previousCode = 0;

              nContinuousFail = 0;

 

              // 判断tracker_client_ip是否正确

              if (*g_tracker_client_ip == '\0')

              {

                     strcpy(g_tracker_client_ip, tracker_client_ip);

              }

              else if (strcmp(tracker_client_ip, g_tracker_client_ip) != 0)

              {

                     logError("file: "__FILE__", line: %d, " \

                            "as a client of tracker server %s:%d, " \

                            "my ip: %s != client ip: %s of other " \

                            "tracker client", __LINE__, \

                            pTrackerServer->ip_addr, pTrackerServer->port, \

                            tracker_client_ip, g_tracker_client_ip);

 

                     close(pTrackerServer->sock);

                     pTrackerServer->sock = -1;

                     break;

              }

 

              // 记录storage本地ip

              insert_into_local_host_ip(tracker_client_ip);

 

              /*

              //printf("file: "__FILE__", line: %d, " \

                     "tracker_client_ip: %s, g_my_server_id_str: %s\n", \

                     __LINE__, tracker_client_ip, g_my_server_id_str);

              //print_local_host_ip_addrs();

              */

 

              // 3.向tracker注册storage,包括storage配置和storage运行状态。[见2.4]

              if (tracker_report_join(pTrackerServer, tracker_index, \

                                   sync_old_done) != 0)

              {

                     sleep(g_heart_beat_interval);

                     continue;

              }

 

              // 如果端口号改变,更新文件.data_init_flag

              if (g_http_port != g_last_http_port)

              {

                     g_last_http_port = g_http_port;

                     if ((result=storage_write_to_sync_ini_file()) != 0)

                     {

                     }

              }

 

              // 如果需要同步

              if (!sync_old_done)

              {

                     // 加report线程锁,为了线程同步

                     if ((result=pthread_mutex_lock(&reporter_thread_lock)) \

                                    != 0)

                     {

                            logError("file: "__FILE__", line: %d, " \

                                   "call pthread_mutex_lock fail, " \

                                   "errno: %d, error info: %s", \

                                   __LINE__, result, STRERROR(result));

 

                            fdfs_quit(pTrackerServer);

                            sleep(g_heart_beat_interval);

                            continue;

                     }

 

                     if (!g_sync_old_done)

                     {

                            // 询问tracker,获取 src storage id and time stamp【见2.6】

                            if (tracker_sync_dest_req(pTrackerServer) == 0)

                            {

                                   g_sync_old_done = true;

                                   // 更新sync信息到.data_init_flag

                                   if (storage_write_to_sync_ini_file() \

                                          != 0)

                                   {

                                   logCrit("file: "__FILE__", line: %d, " \

                                          "storage_write_to_sync_ini_file"\

                                          "  fail, program exit!", \

                                          __LINE__);

 

                                          g_continue_flag = false;

                                          pthread_mutex_unlock( \

                                                 &reporter_thread_lock);

                                          break;

                                   }

                            }

                            else //request failed or need to try again

                            {

                                   pthread_mutex_unlock( \

                                          &reporter_thread_lock);

 

                                   fdfs_quit(pTrackerServer);

                                   sleep(g_heart_beat_interval);

                                   continue;

                            }

                     }

                     else

                     {

                            // 向tracker通知sync's src storage id and time stamp【见2.5】

                            if (tracker_sync_notify(pTrackerServer, tracker_index) != 0)

                            {

                                   pthread_mutex_unlock( \

                                          &reporter_thread_lock);

                                   fdfs_quit(pTrackerServer);

                                   sleep(g_heart_beat_interval);

                                   continue;

                            }

                     }

 

                     if ((result=pthread_mutex_unlock(&reporter_thread_lock))

                             != 0)

                     {

                            logError("file: "__FILE__", line: %d, " \

                                   "call pthread_mutex_unlock fail, " \

                                   "errno: %d, error info: %s", \

                                   __LINE__, result, STRERROR(result));

                     }

 

                     sync_old_done = true;

              }

 

              // 4.向tracker通知sync's src storage id and time stamp,并记录是否成功【见2.5】

              src_storage_status[tracker_index] = \

                                   tracker_sync_notify(pTrackerServer, tracker_index);

              if (src_storage_status[tracker_index] != 0)

              {// 如果不成功,检测是否有成功的tracker。

                     int k;

                     for (k=0; k<g_tracker_group.server_count; k++)

                     {

                            if (src_storage_status[k] != ENOENT)

                            {

                                   break;

                            }

                     }

 

                     // 如果没有,

                     if (k == g_tracker_group.server_count)

                     { //src storage server already be deleted

                            int my_status;

                            if (tracker_get_storage_max_status( \

                                   &g_tracker_group, g_group_name, \

                                   g_tracker_client_ip, my_server_id, \

                                   &my_status) == 0)

                            {

                                   tracker_sync_dest_query(pTrackerServer); // [见2.6]

                                   if(my_status<FDFS_STORAGE_STATUS_OFFLINE

                                          && g_sync_old_done)

                                   {  //need re-sync old files

                                          pthread_mutex_lock( \

                                                 &reporter_thread_lock);

                                          g_sync_old_done = false;

                                          sync_old_done = g_sync_old_done;

                                          storage_write_to_sync_ini_file();

                                          pthread_mutex_unlock( \

                                                 &reporter_thread_lock);

                                   }

                            }

                     }

 

                     fdfs_quit(pTrackerServer);

                     sleep(g_heart_beat_interval);

                     continue;

              }

 

              sync_time_chg_count = 0;

              last_df_report_time = 0;

              last_beat_time = 0;

              last_sync_report_time = 0;

              stat_chg_sync_count = 0;

              last_trunk_file_id = 0;

              last_trunk_total_free_space = -1;

 

              // 5. 周期上报信息

              while (g_continue_flag)

              {

                     current_time = g_current_time;

                     if (current_time - last_beat_time >= \

                                   g_heart_beat_interval)

                     {

                            // 5.1 心跳包,上报storage状态 [见2.7]

                            if (tracker_heart_beat(pTrackerServer, \

                                   &stat_chg_sync_count, \

                                   &bServerPortChanged) != 0)

                            {

                                   break;

                            }

 

                            if (g_storage_ip_changed_auto_adjust && \

                                   tracker_storage_changelog_req( \

                                          pTrackerServer) != 0)

                            {

                                   break;

                            }

 

                            last_beat_time = current_time;

                     }

 

                     if (sync_time_chg_count != g_sync_change_count && \

                            current_time - last_sync_report_time >= \

                                   g_heart_beat_interval)

                     {

                            // 5.2 上报最新的同步时间戳 [见2.8]

                            if (tracker_report_sync_timestamp( \

                                   pTrackerServer, &bServerPortChanged)!=0)

                            {

                                   break;

                            }

 

                            sync_time_chg_count = g_sync_change_count;

                            last_sync_report_time = current_time;

                     }

 

                     if (current_time - last_df_report_time >= \

                                   g_stat_report_interval)

                     {

                            // 5.3 上报storage挂载点磁盘状态 [见2.9]

                            if (tracker_report_df_stat(pTrackerServer, \

                                          &bServerPortChanged) != 0)

                            {

                                   break;

                            }

 

                            last_df_report_time = current_time;

                     }

 

                     // 如果使用“合并存储”

                     if (g_if_trunker_self)

                     {

                            if (last_trunk_file_id < g_current_trunk_file_id)

                            {

                                   if (tracker_report_trunk_fid(pTrackerServer)!=0)

                                   {

                                          break;

                                   }

                                   last_trunk_file_id = g_current_trunk_file_id;

                            }

 

                            if (last_trunk_total_free_space != g_trunk_total_free_space)

                            {

                            if (tracker_report_trunk_free_space(pTrackerServer)!=0)

                            {

                                   break;

                            }

                            last_trunk_total_free_space = g_trunk_total_free_space;

                            }

                     }

 

                     // 判读是否需要重新注册

                     if (need_rejoin_tracker)

                     {

                            need_rejoin_tracker = false;

                            break;

                     }

                     sleep(1);

              } // 周期性上报信息,结束

 

              if ((!g_continue_flag) && fdfs_quit(pTrackerServer) != 0)

              {

              }

 

              close(pTrackerServer->sock);

              pTrackerServer->sock = -1;

              if (g_continue_flag)

              {

                     sleep(1);

              }

       } // 线程 while 结束

 

       if (nContinuousFail > 0)

       {

              logError("file: "__FILE__", line: %d, " \

                     "connect to tracker server %s:%d fail, try count: %d" \

                     ", errno: %d, error info: %s", \

                     __LINE__, pTrackerServer->ip_addr, \

                     pTrackerServer->port, nContinuousFail, \

                     result, STRERROR(result));

       }

 

       thracker_report_thread_exit(pTrackerServer);

 

       return NULL;

}

 

2.4 tracker_report_join函数

向tracker注册storage的函数。

storage/tracker_client_thread.c

int tracker_report_join(ConnectionInfo *pTrackerServer, \

                     const int tracker_index, const bool sync_old_done)

{

       char out_buff[sizeof(TrackerHeader) + sizeof(TrackerStorageJoinBody) + \

                     FDFS_MAX_TRACKERS * FDFS_PROTO_IP_PORT_SIZE];

       TrackerHeader *pHeader;

       TrackerStorageJoinBody *pReqBody;

       TrackerStorageJoinBodyResp respBody;

       char *pInBuff;

       char *p;

       ConnectionInfo *pServer;

       ConnectionInfo *pServerEnd;

       FDFSStorageServer *pTargetServer;

       FDFSStorageServer **ppFound;

       FDFSStorageServer targetServer;

       int out_len;

       //int tracker_count;

       int result;

       int i;

       int64_t in_bytes;

 

       // 1.封装注册上报信息

       pHeader = (TrackerHeader *)out_buff;

       pReqBody = (TrackerStorageJoinBody *)(out_buff+sizeof(TrackerHeader));

 

       memset(out_buff, 0, sizeof(out_buff));

       pHeader->cmd = TRACKER_PROTO_CMD_STORAGE_JOIN; //【见3.1】

       strcpy(pReqBody->group_name, g_group_name);

       strcpy(pReqBody->domain_name, g_http_domain);

       snprintf(pReqBody->version, sizeof(pReqBody->version), "%d.%02d", \

              g_fdfs_version.major, g_fdfs_version.minor);

       long2buff(g_server_port, pReqBody->storage_port);

       long2buff(g_http_port, pReqBody->storage_http_port);

       long2buff(g_fdfs_store_paths.count, pReqBody->store_path_count);

       long2buff(g_subdir_count_per_path, pReqBody->subdir_count_per_path);

       long2buff(g_upload_priority, pReqBody->upload_priority);

       long2buff(g_storage_join_time, pReqBody->join_time);

       long2buff(g_up_time, pReqBody->up_time);

       pReqBody->init_flag = sync_old_done ? 0 : 1;

 

       // 封装stoage当前运行状态

       memset(&targetServer, 0, sizeof(targetServer));

       pTargetServer = &targetServer;

 

       strcpy(targetServer.server.id, g_my_server_id_str);

       ppFound = (FDFSStorageServer **)bsearch(&pTargetServer, \

                     g_sorted_storages, g_storage_count, \

                     sizeof(FDFSStorageServer *), storage_cmp_by_server_id);

       if (ppFound != NULL)

       {

              pReqBody->status = (*ppFound)->server.status;

       }

       else

       {

              if (g_tracker_group.server_count > 1)

              {

                     for (i=0; i<g_tracker_group.server_count; i++)

                     {

                            if (my_report_status[i] == -1)

                            {

                    logInfo("file: "__FILE__", line: %d, "

                            "tracker server: #%d. %s:%d, my_report_status: %d",

                            __LINE__, i, g_tracker_group.servers[i].ip_addr,

                            g_tracker_group.servers[i].port, my_report_status[i]);

                                   break;

                            }

                     }

 

                     if (i == g_tracker_group.server_count)

                     {

                            pReqBody->status = FDFS_STORAGE_STATUS_INIT;

                     }

                     else

                     {

                            pReqBody->status = -1;

                     }

              }

              else

              {

                     pReqBody->status = FDFS_STORAGE_STATUS_INIT;

              }

       }

 

       // 封装storage配置的trackers

       //tracker_count = 0;

       p = out_buff + sizeof(TrackerHeader) + sizeof(TrackerStorageJoinBody);

       pServerEnd = g_tracker_group.servers + g_tracker_group.server_count;

       for (pServer=g_tracker_group.servers; pServer<pServerEnd; pServer++)

       {

              /*

              if (strcmp(pServer->ip_addr, pTrackerServer->ip_addr) == 0 && \

                     pServer->port == pTrackerServer->port)

              {

                     continue;

              }

              tracker_count++;

              */

 

              sprintf(p, "%s:%d", pServer->ip_addr, pServer->port);

              p += FDFS_PROTO_IP_PORT_SIZE;

       }

 

       out_len = p - out_buff;

       long2buff(g_tracker_group.server_count, pReqBody->tracker_count);

       long2buff(out_len - (int)sizeof(TrackerHeader), pHeader->pkg_len);

 

       // 2.发送封装好信息

       if ((result=tcpsenddata_nb(pTrackerServer->sock, out_buff, \

                     out_len, g_fdfs_network_timeout)) != 0)

       {

              logError("file: "__FILE__", line: %d, " \

                     "tracker server %s:%d, send data fail, " \

                     "errno: %d, error info: %s.", \

                     __LINE__, pTrackerServer->ip_addr, \

                     pTrackerServer->port, \

                     result, STRERROR(result));

              return result;

       }

 

       // 3.接收返回信息

    pInBuff = (char *)&respBody;

       result = fdfs_recv_response(pTrackerServer, \

                     &pInBuff, sizeof(respBody), &in_bytes);

       my_report_status[tracker_index] = result;

       if (result != 0)

       {

              logError("file: "__FILE__", line: %d, "

                "fdfs_recv_response fail, result: %d",

                __LINE__, result);

              return result;

       }

 

       if (in_bytes != sizeof(respBody))

       {

              logError("file: "__FILE__", line: %d, " \

                     "tracker server %s:%d, recv data fail, " \

                     "expect %d bytes, but recv " \

                     "%"PRId64" bytes", \

                     __LINE__, pTrackerServer->ip_addr, \

                     pTrackerServer->port, \

                     (int)sizeof(respBody), in_bytes);

              my_report_status[tracker_index] = EINVAL;

              return EINVAL;

       }

 

       if (*(respBody.src_id) == '\0' && *g_sync_src_id != '\0')

       {// 如果返回信息没有src_id信息,而本地存在,则上报

              // pxxian: at this time, notify src storage id.

              return tracker_sync_notify(pTrackerServer, tracker_index);

       }

       else

       {

              return 0;

       }

}

 

2.5 tracker_sync_notify函数

上报src_id和同步时间戳的函数。

 

storage/tracker_client_thread.c

static int tracker_sync_notify(ConnectionInfo *pTrackerServer, const int tracker_index)

{

       char out_buff[sizeof(TrackerHeader)+sizeof(TrackerStorageSyncReqBody)];

       TrackerHeader *pHeader;

       TrackerStorageSyncReqBody *pReqBody;

       int64_t in_bytes;

       int result;

 

       // 1.封装上报信息:g_sync_src_id,g_sync_until_timestamp

       pHeader = (TrackerHeader *)out_buff;

       pReqBody = (TrackerStorageSyncReqBody*)(out_buff+sizeof(TrackerHeader));

 

       memset(out_buff, 0, sizeof(out_buff));

       long2buff((int)sizeof(TrackerStorageSyncReqBody), pHeader->pkg_len);

       pHeader->cmd = TRACKER_PROTO_CMD_STORAGE_SYNC_NOTIFY;//【见3.2】

       strcpy(pReqBody->src_id, g_sync_src_id);

       long2buff(g_sync_until_timestamp, pReqBody->until_timestamp);

 

       // 2.发送上报信息

       if ((result=tcpsenddata_nb(pTrackerServer->sock, out_buff, \

                     sizeof(out_buff), g_fdfs_network_timeout)) != 0)

       {

              logError("file: "__FILE__", line: %d, " \

                     "tracker server %s:%d, send data fail, " \

                     "errno: %d, error info: %s.", \

                     __LINE__, pTrackerServer->ip_addr, \

                     pTrackerServer->port, \

                     result, STRERROR(result));

              return result;

       }

 

       // 3. 接收反馈信息

       if ((result=fdfs_recv_header(pTrackerServer, &in_bytes)) != 0)

    {

              // no such file or directory

        if (result == ENOENT)

        {

               // leader server index

            if (g_tracker_group.leader_index == -1)

            {

                get_tracker_leader();

            }

 

            if (tracker_index == g_tracker_group.leader_index)

            {

                logWarning("file: "__FILE__", line: %d, "

                        "clear sync src id: %s because "

                        "tracker leader response ENOENT",

                        __LINE__, g_sync_src_id);

                *g_sync_src_id = '\0';

                storage_write_to_sync_ini_file();

            }

        }

        if (result != 0 && result != ENOENT)

        {

            logError("file: "__FILE__", line: %d, "

                    "fdfs_recv_header fail, result: %d",

                    __LINE__, result);

            return result;

        }

    }

 

       if (in_bytes != 0)

       {

              logError("file: "__FILE__", line: %d, " \

                     "tracker server %s:%d, recv body length: " \

                     "%"PRId64" != 0",  \

                     __LINE__, pTrackerServer->ip_addr, \

                     pTrackerServer->port, in_bytes);

              return EINVAL;

       }

 

    return result;

}

 

2.6 tracker_sync_dest_req函数

请求同步信息函数。获取g_sync_src_id,g_sync_until_timestamp

 

storage/tracker_client_thread.c

static int tracker_sync_dest_req(ConnectionInfo *pTrackerServer)

{

       TrackerHeader header;

       TrackerStorageSyncReqBody syncReqbody;

       char *pBuff;

       int64_t in_bytes;

       int result;

 

       // 1.发送请求

       memset(&header, 0, sizeof(header));

       header.cmd = TRACKER_PROTO_CMD_STORAGE_SYNC_DEST_REQ;//【见3.3】

       if ((result=tcpsenddata_nb(pTrackerServer->sock, &header, \

                     sizeof(header), g_fdfs_network_timeout)) != 0)

       {

              logError("file: "__FILE__", line: %d, " \

                     "tracker server %s:%d, send data fail, " \

                     "errno: %d, error info: %s.", \

                     __LINE__, pTrackerServer->ip_addr, \

                     pTrackerServer->port, \

                     result, STRERROR(result));

              return result;

       }

 

       // 2.接收反馈

       pBuff = (char *)&syncReqbody;

       if ((result=fdfs_recv_response(pTrackerServer, \

                &pBuff, sizeof(syncReqbody), &in_bytes)) != 0)

       {

              logError("file: "__FILE__", line: %d, "

                "fdfs_recv_response fail, result: %d",

                __LINE__, result);

              return result;

       }

 

       if (in_bytes == 0)

       {

              return result;

       }

 

       if (in_bytes != sizeof(syncReqbody))

       {

              logError("file: "__FILE__", line: %d, " \

                     "tracker server %s:%d, " \

                     "recv body length: %"PRId64" is invalid, " \

                     "expect body length: %d", \

                     __LINE__, pTrackerServer->ip_addr, \

                     pTrackerServer->port, in_bytes, \

                     (int)sizeof(syncReqbody));

              return EINVAL;

       }

 

       // 3.解析反馈信息,获取g_sync_src_id,g_sync_until_timestamp

       memcpy(g_sync_src_id, syncReqbody.src_id, FDFS_STORAGE_ID_MAX_SIZE);

       g_sync_src_id[FDFS_STORAGE_ID_MAX_SIZE - 1] = '\0';

 

       g_sync_until_timestamp = (time_t)buff2long(syncReqbody.until_timestamp);

 

       return 0;

}

2.7 tracker_heart_beat函数

周期性上报信息的心跳函数。主要上报storage status。

 

storage/tracker_client_thread.c

static int tracker_heart_beat(ConnectionInfo *pTrackerServer, \

              int *pstat_chg_sync_count, bool *bServerPortChanged)

{

       char out_buff[sizeof(TrackerHeader) + sizeof(FDFSStorageStatBuff)];

       TrackerHeader *pHeader;

       FDFSStorageStatBuff *pStatBuff;

       int body_len;

       int result;

 

       // 1.封装发送信息FDFSStorageStatBuff

       memset(out_buff, 0, sizeof(out_buff));

       pHeader = (TrackerHeader *)out_buff;

       // 判断是否有变化,无变化不发送

       if (*pstat_chg_sync_count != g_stat_change_count)

       {

              pStatBuff = (FDFSStorageStatBuff *)( \

                            out_buff + sizeof(TrackerHeader));

 

              int2buff(free_queue_alloc_connections(), \

                     pStatBuff->connection.sz_alloc_count);

              int2buff(g_storage_stat.connection.current_count, \

                     pStatBuff->connection.sz_current_count);

              int2buff(g_storage_stat.connection.max_count, \

                     pStatBuff->connection.sz_max_count);

 

              long2buff(g_storage_stat.total_upload_count, \

                     pStatBuff->sz_total_upload_count);

              long2buff(g_storage_stat.success_upload_count, \

                     pStatBuff->sz_success_upload_count);

              long2buff(g_storage_stat.total_append_count, \

                     pStatBuff->sz_total_append_count);

              long2buff(g_storage_stat.success_append_count, \

                     pStatBuff->sz_success_append_count);

              long2buff(g_storage_stat.total_modify_count, \

                     pStatBuff->sz_total_modify_count);

              long2buff(g_storage_stat.success_modify_count, \

                     pStatBuff->sz_success_modify_count);

              long2buff(g_storage_stat.total_truncate_count, \

                     pStatBuff->sz_total_truncate_count);

              long2buff(g_storage_stat.success_truncate_count, \

                     pStatBuff->sz_success_truncate_count);

              long2buff(g_storage_stat.total_download_count, \

                     pStatBuff->sz_total_download_count);

              long2buff(g_storage_stat.success_download_count, \

                     pStatBuff->sz_success_download_count);

              long2buff(g_storage_stat.total_set_meta_count, \

                     pStatBuff->sz_total_set_meta_count);

              long2buff(g_storage_stat.success_set_meta_count, \

                     pStatBuff->sz_success_set_meta_count);

              long2buff(g_storage_stat.total_delete_count, \

                     pStatBuff->sz_total_delete_count);

              long2buff(g_storage_stat.success_delete_count, \

                     pStatBuff->sz_success_delete_count);

              long2buff(g_storage_stat.total_get_meta_count, \

                     pStatBuff->sz_total_get_meta_count);

              long2buff(g_storage_stat.success_get_meta_count, \

                    pStatBuff->sz_success_get_meta_count);

              long2buff(g_storage_stat.total_create_link_count, \

                     pStatBuff->sz_total_create_link_count);

              long2buff(g_storage_stat.success_create_link_count, \

                     pStatBuff->sz_success_create_link_count);

              long2buff(g_storage_stat.total_delete_link_count, \

                     pStatBuff->sz_total_delete_link_count);

              long2buff(g_storage_stat.success_delete_link_count, \

                     pStatBuff->sz_success_delete_link_count);

              long2buff(g_storage_stat.total_upload_bytes, \

                     pStatBuff->sz_total_upload_bytes);

              long2buff(g_storage_stat.success_upload_bytes, \

                     pStatBuff->sz_success_upload_bytes);

              long2buff(g_storage_stat.total_append_bytes, \

                     pStatBuff->sz_total_append_bytes);

              long2buff(g_storage_stat.success_append_bytes, \

                     pStatBuff->sz_success_append_bytes);

              long2buff(g_storage_stat.total_modify_bytes, \

                     pStatBuff->sz_total_modify_bytes);

              long2buff(g_storage_stat.success_modify_bytes, \

                     pStatBuff->sz_success_modify_bytes);

              long2buff(g_storage_stat.total_download_bytes, \

                     pStatBuff->sz_total_download_bytes);

              long2buff(g_storage_stat.success_download_bytes, \

                     pStatBuff->sz_success_download_bytes);

              long2buff(g_storage_stat.total_sync_in_bytes, \

                     pStatBuff->sz_total_sync_in_bytes);

              long2buff(g_storage_stat.success_sync_in_bytes, \

                     pStatBuff->sz_success_sync_in_bytes);

              long2buff(g_storage_stat.total_sync_out_bytes, \

                     pStatBuff->sz_total_sync_out_bytes);

              long2buff(g_storage_stat.success_sync_out_bytes, \

                     pStatBuff->sz_success_sync_out_bytes);

              long2buff(g_storage_stat.total_file_open_count, \

                     pStatBuff->sz_total_file_open_count);

              long2buff(g_storage_stat.success_file_open_count, \

                     pStatBuff->sz_success_file_open_count);

              long2buff(g_storage_stat.total_file_read_count, \

                     pStatBuff->sz_total_file_read_count);

              long2buff(g_storage_stat.success_file_read_count, \

                     pStatBuff->sz_success_file_read_count);

              long2buff(g_storage_stat.total_file_write_count, \

                     pStatBuff->sz_total_file_write_count);

              long2buff(g_storage_stat.success_file_write_count, \

                     pStatBuff->sz_success_file_write_count);

              long2buff(g_storage_stat.last_source_update, \

                     pStatBuff->sz_last_source_update);

              long2buff(g_storage_stat.last_sync_update, \

                     pStatBuff->sz_last_sync_update);

 

              *pstat_chg_sync_count = g_stat_change_count;

              body_len = sizeof(FDFSStorageStatBuff);

       }

       else

       {

              body_len = 0;

       }

      

       // 封装信息头

       long2buff(body_len, pHeader->pkg_len);

       pHeader->cmd = TRACKER_PROTO_CMD_STORAGE_BEAT;//【见3.4】

 

       // 2.发送

       if((result=tcpsenddata_nb(pTrackerServer->sock, out_buff, \

              sizeof(TrackerHeader) + body_len, g_fdfs_network_timeout)) != 0)

       {

              logError("file: "__FILE__", line: %d, " \

                     "tracker server %s:%d, send data fail, " \

                     "errno: %d, error info: %s.", \

                     __LINE__, pTrackerServer->ip_addr, \

                     pTrackerServer->port, \

                     result, STRERROR(result));

              return result;

       }

 

       // 3.接收,根据变化,触发文件同步

       return tracker_check_response(pTrackerServer, bServerPortChanged);

}

2.8 tracker_report_sync_timestamp函数

上报与同组storage同步的时间戳。

 

storage/tracker_client_thread.c

static int tracker_report_sync_timestamp(ConnectionInfo *pTrackerServer, \

              bool *bServerPortChanged)

{

       char out_buff[sizeof(TrackerHeader) + (FDFS_STORAGE_ID_MAX_SIZE + 4) * \

                     FDFS_MAX_SERVERS_EACH_GROUP];

       char *p;

       TrackerHeader *pHeader;

       FDFSStorageServer *pServer;

       FDFSStorageServer *pEnd;

       int result;

       int body_len;

 

       if (g_storage_count == 0)

       {

              return 0;

       }

 

       // 1.封装上报storage记录的同步的storages ip_addr和最后同步时间戳

       memset(out_buff, 0, sizeof(out_buff));

       pHeader = (TrackerHeader *)out_buff;

       p = out_buff + sizeof(TrackerHeader);

 

       body_len = (FDFS_STORAGE_ID_MAX_SIZE + 4) * g_storage_count;

       pHeader->cmd = TRACKER_PROTO_CMD_STORAGE_SYNC_REPORT;//【见3.5】

       long2buff(body_len, pHeader->pkg_len);

 

       pEnd = g_storage_servers + g_storage_count;

       for (pServer=g_storage_servers; pServer<pEnd; pServer++)

       {

              memcpy(p, pServer->server.id, FDFS_STORAGE_ID_MAX_SIZE);

              p += FDFS_STORAGE_ID_MAX_SIZE;

              int2buff(pServer->last_sync_src_timestamp, p);

              p += 4;

       }

 

       // 2.发送

       if((result=tcpsenddata_nb(pTrackerServer->sock, out_buff, \

              sizeof(TrackerHeader) + body_len, g_fdfs_network_timeout)) != 0)

       {

              logError("file: "__FILE__", line: %d, " \

                     "tracker server %s:%d, send data fail, " \

                     "errno: %d, error info: %s.", \

                     __LINE__, pTrackerServer->ip_addr, \

                     pTrackerServer->port, \

                     result, STRERROR(result));

              return result;

       }

 

       // 3.接收反馈。根据变化,触发文件同步sync

       return tracker_check_response(pTrackerServer, bServerPortChanged);

}

2.9 tracker_report_df_stat函数

上报挂载点磁盘信息。如果有一个挂载点无法访问,即不上报。

 

storage/tracker_client_thread.c

static int tracker_report_df_stat(ConnectionInfo *pTrackerServer, \

              bool *bServerPortChanged)

{

       char out_buff[sizeof(TrackerHeader) + \

                     sizeof(TrackerStatReportReqBody) * 16];

       char *pBuff;

       TrackerHeader *pHeader;

       TrackerStatReportReqBody *pStatBuff;

       struct statvfs sbuf;

       int body_len;

       int total_len;

       int store_path_index;

       int i;

       int result;

 

       // 准备上报信息buff

       body_len = (int)sizeof(TrackerStatReportReqBody) * g_fdfs_store_paths.count;

       total_len = (int)sizeof(TrackerHeader) + body_len;

       if (total_len <= sizeof(out_buff))

       {

              pBuff = out_buff;

       }

       else

       {

              pBuff = (char *)malloc(total_len);

              if (pBuff == NULL)

              {

                     logError("file: "__FILE__", line: %d, " \

                            "malloc %d bytes fail, " \

                            "errno: %d, error info: %s", \

                            __LINE__, total_len, \

                            errno, STRERROR(errno));

                     return errno != 0 ? errno : ENOMEM;

              }

       }

 

       // 1. 封装上报信息

       pHeader = (TrackerHeader *)pBuff;

       pStatBuff = (TrackerStatReportReqBody*) \

                     (pBuff + sizeof(TrackerHeader));

       long2buff(body_len, pHeader->pkg_len);

       pHeader->cmd = TRACKER_PROTO_CMD_STORAGE_REPORT_DISK_USAGE;//【见3.6】

       pHeader->status = 0;

 

       for (i=0; i<g_fdfs_store_paths.count; i++)

       {

              // 读取挂载点磁盘信息

              if (statvfs(g_fdfs_store_paths.paths[i], &sbuf) != 0)

              {

                     logError("file: "__FILE__", line: %d, " \

                            "call statfs fail, errno: %d, error info: %s.",\

                            __LINE__, errno, STRERROR(errno));

 

                     if (pBuff != out_buff)

                     {

                            free(pBuff);

                     }

                     return errno != 0 ? errno : EACCES;

              }

 

              // 填充信息

              g_path_space_list[i].total_mb = ((int64_t)(sbuf.f_blocks) * \

                                   sbuf.f_frsize) / FDFS_ONE_MB;

              g_path_space_list[i].free_mb = ((int64_t)(sbuf.f_bavail) * \

                                   sbuf.f_frsize) / FDFS_ONE_MB;

              long2buff(g_path_space_list[i].total_mb, pStatBuff->sz_total_mb);

              long2buff(g_path_space_list[i].free_mb, pStatBuff->sz_free_mb);

 

              pStatBuff++;

       }

 

       if (g_store_path_mode == FDFS_STORE_PATH_LOAD_BALANCE)

       {// store_path 负载均衡模式

              int max_free_mb;

 

              /* find the max free space path */

              max_free_mb = 0;

              store_path_index = -1;

              for (i=0; i<g_fdfs_store_paths.count; i++)

              {

                     if (g_path_space_list[i].free_mb > \

                            g_avg_storage_reserved_mb \

                            && g_path_space_list[i].free_mb > max_free_mb)

                     {

                            store_path_index = i;

                            max_free_mb = g_path_space_list[i].free_mb;

                     }

              }

              if (g_store_path_index != store_path_index)

              {

                     g_store_path_index = store_path_index;

              }

       }

 

       // 2.发送

       result = tcpsenddata_nb(pTrackerServer->sock, pBuff, \

                     total_len, g_fdfs_network_timeout);

       if (pBuff != out_buff)

       {

              free(pBuff);

       }

       if(result != 0)

       {

              logError("file: "__FILE__", line: %d, " \

                     "tracker server %s:%d, send data fail, " \

                     "errno: %d, error info: %s.", \

                     __LINE__, pTrackerServer->ip_addr, \

                     pTrackerServer->port, \

                     result, STRERROR(result));

              return result;

       }

 

       // 3.接收反馈。根据变化,触发文件同步sync

       return tracker_check_response(pTrackerServer, bServerPortChanged);

}

 

3. tracker report相关源代码分析

tracker在nio线程[tracker/tracker_nio.c]接收函数client_sock_read接收完后,调用tracker_deal_task [tracker/tracker_service.c]处理任务。

 

3.1 tracker_deal_storage_join函数

根据tracker_deal_task其中代码:

case TRACKER_PROTO_CMD_STORAGE_JOIN:

       result = tracker_deal_storage_join(pTask);

       break;

storage中上报磁盘信息tracker_report_df_stat函数发送的命令:TRACKER_PROTO_CMD_STORAGE_JOIN,由tracker_deal_storage_join函数处理。

 

tracker/tracker_service.c

static int tracker_deal_storage_join(struct fast_task_info *pTask)

{

       TrackerStorageJoinBodyResp *pJoinBodyResp;

       TrackerStorageJoinBody *pBody;

       ConnectionInfo *pTrackerServer;

       ConnectionInfo *pTrackerEnd;

       char *p;

       char *pSeperator;

       FDFSStorageJoinBody joinBody;

       int result;

       TrackerClientInfo *pClientInfo;

       char tracker_ip[IP_ADDRESS_SIZE];

 

       // 获取client信息

       pClientInfo = (TrackerClientInfo *)pTask->arg;

 

       // 判断包长

       if (pTask->length - sizeof(TrackerHeader) < \

                     sizeof(TrackerStorageJoinBody))

       {

              logError("file: "__FILE__", line: %d, " \

                     "cmd: %d, client ip: %s, " \

                     "package size "PKG_LEN_PRINTF_FORMAT" " \

                     "is not correct, expect length >= %d.", \

                     __LINE__, TRACKER_PROTO_CMD_STORAGE_JOIN, \

                     pTask->client_ip, pTask->length - \

                     (int)sizeof(TrackerHeader),

                     (int)sizeof(TrackerStorageJoinBody));

              pTask->length = sizeof(TrackerHeader);

              return EINVAL;

       }

 

       // 把接收到的信息,写入FDFSStorageJoinBody joinBody。

       pBody = (TrackerStorageJoinBody *)(pTask->data + sizeof(TrackerHeader));

       joinBody.tracker_count = buff2long(pBody->tracker_count);

       if (joinBody.tracker_count <= 0 || \

              joinBody.tracker_count > FDFS_MAX_TRACKERS)

       {

              logError("file: "__FILE__", line: %d, " \

                     "cmd: %d, client ip: %s, " \

                     "tracker_count: %d is invalid, it <= 0 or > %d", \

                     __LINE__, TRACKER_PROTO_CMD_STORAGE_JOIN, \

                     pTask->client_ip, joinBody.tracker_count, \

                     FDFS_MAX_TRACKERS);

              pTask->length = sizeof(TrackerHeader);

              return EINVAL;

       }

 

       if (pTask->length - sizeof(TrackerHeader) != \

              sizeof(TrackerStorageJoinBody) + joinBody.tracker_count *\

              FDFS_PROTO_IP_PORT_SIZE)

       {

              logError("file: "__FILE__", line: %d, " \

                     "cmd: %d, client ip: %s, " \

                     "package size "PKG_LEN_PRINTF_FORMAT" " \

                     "is not correct, expect length %d.", \

                     __LINE__, TRACKER_PROTO_CMD_STORAGE_JOIN, \

                     pTask->client_ip, pTask->length - \

                     (int)sizeof(TrackerHeader),

                     (int)sizeof(TrackerStorageJoinBody) + \

                     joinBody.tracker_count * FDFS_PROTO_IP_PORT_SIZE);

              pTask->length = sizeof(TrackerHeader);

              return EINVAL;

       }

 

       joinBody.service_guid[FDFS_SERVICE_GUID_LEN] = '\0';

       if ((result = fdfs_validate_service_guid(joinBody.service_guid)) != 0)

       {

              logError("file: "__FILE__", line: %d, " \

                            "client ip: %s, null service_guid: %s", \

                            __LINE__, pTask->client_ip, \

                            joinBody.service_guid);

              pTask->length = sizeof(TrackerHeader);

              return result;

       }

 

       memcpy(joinBody.group_name, pBody->group_name, FDFS_GROUP_NAME_MAX_LEN);

       joinBody.group_name[FDFS_GROUP_NAME_MAX_LEN] = '\0';

       if ((result=fdfs_validate_group_name(joinBody.group_name)) != 0)

       {

              logError("file: "__FILE__", line: %d, " \

                     "client ip: %s, invalid group_name: %s", \

                     __LINE__, pTask->client_ip, \

                     joinBody.group_name);

              pTask->length = sizeof(TrackerHeader);

              return result;

       }

 

       joinBody.storage_port = (int)buff2long(pBody->storage_port);

       if (joinBody.storage_port <= 0)

       {

              logError("file: "__FILE__", line: %d, " \

                     "client ip: %s, invalid port: %d", \

                     __LINE__, pTask->client_ip, \

                     joinBody.storage_port);

              pTask->length = sizeof(TrackerHeader);

              return EINVAL;

       }

 

       joinBody.storage_http_port = (int)buff2long(pBody->storage_http_port);

       if (joinBody.storage_http_port < 0)

       {

              logError("file: "__FILE__", line: %d, " \

                     "client ip: %s, invalid http port: %d", \

                     __LINE__, pTask->client_ip, \

                     joinBody.storage_http_port);

              pTask->length = sizeof(TrackerHeader);

              return EINVAL;

       }

 

       joinBody.store_path_count = (int)buff2long(pBody->store_path_count);

       if (joinBody.store_path_count <= 0 || joinBody.store_path_count > 256)

       {

              logError("file: "__FILE__", line: %d, " \

                     "client ip: %s, invalid store_path_count: %d", \

                     __LINE__, pTask->client_ip, \

                     joinBody.store_path_count);

              pTask->length = sizeof(TrackerHeader);

              return EINVAL;

       }

 

       joinBody.subdir_count_per_path = (int)buff2long( \

                                   pBody->subdir_count_per_path);

       if (joinBody.subdir_count_per_path <= 0 || \

           joinBody.subdir_count_per_path > 256)

       {

              logError("file: "__FILE__", line: %d, " \

                     "client ip: %s, invalid subdir_count_per_path: %d", \

                     __LINE__, pTask->client_ip, \

                     joinBody.subdir_count_per_path);

              pTask->length = sizeof(TrackerHeader);

              return EINVAL;

       }

 

       // 写入trackers

       p = pTask->data+sizeof(TrackerHeader)+sizeof(TrackerStorageJoinBody);

       pTrackerEnd = joinBody.tracker_servers + \

                    joinBody.tracker_count;

       for (pTrackerServer=joinBody.tracker_servers; \

              pTrackerServer<pTrackerEnd; pTrackerServer++)

       {

              * (p + FDFS_PROTO_IP_PORT_SIZE - 1) = '\0';

              if ((pSeperator=strchr(p, ':')) == NULL)

              {

                     logError("file: "__FILE__", line: %d, " \

                            "client ip: %s, invalid tracker server ip " \

                            "and port: %s", __LINE__, pTask->client_ip, p);

                     pTask->length = sizeof(TrackerHeader);

                     return EINVAL;

              }

 

              *pSeperator = '\0';

              snprintf(pTrackerServer->ip_addr, \

                     sizeof(pTrackerServer->ip_addr), "%s", p);

              pTrackerServer->port = atoi(pSeperator + 1);

              pTrackerServer->sock = -1;

 

              p += FDFS_PROTO_IP_PORT_SIZE;

       }

 

       joinBody.upload_priority = (int)buff2long(pBody->upload_priority);

       joinBody.join_time = (time_t)buff2long(pBody->join_time);

       joinBody.up_time = (time_t)buff2long(pBody->up_time);

 

       *(pBody->version + (sizeof(pBody->version) - 1)) = '\0';

       *(pBody->domain_name + (sizeof(pBody->domain_name) - 1)) = '\0';

       strcpy(joinBody.version, pBody->version);

       strcpy(joinBody.domain_name, pBody->domain_name);

       joinBody.init_flag = pBody->init_flag;

       joinBody.status = pBody->status;

 

       getSockIpaddr(pTask->event.fd, \

              tracker_ip, IP_ADDRESS_SIZE);

       insert_into_local_host_ip(tracker_ip);

 

       // 根据joinBody更新或者新增storage和组

       result = tracker_mem_add_group_and_storage(pClientInfo, \

                     pTask->client_ip, &joinBody, true);

       if (result != 0)

       {

              pTask->length = sizeof(TrackerHeader);

              return result;

       }

 

       // 打包返回信息

       pJoinBodyResp = (TrackerStorageJoinBodyResp *)(pTask->data + \

                            sizeof(TrackerHeader));

       memset(pJoinBodyResp, 0, sizeof(TrackerStorageJoinBodyResp));

 

       if (pClientInfo->pStorage->psync_src_server != NULL)

       {

              strcpy(pJoinBodyResp->src_id, \

                     pClientInfo->pStorage->psync_src_server->id);

       }

 

       pTask->length = sizeof(TrackerHeader) + \

                     sizeof(TrackerStorageJoinBodyResp);

       return 0;

}

 

3.2 tracker_deal_storage_sync_notify函数

根据tracker_deal_task其中代码:

case TRACKER_PROTO_CMD_STORAGE_SYNC_NOTIFY:

       result = tracker_deal_storage_sync_notify(pTask);

       break;

storage中上报更新源ip和时间戳函数tracker_sync_notify函数发送的命令:TRACKER_PROTO_CMD_STORAGE_SYNC_NOTIFY,由tracker_deal_storage_sync_notify函数处理。

 

tracker/tracker_service.c

static int tracker_deal_storage_sync_notify(struct fast_task_info *pTask)

{

       TrackerStorageSyncReqBody *pBody;

       char sync_src_id[FDFS_STORAGE_ID_MAX_SIZE];

       bool bSaveStorages;

       TrackerClientInfo *pClientInfo;

      

       // 1.获取client信息

       pClientInfo = (TrackerClientInfo *)pTask->arg;

 

       // 2.判断包长

       if (pTask->length  - sizeof(TrackerHeader) != \

                     sizeof(TrackerStorageSyncReqBody))

       {

              logError("file: "__FILE__", line: %d, " \

                     "cmd: %d, client ip: %s, package size " \

                     PKG_LEN_PRINTF_FORMAT" is not correct, " \

                     "expect length: %d", __LINE__, \

                     TRACKER_PROTO_CMD_STORAGE_SYNC_NOTIFY, \

                     pTask->client_ip, pTask->length - \

                     (int)sizeof(TrackerHeader),

                     (int)sizeof(TrackerStorageSyncReqBody));

              pTask->length = sizeof(TrackerHeader);

              return EINVAL;

       }

 

       // 获取消息体

       pBody=(TrackerStorageSyncReqBody *)(pTask->data+sizeof(TrackerHeader));

       if (*(pBody->src_id) == '\0')

       {

              if (pClientInfo->pStorage->status == FDFS_STORAGE_STATUS_INIT || \

                     pClientInfo->pStorage->status == FDFS_STORAGE_STATUS_WAIT_SYNC || \

                     pClientInfo->pStorage->status == FDFS_STORAGE_STATUS_SYNCING)

              {//更新storage运行状态,并保存文件

                     pClientInfo->pStorage->status = FDFS_STORAGE_STATUS_ONLINE;

                     pClientInfo->pGroup->chg_count++;

                     tracker_save_storages();

              }

 

              pTask->length = sizeof(TrackerHeader);

              return 0;

       }

 

       bSaveStorages = false;

       if (pClientInfo->pStorage->status == FDFS_STORAGE_STATUS_INIT)

       {

              pClientInfo->pStorage->status = FDFS_STORAGE_STATUS_WAIT_SYNC;

              pClientInfo->pGroup->chg_count++;

              bSaveStorages = true;

       }

 

       if (pClientInfo->pStorage->psync_src_server == NULL)

       {// 如果源同步服务为空,就根据src_id获取源同步服务

              memcpy(sync_src_id, pBody->src_id, \

                            FDFS_STORAGE_ID_MAX_SIZE);

              sync_src_id[FDFS_STORAGE_ID_MAX_SIZE - 1] = '\0';

 

              // 根据src_id获取源同步服务

              pClientInfo->pStorage->psync_src_server = \

                     tracker_mem_get_storage(pClientInfo->pGroup, \

                            sync_src_id);

              if (pClientInfo->pStorage->psync_src_server == NULL)

              {

                     logError("file: "__FILE__", line: %d, " \

                            "client ip: %s, " \

                            "sync src server: %s not exists", \

                            __LINE__, pTask->client_ip, \

                            sync_src_id);

                     pTask->length = sizeof(TrackerHeader);

                     return ENOENT;

              }

 

              if (pClientInfo->pStorage->psync_src_server->status == \

                     FDFS_STORAGE_STATUS_DELETED)

              {

                     logError("file: "__FILE__", line: %d, " \

                            "client ip: %s, " \

                            "sync src server: %s already be deleted", \

                            __LINE__, pTask->client_ip, \

                            sync_src_id);

                     pTask->length = sizeof(TrackerHeader);

                     return ENOENT;

              }

 

              if (pClientInfo->pStorage->psync_src_server->status == \

                     FDFS_STORAGE_STATUS_IP_CHANGED)

              {

                     logError("file: "__FILE__", line: %d, " \

                            "client ip: %s, the ip address of " \

                            "the sync src server: %s changed", \

                            __LINE__, pTask->client_ip, \

                            sync_src_id);

                     pTask->length = sizeof(TrackerHeader);

                     return ENOENT;

              }

 

              pClientInfo->pStorage->sync_until_timestamp = \

                            (int)buff2long(pBody->until_timestamp);

              bSaveStorages = true;

       }

 

       if (bSaveStorages)

       {

              // 把状态保存到文件

              tracker_save_storages();

       }

 

       pTask->length = sizeof(TrackerHeader);

       return 0;

}

 

3.3 tracker_deal_storage_sync_dest_req函数

根据tracker_deal_task其中代码:

case TRACKER_PROTO_CMD_STORAGE_SYNC_DEST_REQ:

       TRACKER_CHECK_LOGINED(pTask)

       result = tracker_deal_storage_sync_dest_req(pTask);

break;

storage中请求同步信息tracker_sync_dest_req函数发送的命令:TRACKER_PROTO_CMD_STORAGE_SYNC_DEST_REQ,由tracker_deal_storage_sync_dest_req函数处理。

 

tracker/tracker_service.c

 

static int tracker_deal_storage_sync_dest_req(struct fast_task_info *pTask)

{

       TrackerStorageSyncReqBody *pBody;

       FDFSStorageDetail *pSrcStorage;

       FDFSStorageDetail **ppServer;

       FDFSStorageDetail **ppServerEnd;

       int sync_until_timestamp;

       int source_count;

       TrackerClientInfo *pClientInfo;

      

       // 1.获取client信息

       pClientInfo = (TrackerClientInfo *)pTask->arg;

 

       // 2.获同步时间戳

       pSrcStorage = NULL;

       sync_until_timestamp = (int)g_current_time;

      

       // 3.获取更新源 src_id

       do

       {

              if (pTask->length - sizeof(TrackerHeader) != 0)

              {

                     logError("file: "__FILE__", line: %d, " \

                            "cmd=%d, client ip: %s, package size " \

                            PKG_LEN_PRINTF_FORMAT" is not correct, " \

                            "expect length: 0", \

                            __LINE__, TRACKER_PROTO_CMD_STORAGE_SYNC_DEST_REQ, \

                            pTask->client_ip, pTask->length - \

                            (int)sizeof(TrackerHeader));

                     pTask->length = sizeof(TrackerHeader);

                     return EINVAL;

              }

 

              // 如果组内仅不多于一个storage,返回

              if (pClientInfo->pGroup->count <= 1)

              {

                     break;

              }

 

              source_count = 0;

              ppServerEnd = pClientInfo->pGroup->all_servers + \

                              pClientInfo->pGroup->count;

              for (ppServer=pClientInfo->pGroup->all_servers; \

                            ppServer<ppServerEnd; ppServer++)

              {

                     // 如果是自己,跳过

                     if (strcmp((*ppServer)->id, \

                                   pClientInfo->pStorage->id) == 0)

                     {

                            continue;

                     }

 

                     // 统计可能更新源的个数

                     if ((*ppServer)->status == FDFS_STORAGE_STATUS_OFFLINE

                            || (*ppServer)->status == FDFS_STORAGE_STATUS_ONLINE

                            || (*ppServer)->status == FDFS_STORAGE_STATUS_ACTIVE)

                     {

                            source_count++;

                     }

              }

              // 无更新源,返回

              if (source_count == 0)

              {

                     break;

              }

 

              // 在active的组内storages抽取第一个作为该storage的src_storage

              pSrcStorage = tracker_get_group_sync_src_server( \

                            pClientInfo->pGroup, pClientInfo->pStorage);

              if (pSrcStorage == NULL)

              {

                     pTask->length = sizeof(TrackerHeader);

                     return ENOENT;

              }

 

              // 4.封装返回内容,src_id和sync_until_timestamp

              pBody=(TrackerStorageSyncReqBody *)(pTask->data+sizeof(TrackerHeader));

              strcpy(pBody->src_id, pSrcStorage->id);

              long2buff(sync_until_timestamp, pBody->until_timestamp);

 

       } while (0);

 

       if (pSrcStorage == NULL)

       {

              pClientInfo->pStorage->status = \

                            FDFS_STORAGE_STATUS_ONLINE;

              pClientInfo->pGroup->chg_count++;

              tracker_save_storages();

 

              pTask->length = sizeof(TrackerHeader);

              return 0;

       }

 

       // 更新tracker中保存的storage信息

       pClientInfo->pStorage->psync_src_server = pSrcStorage;

       pClientInfo->pStorage->sync_until_timestamp = sync_until_timestamp;

       pClientInfo->pStorage->status = FDFS_STORAGE_STATUS_WAIT_SYNC;

       pClientInfo->pGroup->chg_count++;

 

       // 把storage信息保存到文件中

       tracker_save_storages();

 

       pTask->length = sizeof(TrackerHeader)+sizeof(TrackerStorageSyncReqBody);

       return 0;

}

3.4 tracker_deal_storage_beat函数

根据tracker_deal_task其中代码:

case TRACKER_PROTO_CMD_STORAGE_BEAT:

       TRACKER_CHECK_LOGINED(pTask)

       result = tracker_deal_storage_beat(pTask);

       break;

storage中storage心跳包tracker_heart_beat函数发送的命令:TRACKER_PROTO_CMD_STORAGE_BEAT,由tracker_deal_storage_beat函数处理。

tracker/tracker_service.c

 

static int tracker_deal_storage_beat(struct fast_task_info *pTask)

{

       int nPkgLen;

       int status;

       FDFSStorageStatBuff *pStatBuff;

       FDFSStorageStat *pStat;

       TrackerClientInfo *pClientInfo;

      

       // 1.获取client信息

       pClientInfo = (TrackerClientInfo *)pTask->arg;

 

       do

       {

              // 2. 判断包长

              nPkgLen = pTask->length - sizeof(TrackerHeader);

              if (nPkgLen == 0)

              {

                     status = 0;

                     break;

              }

 

              if (nPkgLen != sizeof(FDFSStorageStatBuff))

              {

                     logError("file: "__FILE__", line: %d, " \

                            "cmd=%d, client ip: %s, package size " \

                            PKG_LEN_PRINTF_FORMAT" is not correct, " \

                            "expect length: 0 or %d", __LINE__, \

                            TRACKER_PROTO_CMD_STORAGE_BEAT, \

                            pTask->client_ip, nPkgLen,

                            (int)sizeof(FDFSStorageStatBuff));

                     status = EINVAL;

                     break;

              }

 

              // 3.把上报的信息更新到tracker记录的storage中

              pStatBuff = (FDFSStorageStatBuff *)(pTask->data + \

                                   sizeof(TrackerHeader));

              pStat = &(pClientInfo->pStorage->stat);

 

              pStat->connection.alloc_count = \

                     buff2int(pStatBuff->connection.sz_alloc_count);

              pStat->connection.current_count = \

                     buff2int(pStatBuff->connection.sz_current_count);

              pStat->connection.max_count = \

                     buff2int(pStatBuff->connection.sz_max_count);

 

              pStat->total_upload_count = \

                     buff2long(pStatBuff->sz_total_upload_count);

              pStat->success_upload_count = \

                     buff2long(pStatBuff->sz_success_upload_count);

              pStat->total_append_count = \

                     buff2long(pStatBuff->sz_total_append_count);

              pStat->success_append_count = \

                     buff2long(pStatBuff->sz_success_append_count);

              pStat->total_modify_count = \

                     buff2long(pStatBuff->sz_total_modify_count);

              pStat->success_modify_count = \

                     buff2long(pStatBuff->sz_success_modify_count);

              pStat->total_truncate_count = \

                     buff2long(pStatBuff->sz_total_truncate_count);

              pStat->success_truncate_count = \

                     buff2long(pStatBuff->sz_success_truncate_count);

              pStat->total_download_count = \

                     buff2long(pStatBuff->sz_total_download_count);

              pStat->success_download_count = \

                     buff2long(pStatBuff->sz_success_download_count);

              pStat->total_set_meta_count = \

                     buff2long(pStatBuff->sz_total_set_meta_count);

              pStat->success_set_meta_count = \

                     buff2long(pStatBuff->sz_success_set_meta_count);

              pStat->total_delete_count = \

                     buff2long(pStatBuff->sz_total_delete_count);

              pStat->success_delete_count = \

                     buff2long(pStatBuff->sz_success_delete_count);

              pStat->total_get_meta_count = \

                     buff2long(pStatBuff->sz_total_get_meta_count);

              pStat->success_get_meta_count = \

                     buff2long(pStatBuff->sz_success_get_meta_count);

              pStat->last_source_update = \

                     buff2long(pStatBuff->sz_last_source_update);

              pStat->last_sync_update = \

                     buff2long(pStatBuff->sz_last_sync_update);

              pStat->total_create_link_count = \

                     buff2long(pStatBuff->sz_total_create_link_count);

              pStat->success_create_link_count = \

                     buff2long(pStatBuff->sz_success_create_link_count);

              pStat->total_delete_link_count = \

                     buff2long(pStatBuff->sz_total_delete_link_count);

              pStat->success_delete_link_count = \

                     buff2long(pStatBuff->sz_success_delete_link_count);

              pStat->total_upload_bytes = \

                     buff2long(pStatBuff->sz_total_upload_bytes);

              pStat->success_upload_bytes = \

                     buff2long(pStatBuff->sz_success_upload_bytes);

              pStat->total_append_bytes = \

                     buff2long(pStatBuff->sz_total_append_bytes);

              pStat->success_append_bytes = \

                     buff2long(pStatBuff->sz_success_append_bytes);

              pStat->total_modify_bytes = \

                     buff2long(pStatBuff->sz_total_modify_bytes);

              pStat->success_modify_bytes = \

                     buff2long(pStatBuff->sz_success_modify_bytes);

              pStat->total_download_bytes = \

                     buff2long(pStatBuff->sz_total_download_bytes);

              pStat->success_download_bytes = \

                     buff2long(pStatBuff->sz_success_download_bytes);

              pStat->total_sync_in_bytes = \

                     buff2long(pStatBuff->sz_total_sync_in_bytes);

              pStat->success_sync_in_bytes = \

                     buff2long(pStatBuff->sz_success_sync_in_bytes);

              pStat->total_sync_out_bytes = \

                     buff2long(pStatBuff->sz_total_sync_out_bytes);

              pStat->success_sync_out_bytes = \

                     buff2long(pStatBuff->sz_success_sync_out_bytes);

              pStat->total_file_open_count = \

                     buff2long(pStatBuff->sz_total_file_open_count);

              pStat->success_file_open_count = \

                     buff2long(pStatBuff->sz_success_file_open_count);

              pStat->total_file_read_count = \

                     buff2long(pStatBuff->sz_total_file_read_count);

              pStat->success_file_read_count = \

                     buff2long(pStatBuff->sz_success_file_read_count);

              pStat->total_file_write_count = \

                     buff2long(pStatBuff->sz_total_file_write_count);

              pStat->success_file_write_count = \

                     buff2long(pStatBuff->sz_success_file_write_count);

 

              // 4.把更新内容写入文件

              if (++g_storage_stat_chg_count % TRACKER_SYNC_TO_FILE_FREQ == 0)

              {

                     status = tracker_save_storages();

              }

              else

              {

                     status = 0;

              }

 

              //printf("g_storage_stat_chg_count=%d\n", g_storage_stat_chg_count);

 

       } while (0);

 

       if (status == 0)

       {

              // 5.更新该storage的状态为active,并且更新最新的心跳时间

              tracker_mem_active_store_server(pClientInfo->pGroup, \

                            pClientInfo->pStorage);

              pClientInfo->pStorage->stat.last_heart_beat_time = g_current_time;

 

       }

 

       // 6.返回同步信息

       //printf("deal heart beat, status=%d\n", status);

       return tracker_check_and_sync(pTask, status);

}

 

3.5 tracker_deal_storage_sync_report函数

根据tracker_deal_task其中代码:

case TRACKER_PROTO_CMD_STORAGE_SYNC_REPORT:

       TRACKER_CHECK_LOGINED(pTask)

       result = tracker_deal_storage_sync_report(pTask);

       break;

storage中上报与同组storage同步的时间戳tracker_report_sync_timestamp函数发送的命令:TRACKER_PROTO_CMD_STORAGE_SYNC_REPORT,由tracker_deal_storage_sync_report函数处理。

 

tracker/tracker_service.c

 

static int tracker_deal_storage_sync_report(struct fast_task_info *pTask)

{

       char *p;

       char *pEnd;

       char *src_id;

       int status;

       int sync_timestamp;

       int src_index;

       int dest_index;

       int nPkgLen;

       FDFSStorageDetail *pSrcStorage;

       TrackerClientInfo *pClientInfo;

      

       // 1.获取client信息

       pClientInfo = (TrackerClientInfo *)pTask->arg;

 

       // 2.判断包长

       nPkgLen = pTask->length - sizeof(TrackerHeader);

       if (nPkgLen <= 0 || nPkgLen % (FDFS_STORAGE_ID_MAX_SIZE + 4) != 0)

       {

              logError("file: "__FILE__", line: %d, " \

                     "cmd=%d, client ip: %s, package size " \

                     PKG_LEN_PRINTF_FORMAT" is not correct", \

                     __LINE__, TRACKER_PROTO_CMD_STORAGE_SYNC_REPORT, \

                     pTask->client_ip, nPkgLen);

 

              pTask->length = sizeof(TrackerHeader);

              return EINVAL;

       }

 

       // 3. 更新最新同步时间戳last_synced_timestamp

       do

       {

              // 获此上报storage的在组内的index

              dest_index = tracker_mem_get_storage_index(pClientInfo->pGroup,

                            pClientInfo->pStorage);

              if (dest_index < 0 || dest_index >= pClientInfo->pGroup->count)

              {

                     status = 0;

                     break;

              }

 

              // 如果是轮询上传

              if (g_groups.store_server == FDFS_STORE_SERVER_ROUND_ROBIN)

              { // pxxian: ROUND ROBIN

                     int min_synced_timestamp;

 

                     min_synced_timestamp = 0;

                     pEnd = pTask->data + pTask->length;

                     for (p=pTask->data + sizeof(TrackerHeader); p<pEnd; \

                            p += (FDFS_STORAGE_ID_MAX_SIZE + 4))

                     {

                            // 读取上报信息src_id和sync_timestamp

                            sync_timestamp = buff2int(p + FDFS_STORAGE_ID_MAX_SIZE);

                            if (sync_timestamp <= 0)

                            {

                                   continue;

                            }

 

                            src_id = p;

                            *(src_id + (FDFS_STORAGE_ID_MAX_SIZE - 1)) = '\0';

                            // 获取src_id指向的storage

                            pSrcStorage = tracker_mem_get_storage( \

                                          pClientInfo->pGroup, src_id);

                            if (pSrcStorage == NULL)

                            {

                                   continue;

                            }

                            if (pSrcStorage->status != FDFS_STORAGE_STATUS_ACTIVE)

                            {

                                   continue;

                            }

                            // 获取src_id的storage的组内index

                            src_index = tracker_mem_get_storage_index( \

                                          pClientInfo->pGroup, pSrcStorage);

                            if (src_index == dest_index || src_index < 0 || \

                                          src_index >= pClientInfo->pGroup->count)

                            {

                                   continue;

                            }

 

                            // 更新同步时间戳sync_timestamp

                            pClientInfo->pGroup->last_sync_timestamps \

                                   [src_index][dest_index] = sync_timestamp;

 

                            // 查找最早的“最后更新时间戳”。

                            if (min_synced_timestamp == 0)

                            {

                                   min_synced_timestamp = sync_timestamp;

                            }

                            else if (sync_timestamp < min_synced_timestamp)

                            {

                                   min_synced_timestamp = sync_timestamp;

                            }

                     }

 

                     // 把最早的“最后更新时间戳”作为“最后的更新时间戳”。这意味着该storage保存了组内早于这个时间的所有文件。

                     if (min_synced_timestamp > 0)

                     {

                            pClientInfo->pStorage->stat.last_synced_timestamp = \

                                                    min_synced_timestamp;

                     }

              }

              else

              { // 在指定源、权重上传模式

                     int max_synced_timestamp;

 

                     max_synced_timestamp = pClientInfo->pStorage->stat.\

                                             last_synced_timestamp;

                     pEnd = pTask->data + pTask->length;

                     for (p=pTask->data + sizeof(TrackerHeader); p<pEnd; \

                            p += (FDFS_STORAGE_ID_MAX_SIZE + 4))

                     {

                            // 读取上报信息src_id和sync_timestamp

                            sync_timestamp = buff2int(p + FDFS_STORAGE_ID_MAX_SIZE);

                            if (sync_timestamp <= 0)

                            {

                                   continue;

                            }

 

                            src_id = p;

                            *(src_id + (FDFS_STORAGE_ID_MAX_SIZE - 1)) = '\0';

                            // 获取src_id指向的storage

                            pSrcStorage = tracker_mem_get_storage( \

                                          pClientInfo->pGroup, src_id);

                            if (pSrcStorage == NULL)

                            {

                                   continue;

                            }

                            if (pSrcStorage->status != FDFS_STORAGE_STATUS_ACTIVE)

                            {

                                   continue;

                            }

 

                            // 获取src_id的storage的组内index

                            src_index = tracker_mem_get_storage_index( \

                                          pClientInfo->pGroup, pSrcStorage);

                            if (src_index == dest_index || src_index < 0 || \

                                          src_index >= pClientInfo->pGroup->count)

                            {

                                   continue;

                            }

 

                            // 更新同步时间戳sync_timestamp

                            pClientInfo->pGroup->last_sync_timestamps \

                                   [src_index][dest_index] = sync_timestamp;

 

                            // 查找最后同步时间

                            if (sync_timestamp > max_synced_timestamp)

                            {

                                   max_synced_timestamp = sync_timestamp;

                            }

                     }

 

                     // 更新最后同步时间

                     pClientInfo->pStorage->stat.last_synced_timestamp = \

                                                        max_synced_timestamp;

              }

 

              // 信息保存到文件

              if (++g_storage_sync_time_chg_count % \

                            TRACKER_SYNC_TO_FILE_FREQ == 0)

              {

                     status = tracker_save_sync_timestamps();

              }

              else

              {

                     status = 0;

              }

       } while (0);

 

       // 返回同步信息

       return tracker_check_and_sync(pTask, status);

}

3.6 tracker_deal_storage_df_report函数

根据tracker_deal_task其中代码:

case TRACKER_PROTO_CMD_STORAGE_REPORT_DISK_USAGE:

       TRACKER_CHECK_LOGINED(pTask)

       result = tracker_deal_storage_df_report(pTask);

break;

storage中上报磁盘信息tracker_report_df_stat函数发送的命令:TRACKER_PROTO_CMD_STORAGE_REPORT_DISK_USAGE,由tracker_deal_storage_df_report函数处理。

 

tracker/tracker_service.c

static int tracker_deal_storage_df_report(struct fast_task_info *pTask)

{

       int nPkgLen;

       int i;

       TrackerStatReportReqBody *pStatBuff;

       int64_t *path_total_mbs;

       int64_t *path_free_mbs;

       int64_t old_free_mb;

       TrackerClientInfo *pClientInfo;

      

       // 获取client信息

       pClientInfo = (TrackerClientInfo *)pTask->arg;

       if (pClientInfo->pGroup == NULL || pClientInfo->pStorage == NULL)

       {

              logError("file: "__FILE__", line: %d, " \

                     "cmd=%d, client ip: %s, not join in!", \

                     __LINE__, TRACKER_PROTO_CMD_STORAGE_REPORT_DISK_USAGE, \

                     pTask->client_ip);

              pTask->length = sizeof(TrackerHeader);

              return EINVAL;

       }

 

       // 判断包长度正确性

       nPkgLen = pTask->length - sizeof(TrackerHeader);

       if (nPkgLen != sizeof(TrackerStatReportReqBody) * \

                     pClientInfo->pGroup->store_path_count)

       {

              logError("file: "__FILE__", line: %d, " \

                     "cmd=%d, client ip: %s, package size " \

                     PKG_LEN_PRINTF_FORMAT" is not correct, " \

                     "expect length: %d", __LINE__, \

                     TRACKER_PROTO_CMD_STORAGE_REPORT_DISK_USAGE, \

                     pTask->client_ip, nPkgLen, \

                     (int)sizeof(TrackerStatReportReqBody) * \

                     pClientInfo->pGroup->store_path_count);

              pTask->length = sizeof(TrackerHeader);

              return EINVAL;

       }

 

       // 更新组存储、挂载点存储信息,剩余空间和总空间

       old_free_mb = pClientInfo->pStorage->free_mb;

       path_total_mbs = pClientInfo->pStorage->path_total_mbs;

       path_free_mbs = pClientInfo->pStorage->path_free_mbs;

       pClientInfo->pStorage->total_mb = 0;

       pClientInfo->pStorage->free_mb = 0;

 

       pStatBuff = (TrackerStatReportReqBody *)(pTask->data + sizeof(TrackerHeader));

       for (i=0; i<pClientInfo->pGroup->store_path_count; i++)

       {

              // pxxian: renew the store_path memory message

              path_total_mbs[i] = buff2long(pStatBuff->sz_total_mb);

              path_free_mbs[i] = buff2long(pStatBuff->sz_free_mb);

 

              pClientInfo->pStorage->total_mb += path_total_mbs[i];

              pClientInfo->pStorage->free_mb += path_free_mbs[i];

 

              if (g_groups.store_path == FDFS_STORE_PATH_LOAD_BALANCE

                            && path_free_mbs[i] > path_free_mbs[ \

                            pClientInfo->pStorage->current_write_path])

              {

                     pClientInfo->pStorage->current_write_path = i;

              }

 

              pStatBuff++;

       }

 

       // 更新组剩余空间,为组内各storage中最小的

       if ((pClientInfo->pGroup->free_mb == 0) ||

              (pClientInfo->pStorage->free_mb < pClientInfo->pGroup->free_mb))

       {

              pClientInfo->pGroup->total_mb = pClientInfo->pStorage->total_mb;

              pClientInfo->pGroup->free_mb = pClientInfo->pStorage->free_mb;

       }

       else if (pClientInfo->pStorage->free_mb > old_free_mb)

       {

              tracker_find_min_free_space(pClientInfo->pGroup);

       }

 

       // 查找剩余空间最大的组,把写入指向标志更新指向该组

       tracker_find_max_free_space_group();

 

       /*

       //logInfo("storage: %s:%d, total_mb=%dMB, free_mb=%dMB\n", \

              pClientInfo->pStorage->ip_addr, \

              pClientInfo->pGroup->storage_port, \

              pClientInfo->pStorage->total_mb, \

              pClientInfo->pStorage->free_mb);

       */

 

       // 把该storage标志为active

       tracker_mem_active_store_server(pClientInfo->pGroup, \

                            pClientInfo->pStorage);

 

       // 返回同步信息

       return tracker_check_and_sync(pTask, 0);

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值