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
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/pager.c.
397
398
399
400
401
402
403
404
405


406
407
408
409
410
411
412
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() */
  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
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);
    }
    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
702
703
704
705
706
707
708

709
710
711
712
713
714
715
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
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
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

3175
3176
3177
3178
3179
3180
3181
3182

3183
3184
3185
3186
3187
3188
3189
3178
3179
3180
3181
3182
3183
3184

3185
3186
3187
3188
3189
3190
3191
3192







-
+







*/
static int pager_recycle(Pager *pPager, PgHdr **ppPg){
  PgHdr *pPg;
  *ppPg = 0;

  /* It is illegal to call this function unless the pager object
  ** pointed to by pPager has at least one free page (page with nRef==0).
  */ 
  */
  assert(!MEMDB);
  assert(pPager->lru.pFirst);

  /* Find a page to recycle.  Try to locate a page that does not
  ** require us to do an fsync() on the journal.
  */
  pPg = pPager->lru.pFirstSynced;
3624
3625
3626
3627
3628
3629
3630
3631

3632
3633



3634
3635
3636
3637
3638
3639
3640
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: */
  ** 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
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
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
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;