예제 #1
0
파일: PgHdr1.cs 프로젝트: smorey2/feaserver
        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();
        }
예제 #2
0
 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);
 }
예제 #3
0
        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();
        }
예제 #4
0
        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--;
            }
        }
예제 #5
0
 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);
     }
 }
예제 #6
0
 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);
     }
 }
예제 #7
0
        private PgHdr1 pcache1AllocPage()
        {
            var pPg = pcache1Alloc(szPage);
            var p   = new PgHdr1();

            p.pCache = this;
            p.pPgHdr = pPg;
            if (bPurgeable)
            {
                pGroup.nCurrentPage++;
            }
            return(p);
        }
예제 #8
0
 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--;
 }
예제 #9
0
        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
        }
예제 #10
0
        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);
        }
예제 #11
0
 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--;
     }
 }
예제 #12
0
        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--;
        }
예제 #13
0
        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);
        }
예제 #14
0
 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);
     }
 }
예제 #15
0
 private static PgHdr PGHDR1_TO_PAGE(PgHdr1 p)
 {
     return(p.pPgHdr);
 }
예제 #16
0
 private PgHdr1 pcache1AllocPage()
 {
     var pPg = pcache1Alloc(szPage);
     var p = new PgHdr1();
     p.pCache = this;
     p.pPgHdr = pPg;
     if (bPurgeable)
         pGroup.nCurrentPage++;
     return p;
 }
예제 #17
0
 private static PgHdr PGHDR1_TO_PAGE(PgHdr1 p)
 {
     return p.pPgHdr;
 }