/ Check-in [8ed944ba]
Login

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

Overview
Comment:Additional tests and commenting for the multiplex VFS.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8ed944ba74566c6241d655a39801ad192c61219a
User & Date: shaneh 2010-11-05 03:43:55
Context
2010-11-05
03:58
Additional error checking and tests for multiplex VFS. check-in: 1ab9a592 user: shaneh tags: trunk
03:43
Additional tests and commenting for the multiplex VFS. check-in: 8ed944ba user: shaneh tags: trunk
00:04
Update the configure script for version 3.7.4. check-in: 18a73795 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/test_multiplex.c.

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
...
180
181
182
183
184
185
186
187


188
189
190
191
192
193

194
195
196
197
198
199
200
...
247
248
249
250
251
252
253

254
255
256
257
258
259
260
...
280
281
282
283
284
285
286

287
288
289
290
291
292
293
...
326
327
328
329
330
331
332

333
334
335
336
337
338
339
340
341
342
343
344
345
...
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
...
399
400
401
402
403
404
405

406
407
408
409
410
411
412
  ** has to create a wrapper sqlite3_file of the same version.  Hence
  ** there are two I/O method structures, one for version 1 and the other
  ** for version 2.
  */
  sqlite3_io_methods sIoMethodsV1;
  sqlite3_io_methods sIoMethodsV2;

  /* True when this shim as been initialized.
  */
  int isInitialized;

  /* For run-time access any of the other global data structures in this
  ** shim, the following mutex must be held.
  */
  sqlite3_mutex *pMutex;

  /* List of multiplexGroup objects.
  */
  multiplexGroup *pGroups;

  /* Chunk params
  */
  int nChunkSize;
  int nMaxChunks;

} gMultiplex;

/************************* Utility Routines *********************************/
................................................................................
  }

  /* We need to create a group structure and manage
  ** access to this group of files.
  */
  multiplexEnter();
  pMultiplexOpen = (multiplexConn*)pConn;
  /* -0000\0 */


  pGroup = sqlite3_malloc( sizeof(multiplexGroup) + (pOrigVfs->szOsFile*gMultiplex.nMaxChunks) + nName + 6 );
  if( pGroup==0 ){
    rc=SQLITE_NOMEM;
  }else{
    pMultiplexOpen->pGroup = pGroup;
    memset(pGroup, 0, sizeof(multiplexGroup) + (pOrigVfs->szOsFile*gMultiplex.nMaxChunks) + nName + 6);

    for(i=0; i<gMultiplex.nMaxChunks; i++){
      pGroup->pReal[i] = (sqlite3_file *)((char *)&pGroup[1] + (pOrigVfs->szOsFile*i));
    }
    pGroup->zName = (char *)&pGroup[1] + (pOrigVfs->szOsFile*gMultiplex.nMaxChunks);
    memcpy(pGroup->zName, zName, nName+1);
    pGroup->nName = nName;
    pGroup->flags = flags;
................................................................................
  sqlite3_free(pGroup);
  multiplexLeave();
  return rc;
}

/* Pass xRead requests thru to the original VFS after
** determining the correct chunk to operate on.

*/
static int multiplexRead(
  sqlite3_file *pConn,
  void *pBuf,
  int iAmt,
  sqlite3_int64 iOfst
){
................................................................................
  }
  multiplexLeave();
  return rc;
}

