diff options
author | dan <dan@noemail.net> | 2011-11-08 20:08:44 +0000 |
---|---|---|
committer | dan <dan@noemail.net> | 2011-11-08 20:08:44 +0000 |
commit | 22e21ff4fc04b67f176060f5f3471a9b4a8afa70 (patch) | |
tree | c72d9ba0079fb6272602a9d7679f8558b1e858f5 /src | |
parent | 5802464316abd24623bdd62e028bf4ad6ed1c184 (diff) | |
download | sqlite-22e21ff4fc04b67f176060f5f3471a9b4a8afa70.tar.gz sqlite-22e21ff4fc04b67f176060f5f3471a9b4a8afa70.zip |
Experimental change to the pcache interface to allow page buffers to be allocated separately from their associated container structures.
FossilOrigin-Name: c275c9d323cb1dccb031b199d413ac3a0b244fea
Diffstat (limited to 'src')
-rw-r--r-- | src/global.c | 2 | ||||
-rw-r--r-- | src/main.c | 19 | ||||
-rw-r--r-- | src/pcache.c | 74 | ||||
-rw-r--r-- | src/pcache.h | 3 | ||||
-rw-r--r-- | src/pcache1.c | 92 | ||||
-rw-r--r-- | src/sqlite.h.in | 23 | ||||
-rw-r--r-- | src/sqliteInt.h | 2 | ||||
-rw-r--r-- | src/test_init.c | 29 | ||||
-rw-r--r-- | src/test_pcache.c | 49 |
9 files changed, 179 insertions, 114 deletions
diff --git a/src/global.c b/src/global.c index 1e691c449..b8a8a49d3 100644 --- a/src/global.c +++ b/src/global.c @@ -147,7 +147,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = { 500, /* nLookaside */ {0,0,0,0,0,0,0,0}, /* m */ {0,0,0,0,0,0,0,0,0}, /* mutex */ - {0,0,0,0,0,0,0,0,0,0,0}, /* pcache */ + {0,0,0,0,0,0,0,0,0,0,0}, /* pcache2 */ (void*)0, /* pHeap */ 0, /* nHeap */ 0, 0, /* mnHeap, mxHeap */ diff --git a/src/main.c b/src/main.c index 42bbba5d0..6e6af78c7 100644 --- a/src/main.c +++ b/src/main.c @@ -365,16 +365,25 @@ int sqlite3_config(int op, ...){ } case SQLITE_CONFIG_PCACHE: { - /* Specify an alternative page cache implementation */ - sqlite3GlobalConfig.pcache = *va_arg(ap, sqlite3_pcache_methods*); + /* no-op */ break; } - case SQLITE_CONFIG_GETPCACHE: { - if( sqlite3GlobalConfig.pcache.xInit==0 ){ + /* now an error */ + rc = SQLITE_ERROR; + break; + } + + case SQLITE_CONFIG_PCACHE2: { + /* Specify an alternative page cache implementation */ + sqlite3GlobalConfig.pcache2 = *va_arg(ap, sqlite3_pcache_methods2*); + break; + } + case SQLITE_CONFIG_GETPCACHE2: { + if( sqlite3GlobalConfig.pcache2.xInit==0 ){ sqlite3PCacheSetDefault(); } - *va_arg(ap, sqlite3_pcache_methods*) = sqlite3GlobalConfig.pcache; + *va_arg(ap, sqlite3_pcache_methods2*) = sqlite3GlobalConfig.pcache2; break; } diff --git a/src/pcache.c b/src/pcache.c index f37511e9e..f689aaa77 100644 --- a/src/pcache.c +++ b/src/pcache.c @@ -131,7 +131,7 @@ static void pcacheUnpin(PgHdr *p){ if( p->pgno==1 ){ pCache->pPage1 = 0; } - sqlite3GlobalConfig.pcache.xUnpin(pCache->pCache, p, 0); + sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 0); } } @@ -141,18 +141,18 @@ static void pcacheUnpin(PgHdr *p){ ** functions are threadsafe. */ int sqlite3PcacheInitialize(void){ - if( sqlite3GlobalConfig.pcache.xInit==0 ){ + if( sqlite3GlobalConfig.pcache2.xInit==0 ){ /* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the ** built-in default page cache is used instead of the application defined ** page cache. */ sqlite3PCacheSetDefault(); } - return sqlite3GlobalConfig.pcache.xInit(sqlite3GlobalConfig.pcache.pArg); + return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg); } void sqlite3PcacheShutdown(void){ - if( sqlite3GlobalConfig.pcache.xShutdown ){ + if( sqlite3GlobalConfig.pcache2.xShutdown ){ /* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */ - sqlite3GlobalConfig.pcache.xShutdown(sqlite3GlobalConfig.pcache.pArg); + sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg); } } @@ -191,7 +191,7 @@ void sqlite3PcacheOpen( void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ assert( pCache->nRef==0 && pCache->pDirty==0 ); if( pCache->pCache ){ - sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache); + sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); pCache->pCache = 0; pCache->pPage1 = 0; } @@ -207,7 +207,8 @@ int sqlite3PcacheFetch( int createFlag, /* If true, create page if it does not exist already */ PgHdr **ppPage /* Write the page here */ ){ - PgHdr *pPage = 0; + sqlite3_pcache_page *pPage = 0; + PgHdr *pPgHdr = 0; int eCreate; assert( pCache!=0 ); @@ -219,19 +220,19 @@ int sqlite3PcacheFetch( */ if( !pCache->pCache && createFlag ){ sqlite3_pcache *p; - int nByte; - nByte = pCache->szPage + pCache->szExtra + sizeof(PgHdr); - p = sqlite3GlobalConfig.pcache.xCreate(nByte, pCache->bPurgeable); + p = sqlite3GlobalConfig.pcache2.xCreate( + pCache->szExtra + sizeof(PgHdr), pCache->szPage, pCache->bPurgeable + ); if( !p ){ return SQLITE_NOMEM; } - sqlite3GlobalConfig.pcache.xCachesize(p, pCache->nMax); + sqlite3GlobalConfig.pcache2.xCachesize(p, pCache->nMax); pCache->pCache = p; } eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty)); if( pCache->pCache ){ - pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, eCreate); + pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); } if( !pPage && eCreate==1 ){ @@ -266,33 +267,36 @@ int sqlite3PcacheFetch( } } - pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, 2); + pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2); } if( pPage ){ - if( !pPage->pData ){ - memset(pPage, 0, sizeof(PgHdr)); - pPage->pData = (void *)&pPage[1]; - pPage->pExtra = (void*)&((char *)pPage->pData)[pCache->szPage]; - memset(pPage->pExtra, 0, pCache->szExtra); - pPage->pCache = pCache; - pPage->pgno = pgno; + pPgHdr = (PgHdr *)pPage->pExtra; + + if( !pPgHdr->pPage ){ + memset(pPgHdr, 0, sizeof(PgHdr)); + pPgHdr->pPage = pPage; + pPgHdr->pData = pPage->pBuf; + pPgHdr->pExtra = (void *)&pPgHdr[1]; + memset(pPgHdr->pExtra, 0, pCache->szExtra); + pPgHdr->pCache = pCache; + pPgHdr->pgno = pgno; } - assert( pPage->pCache==pCache ); - assert( pPage->pgno==pgno ); - assert( pPage->pData==(void *)&pPage[1] ); - assert( pPage->pExtra==(void *)&((char *)&pPage[1])[pCache->szPage] ); + assert( pPgHdr->pCache==pCache ); + assert( pPgHdr->pgno==pgno ); + assert( pPgHdr->pData==pPage->pBuf ); + assert( pPgHdr->pExtra==(void *)&pPgHdr[1] ); - if( 0==pPage->nRef ){ + if( 0==pPgHdr->nRef ){ pCache->nRef++; } - pPage->nRef++; + pPgHdr->nRef++; if( pgno==1 ){ - pCache->pPage1 = pPage; + pCache->pPage1 = pPgHdr; } } - *ppPage = pPage; - return (pPage==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK; + *ppPage = pPgHdr; + return (pPgHdr==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK; } /* @@ -339,7 +343,7 @@ void sqlite3PcacheDrop(PgHdr *p){ if( p->pgno==1 ){ pCache->pPage1 = 0; } - sqlite3GlobalConfig.pcache.xUnpin(pCache->pCache, p, 1); + sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, p->pPage, 1); } /* @@ -397,7 +401,7 @@ void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ PCache *pCache = p->pCache; assert( p->nRef>0 ); assert( newPgno>0 ); - sqlite3GlobalConfig.pcache.xRekey(pCache->pCache, p, p->pgno, newPgno); + sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno); p->pgno = newPgno; if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){ pcacheRemoveFromDirtyList(p); @@ -434,7 +438,7 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){ memset(pCache->pPage1->pData, 0, pCache->szPage); pgno = 1; } - sqlite3GlobalConfig.pcache.xTruncate(pCache->pCache, pgno+1); + sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1); } } @@ -443,7 +447,7 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){ */ void sqlite3PcacheClose(PCache *pCache){ if( pCache->pCache ){ - sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache); + sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); } } @@ -555,7 +559,7 @@ int sqlite3PcachePageRefcount(PgHdr *p){ int sqlite3PcachePagecount(PCache *pCache){ int nPage = 0; if( pCache->pCache ){ - nPage = sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache); + nPage = sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache); } return nPage; } @@ -575,7 +579,7 @@ int sqlite3PcacheGetCachesize(PCache *pCache){ void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){ pCache->nMax = mxPage; if( pCache->pCache ){ - sqlite3GlobalConfig.pcache.xCachesize(pCache->pCache, mxPage); + sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache, mxPage); } } diff --git a/src/pcache.h b/src/pcache.h index 33735d2cb..c4a25b251 100644 --- a/src/pcache.h +++ b/src/pcache.h @@ -23,7 +23,8 @@ typedef struct PCache PCache; ** structure. */ struct PgHdr { - void *pData; /* Content of this page */ + sqlite3_pcache_page *pPage; /* Pcache object page handle */ + void *pData; /* Page data */ void *pExtra; /* Extra content */ PgHdr *pDirty; /* Transient list of dirty pages */ Pgno pgno; /* Page number for this page */ diff --git a/src/pcache1.c b/src/pcache1.c index 077a7b216..f94241f5e 100644 --- a/src/pcache1.c +++ b/src/pcache1.c @@ -72,6 +72,7 @@ struct PCache1 { */ PGroup *pGroup; /* PGroup this cache belongs to */ int szPage; /* Size of allocated pages in bytes */ + int szExtra; /* Size of extra space in bytes */ int bPurgeable; /* True if cache is purgeable */ unsigned int nMin; /* Minimum number of pages reserved */ unsigned int nMax; /* Configured "cache_size" value */ @@ -90,11 +91,12 @@ struct PCache1 { /* ** Each cache entry is represented by an instance of the following -** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated -** directly before this structure in memory (see the PGHDR1_TO_PAGE() -** macro below). +** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of +** PgHdr1.pCache->szPage bytes is allocated directly before this structure +** in memory. */ struct PgHdr1 { + sqlite3_pcache_page page; unsigned int iKey; /* Key value (page number) */ PgHdr1 *pNext; /* Next in hash table chain */ PCache1 *pCache; /* Cache that currently owns this page */ @@ -145,21 +147,6 @@ static SQLITE_WSD struct PCacheGlobal { #define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g)) /* -** When a PgHdr1 structure is allocated, the associated PCache1.szPage -** bytes of data are located directly before it in memory (i.e. the total -** size of the allocation is sizeof(PgHdr1)+PCache1.szPage byte). The -** PGHDR1_TO_PAGE() macro takes a pointer to a PgHdr1 structure as -** an argument and returns a pointer to the associated block of szPage -** bytes. The PAGE_TO_PGHDR1() macro does the opposite: its argument is -** a pointer to a block of szPage bytes of data and the return value is -** a pointer to the associated PgHdr1 structure. -** -** assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(pCache, X))==X ); -*/ -#define PGHDR1_TO_PAGE(p) (void*)(((char*)p) - p->pCache->szPage) -#define PAGE_TO_PGHDR1(c, p) (PgHdr1*)(((char*)p) + c->szPage) - -/* ** Macros to enter and leave the PCache LRU mutex. */ #define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex) @@ -288,7 +275,6 @@ static int pcache1MemSize(void *p){ ** Allocate a new page object initially associated with cache pCache. */ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){ - int nByte = sizeof(PgHdr1) + pCache->szPage; PgHdr1 *p = 0; void *pPg; @@ -297,16 +283,29 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){ ** this mutex is not held. */ assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); pcache1LeaveMutex(pCache->pGroup); - pPg = pcache1Alloc(nByte); +#ifdef SQLITE_PCACHE_SEPARATE_HEADER + pPg = pcache1Alloc(pCache->szPage); + p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra); + if( !pPg || !p ){ + pcache1Free(pPg); + sqlite3_free(p); + pPg = 0; + } +#else + pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra); + p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; +#endif pcache1EnterMutex(pCache->pGroup); if( pPg ){ - p = PAGE_TO_PGHDR1(pCache, pPg); + p->page.pBuf = pPg; + p->page.pExtra = &p[1]; if( pCache->bPurgeable ){ pCache->pGroup->nCurrentPage++; } + return p; } - return p; + return 0; } /* @@ -320,7 +319,10 @@ static void pcache1FreePage(PgHdr1 *p){ if( ALWAYS(p) ){ PCache1 *pCache = p->pCache; assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) ); - pcache1Free(PGHDR1_TO_PAGE(p)); + pcache1Free(p->page.pBuf); +#ifdef SQLITE_PCACHE_SEPARATE_HEADER + sqlite3_free(p); +#endif if( pCache->bPurgeable ){ pCache->pGroup->nCurrentPage--; } @@ -361,7 +363,7 @@ void sqlite3PageFree(void *p){ ** the heap even further. */ static int pcache1UnderMemoryPressure(PCache1 *pCache){ - if( pcache1.nSlot && pCache->szPage<=pcache1.szSlot ){ + if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){ return pcache1.bUnderPressure; }else{ return sqlite3HeapNearlyFull(); @@ -552,7 +554,7 @@ static void pcache1Shutdown(void *NotUsed){ ** ** Allocate a new cache. */ -static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){ +static sqlite3_pcache *pcache1Create(int szExtra, int szPage, int bPurgeable){ PCache1 *pCache; /* The newly created page cache */ PGroup *pGroup; /* The group the new page cache will belong to */ int sz; /* Bytes of memory required to allocate the new cache */ @@ -587,6 +589,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){ } pCache->pGroup = pGroup; pCache->szPage = szPage; + pCache->szExtra = szExtra; pCache->bPurgeable = (bPurgeable ? 1 : 0); if( bPurgeable ){ pCache->nMin = 10; @@ -684,7 +687,11 @@ static int pcache1Pagecount(sqlite3_pcache *p){ ** ** 5. Otherwise, allocate and return a new page buffer. */ -static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){ +static sqlite3_pcache_page *pcache1Fetch( + sqlite3_pcache *p, + unsigned int iKey, + int createFlag +){ int nPinned; PCache1 *pCache = (PCache1 *)p; PGroup *pGroup; @@ -719,7 +726,6 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){ pGroup = pCache->pGroup; #endif - /* Step 3: Abort if createFlag is 1 but the cache is nearly full */ nPinned = pCache->nPage - pCache->nRecyclable; assert( nPinned>=0 ); @@ -747,12 +753,13 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){ pPage = pGroup->pLruTail; pcache1RemoveFromHash(pPage); pcache1PinPage(pPage); - if( (pOtherCache = pPage->pCache)->szPage!=pCache->szPage ){ + if( (pOtherCache = pPage->pCache)->szPage!=pCache->szPage + || pOtherCache->szExtra!=pCache->szExtra + ){ pcache1FreePage(pPage); pPage = 0; }else{ - pGroup->nCurrentPage -= - (pOtherCache->bPurgeable - pCache->bPurgeable); + pGroup->nCurrentPage -= (pOtherCache->bPurgeable - pCache->bPurgeable); } } @@ -773,7 +780,7 @@ static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){ pPage->pCache = pCache; pPage->pLruPrev = 0; pPage->pLruNext = 0; - *(void **)(PGHDR1_TO_PAGE(pPage)) = 0; + *(void **)pPage->page.pExtra = 0; pCache->apHash[h] = pPage; } @@ -782,7 +789,7 @@ fetch_out: pCache->iMaxKey = iKey; } pcache1LeaveMutex(pGroup); - return (pPage ? PGHDR1_TO_PAGE(pPage) : 0); + return &pPage->page; } @@ -791,9 +798,13 @@ fetch_out: ** ** Mark a page as unpinned (eligible for asynchronous recycling). */ -static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){ +static void pcache1Unpin( + sqlite3_pcache *p, + sqlite3_pcache_page *pPg, + int reuseUnlikely +){ PCache1 *pCache = (PCache1 *)p; - PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg); + PgHdr1 *pPage = (PgHdr1 *)pPg; PGroup *pGroup = pCache->pGroup; assert( pPage->pCache==pCache ); @@ -829,12 +840,12 @@ static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){ */ static void pcache1Rekey( sqlite3_pcache *p, - void *pPg, + sqlite3_pcache_page *pPg, unsigned int iOld, unsigned int iNew ){ PCache1 *pCache = (PCache1 *)p; - PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg); + PgHdr1 *pPage = (PgHdr1 *)pPg; PgHdr1 **pp; unsigned int h; assert( pPage->iKey==iOld ); @@ -903,7 +914,7 @@ static void pcache1Destroy(sqlite3_pcache *p){ ** already provided an alternative. */ void sqlite3PCacheSetDefault(void){ - static const sqlite3_pcache_methods defaultMethods = { + static const sqlite3_pcache_methods2 defaultMethods = { 0, /* pArg */ pcache1Init, /* xInit */ pcache1Shutdown, /* xShutdown */ @@ -916,7 +927,7 @@ void sqlite3PCacheSetDefault(void){ pcache1Truncate, /* xTruncate */ pcache1Destroy /* xDestroy */ }; - sqlite3_config(SQLITE_CONFIG_PCACHE, &defaultMethods); + sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods); } #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT @@ -937,7 +948,10 @@ int sqlite3PcacheReleaseMemory(int nReq){ PgHdr1 *p; pcache1EnterMutex(&pcache1.grp); while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){ - nFree += pcache1MemSize(PGHDR1_TO_PAGE(p)); + nFree += pcache1MemSize(p->page.pBuf); +#ifdef SQLITE_PCACHE_SEPARATE_HEADER + nFree += sqlite3MemSize(p); +#endif pcache1PinPage(p); pcache1RemoveFromHash(p); pcache1FreePage(p); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 9679965ce..d3dc86120 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1497,6 +1497,8 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ +#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ /* ** CAPI3REF: Database Connection Configuration Options @@ -6097,6 +6099,27 @@ struct sqlite3_pcache_methods { void (*xDestroy)(sqlite3_pcache*); }; +typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2; +typedef struct sqlite3_pcache_page sqlite3_pcache_page; +struct sqlite3_pcache_page { + void *pBuf; + void *pExtra; +}; +struct sqlite3_pcache_methods2 { + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szExtra, int szPage, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); + void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, + unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); +}; + /* ** CAPI3REF: Online Backup Object ** diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 2171c1574..46bec6a30 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2459,7 +2459,7 @@ struct Sqlite3Config { int nLookaside; /* Default lookaside buffer count */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */ - sqlite3_pcache_methods pcache; /* Low-level page-cache interface */ + sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */ void *pHeap; /* Heap storage space */ int nHeap; /* Size of pHeap[] */ int mnReq, mxReq; /* Min and max heap requests sizes */ diff --git a/src/test_init.c b/src/test_init.c index a67b6788a..7741cd19e 100644 --- a/src/test_init.c +++ b/src/test_init.c @@ -30,9 +30,9 @@ #include <tcl.h> static struct Wrapped { - sqlite3_pcache_methods pcache; - sqlite3_mem_methods mem; - sqlite3_mutex_methods mutex; + sqlite3_pcache_methods2 pcache; + sqlite3_mem_methods mem; + sqlite3_mutex_methods mutex; int mem_init; /* True if mem subsystem is initalized */ int mem_fail; /* True to fail mem subsystem inialization */ @@ -123,8 +123,8 @@ static void wrPCacheShutdown(void *pArg){ wrapped.pcache_init = 0; } -static sqlite3_pcache *wrPCacheCreate(int a, int b){ - return wrapped.pcache.xCreate(a, b); +static sqlite3_pcache *wrPCacheCreate(int a, int b, int c){ + return wrapped.pcache.xCreate(a, b, c); } static void wrPCacheCachesize(sqlite3_pcache *p, int n){ wrapped.pcache.xCachesize(p, n); @@ -132,13 +132,18 @@ static void wrPCacheCachesize(sqlite3_pcache *p, int n){ static int wrPCachePagecount(sqlite3_pcache *p){ return wrapped.pcache.xPagecount(p); } -static void *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){ +static sqlite3_pcache_page *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){ return wrapped.pcache.xFetch(p, a, b); } -static void wrPCacheUnpin(sqlite3_pcache *p, void *a, int b){ +static void wrPCacheUnpin(sqlite3_pcache *p, sqlite3_pcache_page *a, int b){ wrapped.pcache.xUnpin(p, a, b); } -static void wrPCacheRekey(sqlite3_pcache *p, void *a, unsigned b, unsigned c){ +static void wrPCacheRekey( + sqlite3_pcache *p, + sqlite3_pcache_page *a, + unsigned b, + unsigned c +){ wrapped.pcache.xRekey(p, a, b, c); } static void wrPCacheTruncate(sqlite3_pcache *p, unsigned a){ @@ -154,7 +159,7 @@ static void installInitWrappers(void){ wrMutexFree, wrMutexEnter, wrMutexTry, wrMutexLeave, wrMutexHeld, wrMutexNotheld }; - sqlite3_pcache_methods pcachemethods = { + sqlite3_pcache_methods2 pcachemethods = { 0, wrPCacheInit, wrPCacheShutdown, wrPCacheCreate, wrPCacheCachesize, wrPCachePagecount, wrPCacheFetch, @@ -173,10 +178,10 @@ static void installInitWrappers(void){ sqlite3_shutdown(); sqlite3_config(SQLITE_CONFIG_GETMUTEX, &wrapped.mutex); sqlite3_config(SQLITE_CONFIG_GETMALLOC, &wrapped.mem); - sqlite3_config(SQLITE_CONFIG_GETPCACHE, &wrapped.pcache); + sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &wrapped.pcache); sqlite3_config(SQLITE_CONFIG_MUTEX, &mutexmethods); sqlite3_config(SQLITE_CONFIG_MALLOC, &memmethods); - sqlite3_config(SQLITE_CONFIG_PCACHE, &pcachemethods); + sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcachemethods); } static int init_wrapper_install( @@ -218,7 +223,7 @@ static int init_wrapper_uninstall( sqlite3_shutdown(); sqlite3_config(SQLITE_CONFIG_MUTEX, &wrapped.mutex); sqlite3_config(SQLITE_CONFIG_MALLOC, &wrapped.mem); - sqlite3_config(SQLITE_CONFIG_PCACHE, &wrapped.pcache); + sqlite3_config(SQLITE_CONFIG_PCACHE2, &wrapped.pcache); return TCL_OK; } diff --git a/src/test_pcache.c b/src/test_pcache.c index 98aa1367a..1b8424d10 100644 --- a/src/test_pcache.c +++ b/src/test_pcache.c @@ -100,15 +100,16 @@ static void testpcacheShutdown(void *pArg){ typedef struct testpcache testpcache; struct testpcache { int szPage; /* Size of each page. Multiple of 8. */ + int szExtra; /* Size of extra data that accompanies each page */ int bPurgeable; /* True if the page cache is purgeable */ int nFree; /* Number of unused slots in a[] */ int nPinned; /* Number of pinned slots in a[] */ unsigned iRand; /* State of the PRNG */ unsigned iMagic; /* Magic number for sanity checking */ struct testpcachePage { + sqlite3_pcache_page page; /* Base class */ unsigned key; /* The key for this page. 0 means unallocated */ int isPinned; /* True if the page is pinned */ - void *pData; /* Data for this page */ } a[TESTPCACHE_NPAGE]; /* All pages in the cache */ }; @@ -129,27 +130,33 @@ static unsigned testpcacheRandom(testpcache *p){ /* ** Allocate a new page cache instance. */ -static sqlite3_pcache *testpcacheCreate(int szPage, int bPurgeable){ +static sqlite3_pcache *testpcacheCreate( + int szExtra, + int szPage, + int bPurgeable +){ int nMem; char *x; testpcache *p; int i; assert( testpcacheGlobal.pDummy!=0 ); szPage = (szPage+7)&~7; - nMem = sizeof(testpcache) + TESTPCACHE_NPAGE*szPage; + nMem = sizeof(testpcache) + TESTPCACHE_NPAGE*(szPage+szExtra); p = sqlite3_malloc( nMem ); if( p==0 ) return 0; x = (char*)&p[1]; p->szPage = szPage; + p->szExtra = szExtra; p->nFree = TESTPCACHE_NPAGE; p->nPinned = 0; p->iRand = testpcacheGlobal.prngSeed; p->bPurgeable = bPurgeable; p->iMagic = TESTPCACHE_VALID; - for(i=0; i<TESTPCACHE_NPAGE; i++, x += szPage){ + for(i=0; i<TESTPCACHE_NPAGE; i++, x += (szPage+szExtra)){ p->a[i].key = 0; p->a[i].isPinned = 0; - p->a[i].pData = (void*)x; + p->a[i].page.pBuf = (void*)x; + p->a[i].page.pExtra = (void*)&x[szPage]; } testpcacheGlobal.nInstance++; return (sqlite3_pcache*)p; @@ -181,7 +188,7 @@ static int testpcachePagecount(sqlite3_pcache *pCache){ /* ** Fetch a page. */ -static void *testpcacheFetch( +static sqlite3_pcache_page *testpcacheFetch( sqlite3_pcache *pCache, unsigned key, int createFlag @@ -200,7 +207,7 @@ static void *testpcacheFetch( assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); p->a[i].isPinned = 1; } - return p->a[i].pData; + return &p->a[i].page; } } @@ -237,11 +244,12 @@ static void *testpcacheFetch( if( p->a[j].key==0 ){ p->a[j].key = key; p->a[j].isPinned = 1; - memset(p->a[j].pData, 0, p->szPage); + memset(p->a[j].page.pBuf, 0, p->szPage); + memset(p->a[j].page.pExtra, 0, p->szExtra); p->nPinned++; p->nFree--; assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); - return p->a[j].pData; + return &p->a[j].page; } } @@ -263,10 +271,11 @@ static void *testpcacheFetch( if( p->a[j].key>0 && p->a[j].isPinned==0 ){ p->a[j].key = key; p->a[j].isPinned = 1; - memset(p->a[j].pData, 0, p->szPage); + memset(p->a[j].page.pBuf, 0, p->szPage); + memset(p->a[j].page.pExtra, 0, p->szExtra); p->nPinned++; assert( p->nPinned <= TESTPCACHE_NPAGE - p->nFree ); - return p->a[j].pData; + return &p->a[j].page; } } @@ -280,7 +289,7 @@ static void *testpcacheFetch( */ static void testpcacheUnpin( sqlite3_pcache *pCache, - void *pOldPage, + sqlite3_pcache_page *pOldPage, int discard ){ testpcache *p = (testpcache*)pCache; @@ -300,7 +309,7 @@ static void testpcacheUnpin( } for(i=0; i<TESTPCACHE_NPAGE; i++){ - if( p->a[i].pData==pOldPage ){ + if( &p->a[i].page==pOldPage ){ /* The pOldPage pointer always points to a pinned page */ assert( p->a[i].isPinned ); p->a[i].isPinned = 0; @@ -325,7 +334,7 @@ static void testpcacheUnpin( */ static void testpcacheRekey( sqlite3_pcache *pCache, - void *pOldPage, + sqlite3_pcache_page *pOldPage, unsigned oldKey, unsigned newKey ){ @@ -354,7 +363,7 @@ static void testpcacheRekey( for(i=0; i<TESTPCACHE_NPAGE; i++){ if( p->a[i].key==oldKey ){ /* The oldKey and pOldPage parameters match */ - assert( p->a[i].pData==pOldPage ); + assert( &p->a[i].page==pOldPage ); /* Page to be rekeyed must be pinned */ assert( p->a[i].isPinned ); p->a[i].key = newKey; @@ -422,7 +431,7 @@ void installTestPCache( unsigned prngSeed, /* Seed for the PRNG */ unsigned highStress /* Call xStress agressively */ ){ - static const sqlite3_pcache_methods testPcache = { + static const sqlite3_pcache_methods2 testPcache = { (void*)&testpcacheGlobal, testpcacheInit, testpcacheShutdown, @@ -435,7 +444,7 @@ void installTestPCache( testpcacheTruncate, testpcacheDestroy, }; - static sqlite3_pcache_methods defaultPcache; + static sqlite3_pcache_methods2 defaultPcache; static int isInstalled = 0; assert( testpcacheGlobal.nInstance==0 ); @@ -446,12 +455,12 @@ void installTestPCache( testpcacheGlobal.highStress = highStress; if( installFlag!=isInstalled ){ if( installFlag ){ - sqlite3_config(SQLITE_CONFIG_GETPCACHE, &defaultPcache); + sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &defaultPcache); assert( defaultPcache.xCreate!=testpcacheCreate ); - sqlite3_config(SQLITE_CONFIG_PCACHE, &testPcache); + sqlite3_config(SQLITE_CONFIG_PCACHE2, &testPcache); }else{ assert( defaultPcache.xCreate!=0 ); - sqlite3_config(SQLITE_CONFIG_PCACHE, &defaultPcache); + sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultPcache); } isInstalled = installFlag; } |