Import firefox-3.0b1-source tarball
[mozilla-1.9/b1.git] / db / sqlite3 / preload-cache.patch
blob9c7de164ddb7b91f1130657e06e2cff5bf47a4a7
1 Index: build.c
2 ===================================================================
3 RCS file: /cvsroot/mozilla/db/sqlite3/src/build.c,v
4 retrieving revision 1.4.8.3
5 diff -u -u -8 -p -r1.4.8.3 build.c
6 --- build.c 22 Feb 2006 20:56:28 -0000 1.4.8.3
7 +++ build.c 11 Apr 2006 17:28:51 -0000
8 @@ -22,16 +22,19 @@
9 ** COMMIT
10 ** ROLLBACK
12 ** $Id: preload-cache.patch,v 1.2 2006/04/11 17:35:25 brettw%gmail.com Exp $
14 #include "sqliteInt.h"
15 #include <ctype.h>
17 +#include "pager.h"
18 +#include "btree.h"
21 ** This routine is called when a new SQL statement is beginning to
22 ** be parsed. Initialize the pParse structure as needed.
24 void sqlite3BeginParse(Parse *pParse, int explainFlag){
25 pParse->explain = explainFlag;
26 pParse->nVar = 0;
28 @@ -3214,8 +3217,34 @@ KeyInfo *sqlite3IndexKeyinfo(Parse *pPar
31 if( pParse->nErr ){
32 sqliteFree(pKey);
33 pKey = 0;
35 return pKey;
39 +/* See declaration in sqlite3.h for information */
40 +int sqlite3Preload(sqlite3* db)
42 + Pager* pPager;
43 + Btree* pBt;
44 + int rc;
45 + int i;
46 + int dbsLoaded = 0;
48 + for (i = 0; i < db->nDb; i ++) {
49 + pBt = db->aDb[i].pBt;
50 + if (! pBt)
51 + continue;
52 + pPager = sqlite3BtreePager(pBt);
53 + if (pPager) {
54 + rc = sqlite3pager_loadall(pPager);
55 + if (rc == SQLITE_OK)
56 + dbsLoaded ++;
57 + }
58 + }
59 + if (dbsLoaded == 0)
60 + return SQLITE_ERROR;
61 + return SQLITE_OK;
63 Index: pager.c
64 ===================================================================
65 RCS file: /cvsroot/mozilla/db/sqlite3/src/pager.c,v
66 retrieving revision 1.3.8.3
67 diff -u -u -8 -p -r1.3.8.3 pager.c
68 --- pager.c 22 Feb 2006 20:56:28 -0000 1.3.8.3
69 +++ pager.c 11 Apr 2006 17:28:51 -0000
70 @@ -2521,16 +2521,30 @@ int sqlite3pager_release_memory(int nReq
71 ** to find a page in the in-memory cache first. If the page is not already
72 ** in memory, this routine goes to disk to read it in whereas _lookup()
73 ** just returns 0. This routine acquires a read-lock the first time it
74 ** has to go to disk, and could also playback an old journal if necessary.
75 ** Since _lookup() never goes to disk, it never has to deal with locks
76 ** or journal files.
78 int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
79 + /* This just passes through to our modified version with a NULL data pointer */
80 + return sqlite3pager_get2(pPager, pgno, ppPage, 0);
84 +/*
85 +** This is an internal version of pager_get that takes an extra parameter of
86 +** data to use to fill the page with. This allows more efficient filling for
87 +** preloaded data. If this extra parameter is NULL, we'll go to the file.
88 +**
89 +** See sqlite3pager_loadall which uses this function.
90 +*/
91 +int sqlite3pager_get2(Pager *pPager, Pgno pgno, void **ppPage,
92 + unsigned char* pDataToFill) {
93 PgHdr *pPg;
94 int rc;
96 /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
97 ** number greater than this, or zero, is requested.
99 if( pgno>PAGER_MAX_PGNO || pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
100 return SQLITE_CORRUPT_BKPT;
101 @@ -2676,39 +2690,46 @@ int sqlite3pager_get(Pager *pPager, Pgno
104 /* Populate the page with data, either by reading from the database
105 ** file, or by setting the entire page to zero.
107 if( sqlite3pager_pagecount(pPager)<(int)pgno || MEMDB ){
108 memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
109 }else{
110 - assert( MEMDB==0 );
111 - rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize);
112 - if( rc==SQLITE_OK ){
113 - rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg),
114 - pPager->pageSize);
116 - TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
117 - CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
118 - if( rc!=SQLITE_OK ){
119 - i64 fileSize;
120 - int rc2 = sqlite3OsFileSize(pPager->fd, &fileSize);
121 - if( rc2!=SQLITE_OK || fileSize>=pgno*pPager->pageSize ){
122 - /* An IO error occured in one of the the sqlite3OsSeek() or
123 - ** sqlite3OsRead() calls above. */
124 - pPg->pgno = 0;
125 - sqlite3pager_unref(PGHDR_TO_DATA(pPg));
126 - return rc;
127 + if (pDataToFill) {
128 + /* Just copy from the given memory */
129 + memcpy(PGHDR_TO_DATA(pPg), pDataToFill, pPager->pageSize);
130 + CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
131 + } else {
132 + /* Load from disk */
133 + assert( MEMDB==0 );
134 + rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize);
135 + if( rc==SQLITE_OK ){
136 + rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg),
137 + pPager->pageSize);
139 + TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
140 + CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
141 + if( rc!=SQLITE_OK ){
142 + i64 fileSize;
143 + int rc2 = sqlite3OsFileSize(pPager->fd, &fileSize);
144 + if( rc2!=SQLITE_OK || fileSize>=pgno*pPager->pageSize ){
145 + /* An IO error occured in one of the the sqlite3OsSeek() or
146 + ** sqlite3OsRead() calls above. */
147 + pPg->pgno = 0;
148 + sqlite3pager_unref(PGHDR_TO_DATA(pPg));
149 + return rc;
150 + }else{
151 + clear_simulated_io_error();
152 + memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
154 }else{
155 - clear_simulated_io_error();
156 - memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
157 + TEST_INCR(pPager->nRead);
159 - }else{
160 - TEST_INCR(pPager->nRead);
164 /* Link the page into the page hash table */
165 h = pager_hash(pgno);
166 pPg->pNextHash = pPager->aHash[h];
167 pPager->aHash[h] = pPg;
168 if( pPg->pNextHash ){
169 @@ -3773,16 +3794,80 @@ int sqlite3pager_movepage(Pager *pPager,
170 DATA_TO_PGHDR(pNeedSync)->dirty = 1;
171 sqlite3pager_unref(pNeedSync);
174 return SQLITE_OK;
176 #endif
179 +/**
180 + * Addition for Mozilla: This will attempt to populate the database cache with
181 + * the first N bytes of the file, where N is the total size of the cache.
182 + * Because we can load this as one chunk from the disk, this is much faster
183 + * than loading a subset of the pages one at a time in random order.
185 + * The pager must be initialized before this function is called. This means a
186 + * statement must be open that has initialized the pager and is keeping the
187 + * cache in memory.
188 + */
189 +int sqlite3pager_loadall(Pager* pPager)
191 + int i;
192 + int rc;
193 + int loadSize;
194 + int loadPages;
195 + unsigned char* fileData;
197 + if (pPager->dbSize < 0 || pPager->pageSize < 0) {
198 + /* pager not initialized, this means a statement is not open */
199 + return SQLITE_MISUSE;
202 + /* compute sizes */
203 + if (pPager->mxPage < pPager->dbSize)
204 + loadPages = pPager->mxPage;
205 + else
206 + loadPages = pPager->dbSize;
207 + loadSize = loadPages * pPager->pageSize;
209 + rc = sqlite3OsSeek(pPager->fd, 0);
210 + if (rc != SQLITE_OK)
211 + return rc;
213 + /* load the file as one chunk */
214 + fileData = sqliteMallocRaw(loadSize);
215 + if (! fileData)
216 + return SQLITE_NOMEM;
217 + rc = sqlite3OsRead(pPager->fd, fileData, loadSize);
218 + if (rc != SQLITE_OK) {
219 + sqliteFree(fileData);
220 + return rc;
223 + /* Copy the data to each page. Note that the page numbers we pass to _get
224 + * are one-based, 0 is a marker for no page. We also need to check that we
225 + * haven't loaded more pages than the cache can hold total. There may have
226 + * already been a few pages loaded before, so we may fill the cache before
227 + * loading all of the pages we want to.
228 + */
229 + for (i = 1; i <= loadPages && pPager->nPage < pPager->mxPage; i ++) {
230 + void *pPage;
231 + rc = sqlite3pager_get2(pPager, 1, &pPage,
232 + &fileData[(i-1)*(i64)pPager->pageSize]);
233 + if (rc != SQLITE_OK)
234 + break;
235 + sqlite3pager_unref(pPage);
237 + sqliteFree(fileData);
238 + return SQLITE_OK;
242 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
244 ** Return the current state of the file lock for the given pager.
245 ** The return value is one of NO_LOCK, SHARED_LOCK, RESERVED_LOCK,
246 ** PENDING_LOCK, or EXCLUSIVE_LOCK.
248 int sqlite3pager_lockstate(Pager *pPager){
249 return sqlite3OsLockState(pPager->fd);
250 Index: pager.h
251 ===================================================================
252 RCS file: /cvsroot/mozilla/db/sqlite3/src/pager.h,v
253 retrieving revision 1.2.8.3
254 diff -u -u -8 -p -r1.2.8.3 pager.h
255 --- pager.h 22 Feb 2006 20:56:28 -0000 1.2.8.3
256 +++ pager.h 11 Apr 2006 17:28:51 -0000
257 @@ -104,16 +104,17 @@ const char *sqlite3pager_filename(Pager*
258 const char *sqlite3pager_dirname(Pager*);
259 const char *sqlite3pager_journalname(Pager*);
260 int sqlite3pager_nosync(Pager*);
261 int sqlite3pager_rename(Pager*, const char *zNewName);
262 void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*);
263 int sqlite3pager_movepage(Pager*,void*,Pgno);
264 int sqlite3pager_reset(Pager*);
265 int sqlite3pager_release_memory(int);
266 +int sqlite3pager_loadall(Pager*);
268 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
269 int sqlite3pager_lockstate(Pager*);
270 #endif
272 #ifdef SQLITE_TEST
273 void sqlite3pager_refdump(Pager*);
274 int pager3_refinfo_enable;
275 Index: sqlite3.h
276 ===================================================================
277 RCS file: /cvsroot/mozilla/db/sqlite3/src/sqlite3.h,v
278 retrieving revision 1.2.2.4
279 diff -u -u -8 -p -r1.2.2.4 sqlite3.h
280 --- sqlite3.h 22 Feb 2006 20:56:28 -0000 1.2.2.4
281 +++ sqlite3.h 11 Apr 2006 17:28:51 -0000
282 @@ -1482,12 +1482,25 @@ int sqlite3_table_column_metadata(
284 int sqlite3_bind_parameter_indexes(
285 sqlite3_stmt *pStmt,
286 const char *zName,
287 int **pIndexes
289 void sqlite3_free_parameter_indexes(int *pIndexes);
292 +** Preload the databases into the pager cache, up to the maximum size of the
293 +** pager cache.
295 +** For a database to be loaded successfully, the pager must be active. That is,
296 +** there must be an open statement on that database. See sqlite3pager_loadall
298 +** There might be many databases attached to the given connection. We iterate
299 +** them all and try to load them. If none are loadable successfully, we return
300 +** an error. Otherwise, we return OK.
302 +int sqlite3Preload(sqlite3* db);
304 #ifdef __cplusplus
305 } /* End of the 'extern "C"' block */
306 #endif
307 #endif