test-barrier.patch
application/octet-stream
Filename: test-barrier.patch
Type: application/octet-stream
Part: 1
Message:
Re: WIP: [[Parallel] Shared] Hash
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/test/modules/test_barrier/Makefile | 18 | 0 |
| src/test/modules/test_barrier/test_barrier--1.0.sql | 13 | 0 |
| src/test/modules/test_barrier/test_barrier.c | 211 | 0 |
| src/test/modules/test_barrier/test_barrier.control | 4 | 0 |
diff --git a/src/test/modules/test_barrier/Makefile b/src/test/modules/test_barrier/Makefile
new file mode 100644
index 0000000..9f330b6
--- /dev/null
+++ b/src/test/modules/test_barrier/Makefile
@@ -0,0 +1,18 @@
+# src/test/modules/test_barrier/Makefile
+
+MODULES = test_barrier
+
+EXTENSION = test_barrier
+DATA = test_barrier--1.0.sql
+PGFILEDESC = "test_barrier -- some tests for barrier.c"
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_barrier
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_barrier/test_barrier--1.0.sql b/src/test/modules/test_barrier/test_barrier--1.0.sql
new file mode 100644
index 0000000..822915f
--- /dev/null
+++ b/src/test/modules/test_barrier/test_barrier--1.0.sql
@@ -0,0 +1,13 @@
+\echo Use "CREATE EXTENSION test_barrier" to load this file. \quit
+
+CREATE FUNCTION test_barrier_alternate(workers int, loops int)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
+
+CREATE FUNCTION test_barrier_reattach_random(workers int, end_phase int)
+RETURNS void
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
+
+
diff --git a/src/test/modules/test_barrier/test_barrier.c b/src/test/modules/test_barrier/test_barrier.c
new file mode 100644
index 0000000..07127bb
--- /dev/null
+++ b/src/test/modules/test_barrier/test_barrier.c
@@ -0,0 +1,211 @@
+#include "postgres.h"
+
+#include "fmgr.h"
+#include "funcapi.h"
+#include "miscadmin.h"
+#include "pgstat.h"
+#include "postmaster/bgworker.h"
+#include "storage/barrier.h"
+#include "storage/dsm.h"
+#include "storage/proc.h"
+#include "utils/builtins.h"
+#include "utils/resowner.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+PG_MODULE_MAGIC;
+
+PG_FUNCTION_INFO_V1(test_barrier_alternate);
+PG_FUNCTION_INFO_V1(test_barrier_reattach_random);
+
+extern Datum test_barrier_main(Datum);
+
+typedef enum test_mode
+{
+ TEST_MODE_ALTERNATE,
+ TEST_MODE_REATTACH_RANDOM
+} test_mode;
+
+typedef struct test_barrier_alternate_state
+{
+ Barrier barrier1;
+ Barrier barrier2;
+ int loops;
+} test_barrier_alternate_state;
+
+typedef struct test_barrier_reattach_random_state
+{
+ Barrier barrier;
+ int end_phase;
+} test_barrier_reattach_random_state;
+
+typedef struct test_barrier_state
+{
+ test_mode mode;
+ union
+ {
+ test_barrier_alternate_state alternate_state;
+ test_barrier_reattach_random_state reattach_random_state;
+ };
+} test_barrier_state;
+
+/*
+ * Wait at barrier1 and then barrier2, state->loops times.
+ */
+static void
+do_test_barrier_alternate(test_barrier_alternate_state *state)
+{
+ int i;
+
+ for (i = 0; i < state->loops; ++i)
+ {
+ BarrierWait(&state->barrier1, PG_WAIT_EXTENSION);
+ BarrierWait(&state->barrier2, PG_WAIT_EXTENSION);
+ }
+}
+
+/*
+ * Attach, wait a random numer of times, then detach, repeatedly until
+ * state->end_phase is reached.
+ */
+static void
+do_test_barrier_reattach_random(test_barrier_reattach_random_state *state)
+{
+ bool done = false;
+ int expected_phase;
+ int i;
+ int nwaits;
+
+ /* Make sure each backend uses a different pseudo-random sequence. */
+ srand48(getpid());
+
+ while (!done)
+ {
+ expected_phase = BarrierAttach(&state->barrier);
+ nwaits = (int) (lrand48() % 8);
+ for (i = 0; i < nwaits; ++i)
+ {
+ if (expected_phase == state->end_phase)
+ {
+ done = true;
+ break;
+ }
+
+ BarrierWait(&state->barrier, PG_WAIT_EXTENSION);
+ ++expected_phase;
+ Assert(BarrierPhase(&state->barrier) == expected_phase);
+ }
+ BarrierDetach(&state->barrier);
+ }
+}
+
+Datum
+test_barrier_main(Datum arg)
+{
+ dsm_segment *segment;
+ test_barrier_state *state;
+
+ BackgroundWorkerUnblockSignals();
+
+ CurrentResourceOwner = ResourceOwnerCreate(NULL, "test_barrier_main toplevel");
+
+ segment = dsm_attach(DatumGetInt32(arg));
+ state = (test_barrier_state *) dsm_segment_address(segment);
+ switch (state->mode)
+ {
+ case TEST_MODE_ALTERNATE:
+ do_test_barrier_alternate(&state->alternate_state);
+ break;
+ case TEST_MODE_REATTACH_RANDOM:
+ do_test_barrier_reattach_random(&state->reattach_random_state);
+ break;
+ default:
+ Assert(0);
+ }
+ dsm_detach(segment);
+
+ return (Datum) 0;
+}
+
+static void
+launch_test(test_mode mode, int workers, int n)
+{
+ BackgroundWorkerHandle **handles;
+ test_barrier_state *state;
+ dsm_segment *segment;
+ int i;
+
+ handles = palloc(sizeof(BackgroundWorkerHandle *) * workers);
+
+ segment = dsm_create(sizeof(test_barrier_state), 0);
+ state = (test_barrier_state *) dsm_segment_address(segment);
+
+ /* Initialize state. */
+ state->mode = mode;
+ switch (mode)
+ {
+ case TEST_MODE_ALTERNATE:
+ /* Initialize a static barrier for 'workers' workers. */
+ state->alternate_state.loops = n;
+ BarrierInit(&state->alternate_state.barrier1, workers);
+ BarrierInit(&state->alternate_state.barrier2, workers);
+ break;
+ case TEST_MODE_REATTACH_RANDOM:
+ /* Initialize a dynamic barrier. They'll attach and detach. */
+ state->reattach_random_state.end_phase = n;
+ BarrierInit(&state->reattach_random_state.barrier, 0);
+ break;
+ default:
+ Assert(0);
+ }
+
+ /* Start workers. */
+ for (i = 0; i < workers; ++i)
+ {
+ BackgroundWorker bgw;
+
+ snprintf(bgw.bgw_name, sizeof(bgw.bgw_name), "worker%d", i);
+ bgw.bgw_flags = BGWORKER_SHMEM_ACCESS;
+ bgw.bgw_start_time = BgWorkerStart_ConsistentState;
+ bgw.bgw_restart_time = BGW_NEVER_RESTART;
+ bgw.bgw_main = NULL;
+ snprintf(bgw.bgw_library_name, sizeof(bgw.bgw_library_name),
+ "test_barrier");
+ snprintf(bgw.bgw_function_name, sizeof(bgw.bgw_function_name),
+ "test_barrier_main");
+ bgw.bgw_main_arg = Int32GetDatum(dsm_segment_handle(segment));
+ bgw.bgw_notify_pid = MyProcPid;
+
+ if (!RegisterDynamicBackgroundWorker(&bgw, &handles[i]))
+ elog(ERROR, "Can't start worker");
+ }
+
+ /* Wait for workers to complete. */
+ for (i = 0; i < workers; ++i)
+ WaitForBackgroundWorkerShutdown(handles[i]);
+
+ dsm_detach(segment);
+}
+
+Datum
+test_barrier_reattach_random(PG_FUNCTION_ARGS)
+{
+ int workers = PG_GETARG_INT32(0);
+ int end_phase = PG_GETARG_INT32(1);
+
+ launch_test(TEST_MODE_REATTACH_RANDOM, workers, end_phase);
+
+ return (Datum) 0;
+}
+
+Datum
+test_barrier_alternate(PG_FUNCTION_ARGS)
+{
+ int workers = PG_GETARG_INT32(0);
+ int loops = PG_GETARG_INT32(1);
+
+ launch_test(TEST_MODE_ALTERNATE, workers, loops);
+
+ return (Datum) 0;
+}
diff --git a/src/test/modules/test_barrier/test_barrier.control b/src/test/modules/test_barrier/test_barrier.control
new file mode 100644
index 0000000..1cfe3bc
--- /dev/null
+++ b/src/test/modules/test_barrier/test_barrier.control
@@ -0,0 +1,4 @@
+comment = 'test_barrier'
+default_version = '1.0'
+module_pathname = '$libdir/test_barrier'
+relocatable = true