/ Check-in [dc5be2c8]
Login

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

Overview
Comment:Preliminary fix for ticket #599. More testing and analysis needed. (CVS 1208)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:dc5be2c82b591a385adf02863d89e113272e2ebd
User & Date: drh 2004-02-08 00:40:52
Context
2004-02-08
06:05
Fix inaccuracies and add details to comments in the pager. Change the name of one function to make its purpose clearer. Ticket #599. (CVS 1209) check-in: 48832d35 user: drh tags: trunk
00:40
Preliminary fix for ticket #599. More testing and analysis needed. (CVS 1208) check-in: dc5be2c8 user: drh tags: trunk
2004-02-02
12:29
Remove undocumented extensions from sqlite_mprintf() and friends in order to make it about 10% smaller. (CVS 1207) check-in: 0b3f552b 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
...
567
568
569
570
571
572
573




574
575
576
577
578
579
580
...
590
591
592
593
594
595
596









597
598
599
600
601
602
603
...
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
....
1892
1893
1894
1895
1896
1897
1898
1899

1900
1901
1902
1903
1904
1905
1906
** 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.92 2004/01/07 02:52:08 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>

................................................................................
  */
  assert( pPager->journalOpen );
  sqliteOsSeek(&pPager->jfd, 0);
  rc = sqliteOsFileSize(&pPager->jfd, &szJ);
  if( rc!=SQLITE_OK ){
    goto end_playback;
  }




  if( szJ < sizeof(aMagic)+sizeof(Pgno) ){
    goto end_playback;
  }

  /* Read the beginning of the journal and truncate the
  ** database file back to its original size.
  */
