forked from acouzens/open5gs
273 lines
6 KiB
C
273 lines
6 KiB
C
#include "logger.h"
|
|
|
|
#include "core_general.h"
|
|
#include "core_debug.h"
|
|
#include "core_param.h"
|
|
#include "core_file.h"
|
|
#include "core_signal.h"
|
|
|
|
#include <stdio.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
|
|
#define MAX_LOG_FILE_SIZE (6*16*1024) /* 96 KB */
|
|
#define MAX_BACKUP_LOG_FILE_NUM 19 /* 96 KB x 19 */
|
|
#define FILE_CHECK_CYCLE 15
|
|
|
|
static char g_buffer[1024];
|
|
static char g_path[MAX_FILENAME_SIZE] = "wemania.log";
|
|
static file_t *g_file = NULL;
|
|
|
|
static int request_stop = 0;
|
|
|
|
void check_signal(int signum)
|
|
{
|
|
switch (signum)
|
|
{
|
|
case SIGTERM:
|
|
case SIGINT:
|
|
{
|
|
d_info("%s received",
|
|
signum == SIGTERM ? "SIGTERM" : "SIGINT");
|
|
|
|
logger_stop();
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
d_error("Unknown signal number = %d\n", signum);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
status_t log_file_backup()
|
|
{
|
|
status_t rv;
|
|
char fn[MAX_FILENAME_SIZE], nfn[MAX_FILENAME_SIZE];
|
|
file_t *tmpf = NULL;
|
|
int i, j;
|
|
|
|
file_close(g_file);
|
|
|
|
for (i = 0; ; i++)
|
|
{
|
|
sprintf(fn, "%s.%d", g_path, i);
|
|
|
|
rv = file_open(&tmpf, fn, FILE_READ, 0);
|
|
if (rv != CORE_OK)
|
|
break;
|
|
|
|
file_close(tmpf);
|
|
}
|
|
|
|
for (j = i - 1; j >= 0; j--)
|
|
{
|
|
sprintf(fn, "%s.%d", g_path, j);
|
|
sprintf(nfn, "%s.%d", g_path, j + 1);
|
|
|
|
if (j + 1 > MAX_BACKUP_LOG_FILE_NUM)
|
|
{
|
|
rv = file_remove(fn);
|
|
if (rv != CORE_OK)
|
|
{
|
|
fprintf(stderr, "Can't remove '%s'\n", fn);
|
|
return CORE_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rv = file_rename(fn, nfn);
|
|
if (rv != CORE_OK)
|
|
{
|
|
fprintf(stderr, "Can't rename '%s' to '%s'\n", fn, nfn);
|
|
return CORE_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
sprintf(fn, "%s", g_path);
|
|
sprintf(nfn, "%s.0", g_path);
|
|
|
|
rv = file_rename(fn, nfn);
|
|
if (rv != CORE_OK)
|
|
{
|
|
fprintf(stderr, "Can't rename '%s' to '%s'\n", fn, nfn);
|
|
return CORE_ERROR;
|
|
}
|
|
|
|
rv = file_open(&g_file, g_path,
|
|
FILE_CREATE | FILE_WRITE| FILE_APPEND,
|
|
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
|
if (rv != CORE_OK)
|
|
{
|
|
fprintf(stderr, "Cannot open log file '%s'", g_path);
|
|
return CORE_ERROR;
|
|
}
|
|
|
|
return CORE_OK;
|
|
}
|
|
|
|
int logger_start_internal(const char *path)
|
|
{
|
|
status_t rv;
|
|
int ret, count = 0;
|
|
size_t nbytes;
|
|
ssize_t r;
|
|
file_info_t finfo;
|
|
int us;
|
|
fd_set readfd;
|
|
struct timeval timer_val;
|
|
struct sockaddr_un svaddr;
|
|
|
|
/* If path is given, use it */
|
|
if (path)
|
|
strcpy(g_path, path);
|
|
|
|
us = socket(AF_UNIX, SOCK_DGRAM, 0);
|
|
if (us < 0)
|
|
{
|
|
fprintf(stderr, "socket() failed. (%d:%s)\n",
|
|
errno, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
svaddr.sun_family = AF_UNIX;
|
|
strcpy(svaddr.sun_path, D_LOGD_IPC_PATH);
|
|
|
|
ret = bind(us, (struct sockaddr *)&svaddr, sizeof(svaddr));
|
|
if (ret != 0)
|
|
{
|
|
if (errno == EADDRINUSE)
|
|
{
|
|
ret = unlink(D_LOGD_IPC_PATH);
|
|
if (ret != 0)
|
|
{
|
|
fprintf(stderr, "unlink() failed. (%d:%s)\n",
|
|
errno, strerror(errno));
|
|
return -1;
|
|
}
|
|
ret = bind(us, (struct sockaddr *)&svaddr, sizeof(svaddr));
|
|
if (ret != 0)
|
|
{
|
|
fprintf(stderr, "bind() failed 2. (%d:%s)\n",
|
|
errno, strerror(errno));
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "bind() failed. (%d:%s)\n",
|
|
errno, strerror(errno));
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
rv = file_open(&g_file, g_path,
|
|
FILE_CREATE | FILE_WRITE| FILE_APPEND,
|
|
FILE_UREAD | FILE_UWRITE | FILE_GREAD);
|
|
if (rv != CORE_OK)
|
|
{
|
|
fprintf(stderr, "Cannot open log file '%s'\n", g_path);
|
|
close(us);
|
|
return -1;
|
|
}
|
|
|
|
|
|
while (!request_stop)
|
|
{
|
|
timer_val.tv_sec = 0;
|
|
timer_val.tv_usec = 50000;
|
|
FD_ZERO(&readfd);
|
|
FD_SET(us, &readfd);
|
|
|
|
r = select (us+1, &readfd, NULL, NULL, &timer_val);
|
|
if (r == -1)
|
|
{
|
|
if (errno == EINTR)
|
|
break;
|
|
fprintf(stderr, "select() error(%d: %s)",
|
|
errno, strerror(errno));
|
|
}
|
|
|
|
if (r == 0)
|
|
continue;
|
|
|
|
if (FD_ISSET(us, &readfd))
|
|
{
|
|
r = read(us, g_buffer, sizeof(g_buffer));
|
|
|
|
if (r < 0)
|
|
{
|
|
if (errno == EINTR)
|
|
break;
|
|
fprintf(stderr, "read() failed. (%d:%s)\n",
|
|
errno, strerror(errno));
|
|
continue;
|
|
}
|
|
|
|
if (r == 0)
|
|
continue;
|
|
|
|
nbytes = r;
|
|
rv = file_write(g_file, g_buffer, &nbytes);
|
|
if (rv != CORE_OK || r != nbytes)
|
|
{
|
|
fprintf(stderr, "Cannot write %ld bytes to log file (%ld written)\n",
|
|
(long)r, (long)nbytes);
|
|
}
|
|
|
|
if (count % FILE_CHECK_CYCLE == 0)
|
|
{
|
|
file_info_get(&finfo, FILE_INFO_SIZE, g_file);
|
|
if (finfo.size > MAX_LOG_FILE_SIZE)
|
|
{
|
|
log_file_backup();
|
|
}
|
|
}
|
|
|
|
count++;
|
|
}
|
|
}
|
|
|
|
file_close(g_file);
|
|
|
|
close(us);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void logger_start(const char *path)
|
|
{
|
|
pid_t pid;
|
|
pid = fork();
|
|
|
|
d_assert(pid >= 0, _exit(EXIT_FAILURE), "fork() failed");
|
|
|
|
if (pid == 0)
|
|
{
|
|
int ret;
|
|
|
|
/* Child */
|
|
umask(027);
|
|
|
|
signal_unblock(SIGINT);
|
|
signal_unblock(SIGTERM);
|
|
core_signal(SIGINT, check_signal);
|
|
core_signal(SIGTERM, check_signal);
|
|
|
|
ret = logger_start_internal(path);
|
|
d_assert(ret == 0, _exit(EXIT_FAILURE), "logger_start() failed");
|
|
|
|
_exit(EXIT_SUCCESS);
|
|
}
|
|
/* Parent */
|
|
}
|
|
|
|
void logger_stop()
|
|
{
|
|
request_stop = 1;
|
|
}
|