private void RecoverSpace(RecoveryFinishedCondition finishCondition)
        {
            bool finished = false;

            while (!finished)
            {
                if (_cleanupQueue.Count == 0)
                {
                    _cleanupQueue = new Queue <TKey>(_keyCounts.ToArray().Select(k => k.Key));
                }
                TKey key = _cleanupQueue.Dequeue();
                uint count;
                if (_keyCounts.TryGetValue(key, out count))
                {
                    if (count <= 1)
                    {
                        _keyCounts.TryRemove(key, out count);
                        Interlocked.Add(ref _sumOfAmountsOverAllKeys, -count);
                        Interlocked.Add(ref _numberOfElements, -1);
                    }
                    else
                    {
                        _keyCounts.AddOrUpdate(key, k => 0, (k, priorValue) => priorValue - 1);
                        Interlocked.Add(ref _sumOfAmountsOverAllKeys, -1);
                    }
                }
                finished = finishCondition();
            }
            lock (_recoveryTaskLock)
            {
                _recoveryTask = null;
            }
        }
Пример #2
0
        /// <summary>
        /// Recover space when the MaxCapacity limit is reached
        /// </summary>
        private void RecoverSpace(RecoveryFinishedCondition finishCondition)
        {
            // We're finished when the capacity has been reduced to CapacityToTargetWhenRecoveringSpace
            bool finished = false;

            while (!finished)
            {
                // If there queue of keys to cleanup is empty, refill it with all of the key's keys
                if (_cleanupQueue.Count == 0)
                {
                    _cleanupQueue = new Queue <TKey>(_keyCounts.ToArray().Select(k => k.Key));
                }
                // Dequeue one key from the clean-up queue (we only run one recovery-task at a time,
                // so we don't need task/thread safety here.
                TKey key = _cleanupQueue.Dequeue();
                // Reduce the count for the current key on the queue and, if the count reaches 0,
                // remove that key
                uint count;
                if (_keyCounts.TryGetValue(key, out count))
                {
                    if (count <= 1)
                    {
                        _keyCounts.TryRemove(key, out count);
                        Interlocked.Add(ref _sumOfAmountsOverAllKeys, -count);
                        Interlocked.Add(ref _numberOfElements, -1);
                    }
                    else
                    {
                        _keyCounts.AddOrUpdate(key, k => 0, (k, priorValue) => priorValue - 1);
                        Interlocked.Add(ref _sumOfAmountsOverAllKeys, -1);
                    }
                }
                // We're finished when the capacity has reached the target capacity
                finished = finishCondition();
            }
            // Now that the task is done, clear the task object so that a new task can be started
            // if necessary.
            lock (_recoveryTaskLock)
            {
                _recoveryTask = null;
            }
        }