/ Check-in [3e9680c4]
Login

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

Overview
Comment:Add test case for SQLITE_FULL errors to pagerfault.test. Remove a NEVER macro in pager.c that this hits.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3e9680c4c18140d083b24e05a21ea6792aef2487
User & Date: dan 2010-06-23 19:27:36
Context
2010-06-23
22:00
Fix and/or improve comments in wal.c. No code changes. check-in: ee9991be user: drh tags: trunk
19:27
Add test case for SQLITE_FULL errors to pagerfault.test. Remove a NEVER macro in pager.c that this hits. check-in: 3e9680c4 user: dan tags: trunk
17:59
Include the SOURCE_ID value in the log messages output for corruption, misuse, and CANTOPEN errors. check-in: 1727a81f user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pager.c.

1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
....
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
....
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
** This function should be called when an IOERR, CORRUPT or FULL error
** may have occurred. The first argument is a pointer to the pager 
** structure, the second the error-code about to be returned by a pager 
** API function. The value returned is a copy of the second argument 
** to this function. 
**
** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT, or SQLITE_FULL
** the error becomes persistent. Until the persisten error is cleared,
** subsequent API calls on this Pager will immediately return the same 
** error code.
**
** A persistent error indicates that the contents of the pager-cache 
** cannot be trusted. This state can be cleared by completely discarding 
** the contents of the pager-cache. If a transaction was active when
** the persistent error occurred, then the rollback journal may need
................................................................................
    ** flag is set, return without doing anything. The pcache layer will
    ** just have to go ahead and allocate a new page buffer instead of
    ** reusing pPg.
    **
    ** Similarly, if the pager has already entered the error state, do not
    ** try to write the contents of pPg to disk.
    */
    if( NEVER(pPager->errCode)
     || (pPager->doNotSync && pPg->flags&PGHDR_NEED_SYNC)
    ){
      return SQLITE_OK;
    }
  
    /* Sync the journal file if required. */
    if( pPg->flags&PGHDR_NEED_SYNC ){
      rc = syncJournal(pPager);
      if( rc==SQLITE_OK && pPager->fullSync && 
................................................................................
**
** * If in an error state other than SQLITE_FULL, then task (1) is 
**   performed. If successful, task (2). Regardless of the outcome
**   of either, the error state error code is returned to the caller
**   (i.e. either SQLITE_IOERR or SQLITE_CORRUPT).
**
** * If the pager is in PAGER_RESERVED state, then attempt (1). Whether
**   or not (1) is succussful, also attempt (2). If successful, return
**   SQLITE_OK. Otherwise, enter the error state and return the first 
**   error code encountered. 
**
**   In this case there is no chance that the database was written to. 
**   So is safe to finalize the journal file even if the playback 
**   (operation 1) failed. However the pager must enter the error state
**   as the contents of the in-memory cache are now suspect.







|







 







<
|
<







 







|







1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
....
3533
3534
3535
3536
3537
3538
3539

3540

3541
3542
3543
3544
3545
3546
3547
....
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
** This function should be called when an IOERR, CORRUPT or FULL error
** may have occurred. The first argument is a pointer to the pager 
** structure, the second the error-code about to be returned by a pager 
** API function. The value returned is a copy of the second argument 
** to this function. 
**
** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT, or SQLITE_FULL
** the error becomes persistent. Until the persistent error is cleared,
** subsequent API calls on this Pager will immediately return the same 
** error code.
**
** A persistent error indicates that the contents of the pager-cache 
** cannot be trusted. This state can be cleared by completely discarding 
** the contents of the pager-cache. If a transaction was active when
** the persistent error occurred, then the rollback journal may need
................................................................................
    ** flag is set, return without doing anything. The pcache layer will
    ** just have to go ahead and allocate a new page buffer instead of
    ** reusing pPg.
    **
    ** Similarly, if the pager has already entered the error state, do not
    ** try to write the contents of pPg to disk.
    */

    if( pPager->errCode || (pPager->doNotSync && pPg->flags&PGHDR_NEED_SYNC) ){

      return SQLITE_OK;
    }
  
    /* Sync the journal file if required. */
    if( pPg->flags&PGHDR_NEED_SYNC ){
      rc = syncJournal(pPager);
      if( rc==SQLITE_OK && pPager->fullSync && 
................................................................................
**
** * If in an error state other than SQLITE_FULL, then task (1) is 
**   performed. If successful, task (2). Regardless of the outcome
**   of either, the error state error code is returned to the caller
**   (i.e. either SQLITE_IOERR or SQLITE_CORRUPT).
**
** * If the pager is in PAGER_RESERVED state, then attempt (1). Whether
**   or not (1) is successful, also attempt (2). If successful, return
**   SQLITE_OK. Otherwise, enter the error state and return the first 
**   error code encountered. 
**
**   In this case there is no chance that the database was written to. 
**   So is safe to finalize the journal file even if the playback 
**   (operation 1) failed. However the pager must enter the error state
**   as the contents of the in-memory cache are now suspect.

Changes to src/test_vfs.c.

327
328
329
330
331
332
333
334





335
336
337
338
339
340
341
  if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){
    tvfsExecTcl(p, "xWrite", 
        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
    );
    tvfsResultCode(p, &rc);
  }

  if( rc==SQLITE_OK && tvfsInjectFullerr(p) ) rc = SQLITE_FULL;





  
  if( rc==SQLITE_OK ){
    rc = sqlite3OsWrite(pFd->pReal, zBuf, iAmt, iOfst);
  }
  return rc;
}








|
>
>
>
>
>







327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
  if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){
    tvfsExecTcl(p, "xWrite", 
        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
    );
    tvfsResultCode(p, &rc);
  }

  if( rc==SQLITE_OK && tvfsInjectFullerr(p) ){
    rc = SQLITE_FULL;
  }
  if( rc==SQLITE_OK && p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
    rc = SQLITE_IOERR;
  }
  
  if( rc==SQLITE_OK ){
    rc = sqlite3OsWrite(pFd->pReal, zBuf, iAmt, iOfst);
  }
  return rc;
}

