Home | History | Annotate | Download | only in test
      1 /*
      2 ** 2004 January 13
      3 **
      4 ** The author disclaims copyright to this source code.  In place of
      5 ** a legal notice, here is a blessing:
      6 **
      7 **    May you do good and not evil.
      8 **    May you find forgiveness for yourself and forgive others.
      9 **    May you share freely, never taking more than you give.
     10 **
     11 *************************************************************************
     12 ** This file implements a simple standalone program used to test whether
     13 ** or not the SQLite library is threadsafe.
     14 **
     15 ** This file is NOT part of the standard SQLite library.  It is used for
     16 ** testing only.
     17 */
     18 #include <stdio.h>
     19 #include <unistd.h>
     20 #include <pthread.h>
     21 #include <string.h>
     22 #include <stdlib.h>
     23 #include "sqlite.h"
     24 
     25 /*
     26 ** Name of the database
     27 */
     28 #define DB_FILE "test.db"
     29 
     30 /*
     31 ** When this variable becomes non-zero, all threads stop
     32 ** what they are doing.
     33 */
     34 volatile int all_stop = 0;
     35 
     36 /*
     37 ** Callback from the integrity check.  If the result is anything other
     38 ** than "ok" it means the integrity check has failed.  Set the "all_stop"
     39 ** global variable to stop all other activity.  Print the error message
     40 ** or print OK if the string "ok" is seen.
     41 */
     42 int check_callback(void *pid, int argc, char **argv, char **notUsed2){
     43   int id = (int)pid;
     44   if( strcmp(argv[0],"ok") ){
     45     all_stop = 1;
     46     fprintf(stderr,"id: %s\n", id, argv[0]);
     47   }else{
     48     /* fprintf(stderr,"%d: OK\n", id); */
     49   }
     50   return 0;
     51 }
     52 
     53 /*
     54 ** Do an integrity check on the database.  If the first integrity check
     55 ** fails, try it a second time.
     56 */
     57 int integrity_check(sqlite *db, int id){
     58   int rc;
     59   if( all_stop ) return 0;
     60   /* fprintf(stderr,"%d: CHECK\n", id); */
     61   rc = sqlite3_exec(db, "pragma integrity_check", check_callback, 0, 0);
     62   if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
     63     fprintf(stderr,"%d, Integrity check returns %d\n", id, rc);
     64   }
     65   if( all_stop ){
     66     sqlite3_exec(db, "pragma integrity_check", check_callback, 0, 0);
     67   }
     68   return 0;
     69 }
     70 
     71 /*
     72 ** This is the worker thread
     73 */
     74 void *worker(void *workerArg){
     75   sqlite *db;
     76   int id = (int)workerArg;
     77   int rc;
     78   int cnt = 0;
     79   fprintf(stderr, "Starting worker %d\n", id);
     80   while( !all_stop && cnt++<10000 ){
     81     if( cnt%100==0 ) printf("%d: %d\n", id, cnt);
     82     while( (sqlite3_open(DB_FILE, &db))!=SQLITE_OK ) sched_yield();
     83     sqlite3_exec(db, "PRAGMA synchronous=OFF", 0, 0, 0);
     84     /* integrity_check(db, id); */
     85     if( all_stop ){ sqlite3_close(db); break; }
     86     /* fprintf(stderr, "%d: BEGIN\n", id); */
     87     rc = sqlite3_exec(db, "INSERT INTO t1 VALUES('bogus data')", 0, 0, 0);
     88     /* fprintf(stderr, "%d: END rc=%d\n", id, rc); */
     89     sqlite3_close(db);
     90   }
     91   fprintf(stderr, "Worker %d finished\n", id);
     92   return 0;
     93 }
     94 
     95 /*
     96 ** Initialize the database and start the threads
     97 */
     98 int main(int argc, char **argv){
     99   sqlite *db;
    100   int i, rc;
    101   pthread_t aThread[5];
    102 
    103   if( strcmp(DB_FILE,":memory:") ){
    104     char *zJournal = sqlite3_mprintf("%s-journal", DB_FILE);
    105     unlink(DB_FILE);
    106     unlink(zJournal);
    107     sqlite3_free(zJournal);
    108   }
    109   sqlite3_open(DB_FILE, &db);
    110   if( db==0 ){
    111     fprintf(stderr,"unable to initialize database\n");
    112     exit(1);
    113   }
    114   rc = sqlite3_exec(db, "CREATE TABLE t1(x);", 0,0,0);
    115   if( rc ){
    116     fprintf(stderr,"cannot create table t1: %d\n", rc);
    117     exit(1);
    118   }
    119   sqlite3_close(db);
    120   for(i=0; i<sizeof(aThread)/sizeof(aThread[0]); i++){
    121     pthread_create(&aThread[i], 0, worker, (void*)i);
    122   }
    123   for(i=0; i<sizeof(aThread)/sizeof(aThread[i]); i++){
    124     pthread_join(aThread[i], 0);
    125   }
    126   if( !all_stop ){
    127     printf("Everything seems ok.\n");
    128     return 0;
    129   }else{
    130     printf("We hit an error.\n");
    131     return 1;
    132   }
    133 }
    134