• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Adds a new API function sqlite3_preload().  This fills the page cache
2with the first pages of the database.
3
4Index: 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 */
49Index: 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 **
75Index: 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 */
235Index: 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
248Index: 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.
267Index: 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