github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/threadtest2.c (about)

     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,"%d: %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  }