int main(int argc, char *argv[])
{
char *conf_filename;
int result;
int sock;
pthread_t schedule_tid;
struct sigaction act;
//默认3个tracker调度进程
ScheduleEntry scheduleEntries[SCHEDULE_ENTRIES_COUNT];
ScheduleArray scheduleArray;
//配置文件
if (argc < 2)
{
printf("Usage: %s \n", argv[0]);
return 1;
}
//记录启动时间
g_up_time = time(NULL);
srand(g_up_time);
log_init();
#if defined(DEBUG_FLAG) && defined(OS_LINUX)
if (getExeAbsoluteFilename(argv[0], g_exe_name, \
sizeof(g_exe_name)) == NULL)
{
log_destroy();
return errno != 0 ? errno : ENOENT;
}
#endif
conf_filename = argv[1];
memset(bind_addr, 0, sizeof(bind_addr));
//读取配置文件选项
if ((result=tracker_load_from_conf_file(conf_filename, \
bind_addr, sizeof(bind_addr))) != 0)
{
log_destroy();
return result;
}
if ((result=tracker_load_status_from_file(&g_tracker_last_status)) != 0)
{
log_destroy();
return result;
}
base64_init_ex(&g_base64_context, 0, '-', '_', '.');
if ((result=set_rand_seed()) != 0)
{
logCrit("file: "__FILE__", line: %d, " \
"set_rand_seed fail, program exit!", __LINE__);
return result;
}
if ((result=tracker_mem_init()) != 0)
{
log_destroy();
return result;
}
//创建tracker的server socket
sock = socketServer(bind_addr, g_server_port, &result);
if (sock < 0)
{
log_destroy();
return result;
}
//设置tracker socket选项
if ((result=tcpsetserveropt(sock, g_fdfs_network_timeout)) != 0)
{
log_destroy();
return result;
}
//后台执行
daemon_init(true);
umask(0);
if (dup2(g_log_context.log_fd, STDOUT_FILENO) < 0 || \
dup2(g_log_context.log_fd, STDERR_FILENO) < 0)
{
logCrit("file: "__FILE__", line: %d, " \
"call dup2 fail, errno: %d, error info: %s, " \
"program exit!", __LINE__, errno, STRERROR(errno));
g_continue_flag = false;
return errno;
}
//初始化tracker服务进程
if ((result=tracker_service_init()) != 0)
{
log_destroy();
return result;
}
memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
//设置信号处理函数
act.sa_handler = sigUsrHandler;
if(sigaction(SIGUSR1, &act, NULL) < 0 || \
sigaction(SIGUSR2, &act, NULL) < 0)
{
logCrit("file: "__FILE__", line: %d, " \
"call sigaction fail, errno: %d, error info: %s", \
__LINE__, errno, STRERROR(errno));
return errno;
}
act.sa_handler = sigHupHandler;
if(sigaction(SIGHUP, &act, NULL) < 0)
{
logCrit("file: "__FILE__", line: %d, " \
"call sigaction fail, errno: %d, error info: %s", \
__LINE__, errno, STRERROR(errno));
return errno;
}
act.sa_handler = SIG_IGN;
if(sigaction(SIGPIPE, &act, NULL) < 0)
{
logCrit("file: "__FILE__", line: %d, " \
"call sigaction fail, errno: %d, error info: %s", \
__LINE__, errno, STRERROR(errno));
return errno;
}
act.sa_handler = sigQuitHandler;
if(sigaction(SIGINT, &act, NULL) < 0 || \
sigaction(SIGTERM, &act, NULL) < 0 || \
sigaction(SIGQUIT, &act, NULL) < 0)
{
logCrit("file: "__FILE__", line: %d, " \
"call sigaction fail, errno: %d, error info: %s", \
__LINE__, errno, STRERROR(errno));
return errno;
}
#if defined(DEBUG_FLAG)
/*
#if defined(OS_LINUX)
memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_sigaction = sigSegvHandler;
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &act, NULL) < 0 || \
sigaction(SIGABRT, &act, NULL) < 0)
{
logCrit("file: "__FILE__", line: %d, " \
"call sigaction fail, errno: %d, error info: %s", \
__LINE__, errno, STRERROR(errno));
return errno;
}
#endif
*/
memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_handler = sigDumpHandler;
if(sigaction(SIGUSR1, &act, NULL) < 0 || \
sigaction(SIGUSR2, &act, NULL) < 0)
{
logCrit("file: "__FILE__", line: %d, " \
"call sigaction fail, errno: %d, error info: %s", \
__LINE__, errno, STRERROR(errno));
return errno;
}
#endif
#ifdef WITH_HTTPD
if (!g_http_params.disabled)
{
if ((result=tracker_httpd_start(bind_addr)) != 0)
{
logCrit("file: "__FILE__", line: %d, " \
"tracker_httpd_start fail, program exit!", \
__LINE__);
return result;
}
}
if ((result=tracker_http_check_start()) != 0)
{
logCrit("file: "__FILE__", line: %d, " \
"tracker_http_check_start fail, " \
"program exit!", __LINE__);
return result;
}
#endif
//设置运行权限
if ((result=set_run_by(g_run_by_group, g_run_by_user)) != 0)
{
log_destroy();
return result;
}
scheduleArray.entries = scheduleEntries;
scheduleArray.count = SCHEDULE_ENTRIES_COUNT;
//设置调度实体处理函数
memset(scheduleEntries, 0, sizeof(scheduleEntries));
scheduleEntries[0].id = 1;
scheduleEntries[0].time_base.hour = TIME_NONE;
scheduleEntries[0].time_base.minute = TIME_NONE;
scheduleEntries[0].interval = g_sync_log_buff_interval;
scheduleEntries[0].task_func = log_sync_func;
scheduleEntries[0].func_args = &g_log_context;
scheduleEntries[1].id = 2;
scheduleEntries[1].time_base.hour = TIME_NONE;
scheduleEntries[1].time_base.minute = TIME_NONE;
scheduleEntries[1].interval = g_check_active_interval;
scheduleEntries[1].task_func = tracker_mem_check_alive;
scheduleEntries[1].func_args = NULL;
scheduleEntries[2].id = 3;
scheduleEntries[2].time_base.hour = 0;
scheduleEntries[2].time_base.minute = 0;
scheduleEntries[2].interval = TRACKER_SYNC_STATUS_FILE_INTERVAL;
scheduleEntries[2].task_func = tracker_write_status_to_file;
scheduleEntries[2].func_args = NULL;
if ((result=sched_start(&scheduleArray, &schedule_tid, \
g_thread_stack_size, &g_continue_flag)) != 0)
{
log_destroy();
return result;
}
//选主
if ((result=tracker_relationship_init()) != 0)
{
log_destroy();
return result;
}
log_set_cache(true);
bTerminateFlag = false;
bAcceptEndFlag = false;
//接受连接主函数
tracker_accept_loop(sock);
bAcceptEndFlag = true;
if (g_schedule_flag)
{
pthread_kill(schedule_tid, SIGINT);
}
//终止线程
tracker_terminate_threads();
#ifdef WITH_HTTPD
if (g_http_check_flag)
{
tracker_http_check_stop();
}
while (g_http_check_flag)
{
usleep(50000);
}
#endif
while ((g_tracker_thread_count != 0) || g_schedule_flag)
{
/*
#if defined(DEBUG_FLAG) && defined(OS_LINUX)
if (bSegmentFault)
{
sleep(5);
break;
}
#endif
*/
usleep(50000);
}
tracker_mem_destroy();
tracker_service_destroy();
tracker_relationship_destroy();
logInfo("exit nomally.\n");
log_destroy();
return 0;
}
int tracker_service_init()
{
int result;
struct tracker_thread_data *pThreadData;
struct tracker_thread_data *pDataEnd;
pthread_t tid;
pthread_attr_t thread_attr;
//初始化线程锁
if ((result=init_pthread_lock(&tracker_thread_lock)) != 0)
{
return result;
}
//初始化
if ((result=init_pthread_lock(&lb_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;
}
//队列初始化
if ((result=free_queue_init(g_max_connections, TRACKER_MAX_PACKAGE_SIZE,\
TRACKER_MAX_PACKAGE_SIZE, sizeof(TrackerClientInfo))) != 0)
{
return result;
}
//为每个线程分配一个线程结构
g_thread_data = (struct tracker_thread_data *)malloc(sizeof( \
struct tracker_thread_data) * g_work_threads);
if (g_thread_data == NULL)
{
logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail, errno: %d, error info: %s", \
__LINE__, (int)sizeof(struct tracker_thread_data) * \
g_work_threads, errno, STRERROR(errno));
return errno != 0 ? errno : ENOMEM;
}
//遍历N个工作线程结构,创建管道
g_tracker_thread_count = 0;
pDataEnd = g_thread_data + g_work_threads;
for (pThreadData=g_thread_data; 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;
}
//创建tracker工作线程
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_tracker_thread_count, \
result, STRERROR(result));
break;
}
else
{
//创建线程成功,用全局变量记录tracker线程的数量
if ((result=pthread_mutex_lock(&tracker_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
g_tracker_thread_count++;
if ((result=pthread_mutex_unlock(&tracker_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);
return 0;
}
static void *work_thread_entrance(void* arg)
{
int result;
struct tracker_thread_data *pThreadData;
struct event ev_notify;
pThreadData = (struct tracker_thread_data *)arg;
do
{
//设置管道读端的处理函数
event_set(&ev_notify, pThreadData->pipe_fds[0], \
EV_READ | EV_PERSIST, 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;
}
while (g_continue_flag)
{
event_base_loop(pThreadData->ev_base, 0);
}
} while (0);
event_base_free(pThreadData->ev_base);
if ((result=pthread_mutex_lock(&tracker_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
g_tracker_thread_count--;
if ((result=pthread_mutex_unlock(&tracker_thread_lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
return NULL;
}