FastDFS源码阅读笔记(二)

本文为FastDFS源码阅读笔记的第二部分,主要探讨了storage_service.c中的存储服务实现和tracker_client_thread.c中追踪客户端线程的交互机制,详细剖析了文件上传下载及服务器间的通信流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

().storage_service.c

//上传文件完成后的回调函数

static void storage_upload_file_done_callback(struct fast_task_info *pTask,const int err_no)

{

    StorageClientInfo *pClientInfo;

    StorageFileContext *pFileContext;

    TrackerHeader *pHeader;

    int result;

    pClientInfo = (StorageClientInfo *)pTask->arg;

    pFileContext =  &(pClientInfo->file_context);

    if (err_no == 0)

    {

        //检查文件是否写重复,然后在修改文件名

        result = storage_service_upload_file_done(pTask);

        if (result == 0)

        {

            if (pFileContext->create_flag & STORAGE_CREATE_FLAG_FILE)

            {

                result = storage_binlog_write(/

                    pFileContext->timestamp2log, /

                    STORAGE_OP_TYPE_SOURCE_CREATE_FILE, /

                    pFileContext->fname2log);

            }

        }

    }

    else

    {

        result = err_no;

    }

 

    if (result == 0)

    {

        int filename_len;

        char *p;

 

        if (pFileContext->create_flag & STORAGE_CREATE_FLAG_FILE)

        {

            //total_upload_count,success_upload_count自增加

            CHECK_AND_WRITE_TO_STAT_FILE3( /

                g_storage_stat.total_upload_count, /

                g_storage_stat.success_upload_count, /

                g_storage_stat.last_source_update)

        }

        //组返回包,返回组名,文件名

        filename_len = strlen(pFileContext->fname2log);

        //重新设置了返回包的总长度

        pClientInfo->total_length = sizeof(TrackerHeader) + FDFS_GROUP_NAME_MAX_LEN + filename_len;

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

        memcpy(p, g_group_name, FDFS_GROUP_NAME_MAX_LEN);

        p += FDFS_GROUP_NAME_MAX_LEN;

        memcpy(p, pFileContext->fname2log, filename_len);

    }

    else

    {

        pthread_mutex_lock(&stat_count_thread_lock);

        if (pFileContext->create_flag & STORAGE_CREATE_FLAG_FILE)

        {

            g_storage_stat.total_upload_count++;  //否则如果上传失败,上传总数加

        }

        pthread_mutex_unlock(&stat_count_thread_lock);

        pClientInfo->total_length = sizeof(TrackerHeader);

    }

    pClientInfo->total_offset = 0;  //total_offset被重新设置为

    pTask->length = pClientInfo->total_length;

    pHeader = (TrackerHeader *)pTask->data;

    pHeader->status = result;

    pHeader->cmd = STORAGE_PROTO_CMD_RESP;

    long2buff(pClientInfo->total_length - sizeof(TrackerHeader),pHeader->pkg_len);

    //在次触发事件void storage_recv_notify_read()而在接收最后一个包时pClientInfo->stage = FDFS_STORAGE_STAGE_NIO_SEND

    //已经更改了这个状态值,因此在该函数里面,直接去调用storage_send_add_event(pTask)函数,发送响应包

    storage_nio_notify(pTask); 

}

 

//数据服务器服务初始化

int storage_service_init()

{

    int result;

    struct storage_nio_thread_data *pThreadData;

    struct storage_nio_thread_data *pDataEnd;

    pthread_t tid;

    pthread_attr_t thread_attr;

 

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

    {

        return result;

    }

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

    {

        return result;

    }

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

    {

        return result;

    }

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

    {

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

            "init_pthread_attr fail, program exit!", __LINE__);

        return result;

    }

    //StorageClientInfo参数所以说在任务Task结构里面用void * 参数来代替

    //g_buff_size缺省是K

    if ((result=free_queue_init(g_max_connections, g_buff_size, /

        g_buff_size, sizeof(StorageClientInfo))) != 0) 

    {

        return result;

    }

    //分配工作线程空间

    //需要注意的是socket工作线程跟磁盘io线程的是分开的

    g_nio_thread_data = (struct storage_nio_thread_data *)malloc(sizeof( /

    struct storage_nio_thread_data) * g_work_threads);

    if (g_nio_thread_data == NULL)

    {

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

            "malloc %d bytes fail, errno: %d, error info: %s", /

            __LINE__, (int)sizeof(struct storage_nio_thread_data) * /

            g_work_threads, errno, strerror(errno));

        return errno != 0 ? errno : ENOMEM;

    }

    g_storage_thread_count = 0;

    pDataEnd = g_nio_thread_data + g_work_threads;

    for (pThreadData=g_nio_thread_data; pThreadData<pDataEnd; pThreadData++)

    {

        pThreadData->ev_base = event_base_new();

        if (pThreadData->ev_base == NULL)

        {

            result = errno != 0 ? errno : ENOMEM;

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

                "event_base_new fail.", __LINE__);

            return result;

        }

        if (pipe(pThreadData->pipe_fds) != 0)

        {

            result = errno != 0 ? errno : EPERM;

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

                "call pipe fail, " /

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

                __LINE__, result, strerror(result));

            break;

        }

        if ((result=set_nonblock(pThreadData->pipe_fds[0])) != 0)

        {

            break;

        }

        //创建线程

        if ((result=pthread_create(&tid, &thread_attr,work_thread_entrance, pThreadData)) != 0)

        {

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

                "create thread failed, startup threads: %d, " /

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

                __LINE__, g_storage_thread_count, /

                result, strerror(result));

            break;

        }

        else

        {

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

            {

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

                    "call pthread_mutex_lock fail, " /

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

                    __LINE__, result, strerror(result));

            }

            g_storage_thread_count++;

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

            {

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

                    "call pthread_mutex_lock fail, " /

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

                    __LINE__, result, strerror(result));

            }

        }

    }

    pthread_attr_destroy(&thread_attr);

    last_stat_change_count = g_stat_change_count;

    return result;

}

 

