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