Esempio n. 1
0
        public static int GetIndexOfFirstMatchingFsmValue(IPage page, FsmValue targetFsm)
        {
            FreeSpaceMapPageHeader header = GetFsmPageHeader(page);
            var content = page.Content;
            var length  = content.Length;

            var fsmByte = (byte)targetFsm;

            const int full = ((byte)FsmValue.Full | ((byte)FsmValue.Full << 4));

            for (int i = header.Length; i < length; i++)
            {
                if (content[i] == full)
                {
                    continue;
                }

                var first  = (byte)(0x0F & content[i]);
                var second = (byte)((0xF0 & content[i]) >> 4);

                if (first == fsmByte)
                {
                    return((i - header.Length) * 2);
                }

                if (second == fsmByte)
                {
                    return((i - header.Length) * 2 + 1);
                }
            }

            return(-1);
        }
Esempio n. 2
0
        public static void SetAllFsmValues(IPage page, FsmValue value)
        {
            FreeSpaceMapPageHeader header = GetFsmPageHeader(page);

            byte byteValue = (byte)((byte)value | ((byte)value << 4));

            for (int i = header.Length; i < page.Length; i++)
            {
                page.Content[i] = byteValue;
            }
        }
Esempio n. 3
0
        public static void SetFsmValue(IPage page, int index, FsmValue newValue)
        {
            FreeSpaceMapPageHeader header = GetFsmPageHeader(page);

            if (index < 0 || index > (page.Length - header.Length) * 2)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }

            int  targetIndex = index / 2 + header.Length;
            byte b           = page.Content[targetIndex];

            if (index % 2 == 0)
            {
                b = (byte)((b & 0xF0) | (byte)newValue);
            }
            else
            {
                b = (byte)((b & 0x0F) | ((byte)newValue << 4));
            }

            page.Content[targetIndex] = b;
        }
Esempio n. 4
0
        public void FsmPage()
        {
            int pageSize         = 32768;
            var dummyPageManager = new FileSystemPageManager(pageSize);
            var p = new Page(dummyPageManager, 0, new byte[pageSize]);

            var fsmh = new FreeSpaceMapPageHeader();
            var r    = new Random();

            PageFormatter.InitPage(p, fsmh);
            int fsmEntryCount = PageFormatter.GetFsmEntryCount(p);

            // set all values to "full"
            PageFormatter.SetAllFsmValues(p, FsmValue.Full);

            // check if all values are actually "full"
            for (int i = 0; i < fsmEntryCount; i++)
            {
                Assert.AreEqual(FsmValue.Full, PageFormatter.GetFsmValue(p, i));
            }

            var values = new FsmValue[fsmEntryCount];

            // set and keep random values
            for (int i = 0; i < fsmEntryCount; i++)
            {
                var value = (byte)r.Next((byte)FsmValue.Full + 1);
                PageFormatter.SetFsmValue(p, i, (FsmValue)value);
                values[i] = (FsmValue)value;
            }

            // compare it
            for (int i = 0; i < fsmEntryCount; i++)
            {
                Assert.AreEqual(values[i], PageFormatter.GetFsmValue(p, i));
            }
        }
Esempio n. 5
0
        public void Set(long pageIndex, FsmValue value)
        {
            if (!_isInitialized)
            {
                Init();
            }

            IPage page = GetFsmPageByTargetPageIndex(pageIndex);

            if (page == null)
            {
                // fsm-page is missing for requested page index
                long previousPageIndex = _lastFsmPage.Index;
                var  missingPageCount  = (int)((pageIndex - (_fsmPageCount - _fsmPageIndexes.Count) * _entryPerPage) / _entryPerPage + 1);

                var pages = new List <IPage>(missingPageCount);

                // allocate new pages
                for (int i = 0; i < missingPageCount; i++)
                {
                    pages.Add(_pageManager.CreatePage());
                }

                var baseIndex = PageFormatter.GetBasePageIndex(_lastFsmPage);

                // initialize them
                for (int i = 0; i < missingPageCount; i++)
                {
                    baseIndex += _entryPerPage;
                    InitFsmPage(pages[i],
                                previousPageIndex,
                                i == missingPageCount - 1 ? -1 : pages[i + 1].Index,
                                baseIndex);
                    previousPageIndex = pages[i].Index;
                }

                // and update
                pages.ForEach(_pageManager.UpdatePage);

                // save reference to added pages
                var lastPageHeader = (FreeSpaceMapPageHeader)PageFormatter.GetPageHeader(_lastFsmPage);
                lastPageHeader.NextPageIndex = pages[0].Index;
                lastPageHeader.WriteToPage(_lastFsmPage);
                _pageManager.UpdatePage(_lastFsmPage);

                _lastFsmPage  = null;
                _fsmPageCount = -1;

                Set(pageIndex, value);
            }
            else
            {
                PageFormatter.SetFsmValue(page, (int)pageIndex % _entryPerPage, value);
                _pageManager.UpdatePage(page);

                var fsmValuesToUpdate = _luckyFsmPages.Where(item => item.Value.Page.Index == page.Index).Select(item => item.Key).ToList();

                foreach (var fsmValue in fsmValuesToUpdate)
                {
                    _luckyFsmPages[fsmValue].Page = page;
                }

                if (!_luckyFsmPages.ContainsKey(value))
                {
                    _luckyFsmPages[value] = new LuckyPage {
                        Page = page, LastGoodIndex = pageIndex
                    }
                }
                ;
                else
                {
                    if (_scanned.Contains(value))
                    {
                        _scanned.Remove(value);
                    }
                }
            }
        }
Esempio n. 6
0
        public long GetFreePageIndex(FsmValue value)
        {
            if (!_isInitialized)
            {
                Init();
            }

            // try to find in lucky pages
            if (_luckyFsmPages.ContainsKey(value))
            {
                IPage page = _luckyFsmPages[value].Page;

                var requestedFsmIndex = (int)(_luckyFsmPages[value].LastGoodIndex % _entryPerPage);
                int matchingFsmIndex;

                if (PageFormatter.GetFsmValue(page, requestedFsmIndex) == value)
                {
                    matchingFsmIndex = requestedFsmIndex;
                }
                else
                {
                    matchingFsmIndex = PageFormatter.GetIndexOfFirstMatchingFsmValue(page, value);
                    _luckyFsmPages[value].LastGoodIndex = matchingFsmIndex;
                }

                if (matchingFsmIndex == -1)
                {
                    // page becomes unlucky
                    _luckyFsmPages.Remove(value);
                }
                else
                {
                    return(PageFormatter.GetBasePageIndex(page) + matchingFsmIndex);
                }
            }

            var  currentPageIndex = _firstFsmPageIndex;
            long index            = 0;

            if (_scanned.Contains(value))
            {
                return(-1);
            }

            while (true)
            {
                // sequential scan all fsm pages for specified fsm-value
                var currentPage      = _pageManager.FetchPage(currentPageIndex);
                int matchingFsmIndex = PageFormatter.GetIndexOfFirstMatchingFsmValue(currentPage, value);
                if (matchingFsmIndex == -1)
                {
                    index += _entryPerPage;
                    var header = (FreeSpaceMapPageHeader)PageFormatter.GetPageHeader(currentPage);
                    if (header.NextPageIndex == -1)
                    {
                        _scanned.Add(value);
                        return(-1);
                    }

                    currentPageIndex = header.NextPageIndex;
                }
                else
                {
                    // make found page lucky
                    _luckyFsmPages[value] = new LuckyPage {
                        Page = currentPage, LastGoodIndex = matchingFsmIndex + index
                    };
                    return(index + matchingFsmIndex);
                }
            }
        }