/ Check-in [ec6ef5f2]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add options to bc_test1.c to make it more flexible.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | begin-concurrent
Files: files | file ages | folders
SHA1: ec6ef5f2c2dc18e1a19c205f365f4071f0870b68
User & Date: dan 2016-05-07 18:02:53
Wiki:begin-concurrent
Context
2016-05-21
18:50
Use pthreads mutexes and conditions to synchronize threads in bc_test1. check-in: f33aa76f user: dan tags: begin-concurrent
2016-05-07
18:02
Add options to bc_test1.c to make it more flexible. check-in: ec6ef5f2 user: dan tags: begin-concurrent
2016-05-06
21:04
Add test/bc_test1.c, for testing the degree of concurrency provided by this branch under various conditions. check-in: 128c7eae user: dan tags: begin-concurrent
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to test/bc_test1.c.













1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31

32


33
34
35
36
37
38
39
..
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83


84
85
86
87
88
89
90


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133








134
135
136
137














#include <sqlite3.h>

#include <stdlib.h>


#include "tt3_core.c"


typedef struct Config Config;

struct Config {
  int nIPT;                       /* --inserts-per-transaction */
  int nThread;                    /* --threads */
  int nSecond;                    /* --seconds */
  int bMutex;                     /* --mutex */

  int bRm;                        /* --rm */
  sqlite3_mutex *pMutex;
};


static char *thread_main(int iTid, void *pArg){
  Config *pConfig = (Config*)pArg;
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  int nAttempt = 0;               /* Attempted transactions */
  int nCommit = 0;                /* Successful transactions */
  int j;

  opendb(&err, &db, "xyz.db", 0);
  sqlite3_busy_handler(db.db, 0, 0);

  execsql(&err, &db, "PRAGMA wal_autocheckpoint = 0");



  while( !timetostop(&err) ){
    execsql(&err, &db, "BEGIN CONCURRENT");
    for(j=0; j<pConfig->nIPT; j++){
      execsql(&err, &db, 
          "INSERT INTO t1 VALUES"
          "(randomblob(10), randomblob(20), randomblob(30), randomblob(200))"
................................................................................
    }
  }

  closedb(&err, &db);
  return sqlite3_mprintf("%d/%d successful commits", nCommit, nAttempt);
}

static void usage(char *zName){
  fprintf(stderr, "Usage: %s ?SWITCHES?\n", zName);
  fprintf(stderr, "\n");
  fprintf(stderr, "where switches are\n");
  fprintf(stderr, "  --seconds N\n");
  fprintf(stderr, "  --inserts N\n");
  fprintf(stderr, "  --threads N\n");
  fprintf(stderr, "  --rm BOOL\n");
  fprintf(stderr, "  --mutex BOOL\n");
  fprintf(stderr, "\n");
  exit(-1);
}

int main(int argc, char **argv){
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  Threadset threads = {0};        /* Test threads */
  Config sConfig = {5, 3, 5};
  int i;

  for(i=1; i<argc; i++){
    char *z = argv[i];
    int n = strlen(z);
    if( n>=3 && 0==sqlite3_strnicmp(z, "--seconds", n) ){
      if( (++i)==argc ) usage(argv[0]);
      sConfig.nSecond = atoi(argv[i]);


    }

    else if( n>=3 && 0==sqlite3_strnicmp(z, "--inserts", n) ){
      if( (++i)==argc ) usage(argv[0]);
      sConfig.nIPT = atoi(argv[i]);
    }



    else if( n>=3 && 0==sqlite3_strnicmp(z, "--threads", n) ){
      if( (++i)==argc ) usage(argv[0]);
      sConfig.nThread = atoi(argv[i]);
    }

    else if( n>=3 && 0==sqlite3_strnicmp(z, "--rm", n) ){
      if( (++i)==argc ) usage(argv[0]);
      sConfig.bRm = atoi(argv[i]);
    }

    else if( n>=3 && 0==sqlite3_strnicmp(z, "--mutex", n) ){
      if( (++i)==argc ) usage(argv[0]);
      sConfig.bMutex = atoi(argv[i]);
    }

    else usage(argv[0]);
  }

  printf("With: --threads %d --inserts %d --seconds %d --rm %d --mutex %d\n",
      sConfig.nThread, sConfig.nIPT, sConfig.nSecond, sConfig.bRm, 
      sConfig.bMutex
  );

  /* Ensure the schema has been created */
  if( sConfig.bMutex ){
    sConfig.pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE);
  }
  opendb(&err, &db, "xyz.db", sConfig.bRm);

  sql_script(&err, &db,
      "PRAGMA journal_mode = wal;"
      "CREATE TABLE IF NOT EXISTS t1(a PRIMARY KEY, b, c, d) WITHOUT ROWID;"
      "CREATE INDEX IF NOT EXISTS t1b ON t1(b);"
      "CREATE INDEX IF NOT EXISTS t1c ON t1(c);"
  );
  closedb(&err, &db);

  setstoptime(&err, sConfig.nSecond*1000);
  for(i=0; i<sConfig.nThread; i++){
    launch_thread(&err, &threads, thread_main, (void*)&sConfig);
  }
  join_all_threads(&err, &threads);









  sqlite3_mutex_free(sConfig.pMutex);
  print_and_free_err(&err);
  return 0;
}
>
>
>
>
>
>
>
>
>
>
>
>



