Le 07/04/2016 08:30, Karl O. Pinc a écrit : > On Thu, 7 Apr 2016 01:13:51 -0500 > "Karl O. Pinc" <k...@meme.com> wrote: > >> On Wed, 6 Apr 2016 23:37:09 -0500 >> "Karl O. Pinc" <k...@meme.com> wrote: >> >>> On Wed, 6 Apr 2016 22:26:13 -0500 >>> "Karl O. Pinc" <k...@meme.com> wrote: >>>> On Wed, 23 Mar 2016 23:22:26 +0100 >>>> Gilles Darold <gilles.dar...@dalibo.com> wrote: >>>> >>>>> Thanks for the reminder, here is the v3 of the patch after a >>>>> deeper review and testing. It is now registered to the next >>>>> commit fest under the System Administration topic. >> This is what I see at the moment. I'll wait for replies >> before looking further and writing more. > Er, one more thing. Isn't it true that in logfile_rotate() > you only need to call store_current_log_filename() when > logfile_open() is called with a "w" mode, and never need to > call it when logfile_open() is called with an "a" mode? > > > Karl <k...@meme.com> > Free Software: "You don't pay back, you pay forward." > -- Robert A. Heinlein > >
Hi Karl, Thank you very much for the patch review and please apologies this too long response delay. I was traveling since end of April and totally forgotten this patch. I have applied all your useful feedbacks on the patch and attached a new one (v4) to this email : - Fix the missing <row> in doc/src/sgml/func.sgml - Rewrite pg_current_logfile descritption as suggested - Remove comment in src/backend/postmaster/syslogger.c - Use pgrename to first write the filename to a temporary file before overriding the last log file. - Rename store_current_log_filename() into logfile_writename() - logfile_getname is used to retrieve the filename. - Use logfile_open() to enable CRLF line endings on Windows - Change log level for when it can't create pg_log_file, from WARNING to LOG - Remove NOTICE message when the syslogger is not enabled, the function return null. On other questions: > "src/backend/postmaster/syslogger.c expects to see fopen() fail with ENFILE and EMFILE. What will you do if you get these?" - Nothing, if the problem occurs during the log rotate call, then log rotation file is disabled so logfile_writename() will not be called. Case where the problem occurs between the rotation call and the logfile_writename() call is possible but I don't think that it will be useful to try again. In this last case log filename will be updated during next rotation. > "Have you given any thought as to when logfile_rotate() is called? Since logfile_rotate() itself logs with ereport(), it would _seem_ safe to ereport() from within your store_current_log_filename(), called from within logfile_rotate()." - Other part of logfile_rotate() use ereport() so I guess it is safe to use it. > "The indentation of the ereport(), in the part that continues over multiple lines" - This was my first thought but seeing what is done in the other call to ereport() I think I have done it the right way. > "Isn't it true that in logfile_rotate() you only need to call store_current_log_filename() when logfile_open() is called with a "w" mode, and never need to call it when logfile_open() is called with an "a" mode?" - No, it is false, append mode is used when logfile_rotate used an existing file but the filename still change. Best regards, -- Gilles Darold Consultant PostgreSQL http://dalibo.com - http://dalibo.org
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 3f627dc..7100881 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -15293,6 +15293,12 @@ SELECT * FROM pg_ls_dir('.') WITH ORDINALITY AS t(ls,n); </row> <row> + <entry><literal><function>pg_current_logfile()</function></literal></entry> + <entry><type>text</type></entry> + <entry>current log file used by the logging collector</entry> + </row> + + <row> <entry><literal><function>session_user</function></literal></entry> <entry><type>name</type></entry> <entry>session user name</entry> @@ -15499,6 +15505,17 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, .. <primary>pg_notification_queue_usage</primary> </indexterm> + <indexterm> + <primary>pg_current_logfile</primary> + </indexterm> + + <para> + <function>pg_current_logfile</function> returns the name of the + current log file used by the logging collector, as + <type>text</type>. Log collection must be active or the + return value is undefined. + </para> + <para> <function>pg_listening_channels</function> returns a set of names of asynchronous notification channels that the current session is listening diff --git a/doc/src/sgml/storage.sgml b/doc/src/sgml/storage.sgml index 1b812bd..7dae000 100644 --- a/doc/src/sgml/storage.sgml +++ b/doc/src/sgml/storage.sgml @@ -170,6 +170,13 @@ last started with</entry> (this file is not present after server shutdown)</entry> </row> +<row> + <entry><filename>pg_log_file</></entry> + <entry>A file recording the current log file used by the syslogger + when log collection is active</entry> +</row> + + </tbody> </tgroup> </table> diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c index e7e488a..0e25aa6 100644 --- a/src/backend/postmaster/syslogger.c +++ b/src/backend/postmaster/syslogger.c @@ -145,6 +145,7 @@ static char *logfile_getname(pg_time_t timestamp, const char *suffix); static void set_next_rotation_time(void); static void sigHupHandler(SIGNAL_ARGS); static void sigUsr1Handler(SIGNAL_ARGS); +static void logfile_writename(char *filename); /* @@ -571,6 +572,8 @@ SysLogger_Start(void) syslogFile = logfile_open(filename, "a", false); + logfile_writename(filename); + pfree(filename); #ifdef EXEC_BACKEND @@ -1209,6 +1212,8 @@ logfile_rotate(bool time_based_rotation, int size_rotation_for) fclose(syslogFile); syslogFile = fh; + logfile_writename(filename); + /* instead of pfree'ing filename, remember it for next time */ if (last_file_name != NULL) pfree(last_file_name); @@ -1253,6 +1258,8 @@ logfile_rotate(bool time_based_rotation, int size_rotation_for) fclose(csvlogFile); csvlogFile = fh; + logfile_writename(csvfilename); + /* instead of pfree'ing filename, remember it for next time */ if (last_csv_file_name != NULL) pfree(last_csv_file_name); @@ -1362,3 +1369,47 @@ sigUsr1Handler(SIGNAL_ARGS) errno = save_errno; } + + +/* + * Store the name of the file where current log messages are written when + * log collector is enabled. Useful to find the name of the current log file + * when a time-based rotation is defined. Filename is first stored into a + * temporary file and renamed into the final destination. + */ +static void +logfile_writename(char *filename) +{ + FILE *fh; + char tempfn[MAXPGPATH]; + char logpathfilename[MAXPGPATH]; + + snprintf(tempfn, sizeof(tempfn), "%s", + CURRENT_LOG_FILENAME); + strcat(tempfn, ".tmp"); + snprintf(logpathfilename, sizeof(logpathfilename), "%s", + CURRENT_LOG_FILENAME); + if ((fh = logfile_open(tempfn, "w", true) ) == NULL) + { + return; + } + if (fprintf(fh, "%s\n", filename) < 0) + { + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not write log file \"%s\": %m", + tempfn))); + fclose(fh); + return; + } + fclose(fh); + + if (rename(tempfn, logpathfilename) != 0) + { + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not rename file \"%s\": %m", + tempfn))); + return; + } +} diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index a44fa38..c67e07b 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -890,3 +890,59 @@ parse_ident(PG_FUNCTION_ARGS) PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext)); } + +/* + * Report current log file used by log collector + */ +Datum +pg_current_logfile(PG_FUNCTION_ARGS) +{ + FILE *fd; + char log_filename[MAXPGPATH]; + + if (!Logging_collector) + { + PG_RETURN_NULL(); + } + + /* + * See if current log file is present + */ + fd = AllocateFile(CURRENT_LOG_FILENAME, "r"); + if (fd == NULL) + { + if (errno != ENOENT) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read file \"%s\": %m", + CURRENT_LOG_FILENAME))); + PG_RETURN_NULL(); + } + + /* + * Read first line of the file to gather current log filename + * registered by the syslogger. + */ + fgets(log_filename, sizeof(log_filename), fd); + + /* Check for a read error. */ + if (ferror(fd)) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read file \"%s\": %m", CURRENT_LOG_FILENAME))); + + /* Close the current log filename file. */ + if (FreeFile(fd)) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not close file \"%s\": %m", CURRENT_LOG_FILENAME))); + + /* remove trailing newline */ + if (strchr(log_filename, '\n') != NULL) + *strchr(log_filename, '\n') = '\0'; + + if (log_filename[0] == '\0') + PG_RETURN_NULL(); + + PG_RETURN_TEXT_P(cstring_to_text(log_filename)); +} diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index d94943b..32b419a 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -3159,6 +3159,8 @@ DATA(insert OID = 2621 ( pg_reload_conf PGNSP PGUID 12 1 0 0 0 f f f f t f v s DESCR("reload configuration files"); DATA(insert OID = 2622 ( pg_rotate_logfile PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_rotate_logfile _null_ _null_ _null_ )); DESCR("rotate log file"); +DATA(insert OID = 3794 ( pg_current_logfile PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 25 "" _null_ _null_ _null_ _null_ _null_ pg_current_logfile _null_ _null_ _null_ )); +DESCR("current logging collector file location"); DATA(insert OID = 2623 ( pg_stat_file PGNSP PGUID 12 1 0 0 0 f f f f t f v s 1 0 2249 "25" "{25,20,1184,1184,1184,1184,16}" "{i,o,o,o,o,o,o}" "{filename,size,access,modification,change,creation,isdir}" _null_ _null_ pg_stat_file_1arg _null_ _null_ _null_ )); DESCR("get information about file"); diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 356fcc6..4b3f0e9 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -466,4 +466,12 @@ extern bool has_rolreplication(Oid roleid); extern bool BackupInProgress(void); extern void CancelBackup(void); +/* in backend/utils/adt/misc.c and backend/postmaster/syslogger.c */ +/* + * Name of file where current log messages are written when log collector is + * enabled. Useful to find the name of the current log file when a time-based + * rotation is defined. + */ +#define CURRENT_LOG_FILENAME "pg_log_file" + #endif /* MISCADMIN_H */ diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 01976a1..c27f6a8 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -516,6 +516,7 @@ extern Datum pg_collation_for(PG_FUNCTION_ARGS); extern Datum pg_relation_is_updatable(PG_FUNCTION_ARGS); extern Datum pg_column_is_updatable(PG_FUNCTION_ARGS); extern Datum parse_ident(PG_FUNCTION_ARGS); +extern Datum pg_current_logfile(PG_FUNCTION_ARGS); /* oid.c */ extern Datum oidin(PG_FUNCTION_ARGS);
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers