/ 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 Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/bitvec.c.

    30     30   ** Clear operations are exceedingly rare.  There are usually between
    31     31   ** 5 and 500 set operations per Bitvec object, though the number of sets can
    32     32   ** sometimes grow into tens of thousands or larger.  The size of the
    33     33   ** Bitvec object is the number of pages in the database file at the
    34     34   ** start of a transaction, and is thus usually less than a few thousand,
    35     35   ** but can be as large as 2 billion for a really big database.
    36     36   **
    37         -** @(#) $Id: bitvec.c,v 1.9 2008/11/19 18:30:35 shane Exp $
           37  +** @(#) $Id: bitvec.c,v 1.10 2009/01/02 21:39:39 drh Exp $
    38     38   */
    39     39   #include "sqliteInt.h"
    40     40   
    41     41   /* Size of the Bitvec structure in bytes. */
    42     42   #define BITVEC_SZ        512
    43     43   
    44     44   /* Round the union size down to the nearest pointer boundary, since that's how 
................................................................................
   170    170     assert( i>0 );
   171    171     assert( i<=p->iSize );
   172    172     i--;
   173    173     while((p->iSize > BITVEC_NBIT) && p->iDivisor) {
   174    174       u32 bin = i/p->iDivisor;
   175    175       i = i%p->iDivisor;
   176    176       if( p->u.apSub[bin]==0 ){
   177         -      sqlite3BeginBenignMalloc();
   178    177         p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
   179         -      sqlite3EndBenignMalloc();
   180    178         if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
   181    179       }
   182    180       p = p->u.apSub[bin];
   183    181     }
   184    182     if( p->iSize<=BITVEC_NBIT ){
   185    183       p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1));
   186    184       return SQLITE_OK;

Changes to src/pager.c.

    14     14   ** The pager is used to access a database disk file.  It implements
    15     15   ** atomic commit and rollback through the use of a journal file that
    16     16   ** is separate from the database file.  The pager also implements file
    17     17   ** locking to prevent two processes from writing the same database
    18     18   ** file simultaneously, or one process from reading the database while
    19     19   ** another is writing.
    20     20   **
    21         -** @(#) $Id: pager.c,v 1.527 2009/01/02 21:08:09 drh Exp $
           21  +** @(#) $Id: pager.c,v 1.528 2009/01/02 21:39:39 drh Exp $
    22     22   */
    23     23   #ifndef SQLITE_OMIT_DISKIO
    24     24   #include "sqliteInt.h"
    25     25   
    26     26   /*
    27     27   ** Macros for troubleshooting.  Normally turned off
    28     28   */
................................................................................
   956    956   }
   957    957   
   958    958   /*
   959    959   ** Set the bit number pgno in the PagerSavepoint.pInSavepoint bitvecs of
   960    960   ** all open savepoints.
   961    961   */
   962    962   static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
   963         -  int ii;
          963  +  int ii;                   /* Loop counter */
          964  +  int rc = SQLITE_OK;       /* Result code */
          965  +
   964    966     for(ii=0; ii<pPager->nSavepoint; ii++){
   965    967       PagerSavepoint *p = &pPager->aSavepoint[ii];
   966    968       if( pgno<=p->nOrig ){
   967         -      /* TODO: malloc() failure handling */
   968         -      sqlite3BitvecSet(p->pInSavepoint, pgno);
          969  +      rc |= sqlite3BitvecSet(p->pInSavepoint, pgno);
          970  +      assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
   969    971       }
   970    972     }
   971         -  return SQLITE_OK;
          973  +  return rc;
   972    974   }
   973    975   
   974    976   /*
   975    977   ** Unlock the database file. 
   976    978   **
   977    979   ** If the pager is currently in error state, discard the contents of 
   978    980   ** the cache and reset the Pager structure internal state. If there is
................................................................................
  3356   3358           */
  3357   3359           if( rc!=SQLITE_OK ){
  3358   3360             return rc;
  3359   3361           }
  3360   3362   
  3361   3363           pPager->nRec++;
  3362   3364           assert( pPager->pInJournal!=0 );
  3363         -        sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
  3364         -        addToSavepointBitvecs(pPager, pPg->pgno);
         3365  +        rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
         3366  +        testcase( rc==SQLITE_NOMEM );
         3367  +        assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
         3368  +        rc |= addToSavepointBitvecs(pPager, pPg->pgno);
         3369  +        if( rc!=SQLITE_OK ){
         3370  +          assert( rc==SQLITE_NOMEM );
         3371  +          return rc;
         3372  +        }
  3365   3373         }else{
  3366   3374           if( !pPager->journalStarted && !pPager->noSync ){
  3367   3375             pPg->flags |= PGHDR_NEED_SYNC;
  3368   3376             pPager->needSync = 1;
  3369   3377           }
  3370   3378           PAGERTRACE4("APPEND %d page %d needSync=%d\n",
  3371   3379                   PAGERID(pPager), pPg->pgno,
................................................................................
  3388   3396         }
  3389   3397         PAGERTRACE3("STMT-JOURNAL %d page %d @ %d\n", PAGERID(pPager), pPg->pgno);
  3390   3398         if( rc!=SQLITE_OK ){
  3391   3399           return rc;
  3392   3400         }
  3393   3401         pPager->stmtNRec++;
  3394   3402         assert( pPager->nSavepoint>0 );
  3395         -      addToSavepointBitvecs(pPager, pPg->pgno);
         3403  +      rc = addToSavepointBitvecs(pPager, pPg->pgno);
         3404  +      if( rc!=SQLITE_OK ){
         3405  +        assert( rc==SQLITE_NOMEM );
         3406  +        return rc;
         3407  +      }
  3396   3408       }
  3397   3409     }
  3398   3410   
  3399   3411     /* Update the database size and return.
  3400   3412     */
  3401   3413     assert( pPager->state>=PAGER_SHARED );
  3402   3414     if( pPager->dbSize<pPg->pgno ){
................................................................................
  3590   3602   ** If we have not yet actually read the content of this page (if
  3591   3603   ** the PgHdr.needRead flag is set) then this routine acts as a promise
  3592   3604   ** that we will never need to read the page content in the future.
  3593   3605   ** so the needRead flag can be cleared at this point.
  3594   3606   */
  3595   3607   void sqlite3PagerDontRollback(DbPage *pPg){
  3596   3608     Pager *pPager = pPg->pPager;
         3609  +  TESTONLY( int rc; )  /* Return value from sqlite3BitvecSet() */
  3597   3610   
  3598   3611     assert( pPager->state>=PAGER_RESERVED );
  3599   3612   
  3600   3613     /* If the journal file is not open, or DontWrite() has been called on
  3601   3614     ** this page (DontWrite() sets the alwaysRollback flag), then this
  3602   3615     ** function is a no-op.
  3603   3616     */
................................................................................
  3624   3637     ** (Later:)  Not true.  If the database is corrupted by having duplicate
  3625   3638     ** pages on the freelist (ex: corrupt9.test) then the following is not
  3626   3639     ** necessarily true:
  3627   3640     */
  3628   3641     /* assert( !pPg->inJournal && (int)pPg->pgno <= pPager->dbOrigSize ); */
  3629   3642   
  3630   3643     assert( pPager->pInJournal!=0 );
  3631         -  sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
  3632   3644     pPg->flags &= ~PGHDR_NEED_READ;
  3633         -  addToSavepointBitvecs(pPager, pPg->pgno);
         3645  +
         3646  +  /* Failure to set the bits in the InJournal bit-vectors is benign.
         3647  +  ** It merely means that we might do some extra work to journal a page
         3648  +  ** that does not need to be journal.  Nevertheless, be sure to test the
         3649  +  ** case where a malloc error occurs while trying to set a bit in a 
         3650  +  ** bit vector.
         3651  +  */
         3652  +  sqlite3BeginBenignMalloc();
         3653  +  TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
         3654  +  testcase( rc==SQLITE_NOMEM );
         3655  +  TESTONLY( rc = ) addToSavepointBitvecs(pPager, pPg->pgno);
         3656  +  testcase( rc==SQLITE_NOMEM );
         3657  +  sqlite3EndBenignMalloc();
         3658  +
         3659  +
  3634   3660     PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager));
  3635   3661     IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno))
  3636   3662   }
  3637   3663   
  3638   3664   
  3639   3665   /*
  3640   3666   ** This routine is called to increment the database file change-counter,

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.817 2009/01/02 17:33:46 danielk1977 Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.818 2009/01/02 21:39:39 drh Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   /*
    20     20   ** Include the configuration header output by 'configure' if we're using the
    21     21   ** autoconf-based build
................................................................................
    56     56   ** both true and false in order to get full branch coverage.
    57     57   ** This macro can be inserted to ensure adequate test coverage
    58     58   ** in places where simple condition/decision coverage is inadequate.
    59     59   */
    60     60   #ifdef SQLITE_COVERAGE_TEST
    61     61     void sqlite3Coverage(int);
    62     62   # define testcase(X)  if( X ){ sqlite3Coverage(__LINE__); }
           63  +# define TESTONLY(X)  X
    63     64   #else
    64     65   # define testcase(X)
           66  +# define TESTONLY(X)
    65     67   #endif
    66     68   
    67     69   /*
    68     70   ** The ALWAYS and NEVER macros surround boolean expressions which 
    69     71   ** are intended to always be true or false, respectively.  Such
    70     72   ** expressions could be omitted from the code completely.  But they
    71     73   ** are included in a few cases in order to enhance the resilience