/ Check-in [d0745a43]
Login

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

Overview
Comment:In the pager, load the content of pages which were initialized with noContent==1 if they are subsequently requested with noContent==0. (CVS 3875)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d0745a43b6e037d16e1ec38c7c4d961a80d1ef48
User & Date: drh 2007-04-26 12:11:28
Context
2007-04-26
14:42
Add largely untested code for the incremental vacuum function. (CVS 3876) check-in: f6a6d2b8 user: danielk1977 tags: trunk
12:11
In the pager, load the content of pages which were initialized with noContent==1 if they are subsequently requested with noContent==0. (CVS 3875) check-in: d0745a43 user: drh tags: trunk
2007-04-25
18:23
Fix segfaults that can occur if a malloc failure happens just before a built-in function calls sqlite3_value_text(). (CVS 3874) check-in: 9cb0ed6e 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
....
2917
2918
2919
2920
2921
2922
2923



















2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953

2954
2955
2956
2957
2958
2959
2960
2961
....
3056
3057
3058
3059
3060
3061
3062






3063
3064
3065
3066
3067
3068
3069
....
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
** 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.329 2007/04/16 15:02:19 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>
................................................................................
    assert(pPg);
  }
  *ppPg = pPg;

pager_allocate_out:
  return rc;
}




















/*
** Acquire a page.
**
** A read lock on the disk file is obtained when the first page is acquired. 
** This read lock is dropped when the last page is released.
**
** A _get works for any page number greater than 0.  If the database
** file is smaller than the requested page, then no actual disk
** read occurs and the memory image of the page is initialized to
** all zeros.  The extra data appended to a page is always initialized
** to zeros the first time a page is loaded into memory.
**
** The acquisition might fail for several reasons.  In all cases,
** an appropriate error code is returned and *ppPage is set to NULL.
**
** See also sqlite3PagerLookup().  Both this routine and _lookup() attempt
** to find a page in the in-memory cache first.  If the page is not already
** in memory, this routine goes to disk to read it in whereas _lookup()
** just returns 0.  This routine acquires a read-lock the first time it
** has to go to disk, and could also playback an old journal if necessary.
** Since _lookup() never goes to disk, it never has to deal with locks
** or journal files.
**
** If noContent is false, the page contents are actually read from disk.
** If noContent is true, it means that we do not care about the contents
** of the page at this time, so do not do a disk read.  Just fill in the
** page content with zeros.  But mark the fact that we have not read the
** content by setting the PgHdr.needRead flag.  Later on, if 
** sqlite3PagerWrite() is called on this page, that means that the

** content is needed and the disk read should occur at that point.
*/
int sqlite3PagerAcquire(
  Pager *pPager,      /* The pager open on the database file */
  Pgno pgno,          /* Page number to fetch */
  DbPage **ppPage,    /* Write a pointer to the page here */
  int noContent       /* Do not bother reading content from disk if true */
){
................................................................................
#ifdef SQLITE_CHECK_PAGES
    pPg->pageHash = pager_pagehash(pPg);
#endif
  }else{
    /* The requested page is in the page cache. */
    assert(pPager->nRef>0 || pgno==1);
    PAGER_INCR(pPager->nHit);






    page_ref(pPg);
  }
  *ppPage = pPg;
  return SQLITE_OK;
}

/*
................................................................................
  ** we didn't really read in the content of the page.  This can happen
  ** (for example) when the page is being moved to the freelist.  But
  ** now we are (perhaps) moving the page off of the freelist for
  ** reuse and we need to know its original content so that content
  ** can be stored in the rollback journal.  So do the read at this
  ** time.
  */
  if( pPg->needRead ){
    rc = readDbPage(pPager, pPg, pPg->pgno);
    if( rc==SQLITE_OK ){
      pPg->needRead = 0;
    }else{
      return rc;
    }
  }

  /* Mark the page as dirty.  If the page has already been written
  ** to the journal then we can return right away.
  */
  makeDirty(pPg);
  if( pPg->inJournal && (pageInStatement(pPg) || pPager->stmtInUse==0) ){







|







 







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







|








|

|


|







|
>
|







 







>
>
>
>
>
>







 







|
<
|
<
<
|
<







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
....
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
....
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
....
3389
3390
3391
3392
3393
3394
3395
3396

3397


3398

3399
3400
3401
3402
3403
3404
3405
** 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.330 2007/04/26 12:11:28 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>
................................................................................
    assert(pPg);
  }
  *ppPg = pPg;

