/ Check-in [f664f940]
Login

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

Overview
Comment:Increase coverage provided by permutation "coverage-wal" on this branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | begin-concurrent-wal2
Files: files | file ages | folders
SHA3-256: f664f940a7eb6938b1ee171143a691e2f497aec921f979be63ef844d38053f56
User & Date: dan 2018-12-29 16:34:22
Wiki:begin-concurrent-wal2
Context
2018-12-29
20:47
Merge latest begin-concurrent changes with this branch. check-in: 1625887c user: dan tags: begin-concurrent-wal2
16:34
Increase coverage provided by permutation "coverage-wal" on this branch. check-in: f664f940 user: dan tags: begin-concurrent-wal2
2018-12-27
17:11
Merge latest wal2 changes with this branch. check-in: ea96001e user: dan tags: begin-concurrent-wal2
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/wal.c.

  1316   1316     testcase( mxFrame==HASHTABLE_NPAGE_ONE-1 );
  1317   1317     testcase( mxFrame==HASHTABLE_NPAGE_ONE );
  1318   1318     testcase( mxFrame==HASHTABLE_NPAGE_ONE+1 );
  1319   1319   
  1320   1320     if( mxFrame==0 ) return;
  1321   1321   
  1322   1322     /* Obtain pointers to the hash-table and page-number array containing 
  1323         -  ** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed
  1324         -  ** that the page said hash-table and array reside on is already mapped.
  1325         -  */
         1323  +  ** the entry that corresponds to frame pWal->hdr.mxFrame.  */
  1326   1324     assert( pWal->nWiData>walFramePage(iExternal) );
  1327   1325     assert( pWal->apWiData[walFramePage(iExternal)] );
  1328   1326     walHashGet(pWal, walFramePage(iExternal), &sLoc);
  1329   1327   
  1330   1328     /* Zero all hash-table entries that correspond to frame numbers greater
  1331   1329     ** than pWal->hdr.mxFrame.
  1332   1330     */
