Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Changes to btree.c to avoid the unsigned/signed comparison warnings. (CVS 5911) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
24469dbace433ca89e22274f741f3820 |
User & Date: | danielk1977 2008-11-17 14:20:56.000 |
Context
2008-11-17
| ||
15:31 | Modifications to avoid signed/unsigned warnings in vdbe.c. (CVS 5912) (check-in: 9939dd839a user: danielk1977 tags: trunk) | |
14:20 | Changes to btree.c to avoid the unsigned/signed comparison warnings. (CVS 5911) (check-in: 24469dbace user: danielk1977 tags: trunk) | |
08:05 | Added support for vxworks >= 6.4; RTP mode tested, kernel mode untested. (CVS 5910) (check-in: f45a149363 user: chw 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.537 2008/11/17 14:20:56 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ #include "btreeInt.h" |
︙ | ︙ | |||
431 432 433 434 435 436 437 | #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Given a page number of a regular database page, return the page ** number for the pointer-map page that contains the entry for the ** input page number. */ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ | | > | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 | #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Given a page number of a regular database page, return the page ** number for the pointer-map page that contains the entry for the ** input page number. */ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ int nPagesPerMapPage; Pgno iPtrMap, ret; assert( sqlite3_mutex_held(pBt->mutex) ); nPagesPerMapPage = (pBt->usableSize/5)+1; iPtrMap = (pgno-2)/nPagesPerMapPage; ret = (iPtrMap*nPagesPerMapPage) + 2; if( ret==PENDING_BYTE_PAGE(pBt) ){ ret++; } |
︙ | ︙ | |||
1104 1105 1106 1107 1108 1109 1110 | rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent); if( rc ) return rc; *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt); return SQLITE_OK; } /* | | | | > | | | > | 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 | rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent); if( rc ) return rc; *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt); return SQLITE_OK; } /* ** Return the size of the database file in pages. If there is any kind of ** error, return ((unsigned int)-1). */ static Pgno pagerPagecount(BtShared *pBt){ int nPage = -1; int rc; assert( pBt->pPage1 ); rc = sqlite3PagerPagecount(pBt->pPager, &nPage); assert( rc==SQLITE_OK || nPage==-1 ); return (Pgno)nPage; } /* ** Get a page from the pager and initialize it. This routine ** is just a convenience wrapper around separate calls to ** sqlite3BtreeGetPage() and sqlite3BtreeInitPage(). */ |
︙ | ︙ | |||
1145 1146 1147 1148 1149 1150 1151 | pDbPage = sqlite3PagerLookup(pBt->pPager, pgno); if( pDbPage ){ /* Page is already in cache */ *ppPage = pPage = btreePageFromDbPage(pDbPage, pgno, pBt); rc = SQLITE_OK; }else{ /* Page not in cache. Acquire it. */ | | | 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 | pDbPage = sqlite3PagerLookup(pBt->pPager, pgno); if( pDbPage ){ /* Page is already in cache */ *ppPage = pPage = btreePageFromDbPage(pDbPage, pgno, pBt); rc = SQLITE_OK; }else{ /* Page not in cache. Acquire it. */ if( pgno>pagerPagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0); if( rc ) return rc; pPage = *ppPage; } if( !pPage->isInit ){ |
︙ | ︙ | |||
2263 2264 2265 2266 2267 2268 2269 | static int incrVacuumStep(BtShared *pBt, Pgno nFin){ Pgno iLastPg; /* Last page in the database */ Pgno nFreeList; /* Number of pages still on the free-list */ assert( sqlite3_mutex_held(pBt->mutex) ); iLastPg = pBt->nTrunc; if( iLastPg==0 ){ | | | 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 | static int incrVacuumStep(BtShared *pBt, Pgno nFin){ Pgno iLastPg; /* Last page in the database */ Pgno nFreeList; /* Number of pages still on the free-list */ assert( sqlite3_mutex_held(pBt->mutex) ); iLastPg = pBt->nTrunc; if( iLastPg==0 ){ iLastPg = pagerPagecount(pBt); } if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ int rc; u8 eType; Pgno iPtrPage; |
︙ | ︙ | |||
2394 2395 2396 2397 2398 2399 2400 | if( !pBt->incrVacuum ){ Pgno nFin = 0; if( pBt->nTrunc==0 ){ Pgno nFree; Pgno nPtrmap; const int pgsz = pBt->pageSize; | | | 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 | if( !pBt->incrVacuum ){ Pgno nFin = 0; if( pBt->nTrunc==0 ){ Pgno nFree; Pgno nPtrmap; const int pgsz = pBt->pageSize; Pgno nOrig = pagerPagecount(pBt); if( PTRMAP_ISPAGE(pBt, nOrig) ){ return SQLITE_CORRUPT_BKPT; } if( nOrig==PENDING_BYTE_PAGE(pBt) ){ nOrig--; } |
︙ | ︙ | |||
2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 | Btree *p, /* The btree */ int iTable, /* Root page of table to open */ int wrFlag, /* 1 to write. 0 read-only */ struct KeyInfo *pKeyInfo, /* First arg to comparison function */ BtCursor *pCur /* Space for new cursor */ ){ int rc; BtShared *pBt = p->pBt; assert( sqlite3BtreeHoldsMutex(p) ); if( wrFlag ){ if( pBt->readOnly ){ return SQLITE_READONLY; } | > | 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 | Btree *p, /* The btree */ int iTable, /* Root page of table to open */ int wrFlag, /* 1 to write. 0 read-only */ struct KeyInfo *pKeyInfo, /* First arg to comparison function */ BtCursor *pCur /* Space for new cursor */ ){ int rc; Pgno nPage; BtShared *pBt = p->pBt; assert( sqlite3BtreeHoldsMutex(p) ); if( wrFlag ){ if( pBt->readOnly ){ return SQLITE_READONLY; } |
︙ | ︙ | |||
2822 2823 2824 2825 2826 2827 2828 | return rc; } if( pBt->readOnly && wrFlag ){ return SQLITE_READONLY; } } pCur->pgnoRoot = (Pgno)iTable; | > > > > | | 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 | return rc; } if( pBt->readOnly && wrFlag ){ return SQLITE_READONLY; } } pCur->pgnoRoot = (Pgno)iTable; rc = sqlite3PagerPagecount(pBt->pPager, (int *)&nPage); if( rc!=SQLITE_OK ){ return rc; } if( iTable==1 && nPage==0 ){ rc = SQLITE_EMPTY; goto create_cursor_exception; } rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]); if( rc!=SQLITE_OK ){ goto create_cursor_exception; } |
︙ | ︙ | |||
3083 3084 3085 3086 3087 3088 3089 | Pgno iGuess = ovfl+1; u8 eType; while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){ iGuess++; } | | | 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 | Pgno iGuess = ovfl+1; u8 eType; while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){ iGuess++; } if( iGuess<=pagerPagecount(pBt) ){ rc = ptrmapGet(pBt, iGuess, &eType, &pgno); if( rc!=SQLITE_OK ){ return rc; } if( eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){ next = iGuess; } |
︙ | ︙ | |||
3179 3180 3181 3182 3183 3184 3185 | ** ** * An incremental vacuum, ** * A commit in auto_vacuum="full" mode, ** * Creating a table (may require moving an overflow page). */ static int accessPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ | | | < | 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 | ** ** * An incremental vacuum, ** * A commit in auto_vacuum="full" mode, ** * Creating a table (may require moving an overflow page). */ static int accessPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ u32 offset, /* Begin reading this far into payload */ u32 amt, /* Read this many bytes */ unsigned char *pBuf, /* Write the bytes into this buffer */ int skipKey, /* offset begins at data if this is true */ int eOp /* zero to read. non-zero to write. */ ){ unsigned char *aPayload; int rc = SQLITE_OK; u32 nKey; int iIdx = 0; MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */ BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ assert( pPage ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->aiIdx[pCur->iPage]<pPage->nCell ); assert( cursorHoldsMutex(pCur) ); getCellInfo(pCur); aPayload = pCur->info.pCell + pCur->info.nHeader; nKey = (pPage->intKey ? 0 : pCur->info.nKey); if( skipKey ){ |
︙ | ︙ | |||
3227 3228 3229 3230 3231 3232 3233 | pBuf += a; amt -= a; }else{ offset -= pCur->info.nLocal; } if( rc==SQLITE_OK && amt>0 ){ | | | 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 | pBuf += a; amt -= a; }else{ offset -= pCur->info.nLocal; } if( rc==SQLITE_OK && amt>0 ){ const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ Pgno nextPage; nextPage = get4byte(&aPayload[pCur->info.nLocal]); #ifndef SQLITE_OMIT_INCRBLOB /* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[] ** has not been allocated, allocate it now. The array is sized at |
︙ | ︙ | |||
3394 3395 3396 3397 3398 3399 3400 | BtCursor *pCur, /* Cursor pointing to entry to read from */ int *pAmt, /* Write the number of available bytes here */ int skipKey /* read beginning at data if this is true */ ){ unsigned char *aPayload; MemPage *pPage; u32 nKey; | | | 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 | BtCursor *pCur, /* Cursor pointing to entry to read from */ int *pAmt, /* Write the number of available bytes here */ int skipKey /* read beginning at data if this is true */ ){ unsigned char *aPayload; MemPage *pPage; u32 nKey; u32 nLocal; assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); assert( pCur->eState==CURSOR_VALID ); assert( cursorHoldsMutex(pCur) ); pPage = pCur->apPage[pCur->iPage]; assert( pCur->aiIdx[pCur->iPage]<pPage->nCell ); getCellInfo(pCur); |
︙ | ︙ | |||
4084 4085 4086 4087 4088 4089 4090 | u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ /* If the 'exact' parameter was true and a query of the pointer-map ** shows that the page 'nearby' is somewhere on the free-list, then ** the entire-list will be searched for that page. */ #ifndef SQLITE_OMIT_AUTOVACUUM | | | 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 | u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ /* If the 'exact' parameter was true and a query of the pointer-map ** shows that the page 'nearby' is somewhere on the free-list, then ** the entire-list will be searched for that page. */ #ifndef SQLITE_OMIT_AUTOVACUUM if( exact && nearby<=pagerPagecount(pBt) ){ u8 eType; assert( nearby>0 ); assert( pBt->autoVacuum ); rc = ptrmapGet(pBt, nearby, &eType, 0); if( rc ) return rc; if( eType==PTRMAP_FREEPAGE ){ searchList = 1; |
︙ | ︙ | |||
4219 4220 4221 4222 4223 4224 4225 | } }else{ closest = 0; } iPage = get4byte(&aData[8+closest*4]); if( !searchList || iPage==nearby ){ | | | | 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 | } }else{ closest = 0; } iPage = get4byte(&aData[8+closest*4]); if( !searchList || iPage==nearby ){ Pgno nPage; *pPgno = iPage; nPage = pagerPagecount(pBt); if( *pPgno>nPage ){ /* Free page off the end of the file */ rc = SQLITE_CORRUPT_BKPT; goto end_allocate_page; } TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" ": %d more free pages\n", |
︙ | ︙ | |||
4251 4252 4253 4254 4255 4256 4257 | } releasePage(pPrevTrunk); pPrevTrunk = 0; }while( searchList ); }else{ /* There are no pages on the freelist, so create a new page at the ** end of the file */ | | | 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 | } releasePage(pPrevTrunk); pPrevTrunk = 0; }while( searchList ); }else{ /* There are no pages on the freelist, so create a new page at the ** end of the file */ int nPage = pagerPagecount(pBt); *pPgno = nPage + 1; #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->nTrunc ){ /* An incr-vacuum has already run within this transaction. So the ** page to allocate is not from the physical end of the file, but ** at pBt->nTrunc. |
︙ | ︙ | |||
4418 4419 4420 4421 4422 4423 4424 | } ovflPgno = get4byte(&pCell[info.iOverflow]); ovflPageSize = pBt->usableSize - 4; nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; assert( ovflPgno==0 || nOvfl>0 ); while( nOvfl-- ){ MemPage *pOvfl; | | | 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 | } ovflPgno = get4byte(&pCell[info.iOverflow]); ovflPageSize = pBt->usableSize - 4; nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; assert( ovflPgno==0 || nOvfl>0 ); while( nOvfl-- ){ MemPage *pOvfl; if( ovflPgno==0 || ovflPgno>pagerPagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } rc = getOverflowPage(pBt, ovflPgno, &pOvfl, (nOvfl==0)?0:&ovflPgno); if( rc ) return rc; rc = freePage(pOvfl); sqlite3PagerUnref(pOvfl->pDbPage); |
︙ | ︙ | |||
4480 4481 4482 4483 4484 4485 4486 | }else{ nData = nZero = 0; } nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey); sqlite3BtreeParseCellPtr(pPage, pCell, &info); assert( info.nHeader==nHeader ); assert( info.nKey==nKey ); | | | 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 | }else{ nData = nZero = 0; } nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey); sqlite3BtreeParseCellPtr(pPage, pCell, &info); assert( info.nHeader==nHeader ); assert( info.nKey==nKey ); assert( info.nData==(u32)(nData+nZero) ); /* Fill in the payload */ nPayload = nData + nZero; if( pPage->intKey ){ pSrc = pData; nSrc = nData; nData = 0; |
︙ | ︙ | |||
4652 4653 4654 4655 4656 4657 4658 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pTemp ){ memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); pCell = pTemp; } j = pPage->nOverflow++; | | | 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 | assert( sqlite3_mutex_held(pPage->pBt->mutex) ); if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pTemp ){ memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); pCell = pTemp; } j = pPage->nOverflow++; assert( j<(int)(sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0])) ); pPage->aOvfl[j].pCell = pCell; pPage->aOvfl[j].idx = i; pPage->nFree = 0; }else{ int rc = sqlite3PagerWrite(pPage->pDbPage); if( rc!=SQLITE_OK ){ return rc; |
︙ | ︙ | |||
5539 5540 5541 5542 5543 5544 5545 | ** case, then do not do the transfer. Leave page 1 empty except ** for the right-pointer to the child page. The child page becomes ** the virtual root of the tree. */ VVA_ONLY( pCur->pagesShuffled = 1 ); pgnoChild = get4byte(&pPage->aData[pPage->hdrOffset+8]); assert( pgnoChild>0 ); | | | 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 | ** case, then do not do the transfer. Leave page 1 empty except ** for the right-pointer to the child page. The child page becomes ** the virtual root of the tree. */ VVA_ONLY( pCur->pagesShuffled = 1 ); pgnoChild = get4byte(&pPage->aData[pPage->hdrOffset+8]); assert( pgnoChild>0 ); assert( pgnoChild<=pagerPagecount(pPage->pBt) ); rc = sqlite3BtreeGetPage(pPage->pBt, pgnoChild, &pChild, 0); if( rc ) goto end_shallow_balance; if( pPage->pgno==1 ){ rc = sqlite3BtreeInitPage(pChild); if( rc ) goto end_shallow_balance; assert( pChild->nOverflow==0 ); if( pChild->nFree>=100 ){ |
︙ | ︙ | |||
6237 6238 6239 6240 6241 6242 6243 | ){ MemPage *pPage = 0; int rc; unsigned char *pCell; int i; assert( sqlite3_mutex_held(pBt->mutex) ); | | | 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 | ){ MemPage *pPage = 0; int rc; unsigned char *pCell; int i; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>pagerPagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } rc = getAndInitPage(pBt, pgno, &pPage); if( rc ) goto cleardatabasepage_out; for(i=0; i<pPage->nCell; i++){ pCell = findCell(pPage, i); |
︙ | ︙ | |||
6321 6322 6323 6324 6325 6326 6327 | ** root pages are kept at the beginning of the database file, which ** is necessary for AUTOVACUUM to work right. *piMoved is set to the ** page number that used to be the last root page in the file before ** the move. If no page gets moved, *piMoved is set to 0. ** The last root page is recorded in meta[3] and the value of ** meta[3] is updated by this procedure. */ | | | 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 | ** root pages are kept at the beginning of the database file, which ** is necessary for AUTOVACUUM to work right. *piMoved is set to the ** page number that used to be the last root page in the file before ** the move. If no page gets moved, *piMoved is set to 0. ** The last root page is recorded in meta[3] and the value of ** meta[3] is updated by this procedure. */ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){ int rc; MemPage *pPage = 0; BtShared *pBt = p->pBt; assert( sqlite3BtreeHoldsMutex(p) ); if( p->inTrans!=TRANS_WRITE ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; |
︙ | ︙ | |||
6604 6605 6606 6607 6608 6609 6610 | ** Add 1 to the reference count for page iPage. If this is the second ** reference to the page, add an error message to pCheck->zErrMsg. ** Return 1 if there are 2 ore more references to the page and 0 if ** if this is the first reference to the page. ** ** Also check that the page number is in bounds. */ | | | | 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 | ** Add 1 to the reference count for page iPage. If this is the second ** reference to the page, add an error message to pCheck->zErrMsg. ** Return 1 if there are 2 ore more references to the page and 0 if ** if this is the first reference to the page. ** ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, Pgno iPage, char *zContext){ if( iPage==0 ) return 1; if( iPage>pCheck->nPage ){ checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); return 1; } if( pCheck->anRef[iPage]==1 ){ checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage); return 1; } |
︙ | ︙ | |||
6779 6780 6781 6782 6783 6784 6785 | } /* Check out all the cells. */ depth = 0; for(i=0; i<pPage->nCell && pCheck->mxErr; i++){ u8 *pCell; | | | 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 | } /* Check out all the cells. */ depth = 0; for(i=0; i<pPage->nCell && pCheck->mxErr; i++){ u8 *pCell; u32 sz; CellInfo info; /* Check payload overflow pages */ sqlite3_snprintf(sizeof(zContext), zContext, "On tree page %d cell %d: ", iPage, i); pCell = findCell(pPage,i); |
︙ | ︙ | |||
6915 6916 6917 6918 6919 6920 6921 | char *sqlite3BtreeIntegrityCheck( Btree *p, /* The btree to be checked */ int *aRoot, /* An array of root pages numbers for individual trees */ int nRoot, /* Number of entries in aRoot[] */ int mxErr, /* Stop reporting errors after this many */ int *pnErr /* Write number of errors seen to this variable */ ){ | | | | 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 | char *sqlite3BtreeIntegrityCheck( Btree *p, /* The btree to be checked */ int *aRoot, /* An array of root pages numbers for individual trees */ int nRoot, /* Number of entries in aRoot[] */ int mxErr, /* Stop reporting errors after this many */ int *pnErr /* Write number of errors seen to this variable */ ){ Pgno i; int nRef; IntegrityCk sCheck; BtShared *pBt = p->pBt; char zErr[100]; sqlite3BtreeEnter(p); pBt->db = p->db; nRef = sqlite3PagerRefcount(pBt->pPager); if( lockBtreeWithRetry(p)!=SQLITE_OK ){ *pnErr = 1; sqlite3BtreeLeave(p); return sqlite3DbStrDup(0, "cannot acquire a read lock on the database"); } sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; sCheck.nPage = pagerPagecount(sCheck.pBt); sCheck.mxErr = mxErr; sCheck.nErr = 0; sCheck.mallocFailed = 0; *pnErr = 0; #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->nTrunc!=0 ){ sCheck.nPage = pBt->nTrunc; |
︙ | ︙ | |||
6967 6968 6969 6970 6971 6972 6973 | /* Check the integrity of the freelist */ checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), get4byte(&pBt->pPage1->aData[36]), "Main freelist: "); /* Check all the tables. */ | | | 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 | /* Check the integrity of the freelist */ checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), get4byte(&pBt->pPage1->aData[36]), "Main freelist: "); /* Check all the tables. */ for(i=0; (int)i<nRoot && sCheck.mxErr; i++){ if( aRoot[i]==0 ) continue; #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum && aRoot[i]>1 ){ checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0); } #endif checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: "); |
︙ | ︙ | |||
7098 7099 7100 7101 7102 7103 7104 | if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){ return SQLITE_ERROR; } if( pBtTo->pCursor ){ return SQLITE_BUSY; } | | | | 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 | if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){ return SQLITE_ERROR; } if( pBtTo->pCursor ){ return SQLITE_BUSY; } nToPage = pagerPagecount(pBtTo); nFromPage = pagerPagecount(pBtFrom); iSkip = PENDING_BYTE_PAGE(pBtTo); /* Variable nNewPage is the number of pages required to store the ** contents of pFrom using the current page-size of pTo. */ nNewPage = ((i64)nFromPage * (i64)nFromPageSize + (i64)nToPageSize - 1) / (i64)nToPageSize; |
︙ | ︙ |
Changes to src/btreeInt.h.
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: btreeInt.h,v 1.35 2008/11/17 14:20:56 danielk1977 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. |
︙ | ︙ | |||
498 499 500 501 502 503 504 | ** ** If disk I/O is omitted (meaning that the database is stored purely ** in memory) then there is no pending byte. */ #ifdef SQLITE_OMIT_DISKIO # define PENDING_BYTE_PAGE(pBt) 0x7fffffff #else | | | 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 | ** ** If disk I/O is omitted (meaning that the database is stored purely ** in memory) then there is no pending byte. */ #ifdef SQLITE_OMIT_DISKIO # define PENDING_BYTE_PAGE(pBt) 0x7fffffff #else # define PENDING_BYTE_PAGE(pBt) ((Pgno)((PENDING_BYTE/(pBt)->pageSize)+1)) #endif /* ** A linked list of the following structures is stored at BtShared.pLock. ** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor ** is opened on the table with root page BtShared.iTable. Locks are removed ** from this list when a transaction is committed or rolled back, or when |
︙ | ︙ | |||
605 606 607 608 609 610 611 | ** This structure is passed around through all the sanity checking routines ** in order to keep track of some global state information. */ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ | | | 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 | ** This structure is passed around through all the sanity checking routines ** in order to keep track of some global state information. */ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ Pgno nPage; /* Number of pages in the database */ int *anRef; /* Number of times each page is referenced */ int mxErr; /* Stop accumulating errors when this reaches zero */ int nErr; /* Number of messages written to zErrMsg so far */ int mallocFailed; /* A memory allocation error has occurred */ StrAccum errMsg; /* Accumulate the error message text here */ }; |
︙ | ︙ |