Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add code to create/update the btree 'pointer-map' for auto-vacuum mode. (CVS 2035) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
bebd967f3627220c3ce0352c8ca9c7c1 |
User & Date: | danielk1977 2004-10-31 16:25:43.000 |
Context
2004-11-01
| ||
16:03 | Updates to the support.html page. (CVS 2036) (check-in: 5515accee3 user: drh tags: trunk) | |
2004-10-31
| ||
16:25 | Add code to create/update the btree 'pointer-map' for auto-vacuum mode. (CVS 2035) (check-in: bebd967f36 user: danielk1977 tags: trunk) | |
02:22 | Insert #ifdefs that can optionally remove features at compiletime resulting in a database engine with a smaller footprint. (CVS 2034) (check-in: be661acfa8 user: drh tags: trunk) | |
Changes
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | 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. ** ************************************************************************* |
︙ | |||
307 308 309 310 311 312 313 314 315 316 317 318 319 320 | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | + + + | u16 pageSize; /* Total number of bytes on a page */ u16 psAligned; /* pageSize rounded up to a multiple of 8 */ u16 usableSize; /* Number of usable bytes on each page */ int maxLocal; /* Maximum local payload in non-LEAFDATA tables */ int minLocal; /* Minimum local payload in non-LEAFDATA tables */ int maxLeaf; /* Maximum local payload in a LEAFDATA table */ int minLeaf; /* Minimum local payload in a LEAFDATA table */ #ifndef SQLITE_OMIT_AUTOVACUUM u8 autoVacuum; /* True if database supports auto-vacuum */ #endif }; typedef Btree Bt; /* ** Btree.inTrans may take one of the following values. */ #define TRANS_NONE 0 |
︙ | |||
387 388 389 390 391 392 393 394 395 396 397 398 399 400 | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | ** be defined locally, but now we use the varint routines in the util.c ** file. */ #define getVarint sqlite3GetVarint #define getVarint32 sqlite3GetVarint32 #define putVarint sqlite3PutVarint #ifndef SQLITE_OMIT_AUTOVACUUM /* ** These two macros define the location of the pointer-map entry for a ** database page. The first argument to each is the page size used ** by the database (often 1024). The second is the page number to look ** up in the pointer map. ** ** PTRMAP_PAGENO returns the database page number of the pointer-map ** page that stores the required pointer. PTRMAP_PTROFFSET returns ** the offset of the requested map entry. ** ** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page, ** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be ** used to test if pgno is a pointer-map page. */ #define PTRMAP_PAGENO(pgsz, pgno) (((pgno-2)/(pgsz/5+1))*(pgsz/5+1)+2) #define PTRMAP_PTROFFSET(pgsz, pgno) (((pgno-2)%(pgsz/5+1)-1)*5) /* ** The first byte of each 5-byte pointer map entry identifies the type ** of page that the following 4-byte page number refers to (either a ** regular btree page or an overflow page). ** ** If the type is PTRMAP_OVERFLOW, then the page is an overflow page. ** In this case the pointer is always the first 4 bytes of the page. ** ** If the type is PTRMAP_BTREE, then the page is a btree page. In this ** case the pointer may be a 'left-pointer' (stored following a cell-header), ** a pointer to an overflow page (stored after a cell's data payload), ** or the 'right pointer' of a btree page. */ #define PTRMAP_BTREE 1 #define PTRMAP_OVERFLOW 2 /* ** Write an entry into the pointer map. */ static int ptrmapPut(Btree *pBt, Pgno key, u8 eType, Pgno pgno){ u8 *pPtrmap; /* The pointer map page */ Pgno iPtrmap; /* The pointer map page number */ int offset; /* Offset in pointer map page */ int rc; iPtrmap = PTRMAP_PAGENO(pBt->pageSize, key); rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap); if( rc!=0 ){ return rc; } offset = PTRMAP_PTROFFSET(pBt->pageSize, key); if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=pgno ){ rc = sqlite3pager_write(pPtrmap); if( rc!=0 ){ return rc; } pPtrmap[offset] = eType; put4byte(&pPtrmap[offset+1], pgno); } sqlite3pager_unref(pPtrmap); return SQLITE_OK; } /* ** Read an entry from the pointer map. */ static int ptrmapGet(Btree *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ int iPtrmap; /* Pointer map page index */ u8 *pPtrmap; /* Pointer map page data */ int offset; /* Offset of entry in pointer map */ int rc; iPtrmap = PTRMAP_PAGENO(pBt->pageSize, key); rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap); if( rc!=0 ){ return rc; } offset = PTRMAP_PTROFFSET(pBt->pageSize, key); *pEType = pPtrmap[offset]; *pPgno = get4byte(&pPtrmap[offset+1]); sqlite3pager_unref(pPtrmap); return SQLITE_OK; } #endif /* SQLITE_OMIT_AUTOVACUUM */ /* ** Given a btree page and a cell index (0 means the first cell on ** the page, 1 means the second cell, and so forth) return a pointer ** to the cell content. ** ** This routine works only for pages that do not contain overflow cells. */ |
︙ | |||
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 | 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 | + + + + | pBt->minLeafFrac = zDbHeader[23]; pBt->pageSizeFixed = 1; } pBt->usableSize = pBt->pageSize - nReserve; pBt->psAligned = FORCE_ALIGNMENT(pBt->pageSize); sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize); *ppBtree = pBt; #ifdef SQLITE_AUTOVACUUM /* Note: This is temporary code for use during development of auto-vacuum. */ pBt->autoVacuum = 1; #endif return SQLITE_OK; } /* ** Close an open database and invalidate all cursors. */ int sqlite3BtreeClose(Btree *pBt){ |
︙ | |||
2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 | 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 | + + + + + + + + + + + + | rc = sqlite3pager_write((*ppPage)->aData); } } }else{ /* There are no pages on the freelist, so create a new page at the ** end of the file */ *pPgno = sqlite3pager_pagecount(pBt->pPager) + 1; #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum && *pPgno==PTRMAP_PAGENO(pBt->pageSize, *pPgno) ){ /* If *pPgno refers to a pointer-map page, allocate two new pages ** at the end of the file instead of one. The first allocated page ** becomes a new pointer-map page, the second is used by the caller. */ TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", *pPgno)); (*pPgno)++; } #endif rc = getPage(pBt, *pPgno, ppPage); if( rc ) return rc; rc = sqlite3pager_write((*ppPage)->aData); TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); } return rc; } |
︙ | |||
2633 2634 2635 2636 2637 2638 2639 | 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 | + + + - + + + + + + + + + + + + + + + | *pnSize = info.nSize; spaceLeft = info.nLocal; pPayload = &pCell[nHeader]; pPrior = &pCell[info.iOverflow]; while( nPayload>0 ){ if( spaceLeft==0 ){ #ifndef SQLITE_OMIT_AUTOVACUUM Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */ #endif |
︙ | |||
2670 2671 2672 2673 2674 2675 2676 | 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 | - + - + + + + + + + + - + - + + + - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + | } /* ** Change the MemPage.pParent pointer on the page whose number is ** given in the second argument so that MemPage.pParent holds the ** pointer in the third argument. */ |
︙ | |||
3308 3309 3310 3311 3312 3313 3314 | 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 | - + + - + + | put4byte(findOverflowCell(pParent, nxDiv), pgnoNew[nNew-1]); } /* ** Reparent children of all cells. */ for(i=0; i<nNew; i++){ |
︙ | |||
3412 3413 3414 3415 3416 3417 3418 | 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 | - + + | pPage->pParent = 0; rc = initPage(pPage, 0); assert( rc==SQLITE_OK ); freePage(pChild); TRACE(("BALANCE: transfer child %d into root %d\n", pChild->pgno, pPage->pgno)); } |
︙ | |||
4112 4113 4114 4115 4116 4117 4118 | 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 | - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | } if( pCheck->anRef[iPage]==1 ){ checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage); return 1; } return (pCheck->anRef[iPage]++)>1; } |
︙ | |||
4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 | 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 | + + + + + + + + + + | }else{ for(i=0; i<n; i++){ checkRef(pCheck, get4byte(&pOvfl[8+i*4]), zContext); } N -= n; } } #ifndef SQLITE_OMIT_AUTOVACUUM /* If this database supports auto-vacuum and iPage is not the last ** page in this overflow list, check that the pointer-map entry for ** the following page matches iPage. */ if( pCheck->pBt->autoVacuum && !isFreeList && N>0 ){ i = get4byte(pOvfl); checkPtrmap(pCheck, i, PTRMAP_OVERFLOW, iPage, zContext); } #endif iPage = get4byte(pOvfl); sqlite3pager_unref(pOvfl); } } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ #ifndef SQLITE_OMIT_INTEGRITY_CHECK |
︙ | |||
4237 4238 4239 4240 4241 4242 4243 | 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 | - + + + + + + + + + + + + + + + + + | sprintf(zContext, "On tree page %d cell %d: ", iPage, i); pCell = findCell(pPage,i); parseCellPtr(pPage, pCell, &info); sz = info.nData; if( !pPage->intKey ) sz += info.nKey; if( sz>info.nLocal ){ int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); |
︙ | |||
4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 | 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 | + + + + + + + + + + + + + + | if( aRoot[i]==0 ) continue; checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: ", 0,0,0,0); } /* Make sure every page in the file is referenced */ for(i=1; i<=sCheck.nPage; i++){ #ifdef SQLITE_OMIT_AUTOVACUUM if( sCheck.anRef[i]==0 ){ checkAppendMsg(&sCheck, 0, "Page %d is never used", i); } #else /* If the database supports auto-vacuum, make sure no tables contain ** references to pointer-map pages. */ if( sCheck.anRef[i]==0 && (PTRMAP_PAGENO(pBt->pageSize, i)!=i || !pBt->autoVacuum) ){ checkAppendMsg(&sCheck, 0, "Page %d is never used", i); } if( sCheck.anRef[i]!=0 && (PTRMAP_PAGENO(pBt->pageSize, i)==i && pBt->autoVacuum) ){ checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i); } #endif } /* Make sure this analysis did not leave any unref() pages */ unlockBtreeIfUnused(pBt); if( nRef != *sqlite3pager_stats(pBt->pPager) ){ checkAppendMsg(&sCheck, 0, |
︙ |