1 /**
2 * Copyright (C) 2008 Happy Fish / YuQing
3 *
4 * FastDFS may be copied only under the terms of the GNU General
5 * Public License V3, which may be found in the FastDFS source kit.
6 * Please visit the FastDFS Home Page http://www.fastken.com/ for more detail.
7 **/
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <errno.h>
18 #include <signal.h>
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <pthread.h>
23 #include "fastcommon/shared_func.h"
24 #include "fastcommon/pthread_func.h"
25 #include "fastcommon/process_ctrl.h"
26 #include "fastcommon/logger.h"
27 #include "fdfs_global.h"
28 #include "fastcommon/base64.h"
29 #include "fastcommon/sockopt.h"
30 #include "fastcommon/sched_thread.h"
31 #include "tracker_types.h"
32 #include "tracker_mem.h"
33 #include "tracker_service.h"
34 #include "tracker_global.h"
35 #include "tracker_proto.h"
36 #include "tracker_func.h"
37 #include "tracker_status.h"
38 #include "tracker_relationship.h"
39
40 #ifdef WITH_HTTPD
41 #include "tracker_httpd.h"
42 #include "tracker_http_check.h"
43 #endif
44
45 #if defined(DEBUG_FLAG)
46 #include "tracker_dump.h"
47 #endif
48
49 static bool bTerminateFlag = false;
50 static bool bAcceptEndFlag = false;
51
52 static char bind_addr[IP_ADDRESS_SIZE];
53
54 static void sigQuitHandler(int sig);
55 static void sigHupHandler(int sig);
56 static void sigUsrHandler(int sig);
57 static void sigAlarmHandler(int sig);
58
59 #if defined(DEBUG_FLAG)
60 /*
61 #if defined(OS_LINUX)
62 static void sigSegvHandler(int signum, siginfo_t *info, void *ptr);
63 #endif
64 */
65
66 static void sigDumpHandler(int sig);
67 #endif
68
69 #define SCHEDULE_ENTRIES_COUNT 5
70
usage(const char * program)71 static void usage(const char *program)
72 {
73 fprintf(stderr, "FastDFS server v%d.%02d\n"
74 "Usage: %s <config_file> [start | stop | restart]\n",
75 g_fdfs_version.major, g_fdfs_version.minor,
76 program);
77 }
78
main(int argc,char * argv[])79 int main(int argc, char *argv[])
80 {
81 char *conf_filename;
82 int result;
83 int wait_count;
84 int sock;
85 pthread_t schedule_tid;
86 struct sigaction act;
87 ScheduleEntry scheduleEntries[SCHEDULE_ENTRIES_COUNT];
88 ScheduleArray scheduleArray;
89 char pidFilename[MAX_PATH_SIZE];
90 bool stop;
91
92 if (argc < 2)
93 {
94 usage(argv[0]);
95 return 1;
96 }
97
98 g_current_time = time(NULL);
99 g_up_time = g_current_time;
100 srand(g_up_time);
101
102 log_init2();
103
104 conf_filename = argv[1];
105 if (!fileExists(conf_filename))
106 {
107 if (starts_with(conf_filename, "-"))
108 {
109 usage(argv[0]);
110 return 0;
111 }
112 }
113 if ((result=get_base_path_from_conf_file(conf_filename,
114 g_fdfs_base_path, sizeof(g_fdfs_base_path))) != 0)
115 {
116 log_destroy();
117 return result;
118 }
119
120 snprintf(pidFilename, sizeof(pidFilename),
121 "%s/data/fdfs_trackerd.pid", g_fdfs_base_path);
122 if ((result=process_action(pidFilename, argv[2], &stop)) != 0)
123 {
124 if (result == EINVAL)
125 {
126 usage(argv[0]);
127 }
128 log_destroy();
129 return result;
130 }
131 if (stop)
132 {
133 log_destroy();
134 return 0;
135 }
136
137 #if defined(DEBUG_FLAG) && defined(OS_LINUX)
138 if (getExeAbsoluteFilename(argv[0], g_exe_name, \
139 sizeof(g_exe_name)) == NULL)
140 {
141 logCrit("exit abnormally!\n");
142 log_destroy();
143 return errno != 0 ? errno : ENOENT;
144 }
145 #endif
146
147 memset(bind_addr, 0, sizeof(bind_addr));
148 if ((result=tracker_load_from_conf_file(conf_filename, \
149 bind_addr, sizeof(bind_addr))) != 0)
150 {
151 logCrit("exit abnormally!\n");
152 log_destroy();
153 return result;
154 }
155
156 if ((result=tracker_load_status_from_file(&g_tracker_last_status)) != 0)
157 {
158 logCrit("exit abnormally!\n");
159 log_destroy();
160 return result;
161 }
162
163 base64_init_ex(&g_base64_context, 0, '-', '_', '.');
164 if ((result=set_rand_seed()) != 0)
165 {
166 logCrit("file: "__FILE__", line: %d, " \
167 "set_rand_seed fail, program exit!", __LINE__);
168 return result;
169 }
170
171 if ((result=tracker_mem_init()) != 0)
172 {
173 logCrit("exit abnormally!\n");
174 log_destroy();
175 return result;
176 }
177
178 sock = socketServer(bind_addr, g_server_port, &result);
179 if (sock < 0)
180 {
181 logCrit("exit abnormally!\n");
182 log_destroy();
183 return result;
184 }
185
186 if ((result=tcpsetserveropt(sock, g_fdfs_network_timeout)) != 0)
187 {
188 logCrit("exit abnormally!\n");
189 log_destroy();
190 return result;
191 }
192
193 daemon_init(false);
194 umask(0);
195
196 if ((result=write_to_pid_file(pidFilename)) != 0)
197 {
198 log_destroy();
199 return result;
200 }
201
202 if ((result=tracker_service_init()) != 0)
203 {
204 logCrit("exit abnormally!\n");
205 log_destroy();
206 return result;
207 }
208
209 memset(&act, 0, sizeof(act));
210 sigemptyset(&act.sa_mask);
211
212 act.sa_handler = sigUsrHandler;
213 if(sigaction(SIGUSR1, &act, NULL) < 0 || \
214 sigaction(SIGUSR2, &act, NULL) < 0)
215 {
216 logCrit("file: "__FILE__", line: %d, " \
217 "call sigaction fail, errno: %d, error info: %s", \
218 __LINE__, errno, STRERROR(errno));
219 logCrit("exit abnormally!\n");
220 return errno;
221 }
222
223 act.sa_handler = sigHupHandler;
224 if(sigaction(SIGHUP, &act, NULL) < 0)
225 {
226 logCrit("file: "__FILE__", line: %d, " \
227 "call sigaction fail, errno: %d, error info: %s", \
228 __LINE__, errno, STRERROR(errno));
229 logCrit("exit abnormally!\n");
230 return errno;
231 }
232
233 act.sa_handler = SIG_IGN;
234 if(sigaction(SIGPIPE, &act, NULL) < 0)
235 {
236 logCrit("file: "__FILE__", line: %d, " \
237 "call sigaction fail, errno: %d, error info: %s", \
238 __LINE__, errno, STRERROR(errno));
239 logCrit("exit abnormally!\n");
240 return errno;
241 }
242
243 act.sa_handler = sigQuitHandler;
244 if(sigaction(SIGINT, &act, NULL) < 0 || \
245 sigaction(SIGTERM, &act, NULL) < 0 || \
246 sigaction(SIGQUIT, &act, NULL) < 0)
247 {
248 logCrit("file: "__FILE__", line: %d, " \
249 "call sigaction fail, errno: %d, error info: %s", \
250 __LINE__, errno, STRERROR(errno));
251 logCrit("exit abnormally!\n");
252 return errno;
253 }
254
255 #if defined(DEBUG_FLAG)
256 /*
257 #if defined(OS_LINUX)
258 memset(&act, 0, sizeof(act));
259 sigemptyset(&act.sa_mask);
260 act.sa_sigaction = sigSegvHandler;
261 act.sa_flags = SA_SIGINFO;
262 if (sigaction(SIGSEGV, &act, NULL) < 0 || \
263 sigaction(SIGABRT, &act, NULL) < 0)
264 {
265 logCrit("file: "__FILE__", line: %d, " \
266 "call sigaction fail, errno: %d, error info: %s", \
267 __LINE__, errno, STRERROR(errno));
268 logCrit("exit abnormally!\n");
269 return errno;
270 }
271 #endif
272 */
273
274 memset(&act, 0, sizeof(act));
275 sigemptyset(&act.sa_mask);
276 act.sa_handler = sigDumpHandler;
277 if(sigaction(SIGUSR1, &act, NULL) < 0 || \
278 sigaction(SIGUSR2, &act, NULL) < 0)
279 {
280 logCrit("file: "__FILE__", line: %d, " \
281 "call sigaction fail, errno: %d, error info: %s", \
282 __LINE__, errno, STRERROR(errno));
283 logCrit("exit abnormally!\n");
284 return errno;
285 }
286 #endif
287
288 #ifdef WITH_HTTPD
289 if (!g_http_params.disabled)
290 {
291 if ((result=tracker_httpd_start(bind_addr)) != 0)
292 {
293 logCrit("file: "__FILE__", line: %d, " \
294 "tracker_httpd_start fail, program exit!", \
295 __LINE__);
296 return result;
297 }
298
299 }
300
301 if ((result=tracker_http_check_start()) != 0)
302 {
303 logCrit("file: "__FILE__", line: %d, " \
304 "tracker_http_check_start fail, " \
305 "program exit!", __LINE__);
306 return result;
307 }
308 #endif
309
310 if ((result=set_run_by(g_run_by_group, g_run_by_user)) != 0)
311 {
312 logCrit("exit abnormally!\n");
313 log_destroy();
314 return result;
315 }
316
317 scheduleArray.entries = scheduleEntries;
318 scheduleArray.count = 0;
319 memset(scheduleEntries, 0, sizeof(scheduleEntries));
320
321 INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count],
322 scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE,
323 g_sync_log_buff_interval, log_sync_func, &g_log_context);
324 scheduleArray.count++;
325
326 INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count],
327 scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE,
328 g_check_active_interval, tracker_mem_check_alive, NULL);
329 scheduleArray.count++;
330
331 INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count],
332 scheduleArray.count + 1, 0, 0, 0,
333 TRACKER_SYNC_STATUS_FILE_INTERVAL,
334 tracker_write_status_to_file, NULL);
335 scheduleArray.count++;
336
337 if (g_rotate_error_log)
338 {
339 INIT_SCHEDULE_ENTRY_EX(scheduleEntries[scheduleArray.count],
340 scheduleArray.count + 1, g_error_log_rotate_time,
341 24 * 3600, log_notify_rotate, &g_log_context);
342 scheduleArray.count++;
343
344 if (g_log_file_keep_days > 0)
345 {
346 log_set_keep_days(&g_log_context, g_log_file_keep_days);
347
348 INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count],
349 scheduleArray.count + 1, 1, 0, 0, 24 * 3600,
350 log_delete_old_files, &g_log_context);
351 scheduleArray.count++;
352 }
353 }
354
355 if ((result=sched_start(&scheduleArray, &schedule_tid, \
356 g_thread_stack_size, (bool * volatile)&g_continue_flag)) != 0)
357 {
358 logCrit("exit abnormally!\n");
359 log_destroy();
360 return result;
361 }
362
363 if ((result=tracker_relationship_init()) != 0)
364 {
365 logCrit("exit abnormally!\n");
366 log_destroy();
367 return result;
368 }
369
370 log_set_cache(true);
371
372 bTerminateFlag = false;
373 bAcceptEndFlag = false;
374
375 tracker_accept_loop(sock);
376 bAcceptEndFlag = true;
377 if (g_schedule_flag)
378 {
379 pthread_kill(schedule_tid, SIGINT);
380 }
381 tracker_terminate_threads();
382
383 #ifdef WITH_HTTPD
384 if (g_http_check_flag)
385 {
386 tracker_http_check_stop();
387 }
388
389 while (g_http_check_flag)
390 {
391 usleep(50000);
392 }
393 #endif
394
395 wait_count = 0;
396 while ((g_tracker_thread_count != 0) || g_schedule_flag)
397 {
398
399 /*
400 #if defined(DEBUG_FLAG) && defined(OS_LINUX)
401 if (bSegmentFault)
402 {
403 sleep(5);
404 break;
405 }
406 #endif
407 */
408
409 usleep(10000);
410 if (++wait_count > 3000)
411 {
412 logWarning("waiting timeout, exit!");
413 break;
414 }
415 }
416
417 tracker_mem_destroy();
418 tracker_service_destroy();
419 tracker_relationship_destroy();
420
421 logInfo("exit normally.\n");
422 log_destroy();
423
424 delete_pid_file(pidFilename);
425 return 0;
426 }
427
428 #if defined(DEBUG_FLAG)
sigDumpHandler(int sig)429 static void sigDumpHandler(int sig)
430 {
431 static bool bDumpFlag = false;
432 char filename[256];
433
434 if (bDumpFlag)
435 {
436 return;
437 }
438
439 bDumpFlag = true;
440
441 snprintf(filename, sizeof(filename),
442 "%s/logs/tracker_dump.log", g_fdfs_base_path);
443 fdfs_dump_tracker_global_vars_to_file(filename);
444
445 bDumpFlag = false;
446 }
447
448 #endif
449
sigQuitHandler(int sig)450 static void sigQuitHandler(int sig)
451 {
452 if (!bTerminateFlag)
453 {
454 tcp_set_try_again_when_interrupt(false);
455 set_timer(1, 1, sigAlarmHandler);
456
457 bTerminateFlag = true;
458 g_continue_flag = false;
459 logCrit("file: "__FILE__", line: %d, " \
460 "catch signal %d, program exiting...", \
461 __LINE__, sig);
462 }
463 }
464
sigHupHandler(int sig)465 static void sigHupHandler(int sig)
466 {
467 if (g_rotate_error_log)
468 {
469 g_log_context.rotate_immediately = true;
470 }
471
472 logInfo("file: "__FILE__", line: %d, " \
473 "catch signal %d, rotate log", __LINE__, sig);
474 }
475
sigAlarmHandler(int sig)476 static void sigAlarmHandler(int sig)
477 {
478 ConnectionInfo server;
479
480 if (bAcceptEndFlag)
481 {
482 return;
483 }
484
485 logDebug("file: "__FILE__", line: %d, " \
486 "signal server to quit...", __LINE__);
487
488 if (*bind_addr != '\0')
489 {
490 strcpy(server.ip_addr, bind_addr);
491 }
492 else
493 {
494 strcpy(server.ip_addr, "127.0.0.1");
495 }
496 server.port = g_server_port;
497 server.sock = -1;
498
499 if (conn_pool_connect_server(&server, g_fdfs_connect_timeout) != 0)
500 {
501 return;
502 }
503
504 fdfs_quit(&server);
505 conn_pool_disconnect_server(&server);
506
507 logDebug("file: "__FILE__", line: %d, " \
508 "signal server to quit done", __LINE__);
509 }
510
sigUsrHandler(int sig)511 static void sigUsrHandler(int sig)
512 {
513 logInfo("file: "__FILE__", line: %d, " \
514 "catch signal %d, ignore it", __LINE__, sig);
515 }
516
517