SQLite

Check-in [e3968b2562]
Login

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

Overview
Comment:Fix a problem to do with detecting unlocked transaction conflicts if another client restarts the wal while the transaction is running.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | begin-concurrent
Files: files | file ages | folders
SHA1: e3968b256282d8c0a87c26667b1ba02faf7a5a17
User & Date: dan 2015-08-22 20:32:39.272
Context
2015-08-24
06:43
Fix another problem involving unlocked transactions and wal-file restarts. (check-in: 4460764ea8 user: dan tags: begin-concurrent)
2015-08-22
20:32
Fix a problem to do with detecting unlocked transaction conflicts if another client restarts the wal while the transaction is running. (check-in: e3968b2562 user: dan tags: begin-concurrent)
17:28
Add further tests for deferred page allocation. And fixes for the same. (check-in: ed0a31be72 user: dan tags: begin-concurrent)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/wal.c.
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602





2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
  if( rc==SQLITE_OK ){
    volatile WalIndexHdr *pHead;    /* Head of the wal file */
    pHead = walIndexHdr(pWal);

    /* TODO: Check header checksum is good here. */

    if( memcmp(&pWal->hdr, (void*)pHead, sizeof(WalIndexHdr))!=0 ){
      /* TODO: Is this safe? Because it holds the WRITER lock this thread
      ** has exclusive access to the live header, but might it be corrupt? 
      ** This code should check that the wal-index-header is Ok, and return
      ** SQLITE_BUSY_SNAPSHOT if it is not. */
      int iHash;
      int iLastHash = walFramePage(pHead->mxFrame);





      for(iHash=walFramePage(pWal->hdr.mxFrame+1); iHash<=iLastHash; iHash++){
        volatile ht_slot *aHash;
        volatile u32 *aPgno;
        u32 iZero;

        rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero);
        if( rc==SQLITE_OK ){
          int i;
          int iMin = (pWal->hdr.mxFrame+1 - iZero);
          int iMax = (iHash==0) ? HASHTABLE_NPAGE_ONE : HASHTABLE_NPAGE;
          if( iMin<1 ) iMin = 1;
          if( iMax>pHead->mxFrame ) iMax = pHead->mxFrame;
          for(i=iMin; i<=iMax; i++){
            PgHdr *pPg;
            if( aPgno[i]==1 ){
              /* Check that the schema cookie has not been modified. If







<
<
<
<


>
>
>
>
>
|







|







2590
2591
2592
2593
2594
2595
2596




2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
  if( rc==SQLITE_OK ){
    volatile WalIndexHdr *pHead;    /* Head of the wal file */
    pHead = walIndexHdr(pWal);

    /* TODO: Check header checksum is good here. */

    if( memcmp(&pWal->hdr, (void*)pHead, sizeof(WalIndexHdr))!=0 ){




      int iHash;
      int iLastHash = walFramePage(pHead->mxFrame);
      u32 iFirst = pWal->hdr.mxFrame+1;     /* First wal frame to check */
      if( memcmp(pWal->hdr.aSalt, (u32*)pHead->aSalt, sizeof(u32)*2) ){
        assert( pWal->readLock==0 );
        iFirst = 1;
      }
      for(iHash=walFramePage(iFirst); iHash<=iLastHash; iHash++){
        volatile ht_slot *aHash;
        volatile u32 *aPgno;
        u32 iZero;

        rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero);
        if( rc==SQLITE_OK ){
          int i;
          int iMin = (iFirst - iZero);
          int iMax = (iHash==0) ? HASHTABLE_NPAGE_ONE : HASHTABLE_NPAGE;
          if( iMin<1 ) iMin = 1;
          if( iMax>pHead->mxFrame ) iMax = pHead->mxFrame;
          for(i=iMin; i<=iMax; i++){
            PgHdr *pPg;
            if( aPgno[i]==1 ){
              /* Check that the schema cookie has not been modified. If
Changes to test/unlocked2.test.
253
254
255
256
257
258
259



































260
261
    }
  } {1 4}

  do_test 5.$tn.4 { sql1 COMMIT } {}
  do_test 5.$tn.5 { sql3 { PRAGMA integrity_check } } {ok}
}




































finish_test








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


253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
    }
  } {1 4}

  do_test 5.$tn.4 { sql1 COMMIT } {}
  do_test 5.$tn.5 { sql3 { PRAGMA integrity_check } } {ok}
}

#-------------------------------------------------------------------------
#
do_multiclient_test tn {
  do_test 6.$tn.1 {
    sql1 {
      PRAGMA journal_mode = wal;
      CREATE TABLE t1(x);
      INSERT INTO t1 VALUES(randomblob(1500));
      PRAGMA wal_checkpoint;
    }
  } {wal 0 5 5}

  do_test 6.$tn.2 {
    sql1 { 
      BEGIN UNLOCKED;
        INSERT INTO t1 VALUES(randomblob(1500));
        INSERT INTO t1 VALUES(randomblob(1500));
    }
  } {}

  do_test 6.$tn.3 {
    sql2 {
      BEGIN;
        INSERT INTO t1 VALUES(randomblob(1500));
        INSERT INTO t1 VALUES(randomblob(1500));
      COMMIT;
    }
  } {}

  do_test 6.$tn.4 { 
    list [catch { sql1 COMMIT } msg] $msg
  } {1 {database is locked}}
  do_test 6.$tn.5 { sql3 { PRAGMA integrity_check } } {ok}
  do_test 6.$tn.5 { sql3 { SELECT count(*) from t1 } } {3}
}
finish_test

Changes to test/unlocked3.test.
50
51
52
53
54
55
56
















57
58
59
60
61
62
63
    "d" {
      set sql "
        DELETE FROM t$iTbl WHERE rowid IN (
          SELECT rowid FROM t$iTbl ORDER BY 1 ASC LIMIT 10
        )
      "
    }

















    default {
      error "bad iOp parameter: $iOp"
    }
  }

  $db eval $sql







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







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    "d" {
      set sql "
        DELETE FROM t$iTbl WHERE rowid IN (
          SELECT rowid FROM t$iTbl ORDER BY 1 ASC LIMIT 10
        )
      "
    }

    "D" {
      set sql "
        DELETE FROM t$iTbl WHERE rowid IN (
          SELECT rowid FROM t$iTbl o WHERE (
            SELECT count(*) FROM t$iTbl i WHERE i.rowid<o.rowid
          ) % 2
        )
      "
    }

    "I" {
      set sql "
        INSERT INTO t$iTbl SELECT randomblob(800), randomblob(800) FROM t$iTbl;
      "
    }

    default {
      error "bad iOp parameter: $iOp"
    }
  }

  $db eval $sql
74
75
76
77
78
79
80

81

82
83
84
85
86
87
88
  . -----------------------
  4 {1i}
  5 {1d 2i}
  . -----------------------
  6 {1iii 2iii 3iii 4iii}
  7 {1di  2id  3iii 4ddd}
  8 {1iii 2iii 3iii 4iii}

} {

  if {[string range $oplist 0 0]=="-"} {
    reset_db
    create_schema
    continue
  }
  foreach db $DBLIST { sqlite3 $db test.db }








>

>







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  . -----------------------
  4 {1i}
  5 {1d 2i}
  . -----------------------
  6 {1iii 2iii 3iii 4iii}
  7 {1di  2id  3iii 4ddd}
  8 {1iii 2iii 3iii 4iii}

} {
  # 9 {1D  2II}
  if {[string range $oplist 0 0]=="-"} {
    reset_db
    create_schema
    continue
  }
  foreach db $DBLIST { sqlite3 $db test.db }