//数据服务器作为客户端监听socket请求

//具体的实现流程是:

//1.创建工作线程,每个在工作线程里面,绑定socket读写事件

//2.数据服务器服务端监听客户端请求,接收到请求后,从任务队列表取一个任务(从头部取),然后

//  pClientInfo->stage = FDFS_STORAGE_STAGE_NIO_INIT;

//  pClientInfo->nio_thread_index = pClientInfo->sock % g_work_threads;//工作线程取余数

//  pThreadData = g_nio_thread_data + pClientInfo->nio_thread_index;   //确定是哪一个工作线程

//  write(pThreadData->pipe_fds[1], &task_addr, sizeof(task_addr))     //向那一个工作线程写入事件(其实是写的任务)

//3.然后触发socket读的事件,注意读的也是Task任务

void storage_accept_loop(int server_sock)

{

    int incomesock;

    struct sockaddr_in inaddr;

    unsigned int sockaddr_len;

    in_addr_t client_addr;

    char szClientIp[IP_ADDRESS_SIZE];

    long task_addr;

    struct fast_task_info *pTask;

    StorageClientInfo *pClientInfo;

    struct storage_nio_thread_data *pThreadData;

    while (g_continue_flag)

    {

        sockaddr_len = sizeof(inaddr);

        incomesock = accept(server_sock, (struct sockaddr*)&inaddr, /

            &sockaddr_len);

        if (incomesock < 0) //error

        {

            if (!(errno == EINTR || errno == EAGAIN))

            {

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

                    "accept failed, " /

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

                    __LINE__, errno, strerror(errno));

            }

 

            continue;

        }

        client_addr = getPeerIpaddr(incomesock, szClientIp, IP_ADDRESS_SIZE);

        //判断是否允许在可连接的地址列表里面

        if (g_allow_ip_count >= 0)

        {

            if (bsearch(&client_addr, g_allow_ip_addrs, /

                g_allow_ip_count, sizeof(in_addr_t), /

                cmp_by_ip_addr_t) == NULL)

            {

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

                    "ip addr %s is not allowed to access", /

                    __LINE__, szClientIp);

 

                close(incomesock);

                continue;

            }

        }

 

        if (tcpsetnonblockopt(incomesock) != 0)

        {

            close(incomesock);

            continue;

        }

        pTask = free_queue_pop();

        if (pTask == NULL)

        {

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

                "malloc task buff failed", /

                __LINE__);

            close(incomesock);

            continue;

        }

        //在这里对pTask->arg的参数进行了赋值

        pClientInfo = (StorageClientInfo *)pTask->arg;

        pClientInfo->sock = incomesock;

        pClientInfo->stage = FDFS_STORAGE_STAGE_NIO_INIT;

        pClientInfo->nio_thread_index = pClientInfo->sock % g_work_threads;//工作线程取余数:一个nio,一个dio

        pThreadData = g_nio_thread_data + pClientInfo->nio_thread_index;

        strcpy(pTask->client_ip, szClientIp);

        strcpy(pClientInfo->tracker_client_ip, szClientIp);

        //使用的这种方法

        task_addr = (long)pTask;

        if (write(pThreadData->pipe_fds[1], &task_addr, /

            sizeof(task_addr)) != sizeof(task_addr))

        {

            close(incomesock);

            free_queue_push(pTask);

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

                "call write failed, " /

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

                __LINE__, errno, strerror(errno));

        }

    }

}

 

void storage_nio_notify(struct fast_task_info *pTask)

{

    StorageClientInfo *pClientInfo;

    struct storage_nio_thread_data *pThreadData;

    long task_addr;

    pClientInfo = (StorageClientInfo *)pTask->arg;

    //去取工作线程,在写入客户端socket

    pThreadData = g_nio_thread_data + pClientInfo->nio_thread_index;

    task_addr = (long)pTask;

    if (write(pThreadData->pipe_fds[1], &task_addr, /

        sizeof(task_addr)) != sizeof(task_addr))

    {

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

            "call write failed, " /

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

            __LINE__, errno, strerror(errno));

        task_finish_clean_up(pTask);

    }

}

 

