Compare commits
4 Commits
Release41-
...
Release41-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5ca3ccf43 | ||
|
|
a6cb6061ec | ||
|
|
995d5dce95 | ||
|
|
c21be04632 |
@@ -126,7 +126,7 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
|
||||
1. **高性能、占用资源少**
|
||||
多线程异步 IO 模式,cache 缓存查询结果。
|
||||
|
||||
1. **主流系统官方支持**
|
||||
1. **主流系统官方支持**
|
||||
主流路由系统官方软件源安装smartdns。
|
||||
|
||||
## 架构
|
||||
|
||||
@@ -121,7 +121,7 @@ From the comparison, smartdns found the fastest IP address to visit www.baidu.co
|
||||
1. **High performance, low resource consumption**
|
||||
Multi-threaded asynchronous IO mode, cache cache query results.
|
||||
|
||||
1. **DNS domain forwarding**
|
||||
1. **DNS domain forwarding**
|
||||
Support DNS forwarding, ipset and nftables. Support setting the domain result to ipset and nftset set when speed check fails.
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -82,6 +82,9 @@ msgstr "协议类型"
|
||||
msgid "DNS domain result cache size"
|
||||
msgstr "缓存DNS的结果,缓存大小,配置零则不缓存"
|
||||
|
||||
msgid "DNS64 Server Settings"
|
||||
msgstr "DNS64服务器配置"
|
||||
|
||||
msgid "Description"
|
||||
msgstr "描述"
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ s.anonymous = true
|
||||
s:tab("settings", translate("General Settings"))
|
||||
s:tab("advanced", translate('Advanced Settings'))
|
||||
s:tab("seconddns", translate("Second Server Settings"))
|
||||
s:tab("dns64", translate("DNS64 Server Settings"))
|
||||
s:tab("proxy", translate("Proxy Server Settings"))
|
||||
s:tab("custom", translate("Custom Settings"))
|
||||
|
||||
@@ -371,6 +372,12 @@ function o.validate(self, value)
|
||||
return value
|
||||
end
|
||||
|
||||
----- dns64 server settings
|
||||
o = s:taboption("dns64", Value, "dns64", translate("DNS64"));
|
||||
o.placeholder = "64:ff9b::/96"
|
||||
o.datatype = 'ip6addr'
|
||||
o.rmempty = true
|
||||
|
||||
----- custom settings
|
||||
custom = s:taboption("custom", Value, "Custom Settings",
|
||||
translate(""),
|
||||
|
||||
@@ -90,6 +90,9 @@ msgstr "协议类型"
|
||||
msgid "DNS domain result cache size"
|
||||
msgstr "缓存DNS的结果,缓存大小,配置零则不缓存"
|
||||
|
||||
msgid "DNS64 Server Settings"
|
||||
msgstr "DNS64服务器配置"
|
||||
|
||||
msgid "default"
|
||||
msgstr "默认"
|
||||
|
||||
|
||||
@@ -131,6 +131,7 @@ return view.extend({
|
||||
s.tab("settings", _("General Settings"));
|
||||
s.tab("advanced", _('Advanced Settings'));
|
||||
s.tab("seconddns", _("Second Server Settings"));
|
||||
s.tab("dns64", _("DNS64 Server Settings"));
|
||||
s.tab("files", _("Download Files Setting"), _("Download domain list files for domain-rule and include config files, please refresh the page after download to take effect."));
|
||||
s.tab("proxy", _("Proxy Server Settings"));
|
||||
s.tab("custom", _("Custom Settings"));
|
||||
@@ -430,6 +431,14 @@ return view.extend({
|
||||
o.rmempty = false;
|
||||
o.default = o.disabled;
|
||||
|
||||
///////////////////////////////////////
|
||||
// DNS64 Settings
|
||||
///////////////////////////////////////
|
||||
o = s.taboption("dns64", form.Value, "dns64", _("DNS64"));
|
||||
o.placeholder = "64:ff9b::/96";
|
||||
o.datatype = "ip6addr";
|
||||
o.rempty = true;
|
||||
|
||||
///////////////////////////////////////
|
||||
// download Files Settings
|
||||
///////////////////////////////////////
|
||||
|
||||
@@ -480,6 +480,7 @@ load_service()
|
||||
config_get port "$section" "port" "53"
|
||||
config_get ipv6_server "$section" "ipv6_server" "1"
|
||||
config_get tcp_server "$section" "tcp_server" "1"
|
||||
config_get server_flags "$section" "server_flags" ""
|
||||
|
||||
config_get speed_check_mode "$section" "speed_check_mode" ""
|
||||
[ ! -z "$speed_check_mode" ] && conf_append "speed-check-mode" "$speed_check_mode"
|
||||
@@ -563,6 +564,9 @@ load_service()
|
||||
config_get proxy_server "$section" "proxy_server" ""
|
||||
[ -z "$proxy_server" ] || conf_append "proxy-server" "$proxy_server -name default-proxy"
|
||||
|
||||
config_get dns64 "$section" "dns64" ""
|
||||
[ -z "$dns64" ] || conf_append "dns64" "$dns64"
|
||||
|
||||
config_get redirect "$section" "redirect" ""
|
||||
config_get old_port "$section" "old_port" "0"
|
||||
config_get old_enabled "$section" "old_enabled" "0"
|
||||
@@ -629,7 +633,7 @@ load_service()
|
||||
[ "$auto_set_dnsmasq" = "0" ] && [ "$old_auto_set_dnsmasq" = "1" ] && stop_forward_dnsmasq "$old_port" "0"
|
||||
}
|
||||
|
||||
conf_append_bind "$port" "$device" "$tcp_server" "$ipv6_server" "$ARGS"
|
||||
conf_append_bind "$port" "$device" "$tcp_server" "$ipv6_server" "$server_flags"
|
||||
|
||||
load_second_server "$section"
|
||||
|
||||
|
||||
@@ -343,28 +343,28 @@ case "$1" in
|
||||
$SMARTDNS_BIN -c "$SMARTDNS_CONF" -p $SMARTDNS_PID
|
||||
if [ $? -ne 0 ]; then
|
||||
clear_rule
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
status)
|
||||
pid="$(cat $SMARTDNS_PID |head -n 1 2>/dev/null)"
|
||||
if [ -z "$pid" ]; then
|
||||
echo "smartdns not running."
|
||||
return 0
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -d "/proc/$pid" ]; then
|
||||
echo "smartdns running"
|
||||
return 0;
|
||||
echo "smartdns is running"
|
||||
exit 0
|
||||
fi
|
||||
echo "smartdns not running."
|
||||
return 0;
|
||||
exit 0
|
||||
;;
|
||||
stop)
|
||||
clear_rule
|
||||
pid="$(cat "$SMARTDNS_PID" | head -n 1 2>/dev/null)"
|
||||
if [ -z "$pid" ]; then
|
||||
echo "smartdns not running."
|
||||
return 0
|
||||
exit 0
|
||||
fi
|
||||
|
||||
kill -15 "$pid" 2>/dev/null
|
||||
@@ -379,17 +379,17 @@ case "$1" in
|
||||
do
|
||||
pid="$(cat "$SMARTDNS_PID" | head -n 1 2>/dev/null)"
|
||||
if [ -z "$pid" ]; then
|
||||
return 0
|
||||
break
|
||||
fi
|
||||
|
||||
if [ ! -d "/proc/$pid" ]; then
|
||||
return 0
|
||||
break
|
||||
fi
|
||||
|
||||
stat="$(cat /proc/${pid}/stat | awk '{print $3}' 2>/dev/null)"
|
||||
if [ "$stat" = "Z" ]; then
|
||||
$SLEEP $SLEEPTIME
|
||||
return 0
|
||||
break
|
||||
fi
|
||||
|
||||
$SLEEP $SLEEPTIME 2>/dev/null
|
||||
@@ -397,11 +397,15 @@ case "$1" in
|
||||
done
|
||||
|
||||
kill -9 "$pid" 2>/dev/null
|
||||
clear_rule
|
||||
exit 0
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
reload)
|
||||
;;
|
||||
enable)
|
||||
nvram set apps_state_enable=2
|
||||
nvram set apps_state_error=0
|
||||
|
||||
141
src/dns_client.c
141
src/dns_client.c
@@ -41,13 +41,14 @@
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@@ -196,7 +197,6 @@ struct dns_client {
|
||||
|
||||
/* query list */
|
||||
struct list_head dns_request_list;
|
||||
pthread_cond_t run_cond;
|
||||
atomic_t run_period;
|
||||
atomic_t dns_server_num;
|
||||
|
||||
@@ -208,6 +208,8 @@ struct dns_client {
|
||||
pthread_mutex_t domain_map_lock;
|
||||
DECLARE_HASHTABLE(domain_map, 6);
|
||||
DECLARE_HASHTABLE(group, 4);
|
||||
|
||||
int fd_wakeup;
|
||||
};
|
||||
|
||||
/* dns replied server info */
|
||||
@@ -264,6 +266,8 @@ static pthread_mutex_t pending_server_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int dns_client_has_bootstrap_dns = 0;
|
||||
|
||||
static int _dns_client_send_udp(struct dns_server_info *server_info, void *packet, int len);
|
||||
static void _dns_client_clear_wakeup_event(void);
|
||||
static void _dns_client_do_wakeup_event(void);
|
||||
|
||||
static ssize_t _ssl_read(struct dns_server_info *server, void *buff, int num)
|
||||
{
|
||||
@@ -1337,9 +1341,8 @@ static int _dns_client_server_pending(char *server_ip, int port, dns_server_type
|
||||
atomic_set(&client.run_period, 1);
|
||||
pthread_mutex_unlock(&pending_server_mutex);
|
||||
|
||||
pthread_mutex_lock(&client.domain_map_lock);
|
||||
pthread_cond_signal(&client.run_cond);
|
||||
pthread_mutex_unlock(&client.domain_map_lock);
|
||||
_dns_client_do_wakeup_event();
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
if (pending) {
|
||||
@@ -1514,7 +1517,7 @@ static void _dns_client_check_tcp(void)
|
||||
}
|
||||
|
||||
if (server_info->status == DNS_SERVER_STATUS_CONNECTING) {
|
||||
if (server_info->last_send + DNS_TCP_CONNECT_TIMEOUT < now) {
|
||||
if (server_info->last_recv + DNS_TCP_CONNECT_TIMEOUT < now) {
|
||||
tlog(TLOG_DEBUG, "server %s connect timeout.", server_info->ip);
|
||||
_dns_client_close_socket(server_info);
|
||||
}
|
||||
@@ -3569,7 +3572,7 @@ int dns_client_query(const char *domain, int qtype, dns_client_callback callback
|
||||
pthread_mutex_lock(&client.domain_map_lock);
|
||||
if (hash_hashed(&query->domain_node)) {
|
||||
if (list_empty(&client.dns_request_list)) {
|
||||
pthread_cond_signal(&client.run_cond);
|
||||
_dns_client_do_wakeup_event();
|
||||
}
|
||||
|
||||
list_add_tail(&query->dns_request_list, &client.dns_request_list);
|
||||
@@ -3818,15 +3821,12 @@ static void _dns_client_period_run_second(void)
|
||||
_dns_client_add_pending_servers();
|
||||
}
|
||||
|
||||
static void _dns_client_period_run(void)
|
||||
static void _dns_client_period_run(unsigned int msec)
|
||||
{
|
||||
struct dns_query_struct *query = NULL;
|
||||
struct dns_query_struct *tmp = NULL;
|
||||
static unsigned int msec = 0;
|
||||
msec++;
|
||||
|
||||
LIST_HEAD(check_list);
|
||||
|
||||
unsigned long now = get_tick_count();
|
||||
|
||||
/* get query which timed out to check list */
|
||||
@@ -3869,9 +3869,11 @@ static void *_dns_client_work(void *arg)
|
||||
int i = 0;
|
||||
unsigned long now = {0};
|
||||
unsigned long last = {0};
|
||||
unsigned int msec = 0;
|
||||
unsigned int sleep = 100;
|
||||
int sleep_time = 0;
|
||||
unsigned long expect_time = 0;
|
||||
int unused __attribute__((unused));
|
||||
|
||||
sleep_time = sleep;
|
||||
now = get_tick_count() - sleep;
|
||||
@@ -3884,11 +3886,17 @@ static void *_dns_client_work(void *arg)
|
||||
if (sleep_time <= 0) {
|
||||
sleep_time = 0;
|
||||
}
|
||||
|
||||
int cnt = sleep_time / sleep;
|
||||
msec -= cnt;
|
||||
expect_time -= cnt * sleep;
|
||||
sleep_time -= cnt * sleep;
|
||||
}
|
||||
|
||||
if (now >= expect_time) {
|
||||
msec++;
|
||||
if (last != now) {
|
||||
_dns_client_period_run();
|
||||
_dns_client_period_run(msec);
|
||||
}
|
||||
|
||||
sleep_time = sleep - (now - expect_time);
|
||||
@@ -3896,19 +3904,21 @@ static void *_dns_client_work(void *arg)
|
||||
sleep_time = 0;
|
||||
expect_time = now;
|
||||
}
|
||||
|
||||
/* When client is idle, the sleep time is 1000ms, to reduce CPU usage */
|
||||
pthread_mutex_lock(&client.domain_map_lock);
|
||||
if (list_empty(&client.dns_request_list)) {
|
||||
int cnt = 10 - (msec % 10) - 1;
|
||||
sleep_time += sleep * cnt;
|
||||
msec += cnt;
|
||||
/* sleep to next second */
|
||||
expect_time += sleep * cnt;
|
||||
}
|
||||
pthread_mutex_unlock(&client.domain_map_lock);
|
||||
expect_time += sleep;
|
||||
}
|
||||
last = now;
|
||||
|
||||
pthread_mutex_lock(&client.domain_map_lock);
|
||||
if (list_empty(&client.dns_request_list) && atomic_read(&client.run_period) == 0) {
|
||||
pthread_cond_wait(&client.run_cond, &client.domain_map_lock);
|
||||
expect_time = get_tick_count();
|
||||
pthread_mutex_unlock(&client.domain_map_lock);
|
||||
continue;
|
||||
}
|
||||
pthread_mutex_unlock(&client.domain_map_lock);
|
||||
|
||||
num = epoll_wait(client.epoll_fd, events, DNS_MAX_EVENTS, sleep_time);
|
||||
if (num < 0) {
|
||||
usleep(100000);
|
||||
@@ -3918,6 +3928,11 @@ static void *_dns_client_work(void *arg)
|
||||
for (i = 0; i < num; i++) {
|
||||
struct epoll_event *event = &events[i];
|
||||
struct dns_server_info *server_info = (struct dns_server_info *)event->data.ptr;
|
||||
if (event->data.fd == client.fd_wakeup) {
|
||||
_dns_client_clear_wakeup_event();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (server_info == NULL) {
|
||||
tlog(TLOG_WARN, "server info is invalid.");
|
||||
continue;
|
||||
@@ -3971,10 +3986,71 @@ int dns_client_set_ecs(char *ip, int subnet)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_client_create_wakeup_event(void)
|
||||
{
|
||||
int fd_wakeup = -1;
|
||||
|
||||
fd_wakeup = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
if (fd_wakeup < 0) {
|
||||
tlog(TLOG_ERROR, "create eventfd failed, %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
struct epoll_event event;
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.events = EPOLLIN;
|
||||
event.data.fd = fd_wakeup;
|
||||
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_ADD, fd_wakeup, &event) < 0) {
|
||||
tlog(TLOG_ERROR, "add eventfd to epoll failed, %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return fd_wakeup;
|
||||
|
||||
errout:
|
||||
if (fd_wakeup > 0) {
|
||||
close(fd_wakeup);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void _dns_client_close_wakeup_event(void)
|
||||
{
|
||||
if (client.fd_wakeup > 0) {
|
||||
close(client.fd_wakeup);
|
||||
client.fd_wakeup = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void _dns_client_clear_wakeup_event(void)
|
||||
{
|
||||
uint64_t val = 0;
|
||||
int unused __attribute__((unused));
|
||||
|
||||
if (client.fd_wakeup <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
unused = read(client.fd_wakeup, &val, sizeof(val));
|
||||
}
|
||||
|
||||
static void _dns_client_do_wakeup_event(void)
|
||||
{
|
||||
uint64_t val = 1;
|
||||
int unused __attribute__((unused));
|
||||
if (client.fd_wakeup <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
unused = write(client.fd_wakeup, &val, sizeof(val));
|
||||
}
|
||||
|
||||
int dns_client_init(void)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
int epollfd = -1;
|
||||
int fd_wakeup = -1;
|
||||
int ret = 0;
|
||||
|
||||
if (client.epoll_fd > 0) {
|
||||
@@ -4002,8 +4078,6 @@ int dns_client_init(void)
|
||||
hash_init(client.group);
|
||||
INIT_LIST_HEAD(&client.dns_request_list);
|
||||
|
||||
pthread_cond_init(&client.run_cond, NULL);
|
||||
|
||||
if (dns_client_add_group(DNS_SERVER_GROUP_DEFAULT) != 0) {
|
||||
tlog(TLOG_ERROR, "add default server group failed.");
|
||||
goto errout;
|
||||
@@ -4020,6 +4094,14 @@ int dns_client_init(void)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
fd_wakeup = _dns_client_create_wakeup_event();
|
||||
if (fd_wakeup < 0) {
|
||||
tlog(TLOG_ERROR, "create wakeup event failed, %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
client.fd_wakeup = fd_wakeup;
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
if (client.tid) {
|
||||
@@ -4029,13 +4111,16 @@ errout:
|
||||
client.tid = 0;
|
||||
}
|
||||
|
||||
if (epollfd) {
|
||||
if (epollfd > 0) {
|
||||
close(epollfd);
|
||||
}
|
||||
|
||||
if (fd_wakeup > 0) {
|
||||
close(fd_wakeup);
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&client.server_list_lock);
|
||||
pthread_mutex_destroy(&client.domain_map_lock);
|
||||
pthread_cond_destroy(&client.run_cond);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -4045,14 +4130,13 @@ void dns_client_exit(void)
|
||||
if (client.tid) {
|
||||
void *ret = NULL;
|
||||
atomic_set(&client.run, 0);
|
||||
pthread_mutex_lock(&client.domain_map_lock);
|
||||
pthread_cond_signal(&client.run_cond);
|
||||
pthread_mutex_unlock(&client.domain_map_lock);
|
||||
_dns_client_do_wakeup_event();
|
||||
pthread_join(client.tid, &ret);
|
||||
client.tid = 0;
|
||||
}
|
||||
|
||||
/* free all resources */
|
||||
_dns_client_close_wakeup_event();
|
||||
_dns_client_remove_all_pending_servers();
|
||||
_dns_client_server_remove_all();
|
||||
_dns_client_query_remove_all();
|
||||
@@ -4060,7 +4144,6 @@ void dns_client_exit(void)
|
||||
|
||||
pthread_mutex_destroy(&client.server_list_lock);
|
||||
pthread_mutex_destroy(&client.domain_map_lock);
|
||||
pthread_cond_destroy(&client.run_cond);
|
||||
if (client.ssl_ctx) {
|
||||
SSL_CTX_free(client.ssl_ctx);
|
||||
client.ssl_ctx = NULL;
|
||||
|
||||
@@ -346,9 +346,9 @@ static int _dns_server_get_conf_ttl(struct dns_request *request, int ttl)
|
||||
return rr_ttl;
|
||||
}
|
||||
|
||||
if (rr_ttl_max > 0 && ttl > rr_ttl_max) {
|
||||
if (rr_ttl_max > 0 && ttl >= rr_ttl_max) {
|
||||
ttl = rr_ttl_max;
|
||||
} else if (rr_ttl_min > 0 && ttl < rr_ttl_min) {
|
||||
} else if (rr_ttl_min > 0 && ttl <= rr_ttl_min) {
|
||||
ttl = rr_ttl_min;
|
||||
}
|
||||
|
||||
@@ -2948,6 +2948,12 @@ static int _dns_server_passthrough_rule_check(struct dns_request *request, const
|
||||
dns_get_CNAME(rrs, name, DNS_MAX_CNAME_LEN, &ttl, cname, DNS_MAX_CNAME_LEN);
|
||||
} break;
|
||||
default:
|
||||
if (ttl == 0) {
|
||||
/* Get TTL */
|
||||
char tmpname[DNS_MAX_CNAME_LEN];
|
||||
char tmpbuf[DNS_MAX_CNAME_LEN];
|
||||
dns_get_CNAME(rrs, tmpname, DNS_MAX_CNAME_LEN, &ttl, tmpbuf, DNS_MAX_CNAME_LEN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
70
src/tlog.c
70
src/tlog.c
@@ -110,6 +110,7 @@ struct tlog {
|
||||
tlog_log_output_func output_func;
|
||||
struct tlog_log *wait_on_log;
|
||||
int is_wait;
|
||||
char gzip_cmd[PATH_MAX];
|
||||
};
|
||||
|
||||
struct tlog_segment_log_head {
|
||||
@@ -520,7 +521,7 @@ static int _tlog_vprintf(struct tlog_log *log, vprint_callback print_callback, v
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlikely(log->logcount <= 0 && log->logscreen == 0) ) {
|
||||
if (unlikely(log->logcount <= 0 && log->logscreen == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1018,7 +1019,6 @@ errout:
|
||||
static int _tlog_archive_log_compressed(struct tlog_log *log)
|
||||
{
|
||||
char gzip_file[TLOG_BUFF_LEN];
|
||||
char gzip_cmd[PATH_MAX * 2];
|
||||
char log_file[TLOG_BUFF_LEN];
|
||||
char pending_file[TLOG_BUFF_LEN];
|
||||
|
||||
@@ -1046,12 +1046,11 @@ static int _tlog_archive_log_compressed(struct tlog_log *log)
|
||||
}
|
||||
|
||||
/* start gzip process to compress log file */
|
||||
snprintf(gzip_cmd, sizeof(gzip_cmd), "gzip -1 %s", pending_file);
|
||||
if (log->zip_pid <= 0) {
|
||||
int pid = vfork();
|
||||
if (pid == 0) {
|
||||
_tlog_close_all_fd();
|
||||
execl("/bin/sh", "sh", "-c", gzip_cmd, NULL);
|
||||
execl(tlog.gzip_cmd, "-1", pending_file, NULL);
|
||||
_exit(1);
|
||||
} else if (pid < 0) {
|
||||
goto errout;
|
||||
@@ -1363,12 +1362,26 @@ static struct tlog_log *_tlog_wait_log_locked(struct tlog_log *last_log)
|
||||
int ret = 0;
|
||||
struct timespec tm;
|
||||
struct tlog_log *log = NULL;
|
||||
struct tlog_log *next = NULL;
|
||||
int need_wait_pid = 0;
|
||||
|
||||
for (next = tlog.log; next != NULL; next = next->next) {
|
||||
if (next->zip_pid > 0) {
|
||||
need_wait_pid = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &tm);
|
||||
tm.tv_sec += 2;
|
||||
tlog.is_wait = 1;
|
||||
tlog.wait_on_log = last_log;
|
||||
ret = pthread_cond_timedwait(&tlog.cond, &tlog.lock, &tm);
|
||||
if (need_wait_pid != 0) {
|
||||
ret = pthread_cond_timedwait(&tlog.cond, &tlog.lock, &tm);
|
||||
} else {
|
||||
ret = pthread_cond_wait(&tlog.cond, &tlog.lock);
|
||||
}
|
||||
|
||||
tlog.is_wait = 0;
|
||||
tlog.wait_on_log = NULL;
|
||||
errno = ret;
|
||||
@@ -1676,6 +1689,15 @@ int tlog_setlevel(tlog_level level)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tlog_log_enabled(tlog_level level)
|
||||
{
|
||||
if (level >= TLOG_END) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (tlog_set_level >= level) ? 1 : 0;
|
||||
}
|
||||
|
||||
tlog_level tlog_getlevel(void)
|
||||
{
|
||||
return tlog_set_level;
|
||||
@@ -1686,6 +1708,35 @@ void tlog_set_logfile(const char *logfile)
|
||||
tlog_rename_logfile(tlog.root, logfile);
|
||||
}
|
||||
|
||||
static void _tlog_get_gzip_cmd_path(void)
|
||||
{
|
||||
char *copy_path = NULL;
|
||||
char gzip_cmd_path[PATH_MAX];
|
||||
const char *env_path = getenv("PATH");
|
||||
char *save_ptr = NULL;
|
||||
|
||||
if (env_path == NULL) {
|
||||
env_path = "/bin:/usr/bin:/usr/local/bin";
|
||||
}
|
||||
|
||||
copy_path = strdup(env_path);
|
||||
if (copy_path == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (char *tok = strtok_r(copy_path, ":", &save_ptr); tok; tok = strtok_r(NULL, ":", &save_ptr)) {
|
||||
snprintf(gzip_cmd_path, sizeof(gzip_cmd_path), "%s/gzip", tok);
|
||||
if (access(gzip_cmd_path, X_OK) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
snprintf(tlog.gzip_cmd, sizeof(tlog.gzip_cmd), "%s", gzip_cmd_path);
|
||||
break;
|
||||
}
|
||||
|
||||
free(copy_path);
|
||||
}
|
||||
|
||||
tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag)
|
||||
{
|
||||
struct tlog_log *log = NULL;
|
||||
@@ -1726,6 +1777,10 @@ tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int bu
|
||||
log->file_perm = S_IRUSR | S_IWUSR | S_IRGRP;
|
||||
log->archive_perm = S_IRUSR | S_IRGRP;
|
||||
|
||||
if (log->nocompress == 0 && tlog.gzip_cmd[0] == '\0') {
|
||||
log->nocompress = 1;
|
||||
}
|
||||
|
||||
tlog_rename_logfile(log, logfile);
|
||||
if (log->nocompress) {
|
||||
strncpy(log->suffix, TLOG_SUFFIX_LOG, sizeof(log->suffix));
|
||||
@@ -1859,6 +1914,7 @@ int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int buffsize
|
||||
memset(&tlog, 0, sizeof(tlog));
|
||||
tlog.is_wait = 0;
|
||||
|
||||
_tlog_get_gzip_cmd_path();
|
||||
pthread_attr_init(&attr);
|
||||
pthread_cond_init(&tlog.cond, NULL);
|
||||
pthread_mutex_init(&tlog.lock, NULL);
|
||||
@@ -1871,6 +1927,10 @@ int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int buffsize
|
||||
}
|
||||
tlog_reg_output_func(log, _tlog_root_write_log);
|
||||
|
||||
if ((flag & TLOG_NOCOMPRESS) == 0 && tlog.gzip_cmd[0] == '\0') {
|
||||
fprintf(stderr, "can not find gzip command, disable compress.\n");
|
||||
}
|
||||
|
||||
tlog.root = log;
|
||||
ret = pthread_create(&tlog.tid, &attr, _tlog_work, NULL);
|
||||
if (ret != 0) {
|
||||
|
||||
13
src/tlog.h
13
src/tlog.h
@@ -79,9 +79,9 @@ level: Current log Levels
|
||||
format: Log formats
|
||||
*/
|
||||
#ifndef BASE_FILE_NAME
|
||||
#define BASE_FILE_NAME \
|
||||
(__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 \
|
||||
: __FILE__)
|
||||
#define BASE_FILE_NAME \
|
||||
(__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 \
|
||||
: __FILE__)
|
||||
#endif
|
||||
#define tlog(level, format, ...) tlog_ext(level, BASE_FILE_NAME, __LINE__, __func__, NULL, format, ##__VA_ARGS__)
|
||||
|
||||
@@ -95,6 +95,9 @@ extern int tlog_write_log(char *buff, int bufflen);
|
||||
/* set log level */
|
||||
extern int tlog_setlevel(tlog_level level);
|
||||
|
||||
/* is log level enabled*/
|
||||
extern int tlog_log_enabled(tlog_level level);
|
||||
|
||||
/* get log level */
|
||||
extern tlog_level tlog_getlevel(void);
|
||||
|
||||
@@ -137,7 +140,7 @@ read _tlog_format for example.
|
||||
typedef int (*tlog_format_func)(char *buff, int maxlen, struct tlog_loginfo *info, void *userptr, const char *format, va_list ap);
|
||||
extern int tlog_reg_format_func(tlog_format_func func);
|
||||
|
||||
/* register log output callback
|
||||
/* register log output callback
|
||||
Note: info is invalid when flag TLOG_SEGMENT is not set.
|
||||
*/
|
||||
typedef int (*tlog_log_output_func)(struct tlog_loginfo *info, const char *buff, int bufflen, void *private_data);
|
||||
@@ -213,7 +216,7 @@ file: log file permission, default is 640
|
||||
archive: archive file permission, default is 440
|
||||
*/
|
||||
|
||||
extern void tlog_set_permission(struct tlog_log *log, mode_t file, mode_t archive);
|
||||
extern void tlog_set_permission(struct tlog_log *log, mode_t file, mode_t archive);
|
||||
|
||||
#ifdef __cplusplus
|
||||
class Tlog {
|
||||
|
||||
Reference in New Issue
Block a user