/ Check-in [16decc13]
Login

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

Overview
Comment:Fix test case failures on this branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wal2
Files: files | file ages | folders
SHA3-256: 16decc13af908087fb8aa34eeccf43e8da1b8f2e4b808028986d1ef08134c72c
User & Date: dan 2017-10-05 18:14:46
Wiki:wal2
Context
2017-10-06
13:43
Fix frame overwriting in wal2 mode. check-in: a4b02bc9 user: dan tags: wal2
2017-10-05
18:14
Fix test case failures on this branch. check-in: 16decc13 user: dan tags: wal2
2017-10-04
20:57
Add experimental mode that uses two wal files. Activated using "PRAGMA journal_mode = wal2". check-in: e2fc5c81 user: dan tags: wal2
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/wal.c.

1503
1504
1505
1506
1507
1508
1509

1510
1511
1512
1513
1514






1515
1516
1517
1518
1519
1520
1521
....
2160
2161
2162
2163
2164
2165
2166
2167

2168
2169
2170
2171
2172
2173

2174
2175
2176
2177
2178
2179
2180
....
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
....
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
    }

    /* If more than one frame was recovered from the log file, report an
    ** event via sqlite3_log(). This is to help with identifying performance
    ** problems caused by applications routinely shutting down without
    ** checkpointing the log file.  */
    if( pWal->hdr.nPage ){

      sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
          "recovered (%d,%d) frames from WAL files %s[2] (%s mode)",
          walidxGetMxFrame(&pWal->hdr, 0), walidxGetMxFrame(&pWal->hdr, 1), 
          pWal->zWalName, isWalMode2(pWal) ? "wal2" : "wal"
      );






    }
  }

  WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
  walUnlockExclusive(pWal, iLock, nLock);
  return rc;
}
................................................................................
        testcase( IS_BIG_INT(iOffset) );
        rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
        if( rc!=SQLITE_OK ) break;
      }

      /* Truncate the db file, sync the wal file and set the WalCkptInfo
      ** flag to indicate that it has been checkpointed. */
      if( !bWal2 && rc==SQLITE_OK && mxSafeFrame==walIndexHdr(pWal)->mxFrame ){

        i64 szDb = pWal->hdr.nPage*(i64)szPage;
        testcase( IS_BIG_INT(szDb) );
        rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
      }
      if( rc==SQLITE_OK ){
        rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));

      }
      if( rc==SQLITE_OK ){
        pInfo->nBackfill = bWal2 ? 1 : mxSafeFrame;
      }

      /* Release the reader lock held while backfilling */
      walUnlockExclusive(pWal, WAL_READ_LOCK(bWal2 ? 1 + iCkpt*2 : 0), 1);
................................................................................
  ** upgrade to exclusive-mode following such an error.
  */
  assert( pWal->readLock!=WAL_LOCK_NONE || pWal->lockError );
  assert( pWal->readLock!=WAL_LOCK_NONE || (op<=0 && pWal->exclusiveMode==0) );

  if( op==0 ){
    if( pWal->exclusiveMode ){
      pWal->exclusiveMode = 0;
      if( isWalMode2(pWal) ){
        rc = walLockReader(pWal, pWal->readLock, 1);
      }else{
        rc = walLockShared(pWal, WAL_READ_LOCK(pWal->readLock));
      }
      if( rc==SQLITE_OK ){
        pWal->exclusiveMode = 1;
      }
      rc = pWal->exclusiveMode==0;
    }else{
      /* Already in locking_mode=NORMAL */
      rc = 0;
    }
  }else if( op>0 ){
................................................................................
    assert( pWal->exclusiveMode==0 );
    assert( pWal->readLock>=0 );
    if( isWalMode2(pWal) ){
      walLockReader(pWal, pWal->readLock, 0);
    }else{
      walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
    }
    pWal->exclusiveMode = 1;
    rc = 1;
  }else{
    rc = pWal->exclusiveMode==0;
  }
  return rc;
}








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







 







