Index: backend/postmaster/postmaster.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v retrieving revision 1.402 diff -u -r1.402 postmaster.c --- backend/postmaster/postmaster.c 3 Jun 2004 02:08:03 -0000 1.402 +++ backend/postmaster/postmaster.c 8 Jun 2004 18:07:30 -0000 @@ -532,6 +532,9 @@ /* If timezone is not set, determine what the OS uses */ pg_timezone_initialize(); + /* open alternate logfile, if any */ + LogFileOpen(); + #ifdef EXEC_BACKEND write_nondefault_variables(PGC_POSTMASTER); #endif Index: backend/storage/ipc/ipc.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/ipc/ipc.c,v retrieving revision 1.87 diff -u -r1.87 ipc.c --- backend/storage/ipc/ipc.c 12 Dec 2003 18:45:09 -0000 1.87 +++ backend/storage/ipc/ipc.c 8 Jun 2004 18:07:31 -0000 @@ -111,6 +111,8 @@ on_proc_exit_list[on_proc_exit_index].arg); elog(DEBUG3, "exit(%d)", code); + + LogFileClose(); exit(code); } Index: backend/utils/adt/misc.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/misc.c,v retrieving revision 1.34 diff -u -r1.34 misc.c --- backend/utils/adt/misc.c 2 Jun 2004 21:29:29 -0000 1.34 +++ backend/utils/adt/misc.c 8 Jun 2004 18:07:36 -0000 @@ -103,3 +103,64 @@ { PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0),SIGINT)); } + +Datum pg_logfile_length(PG_FUNCTION_ARGS) +{ + extern FILE *logfile; // in elog.c + + if (logfile) + PG_RETURN_INT32(ftell(logfile)); + PG_RETURN_INT32(0); +} + + +#define MAXLOGFILECHUNK 50000 +Datum pg_logfile(PG_FUNCTION_ARGS) +{ + size_t size=MAXLOGFILECHUNK; + char *buf=0; + size_t nbytes; + + char *filename = LogFileName(); + if (filename) + { + if (!PG_ARGISNULL(0)) + size = PG_GETARG_INT32(0); + if (size > MAXLOGFILECHUNK) + { + size = MAXLOGFILECHUNK; + ereport(WARNING, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("Maximum size is %d.", MAXLOGFILECHUNK))); + } + + FILE *f=fopen(filename, "r"); + if (f) + { + if (PG_ARGISNULL(1)) + fseek(f, -size, SEEK_END); + else + { + long pos = PG_GETARG_INT32(1); + if (pos >= 0) + fseek(f, pos, SEEK_SET); + else + fseek(f, pos, SEEK_END); + } + buf = palloc(size+1); + nbytes = fread(buf, 1, size, f); + buf[nbytes] = 0; + + fclose(f); + } + else + { + ereport(WARNING, + (errcode(ERRCODE_NO_DATA), + errmsg("Could not open log file %s.", filename))); + } + free(filename); + } + + PG_RETURN_CSTRING(buf); +} Index: backend/utils/error/elog.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/error/elog.c,v retrieving revision 1.140 diff -u -r1.140 elog.c --- backend/utils/error/elog.c 3 Jun 2004 02:08:04 -0000 1.140 +++ backend/utils/error/elog.c 8 Jun 2004 18:07:39 -0000 @@ -71,8 +71,10 @@ PGErrorVerbosity Log_error_verbosity = PGERROR_VERBOSE; char *Log_line_prefix = NULL; /* format for extra log line info */ unsigned int Log_destination = LOG_DESTINATION_STDERR; +char *Log_filename = NULL; bool in_fatal_exit = false; +FILE *logfile = NULL; #ifdef HAVE_SYSLOG char *Syslog_facility; /* openlog() parameters */ @@ -936,6 +938,69 @@ /* + * Name of configured log file, or NULL + * must be freed after usage + */ +char* +LogFileName(void) +{ + if (Log_filename && (Log_destination & LOG_DESTINATION_FILE)) + { + if (is_absolute_path(Log_filename)) + return strdup(Log_filename); + else + { + char *buf = malloc(strlen(DataDir) + strlen(Log_filename) +2); + if (!buf) + ereport(FATAL, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + + sprintf(buf, "%s/%s", DataDir, Log_filename); + + return buf; + } + } + return NULL; +} + + +/* + * Open log file, if configured. + */ +void +LogFileOpen(void) +{ + char *filename = LogFileName(); + + if (filename) + { + LogFileClose(); + + logfile = fopen(filename, "at"); + + if (!logfile) + ereport(WARNING, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("could not open log file %s", filename))); + + free(filename); + } +} + + +/* + * Close log file, if open. + */ +void +LogFileClose(void) +{ + if (logfile) + fclose(logfile); + logfile = NULL; +} + +/* * Initialization of error output file */ void @@ -1445,6 +1510,11 @@ if ((Log_destination & LOG_DESTINATION_STDERR) || whereToSendOutput == Debug) { fprintf(stderr, "%s", buf.data); + } + + if (logfile && (Log_destination & LOG_DESTINATION_FILE)) + { + fprintf(logfile, "%s", buf.data); } pfree(buf.data); Index: backend/utils/misc/guc.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v retrieving revision 1.210 diff -u -r1.210 guc.c --- backend/utils/misc/guc.c 30 May 2004 23:40:38 -0000 1.210 +++ backend/utils/misc/guc.c 8 Jun 2004 18:07:47 -0000 @@ -76,6 +76,8 @@ static const char *assign_log_destination(const char *value, bool doit, GucSource source); +extern char *Log_filename; + #ifdef HAVE_SYSLOG extern char *Syslog_facility; extern char *Syslog_ident; @@ -1644,13 +1646,23 @@ { {"log_destination", PGC_POSTMASTER, LOGGING_WHERE, gettext_noop("Sets the target for log output."), - gettext_noop("Valid values are combinations of stderr, syslog " + gettext_noop("Valid values are combinations of stderr, file, syslog " "and eventlog, depending on platform."), GUC_LIST_INPUT | GUC_REPORT }, &log_destination_string, "stderr", assign_log_destination, NULL }, + { + {"log_filename", PGC_POSTMASTER, LOGGING_WHERE, + gettext_noop("Sets the target filename for log output."), + gettext_noop("May be specified as relative to the cluster directory " + "or as absolute path."), + GUC_LIST_INPUT | GUC_REPORT + }, + &Log_filename, + "postgresql.log", NULL, NULL + }, #ifdef HAVE_SYSLOG { @@ -4775,6 +4787,8 @@ if (pg_strcasecmp(tok,"stderr") == 0) newlogdest |= LOG_DESTINATION_STDERR; + else if (pg_strcasecmp(tok,"file") == 0) + newlogdest |= LOG_DESTINATION_FILE; #ifdef HAVE_SYSLOG else if (pg_strcasecmp(tok,"syslog") == 0) newlogdest |= LOG_DESTINATION_SYSLOG; Index: backend/utils/misc/postgresql.conf.sample =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v retrieving revision 1.113 diff -u -r1.113 postgresql.conf.sample --- backend/utils/misc/postgresql.conf.sample 7 Apr 2004 05:05:50 -0000 1.113 +++ backend/utils/misc/postgresql.conf.sample 8 Jun 2004 18:07:48 -0000 @@ -147,9 +147,10 @@ # - Where to Log - -#log_destination = 'stderr' # Valid values are combinations of stderr, +#log_destination = 'stderr' # Valid values are combinations of stderr, file, # syslog and eventlog, depending on # platform. +#log_filename = 'pgsql.log' #syslog_facility = 'LOCAL0' #syslog_ident = 'postgres' Index: include/catalog/pg_proc.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v retrieving revision 1.334 diff -u -r1.334 pg_proc.h --- include/catalog/pg_proc.h 2 Jun 2004 21:29:29 -0000 1.334 +++ include/catalog/pg_proc.h 8 Jun 2004 18:08:03 -0000 @@ -3588,6 +3588,12 @@ DATA(insert OID = 2243 ( bit_or PGNSP PGUID 12 t f f f i 1 1560 "1560" _null_ aggregate_dummy - _null_)); DESCR("bitwise-or bit aggregate"); +DATA(insert OID = 2550( pg_logfile_length PGNSP PGUID 12 f f f f v 0 23 "" _null_ pg_logfile_length - _null_ )); +DESCR("length of log file"); +DATA(insert OID = 2551( pg_logfile PGNSP PGUID 12 f f f f v 2 2275 "23 23" _null_ pg_logfile - _null_ )); +DESCR("return log file contents"); + + /* * Symbolic values for provolatile column: these indicate whether the result * of a function is dependent *only* on the values of its explicit arguments, Index: include/utils/builtins.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/utils/builtins.h,v retrieving revision 1.241 diff -u -r1.241 builtins.h --- include/utils/builtins.h 2 Jun 2004 21:29:29 -0000 1.241 +++ include/utils/builtins.h 8 Jun 2004 18:08:05 -0000 @@ -356,6 +356,8 @@ extern Datum current_database(PG_FUNCTION_ARGS); extern Datum pg_terminate_backend(PG_FUNCTION_ARGS); extern Datum pg_cancel_backend(PG_FUNCTION_ARGS); +extern Datum pg_logfile_length(PG_FUNCTION_ARGS); +extern Datum pg_logfile(PG_FUNCTION_ARGS); /* not_in.c */ extern Datum int4notin(PG_FUNCTION_ARGS); Index: include/utils/elog.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/utils/elog.h,v retrieving revision 1.68 diff -u -r1.68 elog.h --- include/utils/elog.h 5 Apr 2004 03:02:10 -0000 1.68 +++ include/utils/elog.h 8 Jun 2004 18:08:06 -0000 @@ -182,8 +182,12 @@ #define LOG_DESTINATION_STDERR 1 #define LOG_DESTINATION_SYSLOG 2 #define LOG_DESTINATION_EVENTLOG 4 +#define LOG_DESTINATION_FILE 8 /* Other exported functions */ extern void DebugFileOpen(void); +extern char *LogFileName(void); +extern void LogFileOpen(void); +extern void LogFileClose(void); #endif /* ELOG_H */