//工作线程入口

static void *work_thread_entrance(void* arg)

{

    int result;

    struct storage_nio_thread_data *pThreadData;

    struct event ev_notify;

 

    pThreadData = (struct storage_nio_thread_data *)arg;

    //暂时先不考虑是否检查文件是否重复

    if (g_check_file_duplicate)

    {

        if ((result=fdht_copy_group_array(&(pThreadData->group_array),/

            &g_group_array)) != 0)

        {

            pthread_mutex_lock(&g_storage_thread_lock);

            g_storage_thread_count--;

            pthread_mutex_unlock(&g_storage_thread_lock);

            return NULL;

        }

    }

    do

    {

        event_set(&ev_notify, pThreadData->pipe_fds[0], /

            EV_READ | EV_PERSIST, storage_recv_notify_read, NULL);

        if ((result=event_base_set(pThreadData->ev_base, &ev_notify)) != 0)

        {

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

                "event_base_set fail.", __LINE__);

            break;

        }

        if ((result=event_add(&ev_notify, NULL)) != 0)

        {

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

                "event_add fail.", __LINE__);

            break;

        }

        //调用libevent库实现socket读写

        while (g_continue_flag)

        {

            event_base_loop(pThreadData->ev_base, 0);

        }

    } while (0);

 

    event_base_free(pThreadData->ev_base);

 

    if (g_check_file_duplicate)

    {

        if (g_keep_alive)

        {

            fdht_disconnect_all_servers(&(pThreadData->group_array));

        }

 

        fdht_free_group_array(&(pThreadData->group_array));

    }

 

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

    {

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

            "call pthread_mutex_lock fail, " /

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

            __LINE__, result, strerror(result));

    }

    g_storage_thread_count--;

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

    {

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

            "call pthread_mutex_lock fail, " /

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

            __LINE__, result, strerror(result));

    }

 

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

        "nio thread exited, thread count: %d", /

        __LINE__, g_storage_thread_count);

 

    return NULL;

}

 

//发送的时候,先发送包头,接收的时候也是这样,在发包体,服务端也在次来接收包体

static int storage_upload_file(struct fast_task_info *pTask)

{

    StorageClientInfo *pClientInfo;

    StorageFileContext *pFileContext;

    char *p;

    char filename[128];

    char file_ext_name[FDFS_FILE_PREFIX_MAX_LEN + 1];

    int64_t nInPackLen;

    int64_t file_bytes;

    int store_path_index;

    int result;

    int filename_len;

    pClientInfo = (StorageClientInfo *)pTask->arg;

    pFileContext =  &(pClientInfo->file_context);

    nInPackLen = pClientInfo->total_length - sizeof(TrackerHeader);

 

    if (nInPackLen < 1 + FDFS_PROTO_PKG_LEN_SIZE + FDFS_FILE_EXT_NAME_MAX_LEN)

    {

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

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

            INT64_PRINTF_FORMAT" is not correct, " /

            "expect length >= %d", __LINE__, /

            STORAGE_PROTO_CMD_UPLOAD_FILE, /

            pTask->client_ip,  nInPackLen, /

            1 + FDFS_PROTO_PKG_LEN_SIZE + /

            FDFS_FILE_EXT_NAME_MAX_LEN);

        pClientInfo->total_length = sizeof(TrackerHeader);

        return EINVAL;

    }

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

    //首先取目录存储路径索引下标

    store_path_index = *p++;

    if (store_path_index < 0 || store_path_index >= g_path_count)

    {

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

            "client ip: %s, store_path_index: %d " /

            "is invalid", __LINE__, /

            pTask->client_ip, store_path_index);

        pClientInfo->total_length = sizeof(TrackerHeader);

        return EINVAL;

    }

    //再取文件长度(注释是整个的长度)

    file_bytes = buff2long(p);

    p += FDFS_PROTO_PKG_LEN_SIZE;

    if (file_bytes < 0 || file_bytes != nInPackLen - /

        (1 + FDFS_PROTO_PKG_LEN_SIZE + /

        FDFS_FILE_EXT_NAME_MAX_LEN))

    {

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

            "client ip: %s, pkg length is not correct, " /

            "invalid file bytes: "INT64_PRINTF_FORMAT /

            ", total body length: "INT64_PRINTF_FORMAT, /

            __LINE__, pTask->client_ip, file_bytes, nInPackLen);

        pClientInfo->total_length = sizeof(TrackerHeader);

        return EINVAL;

    }

    memcpy(file_ext_name, p, FDFS_FILE_EXT_NAME_MAX_LEN);

    *(file_ext_name + FDFS_FILE_EXT_NAME_MAX_LEN) = '/0';

    p += FDFS_FILE_EXT_NAME_MAX_LEN;

    pFileContext->calc_file_hash = g_check_file_duplicate;

    pFileContext->extra_info.upload.gen_filename = true;  //默认生成文件名

    pFileContext->extra_info.upload.start_time = time(NULL);

    *filename = '/0';

    filename_len = 0;

    if ((result=storage_get_filename(pClientInfo, /

        pFileContext->extra_info.upload.start_time, /

        store_path_index, file_bytes, file_ext_name, filename, /

        &filename_len, pFileContext->filename)) != 0)

    {

        pClientInfo->total_length = sizeof(TrackerHeader);

        return result;

    }

    sprintf(pFileContext->fname2log, "%c"STORAGE_DATA_DIR_FORMAT"/%s",FDFS_STORAGE_STORE_PATH_PREFIX_CHAR, store_path_index, filename);

    strcpy(pFileContext->extra_info.upload.file_ext_name, file_ext_name);

    pFileContext->sync_flag = STORAGE_OP_TYPE_SOURCE_CREATE_FILE;

    pFileContext->timestamp2log = pFileContext->extra_info.upload.start_time;

    pFileContext->extra_info.upload.store_path_index = store_path_index;

    pFileContext->op = FDFS_STORAGE_FILE_OP_WRITE;  //写文件

    //参数:任务指针,0 文件偏移量;file_bytes:文件的字节数p - pTask->data:相对于pTask->data的偏移量

    return storage_write_to_file(pTask, 0, file_bytes, p - pTask->data,storage_upload_file_done_callback, store_path_index);

}

 

