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