Exemplo n.º 1
0
        internal void RemoveCacheEntry(MemoryCacheEntry cacheEntry)
        {
            lock (this)
            {
                UsageEntryRef entryRef = cacheEntry.UsageEntryRef;
                if (entryRef.IsInvalid)
                {
                    return;
                }

                UsageEntry[] entries    = (_pages[(entryRef.PageIndex)]._entries);
                int          entryIndex = entryRef.Ref1Index;

                cacheEntry.UsageEntryRef        = UsageEntryRef.INVALID;
                entries[entryIndex]._cacheEntry = null;

                RemoveEntryFromLastRefList(entryRef);

                AddUsageEntryToFreeList(entryRef);

                Reduce();

                Dbg.Trace("CacheUsageRemove",
                          "Removed item=" + cacheEntry.Key +
                          ",_bucket=" + _bucket +
                          ",ref=" + entryRef);

                Dbg.Validate("CacheValidateUsage", this);
                Dbg.Dump("CacheUsageRemove", this);
            }
        }
Exemplo n.º 2
0
        private int FlushExpiredItems(bool checkDelta, bool useInsertBlock)
        {
            int flushed = 0;

            if (Interlocked.Exchange(ref _inFlush, 1) == 0)
            {
                try
                {
                    if (_timerHandleRef == null)
                    {
                        return(0);
                    }
                    DateTime utcNow = DateTime.UtcNow;
                    if (!checkDelta || utcNow - _utcLastFlush >= MIN_FLUSH_INTERVAL || utcNow < _utcLastFlush)
                    {
                        _utcLastFlush = utcNow;
                        foreach (ExpiresBucket bucket in _buckets)
                        {
                            flushed += bucket.FlushExpiredItems(utcNow, useInsertBlock);
                        }

                        Dbg.Trace("CacheExpiresFlushTotal", "FlushExpiredItems flushed a total of " + flushed + " items; Time=" + Dbg.FormatLocalDate(DateTime.Now));
                        Dbg.Dump("CacheExpiresFlush", this);
                    }
                }
                finally
                {
                    Interlocked.Exchange(ref _inFlush, 0);
                }
            }

            return(flushed);
        }
Exemplo n.º 3
0
        private void RemoveCacheEntryNoLock(MemoryCacheEntry cacheEntry)
        {
            ExpiresEntryRef entryRef = cacheEntry.ExpiresEntryRef;

            if (cacheEntry.ExpiresBucket != _bucket || entryRef.IsInvalid)
            {
                return;
            }

            ExpiresEntry[] entries    = (_pages[(entryRef.PageIndex)]._entries);
            int            entryIndex = entryRef.Index;

            RemoveCount(entries[entryIndex]._utcExpires);

            cacheEntry.ExpiresBucket        = 0xff;
            cacheEntry.ExpiresEntryRef      = ExpiresEntryRef.INVALID;
            entries[entryIndex]._cacheEntry = null;

            AddExpiresEntryToFreeList(entryRef);

            if (_cEntriesInUse == 0)
            {
                ResetCounts(DateTime.UtcNow);
            }

            Reduce();

            Dbg.Trace("CacheExpiresRemove",
                      "Removed item=" + cacheEntry.Key +
                      ",_bucket=" + _bucket +
                      ",ref=" + entryRef +
                      ",now=" + Dbg.FormatLocalDate(DateTime.Now) +
                      ",expires=" + cacheEntry.UtcAbsExp.ToLocalTime());

            Dbg.Validate("CacheValidateExpires", this);
            Dbg.Dump("CacheExpiresRemove", this);
        }
