2004-01-14 03:32:37 +00:00
/*
* * 2004 January 13
* *
* * The author disclaims copyright to this source code . In place of
* * a legal notice , here is a blessing :
* *
* * May you do good and not evil .
* * May you find forgiveness for yourself and forgive others .
* * May you share freely , never taking more than you give .
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * This file implements a simple standalone program used to test whether
* * or not the SQLite library is threadsafe .
* *
* * This file is NOT part of the standard SQLite library . It is used for
* * testing only .
*/
# include <stdio.h>
# include <unistd.h>
# include <pthread.h>
# include <string.h>
# include <stdlib.h>
# include "sqlite.h"
/*
* * Name of the database
*/
# define DB_FILE "test.db"
/*
* * When this variable becomes non - zero , all threads stop
* * what they are doing .
*/
volatile int all_stop = 0 ;
/*
* * Callback from the integrity check . If the result is anything other
* * than " ok " it means the integrity check has failed . Set the " all_stop "
* * global variable to stop all other activity . Print the error message
* * or print OK if the string " ok " is seen .
*/
2007-01-05 01:58:26 +00:00
int check_callback ( void * pid , int argc , char * * argv , char * * notUsed2 ) {
int id = ( int ) pid ;
2004-01-14 03:32:37 +00:00
if ( strcmp ( argv [ 0 ] , " ok " ) ) {
all_stop = 1 ;
2015-08-05 08:01:46 +00:00
fprintf ( stderr , " %d: %s \n " , id , argv [ 0 ] ) ;
2004-01-14 03:32:37 +00:00
} else {
2007-01-05 01:58:26 +00:00
/* fprintf(stderr,"%d: OK\n", id); */
2004-01-14 03:32:37 +00:00
}
return 0 ;
}
/*
* * Do an integrity check on the database . If the first integrity check
* * fails , try it a second time .
*/
2007-01-05 01:58:26 +00:00
int integrity_check ( sqlite * db , int id ) {
2004-01-14 03:32:37 +00:00
int rc ;
if ( all_stop ) return 0 ;
2007-01-05 01:58:26 +00:00
/* fprintf(stderr,"%d: CHECK\n", id); */
2004-06-29 03:29:00 +00:00
rc = sqlite3_exec ( db , " pragma integrity_check " , check_callback , 0 , 0 ) ;
2004-01-14 03:32:37 +00:00
if ( rc ! = SQLITE_OK & & rc ! = SQLITE_BUSY ) {
2007-01-05 01:58:26 +00:00
fprintf ( stderr , " %d, Integrity check returns %d \n " , id , rc ) ;
2004-01-14 03:32:37 +00:00
}
if ( all_stop ) {
2004-06-29 03:29:00 +00:00
sqlite3_exec ( db , " pragma integrity_check " , check_callback , 0 , 0 ) ;
2004-01-14 03:32:37 +00:00
}
return 0 ;
}
/*
* * This is the worker thread
*/
2007-01-05 01:58:26 +00:00
void * worker ( void * workerArg ) {
2004-01-14 03:32:37 +00:00
sqlite * db ;
2007-01-05 01:58:26 +00:00
int id = ( int ) workerArg ;
2004-01-14 03:32:37 +00:00
int rc ;
int cnt = 0 ;
2007-01-05 01:58:26 +00:00
fprintf ( stderr , " Starting worker %d \n " , id ) ;
2004-01-14 03:32:37 +00:00
while ( ! all_stop & & cnt + + < 10000 ) {
2007-01-05 01:58:26 +00:00
if ( cnt % 100 = = 0 ) printf ( " %d: %d \n " , id , cnt ) ;
2004-06-29 03:29:00 +00:00
while ( ( sqlite3_open ( DB_FILE , & db ) ) ! = SQLITE_OK ) sched_yield ( ) ;
sqlite3_exec ( db , " PRAGMA synchronous=OFF " , 0 , 0 , 0 ) ;
2007-01-05 01:58:26 +00:00
/* integrity_check(db, id); */
2004-06-29 03:29:00 +00:00
if ( all_stop ) { sqlite3_close ( db ) ; break ; }
2007-01-05 01:58:26 +00:00
/* fprintf(stderr, "%d: BEGIN\n", id); */
2004-06-29 03:29:00 +00:00
rc = sqlite3_exec ( db , " INSERT INTO t1 VALUES('bogus data') " , 0 , 0 , 0 ) ;
2007-01-05 01:58:26 +00:00
/* fprintf(stderr, "%d: END rc=%d\n", id, rc); */
2004-06-29 03:29:00 +00:00
sqlite3_close ( db ) ;
2004-01-14 03:32:37 +00:00
}
2007-01-05 01:58:26 +00:00
fprintf ( stderr , " Worker %d finished \n " , id ) ;
2004-01-14 03:32:37 +00:00
return 0 ;
}
/*
* * Initialize the database and start the threads
*/
int main ( int argc , char * * argv ) {
sqlite * db ;
int i , rc ;
pthread_t aThread [ 5 ] ;
2004-06-29 07:45:33 +00:00
if ( strcmp ( DB_FILE , " :memory: " ) ) {
char * zJournal = sqlite3_mprintf ( " %s-journal " , DB_FILE ) ;
unlink ( DB_FILE ) ;
unlink ( zJournal ) ;
2007-01-05 01:58:26 +00:00
sqlite3_free ( zJournal ) ;
2004-06-29 07:45:33 +00:00
}
2004-06-29 03:29:00 +00:00
sqlite3_open ( DB_FILE , & db ) ;
2004-01-14 03:32:37 +00:00
if ( db = = 0 ) {
fprintf ( stderr , " unable to initialize database \n " ) ;
exit ( 1 ) ;
}
2004-06-29 03:29:00 +00:00
rc = sqlite3_exec ( db , " CREATE TABLE t1(x); " , 0 , 0 , 0 ) ;
2004-01-14 03:32:37 +00:00
if ( rc ) {
fprintf ( stderr , " cannot create table t1: %d \n " , rc ) ;
exit ( 1 ) ;
}
2004-06-29 03:29:00 +00:00
sqlite3_close ( db ) ;
2004-01-14 03:32:37 +00:00
for ( i = 0 ; i < sizeof ( aThread ) / sizeof ( aThread [ 0 ] ) ; i + + ) {
2007-01-05 01:58:26 +00:00
pthread_create ( & aThread [ i ] , 0 , worker , ( void * ) i ) ;
2004-01-14 03:32:37 +00:00
}
for ( i = 0 ; i < sizeof ( aThread ) / sizeof ( aThread [ i ] ) ; i + + ) {
pthread_join ( aThread [ i ] , 0 ) ;
}
if ( ! all_stop ) {
printf ( " Everything seems ok. \n " ) ;
return 0 ;
} else {
printf ( " We hit an error. \n " ) ;
return 1 ;
}
}