]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add code to reduce rollback journal i/o based on IOCAP flags. As yet untested. (CVS...
authordanielk1977 <danielk1977@noemail.net>
Thu, 23 Aug 2007 14:48:23 +0000 (14:48 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Thu, 23 Aug 2007 14:48:23 +0000 (14:48 +0000)
FossilOrigin-Name: 595568492e63822caed5b6970542dcee4615dc4d

manifest
manifest.uuid
src/pager.c

index f76bb919d87d5457c798ad44a64073eaa2f1c7c3..a764a905cb4743a2a07e2b70ccae3e9de99730fd 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-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
@@ -115,7 +115,7 @@ F src/os_unix.c 3ff776e03535b64df12dcc272a913a52d69f3e4a
 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
@@ -560,7 +560,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 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
index 44ae10e4a65c30b47e7c84353fee23f6de603c75..e3b70f662e30dc1d01bd2bf2f4196dde2f383b33 100644 (file)
@@ -1 +1 @@
-cf4e3c158aa71afc91f263a314c2e750d191fb41
\ No newline at end of file
+595568492e63822caed5b6970542dcee4615dc4d
\ No newline at end of file
index eaecdf6df23b63bd218bbf5d2b2428fad7e7d53e..504bfcbf1b0795c61044cbebee43fba706e61256 100644 (file)
@@ -18,7 +18,7 @@
 ** 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"
@@ -822,17 +822,37 @@ static int writeJournalHdr(Pager *pPager){
   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);
@@ -2484,7 +2504,12 @@ int sqlite3PagerRef(DbPage *pPg){
 ** 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.
@@ -2493,12 +2518,15 @@ static int syncJournal(Pager *pPager){
   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
@@ -2512,15 +2540,20 @@ static int syncJournal(Pager *pPager){
         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);
@@ -2532,12 +2565,14 @@ static int syncJournal(Pager *pPager){
         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;
@@ -2774,11 +2809,12 @@ static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){
   ** 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