public void ExitLatch(PagePosition page) { if (LatchLocks.Remove(page, out var latchLock)) { latchLock.Dispose(); } }
public PageContext CreateNextPageContextForCell(PagePosition currentPagePosition, GridPosition position) { var rowPageContext = this.GetOrCreateNextPageContext(currentPagePosition); var horizontalSpace = this.CalculateHorizontalCellSpace(position); return(rowPageContext.Crop(horizontalSpace)); }
private void UpdatePageTranslationTable(Transaction tx, List <PageFromScratchBuffer> txPages, HashSet <PagePosition> unused, Dictionary <long, PagePosition> ptt) { for (int index = 1; index < txPages.Count; index++) { var txPage = txPages[index]; var scratchPage = tx.Environment.ScratchBufferPool.ReadPage(txPage.PositionInScratchBuffer); var pageNumber = ((PageHeader *)scratchPage.Base)->PageNumber; PagePosition value; if (_pageTranslationTable.TryGetValue(tx, pageNumber, out value)) { unused.Add(value); } PagePosition pagePosition; if (ptt.TryGetValue(pageNumber, out pagePosition)) { unused.Add(pagePosition); } ptt[pageNumber] = new PagePosition { ScratchPos = txPage.PositionInScratchBuffer, JournalPos = -1, // needed only during recovery and calculated there TransactionId = tx.Id, JournalNumber = Number }; } }
private PageContext CreateContextForPagePosition( PagePosition pagePosition, Rectangle occupiedRegion, double spaceAfterPrevious, Func <PageNumber, IPage> pageFactory) { var page = pageFactory(pagePosition.PageNumber); var columnSpace = _columnsConfiguration.CalculateColumnSpace(pagePosition.PageColumnIndex); var region = page .GetContentRegion() .CropHorizontal(columnSpace.X, columnSpace.Width); var context = new PageContext( pagePosition, region, page.DocumentVariables); var cropTop = occupiedRegion.BottomY == 0 ? spaceAfterPrevious : occupiedRegion.BottomY + spaceAfterPrevious - page.Margin.Top; // TODO: check -0.001 context = context.CropFromTop(Math.Min(cropTop, context.Region.Height - 0.001)); return(context); }
public File(int id, FileStream stream) { Id = id; Root = new PagePosition(id, 0); Latch = new LatchEntry(this); Stream = stream ?? throw new ArgumentNullException(nameof(stream)); }
/** * Calculates a screen rect in normalized screen space coordinates in one of the 'standard' Page positions (top, middle, bottom). */ public static ScreenRect CalcScreenRect(Vector2 pageScale, PagePosition pagePosition) { float width = Mathf.Clamp01(pageScale.x); float height = Mathf.Clamp01(pageScale.y); ScreenRect screenRect = new ScreenRect(); switch (pagePosition) { case PagePosition.Top: screenRect.x1 = 0.5f - width * 0.5f; screenRect.x2 = 0.5f + width * 0.5f; screenRect.y1 = 0f; screenRect.y2 = height; break; case PagePosition.Middle: screenRect.x1 = 0.5f - width * 0.5f; screenRect.x2 = 0.5f + width * 0.5f; screenRect.y1 = 0.5f - height * 0.5f; screenRect.y2 = 0.5f + height * 0.5f; break; case PagePosition.Bottom: screenRect.x1 = 0.5f - width * 0.5f; screenRect.x2 = 0.5f + width * 0.5f; screenRect.y1 = 1f - Mathf.Clamp01(height); screenRect.y2 = 1; break; } return(screenRect); }
private HeaderFooter ChooseHeaderFooter(HeadersFooters hfs, PagePosition pagePos) { if (hfs == null) { return(null); } PageSetup pageSetup = this.currentSection.PageSetup; if (pagePos == PagePosition.First) { if (pageSetup.DifferentFirstPageHeaderFooter) { return((HeaderFooter)hfs.GetValue("FirstPage", GV.ReadOnly)); } } if (pagePos == PagePosition.Even || this.currentPage % 2 == 0) { if (pageSetup.OddAndEvenPagesHeaderFooter) { return((HeaderFooter)hfs.GetValue("EvenPage", GV.ReadOnly)); } } return((HeaderFooter)hfs.GetValue("Primary", GV.ReadOnly)); }
void FormatHeadersFooters() { HeadersFooters headers = (HeadersFooters)this.currentSection.GetValue("Headers", GV.ReadOnly); if (headers != null) { PagePosition pagePos = CurrentPagePosition; HeaderFooterPosition hfp = new HeaderFooterPosition(this.sectionNumber, pagePos); if (!this.formattedHeaders.ContainsKey(hfp)) { FormatHeader(hfp, ChooseHeaderFooter(headers, pagePos)); } } HeadersFooters footers = (HeadersFooters)this.currentSection.GetValue("Footers", GV.ReadOnly); if (footers != null) { PagePosition pagePos = CurrentPagePosition; HeaderFooterPosition hfp = new HeaderFooterPosition(this.sectionNumber, pagePos); if (!this.formattedFooters.ContainsKey(hfp)) { FormatFooter(hfp, ChooseHeaderFooter(footers, pagePos)); } } }
private void UpdatePageTranslationTable(Transaction tx, HashSet <PagePosition> unused, Dictionary <long, PagePosition> ptt) { var txPages = tx.GetTransactionPages(); foreach (var freedPageNumber in tx.GetFreedPagesNumbers()) { // set freed page marker - note it can be overwritten below by later allocation ptt[freedPageNumber] = new PagePosition { ScratchPos = -1, JournalPos = -1, ScratchNumber = -1, TransactionId = tx.Id, JournalNumber = Number, IsFreedPageMarker = true }; } for (int index = 1; index < txPages.Count; index++) { var txPage = txPages[index]; var scratchPage = tx.Environment.ScratchBufferPool.ReadPage(txPage.ScratchFileNumber, txPage.PositionInScratchBuffer); var pageNumber = scratchPage.PageNumber; PagePosition value; if (_pageTranslationTable.TryGetValue(tx, pageNumber, out value)) { value.UnusedInPTT = true; unused.Add(value); } PagePosition pagePosition; if (ptt.TryGetValue(pageNumber, out pagePosition) && pagePosition.IsFreedPageMarker == false) { unused.Add(pagePosition); } ptt[pageNumber] = new PagePosition { ScratchPos = txPage.PositionInScratchBuffer, ScratchNumber = txPage.ScratchFileNumber, JournalPos = -1, // needed only during recovery and calculated there TransactionId = tx.Id, JournalNumber = Number }; } foreach (var freedPage in tx.GetUnusedScratchPages()) { unused.Add(new PagePosition { ScratchPos = freedPage.PositionInScratchBuffer, ScratchNumber = freedPage.ScratchFileNumber, JournalPos = -1, // needed only during recovery and calculated there TransactionId = tx.Id, JournalNumber = Number }); } }
public bool TryGetValue(Transaction tx, long page, out PagePosition value) { ImmutableAppendOnlyList <PagePosition> list; if (_values.TryGetValue(page, out list) == false) { value = null; return(false); } for (int i = list.Count - 1; i >= 0; i--) { var it = list[i]; if (it.TransactionId > tx.Id) { continue; } if (it.IsFreedPageMarker) { break; } value = it; Debug.Assert(value != null); return(true); } // all the current values are _after_ this transaction started, so it sees nothing value = null; return(false); }
/// <summary> /// Gets a formatted headerfooter object for footer of the given page. /// </summary> /// <param name="page">The page the footer shall appear on.</param> /// <returns>The required footer, null if none exists to render.</returns> internal FormattedHeaderFooter GetFormattedFooter(int page) { PagePosition pagePos = page % 2 == 0 ? PagePosition.Even : PagePosition.Odd; FieldInfos fieldInfos = this.pageFieldInfos[page]; if (page == 1) { pagePos = PagePosition.First; } else //page > 1 { if (IsEmptyPage(page - 1)) // these empty pages only occur between sections. { pagePos = PagePosition.First; } else { FieldInfos prevFieldInfos = this.pageFieldInfos[page - 1]; if (fieldInfos.section != prevFieldInfos.section) { pagePos = PagePosition.First; } } } HeaderFooterPosition hfp = new HeaderFooterPosition(fieldInfos.section, pagePos); if (this.formattedFooters.ContainsKey(hfp)) { return(this.formattedFooters[hfp]); } return(null); }
/// <summary> /// Gets a formatted headerfooter object for footer of the given page. /// </summary> /// <param name="page">The physical page the footer shall appear on.</param> /// <returns>The required footer, null if none exists to render.</returns> public FormattedHeaderFooter GetFormattedFooter(int page) { FieldInfos fieldInfos = _pageFieldInfos[page]; int logicalPage = fieldInfos.DisplayPageNr; PagePosition pagePos = logicalPage % 2 == 0 ? PagePosition.Even : PagePosition.Odd; if (page == 1) { pagePos = PagePosition.First; } else //page > 1 { if (IsEmptyPage(page - 1)) // these empty pages only occur between sections. { pagePos = PagePosition.First; } else { FieldInfos prevFieldInfos = _pageFieldInfos[page - 1]; if (fieldInfos.Section != prevFieldInfos.Section) { pagePos = PagePosition.First; } } } HeaderFooterPosition hfp = new HeaderFooterPosition(fieldInfos.Section, pagePos); if (_formattedFooters.ContainsKey(hfp)) { return(_formattedFooters[hfp]); } return(null); }
/// <summary> /// is other's transaction has held the recrod's lock and conflict with the ctx-lock /// </summary> /// <param name="ctx"></param> /// <returns></returns> private bool IsOthersHeldOrWaitConflictRecLock(Transaction tx, PagePosition page, int slot, LockFlags flags, LockEntry endEntry = null) { var locks = RecLocks.GetValueOrDefault(page); if (locks == null) { return(false); } for (var node = locks.First; node != null; node = node.Next) { var entry = node.Value; if (entry == endEntry) { break; } if (entry.Transaction == tx || entry.GetBit(slot) == 0) { continue; } if (entry.IsExclusive || flags.IsExclusive()) { return(true); } } return(false); }
public bool TryGetValue(LowLevelTransaction tx, long page, out PagePosition value) { if (_values.TryGetValue(page, out var bufferHolder) == false) { value = null; return(false); } var bufferStart = bufferHolder.Start; var bufferPagePositions = bufferHolder.PagePositions; for (int i = bufferHolder.End - 1; i >= bufferStart; i--) { var position = bufferPagePositions[i]; if (position == null || position.TransactionId > tx.Id) { continue; } if (position.IsFreedPageMarker) { break; } value = position; Debug.Assert(value != null); return(true); } // all the current values are _after_ this transaction started, so it sees nothing value = null; return(false); }
public PageDesignContent(PagePosition pos) : base() { if (pos == null) { throw new ArgumentNullException(); } if (string.IsNullOrEmpty(pos.PagePositionId)) { //pos.PagePositionId = Guid.NewGuid().ToString(); pos.PagePositionId = UniqueIdGenerator.GetInstance().GetBase32UniqueId(5); } this.Position = pos; //this.TagName = "li"; this.ClassName = "pagedesign-content"; this.Parameter.Add("Name", PageDesignContent.Code(this.ToString())); this.Parameter.Add("PagePositionId", PageDesignContent.Code(pos.PagePositionId)); this.Parameter.Add("Order", pos.Order.ToString()); this.Parameter.Add("Type", this.GetTypeKey()); }
public void PushLatch(PagePosition page, LatchScope scope) { if (!LatchLocks.TryAdd(page, scope)) { throw new InvalidOperationException($"latch for {page} has already exists!"); } }
/// <summary> /// 获取缓冲项 /// </summary> /// <param name="pos"></param> /// <param name="flags"></param> /// <returns></returns> public BufferEntry GetEntry(PagePosition pos, BufferSeekFlags flags = BufferSeekFlags.None) { //获取或者新分配(创建)一个Buffer var buffer = GetOrCreateEntry(pos, flags); if (buffer == null) { return(buffer); } if (buffer.State == BufferState.NoneLoading) { //新buffer,未加载,加载页面,此时一定是自己获取了写锁 LoadBufferPage(buffer); lock (SyncRoot) { AddLRUEntry(buffer); return(buffer); } } return(buffer); }
/// <summary> /// 获取或创建页面缓冲 /// </summary> /// <param name="pos"></param> /// <param name="flags"></param> /// <returns></returns> public BufferEntry GetOrCreateEntry(PagePosition pos, BufferSeekFlags flags) { //缓冲区锁 Monitor.Enter(SyncRoot); //对应页的buffer不存在,创建,获取写锁(很快)阻塞读,释放缓冲区锁,返回去读取 if (!Buffers.TryGetValue(pos, out var buffer)) { buffer = CreateEntry(pos); buffer.Count++; buffer.Latch.EnterWriteScope(); Buffers[pos] = buffer; Monitor.Exit(SyncRoot); return(buffer); } //buffer对应的页是无须加载的状态,增加引用计数,移动LRU,返回 if (buffer.State != BufferState.NoneLoading) { buffer.Count++; if (!flags.HasFlag(BufferSeekFlags.NoLRU)) { MoveLRUEntry(buffer); } Monitor.Exit(SyncRoot); return(buffer); } //不等待页面加载,不增加引用计数 if (flags.HasFlag(BufferSeekFlags.NoWait)) { Monitor.Exit(SyncRoot); return(null); } //页面未加载,释放缓冲区锁 buffer.Count++; Monitor.Exit(SyncRoot); //等待加载完成 buffer.Latch.EnterReadScope(); buffer.Latch.ExitReadScope(); //加缓冲区锁,移动LRUList Monitor.Enter(SyncRoot); if (!flags.HasFlag(BufferSeekFlags.NoLRU)) { MoveLRUEntry(buffer); } Monitor.Exit(SyncRoot); return(buffer); }
public void AddFlushEntry(PagePosition pos) { lock (SyncRoot) { var buffer = GetEntry(pos); AddFlushEntry(buffer); } }
private BufferEntry CreateEntry(PagePosition pos, BufferState state = BufferState.NoneLoading) { if (Buffers.Count >= Options.LRULimit) { //Flush } return(new BufferEntry(state, pos)); }
private PageContext OnChildPageContextRequest( PagePosition pagePosition, Func <PageNumber, IPage> pageFactory) { var nextPosition = pagePosition.Next(); var context = this.CreateContextForPagePosition(nextPosition, Rectangle.Empty, 0, pageFactory); return(context); }
public PageContext( PagePosition pagePosition, Rectangle region, DocumentVariables variables) { this.Region = region; this.PagePosition = pagePosition; this.PageVariables = new PageVariables(pagePosition.PageNumber, variables.TotalPages); this.TopLeft = new DocumentPosition(pagePosition, this.Region.TopLeft); }
public override void Prepare(IPage page) { var pagePosition = new PagePosition(page.PageNumber); var headerRegion = new Rectangle( this.PageMargin.Left, this.PageMargin.Header, page.Configuration.Width - this.PageMargin.HorizontalMargins, this.PageMargin.MinimalHeaderHeight); this.SetPageRegion(new PageRegion(pagePosition, headerRegion)); }
public override void Prepare(IPage page) { var pagePosition = new PagePosition(page.PageNumber); var footerRegion = new Rectangle( this.PageMargin.Left, page.Configuration.Height - this.PageMargin.Bottom, page.Configuration.Width - this.PageMargin.HorizontalMargins, this.PageMargin.FooterHeight); this.SetPageRegion(new PageRegion(pagePosition, footerRegion)); }
public void WriteBTreePageReorganize(PagePosition pos) { if (LogEnable) { Logger.Add((byte)LogFlags.BPAGE_REORGANIZE); Logger.AddRange(BitConverter.GetBytes(pos.FileId)); Logger.AddRange(BitConverter.GetBytes(pos.PageNumber)); Modified = true; Modifies.Add(pos); } }
public void WriteFixedBTreeRootInitialized(PagePosition pos) { if (LogEnable) { Logger.Add((byte)LogFlags.FBPAGE_ROOT_INITED); Logger.AddRange(BitConverter.GetBytes(pos.FileId)); Logger.AddRange(BitConverter.GetBytes(pos.PageNumber)); Modified = true; Modifies.Add(pos); } }
public void WriteFixedBTreePageDeleteEntry(PagePosition pos, int index) { if (LogEnable) { Logger.Add((byte)LogFlags.FBPAGE_DELETE_ENTRY); Logger.AddRange(BitConverter.GetBytes(pos.FileId)); Logger.AddRange(BitConverter.GetBytes(pos.PageNumber)); Logger.AddRange(BitConverter.GetBytes((ushort)index)); Modified = true; Modifies.Add(pos); } }
private PageContext GetOrCreateNextPageContext(PagePosition currentPagePosition) { var nextPageContext = _pageContexts.FirstOrDefault(pc => pc.PagePosition == currentPagePosition.Next()); if (nextPageContext != null) { return(nextPageContext); } nextPageContext = this.PageContextFactory(currentPagePosition); _pageContexts.Add(nextPageContext); return(nextPageContext); }
public override void Prepare(IPage page) { var pagePosition = new PagePosition(page.PageNumber); var region = page .GetPageRegion() .Crop(page.Margin.Top, this.PageMargin.Right, this.PageMargin.Footer, this.PageMargin.Left); var context = new PageContext(pagePosition, region, page.DocumentVariables); PageContext childContextRequest(PagePosition pagePosition, PageContextElement child) => this.OutOfPageContextFactory(page); var absoluteHeight = page.Configuration.Height; var spaceAfterPrevious = 0.0; foreach (var child in _childs) { child.Prepare(context, childContextRequest); var lastRegion = child.LastPageRegion; spaceAfterPrevious = child.CalculateSpaceAfter(_childs); var cropFromTop = Math.Min(lastRegion.Region.Height + spaceAfterPrevious, absoluteHeight - 0.001); context = context.CropFromTop(cropFromTop); } var boundingRegion = _childs .SelectMany(c => c.PageRegions.Where(pr => pr.PagePosition.PageNumber == page.PageNumber)) .UnionPageRegions(Margin.None) .ToArray() .Single(); var offsetY = page.Configuration.Height - page.Margin.Top - Math.Max(boundingRegion.Region.Height, this.PageMargin.FooterHeight) - this.PageMargin.Footer; _pageOffset = new Point(0, offsetY); foreach (var child in _childs) { child.SetPageOffset(_pageOffset); } if (boundingRegion.Region.Height < this.PageMargin.FooterHeight) { var resized = new Rectangle(boundingRegion.Region.TopLeft, boundingRegion.Region.Width, this.PageMargin.FooterHeight); boundingRegion = new PageRegion(boundingRegion.PagePosition, resized); } this.ResetPageRegions(new[] { boundingRegion }); }
public static IHtmlString Parse(PagePosition position, Site site) { if (position == null) { return(null); } var view = position as ViewPosition; if (view != null) { return(new PageDesignViewContent(view)); } var module = position as ModulePosition; if (module != null) { return(new PageDesignModuleContent(module)); } var html = position as HtmlPosition; if (html != null) { return(new PageDesignHtmlContent(html)); } var folder = position as ContentPosition; if (folder != null) { return(new PageDesignFolderContent(folder)); } var htmlBlock = position as HtmlBlockPosition; if (htmlBlock != null) { var entry = htmlBlock.GetHtmlBlock(site); if (entry != null) { return(new PageDesignHtmlBlockContent(htmlBlock, entry.Body)); } } if (position is ProxyPosition) { return(new PageDesignProxyContent((ProxyPosition)position)); } return(new HtmlString("")); }
public MvcHtmlString Compose(PagePosition position) { var action = _html.ViewContext.RouteData.Values["Action"] as string; // foreach (var child in _childActions) { if (child.Position == position && (child.Template.ToString() == action || child.Template == PageTemplate.All)) { _html.RenderAction(child.Method, child.Controller); } } return MvcHtmlString.Create(""); }
internal HeaderFooterPosition(int sectionNr, PagePosition pagePosition) { this.sectionNr = sectionNr; this.pagePosition = pagePosition; }
private void UpdatePageTranslationTable(Transaction tx, HashSet<PagePosition> unused, Dictionary<long, PagePosition> ptt) { var txPages = tx.GetTransactionPages(); foreach (var freedPageNumber in tx.GetFreedPagesNumbers()) { // set freed page marker - note it can be overwritten below by later allocation ptt[freedPageNumber] = new PagePosition { ScratchPos = -1, JournalPos = -1, TransactionId = tx.Id, JournalNumber = Number, IsFreedPageMarker = true }; } for (int index = 1; index < txPages.Count; index++) { var txPage = txPages[index]; var scratchPage = tx.Environment.ScratchBufferPool.ReadPage(txPage.PositionInScratchBuffer); var pageNumber = scratchPage.PageNumber; PagePosition value; if (_pageTranslationTable.TryGetValue(tx, pageNumber, out value)) unused.Add(value); PagePosition pagePosition; if (ptt.TryGetValue(pageNumber, out pagePosition) && pagePosition.IsFreedPageMarker == false) unused.Add(pagePosition); ptt[pageNumber] = new PagePosition { ScratchPos = txPage.PositionInScratchBuffer, JournalPos = -1, // needed only during recovery and calculated there TransactionId = tx.Id, JournalNumber = Number }; } foreach (var freedPage in tx.GetUnusedScratchPages()) { unused.Add(new PagePosition { ScratchPos = freedPage.PositionInScratchBuffer, JournalPos = -1, // needed only during recovery and calculated there TransactionId = tx.Id, JournalNumber = Number }); } }
protected bool Equals(PagePosition other) { return ScratchPos == other.ScratchPos && TransactionId == other.TransactionId && JournalNumber == other.JournalNumber && IsFreedPageMarker == other.IsFreedPageMarker && ScratchNumber == other.ScratchNumber; }
internal HeaderFooterPosition(int sectionNr, PagePosition pagePosition) { _sectionNr = sectionNr; _pagePosition = pagePosition; }
private HeaderFooter ChooseHeaderFooter(HeadersFooters hfs, PagePosition pagePos) { if (hfs == null) return null; PageSetup pageSetup = _currentSection.PageSetup; if (pagePos == PagePosition.First) { if (pageSetup.DifferentFirstPageHeaderFooter) return (HeaderFooter)hfs.GetValue("FirstPage", GV.ReadOnly); } if (pagePos == PagePosition.Even || _shownPageNumber/*_currentPage*/ % 2 == 0) { if (pageSetup.OddAndEvenPagesHeaderFooter) return (HeaderFooter)hfs.GetValue("EvenPage", GV.ReadOnly); } return (HeaderFooter)hfs.GetValue("Primary", GV.ReadOnly); }
private unsafe void UpdatePageTranslationTable(Transaction tx, List<PageFromScratchBuffer> txPages, HashSet<PagePosition> unused, Dictionary<long, PagePosition> ptt) { for (int index = 1; index < txPages.Count; index++) { var txPage = txPages[index]; var scratchPage = tx.Environment.ScratchBufferPool.ReadPage(txPage.PositionInScratchBuffer); var pageNumber = ((PageHeader*)scratchPage.Base)->PageNumber; PagePosition value; if (_pageTranslationTable.TryGetValue(tx, pageNumber, out value)) unused.Add(value); if (ptt.ContainsKey(pageNumber)) unused.Add(ptt[pageNumber]); ptt[pageNumber] = new PagePosition { ScratchPos = txPage.PositionInScratchBuffer, JournalPos = -1, // needed only during recovery and calculated there TransactionId = tx.Id, JournalNumber = Number }; } }
protected bool Equals(PagePosition other) { return ScratchPos == other.ScratchPos && JournalPos == other.JournalPos && TransactionId == other.TransactionId && JournalNumber == other.JournalNumber; }
private void UpdatePageTranslationTable(Transaction tx, HashSet<PagePosition> unused, Dictionary<long, PagePosition> ptt) { foreach (var freedPageNumber in tx.GetFreedPagesNumbers()) { // set freed page marker - note it can be overwritten below by later allocation ptt[freedPageNumber] = new PagePosition { ScratchPos = -1, ScratchNumber = -1, TransactionId = tx.Id, JournalNumber = Number, IsFreedPageMarker = true }; } var txPages = tx.GetTransactionPages(); foreach ( var txPage in txPages ) { var scratchPage = tx.Environment.ScratchBufferPool.ReadPage(txPage.ScratchFileNumber, txPage.PositionInScratchBuffer); var pageNumber = scratchPage.PageNumber; PagePosition value; if (_pageTranslationTable.TryGetValue(tx, pageNumber, out value)) { value.UnusedInPTT = true; unused.Add(value); } PagePosition pagePosition; if (ptt.TryGetValue(pageNumber, out pagePosition) && pagePosition.IsFreedPageMarker == false) unused.Add(pagePosition); ptt[pageNumber] = new PagePosition { ScratchPos = txPage.PositionInScratchBuffer, ScratchNumber = txPage.ScratchFileNumber, TransactionId = tx.Id, JournalNumber = Number }; } foreach (var freedPage in tx.GetUnusedScratchPages()) { unused.Add(new PagePosition { ScratchPos = freedPage.PositionInScratchBuffer, ScratchNumber = freedPage.ScratchFileNumber, TransactionId = tx.Id, JournalNumber = Number }); } }