/// <summary> /// This is used during the commit of a transaction. It takes all the new /// page versions that were constructed during the commit merge and adds them /// to a dictionary of pages /// </summary> /// <param name="pages">The dictionary of pages to add to</param> public void AddToPages(PageHeadCollection pages) { foreach (var pageVersionElement in _pageVersions) { var pageVersion = pageVersionElement.Data; var pageNumber = pageVersion.Page.PageNumber; var pageHead = pages.GetPageHead(pageNumber, CacheHints.ForUpdate); pageHead.AddVersion(pageVersion); } }
public void AddUpdates(IEnumerable <PageUpdate> updates, PageHeadCollection pages) { EnsureUpdates(); var start = Updates.Count; int end; lock (Updates) { Updates.AddRange(updates.OrderBy(u => u.SequenceNumber).Select(u => { u.SequenceNumber += (uint)start; return(u); })); end = Updates.Count; } for (var i = start; i < end; i++) { PageUpdate update; lock (Updates) update = Updates[i]; IPage modifiedPage = null; try { lock (Transaction) { modifiedPage = GetModifiedPage(update.PageNumber); if (modifiedPage == null) { modifiedPage = _pagePool.Get(update.PageNumber); var pageHead = pages.GetPageHead(update.PageNumber, CacheHints.ForUpdate); using (var originalPage = pageHead.GetVersion(Root.Transaction.BeginVersionNumber)) originalPage.Data.CopyTo(modifiedPage.Data, 0); SetModifiedPage(modifiedPage); } update.Data.CopyTo(modifiedPage.Data, update.Offset); } } finally { modifiedPage.Dispose(); } } }
public PageCache( IFileSet fileSet, IDatabase database, IPagePoolFactory pagePoolFactory, IStartupLog startupLog, IErrorLog errorLog) { _startupLog = startupLog; _errorLog = errorLog; _fileSet = fileSet; _database = database; startupLog.WriteLine("Creating a new page cache for " + _fileSet); _pagePool = pagePoolFactory.Create(fileSet.PageSize); _pages = new PageHeadCollection(fileSet, startupLog, errorLog, _pagePool); _versions = new VersionHeadCollection(startupLog, errorLog, database); _transactions = new TransactionHeadCollection(startupLog, errorLog, _pagePool); }
public void Update(ITransaction transaction, IEnumerable <PageUpdate> updates, PageHeadCollection pages) { if (transaction == null) { IPage page = null; foreach (var update in updates.OrderBy(u => u.PageNumber).ThenBy(u => u.SequenceNumber)) { if (page == null || page.PageNumber != update.PageNumber) { if (page != null) { page.Dispose(); } page = pages.GetPageHead(update.PageNumber, CacheHints.ForUpdate).GetVersion(null); } update.Data.CopyTo(page.Data, update.Offset); } if (page != null) { page.Dispose(); } return; } TransactionHead transactionHead; lock (_transactions) if (!_transactions.TryGetValue(transaction.TransactionId, out transactionHead)) { throw new FileLayerException("You can not apply updates to a transaction context before the transaction has begun or after it has ended"); } transactionHead.AddUpdates(updates, pages); }
public IPage GetPage(ITransaction transaction, ulong pageNumber, CacheHints hints, PageHeadCollection pages) { PageHead pageHead; if (transaction == null) { pageHead = pages.GetPageHead(pageNumber, hints); return(pageHead == null ? null : pageHead.GetVersion(null)); } TransactionHead transactionHead; lock (_transactions) if (!_transactions.TryGetValue(transaction.TransactionId, out transactionHead)) { throw new FileLayerException("You can not get pages for a transaction until you begin the transaction"); } var modifiedPage = transactionHead.GetModifiedPage(pageNumber); if (modifiedPage != null) { return(modifiedPage); } pageHead = pages.GetPageHead(pageNumber, hints); return(pageHead == null ? null : pageHead.GetVersion(transactionHead.Root.Transaction.BeginVersionNumber)); }