pager_allocate_out:
  return rc;
}

/*
** Make sure we have the content for a page.  If the page was
** previously acquired with noContent==1, then the content was
** just initialized to zeros instead of being read from disk.
** But now we need the real data off of disk.  So make sure we
** have it.  Read it in if we do not have it already.
*/
static int pager_get_content(PgHdr *pPg){
  if( pPg->needRead ){
    int rc = readDbPage(pPg->pPager, pPg, pPg->pgno);
    if( rc==SQLITE_OK ){
      pPg->needRead = 0;
    }else{
      return rc;
    }
  }
  return SQLITE_OK;
}

/*
** Acquire a page.
**
** A read lock on the disk file is obtained when the first page is acquired. 
** This read lock is dropped when the last page is released.
**
** This routine works for any page number greater than 0.  If the database
** file is smaller than the requested page, then no actual disk
** read occurs and the memory image of the page is initialized to
** all zeros.  The extra data appended to a page is always initialized
** to zeros the first time a page is loaded into memory.
**
** The acquisition might fail for several reasons.  In all cases,
** an appropriate error code is returned and *ppPage is set to NULL.
**
** See also sqlite3PagerLookup().  Both this routine and Lookup() attempt
** to find a page in the in-memory cache first.  If the page is not already
** in memory, this routine goes to disk to read it in whereas Lookup()
** just returns 0.  This routine acquires a read-lock the first time it
** has to go to disk, and could also playback an old journal if necessary.
** Since Lookup() never goes to disk, it never has to deal with locks
** or journal files.
**
** If noContent is false, the page contents are actually read from disk.
** If noContent is true, it means that we do not care about the contents
** of the page at this time, so do not do a disk read.  Just fill in the
** page content with zeros.  But mark the fact that we have not read the
** content by setting the PgHdr.needRead flag.  Later on, if 
** sqlite3PagerWrite() is called on this page or if this routine is
** called again with noContent==0, that means that the content is needed
** and the disk read should occur at that point.
*/
int sqlite3PagerAcquire(
  Pager *pPager,      /* The pager open on the database file */
  Pgno pgno,          /* Page number to fetch */
  DbPage **ppPage,    /* Write a pointer to the page here */
  int noContent       /* Do not bother reading content from disk if true */
){
................................................................................
#ifdef SQLITE_CHECK_PAGES
    pPg->pageHash = pager_pagehash(pPg);
#endif
  }else{
    /* The requested page is in the page cache. */
    assert(pPager->nRef>0 || pgno==1);
    PAGER_INCR(pPager->nHit);
    if( !noContent ){
      rc = pager_get_content(pPg);
      if( rc ){
        return rc;
      }
    }
    page_ref(pPg);
  }
  *ppPage = pPg;
  return SQLITE_OK;
}

/*
................................................................................
  ** we didn't really read in the content of the page.  This can happen
  ** (for example) when the page is being moved to the freelist.  But
  ** now we are (perhaps) moving the page off of the freelist for
  ** reuse and we need to know its original content so that content
  ** can be stored in the rollback journal.  So do the read at this
  ** time.
  */
  rc = pager_get_content(pPg);

  if( rc ){


    return rc;

  }

  /* Mark the page as dirty.  If the page has already been written
  ** to the journal then we can return right away.
  */
  makeDirty(pPg);
  if( pPg->inJournal && (pageInStatement(pPg) || pPager->stmtInUse==0) ){