/// <summary>
        /// Handles notification of page eviction from the page cache
        /// </summary>
        /// <param name="sender">The page cache performing the eviction</param>
        /// <param name="args">The evication event arguments</param>
        /// <remarks>When the eviction event is for a writeable page, this handler
        /// ensures that the page is queued with the background page writer. If there
        /// is no background page writer because the page store was created with the
        /// disableBackgroundWriter option, then this method cancels an eviction
        /// for a writeable page.</remarks>
        private void BeforePageCacheEvict(object sender, EvictionEventArgs args)
        {
            if (args.Partition.Equals(_path))
            {
                // Evicting a page from this store
                if (args.PageId >= _newPageOffset)
                {
                    // Evicting a writeable page - add the page to the background write queue to ensure it gets written out.
                    if (_backgroundPageWriter == null)
                    {
                        // Do not evict this page
                        args.CancelEviction = true;
                    }
                    else
                    {
                        // Queue the page with the background page writer
#if DEBUG_PAGESTORE
                        Logging.LogDebug("Evict {0}", args.PageId);
#endif
                        var pageToEvict = _newPages[(int)(args.PageId - _newPageOffset)];
                        if (pageToEvict.IsAlive)
                        {
                            // Passing 0 for the transaction id is OK because it is not used for writing append-only pages
                            _backgroundPageWriter.QueueWrite(pageToEvict.Target as IPage, 0ul);
                        }
                        // Once the page write is queued, the cache entry can be evicted.
                        // The background page writer will hold on to the page data object until it is written
                        args.CancelEviction = false;
                    }
                }
            }
        }
Beispiel #2
0
 private void FireAfterEvict(EvictionEventArgs evictionArgs)
 {
     if (AfterEvict != null)
     {
         AfterEvict(this, evictionArgs);
     }
 }
        /// <summary>
        /// Handles notification of page eviction from the page cache
        /// </summary>
        /// <param name="sender">The page cache performing the eviction</param>
        /// <param name="args">The evication event arguments</param>
        /// <remarks>When the eviction event is for a writeable page, this handler 
        /// ensures that the page is queued with the background page writer. If there
        /// is no background page writer because the page store was created with the 
        /// disableBackgroundWriter option, then this method cancels an eviction
        /// for a writeable page.</remarks>
        private void BeforePageCacheEvict(object sender, EvictionEventArgs args)
        {
            if (args.Partition.Equals(_path))
            {
                // Evicting a page from this store
                if (args.PageId >= _newPageOffset)
                {
                    // Evicting a writeable page - add the page to the background write queue to ensure it gets written out.
                    if (_backgroundPageWriter == null)
                    {
                        // Do not evict this page
                        args.CancelEviction = true;
                    }
                    else
                    {
                        // Queue the page with the background page writer
#if DEBUG_PAGESTORE
                        Logging.LogDebug( "Evict {0}", args.PageId );
#endif
                        var pageToEvict = _newPages[(int) (args.PageId - _newPageOffset)];
                        if (pageToEvict.IsAlive)
                        {
                            // Passing 0 for the transaction id is OK because it is not used for writing append-only pages
                            _backgroundPageWriter.QueueWrite(pageToEvict.Target as IPage, 0ul);
                        }
                        // Once the page write is queued, the cache entry can be evicted.
                        // The background page writer will hold on to the page data object until it is written
                        args.CancelEviction = false;
                    }
                }
            }
        }
Beispiel #4
0
 private void FirePostEvict(EvictionEventArgs args)
 {
     if (AfterEvict != null)
     {
         AfterEvict(this, args);
     }
 }
Beispiel #5
0
 private void FireBeforeEvict(EvictionEventArgs evictionArgs)
 {
     if (BeforeEvict != null)
     {
         BeforeEvict(this, evictionArgs);
     }
 }
 private void FirePostEvict(EvictionEventArgs args)
 {
     if (AfterEvict != null)
     {
         AfterEvict(this, args);
     }
 }
Beispiel #7
0
 private bool FirePreEvict(EvictionEventArgs args)
 {
     if (BeforeEvict != null)
     {
         BeforeEvict(this, args);
     }
     return(!args.CancelEviction);
 }
 private bool FirePreEvict(EvictionEventArgs args)
 {
     if (BeforeEvict != null)
     {
         BeforeEvict(this, args);
     }
     return !args.CancelEviction;
 }
