Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add code to free pages and blocks. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
1a0d07f113cf04a7ca902c80fc6fb239 |
User & Date: | dan 2013-11-21 18:46:03.693 |
Context
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 | |
2013-11-20
| ||
19:23 | Combine the bt database and shm headers. check-in: 1512aee6f6 user: dan tags: trunk | |
Changes
Changes to src/btInt.h.
︙ | ︙ | |||
34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #endif #ifndef MAX # define MAX(a,b) (((a)>(b))?(a):(b)) #endif /* By default pages are 1024 bytes in size. */ #define BT_DEFAULT_PGSZ 1024 /************************************************************************* ** Interface to bt_pager.c functionality. */ typedef struct BtPage BtPage; typedef struct BtPager BtPager; | > > > > > > > > > > > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #endif #ifndef MAX # define MAX(a,b) (((a)>(b))?(a):(b)) #endif /* By default pages are 1024 bytes in size. */ #define BT_DEFAULT_PGSZ 1024 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. */ typedef struct BtPage BtPage; typedef struct BtPager BtPager; |
︙ | ︙ | |||
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | int sqlite4BtLogSnapshotEndWrite(BtLog*); int sqlite4BtLogSize(BtLog*); int sqlite4BtLogCheckpoint(BtLog*, int); int sqlite4BtLogFrameToIdx(u32 *aLog, u32 iFrame); int sqlite4BtLogPagesize(BtLog*); int sqlite4BtLogPagecount(BtLog*); u32 sqlite4BtLogCookie(BtLog*); int sqlite4BtLogSetCookie(BtLog*, u32 iCookie); /* ** End of bt_log.c interface. *************************************************************************/ /************************************************************************* | > > > > | 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | int sqlite4BtLogSnapshotEndWrite(BtLog*); int sqlite4BtLogSize(BtLog*); int sqlite4BtLogCheckpoint(BtLog*, int); int sqlite4BtLogFrameToIdx(u32 *aLog, u32 iFrame); #if 0 int sqlite4BtLogPagesize(BtLog*); int sqlite4BtLogPagecount(BtLog*); u32 sqlite4BtLogCookie(BtLog*); #endif BtDbHdr *sqlite4BtLogDbhdr(BtLog*); int sqlite4BtLogSetCookie(BtLog*, u32 iCookie); /* ** End of bt_log.c interface. *************************************************************************/ /************************************************************************* |
︙ | ︙ | |||
264 265 266 267 268 269 270 271 272 273 274 275 276 277 | ** End of bt_lock.c interface. *************************************************************************/ /************************************************************************* ** Utility functions */ void sqlite4BtPutU32(u8 *a, u32 i); /* ** End of utility interface. *************************************************************************/ #ifdef NDEBUG # define sqlite4BtDebugReadPage(a,b,c,d) | > | 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | ** End of bt_lock.c interface. *************************************************************************/ /************************************************************************* ** Utility functions */ void sqlite4BtPutU32(u8 *a, u32 i); u32 sqlite4BtGetU32(const u8 *a); /* ** End of utility interface. *************************************************************************/ #ifdef NDEBUG # define sqlite4BtDebugReadPage(a,b,c,d) |
︙ | ︙ |
Changes to src/bt_log.c.
︙ | ︙ | |||
825 826 827 828 829 830 831 | return SQLITE4_OK; } } } memset(pHdr, 0, sizeof(BtDbHdr)); pHdr->pgsz = BT_DEFAULT_PGSZ; | | | 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 | return SQLITE4_OK; } } } memset(pHdr, 0, sizeof(BtDbHdr)); pHdr->pgsz = BT_DEFAULT_PGSZ; pHdr->nPg = 2; pHdr->iRoot = 2; return rc; } static int btLogUpdateDbhdr(BtLog *pLog, u8 *aData){ BtDbHdrCksum hdr; |
︙ | ︙ | |||
1064 1065 1066 1067 1068 1069 1070 | /* ** If parameter iSafe is non-zero, then this function is being called as ** part of a checkpoint operation. In this case, if there exists a version ** of page pgno within the log at some point past frame iSafe, return ** SQLITE4_NOTFOUND. */ int btLogRead(BtLog *pLog, u32 pgno, u8 *aData, u32 iSafe){ | | | 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 | /* ** If parameter iSafe is non-zero, then this function is being called as ** part of a checkpoint operation. In this case, if there exists a version ** of page pgno within the log at some point past frame iSafe, return ** SQLITE4_NOTFOUND. */ int btLogRead(BtLog *pLog, u32 pgno, u8 *aData, u32 iSafe){ const int pgsz = pLog->snapshot.dbhdr.pgsz; int rc = SQLITE4_NOTFOUND; u32 iFrame = 0; int i; u32 *aLog = pLog->snapshot.aLog; int iSafeIdx = sqlite4BtLogFrameToIdx(aLog, iSafe); |
︙ | ︙ | |||
1147 1148 1149 1150 1151 1152 1153 | if( rc==SQLITE4_OK ){ memset(aHash, 0, sizeof(ht_slot)*HASHTABLE_NSLOT); } return rc; } static int btLogWriteFrame(BtLog *pLog, int nPad, u32 pgno, u8 *aData, u32 nPg){ | | | 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 | if( rc==SQLITE4_OK ){ memset(aHash, 0, sizeof(ht_slot)*HASHTABLE_NSLOT); } return rc; } static int btLogWriteFrame(BtLog *pLog, int nPad, u32 pgno, u8 *aData, u32 nPg){ const int pgsz = pLog->snapshot.dbhdr.pgsz; u32 *aLog = pLog->snapshot.aLog; int rc = SQLITE4_OK; /* Return code */ u32 iFrame; /* Write this frame (numbered from 1) */ u32 iNextFrame; /* Frame to write following this one */ i64 iOff; /* Offset of log file to write to */ BtFrameHdr frame; /* Header for new frame */ |
︙ | ︙ | |||
1258 1259 1260 1261 1262 1263 1264 | return rc; } /* ** Write a frame to the log file. */ int sqlite4BtLogWrite(BtLog *pLog, u32 pgno, u8 *aData, u32 nPg){ | | | | 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 | return rc; } /* ** Write a frame to the log file. */ int sqlite4BtLogWrite(BtLog *pLog, u32 pgno, u8 *aData, u32 nPg){ const int pgsz = pLog->snapshot.dbhdr.pgsz; int rc = SQLITE4_OK; int nPad = 0; if( pLog->pLock->iSafetyLevel==BT_SAFETY_FULL ){ nPad = (pLog->snapshot.nSector + pgsz-1) / pgsz; } /* If this is a commit frame and the size of the database has changed, ** ensure that the log file contains at least one copy of page 1 written ** since the last checkpoint. This is required as a future checkpoint ** will need to update the nPg field in the database header located on ** page 1. */ if( nPg /* && nPg!=pLog->snapshot.dbhdr.nPg */ ){ BtPager *pPager = (BtPager *)(pLog->pLock); BtPage *pOne = 0; rc = sqlite4BtPageGet(pPager, 1, &pOne); if( rc==SQLITE4_OK ){ rc = sqlite4BtLogWrite(pLog, 1, sqlite4BtPageData(pOne), 0); sqlite4BtPageRelease(pOne); } |
︙ | ︙ | |||
1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 | sqlite4_free(pLock->pEnv, aBuf); sqlite4_free(pLock->pEnv, aPgno); sqlite4BtLockCkptUnlock(pLog->pLock); } return rc; } /* ** Return the database page size in bytes. */ int sqlite4BtLogPagesize(BtLog *pLog){ return pLog->snapshot.dbhdr.pgsz; } /* ** Return the number of pages in the database at last commit. */ int sqlite4BtLogPagecount(BtLog *pLog){ return (pLog->snapshot.dbhdr.nPg==1 ? 2 : pLog->snapshot.dbhdr.nPg); } /* ** Return the current value of the user cookie. */ u32 sqlite4BtLogCookie(BtLog *pLog){ return pLog->snapshot.dbhdr.iCookie; } /* ** Set the value of the user cookie. */ int sqlite4BtLogSetCookie(BtLog *pLog, u32 iCookie){ BtPager *pPager = (BtPager *)(pLog->pLock); | > > > > > > | 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 | sqlite4_free(pLock->pEnv, aBuf); sqlite4_free(pLock->pEnv, aPgno); sqlite4BtLockCkptUnlock(pLog->pLock); } return rc; } #if 0 /* ** Return the database page size in bytes. */ int sqlite4BtLogPagesize(BtLog *pLog){ return pLog->snapshot.dbhdr.pgsz; } /* ** Return the number of pages in the database at last commit. */ int sqlite4BtLogPagecount(BtLog *pLog){ return (pLog->snapshot.dbhdr.nPg==1 ? 2 : pLog->snapshot.dbhdr.nPg); } /* ** Return the current value of the user cookie. */ u32 sqlite4BtLogCookie(BtLog *pLog){ return pLog->snapshot.dbhdr.iCookie; } #endif BtDbHdr *sqlite4BtLogDbhdr(BtLog *pLog){ return &pLog->snapshot.dbhdr; } /* ** Set the value of the user cookie. */ int sqlite4BtLogSetCookie(BtLog *pLog, u32 iCookie){ BtPager *pPager = (BtPager *)(pLog->pLock); |
︙ | ︙ |
Changes to src/bt_main.c.
︙ | ︙ | |||
80 81 82 83 84 85 86 | # define btCheckPageRefs(x) #endif /* ** Interpret the first 4 bytes of the buffer indicated by the first ** parameter as a 32-bit unsigned big-endian integer. */ | | > | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | # define btCheckPageRefs(x) #endif /* ** Interpret the first 4 bytes of the buffer indicated by the first ** parameter as a 32-bit unsigned big-endian integer. */ u32 sqlite4BtGetU32(const u8 *a){ return ((u32)a[0] << 24) + ((u32)a[1] << 16) + ((u32)a[2] << 8) + ((u32)a[3]); } #define btGetU32(x) sqlite4BtGetU32(x) /* ** Interpret the first 2 bytes of the buffer indicated by the first ** parameter as a 16-bit unsigned big-endian integer. */ static u16 btGetU16(const u8 *a){ return ((u32)a[0] << 8) + (u32)a[1]; |
︙ | ︙ |
Changes to src/bt_pager.c.
︙ | ︙ | |||
89 90 91 92 93 94 95 | int nFile; /* Length of string zFile in bytes */ BtPageHash hash; /* Hash table */ BtPage *pDirty; /* List of all dirty pages */ int nTotalRef; /* Total number of outstanding page refs */ int bDoAutoCkpt; /* Do auto-checkpoint after next unlock */ BtSavepoint *aSavepoint; /* Savepoint array */ int nSavepoint; /* Number of entries in aSavepoint array */ | < < | | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | int nFile; /* Length of string zFile in bytes */ BtPageHash hash; /* Hash table */ BtPage *pDirty; /* List of all dirty pages */ int nTotalRef; /* Total number of outstanding page refs */ int bDoAutoCkpt; /* Do auto-checkpoint after next unlock */ BtSavepoint *aSavepoint; /* Savepoint array */ int nSavepoint; /* Number of entries in aSavepoint array */ BtDbHdr *pHdr; /* Header object for current read snapshot */ void *pLogsizeCtx; /* A copy of this is passed to xLogsize() */ void (*xLogsize)(void*, int); /* Log-size Callback function */ }; /************************************************************************** ** Interface to BtPageHash object. |
︙ | ︙ | |||
320 321 322 323 324 325 326 | rc = btErrorBkpt(SQLITE4_NOMEM); }else{ memset(pSavepage, 0, sizeof(BtSavepage)); } /* Populate the new BtSavepage structure */ if( rc==SQLITE4_OK && (1 || (pPg->flags & BT_PAGE_DIRTY)) ){ | | | | 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 | rc = btErrorBkpt(SQLITE4_NOMEM); }else{ memset(pSavepage, 0, sizeof(BtSavepage)); } /* Populate the new BtSavepage structure */ if( rc==SQLITE4_OK && (1 || (pPg->flags & BT_PAGE_DIRTY)) ){ pSavepage->aData = (u8*)sqlite4_malloc(p->btl.pEnv, p->pHdr->pgsz); if( pSavepage->aData==0 ){ sqlite4_free(p->btl.pEnv, pSavepage); rc = btErrorBkpt(SQLITE4_NOMEM); }else{ memcpy(pSavepage->aData, pPg->aData, p->pHdr->pgsz); } } /* Link the new BtSavepage structure into the pPg->pSavepage list */ if( rc==SQLITE4_OK ){ pSavepage->pPg = pPg; pSavepage->iSavepoint = iLevel; |
︙ | ︙ | |||
382 383 384 385 386 387 388 | pNext = pSavepg->pNext; assert( pSavepg==pPg->pSavepage ); assert( pSavepg->iSavepoint==pSavepoint->iLevel ); /* If bRollback is set, restore the page data */ if( bRollback ){ | | | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | pNext = pSavepg->pNext; assert( pSavepg==pPg->pSavepage ); assert( pSavepg->iSavepoint==pSavepoint->iLevel ); /* If bRollback is set, restore the page data */ if( bRollback ){ memcpy(pPg->aData, pSavepg->aData, p->pHdr->pgsz); }else{ int iNextSaved = ( pSavepg->pNextSavepage ? pSavepg->pNextSavepage->iSavepoint : 2 ); if( iLevel>iNextSaved ){ assert( iLevel>=3 ); assert( p->aSavepoint[iLevel-3].iLevel==iLevel ); |
︙ | ︙ | |||
491 492 493 494 495 496 497 498 499 500 501 502 503 504 | ** Open a read-transaction. */ static int btOpenReadTransaction(BtPager *p){ int rc; assert( p->iTransactionLevel==0 ); assert( p->btl.pFd ); rc = sqlite4BtLogSnapshotOpen(p->pLog); if( rc==SQLITE4_OK ){ /* If the read transaction was successfully opened, the transaction ** level is now 1. */ p->iTransactionLevel = 1; | > | < > > > | 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 | ** Open a read-transaction. */ static int btOpenReadTransaction(BtPager *p){ int rc; assert( p->iTransactionLevel==0 ); assert( p->btl.pFd ); assert( p->pHdr==0 ); rc = sqlite4BtLogSnapshotOpen(p->pLog); if( rc==SQLITE4_OK ){ /* If the read transaction was successfully opened, the transaction ** level is now 1. */ p->iTransactionLevel = 1; p->pHdr = sqlite4BtLogDbhdr(p->pLog); } return rc; } static int btOpenWriteTransaction(BtPager *p){ int rc; assert( p->iTransactionLevel==1 ); assert( p->btl.pFd ); rc = sqlite4BtLogSnapshotWrite(p->pLog); return rc; } static int btCloseReadTransaction(BtPager *p){ int rc; assert( p->iTransactionLevel==0 ); assert( p->pHdr ); p->pHdr = 0; rc = sqlite4BtLogSnapshotClose(p->pLog); /* Purge the page cache. */ assert( p->pDirty==0 ); btPurgeCache(p); if( rc==SQLITE4_OK && p->bDoAutoCkpt ){ |
︙ | ︙ | |||
547 548 549 550 551 552 553 | btCloseSavepoints(p, 2, 0); for(pPg=p->pDirty; pPg; pPg=pNext){ pNext = pPg->pNextDirty; pPg->flags &= ~(BT_PAGE_DIRTY); pPg->pNextDirty = 0; if( rc==SQLITE4_OK ){ | | | 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 | btCloseSavepoints(p, 2, 0); for(pPg=p->pDirty; pPg; pPg=pNext){ pNext = pPg->pNextDirty; pPg->flags &= ~(BT_PAGE_DIRTY); pPg->pNextDirty = 0; if( rc==SQLITE4_OK ){ int nPg = ((pNext==0) ? p->pHdr->nPg : 0); rc = sqlite4BtLogWrite(p->pLog, pPg->pgno, pPg->aData, nPg); } } p->pDirty = 0; sqlite4BtLogSnapshotEndWrite(p->pLog); nLogsize = sqlite4BtLogSize(p->pLog); |
︙ | ︙ | |||
577 578 579 580 581 582 583 | ** data was loaded successfully. If SQLITE4_NOTFOUND, the required page ** is not present in the log and should be loaded from the database ** file. Any other error code is returned to the caller. */ rc = sqlite4BtLogRead(p->pLog, pPg->pgno, pPg->aData); /* If necessary, load data from the database file. */ if( rc==SQLITE4_NOTFOUND ){ | | | | | 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 | ** data was loaded successfully. If SQLITE4_NOTFOUND, the required page ** is not present in the log and should be loaded from the database ** file. Any other error code is returned to the caller. */ rc = sqlite4BtLogRead(p->pLog, pPg->pgno, pPg->aData); /* If necessary, load data from the database file. */ if( rc==SQLITE4_NOTFOUND ){ i64 iOff = (i64)p->pHdr->pgsz * (i64)(pPg->pgno-1); rc = p->btl.pVfs->xRead(p->btl.pFd, iOff, pPg->aData, p->pHdr->pgsz); } return rc; } static int btAllocatePage(BtPager *p, BtPage **ppPg){ int rc; /* Return code */ BtPage *pRet; u8 *aData; pRet = (BtPage*)sqlite4_malloc(p->btl.pEnv, sizeof(BtPage)); aData = (u8*)sqlite4_malloc(p->btl.pEnv, p->pHdr->pgsz); if( pRet && aData ){ memset(pRet, 0, sizeof(BtPage)); pRet->aData = aData; pRet->pPager = p; rc = SQLITE4_OK; }else{ |
︙ | ︙ | |||
628 629 630 631 632 633 634 | for(pPg=p->pDirty; pPg; pPg=pNext){ pNext = pPg->pNextDirty; pPg->flags &= ~(BT_PAGE_DIRTY); pPg->pNextDirty = 0; if( pPg->nRef==0 ){ btHashRemove(p, pPg); btFreePage(p, pPg); | | | 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 | for(pPg=p->pDirty; pPg; pPg=pNext){ pNext = pPg->pNextDirty; pPg->flags &= ~(BT_PAGE_DIRTY); pPg->pNextDirty = 0; if( pPg->nRef==0 ){ btHashRemove(p, pPg); btFreePage(p, pPg); }else if( rc==SQLITE4_OK && (pPg->pgno<=p->pHdr->nPg) ){ rc = btLoadPageData(p, pPg); } } p->pDirty = 0; return rc; } |
︙ | ︙ | |||
748 749 750 751 752 753 754 | } /* ** Query for the database page size. Requires an open read transaction. */ int sqlite4BtPagerPagesize(BtPager *p){ /* assert( p->iTransactionLevel>=1 && p->btl.pFd ); */ | | | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 | } /* ** Query for the database page size. Requires an open read transaction. */ int sqlite4BtPagerPagesize(BtPager *p){ /* assert( p->iTransactionLevel>=1 && p->btl.pFd ); */ return (int)p->pHdr->pgsz; } /* ** Query for the root page number. Requires an open read transaction. */ u32 sqlite4BtPagerRootpgno(BtPager *p){ assert( p->iTransactionLevel>=1 && p->btl.pFd ); |
︙ | ︙ | |||
774 775 776 777 778 779 780 | pRet = btHashSearch(p, pgno); /* If the page is not in the cache, load it from disk */ if( pRet==0 ){ rc = btAllocatePage(p, &pRet); if( rc==SQLITE4_OK ){ pRet->pgno = pgno; | | | | | 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 | pRet = btHashSearch(p, pgno); /* If the page is not in the cache, load it from disk */ if( pRet==0 ){ rc = btAllocatePage(p, &pRet); if( rc==SQLITE4_OK ){ pRet->pgno = pgno; if( pgno<=p->pHdr->nPg ){ rc = btLoadPageData(p, pRet); }else{ memset(pRet->aData, 0, p->pHdr->pgsz); } if( rc==SQLITE4_OK ){ rc = btHashAdd(p, pRet); } if( rc!=SQLITE4_OK ){ btFreePage(p, pRet); pRet = 0; }else{ sqlite4BtDebugReadPage(&p->btl, pgno, pRet->aData, p->pHdr->pgsz); } } } assert( (pRet!=0)==(rc==SQLITE4_OK) ); if( rc==SQLITE4_OK ){ p->nTotalRef++; |
︙ | ︙ | |||
818 819 820 821 822 823 824 825 826 827 828 829 830 | if( (pPg->flags & BT_PAGE_DIRTY)==0 ){ pPg->flags |= BT_PAGE_DIRTY; pPg->pNextDirty = pPg->pPager->pDirty; pPg->pPager->pDirty = pPg; } return rc; } /* ** Decrement the refcount on page pPg. Also, indicate that page pPg is ** no longer in use. */ int sqlite4BtPageTrim(BtPage *pPg){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < > > | | | 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 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 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 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 | if( (pPg->flags & BT_PAGE_DIRTY)==0 ){ pPg->flags |= BT_PAGE_DIRTY; pPg->pNextDirty = pPg->pPager->pDirty; pPg->pPager->pDirty = pPg; } return rc; } /* ** Add page pgno to the free-page list. If argument pPg is not NULL, then ** it is a reference to page pgno. */ static int btFreelistAdd(BtPager *p, BtPage *pPg, u32 pgno){ BtDbHdr *pHdr = sqlite4BtLogDbhdr(p->pLog); int rc = SQLITE4_OK; int bDone = 0; /* Check if there is space on the first free-list trunk page. If so, ** add the new entry to it. Set variable bDone to indicate that the ** page has already been added to the free-list. */ if( pHdr->iFreePg ){ BtPage *pTrunk; rc = sqlite4BtPageGet(p, pHdr->iFreePg, &pTrunk); if( rc==SQLITE4_OK ){ const int nMax = ((pHdr->pgsz - 8) / 4); 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 ){ sqlite4BtPutU32(&pTrunk->aData[4], 0); sqlite4BtPutU32(&pTrunk->aData[0], pHdr->iFreePg); pHdr->iFreePg = pgno; } } sqlite4BtPageRelease(pRelease); } return rc; } static int btFreelistAlloc(BtPager *p, u32 *pPgno){ BtDbHdr *pHdr = sqlite4BtLogDbhdr(p->pLog); int rc = SQLITE4_OK; assert( *pPgno==0 ); if( pHdr->iFreePg ){ BtPage *pTrunk = 0; rc = sqlite4BtPageGet(p, pHdr->iFreePg, &pTrunk); if( rc==SQLITE4_OK ){ rc = sqlite4BtPageWrite(pTrunk); } 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; } /* ** Decrement the refcount on page pPg. Also, indicate that page pPg is ** no longer in use. */ int sqlite4BtPageTrim(BtPage *pPg){ int rc; /* Return code */ rc = btFreelistAdd(pPg->pPager, pPg, pPg->pgno); sqlite4BtPageRelease(pPg); return rc; } /* ** Page number pgno is no longer in use. */ int sqlite4BtPageTrimPgno(BtPager *pPager, u32 pgno){ return btFreelistAdd(pPager, 0, pgno); } int sqlite4BtPageRelease(BtPage *pPg){ if( pPg ){ assert( pPg->nRef>=1 ); pPg->nRef--; pPg->pPager->nTotalRef--; |
︙ | ︙ | |||
857 858 859 860 861 862 863 | /* ** Allocate a new database page and return a writable reference to it. */ int sqlite4BtPageAllocate(BtPager *p, BtPage **ppPg){ BtPage *pPg = 0; int rc; | | > > > > > > > > | | 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 | /* ** Allocate a new database page and return a writable reference to it. */ int sqlite4BtPageAllocate(BtPager *p, BtPage **ppPg){ BtPage *pPg = 0; int rc; u32 pgno = 0; /* 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); pPg = 0; }else{ p->pHdr->nPg = MAX(p->pHdr->nPg, pgno); } } #ifdef BT_STDERR_DEBUG fprintf(stderr, "allocated page %d\n", pgno); #endif |
︙ | ︙ | |||
905 906 907 908 909 910 911 | } /* ** Set the schema cookie value. Requires an open write-transaction. */ int sqlite4BtPagerGetCookie(BtPager *p, u32 *piVal){ assert( p->iTransactionLevel>=1 ); | | | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 | } /* ** Set the schema cookie value. Requires an open write-transaction. */ int sqlite4BtPagerGetCookie(BtPager *p, u32 *piVal){ assert( p->iTransactionLevel>=1 ); *piVal = p->pHdr->iCookie; return SQLITE4_OK; } const char *sqlite4BtPagerFilename(BtPager *p, int ePagerfile){ const char *zTail; switch( ePagerfile ){ |
︙ | ︙ |