mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
169 lines
3.9 KiB
C
169 lines
3.9 KiB
C
|
/* Copyright (C) 2012 Monty Program Ab
|
||
|
|
||
|
This program is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; version 2 of the License.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||
|
|
||
|
|
||
|
#include "my_global.h"
|
||
|
#include <my_sys.h>
|
||
|
#include <mysql/service_logger.h>
|
||
|
|
||
|
extern char *mysql_data_home;
|
||
|
extern PSI_mutex_key key_LOCK_logger_service;
|
||
|
|
||
|
typedef struct logger_handle_st {
|
||
|
FILE *file;
|
||
|
char path[FN_REFLEN];
|
||
|
long size_limit;
|
||
|
unsigned int rotations;
|
||
|
size_t path_len;
|
||
|
mysql_mutex_t lock;
|
||
|
} LSFS;
|
||
|
|
||
|
|
||
|
static unsigned int n_dig(unsigned int i)
|
||
|
{
|
||
|
return (i == 0) ? 0 : ((i < 10) ? 1 : ((i < 100) ? 2 : 3));
|
||
|
}
|
||
|
|
||
|
|
||
|
LOGGER_HANDLE *logger_open(const char *path,
|
||
|
unsigned long size_limit,
|
||
|
unsigned int rotations)
|
||
|
{
|
||
|
LOGGER_HANDLE new_log, *l_perm;
|
||
|
|
||
|
/*
|
||
|
I don't think we ever need more rotations,
|
||
|
but if it's so, the rotation procedure should be adapted to it.
|
||
|
*/
|
||
|
if (rotations > 999)
|
||
|
return 0;
|
||
|
|
||
|
new_log.rotations= rotations;
|
||
|
new_log.size_limit= size_limit;
|
||
|
new_log.path_len= strlen(fn_format(new_log.path, path,
|
||
|
mysql_data_home, "", MY_UNPACK_FILENAME));
|
||
|
|
||
|
if (new_log.path_len+n_dig(rotations)+1 > FN_REFLEN)
|
||
|
{
|
||
|
errno= ENAMETOOLONG;
|
||
|
/* File path too long */
|
||
|
return 0;
|
||
|
}
|
||
|
if (!(new_log.file= fopen(new_log.path, "a+")))
|
||
|
{
|
||
|
/* Check errno for the cause */
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
setbuf(new_log.file, 0);
|
||
|
fseek(new_log.file, 0, SEEK_END);
|
||
|
if (!(l_perm= (LOGGER_HANDLE *)
|
||
|
my_malloc(sizeof(LOGGER_HANDLE), MYF(0))))
|
||
|
{
|
||
|
fclose(new_log.file);
|
||
|
new_log.file= NULL;
|
||
|
return 0; /* End of memory */
|
||
|
}
|
||
|
*l_perm= new_log;
|
||
|
mysql_mutex_init(key_LOCK_logger_service, &l_perm->lock, MY_MUTEX_INIT_FAST);
|
||
|
return l_perm;
|
||
|
}
|
||
|
|
||
|
int logger_close(LOGGER_HANDLE *log)
|
||
|
{
|
||
|
int result;
|
||
|
mysql_mutex_destroy(&log->lock);
|
||
|
result= fclose(log->file);
|
||
|
my_free(log);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
static char *logname(LOGGER_HANDLE *log, char *buf, unsigned int n_log)
|
||
|
{
|
||
|
sprintf(buf+log->path_len, ".%0*u", n_dig(log->rotations), n_log);
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
|
||
|
static int do_rotate(LOGGER_HANDLE *log)
|
||
|
{
|
||
|
char namebuf[FN_REFLEN];
|
||
|
int result;
|
||
|
unsigned int i;
|
||
|
char *buf_old, *buf_new, *tmp;
|
||
|
|
||
|
memcpy(namebuf, log->path, log->path_len);
|
||
|
|
||
|
buf_new= logname(log, namebuf, log->rotations);
|
||
|
buf_old= log->path;
|
||
|
for (i=log->rotations-1; i>0; i--)
|
||
|
{
|
||
|
logname(log, buf_old, i);
|
||
|
if (!access(buf_old, F_OK) &&
|
||
|
(result= my_rename(buf_old, buf_new, MYF(0))))
|
||
|
return result;
|
||
|
tmp= buf_old;
|
||
|
buf_old= buf_new;
|
||
|
buf_new= tmp;
|
||
|
}
|
||
|
if ((result= fclose(log->file)))
|
||
|
return result;
|
||
|
namebuf[log->path_len]= 0;
|
||
|
result= my_rename(namebuf, logname(log, log->path, 1), MYF(0));
|
||
|
log->file= fopen(namebuf, "a+");
|
||
|
return log->file==NULL || result;
|
||
|
}
|
||
|
|
||
|
|
||
|
int logger_vprintf(LOGGER_HANDLE *log, const char* fmt, va_list ap)
|
||
|
{
|
||
|
int result;
|
||
|
mysql_mutex_lock(&log->lock);
|
||
|
if (ftell(log->file) >= log->size_limit &&
|
||
|
do_rotate(log))
|
||
|
{
|
||
|
result= -1;
|
||
|
goto exit; /* Log rotation needed but failed */
|
||
|
}
|
||
|
|
||
|
result= my_vfprintf(log->file, fmt, ap);
|
||
|
exit:
|
||
|
mysql_mutex_unlock(&log->lock);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
int logger_rotate(LOGGER_HANDLE *log)
|
||
|
{
|
||
|
int result;
|
||
|
mysql_mutex_lock(&log->lock);
|
||
|
result= do_rotate(log);
|
||
|
mysql_mutex_unlock(&log->lock);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...)
|
||
|
{
|
||
|
int result;
|
||
|
va_list args;
|
||
|
va_start(args,fmt);
|
||
|
result= logger_vprintf(log, fmt, args);
|
||
|
va_end(args);
|
||
|
return result;
|
||
|
}
|
||
|
|