| OLD | NEW | 
 | (Empty) | 
|    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 } |  | 
| OLD | NEW |