0001-Add-multixact-CV-sleep.patch
application/octet-stream
Filename: 0001-Add-multixact-CV-sleep.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Add multixact CV sleep
| File | + | − |
|---|---|---|
| src/backend/access/transam/multixact.c | 5 | 0 |
| src/test/modules/injection_points/injection_points--1.0.sql | 1 | 1 |
| src/test/modules/injection_points/injection_points.c | 1 | 1 |
| src/test/modules/test_slru/Makefile | 3 | 0 |
| src/test/modules/test_slru/meson.build | 8 | 0 |
| src/test/modules/test_slru/t/001_multixact.pl | 66 | 0 |
| src/test/modules/test_slru/test_slru--1.0.sql | 6 | 0 |
| src/test/modules/test_slru/test_slru.c | 29 | 0 |
From 61e698159acd8d0a374292a75bbbcd3ad2bf8a48 Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Mon, 20 May 2024 15:20:31 +0500
Subject: [PATCH] Add multixact CV sleep
---
src/backend/access/transam/multixact.c | 5 ++
.../injection_points--1.0.sql | 2 +-
.../injection_points/injection_points.c | 2 +-
src/test/modules/test_slru/Makefile | 3 +
src/test/modules/test_slru/meson.build | 8 +++
src/test/modules/test_slru/t/001_multixact.pl | 66 +++++++++++++++++++
src/test/modules/test_slru/test_slru--1.0.sql | 6 ++
src/test/modules/test_slru/test_slru.c | 29 ++++++++
8 files changed, 119 insertions(+), 2 deletions(-)
create mode 100644 src/test/modules/test_slru/t/001_multixact.pl
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 54c916e0347..58ec847cf02 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -88,6 +88,7 @@
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/fmgrprotos.h"
+#include "utils/injection_point.h"
#include "utils/guc_hooks.h"
#include "utils/memutils.h"
@@ -825,8 +826,12 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
* in vacuum. During vacuum, in particular, it would be unacceptable to
* keep OldestMulti set, in case it runs for long.
*/
+ INJECTION_POINT_PRELOAD("GetNewMultiXactId-done");
+
multi = GetNewMultiXactId(nmembers, &offset);
+ INJECTION_POINT("GetNewMultiXactId-done");
+
/* Make an XLOG entry describing the new MXID. */
xlrec.mid = multi;
xlrec.moff = offset;
diff --git a/src/test/modules/injection_points/injection_points--1.0.sql b/src/test/modules/injection_points/injection_points--1.0.sql
index 29d43cc5566..998a513bffc 100644
--- a/src/test/modules/injection_points/injection_points--1.0.sql
+++ b/src/test/modules/injection_points/injection_points--1.0.sql
@@ -73,4 +73,4 @@ LANGUAGE C STRICT PARALLEL UNSAFE;
CREATE FUNCTION injection_points_detach(IN point_name TEXT)
RETURNS void
AS 'MODULE_PATHNAME', 'injection_points_detach'
-LANGUAGE C STRICT PARALLEL UNSAFE;
+LANGUAGE C STRICT PARALLEL UNSAFE;
\ No newline at end of file
diff --git a/src/test/modules/injection_points/injection_points.c b/src/test/modules/injection_points/injection_points.c
index 086b8a6a5e4..a819aebe5b3 100644
--- a/src/test/modules/injection_points/injection_points.c
+++ b/src/test/modules/injection_points/injection_points.c
@@ -452,4 +452,4 @@ injection_points_detach(PG_FUNCTION_ARGS)
}
PG_RETURN_VOID();
-}
+}
\ No newline at end of file
diff --git a/src/test/modules/test_slru/Makefile b/src/test/modules/test_slru/Makefile
index 936886753b7..a0f49129079 100644
--- a/src/test/modules/test_slru/Makefile
+++ b/src/test/modules/test_slru/Makefile
@@ -6,6 +6,9 @@ OBJS = \
test_slru.o
PGFILEDESC = "test_slru - test module for SLRUs"
+EXTRA_INSTALL=src/test/modules/injection_points
+TAP_TESTS = 1
+
EXTENSION = test_slru
DATA = test_slru--1.0.sql
diff --git a/src/test/modules/test_slru/meson.build b/src/test/modules/test_slru/meson.build
index ce91e606313..4a5bc6349a4 100644
--- a/src/test/modules/test_slru/meson.build
+++ b/src/test/modules/test_slru/meson.build
@@ -32,4 +32,12 @@ tests += {
'regress_args': ['--temp-config', files('test_slru.conf')],
'runningcheck': false,
},
+ 'tap': {
+ 'env': {
+ 'enable_injection_points': get_option('injection_points') ? 'yes' : 'no',
+ },
+ 'tests': [
+ 't/001_multixact.pl'
+ ],
+ },
}
diff --git a/src/test/modules/test_slru/t/001_multixact.pl b/src/test/modules/test_slru/t/001_multixact.pl
new file mode 100644
index 00000000000..b46e0994351
--- /dev/null
+++ b/src/test/modules/test_slru/t/001_multixact.pl
@@ -0,0 +1,66 @@
+
+# Copyright (c) 2024, PostgreSQL Global Development Group
+
+use strict;
+use warnings FATAL => 'all';
+
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+
+use Test::More;
+
+my ($node, $result);
+
+$node = PostgreSQL::Test::Cluster->new('multixact_CV_sleep');
+$node->init;
+$node->append_conf('postgresql.conf',
+ "shared_preload_libraries = 'test_slru'");
+$node->start;
+$node->safe_psql('postgres', q(CREATE EXTENSION injection_points));
+$node->safe_psql('postgres', q(CREATE EXTENSION test_slru));
+
+# Test for Multixact generation edge case
+$node->safe_psql('postgres', q(select injection_points_attach('test_read_multixact','wait')));
+$node->safe_psql('postgres', q(select injection_points_attach('GetMultiXactIdMembers-CV-sleep','notice')));
+
+# This session must observe sleep on CV when generating multixact.
+# To achive this it first will create a multixact, then pause before reading it.
+my $observer = $node->background_psql('postgres');
+
+$observer->query_until(qr/start/,
+q(
+ \echo start
+ select test_read_multixact(test_create_multixact());
+));
+
+# This session will create next Multixact, it's necessary to avoid edge case 1 (see multixact.c)
+my $creator = $node->background_psql('postgres');
+$node->safe_psql('postgres', q(select injection_points_attach('GetNewMultiXactId-done','wait')));
+
+# We expect this query to hand in critical section after generating new multixact,
+# but before filling it's offset into SLRU
+$creator->query_until(qr/start/, q(
+ \echo start
+ select test_create_multixact();
+));
+
+# Now we are sure we can reach edge case 2. Proceed session that is reading that multixact.
+$node->safe_psql('postgres', q(select injection_points_detach('test_read_multixact')));
+
+# Release critical section. We have to do this so everyon can proceed.
+# But this is inherent race condition, I hope the tast will not be unstable here.
+# The only way to stabilize it will be adding some sleep here.
+$node->safe_psql('postgres', q(select injection_points_detach('GetNewMultiXactId-done')));
+
+# Here goes the whole purpose of this test: see that sleep in fact occured.
+ok( pump_until(
+ $observer->{run}, $observer->{timeout},
+ \$observer->{stderr}, qr/notice triggered for injection point GetMultiXactIdMembers-CV-sleep/),
+ "sleep observed");
+
+$observer->quit;
+
+$creator->quit;
+
+$node->stop;
+done_testing();
diff --git a/src/test/modules/test_slru/test_slru--1.0.sql b/src/test/modules/test_slru/test_slru--1.0.sql
index 202e8da3fde..58300c59a77 100644
--- a/src/test/modules/test_slru/test_slru--1.0.sql
+++ b/src/test/modules/test_slru/test_slru--1.0.sql
@@ -19,3 +19,9 @@ CREATE OR REPLACE FUNCTION test_slru_page_truncate(bigint) RETURNS VOID
AS 'MODULE_PATHNAME', 'test_slru_page_truncate' LANGUAGE C;
CREATE OR REPLACE FUNCTION test_slru_delete_all() RETURNS VOID
AS 'MODULE_PATHNAME', 'test_slru_delete_all' LANGUAGE C;
+
+
+CREATE OR REPLACE FUNCTION test_create_multixact() RETURNS xid
+ AS 'MODULE_PATHNAME', 'test_create_multixact' LANGUAGE C;
+CREATE OR REPLACE FUNCTION test_read_multixact(xid) RETURNS VOID
+ AS 'MODULE_PATHNAME', 'test_read_multixact'LANGUAGE C;
\ No newline at end of file
diff --git a/src/test/modules/test_slru/test_slru.c b/src/test/modules/test_slru/test_slru.c
index d227b067034..b3fabc3b6ed 100644
--- a/src/test/modules/test_slru/test_slru.c
+++ b/src/test/modules/test_slru/test_slru.c
@@ -14,13 +14,16 @@
#include "postgres.h"
+#include "access/multixact.h"
#include "access/slru.h"
+#include "access/xact.h"
#include "access/transam.h"
#include "miscadmin.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/shmem.h"
#include "utils/builtins.h"
+#include "utils/injection_point.h"
PG_MODULE_MAGIC;
@@ -36,6 +39,8 @@ PG_FUNCTION_INFO_V1(test_slru_page_sync);
PG_FUNCTION_INFO_V1(test_slru_page_delete);
PG_FUNCTION_INFO_V1(test_slru_page_truncate);
PG_FUNCTION_INFO_V1(test_slru_delete_all);
+PG_FUNCTION_INFO_V1(test_create_multixact);
+PG_FUNCTION_INFO_V1(test_read_multixact);
/* Number of SLRU page slots */
#define NUM_TEST_BUFFERS 16
@@ -260,3 +265,27 @@ _PG_init(void)
prev_shmem_startup_hook = shmem_startup_hook;
shmem_startup_hook = test_slru_shmem_startup;
}
+
+Datum
+test_create_multixact(PG_FUNCTION_ARGS)
+{
+ MultiXactId id;
+ MultiXactIdSetOldestMember();
+ id = MultiXactIdCreate(GetCurrentTransactionId(), MultiXactStatusUpdate,
+ GetCurrentTransactionId(), MultiXactStatusForShare);
+ PG_RETURN_TRANSACTIONID(id);
+}
+
+Datum
+test_read_multixact(PG_FUNCTION_ARGS)
+{
+ MultiXactId id = PG_GETARG_TRANSACTIONID(0);
+ MultiXactMember *members;
+ INJECTION_POINT("test_read_multixact");
+ /* discard caches */
+ AtEOXact_MultiXact();
+
+ if (GetMultiXactIdMembers(id,&members,false, false) == -1)
+ elog(ERROR, "MultiXactId not found");
+ PG_RETURN_VOID();
+}
\ No newline at end of file
--
2.37.1 (Apple Git-137.1)