/ Check-in [36e364a3]
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:Additional test cases; Round chunk size up to a multiple of max page size;
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | multiplex-enhancements
Files: files | file ages | folders
SHA1: 36e364a3fe7d3a9a521189ff0262611a492c21dc
User & Date: shaneh 2011-03-31 05:31:24
Context
2011-03-31
13:14
Add tests and fixes for SELECT multiplex_control(op, val); check-in: fee9734c user: shaneh tags: multiplex-enhancements
05:31
Additional test cases; Round chunk size up to a multiple of max page size; check-in: 36e364a3 user: shaneh tags: multiplex-enhancements
2011-03-30
21:03
Updates to multiplex.test script; misc. bug fixes; check-in: c41ff235 user: shaneh tags: multiplex-enhancements
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/test_multiplex.c.

21
22
23
24
25
26
27





28
29
30
31
32
33
34
..
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
...
195
196
197
198
199
200
201

202
203
204

















205
206
207
208
209
210
211
212
213
214
215
216


217
218
219
220
221
222
223
...
659
660
661
662
663
664
665
666
667
668



669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
...
777
778
779
780
781
782
783
784

785
786
787
788
789
790
791
792
793
...
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
*/
#include "sqlite3.h"
#include <string.h>
#include <assert.h>
#include "sqliteInt.h"
#include "test_multiplex.h"






/*
** For a build without mutexes, no-op the mutex calls.
*/
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
#define sqlite3_mutex_alloc(X)    ((sqlite3_mutex*)8)
#define sqlite3_mutex_free(X)
#define sqlite3_mutex_enter(X)
................................................................................


/************************ Shim Definitions ******************************/

#define SQLITE_MULTIPLEX_VFS_NAME "multiplex"

/* This is the limit on the chunk size.  It may be changed by calling
** the xFileControl() interface.

*/
#define SQLITE_MULTIPLEX_CHUNK_SIZE 0x40000000
/* Default limit on number of chunks.  Care should be taken
** so that values for chunks numbers fit in the SQLITE_MULTIPLEX_EXT_FMT
** format specifier. It may be changed by calling
** the xFileControl() interface.
*/
#define SQLITE_MULTIPLEX_MAX_CHUNKS 32

................................................................................
static void multiplexControlFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  extern const char *sqlite3TestErrorName(int);
  extern int multiplexFileControl(sqlite3_file *, int, void *);

  sqlite3_file *db = (sqlite3_file *)sqlite3_user_data(context);
  int op = sqlite3_value_int(argv[0]);
  int iVal = sqlite3_value_int(argv[1]);

















  int rc = multiplexFileControl(db, op, &iVal);
  if( rc== 0 ){
    sqlite3_result_text(context, (char *)sqlite3TestErrorName(rc), -1, SQLITE_TRANSIENT);
  }
  sqlite3_result_text(context, (char *)sqlite3TestErrorName(rc), -1, SQLITE_TRANSIENT);
}

/*
** This is the entry point to register the extension for the multiplex_control() function.
*/
static int multiplexFuncInit(
  sqlite3 *db


){
  int rc;
  rc = sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY, 
    db, multiplexControlFunc, 0, 0);
  return rc;
}

................................................................................
        pGroup->bEnabled = bEnabled;
        rc = SQLITE_OK;
      }
      break;
    case MULTIPLEX_CTRL_SET_CHUNK_SIZE:
      if( pArg ) {
        int nChunkSize = *(int *)pArg;
        if( nChunkSize<32 ){ 
          rc = SQLITE_MISUSE;
        }else{



          pGroup->nChunkSize = nChunkSize;
          rc = SQLITE_OK;
        }
      }
      break;
    case MULTIPLEX_CTRL_SET_MAX_CHUNKS:
      if( pArg ) {
        int nMaxChunks = *(int *)pArg;
        if(( nMaxChunks<1 ) || ( nMaxChunks>99 )){
          rc = SQLITE_MISUSE;
        }else{
          pGroup->nMaxChunks = nMaxChunks;
          rc = SQLITE_OK;
        }
      }
      break;
................................................................................
    return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag);
  }
  return SQLITE_OK;
}

/************************** Public Interfaces *****************************/
/*
** Initialize the multiplex VFS shim.  Use the VFS named zOrigVfsName

** as the VFS that does the actual work.  Use the default if
** zOrigVfsName==NULL.  
**
** The multiplex VFS shim is named "multiplex".  It will become the default
** VFS if makeDefault is non-zero.
**
** THIS ROUTINE IS NOT THREADSAFE.  Call this routine exactly once
** during start-up.
*/
................................................................................

  sqlite3_auto_extension((void*)multiplexFuncInit);

  return SQLITE_OK;
}

