SQLite

Check-in [c50e972f1b]
Login

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

Overview
Comment:Add additional pagerMutexHeld() macros to better verify the correct operation of pager.c.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | branch-3.5.9
Files: files | file ages | folders
SHA1: c50e972f1bea2e357f64ffd5df868bf51d942e2d
User & Date: drh 2010-01-30 18:22:56.000
Context
2010-01-30
19:00
Remove all cache pages from the LRU list prior to removing the pager from the pager list when closing a pager. (check-in: 9d13acc449 user: drh tags: branch-3.5.9)
18:22
Add additional pagerMutexHeld() macros to better verify the correct operation of pager.c. (check-in: c50e972f1b user: drh tags: branch-3.5.9)
2010-01-29
21:23
Fix a missing mutex on page cache truncation during vacuum and auto-vacuum when SQLITE_ENABLE_MEMORY_MANAGEMENT is engaged. (check-in: ea3b941a71 user: drh tags: branch-3.5.9)
Changes
Unified Diff Show Whitespace Changes Patch
Changes to src/pager.c.
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  void *pCodecArg;            /* First argument to xCodec() */
#endif
  int nHash;                  /* Size of the pager hash table */
  PgHdr **aHash;              /* Hash table to map page number to PgHdr */
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  Pager *pNext;               /* Doubly linked list of pagers on which */
  Pager *pPrev;               /* sqlite3_release_memory() will work */
  int iInUseMM;               /* Non-zero if unavailable to MM */
  int iInUseDB;               /* Non-zero if in sqlite3_release_memory() */
  u8 onPagerList;             /* True if part of the sqlite3PagerList */
#endif
  char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
  char dbFileVers[16];        /* Changes whenever database file changes */
};

/*







|
|







397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  void *pCodecArg;            /* First argument to xCodec() */
#endif
  int nHash;                  /* Size of the pager hash table */
  PgHdr **aHash;              /* Hash table to map page number to PgHdr */
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  Pager *pNext;               /* Doubly linked list of pagers on which */
  Pager *pPrev;               /* sqlite3_release_memory() will work */
  volatile int iInUseMM;      /* Non-zero if unavailable to MM */
  volatile int iInUseDB;      /* Non-zero if in sqlite3_release_memory() */
  u8 onPagerList;             /* True if part of the sqlite3PagerList */
#endif
  char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
  char dbFileVers[16];        /* Changes whenever database file changes */
};

/*
523
524
525
526
527
528
529

530
531
532
533
534
535
536
537
538
539
540
    if( p->iInUseMM && p->iInUseDB==1 ){
#ifndef SQLITE_MUTEX_NOOP
      sqlite3_mutex *mutex;
      mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
#endif
      p->iInUseDB = 0;
      sqlite3_mutex_enter(mutex);

      p->iInUseDB = 1;
      sqlite3_mutex_leave(mutex);
    }
    assert( p->iInUseMM==0 );
  }
  static void pagerLeave(Pager *p){
    p->iInUseDB--;
    assert( p->iInUseDB>=0 );
  }
# define pagerMutexHeld(X)  assert( (X)->iInUseDB>0 || !(X)->onPagerList )
#else







>



<







523
524
525
526
527
528
529
530
531
532
533

534
535
536
537
538
539
540
    if( p->iInUseMM && p->iInUseDB==1 ){
#ifndef SQLITE_MUTEX_NOOP
      sqlite3_mutex *mutex;
      mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
#endif
      p->iInUseDB = 0;
      sqlite3_mutex_enter(mutex);
      assert( p->iInUseMM==0 );
      p->iInUseDB = 1;
      sqlite3_mutex_leave(mutex);
    }

  }
  static void pagerLeave(Pager *p){
    p->iInUseDB--;
    assert( p->iInUseDB>=0 );
  }
# define pagerMutexHeld(X)  assert( (X)->iInUseDB>0 || !(X)->onPagerList )
#else
702
703
704
705
706
707
708

709
710
711
712
713
714
715
  if( aHash==0 ){
    /* Failure to rehash is not an error.  It is only a performance hit. */
    return;
  }
  sqlite3_free(pPager->aHash);
  pPager->nHash = N;
  pPager->aHash = aHash;

  for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
    int h;
    if( pPg->pgno==0 ){
      assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );
      continue;
    }
    h = pPg->pgno & (N-1);