Beispiel #9
0
        private void EvictItems()
        {
            if (_evictInProgress)
            {
                return;
            }
            _evictInProgress = true;
            try
            {
#if DEBUG_PAGECACHE
                Logging.LogDebug("LruPageCache.EvictItems: START");
#endif
                var evictPointer = _accessList.Last;
                while (evictPointer != null && _count > _lowWaterMark)
                {
                    var partition    = evictPointer.Value.Key;
                    var pageId       = evictPointer.Value.Value.Id;
                    var evictionArgs = new EvictionEventArgs(partition, pageId);
#if DEBUG_PAGECACHE
                    Logging.LogDebug("LruPageCache.EvictItems: Selected {0}", pageId);
#endif
                    FireBeforeEvict(evictionArgs);
                    if (!evictionArgs.CancelEviction)
                    {
                        var cacheKey = MakeCacheKey(partition, pageId);
                        var tmp      = evictPointer.Previous;
                        _accessList.Remove(evictPointer);
                        _cacheItems.Remove(cacheKey);
                        _count--;
                        FireAfterEvict(evictionArgs);
#if DEBUG_PAGECACHE
                        Logging.LogDebug("LruPageCache.EvictItems: Evicted {0}", pageId);
#endif
                        evictPointer = tmp;
                    }
                    else
                    {
#if DEBUG_PAGECACHE
                        Logging.LogDebug("LruPageCache.EvictItems: Eviction of {0} was cancelled", pageId);
#endif
                        evictPointer = evictPointer.Previous;
                    }
                }
#if DEBUG_PAGECACHE
                Logging.LogDebug("LruPageCache.EvictItems: END");
#endif
            }
            finally
            {
                _evictInProgress = false;
            }
        }
 private void BeforePageCacheEvict(object sender, EvictionEventArgs args)
 {
     if (args.Partition.Equals(_filePath))
     {
         Tuple<BinaryFilePage, ulong> bfpTuple;
         if (_modifiedPages.TryGetValue(args.PageId, out bfpTuple))
         {
             EnsureOutputStream();
             bfpTuple.Item1.Write(_outputStream, bfpTuple.Item2);
         }
         _modifiedPages.Remove(args.PageId);
     }
 }
 public void Clear(string partition)
 {
     var partitionId = AssertPartitionId(partition);
     foreach(var k in _pages.Keys.Where(k=>k.PartitionId == partitionId).ToList())
     {
         var eventArgs = new EvictionEventArgs(partition, k.PageId);
         if (FirePreEvict(eventArgs))
         {
             _pages.Remove(k);
             FirePostEvict(eventArgs);
         }
     }
 }
 private void BeforePageCacheEvict(object sender, EvictionEventArgs args)
 {
     if (args.Partition.Equals(_filePath))
     {
         Tuple <BinaryFilePage, ulong> bfpTuple;
         if (_modifiedPages.TryGetValue(args.PageId, out bfpTuple))
         {
             EnsureOutputStream();
             bfpTuple.Item1.Write(_outputStream, bfpTuple.Item2);
         }
         _modifiedPages.Remove(args.PageId);
     }
 }
Beispiel #13
0
        public void Clear(string partition)
        {
            var partitionId = AssertPartitionId(partition);

            foreach (var k in _pages.Keys.Where(k => k.PartitionId == partitionId).ToList())
            {
                var eventArgs = new EvictionEventArgs(partition, k.PageId);
                if (FirePreEvict(eventArgs))
                {
                    _pages.Remove(k);
                    FirePostEvict(eventArgs);
                }
            }
        }
        private void BeforePageCacheEvict(object sender, EvictionEventArgs args)
        {
            args.CancelEviction = _modifiedPages.ContainsKey(args.PageId);
            return;

            /*
             * lock (_restartLock) // Ensure we don't try to process page evictions while restarting the background writer
             * {
             *  if (_modifiedPages.ContainsKey(args.PageId))
             *  {
             *      var page = PageCache.Instance.Lookup(_filePath, args.PageId) as BinaryFilePage;
             *      if (page != null)
             *      {
             *          _backgroundPageWriter.QueueWrite(page, _currentReadTxnId + 1);
             *      }
             *  }
             *  // Unmodified pages can just be evicted
             * }
             */
        }
