-C Ensure\stemporary\sfiles\sare\sdeleted\swhen\sthey\sare\sclosed.\s(CVS\s4277)
-D 2007-08-23T11:47:59
+C Add\scode\sto\sreduce\srollback\sjournal\si/o\sbased\son\sIOCAP\sflags.\sAs\syet\suntested.\s(CVS\s4278)
+D 2007-08-23T14:48:24
F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
F src/os_win.c 29c0e19c1072679a4c7818c49fab2f35d2ad7747
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c 896e95aa2dcb74d5b951a87be4eec811617c835b
+F src/pager.c 0879439873a9da769ee400b3b8c0967afd786fe8
F src/pager.h 53087c6fb9db01aed17c7fd044662a27507e89b8
F src/parse.y 2d2ce439dc6184621fb0b86f4fc5aca7f391a590
F src/pragma.c 9b989506a1b7c8aecd6befb8235e2f57a4aba7e5
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 5f0fb894f44069c4aa9b8dba62b4d8a262c991de
-R 22b54f8709250bd737f996dad2021c82
+P cf4e3c158aa71afc91f263a314c2e750d191fb41
+R 48618499cdb378fd88ded4f7882609ca
U danielk1977
-Z fa59609801ef669b738463099d997068
+Z c7849b12c2cdd0aee60800e4b6323c91
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.370 2007/08/23 11:47:59 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.371 2007/08/23 14:48:24 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
seekJournalHdr(pPager);
pPager->journalHdr = pPager->journalOff;
- /* FIX ME:
+ memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
+
+ /*
+ ** Write the nRec Field - the number of page records that follow this
+ ** journal header. Normally, zero is written to this value at this time.
+ ** After the records are added to the journal (and the journal synced,
+ ** if in full-sync mode), the zero is overwritten with the true number
+ ** of records (see syncJournal()).
+ **
+ ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When
+ ** reading the journal this value tells SQLite to assume that the
+ ** rest of the journal file contains valid page records. This assumption
+ ** is dangerous, as if a failure occured whilst writing to the journal
+ ** file it may contain some garbage data. There are two scenarios
+ ** where this risk can be ignored:
**
- ** Possibly for a pager not in no-sync mode, the journal magic should not
- ** be written until nRec is filled in as part of next syncJournal().
+ ** * When the pager is in no-sync mode. Corruption can follow a
+ ** power failure in this case anyway.
**
- ** Actually maybe the whole journal header should be delayed until that
- ** point. Think about this.
+ ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
+ ** that garbage data is never appended to the journal file.
*/
- memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
- /* The nRec Field. 0xFFFFFFFF for no-sync journals. */
- put32bits(&zHeader[sizeof(aJournalMagic)], pPager->noSync ? 0xffffffff : 0);
+ assert(pPager->fd->pMethods||pPager->noSync);
+ if( (pPager->noSync)
+ || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
+ ){
+ put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
+ }else{
+ put32bits(&zHeader[sizeof(aJournalMagic)], 0);
+ }
+
/* The random check-hash initialiser */
sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
** is synced, then the nRec field is updated, then a second sync occurs.
**
** For temporary databases, we do not care if we are able to rollback
-** after a power failure, so sync occurs.
+** after a power failure, so no sync occurs.
+**
+** If the IOCAP_SEQUENTIAL flag is set for the persistent media on which
+** the database is stored, then OsSync() is never called on the journal
+** file. In this case all that is required is to update the nRec field in
+** the journal header.
**
** This routine clears the needSync field of every page current held in
** memory.
PgHdr *pPg;
int rc = SQLITE_OK;
+
/* Sync the journal before modifying the main database
** (assuming there is a journal and it needs to be synced.)
*/
if( pPager->needSync ){
if( !pPager->tempFile ){
+ int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
assert( pPager->journalOpen );
+
/* assert( !pPager->noSync ); // noSync might be set if synchronous
** was turned off after the transaction was started. Ticket #615 */
#ifndef NDEBUG
assert( pPager->journalOff==jSz );
}
#endif
- {
- i64 jrnlOff;
-
+ if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
/* Write the nRec value into the journal file header. If in
** full-synchronous mode, sync the journal first. This ensures that
** all data has really hit the disk before nRec is updated to mark
- ** it as a candidate for rollback.
+ ** it as a candidate for rollback.
+ **
+ ** This is not required if the persistent media supports the
+ ** SAFE_APPEND property. Because in this case it is not possible
+ ** for garbage data to be appended to the file, the nRec field
+ ** is populated with 0xFFFFFFFF when the journal header is written
+ ** and never needs to be updated.
*/
- if( pPager->fullSync ){
+ i64 jrnlOff;
+ if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager));
IOTRACE(("JSYNC %p\n", pPager))
rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags);
rc = write32bits(pPager->jfd, jrnlOff, pPager->nRec);
if( rc ) return rc;
}
- PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager));
- IOTRACE(("JSYNC %p\n", pPager))
- rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags|
- (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
- );
- if( rc!=0 ) return rc;
+ if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
+ PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager));
+ IOTRACE(("JSYNC %p\n", pPager))
+ rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags|
+ (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
+ );
+ if( rc!=0 ) return rc;
+ }
pPager->journalStarted = 1;
}
pPager->needSync = 0;
** it can't be helped.
*/
if( pPg==0 && pPager->pFirst && syncOk && !MEMDB){
+ int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
int rc = syncJournal(pPager);
if( rc!=0 ){
return rc;
}
- if( pPager->fullSync ){
+ if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
/* If in full-sync mode, write a new journal header into the
** journal file. This is done to avoid ever modifying a journal
** header that is involved in the rollback of pages that have