Exemplo n.º 4
0
        internal int FlushExpiredItems(DateTime utcNow, bool useInsertBlock)
        {
            if (_cEntriesInUse == 0 || GetExpiresCount(utcNow) == 0)
            {
                return(0);
            }

            Dbg.Assert(_cEntriesInFlush == 0, "_cEntriesInFlush == 0");

            ExpiresEntryRef inFlushHead = ExpiresEntryRef.INVALID;

            ExpiresEntry[]   entries;
            int              entryIndex;
            MemoryCacheEntry cacheEntry;
            int              flushed = 0;

            try
            {
                if (useInsertBlock)
                {
                    _cacheExpires.MemoryCacheStore.BlockInsert();
                }

                lock (this)
                {
                    Dbg.Assert(_blockReduce == false, "_blockReduce == false");

                    if (_cEntriesInUse == 0 || GetExpiresCount(utcNow) == 0)
                    {
                        return(0);
                    }

                    ResetCounts(utcNow);
                    int cPages = _cPagesInUse;
                    for (int i = 0; i < _pages.Length; i++)
                    {
                        entries = _pages[i]._entries;
                        if (entries != null)
                        {
                            int cEntries = NUM_ENTRIES - ((entries)[0]._cFree);
                            for (int j = 1; j < entries.Length; j++)
                            {
                                cacheEntry = entries[j]._cacheEntry;
                                if (cacheEntry != null)
                                {
                                    if (entries[j]._utcExpires > utcNow)
                                    {
                                        AddCount(entries[j]._utcExpires);
                                    }
                                    else
                                    {
                                        cacheEntry.ExpiresBucket   = 0xff;
                                        cacheEntry.ExpiresEntryRef = ExpiresEntryRef.INVALID;

                                        entries[j]._cFree = 1;

                                        entries[j]._next = inFlushHead;
                                        inFlushHead      = new ExpiresEntryRef(i, j);

                                        flushed++;
                                        _cEntriesInFlush++;
                                    }

                                    cEntries--;
                                    if (cEntries == 0)
                                    {
                                        break;
                                    }
                                }
                            }

                            cPages--;
                            if (cPages == 0)
                            {
                                break;
                            }
                        }
                    }

                    if (flushed == 0)
                    {
                        Dbg.Trace("CacheExpiresFlushTotal", "FlushExpiredItems flushed " + flushed +
                                  " expired items, bucket=" + _bucket + "; Time=" + Dbg.FormatLocalDate(DateTime.Now));

                        return(0);
                    }

                    _blockReduce = true;
                }
            }
            finally
            {
                if (useInsertBlock)
                {
                    _cacheExpires.MemoryCacheStore.UnblockInsert();
                }
            }

            Dbg.Assert(!inFlushHead.IsInvalid, "!inFlushHead.IsInvalid");

            MemoryCacheStore cacheStore = _cacheExpires.MemoryCacheStore;
            ExpiresEntryRef  current    = inFlushHead;
            ExpiresEntryRef  next;

            while (!current.IsInvalid)
            {
                entries    = (_pages[(current.PageIndex)]._entries);
                entryIndex = current.Index;

                next = entries[entryIndex]._next;

                cacheEntry = entries[entryIndex]._cacheEntry;
                entries[entryIndex]._cacheEntry = null;
                Dbg.Assert(cacheEntry.ExpiresEntryRef.IsInvalid, "cacheEntry.ExpiresEntryRef.IsInvalid");
                cacheStore.Remove(cacheEntry, cacheEntry, CacheEntryRemovedReason.Expired);

                current = next;
            }

            try
            {
                if (useInsertBlock)
                {
                    _cacheExpires.MemoryCacheStore.BlockInsert();
                }

                lock (this)
                {
                    current = inFlushHead;
                    while (!current.IsInvalid)
                    {
                        entries    = (_pages[(current.PageIndex)]._entries);
                        entryIndex = current.Index;

                        next = entries[entryIndex]._next;

                        _cEntriesInFlush--;
                        AddExpiresEntryToFreeList(current);

                        current = next;
                    }

                    Dbg.Assert(_cEntriesInFlush == 0, "_cEntriesInFlush == 0");
                    _blockReduce = false;
                    Reduce();

                    Dbg.Trace("CacheExpiresFlushTotal", "FlushExpiredItems flushed " + flushed +
                              " expired items, bucket=" + _bucket + "; Time=" + Dbg.FormatLocalDate(DateTime.Now));

                    Dbg.Validate("CacheValidateExpires", this);
                    Dbg.Dump("CacheExpiresFlush", this);
                }
            }
            finally
            {
                if (useInsertBlock)
                {
                    _cacheExpires.MemoryCacheStore.UnblockInsert();
                }
            }

            return(flushed);
        }