/*
** Shutdown the multiplex system.
**
** All SQLite database connections must be closed before calling this
** routine.
**
** THIS ROUTINE IS NOT THREADSAFE.  Call this routine exactly once while
** shutting down in order to free all remaining multiplex groups.
*/







>
>
>
>
>







 







|
>

|







 







>
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<








|
>
>







 







|


>
>
>








|







 







|
>
|
|







 







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
..
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
...
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229


230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
...
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
...
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
...
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
*/
#include "sqlite3.h"
#include <string.h>
#include <assert.h>
#include "sqliteInt.h"
#include "test_multiplex.h"

#ifndef SQLITE_CORE
  #define SQLITE_CORE 1  /* Disable the API redefinition in sqlite3ext.h */
#endif
#include "sqlite3ext.h"

/*
** For a build without mutexes, no-op the mutex calls.
*/
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
#define sqlite3_mutex_alloc(X)    ((sqlite3_mutex*)8)
#define sqlite3_mutex_free(X)
#define sqlite3_mutex_enter(X)
................................................................................


/************************ Shim Definitions ******************************/

#define SQLITE_MULTIPLEX_VFS_NAME "multiplex"

/* This is the limit on the chunk size.  It may be changed by calling
** the xFileControl() interface.  It will be rounded up to a 
** multiple of SQLITE_MAX_PAGE_SIZE.
*/
#define SQLITE_MULTIPLEX_CHUNK_SIZE (SQLITE_MAX_PAGE_SIZE*32)
/* Default limit on number of chunks.  Care should be taken
** so that values for chunks numbers fit in the SQLITE_MULTIPLEX_EXT_FMT
** format specifier. It may be changed by calling
** the xFileControl() interface.
*/
#define SQLITE_MULTIPLEX_MAX_CHUNKS 32

................................................................................
static void multiplexControlFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  extern const char *sqlite3TestErrorName(int);
  extern int multiplexFileControl(sqlite3_file *, int, void *);
  // pPager->fd
  sqlite3 *db = (sqlite3 *)sqlite3_user_data(context);
  int op = sqlite3_value_int(argv[0]);
  int iVal = sqlite3_value_int(argv[1]);
  int rc = SQLITE_OK;
  switch( op ){
    case 1: 
      op = MULTIPLEX_CTRL_ENABLE; 
      break;
    case 2: 
      op = MULTIPLEX_CTRL_SET_CHUNK_SIZE; 
      break;
    case 3: 
      op = MULTIPLEX_CTRL_SET_MAX_CHUNKS; 
      break;
    default:
      rc = SQLITE_ERROR;
      break;
  }
  if( rc==SQLITE_OK ){
    sqlite3_file *f = (sqlite3_file *)db;
    rc = multiplexFileControl(f, op, &iVal);


  }
  sqlite3_result_text(context, (char *)sqlite3TestErrorName(rc), -1, SQLITE_TRANSIENT);
}

/*
** This is the entry point to register the extension for the multiplex_control() function.
*/
static int multiplexFuncInit(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc;
  rc = sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY, 
    db, multiplexControlFunc, 0, 0);
  return rc;
}

................................................................................
        pGroup->bEnabled = bEnabled;
        rc = SQLITE_OK;
      }
      break;
    case MULTIPLEX_CTRL_SET_CHUNK_SIZE:
      if( pArg ) {
        int nChunkSize = *(int *)pArg;
        if( nChunkSize<1 ){
          rc = SQLITE_MISUSE;
        }else{
          /* Round up to nearest multiple of SQLITE_MAX_PAGE_SIZE. */
          nChunkSize = (nChunkSize + (SQLITE_MAX_PAGE_SIZE-1));
          nChunkSize &= ~(SQLITE_MAX_PAGE_SIZE-1);
          pGroup->nChunkSize = nChunkSize;
          rc = SQLITE_OK;
        }
      }
      break;
    case MULTIPLEX_CTRL_SET_MAX_CHUNKS:
      if( pArg ) {
        int nMaxChunks = *(int *)pArg;
        if(( nMaxChunks<1 ) || ( nMaxChunks>SQLITE_MULTIPLEX_MAX_CHUNKS )){
          rc = SQLITE_MISUSE;
        }else{
          pGroup->nMaxChunks = nMaxChunks;
          rc = SQLITE_OK;
        }
      }
      break;