>







702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
  if( aHash==0 ){
    /* Failure to rehash is not an error.  It is only a performance hit. */
    return;
  }
  sqlite3_free(pPager->aHash);
  pPager->nHash = N;
  pPager->aHash = aHash;
  pagerMutexHeld(pPager);
  for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
    int h;
    if( pPg->pgno==0 ){
      assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );
      continue;
    }
    h = pPg->pgno & (N-1);
1420
1421
1422
1423
1424
1425
1426

1427
1428
1429
1430
1431
1432
1433
      pPager->journalOpen = 0;
      if( rc==SQLITE_OK ){
        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
      }
    }
    sqlite3BitvecDestroy(pPager->pInJournal);
    pPager->pInJournal = 0;

    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
      pPg->inJournal = 0;
      pPg->dirty = 0;
      pPg->needSync = 0;
      pPg->alwaysRollback = 0;
#ifdef SQLITE_CHECK_PAGES
      pPg->pageHash = pager_pagehash(pPg);







>







1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
      pPager->journalOpen = 0;
      if( rc==SQLITE_OK ){
        rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
      }
    }
    sqlite3BitvecDestroy(pPager->pInJournal);
    pPager->pInJournal = 0;
    pagerMutexHeld(pPager);
    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
      pPg->inJournal = 0;
      pPg->dirty = 0;
      pPg->needSync = 0;
      pPg->alwaysRollback = 0;
#ifdef SQLITE_CHECK_PAGES
      pPg->pageHash = pager_pagehash(pPg);
2937
2938
2939
2940
2941
2942
2943

2944
2945
2946
2947
2948
2949
2950

#ifndef NDEBUG
  /* If the Pager.needSync flag is clear then the PgHdr.needSync
  ** flag must also be clear for all pages.  Verify that this
  ** invariant is true.
  */
  else{

    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
      assert( pPg->needSync==0 );
    }
    assert( pPager->lru.pFirstSynced==pPager->lru.pFirst );
  }
#endif








>







2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953

#ifndef NDEBUG
  /* If the Pager.needSync flag is clear then the PgHdr.needSync
  ** flag must also be clear for all pages.  Verify that this
  ** invariant is true.
  */
  else{
    pagerMutexHeld(pPager);
    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
      assert( pPg->needSync==0 );
    }
    assert( pPager->lru.pFirstSynced==pPager->lru.pFirst );
  }
#endif

3624
3625
3626
3627
3628
3629
3630
3631

3632
3633