/* Pass xWrite requests thru to the original VFS after
** determining the correct chunk to operate on.

*/
static int multiplexWrite(
  sqlite3_file *pConn,
  const void *pBuf,
  int iAmt,
  sqlite3_int64 iOfst
){
................................................................................
  int rc2;
  int i;
  sqlite3_file *pSubOpen;
  sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
  multiplexEnter();
  /* delete the chunks above the truncate limit */
  for(i=(int)(size/gMultiplex.nChunkSize)+1; i<gMultiplex.nMaxChunks; i++){

    if( pGroup->bOpen[i] ){
      pSubOpen = pGroup->pReal[i];
      rc2 = pSubOpen->pMethods->xClose(pSubOpen);
      if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE;
    }
    pGroup->zName[pGroup->nName] = '\0';
    if( i ) sqlite3_snprintf(pGroup->nName+6, pGroup->zName+pGroup->nName, "-%04d", i);
    rc2 = pOrigVfs->xDelete(pOrigVfs, pGroup->zName, 0);
    if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE;
  }
  pSubOpen = multiplexSubOpen(p, (int)(size/gMultiplex.nChunkSize), &rc2, NULL);
  if( pSubOpen ){
    rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size%gMultiplex.nChunkSize);
................................................................................
  int rc = SQLITE_OK;
  int rc2;
  int i;
  multiplexEnter();
  *pSize = 0;
  for(i=0; i<gMultiplex.nMaxChunks; i++){
    sqlite3_file *pSubOpen = NULL;
    sqlite3_int64 sz;
    /* if not opened already, check to see if the chunk exists */
    if( pGroup->bOpen[i] ){
      pSubOpen = pGroup->pReal[i];
    }else{
      sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
      int exists = 0;
      pGroup->zName[pGroup->nName] = '\0';
................................................................................
        pSubOpen = multiplexSubOpen(p, i, &rc, NULL);
      }else{
        /* stop at first "gap" */
        break;
      }
    }
    if( pSubOpen ){

      rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
      if( rc2!=SQLITE_OK ){
        rc = rc2;
      }else{
        *pSize += sz;
      }
    }else{







|












|







 







|
>
>






>







 







>







 







>







 







>





<







 







<







 







>







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
...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
...
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
...
331
332
333
334
335
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
...
385
386
387
388
389
390
391

392
393
394
395
396
397
398
...
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
  ** has to create a wrapper sqlite3_file of the same version.  Hence
  ** there are two I/O method structures, one for version 1 and the other
  ** for version 2.
  */
  sqlite3_io_methods sIoMethodsV1;
  sqlite3_io_methods sIoMethodsV2;

  /* True when this shim has been initialized.
  */
  int isInitialized;

  /* For run-time access any of the other global data structures in this
  ** shim, the following mutex must be held.
  */
  sqlite3_mutex *pMutex;

  /* List of multiplexGroup objects.
  */
  multiplexGroup *pGroups;

  /* Chunk params.
  */
  int nChunkSize;
  int nMaxChunks;

} gMultiplex;

/************************* Utility Routines *********************************/
................................................................................
  }

  /* We need to create a group structure and manage
  ** access to this group of files.
  */
  multiplexEnter();
  pMultiplexOpen = (multiplexConn*)pConn;
  /* allocate space for group, file handles, 
  ** and file name (+ extra for "-0000\0") 
  */
  pGroup = sqlite3_malloc( sizeof(multiplexGroup) + (pOrigVfs->szOsFile*gMultiplex.nMaxChunks) + nName + 6 );
  if( pGroup==0 ){
    rc=SQLITE_NOMEM;
  }else{
    pMultiplexOpen->pGroup = pGroup;
    memset(pGroup, 0, sizeof(multiplexGroup) + (pOrigVfs->szOsFile*gMultiplex.nMaxChunks) + nName + 6);
    /* assign pointers to extra space for file handles */
    for(i=0; i<gMultiplex.nMaxChunks; i++){
      pGroup->pReal[i] = (sqlite3_file *)((char *)&pGroup[1] + (pOrigVfs->szOsFile*i));
    }
    pGroup->zName = (char *)&pGroup[1] + (pOrigVfs->szOsFile*gMultiplex.nMaxChunks);
    memcpy(pGroup->zName, zName, nName+1);
    pGroup->nName = nName;
    pGroup->flags = flags;
................................................................................
  sqlite3_free(pGroup);
  multiplexLeave();
  return rc;
}

/* Pass xRead requests thru to the original VFS after
** determining the correct chunk to operate on.
** Break up reads across chunk boundaries.
*/
static int multiplexRead(
  sqlite3_file *pConn,
  void *pBuf,
  int iAmt,
  sqlite3_int64 iOfst
){
................................................................................
  }
  multiplexLeave();
  return rc;
}

