Create waitfuncs.c for pg_isolation_test_session_is_blocked().
authorNoah Misch <noah@leadboat.com>
Fri, 28 Jun 2024 02:21:05 +0000 (19:21 -0700)
committerNoah Misch <noah@leadboat.com>
Fri, 28 Jun 2024 02:21:05 +0000 (19:21 -0700)
The next commit makes the function inspect an additional non-lock
contention source, so it no longer fits in lockfuncs.c.

Reviewed by Robert Haas.

Discussion: https://postgr.es/m/20240512232923.aa.nmisch@google.com

src/backend/utils/adt/Makefile
src/backend/utils/adt/lockfuncs.c
src/backend/utils/adt/meson.build
src/backend/utils/adt/waitfuncs.c [new file with mode: 0644]

index 610ccf2f7994d05d5fa3285dde2d358cb592b5a8..edb09d4e35622346ecb943d82edaa2c173d12004 100644 (file)
@@ -116,6 +116,7 @@ OBJS = \
        varchar.o \
        varlena.o \
        version.o \
+       waitfuncs.o \
        windowfuncs.o \
        xid.o \
        xid8funcs.o \
index 13009cc3d0d142784436c26414cf37fd5381d315..e790f856ab37066d33145386f0a6c6ca530ea7e9 100644 (file)
@@ -13,7 +13,6 @@
 #include "postgres.h"
 
 #include "access/htup_details.h"
-#include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "miscadmin.h"
 #include "storage/predicate_internals.h"
@@ -601,84 +600,6 @@ pg_safe_snapshot_blocking_pids(PG_FUNCTION_ARGS)
 }
 
 
