| /* |
| * Thread test program |
| * by Philip Yarra & Lee Kindness. |
| */ |
| #include <stdint.h> |
| #include <stdlib.h> |
| #include "ecpg_config.h" |
| |
| #ifndef ENABLE_THREAD_SAFETY |
| int |
| main(void) |
| { |
| printf("No threading enabled.\n"); |
| return 0; |
| } |
| #else |
| #ifndef WIN32 |
| #include <pthread.h> |
| #else |
| #include <windows.h> |
| #include <locale.h> |
| #endif |
| |
| exec sql include ../regression; |
| |
| void *test_thread(void *arg); |
| |
| int nthreads = 10; |
| int iterations = 20; |
| |
| int main() |
| { |
| #ifndef WIN32 |
| pthread_t *threads; |
| #else |
| HANDLE *threads; |
| #endif |
| intptr_t n; |
| EXEC SQL BEGIN DECLARE SECTION; |
| int l_rows; |
| EXEC SQL END DECLARE SECTION; |
| |
| /* Do not switch on debug output for regression tests. The threads get executed in |
| * more or less random order */ |
| /* ECPGdebug(1, stderr); */ |
| |
| /* setup test_thread table */ |
| EXEC SQL CONNECT TO REGRESSDB1; |
| 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(threads[0])); |
| if( threads == NULL ) |
| { |
| fprintf(stderr, "Cannot alloc memory\n"); |
| return 1; |
| } |
| for( n = 0; n < nthreads; n++ ) |
| { |
| #ifndef WIN32 |
| pthread_create(&threads[n], NULL, test_thread, (void *) (n + 1)); |
| #else |
| threads[n] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (void (*) (void)) test_thread, (void *) (n + 1), 0, NULL); |
| #endif |
| } |
| |
| /* wait for thread completion */ |
| #ifndef WIN32 |
| for( n = 0; n < nthreads; n++ ) |
| { |
| pthread_join(threads[n], NULL); |
| } |
| #else |
| WaitForMultipleObjects(nthreads, threads, TRUE, INFINITE); |
| #endif |
| free(threads); |
| |
| /* and check results */ |
| EXEC SQL CONNECT TO REGRESSDB1; |
| EXEC SQL SELECT COUNT(*) INTO :l_rows FROM test_thread; |
| EXEC SQL COMMIT; |
| EXEC SQL DISCONNECT; |
| if( l_rows == (nthreads * iterations) ) |
| printf("Success.\n"); |
| else |
| printf("ERROR: Failure - expecting %d rows, got %d.\n", nthreads * iterations, l_rows); |
| |
| return 0; |
| } |
| |
| void *test_thread(void *arg) |
| { |
| long threadnum = (intptr_t) 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 */ |
| #ifndef _MSC_VER |
| snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum); |
| #else |
| _snprintf(l_connection, sizeof(l_connection), "thread_%03ld", threadnum); |
| #endif |
| EXEC SQL WHENEVER sqlerror sqlprint; |
| EXEC SQL CONNECT TO REGRESSDB1 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++ ) |
| { |
| EXEC SQL AT :l_connection INSERT INTO test_thread(thread, iteration) VALUES(:l_connection, :l_i); |
| if( sqlca.sqlcode != 0 ) |
| printf("%s: ERROR: insert failed!\n", l_connection); |
| } |
| |
| /* all done */ |
| EXEC SQL AT :l_connection COMMIT; |
| EXEC SQL DISCONNECT :l_connection; |
| return NULL; |
| } |
| #endif /* ENABLE_THREAD_SAFETY */ |