//从数据服务器上下载文件

static int storage_server_download_file(struct fast_task_info *pTask)

{

    StorageClientInfo *pClientInfo;

    StorageFileContext *pFileContext;

    char *p;

    int result;

    int store_path_index;

    char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];

    char true_filename[128];

    char *filename;

    int filename_len;

    int64_t file_offset;

    int64_t download_bytes;

    int64_t file_bytes;

    struct stat stat_buf;

    int64_t nInPackLen;

    pClientInfo = (StorageClientInfo *)pTask->arg;

    pFileContext =  &(pClientInfo->file_context);

    //实际上在接收包的过程中,设置了pClientInfo->total_length=pClientInfo->total_length+sizeof(TrackerHeader)

    //因此这里在重新减回去

    nInPackLen = pClientInfo->total_length - sizeof(TrackerHeader);

    pClientInfo->total_length = sizeof(TrackerHeader);

    if (nInPackLen <= 16 + FDFS_GROUP_NAME_MAX_LEN)

    {

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

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

            INT64_PRINTF_FORMAT" is not correct, " /

            "expect length > %d", __LINE__, /

            STORAGE_PROTO_CMD_UPLOAD_FILE, /

            pTask->client_ip,  /

            nInPackLen, 16 + FDFS_GROUP_NAME_MAX_LEN);

        return EINVAL;

    }

    if (nInPackLen >= pTask->size)

    {

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

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

            INT64_PRINTF_FORMAT" is too large, " /

            "expect length should < %d", __LINE__, /

            STORAGE_PROTO_CMD_UPLOAD_FILE, /

            pTask->client_ip,  /

            nInPackLen, pTask->size);

        return EINVAL;

    }

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

    //文件偏移量:下载传来的请求包里面值是

    file_offset = buff2long(p); 

    p += FDFS_PROTO_PKG_LEN_SIZE;

    download_bytes = buff2long(p); //需要下载的字节数

    p += FDFS_PROTO_PKG_LEN_SIZE;

    if (file_offset < 0)

    {

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

            "client ip:%s, invalid file offset: " /

            INT64_PRINTF_FORMAT,  __LINE__, /

            pTask->client_ip, file_offset);

        return EINVAL;

    }

    if (download_bytes < 0)

    {

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

            "client ip:%s, invalid download file bytes: " /

            INT64_PRINTF_FORMAT,  __LINE__, /

            pTask->client_ip, download_bytes);

        return EINVAL;

    }

    memcpy(group_name, p, FDFS_GROUP_NAME_MAX_LEN);

    *(group_name + FDFS_GROUP_NAME_MAX_LEN) = '/0';

    p += FDFS_GROUP_NAME_MAX_LEN;

    if (strcmp(group_name, g_group_name) != 0)

    {

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

            "client ip:%s, group_name: %s " /

            "not correct, should be: %s", /

            __LINE__, pTask->client_ip, /

            group_name, g_group_name);

        return EINVAL;

    }

    filename = p;

    filename_len = nInPackLen - (16 + FDFS_GROUP_NAME_MAX_LEN);

    *(filename + filename_len) = '/0';

    //拆分文件名,确定store_path_index磁盘目录索引值

    if ((result=storage_split_filename_ex(filename, /

        &filename_len, true_filename, &store_path_index)) != 0)

    {

        return result;

    }

    if ((result=fdfs_check_data_filename(true_filename, filename_len)) != 0)

    {

        return result;

    }

    //在这里就直接确定了磁盘的目录名

    sprintf(pFileContext->filename, "%s/data/%s",g_store_paths[store_path_index], true_filename);

    if (stat(pFileContext->filename, &stat_buf) == 0)

    {

        if (!S_ISREG(stat_buf.st_mode))

        {

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

                "%s is not a regular file", /

                __LINE__, pFileContext->filename);

            return EISDIR;

        }

        file_bytes = stat_buf.st_size;

    }

    else

    {

        file_bytes = 0;

        result = errno != 0 ? errno : ENOENT;

 

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

            "call stat fail, file: %s, "/

            "error no: %d, error info: %s", /

            __LINE__, pFileContext->filename, /

            result, strerror(result));

        return result;

    }

    //请求下载文件发来的包里面,下载字节数填写的是download_bytes=0,那么下载的字节数就是文件本身的字节大小

    //并且文件偏移量file_offset=0

    if (download_bytes == 0)

    {

        download_bytes  = file_bytes - file_offset;

    }

    else if (download_bytes > file_bytes - file_offset)

    {

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

            "client ip:%s, invalid download file bytes: " /

            INT64_PRINTF_FORMAT" > file remain bytes: " /

            INT64_PRINTF_FORMAT,  __LINE__, /

            pTask->client_ip, download_bytes, /

            file_bytes - file_offset);

        return EINVAL;

    }

    return storage_read_from_file(pTask, file_offset,download_bytes,storage_download_file_done_callback, store_path_index);

}

 