................................................................................
    return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag);
  }
  return SQLITE_OK;
}

/************************** Public Interfaces *****************************/
/*
** CAPI: Initialize the multiplex VFS shim - sqlite3_multiplex_initialize()
**
** Use the VFS named zOrigVfsName as the VFS that does the actual work.  
** Use the default if zOrigVfsName==NULL.  
**
** The multiplex VFS shim is named "multiplex".  It will become the default
** VFS if makeDefault is non-zero.
**
** THIS ROUTINE IS NOT THREADSAFE.  Call this routine exactly once
** during start-up.
*/
................................................................................

  sqlite3_auto_extension((void*)multiplexFuncInit);

  return SQLITE_OK;
}

/*
** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown()
**
** All SQLite database connections must be closed before calling this
** routine.
**
** THIS ROUTINE IS NOT THREADSAFE.  Call this routine exactly once while
** shutting down in order to free all remaining multiplex groups.
*/

Changes to src/test_multiplex.h.

30
31
32
33
34
35
36
37


38
39
40
41
42
43
44
45
46






























47











48
**
** MULTIPLEX_CTRL_ENABLE:
**   This file control is used to enable or disable the multiplex
**   shim.
**
** MULTIPLEX_CTRL_SET_CHUNK_SIZE:
**   This file control is used to set the maximum allowed chunk 
**   size for a multiplex file set.


**
** MULTIPLEX_CTRL_SET_MAX_CHUNKS:
**   This file control is used to set the maximum number of chunks
**   allowed to be used for a mutliplex file set.
*/
#define MULTIPLEX_CTRL_ENABLE          214014
#define MULTIPLEX_CTRL_SET_CHUNK_SIZE  214015
#define MULTIPLEX_CTRL_SET_MAX_CHUNKS  214016











































#endif







|
>
>









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

>
>
>
>
>
>
>
>
>
>
>

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
**
** MULTIPLEX_CTRL_ENABLE:
**   This file control is used to enable or disable the multiplex
**   shim.
**
** MULTIPLEX_CTRL_SET_CHUNK_SIZE:
**   This file control is used to set the maximum allowed chunk 
**   size for a multiplex file set.  The chunk size should be 
**   a multiple of SQLITE_MAX_PAGE_SIZE, and will be rounded up
**   if not.
**
** MULTIPLEX_CTRL_SET_MAX_CHUNKS:
**   This file control is used to set the maximum number of chunks
**   allowed to be used for a mutliplex file set.
*/
#define MULTIPLEX_CTRL_ENABLE          214014
#define MULTIPLEX_CTRL_SET_CHUNK_SIZE  214015
#define MULTIPLEX_CTRL_SET_MAX_CHUNKS  214016

/*
** CAPI: Initialize the multiplex VFS shim - sqlite3_multiplex_initialize()
**
** Use the VFS named zOrigVfsName as the VFS that does the actual work.  
** Use the default if zOrigVfsName==NULL.  
**
** The multiplex VFS shim is named "multiplex".  It will become the default
** VFS if makeDefault is non-zero.
**
** An auto-extension is registered which will make the function 
** multiplex_control() available to open database connections.  This
** function gives access to the xFileControl interface of the 
** multiplex VFS shim.
**
** multiplex_control(<op>,<val>) 
** 
**   <op>=1 MULTIPLEX_CTRL_ENABLE
**   <val>=1 enable
**   <val>=2 disable
** 
**   <op>=1 MULTIPLEX_CTRL_SET_CHUNK_SIZE
**   <val> int, chunk size
** 
**   <op>=1 MULTIPLEX_CTRL_SET_MAX_CHUNKS
**   <val> int, max chunks
**
** THIS ROUTINE IS NOT THREADSAFE.  Call this routine exactly once
** during start-up.
*/
extern int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault);

/*
** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown()
**
** All SQLite database connections must be closed before calling this
** routine.
**
** THIS ROUTINE IS NOT THREADSAFE.  Call this routine exactly once while
** shutting down in order to free all remaining multiplex groups.
*/
extern int sqlite3_multiplex_shutdown(void);

#endif

Changes to test/multiplex.test.

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85












86
87
88
89
90
91
92
...
167
168
169
170
171
172
173
174


175
176
177
178
179
180
181
...
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
}

