/ Check-in [f3398fc4]
Login

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

Overview
Comment:Fix a bug in transaction rollback during backup when the CODEC is enabled that can result in a corrupt backup file. This is only a problem when SQLITE_HAS_CODEC is defined.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f3398fc4db765e2c63d425d570c4469a84b3328c
User & Date: drh 2009-11-21 01:33:51
Context
2009-11-21
03:03
Add some missing comments to fts3 files. No source code changes. check-in: b6402b20 user: dan tags: trunk
01:33
Fix a bug in transaction rollback during backup when the CODEC is enabled that can result in a corrupt backup file. This is only a problem when SQLITE_HAS_CODEC is defined. check-in: f3398fc4 user: drh tags: trunk
2009-11-20
18:48
When moving pages as part of autovacuum on an in-memory database, make sure that the source location is journalled so that a ROLLBACK can occur. Part of the fix for ticket [564d412f15a00] check-in: 2f42f91f user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

  1417   1417     int isSavepnt,                /* True for a savepoint rollback */
  1418   1418     Bitvec *pDone                 /* Bitvec of pages already played back */
  1419   1419   ){
  1420   1420     int rc;
  1421   1421     PgHdr *pPg;                   /* An existing page in the cache */
  1422   1422     Pgno pgno;                    /* The page number of a page in journal */
  1423   1423     u32 cksum;                    /* Checksum used for sanity checking */
  1424         -  u8 *aData;                    /* Temporary storage for the page */
         1424  +  char *aData;                  /* Temporary storage for the page */
  1425   1425     sqlite3_file *jfd;            /* The file descriptor for the journal file */
  1426   1426   
  1427   1427     assert( (isMainJrnl&~1)==0 );      /* isMainJrnl is 0 or 1 */
  1428   1428     assert( (isSavepnt&~1)==0 );       /* isSavepnt is 0 or 1 */
  1429   1429     assert( isMainJrnl || pDone );     /* pDone always used on sub-journals */
  1430   1430     assert( isSavepnt || pDone==0 );   /* pDone never used on non-savepoint */
  1431   1431   
  1432         -  aData = (u8*)pPager->pTmpSpace;
         1432  +  aData = pPager->pTmpSpace;
  1433   1433     assert( aData );         /* Temp storage must have already been allocated */
  1434   1434   
  1435   1435     /* Read the page number and page data from the journal or sub-journal
  1436   1436     ** file. Return an error code to the caller if an IO error occurs.
  1437   1437     */
  1438   1438     jfd = isMainJrnl ? pPager->jfd : pPager->sjfd;
  1439   1439     rc = read32bits(jfd, *pOffset, &pgno);
  1440   1440     if( rc!=SQLITE_OK ) return rc;
  1441         -  rc = sqlite3OsRead(jfd, aData, pPager->pageSize, (*pOffset)+4);
         1441  +  rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4);
  1442   1442     if( rc!=SQLITE_OK ) return rc;
  1443   1443     *pOffset += pPager->pageSize + 4 + isMainJrnl*4;
  1444   1444   
  1445   1445     /* Sanity checking on the page.  This is more important that I originally
  1446   1446     ** thought.  If a power failure occurs while the journal is being written,
  1447   1447     ** it could cause invalid data to be written into the journal.  We need to
  1448   1448     ** detect this invalid data (with high probability) and ignore it.
................................................................................
  1453   1453     }
  1454   1454     if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){
  1455   1455       return SQLITE_OK;
  1456   1456     }
  1457   1457     if( isMainJrnl ){
  1458   1458       rc = read32bits(jfd, (*pOffset)-4, &cksum);
  1459   1459       if( rc ) return rc;
  1460         -    if( !isSavepnt && pager_cksum(pPager, aData)!=cksum ){
         1460  +    if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){
  1461   1461         return SQLITE_DONE;
  1462   1462       }
  1463   1463     }
  1464   1464   
  1465   1465     if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
  1466   1466       return rc;
  1467   1467     }
................................................................................
  1499   1499     ** 2008-04-14:  When attempting to vacuum a corrupt database file, it
  1500   1500     ** is possible to fail a statement on a database that does not yet exist.
  1501   1501     ** Do not attempt to write if database file has never been opened.
  1502   1502     */
  1503   1503     pPg = pager_lookup(pPager, pgno);
  1504   1504     assert( pPg || !MEMDB );
  1505   1505     PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
  1506         -               PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData),
  1507         -               (isMainJrnl?"main-journal":"sub-journal")
         1506  +           PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
         1507  +           (isMainJrnl?"main-journal":"sub-journal")
  1508   1508     ));
  1509   1509     if( (pPager->state>=PAGER_EXCLUSIVE)
  1510   1510      && (pPg==0 || 0==(pPg->flags&PGHDR_NEED_SYNC))
  1511   1511      && isOpen(pPager->fd)
  1512   1512      && !isUnsync
  1513   1513     ){
  1514   1514       i64 ofst = (pgno-1)*(i64)pPager->pageSize;
  1515         -    rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, ofst);
         1515  +    rc = sqlite3OsWrite(pPager->fd, (u8*)aData, pPager->pageSize, ofst);
  1516   1516       if( pgno>pPager->dbFileSize ){
  1517   1517         pPager->dbFileSize = pgno;
  1518   1518       }
  1519   1519       if( pPager->pBackup ){
  1520   1520         CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM);
  1521         -      sqlite3BackupUpdate(pPager->pBackup, pgno, aData);
  1522         -      CODEC1(pPager, aData, pgno, 0, rc=SQLITE_NOMEM);
         1521  +      sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
         1522  +      CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData);
  1523   1523       }
  1524   1524     }else if( !isMainJrnl && pPg==0 ){
  1525   1525       /* If this is a rollback of a savepoint and data was not written to
  1526   1526       ** the database and the page is not in-memory, there is a potential
  1527   1527       ** problem. When the page is next fetched by the b-tree layer, it 
  1528   1528       ** will be read from the database file, which may or may not be 
  1529   1529       ** current. 
................................................................................
  1550   1550       ** for page 1 which is held in use in order to keep the lock on the
  1551   1551       ** database active. However such a page may be rolled back as a result
  1552   1552       ** of an internal error resulting in an automatic call to
  1553   1553       ** sqlite3PagerRollback().
  1554   1554       */
  1555   1555       void *pData;
  1556   1556       pData = pPg->pData;
  1557         -    memcpy(pData, aData, pPager->pageSize);
         1557  +    memcpy(pData, (u8*)aData, pPager->pageSize);
  1558   1558       pPager->xReiniter(pPg);
  1559   1559       if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){
  1560   1560         /* If the contents of this page were just restored from the main 
  1561   1561         ** journal file, then its content must be as they were when the 
  1562   1562         ** transaction was first opened. In this case we can mark the page
  1563   1563         ** as clean, since there will be no need to write it out to the.
  1564   1564         **