/* Pass xWrite requests thru to the original VFS after
** determining the correct chunk to operate on.
** Break up writes across chunk boundaries.
*/
static int multiplexWrite(
  sqlite3_file *pConn,
  const void *pBuf,
  int iAmt,
  sqlite3_int64 iOfst
){
................................................................................
  int rc2;
  int i;
  sqlite3_file *pSubOpen;
  sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
  multiplexEnter();
  /* delete the chunks above the truncate limit */
  for(i=(int)(size/gMultiplex.nChunkSize)+1; i<gMultiplex.nMaxChunks; i++){
    /* close any open chunks before deleting them */
    if( pGroup->bOpen[i] ){
      pSubOpen = pGroup->pReal[i];
      rc2 = pSubOpen->pMethods->xClose(pSubOpen);
      if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE;
    }

    if( i ) sqlite3_snprintf(pGroup->nName+6, pGroup->zName+pGroup->nName, "-%04d", i);
    rc2 = pOrigVfs->xDelete(pOrigVfs, pGroup->zName, 0);
    if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE;
  }
  pSubOpen = multiplexSubOpen(p, (int)(size/gMultiplex.nChunkSize), &rc2, NULL);
  if( pSubOpen ){
    rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size%gMultiplex.nChunkSize);
................................................................................
  int rc = SQLITE_OK;
  int rc2;
  int i;
  multiplexEnter();
  *pSize = 0;
  for(i=0; i<gMultiplex.nMaxChunks; i++){
    sqlite3_file *pSubOpen = NULL;

    /* if not opened already, check to see if the chunk exists */
    if( pGroup->bOpen[i] ){
      pSubOpen = pGroup->pReal[i];
    }else{
      sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
      int exists = 0;
      pGroup->zName[pGroup->nName] = '\0';
................................................................................
        pSubOpen = multiplexSubOpen(p, i, &rc, NULL);
      }else{
        /* stop at first "gap" */
        break;
      }
    }
    if( pSubOpen ){
      sqlite3_int64 sz;
      rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
      if( rc2!=SQLITE_OK ){
        rc = rc2;
      }else{
        *pSize += sz;
      }
    }else{

Changes to test/multiplex.test.

21
22
23
24
25
26
27



28
29
30
31
32
33
34
..
48
49
50
51
52
53
54

55
56
57
58
59
60
61
..
88
89
90
91
92
93
94




















































95
96
97
98
99
100
101
  for {set i 1} {$i<=15} {incr i} {
    file delete -force $name-000$i
    file delete -force $name-00$i
  }
}

db close




do_test multiplex-1.1 { sqlite3_multiplex_initialize nosuchvfs 1 } {SQLITE_ERROR}
do_test multiplex-1.2 { sqlite3_multiplex_initialize "" 1 }        {SQLITE_OK}
do_test multiplex-1.3 { sqlite3_multiplex_initialize "" 1 }        {SQLITE_MISUSE}
do_test multiplex-1.4 { sqlite3_multiplex_shutdown }               {SQLITE_OK}

do_test multiplex-1.5 { sqlite3_multiplex_initialize "" 0 }        {SQLITE_OK}
................................................................................
#   multiplex-2.3.*: Open and close a second db.
#
#   multiplex-2.4.*: Try to shutdown the multiplex system before closing the db
#                file. Check that this fails and the multiplex system still works
#                afterwards. Then close the database and successfully shut
#                down the multiplex system.
#


sqlite3_multiplex_initialize "" 1
sqlite3_multiplex_set 0x8000 16

do_test multiplex-2.1.2 {
  sqlite3 db test.db
  execsql {
................................................................................
  sqlite3_multiplex_shutdown
} {SQLITE_MISUSE}
do_test multiplex-2.4.2 {
  execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
} {}
do_test multiplex-2.4.4 { file size test.db } {7168}
do_test multiplex-2.4.99 {




















































  db close
  sqlite3_multiplex_shutdown
} {SQLITE_OK}

#-------------------------------------------------------------------------
# Try some tests with more than one connection to a database file. Still
# in rollback mode.







>
>
>







 







>







 







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







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
..
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
  for {set i 1} {$i<=15} {incr i} {
    file delete -force $name-000$i
    file delete -force $name-00$i
  }
}

db close

#-------------------------------------------------------------------------
#   multiplex-1.1.*: Test initialize and shutdown.

do_test multiplex-1.1 { sqlite3_multiplex_initialize nosuchvfs 1 } {SQLITE_ERROR}
do_test multiplex-1.2 { sqlite3_multiplex_initialize "" 1 }        {SQLITE_OK}
do_test multiplex-1.3 { sqlite3_multiplex_initialize "" 1 }        {SQLITE_MISUSE}
do_test multiplex-1.4 { sqlite3_multiplex_shutdown }               {SQLITE_OK}

do_test multiplex-1.5 { sqlite3_multiplex_initialize "" 0 }        {SQLITE_OK}
................................................................................
#   multiplex-2.3.*: Open and close a second db.
#
#   multiplex-2.4.*: Try to shutdown the multiplex system before closing the db
#                file. Check that this fails and the multiplex system still works
#                afterwards. Then close the database and successfully shut
#                down the multiplex system.
#
#   multiplex-2.5.*: More reading/writing with small chunk size.

sqlite3_multiplex_initialize "" 1
sqlite3_multiplex_set 0x8000 16

do_test multiplex-2.1.2 {
  sqlite3 db test.db
  execsql {
................................................................................
  sqlite3_multiplex_shutdown
} {SQLITE_MISUSE}
do_test multiplex-2.4.2 {
  execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
} {}
do_test multiplex-2.4.4 { file size test.db } {7168}
do_test multiplex-2.4.99 {
  db close
  sqlite3_multiplex_shutdown
} {SQLITE_OK}


do_test multiplex-2.5.1 {
  multiplex_delete test.db
  sqlite3_multiplex_initialize "" 1
  sqlite3_multiplex_set 0x1000 16
} {SQLITE_OK}

do_test multiplex-2.5.2 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size = 1024;
    PRAGMA journal_mode = delete;
    PRAGMA auto_vacuum = off;
    CREATE TABLE t1(a PRIMARY KEY, b);
  }
} {delete}

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}

do_test multiplex-2.5.5 {
  db eval {SELECT * FROM t1 WHERE a=3}
} {3 three}

do_test multiplex-2.5.6 {
  db eval {SELECT * FROM t1 WHERE a=5}
} {5 five}

do_test multiplex-2.5.7 {
  db eval {SELECT a,length(b) FROM t1 WHERE a=2}
} {2 4000}

do_test multiplex-2.5.8 {
  db eval {SELECT a,length(b) FROM t1 WHERE a=4}
} {4 4000}

do_test multiplex-2.5.99 {
  db close
  sqlite3_multiplex_shutdown
} {SQLITE_OK}

#-------------------------------------------------------------------------
# Try some tests with more than one connection to a database file. Still
# in rollback mode.