<

<
>




<





|



>











>
|
>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
|



|


|
|
|
|
|
|
>
>
|

<
<
|
<
<
>
>
|
|
<
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
|

|







<

|
|
|



>
>
>
>
>
>
>
>
|



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

16

17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
65
66
67
68
69
70
71













72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88


89


90
91
92
93

94
95


















96
97
98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
** 2016-05-07
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
*/


#include <sqlite3.h>

#include <stdlib.h>

#include <stddef.h>
#include "tt3_core.c"


typedef struct Config Config;

struct Config {
  int nIPT;                       /* --inserts-per-transaction */
  int nThread;                    /* --threads */
  int nSecond;                    /* --seconds */
  int bMutex;                     /* --mutex */
  int nAutoCkpt;                  /* --autockpt */
  int bRm;                        /* --rm */
  sqlite3_mutex *pMutex;
};


static char *thread_main(int iTid, void *pArg){
  Config *pConfig = (Config*)pArg;
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  int nAttempt = 0;               /* Attempted transactions */
  int nCommit = 0;                /* Successful transactions */
  int j;

  opendb(&err, &db, "xyz.db", 0);
  sqlite3_busy_handler(db.db, 0, 0);
  sql_script_printf(&err, &db, 
      "PRAGMA wal_autocheckpoint = %d;"
      "PRAGMA synchronous = 0;", pConfig->nAutoCkpt
  );

  while( !timetostop(&err) ){
    execsql(&err, &db, "BEGIN CONCURRENT");
    for(j=0; j<pConfig->nIPT; j++){
      execsql(&err, &db, 
          "INSERT INTO t1 VALUES"
          "(randomblob(10), randomblob(20), randomblob(30), randomblob(200))"
................................................................................
    }
  }

  closedb(&err, &db);
  return sqlite3_mprintf("%d/%d successful commits", nCommit, nAttempt);
}














int main(int argc, const char **argv){
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  Threadset threads = {0};        /* Test threads */
  Config conf = {5, 3, 5};
  int i;

  CmdlineArg apArg[] = {
    { "--seconds", CMDLINE_INT,  offsetof(Config, nSecond) },
    { "--inserts", CMDLINE_INT,  offsetof(Config, nIPT) },
    { "--threads", CMDLINE_INT,  offsetof(Config, nThread) },
    { "--mutex",   CMDLINE_BOOL, offsetof(Config, bMutex) },
    { "--rm",      CMDLINE_BOOL, offsetof(Config, bRm) },
    { "--autockpt",CMDLINE_INT,  offsetof(Config, nAutoCkpt) },
    { 0, 0, 0 }
  };



  cmdline_process(apArg, argc, argv, (void*)&conf);


  if( err.rc==SQLITE_OK ){
    char *z = cmdline_construct(apArg, (void*)&conf);
    printf("With: %s\n", z);
    sqlite3_free(z);

  }



















  /* Ensure the schema has been created */
  if( conf.bMutex ){
    conf.pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE);
  }
  opendb(&err, &db, "xyz.db", conf.bRm);

  sql_script(&err, &db,
      "PRAGMA journal_mode = wal;"
      "CREATE TABLE IF NOT EXISTS t1(a PRIMARY KEY, b, c, d) WITHOUT ROWID;"
      "CREATE INDEX IF NOT EXISTS t1b ON t1(b);"
      "CREATE INDEX IF NOT EXISTS t1c ON t1(c);"
  );


  setstoptime(&err, conf.nSecond*1000);
  for(i=0; i<conf.nThread; i++){
    launch_thread(&err, &threads, thread_main, (void*)&conf);
  }
  join_all_threads(&err, &threads);

  if( err.rc==SQLITE_OK ){
    printf("Database is %dK\n", (int)(filesize(&err, "xyz.db") / 1024));
  }
  if( err.rc==SQLITE_OK ){
    printf("Wal file is %dK\n", (int)(filesize(&err, "xyz.db-wal") / 1024));
  }

  closedb(&err, &db);
  sqlite3_mutex_free(conf.pMutex);
  print_and_free_err(&err);
  return 0;
}