Beispiel #15
0
        private void EvictItems()
        {
            if (DateTime.Now.Subtract(_cacheBlocked).TotalSeconds < BlockedCacheRetryTimeout)
            {
#if DEBUG_PAGECACHE
                Logging.LogDebug("LruPageCache.EvictItems: In cache blocked timeout.");
#endif
                return; // Last eviction failed recently so don't repeat until the timeout is exceeded
            }

            if (_evictInProgress) return;
            _evictInProgress = true;
            try
            {
#if DEBUG_PAGECACHE
            Logging.LogDebug("LruPageCache.EvictItems: START");
#endif
                var evictionCount = 0;
                lock (_updateLock)
                {
                    var evictPointer = _accessList.Last;
                    while (evictPointer != null && _count > _lowWaterMark)
                    {
                        var partition = evictPointer.Value.Key;
                        var pageId = evictPointer.Value.Value.Id;
                        var evictionArgs = new EvictionEventArgs(partition, pageId);
#if DEBUG_PAGECACHE
                Logging.LogDebug("LruPageCache.EvictItems: Selected {0}", pageId);
#endif
                        FireBeforeEvict(evictionArgs);
                        if (!evictionArgs.CancelEviction)
                        {
                            var cacheKey = MakeCacheKey(partition, pageId);
                            var tmp = evictPointer.Previous;
                            _accessList.Remove(evictPointer);
                            _cacheItems.Remove(cacheKey);
                            _count--;
                            evictionCount++;
                            FireAfterEvict(evictionArgs);
#if DEBUG_PAGECACHE
                    Logging.LogDebug("LruPageCache.EvictItems: Evicted {0}", pageId);
#endif
                            evictPointer = tmp;
                        }
                        else
                        {
#if DEBUG_PAGECACHE
                    Logging.LogDebug("LruPageCache.EvictItems: Eviction of {0} was cancelled", pageId);
#endif
                            evictPointer = evictPointer.Previous;
                        }
                    }
                }
                if (evictionCount == 0)
                {
                    // The entire cache is blocked with modified pages that cannot be written out
                    // this can happen with large transactions on the BinaryFilePageStore or on
                    // the AppendOnlyFilePageStore with background writes disabled.
                    // To prevent repeated iteration through a blocked cache we will check this timestamp:
                    _cacheBlocked = DateTime.Now;
#if DEBUG_PAGECACHE
                    Logging.LogDebug("LruPageCache.EvictItems: Setting cached blocked timeout");
#endif
                }
#if DEBUG_PAGECACHE
            Logging.LogDebug("LruPageCache.EvictItems: END");
#endif
            }
            finally
            {
                try
                {
                    FireEvictionCompleted();
                }
                finally
                {
                    _evictInProgress = false;
                }
            }
        }
        private void EvictItems()
        {
            if (DateTime.Now.Subtract(_cacheBlocked).TotalSeconds < BlockedCacheRetryTimeout)
            {
#if DEBUG_PAGECACHE
                Logging.LogDebug("LruPageCache.EvictItems: In cache blocked timeout.");
#endif
                return; // Last eviction failed recently so don't repeat until the timeout is exceeded
            }

            if (_evictInProgress)
            {
                return;
            }
            _evictInProgress = true;
            try
            {
#if DEBUG_PAGECACHE
                Logging.LogDebug("LruPageCache.EvictItems: START");
#endif
                var evictionCount = 0;
                lock (_updateLock)
                {
                    var evictPointer = _accessList.Last;
                    while (evictPointer != null && _count > _lowWaterMark)
                    {
                        var partition    = evictPointer.Value.Key;
                        var pageId       = evictPointer.Value.Value.Id;
                        var evictionArgs = new EvictionEventArgs(partition, pageId);
#if DEBUG_PAGECACHE
                        Logging.LogDebug("LruPageCache.EvictItems: Selected {0}", pageId);
#endif
                        FireBeforeEvict(evictionArgs);
                        if (!evictionArgs.CancelEviction)
                        {
                            var cacheKey = MakeCacheKey(partition, pageId);
                            var tmp      = evictPointer.Previous;
                            _accessList.Remove(evictPointer);
                            _cacheItems.Remove(cacheKey);
                            _count--;
                            evictionCount++;
                            FireAfterEvict(evictionArgs);
#if DEBUG_PAGECACHE
                            Logging.LogDebug("LruPageCache.EvictItems: Evicted {0}", pageId);
#endif
                            evictPointer = tmp;
                        }
                        else
                        {
#if DEBUG_PAGECACHE
                            Logging.LogDebug("LruPageCache.EvictItems: Eviction of {0} was cancelled", pageId);
#endif
                            evictPointer = evictPointer.Previous;
                        }
                    }
                }
                if (evictionCount == 0)
                {
                    // The entire cache is blocked with modified pages that cannot be written out
                    // this can happen with large transactions on the BinaryFilePageStore or on
                    // the AppendOnlyFilePageStore with background writes disabled.
                    // To prevent repeated iteration through a blocked cache we will check this timestamp:
                    _cacheBlocked = DateTime.Now;
#if DEBUG_PAGECACHE
                    Logging.LogDebug("LruPageCache.EvictItems: Setting cached blocked timeout");
#endif
                }
#if DEBUG_PAGECACHE
                Logging.LogDebug("LruPageCache.EvictItems: END");
#endif
            }
            finally
            {
                try
                {
                    FireEvictionCompleted();
                }
                finally
                {
                    _evictInProgress = false;
                }
            }
        }