Exemplo n.º 5
0
        internal int FlushUnderUsedItems(int maxFlush, bool force)
        {
            if (_cEntriesInUse == 0)
            {
                return(0);
            }

            Dbg.Assert(maxFlush > 0, "maxFlush is not greater than 0, instead is " + maxFlush);
            Dbg.Assert(_cEntriesInFlush == 0, "_cEntriesInFlush == 0");

            UsageEntryRef inFlushHead = UsageEntryRef.INVALID;

            UsageEntryRef prev, prevNext;
            DateTime      utcDate;

            UsageEntry[]     entries;
            int              entryIndex;
            MemoryCacheEntry cacheEntry;
            int              flushed = 0;

            try
            {
                _cacheUsage.MemoryCacheStore.BlockInsert();

                lock (this)
                {
                    Dbg.Assert(_blockReduce == false, "_blockReduce == false");

                    if (_cEntriesInUse == 0)
                    {
                        return(0);
                    }

                    DateTime utcNow = DateTime.UtcNow;

                    for (prev = _lastRefTail; _cEntriesInFlush < maxFlush && !prev.IsInvalid; prev = prevNext)
                    {
                        Dbg.Assert(_cEntriesInUse > 0, "_cEntriesInUse > 0");

                        prevNext = (_pages[(prev.PageIndex)]._entries)[prev.Ref2Index]._ref2._prev;
                        while (prevNext.IsRef1)
                        {
                            prevNext = (_pages[(prevNext.PageIndex)]._entries)[prevNext.Ref1Index]._ref1._prev;
                        }

                        entries    = (_pages[(prev.PageIndex)]._entries);
                        entryIndex = prev.Ref2Index;

                        if (!force)
                        {
                            utcDate = entries[entryIndex]._utcDate;
                            Dbg.Assert(utcDate != DateTime.MinValue, "utcDate != DateTime.MinValue");

                            if (utcNow - utcDate <= CacheUsage.NEWADD_INTERVAL && utcNow >= utcDate)
                            {
                                continue;
                            }
                        }

                        UsageEntryRef prev1 = (new UsageEntryRef((prev).PageIndex, (prev).Ref2Index));
                        cacheEntry = entries[entryIndex]._cacheEntry;
                        Dbg.Assert(cacheEntry.UsageEntryRef == prev1, "cacheEntry.UsageEntryRef == prev1");
                        Dbg.Trace("CacheUsageFlushUnderUsedItem", "Flushing underused items, item=" + cacheEntry.Key + ", bucket=" + _bucket);

                        cacheEntry.UsageEntryRef = UsageEntryRef.INVALID;

                        RemoveEntryFromLastRefList(prev1);

                        entries[entryIndex]._ref1._next = inFlushHead;
                        inFlushHead = prev1;

                        flushed++;
                        _cEntriesInFlush++;
                    }

                    if (flushed == 0)
                    {
                        Dbg.Trace("CacheUsageFlushTotal", "Flush(" + maxFlush + "," + force + ") removed " + flushed +
                                  " underused items; Time=" + Dbg.FormatLocalDate(DateTime.Now));

                        return(0);
                    }

                    _blockReduce = true;
                }
            }
            finally
            {
                _cacheUsage.MemoryCacheStore.UnblockInsert();
            }

            Dbg.Assert(!inFlushHead.IsInvalid, "!inFlushHead.IsInvalid");

            MemoryCacheStore cacheStore = _cacheUsage.MemoryCacheStore;
            UsageEntryRef    current    = inFlushHead;
            UsageEntryRef    next;

            while (!current.IsInvalid)
            {
                entries    = (_pages[(current.PageIndex)]._entries);
                entryIndex = current.Ref1Index;

                next = entries[entryIndex]._ref1._next;

                cacheEntry = entries[entryIndex]._cacheEntry;
                entries[entryIndex]._cacheEntry = null;
                Dbg.Assert(cacheEntry.UsageEntryRef.IsInvalid, "cacheEntry.UsageEntryRef.IsInvalid");
                cacheStore.Remove(cacheEntry, cacheEntry, CacheEntryRemovedReason.Evicted);

                current = next;
            }

            try
            {
                _cacheUsage.MemoryCacheStore.BlockInsert();

                lock (this)
                {
                    current = inFlushHead;
                    while (!current.IsInvalid)
                    {
                        entries    = (_pages[(current.PageIndex)]._entries);
                        entryIndex = current.Ref1Index;

                        next = entries[entryIndex]._ref1._next;

                        _cEntriesInFlush--;
                        AddUsageEntryToFreeList(current);

                        current = next;
                    }

                    Dbg.Assert(_cEntriesInFlush == 0, "_cEntriesInFlush == 0");

                    _blockReduce = false;
                    Reduce();

                    Dbg.Trace("CacheUsageFlushTotal", "Flush(" + maxFlush + "," + force + ") removed " + flushed +
                              " underused items; Time=" + Dbg.FormatLocalDate(DateTime.Now));

                    Dbg.Validate("CacheValidateUsage", this);
                    Dbg.Dump("CacheUsageFlush", this);
                }
            }
            finally
            {
                _cacheUsage.MemoryCacheStore.UnblockInsert();
            }

            return(flushed);
        }
