Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a couple of bugs to do with recovering the database header and recycling large overflow trees. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
8341d438d3c3040e762fb307f639bd38 |
User & Date: | dan 2013-11-22 18:06:56.665 |
Context
2013-11-23
| ||
18:41 | Add a BT_CONTROL_INFO option to query for database header values. Add a command line interface to lsmtest to access this and other options. "lsmtest bt <filename> <option> ....". check-in: e09d4c6aa8 user: dan tags: trunk | |
2013-11-22
| ||
18:06 | Fix a couple of bugs to do with recovering the database header and recycling large overflow trees. check-in: 8341d438d3 user: dan tags: trunk | |
2013-11-21
| ||
18:46 | Add code to free pages and blocks. check-in: 1a0d07f113 user: dan tags: trunk | |
Changes
Changes to src/btInt.h.
︙ | ︙ | |||
41 42 43 44 45 46 47 | typedef struct BtDbHdr BtDbHdr; struct BtDbHdr { u32 pgsz; /* Page size in bytes */ u32 nPg; /* Size of database file in pages */ u32 iRoot; /* B-tree root page */ u32 iCookie; /* Current value of schema cookie */ | < | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | typedef struct BtDbHdr BtDbHdr; struct BtDbHdr { u32 pgsz; /* Page size in bytes */ u32 nPg; /* Size of database file in pages */ u32 iRoot; /* B-tree root page */ u32 iCookie; /* Current value of schema cookie */ u32 iFreePg; /* First page in free-page list trunk */ u32 iFreeBlk; /* First page in free-block list trunk */ }; /************************************************************************* ** Interface to bt_pager.c functionality. */ |
︙ | ︙ | |||
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | ** End of utility interface. *************************************************************************/ #ifdef NDEBUG # define sqlite4BtDebugReadPage(a,b,c,d) # define sqlite4BtDebugKV(a,b,c,d,e,f) # define sqlite4BtDebugReadlock(a,b,c) # define btErrorBkpt(x) x #else void sqlite4BtDebugReadPage(BtLock *pLock, u32 pgno, u8 *aData, int pgsz); void sqlite4BtDebugKV(BtLock*, const char*,u8 *pK, int nK, u8 *pV, int nV); void sqlite4BtDebugReadlock(BtLock *pLock, u32 iFirst, u32 iLast); int btErrorBkpt(int rc); #endif | > > > > | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | ** End of utility interface. *************************************************************************/ #ifdef NDEBUG # define sqlite4BtDebugReadPage(a,b,c,d) # define sqlite4BtDebugKV(a,b,c,d,e,f) # define sqlite4BtDebugReadlock(a,b,c) # define sqlite4BtDebugPageAlloc(a,b,c) # define sqlite4BtDebugPageFree(a,b,c) # define btErrorBkpt(x) x #else void sqlite4BtDebugReadPage(BtLock *pLock, u32 pgno, u8 *aData, int pgsz); void sqlite4BtDebugKV(BtLock*, const char*,u8 *pK, int nK, u8 *pV, int nV); void sqlite4BtDebugReadlock(BtLock *pLock, u32 iFirst, u32 iLast); void sqlite4BtDebugPageAlloc(BtLock *pLock, const char*, u32); void sqlite4BtDebugPageFree(BtLock *pLock, const char*, u32); int btErrorBkpt(int rc); #endif |
Changes to src/bt_log.c.
︙ | ︙ | |||
41 42 43 44 45 46 47 48 49 50 51 52 53 54 | ** VFS method). */ struct BtWalHdr { u32 iMagic; /* Magic number (BT_WAL_MAGIC) */ u32 iVersion; /* File format version */ u32 iCnt; /* 0, 1 or 2 */ u32 nSector; /* Sector size when header written */ u32 nPgsz; /* Database page size in bytes */ u32 nPg; /* Database size in pages at last commit */ u32 padding; u32 iSalt1; /* Initial frame cksum-0 value */ u32 iSalt2; /* Initial frame cksum-1 value */ | > | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | ** VFS method). */ struct BtWalHdr { u32 iMagic; /* Magic number (BT_WAL_MAGIC) */ u32 iVersion; /* File format version */ u32 iCnt; /* 0, 1 or 2 */ u32 nSector; /* Sector size when header written */ u32 nPgsz; /* Database page size in bytes */ u32 nPg; /* Database size in pages at last commit */ u32 padding; u32 iSalt1; /* Initial frame cksum-0 value */ u32 iSalt2; /* Initial frame cksum-1 value */ |
︙ | ︙ | |||
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | pLock->iDebugId, zStr, iSide, (int)aLog[0], (int)aLog[1], (int)aLog[2], (int)aLog[3], (int)aLog[4], (int)aLog[5] ); fflush(stderr); #endif } #ifndef NDEBUG void sqlite4BtDebugReadlock(BtLock *pLock, u32 iFirst, u32 iLast){ #if BT_PAGE_DEBUG static int nCall = 0; fprintf(stderr, "%d:%d: readlock=(%d..%d)\n", pLock->iDebugId, nCall++, (int)iFirst, (int)iLast ); fflush(stderr); #endif } #endif #ifndef NDEBUG static void btDebugCheckSnapshot(BtShmHdr *pHdr){ u32 *aLog = pHdr->aLog; assert( pHdr->iNextFrame!=1 || (aLog[0]==0 && aLog[1]==0 && aLog[2]==0 && aLog[3]==0) ); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | pLock->iDebugId, zStr, iSide, (int)aLog[0], (int)aLog[1], (int)aLog[2], (int)aLog[3], (int)aLog[4], (int)aLog[5] ); fflush(stderr); #endif } static void btDebugDbhdr(BtLock *pLock, const char *zStr, BtDbHdr *pHdr){ #if BT_HDR_DEBUG static int nCall = 0; fprintf(stderr, "%d:%d: %s db-header " "(pgsz=%d nPg=%d iRoot=%d iCookie=%d iFreePg=%d iFreeBlk=%d)\n", pLock->iDebugId, nCall++, zStr, (int)pHdr->pgsz, (int)pHdr->nPg, (int)pHdr->iRoot, (int)pHdr->iCookie, (int)pHdr->iFreePg, (int)pHdr->iFreeBlk ); fflush(stderr); #endif } #ifndef NDEBUG void sqlite4BtDebugReadlock(BtLock *pLock, u32 iFirst, u32 iLast){ #if BT_PAGE_DEBUG static int nCall = 0; fprintf(stderr, "%d:%d: readlock=(%d..%d)\n", pLock->iDebugId, nCall++, (int)iFirst, (int)iLast ); fflush(stderr); #endif } #endif #ifndef NDEBUG void sqlite4BtDebugPageAlloc(BtLock *pLock, const char *zStr, u32 pgno){ #if BT_PAGE_DEBUG static int nCall = 0; fprintf(stderr, "%d:%d: allocate page %d from %s\n", pLock->iDebugId, nCall++, pgno, zStr ); fflush(stderr); #endif } #endif #ifndef NDEBUG void sqlite4BtDebugPageFree(BtLock *pLock, const char *zStr, u32 pgno){ #if BT_PAGE_DEBUG static int nCall = 0; fprintf(stderr, "%d:%d: trim page %d (%s)\n", pLock->iDebugId, nCall++, pgno, zStr ); fflush(stderr); assert( pgno<1000000 ); #endif } #endif #ifndef NDEBUG static void btDebugCheckSnapshot(BtShmHdr *pHdr){ u32 *aLog = pHdr->aLog; assert( pHdr->iNextFrame!=1 || (aLog[0]==0 && aLog[1]==0 && aLog[2]==0 && aLog[3]==0) ); |
︙ | ︙ | |||
716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 | return (pLog->snapshot.aLog[4]==0 && pLog->snapshot.iNextFrame==0); } typedef struct FrameRecoverCtx FrameRecoverCtx; struct FrameRecoverCtx { u32 iLast; /* Frame containing last commit flag in log */ u32 iNextFrame; /* Frame that follows frame iLast */ }; static int btLogRecoverFrame( BtLog *pLog, /* Log module handle */ void *pCtx, /* woints to type u32 - pgno of last commit*/ u32 iFrame, /* Frame number */ BtFrameHdr *pHdr /* Frame header */ ){ if( btLogIsEmpty(pLog) ){ /* This is the first frame recovered. It is therefore both the first ** and last frame of log region (c). */ pLog->snapshot.aLog[4] = iFrame; pLog->snapshot.aLog[5] = iFrame; }else{ | > > | 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 | return (pLog->snapshot.aLog[4]==0 && pLog->snapshot.iNextFrame==0); } typedef struct FrameRecoverCtx FrameRecoverCtx; struct FrameRecoverCtx { u32 iLast; /* Frame containing last commit flag in log */ u32 iNextFrame; /* Frame that follows frame iLast */ u32 iPageOneFrame; /* Frame containing most recent page 1 */ }; static int btLogRecoverFrame( BtLog *pLog, /* Log module handle */ void *pCtx, /* woints to type u32 - pgno of last commit*/ u32 iFrame, /* Frame number */ BtFrameHdr *pHdr /* Frame header */ ){ FrameRecoverCtx *pFRC = (FrameRecoverCtx*)pCtx; if( btLogIsEmpty(pLog) ){ /* This is the first frame recovered. It is therefore both the first ** and last frame of log region (c). */ pLog->snapshot.aLog[4] = iFrame; pLog->snapshot.aLog[5] = iFrame; }else{ |
︙ | ︙ | |||
753 754 755 756 757 758 759 | pLog->snapshot.aLog[4] = iFrame; pLog->snapshot.aLog[5] = iFrame; } } btLogHashInsert(pLog, pHdr->pgno, iFrame); if( pHdr->nPg!=0 ){ | < > > > > | 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 | pLog->snapshot.aLog[4] = iFrame; pLog->snapshot.aLog[5] = iFrame; } } btLogHashInsert(pLog, pHdr->pgno, iFrame); if( pHdr->nPg!=0 ){ pFRC->iLast = iFrame; pFRC->iNextFrame = pHdr->iNext; memcpy(pLog->snapshot.aFrameCksum, pHdr->aCksum, sizeof(pHdr->aCksum)); pLog->snapshot.dbhdr.nPg = pHdr->nPg; } if( pHdr->pgno==1 ){ pFRC->iPageOneFrame = iFrame; } #if 0 fprintf(stderr, "recovered frame=%d pgno=%d\n", iFrame, pHdr->pgno); fflush(stderr); #endif return 0; } |
︙ | ︙ | |||
802 803 804 805 806 807 808 | } } aLog[5] = iLast; return btLogHashRollback(pLog, btLogFrameHash(pLog, iLast), iLast); } | > > > > > > > > > > > > > > > > > > > | | | > > | | < | < | < | < < < | > > > > | | | < < | < | < > | | 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 | } } aLog[5] = iLast; return btLogHashRollback(pLog, btLogFrameHash(pLog, iLast), iLast); } static void btLogDecodeDbhdr(BtLog *pLog, u8 *aData, BtDbHdr *pHdr){ BtDbHdrCksum hdr; u32 aCksum[2]; if( aData ){ memcpy(&hdr, aData, sizeof(BtDbHdrCksum)); btLogChecksum(1, (u8*)&hdr, offsetof(BtDbHdrCksum, aCksum), 0, aCksum); } if( aData==0 || aCksum[0]!=hdr.aCksum[0] || aCksum[1]!=hdr.aCksum[1] ){ memset(&hdr, 0, sizeof(BtDbHdrCksum)); hdr.hdr.pgsz = BT_DEFAULT_PGSZ; hdr.hdr.nPg = 2; hdr.hdr.iRoot = 2; } memcpy(pHdr, &hdr, sizeof(BtDbHdr)); } static int btLogReadDbhdr(BtLog *pLog, BtDbHdr *pHdr, u32 iFrame){ BtLock *p = pLog->pLock; /* BtLock handle */ int rc; /* Return code */ i64 nByte; /* Size of database file in byte */ u8 *aBuffer[sizeof(BtDbHdrCksum)]; u8 *aData = 0; if( iFrame==0 ){ rc = p->pVfs->xSize(p->pFd, &nByte); if( rc==SQLITE4_OK && nByte>0 ){ rc = p->pVfs->xRead(p->pFd, 0, aBuffer, sizeof(BtDbHdrCksum)); aData = aBuffer; } }else{ i64 iOff = btLogFrameOffset(pLog, pLog->snapshot.dbhdr.pgsz, iFrame); iOff += sizeof(BtFrameHdr); rc = p->pVfs->xRead(pLog->pFd, iOff, aBuffer, sizeof(BtDbHdrCksum)); aData = aBuffer; } if( rc==SQLITE4_OK ){ btLogDecodeDbhdr(pLog, aData, pHdr); } return rc; } static int btLogUpdateDbhdr(BtLog *pLog, u8 *aData){ BtDbHdrCksum hdr; memcpy(&hdr.hdr, &pLog->snapshot.dbhdr, sizeof(BtDbHdr)); btLogChecksum(1, (u8*)&hdr, offsetof(BtDbHdrCksum, aCksum), 0, hdr.aCksum); btDebugDbhdr(pLog->pLock, "update", &pLog->snapshot.dbhdr); assert( hdr.hdr.iRoot==2 ); assert( hdr.hdr.pgsz>0 ); memcpy(aData, &hdr, sizeof(BtDbHdrCksum)); return SQLITE4_OK; } |
︙ | ︙ | |||
910 911 912 913 914 915 916 | pShm->ckpt.iFirstRead = pHdr->iFirstFrame; pShm->ckpt.iFirstRecover = pHdr->iFirstFrame; rc = btLogRollbackRecovery(pLog, &ctx); pLog->snapshot.iNextFrame = ctx.iNextFrame; pLog->snapshot.dbhdr.pgsz = pHdr->nPgsz; assert( pShm->ckpt.iFirstRead>0 ); } | | > > > > > | | > < < < | > > | 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 | pShm->ckpt.iFirstRead = pHdr->iFirstFrame; pShm->ckpt.iFirstRecover = pHdr->iFirstFrame; rc = btLogRollbackRecovery(pLog, &ctx); pLog->snapshot.iNextFrame = ctx.iNextFrame; pLog->snapshot.dbhdr.pgsz = pHdr->nPgsz; assert( pShm->ckpt.iFirstRead>0 ); } /* Based on the wal-header, the page-size and number of pages in the ** database are now known and stored in snapshot.dbhdr. But the other ** header field values (iCookie, iRoot etc.) are still unknown. Read ** them from page 1 of the database file now. */ rc = btLogReadDbhdr(pLog, &pLog->snapshot.dbhdr, ctx.iPageOneFrame); }else if( rc==SQLITE4_OK ){ /* There is no data in the log file. Read the database header directly ** from offset 0 of the database file. */ btLogZeroSnapshot(pLog); rc = btLogReadDbhdr(pLog, &pLog->snapshot.dbhdr, 0); } if( rc==SQLITE4_OK ){ btDebugTopology( pLog->pLock, "recovered", pLog->snapshot.iHashSide, pLog->snapshot.aLog ); btDebugDbhdr(pLog->pLock, "read", &pLog->snapshot.dbhdr); } return rc; } /* ** Open the log file for pager pPager. If successful, return the BtLog* ** handle via output variable *ppLog. If parameter bRecover is true, then |
︙ | ︙ |
Changes to src/bt_main.c.
︙ | ︙ | |||
965 966 967 968 969 970 971 | BtPager *pPager, u32 pgno, int nDepth ){ int rc = SQLITE4_OK; assert( nDepth<=8 ); | | < < > | 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 | BtPager *pPager, u32 pgno, int nDepth ){ int rc = SQLITE4_OK; assert( nDepth<=8 ); if( nDepth>0 ){ const int nPgPtr = pgsz / 4; BtPage *pPg; u8 *aData; int i; rc = sqlite4BtPageGet(pPager, pgno, &pPg); if( rc!=SQLITE4_OK ) return rc; aData = sqlite4BtPageData(pPg); for(i=0; rc==SQLITE4_OK && i<nPgPtr; i++){ u32 child = btGetU32(&aData[i*4]); if( child==0 ) break; rc = btOverflowTrimtree(pgsz, pPager, child, nDepth-1); } sqlite4BtPageRelease(pPg); } sqlite4BtPageTrimPgno(pPager, pgno); return rc; } /* ** Cursor pCsr currently points to a leaf page cell. If the leaf page ** cell contains an overflow array, all overflow pages are trimmed here. ** |
︙ | ︙ | |||
1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 | int nPg; nPg = (nContent + pgsz - 1) / pgsz; if( nPg<=BT_MAX_DIRECT_OVERFLOW ){ return 1 + nPg*4; } return 1 + (BT_MAX_DIRECT_OVERFLOW+1) * 4; } static int btOverflowArrayPopulate( bt_db *db, u8 **ppOut, u8 *pBuf1, int nBuf1, u8 *pBuf2, int nBuf2 ){ const int pgsz = sqlite4BtPagerPagesize(db->pPager); | > > > > > > > > > > > > > > | 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 | int nPg; nPg = (nContent + pgsz - 1) / pgsz; if( nPg<=BT_MAX_DIRECT_OVERFLOW ){ return 1 + nPg*4; } return 1 + (BT_MAX_DIRECT_OVERFLOW+1) * 4; } static int btAllocateAndZero(bt_db *db, BtPage **ppPg){ BtPage *pPg = 0; /* Allocated page handle */ int rc; /* Return code */ rc = sqlite4BtPageAllocate(db->pPager, &pPg); if( rc==SQLITE4_OK ){ const int pgsz = sqlite4BtPagerPagesize(db->pPager); memset(sqlite4BtPageData(pPg), 0, pgsz); } *ppPg = pPg; return rc; } static int btOverflowArrayPopulate( bt_db *db, u8 **ppOut, u8 *pBuf1, int nBuf1, u8 *pBuf2, int nBuf2 ){ const int pgsz = sqlite4BtPagerPagesize(db->pPager); |
︙ | ︙ | |||
1398 1399 1400 1401 1402 1403 1404 | while( nOvfl>1 ){ nDepth++; nOvfl = (nOvfl+nPgPtr-1) / nPgPtr; } for(i=0; rc==SQLITE4_OK && i<nDepth; i++){ u32 pgno; | | | 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 | while( nOvfl>1 ){ nDepth++; nOvfl = (nOvfl+nPgPtr-1) / nPgPtr; } for(i=0; rc==SQLITE4_OK && i<nDepth; i++){ u32 pgno; rc = btAllocateAndZero(db, &apHier[i].pPg); pgno = sqlite4BtPagePgno(apHier[i].pPg); if( i==0 ){ btPutU32(&aOut[1 + BT_MAX_DIRECT_OVERFLOW*4], pgno); }else{ u8 *a = sqlite4BtPageData(apHier[i-1].pPg); btPutU32(a, pgno); apHier[i-1].iCell++; |
︙ | ︙ | |||
1439 1440 1441 1442 1443 1444 1445 | assert( nDepth>0 ); for(i=nDepth-1; pgno && i>=0; i--){ u8 *a = sqlite4BtPageData(apHier[i].pPg); if( apHier[i].iCell==nPgPtr ){ BtPage *pNew = 0; rc = sqlite4BtPageRelease(apHier[i].pPg); if( rc==SQLITE4_OK ){ | | | 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 | assert( nDepth>0 ); for(i=nDepth-1; pgno && i>=0; i--){ u8 *a = sqlite4BtPageData(apHier[i].pPg); if( apHier[i].iCell==nPgPtr ){ BtPage *pNew = 0; rc = sqlite4BtPageRelease(apHier[i].pPg); if( rc==SQLITE4_OK ){ rc = btAllocateAndZero(db, &pNew); if( rc==SQLITE4_OK ){ u8 *a = sqlite4BtPageData(pNew); btPutU32(a, pgno); pgno = sqlite4BtPagePgno(pNew); } } |
︙ | ︙ | |||
2559 2560 2561 2562 2563 2564 2565 | case BT_CONTROL_LOGSIZECB: { bt_logsizecb *p = (bt_logsizecb*)pArg; sqlite4BtPagerLogsizeCb(db->pPager, p); break; } case BT_CONTROL_CHECKPOINT: { | | | 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 | case BT_CONTROL_LOGSIZECB: { bt_logsizecb *p = (bt_logsizecb*)pArg; sqlite4BtPagerLogsizeCb(db->pPager, p); break; } case BT_CONTROL_CHECKPOINT: { bt_checkpoint *p = (bt_checkpoint*)pArg; rc = sqlite4BtPagerCheckpoint(db->pPager, p); break; } } return rc; } |
Changes to src/bt_pager.c.
︙ | ︙ | |||
715 716 717 718 719 720 721 | if( iLevel<2 ) sqlite4BtLogSnapshotEndWrite(p->pLog); }else{ rc = btCloseSavepoints(p, iLevel-1, 1); p->nSavepoint++; } } | > | | | | > | 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 | if( iLevel<2 ) sqlite4BtLogSnapshotEndWrite(p->pLog); }else{ rc = btCloseSavepoints(p, iLevel-1, 1); p->nSavepoint++; } } if( p->iTransactionLevel>iLevel ){ p->iTransactionLevel = iLevel; if( iLevel==0 ){ int rc2 = btCloseReadTransaction(p); if( rc==SQLITE4_OK ) rc = rc2; } } } return rc; } int sqlite4BtPagerRevert(BtPager *p, int iLevel){ |
︙ | ︙ | |||
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 | u8 *aData = pTrunk->aData; int nFree = (int)sqlite4BtGetU32(aData); if( nFree<nMax ){ sqlite4BtPutU32(&pTrunk->aData[8 + nFree*4], pgno); sqlite4BtPutU32(pTrunk->aData, nFree+1); bDone = 1; } sqlite4BtPageRelease(pTrunk); } } /* If no error has occurred but the page number has not yet been added ** to the free-list, this page becomes the first trunk in the list. */ if( rc==SQLITE4_OK && bDone==0 ){ BtPage *pRelease = 0; if( pPg==0 ){ rc = sqlite4BtPageGet(p, pgno, &pRelease); } if( rc==SQLITE4_OK ){ BtPage *pTrunk = pPg ? pPg : pRelease; rc = sqlite4BtPageWrite(pTrunk); if( rc==SQLITE4_OK ){ | > | | > | 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 | u8 *aData = pTrunk->aData; int nFree = (int)sqlite4BtGetU32(aData); if( nFree<nMax ){ sqlite4BtPutU32(&pTrunk->aData[8 + nFree*4], pgno); sqlite4BtPutU32(pTrunk->aData, nFree+1); bDone = 1; sqlite4BtDebugPageFree((BtLock*)p, "free-list", pgno); } sqlite4BtPageRelease(pTrunk); } } /* If no error has occurred but the page number has not yet been added ** to the free-list, this page becomes the first trunk in the list. */ if( rc==SQLITE4_OK && bDone==0 ){ BtPage *pRelease = 0; if( pPg==0 ){ rc = sqlite4BtPageGet(p, pgno, &pRelease); } if( rc==SQLITE4_OK ){ BtPage *pTrunk = pPg ? pPg : pRelease; rc = sqlite4BtPageWrite(pTrunk); if( rc==SQLITE4_OK ){ sqlite4BtPutU32(&pTrunk->aData[0], 0); sqlite4BtPutU32(&pTrunk->aData[4], pHdr->iFreePg); pHdr->iFreePg = pgno; sqlite4BtDebugPageFree((BtLock*)p, "free-list-trunk", pgno); } } sqlite4BtPageRelease(pRelease); } return rc; } |
︙ | ︙ | |||
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 | if( rc==SQLITE4_OK ){ u8 *aData = pTrunk->aData; u32 nFree = sqlite4BtGetU32(aData); if( nFree==0 ){ u32 iNext = sqlite4BtGetU32(&aData[4]); *pPgno = pHdr->iFreePg; pHdr->iFreePg = iNext; }else{ *pPgno = sqlite4BtGetU32(&aData[8 + 4*(nFree-1)]); sqlite4BtPutU32(aData, nFree-1); } } sqlite4BtPageRelease(pTrunk); } return rc; | > > > | 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 | if( rc==SQLITE4_OK ){ u8 *aData = pTrunk->aData; u32 nFree = sqlite4BtGetU32(aData); if( nFree==0 ){ u32 iNext = sqlite4BtGetU32(&aData[4]); *pPgno = pHdr->iFreePg; pHdr->iFreePg = iNext; sqlite4BtDebugPageAlloc((BtLock*)p, "free-list-trunk", *pPgno); }else{ *pPgno = sqlite4BtGetU32(&aData[8 + 4*(nFree-1)]); sqlite4BtPutU32(aData, nFree-1); sqlite4BtDebugPageAlloc((BtLock*)p, "free-list", *pPgno); assert( *pPgno < 1000000 ); } } sqlite4BtPageRelease(pTrunk); } return rc; |
︙ | ︙ | |||
949 950 951 952 953 954 955 956 957 958 959 960 961 962 | /* Find the page number of the new page. There are two ways a page may ** be allocated - from the free-list or by appending it to the end of ** the database file. */ rc = btFreelistAlloc(p, &pgno); if( rc==SQLITE4_OK && pgno==0 ){ pgno = p->pHdr->nPg+1; } rc = sqlite4BtPageGet(p, pgno, &pPg); if( rc==SQLITE4_OK ){ rc = sqlite4BtPageWrite(pPg); if( rc!=SQLITE4_OK ){ sqlite4BtPageRelease(pPg); | > | 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 | /* Find the page number of the new page. There are two ways a page may ** be allocated - from the free-list or by appending it to the end of ** the database file. */ rc = btFreelistAlloc(p, &pgno); if( rc==SQLITE4_OK && pgno==0 ){ pgno = p->pHdr->nPg+1; sqlite4BtDebugPageAlloc((BtLock*)p, "end-of-file", pgno); } rc = sqlite4BtPageGet(p, pgno, &pPg); if( rc==SQLITE4_OK ){ rc = sqlite4BtPageWrite(pPg); if( rc!=SQLITE4_OK ){ sqlite4BtPageRelease(pPg); |
︙ | ︙ |