Re: ECPG - Remove need for "AT connection" when using threads

Поиск
Список
Период
Сортировка
От Lee Kindness
Тема Re: ECPG - Remove need for "AT connection" when using threads
Дата
Msg-id 16469.55209.259726.362010@kelvin.csl.co.uk
обсуждение исходный текст
Ответ на Re: ECPG - Remove need for "AT connection" when using threads  (Bruce Momjian <pgman@candle.pha.pa.us>)
Ответы Re: ECPG - Remove need for "AT connection" when using threads  (Bruce Momjian <pgman@candle.pha.pa.us>)
Список pgsql-patches
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.

Thanks, L.

Michael Meskes writes:
 > On Sun, Mar 14, 2004 at 09:11:27AM -0500, Bruce Momjian wrote:
 > > > I just applied this patch and the last one.
 > >
 > > I assume you mean you applied:
 > >
 > >     Update tests & memory leak fix
 > >
 > > and
 > >
 > >     ECPG - Remove need for "AT connection" when using threads
 >
 > Yes. Sorry, should have said so.
 >
 > Michael

/*
 *    Thread test program
 *    by 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_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 );
}
Index: src/interfaces/ecpg/ecpglib/connect.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/ecpg/ecpglib/connect.c,v
retrieving revision 1.20
diff -c -r1.20 connect.c
*** src/interfaces/ecpg/ecpglib/connect.c    14 Mar 2004 12:16:29 -0000    1.20
--- src/interfaces/ecpg/ecpglib/connect.c    15 Mar 2004 16:17:36 -0000
***************
*** 62,79 ****
  {
      struct connection *ret = NULL;

  #ifdef ENABLE_THREAD_SAFETY
!     pthread_mutex_lock(&connections_mutex);
  #endif

!     ret = ecpg_get_connection_nr(connection_name);

  #ifdef ENABLE_THREAD_SAFETY
!     pthread_mutex_unlock(&connections_mutex);
  #endif

      return (ret);
-
  }

  static void
--- 62,89 ----
  {
      struct connection *ret = NULL;

+     if ((connection_name == NULL) || (strcmp(connection_name, "CURRENT") == 0))
+     {
  #ifdef ENABLE_THREAD_SAFETY
!         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);

  #ifdef ENABLE_THREAD_SAFETY
!         pthread_mutex_unlock(&connections_mutex);
  #endif
+     }

      return (ret);
  }

  static void

В списке pgsql-patches по дате отправления:

Предыдущее
От: Bruce Momjian
Дата:
Сообщение: Re: misc patches (minor)
Следующее
От: Bruce Momjian
Дата:
Сообщение: Re: ECPG - Remove need for "AT connection" when using threads