/ Check-in [2f89e9e6]
Login

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

Overview
Comment:Avoid calling truncate() and stat() on the checkpoint journal to improve the speed of a large number of UPDATEs within a transaction. (CVS 819)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:2f89e9e6963cb715f3671f1fdbf4c966aadff6c8
User & Date: drh 2003-01-07 14:46:08
Context
2003-01-08
13:02
Port ot MacOS Classic. Ticket #218. (CVS 820) check-in: 13f82d67 user: drh tags: trunk
2003-01-07
14:46
Avoid calling truncate() and stat() on the checkpoint journal to improve the speed of a large number of UPDATEs within a transaction. (CVS 819) check-in: 2f89e9e6 user: drh tags: trunk
13:55
In the VDBE, allocate space to hold column names when the VDBE first starts. The ColumnCount opcode now just writes the null terminator into this space. (CVS 818) check-in: 46d8f5e3 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
...
105
106
107
108
109
110
111

112
113
114
115
116
117
118
...
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
....
1370
1371
1372
1373
1374
1375
1376

1377
1378
1379
1380
1381
1382
1383
....
1617
1618
1619
1620
1621
1622
1623

1624
1625
1626
1627
1628
1629
1630
....
1636
1637
1638
1639
1640
1641
1642
1643

1644
1645
1646
1647
1648
1649
1650
** 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.64 2003/01/03 02:04:27 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>

................................................................................
  char *zJournal;             /* Name of the journal file */
  OsFile fd, jfd;             /* File descriptors for database and journal */
  OsFile cpfd;                /* File descriptor for the checkpoint journal */
  int dbSize;                 /* Number of pages in the file */
  int origDbSize;             /* dbSize before the current change */
  int ckptSize;               /* Size of database (in pages) at ckpt_begin() */
  off_t ckptJSize;            /* Size of journal at ckpt_begin() */

  int nExtra;                 /* Add this many bytes to each in-memory page */
  void (*xDestructor)(void*); /* Call this routine when freeing pages */
  int nPage;                  /* Total number of in-memory pages */
  int nRef;                   /* Number of in-memory pages with PgHdr.nRef>0 */
  int mxPage;                 /* Maximum number of pages to hold in cache */
  int nHit, nMiss, nOvfl;     /* Cache hits, missing, and LRU overflows */
  u8 journalOpen;             /* True if journal file descriptors is valid */
................................................................................
  rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)pPager->ckptSize);
  pPager->dbSize = pPager->ckptSize;

  /* Figure out how many records are in the checkpoint journal.
  */
  assert( pPager->ckptInUse && pPager->journalOpen );
  sqliteOsSeek(&pPager->cpfd, 0);
  rc = sqliteOsFileSize(&pPager->cpfd, &nRec);
  if( rc!=SQLITE_OK ){
    goto end_ckpt_playback;
  }
  nRec /= sizeof(PageRecord);
  
  /* Copy original pages out of the checkpoint journal and back into the
  ** database file.
  */
  if( pager_old_format ){
    pPager->journalFormat = SQLITE_OLD_JOURNAL_FORMAT;
  }else{
................................................................................
      rc = sqliteOsWrite(&pPager->cpfd, pData, SQLITE_PAGE_SIZE);
    }
    if( rc!=SQLITE_OK ){
      sqlitepager_rollback(pPager);
      pPager->errMask |= PAGER_ERR_FULL;
      return rc;
    }

    assert( pPager->aInCkpt!=0 );
    pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
    page_add_to_ckpt_list(pPg);
  }

  /* Update the database size and return.
  */
................................................................................
  rc = sqliteOsFileSize(&pPager->jfd, &pPager->ckptJSize);
  if( rc ) goto ckpt_begin_failed;
  pPager->ckptSize = pPager->dbSize;
  if( !pPager->ckptOpen ){
    rc = sqlitepager_opentemp(zTemp, &pPager->cpfd);
    if( rc ) goto ckpt_begin_failed;
    pPager->ckptOpen = 1;

  }
  pPager->ckptInUse = 1;
  return SQLITE_OK;
 