Changes to test/malloc_common.tcl.

189
190
191
192
193
194
195

196
197
198
199
200
201
202
...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230


# The following procs are used as [do_one_faultsim_test] callbacks when 
# injecting shared-memory related error faults into test cases.
#
proc shmerr_injectinstall {} {
  testvfs shmfault -default true

}
proc shmerr_injectuninstall {} {
  catch {db  close}
  catch {db2 close}
  shmfault delete
}
proc shmerr_injectstart {persist iFail} {
................................................................................
}
proc fullerr_injectstart {iFail} {
  shmfault full $iFail
}
proc fullerr_injectstop {} {
  shmfault full 0
}


# This command is not called directly. It is used by the 
# [faultsim_test_result] command created by [do_faultsim_test] and used
# by -test scripts.
#
proc faultsim_test_result_int {args} {
  upvar testrc testrc testresult testresult testnfail testnfail







>







 







<







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
...
217
218
219
220
221
222
223

224
225
226
227
228
229
230


# The following procs are used as [do_one_faultsim_test] callbacks when 
# injecting shared-memory related error faults into test cases.
#
proc shmerr_injectinstall {} {
  testvfs shmfault -default true
  shmfault filter {xShmOpen xShmMap xShmLock}
}
proc shmerr_injectuninstall {} {
  catch {db  close}
  catch {db2 close}
  shmfault delete
}
proc shmerr_injectstart {persist iFail} {
................................................................................
}
proc fullerr_injectstart {iFail} {
  shmfault full $iFail
}
proc fullerr_injectstop {} {
  shmfault full 0
}


# This command is not called directly. It is used by the 
# [faultsim_test_result] command created by [do_faultsim_test] and used
# by -test scripts.
#
proc faultsim_test_result_int {args} {
  upvar testrc testrc testresult testresult testnfail testnfail

Changes to test/pagerfault.test.

302
303
304
305
306
307
308
309


































310
#     COMMIT;
#     SELECT DISTINCT x FROM t1;
#   }
# } -test {
#   faultsim_test_result {0 {5 6 7 8}}
#   faultsim_integrity_check
# }



































finish_test







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

302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
#     COMMIT;
#     SELECT DISTINCT x FROM t1;
#   }
# } -test {
#   faultsim_test_result {0 {5 6 7 8}}
#   faultsim_integrity_check
# }
#
do_test pagerfault-7-pre1 {
  faultsim_delete_and_reopen
  execsql {
    CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
    BEGIN;
      INSERT INTO t2 VALUES(NULL, randomblob(1500));
      INSERT INTO t2 VALUES(NULL, randomblob(1500));
      INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2;    --  4
      INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2;    --  8
      INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2;    -- 16
      INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2;    -- 32
      INSERT INTO t2 SELECT NULL, randomblob(1500) FROM t2;    -- 64
    COMMIT;
    CREATE TABLE t1(a PRIMARY KEY, b);
    INSERT INTO t1 SELECT * FROM t2;
    DROP TABLE t2;
  }
  faultsim_save_and_close
} {}
do_faultsim_test pagerfault-7 -faults full -prep {
  faultsim_restore_and_reopen
  execsql { 
    PRAGMA cache_size = 10;
    BEGIN;
      UPDATE t1 SET b = randomblob(1500);
  }
} -body {
  execsql { UPDATE t1 SET a = 65, b = randomblob(1500) WHERE (a+1)>200 }
  execsql COMMIT
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}

finish_test