예제 #1
0
        private ScratchBufferItem NextFile(long minSize, long?requestedSize)
        {
            var current  = _recycleArea.Last;
            var oldestTx = _env.PossibleOldestReadTransaction(null);

            while (current != null)
            {
                var recycled = current.Value;

                if (recycled.File.Size >= Math.Max(minSize, requestedSize ?? 0) &&
                    // even though this is in the recyle bin, there might still be some transactions looking at it
                    // so we have to make sure that this is really unused before actually reusing it
                    recycled.File.HasActivelyUsedBytes(oldestTx) == false)
                {
                    recycled.File.Reset();
                    recycled.RecycledAt = default(DateTime);
                    _recycleArea.Remove(current);
                    AddScratchBufferFile(recycled);

                    _scratchSpaceMonitor.Increase(recycled.File.NumberOfAllocatedPages * Constants.Storage.PageSize);

                    return(recycled);
                }

                current = current.Previous;
            }

            _currentScratchNumber++;
            AbstractPager scratchPager;

            if (requestedSize != null)
            {
                try
                {
                    scratchPager =
                        _options.CreateScratchPager(StorageEnvironmentOptions.ScratchBufferName(_currentScratchNumber),
                                                    requestedSize.Value);
                }
                catch (Exception)
                {
                    // this can fail because of disk space issue, let us just ignore it
                    // we'll allocate the minimum amount in a bit anyway
                    return(NextFile(minSize, null));
                }
            }
            else
            {
                scratchPager = _options.CreateScratchPager(StorageEnvironmentOptions.ScratchBufferName(_currentScratchNumber),
                                                           Math.Max(_options.InitialLogFileSize, minSize));
            }

            var scratchFile = new ScratchBufferFile(scratchPager, _currentScratchNumber);
            var item        = new ScratchBufferItem(scratchFile.Number, scratchFile);

            AddScratchBufferFile(item);

            _scratchSpaceMonitor.Increase(item.File.NumberOfAllocatedPages * Constants.Storage.PageSize);

            return(item);
        }