/ Check-in [50c0f220]
Login

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

Overview
Comment:Make sure a connection has an exclusive lock on all database files involved in a multi-file transaction before writing the master-journal pointer into any journal files. Fix for [f3e5abed55].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1: 50c0f2202d21bbf6b593d75fd20f13c0fac23eff
User & Date: dan 2010-07-30 10:02:24
Context
2010-07-30
10:09
Add the test cases for bug [f3e5abed55]. check-in: cbbaf8e6 user: dan tags: experimental
10:02
Make sure a connection has an exclusive lock on all database files involved in a multi-file transaction before writing the master-journal pointer into any journal files. Fix for [f3e5abed55]. check-in: 50c0f220 user: dan tags: experimental
07:26
Merge further trunk changes into experimental branch. check-in: fb847d70 user: dan tags: experimental
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

  5056   5056     if( pPager->noSync ){
  5057   5057       rc = SQLITE_OK;
  5058   5058     }else{
  5059   5059       rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
  5060   5060     }
  5061   5061     return rc;
  5062   5062   }
         5063  +
         5064  +/*
         5065  +** This function may only be called while a write-transaction is active in
         5066  +** rollback. If the connection is in WAL mode, this call is a no-op. 
         5067  +** Otherwise, if the connection does not already have an EXCLUSIVE lock on 
         5068  +** the database file, an attempt is made to obtain one.
         5069  +**
         5070  +** If the EXCLUSIVE lock is already held or the attempt to obtain it is
         5071  +** successful, or the connection is in WAL mode, SQLITE_OK is returned.
         5072  +** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is 
         5073  +** returned.
         5074  +*/
         5075  +int sqlite3PagerExclusiveLock(Pager *pPager){
         5076  +  int rc = SQLITE_OK;
         5077  +  assert( pPager->state>=PAGER_RESERVED );
         5078  +  if( 0==pagerUseWal(pPager) ){
         5079  +    rc = pager_wait_on_lock(pPager, PAGER_EXCLUSIVE);
         5080  +  }
         5081  +  return rc;
         5082  +}
  5063   5083   
  5064   5084   /*
  5065   5085   ** Sync the database file for the pager pPager. zMaster points to the name
  5066   5086   ** of a master journal file that should be written into the individual
  5067   5087   ** journal file. zMaster may be NULL, which is interpreted as no master
  5068   5088   ** journal (a single database transaction).
  5069   5089   **

Changes to src/vdbeaux.c.

  1642   1642     /* Before doing anything else, call the xSync() callback for any
  1643   1643     ** virtual module tables written in this transaction. This has to
  1644   1644     ** be done before determining whether a master journal file is 
  1645   1645     ** required, as an xSync() callback may add an attached database
  1646   1646     ** to the transaction.
  1647   1647     */
  1648   1648     rc = sqlite3VtabSync(db, &p->zErrMsg);
  1649         -  if( rc!=SQLITE_OK ){
  1650         -    return rc;
  1651         -  }
  1652   1649   
  1653   1650     /* This loop determines (a) if the commit hook should be invoked and
  1654   1651     ** (b) how many database files have open write transactions, not 
  1655   1652     ** including the temp database. (b) is important because if more than 
  1656   1653     ** one database file has an open write transaction, a master journal
  1657   1654     ** file is required for an atomic commit.
  1658   1655     */ 
  1659         -  for(i=0; i<db->nDb; i++){ 
         1656  +  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ 
  1660   1657       Btree *pBt = db->aDb[i].pBt;
  1661   1658       if( sqlite3BtreeIsInTrans(pBt) ){
  1662   1659         needXcommit = 1;
  1663   1660         if( i!=1 ) nTrans++;
         1661  +      rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt));
  1664   1662       }
         1663  +  }
         1664  +  if( rc!=SQLITE_OK ){
         1665  +    return rc;
  1665   1666     }
  1666   1667   
  1667   1668     /* If there are any write-transactions at all, invoke the commit hook */
  1668   1669     if( needXcommit && db->xCommitCallback ){
  1669   1670       rc = db->xCommitCallback(db->pCommitArg);
  1670   1671       if( rc ){
  1671   1672         return SQLITE_CONSTRAINT;