Skip to content

Commit 5b59480

Browse files
authored
Merge branch 'master' into patch-7
2 parents 8018d57 + 3778046 commit 5b59480

25 files changed

+292
-116
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ unittest: prepare
233233
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/mkdir_p unittest/mkdir_test.c base/hbase.c
234234
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/rmdir_p unittest/rmdir_test.c base/hbase.c
235235
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/date unittest/date_test.c base/htime.c
236+
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/hlog_test unittest/hlog_test.c base/hlog.c
236237
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/hatomic_test unittest/hatomic_test.c -pthread
237238
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -o bin/hatomic_cpp_test unittest/hatomic_test.cpp -pthread
238239
$(CXX) -g -Wall -O0 -std=c++11 -I. -Ibase -o bin/hthread_test unittest/hthread_test.cpp -pthread

base/hlog.c

Lines changed: 73 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "hlog.h"
22

3+
#include <assert.h>
34
#include <stdio.h>
45
#include <stdlib.h>
56
#include <string.h>
@@ -44,6 +45,7 @@ struct logger_s {
4445
// for file logger
4546
char filepath[256];
4647
unsigned long long max_filesize;
48+
float truncate_percent;
4749
int remain_days;
4850
int enable_fsync;
4951
FILE* fp_;
@@ -67,6 +69,7 @@ static void logger_init(logger_t* logger) {
6769

6870
logger->fp_ = NULL;
6971
logger->max_filesize = DEFAULT_LOG_MAX_FILESIZE;
72+
logger->truncate_percent = DEFAULT_LOG_TRUNCATE_PERCENT;
7073
logger->remain_days = DEFAULT_LOG_REMAIN_DAYS;
7174
logger->enable_fsync = 1;
7275
logger_set_file(logger, DEFAULT_LOG_FILE);
@@ -146,6 +149,11 @@ void logger_set_remain_days(logger_t* logger, int days) {
146149
logger->remain_days = days;
147150
}
148151

152+
void logger_set_truncate_percent(logger_t* logger, float percent) {
153+
assert(percent <= 1.0f);
154+
logger->truncate_percent = percent;
155+
}
156+
149157
void logger_set_max_bufsize(logger_t* logger, unsigned int bufsize) {
150158
logger->bufsize = bufsize;
151159
logger->buf = (char*)realloc(logger->buf, bufsize);
@@ -214,6 +222,68 @@ static void logfile_name(const char* filepath, time_t ts, char* buf, int len) {
214222
tm->tm_mday);
215223
}
216224

225+
static void logfile_truncate(logger_t* logger) {
226+
// close
227+
if (logger->fp_) {
228+
fclose(logger->fp_);
229+
logger->fp_ = NULL;
230+
}
231+
char tmp_logfile[sizeof(logger->cur_logfile) + 4] = {0};
232+
FILE* tmpfile = NULL;
233+
if (logger->truncate_percent < 1.0f) {
234+
snprintf(tmp_logfile, sizeof(tmp_logfile), "%s.tmp", logger->cur_logfile);
235+
tmpfile = fopen(tmp_logfile, "w");
236+
}
237+
if (tmpfile) {
238+
// truncate percent
239+
logger->fp_ = fopen(logger->cur_logfile, "r");
240+
if (logger->fp_) {
241+
fseek(logger->fp_, 0, SEEK_END);
242+
long filesize = ftell(logger->fp_);
243+
long truncate_size = (long)((double)filesize * logger->truncate_percent);
244+
fseek(logger->fp_, -(filesize - truncate_size), SEEK_CUR);
245+
long cur_pos = ftell(logger->fp_);
246+
char buf[4096] = {0};
247+
const char* pbuf = buf;
248+
size_t nread = 0, nwrite = 0;
249+
char find_newline = 0;
250+
while ((nread = fread(buf, 1, sizeof(buf), logger->fp_)) > 0) {
251+
pbuf = buf;
252+
if (find_newline == 0) {
253+
while (nread > 0) {
254+
if (*pbuf == '\n') {
255+
find_newline = 1;
256+
++pbuf;
257+
--nread;
258+
break;
259+
}
260+
++pbuf;
261+
--nread;
262+
}
263+
}
264+
if (nread > 0) {
265+
nwrite += fwrite(pbuf, 1, nread, tmpfile);
266+
}
267+
}
268+
fclose(tmpfile);
269+
fclose(logger->fp_);
270+
logger->fp_ = NULL;
271+
remove(logger->cur_logfile);
272+
rename(tmp_logfile, logger->cur_logfile);
273+
}
274+
} else {
275+
// truncate all
276+
// remove(logger->cur_logfile);
277+
logger->fp_ = fopen(logger->cur_logfile, "w");
278+
if (logger->fp_) {
279+
fclose(logger->fp_);
280+
logger->fp_ = NULL;
281+
}
282+
}
283+
// reopen
284+
logger->fp_ = fopen(logger->cur_logfile, "a");
285+
}
286+
217287
static FILE* logfile_shift(logger_t* logger) {
218288
time_t ts_now = time(NULL);
219289
int interval_days = logger->last_logfile_ts == 0 ? 0 : (ts_now+s_gmtoff) / SECONDS_PER_DAY - (logger->last_logfile_ts+s_gmtoff) / SECONDS_PER_DAY;
@@ -258,17 +328,8 @@ static FILE* logfile_shift(logger_t* logger) {
258328
fseek(logger->fp_, 0, SEEK_END);
259329
long filesize = ftell(logger->fp_);
260330
if (filesize > logger->max_filesize) {
261-
fclose(logger->fp_);
262-
logger->fp_ = NULL;
263-
// ftruncate
264-
logger->fp_ = fopen(logger->cur_logfile, "w");
265-
// reopen with O_APPEND for multi-processes
266-
if (logger->fp_) {
267-
fclose(logger->fp_);
268-
logger->fp_ = fopen(logger->cur_logfile, "a");
269-
}
270-
}
271-
else {
331+
logfile_truncate(logger);
332+
} else {
272333
logger->can_write_cnt = (logger->max_filesize - filesize) / logger->bufsize;
273334
}
274335
}
@@ -419,7 +480,7 @@ int logger_print(logger_t* logger, int level, const char* fmt, ...) {
419480
len += snprintf(buf + len, bufsize - len, "%s", CLR_CLR);
420481
}
421482

422-
if(len<bufsize) {
483+
if(len < bufsize) {
423484
buf[len++] = '\n';
424485
}
425486

base/hlog.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ typedef enum {
6767
#define DEFAULT_LOG_REMAIN_DAYS 1
6868
#define DEFAULT_LOG_MAX_BUFSIZE (1<<14) // 16k
6969
#define DEFAULT_LOG_MAX_FILESIZE (1<<24) // 16M
70+
#define DEFAULT_LOG_TRUNCATE_PERCENT 0.99f // truncate when exceeded max filesize
7071

7172
// logger: default file_logger
7273
// network_logger() see event/nlog.h
@@ -113,6 +114,7 @@ HV_EXPORT void logger_set_max_filesize(logger_t* logger, unsigned long long file
113114
// 16, 16M, 16MB
114115
HV_EXPORT void logger_set_max_filesize_by_str(logger_t* logger, const char* filesize);
115116
HV_EXPORT void logger_set_remain_days(logger_t* logger, int days);
117+
HV_EXPORT void logger_set_truncate_percent(logger_t* logger, float percent);
116118
HV_EXPORT void logger_enable_fsync(logger_t* logger, int on);
117119
HV_EXPORT void logger_fsync(logger_t* logger);
118120
HV_EXPORT const char* logger_get_cur_file(logger_t* logger);
@@ -133,6 +135,7 @@ HV_EXPORT void hv_destroy_default_logger(void);
133135
#define hlog_set_max_filesize(filesize) logger_set_max_filesize(hlog, filesize)
134136
#define hlog_set_max_filesize_by_str(filesize) logger_set_max_filesize_by_str(hlog, filesize)
135137
#define hlog_set_remain_days(days) logger_set_remain_days(hlog, days)
138+
#define hlog_set_truncate_percent(val) logger_set_truncate_percent(hlog, val)
136139
#define hlog_enable_fsync() logger_enable_fsync(hlog, 1)
137140
#define hlog_disable_fsync() logger_enable_fsync(hlog, 0)
138141
#define hlog_fsync() logger_fsync(hlog)

base/hmain.c

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
static FILE* s_fp = NULL;
1919

2020
main_ctx_t g_main_ctx;
21+
printf_t printf_fn = printf;
2122

2223
static void init_arg_kv(int maxsize) {
2324
g_main_ctx.arg_kv_size = 0;
@@ -238,7 +239,7 @@ int parse_opt(int argc, char** argv, const char* options) {
238239
while (*++p) {
239240
int arg_type = get_arg_type(*p, options);
240241
if (arg_type == UNDEFINED_OPTION) {
241-
printf("Invalid option '%c'\n", *p);
242+
printf_fn("Invalid option '%c'\n", *p);
242243
return -20;
243244
} else if (arg_type == NO_ARGUMENT) {
244245
save_arg_kv(p, 1, OPTION_ENABLE, 0);
@@ -251,7 +252,7 @@ int parse_opt(int argc, char** argv, const char* options) {
251252
save_arg_kv(p, 1, argv[++i], 0);
252253
break;
253254
} else {
254-
printf("Option '%c' requires param\n", *p);
255+
printf_fn("Option '%c' requires param\n", *p);
255256
return -30;
256257
}
257258
}
@@ -309,7 +310,7 @@ int parse_opt_long(int argc, char** argv, const option_t* long_options, int size
309310
char* delim = strchr(arg, OPTION_DELIM);
310311
if (delim) {
311312
if (delim == arg || delim == arg+arg_len-1 || delim-arg > MAX_OPTION) {
312-
printf("Invalid option '%s'\n", argv[i]);
313+
printf_fn("Invalid option '%s'\n", argv[i]);
313314
return -10;
314315
}
315316
memcpy(opt, arg, delim-arg);
@@ -329,7 +330,7 @@ int parse_opt_long(int argc, char** argv, const option_t* long_options, int size
329330
save_arg_list(arg);
330331
continue;
331332
} else {
332-
printf("Invalid option: '%s'\n", argv[i]);
333+
printf_fn("Invalid option: '%s'\n", argv[i]);
333334
return -10;
334335
}
335336
}
@@ -349,7 +350,7 @@ int parse_opt_long(int argc, char** argv, const option_t* long_options, int size
349350
// --port 80
350351
value = argv[++i];
351352
} else if (pOption->arg_type == REQUIRED_ARGUMENT) {
352-
printf("Option '%s' requires parament\n", opt);
353+
printf_fn("Option '%s' requires parament\n", opt);
353354
return -20;
354355
} else {
355356
// arg_type == OPTIONAL_ARGUMENT
@@ -586,21 +587,22 @@ int signal_init(procedure_t reload_fn, void* reload_userdata) {
586587
#include <mmsystem.h> // for timeSetEvent
587588

588589
// win32 use Event
589-
//static HANDLE s_hEventTerm = NULL;
590+
static HANDLE s_hEventTerm = NULL;
591+
static HANDLE s_hEventTermWait = NULL;
590592
static HANDLE s_hEventReload = NULL;
591593

592594
static void WINAPI on_timer(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) {
593595
DWORD ret;
594-
/*
596+
595597
ret = WaitForSingleObject(s_hEventTerm, 0);
596598
if (ret == WAIT_OBJECT_0) {
597599
hlogi("pid=%d recv event [TERM]", getpid());
598600
if (getpid_from_pidfile() == getpid()) {
601+
SetEvent(s_hEventTermWait);
599602
timeKillEvent(uTimerID);
600603
exit(0);
601604
}
602605
}
603-
*/
604606

605607
ret = WaitForSingleObject(s_hEventReload, 0);
606608
if (ret == WAIT_OBJECT_0) {
@@ -612,8 +614,10 @@ static void WINAPI on_timer(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PT
612614
}
613615

614616
static void signal_cleanup(void) {
615-
//CloseHandle(s_hEventTerm);
616-
//s_hEventTerm = NULL;
617+
CloseHandle(s_hEventTerm);
618+
s_hEventTerm = NULL;
619+
CloseHandle(s_hEventTermWait);
620+
s_hEventTermWait = NULL;
617621
CloseHandle(s_hEventReload);
618622
s_hEventReload = NULL;
619623
}
@@ -623,11 +627,17 @@ int signal_init(procedure_t reload_fn, void* reload_userdata) {
623627
g_main_ctx.reload_userdata = reload_userdata;
624628

625629
char eventname[MAX_PATH] = {0};
626-
//snprintf(eventname, sizeof(eventname), "%s_term_event", g_main_ctx.program_name);
627-
//s_hEventTerm = CreateEvent(NULL, FALSE, FALSE, eventname);
628-
//s_hEventTerm = OpenEvent(EVENT_ALL_ACCESS, FALSE, eventname);
630+
snprintf(eventname, sizeof(eventname), "%s_term_event", g_main_ctx.program_name);
631+
s_hEventTerm = CreateEvent(NULL, FALSE, FALSE, eventname);
632+
if(s_hEventTerm == NULL) return -1;
633+
634+
snprintf(eventname, sizeof(eventname), "%s_term_wait_event", g_main_ctx.program_name);
635+
s_hEventTermWait = CreateEvent(NULL, FALSE, FALSE, eventname);
636+
if(s_hEventTermWait == NULL) return -2;
637+
629638
snprintf(eventname, sizeof(eventname), "%s_reload_event", g_main_ctx.program_name);
630639
s_hEventReload = CreateEvent(NULL, FALSE, FALSE, eventname);
640+
if(s_hEventReload == NULL) return -3;
631641

632642
timeSetEvent(1000, 1000, on_timer, 0, TIME_PERIODIC);
633643

@@ -640,8 +650,8 @@ static void kill_proc(int pid) {
640650
#ifdef OS_UNIX
641651
kill(pid, SIGNAL_TERMINATE);
642652
#else
643-
//SetEvent(s_hEventTerm);
644-
//hv_sleep(1);
653+
SetEvent(s_hEventTerm);
654+
if (WaitForSingleObject(s_hEventTermWait, 2000) == WAIT_OBJECT_0) return;
645655
HANDLE hproc = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
646656
if (hproc) {
647657
TerminateProcess(hproc, 0);
@@ -651,50 +661,55 @@ static void kill_proc(int pid) {
651661
}
652662

653663
void signal_handle(const char* signal) {
664+
if (signal_handle_noexit(signal)) exit(0);
665+
}
666+
667+
bool signal_handle_noexit(const char* signal) {
654668
if (strcmp(signal, "start") == 0) {
655669
if (g_main_ctx.oldpid > 0) {
656-
printf("%s is already running, pid=%d\n", g_main_ctx.program_name, g_main_ctx.oldpid);
657-
exit(0);
670+
printf_fn("%s is already running, pid=%d\n", g_main_ctx.program_name, g_main_ctx.oldpid);
671+
return true;
658672
}
659673
} else if (strcmp(signal, "stop") == 0) {
660674
if (g_main_ctx.oldpid > 0) {
661675
kill_proc(g_main_ctx.oldpid);
662-
printf("%s stop/waiting\n", g_main_ctx.program_name);
676+
printf_fn("%s stop/waiting\n", g_main_ctx.program_name);
663677
} else {
664-
printf("%s is already stopped\n", g_main_ctx.program_name);
678+
printf_fn("%s is already stopped\n", g_main_ctx.program_name);
665679
}
666-
exit(0);
680+
return true;
667681
} else if (strcmp(signal, "restart") == 0) {
668682
if (g_main_ctx.oldpid > 0) {
669683
kill_proc(g_main_ctx.oldpid);
670-
printf("%s stop/waiting\n", g_main_ctx.program_name);
684+
printf_fn("%s stop/waiting\n", g_main_ctx.program_name);
671685
hv_sleep(1);
672686
}
673687
} else if (strcmp(signal, "status") == 0) {
674688
if (g_main_ctx.oldpid > 0) {
675-
printf("%s start/running, pid=%d\n", g_main_ctx.program_name, g_main_ctx.oldpid);
689+
printf_fn("%s start/running, pid=%d\n", g_main_ctx.program_name, g_main_ctx.oldpid);
676690
} else {
677-
printf("%s is already stopped\n", g_main_ctx.program_name);
691+
printf_fn("%s is already stopped\n", g_main_ctx.program_name);
678692
}
679-
exit(0);
693+
return true;
680694
} else if (strcmp(signal, "reload") == 0) {
681695
if (g_main_ctx.oldpid > 0) {
682-
printf("reload confile [%s]\n", g_main_ctx.confile);
696+
printf_fn("reload confile [%s]\n", g_main_ctx.confile);
683697
#ifdef OS_UNIX
684698
kill(g_main_ctx.oldpid, SIGNAL_RELOAD);
685699
#else
686700
SetEvent(s_hEventReload);
687701
#endif
688702
hv_sleep(1);
689703
} else {
690-
printf("%s is already stopped\n", g_main_ctx.program_name);
704+
printf_fn("%s is already stopped\n", g_main_ctx.program_name);
691705
}
692-
exit(0);
706+
return true;
693707
} else {
694-
printf("Invalid signal: '%s'\n", signal);
695-
exit(0);
708+
printf_fn("Invalid signal: '%s'\n", signal);
709+
return true;
696710
}
697-
printf("%s start/running\n", g_main_ctx.program_name);
711+
printf_fn("%s start/running\n", g_main_ctx.program_name);
712+
return false;
698713
}
699714

700715
// master-workers processes

base/hmain.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
BEGIN_EXTERN_C
1414

15+
typedef int (*printf_t)(const char *const fmt, ...);
16+
1517
typedef struct main_ctx_s {
1618
char run_dir[MAX_PATH];
1719
char program_name[MAX_PATH];
@@ -94,6 +96,7 @@ HV_EXPORT pid_t getpid_from_pidfile();
9496
// signal=[start,stop,restart,status,reload]
9597
HV_EXPORT int signal_init(procedure_t reload_fn DEFAULT(NULL), void* reload_userdata DEFAULT(NULL));
9698
HV_EXPORT void signal_handle(const char* signal);
99+
HV_EXPORT bool signal_handle_noexit(const char* signal);
97100
#ifdef OS_UNIX
98101
// we use SIGTERM to quit process, SIGUSR1 to reload confile
99102
#define SIGNAL_TERMINATE SIGTERM
@@ -105,6 +108,7 @@ void signal_handler(int signo);
105108
#define DEFAULT_WORKER_PROCESSES 4
106109
#define MAXNUM_WORKER_PROCESSES 256
107110
HV_EXPORT extern main_ctx_t g_main_ctx;
111+
HV_EXPORT extern printf_t printf_fn;
108112

109113
// master-workers processes
110114
HV_EXPORT int master_workers_run(

0 commit comments

Comments
 (0)