................................................................................
  }else if( memcmp(aMagic, aJournalMagic1, sizeof(aMagic))==0 ){
    format = JOURNAL_FORMAT_1;
  }else{
    rc = SQLITE_PROTOCOL;
    goto end_playback;
  }
  if( format>=JOURNAL_FORMAT_3 ){









    rc = read32bits(format, &pPager->jfd, (u32*)&nRec);
    if( rc ) goto end_playback;
    rc = read32bits(format, &pPager->jfd, &pPager->cksumInit);
    if( rc ) goto end_playback;
    if( nRec==0xffffffff || useJournalSize ){
      nRec = (szJ - JOURNAL_HDR_SZ(3))/JOURNAL_PG_SZ(3);
    }
................................................................................
      }
      break;
    }
  }

  /* Pages that have been written to the journal but never synced
  ** where not restored by the loop above.  We have to restore those
  ** pages by reading the back from the original database.
  */
  if( rc==SQLITE_OK ){
    PgHdr *pPg;
    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
      char zBuf[SQLITE_PAGE_SIZE];
      if( !pPg->dirty ) continue;
      if( (int)pPg->pgno <= pPager->origDbSize ){
................................................................................
    ** if there have been no changes to the database file. */
    assert( pPager->needSync==0 );
    rc = pager_unwritelock(pPager);
    pPager->dbSize = -1;
    return rc;
  }
  assert( pPager->journalOpen );
  if( pPager->needSync && sqliteOsSync(&pPager->jfd)!=SQLITE_OK ){

    goto commit_abort;
  }
  pPg = pager_get_all_dirty_pages(pPager);
  if( pPg ){
    rc = pager_write_pagelist(pPg);
    if( rc || (!pPager->noSync && sqliteOsSync(&pPager->fd)!=SQLITE_OK) ){
      goto commit_abort;







|







 







>
>
>
>







 







>
>
>
>
>
>
>
>
>







 







|







 







|
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
...
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
....
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
** 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.93 2004/02/08 00:40:52 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>

................................................................................
  */
  assert( pPager->journalOpen );
  sqliteOsSeek(&pPager->jfd, 0);
  rc = sqliteOsFileSize(&pPager->jfd, &szJ);
  if( rc!=SQLITE_OK ){
    goto end_playback;
  }

  /* If the journal file is too small to contain a complete header,
  ** then ignore the journal completely.
  */
  if( szJ < sizeof(aMagic)+sizeof(Pgno) ){
    goto end_playback;
  }

  /* Read the beginning of the journal and truncate the
  ** database file back to its original size.
  */
................................................................................
  }else if( memcmp(aMagic, aJournalMagic1, sizeof(aMagic))==0 ){
    format = JOURNAL_FORMAT_1;
  }else{
    rc = SQLITE_PROTOCOL;
    goto end_playback;
  }
  if( format>=JOURNAL_FORMAT_3 ){
    if( szJ < sizeof(aMagic) + 3*sizeof(u32) ){
      /* Ignore the journal if it is too small to contain a complete
      ** header.  We already did this test once above, but at the prior
      ** test, we did not know the journal format and so we had to assume
      ** the smallest possible header.  Now we know the header is bigger
      ** than that so we test again.
      */
      goto end_playback;
    }
    rc = read32bits(format, &pPager->jfd, (u32*)&nRec);
    if( rc ) goto end_playback;
    rc = read32bits(format, &pPager->jfd, &pPager->cksumInit);
    if( rc ) goto end_playback;
    if( nRec==0xffffffff || useJournalSize ){
      nRec = (szJ - JOURNAL_HDR_SZ(3))/JOURNAL_PG_SZ(3);
    }
................................................................................
      }
      break;
    }
  }

  /* Pages that have been written to the journal but never synced
  ** where not restored by the loop above.  We have to restore those
  ** pages by reading them back from the original database.
  */
  if( rc==SQLITE_OK ){
    PgHdr *pPg;
    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
      char zBuf[SQLITE_PAGE_SIZE];
      if( !pPg->dirty ) continue;
      if( (int)pPg->pgno <= pPager->origDbSize ){
................................................................................
    ** if there have been no changes to the database file. */
    assert( pPager->needSync==0 );
    rc = pager_unwritelock(pPager);
    pPager->dbSize = -1;
    return rc;
  }
  assert( pPager->journalOpen );
  rc = syncAllPages(pPager);
  if( rc!=SQLITE_OK ){
    goto commit_abort;
  }
  pPg = pager_get_all_dirty_pages(pPager);
  if( pPg ){
    rc = pager_write_pagelist(pPg);
    if( rc || (!pPager->noSync && sqliteOsSync(&pPager->fd)!=SQLITE_OK) ){
      goto commit_abort;

Changes to tool/showjournal.c.

39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
56

57






58
59


60




61
62
63
  free(aData);
}

int main(int argc, char **argv){
  struct stat sbuf;
  unsigned int u;
  int rc;
  char zBuf[100];

  if( argc!=2 ){
    fprintf(stderr,"Usage: %s FILENAME\n", argv[0]);
    exit(1);
  }
  db = open(argv[1], O_RDONLY);
  if( db<0 ){
    fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
    exit(1);
  }
  read(db, zBuf, 8);

  read(db, &u, sizeof(u));






  printf("Database Size: %u\n", u);
  while( read(db, &u, sizeof(u))==sizeof(u) ){


    print_page(u);




  }
  close(db);
}







|
>










>
|
>
>
>
>
>
>

<
>
>

>
>
>
>



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
  free(aData);
}

int main(int argc, char **argv){
  struct stat sbuf;
  unsigned int u;
  int rc;
  unsigned char zBuf[10];
  unsigned char zBuf2[sizeof(u)];
  if( argc!=2 ){
    fprintf(stderr,"Usage: %s FILENAME\n", argv[0]);
    exit(1);
  }
  db = open(argv[1], O_RDONLY);
  if( db<0 ){
    fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
    exit(1);
  }
  read(db, zBuf, 8);
  if( zBuf[7]==0xd6 ){
    read(db, &u, sizeof(u));
    printf("Records in Journal: %u\n", u);
    read(db, &u, sizeof(u));
    printf("Magic Number: 0x%08x\n", u);
  }
  read(db, zBuf2, sizeof(zBuf2));
  u = zBuf2[0]<<24 | zBuf2[1]<<16 | zBuf2[2]<<8 | zBuf2[3];
  printf("Database Size: %u\n", u);

  while( read(db, zBuf2, sizeof(zBuf2))==sizeof(zBuf2) ){
    u = zBuf2[0]<<24 | zBuf2[1]<<16 | zBuf2[2]<<8 | zBuf2[3];
    print_page(u);
    if( zBuf[7]==0xd6 ){
      read(db, &u, sizeof(u));
      printf("Checksum: 0x%08x\n", u);
    }
  }
  close(db);
}