//从数据服务器读取文件

static int storage_read_from_file(struct fast_task_info *pTask, /

                                  const int64_t file_offset, const int64_t download_bytes, /

                                  FileDealDoneCallback done_callback, /

                                  const int store_path_index)

{

    StorageClientInfo *pClientInfo;

    StorageFileContext *pFileContext;

    TrackerHeader *pHeader;

    int result;

    pClientInfo = (StorageClientInfo *)pTask->arg;

    pFileContext =  &(pClientInfo->file_context);

    pClientInfo->deal_func = dio_deal_task;

    //在这里重新设置总的长度

    pClientInfo->total_length = sizeof(TrackerHeader) + download_bytes; 

    pClientInfo->total_offset = 0;

    pFileContext->fd = -1;

    pFileContext->op = FDFS_STORAGE_FILE_OP_READ;

    pFileContext->offset = file_offset;

    pFileContext->start = file_offset;

    pFileContext->end = file_offset + download_bytes;

    //获得磁盘ip读写的线程索引下标,从而确定是由哪个线程取进行读写的操作

    pFileContext->dio_thread_index = storage_dio_get_thread_index(pTask, store_path_index, pFileContext->op);

    pFileContext->done_callback = done_callback;

    pTask->length = sizeof(TrackerHeader); //任务的数据长度重新进行了设置

    pHeader = (TrackerHeader *)pTask->data;

    pHeader->status = 0;

    pHeader->cmd = STORAGE_PROTO_CMD_RESP;

    long2buff(download_bytes, pHeader->pkg_len);

    //这里连同包头+单片数据文件的包体一起进行了如磁盘线程的处理队列中

    //客户端在接收时可以先指定接收包头,然后在接收后面的包体数据

    if ((result=storage_dio_queue_push(pTask)) != 0)

    {

        pClientInfo->total_length = sizeof(TrackerHeader);

        return result;

    }

    return STORAGE_STATUE_DEAL_FILE;

}

 

//数据服务器处理写文件

static int storage_write_to_file(struct fast_task_info *pTask, /

                                 const int64_t file_offset, const int64_t upload_bytes, /

                                 const int buff_offset, FileDealDoneCallback done_callback, /

                                 const int store_path_index)

{

    StorageClientInfo *pClientInfo;

    StorageFileContext *pFileContext;

    int result;

    pClientInfo = (StorageClientInfo *)pTask->arg;

    pFileContext =  &(pClientInfo->file_context);

    pClientInfo->deal_func = dio_deal_task;  //处理任务函数指针

    pFileContext->fd = -1;

    pFileContext->buff_offset = buff_offset;

    pFileContext->offset = file_offset;

    pFileContext->start = file_offset;

    pFileContext->end = file_offset + upload_bytes;

    //获得磁盘读写的线程

    pFileContext->dio_thread_index = storage_dio_get_thread_index(pTask, store_path_index, pFileContext->op); 

    pFileContext->done_callback = done_callback;  //处理完成的回调函数

    if (pFileContext->calc_file_hash)

    {

        INIT_HASH_CODES4(pFileContext->file_hash_codes)

    }

    //插入到磁盘处理队列中,而磁盘处理线程调用dio_thread_entrance()不断来处理队列里面的任务元素

    if ((result=storage_dio_queue_push(pTask)) != 0)

    {

        pClientInfo->total_length = sizeof(TrackerHeader);

        return result;

    }

 

    return STORAGE_STATUE_DEAL_FILE;

}

 

 ().tracker_client_thread.c

//与跟踪服务器的报告线程

static void *tracker_report_thread_entrance(void *arg)