Changes to test/tt3_core.c.

60
61
62
63
64
65
66

































































































































67
68
69
70
71
72
73

#define PTR2INT(x) ((int)((intptr_t)x))
#define INT2PTR(x) ((void*)((intptr_t)x))

/*
** End of test code/infrastructure interface macros.
*************************************************************************/


































































































































/*
 * This code implements the MD5 message-digest algorithm.
 * The algorithm is due to Ron Rivest.  This code was
 * written by Colin Plumb in 1993, no copyright is claimed.
 * This code is in the public domain; do with it what you wish.
 *







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

#define PTR2INT(x) ((int)((intptr_t)x))
#define INT2PTR(x) ((void*)((intptr_t)x))

/*
** End of test code/infrastructure interface macros.
*************************************************************************/


/************************************************************************
** Start of command line processing utilities.
*/
#define CMDLINE_INT   1
#define CMDLINE_BOOL  2

typedef struct CmdlineArg CmdlineArg;
struct CmdlineArg {
  const char *zSwitch;
  int eType;
  int iOffset;
};

static void cmdline_error(const char *zFmt, ...){
  va_list ap;                   /* ... arguments */
  char *zMsg = 0;
  va_start(ap, zFmt);
  zMsg = sqlite3_vmprintf(zFmt, ap);
  fprintf(stderr, "%s\n", zMsg);
  sqlite3_free(zMsg);
  va_end(ap);
  exit(-1);
}

static void cmdline_usage(const char *zPrg, CmdlineArg *apArg){
  int i;
  fprintf(stderr, "Usage: %s SWITCHES\n", zPrg);
  fprintf(stderr, "\n");
  fprintf(stderr, "where switches are\n");
  for(i=0; apArg[i].zSwitch; i++){
    const char *zExtra = "";
    switch( apArg[i].eType ){
      case CMDLINE_INT: zExtra = "N"; break;
      case CMDLINE_BOOL: zExtra = ""; break;
      default:
        zExtra = "???";
        break;
    }
    fprintf(stderr, "  %s %s\n", apArg[i].zSwitch, zExtra);
  }
  fprintf(stderr, "\n");
  exit(-2);
}

static char *cmdline_construct(CmdlineArg *apArg, void *pObj){
  unsigned char *p = (unsigned char*)pObj;
  char *zRet = 0;
  int iArg;

  for(iArg=0; apArg[iArg].zSwitch; iArg++){
    const char *zSpace = (zRet ? " " : "");
    CmdlineArg *pArg = &apArg[iArg];

    switch( pArg->eType ){
      case CMDLINE_INT: {
        zRet = sqlite3_mprintf("%z%s%s %d", zRet, zSpace, pArg->zSwitch, 
            *(int*)(p + pArg->iOffset)
        );
        break;
      };

      case CMDLINE_BOOL: 
        if( *(int*)(p + pArg->iOffset) ){
          zRet = sqlite3_mprintf("%z%s%s", zRet, zSpace, pArg->zSwitch);
        }
        break;
        
      default:
        zRet = sqlite3_mprintf("%z%s%s ???", zRet, zSpace, pArg->zSwitch);
    }
  }

  return zRet;
}

static void cmdline_process(
 CmdlineArg *apArg, 
 int argc,
 const char **argv,
 void *pObj
){
  int i;
  int iArg;
  unsigned char *p = (unsigned char*)pObj;

  for(i=1; i<argc; i++){
    const char *z = argv[i];
    int n = strlen(z);
    int iOpt = -1;

    for(iArg=0; apArg[iArg].zSwitch; iArg++){
      if( 0==sqlite3_strnicmp(apArg[iArg].zSwitch, z, n) ){
        if( iOpt>=0 ){
          cmdline_error("ambiguous switch: %s", z);
        }
        iOpt = iArg;
        switch( apArg[iArg].eType ){
          case CMDLINE_INT:
            i++;
            if( i==argc ){
              cmdline_error("option requires an argument: %s", z);
            }
            *(int*)(p + apArg[iArg].iOffset) = atoi(argv[i]);
            break;

          case CMDLINE_BOOL:
            *(int*)(p + apArg[iArg].iOffset) = 1;
            break;

          default:
            assert( 0 );
            cmdline_error("internal error");
            return;
        }
      }
    }

    if( iOpt<0 ){
      cmdline_usage(argv[0], apArg);
    }
  }
}

/*
** End of command line processing utilities.
*************************************************************************/


/*
 * This code implements the MD5 message-digest algorithm.
 * The algorithm is due to Ron Rivest.  This code was
 * written by Colin Plumb in 1993, no copyright is claimed.
 * This code is in the public domain; do with it what you wish.
 *