SQLite

Check-in [8ed944ba74]
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
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8ed944ba74566c6241d655a39801ad192c61219a
User & Date: shaneh 2010-11-05 03:43:55.000
Context
2010-11-05
03:58
Additional error checking and tests for multiplex VFS. (check-in: 1ab9a59237 user: shaneh tags: trunk)
03:43
Additional tests and commenting for the multiplex VFS. (check-in: 8ed944ba74 user: shaneh tags: trunk)
00:04
Update the configure script for version 3.7.4. (check-in: 18a73795b4 user: drh tags: trunk)
Changes
Unified Diff 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
  ** 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 *********************************/







|












|







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
  ** 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 *********************************/
180
181
182
183
184
185
186

187

188
189
190
191
192
193

194
195
196
197
198
199
200
  }

  /* 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;







>
|
>






>







180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
  }

  /* 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;
247
248
249
250
251
252
253

254
255
256
257
258
259
260
  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
){







>







250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  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
){
280
281
282
283
284
285
286

287
288
289
290
291
292
293
  }
  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
){







>







284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
  }
  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
){
326
327
328
329
330
331
332

333
334
335
336
337
338
339
340
341
342
343
344
345
  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);







>





<







331
332
333
334
335
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
  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);
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
  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';
      if( i ) sqlite3_snprintf(pGroup->nName+6, pGroup->zName+pGroup->nName, "-%04d", i);
      rc2 = pOrigVfs->xAccess(pOrigVfs, pGroup->zName, SQLITE_ACCESS_EXISTS, &exists);
      if( rc2==SQLITE_OK && exists){
        /* if it exists, open it */
        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{







<


















>







385
386
387
388
389
390
391

392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
  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';
      if( i ) sqlite3_snprintf(pGroup->nName+6, pGroup->zName+pGroup->nName, "-%04d", i);
      rc2 = pOrigVfs->xAccess(pOrigVfs, pGroup->zName, SQLITE_ACCESS_EXISTS, &exists);
      if( rc2==SQLITE_OK && exists){
        /* if it exists, open it */
        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
  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}







>
>
>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  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}
48
49
50
51
52
53
54

55
56
57
58
59
60
61
#   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 {







>







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#   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 {
88
89
90
91
92
93
94




















































95
96
97
98
99
100
101
  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.







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







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
  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.