/ Check-in [50ca94b9]
Login

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

Overview
Comment:Add test cases for the instrumentation on this branch. Fix some OOM handling issues in the same.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | transaction-pages
Files: files | file ages | folders
SHA1: 50ca94b919ccb462f523513fd7fe99957f0b9204
User & Date: dan 2017-01-19 11:52:13
Context
2017-01-19
11:52
Add test cases for the instrumentation on this branch. Fix some OOM handling issues in the same. Leaf check-in: 50ca94b9 user: dan tags: transaction-pages
2017-01-18
20:14
Add temporary code to record and report on the set of b-tree pages read and written by the current transaction. This is likely still buggy. check-in: 2a8f6c89 user: dan tags: transaction-pages
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

3115
3116
3117
3118
3119
3120
3121





















3122
3123
3124
3125
3126
3127
3128
....
3199
3200
3201
3202
3203
3204
3205














3206
3207
3208
3209
3210
3211
3212
....
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306

3307
3308
3309
3310
3311
3312
3313
....
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
  sqlite3BtreeEnter(p);
  p->pBt->nPage = 0;
  rc = newDatabase(p->pBt);
  sqlite3BtreeLeave(p);
  return rc;
}






















/*
** Attempt to start a new transaction. A write-transaction
** is started if the second argument is nonzero, otherwise a read-
** transaction.  If the second argument is 2 or more and exclusive
** transaction is started, meaning that no other process is allowed
** to access the database.  A preexisting transaction may not be
** upgraded to exclusive by calling this routine a second time - the
................................................................................
    if( pBlock ){
      sqlite3ConnectionBlocked(p->db, pBlock);
      rc = SQLITE_LOCKED_SHAREDCACHE;
      goto trans_begun;
    }
  }
#endif















  /* Any read-only or read-write transaction implies a read-lock on 
  ** page 1. So if some other shared-cache client already has a write-lock 
  ** on page 1, the transaction cannot be opened. */
  rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
  if( SQLITE_OK!=rc ) goto trans_begun;

................................................................................
        if( rc==SQLITE_OK ){
          put4byte(&pPage1->aData[28], pBt->nPage);
        }
      }
    }
  }

#ifdef SQLITE_ENABLE_TRANSACTION_PAGES
  if( rc==SQLITE_OK && wrflag ){
    assert( pBt->pBtRead==0 && pBt->pBtWrite==0 );
    pBt->pBtRead = sqlite3BitvecCreate(pBt->nPage);
    pBt->pBtWrite = sqlite3BitvecCreate(pBt->nPage);
    pBt->pBtAlloc = sqlite3BitvecCreate(pBt->nPage);
    if( pBt->pBtRead==0 || pBt->pBtWrite==0 || pBt->pBtAlloc==0 ){
      rc = SQLITE_NOMEM;
      sqlite3BitvecDestroy(pBt->pBtRead);
      sqlite3BitvecDestroy(pBt->pBtWrite);
      sqlite3BitvecDestroy(pBt->pBtAlloc);
      pBt->pBtAlloc = pBt->pBtRead = pBt->pBtWrite = 0;
    }
  }
#endif

trans_begun:
  if( rc==SQLITE_OK && wrflag ){
    /* This call makes sure that the pager has the correct number of
    ** open savepoints. If the second parameter is greater than 0 and
    ** the sub-journal is not already open, then it will be opened here.
    */
    rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
  }


  btreeIntegrity(p);
  sqlite3BtreeLeave(p);
  return rc;
}

#ifndef SQLITE_OMIT_AUTOVACUUM

................................................................................

    /* Set the current transaction state to TRANS_NONE and unlock the 
    ** pager if this call closed the only read or write transaction.  */
    p->inTrans = TRANS_NONE;
    unlockBtreeIfUnused(pBt);
  }

