diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index f25ed24986c..97cf9452617 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1,4 +1,4 @@ - + Server Configuration @@ -3331,6 +3331,22 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; + + track_activity_query_size (integer) + + track_activity_query_size configuration parameter + + + + Specifies the number of bytes reserved to track the currently + executing command for each active session, for the + pg_stat_activity.current_query field. + The default value is 1024. This parameter can only be set at server + start. + + + + track_counts (boolean) diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 5d9dcd6c94c..e3cb0be5bb7 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -13,7 +13,7 @@ * * Copyright (c) 2001-2008, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.175 2008/06/19 00:46:05 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.176 2008/06/30 10:58:47 heikki Exp $ * ---------- */ #include "postgres.h" @@ -101,6 +101,7 @@ bool pgstat_track_activities = false; bool pgstat_track_counts = false; int pgstat_track_functions = TRACK_FUNC_OFF; +int pgstat_track_activity_query_size = 1024; /* * BgWriter global statistics counters (unused in other processes). @@ -2010,6 +2011,7 @@ pgstat_fetch_global(void) static PgBackendStatus *BackendStatusArray = NULL; static PgBackendStatus *MyBEEntry = NULL; +static char *BackendActivityBuffer = NULL; /* @@ -2020,20 +2022,25 @@ BackendStatusShmemSize(void) { Size size; - size = mul_size(sizeof(PgBackendStatus), MaxBackends); + size = add_size(mul_size(sizeof(PgBackendStatus), MaxBackends), + mul_size(pgstat_track_activity_query_size, MaxBackends)); return size; } /* - * Initialize the shared status array during postmaster startup. + * Initialize the shared status array and activity string buffer during + * postmaster startup. */ void CreateSharedBackendStatus(void) { - Size size = BackendStatusShmemSize(); + Size size; bool found; + int i; + char *buffer; /* Create or attach to the shared array */ + size = mul_size(sizeof(PgBackendStatus), MaxBackends); BackendStatusArray = (PgBackendStatus *) ShmemInitStruct("Backend Status Array", size, &found); @@ -2044,6 +2051,23 @@ CreateSharedBackendStatus(void) */ MemSet(BackendStatusArray, 0, size); } + + /* Create or attach to the shared activity buffer */ + size = mul_size(pgstat_track_activity_query_size, MaxBackends); + BackendActivityBuffer = (char*) + ShmemInitStruct("Backend Activity Buffer", size, &found); + + if (!found) + { + MemSet(BackendActivityBuffer, 0, size); + + /* Initialize st_activity pointers. */ + buffer = BackendActivityBuffer; + for (i = 0; i < MaxBackends; i++) { + BackendStatusArray[i].st_activity = buffer; + buffer += pgstat_track_activity_query_size; + } + } } @@ -2128,7 +2152,7 @@ pgstat_bestart(void) beentry->st_waiting = false; beentry->st_activity[0] = '\0'; /* Also make sure the last byte in the string area is always 0 */ - beentry->st_activity[PGBE_ACTIVITY_SIZE - 1] = '\0'; + beentry->st_activity[pgstat_track_activity_query_size - 1] = '\0'; beentry->st_changecount++; Assert((beentry->st_changecount & 1) == 0); @@ -2188,7 +2212,7 @@ pgstat_report_activity(const char *cmd_str) start_timestamp = GetCurrentStatementStartTimestamp(); len = strlen(cmd_str); - len = pg_mbcliplen(cmd_str, len, PGBE_ACTIVITY_SIZE - 1); + len = pg_mbcliplen(cmd_str, len, pgstat_track_activity_query_size - 1); /* * Update my status entry, following the protocol of bumping @@ -2267,6 +2291,7 @@ pgstat_read_current_status(void) volatile PgBackendStatus *beentry; PgBackendStatus *localtable; PgBackendStatus *localentry; + char *localactivity; int i; Assert(!pgStatRunningInCollector); @@ -2278,6 +2303,9 @@ pgstat_read_current_status(void) localtable = (PgBackendStatus *) MemoryContextAlloc(pgStatLocalContext, sizeof(PgBackendStatus) * MaxBackends); + localactivity = (char *) + MemoryContextAlloc(pgStatLocalContext, + pgstat_track_activity_query_size * MaxBackends); localNumBackends = 0; beentry = BackendStatusArray; @@ -2295,11 +2323,17 @@ pgstat_read_current_status(void) { int save_changecount = beentry->st_changecount; - /* - * XXX if PGBE_ACTIVITY_SIZE is really large, it might be best to - * use strcpy not memcpy for copying the activity string? - */ - memcpy(localentry, (char *) beentry, sizeof(PgBackendStatus)); + localentry->st_procpid = beentry->st_procpid; + if (localentry->st_procpid > 0) + { + memcpy(localentry, (char *) beentry, sizeof(PgBackendStatus)); + /* + * strcpy is safe even if the string is modified concurrently, + * because there's always a \0 at the end of the buffer. + */ + strcpy(localactivity, (char *) beentry->st_activity); + localentry->st_activity = localactivity; + } if (save_changecount == beentry->st_changecount && (save_changecount & 1) == 0) @@ -2314,6 +2348,7 @@ pgstat_read_current_status(void) if (localentry->st_procpid > 0) { localentry++; + localactivity += pgstat_track_activity_query_size; localNumBackends++; } } diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index b3409111b11..76c6843fd6c 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.456 2008/05/28 09:04:06 mha Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.457 2008/06/30 10:58:47 heikki Exp $ * *-------------------------------------------------------------------- */ @@ -1848,6 +1848,15 @@ static struct config_int ConfigureNamesInt[] = -1, -1, INT_MAX, NULL, NULL }, + { + {"track_activity_query_size", PGC_POSTMASTER, RESOURCES_MEM, + gettext_noop("Sets the size reserved for pg_stat_activity.current_query, in bytes."), + NULL, + }, + &pgstat_track_activity_query_size, + 1024, 100, 102400, NULL, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 033a74b2d4e..552d856ae29 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -364,6 +364,7 @@ #track_activities = on #track_counts = on #track_functions = none # none, pl, all +#track_activity_query_size = 1024 #update_process_title = on diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 9b48f42bb0f..fabc5fb4a07 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -5,7 +5,7 @@ * * Copyright (c) 2001-2008, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/pgstat.h,v 1.76 2008/06/19 00:46:05 alvherre Exp $ + * $PostgreSQL: pgsql/src/include/pgstat.h,v 1.77 2008/06/30 10:58:47 heikki Exp $ * ---------- */ #ifndef PGSTAT_H @@ -509,9 +509,6 @@ typedef struct PgStat_GlobalStats * ---------- */ -/* Max length of st_activity string ... perhaps replace with a GUC var? */ -#define PGBE_ACTIVITY_SIZE 1024 - /* ---------- * PgBackendStatus * @@ -551,7 +548,7 @@ typedef struct PgBackendStatus bool st_waiting; /* current command string; MUST be null-terminated */ - char st_activity[PGBE_ACTIVITY_SIZE]; + char *st_activity; } PgBackendStatus; /* @@ -578,6 +575,7 @@ typedef struct PgStat_FunctionCallUsage extern bool pgstat_track_activities; extern bool pgstat_track_counts; extern int pgstat_track_functions; +extern int pgstat_track_activity_query_size; /* * BgWriter statistics counters are updated directly by bgwriter and bufmgr