Tom Lane wrote:
Andrew Dunstan [EMAIL PROTECTED] writes:
I'll try to get a patch out for just the stderr case, which should be
back-patchable, then adjust the CSVlog patch to use it.
Sounds like a plan.
I'm thinking of handling the partial lines with a small dynahash of
StringInfo buffers, which get discarded whenever we don't have a partial
line for the PID.
A hashtable might be overkill --- based on reports so far, it's unlikely
you'd have more than two or three messages being received concurrently,
so a simple list or array might be quicker to search.
Attached is a WIP patch ... I still have some debugging to do but I
think the basic logic is there. Comments welcome.
ATM it gets stuck in running installcheck and gdb shows the logger
hanging here:
enlargeStringInfo (str=0x9a91c8, needed=4085) at stringinfo.c:263
263 newlen = 2 * newlen;
Can I not use a StringInfo in the syslogger?
cheers
andrew
Index: src/backend/postmaster/syslogger.c
===
RCS file: /cvsroot/pgsql/src/backend/postmaster/syslogger.c,v
retrieving revision 1.31
diff -c -r1.31 syslogger.c
*** src/backend/postmaster/syslogger.c 4 Jun 2007 22:21:42 - 1.31
--- src/backend/postmaster/syslogger.c 12 Jun 2007 23:23:38 -
***
*** 42,47
--- 42,48
#include utils/guc.h
#include utils/ps_status.h
#include utils/timestamp.h
+ #include lib/stringinfo.h
/*
* We really want line-buffered mode for logfile output, but Windows does
***
*** 54,59
--- 55,76
#define LBF_MODE _IOLBF
#endif
+ #if PIPE_BUF 1024
+ #define READ_SIZE PIPE_BUF
+ #else
+ #define READ_SIZE 1024
+ #endif
+
+ /*
+ * we use a buffer twice as big as a read so that if there is a fragment left
+ * after process what is read we can save it and copy it back before the next
+ * read.
+ */
+ #define READ_BUF_SIZE 2 * READ_SIZE
+
+ /* buffer to keep any partial chunks read between calls to read()/ReadFile() */
+ static char * read_fragment[READ_SIZE];
+ static int read_fragment_len = 0;
/*
* GUC parameters. Redirect_stderr cannot be changed after postmaster
***
*** 75,89
* Private state
*/
static pg_time_t next_rotation_time;
-
static bool redirection_done = false;
-
static bool pipe_eof_seen = false;
-
static FILE *syslogFile = NULL;
-
static char *last_file_name = NULL;
/* These must be exported for EXEC_BACKEND case ... annoying */
#ifndef WIN32
int syslogPipe[2] = {-1, -1};
--- 92,110
* Private state
*/
static pg_time_t next_rotation_time;
static bool redirection_done = false;
static bool pipe_eof_seen = false;
static FILE *syslogFile = NULL;
static char *last_file_name = NULL;
+ typedef struct
+ {
+ pid_t pid;
+ StringInfoData data;
+ } save_buffer;
+ #define CHUNK_SLOTS 20
+ static save_buffer saved_chunks[CHUNK_SLOTS];
+
/* These must be exported for EXEC_BACKEND case ... annoying */
#ifndef WIN32
int syslogPipe[2] = {-1, -1};
***
*** 117,123
static void set_next_rotation_time(void);
static void sigHupHandler(SIGNAL_ARGS);
static void sigUsr1Handler(SIGNAL_ARGS);
!
/*
* Main entry point for syslogger process
--- 138,144
static void set_next_rotation_time(void);
static void sigHupHandler(SIGNAL_ARGS);
static void sigUsr1Handler(SIGNAL_ARGS);
! static void write_chunk(const char * buffer, int count);
/*
* Main entry point for syslogger process
***
*** 244,250
bool time_based_rotation = false;
#ifndef WIN32
! char logbuffer[1024];
int bytesRead;
int rc;
fd_set rfds;
--- 265,271
bool time_based_rotation = false;
#ifndef WIN32
! char logbuffer[READ_BUF_SIZE];
int bytesRead;
int rc;
fd_set rfds;
***
*** 325,332
}
else if (rc 0 FD_ISSET(syslogPipe[0], rfds))
{
bytesRead = piperead(syslogPipe[0],
! logbuffer, sizeof(logbuffer));
if (bytesRead 0)
{
--- 346,354
}
else if (rc 0 FD_ISSET(syslogPipe[0], rfds))
{
+ memcpy(logbuffer, read_fragment, read_fragment_len);
bytesRead = piperead(syslogPipe[0],
! logbuffer + read_fragment_len, READ_SIZE);
if (bytesRead 0)
{
***
*** 337,343
}
else if (bytesRead 0)
{
! write_syslogger_file(logbuffer, bytesRead);
continue;
}
else
--- 359,365
}
else if (bytesRead 0)
{
! write_syslogger_file(logbuffer, bytesRead + read_fragment_len);
continue;
}
else
***
*** 349,354
--- 371,380
* and all backends are shut down, and we are done.
*/
pipe_eof_seen = true;
+
+ /* if there's a fragment left then force it out now */
+ if (read_fragment_len)
+