{

    TrackerServerInfo *pTrackerServer;

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

    int previousCode;

    int nContinuousFail;

    int tracker_index;

    bool bServerPortChanged;

    //判断数据服务器的端口是否改变

    bServerPortChanged = (g_last_server_port != 0) &&(g_server_port != g_last_server_port);

    stat_chg_sync_count = 0;

    pTrackerServer = (TrackerServerInfo *)arg;

    pTrackerServer->sock = -1;

    //获得跟踪的下标

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

    //初始时g_sync_old_done=false

    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)

    {

        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;

            }

        }

        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;

        //初始g_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;

        }

        //因为要连接多个跟踪服务器,每连接一个都会产生一个tracker_client_ip

        //因此插入这个g_local_host_ip_addrs 大串里面

        insert_into_local_host_ip(tracker_client_ip);

        //向每一个跟踪服务器发起加入的请求

        if (tracker_report_join(pTrackerServer, tracker_index, sync_old_done) != 0)

        {

            sleep(g_heart_beat_interval);

            continue;

        }

 

        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)

        {

            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;

            }

            //初始g_sync_old_done=false,如果旧的同步操作没有完成

            if (!g_sync_old_done)

            {

                //获得向该storage server同步已有数据文件的源服务器请求

                if (tracker_sync_dest_req(pTrackerServer) == 0)

                {

                    g_sync_old_done = true;  //获得源服务器请求完成后,旧的同步设为标记true

                    //在写入同步状态的文件中

                    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

            {

                //如果已经获得了源数据服务器,那么这里向发出跟踪服务器发起同步的请求

                if (tracker_sync_notify(pTrackerServer) != 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;  //旧的同步设为标记true

        }

        //获得源数据服务器的状态

        src_storage_status[tracker_index] = tracker_sync_notify(pTrackerServer);

        if (src_storage_status[tracker_index] != 0)

        {

            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_status(&g_tracker_group,

                    g_group_name, g_tracker_client_ip,

                    &my_status) == 0)

                {

                    tracker_sync_dest_query(pTrackerServer);

                    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;

        while (g_continue_flag)

        {

            current_time = time(NULL);

            //比较心跳的时间间隔

            if (current_time - last_beat_time >= g_heart_beat_interval)

            {

                //发送心跳

                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)

            {

                //向跟踪服务器报告同步时间戳

                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)

            {

                if (tracker_report_df_stat(pTrackerServer,&bServerPortChanged) != 0)

                {

                    break;

                }

 

                last_df_report_time = current_time;

            }

            sleep(1);

        }

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

        {

        }

        close(pTrackerServer->sock);

        pTrackerServer->sock = -1;

        if (g_continue_flag)

        {

            sleep(1);

        }

    }

    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;

}

 

//合并数据服务器:server_count参数:返回的数据服务器个数

static int tracker_merge_servers(TrackerServerInfo *pTrackerServer,FDFSStorageBrief *briefServers, const int server_count)

{

    FDFSStorageBrief *pServer;

    FDFSStorageBrief *pEnd;

    FDFSStorageServer *pInsertedServer;

    FDFSStorageServer **ppFound;

    FDFSStorageServer **ppGlobalServer;

    FDFSStorageServer **ppGlobalEnd;

    FDFSStorageServer targetServer;

    FDFSStorageServer *pTargetServer;

    FDFSStorageBrief diffServers[FDFS_MAX_SERVERS_EACH_GROUP];

    FDFSStorageBrief *pDiffServer;

    int res;

    int result;

    int nDeletedCount;

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

    //pTargetServer指向它

    pTargetServer = &targetServer;

    nDeletedCount = 0;

    pDiffServer = diffServers;  //指向了指针数组

    pEnd = briefServers + server_count;

    //storage server有个状态,如下:

    //FDFS_STORAGE_STATUS_INIT       0:初始化,尚未得到同步已有数据的源服务器

    //FDFS_STORAGE_STATUS_WAIT_SYNC  1:等待同步,已得到同步已有数据的源服务器

    //FDFS_STORAGE_STATUS_SYNCING    2:同步中

    //FDFS_STORAGE_STATUS_DELETED    3:已删除,该服务器从本组中摘除(注:本状态的功能尚未实现)

    //FDFS_STORAGE_STATUS_OFFLINE    4:离线

    //FDFS_STORAGE_STATUS_ONLINE     5:在线,尚不能提供服务

    //FDFS_STORAGE_STATUS_ACTIVE     6:在线,可以提供服务

    //FDFS_STORAGE_STATUS_NONE      99

    //storage server的状态为FDFS_STORAGE_STATUS_ONLINE时,当该storage servertracker server发起一次heart beat,

    //tracker server将其状态更改为FDFS_STORAGE_STATUS_ACTIVE

    //组内新增加一台storage server A时,由系统自动完成已有数据同步,处理逻辑如下:

    //1.storage server A连接tracker servertracker serverstorage server A的状态设置为FDFS_STORAGE_STATUS_INITstorage server

    //  A询问追加同步的源服务器和追加同步截至时间点,如果该组内只有storage serverA或该组内已成功上传的文件数为,则没有数据需要同步,

    //  storage server A就可以提供在线服务,此时tracker将其状态设置为FDFS_STORAGE_STATUS_ONLINE,否则tracker server将其状态设置为

    //  FDFS_STORAGE_STATUS_WAIT_SYNC,进入第二步的处理;

    //2.假设tracker server分配向storage server A同步已有数据的源storage serverB。同组的storage servertracker server通讯得知新

    //  增了storage server A,将启动同步线程,并向tracker server询问向storage server A追加同步的源服务器和截至时间点。storage server

    //  B将把截至时间点之前的所有数据同步给storage server A;而其余的storage server从截至时间点之后进行正常同步,只把源头数据同步

    //  storage server A。到了截至时间点之后,storage server Bstorage server A的同步将由追加同步切换为正常同步,只同步源头数据;

    //3.storage server Bstorage server A同步完所有数据,暂时没有数据要同步时,storage server B请求tracker serverstorage server A

    //  状态设置为FDFS_STORAGE_STATUS_ONLINE

    //4.storage server Atracker server发起heart beat时,tracker server将其状态更改为FDFS_STORAGE_STATUS_ACTIVE

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

    {

        //拷贝targetServer.server

        memcpy(&(targetServer.server),pServer,sizeof(FDFSStorageBrief));

        ppFound = (FDFSStorageServer **)bsearch(&pTargetServer,g_sorted_storages, g_storage_count,sizeof(FDFSStorageServer *),storage_cmp_by_ip_addr);

        //从排序的g_sorted_storages数据服务器列表进行查找

        if (ppFound != NULL)

        {

            //logInfo("ip_addr=%s, local status: %d, tracker status: %d", pServer->ip_addr, (*ppFound)->server.status, pServer->status);

            //如果状态一致,不作处理

            if ((*ppFound)->server.status == pServer->status)

            {

                continue;

            }

            //如果返回的是离线的状态

            if (pServer->status == FDFS_STORAGE_STATUS_OFFLINE) 

            {

                //与本地的状态进行比较

                if ((*ppFound)->server.status == FDFS_STORAGE_STATUS_ACTIVE|| (*ppFound)->server.status == FDFS_STORAGE_STATUS_ONLINE)

                {

                    //更新自己为离线的状态

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

                }

                else if ((*ppFound)->server.status != FDFS_STORAGE_STATUS_NONE&& (*ppFound)->server.status != FDFS_STORAGE_STATUS_INIT)

                {

                    //将不同的数据服务器的状态进行拷贝

                    memcpy(pDiffServer++,&((*ppFound)->server),sizeof(FDFSStorageBrief));

                }

            }

            else if ((*ppFound)->server.status == FDFS_STORAGE_STATUS_OFFLINE)

            {

                //如果本地是离线的状态,并且返回的状态不是离线状态,那么用新的返回的状态进行更新

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

            }

            else if ((*ppFound)->server.status == FDFS_STORAGE_STATUS_NONE)  //如果本地是未知的状态

            {

                if (pServer->status == FDFS_STORAGE_STATUS_DELETED || pServer->status == FDFS_STORAGE_STATUS_IP_CHANGED)

                { //ignore

                }

                else

                {

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

                    //如果本地是未知的状态,并且返回的不是删除状态,那么启动同步线程

                    if ((result=storage_sync_thread_start(&((*ppFound)->server))) != 0)

                    {

                        return result;

                    }

                }

            }

            else if (((pServer->status==FDFS_STORAGE_STATUS_WAIT_SYNC)||(pServer->status==FDFS_STORAGE_STATUS_SYNCING))&&((*ppFound)->server.status>pServer->status))

            {

                memcpy(pDiffServer++, &((*ppFound)->server), sizeof(FDFSStorageBrief));

            }

            else

            {

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

            }

        }

        else if (pServer->status == FDFS_STORAGE_STATUS_DELETED|| pServer->status == FDFS_STORAGE_STATUS_IP_CHANGED)

        {  

            //如果本地存在该数据服务器,返回的删除的暂时不做处理

            nDeletedCount++;

        }

        else

        {

            //logInfo("ip_addr=%s, tracker status: %d", pServer->ip_addr, pServer->status);

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

            {

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

                    "call pthread_mutex_lock fail,"/

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

                    __LINE__, res, strerror(res));

            }

            //在本地数据服务器列表找不到,那么它是新来的数据服务器

            if (g_storage_count < FDFS_MAX_SERVERS_EACH_GROUP)

            {

                pInsertedServer = g_storage_servers + g_storage_count;

                memcpy(&(pInsertedServer->server), pServer, sizeof(FDFSStorageBrief));

                if (tracker_insert_into_sorted_servers(pInsertedServer))

                {

                    g_storage_count++;

                }

                //在来启动同步线程:这个数据服务器是新加入的

                result = storage_sync_thread_start(&(pInsertedServer->server));

            }

            else

            {

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

                    "tracker server %s:%d, " /

                    "storage servers of group /"%s/" " /

                    "exceeds max: %d", /

                    __LINE__, pTrackerServer->ip_addr, /

                    pTrackerServer->port, /

                    pTrackerServer->group_name, /

                    FDFS_MAX_SERVERS_EACH_GROUP);

                result = ENOSPC;

            }

            if ((res=pthread_mutex_unlock( /

                &reporter_thread_lock)) != 0)

            {

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

                    "call pthread_mutex_unlock fail, " /

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

                    __LINE__, res, strerror(res));

            }

            if (result != 0)

            {

                return result;

            }

        }

    }

    if (g_storage_count + nDeletedCount == server_count)

    {

        if (pDiffServer - diffServers > 0)

        {

            return tracker_sync_diff_servers(pTrackerServer,diffServers, pDiffServer - diffServers);

        }

        return 0;

    }

    //比较得出发生改变的数据服务器:g_sorted_storages=本地的数据服务器briefServers=跟踪服务器返回的数据服务器

    ppGlobalServer = g_sorted_storages;

    ppGlobalEnd = g_sorted_storages + g_storage_count;

    pServer = briefServers;

    while (pServer < pEnd && ppGlobalServer < ppGlobalEnd)

    {

        if ((*ppGlobalServer)->server.status == FDFS_STORAGE_STATUS_NONE)

        {

            ppGlobalServer++;

            continue;

        }

        res = strcmp(pServer->ip_addr, (*ppGlobalServer)->server.ip_addr);

        if (res < 0)

        {

            if (pServer->status != FDFS_STORAGE_STATUS_DELETED&& pServer->status != FDFS_STORAGE_STATUS_IP_CHANGED)

            {

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

                    "tracker server %s:%d, " /

                    "group /"%s/", " /

                    "enter impossible statement branch", /

                    __LINE__, pTrackerServer->ip_addr, /

                    pTrackerServer->port, /

                    pTrackerServer->group_name);

            }

            //因为g_sorted_storages是已经排序好了(由大到小排序),所以直接查询pServer的下一个

            pServer++;

        }

        else if (res == 0)

        {

            pServer++;

            ppGlobalServer++;

        }

        else

        {

            //显然ppGlobalServer后面都是小的,pServerppGlobalServer,因此不必在找下去了,

            //这一个直接就是不同的

            memcpy(pDiffServer++, &((*ppGlobalServer)->server),sizeof(FDFSStorageBrief));

            ppGlobalServer++;

        }

    }

    //这段代码有什么用???

    while (ppGlobalServer < ppGlobalEnd)

    {

        if ((*ppGlobalServer)->server.status == FDFS_STORAGE_STATUS_NONE)

        {

            ppGlobalServer++;

            continue;

        }

        memcpy(pDiffServer++, &((*ppGlobalServer)->server),sizeof(FDFSStorageBrief));

        ppGlobalServer++;

    }

    return tracker_sync_diff_servers(pTrackerServer,diffServers, pDiffServer - diffServers);

}

 

