aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/pgbuffercache.sgml12
-rw-r--r--src/backend/access/heap/visibilitymap.c2
-rw-r--r--src/backend/commands/foreigncmds.c1
-rw-r--r--src/backend/commands/schemacmds.c1
-rw-r--r--src/backend/executor/execParallel.c1
-rw-r--r--src/backend/libpq/auth.c12
-rw-r--r--src/backend/optimizer/plan/planner.c1
-rw-r--r--src/backend/parser/gram.y124
-rw-r--r--src/backend/postmaster/bgworker.c1
-rw-r--r--src/backend/postmaster/postmaster.c7
-rw-r--r--src/backend/replication/walsender.c33
-rw-r--r--src/backend/storage/ipc/latch.c8
-rw-r--r--src/backend/storage/lmgr/generate-lwlocknames.pl110
-rw-r--r--src/backend/storage/lmgr/lwlock.c48
-rw-r--r--src/backend/tcop/postgres.c1
-rw-r--r--src/backend/tcop/utility.c2
-rw-r--r--src/backend/utils/activity/wait_event_names.txt10
-rw-r--r--src/backend/utils/cache/plancache.c8
-rw-r--r--src/bin/pg_basebackup/pg_createsubscriber.c11
-rw-r--r--src/include/access/xlog_internal.h10
-rw-r--r--src/include/access/xlogrecovery.h10
-rw-r--r--src/include/nodes/plannodes.h17
-rw-r--r--src/include/port/solaris.h9
-rw-r--r--src/include/storage/lwlock.h56
-rw-r--r--src/include/storage/lwlocklist.h57
-rw-r--r--src/include/utils/pgstat_kind.h6
-rw-r--r--src/test/modules/injection_points/injection_stats.c2
-rw-r--r--src/test/modules/injection_points/injection_stats_fixed.c2
-rw-r--r--src/test/subscription/t/035_conflicts.pl10
-rw-r--r--src/tools/pgindent/typedefs.list1
30 files changed, 346 insertions, 227 deletions
diff --git a/doc/src/sgml/pgbuffercache.sgml b/doc/src/sgml/pgbuffercache.sgml
index 546ace8369e..eeb85a0e049 100644
--- a/doc/src/sgml/pgbuffercache.sgml
+++ b/doc/src/sgml/pgbuffercache.sgml
@@ -20,10 +20,18 @@
</indexterm>
<indexterm>
+ <primary>pg_buffercache_numa</primary>
+ </indexterm>
+
+ <indexterm>
<primary>pg_buffercache_summary</primary>
</indexterm>
<indexterm>
+ <primary>pg_buffercache_usage_counts</primary>
+ </indexterm>
+
+ <indexterm>
<primary>pg_buffercache_evict</primary>
</indexterm>
@@ -489,7 +497,7 @@
</sect2>
<sect2 id="pgbuffercache-pg-buffercache-evict-relation">
- <title>The <structname>pg_buffercache_evict_relation</structname> Function</title>
+ <title>The <structname>pg_buffercache_evict_relation()</structname> Function</title>
<para>
The <function>pg_buffercache_evict_relation()</function> function is very
similar to the <function>pg_buffercache_evict()</function> function. The
@@ -507,7 +515,7 @@
</sect2>
<sect2 id="pgbuffercache-pg-buffercache-evict-all">
- <title>The <structname>pg_buffercache_evict_all</structname> Function</title>
+ <title>The <structname>pg_buffercache_evict_all()</structname> Function</title>
<para>
The <function>pg_buffercache_evict_all()</function> function is very
similar to the <function>pg_buffercache_evict()</function> function. The
diff --git a/src/backend/access/heap/visibilitymap.c b/src/backend/access/heap/visibilitymap.c
index 745a04ef26e..8f918e00af7 100644
--- a/src/backend/access/heap/visibilitymap.c
+++ b/src/backend/access/heap/visibilitymap.c
@@ -364,7 +364,7 @@ visibilitymap_get_status(Relation rel, BlockNumber heapBlk, Buffer *vmbuf)
{
*vmbuf = vm_readbuf(rel, mapBlock, false);
if (!BufferIsValid(*vmbuf))
- return false;
+ return (uint8) 0;
}
map = PageGetContents(BufferGetPage(*vmbuf));
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index 8d2d7431544..fcd5fcd8915 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -1588,6 +1588,7 @@ ImportForeignSchema(ImportForeignSchemaStmt *stmt)
pstmt->utilityStmt = (Node *) cstmt;
pstmt->stmt_location = rs->stmt_location;
pstmt->stmt_len = rs->stmt_len;
+ pstmt->cached_plan_type = PLAN_CACHE_NONE;
/* Execute statement */
ProcessUtility(pstmt, cmd, false,
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 546160f0941..c00f1a11384 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -215,6 +215,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
wrapper->utilityStmt = stmt;
wrapper->stmt_location = stmt_location;
wrapper->stmt_len = stmt_len;
+ wrapper->cached_plan_type = PLAN_CACHE_NONE;
/* do this step */
ProcessUtility(wrapper,
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index f3e77bda279..fc76f22fb82 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -189,6 +189,7 @@ ExecSerializePlan(Plan *plan, EState *estate)
pstmt->permInfos = estate->es_rteperminfos;
pstmt->resultRelations = NIL;
pstmt->appendRelations = NIL;
+ pstmt->cached_plan_type = PLAN_CACHE_NONE;
/*
* Transfer only parallel-safe subplans, leaving a NULL "hole" in the list
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 9f4d05ffbd4..4da46666439 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -94,8 +94,16 @@ static int auth_peer(hbaPort *port);
#define PGSQL_PAM_SERVICE "postgresql" /* Service name passed to PAM */
+/* Work around original Solaris' lack of "const" in the conv_proc signature */
+#ifdef _PAM_LEGACY_NONCONST
+#define PG_PAM_CONST
+#else
+#define PG_PAM_CONST const
+#endif
+
static int CheckPAMAuth(Port *port, const char *user, const char *password);
-static int pam_passwd_conv_proc(int num_msg, const struct pam_message **msg,
+static int pam_passwd_conv_proc(int num_msg,
+ PG_PAM_CONST struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr);
static struct pam_conv pam_passw_conv = {
@@ -1917,7 +1925,7 @@ auth_peer(hbaPort *port)
*/
static int
-pam_passwd_conv_proc(int num_msg, const struct pam_message **msg,
+pam_passwd_conv_proc(int num_msg, PG_PAM_CONST struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
const char *passwd;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index c989e72cac5..a77b2147e95 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -582,6 +582,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions,
result->utilityStmt = parse->utilityStmt;
result->stmt_location = parse->stmt_location;
result->stmt_len = parse->stmt_len;
+ result->cached_plan_type = PLAN_CACHE_NONE;
result->jitFlags = PGJIT_NONE;
if (jit_enabled && jit_above_cost >= 0 &&
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 73345bb3c70..db43034b9db 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -318,6 +318,11 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <list> opt_qualified_name
%type <boolean> opt_concurrently
%type <dbehavior> opt_drop_behavior
+%type <list> opt_utility_option_list
+%type <list> utility_option_list
+%type <defelt> utility_option_elem
+%type <str> utility_option_name
+%type <node> utility_option_arg
%type <node> alter_column_default opclass_item opclass_drop alter_using
%type <ival> add_drop opt_asc_desc opt_nulls_order
@@ -338,10 +343,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
create_extension_opt_item alter_extension_opt_item
%type <ival> opt_lock lock_type cast_context
-%type <str> utility_option_name
-%type <defelt> utility_option_elem
-%type <list> utility_option_list
-%type <node> utility_option_arg
%type <defelt> drop_option
%type <boolean> opt_or_replace opt_no
opt_grant_grant_option
@@ -556,7 +557,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <list> generic_option_list alter_generic_option_list
%type <ival> reindex_target_relation reindex_target_all
-%type <list> opt_reindex_option_list
%type <node> copy_generic_opt_arg copy_generic_opt_arg_list_item
%type <defelt> copy_generic_opt_elem
@@ -1141,6 +1141,41 @@ opt_drop_behavior:
| /* EMPTY */ { $$ = DROP_RESTRICT; /* default */ }
;
+opt_utility_option_list:
+ '(' utility_option_list ')' { $$ = $2; }
+ | /* EMPTY */ { $$ = NULL; }
+ ;
+
+utility_option_list:
+ utility_option_elem
+ {
+ $$ = list_make1($1);
+ }
+ | utility_option_list ',' utility_option_elem
+ {
+ $$ = lappend($1, $3);
+ }
+ ;
+
+utility_option_elem:
+ utility_option_name utility_option_arg
+ {
+ $$ = makeDefElem($1, $2, @1);
+ }
+ ;
+
+utility_option_name:
+ NonReservedWord { $$ = $1; }
+ | analyze_keyword { $$ = "analyze"; }
+ | FORMAT_LA { $$ = "format"; }
+ ;
+
+utility_option_arg:
+ opt_boolean_or_string { $$ = (Node *) makeString($1); }
+ | NumericOnly { $$ = (Node *) $1; }
+ | /* EMPTY */ { $$ = NULL; }
+ ;
+
/*****************************************************************************
*
* CALL statement
@@ -2028,18 +2063,12 @@ constraints_set_mode:
* Checkpoint statement
*/
CheckPointStmt:
- CHECKPOINT
+ CHECKPOINT opt_utility_option_list
{
CheckPointStmt *n = makeNode(CheckPointStmt);
$$ = (Node *) n;
- }
- | CHECKPOINT '(' utility_option_list ')'
- {
- CheckPointStmt *n = makeNode(CheckPointStmt);
-
- $$ = (Node *) n;
- n->options = $3;
+ n->options = $2;
}
;
@@ -9354,7 +9383,7 @@ DropTransformStmt: DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_d
*****************************************************************************/
ReindexStmt:
- REINDEX opt_reindex_option_list reindex_target_relation opt_concurrently qualified_name
+ REINDEX opt_utility_option_list reindex_target_relation opt_concurrently qualified_name
{
ReindexStmt *n = makeNode(ReindexStmt);
@@ -9367,7 +9396,7 @@ ReindexStmt:
makeDefElem("concurrently", NULL, @4));
$$ = (Node *) n;
}
- | REINDEX opt_reindex_option_list SCHEMA opt_concurrently name
+ | REINDEX opt_utility_option_list SCHEMA opt_concurrently name
{
ReindexStmt *n = makeNode(ReindexStmt);
@@ -9380,7 +9409,7 @@ ReindexStmt:
makeDefElem("concurrently", NULL, @4));
$$ = (Node *) n;
}
- | REINDEX opt_reindex_option_list reindex_target_all opt_concurrently opt_single_name
+ | REINDEX opt_utility_option_list reindex_target_all opt_concurrently opt_single_name
{
ReindexStmt *n = makeNode(ReindexStmt);
@@ -9402,10 +9431,6 @@ reindex_target_all:
SYSTEM_P { $$ = REINDEX_OBJECT_SYSTEM; }
| DATABASE { $$ = REINDEX_OBJECT_DATABASE; }
;
-opt_reindex_option_list:
- '(' utility_option_list ')' { $$ = $2; }
- | /* EMPTY */ { $$ = NULL; }
- ;
/*****************************************************************************
*
@@ -11903,13 +11928,13 @@ ClusterStmt:
n->params = $3;
$$ = (Node *) n;
}
- | CLUSTER '(' utility_option_list ')'
+ | CLUSTER opt_utility_option_list
{
ClusterStmt *n = makeNode(ClusterStmt);
n->relation = NULL;
n->indexname = NULL;
- n->params = $3;
+ n->params = $2;
$$ = (Node *) n;
}
/* unparenthesized VERBOSE kept for pre-14 compatibility */
@@ -11919,21 +11944,18 @@ ClusterStmt:
n->relation = $3;
n->indexname = $4;
- n->params = NIL;
if ($2)
- n->params = lappend(n->params, makeDefElem("verbose", NULL, @2));
+ n->params = list_make1(makeDefElem("verbose", NULL, @2));
$$ = (Node *) n;
}
/* unparenthesized VERBOSE kept for pre-17 compatibility */
- | CLUSTER opt_verbose
+ | CLUSTER VERBOSE
{
ClusterStmt *n = makeNode(ClusterStmt);
n->relation = NULL;
n->indexname = NULL;
- n->params = NIL;
- if ($2)
- n->params = lappend(n->params, makeDefElem("verbose", NULL, @2));
+ n->params = list_make1(makeDefElem("verbose", NULL, @2));
$$ = (Node *) n;
}
/* kept for pre-8.3 compatibility */
@@ -11943,9 +11965,8 @@ ClusterStmt:
n->relation = $5;
n->indexname = $3;
- n->params = NIL;
if ($2)
- n->params = lappend(n->params, makeDefElem("verbose", NULL, @2));
+ n->params = list_make1(makeDefElem("verbose", NULL, @2));
$$ = (Node *) n;
}
;
@@ -11996,64 +12017,31 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose opt_analyze opt_vacuum_relati
}
;
-AnalyzeStmt: analyze_keyword opt_verbose opt_vacuum_relation_list
+AnalyzeStmt: analyze_keyword opt_utility_option_list opt_vacuum_relation_list
{
VacuumStmt *n = makeNode(VacuumStmt);
- n->options = NIL;
- if ($2)
- n->options = lappend(n->options,
- makeDefElem("verbose", NULL, @2));
+ n->options = $2;
n->rels = $3;
n->is_vacuumcmd = false;
$$ = (Node *) n;
}
- | analyze_keyword '(' utility_option_list ')' opt_vacuum_relation_list
+ | analyze_keyword VERBOSE opt_vacuum_relation_list
{
VacuumStmt *n = makeNode(VacuumStmt);
- n->options = $3;
- n->rels = $5;
+ n->options = list_make1(makeDefElem("verbose", NULL, @2));
+ n->rels = $3;
n->is_vacuumcmd = false;
$$ = (Node *) n;
}
;
-utility_option_list:
- utility_option_elem
- {
- $$ = list_make1($1);
- }
- | utility_option_list ',' utility_option_elem
- {
- $$ = lappend($1, $3);
- }
- ;
-
analyze_keyword:
ANALYZE
| ANALYSE /* British */
;
-utility_option_elem:
- utility_option_name utility_option_arg
- {
- $$ = makeDefElem($1, $2, @1);
- }
- ;
-
-utility_option_name:
- NonReservedWord { $$ = $1; }
- | analyze_keyword { $$ = "analyze"; }
- | FORMAT_LA { $$ = "format"; }
- ;
-
-utility_option_arg:
- opt_boolean_or_string { $$ = (Node *) makeString($1); }
- | NumericOnly { $$ = (Node *) $1; }
- | /* EMPTY */ { $$ = NULL; }
- ;
-
opt_analyze:
analyze_keyword { $$ = true; }
| /*EMPTY*/ { $$ = false; }
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 116ddf7b835..1ad65c237c3 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -613,6 +613,7 @@ ResetBackgroundWorkerCrashTimes(void)
* resetting.
*/
rw->rw_crashed_at = 0;
+ rw->rw_pid = 0;
/*
* If there was anyone waiting for it, they're history.
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index cca9b946e53..e01d9f0cfe8 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -2630,6 +2630,13 @@ CleanupBackend(PMChild *bp,
}
bp = NULL;
+ /*
+ * In a crash case, exit immediately without resetting background worker
+ * state. However, if restart_after_crash is enabled, the background
+ * worker state (e.g., rw_pid) still needs be reset so the worker can
+ * restart after crash recovery. This reset is handled in
+ * ResetBackgroundWorkerCrashTimes(), not here.
+ */
if (crashed)
{
HandleChildCrash(bp_pid, exitstatus, procname);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 4c72a0d43b3..ee911394a23 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -65,6 +65,7 @@
#include "funcapi.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
+#include "libpq/protocol.h"
#include "miscadmin.h"
#include "nodes/replnodes.h"
#include "pgstat.h"
@@ -735,13 +736,13 @@ HandleUploadManifestPacket(StringInfo buf, off_t *offset,
switch (mtype)
{
- case 'd': /* CopyData */
+ case PqMsg_CopyData:
maxmsglen = PQ_LARGE_MESSAGE_LIMIT;
break;
- case 'c': /* CopyDone */
- case 'f': /* CopyFail */
- case 'H': /* Flush */
- case 'S': /* Sync */
+ case PqMsg_CopyDone:
+ case PqMsg_CopyFail:
+ case PqMsg_Flush:
+ case PqMsg_Sync:
maxmsglen = PQ_SMALL_MESSAGE_LIMIT;
break;
default:
@@ -763,19 +764,19 @@ HandleUploadManifestPacket(StringInfo buf, off_t *offset,
/* Process the message */
switch (mtype)
{
- case 'd': /* CopyData */
+ case PqMsg_CopyData:
AppendIncrementalManifestData(ib, buf->data, buf->len);
return true;
- case 'c': /* CopyDone */
+ case PqMsg_CopyDone:
return false;
- case 'H': /* Sync */
- case 'S': /* Flush */
+ case PqMsg_Sync:
+ case PqMsg_Flush:
/* Ignore these while in CopyOut mode as we do elsewhere. */
return true;
- case 'f':
+ case PqMsg_CopyFail:
ereport(ERROR,
(errcode(ERRCODE_QUERY_CANCELED),
errmsg("COPY from stdin failed: %s",
@@ -1569,7 +1570,7 @@ WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid,
tmpbuf.data, sizeof(int64));
/* output previously gathered data in a CopyData packet */
- pq_putmessage_noblock('d', ctx->out->data, ctx->out->len);
+ pq_putmessage_noblock(PqMsg_CopyData, ctx->out->data, ctx->out->len);
CHECK_FOR_INTERRUPTS();
@@ -2305,7 +2306,7 @@ ProcessRepliesIfAny(void)
case PqMsg_CopyDone:
if (!streamingDoneSending)
{
- pq_putmessage_noblock('c', NULL, 0);
+ pq_putmessage_noblock(PqMsg_CopyDone, NULL, 0);
streamingDoneSending = true;
}
@@ -2758,7 +2759,7 @@ ProcessStandbyPSRequestMessage(void)
pq_sendint64(&output_message, GetCurrentTimestamp());
/* ... and send it wrapped in CopyData */
- pq_putmessage_noblock('d', output_message.data, output_message.len);
+ pq_putmessage_noblock(PqMsg_CopyData, output_message.data, output_message.len);
}
/*
@@ -3306,7 +3307,7 @@ XLogSendPhysical(void)
wal_segment_close(xlogreader);
/* Send CopyDone */
- pq_putmessage_noblock('c', NULL, 0);
+ pq_putmessage_noblock(PqMsg_CopyDone, NULL, 0);
streamingDoneSending = true;
WalSndCaughtUp = true;
@@ -3434,7 +3435,7 @@ retry:
memcpy(&output_message.data[1 + sizeof(int64) + sizeof(int64)],
tmpbuf.data, sizeof(int64));
- pq_putmessage_noblock('d', output_message.data, output_message.len);
+ pq_putmessage_noblock(PqMsg_CopyData, output_message.data, output_message.len);
sentPtr = endptr;
@@ -4140,7 +4141,7 @@ WalSndKeepalive(bool requestReply, XLogRecPtr writePtr)
pq_sendbyte(&output_message, requestReply ? 1 : 0);
/* ... and send it wrapped in CopyData */
- pq_putmessage_noblock('d', output_message.data, output_message.len);
+ pq_putmessage_noblock(PqMsg_CopyData, output_message.data, output_message.len);
/* Set local flag */
if (requestReply)
diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c
index c6aefd2f688..beadeb5e46a 100644
--- a/src/backend/storage/ipc/latch.c
+++ b/src/backend/storage/ipc/latch.c
@@ -187,9 +187,11 @@ WaitLatch(Latch *latch, int wakeEvents, long timeout,
if (!(wakeEvents & WL_LATCH_SET))
latch = NULL;
ModifyWaitEvent(LatchWaitSet, LatchWaitSetLatchPos, WL_LATCH_SET, latch);
- ModifyWaitEvent(LatchWaitSet, LatchWaitSetPostmasterDeathPos,
- (wakeEvents & (WL_EXIT_ON_PM_DEATH | WL_POSTMASTER_DEATH)),
- NULL);
+
+ if (IsUnderPostmaster)
+ ModifyWaitEvent(LatchWaitSet, LatchWaitSetPostmasterDeathPos,
+ (wakeEvents & (WL_EXIT_ON_PM_DEATH | WL_POSTMASTER_DEATH)),
+ NULL);
if (WaitEventSetWait(LatchWaitSet,
(wakeEvents & WL_TIMEOUT) ? timeout : -1,
diff --git a/src/backend/storage/lmgr/generate-lwlocknames.pl b/src/backend/storage/lmgr/generate-lwlocknames.pl
index c7a6720440d..cd3e43c448a 100644
--- a/src/backend/storage/lmgr/generate-lwlocknames.pl
+++ b/src/backend/storage/lmgr/generate-lwlocknames.pl
@@ -27,18 +27,24 @@ print $h "/* there is deliberately not an #ifndef LWLOCKNAMES_H here */\n\n";
#
-# First, record the predefined LWLocks listed in wait_event_names.txt. We'll
-# cross-check those with the ones in lwlocklist.h.
+# First, record the predefined LWLocks and built-in tranches listed in
+# wait_event_names.txt. We'll cross-check those with the ones in lwlocklist.h.
#
+my @wait_event_tranches;
my @wait_event_lwlocks;
my $record_lwlocks = 0;
+my $in_tranches = 0;
while (<$wait_event_names>)
{
chomp;
# Check for end marker.
- last if /^# END OF PREDEFINED LWLOCKS/;
+ if (/^# END OF PREDEFINED LWLOCKS/)
+ {
+ $in_tranches = 1;
+ next;
+ }
# Skip comments and empty lines.
next if /^#/;
@@ -54,13 +60,29 @@ while (<$wait_event_names>)
# Go to the next line if we are not yet recording LWLocks.
next if not $record_lwlocks;
+ # Stop recording if we reach another section.
+ last if /^Section:/;
+
# Record the LWLock.
(my $waiteventname, my $waitevendocsentence) = split(/\t/, $_);
- push(@wait_event_lwlocks, $waiteventname);
+
+ if ($in_tranches)
+ {
+ push(@wait_event_tranches, $waiteventname);
+ }
+ else
+ {
+ push(@wait_event_lwlocks, $waiteventname);
+ }
}
+#
+# While gathering the list of predefined LWLocks, cross-check the lists in
+# lwlocklist.h with the wait events we just recorded.
+#
my $in_comment = 0;
-my $i = 0;
+my $lwlock_count = 0;
+my $tranche_count = 0;
while (<$lwlocklist>)
{
chomp;
@@ -81,38 +103,72 @@ while (<$lwlocklist>)
next;
}
- die "unable to parse lwlocklist.h line \"$_\""
- unless /^PG_LWLOCK\((\d+),\s+(\w+)\)$/;
+ #
+ # Gather list of predefined LWLocks and cross-check with the wait events.
+ #
+ if (/^PG_LWLOCK\((\d+),\s+(\w+)\)$/)
+ {
+ my ($lockidx, $lockname) = ($1, $2);
- (my $lockidx, my $lockname) = ($1, $2);
+ die "lwlocklist.h not in order" if $lockidx < $lastlockidx;
+ die "lwlocklist.h has duplicates" if $lockidx == $lastlockidx;
- die "lwlocklist.h not in order" if $lockidx < $lastlockidx;
- die "lwlocklist.h has duplicates" if $lockidx == $lastlockidx;
+ die "$lockname defined in lwlocklist.h but missing from "
+ . "wait_event_names.txt"
+ if $lwlock_count >= scalar @wait_event_lwlocks;
+ die "lists of predefined LWLocks do not match (first mismatch at "
+ . "$wait_event_lwlocks[$lwlock_count] in wait_event_names.txt and "
+ . "$lockname in lwlocklist.h)"
+ if $wait_event_lwlocks[$lwlock_count] ne $lockname;
- die "$lockname defined in lwlocklist.h but missing from "
- . "wait_event_names.txt"
- if $i >= scalar @wait_event_lwlocks;
- die "lists of predefined LWLocks do not match (first mismatch at "
- . "$wait_event_lwlocks[$i] in wait_event_names.txt and $lockname in "
- . "lwlocklist.h)"
- if $wait_event_lwlocks[$i] ne $lockname;
- $i++;
+ $lwlock_count++;
- while ($lastlockidx < $lockidx - 1)
+ while ($lastlockidx < $lockidx - 1)
+ {
+ ++$lastlockidx;
+ }
+ $lastlockidx = $lockidx;
+
+ # Add a "Lock" suffix to each lock name, as the C code depends on that.
+ printf $h "#define %-32s (&MainLWLockArray[$lockidx].lock)\n",
+ $lockname . "Lock";
+
+ next;
+ }
+
+ #
+ # Cross-check the built-in LWLock tranches with the wait events.
+ #
+ if (/^PG_LWLOCKTRANCHE\((\w+),\s+(\w+)\)$/)
{
- ++$lastlockidx;
+ my ($tranche_id, $tranche_name) = ($1, $2);
+
+ die "$tranche_name defined in lwlocklist.h but missing from "
+ . "wait_event_names.txt"
+ if $tranche_count >= scalar @wait_event_tranches;
+ die
+ "lists of built-in LWLock tranches do not match (first mismatch at "
+ . "$wait_event_tranches[$tranche_count] in wait_event_names.txt and "
+ . "$tranche_name in lwlocklist.h)"
+ if $wait_event_tranches[$tranche_count] ne $tranche_name;
+
+ $tranche_count++;
+
+ next;
}
- $lastlockidx = $lockidx;
- # Add a "Lock" suffix to each lock name, as the C code depends on that
- printf $h "#define %-32s (&MainLWLockArray[$lockidx].lock)\n",
- $lockname . "Lock";
+ die "unable to parse lwlocklist.h line \"$_\"";
}
die
- "$wait_event_lwlocks[$i] defined in wait_event_names.txt but missing from "
- . "lwlocklist.h"
- if $i < scalar @wait_event_lwlocks;
+ "$wait_event_lwlocks[$lwlock_count] defined in wait_event_names.txt but "
+ . " missing from lwlocklist.h"
+ if $lwlock_count < scalar @wait_event_lwlocks;
+
+die
+ "$wait_event_tranches[$tranche_count] defined in wait_event_names.txt but "
+ . "missing from lwlocklist.h"
+ if $tranche_count < scalar @wait_event_tranches;
print $h "\n";
printf $h "#define NUM_INDIVIDUAL_LWLOCKS %s\n", $lastlockidx + 1;
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 2d43bf2cc13..ec9c345ffdf 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -122,9 +122,8 @@ StaticAssertDecl((LW_VAL_EXCLUSIVE & LW_FLAG_MASK) == 0,
* own tranche. We absorb the names of these tranches from there into
* BuiltinTrancheNames here.
*
- * 2. There are some predefined tranches for built-in groups of locks.
- * These are listed in enum BuiltinTrancheIds in lwlock.h, and their names
- * appear in BuiltinTrancheNames[] below.
+ * 2. There are some predefined tranches for built-in groups of locks defined
+ * in lwlocklist.h. We absorb the names of these tranches, too.
*
* 3. Extensions can create new tranches, via either RequestNamedLWLockTranche
* or LWLockRegisterTranche. The names of these that are known in the current
@@ -135,49 +134,10 @@ StaticAssertDecl((LW_VAL_EXCLUSIVE & LW_FLAG_MASK) == 0,
*/
static const char *const BuiltinTrancheNames[] = {
#define PG_LWLOCK(id, lockname) [id] = CppAsString(lockname),
+#define PG_LWLOCKTRANCHE(id, lockname) [LWTRANCHE_##id] = CppAsString(lockname),
#include "storage/lwlocklist.h"
#undef PG_LWLOCK
- [LWTRANCHE_XACT_BUFFER] = "XactBuffer",
- [LWTRANCHE_COMMITTS_BUFFER] = "CommitTsBuffer",
- [LWTRANCHE_SUBTRANS_BUFFER] = "SubtransBuffer",
- [LWTRANCHE_MULTIXACTOFFSET_BUFFER] = "MultiXactOffsetBuffer",
- [LWTRANCHE_MULTIXACTMEMBER_BUFFER] = "MultiXactMemberBuffer",
- [LWTRANCHE_NOTIFY_BUFFER] = "NotifyBuffer",
- [LWTRANCHE_SERIAL_BUFFER] = "SerialBuffer",
- [LWTRANCHE_WAL_INSERT] = "WALInsert",
- [LWTRANCHE_BUFFER_CONTENT] = "BufferContent",
- [LWTRANCHE_REPLICATION_ORIGIN_STATE] = "ReplicationOriginState",
- [LWTRANCHE_REPLICATION_SLOT_IO] = "ReplicationSlotIO",
- [LWTRANCHE_LOCK_FASTPATH] = "LockFastPath",
- [LWTRANCHE_BUFFER_MAPPING] = "BufferMapping",
- [LWTRANCHE_LOCK_MANAGER] = "LockManager",
- [LWTRANCHE_PREDICATE_LOCK_MANAGER] = "PredicateLockManager",
- [LWTRANCHE_PARALLEL_HASH_JOIN] = "ParallelHashJoin",
- [LWTRANCHE_PARALLEL_BTREE_SCAN] = "ParallelBtreeScan",
- [LWTRANCHE_PARALLEL_QUERY_DSA] = "ParallelQueryDSA",
- [LWTRANCHE_PER_SESSION_DSA] = "PerSessionDSA",
- [LWTRANCHE_PER_SESSION_RECORD_TYPE] = "PerSessionRecordType",
- [LWTRANCHE_PER_SESSION_RECORD_TYPMOD] = "PerSessionRecordTypmod",
- [LWTRANCHE_SHARED_TUPLESTORE] = "SharedTupleStore",
- [LWTRANCHE_SHARED_TIDBITMAP] = "SharedTidBitmap",
- [LWTRANCHE_PARALLEL_APPEND] = "ParallelAppend",
- [LWTRANCHE_PER_XACT_PREDICATE_LIST] = "PerXactPredicateList",
- [LWTRANCHE_PGSTATS_DSA] = "PgStatsDSA",
- [LWTRANCHE_PGSTATS_HASH] = "PgStatsHash",
- [LWTRANCHE_PGSTATS_DATA] = "PgStatsData",
- [LWTRANCHE_LAUNCHER_DSA] = "LogicalRepLauncherDSA",
- [LWTRANCHE_LAUNCHER_HASH] = "LogicalRepLauncherHash",
- [LWTRANCHE_DSM_REGISTRY_DSA] = "DSMRegistryDSA",
- [LWTRANCHE_DSM_REGISTRY_HASH] = "DSMRegistryHash",
- [LWTRANCHE_COMMITTS_SLRU] = "CommitTsSLRU",
- [LWTRANCHE_MULTIXACTOFFSET_SLRU] = "MultiXactOffsetSLRU",
- [LWTRANCHE_MULTIXACTMEMBER_SLRU] = "MultiXactMemberSLRU",
- [LWTRANCHE_NOTIFY_SLRU] = "NotifySLRU",
- [LWTRANCHE_SERIAL_SLRU] = "SerialSLRU",
- [LWTRANCHE_SUBTRANS_SLRU] = "SubtransSLRU",
- [LWTRANCHE_XACT_SLRU] = "XactSLRU",
- [LWTRANCHE_PARALLEL_VACUUM_DSA] = "ParallelVacuumDSA",
- [LWTRANCHE_AIO_URING_COMPLETION] = "AioUringCompletion",
+#undef PG_LWLOCKTRANCHE
};
StaticAssertDecl(lengthof(BuiltinTrancheNames) ==
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2f8c3d5f918..a297606cdd7 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -988,6 +988,7 @@ pg_plan_queries(List *querytrees, const char *query_string, int cursorOptions,
stmt->stmt_location = query->stmt_location;
stmt->stmt_len = query->stmt_len;
stmt->queryId = query->queryId;
+ stmt->cached_plan_type = PLAN_CACHE_NONE;
}
else
{
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 4c1faf5575c..babc34d0cbe 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1234,6 +1234,7 @@ ProcessUtilitySlow(ParseState *pstate,
wrapper->utilityStmt = stmt;
wrapper->stmt_location = pstmt->stmt_location;
wrapper->stmt_len = pstmt->stmt_len;
+ wrapper->cached_plan_type = PLAN_CACHE_NONE;
ProcessUtility(wrapper,
queryString,
@@ -1964,6 +1965,7 @@ ProcessUtilityForAlterTable(Node *stmt, AlterTableUtilityContext *context)
wrapper->utilityStmt = stmt;
wrapper->stmt_location = context->pstmt->stmt_location;
wrapper->stmt_len = context->pstmt->stmt_len;
+ wrapper->cached_plan_type = PLAN_CACHE_NONE;
ProcessUtility(wrapper,
context->queryString,
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
index 4da68312b5f..0be307d2ca0 100644
--- a/src/backend/utils/activity/wait_event_names.txt
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -356,9 +356,13 @@ AioWorkerSubmissionQueue "Waiting to access AIO worker submission queue."
#
# END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE)
#
-# Predefined LWLocks (i.e., those declared in lwlocknames.h) must be listed
-# in the section above and must be listed in the same order as in
-# lwlocknames.h. Other LWLocks must be listed in the section below.
+# Predefined LWLocks (i.e., those declared at the top of lwlocknames.h) must be
+# listed in the section above and must be listed in the same order as in
+# lwlocknames.h.
+#
+# Likewise, the built-in LWLock tranches (i.e., those declared at the bottom of
+# lwlocknames.h) must be listed in the section below and must be listed in the
+# same order as in lwlocknames.h.
#
XactBuffer "Waiting for I/O on a transaction status SLRU buffer."
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 89a1c79e984..f4d2b9458a5 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -1283,6 +1283,7 @@ GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams,
CachedPlan *plan = NULL;
List *qlist;
bool customplan;
+ ListCell *lc;
/* Assert caller is doing things in a sane order */
Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
@@ -1385,6 +1386,13 @@ GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams,
plan->is_saved = true;
}
+ foreach(lc, plan->stmt_list)
+ {
+ PlannedStmt *pstmt = (PlannedStmt *) lfirst(lc);
+
+ pstmt->cached_plan_type = customplan ? PLAN_CACHE_CUSTOM : PLAN_CACHE_GENERIC;
+ }
+
return plan;
}
diff --git a/src/bin/pg_basebackup/pg_createsubscriber.c b/src/bin/pg_basebackup/pg_createsubscriber.c
index 025b893a41e..3986882f042 100644
--- a/src/bin/pg_basebackup/pg_createsubscriber.c
+++ b/src/bin/pg_basebackup/pg_createsubscriber.c
@@ -1250,8 +1250,17 @@ setup_recovery(const struct LogicalRepInfo *dbinfo, const char *datadir, const c
appendPQExpBufferStr(recoveryconfcontents, "recovery_target = ''\n");
appendPQExpBufferStr(recoveryconfcontents,
"recovery_target_timeline = 'latest'\n");
+
+ /*
+ * Set recovery_target_inclusive = false to avoid reapplying the
+ * transaction committed at 'lsn' after subscription is enabled. This is
+ * because the provided 'lsn' is also used as the replication start point
+ * for the subscription. So, the server can send the transaction committed
+ * at that 'lsn' after replication is started which can lead to applying
+ * the same transaction twice if we keep recovery_target_inclusive = true.
+ */
appendPQExpBufferStr(recoveryconfcontents,
- "recovery_target_inclusive = true\n");
+ "recovery_target_inclusive = false\n");
appendPQExpBufferStr(recoveryconfcontents,
"recovery_target_action = promote\n");
appendPQExpBufferStr(recoveryconfcontents, "recovery_target_name = ''\n");
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 2cf8d55d706..cc06fc29ab2 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -316,16 +316,6 @@ typedef struct XLogRecData
uint32 len; /* length of rmgr data to include */
} XLogRecData;
-/*
- * Recovery target action.
- */
-typedef enum
-{
- RECOVERY_TARGET_ACTION_PAUSE,
- RECOVERY_TARGET_ACTION_PROMOTE,
- RECOVERY_TARGET_ACTION_SHUTDOWN,
-} RecoveryTargetAction;
-
struct LogicalDecodingContext;
struct XLogRecordBuffer;
diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h
index 91446303024..8e475e266d1 100644
--- a/src/include/access/xlogrecovery.h
+++ b/src/include/access/xlogrecovery.h
@@ -40,6 +40,16 @@ typedef enum
RECOVERY_TARGET_TIMELINE_NUMERIC,
} RecoveryTargetTimeLineGoal;
+/*
+ * Recovery target action.
+ */
+typedef enum
+{
+ RECOVERY_TARGET_ACTION_PAUSE,
+ RECOVERY_TARGET_ACTION_PROMOTE,
+ RECOVERY_TARGET_ACTION_SHUTDOWN,
+} RecoveryTargetAction;
+
/* Recovery pause states */
typedef enum RecoveryPauseState
{
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 4f59e30d62d..46e2e09ea35 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -29,6 +29,20 @@
*/
/* ----------------
+ * CachedPlanType
+ *
+ * CachedPlanType identifies whether a PlannedStmt is a cached plan, and if
+ * so, whether it is generic or custom.
+ * ----------------
+ */
+typedef enum CachedPlanType
+{
+ PLAN_CACHE_NONE = 0, /* Not a cached plan */
+ PLAN_CACHE_GENERIC, /* Generic cached plan */
+ PLAN_CACHE_CUSTOM, /* Custom cached plan */
+} CachedPlanType;
+
+/* ----------------
* PlannedStmt node
*
* The output of the planner is a Plan tree headed by a PlannedStmt node.
@@ -58,6 +72,9 @@ typedef struct PlannedStmt
/* plan identifier (can be set by plugins) */
int64 planId;
+ /* type of cached plan */
+ CachedPlanType cached_plan_type;
+
/* is it insert|update|delete|merge RETURNING? */
bool hasReturning;
diff --git a/src/include/port/solaris.h b/src/include/port/solaris.h
index e63a3bd824d..8ff40007c7f 100644
--- a/src/include/port/solaris.h
+++ b/src/include/port/solaris.h
@@ -24,3 +24,12 @@
#if defined(__i386__)
#include <sys/isa_defs.h>
#endif
+
+/*
+ * On original Solaris, PAM conversation procs lack a "const" in their
+ * declaration; but recent OpenIndiana versions put it there by default.
+ * The least messy way to deal with this is to define _PAM_LEGACY_NONCONST,
+ * which causes OpenIndiana to declare pam_conv per the Solaris tradition,
+ * and also use that symbol to control omitting the "const" in our own code.
+ */
+#define _PAM_LEGACY_NONCONST 1
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index 08a72569ae5..5e717765764 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -176,51 +176,23 @@ extern void LWLockInitialize(LWLock *lock, int tranche_id);
* Every tranche ID less than NUM_INDIVIDUAL_LWLOCKS is reserved; also,
* we reserve additional tranche IDs for builtin tranches not included in
* the set of individual LWLocks. A call to LWLockNewTrancheId will never
- * return a value less than LWTRANCHE_FIRST_USER_DEFINED.
+ * return a value less than LWTRANCHE_FIRST_USER_DEFINED. The actual list of
+ * built-in tranches is kept in lwlocklist.h.
*/
typedef enum BuiltinTrancheIds
{
- LWTRANCHE_XACT_BUFFER = NUM_INDIVIDUAL_LWLOCKS,
- LWTRANCHE_COMMITTS_BUFFER,
- LWTRANCHE_SUBTRANS_BUFFER,
- LWTRANCHE_MULTIXACTOFFSET_BUFFER,
- LWTRANCHE_MULTIXACTMEMBER_BUFFER,
- LWTRANCHE_NOTIFY_BUFFER,
- LWTRANCHE_SERIAL_BUFFER,
- LWTRANCHE_WAL_INSERT,
- LWTRANCHE_BUFFER_CONTENT,
- LWTRANCHE_REPLICATION_ORIGIN_STATE,
- LWTRANCHE_REPLICATION_SLOT_IO,
- LWTRANCHE_LOCK_FASTPATH,
- LWTRANCHE_BUFFER_MAPPING,
- LWTRANCHE_LOCK_MANAGER,
- LWTRANCHE_PREDICATE_LOCK_MANAGER,
- LWTRANCHE_PARALLEL_HASH_JOIN,
- LWTRANCHE_PARALLEL_BTREE_SCAN,
- LWTRANCHE_PARALLEL_QUERY_DSA,
- LWTRANCHE_PER_SESSION_DSA,
- LWTRANCHE_PER_SESSION_RECORD_TYPE,
- LWTRANCHE_PER_SESSION_RECORD_TYPMOD,
- LWTRANCHE_SHARED_TUPLESTORE,
- LWTRANCHE_SHARED_TIDBITMAP,
- LWTRANCHE_PARALLEL_APPEND,
- LWTRANCHE_PER_XACT_PREDICATE_LIST,
- LWTRANCHE_PGSTATS_DSA,
- LWTRANCHE_PGSTATS_HASH,
- LWTRANCHE_PGSTATS_DATA,
- LWTRANCHE_LAUNCHER_DSA,
- LWTRANCHE_LAUNCHER_HASH,
- LWTRANCHE_DSM_REGISTRY_DSA,
- LWTRANCHE_DSM_REGISTRY_HASH,
- LWTRANCHE_COMMITTS_SLRU,
- LWTRANCHE_MULTIXACTMEMBER_SLRU,
- LWTRANCHE_MULTIXACTOFFSET_SLRU,
- LWTRANCHE_NOTIFY_SLRU,
- LWTRANCHE_SERIAL_SLRU,
- LWTRANCHE_SUBTRANS_SLRU,
- LWTRANCHE_XACT_SLRU,
- LWTRANCHE_PARALLEL_VACUUM_DSA,
- LWTRANCHE_AIO_URING_COMPLETION,
+ /*
+ * LWTRANCHE_INVALID is an unused value that only exists to initialize the
+ * rest of the tranches to appropriate values.
+ */
+ LWTRANCHE_INVALID = NUM_INDIVIDUAL_LWLOCKS - 1,
+
+#define PG_LWLOCK(id, name)
+#define PG_LWLOCKTRANCHE(id, name) LWTRANCHE_##id,
+#include "storage/lwlocklist.h"
+#undef PG_LWLOCK
+#undef PG_LWLOCKTRANCHE
+
LWTRANCHE_FIRST_USER_DEFINED,
} BuiltinTrancheIds;
diff --git a/src/include/storage/lwlocklist.h b/src/include/storage/lwlocklist.h
index a9681738146..208d2e3a8ed 100644
--- a/src/include/storage/lwlocklist.h
+++ b/src/include/storage/lwlocklist.h
@@ -2,9 +2,10 @@
*
* lwlocklist.h
*
- * The predefined LWLock list is kept in its own source file for use by
- * automatic tools. The exact representation of a keyword is determined by
- * the PG_LWLOCK macro, which is not defined in this file; it can be
+ * The list of predefined LWLocks and built-in LWLock tranches is kept in
+ * its own source file for use by automatic tools. The exact
+ * representation of a keyword is determined by the PG_LWLOCK and
+ * PG_LWLOCKTRANCHE macros, which are not defined in this file; they can be
* defined by the caller for special purposes.
*
* Also, generate-lwlocknames.pl processes this file to create lwlocknames.h.
@@ -84,3 +85,53 @@ PG_LWLOCK(50, DSMRegistry)
PG_LWLOCK(51, InjectionPoint)
PG_LWLOCK(52, SerialControl)
PG_LWLOCK(53, AioWorkerSubmissionQueue)
+
+/*
+ * There also exist several built-in LWLock tranches. As with the predefined
+ * LWLocks, be sure to update the WaitEventLWLock section of
+ * src/backend/utils/activity/wait_event_names.txt when modifying this list.
+ *
+ * Note that the IDs here (the first value) don't include the LWTRANCHE_
+ * prefix. It's added elsewhere.
+ */
+PG_LWLOCKTRANCHE(XACT_BUFFER, XactBuffer)
+PG_LWLOCKTRANCHE(COMMITTS_BUFFER, CommitTsBuffer)
+PG_LWLOCKTRANCHE(SUBTRANS_BUFFER, SubtransBuffer)
+PG_LWLOCKTRANCHE(MULTIXACTOFFSET_BUFFER, MultiXactOffsetBuffer)
+PG_LWLOCKTRANCHE(MULTIXACTMEMBER_BUFFER, MultiXactMemberBuffer)
+PG_LWLOCKTRANCHE(NOTIFY_BUFFER, NotifyBuffer)
+PG_LWLOCKTRANCHE(SERIAL_BUFFER, SerialBuffer)
+PG_LWLOCKTRANCHE(WAL_INSERT, WALInsert)
+PG_LWLOCKTRANCHE(BUFFER_CONTENT, BufferContent)
+PG_LWLOCKTRANCHE(REPLICATION_ORIGIN_STATE, ReplicationOriginState)
+PG_LWLOCKTRANCHE(REPLICATION_SLOT_IO, ReplicationSlotIO)
+PG_LWLOCKTRANCHE(LOCK_FASTPATH, LockFastPath)
+PG_LWLOCKTRANCHE(BUFFER_MAPPING, BufferMapping)
+PG_LWLOCKTRANCHE(LOCK_MANAGER, LockManager)
+PG_LWLOCKTRANCHE(PREDICATE_LOCK_MANAGER, PredicateLockManager)
+PG_LWLOCKTRANCHE(PARALLEL_HASH_JOIN, ParallelHashJoin)
+PG_LWLOCKTRANCHE(PARALLEL_BTREE_SCAN, ParallelBtreeScan)
+PG_LWLOCKTRANCHE(PARALLEL_QUERY_DSA, ParallelQueryDSA)
+PG_LWLOCKTRANCHE(PER_SESSION_DSA, PerSessionDSA)
+PG_LWLOCKTRANCHE(PER_SESSION_RECORD_TYPE, PerSessionRecordType)
+PG_LWLOCKTRANCHE(PER_SESSION_RECORD_TYPMOD, PerSessionRecordTypmod)
+PG_LWLOCKTRANCHE(SHARED_TUPLESTORE, SharedTupleStore)
+PG_LWLOCKTRANCHE(SHARED_TIDBITMAP, SharedTidBitmap)
+PG_LWLOCKTRANCHE(PARALLEL_APPEND, ParallelAppend)
+PG_LWLOCKTRANCHE(PER_XACT_PREDICATE_LIST, PerXactPredicateList)
+PG_LWLOCKTRANCHE(PGSTATS_DSA, PgStatsDSA)
+PG_LWLOCKTRANCHE(PGSTATS_HASH, PgStatsHash)
+PG_LWLOCKTRANCHE(PGSTATS_DATA, PgStatsData)
+PG_LWLOCKTRANCHE(LAUNCHER_DSA, LogicalRepLauncherDSA)
+PG_LWLOCKTRANCHE(LAUNCHER_HASH, LogicalRepLauncherHash)
+PG_LWLOCKTRANCHE(DSM_REGISTRY_DSA, DSMRegistryDSA)
+PG_LWLOCKTRANCHE(DSM_REGISTRY_HASH, DSMRegistryHash)
+PG_LWLOCKTRANCHE(COMMITTS_SLRU, CommitTsSLRU)
+PG_LWLOCKTRANCHE(MULTIXACTOFFSET_SLRU, MultiXactOffsetSLRU)
+PG_LWLOCKTRANCHE(MULTIXACTMEMBER_SLRU, MultiXactMemberSLRU)
+PG_LWLOCKTRANCHE(NOTIFY_SLRU, NotifySLRU)
+PG_LWLOCKTRANCHE(SERIAL_SLRU, SerialSLRU)
+PG_LWLOCKTRANCHE(SUBTRANS_SLRU, SubtransSLRU)
+PG_LWLOCKTRANCHE(XACT_SLRU, XactSLRU)
+PG_LWLOCKTRANCHE(PARALLEL_VACUUM_DSA, ParallelVacuumDSA)
+PG_LWLOCKTRANCHE(AIO_URING_COMPLETION, AioUringCompletion)
diff --git a/src/include/utils/pgstat_kind.h b/src/include/utils/pgstat_kind.h
index f44169fd5a3..eb5f0b3ae6d 100644
--- a/src/include/utils/pgstat_kind.h
+++ b/src/include/utils/pgstat_kind.h
@@ -18,7 +18,7 @@
/* Range of IDs allowed, for built-in and custom kinds */
#define PGSTAT_KIND_MIN 1 /* Minimum ID allowed */
-#define PGSTAT_KIND_MAX 256 /* Maximum ID allowed */
+#define PGSTAT_KIND_MAX 32 /* Maximum ID allowed */
/* use 0 for INVALID, to catch zero-initialized data */
#define PGSTAT_KIND_INVALID 0
@@ -46,7 +46,7 @@
/* Custom stats kinds */
/* Range of IDs allowed for custom stats kinds */
-#define PGSTAT_KIND_CUSTOM_MIN 128
+#define PGSTAT_KIND_CUSTOM_MIN 24
#define PGSTAT_KIND_CUSTOM_MAX PGSTAT_KIND_MAX
#define PGSTAT_KIND_CUSTOM_SIZE (PGSTAT_KIND_CUSTOM_MAX - PGSTAT_KIND_CUSTOM_MIN + 1)
@@ -55,7 +55,7 @@
* development and have not reserved their own unique kind ID yet. See:
* https://wiki.postgresql.org/wiki/CustomCumulativeStats
*/
-#define PGSTAT_KIND_EXPERIMENTAL 128
+#define PGSTAT_KIND_EXPERIMENTAL 24
static inline bool
pgstat_is_kind_builtin(PgStat_Kind kind)
diff --git a/src/test/modules/injection_points/injection_stats.c b/src/test/modules/injection_points/injection_stats.c
index 14903c629e0..e3947b23ba5 100644
--- a/src/test/modules/injection_points/injection_stats.c
+++ b/src/test/modules/injection_points/injection_stats.c
@@ -59,7 +59,7 @@ static const PgStat_KindInfo injection_stats = {
/*
* Kind ID reserved for statistics of injection points.
*/
-#define PGSTAT_KIND_INJECTION 129
+#define PGSTAT_KIND_INJECTION 25
/* Track if stats are loaded */
static bool inj_stats_loaded = false;
diff --git a/src/test/modules/injection_points/injection_stats_fixed.c b/src/test/modules/injection_points/injection_stats_fixed.c
index 3d0c01bdd05..bc54c79d190 100644
--- a/src/test/modules/injection_points/injection_stats_fixed.c
+++ b/src/test/modules/injection_points/injection_stats_fixed.c
@@ -64,7 +64,7 @@ static const PgStat_KindInfo injection_stats_fixed = {
/*
* Kind ID reserved for statistics of injection points.
*/
-#define PGSTAT_KIND_INJECTION_FIXED 130
+#define PGSTAT_KIND_INJECTION_FIXED 26
/* Track if fixed-numbered stats are loaded */
static bool inj_fixed_loaded = false;
diff --git a/src/test/subscription/t/035_conflicts.pl b/src/test/subscription/t/035_conflicts.pl
index 7458d7fba7e..976d53a870e 100644
--- a/src/test/subscription/t/035_conflicts.pl
+++ b/src/test/subscription/t/035_conflicts.pl
@@ -228,6 +228,11 @@ ok( $stderr =~
# Disable the subscription
$node_A->psql('postgres', "ALTER SUBSCRIPTION $subname_AB DISABLE;");
+# Wait for the apply worker to stop
+$node_A->poll_query_until('postgres',
+ "SELECT count(*) = 0 FROM pg_stat_activity WHERE backend_type = 'logical replication apply worker'"
+);
+
# Enable retain_dead_tuples for disabled subscription
($cmdret, $stdout, $stderr) = $node_A->psql('postgres',
"ALTER SUBSCRIPTION $subname_AB SET (retain_dead_tuples = true);");
@@ -278,6 +283,11 @@ is($result, qq(1|1
# Disable the logical replication from node B to node A
$node_A->safe_psql('postgres', "ALTER SUBSCRIPTION $subname_AB DISABLE");
+# Wait for the apply worker to stop
+$node_A->poll_query_until('postgres',
+ "SELECT count(*) = 0 FROM pg_stat_activity WHERE backend_type = 'logical replication apply worker'"
+);
+
$node_B->safe_psql('postgres', "UPDATE tab SET b = 3 WHERE a = 1;");
$node_A->safe_psql('postgres', "DELETE FROM tab WHERE a = 1;");
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index a8656419cb6..4353befab99 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -391,6 +391,7 @@ CachedFunctionHashEntry
CachedFunctionHashKey
CachedPlan
CachedPlanSource
+CachedPlanType
CallContext
CallStmt
CancelRequestPacket