Beispiel #17
0
        private void EvictItems()
        {
            if (_evictInProgress) return;
            _evictInProgress = true;
            try
            {
#if DEBUG_PAGECACHE
            Logging.LogDebug("LruPageCache.EvictItems: START");
#endif
                var evictPointer = _accessList.Last;
                while (evictPointer != null && _count > _lowWaterMark)
                {
                    var partition = evictPointer.Value.Key;
                    var pageId = evictPointer.Value.Value.Id;
                    var evictionArgs = new EvictionEventArgs(partition, pageId);
#if DEBUG_PAGECACHE
                Logging.LogDebug("LruPageCache.EvictItems: Selected {0}", pageId);
#endif
                    FireBeforeEvict(evictionArgs);
                    if (!evictionArgs.CancelEviction)
                    {
                        var cacheKey = MakeCacheKey(partition, pageId);
                        var tmp = evictPointer.Previous;
                        _accessList.Remove(evictPointer);
                        _cacheItems.Remove(cacheKey);
                        _count--;
                        FireAfterEvict(evictionArgs);
#if DEBUG_PAGECACHE
                    Logging.LogDebug("LruPageCache.EvictItems: Evicted {0}", pageId);
#endif
                        evictPointer = tmp;
                    }
                    else
                    {
#if DEBUG_PAGECACHE
                    Logging.LogDebug("LruPageCache.EvictItems: Eviction of {0} was cancelled", pageId);
#endif
                        evictPointer = evictPointer.Previous;
                    }
                }
#if DEBUG_PAGECACHE
            Logging.LogDebug("LruPageCache.EvictItems: END");
#endif
            }
            finally
            {
                _evictInProgress = false;
            }
        }
Beispiel #18
0
 private void FireAfterEvict(EvictionEventArgs evictionArgs)
 {
     if (AfterEvict != null) AfterEvict(this, evictionArgs);
 }
Beispiel #19
0
 private void FireBeforeEvict(EvictionEventArgs evictionArgs)
 {
     if (BeforeEvict != null) BeforeEvict(this, evictionArgs);
 }
 private void BeforePageCacheEvict(object sender, EvictionEventArgs args)
 {
     args.CancelEviction = _modifiedPages.ContainsKey(args.PageId);
     return;
     /*
     lock (_restartLock) // Ensure we don't try to process page evictions while restarting the background writer
     {
         if (_modifiedPages.ContainsKey(args.PageId))
         {
             var page = PageCache.Instance.Lookup(_filePath, args.PageId) as BinaryFilePage;
             if (page != null)
             {
                 _backgroundPageWriter.QueueWrite(page, _currentReadTxnId + 1);
             }
         }
         // Unmodified pages can just be evicted
     }
      */
 }