/ Check-in [531abc80]
Login

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

Overview
Comment:Fix a problem wherein changing the journal-mode immediately after leaving exclusive-locking mode could lead to the database being unlocked without clearing the changeCountDone flag.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1:531abc808526d607768bf6f503268d4cc66ab169
User & Date: dan 2010-08-07 09:31:14
Context
2010-08-07
16:17
Fix minor problems and update comments in pager.c. check-in: 92e45637 user: dan tags: experimental
09:31
Fix a problem wherein changing the journal-mode immediately after leaving exclusive-locking mode could lead to the database being unlocked without clearing the changeCountDone flag. check-in: 531abc80 user: dan tags: experimental
05:15
Add test case 'cgt_pager_1', intended for use with callgrind to detect performance regression in the pager module, to threadtest3.c. check-in: b5d46f1e user: dan tags: experimental
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pager.c.

6360
6361
6362
6363
6364
6365
6366

6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392




6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410

6411
6412
6413
6414
6415
6416
6417
      eMode = eOld;
    }
  }

  if( eMode!=eOld ){

    /* Change the journal mode. */

    pPager->journalMode = (u8)eMode;

    /* When transistioning from TRUNCATE or PERSIST to any other journal
    ** mode except WAL (and we are not in locking_mode=EXCLUSIVE) then 
    ** delete the journal file.
    */
    assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
    assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
    assert( (PAGER_JOURNALMODE_DELETE & 5)==0 );
    assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 );
    assert( (PAGER_JOURNALMODE_OFF & 5)==0 );
    assert( (PAGER_JOURNALMODE_WAL & 5)==5 );

    assert( isOpen(pPager->fd) || pPager->exclusiveMode );
    if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){

      sqlite3OsClose(pPager->jfd);

      /* In this case we would like to delete the journal file. If it is
      ** not possible, then that is not a problem. Deleting the journal file
      ** here is an optimization only.
      **
      ** Before deleting the journal file, obtain a RESERVED lock on the
      ** database file. This ensures that the journal file is not deleted
      ** while it is in use by some other client.
      */




      int rc = SQLITE_OK;
      int state = pPager->eState;
      if( state==PAGER_OPEN ){
        rc = sqlite3PagerSharedLock(pPager);
      }
      if( pPager->eState==PAGER_READER ){
        assert( rc==SQLITE_OK );
        rc = pagerLockDb(pPager, RESERVED_LOCK);
      }
      if( rc==SQLITE_OK ){
        sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
      }
      if( rc==SQLITE_OK && state==PAGER_READER ){
        pagerUnlockDb(pPager, SHARED_LOCK);
      }else if( state==PAGER_OPEN ){
        pager_unlock(pPager);
      }
      assert( state==pPager->eState );

    }
  }

  /* Return the new journal mode */
  return (int)pPager->journalMode;
}








>



|












<
<








>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>







6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383


6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
      eMode = eOld;
    }
  }

  if( eMode!=eOld ){

    /* Change the journal mode. */
    assert( pPager->eState!=PAGER_ERROR );
    pPager->journalMode = (u8)eMode;

    /* When transistioning from TRUNCATE or PERSIST to any other journal
    ** mode except WAL, unless the pager is in locking_mode=exclusive mode,
    ** delete the journal file.
    */
    assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
    assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
    assert( (PAGER_JOURNALMODE_DELETE & 5)==0 );
    assert( (PAGER_JOURNALMODE_MEMORY & 5)==4 );
    assert( (PAGER_JOURNALMODE_OFF & 5)==0 );
    assert( (PAGER_JOURNALMODE_WAL & 5)==5 );

    assert( isOpen(pPager->fd) || pPager->exclusiveMode );
    if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){



      /* In this case we would like to delete the journal file. If it is
      ** not possible, then that is not a problem. Deleting the journal file
      ** here is an optimization only.
      **
      ** Before deleting the journal file, obtain a RESERVED lock on the
      ** database file. This ensures that the journal file is not deleted
      ** while it is in use by some other client.
      */
      sqlite3OsClose(pPager->jfd);
      if( pPager->eLock>=RESERVED_LOCK ){
        sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
      }else{
        int rc = SQLITE_OK;
        int state = pPager->eState;
        if( state==PAGER_OPEN ){
          rc = sqlite3PagerSharedLock(pPager);
        }
        if( pPager->eState==PAGER_READER ){
          assert( rc==SQLITE_OK );
          rc = pagerLockDb(pPager, RESERVED_LOCK);
        }
        if( rc==SQLITE_OK ){
          sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
        }
        if( rc==SQLITE_OK && state==PAGER_READER ){
          pagerUnlockDb(pPager, SHARED_LOCK);
        }else if( state==PAGER_OPEN ){
          pager_unlock(pPager);
        }
        assert( state==pPager->eState );
      }
    }
  }

  /* Return the new journal mode */
  return (int)pPager->journalMode;
}