//报告数据服务器磁盘容量

static int tracker_report_df_stat(TrackerServerInfo *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 i;

    int result;

    body_len = (int)sizeof(TrackerStatReportReqBody) * g_path_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;

        }

    }

    pHeader = (TrackerHeader *)pBuff;

    pStatBuff = (TrackerStatReportReqBody*) (pBuff + sizeof(TrackerHeader));

    long2buff(body_len, pHeader->pkg_len);

    pHeader->cmd = TRACKER_PROTO_CMD_STORAGE_REPORT_DISK_USAGE;

    pHeader->status = 0;

    for (i=0; i<g_path_count; i++)

    {

        //直接调用取磁盘容量的函数

        if (statvfs(g_store_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;

        }

        long2buff((((int64_t)(sbuf.f_blocks) * sbuf.f_frsize) / FDFS_ONE_MB),/

            pStatBuff->sz_total_mb);

        long2buff((((int64_t)(sbuf.f_bavail) * sbuf.f_frsize) / FDFS_ONE_MB),/

            pStatBuff->sz_free_mb);

        pStatBuff++;

    }

    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;

    }

    return tracker_check_response(pTrackerServer, bServerPortChanged);

}

 

//向跟踪服务器发起心跳

static int tracker_heart_beat(TrackerServerInfo *pTrackerServer, /

                              int *pstat_chg_sync_count, bool *bServerPortChanged)

{

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

    TrackerHeader *pHeader;

    FDFSStorageStatBuff *pStatBuff;

    int body_len;

    int result;

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

        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_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.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;

 

    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;

    }

    return tracker_check_response(pTrackerServer, bServerPortChanged);

}

//数据服务器启动向跟踪服务器的汇报线程

int tracker_report_thread_start()

{

    TrackerServerInfo *pTrackerServer;

    TrackerServerInfo *pServerEnd;

    pthread_attr_t pattr;

    pthread_t tid;

    int result;

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

    {

        return result;

    }

    //获得跟踪服务器个数

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

    //源数据服务器状态列表====>对应于多个跟踪服务器

    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;

    }

    //src_storage_status初始全部填为-1

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

    //报告状态数组

    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;

    }

    //my_report_status初始全部填为-1

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

    g_tracker_reporter_count = 0;

    pServerEnd = g_tracker_group.servers + g_tracker_group.server_count;

    //有多少个跟踪服务器就创建多少个线程

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

        pTrackerServer++)

    {

        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;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值