ckpt_begin_failed:
  if( pPager->aInCkpt ){
    sqliteFree(pPager->aInCkpt);
................................................................................
/*
** Commit a checkpoint.
*/
int sqlitepager_ckpt_commit(Pager *pPager){
  if( pPager->ckptInUse ){
    PgHdr *pPg, *pNext;
    sqliteOsSeek(&pPager->cpfd, 0);
    sqliteOsTruncate(&pPager->cpfd, 0);

    pPager->ckptInUse = 0;
    sqliteFree( pPager->aInCkpt );
    pPager->aInCkpt = 0;
    for(pPg=pPager->pCkpt; pPg; pPg=pNext){
      pNext = pPg->pNextCkpt;
      assert( pPg->inCkpt );
      pPg->inCkpt = 0;







|







 







>







 







|
<
<
<
<







 







>







 







>







 







|
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
518
519
520
521
522
523
524
525




526
527
528
529
530
531
532
....
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
....
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
....
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
** 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.65 2003/01/07 14:46: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>

................................................................................
  char *zJournal;             /* Name of the journal file */
  OsFile fd, jfd;             /* File descriptors for database and journal */
  OsFile cpfd;                /* File descriptor for the checkpoint journal */
  int dbSize;                 /* Number of pages in the file */
  int origDbSize;             /* dbSize before the current change */
  int ckptSize;               /* Size of database (in pages) at ckpt_begin() */
  off_t ckptJSize;            /* Size of journal at ckpt_begin() */
  int ckptNRec;               /* Number of records in the checkpoint journal */
  int nExtra;                 /* Add this many bytes to each in-memory page */
  void (*xDestructor)(void*); /* Call this routine when freeing pages */
  int nPage;                  /* Total number of in-memory pages */
  int nRef;                   /* Number of in-memory pages with PgHdr.nRef>0 */
  int mxPage;                 /* Maximum number of pages to hold in cache */
  int nHit, nMiss, nOvfl;     /* Cache hits, missing, and LRU overflows */
  u8 journalOpen;             /* True if journal file descriptors is valid */
................................................................................
  rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)pPager->ckptSize);
  pPager->dbSize = pPager->ckptSize;

  /* Figure out how many records are in the checkpoint journal.
  */
  assert( pPager->ckptInUse && pPager->journalOpen );
  sqliteOsSeek(&pPager->cpfd, 0);
  nRec = pPager->ckptNRec;




  
  /* Copy original pages out of the checkpoint journal and back into the
  ** database file.
  */
  if( pager_old_format ){
    pPager->journalFormat = SQLITE_OLD_JOURNAL_FORMAT;
  }else{
................................................................................
      rc = sqliteOsWrite(&pPager->cpfd, pData, SQLITE_PAGE_SIZE);
    }
    if( rc!=SQLITE_OK ){
      sqlitepager_rollback(pPager);
      pPager->errMask |= PAGER_ERR_FULL;
      return rc;
    }
    pPager->ckptNRec++;
    assert( pPager->aInCkpt!=0 );
    pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
    page_add_to_ckpt_list(pPg);
  }

  /* Update the database size and return.
  */
................................................................................
  rc = sqliteOsFileSize(&pPager->jfd, &pPager->ckptJSize);
  if( rc ) goto ckpt_begin_failed;
  pPager->ckptSize = pPager->dbSize;
  if( !pPager->ckptOpen ){
    rc = sqlitepager_opentemp(zTemp, &pPager->cpfd);
    if( rc ) goto ckpt_begin_failed;
    pPager->ckptOpen = 1;
    pPager->ckptNRec = 0;
  }
  pPager->ckptInUse = 1;
  return SQLITE_OK;
 
ckpt_begin_failed:
  if( pPager->aInCkpt ){
    sqliteFree(pPager->aInCkpt);
................................................................................
/*
** Commit a checkpoint.
*/
int sqlitepager_ckpt_commit(Pager *pPager){
  if( pPager->ckptInUse ){
    PgHdr *pPg, *pNext;
    sqliteOsSeek(&pPager->cpfd, 0);
    /* sqliteOsTruncate(&pPager->cpfd, 0); */
    pPager->ckptNRec = 0;
    pPager->ckptInUse = 0;
    sqliteFree( pPager->aInCkpt );
    pPager->aInCkpt = 0;
    for(pPg=pPager->pCkpt; pPg; pPg=pNext){
      pNext = pPg->pNextCkpt;
      assert( pPg->inCkpt );
      pPg->inCkpt = 0;