/ Check-in [4688e1c8]
Login

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

Overview
Comment:Memory allocation failure in Bitvec are probably all benign. Still, add code to check this, just to be sure. (CVS 6104)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:4688e1c8b1203c3538aa862421ed344888059fe2
User & Date: drh 2009-01-02 21:39:39
Context
2009-01-03
10:41
Add test file savepoint6.test. Contains pseudo random tests of savepoint related commands. (CVS 6105) check-in: 2946fbb7 user: danielk1977 tags: trunk
2009-01-02
21:39
Memory allocation failure in Bitvec are probably all benign. Still, add code to check this, just to be sure. (CVS 6104) check-in: 4688e1c8 user: drh tags: trunk
21:08
Reinitialize page 1 of the database file following a ROLLBACK TO of a transactional SAVEPOINT on an initially empty database. (CVS 6103) check-in: 3e9efb76 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/bitvec.c.

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
** Clear operations are exceedingly rare.  There are usually between
** 5 and 500 set operations per Bitvec object, though the number of sets can
** sometimes grow into tens of thousands or larger.  The size of the
** Bitvec object is the number of pages in the database file at the
** start of a transaction, and is thus usually less than a few thousand,
** but can be as large as 2 billion for a really big database.
**
** @(#) $Id: bitvec.c,v 1.9 2008/11/19 18:30:35 shane Exp $
*/
#include "sqliteInt.h"

/* Size of the Bitvec structure in bytes. */
#define BITVEC_SZ        512

/* Round the union size down to the nearest pointer boundary, since that's how 
................................................................................
  assert( i>0 );
  assert( i<=p->iSize );
  i--;
  while((p->iSize > BITVEC_NBIT) && p->iDivisor) {
    u32 bin = i/p->iDivisor;
    i = i%p->iDivisor;
    if( p->u.apSub[bin]==0 ){
      sqlite3BeginBenignMalloc();
      p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
      sqlite3EndBenignMalloc();
      if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
    }
    p = p->u.apSub[bin];
  }
  if( p->iSize<=BITVEC_NBIT ){
    p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1));
    return SQLITE_OK;







|







 







<

<







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
...
170
171
172
173
174
175
176

177

178
179
180
181
182
183
184
** Clear operations are exceedingly rare.  There are usually between
** 5 and 500 set operations per Bitvec object, though the number of sets can
** sometimes grow into tens of thousands or larger.  The size of the
** Bitvec object is the number of pages in the database file at the
** start of a transaction, and is thus usually less than a few thousand,
** but can be as large as 2 billion for a really big database.
**
** @(#) $Id: bitvec.c,v 1.10 2009/01/02 21:39:39 drh Exp $
*/
#include "sqliteInt.h"

/* Size of the Bitvec structure in bytes. */
#define BITVEC_SZ        512

/* Round the union size down to the nearest pointer boundary, since that's how 
................................................................................
  assert( i>0 );
  assert( i<=p->iSize );
  i--;
  while((p->iSize > BITVEC_NBIT) && p->iDivisor) {
    u32 bin = i/p->iDivisor;
    i = i%p->iDivisor;
    if( p->u.apSub[bin]==0 ){

      p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );

      if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
    }
    p = p->u.apSub[bin];
  }
  if( p->iSize<=BITVEC_NBIT ){
    p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1));
    return SQLITE_OK;

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
956
957
958
959
960
961
962
963


964
965
966
967
968

969
970
971
972
973
974
975
976
977
978
....
3356
3357
3358
3359
3360
3361
3362
3363


3364




3365
3366
3367
3368
3369
3370
3371
....
3388
3389
3390
3391
3392
3393
3394
3395




3396
3397
3398
3399
3400
3401
3402
....
3590
3591
3592
3593
3594
3595
3596

3597
3598
3599
3600
3601
3602
3603
....
3624
3625
3626
3627
3628
3629
3630
3631
3632










3633




3634
3635
3636
3637
3638
3639
3640
** 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.527 2009/01/02 21:08:09 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"

/*
** Macros for troubleshooting.  Normally turned off
*/
................................................................................
}

