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