From 98add2ed7428ac2b9d6409da33d2232c7ded8603 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 20 Jul 2009 17:11:49 +0000 Subject: [PATCH] Modify various routines inside btree.c to take a pointer to the return-code as a parameter and to no-op if the return-code storage location already contains a non-zero code. (CVS 6911) FossilOrigin-Name: 7dcf2a78727ce448d9d26bd6e2e23b553456ec54 --- manifest | 12 ++-- manifest.uuid | 2 +- src/btree.c | 156 ++++++++++++++++++++++++++------------------------ 3 files changed, 89 insertions(+), 81 deletions(-) diff --git a/manifest b/manifest index 0e947aaf5b..f3fedf37b2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\san\sALWAYS()\son\sa\sconditional\sin\sbtmutex.c\sthat\sis\salways\strue.\s(CVS\s6910) -D 2009-07-20T12:33:33 +C Modify\svarious\sroutines\sinside\sbtree.c\sto\stake\sa\spointer\sto\sthe\sreturn-code\nas\sa\sparameter\sand\sto\sno-op\sif\sthe\sreturn-code\sstorage\slocation\salready\ncontains\sa\snon-zero\scode.\s(CVS\s6911) +D 2009-07-20T17:11:50 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in df9359da7a726ccb67a45db905c5447d5c00c6ef F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -106,7 +106,7 @@ F src/auth.c 802a9439dfa0b8c208b10055cba400e82ef18025 F src/backup.c 6f1c2d9862c8a3feb7739dfcca02c1f5352e37f3 F src/bitvec.c cfbf6af5b0ababb4f06ed3e75c616dadaf47fcbd F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7 -F src/btree.c 4d964398d7291fd536cd6361c70ccad9c8dc3b9a +F src/btree.c a597d1d9608c88d6ce06f89c396fb560d244f2bc F src/btree.h e53a10fd31d16c60a86f03c9467a6f470aa3683b F src/btreeInt.h 1c86297e69380f6577e7ae67452597dd8d5c2705 F src/build.c 867028ee9f63f7bc8eb8d4a720bb98cf9b9a12b4 @@ -741,7 +741,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746 -P 7572991bc2232f57d04c972d516a3e8f85f34f14 -R 9782ac6fe60ba619daf4a6a17cc11b51 +P 609022caff12c010575e704be550da6f52226d33 +R f0dac37b25de3361940901b7ede7713d U drh -Z d571a5e8243db19d230ca1d0fe109d34 +Z 0886d43bf9f8d479825e913af0119cfa diff --git a/manifest.uuid b/manifest.uuid index bd354db025..2d960a61ac 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -609022caff12c010575e704be550da6f52226d33 \ No newline at end of file +7dcf2a78727ce448d9d26bd6e2e23b553456ec54 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index e363e91f2a..6b27779cc0 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.691 2009/07/16 18:21:18 drh Exp $ +** $Id: btree.c,v 1.692 2009/07/20 17:11:50 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -724,14 +724,19 @@ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ ** ** This routine updates the pointer map entry for page number 'key' ** so that it maps to type 'eType' and parent page number 'pgno'. -** An error code is returned if something goes wrong, otherwise SQLITE_OK. +** +** If *pRC is initially non-zero (non-SQLITE_OK) then this routine is +** a no-op. If an error occurs, the appropriate error code is written +** into *pRC. */ -static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){ +static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ DbPage *pDbPage; /* The pointer map page */ u8 *pPtrmap; /* The pointer map data */ Pgno iPtrmap; /* The pointer map page number */ int offset; /* Offset in pointer map page */ - int rc; + int rc; /* Return code from subfunctions */ + + if( *pRC ) return; assert( sqlite3_mutex_held(pBt->mutex) ); /* The master-journal page number must never be used as a pointer map page */ @@ -739,23 +744,25 @@ static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){ assert( pBt->autoVacuum ); if( key==0 ){ - return SQLITE_CORRUPT_BKPT; + *pRC = SQLITE_CORRUPT_BKPT; + return; } iPtrmap = PTRMAP_PAGENO(pBt, key); rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); if( rc!=SQLITE_OK ){ - return rc; + *pRC = rc; + return; } offset = PTRMAP_PTROFFSET(iPtrmap, key); if( offset<0 ){ - rc = SQLITE_CORRUPT_BKPT; + *pRC = SQLITE_CORRUPT_BKPT; goto ptrmap_exit; } pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); - rc = sqlite3PagerWrite(pDbPage); + *pRC= rc = sqlite3PagerWrite(pDbPage); if( rc==SQLITE_OK ){ pPtrmap[offset] = eType; put4byte(&pPtrmap[offset+1], parent); @@ -764,7 +771,6 @@ static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){ ptrmap_exit: sqlite3PagerUnref(pDbPage); - return rc; } /* @@ -801,9 +807,9 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ } #else /* if defined SQLITE_OMIT_AUTOVACUUM */ - #define ptrmapPut(w,x,y,z) SQLITE_OK + #define ptrmapPut(w,x,y,z,rc) #define ptrmapGet(w,x,y,z) SQLITE_OK - #define ptrmapPutOvflPtr(x, y) SQLITE_OK + #define ptrmapPutOvflPtr(x, y, rc) #endif /* @@ -998,16 +1004,16 @@ static u16 cellSize(MemPage *pPage, int iCell){ ** to an overflow page, insert an entry into the pointer-map ** for the overflow page. */ -static int ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell){ +static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){ CellInfo info; + if( *pRC ) return; assert( pCell!=0 ); btreeParseCellPtr(pPage, pCell, &info); assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); if( info.iOverflow ){ Pgno ovfl = get4byte(&pCell[info.iOverflow]); - return ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno); + ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC); } - return SQLITE_OK; } #endif @@ -2529,21 +2535,17 @@ static int setChildPtrmaps(MemPage *pPage){ for(i=0; ileaf ){ Pgno childPgno = get4byte(pCell); - rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno); - if( rc!=SQLITE_OK ) goto set_child_ptrmaps_out; + ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc); } } if( !pPage->leaf ){ Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); - rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno); + ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc); } set_child_ptrmaps_out: @@ -2667,7 +2669,7 @@ static int relocatePage( }else{ Pgno nextOvfl = get4byte(pDbPage->aData); if( nextOvfl!=0 ){ - rc = ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage); + ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage, &rc); if( rc!=SQLITE_OK ){ return rc; } @@ -2691,7 +2693,7 @@ static int relocatePage( rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType); releasePage(pPtrPage); if( rc==SQLITE_OK ){ - rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage); + ptrmapPut(pBt, iFreePage, eType, iPtrPage, &rc); } } return rc; @@ -4876,7 +4878,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ ** to indicate that the page is free. */ if( ISAUTOVACUUM ){ - rc = ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0); + ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0, &rc); if( rc ) goto freepage_out; } @@ -5107,7 +5109,7 @@ static int fillInCell( */ if( pBt->autoVacuum && rc==SQLITE_OK ){ u8 eType = (pgnoPtrmap?PTRMAP_OVERFLOW2:PTRMAP_OVERFLOW1); - rc = ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap); + ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap, &rc); if( rc ){ releasePage(pOvfl); } @@ -5176,13 +5178,15 @@ static int fillInCell( ** ** "sz" must be the number of bytes in the cell. */ -static int dropCell(MemPage *pPage, int idx, int sz){ +static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ int i; /* Loop counter */ int pc; /* Offset to cell content of cell being deleted */ u8 *data; /* pPage->aData */ u8 *ptr; /* Used to move bytes around within data[] */ int rc; /* The return code */ + if( *pRC ) return; + assert( idx>=0 && idxnCell ); assert( sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); @@ -5192,11 +5196,13 @@ static int dropCell(MemPage *pPage, int idx, int sz){ pc = get2byte(ptr); if( (pchdrOffset+6+pPage->childPtrSize) || (pc+sz>pPage->pBt->usableSize) ){ - return SQLITE_CORRUPT_BKPT; + *pRC = SQLITE_CORRUPT_BKPT; + return; } rc = freeSpace(pPage, pc, sz); - if( rc!=SQLITE_OK ){ - return rc; + if( rc ){ + *pRC = rc; + return; } for(i=idx+1; inCell; i++, ptr+=2){ ptr[0] = ptr[2]; @@ -5205,7 +5211,6 @@ static int dropCell(MemPage *pPage, int idx, int sz){ pPage->nCell--; put2byte(&data[pPage->hdrOffset+3], pPage->nCell); pPage->nFree += 2; - return SQLITE_OK; } /* @@ -5225,13 +5230,14 @@ static int dropCell(MemPage *pPage, int idx, int sz){ ** nSkip is non-zero, then pCell may not point to an invalid memory location ** (but pCell+nSkip is always valid). */ -static int insertCell( +static void insertCell( MemPage *pPage, /* Page into which we are copying */ int i, /* New cell becomes the i-th cell of the page */ u8 *pCell, /* Content of the new cell */ int sz, /* Bytes of content in pCell */ u8 *pTemp, /* Temp storage space for pCell, if needed */ - Pgno iChild /* If non-zero, replace first 4 bytes with this value */ + Pgno iChild, /* If non-zero, replace first 4 bytes with this value */ + int *pRC /* Read and write return code from here */ ){ int idx; /* Where to write new cell content in data[] */ int j; /* Loop counter */ @@ -5243,6 +5249,8 @@ static int insertCell( int nSkip = (iChild ? 4 : 0); + if( *pRC ) return; + assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 ); assert( pPage->nOverflow<=ArraySize(pPage->aOvfl) ); @@ -5263,7 +5271,8 @@ static int insertCell( }else{ int rc = sqlite3PagerWrite(pPage->pDbPage); if( rc!=SQLITE_OK ){ - return rc; + *pRC = rc; + return; } assert( sqlite3PagerIswriteable(pPage->pDbPage) ); data = pPage->aData; @@ -5271,10 +5280,11 @@ static int insertCell( end = cellOffset + 2*pPage->nCell; ins = cellOffset + 2*i; rc = allocateSpace(pPage, sz, &idx); - if( rc ) return rc; + if( rc ){ *pRC = rc; return; } assert( idx>=end+2 ); if( idx+sz > pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_BKPT; + *pRC = SQLITE_CORRUPT_BKPT; + return; } pPage->nCell++; pPage->nFree -= (u16)(2 + sz); @@ -5293,12 +5303,10 @@ static int insertCell( /* The cell may contain a pointer to an overflow page. If so, write ** the entry for the overflow page into the pointer map. */ - return ptrmapPutOvflPtr(pPage, pCell); + ptrmapPutOvflPtr(pPage, pCell, pRC); } #endif } - - return SQLITE_OK; } /* @@ -5421,9 +5429,9 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ ** rollback, undoing any changes made to the parent page. */ if( ISAUTOVACUUM ){ - rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno); - if( szCell>pNew->minLocal && rc==SQLITE_OK ){ - rc = ptrmapPutOvflPtr(pNew, pCell); + ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc); + if( szCell>pNew->minLocal ){ + ptrmapPutOvflPtr(pNew, pCell, &rc); } } @@ -5447,7 +5455,8 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ while( ((*(pOut++) = *(pCell++))&0x80) && pCellnCell,pSpace,(int)(pOut-pSpace),0,pPage->pgno); + insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace), + 0, pPage->pgno, &rc); /* Set the right-child pointer of pParent to point to the new page. */ put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); @@ -5711,7 +5720,7 @@ static int balance_nonroot( memcpy(&aOvflSpace[apDiv[i]-pParent->aData], apDiv[i], szNew[i]); apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData]; #endif - dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i]); + dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc); } } @@ -5905,7 +5914,7 @@ static int balance_nonroot( /* Set the pointer-map entry for the new sibling page. */ if( ISAUTOVACUUM ){ - rc = ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno); + ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno, &rc); if( rc!=SQLITE_OK ){ goto balance_cleanup; } @@ -6029,7 +6038,7 @@ static int balance_nonroot( iOvflSpace += sz; assert( sz<=pBt->pageSize/4 ); assert( iOvflSpace<=pBt->pageSize ); - rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, pNew->pgno); + insertCell(pParent, nxDiv, pCell, sz, pTemp, pNew->pgno, &rc); if( rc!=SQLITE_OK ) goto balance_cleanup; assert( sqlite3PagerIswriteable(pParent->pDbPage) ); @@ -6148,18 +6157,18 @@ static int balance_nonroot( ** with any child or overflow pages need to be updated. */ if( isDivider || pOld->pgno!=pNew->pgno ){ if( !leafCorrection ){ - rc = ptrmapPut(pBt, get4byte(apCell[i]), PTRMAP_BTREE, pNew->pgno); + ptrmapPut(pBt, get4byte(apCell[i]), PTRMAP_BTREE, pNew->pgno, &rc); } - if( szCell[i]>pNew->minLocal && rc==SQLITE_OK ){ - rc = ptrmapPutOvflPtr(pNew, apCell[i]); + if( szCell[i]>pNew->minLocal ){ + ptrmapPutOvflPtr(pNew, apCell[i], &rc); } } } if( !leafCorrection ){ - for(i=0; rc==SQLITE_OK && iaData[8]), PTRMAP_BTREE, apNew[i]->pgno); + for(i=0; iaData[8]); + ptrmapPut(pBt, key, PTRMAP_BTREE, apNew[i]->pgno, &rc); } } @@ -6225,12 +6234,17 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){ ** page that will become the new right-child of pPage. Copy the contents ** of the node stored on pRoot into the new child page. */ - if( SQLITE_OK!=(rc = sqlite3PagerWrite(pRoot->pDbPage)) - || SQLITE_OK!=(rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0)) - || SQLITE_OK!=(rc = copyNodeContent(pRoot, pChild)) - || (ISAUTOVACUUM && - SQLITE_OK!=(rc = ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno))) - ){ + rc = sqlite3PagerWrite(pRoot->pDbPage); + if( rc==SQLITE_OK ){ + rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0); + if( rc==SQLITE_OK ){ + rc = copyNodeContent(pRoot, pChild); + if( ISAUTOVACUUM ){ + ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc); + } + } + } + if( rc ){ *ppChild = 0; releasePage(pChild); return rc; @@ -6414,6 +6428,11 @@ int sqlite3BtreeInsert( unsigned char *oldCell; unsigned char *newCell = 0; + if( pCur->eState==CURSOR_FAULT ){ + assert( pCur->skipNext!=SQLITE_OK ); + return pCur->skipNext; + } + assert( cursorHoldsMutex(pCur) ); assert( pCur->wrFlag && pBt->inTransaction==TRANS_WRITE && !pBt->readOnly ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); @@ -6432,11 +6451,6 @@ int sqlite3BtreeInsert( invalidateIncrblobCursors(p, pCur->pgnoRoot, nKey, 0); } - if( pCur->eState==CURSOR_FAULT ){ - assert( pCur->skipNext!=SQLITE_OK ); - return pCur->skipNext; - } - /* Save the positions of any other cursors open on this table. ** ** In some cases, the call to btreeMoveto() below is a no-op. For @@ -6485,18 +6499,15 @@ int sqlite3BtreeInsert( } szOld = cellSizePtr(pPage, oldCell); rc = clearCell(pPage, oldCell); + dropCell(pPage, idx, szOld, &rc); if( rc ) goto end_insert; - rc = dropCell(pPage, idx, szOld); - if( rc!=SQLITE_OK ) { - goto end_insert; - } }else if( loc<0 && pPage->nCell>0 ){ assert( pPage->leaf ); idx = ++pCur->aiIdx[pCur->iPage]; }else{ assert( pPage->leaf ); } - rc = insertCell(pPage, idx, newCell, szNew, 0, 0); + insertCell(pPage, idx, newCell, szNew, 0, 0, &rc); assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); /* If no error has occured and pPage has an overflow cell, call balance() @@ -6597,8 +6608,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){ rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ) return rc; rc = clearCell(pPage, pCell); - if( rc ) return rc; - rc = dropCell(pPage, iCellIdx, cellSizePtr(pPage, pCell)); + dropCell(pPage, iCellIdx, cellSizePtr(pPage, pCell), &rc); if( rc ) return rc; /* If the cell deleted was not located on a leaf page, then the cursor @@ -6620,10 +6630,8 @@ int sqlite3BtreeDelete(BtCursor *pCur){ pTmp = pBt->pTmpSpace; rc = sqlite3PagerWrite(pLeaf->pDbPage); - if( rc ) return rc; - rc = insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n); - if( rc ) return rc; - rc = dropCell(pLeaf, pLeaf->nCell-1, nCell); + insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc); + dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc); if( rc ) return rc; } @@ -6767,7 +6775,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int flags){ } /* Update the pointer-map and meta-data with the new root-page number. */ - rc = ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0); + ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc); if( rc ){ releasePage(pRoot); return rc;