1 2 #pragma ident "%Z%%M% %I% %E% SMI" 3 4 /* 5 ** This program tests the ability of SQLite database to recover from a crash. 6 ** This program runs under Unix only, but the results are applicable to all 7 ** systems. 8 ** 9 ** The main process first constructs a test database, then starts creating 10 ** subprocesses that write to that database. Each subprocess is killed off, 11 ** without a chance to clean up its database connection, after a random 12 ** delay. This killing of the subprocesses simulates a crash or power 13 ** failure. The next subprocess to open the database should rollback 14 ** whatever operation was in process at the time of the simulated crash. 15 ** 16 ** If any problems are encountered, an error is reported and the test stops. 17 ** If no problems are seen after a large number of tests, we assume that 18 ** the rollback mechanism is working. 19 */ 20 #include <stdio.h> 21 #include <unistd.h> 22 #include <sys/types.h> 23 #include <sys/wait.h> 24 #include <signal.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <sched.h> 28 #include "sqlite.h" 29 30 static void do_some_sql(int parent){ 31 char *zErr; 32 int rc = SQLITE_OK; 33 sqlite *db; 34 int cnt = 0; 35 static char zBig[] = 36 "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 37 "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 38 39 if( access("./test.db-journal",0)==0 ){ 40 /*printf("pid %d: journal exists. rollback will be required\n",getpid());*/ unlink("test.db-saved"); 41 system("cp test.db test.db-saved"); 42 unlink("test.db-journal-saved"); 43 system("cp test.db-journal test.db-journal-saved"); 44 } 45 db = sqlite_open("./test.db", 0, &zErr); 46 if( db==0 ){ 47 printf("ERROR: %s\n", zErr); 48 if( strcmp(zErr,"database disk image is malformed")==0 ){ 49 kill(parent, SIGKILL); 50 } 51 exit(1); 52 } 53 srand(getpid()); 54 while( rc==SQLITE_OK ){ 55 cnt++; 56 rc = sqlite_exec_printf(db, 57 "INSERT INTO t1 VALUES(%d,'%d%s')", 0, 0, &zErr, 58 rand(), rand(), zBig); 59 } 60 if( rc!=SQLITE_OK ){ 61 printf("ERROR #%d: %s\n", rc, zErr); 62 if( rc==SQLITE_CORRUPT ){ 63 kill(parent, SIGKILL); 64 } 65 } 66 printf("pid %d: cnt=%d\n", getpid(), cnt); 67 } 68 69 70 int main(int argc, char **argv){ 71 int i; 72 sqlite *db; 73 char *zErr; 74 int status; 75 int parent = getpid(); 76 77 unlink("test.db"); 78 unlink("test.db-journal"); 79 db = sqlite_open("test.db", 0, &zErr); 80 if( db==0 ){ 81 printf("Cannot initialize: %s\n", zErr); 82 return 1; 83 } 84 sqlite_exec(db, "CREATE TABLE t1(a,b)", 0, 0, 0); 85 sqlite_close(db); 86 for(i=0; i<10000; i++){ 87 int pid = fork(); 88 if( pid==0 ){ 89 sched_yield(); 90 do_some_sql(parent); 91 return 0; 92 } 93 printf("test %d, pid=%d\n", i, pid); 94 usleep(rand()%10000 + 1000); 95 kill(pid, SIGKILL); 96 waitpid(pid, &status, 0); 97 } 98 return 0; 99 } 100