/ Check-in [6c927dd3]
Login

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

Overview
Comment:Fix a bug in the legacy journal format writing logic. (CVS 862)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6c927dd36c19ebb8bb8222b4d18ed67f4fe733e8
User & Date: drh 2003-02-12 02:10:15
Context
2003-02-12
14:09
Added the new FULL option to the SYNCHRONOUS pragma. Still need to test it. (CVS 863) check-in: 792a9e15 user: drh tags: trunk
02:10
Fix a bug in the legacy journal format writing logic. (CVS 862) check-in: 6c927dd3 user: drh tags: trunk
2003-02-11
14:55
Modify the journal format to be more robust against garbage that might appear in the file after a power failure. The changes are mostly working but more testing is still required. This check-in is to checkpoint the changes so far. (CVS 861) check-in: 8ec56325 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
608
609
610
611
612
613
614
615

616
617
618
619
620

621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
....
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041


1042
1043
1044
1045
1046
1047
1048
1049
1050
1051

1052
1053
1054
1055
1056
1057
1058
** 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.73 2003/02/11 14:55:41 drh Exp $
*/
#include "os.h"         /* Must be first to enable large file support */
#include "sqliteInt.h"
#include "pager.h"
#include <assert.h>
#include <string.h>

................................................................................
    if( rc ) goto end_playback;
    rc = read32bits(format, &pPager->jfd, &pPager->cksumInit);
    if( rc ) goto end_playback;
    if( nRec==0xffffffff ){
      nRec = (szJ - JOURNAL_HDR_SZ(3))/JOURNAL_PG_SZ(3);
    }
  }else{
    nRec = (szJ - (sizeof(aMagic)+sizeof(Pgno))) / sizeof(PageRecord);

  }
  rc = read32bits(format, &pPager->jfd, &mxPg);
  if( rc!=SQLITE_OK ){
    goto end_playback;
  }

  rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)mxPg);
  if( rc!=SQLITE_OK ){
    goto end_playback;
  }
  pPager->dbSize = mxPg;
  
  /* Copy original pages out of the journal and back into the database file.
  */
  for(i=0; i<nRec; i++){
    rc = pager_playback_one_page(pPager, &pPager->jfd, format);
    if( rc!=SQLITE_OK ){
      if( rc==SQLITE_DONE ){
fprintf(stderr,"Playback complete after %d of %d records\n", i, nRec);
        rc = SQLITE_OK;
      }
      break;
    }
  }


................................................................................
  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 ){
      off_t szJ;
      assert( pPager->journalOpen );
      assert( !pPager->noSync );
#ifndef NDEBUG
      {
        off_t hdrSz, pgSz;
        hdrSz = JOURNAL_HDR_SZ(journal_format);
        pgSz = JOURNAL_PG_SZ(journal_format);
        rc = sqliteOsFileSize(&pPager->jfd, &pPager->syncJSize);
        if( rc!=0 ) return rc;
        assert( pPager->nRec*pgSz+hdrSz==pPager->syncJSize );
      }
#endif


      if( pPager->fullSync ){
        TRACE1("SYNC\n");
        rc = sqliteOsSync(&pPager->jfd);
        if( rc!=0 ) return rc;
      }
      sqliteOsSeek(&pPager->jfd, sizeof(aJournalMagic1));
      write32bits(&pPager->jfd, pPager->nRec);
      szJ = JOURNAL_HDR_SZ(journal_format) +
               pPager->nRec*JOURNAL_PG_SZ(journal_format);
      sqliteOsSeek(&pPager->jfd, szJ);

      TRACE1("SYNC\n");
      rc = sqliteOsSync(&pPager->jfd);
      if( rc!=0 ) return rc;
      pPager->journalStarted = 1;
    }
    pPager->needSync = 0;








|







 







|
>





>












<







 







<












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







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634

635
636
637
638
639
640
641
....
1023
1024
1025
1026
1027
1028
1029

1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
** 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.74 2003/02/12 02:10:15 drh Exp $
*/
#include "os.h"         /* Must be first to enable large file support */
#include "sqliteInt.h"
#include "pager.h"
#include <assert.h>
#include <string.h>

................................................................................
    if( rc ) goto end_playback;
    rc = read32bits(format, &pPager->jfd, &pPager->cksumInit);
    if( rc ) goto end_playback;
    if( nRec==0xffffffff ){
      nRec = (szJ - JOURNAL_HDR_SZ(3))/JOURNAL_PG_SZ(3);
    }
  }else{
    nRec = (szJ - JOURNAL_HDR_SZ(2))/JOURNAL_PG_SZ(2);
    assert( nRec*JOURNAL_PG_SZ(2)+JOURNAL_HDR_SZ(2)==szJ );
  }
  rc = read32bits(format, &pPager->jfd, &mxPg);
  if( rc!=SQLITE_OK ){
    goto end_playback;
  }
  assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg );
  rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)mxPg);
  if( rc!=SQLITE_OK ){
    goto end_playback;
  }
  pPager->dbSize = mxPg;
  
  /* Copy original pages out of the journal and back into the database file.
  */
  for(i=0; i<nRec; i++){
    rc = pager_playback_one_page(pPager, &pPager->jfd, format);
    if( rc!=SQLITE_OK ){
      if( rc==SQLITE_DONE ){

        rc = SQLITE_OK;
      }
      break;
    }
  }


................................................................................
  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 ){

      assert( pPager->journalOpen );
      assert( !pPager->noSync );
#ifndef NDEBUG
      {
        off_t hdrSz, pgSz;
        hdrSz = JOURNAL_HDR_SZ(journal_format);
        pgSz = JOURNAL_PG_SZ(journal_format);
        rc = sqliteOsFileSize(&pPager->jfd, &pPager->syncJSize);
        if( rc!=0 ) return rc;
        assert( pPager->nRec*pgSz+hdrSz==pPager->syncJSize );
      }
#endif
      if( journal_format>=3 ){
        off_t szJ;
        if( pPager->fullSync ){
          TRACE1("SYNC\n");
          rc = sqliteOsSync(&pPager->jfd);
          if( rc!=0 ) return rc;
        }
        sqliteOsSeek(&pPager->jfd, sizeof(aJournalMagic1));
        write32bits(&pPager->jfd, pPager->nRec);
        szJ = JOURNAL_HDR_SZ(journal_format) +
                 pPager->nRec*JOURNAL_PG_SZ(journal_format);
        sqliteOsSeek(&pPager->jfd, szJ);
      }
      TRACE1("SYNC\n");
      rc = sqliteOsSync(&pPager->jfd);
      if( rc!=0 ) return rc;
      pPager->journalStarted = 1;
    }
    pPager->needSync = 0;