Exemplo n.º 6
0
        internal void UpdateCacheEntry(MemoryCacheEntry cacheEntry)
        {
            lock (this)
            {
                UsageEntryRef entryRef = cacheEntry.UsageEntryRef;
                if (entryRef.IsInvalid)
                {
                    return;
                }

                UsageEntry[]  entries    = (_pages[(entryRef.PageIndex)]._entries);
                int           entryIndex = entryRef.Ref1Index;
                UsageEntryRef entryRef2  = (new UsageEntryRef((entryRef).PageIndex, -(entryRef).Ref1Index));

                UsageEntryRef prev = entries[entryIndex]._ref2._prev;
                UsageEntryRef next = entries[entryIndex]._ref2._next;

                { if ((prev).IsRef1)
                  {
                      (_pages[((prev).PageIndex)]._entries)[(prev).Ref1Index]._ref1._next = (next);
                  }
                  else if ((prev).IsRef2)
                  {
                      (_pages[((prev).PageIndex)]._entries)[(prev).Ref2Index]._ref2._next = (next);
                  }
                  else
                  {
                      _lastRefHead = (next);
                  } };
                { if ((next).IsRef1)
                  {
                      (_pages[((next).PageIndex)]._entries)[(next).Ref1Index]._ref1._prev = (prev);
                  }
                  else if ((next).IsRef2)
                  {
                      (_pages[((next).PageIndex)]._entries)[(next).Ref2Index]._ref2._prev = (prev);
                  }
                  else
                  {
                      _lastRefTail = (prev);
                  } };

                if (_addRef2Head == entryRef2)
                {
                    _addRef2Head = next;
                }

                entries[entryIndex]._ref2 = entries[entryIndex]._ref1;
                prev = entries[entryIndex]._ref2._prev;
                next = entries[entryIndex]._ref2._next;

                { if ((prev).IsRef1)
                  {
                      (_pages[((prev).PageIndex)]._entries)[(prev).Ref1Index]._ref1._next = (entryRef2);
                  }
                  else if ((prev).IsRef2)
                  {
                      (_pages[((prev).PageIndex)]._entries)[(prev).Ref2Index]._ref2._next = (entryRef2);
                  }
                  else
                  {
                      _lastRefHead = (entryRef2);
                  } };
                { if ((next).IsRef1)
                  {
                      (_pages[((next).PageIndex)]._entries)[(next).Ref1Index]._ref1._prev = (entryRef2);
                  }
                  else if ((next).IsRef2)
                  {
                      (_pages[((next).PageIndex)]._entries)[(next).Ref2Index]._ref2._prev = (entryRef2);
                  }
                  else
                  {
                      _lastRefTail = (entryRef2);
                  } };

                entries[entryIndex]._ref1._prev = UsageEntryRef.INVALID;
                entries[entryIndex]._ref1._next = _lastRefHead;

                { if ((_lastRefHead).IsRef1)
                  {
                      (_pages[((_lastRefHead).PageIndex)]._entries)[(_lastRefHead).Ref1Index]._ref1._prev = (entryRef);
                  }
                  else if ((_lastRefHead).IsRef2)
                  {
                      (_pages[((_lastRefHead).PageIndex)]._entries)[(_lastRefHead).Ref2Index]._ref2._prev = (entryRef);
                  }
                  else
                  {
                      _lastRefTail = (entryRef);
                  } };
                _lastRefHead = entryRef;

                Dbg.Trace("CacheUsageUpdate",
                          "Updated item=" + cacheEntry.Key +
                          ",_bucket=" + _bucket +
                          ",ref=" + entryRef);

                Dbg.Validate("CacheValidateUsage", this);
                Dbg.Dump("CacheUsageUpdate", this);
            }
        }
