pgsyslogger.patch
text/x-patch
Filename: pgsyslogger.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| src/backend/postmaster/syslogger.c | 33 | 0 |
*** a/src/backend/postmaster/syslogger.c
--- b/src/backend/postmaster/syslogger.c
***************
*** 93,101 **** static char *last_file_name = NULL;
static char *last_csv_file_name = NULL;
/*
! * Buffers for saving partial messages from different backends. We don't expect
! * that there will be very many outstanding at one time, so 20 seems plenty of
! * leeway. If this array gets full we won't lose messages, but we will lose
* the protocol protection against them being partially written or interleaved.
*
* An inactive buffer has pid == 0 and undefined contents of data.
--- 93,108 ----
static char *last_csv_file_name = NULL;
/*
! * Buffers for saving partial messages from different backends.
! *
! * Under heavy load we can get quite a few of them, so we stripe them across
! * an array based on the mod of the pid, which seem an adequate hash function
! * for pids. We do this rather then just keeping a one-dimensional array so
! * we don't have to probe too many slots for any given pid.
! * 20 stripes of 20 slots each seems likely to be adequate leeway, but if there
! * are lots of overruns we might need to increase CHUNK_STRIPES a bit, or look
! * at some alternative scheme.
! * If a stripe gets full we won't lose messages, but we will lose
* the protocol protection against them being partially written or interleaved.
*
* An inactive buffer has pid == 0 and undefined contents of data.
***************
*** 107,113 **** typedef struct
} save_buffer;
#define CHUNK_SLOTS 20
! static save_buffer saved_chunks[CHUNK_SLOTS];
/* These must be exported for EXEC_BACKEND case ... annoying */
#ifndef WIN32
--- 114,121 ----
} save_buffer;
#define CHUNK_SLOTS 20
! #define CHUNK_STRIPES 20
! static save_buffer saved_chunks[CHUNK_STRIPES][CHUNK_SLOTS];
/* These must be exported for EXEC_BACKEND case ... annoying */
#ifndef WIN32
***************
*** 725,730 **** process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
--- 733,739 ----
{
PipeProtoHeader p;
int chunklen;
+ int stripe;
/* Do we have a valid header? */
memcpy(&p, cursor, sizeof(PipeProtoHeader));
***************
*** 743,748 **** process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
--- 752,759 ----
dest = (p.is_last == 'T' || p.is_last == 'F') ?
LOG_DESTINATION_CSVLOG : LOG_DESTINATION_STDERR;
+ stripe = p.pid % CHUNK_STRIPES;
+
if (p.is_last == 'f' || p.is_last == 'F')
{
/*
***************
*** 756,780 **** process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
for (i = 0; i < CHUNK_SLOTS; i++)
{
! if (saved_chunks[i].pid == p.pid)
{
existing_slot = i;
break;
}
! if (free_slot < 0 && saved_chunks[i].pid == 0)
free_slot = i;
}
if (existing_slot >= 0)
{
! str = &(saved_chunks[existing_slot].data);
appendBinaryStringInfo(str,
cursor + PIPE_HEADER_SIZE,
p.len);
}
else if (free_slot >= 0)
{
! saved_chunks[free_slot].pid = p.pid;
! str = &(saved_chunks[free_slot].data);
initStringInfo(str);
appendBinaryStringInfo(str,
cursor + PIPE_HEADER_SIZE,
--- 767,791 ----
for (i = 0; i < CHUNK_SLOTS; i++)
{
! if (saved_chunks[stripe][i].pid == p.pid)
{
existing_slot = i;
break;
}
! if (free_slot < 0 && saved_chunks[stripe][i].pid == 0)
free_slot = i;
}
if (existing_slot >= 0)
{
! str = &(saved_chunks[stripe][existing_slot].data);
appendBinaryStringInfo(str,
cursor + PIPE_HEADER_SIZE,
p.len);
}
else if (free_slot >= 0)
{
! saved_chunks[stripe][free_slot].pid = p.pid;
! str = &(saved_chunks[stripe][free_slot].data);
initStringInfo(str);
appendBinaryStringInfo(str,
cursor + PIPE_HEADER_SIZE,
***************
*** 803,809 **** process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
for (i = 0; i < CHUNK_SLOTS; i++)
{
! if (saved_chunks[i].pid == p.pid)
{
existing_slot = i;
break;
--- 814,820 ----
for (i = 0; i < CHUNK_SLOTS; i++)
{
! if (saved_chunks[stripe][i].pid == p.pid)
{
existing_slot = i;
break;
***************
*** 811,822 **** process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
}
if (existing_slot >= 0)
{
! str = &(saved_chunks[existing_slot].data);
appendBinaryStringInfo(str,
cursor + PIPE_HEADER_SIZE,
p.len);
write_syslogger_file(str->data, str->len, dest);
! saved_chunks[existing_slot].pid = 0;
pfree(str->data);
}
else
--- 822,833 ----
}
if (existing_slot >= 0)
{
! str = &(saved_chunks[stripe][existing_slot].data);
appendBinaryStringInfo(str,
cursor + PIPE_HEADER_SIZE,
p.len);
write_syslogger_file(str->data, str->len, dest);
! saved_chunks[stripe][existing_slot].pid = 0;
pfree(str->data);
}
else
***************
*** 871,890 **** process_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
static void
flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
{
! int i;
StringInfo str;
/* Dump any incomplete protocol messages */
! for (i = 0; i < CHUNK_SLOTS; i++)
! {
! if (saved_chunks[i].pid != 0)
{
! str = &(saved_chunks[i].data);
! write_syslogger_file(str->data, str->len, LOG_DESTINATION_STDERR);
! saved_chunks[i].pid = 0;
! pfree(str->data);
}
- }
/*
* Force out any remaining pipe data as-is; we don't bother trying to
--- 882,902 ----
static void
flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer)
{
! int i, stripe;
StringInfo str;
/* Dump any incomplete protocol messages */
! for (stripe = 0; stripe < CHUNK_STRIPES; stripe++)
! for (i = 0; i < CHUNK_SLOTS; i++)
{
! if (saved_chunks[stripe][i].pid != 0)
! {
! str = &(saved_chunks[stripe][i].data);
! write_syslogger_file(str->data, str->len, LOG_DESTINATION_STDERR);
! saved_chunks[stripe][i].pid = 0;
! pfree(str->data);
! }
}
/*
* Force out any remaining pipe data as-is; we don't bother trying to