#ifdef SQLITE_ENABLE_TRANSACTION_PAGES
  if( pBt->inTransaction!=TRANS_WRITE ){
    sqlite3BitvecDestroy(pBt->pBtRead);
    sqlite3BitvecDestroy(pBt->pBtWrite);
    sqlite3BitvecDestroy(pBt->pBtAlloc);
    pBt->pBtAlloc = pBt->pBtRead = pBt->pBtWrite = 0;
    sqlite3_free(pBt->aiRead);
    sqlite3_free(pBt->aiWrite);
    pBt->aiRead = pBt->aiWrite = 0;
    pBt->nRead = pBt->nWrite = 0;
  }
#endif

  btreeIntegrity(p);
}

/*
** Commit the transaction currently in progress.
**
** This routine implements the second phase of a 2-phase commit.  The







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







 







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







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









>







 







|
<
<
<
<
<
<
<
<
<
<
<
<







3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
....
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
....
3310
3311
3312
3313
3314
3315
3316
















3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
....
3834
3835
3836
3837
3838
3839
3840
3841












3842
3843
3844
3845
3846
3847
3848
  sqlite3BtreeEnter(p);
  p->pBt->nPage = 0;
  rc = newDatabase(p->pBt);
  sqlite3BtreeLeave(p);
  return rc;
}

#ifdef SQLITE_ENABLE_TRANSACTION_PAGES
/*
** If the b-tree is not currently in a write transaction, free the various
** resources allocated for the sqlite3_transaction_pages() functionality.
*/
static void freeTransactionPagesBitvec(BtShared *pBt){
  if( pBt->inTransaction!=TRANS_WRITE ){
    sqlite3BitvecDestroy(pBt->pBtRead);
    sqlite3BitvecDestroy(pBt->pBtWrite);
    sqlite3BitvecDestroy(pBt->pBtAlloc);
    pBt->pBtAlloc = pBt->pBtRead = pBt->pBtWrite = 0;
    sqlite3_free(pBt->aiRead);
    sqlite3_free(pBt->aiWrite);
    pBt->aiRead = pBt->aiWrite = 0;
    pBt->nRead = pBt->nWrite = 0;
  }
}
#else
# define freeTransactionPagesBitvec(x) 
#endif

/*
** Attempt to start a new transaction. A write-transaction
** is started if the second argument is nonzero, otherwise a read-
** transaction.  If the second argument is 2 or more and exclusive
** transaction is started, meaning that no other process is allowed
** to access the database.  A preexisting transaction may not be
** upgraded to exclusive by calling this routine a second time - the
................................................................................
    if( pBlock ){
      sqlite3ConnectionBlocked(p->db, pBlock);
      rc = SQLITE_LOCKED_SHAREDCACHE;
      goto trans_begun;
    }
  }
#endif

#ifdef SQLITE_ENABLE_TRANSACTION_PAGES
  if( wrflag ){
    assert( pBt->pBtRead==0 && pBt->pBtWrite==0 && pBt->pBtAlloc==0 );
    assert( rc==SQLITE_OK );
    pBt->pBtRead = sqlite3BitvecCreate(pBt->nPage);
    pBt->pBtWrite = sqlite3BitvecCreate(pBt->nPage);
    pBt->pBtAlloc = sqlite3BitvecCreate(pBt->nPage);
    if( pBt->pBtRead==0 || pBt->pBtWrite==0 || pBt->pBtAlloc==0 ){
      rc = SQLITE_NOMEM;
      goto trans_begun;
    }
  }
#endif

  /* Any read-only or read-write transaction implies a read-lock on 
  ** page 1. So if some other shared-cache client already has a write-lock 
  ** on page 1, the transaction cannot be opened. */
  rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
  if( SQLITE_OK!=rc ) goto trans_begun;

................................................................................
        if( rc==SQLITE_OK ){
          put4byte(&pPage1->aData[28], pBt->nPage);
        }
      }
    }
  }

















