- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / sqlite / preload-cache.patch
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 */