15
15
#include <time.h>
16
16
17
17
#include "logger.h"
18
+ #include "pgut.h"
18
19
19
20
/* Logger parameters */
20
21
@@ -25,7 +26,9 @@ char *error_log_filename = NULL;
25
26
char * log_directory = NULL ;
26
27
char log_path [MAXPGPATH ] = "" ;
27
28
29
+ /* Maximum size of an individual log file in kilobytes */
28
30
int log_rotation_size = 0 ;
31
+ /* Maximum lifetime of an individual log file in minutes */
29
32
int log_rotation_age = 0 ;
30
33
31
34
/* Implementation for logging.h */
@@ -102,7 +105,9 @@ elog_internal(int elevel, const char *fmt, va_list args)
102
105
{
103
106
bool wrote_to_file = false;
104
107
105
- pthread_mutex_lock (& log_file_mutex );
108
+ /* There is no need to lock if this is elog() from upper elog() */
109
+ if (!logging_to_file )
110
+ pthread_mutex_lock (& log_file_mutex );
106
111
107
112
/*
108
113
* Write message to log file.
@@ -161,7 +166,8 @@ elog_internal(int elevel, const char *fmt, va_list args)
161
166
fflush (stderr );
162
167
}
163
168
164
- pthread_mutex_unlock (& log_file_mutex );
169
+ if (!logging_to_file )
170
+ pthread_mutex_unlock (& log_file_mutex );
165
171
166
172
/* Exit with code if it is an error */
167
173
if (elevel > WARNING )
@@ -329,56 +335,82 @@ static void
329
335
open_logfile (FILE * * file , const char * filename_format )
330
336
{
331
337
char * filename ;
338
+ char control [MAXPGPATH ];
332
339
struct stat st ;
333
- bool rotation_requested = false;
340
+ FILE * control_file ;
341
+ time_t cur_time = time (NULL );
342
+ bool rotation_requested = false,
343
+ logfile_exists = false;
334
344
335
- filename = logfile_getname (filename_format , time ( NULL ) );
345
+ filename = logfile_getname (filename_format , cur_time );
336
346
337
- /* First check for rotation */
338
- if (log_rotation_size > 0 || log_rotation_age > 0 )
347
+ /* "log_path" was checked in logfile_getname() */
348
+ snprintf (control , MAXPGPATH , "%s/log_rotation" , log_path );
349
+
350
+ if (stat (filename , & st ) == -1 )
339
351
{
340
- if (stat ( filename , & st ) == -1 )
352
+ if (errno == ENOENT )
341
353
{
342
- if (errno == ENOENT )
343
- {
344
- /* There is no file "filename" and rotation does not need */
345
- goto logfile_open ;
346
- }
347
- else
348
- elog (ERROR , "cannot stat log file \"%s\": %s" ,
349
- filename , strerror (errno ));
354
+ /* There is no file "filename" and rotation does not need */
355
+ goto logfile_open ;
350
356
}
351
- /* Found log file "filename" */
357
+ else
358
+ elog (ERROR , "cannot stat log file \"%s\": %s" ,
359
+ filename , strerror (errno ));
360
+ }
361
+ /* Found log file "filename" */
362
+ logfile_exists = true;
352
363
364
+ /* First check for rotation */
365
+ if (log_rotation_size > 0 || log_rotation_age > 0 )
366
+ {
353
367
/* Check for rotation by age */
354
368
if (log_rotation_age > 0 )
355
369
{
356
- char control [MAXPGPATH ];
357
370
struct stat control_st ;
358
- FILE * control_file ;
359
371
360
- snprintf (control , MAXPGPATH , "%s.rotation" , filename );
361
372
if (stat (control , & control_st ) == -1 )
362
373
{
363
- if (errno == ENOENT )
364
- {
365
- /* There is no control file for rotation */
366
- goto logfile_open ;
367
- }
368
- else
374
+ if (errno != ENOENT )
369
375
elog (ERROR , "cannot stat rotation file \"%s\": %s" ,
370
376
control , strerror (errno ));
371
377
}
378
+ else
379
+ {
380
+ char buf [1024 ];
372
381
373
- /* Found control file for rotation */
382
+ control_file = fopen (control , "r" );
383
+ if (control_file == NULL )
384
+ elog (ERROR , "cannot open rotation file \"%s\": %s" ,
385
+ control , strerror (errno ));
386
+
387
+ if (fgets (buf , lengthof (buf ), control_file ))
388
+ {
389
+ time_t creation_time ;
390
+
391
+ if (!parse_int64 (buf , (int64 * ) & creation_time ))
392
+ elog (ERROR , "rotation file \"%s\" has wrong "
393
+ "creation timestamp \"%s\"" ,
394
+ control , buf );
395
+ /* Parsed creation time */
396
+
397
+ rotation_requested = (cur_time - creation_time ) >
398
+ /* convert to seconds */
399
+ log_rotation_age * 60 ;
400
+ }
401
+ else
402
+ elog (ERROR , "cannot read creation timestamp from "
403
+ "rotation file \"%s\"" , control );
374
404
375
- control_file = fopen ( control , "r" );
376
- fclose ( control_file );
405
+ fclose ( control_file );
406
+ }
377
407
}
378
408
379
409
/* Check for rotation by size */
380
410
if (!rotation_requested && log_rotation_size > 0 )
381
- rotation_requested = (st .st_size >= log_rotation_size * 1024L );
411
+ rotation_requested = st .st_size >=
412
+ /* convert to bytes */
413
+ log_rotation_size * 1024L ;
382
414
}
383
415
384
416
logfile_open :
@@ -388,6 +420,21 @@ open_logfile(FILE **file, const char *filename_format)
388
420
* file = logfile_open (filename , "a" );
389
421
pfree (filename );
390
422
423
+ /* Rewrite rotation control file */
424
+ if (rotation_requested || !logfile_exists )
425
+ {
426
+ time_t timestamp = time (NULL );
427
+
428
+ control_file = fopen (control , "w" );
429
+ if (control_file == NULL )
430
+ elog (ERROR , "cannot open rotation file \"%s\": %s" ,
431
+ control , strerror (errno ));
432
+
433
+ fprintf (control_file , "%ld" , timestamp );
434
+
435
+ fclose (control_file );
436
+ }
437
+
391
438
/*
392
439
* Arrange to close opened file at proc_exit.
393
440
*/
0 commit comments