/ Check-in [c50e972f]
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 | SQL 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
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: 9d13acc4 user: drh tags: branch-3.5.9
18:22
Add additional pagerMutexHeld() macros to better verify the correct operation of pager.c. check-in: c50e972f 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: ea3b941a user: drh tags: branch-3.5.9
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

   397    397     void *pCodecArg;            /* First argument to xCodec() */
   398    398   #endif
   399    399     int nHash;                  /* Size of the pager hash table */
   400    400     PgHdr **aHash;              /* Hash table to map page number to PgHdr */
   401    401   #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
   402    402     Pager *pNext;               /* Doubly linked list of pagers on which */
   403    403     Pager *pPrev;               /* sqlite3_release_memory() will work */
   404         -  int iInUseMM;               /* Non-zero if unavailable to MM */
   405         -  int iInUseDB;               /* Non-zero if in sqlite3_release_memory() */
          404  +  volatile int iInUseMM;      /* Non-zero if unavailable to MM */
          405  +  volatile int iInUseDB;      /* Non-zero if in sqlite3_release_memory() */
   406    406     u8 onPagerList;             /* True if part of the sqlite3PagerList */
   407    407   #endif
   408    408     char *pTmpSpace;            /* Pager.pageSize bytes of space for tmp use */
   409    409     char dbFileVers[16];        /* Changes whenever database file changes */
   410    410   };
   411    411   
   412    412   /*
................................................................................
   523    523       if( p->iInUseMM && p->iInUseDB==1 ){
   524    524   #ifndef SQLITE_MUTEX_NOOP
   525    525         sqlite3_mutex *mutex;
   526    526         mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
   527    527   #endif
   528    528         p->iInUseDB = 0;
   529    529         sqlite3_mutex_enter(mutex);
          530  +      assert( p->iInUseMM==0 );
   530    531         p->iInUseDB = 1;
   531    532         sqlite3_mutex_leave(mutex);
   532    533       }
   533         -    assert( p->iInUseMM==0 );
   534    534     }
   535    535     static void pagerLeave(Pager *p){
   536    536       p->iInUseDB--;
   537    537       assert( p->iInUseDB>=0 );
   538    538     }
   539    539   # define pagerMutexHeld(X)  assert( (X)->iInUseDB>0 || !(X)->onPagerList )
   540    540   #else
................................................................................
   702    702     if( aHash==0 ){
   703    703       /* Failure to rehash is not an error.  It is only a performance hit. */
   704    704       return;
   705    705     }
   706    706     sqlite3_free(pPager->aHash);
   707    707     pPager->nHash = N;
   708    708     pPager->aHash = aHash;
          709  +  pagerMutexHeld(pPager);
   709    710     for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
   710    711       int h;
   711    712       if( pPg->pgno==0 ){
   712    713         assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );
   713    714         continue;
   714    715       }
   715    716       h = pPg->pgno & (N-1);
................................................................................
  1420   1421         pPager->journalOpen = 0;
  1421   1422         if( rc==SQLITE_OK ){
  1422   1423           rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
  1423   1424         }
  1424   1425       }
  1425   1426       sqlite3BitvecDestroy(pPager->pInJournal);
  1426   1427       pPager->pInJournal = 0;
         1428  +    pagerMutexHeld(pPager);
  1427   1429       for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
  1428   1430         pPg->inJournal = 0;
  1429   1431         pPg->dirty = 0;
  1430   1432         pPg->needSync = 0;
  1431   1433         pPg->alwaysRollback = 0;
  1432   1434   #ifdef SQLITE_CHECK_PAGES
  1433   1435         pPg->pageHash = pager_pagehash(pPg);
................................................................................
  2937   2939   
  2938   2940   #ifndef NDEBUG
  2939   2941     /* If the Pager.needSync flag is clear then the PgHdr.needSync
  2940   2942     ** flag must also be clear for all pages.  Verify that this
  2941   2943     ** invariant is true.
  2942   2944     */
  2943   2945     else{
         2946  +    pagerMutexHeld(pPager);
  2944   2947       for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
  2945   2948         assert( pPg->needSync==0 );
  2946   2949       }
  2947   2950       assert( pPager->lru.pFirstSynced==pPager->lru.pFirst );
  2948   2951     }
  2949   2952   #endif
  2950   2953   