trans_begun:
  if( rc==SQLITE_OK && wrflag ){
    /* This call makes sure that the pager has the correct number of
    ** open savepoints. If the second parameter is greater than 0 and
    ** the sub-journal is not already open, then it will be opened here.
    */
    rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
  }

  freeTransactionPagesBitvec(pBt);
  btreeIntegrity(p);
  sqlite3BtreeLeave(p);
  return rc;
}

#ifndef SQLITE_OMIT_AUTOVACUUM

................................................................................

    /* Set the current transaction state to TRANS_NONE and unlock the 
    ** pager if this call closed the only read or write transaction.  */
    p->inTrans = TRANS_NONE;
    unlockBtreeIfUnused(pBt);
  }

  freeTransactionPagesBitvec(pBt);












  btreeIntegrity(p);
}

/*
** Commit the transaction currently in progress.
**
** This routine implements the second phase of a 2-phase commit.  The

Changes to test/tpages.test.

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
..
75
76
77
78
79
80
81

82




83
84






















































85

   5001 5001
  60000 5001
  60000    5
   5000 1000
   6000 1000
   7000 1000
} {

  set n1 [expr $n1]
  set n2 [expr $n2]

  reset_db
  do_execsql_test 1.$n1.1 {
    CREATE TABLE t1(a, b, c);
    WITH s(i) AS (
................................................................................
      SELECT * FROM t2;
    }
    sqlite3_transaction_pages db main
  } [list [integers $iFirst $nInt] {}]
  execsql cOMMIT
}































































finish_test








<







 







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

>
40
41
42
43
44
45
46

47
48
49
50
51
52
53
..
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
   5001 5001
  60000 5001
  60000    5
   5000 1000
   6000 1000
   7000 1000
} {

  set n1 [expr $n1]
  set n2 [expr $n2]

  reset_db
  do_execsql_test 1.$n1.1 {
    CREATE TABLE t1(a, b, c);
    WITH s(i) AS (
................................................................................
      SELECT * FROM t2;
    }
    sqlite3_transaction_pages db main
  } [list [integers $iFirst $nInt] {}]
  execsql cOMMIT
}

#-------------------------------------------------------------------------
#
proc do_transaction_pages_test {tn sql pages} {
  uplevel [list execsql $sql]
  uplevel [list \
    do_test $tn {sqlite3_transaction_pages db main} [list {*}$pages]
  ]
}
reset_db
do_transaction_pages_test 2.0 {
  PRAGMA auto_vacuum = 0;
  PRAGMA page_size = 1024;
  CREATE TABLE t1(x);
  BEGIN;
    INSERT INTO t1 VALUES(randomblob(1500));
} {2 2}

do_transaction_pages_test 2.1 {
  COMMIT;
  BEGIN;
    DELETE FROM t1;
} {2 2}

reset_db
do_execsql_test 2.2 {
  PRAGMA auto_vacuum = 0;
  PRAGMA page_size = 1024;
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES(randomblob(900));
  INSERT INTO t1 VALUES(randomblob(900));
  CREATE TABLE t2(y);
}  

do_transaction_pages_test 2.3 {
  BEGIN;
    UPDATE t1 SET x=randomblob(899);
} {{2 3 4} {3 4}}

do_transaction_pages_test 2.4 {
    DELETE FROM t1;
  COMMIT;
} {{} {}}

do_transaction_pages_test 2.5 {
  BEGIN;
    INSERT INTO t2 VALUES(randomblob(900));
    INSERT INTO t2 VALUES(randomblob(900));
} {5 5}

do_transaction_pages_test 2.6 {
  COMMIT;
  BEGIN;
    INSERT INTO t1 VALUES(randomblob(900));
} {2 2}

do_transaction_pages_test 2.7 {
    INSERT INTO t1 VALUES(randomblob(900));
    INSERT INTO t1 VALUES(randomblob(900));
    INSERT INTO t1 VALUES(randomblob(900));
    INSERT INTO t1 VALUES(randomblob(900));
} {2 2}

finish_test