From 0924b7cc9f1a516df710677b246d26226cd01624 Mon Sep 17 00:00:00 2001 From: "Andrey M. Borodin" Date: Sun, 28 Jan 2024 22:22:22 +0500 Subject: [PATCH v2 2/3] Add wait type for injection points --- src/backend/utils/misc/injection_point.c | 20 ++++++++++ src/include/utils/injection_point.h | 1 + src/test/modules/injection_points/Makefile | 1 + .../injection_points/injection_points.c | 16 ++++++++ .../modules/injection_points/t/001_wait.pl | 40 +++++++++++++++++++ 5 files changed, 78 insertions(+) create mode 100644 src/test/modules/injection_points/t/001_wait.pl diff --git a/src/backend/utils/misc/injection_point.c b/src/backend/utils/misc/injection_point.c index 0cf4d51cac..398ef2cf30 100644 --- a/src/backend/utils/misc/injection_point.c +++ b/src/backend/utils/misc/injection_point.c @@ -252,6 +252,26 @@ InjectionPointDetach(const char *name) #endif } +/* + * Test if injection point is attached. + */ +bool +InjectionPointIsAttach(const char *name) +{ +#ifdef USE_INJECTION_POINTS + bool found; + + LWLockAcquire(InjectionPointLock, LW_EXCLUSIVE); + hash_search(InjectionPointHash, name, HASH_FIND, &found); + LWLockRelease(InjectionPointLock); + + return found; + +#else + elog(ERROR, "Injection points are not supported by this build"); +#endif +} + /* * Execute an injection point, if defined. * diff --git a/src/include/utils/injection_point.h b/src/include/utils/injection_point.h index 55524b568f..e07f6b7024 100644 --- a/src/include/utils/injection_point.h +++ b/src/include/utils/injection_point.h @@ -33,5 +33,6 @@ extern void InjectionPointAttach(const char *name, const char *function); extern void InjectionPointRun(const char *name); extern void InjectionPointDetach(const char *name); +extern bool InjectionPointIsAttach(const char *name); #endif /* INJECTION_POINT_H */ diff --git a/src/test/modules/injection_points/Makefile b/src/test/modules/injection_points/Makefile index 2cbbae4e0a..543d2ab927 100644 --- a/src/test/modules/injection_points/Makefile +++ b/src/test/modules/injection_points/Makefile @@ -7,6 +7,7 @@ DATA = injection_points--1.0.sql PGFILEDESC = "injection_points - facility for injection points" REGRESS = injection_points +TAP_TESTS = 1 ifdef USE_PGXS PG_CONFIG = pg_config diff --git a/src/test/modules/injection_points/injection_points.c b/src/test/modules/injection_points/injection_points.c index e843e6594f..fbb30b15ad 100644 --- a/src/test/modules/injection_points/injection_points.c +++ b/src/test/modules/injection_points/injection_points.c @@ -18,6 +18,7 @@ #include "postgres.h" #include "fmgr.h" +#include "miscadmin.h" #include "storage/lwlock.h" #include "storage/shmem.h" #include "utils/builtins.h" @@ -28,6 +29,7 @@ PG_MODULE_MAGIC; extern PGDLLEXPORT void injection_error(const char *name); extern PGDLLEXPORT void injection_notice(const char *name); +extern PGDLLEXPORT void injection_wait(const char *name); /* Set of callbacks available to be attached to an injection point. */ @@ -43,6 +45,18 @@ injection_notice(const char *name) elog(NOTICE, "notice triggered for injection point %s", name); } +void +injection_wait(const char *name) +{ + elog(NOTICE, "waiting triggered for injection point %s", name); + do + { + CHECK_FOR_INTERRUPTS(); + pg_usleep(1000L); + } while (InjectionPointIsAttach(name)); + elog(NOTICE, "waiting done for injection point %s", name); +} + /* * SQL function for creating an injection point. */ @@ -58,6 +72,8 @@ injection_points_attach(PG_FUNCTION_ARGS) function = "injection_error"; else if (strcmp(action, "notice") == 0) function = "injection_notice"; + else if (strcmp(action, "wait") == 0) + function = "injection_wait"; else elog(ERROR, "incorrect action \"%s\" for injection point creation", action); diff --git a/src/test/modules/injection_points/t/001_wait.pl b/src/test/modules/injection_points/t/001_wait.pl new file mode 100644 index 0000000000..98f7a8bcef --- /dev/null +++ b/src/test/modules/injection_points/t/001_wait.pl @@ -0,0 +1,40 @@ + +# 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('injection_points'); +$node->init; +$node->start; +$node->safe_psql('postgres', q(CREATE EXTENSION injection_points)); + +$result = $node->psql('postgres', q(select injection_points_attach('FIRST','wait'))); +is($result, '0', 'wait injection point set'); + +my $bg = $node->background_psql('postgres'); + +$bg->query_until( + qr/start/, q( +\echo start +select injection_points_run('FIRST'); +select injection_points_attach('SECOND','wait'); +)); + +$result = $node->psql('postgres', q( +select injection_points_run('SECOND'); +select injection_points_detach('FIRST'); +)); +is($result, '0', 'wait injection point set'); + +$bg->quit; + +$node->stop; +done_testing(); -- 2.37.1 (Apple Git-137.1)