/*
** Set the bit number pgno in the PagerSavepoint.pInSavepoint bitvecs of
** all open savepoints.
*/
static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
  int ii;


  for(ii=0; ii<pPager->nSavepoint; ii++){
    PagerSavepoint *p = &pPager->aSavepoint[ii];
    if( pgno<=p->nOrig ){
      /* TODO: malloc() failure handling */
      sqlite3BitvecSet(p->pInSavepoint, pgno);

    }
  }
  return SQLITE_OK;
}

/*
** Unlock the database file. 
**
** If the pager is currently in error state, discard the contents of 
** the cache and reset the Pager structure internal state. If there is
................................................................................
        */
        if( rc!=SQLITE_OK ){
          return rc;
        }

        pPager->nRec++;
        assert( pPager->pInJournal!=0 );
        sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);


        addToSavepointBitvecs(pPager, pPg->pgno);




      }else{
        if( !pPager->journalStarted && !pPager->noSync ){
          pPg->flags |= PGHDR_NEED_SYNC;
          pPager->needSync = 1;
        }
        PAGERTRACE4("APPEND %d page %d needSync=%d\n",
                PAGERID(pPager), pPg->pgno,
................................................................................
      }
      PAGERTRACE3("STMT-JOURNAL %d page %d @ %d\n", PAGERID(pPager), pPg->pgno);
      if( rc!=SQLITE_OK ){
        return rc;
      }
      pPager->stmtNRec++;
      assert( pPager->nSavepoint>0 );
      addToSavepointBitvecs(pPager, pPg->pgno);




    }
  }

  /* Update the database size and return.
  */
  assert( pPager->state>=PAGER_SHARED );
  if( pPager->dbSize<pPg->pgno ){
................................................................................
** If we have not yet actually read the content of this page (if
** the PgHdr.needRead flag is set) then this routine acts as a promise
** that we will never need to read the page content in the future.
** so the needRead flag can be cleared at this point.
*/
void sqlite3PagerDontRollback(DbPage *pPg){
  Pager *pPager = pPg->pPager;


  assert( pPager->state>=PAGER_RESERVED );

  /* If the journal file is not open, or DontWrite() has been called on
  ** this page (DontWrite() sets the alwaysRollback flag), then this
  ** function is a no-op.
  */
................................................................................
  ** (Later:)  Not true.  If the database is corrupted by having duplicate
  ** pages on the freelist (ex: corrupt9.test) then the following is not
  ** necessarily true:
  */
  /* assert( !pPg->inJournal && (int)pPg->pgno <= pPager->dbOrigSize ); */

  assert( pPager->pInJournal!=0 );
  sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
  pPg->flags &= ~PGHDR_NEED_READ;










  addToSavepointBitvecs(pPager, pPg->pgno);




  PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager));
  IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno))
}


/*
** This routine is called to increment the database file change-counter,







|







 







|
>
>



<
|
>


|







 







|
>
>
|
>
>
>
>







 







|
>
>
>
>







 







>







 







<

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







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
956
957
958
959
960
961
962
963
964
965
966
967
968

969
970
971
972
973
974
975
976
977
978
979
980
....
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
....
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
....
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
....
3637
3638
3639
3640
3641
3642
3643

3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
** 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.528 2009/01/02 21:39:39 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"

/*
** Macros for troubleshooting.  Normally turned off
*/
................................................................................
}

/*
** Set the bit number pgno in the PagerSavepoint.pInSavepoint bitvecs of
** all open savepoints.
*/
static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
  int ii;                   /* Loop counter */
  int rc = SQLITE_OK;       /* Result code */

  for(ii=0; ii<pPager->nSavepoint; ii++){
    PagerSavepoint *p = &pPager->aSavepoint[ii];
    if( pgno<=p->nOrig ){

      rc |= sqlite3BitvecSet(p->pInSavepoint, pgno);
      assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
    }
  }
  return rc;
}