|
>
|
|
|
|
|
|
>







 







|





|
|







 







|







1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
....
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
....
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
....
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
    }

    /* If more than one frame was recovered from the log file, report an
    ** event via sqlite3_log(). This is to help with identifying performance
    ** problems caused by applications routinely shutting down without
    ** checkpointing the log file.  */
    if( pWal->hdr.nPage ){
      if( isWalMode2(pWal) ){
        sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
            "recovered (%d,%d) frames from WAL files %s[2] (%s mode)",
            walidxGetMxFrame(&pWal->hdr, 0), walidxGetMxFrame(&pWal->hdr, 1), 
            pWal->zWalName, isWalMode2(pWal) ? "wal2" : "wal"
        );
      }else{
        sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
            "recovered %d frames from WAL file %s",
            pWal->hdr.mxFrame, pWal->zWalName
        );
      }
    }
  }

  WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
  walUnlockExclusive(pWal, iLock, nLock);
  return rc;
}
................................................................................
        testcase( IS_BIG_INT(iOffset) );
        rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
        if( rc!=SQLITE_OK ) break;
      }

      /* Truncate the db file, sync the wal file and set the WalCkptInfo
      ** flag to indicate that it has been checkpointed. */
      if( rc==SQLITE_OK && (bWal2 || mxSafeFrame==walIndexHdr(pWal)->mxFrame) ){
        if( !bWal2 ){
          i64 szDb = pWal->hdr.nPage*(i64)szPage;
          testcase( IS_BIG_INT(szDb) );
          rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
        }
        if( rc==SQLITE_OK ){
          rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
        }
      }
      if( rc==SQLITE_OK ){
        pInfo->nBackfill = bWal2 ? 1 : mxSafeFrame;
      }

      /* Release the reader lock held while backfilling */
      walUnlockExclusive(pWal, WAL_READ_LOCK(bWal2 ? 1 + iCkpt*2 : 0), 1);
................................................................................
  ** upgrade to exclusive-mode following such an error.
  */
  assert( pWal->readLock!=WAL_LOCK_NONE || pWal->lockError );
  assert( pWal->readLock!=WAL_LOCK_NONE || (op<=0 && pWal->exclusiveMode==0) );

  if( op==0 ){
    if( pWal->exclusiveMode ){
      pWal->exclusiveMode = WAL_NORMAL_MODE;
      if( isWalMode2(pWal) ){
        rc = walLockReader(pWal, pWal->readLock, 1);
      }else{
        rc = walLockShared(pWal, WAL_READ_LOCK(pWal->readLock));
      }
      if( rc!=SQLITE_OK ){
        pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
      }
      rc = pWal->exclusiveMode==0;
    }else{
      /* Already in locking_mode=NORMAL */
      rc = 0;
    }
  }else if( op>0 ){
................................................................................
    assert( pWal->exclusiveMode==0 );
    assert( pWal->readLock>=0 );
    if( isWalMode2(pWal) ){
      walLockReader(pWal, pWal->readLock, 0);
    }else{
      walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
    }
    pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
    rc = 1;
  }else{
    rc = pWal->exclusiveMode==0;
  }
  return rc;
}

Changes to test/corruptA.test.

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# Corrupt the file header in various ways and make sure the corruption
# is detected when opening the database file.
#
db close
forcecopy test.db test.db-template

set unreadable_version 02
ifcapable wal { set unreadable_version 03 }
do_test corruptA-2.1 {
  forcecopy test.db-template test.db
  hexio_write test.db 19 $unreadable_version   ;# the read format number
  sqlite3 db test.db
  catchsql {SELECT * FROM t1}  
} {1 {file is not a database}}
 







|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# Corrupt the file header in various ways and make sure the corruption
# is detected when opening the database file.
#
db close
forcecopy test.db test.db-template

set unreadable_version 02
ifcapable wal { set unreadable_version 04 }
do_test corruptA-2.1 {
  forcecopy test.db-template test.db
  hexio_write test.db 19 $unreadable_version   ;# the read format number
  sqlite3 db test.db
  catchsql {SELECT * FROM t1}  
} {1 {file is not a database}}
 

