From 8526f537cc24301f28015020862f02a6a8318196 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Mon, 15 Mar 2004 16:27:43 +0000 Subject: [PATCH] The "cvs add" of test_thread_implicit.pgc seems to have been missed, i've attached this again. Additionally I include a small patch to remove mutex locking when a DEFAULT/NULL connection is being retrieved. This is consistent with libpq. Lee Kindness --- src/interfaces/ecpg/ecpglib/connect.c | 20 ++- .../ecpg/test/test_thread_implicit.pgc | 140 ++++++++++++++++++ 2 files changed, 155 insertions(+), 5 deletions(-) create mode 100644 src/interfaces/ecpg/test/test_thread_implicit.pgc diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c index a4a02c3914..82504723d1 100644 --- a/src/interfaces/ecpg/ecpglib/connect.c +++ b/src/interfaces/ecpg/ecpglib/connect.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.20 2004/03/14 12:16:29 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.21 2004/03/15 16:27:43 momjian Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -62,18 +62,28 @@ ECPGget_connection(const char *connection_name) { struct connection *ret = NULL; + if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0)) + { #ifdef ENABLE_THREAD_SAFETY - pthread_mutex_lock(&connections_mutex); + ret = pthread_getspecific(actual_connection_key); +#else + ret = actual_connection; +#endif + } + else + { +#ifdef ENABLE_THREAD_SAFETY + pthread_mutex_lock(&connections_mutex); #endif - ret = ecpg_get_connection_nr(connection_name); + ret = ecpg_get_connection_nr(connection_name); #ifdef ENABLE_THREAD_SAFETY - pthread_mutex_unlock(&connections_mutex); + pthread_mutex_unlock(&connections_mutex); #endif + } return (ret); - } static void diff --git a/src/interfaces/ecpg/test/test_thread_implicit.pgc b/src/interfaces/ecpg/test/test_thread_implicit.pgc new file mode 100644 index 0000000000..367290d8ea --- /dev/null +++ b/src/interfaces/ecpg/test/test_thread_implicit.pgc @@ -0,0 +1,140 @@ +/* + * Thread test program + * by Lee Kindness. + */ + +/* #define ECPGDEBUG */ + +#include +#include + +void *test_thread(void *arg); + +EXEC SQL BEGIN DECLARE SECTION; +char *l_dbname; +EXEC SQL END DECLARE SECTION; +int nthreads = 2; +int iterations = 10; + +int main(int argc, char *argv[]) +{ +#ifdef ECPGDEBUG + char debugfilename[] = "thread_test_implicit.log"; + FILE *debugfile; +#endif + pthread_t *threads; + int n; + EXEC SQL BEGIN DECLARE SECTION; + int l_rows; + EXEC SQL END DECLARE SECTION; + + /* parse command line arguments */ + if( (argc < 2) || (argc > 4) ) + { + fprintf(stderr, "Usage: %s dbname [threads] [iterations_per_thread]\n", argv[0]); + return( 1 ); + } + l_dbname = argv[1]; + if( argc >= 3 ) + nthreads = atoi(argv[2]); + if( argc == 4 ) + iterations = atoi(argv[3]); + + /* open ECPG debug log? */ +#ifdef ECPGDEBUG + debugfile = fopen(debugfilename, "w"); + if( debugfile != NULL ) + ECPGdebug(1, debugfile); + else + fprintf(stderr, "Cannot open ECPG debug log: %s\n", debugfilename); +#endif + + /* setup test_thread table */ + EXEC SQL CONNECT TO:l_dbname; + 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(pthread_t)); + if( threads == NULL ) + { + fprintf(stderr, "Cannot alloc memory\n"); + return( 1 ); + } + for( n = 0; n < nthreads; n++ ) + { + pthread_create(&threads[n], NULL, test_thread, (void *)n + 1); + } + + /* wait for thread completion */ + for( n = 0; n < nthreads; n++ ) + { + pthread_join(threads[n], NULL); + } + free(threads); + + /* and check results */ + EXEC SQL CONNECT TO :l_dbname; + EXEC SQL SELECT COUNT(*) INTO :l_rows FROM test_thread; + EXEC SQL COMMIT; + EXEC SQL DISCONNECT; + if( l_rows == (nthreads * iterations) ) + printf("\nSuccess.\n"); + else + printf("\nERROR: Failure - expecting %d rows, got %d.\n", nthreads * iterations, l_rows); + + /* close ECPG debug log? */ +#ifdef ECPGDEBUG + if( debugfile != NULL ) + { + ECPGdebug(0, debugfile); + fclose(debugfile); + } +#endif + + return( 0 ); +} + +void *test_thread(void *arg) +{ + long threadnum = (long)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 */ + snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum); + EXEC SQL WHENEVER sqlerror sqlprint; + EXEC SQL CONNECT TO :l_dbname 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++ ) + { + printf("%s: inserting %d\n", l_connection, l_i); + EXEC SQL INSERT INTO test_thread(thread, iteration) VALUES(:l_connection, :l_i); + if( sqlca.sqlcode == 0 ) + printf("%s: insert done\n", l_connection); + else + printf("%s: ERROR: insert failed!\n", l_connection); + } + + /* all done */ + EXEC SQL COMMIT; + EXEC SQL DISCONNECT :l_connection; + printf("%s: done!\n", l_connection); + return( NULL ); +} -- 2.40.0