Experimental changes that cause SQLite to use bytes 28..31 of the database

header to determine the database size, rather than using the actual database
size.  This allows database space to be preallocated.

FossilOrigin-Name: b844ac6fcb72595a71e5c5283ec461309a87ba79
This commit is contained in:
drh 2010-03-27 17:12:36 +00:00
parent c26c00495f
commit dd3cd977cc
7 changed files with 71 additions and 55 deletions

View File

@ -1,5 +1,8 @@
C Increase\sthe\sestimated\scost\sof\susing\sa\svirtual\stable\sas\sthe\souter\sloop\sof\sa\sjoin\swhen\sthere\sexists\san\sORDER\sBY\sclause\sthat\sis\snot\ssatisfied\sby\sthe\svirtual\stable.\sFix\sfor\s[775b39dd3c].
D 2010-03-27T09:44:42
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
C Experimental\schanges\sthat\scause\sSQLite\sto\suse\sbytes\s28..31\sof\sthe\sdatabase\nheader\sto\sdetermine\sthe\sdatabase\ssize,\srather\sthan\susing\sthe\sactual\sdatabase\nsize.\s\sThis\sallows\sdatabase\sspace\sto\sbe\spreallocated.
D 2010-03-27T17:12:36
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 4f2f967b7e58a35bb74fb7ec8ae90e0f4ca7868b
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -109,9 +112,9 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c b293534bc2df23c57668a585b17ee7faaaef0939
F src/bitvec.c 06ad2c36a9c3819c0b9cbffec7b15f58d5d834e0
F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff
F src/btree.c 0d6e44d664b1775b269ea7e6f66fdffcfc32ceb3
F src/btree.c 28c3975060209dc5c5ca91abaa5e034dab03539f
F src/btree.h 0e193b7e90f1d78b79c79474040e3d66a553a4fa
F src/btreeInt.h 71ed5e7f009caf17b7dc304350b3cb64b5970135
F src/btreeInt.h 132d750db5d86b75344cec870501fa09a67b1f96
F src/build.c 11100b66fb97638d2d874c1d34d8db90650bb1d7
F src/callback.c 908f3e0172c3d4058f4ca0acd42c637c52e9669f
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
@ -152,7 +155,7 @@ F src/os_common.h 240c88b163b02c21a9f21f87d49678a0aa21ff30
F src/os_os2.c 75a8c7b9a00a2cf1a65f9fa4afbc27d46634bb2f
F src/os_unix.c 148d2f625db3727250c0b880481ae7630b6d0eb0
F src/os_win.c 1c7453c2df4dab26d90ff6f91272aea18bcf7053
F src/pager.c 2a374f72e6c87150d043173b8041dc537f926b02
F src/pager.c af1c58b7b884839853cc553681f771297de56049
F src/pager.h ef8a2cf10084f60ab45ee2dfded8bf8b0c655ddf
F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
F src/pcache.c ace8f6a5ecd4711cc66a1b23053be7109bd437cf
@ -293,7 +296,7 @@ F test/colmeta.test 087c42997754b8c648819832241daf724f813322
F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b
F test/conflict.test 0ed68b11f22721052d880ee80bd528a0e0828236
F test/corrupt.test 0d346c9fe064ca71281685a8a732fcc83461bb99
F test/corrupt2.test a571e30ea4e82318f319a24b6cc55935ce862079
F test/corrupt2.test 576122d756feda40e63ef1c1ff6c4720a927d126
F test/corrupt3.test 263e8bb04e2728df832fddf6973cf54c91db0c32
F test/corrupt4.test acdb01afaedf529004b70e55de1a6f5a05ae7fff
F test/corrupt5.test c23da7bfb20917cc7fdbb13ee25c7cc4e9fffeff
@ -528,7 +531,7 @@ F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
F test/pcache.test eebc4420b37cb07733ae9b6e99c9da7c40dd6d58
F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
F test/permutations.test 91928573ca2db2c88dbc50ab34e4a585d912b580
F test/pragma.test 5aeb48a442dba3c3e8e38773b121371814ab3b17
F test/pragma.test 6960f9efbce476f70ba9ee2171daf5042f9e3d8a
F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
@ -794,7 +797,18 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P c33b38b59f733494ca0bce3f59a669fe7ed76b9f
R 1048b4f005b8cf985bff319e6cd284fa
U dan
Z 25a9f1889e9ba9dd674533c69390c60b
P 9e075e70f0e2a1ad302d17150cd58f91669a97a6
R 8d4f88bef4d5dad0eb6446592a8450b9
T *bgcolor * #c0ffc0
T *branch * experimental
T *sym-experimental *
T -sym-trunk *
U drh
Z 4146840317f4bfa6058f588cd6ed7701
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFLrjyHoxKgR168RlERArtLAKCJtnFICZRpFQj18diXIg+u0uOi3ACgh4j0
mhbXREy6ig+7NdEp5dlms38=
=ITwY
-----END PGP SIGNATURE-----

