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