Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix an obscure pager refcnt leak that occurs following a transient I/O error. (CVS 3829) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
ce6f56ece8eab743d20cd2c0a84b4a26 |
User & Date: | drh 2007-04-09 12:45:03.000 |
Context
2007-04-09
| ||
13:18 | Perparations for the release of 3.3.15. (CVS 3830) (check-in: 8d0dea873d user: drh tags: trunk) | |
12:45 | Fix an obscure pager refcnt leak that occurs following a transient I/O error. (CVS 3829) (check-in: ce6f56ece8 user: drh tags: trunk) | |
11:20 | Have the pager call xReiniter() instead of xDestructor() to restore btree level state after rolling back a page. (CVS 3828) (check-in: 4e8941333e user: danielk1977 tags: trunk) | |
Changes
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** 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. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** 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. ** ************************************************************************* ** $Id: btree.c,v 1.354 2007/04/09 12:45:03 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. |
︙ | ︙ | |||
3940 3941 3942 3943 3944 3945 3946 | put4byte(&pPage->aData[4], 0); put4byte(&pPage1->aData[32], pPage->pgno); TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, pTrunk->pgno)); }else{ /* Add the newly freed page as a leaf on the current trunk */ rc = sqlite3PagerWrite(pTrunk->pDbPage); | | | | | > | 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 | put4byte(&pPage->aData[4], 0); put4byte(&pPage1->aData[32], pPage->pgno); TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, pTrunk->pgno)); }else{ /* Add the newly freed page as a leaf on the current trunk */ rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc==SQLITE_OK ){ put4byte(&pTrunk->aData[4], k+1); put4byte(&pTrunk->aData[8+k*4], pPage->pgno); #ifndef SQLITE_SECURE_DELETE sqlite3PagerDontWrite(pBt->pPager, pPage->pgno); #endif } TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); } releasePage(pTrunk); } return rc; } |
︙ | ︙ | |||
4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 | for(i=0; i<k; i++){ MemPage *pNew; if( i<nOld ){ pNew = apNew[i] = apOld[i]; pgnoNew[i] = pgnoOld[i]; apOld[i] = 0; rc = sqlite3PagerWrite(pNew->pDbPage); if( rc ) goto balance_cleanup; }else{ assert( i>0 ); rc = allocateBtreePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0); if( rc ) goto balance_cleanup; apNew[i] = pNew; | > < | > | 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 | for(i=0; i<k; i++){ MemPage *pNew; if( i<nOld ){ pNew = apNew[i] = apOld[i]; pgnoNew[i] = pgnoOld[i]; apOld[i] = 0; rc = sqlite3PagerWrite(pNew->pDbPage); nNew++; if( rc ) goto balance_cleanup; }else{ assert( i>0 ); rc = allocateBtreePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0); if( rc ) goto balance_cleanup; apNew[i] = pNew; nNew++; } zeroPage(pNew, pageFlags); } /* Free any old pages that were not reused as new pages. */ while( i<nOld ){ rc = freePage(apOld[i]); |
︙ | ︙ | |||
5415 5416 5417 5418 5419 5420 5421 | ** initialized before use. Adding an extra initialization ** to silence the compiler slows down the code. */ int notUsed; unsigned char *tempCell = 0; assert( !pPage->leafData ); getTempCursor(pCur, &leafCur); rc = sqlite3BtreeNext(&leafCur, ¬Used); | < < < < < | 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 | ** initialized before use. Adding an extra initialization ** to silence the compiler slows down the code. */ int notUsed; unsigned char *tempCell = 0; assert( !pPage->leafData ); getTempCursor(pCur, &leafCur); rc = sqlite3BtreeNext(&leafCur, ¬Used); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(leafCur.pPage->pDbPage); } if( rc==SQLITE_OK ){ TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n", pCur->pgnoRoot, pPage->pgno, leafCur.pPage->pgno)); dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test1.c,v 1.236 2007/04/09 12:45:03 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include "os.h" #include <stdlib.h> #include <string.h> |
︙ | ︙ | |||
3749 3750 3751 3752 3753 3754 3755 | return TCL_OK; } /* ** Usage: sqlite3_pager_refcounts DB ** | | | | | 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 | return TCL_OK; } /* ** Usage: sqlite3_pager_refcounts DB ** ** Return a list of numbers which are the PagerRefcount for all ** pagers on each database connection. */ static int test_pager_refcounts( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ sqlite3 *db; int i; int v, *a; Tcl_Obj *pResult; if( objc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", Tcl_GetStringFromObj(objv[0], 0), " DB", 0); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; pResult = Tcl_NewObj(); for(i=0; i<db->nDb; i++){ if( db->aDb[i].pBt==0 ){ v = -1; |
︙ | ︙ |
Changes to test/ioerr2.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 | # This file implements regression tests for SQLite library. The # focus of this file is testing for correct handling of I/O errors # such as writes failing because the disk is full. # # The tests in this file use special facilities that are only # available in the SQLite test fixture. # | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # This file implements regression tests for SQLite library. The # focus of this file is testing for correct handling of I/O errors # such as writes failing because the disk is full. # # The tests in this file use special facilities that are only # available in the SQLite test fixture. # # $Id: ioerr2.test,v 1.3 2007/04/09 12:45:03 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl do_test ioerr2-1.1 { execsql { PRAGMA cache_size = 10; |
︙ | ︙ | |||
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | # pager must be in error state. In this case open a new database # connection. Otherwise, try a ROLLBACK, in case a transaction # is still active. set rc [catch {execsql {PRAGMA integrity_check}} msg] if {$rc && $msg eq "disk I/O error"} { db close sqlite3 db test.db } else { if {$rc || $msg ne "ok"} { error $msg } catch {execsql ROLLBACK} } # Check that the database checksum is still $::cksum, and that # the integrity-check passes. set ck [execsql {SELECT md5sum(a, b) FROM t1}] do_test ${testname}.cksum [list set ck $ck] $::cksum integrity_check ${testname}.integrity } check_db ioerr2-2 set sql { PRAGMA cache_size = 10; PRAGMA default_cache_size = 10; | > > > > | 46 47 48 49 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 | # pager must be in error state. In this case open a new database # connection. Otherwise, try a ROLLBACK, in case a transaction # is still active. set rc [catch {execsql {PRAGMA integrity_check}} msg] if {$rc && $msg eq "disk I/O error"} { db close sqlite3 db test.db set refcnt 0 } else { if {$rc || $msg ne "ok"} { error $msg } catch {execsql ROLLBACK} } # Check that the database checksum is still $::cksum, and that # the integrity-check passes. set ck [execsql {SELECT md5sum(a, b) FROM t1}] do_test ${testname}.cksum [list set ck $ck] $::cksum integrity_check ${testname}.integrity do_test ${testname}.refcnt { lindex [sqlite3_pager_refcounts db] 0 } 0 } check_db ioerr2-2 set sql { PRAGMA cache_size = 10; PRAGMA default_cache_size = 10; |
︙ | ︙ |