View File

@ -1 +1 @@
9e075e70f0e2a1ad302d17150cd58f91669a97a6
b844ac6fcb72595a71e5c5283ec461309a87ba79

View File

@ -516,11 +516,8 @@ static void invalidateIncrblobCursors(
static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
int rc = SQLITE_OK;
if( !pBt->pHasContent ){
int nPage = 100;
sqlite3PagerPagecount(pBt->pPager, &nPage);
/* If sqlite3PagerPagecount() fails there is no harm because the
** nPage variable is unchanged from its default value of 100 */
pBt->pHasContent = sqlite3BitvecCreate((u32)nPage);
assert( pgno<=pBt->nPage );
pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage);
if( !pBt->pHasContent ){
rc = SQLITE_NOMEM;
}
@ -1564,12 +1561,8 @@ static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){
** 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;
int nPage = (int)pBt->nPage;
return nPage;
}
/*
@ -2254,8 +2247,8 @@ static int lockBtree(BtShared *pBt){
/* Do some checking to help insure the file we opened really is
** a valid database file.
*/
rc = sqlite3PagerPagecount(pBt->pPager, &nPage);
if( rc!=SQLITE_OK ){
nPage = get4byte(28+(u8*)pPage1->aData);
if( nPage==0 && (rc = sqlite3PagerPagecount(pBt->pPager, &nPage))!=0 ){
goto page1_init_failed;
}else if( nPage>0 ){
int pageSize;
@ -2333,6 +2326,7 @@ static int lockBtree(BtShared *pBt){
pBt->minLeaf = (pBt->usableSize-12)*32/255 - 23;
assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
pBt->pPage1 = pPage1;
pBt->nPage = nPage;
return SQLITE_OK;
page1_init_failed:
@ -2370,12 +2364,10 @@ static int newDatabase(BtShared *pBt){
MemPage *pP1;
unsigned char *data;
int rc;
int nPage;
assert( sqlite3_mutex_held(pBt->mutex) );
rc = sqlite3PagerPagecount(pBt->pPager, &nPage);
if( rc!=SQLITE_OK || nPage>0 ){
return rc;
if( pBt->nPage>0 ){
return SQLITE_OK;
}
pP1 = pBt->pPage1;
assert( pP1!=0 );
@ -2401,6 +2393,8 @@ static int newDatabase(BtShared *pBt){
put4byte(&data[36 + 4*4], pBt->autoVacuum);
put4byte(&data[36 + 7*4], pBt->incrVacuum);
#endif
pBt->nPage = 1;
data[31] = 1;
return SQLITE_OK;
}
@ -2769,12 +2763,12 @@ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
*/
static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
Pgno nFreeList; /* Number of pages still on the free-list */
int rc;
assert( sqlite3_mutex_held(pBt->mutex) );
assert( iLastPg>nFin );
if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){
int rc;
u8 eType;
Pgno iPtrPage;
@ -2850,7 +2844,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){
if( PTRMAP_ISPAGE(pBt, iLastPg) ){
MemPage *pPg;
int rc = btreeGetPage(pBt, iLastPg, &pPg, 0);
rc = btreeGetPage(pBt, iLastPg, &pPg, 0);
if( rc!=SQLITE_OK ){
return rc;
}
@ -2863,6 +2857,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
iLastPg--;
}
sqlite3PagerTruncateImage(pBt->pPager, iLastPg);
pBt->nPage = iLastPg;
}
return SQLITE_OK;
}
@ -2886,6 +2881,10 @@ int sqlite3BtreeIncrVacuum(Btree *p){
}else{
invalidateAllOverflowCache(pBt);
rc = incrVacuumStep(pBt, 0, pagerPagecount(pBt));
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
put4byte(&pBt->pPage1->aData[28], pBt->nPage);
}
}
sqlite3BtreeLeave(p);
return rc;
@ -2941,11 +2940,12 @@ static int autoVacuumCommit(BtShared *pBt){
rc = incrVacuumStep(pBt, nFin, iFree);
}
if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
rc = SQLITE_OK;
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
put4byte(&pBt->pPage1->aData[32], 0);
put4byte(&pBt->pPage1->aData[36], 0);
put4byte(&pBt->pPage1->aData[28], nFin);
sqlite3PagerTruncateImage(pBt->pPager, nFin);
pBt->nPage = nFin;
}
if( rc!=SQLITE_OK ){
sqlite3PagerRollback(pPager);
@ -3269,6 +3269,7 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
if( rc==SQLITE_OK ){
rc = newDatabase(pBt);
pBt->nPage = get4byte(28 + pBt->pPage1->aData);
}
sqlite3BtreeLeave(p);
}
@ -4833,32 +4834,32 @@ static int allocateBtreePage(
}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;
if( *pPgno==PENDING_BYTE_PAGE(pBt) ){
(*pPgno)++;
}
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
if( rc ) return rc;
pBt->nPage++;
if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, *pPgno) ){
if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){
/* 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.
*/
MemPage *pPg = 0;
TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", *pPgno));
assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
rc = btreeGetPage(pBt, *pPgno, &pPg, 0);
TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
rc = btreeGetPage(pBt, pBt->nPage, &pPg, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(pPg->pDbPage);
releasePage(pPg);
}
if( rc ) return rc;
(*pPgno)++;
if( *pPgno==PENDING_BYTE_PAGE(pBt) ){ (*pPgno)++; }
pBt->nPage++;
if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; }
}
#endif
put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage);
*pPgno = pBt->nPage;
assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
rc = btreeGetPage(pBt, *pPgno, ppPage, 0);