Exemplo n.º 7
0
        internal void AddCacheEntry(MemoryCacheEntry cacheEntry)
        {
            lock (this)
            {
                if (_freeEntryList._head == -1)
                {
                    Expand();
                }

                UsageEntryRef freeRef1 = GetFreeUsageEntry();
                UsageEntryRef freeRef2 = (new UsageEntryRef((freeRef1).PageIndex, -(freeRef1).Ref1Index));
                Dbg.Assert(cacheEntry.UsageEntryRef.IsInvalid, "cacheEntry.UsageEntryRef.IsInvalid");
                cacheEntry.UsageEntryRef = freeRef1;

                UsageEntry[] entries    = (_pages[(freeRef1.PageIndex)]._entries);
                int          entryIndex = freeRef1.Ref1Index;
                entries[entryIndex]._cacheEntry = cacheEntry;
                entries[entryIndex]._utcDate    = DateTime.UtcNow;

                entries[entryIndex]._ref1._prev = UsageEntryRef.INVALID;
                entries[entryIndex]._ref2._next = _addRef2Head;
                if (_lastRefHead.IsInvalid)
                {
                    entries[entryIndex]._ref1._next = freeRef2;
                    entries[entryIndex]._ref2._prev = freeRef1;
                    _lastRefTail = freeRef2;
                }
                else
                {
                    entries[entryIndex]._ref1._next = _lastRefHead;
                    { if ((_lastRefHead).IsRef1)
                      {
                          (_pages[((_lastRefHead).PageIndex)]._entries)[(_lastRefHead).Ref1Index]._ref1._prev = (freeRef1);
                      }
                      else if ((_lastRefHead).IsRef2)
                      {
                          (_pages[((_lastRefHead).PageIndex)]._entries)[(_lastRefHead).Ref2Index]._ref2._prev = (freeRef1);
                      }
                      else
                      {
                          _lastRefTail = (freeRef1);
                      } };

                    UsageEntryRef next, prev;
                    if (_addRef2Head.IsInvalid)
                    {
                        prev = _lastRefTail;
                        next = UsageEntryRef.INVALID;
                    }
                    else
                    {
                        prev = (_pages[(_addRef2Head.PageIndex)]._entries)[_addRef2Head.Ref2Index]._ref2._prev;
                        next = _addRef2Head;
                    }

                    entries[entryIndex]._ref2._prev = prev;
                    { if ((prev).IsRef1)
                      {
                          (_pages[((prev).PageIndex)]._entries)[(prev).Ref1Index]._ref1._next = (freeRef2);
                      }
                      else if ((prev).IsRef2)
                      {
                          (_pages[((prev).PageIndex)]._entries)[(prev).Ref2Index]._ref2._next = (freeRef2);
                      }
                      else
                      {
                          _lastRefHead = (freeRef2);
                      } };
                    { if ((next).IsRef1)
                      {
                          (_pages[((next).PageIndex)]._entries)[(next).Ref1Index]._ref1._prev = (freeRef2);
                      }
                      else if ((next).IsRef2)
                      {
                          (_pages[((next).PageIndex)]._entries)[(next).Ref2Index]._ref2._prev = (freeRef2);
                      }
                      else
                      {
                          _lastRefTail = (freeRef2);
                      } };
                }

                _lastRefHead = freeRef1;
                _addRef2Head = freeRef2;

                _cEntriesInUse++;

                Dbg.Trace("CacheUsageAdd",
                          "Added item=" + cacheEntry.Key +
                          ",_bucket=" + _bucket +
                          ",ref=" + freeRef1);

                Dbg.Validate("CacheValidateUsage", this);
                Dbg.Dump("CacheUsageAdd", this);
            }
        }