/ Check-in [ea8507a7]
Login

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

Overview
Comment:Fix the pager so that it handles persistent I/O errors correctly. Update the testing infrastructure so that it tests for persistent I/O errors instead of just transient errors. (CVS 3690)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ea8507a796c65041f7e720edea89f919fca1a028
User & Date: drh 2007-03-15 12:51:16
Context
2007-03-15
15:33
Check for multiple calls to sqlite3FailedMalloc(). Ignore the second and subsequent calls. (CVS 3691) check-in: 71808745 user: danielk1977 tags: trunk
12:51
Fix the pager so that it handles persistent I/O errors correctly. Update the testing infrastructure so that it tests for persistent I/O errors instead of just transient errors. (CVS 3690) check-in: ea8507a7 user: drh tags: trunk
12:17
Infrastructure to make simulated I/O errors persistent instead of transient. (CVS 3689) check-in: 1a53f531 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_common.h.

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
#ifdef SQLITE_TEST
int sqlite3_io_error_hit = 0;
int sqlite3_io_error_pending = 0;
int sqlite3_io_error_persist = 0;
int sqlite3_diskfull_pending = 0;
int sqlite3_diskfull = 0;
#define SimulateIOError(CODE)  \
   if( sqlite3_io_error_pending ) \
     if( sqlite3_io_error_pending-- == 1 \
         || (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \
                { local_ioerr(); CODE; }
static void local_ioerr(){
  sqlite3_io_error_hit = 1;
}
#define SimulateDiskfullError(CODE) \
   if( sqlite3_diskfull_pending ){ \
     if( sqlite3_diskfull_pending == 1 ){ \
       local_ioerr(); \
       sqlite3_diskfull = 1; \

       CODE; \
     }else{ \
       sqlite3_diskfull_pending--; \
     } \
   }
#else
#define SimulateIOError(A)







|











>







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
#ifdef SQLITE_TEST
int sqlite3_io_error_hit = 0;
int sqlite3_io_error_pending = 0;
int sqlite3_io_error_persist = 0;
int sqlite3_diskfull_pending = 0;
int sqlite3_diskfull = 0;
#define SimulateIOError(CODE)  \
  if( sqlite3_io_error_pending || sqlite3_io_error_hit ) \
     if( sqlite3_io_error_pending-- == 1 \
         || (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \
                { local_ioerr(); CODE; }
static void local_ioerr(){
  sqlite3_io_error_hit = 1;
}
#define SimulateDiskfullError(CODE) \
   if( sqlite3_diskfull_pending ){ \
     if( sqlite3_diskfull_pending == 1 ){ \
       local_ioerr(); \
       sqlite3_diskfull = 1; \
       sqlite3_io_error_hit = 1; \
       CODE; \
     }else{ \
       sqlite3_diskfull_pending--; \
     } \
   }
#else
#define SimulateIOError(A)

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
....
1856
1857
1858
1859
1860
1861
1862



1863
1864
1865
1866
1867
1868
1869
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.287 2007/03/15 01:16:48 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>
................................................................................
** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the
** file is 4096 bytes, 5 is returned instead of 4.
*/
int sqlite3pager_pagecount(Pager *pPager){
  i64 n;
  int rc;
  assert( pPager!=0 );



  if( pPager->dbSize>=0 ){
    n = pPager->dbSize;
  } else {
    if( (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){
      pager_error(pPager, rc);
      return 0;
    }







|







 







>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
....
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.288 2007/03/15 12:51:16 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>
................................................................................
** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the
** file is 4096 bytes, 5 is returned instead of 4.
*/
int sqlite3pager_pagecount(Pager *pPager){
  i64 n;
  int rc;
  assert( pPager!=0 );
  if( pPager->errCode ){
    return 0;
  }
  if( pPager->dbSize>=0 ){
    n = pPager->dbSize;
  } else {
    if( (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){
      pager_error(pPager, rc);
      return 0;
    }

Changes to test/diskfull.test.

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



20
21
22
23
24
25
26
..
43
44
45
46
47
48
49

50
51
52
53
54
55
56
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing for correct handling of disk full
# errors.
# 
# $Id: diskfull.test,v 1.3 2005/09/09 10:46:19 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl




do_test diskfull-1.1 {
  execsql {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(randstr(1000,1000));
    INSERT INTO t1 SELECT * FROM t1;
    INSERT INTO t1 SELECT * FROM t1;
    INSERT INTO t1 SELECT * FROM t1;
................................................................................
do_test diskfull-1.5 {
  set sqlite_diskfull_pending 1
  catchsql {
    DELETE FROM t1;
  }
} {1 {database or disk is full}}
set sqlite_diskfull_pending 0

integrity_check diskfull-1.6

set go 1
set i 0
while {$go} {
  incr i
  do_test diskfull-2.$i.1 {







|




>
>
>







 







>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
..
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing for correct handling of disk full
# errors.
# 
# $Id: diskfull.test,v 1.4 2007/03/15 12:51:17 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set sqlite_io_error_persist 0
set sqlite_io_error_hit 0
set sqlite_io_error_pending 0
do_test diskfull-1.1 {
  execsql {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(randstr(1000,1000));
    INSERT INTO t1 SELECT * FROM t1;
    INSERT INTO t1 SELECT * FROM t1;
    INSERT INTO t1 SELECT * FROM t1;
................................................................................
do_test diskfull-1.5 {
  set sqlite_diskfull_pending 1
  catchsql {
    DELETE FROM t1;
  }
} {1 {database or disk is full}}
set sqlite_diskfull_pending 0
set sqlite_io_error_hit 0
integrity_check diskfull-1.6

set go 1
set i 0
while {$go} {
  incr i
  do_test diskfull-2.$i.1 {