Home | History | Annotate | Download | only in sqlite
      1 Adds a new API function sqlite3_preload().  This fills the page cache
      2 with the first pages of the database.
      3 
      4 Index: src/build.c
      5 ===================================================================
      6 --- src/build.c	2009-09-11 07:02:46.000000000 -0700
      7 +++ src/build.c	2009-09-14 18:16:46.000000000 -0700
      8 @@ -26,6 +26,9 @@
      9  */
     10  #include "sqliteInt.h"
     11  
     12 +#include "pager.h"
     13 +#include "btree.h"
     14 +
     15  /*
     16  ** This routine is called when a new SQL statement is beginning to
     17  ** be parsed.  Initialize the pParse structure as needed.
     18 @@ -3659,3 +3662,30 @@
     19    }
     20    return pKey;
     21  }
     22 +
     23 +/* Begin preload-cache.patch for Chromium */
     24 +/* See declaration in sqlite3.h for information */
     25 +int sqlite3_preload(sqlite3 *db)
     26 +{
     27 +  Pager *pPager;
     28 +  Btree *pBt;
     29 +  int rc;
     30 +  int i;
     31 +  int dbsLoaded = 0;
     32 +
     33 +  for(i=0; i<db->nDb; i++) {
     34 +    pBt = db->aDb[i].pBt;
     35 +    if( !pBt )
     36 +      continue;
     37 +    pPager = sqlite3BtreePager(pBt);
     38 +    if( pPager ) {
     39 +      rc = sqlite3PagerLoadall(pPager);
     40 +      if (rc == SQLITE_OK)
     41 +        dbsLoaded++;
     42 +    }
     43 +  }
     44 +  if (dbsLoaded == 0)
     45 +    return SQLITE_ERROR;
     46 +  return SQLITE_OK;
     47 +}
     48 +/* End preload-cache.patch for Chromium */
     49 Index: src/sqlite3.h.in
     50 ===================================================================
     51 --- src/sqlite.h.in	2009-09-09 07:03:20.000000000 -0700
     52 +++ src/sqlite.h.in	2009-09-15 11:34:26.000000000 -0700
     53 @@ -4677,6 +4677,21 @@
     54  */
     55  int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
     56  
     57 +/* Begin preload-cache.patch for Chromium */
     58 +/*
     59 +** Preload the databases into the pager cache, up to the maximum size of the
     60 +** pager cache.
     61 +**
     62 +** For a database to be loaded successfully, the pager must be active. That is,
     63 +** there must be an open statement on that database. See sqlite3pager_loadall
     64 +**
     65 +** There might be many databases attached to the given connection. We iterate
     66 +** them all and try to load them. If none are loadable successfully, we return
     67 +** an error. Otherwise, we return OK.
     68 +*/
     69 +int sqlite3_preload(sqlite3 *db);
     70 +/* End preload-cache.patch for Chromium */
     71 +
     72  /*
     73  ** CAPI3REF: Virtual File System Objects {H11200} <S20100>
     74  **
     75 Index: src/pager.c
     76 ===================================================================
     77 --- src/pager.c	2009-09-07 08:58:09.000000000 -0700
     78 +++ src/pager.c	2009-09-15 16:43:07.000000000 -0700
     79 @@ -388,6 +388,16 @@
     80  */
     81  #define PAGER_MAX_PGNO 2147483647
     82  
     83 +/* Begin preload-cache.patch for Chromium */
     84 +/* See comments above the definition. */
     85 +int sqlite3PagerAcquire2(
     86 +  Pager *pPager,
     87 +  Pgno pgno,
     88 +  DbPage **ppPage,
     89 +  int noContent,
     90 +  unsigned char *pDataToFill);
     91 +/* End preload-cache.patch for Chromium */
     92 +
     93  #ifndef NDEBUG 
     94  /*
     95  ** Usage:
     96 @@ -3788,6 +3798,25 @@
     97    DbPage **ppPage,    /* Write a pointer to the page here */
     98    int noContent       /* Do not bother reading content from disk if true */
     99  ){
    100 +  /* This just passes through to our modified version with NULL data. */
    101 +  return sqlite3PagerAcquire2(pPager, pgno, ppPage, noContent, 0);
    102 +}
    103 +
    104 +/*
    105 +** This is an internal version of sqlite3PagerAcquire that takes an extra
    106 +** parameter of data to use to fill the page with. This allows more efficient
    107 +** filling for preloaded data. If this extra parameter is NULL, we'll go to
    108 +** the file.
    109 +**
    110 +** See sqlite3PagerLoadall which uses this function.
    111 +*/
    112 +int sqlite3PagerAcquire2(
    113 +  Pager *pPager,      /* The pager open on the database file */
    114 +  Pgno pgno,          /* Page number to fetch */
    115 +  DbPage **ppPage,    /* Write a pointer to the page here */
    116 +  int noContent,      /* Do not bother reading content from disk if true */
    117 +  unsigned char* pDataToFill
    118 +){
    119    int rc;
    120    PgHdr *pPg;
    121  
    122 @@ -3870,9 +3899,17 @@
    123        IOTRACE(("ZERO %p %d\n", pPager, pgno));
    124      }else{
    125        assert( pPg->pPager==pPager );
    126 -      rc = readDbPage(pPg);
    127 -      if( rc!=SQLITE_OK ){
    128 -        goto pager_acquire_err;
    129 +      if( pDataToFill ){
    130 +        /* Just copy from the given memory */
    131 +        memcpy(pPg->pData, pDataToFill, pPager->pageSize);
    132 +        CODEC1(pPager, pPg->pData, pPg->pgno, 3, rc = SQLITE_NOMEM;
    133 +                                                 goto pager_acquire_err);
    134 +      }else{
    135 +        /* Load from disk (old regular sqlite code path) */
    136 +        rc = readDbPage(pPg);
    137 +        if( rc!=SQLITE_OK ){
    138 +          goto pager_acquire_err;
    139 +        }
    140        }
    141      }
    142  #ifdef SQLITE_CHECK_PAGES
    143 @@ -5221,6 +5258,91 @@
    144  }
    145  #endif
    146  
    147 +/* Begin preload-cache.patch for Chromium */
    148 +/**
    149 +** When making large allocations, there is no need to stress the heap and
    150 +** potentially hold its lock while we allocate a bunch of memory.  If we know
    151 +** the allocation will be large, go directly to the OS instead of the heap.
    152 +**/
    153 +static void* allocLarge(size_t size) {
    154 +#if SQLITE_OS_WIN
    155 +  return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    156 +#else
    157 +  return sqlite3Malloc(size);
    158 +#endif
    159 +}
    160 +
    161 +static void freeLarge(void* ptr) {
    162 +#if SQLITE_OS_WIN
    163 +  VirtualFree(ptr, 0, MEM_RELEASE);
    164 +#else
    165 +  sqlite3_free(ptr);
    166 +#endif
    167 +}
    168 +
    169 +/**
    170 +** Addition: This will attempt to populate the database cache with
    171 +** the first N bytes of the file, where N is the total size of the cache.
    172 +** Because we can load this as one chunk from the disk, this is much faster
    173 +** than loading a subset of the pages one at a time in random order.
    174 +**
    175 +** The pager must be initialized before this function is called. This means a
    176 +* statement must be open that has initialized the pager and is keeping the
    177 +** cache in memory.
    178 +**/
    179 +int sqlite3PagerLoadall(Pager* pPager)
    180 +{
    181 +  int i;
    182 +  int rc;
    183 +  int nMax;
    184 +  int loadSize;
    185 +  int loadPages;
    186 +  unsigned char *fileData;
    187 +
    188 +  if (pPager->dbSize < 0 || pPager->pageSize < 0) {
    189 +    /* pager not initialized, this means a statement is not open */
    190 +    return SQLITE_MISUSE;
    191 +  }
    192 +
    193 +  /* compute sizes */
    194 +  nMax = sqlite3PcacheGetCachesize(pPager->pPCache);
    195 +  if (nMax < pPager->dbSize)
    196 +    loadPages = nMax;
    197 +  else
    198 +    loadPages = pPager->dbSize;
    199 +  loadSize = loadPages * pPager->pageSize;
    200 +
    201 +  /* load the file as one chunk */
    202 +  fileData = allocLarge(loadSize);
    203 +  if (! fileData)
    204 +    return SQLITE_NOMEM;
    205 +  rc = sqlite3OsRead(pPager->fd, fileData, loadSize, 0);
    206 +  if (rc != SQLITE_OK) {
    207 +    freeLarge(fileData);
    208 +    return rc;
    209 +  }
    210 +
    211 +  /* Copy the data to each page. Note that the page numbers we pass to _get
    212 +   * are one-based, 0 is a marker for no page. We also need to check that we
    213 +   * haven't loaded more pages than the cache can hold total. There may have
    214 +   * already been a few pages loaded before, so we may fill the cache before
    215 +   * loading all of the pages we want to.
    216 +   */
    217 +  for(i=1;
    218 +      i <= loadPages && sqlite3PcachePagecount(pPager->pPCache) < nMax;
    219 +      i++) {
    220 +    DbPage *pPage = 0;
    221 +    rc = sqlite3PagerAcquire2(pPager, i, &pPage, 0,
    222 +                              &fileData[(i-1)*(i64)pPager->pageSize]);
    223 +    if (rc != SQLITE_OK)
    224 +      break;
    225 +    sqlite3PagerUnref(pPage);
    226 +  }
    227 +  freeLarge(fileData);
    228 +  return SQLITE_OK;
    229 +}
    230 +/* End preload-cache.patch for Chromium */
    231 +
    232  /*
    233  ** Return a pointer to the data for the specified page.
    234  */
    235 Index: src/pager.h
    236 ===================================================================
    237 --- src/pager.h	2009-09-04 13:37:42.000000000 -0700
    238 +++ src/pager.h	2009-09-15 11:31:55.000000000 -0700
    239 @@ -143,6 +143,8 @@
    240  sqlite3_file *sqlite3PagerFile(Pager*);
    241  const char *sqlite3PagerJournalname(Pager*);
    242  int sqlite3PagerNosync(Pager*);
    243 +/* This function is for preload-cache.patch for Chromium: */
    244 +int sqlite3PagerLoadall(Pager*);
    245  void *sqlite3PagerTempSpace(Pager*);
    246  int sqlite3PagerIsMemdb(Pager*);
    247  
    248 Index: src/pcache.c
    249 ===================================================================
    250 --- src/pcache.c	2009-09-04 13:37:42.000000000 -0700
    251 +++ src/pcache.c	2009-09-15 16:41:55.000000000 -0700
    252 @@ -542,14 +542,12 @@
    253    return nPage;
    254  }
    255  
    256 -#ifdef SQLITE_TEST
    257  /*
    258  ** Get the suggested cache-size value.
    259  */
    260  int sqlite3PcacheGetCachesize(PCache *pCache){
    261    return pCache->nMax;
    262  }
    263 -#endif
    264  
    265  /*
    266  ** Set the suggested cache-size value.
    267 Index: src/pcache.h
    268 ===================================================================
    269 --- src/pcache.h	2009-09-04 13:37:42.000000000 -0700
    270 +++ src/pcache.h	2009-09-15 16:41:52.000000000 -0700
    271 @@ -139,9 +139,7 @@
    272  ** of the suggested cache-sizes.
    273  */
    274  void sqlite3PcacheSetCachesize(PCache *, int);
    275 -#ifdef SQLITE_TEST
    276  int sqlite3PcacheGetCachesize(PCache *);
    277 -#endif
    278  
    279  #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
    280  /* Try to return memory used by the pcache module to the main memory heap */
    281