/*
** Unlock the database file. 
**
** If the pager is currently in error state, discard the contents of 
** the cache and reset the Pager structure internal state. If there is
................................................................................
        */
        if( rc!=SQLITE_OK ){
          return rc;
        }

        pPager->nRec++;
        assert( pPager->pInJournal!=0 );
        rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
        testcase( rc==SQLITE_NOMEM );
        assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
        rc |= addToSavepointBitvecs(pPager, pPg->pgno);
        if( rc!=SQLITE_OK ){
          assert( rc==SQLITE_NOMEM );
          return rc;
        }
      }else{
        if( !pPager->journalStarted && !pPager->noSync ){
          pPg->flags |= PGHDR_NEED_SYNC;
          pPager->needSync = 1;
        }
        PAGERTRACE4("APPEND %d page %d needSync=%d\n",
                PAGERID(pPager), pPg->pgno,
................................................................................
      }
      PAGERTRACE3("STMT-JOURNAL %d page %d @ %d\n", PAGERID(pPager), pPg->pgno);
      if( rc!=SQLITE_OK ){
        return rc;
      }
      pPager->stmtNRec++;
      assert( pPager->nSavepoint>0 );
      rc = addToSavepointBitvecs(pPager, pPg->pgno);
      if( rc!=SQLITE_OK ){
        assert( rc==SQLITE_NOMEM );
        return rc;
      }
    }
  }

  /* Update the database size and return.
  */
  assert( pPager->state>=PAGER_SHARED );
  if( pPager->dbSize<pPg->pgno ){
................................................................................
** If we have not yet actually read the content of this page (if
** the PgHdr.needRead flag is set) then this routine acts as a promise
** that we will never need to read the page content in the future.
** so the needRead flag can be cleared at this point.
*/
void sqlite3PagerDontRollback(DbPage *pPg){
  Pager *pPager = pPg->pPager;
  TESTONLY( int rc; )  /* Return value from sqlite3BitvecSet() */

  assert( pPager->state>=PAGER_RESERVED );

  /* If the journal file is not open, or DontWrite() has been called on
  ** this page (DontWrite() sets the alwaysRollback flag), then this
  ** function is a no-op.
  */
................................................................................
  ** (Later:)  Not true.  If the database is corrupted by having duplicate
  ** pages on the freelist (ex: corrupt9.test) then the following is not
  ** necessarily true:
  */
  /* assert( !pPg->inJournal && (int)pPg->pgno <= pPager->dbOrigSize ); */

  assert( pPager->pInJournal!=0 );

  pPg->flags &= ~PGHDR_NEED_READ;

  /* Failure to set the bits in the InJournal bit-vectors is benign.
  ** It merely means that we might do some extra work to journal a page
  ** that does not need to be journal.  Nevertheless, be sure to test the
  ** case where a malloc error occurs while trying to set a bit in a 
  ** bit vector.
  */
  sqlite3BeginBenignMalloc();
  TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
  testcase( rc==SQLITE_NOMEM );
  TESTONLY( rc = ) addToSavepointBitvecs(pPager, pPg->pgno);
  testcase( rc==SQLITE_NOMEM );
  sqlite3EndBenignMalloc();


  PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager));
  IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno))
}


/*
** This routine is called to increment the database file change-counter,

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
56
57
58
59
60
61
62

63
64

65
66
67
68
69
70
71
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.817 2009/01/02 17:33:46 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
** both true and false in order to get full branch coverage.
** This macro can be inserted to ensure adequate test coverage
** in places where simple condition/decision coverage is inadequate.
*/
#ifdef SQLITE_COVERAGE_TEST
  void sqlite3Coverage(int);
# define testcase(X)  if( X ){ sqlite3Coverage(__LINE__); }

#else
# define testcase(X)

#endif

/*
** The ALWAYS and NEVER macros surround boolean expressions which 
** are intended to always be true or false, respectively.  Such
** expressions could be omitted from the code completely.  But they
** are included in a few cases in order to enhance the resilience







|







 







>


>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.818 2009/01/02 21:39:39 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
** both true and false in order to get full branch coverage.
** This macro can be inserted to ensure adequate test coverage
** in places where simple condition/decision coverage is inadequate.
*/
#ifdef SQLITE_COVERAGE_TEST
  void sqlite3Coverage(int);
# define testcase(X)  if( X ){ sqlite3Coverage(__LINE__); }
# define TESTONLY(X)  X
#else
# define testcase(X)
# define TESTONLY(X)
#endif

/*
** The ALWAYS and NEVER macros surround boolean expressions which 
** are intended to always be true or false, respectively.  Such
** expressions could be omitted from the code completely.  But they
** are included in a few cases in order to enhance the resilience