-/*
- * pg_isolation_test_session_is_blocked - support function for isolationtester
- *
- * Check if specified PID is blocked by any of the PIDs listed in the second
- * argument.  Currently, this looks for blocking caused by waiting for
- * heavyweight locks or safe snapshots.  We ignore blockage caused by PIDs
- * not directly under the isolationtester's control, eg autovacuum.
- *
- * This is an undocumented function intended for use by the isolation tester,
- * and may change in future releases as required for testing purposes.
- */
-Datum
-pg_isolation_test_session_is_blocked(PG_FUNCTION_ARGS)
-{
-       int                     blocked_pid = PG_GETARG_INT32(0);
-       ArrayType  *interesting_pids_a = PG_GETARG_ARRAYTYPE_P(1);
-       ArrayType  *blocking_pids_a;
-       int32      *interesting_pids;
-       int32      *blocking_pids;
-       int                     num_interesting_pids;
-       int                     num_blocking_pids;
-       int                     dummy;
-       int                     i,
-                               j;
-
-       /* Validate the passed-in array */
-       Assert(ARR_ELEMTYPE(interesting_pids_a) == INT4OID);
-       if (array_contains_nulls(interesting_pids_a))
-               elog(ERROR, "array must not contain nulls");
-       interesting_pids = (int32 *) ARR_DATA_PTR(interesting_pids_a);
-       num_interesting_pids = ArrayGetNItems(ARR_NDIM(interesting_pids_a),
-                                                                                 ARR_DIMS(interesting_pids_a));
-
-       /*
-        * Get the PIDs of all sessions blocking the given session's attempt to
-        * acquire heavyweight locks.
-        */
-       blocking_pids_a =
-               DatumGetArrayTypeP(DirectFunctionCall1(pg_blocking_pids, blocked_pid));
-
-       Assert(ARR_ELEMTYPE(blocking_pids_a) == INT4OID);
-       Assert(!array_contains_nulls(blocking_pids_a));
-       blocking_pids = (int32 *) ARR_DATA_PTR(blocking_pids_a);
-       num_blocking_pids = ArrayGetNItems(ARR_NDIM(blocking_pids_a),
-                                                                          ARR_DIMS(blocking_pids_a));
-
-       /*
-        * Check if any of these are in the list of interesting PIDs, that being
-        * the sessions that the isolation tester is running.  We don't use
-        * "arrayoverlaps" here, because it would lead to cache lookups and one of
-        * our goals is to run quickly with debug_discard_caches > 0.  We expect
-        * blocking_pids to be usually empty and otherwise a very small number in
-        * isolation tester cases, so make that the outer loop of a naive search
-        * for a match.
-        */
-       for (i = 0; i < num_blocking_pids; i++)
-               for (j = 0; j < num_interesting_pids; j++)
-               {
-                       if (blocking_pids[i] == interesting_pids[j])
-                               PG_RETURN_BOOL(true);
-               }
-
-       /*
-        * Check if blocked_pid is waiting for a safe snapshot.  We could in
-        * theory check the resulting array of blocker PIDs against the
-        * interesting PIDs list, but since there is no danger of autovacuum
-        * blocking GetSafeSnapshot there seems to be no point in expending cycles
-        * on allocating a buffer and searching for overlap; so it's presently
-        * sufficient for the isolation tester's purposes to use a single element
-        * buffer and check if the number of safe snapshot blockers is non-zero.
-        */
-       if (GetSafeSnapshotBlockingPids(blocked_pid, &dummy, 1) > 0)
-               PG_RETURN_BOOL(true);
-
-       PG_RETURN_BOOL(false);
-}
-
-
 /*
  * Functions for manipulating advisory locks
  *
index 48dbcf59a58ffb678187d0465b129184759906e6..8c6fc80c373b260ae76485c1ccfa868ec5ebb824 100644 (file)
@@ -103,6 +103,7 @@ backend_sources += files(
   'varchar.c',
   'varlena.c',
   'version.c',
+  'waitfuncs.c',
   'windowfuncs.c',
   'xid.c',
   'xid8funcs.c',
diff --git a/src/backend/utils/adt/waitfuncs.c b/src/backend/utils/adt/waitfuncs.c
new file mode 100644 (file)
index 0000000..d9c92c3
--- /dev/null
@@ -0,0 +1,96 @@
+/*-------------------------------------------------------------------------
+ *
+ * waitfuncs.c
+ *             Functions for SQL access to syntheses of multiple contention types.
+ *
+ * Copyright (c) 2002-2024, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *             src/backend/utils/adt/waitfuncs.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "catalog/pg_type.h"
+#include "storage/predicate_internals.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+
+
+/*
+ * pg_isolation_test_session_is_blocked - support function for isolationtester
+ *
+ * Check if specified PID is blocked by any of the PIDs listed in the second
+ * argument.  Currently, this looks for blocking caused by waiting for
+ * heavyweight locks or safe snapshots.  We ignore blockage caused by PIDs
+ * not directly under the isolationtester's control, eg autovacuum.
+ *
+ * This is an undocumented function intended for use by the isolation tester,
+ * and may change in future releases as required for testing purposes.
+ */
+Datum
+pg_isolation_test_session_is_blocked(PG_FUNCTION_ARGS)
+{
+       int                     blocked_pid = PG_GETARG_INT32(0);
+       ArrayType  *interesting_pids_a = PG_GETARG_ARRAYTYPE_P(1);
+       ArrayType  *blocking_pids_a;
+       int32      *interesting_pids;
+       int32      *blocking_pids;
+       int                     num_interesting_pids;
+       int                     num_blocking_pids;
+       int                     dummy;
+       int                     i,
+                               j;
+
+       /* Validate the passed-in array */
+       Assert(ARR_ELEMTYPE(interesting_pids_a) == INT4OID);
+       if (array_contains_nulls(interesting_pids_a))
+               elog(ERROR, "array must not contain nulls");
+       interesting_pids = (int32 *) ARR_DATA_PTR(interesting_pids_a);
+       num_interesting_pids = ArrayGetNItems(ARR_NDIM(interesting_pids_a),
+                                                                                 ARR_DIMS(interesting_pids_a));
+
+       /*
+        * Get the PIDs of all sessions blocking the given session's attempt to
+        * acquire heavyweight locks.
+        */
+       blocking_pids_a =
+               DatumGetArrayTypeP(DirectFunctionCall1(pg_blocking_pids, blocked_pid));
+
+       Assert(ARR_ELEMTYPE(blocking_pids_a) == INT4OID);
+       Assert(!array_contains_nulls(blocking_pids_a));
+       blocking_pids = (int32 *) ARR_DATA_PTR(blocking_pids_a);
+       num_blocking_pids = ArrayGetNItems(ARR_NDIM(blocking_pids_a),
+                                                                          ARR_DIMS(blocking_pids_a));
+
+       /*
+        * Check if any of these are in the list of interesting PIDs, that being
+        * the sessions that the isolation tester is running.  We don't use
+        * "arrayoverlaps" here, because it would lead to cache lookups and one of
+        * our goals is to run quickly with debug_discard_caches > 0.  We expect
+        * blocking_pids to be usually empty and otherwise a very small number in
+        * isolation tester cases, so make that the outer loop of a naive search
+        * for a match.
+        */
+       for (i = 0; i < num_blocking_pids; i++)
+               for (j = 0; j < num_interesting_pids; j++)
+               {
+                       if (blocking_pids[i] == interesting_pids[j])
+                               PG_RETURN_BOOL(true);
+               }
+
+       /*
+        * Check if blocked_pid is waiting for a safe snapshot.  We could in
+        * theory check the resulting array of blocker PIDs against the
+        * interesting PIDs list, but since there is no danger of autovacuum
+        * blocking GetSafeSnapshot there seems to be no point in expending cycles
+        * on allocating a buffer and searching for overlap; so it's presently
+        * sufficient for the isolation tester's purposes to use a single element
+        * buffer and check if the number of safe snapshot blockers is non-zero.
+        */
+       if (GetSafeSnapshotBlockingPids(blocked_pid, &dummy, 1) > 0)
+               PG_RETURN_BOOL(true);
+
+       PG_RETURN_BOOL(false);
+}