/ Check-in [4d8c6bf4]
Login

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

Overview
Comment:Correctly handle the obscure case of a read-only hot-journal file. (CVS 3791)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 4d8c6bf44ec00ec04e615983cb33425ca2c3998a
User & Date: danielk1977 2007-04-02 11:08:59
Context
2007-04-02
11:22
If an IO error is encountered on a commit, close the journal so that it persists and can (hopefully) rollback the failed transaction later. (CVS 3792) check-in: 22e10cc2 user: drh tags: trunk
11:08
Correctly handle the obscure case of a read-only hot-journal file. (CVS 3791) check-in: 4d8c6bf4 user: danielk1977 tags: trunk
05:07
Fix a resource leak introduced by the change-counter optimisation. Also add some test coverage. (CVS 3790) check-in: ba0538a4 user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

    14     14   ** The pager is used to access a database disk file.  It implements
    15     15   ** atomic commit and rollback through the use of a journal file that
    16     16   ** is separate from the database file.  The pager also implements file
    17     17   ** locking to prevent two processes from writing the same database
    18     18   ** file simultaneously, or one process from reading the database while
    19     19   ** another is writing.
    20     20   **
    21         -** @(#) $Id: pager.c,v 1.314 2007/04/02 05:07:47 danielk1977 Exp $
           21  +** @(#) $Id: pager.c,v 1.315 2007/04/02 11:08:59 danielk1977 Exp $
    22     22   */
    23     23   #ifndef SQLITE_OMIT_DISKIO
    24     24   #include "sqliteInt.h"
    25     25   #include "os.h"
    26     26   #include "pager.h"
    27     27   #include <assert.h>
    28     28   #include <string.h>
................................................................................
  2756   2756           rc = SQLITE_BUSY;
  2757   2757           if( sqlite3OsFileExists(pPager->zJournal) ){
  2758   2758             int ro;
  2759   2759             assert( !pPager->tempFile );
  2760   2760             rc = sqlite3OsOpenReadWrite(pPager->zJournal, &pPager->jfd, &ro);
  2761   2761             if( ro ){
  2762   2762               rc = SQLITE_BUSY;
         2763  +            sqlite3OsClose(&pPager->jfd);
  2763   2764             }
  2764   2765           }
  2765   2766           if( rc!=SQLITE_OK ){
  2766   2767             pager_unlock(pPager);
  2767   2768             return SQLITE_BUSY;
  2768   2769           }
  2769   2770           pPager->journalOpen = 1;
................................................................................
  2796   2797           ** must be discarded.
  2797   2798           */
  2798   2799   
  2799   2800           PgHdr *pPage1 = pager_lookup(pPager, 1);
  2800   2801           if( pPage1 ){
  2801   2802             unlinkPage(pPage1);
  2802   2803   
         2804  +          /* Make sure the former page 1 is right at the start of the
         2805  +          ** free-list. This triggers a special case in pagerAllocatePage()
         2806  +          ** to re-use this page even if the total number of pages in
         2807  +          ** the cache is less than Pager.mxPage.
         2808  +          */
  2803   2809             assert( pPager->pFirst==pPager->pFirstSynced );
  2804   2810             pPage1->pNextFree = pPager->pFirst;
  2805   2811             if( pPager->pFirst ){
  2806   2812               pPager->pFirst->pPrevFree = pPage1;
  2807   2813             }else{
  2808   2814               assert( !pPager->pLast );
  2809   2815               pPager->pLast = pPage1;
  2810   2816             }
  2811   2817             pPager->pFirst = pPage1;
  2812   2818             pPager->pFirstSynced = pPage1;
  2813         -
  2814   2819           }
  2815   2820   
  2816   2821           assert( !pager_lookup(pPager, 1) );
  2817   2822           rc = sqlite3PagerAcquire(pPager, 1, &pPage1, 0);
  2818   2823           if( rc==SQLITE_OK ){
  2819   2824   	  /* The change-counter is stored at offset 24. See also
  2820   2825             ** pager_incr_changecounter().

Changes to test/misc7.test.

     6      6   #    May you do good and not evil.
     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13         -# $Id: misc7.test,v 1.10 2007/04/02 05:07:48 danielk1977 Exp $
           13  +# $Id: misc7.test,v 1.11 2007/04/02 11:08:59 danielk1977 Exp $
    14     14   
    15     15   set testdir [file dirname $argv0]
    16     16   source $testdir/tester.tcl
    17     17   
    18     18   do_test misc7-1 {
    19     19     c_misuse_test
    20     20   } {}
................................................................................
   325    325       set msg
   326    326     } else {
   327    327       error $msg
   328    328     }
   329    329   }
   330    330   
   331    331   sqlite3 db test.db
          332  +
          333  +do_test misc7-16.X {
          334  +  execsql {
          335  +    SELECT count(*) FROM t3;
          336  +  }
          337  +} {32}
          338  +
   332    339   set sqlite_pager_n_sort_bucket 4
   333    340   do_test misc7-17 {
   334    341     execsql {
   335    342       PRAGMA integrity_check;
   336    343       VACUUM;
   337    344       PRAGMA integrity_check;
   338    345     }
   339    346   } {ok ok}
   340    347   set sqlite_pager_n_sort_bucket 0
          348  +
          349  +#----------------------------------------------------------------------
          350  +# Test the situation where a hot-journal is discovered but write-access
          351  +# to it is denied. This should return SQLITE_BUSY.
          352  +#
          353  +do_test misc7-17.1 {
          354  +  execsql {
          355  +    BEGIN;
          356  +    DELETE FROM t3 WHERE (oid%3)==0;
          357  +  }
          358  +  copy_file test.db bak.db
          359  +  copy_file test.db-journal bak.db-journal
          360  +  execsql {
          361  +    COMMIT;
          362  +  }
          363  +
          364  +  copy_file bak.db test.db
          365  +  copy_file bak.db-journal test.db-journal
          366  +  file attributes test.db-journal -permissions r--------
          367  +
          368  +  catchsql {
          369  +    SELECT count(*) FROM t3;
          370  +  }
          371  +} {1 {database is locked}}
          372  +do_test misc7-17.2 {
          373  +  file attributes test.db-journal -permissions rw-------
          374  +  catchsql {
          375  +    SELECT count(*) FROM t3;
          376  +  }
          377  +} {0 28}
   341    378   
   342    379   finish_test