# This saves off the parameters and calls the 
# underlying sqlite3_multiplex_control() API.
proc multiplex_set {db name chunk_size max_chunks} {
  global g_chunk_size
  global g_max_chunks
  set g_chunk_size $chunk_size
  set g_max_chunks $max_chunks
  set rc [catch {sqlite3_multiplex_control $db $name chunk_size $chunk_size} msg]
  if { $rc==0 } { 
    set rc [catch {sqlite3_multiplex_control $db $name max_chunks $max_chunks} msg]
  }
  list $msg
}
................................................................................
do_test multiplex-1.4 { sqlite3_multiplex_shutdown }               {SQLITE_OK}

do_test multiplex-1.5 { sqlite3_multiplex_initialize "" 0 }        {SQLITE_OK}
do_test multiplex-1.6 { sqlite3_multiplex_shutdown }               {SQLITE_OK}
do_test multiplex-1.7 { sqlite3_multiplex_initialize "" 1 }        {SQLITE_OK}
do_test multiplex-1.8 { sqlite3_multiplex_shutdown }               {SQLITE_OK}

do_test multiplex-1.9  { sqlite3_multiplex_initialize "" 1 }       {SQLITE_OK}
sqlite3 db test.db
do_test multiplex-1.10.1 { multiplex_set db main 32768 16 }        {SQLITE_OK}
do_test multiplex-1.10.2 { multiplex_set db main 32768 -1 }        {SQLITE_MISUSE}
do_test multiplex-1.10.3 { multiplex_set db main -1 16 }           {SQLITE_MISUSE}
do_test multiplex-1.10.4 { multiplex_set db main 31 16 }           {SQLITE_MISUSE}
do_test multiplex-1.10.5 { multiplex_set db main 32768 100 }       {SQLITE_MISUSE}
db close
do_test multiplex-1.11 { sqlite3_multiplex_shutdown }              {SQLITE_OK}













#-------------------------------------------------------------------------
# Some simple warm-body tests with a single database file in rollback 
# mode:
#
#   multiplex-2.1.*: Test simple writing to a multiplex file.
#
................................................................................

do_test multiplex-2.5.3 { 
  execsql { 
    INSERT INTO t1 VALUES(1, 'one');
    INSERT INTO t1 VALUES(2, randomblob(4000));
    INSERT INTO t1 VALUES(3, 'three');
    INSERT INTO t1 VALUES(4, randomblob(4000));
    INSERT INTO t1 VALUES(5, 'five') 


  }
} {}

do_test multiplex-2.5.4 {
  db eval {SELECT * FROM t1 WHERE a=1}
} {1 one}

................................................................................
        PRAGMA auto_vacuum = off;
      }
      db eval "PRAGMA journal_mode = $jmode;"
    } $jmode
    do_test multiplex-5.6.2.$jmode {
      execsql {
        CREATE TABLE t1(a, b);
        INSERT INTO t1 VALUES(1, randomblob(1100));
        INSERT INTO t1 VALUES(2, randomblob(1100));
        INSERT INTO t1 VALUES(3, randomblob(1100));
        INSERT INTO t1 VALUES(4, randomblob(1100));
        INSERT INTO t1 VALUES(5, randomblob(1100));
      }
      db close
      sqlite3_multiplex_initialize "" 1
      sqlite3 db test.db
      multiplex_set db main 4096 16
    } {SQLITE_OK}
    do_test multiplex-5.6.3.$jmode {
      catchsql {
        INSERT INTO t1 VALUES(6, randomblob(1100));
      }
    } {1 {disk I/O error}}
    do_test multiplex-5.6.4.$jmode {
      db close
    } {}
  }
}

catch { sqlite3_multiplex_shutdown }
finish_test







|







 







|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>







 







|
>
>







 







|
|
|
|
|








|










32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
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
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
...
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
}

# This saves off the parameters and calls the 
# underlying sqlite3_multiplex_control() API.
proc multiplex_set {db name chunk_size max_chunks} {
  global g_chunk_size
  global g_max_chunks
  set g_chunk_size [ expr (($chunk_size+($::SQLITE_MAX_PAGE_SIZE-1)) & ~($::SQLITE_MAX_PAGE_SIZE-1)) ]
  set g_max_chunks $max_chunks
  set rc [catch {sqlite3_multiplex_control $db $name chunk_size $chunk_size} msg]
  if { $rc==0 } { 
    set rc [catch {sqlite3_multiplex_control $db $name max_chunks $max_chunks} msg]
  }
  list $msg
}
................................................................................
do_test multiplex-1.4 { sqlite3_multiplex_shutdown }               {SQLITE_OK}

