? 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 -c -r1.18 misc.c
*** src/interfaces/ecpg/ecpglib/misc.c	29 Nov 2003 19:52:08 -0000	1.18
--- src/interfaces/ecpg/ecpglib/misc.c	6 Mar 2004 15:41:59 -0000
***************
*** 118,127 ****
  }
  
  #ifdef ENABLE_THREAD_SAFETY
! static void
! ecpg_sqlca_key_init(void)
  {
! 	pthread_key_create(&sqlca_key, NULL);
  }
  #endif
  
--- 118,132 ----
  }
  
  #ifdef ENABLE_THREAD_SAFETY
! static void *ecpg_sqlca_key_destructor(void *arg)
  {
!   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);
  }
  #endif
  
Index: src/interfaces/ecpg/test/Makefile
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/ecpg/test/Makefile,v
retrieving revision 1.43
diff -c -r1.43 Makefile
*** src/interfaces/ecpg/test/Makefile	19 Dec 2003 23:29:15 -0000	1.43
--- src/interfaces/ecpg/test/Makefile	6 Mar 2004 15:41:59 -0000
***************
*** 10,16 ****
  
  TESTS = test1 test2 test3 test4 perftest dyntest dyntest2 test_notice test_code100 test_init testdynalloc num_test dt_test test_informix
  ifeq ($(enable_thread_safety), yes)
! TESTS += test_thread
  endif
  
  all: $(TESTS)
--- 10,16 ----
  
  TESTS = test1 test2 test3 test4 perftest dyntest dyntest2 test_notice test_code100 test_init testdynalloc num_test dt_test test_informix
  ifeq ($(enable_thread_safety), yes)
! TESTS += test_thread test_thread_implicit
  endif
  
  all: $(TESTS)
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 -c -r1.6 test_thread.pgc
*** src/interfaces/ecpg/test/test_thread.pgc	5 Sep 2003 01:53:41 -0000	1.6
--- src/interfaces/ecpg/test/test_thread.pgc	6 Mar 2004 15:41:59 -0000
***************
*** 1,107 ****
  /*
   *	Thread test program
!  *	by Philip Yarra
   */
  
  
  #include <pthread.h>
  #include <stdlib.h>
  
! void		ins1(void);
! void		ins2(void);
  
  EXEC SQL BEGIN DECLARE SECTION;
! char	   *dbname;
! int	    iterations = 10;
  EXEC SQL END DECLARE SECTION;
  
! int
! main(int argc, char *argv[])
  {
! 	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;
! }
  
! 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");
  }
  
! 
! void
! ins2(void)
  {
! 	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");
  }
--- 1,140 ----
  /*
   *	Thread test program
!  *	by Philip Yarra & Lee Kindness.
   */
  
+ /* #define ECPGDEBUG */
  
  #include <pthread.h>
  #include <stdlib.h>
  
! 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.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 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 );
  }
