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