SQLite

Check-in [9a429349cc]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Avoid unnecessary page cache allocations when move a page while autovacuuming an in-memory database, since the allocation might fail making it impossible to rollback the transaction.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9a429349ccc2fa9acd28365a86578f602e87dafb
User & Date: drh 2009-11-20 13:18:14.000
References
2009-11-20
18:51 Fixed ticket [564d412f15]: OOM on autovacuum of in-memory database causes problems. plus 3 other changes (artifact: 3ed1331e03 user: drh)
Context
2009-11-20
17:18
Add a test to make sure a database can be attached to a single handle twice if not in shared-cache mode. (check-in: 1c4984c62f user: dan tags: trunk)
15:02
If the root pages numbers of the internal schema are adjusted due to autovacuum on a DROP TABLE statement and that statement later aborts (for example, due to an OOM error) then reset the internal schema at the conclusion of the statement. Partial fix for ticket [564d412f15a]. (check-in: e493b093f8 user: drh tags: trunk)
13:18
Avoid unnecessary page cache allocations when move a page while autovacuuming an in-memory database, since the allocation might fail making it impossible to rollback the transaction. (check-in: 9a429349cc user: drh tags: trunk)
05:05
Improve comments and other things in fts3_write.c. (check-in: 1cf0e3cc14 user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/pager.c.
5150
5151
5152
5153
5154
5155
5156






5157

5158
5159
5160
5161
5162
5163
5164
  ** for the page moved there.
  */
  pPg->flags &= ~PGHDR_NEED_SYNC;
  pPgOld = pager_lookup(pPager, pgno);
  assert( !pPgOld || pPgOld->nRef==1 );
  if( pPgOld ){
    pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);






    sqlite3PcacheDrop(pPgOld);

  }

  origPgno = pPg->pgno;
  sqlite3PcacheMove(pPg, pgno);
  sqlite3PcacheMakeDirty(pPg);
  pPager->dbModified = 1;








>
>
>
>
>
>
|
>







5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
  ** for the page moved there.
  */
  pPg->flags &= ~PGHDR_NEED_SYNC;
  pPgOld = pager_lookup(pPager, pgno);
  assert( !pPgOld || pPgOld->nRef==1 );
  if( pPgOld ){
    pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
    if( MEMDB ){
      /* Do not discard pages from an in-memory database since we might
      ** need to rollback later.  Just move the page out of the way. */
      assert( pPager->dbSizeValid );
      sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
    }else{
      sqlite3PcacheDrop(pPgOld);
    }
  }

  origPgno = pPg->pgno;
  sqlite3PcacheMove(pPg, pgno);
  sqlite3PcacheMakeDirty(pPg);
  pPager->dbModified = 1;

5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
    pPgHdr->flags |= PGHDR_NEED_SYNC;
    sqlite3PcacheMakeDirty(pPgHdr);
    sqlite3PagerUnref(pPgHdr);
  }

  /*
  ** For an in-memory database, make sure the original page continues
  ** to exist, in case the transaction needs to roll back.  We allocate
  ** the page now, instead of at rollback, because we can better deal
  ** with an out-of-memory error now.  Ticket #3761.
  */
  if( MEMDB ){
    DbPage *pNew;
    rc = sqlite3PagerAcquire(pPager, origPgno, &pNew, 1);
    if( rc!=SQLITE_OK ){
      sqlite3PcacheMove(pPg, origPgno);
      return rc;
    }
    sqlite3PagerUnref(pNew);
  }

  return SQLITE_OK;
}
#endif

/*







|
|
<


<
<
<
|
<
<
|







5202
5203
5204
5205
5206
5207
5208
5209
5210

5211
5212



5213


5214
5215
5216
5217
5218
5219
5220
5221
    pPgHdr->flags |= PGHDR_NEED_SYNC;
    sqlite3PcacheMakeDirty(pPgHdr);
    sqlite3PagerUnref(pPgHdr);
  }

  /*
  ** For an in-memory database, make sure the original page continues
  ** to exist, in case the transaction needs to roll back.  Use pPgOld
  ** as the original page since it has already been allocated.

  */
  if( MEMDB ){



    sqlite3PcacheMove(pPgOld, origPgno);


    sqlite3PagerUnref(pPgOld);
  }

  return SQLITE_OK;
}
#endif

/*
Changes to src/pcache1.c.
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
  }
  *pp = pPage->pNext;

  h = iNew%pCache->nHash;
  pPage->iKey = iNew;
  pPage->pNext = pCache->apHash[h];
  pCache->apHash[h] = pPage;

  /* The xRekey() interface is only used to move pages earlier in the
  ** database file (in order to move all free pages to the end of the
  ** file where they can be truncated off.)  Hence, it is not possible
  ** for the new page number to be greater than the largest previously
  ** fetched page.  But we retain the following test in case xRekey()
  ** begins to be used in different ways in the future.
  */
  if( NEVER(iNew>pCache->iMaxKey) ){
    pCache->iMaxKey = iNew;
  }

  pcache1LeaveMutex();
}

/*







<
<
<
<
<
<
<
<
|







661
662
663
664
665
666
667








668
669
670
671
672
673
674
675
  }
  *pp = pPage->pNext;

  h = iNew%pCache->nHash;
  pPage->iKey = iNew;
  pPage->pNext = pCache->apHash[h];
  pCache->apHash[h] = pPage;








  if( iNew>pCache->iMaxKey ){
    pCache->iMaxKey = iNew;
  }

  pcache1LeaveMutex();
}

/*