Changes to test/jrnlmode.test.

519
520
521
522
523
524
525
526































527
      PRAGMA page_size = 1024;
      PRAGMA user_version = 5;
      PRAGMA user_version;
    }
  } {memory 5}
  do_test jrnlmode-7.2 { file size test.db } {1024}
}
































finish_test








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

519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
      PRAGMA page_size = 1024;
      PRAGMA user_version = 5;
      PRAGMA user_version;
    }
  } {memory 5}
  do_test jrnlmode-7.2 { file size test.db } {1024}
}

do_execsql_test jrnlmode-8.1  { PRAGMA locking_mode=EXCLUSIVE } {exclusive}
do_execsql_test jrnlmode-8.2  { CREATE TABLE t1(x) }            {}
do_execsql_test jrnlmode-8.3  { INSERT INTO t1 VALUES(123) }    {}
do_execsql_test jrnlmode-8.4  { SELECT * FROM t1 }              {123}
do_execsql_test jrnlmode-8.5  { PRAGMA journal_mode=PERSIST }   {persist}
do_execsql_test jrnlmode-8.6  { PRAGMA journal_mode=DELETE }    {delete}
do_execsql_test jrnlmode-8.7  { PRAGMA journal_mode=TRUNCATE }  {truncate}
do_execsql_test jrnlmode-8.8  { PRAGMA journal_mode=DELETE }    {delete}
do_execsql_test jrnlmode-8.9  { CREATE TABLE t2(y) }            {}
do_execsql_test jrnlmode-8.10 { INSERT INTO t2 VALUES(456) }    {}
do_execsql_test jrnlmode-8.11 { SELECT * FROM t1, t2 }          {123 456}
do_execsql_test jrnlmode-8.12 { PRAGMA locking_mode=NORMAL }    {normal}
do_execsql_test jrnlmode-8.13 { PRAGMA journal_mode=PERSIST }   {persist}
do_execsql_test jrnlmode-8.14 { PRAGMA journal_mode=TRUNCATE }  {truncate}
do_execsql_test jrnlmode-8.15 { PRAGMA journal_mode=PERSIST }   {persist}
do_execsql_test jrnlmode-8.16 { PRAGMA journal_mode=DELETE }    {delete}
do_execsql_test jrnlmode-8.17 { PRAGMA journal_mode=TRUNCATE }  {truncate}
do_execsql_test jrnlmode-8.18 { PRAGMA locking_mode=EXCLUSIVE } {exclusive}
do_execsql_test jrnlmode-8.19 { CREATE TABLE t3(z) }            {}
do_execsql_test jrnlmode-8.20 { BEGIN IMMEDIATE }               {}
do_execsql_test jrnlmode-8.21 { PRAGMA journal_mode=DELETE }    {delete}
do_execsql_test jrnlmode-8.22 { COMMIT }                        {}
do_execsql_test jrnlmode-8.23 { PRAGMA journal_mode=DELETE }    {delete}
do_execsql_test jrnlmode-8.24 { PRAGMA journal_mode=TRUNCATE }  {truncate}
do_execsql_test jrnlmode-8.25 { PRAGMA locking_mode=NORMAL }    {normal}
do_execsql_test jrnlmode-8.26 { CREATE TABLE t4(w) }            {}
do_execsql_test jrnlmode-8.27 { BEGIN IMMEDIATE }               {}
do_execsql_test jrnlmode-8.28 { PRAGMA journal_mode=DELETE }    {delete}
do_execsql_test jrnlmode-8.29 { COMMIT }                        {}
do_execsql_test jrnlmode-8.30 { PRAGMA journal_mode=DELETE }    {delete}

finish_test