View File

@ -420,6 +420,7 @@ struct BtShared {
u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
u8 inTransaction; /* Transaction state */
int nTransaction; /* Number of open transactions (read + write) */
u32 nPage; /* Number of pages in the database */
void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */

View File

@ -4156,10 +4156,10 @@ static int pager_write(PgHdr *pPg){
*/
assert( pPager->state>=PAGER_RESERVED );
/* If an error has been previously detected, we should not be
** calling this routine. Repeat the error for robustness.
/* If an error has been previously detected, report the same error
** again.
*/
if( NEVER(pPager->errCode) ) return pPager->errCode;
if( pPager->errCode ) return pPager->errCode;
/* Higher-level routines never call this function if database is not
** writable. But check anyway, just for robustness. */
@ -4489,10 +4489,6 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
change_counter++;
put32bits(((char*)pPgHdr->pData)+24, change_counter);
/* Also store the current database size in bytes 28..31 */
assert( pPager->dbSizeValid );
put32bits(((char*)pPgHdr->pData)+28, pPager->dbSize);
/* Also store the SQLite version number in bytes 96..99 */
assert( pPager->dbSizeValid );
put32bits(((char*)pPgHdr->pData)+96, SQLITE_VERSION_NUMBER);
@ -4570,10 +4566,8 @@ int sqlite3PagerCommitPhaseOne(
/* The dbOrigSize is never set if journal_mode=OFF */
assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF || pPager->dbOrigSize==0 );
/* If a prior error occurred, this routine should not be called. ROLLBACK
** is the appropriate response to an error, not COMMIT. Guard against
** coding errors by repeating the prior error. */
if( NEVER(pPager->errCode) ) return pPager->errCode;
/* If a prior error occurred, report that error again. */
if( pPager->errCode ) return pPager->errCode;
PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
pPager->zFilename, zMaster, pPager->dbSize));
@ -4925,6 +4919,9 @@ int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
int ii; /* Iterator variable */
PagerSavepoint *aNew; /* New Pager.aSavepoint array */
rc = sqlite3PagerPagecount(pPager, 0);
if( rc ) return rc;
/* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
** if the allocation fails. Otherwise, zero the new portion in case a
** malloc failure occurs while populating it in the for(...) loop below.

View File

@ -334,6 +334,7 @@ ifcapable autovacuum {
seek $fd 0 end
puts -nonewline $fd [string repeat x $nAppend]
close $fd
hexio_write corrupt.db 28 00000000
} -test {
do_test corrupt2-6.4 {
catchsql {
@ -522,6 +523,7 @@ ifcapable autovacuum {
file size corrupt.db
} $::sqlite_pending_byte
hexio_write corrupt.db [expr $::sqlite_pending_byte+1023] 00
hexio_write corrupt.db 28 00000000
} -test {
do_test corrupt2-13.2 {
file size corrupt.db

View File

@ -317,6 +317,7 @@ ifcapable attach {
puts -nonewline $out [read $in]
close $in
close $out
hexio_write testerr.db 28 00000000
execsql {REINDEX t2}
execsql {PRAGMA integrity_check}
} {ok}