3634
3635
3636
3637
3638
3639
3640
**          to be synced to disk or else disk syncing is currently
**          allowed.
*/
static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){
  int rc = SQLITE_OK;
  PgHdr *pPg;
  int nByteHdr;


  /* Create a new PgHdr if any of the four conditions defined 
  ** above are met: */


  if( pPager->nPage<pPager->mxPage
   || pPager->lru.pFirst==0 
   || MEMDB
   || (pPager->lru.pFirstSynced==0 && pPager->doNotSync)
  ){
    void *pData;
    if( pPager->nPage>=pPager->nHash ){








>

|
>
>







3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
**          to be synced to disk or else disk syncing is currently
**          allowed.
*/
static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){
  int rc = SQLITE_OK;
  PgHdr *pPg;
  int nByteHdr;


  /* Create a new PgHdr if any of the four conditions defined 
  ** above are met: 
  */
  pagerMutexHeld(pPager);
  if( pPager->nPage<pPager->mxPage
   || pPager->lru.pFirst==0 
   || MEMDB
   || (pPager->lru.pFirstSynced==0 && pPager->doNotSync)
  ){
    void *pData;
    if( pPager->nPage>=pPager->nHash ){
3660
3661
3662
3663
3664
3665
3666

3667
3668
3669
3670
3671

3672
3673
3674
3675
3676
3677
3678
    if( pPg==0 ){
      rc = SQLITE_NOMEM;
      goto pager_allocate_out;
    }
    memset(pPg, 0, nByteHdr);
    pPg->pData = pData;
    pPg->pPager = pPager;

    pPg->pNextAll = pPager->pAll;
    pPager->pAll = pPg;
    pPager->nPage++;
  }else{
    /* Recycle an existing page with a zero ref-count. */

    rc = pager_recycle(pPager, &pPg);
    if( rc==SQLITE_BUSY ){
      rc = SQLITE_IOERR_BLOCKED;
    }
    if( rc!=SQLITE_OK ){
      goto pager_allocate_out;
    }







>





>







3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
    if( pPg==0 ){
      rc = SQLITE_NOMEM;
      goto pager_allocate_out;
    }
    memset(pPg, 0, nByteHdr);
    pPg->pData = pData;
    pPg->pPager = pPager;
    pagerMutexHeld(pPager);
    pPg->pNextAll = pPager->pAll;
    pPager->pAll = pPg;
    pPager->nPage++;
  }else{
    /* Recycle an existing page with a zero ref-count. */
    pagerMutexHeld(pPager);
    rc = pager_recycle(pPager, &pPg);
    if( rc==SQLITE_BUSY ){
      rc = SQLITE_IOERR_BLOCKED;
    }
    if( rc!=SQLITE_OK ){
      goto pager_allocate_out;
    }
4711
4712
4713
4714
4715
4716
4717

4718
4719
4720
4721
4722
4723
4724
            if( rc!=SQLITE_OK ) goto sync_exit;
          }
        } 
      }
#endif
      rc = writeMasterJournal(pPager, zMaster);
      if( rc!=SQLITE_OK ) goto sync_exit;

      rc = syncJournal(pPager);
    }
    if( rc!=SQLITE_OK ) goto sync_exit;

#ifndef SQLITE_OMIT_AUTOVACUUM
    if( nTrunc!=0 ){
      rc = sqlite3PagerTruncate(pPager, nTrunc);







>







4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
            if( rc!=SQLITE_OK ) goto sync_exit;
          }
        } 
      }
#endif
      rc = writeMasterJournal(pPager, zMaster);
      if( rc!=SQLITE_OK ) goto sync_exit;
      pagerMutexHeld(pPager);
      rc = syncJournal(pPager);
    }
    if( rc!=SQLITE_OK ) goto sync_exit;

#ifndef SQLITE_OMIT_AUTOVACUUM
    if( nTrunc!=0 ){
      rc = sqlite3PagerTruncate(pPager, nTrunc);
4838
4839
4840
4841
4842
4843
4844

4845
4846
4847
4848
4849
4850
4851
** SQLITE_OK is returned.
*/
int sqlite3PagerRollback(Pager *pPager){
  int rc;
  PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
  if( MEMDB ){
    PgHdr *p;

    for(p=pPager->pAll; p; p=p->pNextAll){
      PgHistory *pHist;
      assert( !p->alwaysRollback );
      if( !p->dirty ){
        assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig );
        assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt );
        continue;







>







4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
** SQLITE_OK is returned.
*/
int sqlite3PagerRollback(Pager *pPager){
  int rc;
  PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
  if( MEMDB ){
    PgHdr *p;
    pagerMutexHeld(pPager);
    for(p=pPager->pAll; p; p=p->pNextAll){
      PgHistory *pHist;
      assert( !p->alwaysRollback );
      if( !p->dirty ){
        assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig );
        assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt );
        continue;