................................................................................
  3175   3178   */
  3176   3179   static int pager_recycle(Pager *pPager, PgHdr **ppPg){
  3177   3180     PgHdr *pPg;
  3178   3181     *ppPg = 0;
  3179   3182   
  3180   3183     /* It is illegal to call this function unless the pager object
  3181   3184     ** pointed to by pPager has at least one free page (page with nRef==0).
  3182         -  */ 
         3185  +  */
  3183   3186     assert(!MEMDB);
  3184   3187     assert(pPager->lru.pFirst);
  3185   3188   
  3186   3189     /* Find a page to recycle.  Try to locate a page that does not
  3187   3190     ** require us to do an fsync() on the journal.
  3188   3191     */
  3189   3192     pPg = pPager->lru.pFirstSynced;
................................................................................
  3624   3627   **          to be synced to disk or else disk syncing is currently
  3625   3628   **          allowed.
  3626   3629   */
  3627   3630   static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){
  3628   3631     int rc = SQLITE_OK;
  3629   3632     PgHdr *pPg;
  3630   3633     int nByteHdr;
         3634  +
  3631   3635   
  3632   3636     /* Create a new PgHdr if any of the four conditions defined 
  3633         -  ** above are met: */
         3637  +  ** above are met: 
         3638  +  */
         3639  +  pagerMutexHeld(pPager);
  3634   3640     if( pPager->nPage<pPager->mxPage
  3635   3641      || pPager->lru.pFirst==0 
  3636   3642      || MEMDB
  3637   3643      || (pPager->lru.pFirstSynced==0 && pPager->doNotSync)
  3638   3644     ){
  3639   3645       void *pData;
  3640   3646       if( pPager->nPage>=pPager->nHash ){
................................................................................
  3660   3666       if( pPg==0 ){
  3661   3667         rc = SQLITE_NOMEM;
  3662   3668         goto pager_allocate_out;
  3663   3669       }
  3664   3670       memset(pPg, 0, nByteHdr);
  3665   3671       pPg->pData = pData;
  3666   3672       pPg->pPager = pPager;
         3673  +    pagerMutexHeld(pPager);
  3667   3674       pPg->pNextAll = pPager->pAll;
  3668   3675       pPager->pAll = pPg;
  3669   3676       pPager->nPage++;
  3670   3677     }else{
  3671   3678       /* Recycle an existing page with a zero ref-count. */
         3679  +    pagerMutexHeld(pPager);
  3672   3680       rc = pager_recycle(pPager, &pPg);
  3673   3681       if( rc==SQLITE_BUSY ){
  3674   3682         rc = SQLITE_IOERR_BLOCKED;
  3675   3683       }
  3676   3684       if( rc!=SQLITE_OK ){
  3677   3685         goto pager_allocate_out;
  3678   3686       }
................................................................................
  4711   4719               if( rc!=SQLITE_OK ) goto sync_exit;
  4712   4720             }
  4713   4721           } 
  4714   4722         }
  4715   4723   #endif
  4716   4724         rc = writeMasterJournal(pPager, zMaster);
  4717   4725         if( rc!=SQLITE_OK ) goto sync_exit;
         4726  +      pagerMutexHeld(pPager);
  4718   4727         rc = syncJournal(pPager);
  4719   4728       }
  4720   4729       if( rc!=SQLITE_OK ) goto sync_exit;
  4721   4730   
  4722   4731   #ifndef SQLITE_OMIT_AUTOVACUUM
  4723   4732       if( nTrunc!=0 ){
  4724   4733         rc = sqlite3PagerTruncate(pPager, nTrunc);
................................................................................
  4838   4847   ** SQLITE_OK is returned.
  4839   4848   */
  4840   4849   int sqlite3PagerRollback(Pager *pPager){
  4841   4850     int rc;
  4842   4851     PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
  4843   4852     if( MEMDB ){
  4844   4853       PgHdr *p;
         4854  +    pagerMutexHeld(pPager);
  4845   4855       for(p=pPager->pAll; p; p=p->pNextAll){
  4846   4856         PgHistory *pHist;
  4847   4857         assert( !p->alwaysRollback );
  4848   4858         if( !p->dirty ){
  4849   4859           assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig );
  4850   4860           assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt );
  4851   4861           continue;