示例#1
0
        private byte[] FetchBlock(long index)
        {
            if (_blockCache.ContainsKey(index))
            {
                return(_blockCache[index]);
            }

            var result   = new byte[_blockLength];
            var position = _blockLength + index * _blockLength;

            if (position == _fileStream.Length)
            {
                return(result);
            }

            _fileStream.Seek(position, SeekOrigin.Begin);
            _fileStream.BlockingRead(result);

            _blockCache[index] = result;
            return(result);
        }
示例#2
0
        private void Vacuum()
        {
            // here we get all free page indexes and allocations
            var freePageIndexes = _pagemap.FreePageIndexes;

            var freePageData = freePageIndexes.Select(freePageIndex =>
                                                      new Tuple <long, long>(_pagemap.GetPageAllocation(freePageIndex), freePageIndex)).ToList();

            // sort allocations
            freePageData.Sort((p1, p2) => p1.Item1.CompareTo(p2.Item1));

            var reallocatedPageBytes = new byte[_pageSize];

            // reallocate pages at the end of storage file
            while (freePageData.Any())
            {
                long lastPageIndex = _pagemap.ReadLastPageIndex();

                // compute last page allocation
                long lastPageAllocation = _storageStream.Length - _pageSize;
                if (freePageData.All(t => t.Item1 != lastPageAllocation))
                {
                    // last page is occupied
                    // read its content
                    _storageStream.Seek(-_pageSize, SeekOrigin.End);
                    _storageStream.BlockingRead(reallocatedPageBytes);

                    var firstFreePage     = freePageData[0];
                    var newPageAllocation = firstFreePage.Item1;
                    freePageData.RemoveAt(0);

                    // write a page content to new place
                    _storageStream.Seek(newPageAllocation, SeekOrigin.Begin);
                    _storageStream.Write(reallocatedPageBytes, 0, _pageSize);

                    // write an allocation marker of reallocated page
                    _pagemap.WritePageAllocation(lastPageIndex, newPageAllocation);

                    // write an allocation marker of first free page
                    _pagemap.WritePageAllocation(firstFreePage.Item2, -1);

                    // write a disk-to-virtual entry of reallocated page
                    _pagemap.WritePageIndex(lastPageIndex, newPageAllocation);
                }
                else
                {
                    // last page is empty
                    _pagemap.WritePageAllocation(lastPageIndex, -1);

                    freePageData.RemoveAll(t => t.Item1 == lastPageAllocation);
                }

                // truncate pagemap
                _pagemap.TruncateLastPageIndex();

                // truncate storage file
                _storageStream.SetLength(_storageStream.Length - _pageSize);
            }

            // clear free page indexes
            _pagemap.ClearFreePageMarkers();

            Flush(_storageStream);
            _pagemap.Flush();
        }