Task IFileSet.FinalizeTransaction(ITransaction transaction) { TransactionDetail transactionDetail; lock (_transactions) { if (!_transactions.TryGetValue(transaction, out transactionDetail)) { return(Task.CompletedTask); } _transactions.Remove(transaction); } // TODO: needs to be a single thread with a queue to ensure transactions are committed in order // TODO: maybe group updates by page across multiple transactions var task = Task.Run(() => { var updatesByPage = transactionDetail.PendingUpdates .OrderBy(u => u.PageNumber) .ThenBy(u => u.SequenceNumber); IPage page = null; ulong filePageNumber; int fileIndex; foreach (var update in updatesByPage) { if (page == null || page.PageNumber != update.PageNumber) { if (page != null) { GetPageLocation(page.PageNumber, out filePageNumber, out fileIndex); _dataFiles[fileIndex].Write(filePageNumber, page.Data); page.Dispose(); } page = _pagePool.Get(update.PageNumber); GetPageLocation(update.PageNumber, out filePageNumber, out fileIndex); _dataFiles[fileIndex].Read(filePageNumber, page.Data); } update.Data.CopyTo(page.Data, update.Offset); } if (page != null) { GetPageLocation(page.PageNumber, out filePageNumber, out fileIndex); _dataFiles[fileIndex].Write(filePageNumber, page.Data); page.Dispose(); } _logFiles[transactionDetail.LogFileIndex].CommitComplete(transactionDetail.LogFileOffset); }); return(task); }
/// <inheritdoc/> public void NavTo(Type pageType) { if (disposedValue) { throw new ObjectDisposedException(nameof(PageNavigator)); } if (pageType is null) { throw new ArgumentNullException(nameof(pageType)); } IPage page = Dispatcher.Invoke(() => (IPage)ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, pageType)); if (page is not Page pg) { throw new ArgumentException("invalid type", nameof(pageType)); } if (!TryNavTo(pg)) { page.Dispose(); } }
public void Dispose() { lock (lockToken) { page.Dispose(); } }
protected override void Dispose(bool disposing) { if (disposing) { p.Dispose(); } base.Dispose(disposing); }
protected override void Dispose(bool disposing) { if (disposing) { pageRepository.Dispose(); pageGroupRepository.Dispose(); } base.Dispose(disposing); }
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 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(); } } }