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 |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
4688e1c8b1203c3538aa862421ed3448 |
User & Date: | drh 2009-01-02 21:39:39.000 |
Context
2009-01-03
| ||
10:41 | Add test file savepoint6.test. Contains pseudo random tests of savepoint related commands. (CVS 6105) (check-in: 2946fbb718 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: 4688e1c8b1 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: 3e9efb7638 user: drh tags: trunk) | |
Changes
Changes to src/bitvec.c.
︙ | ︙ | |||
30 31 32 33 34 35 36 | ** 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. ** | | | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | ** 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 |
︙ | ︙ | |||
170 171 172 173 174 175 176 | 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 ){ | < < | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | 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 | ** 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. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** 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 */ |
︙ | ︙ | |||
956 957 958 959 960 961 962 | } /* ** Set the bit number pgno in the PagerSavepoint.pInSavepoint bitvecs of ** all open savepoints. */ static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){ | | > > < | > | | 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 | } /* ** 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 |
︙ | ︙ | |||
3356 3357 3358 3359 3360 3361 3362 | */ if( rc!=SQLITE_OK ){ return rc; } pPager->nRec++; assert( pPager->pInJournal!=0 ); | | > > | > > > > | 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 | */ 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, |
︙ | ︙ | |||
3388 3389 3390 3391 3392 3393 3394 | } PAGERTRACE3("STMT-JOURNAL %d page %d @ %d\n", PAGERID(pPager), pPg->pgno); if( rc!=SQLITE_OK ){ return rc; } pPager->stmtNRec++; assert( pPager->nSavepoint>0 ); | | > > > > | 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 | } 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 ){ |
︙ | ︙ | |||
3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 | ** 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. */ | > | 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 | ** 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. */ |
︙ | ︙ | |||
3624 3625 3626 3627 3628 3629 3630 | ** (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 ); | < > > > > > > > > > > | > > > > | 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 | ** (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.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** 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. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** 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 |
︙ | ︙ | |||
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | ** 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 | > > | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | ** 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 |
︙ | ︙ |