1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Demostrate a prototype sqlite3_autovacuum_pages() interface.

FossilOrigin-Name: bb6f2b8b486c225043bc64e5f74ff6bbad6c5d1f337f0c81eeb6172b087bb943
This commit is contained in:
drh
2021-10-15 23:02:27 +00:00
parent 220f0d6f8e
commit 1bbfc6744c
11 changed files with 350 additions and 29 deletions

View File

@@ -3939,16 +3939,18 @@ int sqlite3BtreeIncrVacuum(Btree *p){
/*
** This routine is called prior to sqlite3PagerCommit when a transaction
** is committed for an auto-vacuum database.
**
** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
** the database file should be truncated to during the commit process.
** i.e. the database has been reorganized so that only the first *pnTrunc
** pages are in use.
*/
static int autoVacuumCommit(BtShared *pBt){
static int autoVacuumCommit(Btree *p){
int rc = SQLITE_OK;
Pager *pPager = pBt->pPager;
VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager); )
Pager *pPager;
BtShared *pBt;
sqlite3 *db;
VVA_ONLY( int nRef );
assert( p!=0 );
pBt = p->pBt;
pPager = pBt->pPager;
VVA_ONLY( nRef = sqlite3PagerRefcount(pPager); )
assert( sqlite3_mutex_held(pBt->mutex) );
invalidateAllOverflowCache(pBt);
@@ -3956,6 +3958,7 @@ static int autoVacuumCommit(BtShared *pBt){
if( !pBt->incrVacuum ){
Pgno nFin; /* Number of pages in database after autovacuuming */
Pgno nFree; /* Number of pages on the freelist initially */
Pgno nVac; /* Number of pages to vacuum */
Pgno iFree; /* The next page to be freed */
Pgno nOrig; /* Database size before freeing */
@@ -3969,18 +3972,42 @@ static int autoVacuumCommit(BtShared *pBt){
}
nFree = get4byte(&pBt->pPage1->aData[36]);
nFin = finalDbSize(pBt, nOrig, nFree);
db = p->db;
if( db->xAutovacPages ){
int iDb;
for(iDb=0; ALWAYS(iDb<db->nDb); iDb++){
if( db->aDb[iDb].pBt==p ) break;
}
nVac = db->xAutovacPages(
db->pAutovacPagesArg,
db->aDb[iDb].zDbSName,
nOrig,
nFree,
pBt->pageSize
);
if( nVac>nFree ){
nVac = nFree;
}
if( nVac==0 ){
return SQLITE_OK;
}
}else{
nVac = nFree;
}
nFin = finalDbSize(pBt, nOrig, nVac);
if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
if( nFin<nOrig ){
rc = saveAllCursors(pBt, 0, 0);
}
for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
rc = incrVacuumStep(pBt, nFin, iFree, 1);
rc = incrVacuumStep(pBt, nFin, iFree, nVac==nFree);
}
if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
put4byte(&pBt->pPage1->aData[32], 0);
put4byte(&pBt->pPage1->aData[36], 0);
if( nVac==nFree ){
put4byte(&pBt->pPage1->aData[32], 0);
put4byte(&pBt->pPage1->aData[36], 0);
}
put4byte(&pBt->pPage1->aData[28], nFin);
pBt->bDoTruncate = 1;
pBt->nPage = nFin;
@@ -4031,7 +4058,7 @@ int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zSuperJrnl){
sqlite3BtreeEnter(p);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
rc = autoVacuumCommit(pBt);
rc = autoVacuumCommit(p);
if( rc!=SQLITE_OK ){
sqlite3BtreeLeave(p);
return rc;