예제 #1
0
        private const int nrBags = 265; // based on 240 timeslices + 20 bags for ItemLimit + 5 bags empty buffer

        public LifespanManager(FluidCache <T> owner, TimeSpan minAge, TimeSpan maxAge, GetNow getNow)
        {
            this.owner = owner;
            int maxMS = Math.Min((int)maxAge.TotalMilliseconds, 12 * 60 * 60 * 1000); // max = 12 hours

            this.minAge           = minAge;
            this.getNow           = getNow;
            this.maxAge           = TimeSpan.FromMilliseconds(maxMS);
            validatyCheckInterval = TimeSpan.FromMilliseconds(maxMS / 240.0); // max timeslice = 3 min
            bagItemLimit          = this.owner.Capacity / 20;                 // max 5% of capacity per bag
            bags = new AgeBag <T> [nrBags];

            for (int loop = nrBags - 1; loop >= 0; --loop)
            {
                bags[loop] = new AgeBag <T>();
            }

            OpenCurrentBag(getNow(), 0);
        }
예제 #2
0
        /// <summary>
        /// Remove old items or items beyond capacity from LifespanMgr allowing them to be garbage collected
        /// </summary>
        /// <remarks>
        /// Since we do not physically move items when touched we must check items in bag to determine if they should
        /// be deleted or moved. Also items that were removed by setting value to null get removed now.  Rremoving
        /// an item from LifespanMgr allows it to be garbage collected. If removed item is retrieved by index prior
        /// to GC then it will be readded to LifespanMgr.
        /// </remarks>
        private void CleanUp(DateTime now)
        {
            lock (syncObject)
            {
                int        itemsAboveCapacity = Stats.Current - Stats.Capacity;
                AgeBag <T> bag = bags[OldestBagIndex];

                while (!HasProcessedAllBags && (AlmostOutOfBags || BagNeedsCleaning(bag, itemsAboveCapacity, now)))
                {
                    itemsAboveCapacity = CleanBag(bag, itemsAboveCapacity);

                    ++OldestBagIndex;
                    bag = bags[OldestBagIndex];
                }

                ++CurrentBagIndex;
                OpenBag(CurrentBagIndex);

                EnsureIndexIsValid();
            }
        }
예제 #3
0
        /// <summary>ready a new current AgeBag for use and close the previous one</summary>
        private void OpenCurrentBag(DateTime now, int bagNumber)
        {
            lock (this)
            {
                // close last age bag
                if (this.currentBag != null)
                {
                    this.currentBag.StopTime = now;
                }

                // open new age bag for next time slice
                currentBagIndex = bagNumber;

                AgeBag <T> currentBag = bags[currentBagIndex % nrBags];
                currentBag.StartTime = now;
                currentBag.First     = null;

                this.currentBag = currentBag;

                // reset counters for CheckValidity()
                nextValidityCheck = now.Add(validatyCheckInterval);
                itemsInCurrentBag = 0;
            }
        }
예제 #4
0
 private bool BagNeedsCleaning(AgeBag <T> bag, int itemsAboveCapacity, DateTime now)
 {
     return(bag.HasExpired(maxAge, now) || (itemsAboveCapacity > 0 && bag.HasReachedMinimumAge(minAge, now)));
 }