? src/interfaces/ecpg/test/test_thread_implicit.pgc Index: src/interfaces/ecpg/ecpglib/misc.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/misc.c,v retrieving revision 1.18 diff -r1.18 misc.c 121,122c121 < static void < ecpg_sqlca_key_init(void) --- > static void *ecpg_sqlca_key_destructor(void *arg) 124c123,129 < pthread_key_create(&sqlca_key, NULL); --- > if( arg != NULL ) > free(arg); /* sqlca structure allocated in ECPGget_sqlca */ > } > > static void ecpg_sqlca_key_init(void) > { > pthread_key_create(&sqlca_key, ecpg_sqlca_key_destructor); Index: src/interfaces/ecpg/test/Makefile =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/interfaces/ecpg/test/Makefile,v retrieving revision 1.43 diff -r1.43 Makefile 13c13 < TESTS += test_thread --- > TESTS += test_thread test_thread_implicit Index: src/interfaces/ecpg/test/test_thread.pgc =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/interfaces/ecpg/test/test_thread.pgc,v retrieving revision 1.6 diff -r1.6 test_thread.pgc 3c3 < * by Philip Yarra --- > * by Philip Yarra & Lee Kindness. 5a6 > /* #define ECPGDEBUG */ 10,11c11 < void ins1(void); < void ins2(void); --- > void *test_thread(void *arg); 14,15c14 < char *dbname; < int iterations = 10; --- > char *l_dbname; 16a16,17 > int nthreads = 2; > int iterations = 10; 18,19c19 < int < main(int argc, char *argv[]) --- > int main(int argc, char *argv[]) 21,66c21,100 < pthread_t thread1, < thread2; < EXEC SQL BEGIN DECLARE SECTION; < int rows; < EXEC SQL END DECLARE SECTION; < < if (argc < 2 || argc > 3) < { < fprintf(stderr, "Usage: %s dbname [iterations]\n", argv[0]); < return 1; < } < dbname = argv[1]; < < if (argc == 3) < iterations = atoi(argv[2]); < if (iterations % 2 != 0) < { < fprintf(stderr, "iterations must be an even number\n"); < return 1; < } < < EXEC SQL CONNECT TO:dbname AS test0; < < /* DROP might fail */ < EXEC SQL AT test0 DROP TABLE test_thread; < EXEC SQL AT test0 COMMIT WORK; < EXEC SQL AT test0 CREATE TABLE test_thread(message TEXT); < EXEC SQL AT test0 COMMIT WORK; < EXEC SQL DISCONNECT test0; < < pthread_create(&thread1, NULL, (void * (*)(void *)) ins1, NULL); < pthread_create(&thread2, NULL, (void * (*)(void *)) ins2, NULL); < pthread_join(thread1, NULL); < pthread_join(thread2, NULL); < < EXEC SQL CONNECT TO:dbname AS test3; < EXEC SQL AT test3 SELECT COUNT(*) INTO :rows FROM test_thread; < EXEC SQL AT test3 COMMIT WORK; < EXEC SQL DISCONNECT test3; < < if (rows == iterations) < printf("\nSuccess.\n"); < else < printf("\nFailure.\n"); < return 0; < } --- > #ifdef ECPGDEBUG > char debugfilename[] = "thread_test.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 68,85c102 < void < ins1(void) < { < int i; < EXEC SQL WHENEVER sqlerror sqlprint; < EXEC SQL CONNECT TO:dbname AS test1; < < for (i = 0; i < iterations / 2; i++) < { < printf("thread 1 : inserting\n"); < EXEC SQL AT test1 INSERT INTO test_thread VALUES('thread1'); < < printf("thread 1 : insert done\n"); < } < EXEC SQL AT test1 COMMIT WORK; < EXEC SQL DISCONNECT test1; < < printf("thread 1 : done!\n"); --- > return( 0 ); 88,90c105 < < void < ins2(void) --- > void *test_thread(void *arg) 92,106c107,139 < int i; < EXEC SQL WHENEVER sqlerror sqlprint; < EXEC SQL CONNECT TO:dbname AS test2; < < for (i = 0; i < iterations / 2; i++) < { < printf("thread 2: inserting\n"); < EXEC SQL AT test2 INSERT INTO test_thread VALUES('thread2'); < < printf("thread 2: insert done\n"); < } < EXEC SQL AT test2 COMMIT WORK; < EXEC SQL DISCONNECT test2; < < printf("thread 2: done!\n"); --- > 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 AT :l_connection 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 AT :l_connection 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 AT :l_connection COMMIT; > EXEC SQL DISCONNECT :l_connection; > printf("%s: done!\n", l_connection); > return( NULL );