/* ** This function is called when a new transaction is opened, just after ** the first journal-header is written to the journal file. */ static int openTransaction(jt_file *pMain, jt_file *pJournal){ unsigned char *aData; sqlite3_file *p = pMain->pReal; int rc = SQLITE_OK; closeTransaction(pMain); aData = sqlite3_malloc(pMain->nPagesize); pMain->pWritable = sqlite3BitvecCreate(pMain->nPage); pMain->aCksum = sqlite3_malloc(sizeof(u32) * (pMain->nPage + 1)); pJournal->iMaxOff = 0; if( !pMain->pWritable || !pMain->aCksum || !aData ){ rc = SQLITE_IOERR_NOMEM; }else if( pMain->nPage>0 ){ u32 iTrunk; int iSave; int iSave2; stop_ioerr_simulation(&iSave, &iSave2); /* Read the database free-list. Add the page-number for each free-list ** leaf to the jt_file.pWritable bitvec. */ rc = sqlite3OsRead(p, aData, pMain->nPagesize, 0); if( rc==SQLITE_OK ){ u32 nDbsize = decodeUint32(&aData[28]); if( nDbsize>0 && memcmp(&aData[24], &aData[92], 4)==0 ){ u32 iPg; for(iPg=nDbsize+1; iPg<=pMain->nPage; iPg++){ sqlite3BitvecSet(pMain->pWritable, iPg); } } } iTrunk = decodeUint32(&aData[32]); while( rc==SQLITE_OK && iTrunk>0 ){ u32 nLeaf; u32 iLeaf; sqlite3_int64 iOff = (iTrunk-1)*pMain->nPagesize; rc = sqlite3OsRead(p, aData, pMain->nPagesize, iOff); nLeaf = decodeUint32(&aData[4]); for(iLeaf=0; rc==SQLITE_OK && iLeaf<nLeaf; iLeaf++){ u32 pgno = decodeUint32(&aData[8+4*iLeaf]); sqlite3BitvecSet(pMain->pWritable, pgno); } iTrunk = decodeUint32(aData); } /* Calculate and store a checksum for each page in the database file. */ if( rc==SQLITE_OK ){ int ii; for(ii=0; rc==SQLITE_OK && ii<pMain->nPage; ii++){ i64 iOff = (i64)(pMain->nPagesize) * (i64)ii; if( iOff==PENDING_BYTE ) continue; rc = sqlite3OsRead(pMain->pReal, aData, pMain->nPagesize, iOff); pMain->aCksum[ii] = genCksum(aData, pMain->nPagesize); } } start_ioerr_simulation(iSave, iSave2); } sqlite3_free(aData); return rc; }
/* ** The first argument to this function is a handle open on a journal file. ** This function reads the journal file and adds the page number for each ** page in the journal to the Bitvec object passed as the second argument. */ static int readJournalFile(jt_file *p, jt_file *pMain){ int rc = SQLITE_OK; unsigned char zBuf[28]; sqlite3_file *pReal = p->pReal; sqlite3_int64 iOff = 0; sqlite3_int64 iSize = p->iMaxOff; unsigned char *aPage; int iSave; int iSave2; aPage = sqlite3_malloc(pMain->nPagesize); if( !aPage ){ return SQLITE_IOERR_NOMEM; } stop_ioerr_simulation(&iSave, &iSave2); while( rc==SQLITE_OK && iOff<iSize ){ u32 nRec, nPage, nSector, nPagesize; u32 ii; /* Read and decode the next journal-header from the journal file. */ rc = sqlite3OsRead(pReal, zBuf, 28, iOff); if( rc!=SQLITE_OK || decodeJournalHdr(zBuf, &nRec, &nPage, &nSector, &nPagesize) ){ goto finish_rjf; } iOff += nSector; if( nRec==0 ){ /* A trick. There might be another journal-header immediately ** following this one. In this case, 0 records means 0 records, ** not "read until the end of the file". See also ticket #2565. */ if( iSize>=(iOff+nSector) ){ rc = sqlite3OsRead(pReal, zBuf, 28, iOff); if( rc!=SQLITE_OK || 0==decodeJournalHdr(zBuf, 0, 0, 0, 0) ){ continue; } } nRec = (iSize-iOff) / (pMain->nPagesize+8); } /* Read all the records that follow the journal-header just read. */ for(ii=0; rc==SQLITE_OK && ii<nRec && iOff<iSize; ii++){ u32 pgno; rc = sqlite3OsRead(pReal, zBuf, 4, iOff); if( rc==SQLITE_OK ){ pgno = decodeUint32(zBuf); if( pgno>0 && pgno<=pMain->nPage ){ if( 0==sqlite3BitvecTest(pMain->pWritable, pgno) ){ rc = sqlite3OsRead(pReal, aPage, pMain->nPagesize, iOff+4); if( rc==SQLITE_OK ){ u32 cksum = genCksum(aPage, pMain->nPagesize); assert( cksum==pMain->aCksum[pgno-1] ); } } sqlite3BitvecSet(pMain->pWritable, pgno); } iOff += (8 + pMain->nPagesize); } } iOff = ((iOff + (nSector-1)) / nSector) * nSector; } finish_rjf: start_ioerr_simulation(iSave, iSave2); sqlite3_free(aPage); if( rc==SQLITE_IOERR_SHORT_READ ){ rc = SQLITE_OK; } return rc; }
static int readJournalFile(jt_file *p, jt_file *pMain){ int rc = SQLITE_OK; unsigned char zBuf[28]; sqlite3_file *pReal = p->pReal; sqlite3_int64 iOff = 0; sqlite3_int64 iSize = p->iMaxOff; unsigned char *aPage; int iSave; int iSave2; aPage = sqlite3_malloc(pMain->nPagesize); if( !aPage ){ return SQLITE_IOERR_NOMEM; } stop_ioerr_simulation(&iSave, &iSave2); while( rc==SQLITE_OK && iOff<iSize ){ u32 nRec, nPage, nSector, nPagesize; u32 ii; rc = sqlite3OsRead(pReal, zBuf, 28, iOff); if( rc!=SQLITE_OK || decodeJournalHdr(zBuf, &nRec, &nPage, &nSector, &nPagesize) ){ goto finish_rjf; } iOff += nSector; if( nRec==0 ){ if( iSize>=(iOff+nSector) ){ rc = sqlite3OsRead(pReal, zBuf, 28, iOff); if( rc!=SQLITE_OK || 0==decodeJournalHdr(zBuf, 0, 0, 0, 0) ){ continue; } } nRec = (iSize-iOff) / (pMain->nPagesize+8); } for(ii=0; rc==SQLITE_OK && ii<nRec && iOff<iSize; ii++){ u32 pgno; rc = sqlite3OsRead(pReal, zBuf, 4, iOff); if( rc==SQLITE_OK ){ pgno = decodeUint32(zBuf); if( pgno>0 && pgno<=pMain->nPage ){ if( 0==sqlite3BitvecTest(pMain->pWritable, pgno) ){ rc = sqlite3OsRead(pReal, aPage, pMain->nPagesize, iOff+4); if( rc==SQLITE_OK ){ u32 cksum = genCksum(aPage, pMain->nPagesize); assert( cksum==pMain->aCksum[pgno-1] ); } } sqlite3BitvecSet(pMain->pWritable, pgno); } iOff += (8 + pMain->nPagesize); } } iOff = ((iOff + (nSector-1)) / nSector) * nSector; } finish_rjf: start_ioerr_simulation(iSave, iSave2); sqlite3_free(aPage); if( rc==SQLITE_IOERR_SHORT_READ ){ rc = SQLITE_OK; } return rc; }