Changes to test/rdonly.test.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# returns 1 if the database N of connection D is read-only, 0 if it is
# read/write, or -1 if N is not the name of a database on connection D.
#
do_test rdonly-1.1.1 {
  sqlite3_db_readonly db main
} {0}

# Changes the write version from 1 to 3.  Verify that the database
# can be read but not written.
#
do_test rdonly-1.2 {
  db close
  hexio_get_int [hexio_read test.db 18 1]
} 1
do_test rdonly-1.3 {
  hexio_write test.db 18 03
  sqlite3 db test.db
  execsql {
    SELECT * FROM t1;
  }
} {1}
do_test rdonly-1.3.1 {
  sqlite3_db_readonly db main
................................................................................

# Now, after connection [db] has loaded the database schema, modify the
# write-version of the file (and the change-counter, so that the 
# write-version is reloaded). This way, SQLite does not discover that
# the database is read-only until after it is locked.
#
set ro_version 02
ifcapable wal { set ro_version 03 }
do_test rdonly-1.6 {
  hexio_write test.db 18 $ro_version     ; # write-version
  hexio_write test.db 24 11223344        ; # change-counter
  catchsql {
    INSERT INTO t1 VALUES(2);
  }
} {1 {attempt to write a readonly database}}

finish_test







|







|







 







|









37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# returns 1 if the database N of connection D is read-only, 0 if it is
# read/write, or -1 if N is not the name of a database on connection D.
#
do_test rdonly-1.1.1 {
  sqlite3_db_readonly db main
} {0}

# Changes the write version from 1 to 4.  Verify that the database
# can be read but not written.
#
do_test rdonly-1.2 {
  db close
  hexio_get_int [hexio_read test.db 18 1]
} 1
do_test rdonly-1.3 {
  hexio_write test.db 18 04
  sqlite3 db test.db
  execsql {
    SELECT * FROM t1;
  }
} {1}
do_test rdonly-1.3.1 {
  sqlite3_db_readonly db main
................................................................................

# Now, after connection [db] has loaded the database schema, modify the
# write-version of the file (and the change-counter, so that the 
# write-version is reloaded). This way, SQLite does not discover that
# the database is read-only until after it is locked.
#
set ro_version 02
ifcapable wal { set ro_version 04 }
do_test rdonly-1.6 {
  hexio_write test.db 18 $ro_version     ; # write-version
  hexio_write test.db 24 11223344        ; # change-counter
  catchsql {
    INSERT INTO t1 VALUES(2);
  }
} {1 {attempt to write a readonly database}}

finish_test

Changes to test/uri.test.

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
      CREATE TABLE aux.t2(a, b);
      PRAGMA main.journal_mode = WAL;
      PRAGMA aux.journal_mode = WAL;
      INSERT INTO t1 VALUES('x', 'y');
      INSERT INTO t2 VALUES('x', 'y');
    }
    lsort [array names ::T1]
  } {test.db1 test.db1-journal test.db1-wal}
  
  do_test 5.1.2 {
    lsort [array names ::T2]
  } {test.db2 test.db2-journal test.db2-wal}
  db close
  
  tvfs1 delete
  tvfs2 delete
}

#-------------------------------------------------------------------------







|



|







276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
      CREATE TABLE aux.t2(a, b);
      PRAGMA main.journal_mode = WAL;
      PRAGMA aux.journal_mode = WAL;
      INSERT INTO t1 VALUES('x', 'y');
      INSERT INTO t2 VALUES('x', 'y');
    }
    lsort [array names ::T1]
  } {test.db1 test.db1-journal test.db1-wal test.db1-wal2}
  
  do_test 5.1.2 {
    lsort [array names ::T2]
  } {test.db2 test.db2-journal test.db2-wal test.db2-wal2}
  db close
  
  tvfs1 delete
  tvfs2 delete
}

#-------------------------------------------------------------------------