................................................................................
  3866   3864         ** occurs if some other writer has crashed while committing a 
  3867   3865         ** transaction to this database since the current concurrent transaction
  3868   3866         ** was opened.  */
  3869   3867         rc = SQLITE_BUSY_SNAPSHOT;
  3870   3868       }else if( memcmp(&pWal->hdr, (void*)&head, sizeof(WalIndexHdr))!=0 ){
  3871   3869         int bWal2 = isWalMode2(pWal);
  3872   3870         int iHash;
  3873         -      int iLastHash = walFramePage(head.mxFrame);
  3874   3871         int nLoop = 1+(bWal2 && walidxGetFile(&head)!=walidxGetFile(&pWal->hdr));
  3875   3872         int iLoop;
  3876   3873         
  3877   3874   
  3878   3875         assert( nLoop==1 || nLoop==2 );
  3879         -      for(iLoop=0; iLoop<nLoop && rc==SQLITE_OK; iLoop++){
         3876  +      for(iLoop=0; rc==SQLITE_OK && iLoop<nLoop; iLoop++){
  3880   3877           u32 iFirst;               /* First (external) wal frame to check */
  3881   3878           u32 iLastHash;            /* Last hash to check this loop */
  3882   3879           u32 mxFrame;              /* Last (external) wal frame to check */
  3883   3880   
  3884   3881           if( bWal2==0 ){
  3885   3882             assert( iLoop==0 );
  3886   3883             /* Special case for wal mode. If this concurrent transaction was
................................................................................
  3925   3922                 if( sLoc.aPgno[i]==1 ){
  3926   3923                   /* Check that the schema cookie has not been modified. If
  3927   3924                   ** it has not, the commit can proceed. */
  3928   3925                   u8 aNew[4];
  3929   3926                   u8 *aOld = &((u8*)pPage1->pData)[40];
  3930   3927                   int sz;
  3931   3928                   i64 iOff;
  3932         -                int iFrame = sLoc.iZero + i;
         3929  +                u32 iFrame = sLoc.iZero + i;
  3933   3930                   int iWal = 0;
  3934   3931                   if( bWal2 ){
  3935   3932                     iWal = walExternalDecode(iFrame, &iFrame);
  3936   3933                   }
  3937   3934                   sz = pWal->hdr.szPage;
  3938   3935                   sz = (sz&0xfe00) + ((sz&0x0001)<<16);
  3939   3936                   iOff = walFrameOffset(iFrame, sz) + WAL_FRAME_HDRSIZE + 40;
................................................................................
  4045   4042   
  4046   4043       assert( isWalMode2(pWal) || iWal==0 );
  4047   4044   
  4048   4045       /* Restore the clients cache of the wal-index header to the state it
  4049   4046       ** was in before the client began writing to the database. 
  4050   4047       */
  4051   4048       memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
  4052         -    assert( walidxGetFile(&pWal->hdr)==iWal );
  4053   4049       iNew = walidxGetMxFrame(&pWal->hdr, walidxGetFile(&pWal->hdr));
         4050  +
         4051  +    /* BEGIN CONCURRENT transactions are different, as the header just
         4052  +    ** memcpy()d into pWal->hdr may not be the same as the current header 
         4053  +    ** when the transaction was started. Instead, pWal->hdr now contains
         4054  +    ** the header written by the most recent successful COMMIT. Because
         4055  +    ** Wal.writeLock is set, if this is a BEGIN CONCURRENT transaction,
         4056  +    ** the rollback must be taking place because an error occurred during
         4057  +    ** a COMMIT.
         4058  +    **
         4059  +    ** The code below is still valid. All frames between (iNew+1) and iMax 
         4060  +    ** must have been written by this transaction before the error occurred.
         4061  +    ** The exception is in wal2 mode - if the current wal file at the time
         4062  +    ** of the last COMMIT is not wal file iWal, then the error must have
         4063  +    ** occurred in WalLockForCommit(), before any pages were written
         4064  +    ** to the database file. In this case return early.  */
         4065  +#ifndef SQLITE_OMIT_CONCURRENT
         4066  +    if( walidxGetFile(&pWal->hdr)!=iWal ){
         4067  +      assert( isWalMode2(pWal) );
         4068  +      return SQLITE_OK;
         4069  +    }
         4070  +#endif
         4071  +    assert( walidxGetFile(&pWal->hdr)==iWal );
  4054   4072   
  4055   4073       for(iFrame=iNew+1; ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; iFrame++){
  4056   4074         /* This call cannot fail. Unless the page for which the page number
  4057   4075         ** is passed as the second argument is (a) in the cache and 
  4058   4076         ** (b) has an outstanding reference, then xUndo is either a no-op
  4059   4077         ** (if (a) is false) or simply expels the page from the cache (if (b)
  4060   4078         ** is false).

Added test/concfault2.test.

            1  +# 2018 Dec 28
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +# This file contains fault injection tests designed to test the concurrent
           13  +# transactions feature.
           14  +#
           15  +
           16  +set testdir [file dirname $argv0]
           17  +source $testdir/tester.tcl
           18  +source $testdir/malloc_common.tcl
           19  +set testprefix concfault2
           20  +
           21  +ifcapable !concurrent {
           22  +  finish_test
           23  +  return
           24  +}
           25  +
           26  +do_execsql_test 1.0 {
           27  +  PRAGMA auto_vacuum = 0;
           28  +  PRAGMA journal_mode = wal2;
           29  +  CREATE TABLE t1(a PRIMARY KEY, b);
           30  +  CREATE TABLE t2(a PRIMARY KEY, b);
           31  +  INSERT INTO t1 VALUES(randomblob(1000), randomblob(100));
           32  +  INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
           33  +  INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
           34  +  INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
           35  +  INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
           36  +  DELETE FROM t1 WHERE rowid%2;
           37  +} {wal2}
           38  +
           39  +do_test 1.1 {
           40  +  list [expr [file size test.db-wal]>75000] [file size test.db-shm]
           41  +} {1 32768}
           42  +
           43  +faultsim_save_and_close
           44  +
           45  +do_faultsim_test 1 -prep {
           46  +  faultsim_restore_and_reopen
           47  +  execsql {
           48  +    BEGIN CONCURRENT;
           49  +      INSERT INTO t2 VALUES(1, 2);
           50  +  }
           51  +  sqlite3 db2 test.db
           52  +  execsql {
           53  +    PRAGMA journal_size_limit = 10000;
           54  +    INSERT INTO t1 VALUES(randomblob(1000), randomblob(1000));
           55  +  } db2
           56  +  db2 close
           57  +} -body {
           58  +  execsql { COMMIT }
           59  +} -test {
           60  +  faultsim_test_result {0 {}} 
           61  +  catchsql { ROLLBACK }
           62  +  faultsim_integrity_check
           63  +}
           64  +finish_test
           65  +

Changes to test/concurrent2.test.

    18     18   source $testdir/wal_common.tcl
    19     19   set ::testprefix concurrent2
    20     20   
    21     21   ifcapable !concurrent {
    22     22     finish_test
    23     23     return
    24     24   }
           25  +
           26  +do_test 0.1 {
           27  +  llength [sqlite3_wal_info db main]
           28  +} {2}
    25     29   
    26     30   do_multiclient_test tn {
    27     31   
    28     32     do_test 1.$tn.1 {
    29     33       sql1 {
    30     34         PRAGMA journal_mode = wal;
    31     35         CREATE TABLE t1(x);

Changes to test/permutations.test.

   441    441   walshared.test walslow.test wal.test
   442    442   wal2savepoint.test wal2lock.test wal2recover2.test
   443    443   
   444    444     wal2concurrent.test
   445    445     concurrent.test concurrent2.test concurrent3.test
   446    446     concurrent4.test concurrent5.test concurrent6.test
   447    447     concurrent7.test
          448  +  concfault.test concfault2.test
   448    449   
   449    450     walvfs.test walfault2.test nockpt.test
   450    451     snapshot2.test snapshot3.test snapshot4.test
   451    452     snapshot_fault.test snapshot.test snapshot_up.test
   452    453     walcrash2.test walcrash3.test walcrash4.test walcrash.test
   453    454     wal2fault.test
   454    455   } 

Changes to test/wal2recover2.test.

   216    216         SELECT sum(x) FROM t1;
   217    217         SELECT sum(x) FROM t2;
   218    218       } db2
   219    219     } $res
   220    220     db2 close
   221    221   }
   222    222   
          223  +
          224  +#-------------------------------------------------------------------------
          225  +reset_db
          226  +do_execsql_test 1.8.1 {
          227  +  PRAGMA autovacuum = 0;
          228  +  PRAGMA page_size = 4096;
          229  +  CREATE TABLE t1(x);
          230  +  CREATE TABLE t2(x);
          231  +  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
          232  +    INSERT INTO t1 SELECT i FROM s;
          233  +  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
          234  +    INSERT INTO t2 SELECT i FROM s;
          235  +
          236  +  PRAGMA journal_mode = wal2;
          237  +  PRAGMA journal_size_limit = 10000;
          238  +
          239  +  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
          240  +    INSERT INTO t2 SELECT i FROM s;
          241  +} {wal2 10000}
          242  +
          243  +do_test 1.8.2 {
          244  +  list [file size test.db-wal] [file size test.db-wal2]
          245  +} {24752 0}
          246  +
          247  +do_execsql_test 1.8.3 { PRAGMA user_version = 123 }
          248  +do_test 1.8.4 {
          249  +  list [file size test.db-wal] [file size test.db-wal2]
          250  +} {24752 4152}
          251  +
          252  +do_test 1.8.5 {
          253  +  hexio_write test.db-wal2 [expr 56+16] 0400
          254  +  fix_wal_cksums test.db-wal2
          255  +} {}
          256  +
          257  +do_test 1.8.6 {
          258  +  forcecopy test.db test.db2
          259  +  forcecopy test.db-wal test.db2-wal
          260  +  forcecopy test.db-wal2 test.db2-wal2
          261  +  sqlite3 db2 test.db2
          262  +  catchsql { SELECT * FROM sqlite_master } db2
          263  +} {1 {database disk image is malformed}}
          264  +db2 close
          265  +
   223    266   #-------------------------------------------------------------------------
   224    267   reset_db
   225    268   do_execsql_test 1.0 {
   226    269     CREATE TABLE t1(a, b, c);
   227    270     CREATE INDEX t1a ON t1(a);
   228    271     CREATE INDEX t1b ON t1(b);
   229    272     CREATE INDEX t1c ON t1(c);

Changes to test/wal2savepoint.test.

    50     50       ROLLBACK TO abc;
    51     51       WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 10)
    52     52       INSERT INTO t1 SELECT random(), random(), random() FROM s;
    53     53     COMMIT;
    54     54     SELECT count(*) FROM t1;
    55     55     PRAGMA integrity_check;
    56     56   } {210 ok}
           57  +
           58  +do_execsql_test 1.4 {
           59  +  BEGIN;
           60  +    SAVEPOINT abc;
           61  +      WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 100)
           62  +      INSERT INTO t1 SELECT random(), random(), random() FROM s;
           63  +    ROLLBACK TO abc;
           64  +    WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s where i < 10)
           65  +    INSERT INTO t1 SELECT random(), random(), random() FROM s;
           66  +  COMMIT;
           67  +  SELECT count(*) FROM t1;
           68  +  PRAGMA integrity_check;
           69  +} {220 ok}
    57     70   
    58     71   
    59     72   finish_test
    60     73   

Changes to test/wal2snapshot.test.

    63     63       do_test 1.6 {
    64     64         execsql BEGIN
    65     65         set SNAPSHOT [sqlite3_snapshot_get_blob db main]
    66     66         sqlite3_snapshot_open_blob db main $SNAPSHOT
    67     67         execsql COMMIT
    68     68       } {}
    69     69     } else {
    70         -    do_test 2.6 {
           70  +
           71  +    do_test 2.6.1 {
           72  +      execsql BEGIN
           73  +      set res [
           74  +        list [catch { sqlite3_snapshot_open_blob db main $SNAPSHOT } msg] $msg
           75  +      ]
           76  +      execsql COMMIT
           77  +      set res
           78  +    } {1 SQLITE_ERROR}
           79  +    do_test 2.6.2 {
    71     80         execsql BEGIN
           81  +      execsql {SELECT * FROM sqlite_master}
    72     82         set res [
    73     83           list [catch { sqlite3_snapshot_open_blob db main $SNAPSHOT } msg] $msg
    74     84         ]
    75     85         execsql COMMIT
    76     86         set res
    77     87       } {1 SQLITE_ERROR}
    78     88     }
    79     89   }
    80     90   
    81     91   
    82     92   finish_test
    83     93   
    84     94