OLD | NEW |
1 /* | 1 /* |
2 ** 2008 November 18 | 2 ** 2008 November 18 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 */ | 93 */ |
94 #define TESTPCACHE_VALID 0x364585fd | 94 #define TESTPCACHE_VALID 0x364585fd |
95 #define TESTPCACHE_CLEAR 0xd42670d4 | 95 #define TESTPCACHE_CLEAR 0xd42670d4 |
96 | 96 |
97 /* | 97 /* |
98 ** Private implementation of a page cache. | 98 ** Private implementation of a page cache. |
99 */ | 99 */ |
100 typedef struct testpcache testpcache; | 100 typedef struct testpcache testpcache; |
101 struct testpcache { | 101 struct testpcache { |
102 int szPage; /* Size of each page. Multiple of 8. */ | 102 int szPage; /* Size of each page. Multiple of 8. */ |
| 103 int szExtra; /* Size of extra data that accompanies each page */ |
103 int bPurgeable; /* True if the page cache is purgeable */ | 104 int bPurgeable; /* True if the page cache is purgeable */ |
104 int nFree; /* Number of unused slots in a[] */ | 105 int nFree; /* Number of unused slots in a[] */ |
105 int nPinned; /* Number of pinned slots in a[] */ | 106 int nPinned; /* Number of pinned slots in a[] */ |
106 unsigned iRand; /* State of the PRNG */ | 107 unsigned iRand; /* State of the PRNG */ |
107 unsigned iMagic; /* Magic number for sanity checking */ | 108 unsigned iMagic; /* Magic number for sanity checking */ |
108 struct testpcachePage { | 109 struct testpcachePage { |
| 110 sqlite3_pcache_page page; /* Base class */ |
109 unsigned key; /* The key for this page. 0 means unallocated */ | 111 unsigned key; /* The key for this page. 0 means unallocated */ |
110 int isPinned; /* True if the page is pinned */ | 112 int isPinned; /* True if the page is pinned */ |
111 void *pData; /* Data for this page */ | |
112 } a[TESTPCACHE_NPAGE]; /* All pages in the cache */ | 113 } a[TESTPCACHE_NPAGE]; /* All pages in the cache */ |
113 }; | 114 }; |
114 | 115 |
115 /* | 116 /* |
116 ** Get a random number using the PRNG in the given page cache. | 117 ** Get a random number using the PRNG in the given page cache. |
117 */ | 118 */ |
118 static unsigned testpcacheRandom(testpcache *p){ | 119 static unsigned testpcacheRandom(testpcache *p){ |
119 unsigned x = 0; | 120 unsigned x = 0; |
120 int i; | 121 int i; |
121 for(i=0; i<4; i++){ | 122 for(i=0; i<4; i++){ |
122 p->iRand = (p->iRand*69069 + 5); | 123 p->iRand = (p->iRand*69069 + 5); |
123 x = (x<<8) | ((p->iRand>>16)&0xff); | 124 x = (x<<8) | ((p->iRand>>16)&0xff); |
124 } | 125 } |
125 return x; | 126 return x; |
126 } | 127 } |
127 | 128 |
128 | 129 |
129 /* | 130 /* |
130 ** Allocate a new page cache instance. | 131 ** Allocate a new page cache instance. |
131 */ | 132 */ |
132 static sqlite3_pcache *testpcacheCreate(int szPage, int bPurgeable){ | 133 static sqlite3_pcache *testpcacheCreate( |
| 134 int szPage, |
| 135 int szExtra, |
| 136 int bPurgeable |
| 137 ){ |
133 int nMem; | 138 int nMem; |
134 char *x; | 139 char *x; |
135 testpcache *p; | 140 testpcache *p; |
136 int i; | 141 int i; |
137 assert( testpcacheGlobal.pDummy!=0 ); | 142 assert( testpcacheGlobal.pDummy!=0 ); |
138 szPage = (szPage+7)&~7; | 143 szPage = (szPage+7)&~7; |
139 nMem = sizeof(testpcache) + TESTPCACHE_NPAGE*szPage; | 144 nMem = sizeof(testpcache) + TESTPCACHE_NPAGE*(szPage+szExtra); |
140 p = sqlite3_malloc( nMem ); | 145 p = sqlite3_malloc( nMem ); |
141 if( p==0 ) return 0; | 146 if( p==0 ) return 0; |
142 x = (char*)&p[1]; | 147 x = (char*)&p[1]; |
143 p->szPage = szPage; | 148 p->szPage = szPage; |
| 149 p->szExtra = szExtra; |
144 p->nFree = TESTPCACHE_NPAGE; | 150 p->nFree = TESTPCACHE_NPAGE; |
145 p->nPinned = 0; | 151 p->nPinned = 0; |
146 p->iRand = testpcacheGlobal.prngSeed; | 152 p->iRand = testpcacheGlobal.prngSeed; |
147 p->bPurgeable = bPurgeable; | 153 p->bPurgeable = bPurgeable; |
148 p->iMagic = TESTPCACHE_VALID; | 154 p->iMagic = TESTPCACHE_VALID; |
149 for(i=0; i<TESTPCACHE_NPAGE; i++, x += szPage){ | 155 for(i=0; i<TESTPCACHE_NPAGE; i++, x += (szPage+szExtra)){ |
150 p->a[i].key = 0; | 156 p->a[i].key = 0; |
151 p->a[i].isPinned = 0; | 157 p->a[i].isPinned = 0; |
152 p->a[i].pData = (void*)x; | 158 p->a[i].page.pBuf = (void*)x; |
| 159 p->a[i].page.pExtra = (void*)&x[szPage]; |
153 } | 160 } |
154 testpcacheGlobal.nInstance++; | 161 testpcacheGlobal.nInstance++; |
155 return (sqlite3_pcache*)p; | 162 return (sqlite3_pcache*)p; |
156 } | 163 } |
157 | 164 |
158 /* | 165 /* |
159 ** Set the cache size | 166 ** Set the cache size |
160 */ | 167 */ |
161 static void testpcacheCachesize(sqlite3_pcache *pCache, int newSize){ | 168 static void testpcacheCachesize(sqlite3_pcache *pCache, int newSize){ |
162 testpcache *p = (testpcache*)pCache; | 169 testpcache *p = (testpcache*)pCache; |
163 assert( p->iMagic==TESTPCACHE_VALID ); | 170 assert( p->iMagic==TESTPCACHE_VALID ); |
164 assert( newSize>=1 ); | |
165 assert( testpcacheGlobal.pDummy!=0 ); | 171 assert( testpcacheGlobal.pDummy!=0 ); |
166 assert( testpcacheGlobal.nInstance>0 ); | 172 assert( testpcacheGlobal.nInstance>0 ); |
167 } | 173 } |
168 | 174 |
169 /* | 175 /* |
170 ** Return the number of pages in the cache that are being used. | 176 ** Return the number of pages in the cache that are being used. |
171 ** This includes both pinned and unpinned pages. | 177 ** This includes both pinned and unpinned pages. |
172 */ | 178 */ |
173 static int testpcachePagecount(sqlite3_pcache *pCache){ | 179 static int testpcachePagecount(sqlite3_pcache *pCache){ |
174 testpcache *p = (testpcache*)pCache; | 180 testpcache *p = (testpcache*)pCache; |
175 assert( p->iMagic==TESTPCACHE_VALID ); | 181 assert( p->iMagic==TESTPCACHE_VALID ); |
176 assert( testpcacheGlobal.pDummy!=0 ); | 182 assert( testpcacheGlobal.pDummy!=0 ); |
177 assert( testpcacheGlobal.nInstance>0 ); | 183 assert( testpcacheGlobal.nInstance>0 ); |
178 return TESTPCACHE_NPAGE - p->nFree; | 184 return TESTPCACHE_NPAGE - p->nFree; |
179 } | 185 } |
180 | 186 |
181 /* | 187 /* |
182 ** Fetch a page. | 188 ** Fetch a page. |
183 */ | 189 */ |
184 static void *testpcacheFetch( | 190 static sqlite3_pcache_page *testpcacheFetch( |
185 sqlite3_pcache *pCache, | 191 sqlite3_pcache *pCache, |
186 unsigned key, | 192 unsigned key, |
187 int createFlag | 193 int createFlag |
188 ){ | 194 ){ |
189 testpcache *p = (testpcache*)pCache; | 195 testpcache *p = (testpcache*)pCache; |
190 int i, j; | 196 int i, j; |
191 assert( p->iMagic==TESTPCACHE_VALID ); | 197 assert( p->iMagic==TESTPCACHE_VALID ); |
192 assert( testpcacheGlobal.pDummy!=0 ); | 198 assert( testpcacheGlobal.pDummy!=0 ); |
193 assert( testpcacheGlobal.nInstance>0 ); | 199 assert( testpcacheGlobal.nInstance>0 ); |
194 | 200 |
195 /* See if the page is already in cache. Return immediately if it is */ | 201 /* See if the page is already in cache. Return immediately if it is */ |
196 for(i=0; i<TESTPCACHE_NPAGE; i++){ | 202 for(i=0; i<TESTPCACHE_NPAGE; i++){ |
197 if( p->a[i].key==key ){ | 203 if( p->a[i].key==key ){ |
198 if( !p->a[i].isPinned ){ | 204 if( !p->a[i].isPinned ){ |
199 p->nPinned++; | 205 p->nPinned++; |
200 assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); | 206 assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); |
201 p->a[i].isPinned = 1; | 207 p->a[i].isPinned = 1; |
202 } | 208 } |
203 return p->a[i].pData; | 209 return &p->a[i].page; |
204 } | 210 } |
205 } | 211 } |
206 | 212 |
207 /* If createFlag is 0, never allocate a new page */ | 213 /* If createFlag is 0, never allocate a new page */ |
208 if( createFlag==0 ){ | 214 if( createFlag==0 ){ |
209 return 0; | 215 return 0; |
210 } | 216 } |
211 | 217 |
212 /* If no pages are available, always fail */ | 218 /* If no pages are available, always fail */ |
213 if( p->nPinned==TESTPCACHE_NPAGE ){ | 219 if( p->nPinned==TESTPCACHE_NPAGE ){ |
(...skipping 16 matching lines...) Expand all Loading... |
230 | 236 |
231 /* Find a free page to allocate if there are any free pages. | 237 /* Find a free page to allocate if there are any free pages. |
232 ** Withhold TESTPCACHE_RESERVE free pages until createFlag is 2. | 238 ** Withhold TESTPCACHE_RESERVE free pages until createFlag is 2. |
233 */ | 239 */ |
234 if( p->nFree>TESTPCACHE_RESERVE || (createFlag==2 && p->nFree>0) ){ | 240 if( p->nFree>TESTPCACHE_RESERVE || (createFlag==2 && p->nFree>0) ){ |
235 j = testpcacheRandom(p) % TESTPCACHE_NPAGE; | 241 j = testpcacheRandom(p) % TESTPCACHE_NPAGE; |
236 for(i=0; i<TESTPCACHE_NPAGE; i++, j = (j+1)%TESTPCACHE_NPAGE){ | 242 for(i=0; i<TESTPCACHE_NPAGE; i++, j = (j+1)%TESTPCACHE_NPAGE){ |
237 if( p->a[j].key==0 ){ | 243 if( p->a[j].key==0 ){ |
238 p->a[j].key = key; | 244 p->a[j].key = key; |
239 p->a[j].isPinned = 1; | 245 p->a[j].isPinned = 1; |
240 memset(p->a[j].pData, 0, p->szPage); | 246 memset(p->a[j].page.pBuf, 0, p->szPage); |
| 247 memset(p->a[j].page.pExtra, 0, p->szExtra); |
241 p->nPinned++; | 248 p->nPinned++; |
242 p->nFree--; | 249 p->nFree--; |
243 assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); | 250 assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); |
244 return p->a[j].pData; | 251 return &p->a[j].page; |
245 } | 252 } |
246 } | 253 } |
247 | 254 |
248 /* The prior loop always finds a freepage to allocate */ | 255 /* The prior loop always finds a freepage to allocate */ |
249 assert( 0 ); | 256 assert( 0 ); |
250 } | 257 } |
251 | 258 |
252 /* If this cache is not purgeable then we have to fail. | 259 /* If this cache is not purgeable then we have to fail. |
253 */ | 260 */ |
254 if( p->bPurgeable==0 ){ | 261 if( p->bPurgeable==0 ){ |
255 return 0; | 262 return 0; |
256 } | 263 } |
257 | 264 |
258 /* If there are no free pages, recycle a page. The page to | 265 /* If there are no free pages, recycle a page. The page to |
259 ** recycle is selected at random from all unpinned pages. | 266 ** recycle is selected at random from all unpinned pages. |
260 */ | 267 */ |
261 j = testpcacheRandom(p) % TESTPCACHE_NPAGE; | 268 j = testpcacheRandom(p) % TESTPCACHE_NPAGE; |
262 for(i=0; i<TESTPCACHE_NPAGE; i++, j = (j+1)%TESTPCACHE_NPAGE){ | 269 for(i=0; i<TESTPCACHE_NPAGE; i++, j = (j+1)%TESTPCACHE_NPAGE){ |
263 if( p->a[j].key>0 && p->a[j].isPinned==0 ){ | 270 if( p->a[j].key>0 && p->a[j].isPinned==0 ){ |
264 p->a[j].key = key; | 271 p->a[j].key = key; |
265 p->a[j].isPinned = 1; | 272 p->a[j].isPinned = 1; |
266 memset(p->a[j].pData, 0, p->szPage); | 273 memset(p->a[j].page.pBuf, 0, p->szPage); |
| 274 memset(p->a[j].page.pExtra, 0, p->szExtra); |
267 p->nPinned++; | 275 p->nPinned++; |
268 assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); | 276 assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); |
269 return p->a[j].pData; | 277 return &p->a[j].page; |
270 } | 278 } |
271 } | 279 } |
272 | 280 |
273 /* The previous loop always finds a page to recycle. */ | 281 /* The previous loop always finds a page to recycle. */ |
274 assert(0); | 282 assert(0); |
275 return 0; | 283 return 0; |
276 } | 284 } |
277 | 285 |
278 /* | 286 /* |
279 ** Unpin a page. | 287 ** Unpin a page. |
280 */ | 288 */ |
281 static void testpcacheUnpin( | 289 static void testpcacheUnpin( |
282 sqlite3_pcache *pCache, | 290 sqlite3_pcache *pCache, |
283 void *pOldPage, | 291 sqlite3_pcache_page *pOldPage, |
284 int discard | 292 int discard |
285 ){ | 293 ){ |
286 testpcache *p = (testpcache*)pCache; | 294 testpcache *p = (testpcache*)pCache; |
287 int i; | 295 int i; |
288 assert( p->iMagic==TESTPCACHE_VALID ); | 296 assert( p->iMagic==TESTPCACHE_VALID ); |
289 assert( testpcacheGlobal.pDummy!=0 ); | 297 assert( testpcacheGlobal.pDummy!=0 ); |
290 assert( testpcacheGlobal.nInstance>0 ); | 298 assert( testpcacheGlobal.nInstance>0 ); |
291 | 299 |
292 /* Randomly discard pages as they are unpinned according to the | 300 /* Randomly discard pages as they are unpinned according to the |
293 ** discardChance setting. If discardChance is 0, the random discard | 301 ** discardChance setting. If discardChance is 0, the random discard |
294 ** never happens. If discardChance is 100, it always happens. | 302 ** never happens. If discardChance is 100, it always happens. |
295 */ | 303 */ |
296 if( p->bPurgeable | 304 if( p->bPurgeable |
297 && (100-testpcacheGlobal.discardChance) <= (testpcacheRandom(p)%100) | 305 && (100-testpcacheGlobal.discardChance) <= (testpcacheRandom(p)%100) |
298 ){ | 306 ){ |
299 discard = 1; | 307 discard = 1; |
300 } | 308 } |
301 | 309 |
302 for(i=0; i<TESTPCACHE_NPAGE; i++){ | 310 for(i=0; i<TESTPCACHE_NPAGE; i++){ |
303 if( p->a[i].pData==pOldPage ){ | 311 if( &p->a[i].page==pOldPage ){ |
304 /* The pOldPage pointer always points to a pinned page */ | 312 /* The pOldPage pointer always points to a pinned page */ |
305 assert( p->a[i].isPinned ); | 313 assert( p->a[i].isPinned ); |
306 p->a[i].isPinned = 0; | 314 p->a[i].isPinned = 0; |
307 p->nPinned--; | 315 p->nPinned--; |
308 assert( p->nPinned>=0 ); | 316 assert( p->nPinned>=0 ); |
309 if( discard ){ | 317 if( discard ){ |
310 p->a[i].key = 0; | 318 p->a[i].key = 0; |
311 p->nFree++; | 319 p->nFree++; |
312 assert( p->nFree<=TESTPCACHE_NPAGE ); | 320 assert( p->nFree<=TESTPCACHE_NPAGE ); |
313 } | 321 } |
314 return; | 322 return; |
315 } | 323 } |
316 } | 324 } |
317 | 325 |
318 /* The pOldPage pointer always points to a valid page */ | 326 /* The pOldPage pointer always points to a valid page */ |
319 assert( 0 ); | 327 assert( 0 ); |
320 } | 328 } |
321 | 329 |
322 | 330 |
323 /* | 331 /* |
324 ** Rekey a single page. | 332 ** Rekey a single page. |
325 */ | 333 */ |
326 static void testpcacheRekey( | 334 static void testpcacheRekey( |
327 sqlite3_pcache *pCache, | 335 sqlite3_pcache *pCache, |
328 void *pOldPage, | 336 sqlite3_pcache_page *pOldPage, |
329 unsigned oldKey, | 337 unsigned oldKey, |
330 unsigned newKey | 338 unsigned newKey |
331 ){ | 339 ){ |
332 testpcache *p = (testpcache*)pCache; | 340 testpcache *p = (testpcache*)pCache; |
333 int i; | 341 int i; |
334 assert( p->iMagic==TESTPCACHE_VALID ); | 342 assert( p->iMagic==TESTPCACHE_VALID ); |
335 assert( testpcacheGlobal.pDummy!=0 ); | 343 assert( testpcacheGlobal.pDummy!=0 ); |
336 assert( testpcacheGlobal.nInstance>0 ); | 344 assert( testpcacheGlobal.nInstance>0 ); |
337 | 345 |
338 /* If there already exists another page at newKey, verify that | 346 /* If there already exists another page at newKey, verify that |
339 ** the other page is unpinned and discard it. | 347 ** the other page is unpinned and discard it. |
340 */ | 348 */ |
341 for(i=0; i<TESTPCACHE_NPAGE; i++){ | 349 for(i=0; i<TESTPCACHE_NPAGE; i++){ |
342 if( p->a[i].key==newKey ){ | 350 if( p->a[i].key==newKey ){ |
343 /* The new key is never a page that is already pinned */ | 351 /* The new key is never a page that is already pinned */ |
344 assert( p->a[i].isPinned==0 ); | 352 assert( p->a[i].isPinned==0 ); |
345 p->a[i].key = 0; | 353 p->a[i].key = 0; |
346 p->nFree++; | 354 p->nFree++; |
347 assert( p->nFree<=TESTPCACHE_NPAGE ); | 355 assert( p->nFree<=TESTPCACHE_NPAGE ); |
348 break; | 356 break; |
349 } | 357 } |
350 } | 358 } |
351 | 359 |
352 /* Find the page to be rekeyed and rekey it. | 360 /* Find the page to be rekeyed and rekey it. |
353 */ | 361 */ |
354 for(i=0; i<TESTPCACHE_NPAGE; i++){ | 362 for(i=0; i<TESTPCACHE_NPAGE; i++){ |
355 if( p->a[i].key==oldKey ){ | 363 if( p->a[i].key==oldKey ){ |
356 /* The oldKey and pOldPage parameters match */ | 364 /* The oldKey and pOldPage parameters match */ |
357 assert( p->a[i].pData==pOldPage ); | 365 assert( &p->a[i].page==pOldPage ); |
358 /* Page to be rekeyed must be pinned */ | 366 /* Page to be rekeyed must be pinned */ |
359 assert( p->a[i].isPinned ); | 367 assert( p->a[i].isPinned ); |
360 p->a[i].key = newKey; | 368 p->a[i].key = newKey; |
361 return; | 369 return; |
362 } | 370 } |
363 } | 371 } |
364 | 372 |
365 /* Rekey is always given a valid page to work with */ | 373 /* Rekey is always given a valid page to work with */ |
366 assert( 0 ); | 374 assert( 0 ); |
367 } | 375 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 ** indicates the probability of discarding a page when unpinning the | 423 ** indicates the probability of discarding a page when unpinning the |
416 ** page. 0 means never discard (unless the discard flag is set). | 424 ** page. 0 means never discard (unless the discard flag is set). |
417 ** 100 means always discard. | 425 ** 100 means always discard. |
418 */ | 426 */ |
419 void installTestPCache( | 427 void installTestPCache( |
420 int installFlag, /* True to install. False to uninstall. */ | 428 int installFlag, /* True to install. False to uninstall. */ |
421 unsigned discardChance, /* 0-100. Chance to discard on unpin */ | 429 unsigned discardChance, /* 0-100. Chance to discard on unpin */ |
422 unsigned prngSeed, /* Seed for the PRNG */ | 430 unsigned prngSeed, /* Seed for the PRNG */ |
423 unsigned highStress /* Call xStress agressively */ | 431 unsigned highStress /* Call xStress agressively */ |
424 ){ | 432 ){ |
425 static const sqlite3_pcache_methods testPcache = { | 433 static const sqlite3_pcache_methods2 testPcache = { |
| 434 1, |
426 (void*)&testpcacheGlobal, | 435 (void*)&testpcacheGlobal, |
427 testpcacheInit, | 436 testpcacheInit, |
428 testpcacheShutdown, | 437 testpcacheShutdown, |
429 testpcacheCreate, | 438 testpcacheCreate, |
430 testpcacheCachesize, | 439 testpcacheCachesize, |
431 testpcachePagecount, | 440 testpcachePagecount, |
432 testpcacheFetch, | 441 testpcacheFetch, |
433 testpcacheUnpin, | 442 testpcacheUnpin, |
434 testpcacheRekey, | 443 testpcacheRekey, |
435 testpcacheTruncate, | 444 testpcacheTruncate, |
436 testpcacheDestroy, | 445 testpcacheDestroy, |
437 }; | 446 }; |
438 static sqlite3_pcache_methods defaultPcache; | 447 static sqlite3_pcache_methods2 defaultPcache; |
439 static int isInstalled = 0; | 448 static int isInstalled = 0; |
440 | 449 |
441 assert( testpcacheGlobal.nInstance==0 ); | 450 assert( testpcacheGlobal.nInstance==0 ); |
442 assert( testpcacheGlobal.pDummy==0 ); | 451 assert( testpcacheGlobal.pDummy==0 ); |
443 assert( discardChance<=100 ); | 452 assert( discardChance<=100 ); |
444 testpcacheGlobal.discardChance = discardChance; | 453 testpcacheGlobal.discardChance = discardChance; |
445 testpcacheGlobal.prngSeed = prngSeed ^ (prngSeed<<16); | 454 testpcacheGlobal.prngSeed = prngSeed ^ (prngSeed<<16); |
446 testpcacheGlobal.highStress = highStress; | 455 testpcacheGlobal.highStress = highStress; |
447 if( installFlag!=isInstalled ){ | 456 if( installFlag!=isInstalled ){ |
448 if( installFlag ){ | 457 if( installFlag ){ |
449 sqlite3_config(SQLITE_CONFIG_GETPCACHE, &defaultPcache); | 458 sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &defaultPcache); |
450 assert( defaultPcache.xCreate!=testpcacheCreate ); | 459 assert( defaultPcache.xCreate!=testpcacheCreate ); |
451 sqlite3_config(SQLITE_CONFIG_PCACHE, &testPcache); | 460 sqlite3_config(SQLITE_CONFIG_PCACHE2, &testPcache); |
452 }else{ | 461 }else{ |
453 assert( defaultPcache.xCreate!=0 ); | 462 assert( defaultPcache.xCreate!=0 ); |
454 sqlite3_config(SQLITE_CONFIG_PCACHE, &defaultPcache); | 463 sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultPcache); |
455 } | 464 } |
456 isInstalled = installFlag; | 465 isInstalled = installFlag; |
457 } | 466 } |
458 } | 467 } |
OLD | NEW |