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); } } }