The patch is attached for the following TODO item:
*Allow server logs to be remotely read.
Steps:
1. When the server starts (**pg_ctl start)**, the path of the postmaster file is stored
2. The user can access the logfile using the following 2 functions:
* pg_file_readlog(int linenumber) - Retrieves the string for the given line number
* **pg_file_countlog() - Retrieves the number of lines existing in the
logfile*
I have implemented this based on the suggestions given in the hackers mailing
list.
If you know a better way, please share it with me. Waiting for your reply.
Thanks
Dhanaraj
*** ./contrib/adminpack/adminpack.c.orig Thu Jun 8 17:04:42 2006
--- ./contrib/adminpack/adminpack.c Thu Jun 8 18:34:37 2006
***************
*** 24,30 ****
--- 24,32 ----
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "utils/datetime.h"
+ #include "utils/builtins.h"
+ #define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))
#ifdef WIN32
***************
*** 48,58 ****
--- 50,64 ----
Datum pg_file_rename(PG_FUNCTION_ARGS);
Datum pg_file_unlink(PG_FUNCTION_ARGS);
Datum pg_logdir_ls(PG_FUNCTION_ARGS);
+ Datum pg_file_readlog(PG_FUNCTION_ARGS);
+ Datum pg_file_countlog();
PG_FUNCTION_INFO_V1(pg_file_write);
PG_FUNCTION_INFO_V1(pg_file_rename);
PG_FUNCTION_INFO_V1(pg_file_unlink);
PG_FUNCTION_INFO_V1(pg_logdir_ls);
+ PG_FUNCTION_INFO_V1(pg_file_readlog);
+ PG_FUNCTION_INFO_V1(pg_file_countlog);
typedef struct
{
***************
*** 390,392 ****
--- 396,520 ----
FreeDir(fctx->dirdesc);
SRF_RETURN_DONE(funcctx);
}
+
+ /* Retrieves n-th line from the postmaster logfile */
+
+ Datum pg_file_readlog(PG_FUNCTION_ARGS)
+ {
+ char c, buffer[MAXPGPATH];
+ char file_path2[MAXPGPATH], file_path1[MAXPGPATH];
+ int64 linenumber = PG_GETARG_INT64(0);
+ FILE *filePtr1, *filePtr2;
+ int64 count=1;
+ int index=0;
+
+ if(OutputFileName[0])
+ {
+ filePtr1 = fopen(OutputFileName, "r");
+ }
+ else
+ {
+ /* Finds the logfile path from postmasterlog_path file */
+ snprintf(file_path1, MAXPGPATH, "%s/postmasterlog_path", DataDir);
+ filePtr2 = fopen(file_path1, "r");
+ if(filePtr2 != NULL)
+ {
+ memset(file_path2, 0, MAXPGPATH);
+ fread(file_path2, 1, MAXPGPATH, filePtr2);
+ }
+ else
+ {
+ snprintf(buffer, MAXPGPATH, "Could not find the logfile path in: %s", file_path1);
+ ereport(ERROR, (errcode_for_file_access(), errmsg(buffer)));
+ }
+
+ fclose(filePtr2);
+ filePtr1 = fopen(file_path2, "r");
+ }
+
+ memset(buffer, 0, MAXPGPATH);
+
+ if(filePtr1 == NULL)
+ {
+ snprintf(buffer, MAXPGPATH, "Logfile: %s - Not found", file_path2);
+ ereport(ERROR, (errcode_for_file_access(), errmsg(buffer)));
+ }
+
+ /* Reads the logfile and extract n-th line */
+ while( (c= fgetc(filePtr1))!=EOF)
+ {
+ if (linenumber == count)
+ {
+ buffer[index] = c;
+ index++;
+ }
+
+ /* Counts the number of lines */
+ if(c=='\n')
+ {
+ count++;
+ }
+ }
+
+ if(count <= linenumber)
+ {
+ sprintf(buffer, "Given line number does not exist");
+ ereport(ERROR, (errcode_for_file_access(), errmsg(buffer)));
+ }
+
+ fclose(filePtr1);
+ PG_RETURN_TEXT_P(GET_TEXT(buffer));
+ }
+
+ /* Counts the number of lines in the postmaster logfile */
+
+ Datum pg_file_countlog()
+ {
+ char c, buffer[MAXPGPATH];
+ char file_path2[MAXPGPATH], file_path1[MAXPGPATH];
+ FILE *filePtr1, *filePtr2;
+ int64 count=1;
+
+ if(OutputFileName[0])
+ {
+ filePtr1 = fopen(OutputFileName, "r");
+ }
+ else
+ {
+ /* Finds the logfile path from postmasterlog_path file */
+ snprintf(file_path1, MAXPGPATH, "%s/postmasterlog_path", DataDir);
+ filePtr2 = fopen(file_path1, "r");
+ if(filePtr2 != NULL)
+ {
+ memset(file_path2, 0, MAXPGPATH);
+ fread(file_path2, 1, MAXPGPATH, filePtr2);
+ }
+ else
+ {
+ snprintf(buffer, MAXPGPATH, "Could not find the logfile path in: %s", file_path1);
+ ereport(ERROR, (errcode_for_file_access(), errmsg(buffer)));
+ }
+
+ fclose(filePtr2);
+ filePtr1 = fopen(file_path2, "r");
+ }
+
+ memset(buffer, 0, MAXPGPATH);
+
+ if(filePtr1== NULL)
+ {
+ snprintf(buffer, MAXPGPATH, "Logfile: %s - Not found", file_path2);
+ ereport(ERROR, (errcode_for_file_access(), errmsg(buffer)));
+ }
+
+ /* Counts the number of lines */
+ while( (c= fgetc(filePtr1))!=EOF)
+ {
+ if(c=='\n')
+ count++;
+ }
+
+ fclose(filePtr1);
+ PG_RETURN_INT64(count-1);
+ }
+
*** ./contrib/adminpack/adminpack.sql.in.orig Thu Jun 8 17:05:16 2006
--- ./contrib/adminpack/adminpack.sql.in Thu Jun 8 17:06:11 2006
***************
*** 24,30 ****
--- 24,37 ----
AS 'MODULE_PATHNAME', 'pg_logdir_ls'
LANGUAGE C VOLATILE STRICT;
+ CREATE FUNCTION pg_catalog.pg_file_readlog(bigint) RETURNS text
+ AS 'MODULE_PATHNAME', 'pg_file_readlog'
+ LANGUAGE C VOLATILE STRICT;
+ CREATE FUNCTION pg_catalog.pg_file_countlog() RETURNS bigint
+ AS 'MODULE_PATHNAME', 'pg_file_countlog'
+ LANGUAGE C VOLATILE STRICT;
+
/* compatibility redefines */
CREATE FUNCTION pg_catalog.pg_logfile_rotate() RETURNS int4
*** ./src/bin/pg_ctl/pg_ctl.c.orig Thu Jun 8 16:47:20 2006
--- ./src/bin/pg_ctl/pg_ctl.c Thu Jun 8 17:32:48 2006
***************
*** 1719,1724 ****
--- 1719,1752 ----
snprintf(conf_file, MAXPGPATH, "%s/postgresql.conf", pg_data);
}
+ /* Store the postmaster logfile name in postmasterlog_path file */
+
+ if( (ctl_command == START_COMMAND) || (ctl_command == RESTART_COMMAND) || (ctl_command == RELOAD_COMMAND))
+ {
+ FILE *filePtr;
+ char file_path[MAXPGPATH];
+ char *cwd;
+
+ snprintf(file_path, MAXPGPATH, "%s/postmasterlog_path", pg_data);
+ filePtr = fopen(file_path, "w+");
+
+ if(log_file[0] == '/')
+ {
+ fprintf(filePtr,"%s", log_file);
+ }
+ else
+ {
+ /* Append the current path string with the logfile name */
+ if ((cwd = getcwd(NULL, 64)) != NULL)
+ {
+ fprintf(filePtr, "%s/%s", cwd, log_file);
+ free(cwd);
+ }
+ }
+ fclose(filePtr);
+ }
+
+
switch (ctl_command)
{
case STATUS_COMMAND:
---------------------------(end of broadcast)---------------------------
TIP 5: don't forget to increase your free space map settings