Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: third_party/sqlite/sqlite-src-3080704/src/test_pcache.c

Issue 883353008: [sql] Import reference version of SQLite 3.8.7.4. (Closed) Base URL: http://chromium.googlesource.com/chromium/src.git@master
Patch Set: Hold back encoding change which is messing up patch. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « third_party/sqlite/sqlite-src-3080704/src/test_osinst.c ('k') | third_party/sqlite/sqlite-src-3080704/src/test_quota.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698