? 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 );