do_test multiplex-1.5 { sqlite3_multiplex_initialize "" 0 }        {SQLITE_OK}
do_test multiplex-1.6 { sqlite3_multiplex_shutdown }               {SQLITE_OK}
do_test multiplex-1.7 { sqlite3_multiplex_initialize "" 1 }        {SQLITE_OK}
do_test multiplex-1.8 { sqlite3_multiplex_shutdown }               {SQLITE_OK}

do_test multiplex-1.9.1 { sqlite3_multiplex_initialize "" 1 }     {SQLITE_OK}
do_test multiplex-1.9.2 { sqlite3 db test.db }                    {}
do_test multiplex-1.9.3 { multiplex_set db main 32768 16 }        {SQLITE_OK}
do_test multiplex-1.9.4 { multiplex_set db main 32768 -1 }        {SQLITE_MISUSE}
do_test multiplex-1.9.5 { multiplex_set db main -1 16 }           {SQLITE_MISUSE}
do_test multiplex-1.9.6 { multiplex_set db main 31 16 }           {SQLITE_OK}
do_test multiplex-1.9.7 { multiplex_set db main 32768 100 }       {SQLITE_MISUSE}
do_test multiplex-1.9.8 { db close }                              {}
do_test multiplex-1.9.9 { sqlite3_multiplex_shutdown }            {SQLITE_OK}

do_test multiplex-1.10.1 { sqlite3_multiplex_initialize "" 1 }                {SQLITE_OK}
do_test multiplex-1.10.2 { sqlite3 db test.db }                               {}
if { 0 } {
do_test multiplex-1.10.3 { execsql { SELECT multiplex_control(2, 32768); } }  {SQLITE_OK}
do_test multiplex-1.10.4 { execsql { SELECT multiplex_control(3, -1); } }     {SQLITE_MISUSE}
do_test multiplex-1.10.5 { execsql { SELECT multiplex_control(2, -1); } }     {SQLITE_MISUSE}
do_test multiplex-1.10.6 { execsql { SELECT multiplex_control(2, 31); } }     {SQLITE_OK}
do_test multiplex-1.10.7 { execsql { SELECT multiplex_control(3, 100); } }    {SQLITE_MISUSE}
}
do_test multiplex-1.10.8 { db close }                                         {}
do_test multiplex-1.10.9 { sqlite3_multiplex_shutdown }                       {SQLITE_OK}

#-------------------------------------------------------------------------
# Some simple warm-body tests with a single database file in rollback 
# mode:
#
#   multiplex-2.1.*: Test simple writing to a multiplex file.
#
................................................................................

do_test multiplex-2.5.3 { 
  execsql { 
    INSERT INTO t1 VALUES(1, 'one');
    INSERT INTO t1 VALUES(2, randomblob(4000));
    INSERT INTO t1 VALUES(3, 'three');
    INSERT INTO t1 VALUES(4, randomblob(4000));
    INSERT INTO t1 VALUES(5, 'five');
    INSERT INTO t1 VALUES(6, randomblob($g_chunk_size));
    INSERT INTO t1 VALUES(7, randomblob($g_chunk_size));
  }
} {}

do_test multiplex-2.5.4 {
  db eval {SELECT * FROM t1 WHERE a=1}
} {1 one}

................................................................................
        PRAGMA auto_vacuum = off;
      }
      db eval "PRAGMA journal_mode = $jmode;"
    } $jmode
    do_test multiplex-5.6.2.$jmode {
      execsql {
        CREATE TABLE t1(a, b);
        INSERT INTO t1 VALUES(1, randomblob(15000));
        INSERT INTO t1 VALUES(2, randomblob(15000));
        INSERT INTO t1 VALUES(3, randomblob(15000));
        INSERT INTO t1 VALUES(4, randomblob(15000));
        INSERT INTO t1 VALUES(5, randomblob(15000));
      }
      db close
      sqlite3_multiplex_initialize "" 1
      sqlite3 db test.db
      multiplex_set db main 4096 16
    } {SQLITE_OK}
    do_test multiplex-5.6.3.$jmode {
      catchsql {
        INSERT INTO t1 VALUES(6, randomblob(15000));
      }
    } {1 {disk I/O error}}
    do_test multiplex-5.6.4.$jmode {
      db close
    } {}
  }
}

catch { sqlite3_multiplex_shutdown }
finish_test