public PgHdr pPgHdr = new PgHdr(); // Pointer to Actual Page Header public void Clear() { this.iKey = 0; this.pNext = null; this.pCache = null; this.pPgHdr.ClearState(); }
private RC pcache1ResizeHash() { Debug.Assert(MutexEx.Held(pGroup.mutex)); var nNew = nHash * 2; if (nNew < 256) nNew = 256; pcache1LeaveMutex(pGroup); if (nHash != 0) MallocEx.sqlite3BeginBenignMalloc(); var apNew = new PgHdr1[nNew]; if (nHash != 0) MallocEx.sqlite3EndBenignMalloc(); pcache1EnterMutex(pGroup); if (apNew != null) { for (var i = 0; i < nHash; i++) { var pNext = apHash[i]; PgHdr1 pPage; while ((pPage = pNext) != null) { var h = (Pgno)(pPage.iKey % nNew); pNext = pPage.pNext; pPage.pNext = apNew[h]; apNew[h] = pPage; } } apHash = apNew; nHash = nNew; } return (apHash != null ? RC.OK : RC.NOMEM); }
private static void pcache1PinPage(PgHdr1 pPage) { if (pPage == null) { return; } var pCache = pPage.pCache; var pGroup = pCache.pGroup; Debug.Assert(MutexEx.Held(pGroup.mutex)); if (pPage.pLruNext != null || pPage == pGroup.pLruTail) { if (pPage.pLruPrev != null) { pPage.pLruPrev.pLruNext = pPage.pLruNext; } if (pPage.pLruNext != null) { pPage.pLruNext.pLruPrev = pPage.pLruPrev; } if (pGroup.pLruHead == pPage) { pGroup.pLruHead = pPage.pLruNext; } if (pGroup.pLruTail == pPage) { pGroup.pLruTail = pPage.pLruPrev; } pPage.pLruNext = null; pPage.pLruPrev = null; pPage.pCache.nRecyclable--; } }
private static void pcache1EnforceMaxPage(PGroup pGroup) { Debug.Assert(MutexEx.Held(pGroup.mutex)); while (pGroup.nCurrentPage > pGroup.nMaxPage && pGroup.pLruTail != null) { PgHdr1 p = pGroup.pLruTail; Debug.Assert(p.pCache.pGroup == pGroup); pcache1PinPage(p); pcache1RemoveFromHash(p); pcache1FreePage(ref p); } }
private static void pcache1FreePage(ref PgHdr1 p) { if (Check.ALWAYS(p) != null) { var pCache = p.pCache; if (pCache.bPurgeable) { pCache.pGroup.nCurrentPage--; } pcache1Free(ref p.pPgHdr); } }
private PgHdr1 pcache1AllocPage() { var pPg = pcache1Alloc(szPage); var p = new PgHdr1(); p.pCache = this; p.pPgHdr = pPg; if (bPurgeable) { pGroup.nCurrentPage++; } return(p); }
private static void pcache1RemoveFromHash(PgHdr1 pPage) { var pCache = pPage.pCache; Debug.Assert(MutexEx.Held(pCache.pGroup.mutex)); var h = (int)(pPage.iKey % pCache.nHash); PgHdr1 pPrev = null; PgHdr1 pp; for (pp = pCache.apHash[h]; pp != pPage; pPrev = pp, pp = pp.pNext) ; if (pPrev == null) pCache.apHash[h] = pp.pNext; else pPrev.pNext = pp.pNext; pCache.nPage--; }
private void pcache1TruncateUnsafe(uint iLimit) { #if !DEBUG uint nPage = 0; #endif Debug.Assert(MutexEx.Held(pGroup.mutex)); for (uint h = 0; h < nHash; h++) { var pp = apHash[h]; PgHdr1 pPrev = null; PgHdr1 pPage; while ((pPage = pp) != null) { if (pPage.iKey >= iLimit) { nPage--; pp = pPage.pNext; pcache1PinPage(pPage); if (apHash[h] == pPage) { apHash[h] = pPage.pNext; } else { pPrev.pNext = pp; } pcache1FreePage(ref pPage); } else { pp = pPage.pNext; #if !DEBUG nPage++; #endif } pPrev = pPage; } } #if !DEBUG Debug.Assert(pCache.nPage == nPage); #endif }
private RC pcache1ResizeHash() { Debug.Assert(MutexEx.Held(pGroup.mutex)); var nNew = nHash * 2; if (nNew < 256) { nNew = 256; } pcache1LeaveMutex(pGroup); if (nHash != 0) { MallocEx.sqlite3BeginBenignMalloc(); } var apNew = new PgHdr1[nNew]; if (nHash != 0) { MallocEx.sqlite3EndBenignMalloc(); } pcache1EnterMutex(pGroup); if (apNew != null) { for (var i = 0; i < nHash; i++) { var pNext = apHash[i]; PgHdr1 pPage; while ((pPage = pNext) != null) { var h = (Pgno)(pPage.iKey % nNew); pNext = pPage.pNext; pPage.pNext = apNew[h]; apNew[h] = pPage; } } apHash = apNew; nHash = nNew; } return(apHash != null ? RC.OK : RC.NOMEM); }
private static void pcache1PinPage(PgHdr1 pPage) { if (pPage == null) return; var pCache = pPage.pCache; var pGroup = pCache.pGroup; Debug.Assert(MutexEx.Held(pGroup.mutex)); if (pPage.pLruNext != null || pPage == pGroup.pLruTail) { if (pPage.pLruPrev != null) pPage.pLruPrev.pLruNext = pPage.pLruNext; if (pPage.pLruNext != null) pPage.pLruNext.pLruPrev = pPage.pLruPrev; if (pGroup.pLruHead == pPage) pGroup.pLruHead = pPage.pLruNext; if (pGroup.pLruTail == pPage) pGroup.pLruTail = pPage.pLruPrev; pPage.pLruNext = null; pPage.pLruPrev = null; pPage.pCache.nRecyclable--; } }
private static void pcache1RemoveFromHash(PgHdr1 pPage) { var pCache = pPage.pCache; Debug.Assert(MutexEx.Held(pCache.pGroup.mutex)); var h = (int)(pPage.iKey % pCache.nHash); PgHdr1 pPrev = null; PgHdr1 pp; for (pp = pCache.apHash[h]; pp != pPage; pPrev = pp, pp = pp.pNext) { ; } if (pPrev == null) { pCache.apHash[h] = pp.pNext; } else { pPrev.pNext = pp.pNext; } pCache.nPage--; }
public PgHdr xFetch(Pgno key, int createFlag) { Debug.Assert(bPurgeable || createFlag != 1); Debug.Assert(bPurgeable || nMin == 0); Debug.Assert(!bPurgeable || nMin == 10); Debug.Assert(nMin == 0 || bPurgeable); PGroup pGroup; pcache1EnterMutex(pGroup = this.pGroup); // Step 1: Search the hash table for an existing entry. PgHdr1 pPage = null; if (nHash > 0) { var h = (int)(key % nHash); for (pPage = apHash[h]; pPage != null && pPage.iKey != key; pPage = pPage.pNext) { ; } } // Step 2: Abort if no existing page is found and createFlag is 0 if (pPage != null || createFlag == 0) { pcache1PinPage(pPage); goto fetch_out; } // The pGroup local variable will normally be initialized by the pcache1EnterMutex() macro above. But if SQLITE_MUTEX_OMIT is defined, // then pcache1EnterMutex() is a no-op, so we have to initialize the local variable here. Delaying the initialization of pGroup is an // optimization: The common case is to exit the module before reaching // this point. #if SQLITE_MUTEX_OMIT pGroup = pCache.pGroup; #endif // Step 3: Abort if createFlag is 1 but the cache is nearly full var nPinned = nPage - nRecyclable; Debug.Assert(nPinned >= 0); Debug.Assert(pGroup.mxPinned == pGroup.nMaxPage + 10 - pGroup.nMinPage); Debug.Assert(n90pct == nMax * 9 / 10); if (createFlag == 1 && (nPinned >= pGroup.mxPinned || nPinned >= (int)n90pct || pcache1UnderMemoryPressure())) { goto fetch_out; } if (nPage >= nHash && pcache1ResizeHash() != 0) { goto fetch_out; } // Step 4. Try to recycle a page. if (bPurgeable && pGroup.pLruTail != null && ((nPage + 1 >= nMax) || pGroup.nCurrentPage >= pGroup.nMaxPage || pcache1UnderMemoryPressure())) { pPage = pGroup.pLruTail; pcache1RemoveFromHash(pPage); pcache1PinPage(pPage); PCache1 pOtherCache; if ((pOtherCache = pPage.pCache).szPage != szPage) { pcache1FreePage(ref pPage); pPage = null; } else { pGroup.nCurrentPage -= (pOtherCache.bPurgeable ? 1 : 0) - (bPurgeable ? 1 : 0); } } // Step 5. If a usable page buffer has still not been found, attempt to allocate a new one. if (null == pPage) { if (createFlag == 1) { MallocEx.sqlite3BeginBenignMalloc(); } pcache1LeaveMutex(pGroup); pPage = pcache1AllocPage(); pcache1EnterMutex(pGroup); if (createFlag == 1) { MallocEx.sqlite3EndBenignMalloc(); } } if (pPage != null) { var h = (int)(key % nHash); nPage++; pPage.iKey = key; pPage.pNext = apHash[h]; pPage.pCache = this; pPage.pLruPrev = null; pPage.pLruNext = null; PGHDR1_TO_PAGE(pPage).ClearState(); pPage.pPgHdr.PgHdr1 = pPage; apHash[h] = pPage; } fetch_out: if (pPage != null && key > iMaxKey) { iMaxKey = key; } pcache1LeaveMutex(pGroup); return(pPage != null ? PGHDR1_TO_PAGE(pPage) : null); }
private static void pcache1FreePage(ref PgHdr1 p) { if (Check.ALWAYS(p) != null) { var pCache = p.pCache; if (pCache.bPurgeable) pCache.pGroup.nCurrentPage--; pcache1Free(ref p.pPgHdr); } }
private static PgHdr PGHDR1_TO_PAGE(PgHdr1 p) { return(p.pPgHdr); }
private PgHdr1 pcache1AllocPage() { var pPg = pcache1Alloc(szPage); var p = new PgHdr1(); p.pCache = this; p.pPgHdr = pPg; if (bPurgeable) pGroup.nCurrentPage++; return p; }
private static PgHdr PGHDR1_TO_PAGE(PgHdr1 p) { return p.pPgHdr; }