/ 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 Unified Diffs Show Whitespace Changes Patch

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
....
2756
2757
2758
2759
2760
2761
2762

2763
2764
2765
2766
2767
2768
2769
....
2796
2797
2798
2799
2800
2801
2802





2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.314 2007/04/02 05:07:47 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>
................................................................................
        rc = SQLITE_BUSY;
        if( sqlite3OsFileExists(pPager->zJournal) ){
          int ro;
          assert( !pPager->tempFile );
          rc = sqlite3OsOpenReadWrite(pPager->zJournal, &pPager->jfd, &ro);
          if( ro ){
            rc = SQLITE_BUSY;

          }
        }
        if( rc!=SQLITE_OK ){
          pager_unlock(pPager);
          return SQLITE_BUSY;
        }
        pPager->journalOpen = 1;
................................................................................
        ** must be discarded.
        */

        PgHdr *pPage1 = pager_lookup(pPager, 1);
        if( pPage1 ){
          unlinkPage(pPage1);






          assert( pPager->pFirst==pPager->pFirstSynced );
          pPage1->pNextFree = pPager->pFirst;
          if( pPager->pFirst ){
            pPager->pFirst->pPrevFree = pPage1;
          }else{
            assert( !pPager->pLast );
            pPager->pLast = pPage1;
          }
          pPager->pFirst = pPage1;
          pPager->pFirstSynced = pPage1;

        }

        assert( !pager_lookup(pPager, 1) );
        rc = sqlite3PagerAcquire(pPager, 1, &pPage1, 0);
        if( rc==SQLITE_OK ){
	  /* The change-counter is stored at offset 24. See also
          ** pager_incr_changecounter().







|







 







>







 







>
>
>
>
>










<







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
....
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
....
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818

2819
2820
2821
2822
2823
2824
2825
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.315 2007/04/02 11:08:59 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>
................................................................................
        rc = SQLITE_BUSY;
        if( sqlite3OsFileExists(pPager->zJournal) ){
          int ro;
          assert( !pPager->tempFile );
          rc = sqlite3OsOpenReadWrite(pPager->zJournal, &pPager->jfd, &ro);
          if( ro ){
            rc = SQLITE_BUSY;
            sqlite3OsClose(&pPager->jfd);
          }
        }
        if( rc!=SQLITE_OK ){
          pager_unlock(pPager);
          return SQLITE_BUSY;
        }
        pPager->journalOpen = 1;
................................................................................
        ** must be discarded.
        */

        PgHdr *pPage1 = pager_lookup(pPager, 1);
        if( pPage1 ){
          unlinkPage(pPage1);

          /* Make sure the former page 1 is right at the start of the
          ** free-list. This triggers a special case in pagerAllocatePage()
          ** to re-use this page even if the total number of pages in
          ** the cache is less than Pager.mxPage.
          */
          assert( pPager->pFirst==pPager->pFirstSynced );
          pPage1->pNextFree = pPager->pFirst;
          if( pPager->pFirst ){
            pPager->pFirst->pPrevFree = pPage1;
          }else{
            assert( !pPager->pLast );
            pPager->pLast = pPage1;
          }
          pPager->pFirst = pPage1;
          pPager->pFirstSynced = pPage1;

        }

        assert( !pager_lookup(pPager, 1) );
        rc = sqlite3PagerAcquire(pPager, 1, &pPage1, 0);
        if( rc==SQLITE_OK ){
	  /* The change-counter is stored at offset 24. See also
          ** pager_incr_changecounter().

Changes to test/misc7.test.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
325
326
327
328
329
330
331







332
333
334
335
336
337
338
339
340
341






























342
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# $Id: misc7.test,v 1.10 2007/04/02 05:07:48 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test misc7-1 {
  c_misuse_test
} {}
................................................................................
    set msg
  } else {
    error $msg
  }
}

sqlite3 db test.db







set sqlite_pager_n_sort_bucket 4
do_test misc7-17 {
  execsql {
    PRAGMA integrity_check;
    VACUUM;
    PRAGMA integrity_check;
  }
} {ok ok}
set sqlite_pager_n_sort_bucket 0































finish_test







|







 







>
>
>
>
>
>
>










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# $Id: misc7.test,v 1.11 2007/04/02 11:08:59 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test misc7-1 {
  c_misuse_test
} {}
................................................................................
    set msg
  } else {
    error $msg
  }
}

sqlite3 db test.db

do_test misc7-16.X {
  execsql {
    SELECT count(*) FROM t3;
  }
} {32}

set sqlite_pager_n_sort_bucket 4
do_test misc7-17 {
  execsql {
    PRAGMA integrity_check;
    VACUUM;
    PRAGMA integrity_check;
  }
} {ok ok}
set sqlite_pager_n_sort_bucket 0

#----------------------------------------------------------------------
# Test the situation where a hot-journal is discovered but write-access
# to it is denied. This should return SQLITE_BUSY.
#
do_test misc7-17.1 {
  execsql {
    BEGIN;
    DELETE FROM t3 WHERE (oid%3)==0;
  }
  copy_file test.db bak.db
  copy_file test.db-journal bak.db-journal
  execsql {
    COMMIT;
  }

  copy_file bak.db test.db
  copy_file bak.db-journal test.db-journal
  file attributes test.db-journal -permissions r--------

  catchsql {
    SELECT count(*) FROM t3;
  }
} {1 {database is locked}}
do_test misc7-17.2 {
  file attributes test.db-journal -permissions rw-------
  catchsql {
    SELECT count(*) FROM t3;
  }
} {0 28}

finish_test