Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --- C:/Dokumente und Einstellungen/gc/Lokale Einstellungen/Temp/_tc/sqlite-src-3071502/src/pcache1.c Wed Jan 09 20:51:48 2013
- +++ c:/MinGW/projects/sqlite-src-3071502/src/pcache1.c Mon Feb 25 12:02:42 2013
- @@ -23,6 +23,17 @@
- typedef struct PgHdr1 PgHdr1;
- typedef struct PgFreeslot PgFreeslot;
- typedef struct PGroup PGroup;
- +typedef struct PHeap1 PHeap1;
- +
- +/* gc:
- + Heap structure for keeping cached pages
- +*/
- +struct PHeap1{
- + PgHdr1 **hItems; // 1 extra item; valid 1..iCount
- + int iCount; // stored entries
- + int iCap; // capacity
- +};
- +
- /* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
- ** of one or more PCaches that are able to recycle each others unpinned
- @@ -52,7 +63,8 @@
- unsigned int nMinPage; /* Sum of nMin for purgeable caches */
- unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
- unsigned int nCurrentPage; /* Number of purgeable pages allocated */
- - PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */
- +
- + PHeap1 h; /* heap containing unpinned pages */
- };
- /* Each page cache is an instance of the following object. Every
- @@ -96,13 +108,120 @@
- struct PgHdr1 {
- sqlite3_pcache_page page;
- unsigned int iKey; /* Key value (page number) */
- + unsigned int iFetch; /* fetch count */
- + unsigned int hPos; /* heap position; updated on change */
- PgHdr1 *pNext; /* Next in hash table chain */
- PCache1 *pCache; /* Cache that currently owns this page */
- - PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
- - PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
- };
- /*
- + Gabriel Corneanu: heap implementation on cache pages
- +*/
- +static int HGrow(PHeap1 *h){
- + h->iCap = (h->iCap >= 20) ? h->iCap * 11 / 10 : 20;
- + h->hItems = sqlite3Realloc(h->hItems, h->iCap * sizeof(PgHdr1));
- +}
- +
- +static int HInit(PHeap1 *h){
- + h->iCount = 0;
- + h->hItems = 0;
- + h->iCap = 50;
- + h->hItems = 0;
- + HGrow(h);
- +}
- +
- +static int HFree(PHeap1 *h){
- + sqlite3_free(h->hItems);
- +}
- +
- +#define HeapCompare(A,B) \
- + (h->hItems[A]->iFetch <= h->hItems[B]->iFetch)
- +
- +#define ParentElement(i) (i / 2)
- +#define LeftChildElement(i) (i * 2)
- +
- +static void HPropagateDown(PHeap1 *h, int Elem){
- +//
- +// propagate the given element down to its place in the heap
- +// this makes sense from the top (or for rebuild)
- +// returns new position
- +//
- + if (Elem >= h->iCount) return;
- + int c = LeftChildElement(Elem);
- + PgHdr1 *t = h->hItems[Elem]; // compare value
- + while (c <= h->iCount){
- + //smallest child, if available
- + if ((c < h->iCount) && !HeapCompare(c, c+1) )
- + c++; //the other child
- +
- + if (t->iFetch <= h->hItems[c]->iFetch) break;
- + //exchange is not needed, only once at the end!
- + h->hItems[Elem] = h->hItems[c];
- + h->hItems[Elem]->hPos = Elem;
- + Elem = c;
- + c = LeftChildElement(c);
- + }
- + h->hItems[Elem] = t;
- + h->hItems[Elem]->hPos = Elem;
- +}
- +
- +/*
- +// propagate the given element down to its place in the heap
- +// returns new position
- +*/
- +void HPropagateUp(PHeap1 *h, int Elem){
- + if (Elem <= 1) return;
- + int p = ParentElement(Elem);
- + PgHdr1 *t = h->hItems[Elem]; // compare value
- + while (p > 1 && (t->iFetch <= h->hItems[p]->iFetch) ) {
- + //exchange is not needed, only once at the end!
- + h->hItems[Elem] = h->hItems[p];
- + h->hItems[Elem]->hPos = Elem;
- + Elem = p;
- + p = ParentElement(p);
- + }
- + h->hItems[Elem] = t;
- + h->hItems[Elem]->hPos = Elem;
- +}
- +
- +/*
- +// extract requested element and adjust the heap
- +*/
- +static PgHdr1 *HExtract(PHeap1 *h, int Elem){
- + if (Elem < 1 || Elem > h->iCount){
- + return 0;
- + }
- +
- + PgHdr1 *p = h->hItems[Elem];
- + assert(p->hPos == Elem);
- + p->hPos = 0;
- + h->hItems[Elem] = h->hItems[ h->iCount -- ];
- + h->hItems[Elem]->hPos = Elem;
- + HPropagateDown(h, Elem);
- + return p;
- +}
- +
- +/* usual pop, not used * /
- +static PgHdr1 *HPop(PHeap1 *h){ return HExtract(h->iCount); }
- +*/
- +
- +/* usual peek; extraction is done via pcache1PinPage */
- +static PgHdr1 *HPeek(PHeap1 *h){ return h->iCount ? h->hItems[1] : 0 ; }
- +
- +/*
- +//add a new element in heap
- +*/
- +static void HPush(PHeap1 *h, PgHdr1 *p){
- + if (h->iCount >= h->iCap)
- + HGrow(h);
- +
- + int pos = ++ (h->iCount);
- + p->hPos = pos;
- + h->hItems[pos] = p;
- + HPropagateUp(h, pos);
- +}
- +
- +/*
- ** Free slots in the allocator used to divide up the buffer provided using
- ** the SQLITE_CONFIG_PAGECACHE mechanism.
- */
- @@ -435,22 +554,9 @@
- pCache = pPage->pCache;
- pGroup = pCache->pGroup;
- assert( sqlite3_mutex_held(pGroup->mutex) );
- - if( pPage->pLruNext || pPage==pGroup->pLruTail ){
- - if( pPage->pLruPrev ){
- - pPage->pLruPrev->pLruNext = pPage->pLruNext;
- - }
- - if( pPage->pLruNext ){
- - pPage->pLruNext->pLruPrev = pPage->pLruPrev;
- - }
- - if( pGroup->pLruHead==pPage ){
- - pGroup->pLruHead = pPage->pLruNext;
- - }
- - if( pGroup->pLruTail==pPage ){
- - pGroup->pLruTail = pPage->pLruPrev;
- - }
- - pPage->pLruNext = 0;
- - pPage->pLruPrev = 0;
- - pPage->pCache->nRecyclable--;
- + if( pPage->hPos ){
- + HExtract(&pGroup->h, pPage->hPos);
- + pCache->nRecyclable--;
- }
- }
- @@ -480,8 +586,8 @@
- */
- static void pcache1EnforceMaxPage(PGroup *pGroup){
- assert( sqlite3_mutex_held(pGroup->mutex) );
- - while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
- - PgHdr1 *p = pGroup->pLruTail;
- + PgHdr1 *p;
- + while( pGroup->nCurrentPage>pGroup->nMaxPage && (p = HPeek(&pGroup->h))){
- assert( p->pCache->pGroup==pGroup );
- pcache1PinPage(p);
- pcache1RemoveFromHash(p);
- @@ -535,6 +641,7 @@
- pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
- pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);
- }
- + HInit(&pcache1.grp.h);
- pcache1.grp.mxPinned = 10;
- pcache1.isInit = 1;
- return SQLITE_OK;
- @@ -548,6 +655,7 @@
- static void pcache1Shutdown(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- assert( pcache1.isInit!=0 );
- + HFree(&pcache1.grp.h);
- memset(&pcache1, 0, sizeof(pcache1));
- }
- @@ -588,6 +696,7 @@
- if( separateCache ){
- pGroup = (PGroup*)&pCache[1];
- pGroup->mxPinned = 10;
- + HInit(&pGroup->h);
- }else{
- pGroup = &pcache1.grp;
- }
- @@ -735,6 +844,11 @@
- /* Step 2: Abort if no existing page is found and createFlag is 0 */
- if( pPage || createFlag==0 ){
- pcache1PinPage(pPage);
- + if(pPage){
- + pPage->iFetch++; //increment fetch counter
- + if(pPage->hPos)
- + HPropagateDown(&pGroup->h, pPage->hPos);
- + }
- goto fetch_out;
- }
- @@ -767,13 +881,13 @@
- }
- /* Step 4. Try to recycle a page. */
- - if( pCache->bPurgeable && pGroup->pLruTail && (
- + if( pCache->bPurgeable && pGroup->h.iCount && (
- (pCache->nPage+1>=pCache->nMax)
- || pGroup->nCurrentPage>=pGroup->nMaxPage
- || pcache1UnderMemoryPressure(pCache)
- )){
- PCache1 *pOther;
- - pPage = pGroup->pLruTail;
- + pPage = HPeek(&pGroup->h);
- pcache1RemoveFromHash(pPage);
- pcache1PinPage(pPage);
- pOther = pPage->pCache;
- @@ -808,8 +922,8 @@
- pPage->iKey = iKey;
- pPage->pNext = pCache->apHash[h];
- pPage->pCache = pCache;
- - pPage->pLruPrev = 0;
- - pPage->pLruNext = 0;
- + pPage->hPos = 0;
- + pPage->iFetch = 0;
- *(void **)pPage->page.pExtra = 0;
- pCache->apHash[h] = pPage;
- }
- @@ -843,22 +957,14 @@
- /* It is an error to call this function if the page is already
- ** part of the PGroup LRU list.
- */
- - assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
- - assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
- + assert( pPage->hPos==0 );
- if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
- pcache1RemoveFromHash(pPage);
- pcache1FreePage(pPage);
- }else{
- /* Add the page to the PGroup LRU list. */
- - if( pGroup->pLruHead ){
- - pGroup->pLruHead->pLruPrev = pPage;
- - pPage->pLruNext = pGroup->pLruHead;
- - pGroup->pLruHead = pPage;
- - }else{
- - pGroup->pLruTail = pPage;
- - pGroup->pLruHead = pPage;
- - }
- + HPush(&pGroup->h, pPage);
- pCache->nRecyclable++;
- }
- @@ -935,6 +1041,8 @@
- pGroup->nMinPage -= pCache->nMin;
- pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
- pcache1EnforceMaxPage(pGroup);
- + if(pGroup != &pcache1.grp)
- + HFree(&pGroup->h);
- pcache1LeaveMutex(pGroup);
- sqlite3_free(pCache->apHash);
- sqlite3_free(pCache);
- @@ -981,7 +1089,7 @@
- if( pcache1.pStart==0 ){
- PgHdr1 *p;
- pcache1EnterMutex(&pcache1.grp);
- - while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
- + while( (nReq<0 || nFree<nReq) && (p=HPeek(&pcache1.grp.h)) ){
- nFree += pcache1MemSize(p->page.pBuf);
- #ifdef SQLITE_PCACHE_SEPARATE_HEADER
- nFree += sqlite3MemSize(p);
- @@ -1007,11 +1115,7 @@
- int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */
- int *pnRecyclable /* OUT: Total number of pages available for recycling */
- ){
- - PgHdr1 *p;
- - int nRecyclable = 0;
- - for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
- - nRecyclable++;
- - }
- + int nRecyclable = pcache1.grp.h.iCount;
- *pnCurrent = pcache1.grp.nCurrentPage;
- *pnMax = (int)pcache1.grp.nMaxPage;
- *pnMin = (int)pcache1.grp.nMinPage;
Advertisement
Add Comment
Please, Sign In to add comment