summaryrefslogtreecommitdiffstats
path: root/src/interfaces/ecpg/test/thread
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:46:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:46:48 +0000
commit311bcfc6b3acdd6fd152798c7f287ddf74fa2a98 (patch)
tree0ec307299b1dada3701e42f4ca6eda57d708261e /src/interfaces/ecpg/test/thread
parentInitial commit. (diff)
downloadpostgresql-15-upstream.tar.xz
postgresql-15-upstream.zip
Adding upstream version 15.4.upstream/15.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/interfaces/ecpg/test/thread')
-rw-r--r--src/interfaces/ecpg/test/thread/.gitignore10
-rw-r--r--src/interfaces/ecpg/test/thread/Makefile13
-rw-r--r--src/interfaces/ecpg/test/thread/alloc.pgc90
-rw-r--r--src/interfaces/ecpg/test/thread/descriptor.pgc68
-rw-r--r--src/interfaces/ecpg/test/thread/prep.pgc96
-rw-r--r--src/interfaces/ecpg/test/thread/thread.pgc136
-rw-r--r--src/interfaces/ecpg/test/thread/thread_implicit.pgc136
7 files changed, 549 insertions, 0 deletions
diff --git a/src/interfaces/ecpg/test/thread/.gitignore b/src/interfaces/ecpg/test/thread/.gitignore
new file mode 100644
index 0000000..12ff319
--- /dev/null
+++ b/src/interfaces/ecpg/test/thread/.gitignore
@@ -0,0 +1,10 @@
+/alloc
+/alloc.c
+/descriptor
+/descriptor.c
+/prep
+/prep.c
+/thread
+/thread.c
+/thread_implicit
+/thread_implicit.c
diff --git a/src/interfaces/ecpg/test/thread/Makefile b/src/interfaces/ecpg/test/thread/Makefile
new file mode 100644
index 0000000..1b4ddcf
--- /dev/null
+++ b/src/interfaces/ecpg/test/thread/Makefile
@@ -0,0 +1,13 @@
+subdir = src/interfaces/ecpg/test/thread
+top_builddir = ../../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/$(subdir)/../Makefile.regress
+
+
+TESTS = thread_implicit thread_implicit.c \
+ thread thread.c \
+ prep prep.c \
+ descriptor descriptor.c \
+ alloc alloc.c
+
+all: $(TESTS)
diff --git a/src/interfaces/ecpg/test/thread/alloc.pgc b/src/interfaces/ecpg/test/thread/alloc.pgc
new file mode 100644
index 0000000..c0021a7
--- /dev/null
+++ b/src/interfaces/ecpg/test/thread/alloc.pgc
@@ -0,0 +1,90 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include "ecpg_config.h"
+
+#ifndef ENABLE_THREAD_SAFETY
+int
+main(void)
+{
+ printf("No threading enabled.\n");
+ return 0;
+}
+#else
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <process.h>
+#include <locale.h>
+#else
+#include <pthread.h>
+#endif
+#include <stdio.h>
+
+#define THREADS 16
+#define REPEATS 50
+
+exec sql include sqlca;
+exec sql include ../regression;
+
+exec sql whenever sqlerror sqlprint;
+exec sql whenever not found sqlprint;
+
+#ifdef WIN32
+static unsigned __stdcall fn(void* arg)
+#else
+static void* fn(void* arg)
+#endif
+{
+ int i;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ int value;
+ char name[100];
+ char **r = NULL;
+ EXEC SQL END DECLARE SECTION;
+
+ value = (intptr_t) arg;
+ sprintf(name, "Connection: %d", value);
+
+ EXEC SQL CONNECT TO REGRESSDB1 AS :name;
+ EXEC SQL SET AUTOCOMMIT TO ON;
+ for (i = 1; i <= REPEATS; ++i)
+ {
+ EXEC SQL SELECT relname INTO :r FROM pg_class WHERE relname = 'pg_class';
+ free(r);
+ r = NULL;
+ }
+ EXEC SQL DISCONNECT :name;
+
+ return 0;
+}
+
+int main ()
+{
+ intptr_t i;
+#ifdef WIN32
+ HANDLE threads[THREADS];
+#else
+ pthread_t threads[THREADS];
+#endif
+
+#ifdef WIN32
+ for (i = 0; i < THREADS; ++i)
+ {
+ unsigned id;
+ threads[i] = (HANDLE)_beginthreadex(NULL, 0, fn, (void*)i, 0, &id);
+ }
+
+ WaitForMultipleObjects(THREADS, threads, TRUE, INFINITE);
+ for (i = 0; i < THREADS; ++i)
+ CloseHandle(threads[i]);
+#else
+ for (i = 0; i < THREADS; ++i)
+ pthread_create(&threads[i], NULL, fn, (void *) i);
+ for (i = 0; i < THREADS; ++i)
+ pthread_join(threads[i], NULL);
+#endif
+
+ return 0;
+}
+#endif
diff --git a/src/interfaces/ecpg/test/thread/descriptor.pgc b/src/interfaces/ecpg/test/thread/descriptor.pgc
new file mode 100644
index 0000000..76a7a5d
--- /dev/null
+++ b/src/interfaces/ecpg/test/thread/descriptor.pgc
@@ -0,0 +1,68 @@
+#ifdef ENABLE_THREAD_SAFETY
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <process.h>
+#include <locale.h>
+#else
+#include <pthread.h>
+#endif
+#endif
+#include <stdio.h>
+
+#define THREADS 16
+#define REPEATS 50000
+
+EXEC SQL include sqlca;
+EXEC SQL whenever sqlerror sqlprint;
+EXEC SQL whenever not found sqlprint;
+
+#if defined(ENABLE_THREAD_SAFETY) && defined(WIN32)
+static unsigned __stdcall fn(void* arg)
+#else
+static void* fn(void* arg)
+#endif
+{
+ int i;
+
+ for (i = 1; i <= REPEATS; ++i)
+ {
+ EXEC SQL ALLOCATE DESCRIPTOR mydesc;
+ EXEC SQL DEALLOCATE DESCRIPTOR mydesc;
+ }
+
+ return 0;
+}
+
+int main ()
+{
+#ifdef ENABLE_THREAD_SAFETY
+ int i;
+#ifdef WIN32
+ HANDLE threads[THREADS];
+#else
+ pthread_t threads[THREADS];
+#endif
+
+#ifdef WIN32
+ for (i = 0; i < THREADS; ++i)
+ {
+ unsigned id;
+ threads[i] = (HANDLE)_beginthreadex(NULL, 0, fn, NULL, 0, &id);
+ }
+
+ WaitForMultipleObjects(THREADS, threads, TRUE, INFINITE);
+ for (i = 0; i < THREADS; ++i)
+ CloseHandle(threads[i]);
+#else
+ for (i = 0; i < THREADS; ++i)
+ pthread_create(&threads[i], NULL, fn, NULL);
+ for (i = 0; i < THREADS; ++i)
+ pthread_join(threads[i], NULL);
+#endif
+#else
+ fn(NULL);
+#endif
+
+ return 0;
+}
diff --git a/src/interfaces/ecpg/test/thread/prep.pgc b/src/interfaces/ecpg/test/thread/prep.pgc
new file mode 100644
index 0000000..d7ecfd4
--- /dev/null
+++ b/src/interfaces/ecpg/test/thread/prep.pgc
@@ -0,0 +1,96 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include "ecpg_config.h"
+
+#ifndef ENABLE_THREAD_SAFETY
+int
+main(void)
+{
+ printf("No threading enabled.\n");
+ return 0;
+}
+#else
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <process.h>
+#include <locale.h>
+#else
+#include <pthread.h>
+#endif
+#include <stdio.h>
+
+#define THREADS 16
+#define REPEATS 50
+
+exec sql include sqlca;
+exec sql include ../regression;
+
+exec sql whenever sqlerror sqlprint;
+exec sql whenever not found sqlprint;
+
+#ifdef WIN32
+static unsigned __stdcall fn(void* arg)
+#else
+static void* fn(void* arg)
+#endif
+{
+ int i;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ int value;
+ char name[100];
+ char query[256] = "INSERT INTO T VALUES ( ? )";
+ EXEC SQL END DECLARE SECTION;
+
+ value = (intptr_t) arg;
+ sprintf(name, "Connection: %d", value);
+
+ EXEC SQL CONNECT TO REGRESSDB1 AS :name;
+ EXEC SQL SET AUTOCOMMIT TO ON;
+ for (i = 1; i <= REPEATS; ++i)
+ {
+ EXEC SQL PREPARE I FROM :query;
+ EXEC SQL EXECUTE I USING :value;
+ }
+ EXEC SQL DEALLOCATE I;
+ EXEC SQL DISCONNECT :name;
+
+ return 0;
+}
+
+int main ()
+{
+ intptr_t i;
+#ifdef WIN32
+ HANDLE threads[THREADS];
+#else
+ pthread_t threads[THREADS];
+#endif
+
+ EXEC SQL CONNECT TO REGRESSDB1;
+ EXEC SQL SET AUTOCOMMIT TO ON;
+ EXEC SQL DROP TABLE IF EXISTS T;
+ EXEC SQL CREATE TABLE T ( i int );
+ EXEC SQL DISCONNECT;
+
+#ifdef WIN32
+ for (i = 0; i < THREADS; ++i)
+ {
+ unsigned id;
+ threads[i] = (HANDLE)_beginthreadex(NULL, 0, fn, (void*)i, 0, &id);
+ }
+
+ WaitForMultipleObjects(THREADS, threads, TRUE, INFINITE);
+ for (i = 0; i < THREADS; ++i)
+ CloseHandle(threads[i]);
+#else
+ for (i = 0; i < THREADS; ++i)
+ pthread_create(&threads[i], NULL, fn, (void *) i);
+ for (i = 0; i < THREADS; ++i)
+ pthread_join(threads[i], NULL);
+#endif
+
+ return 0;
+}
+#endif
diff --git a/src/interfaces/ecpg/test/thread/thread.pgc b/src/interfaces/ecpg/test/thread/thread.pgc
new file mode 100644
index 0000000..e7d8c00
--- /dev/null
+++ b/src/interfaces/ecpg/test/thread/thread.pgc
@@ -0,0 +1,136 @@
+/*
+ * Thread test program
+ * by Philip Yarra & Lee Kindness.
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include "ecpg_config.h"
+
+#ifndef ENABLE_THREAD_SAFETY
+int
+main(void)
+{
+ printf("No threading enabled.\n");
+ return 0;
+}
+#else
+#ifndef WIN32
+#include <pthread.h>
+#else
+#include <windows.h>
+#include <locale.h>
+#endif
+
+exec sql include ../regression;
+
+void *test_thread(void *arg);
+
+int nthreads = 10;
+int iterations = 20;
+
+int main()
+{
+#ifndef WIN32
+ pthread_t *threads;
+#else
+ HANDLE *threads;
+#endif
+ intptr_t n;
+ EXEC SQL BEGIN DECLARE SECTION;
+ int l_rows;
+ EXEC SQL END DECLARE SECTION;
+
+ /* Do not switch on debug output for regression tests. The threads get executed in
+ * more or less random order */
+ /* ECPGdebug(1, stderr); */
+
+ /* setup test_thread table */
+ EXEC SQL CONNECT TO REGRESSDB1;
+ EXEC SQL DROP TABLE test_thread; /* DROP might fail */
+ EXEC SQL COMMIT;
+ EXEC SQL CREATE TABLE
+ test_thread(tstamp TIMESTAMP NOT NULL DEFAULT CAST(timeofday() AS TIMESTAMP),
+ thread TEXT NOT NULL,
+ iteration INTEGER NOT NULL,
+ PRIMARY KEY(thread, iteration));
+ EXEC SQL COMMIT;
+ EXEC SQL DISCONNECT;
+
+ /* create, and start, threads */
+ threads = calloc(nthreads, sizeof(threads[0]));
+ if( threads == NULL )
+ {
+ fprintf(stderr, "Cannot alloc memory\n");
+ return 1;
+ }
+ for( n = 0; n < nthreads; n++ )
+ {
+#ifndef WIN32
+ pthread_create(&threads[n], NULL, test_thread, (void *) (n + 1));
+#else
+ threads[n] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (void (*) (void)) test_thread, (void *) (n + 1), 0, NULL);
+#endif
+ }
+
+ /* wait for thread completion */
+#ifndef WIN32
+ for( n = 0; n < nthreads; n++ )
+ {
+ pthread_join(threads[n], NULL);
+ }
+#else
+ WaitForMultipleObjects(nthreads, threads, TRUE, INFINITE);
+#endif
+ free(threads);
+
+ /* and check results */
+ EXEC SQL CONNECT TO REGRESSDB1;
+ EXEC SQL SELECT COUNT(*) INTO :l_rows FROM test_thread;
+ EXEC SQL COMMIT;
+ EXEC SQL DISCONNECT;
+ if( l_rows == (nthreads * iterations) )
+ printf("Success.\n");
+ else
+ printf("ERROR: Failure - expecting %d rows, got %d.\n", nthreads * iterations, l_rows);
+
+ return 0;
+}
+
+void *test_thread(void *arg)
+{
+ long threadnum = (intptr_t) arg;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ int l_i;
+ char l_connection[128];
+ EXEC SQL END DECLARE SECTION;
+
+ /* build up connection name, and connect to database */
+#ifndef _MSC_VER
+ snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum);
+#else
+ _snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum);
+#endif
+ EXEC SQL WHENEVER sqlerror sqlprint;
+ EXEC SQL CONNECT TO REGRESSDB1 AS :l_connection;
+ if( sqlca.sqlcode != 0 )
+ {
+ printf("%s: ERROR: cannot connect to database!\n", l_connection);
+ return NULL;
+ }
+ EXEC SQL AT :l_connection BEGIN;
+
+ /* insert into test_thread table */
+ for( l_i = 1; l_i <= iterations; l_i++ )
+ {
+ EXEC SQL AT :l_connection INSERT INTO test_thread(thread, iteration) VALUES(:l_connection, :l_i);
+ if( sqlca.sqlcode != 0 )
+ printf("%s: ERROR: insert failed!\n", l_connection);
+ }
+
+ /* all done */
+ EXEC SQL AT :l_connection COMMIT;
+ EXEC SQL DISCONNECT :l_connection;
+ return NULL;
+}
+#endif /* ENABLE_THREAD_SAFETY */
diff --git a/src/interfaces/ecpg/test/thread/thread_implicit.pgc b/src/interfaces/ecpg/test/thread/thread_implicit.pgc
new file mode 100644
index 0000000..b4cae7e
--- /dev/null
+++ b/src/interfaces/ecpg/test/thread/thread_implicit.pgc
@@ -0,0 +1,136 @@
+/*
+ * Thread test program
+ * by Lee Kindness.
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include "ecpg_config.h"
+
+#ifndef ENABLE_THREAD_SAFETY
+int
+main(void)
+{
+ printf("No threading enabled.\n");
+ return 0;
+}
+#else
+#ifndef WIN32
+#include <pthread.h>
+#else
+#include <windows.h>
+#include <locale.h>
+#endif
+
+exec sql include ../regression;
+
+void *test_thread(void *arg);
+
+int nthreads = 10;
+int iterations = 20;
+
+int main()
+{
+#ifndef WIN32
+ pthread_t *threads;
+#else
+ HANDLE *threads;
+#endif
+ intptr_t n;
+ EXEC SQL BEGIN DECLARE SECTION;
+ int l_rows;
+ EXEC SQL END DECLARE SECTION;
+
+ /* Do not switch on debug output for regression tests. The threads get executed in
+ * more or less random order */
+ /* ECPGdebug(1, stderr); */
+
+ /* setup test_thread table */
+ EXEC SQL CONNECT TO REGRESSDB1;
+ EXEC SQL DROP TABLE test_thread; /* DROP might fail */
+ EXEC SQL COMMIT;
+ EXEC SQL CREATE TABLE
+ test_thread(tstamp TIMESTAMP NOT NULL DEFAULT CAST(timeofday() AS TIMESTAMP),
+ thread TEXT NOT NULL,
+ iteration INTEGER NOT NULL,
+ PRIMARY KEY(thread, iteration));
+ EXEC SQL COMMIT;
+ EXEC SQL DISCONNECT;
+
+ /* create, and start, threads */
+ threads = calloc(nthreads, sizeof(threads[0]));
+ if( threads == NULL )
+ {
+ fprintf(stderr, "Cannot alloc memory\n");
+ return 1;
+ }
+ for( n = 0; n < nthreads; n++ )
+ {
+#ifndef WIN32
+ pthread_create(&threads[n], NULL, test_thread, (void *) (n + 1));
+#else
+ threads[n] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (void (*) (void)) test_thread, (void *) (n+1), 0, NULL);
+#endif
+ }
+
+ /* wait for thread completion */
+#ifndef WIN32
+ for( n = 0; n < nthreads; n++ )
+ {
+ pthread_join(threads[n], NULL);
+ }
+#else
+ WaitForMultipleObjects(nthreads, threads, TRUE, INFINITE);
+#endif
+ free(threads);
+
+ /* and check results */
+ EXEC SQL CONNECT TO REGRESSDB1;
+ EXEC SQL SELECT COUNT(*) INTO :l_rows FROM test_thread;
+ EXEC SQL COMMIT;
+ EXEC SQL DISCONNECT;
+ if( l_rows == (nthreads * iterations) )
+ printf("Success.\n");
+ else
+ printf("ERROR: Failure - expecting %d rows, got %d.\n", nthreads * iterations, l_rows);
+
+ return 0;
+}
+
+void *test_thread(void *arg)
+{
+ long threadnum = (intptr_t) arg;
+
+ EXEC SQL BEGIN DECLARE SECTION;
+ int l_i;
+ char l_connection[128];
+ EXEC SQL END DECLARE SECTION;
+
+ /* build up connection name, and connect to database */
+#ifndef _MSC_VER
+ snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum);
+#else
+ _snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum);
+#endif
+ EXEC SQL WHENEVER sqlerror sqlprint;
+ EXEC SQL CONNECT TO REGRESSDB1 AS :l_connection;
+ if( sqlca.sqlcode != 0 )
+ {
+ printf("%s: ERROR: cannot connect to database!\n", l_connection);
+ return NULL;
+ }
+ EXEC SQL BEGIN;
+
+ /* insert into test_thread table */
+ for( l_i = 1; l_i <= iterations; l_i++ )
+ {
+ EXEC SQL INSERT INTO test_thread(thread, iteration) VALUES(:l_connection, :l_i);
+ if( sqlca.sqlcode != 0 )
+ printf("%s: ERROR: insert failed!\n", l_connection);
+ }
+
+ /* all done */
+ EXEC SQL COMMIT;
+ EXEC SQL DISCONNECT :l_connection;
+ return NULL;
+}
+#endif /* ENABLE_THREAD_SAFETY */