public void AddToBuffer(long position, CompressedPagesResult pages) { NumberOfPages += pages.NumberOfUncompressedPages; if (_firstPositionInJournalFile == null) { _firstPositionInJournalFile = position; // first lazy tx saves position to all lazy tx that comes afterwards } using (var writer = _lazyTransactionPager.BatchWriter()) { writer.Write(_lastUsed4Kbs, pages.NumberOf4Kbs, pages.Base); } _lastUsed4Kbs += pages.NumberOf4Kbs; }
/// <summary> /// write transaction's raw page data into journal /// </summary> public UpdatePageTranslationTableAndUnusedPagesAction Write(LowLevelTransaction tx, CompressedPagesResult pages, LazyTransactionBuffer lazyTransactionScratch) { var ptt = new Dictionary <long, PagePosition>(NumericEqualityComparer.BoxedInstanceInt64); var cur4KbPos = _writePosIn4Kb; Debug.Assert(pages.NumberOf4Kbs > 0); UpdatePageTranslationTable(tx, _unusedPagesHashSetPool, ptt); if (tx.IsLazyTransaction == false && (lazyTransactionScratch == null || lazyTransactionScratch.HasDataInBuffer() == false)) { try { Write(cur4KbPos, pages.Base, pages.NumberOf4Kbs); } catch (Exception e) { _env.Options.SetCatastrophicFailure(ExceptionDispatchInfo.Capture(e)); throw; } } else { if (lazyTransactionScratch == null) { throw new InvalidOperationException("lazyTransactionScratch cannot be null if the transaction is lazy (or a previous one was)"); } var sizeInBytes = _journalWriter.NumberOfAllocated4Kb * 4 * Constants.Size.Kilobyte; int sizeInPages = checked (sizeInBytes / Constants.Storage.PageSize + sizeInBytes % Constants.Storage.PageSize == 0 ? 0 : 1); lazyTransactionScratch.EnsureSize(sizeInPages); lazyTransactionScratch.AddToBuffer(cur4KbPos, pages); // non lazy tx will add itself to the buffer and then flush scratch to journal if (tx.IsLazyTransaction == false || lazyTransactionScratch.NumberOfPages > tx.Environment.ScratchBufferPool.GetAvailablePagesCount() / 2) { try { lazyTransactionScratch.WriteBufferToFile(this, tx); } catch (Exception e) { _env.Options.SetCatastrophicFailure(ExceptionDispatchInfo.Capture(e)); throw; } } else { lazyTransactionScratch.EnsureHasExistingReadTransaction(tx); } } return(new UpdatePageTranslationTableAndUnusedPagesAction(this, tx, ptt, pages.NumberOf4Kbs)); }
/// <summary> /// write transaction's raw page data into journal /// </summary> public void Write(LowLevelTransaction tx, CompressedPagesResult pages, LazyTransactionBuffer lazyTransactionScratch) { var ptt = new Dictionary <long, PagePosition>(NumericEqualityComparer.Instance); var cur4KbPos = _writePosIn4Kb; Debug.Assert(pages.NumberOf4Kbs > 0); UpdatePageTranslationTable(tx, _unusedPagesHashSetPool, ptt); using (_locker2.Lock()) { _writePosIn4Kb += pages.NumberOf4Kbs; Debug.Assert(!_unusedPages.Any(_unusedPagesHashSetPool.Contains)); // We ensure there cannot be duplicates here (disjoint sets). foreach (var item in _unusedPagesHashSetPool) { _unusedPages.Add(item); } } _unusedPagesHashSetPool.Clear(); if (tx.IsLazyTransaction == false && (lazyTransactionScratch == null || lazyTransactionScratch.HasDataInBuffer() == false)) { try { _journalWriter.Write(cur4KbPos, pages.Base, pages.NumberOf4Kbs); } catch (Exception e) { _env.Options.SetCatastrophicFailure(ExceptionDispatchInfo.Capture(e)); throw; } } else { if (lazyTransactionScratch == null) { throw new InvalidOperationException("lazyTransactionScratch cannot be null if the transaction is lazy (or a previous one was)"); } lazyTransactionScratch.EnsureSize(_journalWriter.NumberOfAllocated4Kb); lazyTransactionScratch.AddToBuffer(cur4KbPos, pages); // non lazy tx will add itself to the buffer and then flush scratch to journal if (tx.IsLazyTransaction == false || lazyTransactionScratch.NumberOfPages > tx.Environment.ScratchBufferPool.GetAvailablePagesCount() / 2) { try { lazyTransactionScratch.WriteBufferToFile(this, tx); } catch (Exception e) { _env.Options.SetCatastrophicFailure(ExceptionDispatchInfo.Capture(e)); throw; } } else { lazyTransactionScratch.EnsureHasExistingReadTransaction(tx); } } using (_locker2.Lock()) { _pageTranslationTable.SetItems(tx, ptt); } }
/// <summary> /// write transaction's raw page data into journal /// </summary> public void Write(LowLevelTransaction tx, CompressedPagesResult pages, LazyTransactionBuffer lazyTransactionScratch) { var ptt = new Dictionary <long, PagePosition>(NumericEqualityComparer.BoxedInstanceInt64); var cur4KbPos = _writePosIn4Kb; Debug.Assert(pages.NumberOf4Kbs > 0); UpdatePageTranslationTable(tx, _unusedPagesHashSetPool, ptt); using (_locker2.Lock()) { Debug.Assert(!_unusedPages.Any(_unusedPagesHashSetPool.Contains)); // We ensure there cannot be duplicates here (disjoint sets). foreach (var item in _unusedPagesHashSetPool) { _unusedPages.Add(item); } } _unusedPagesHashSetPool.Clear(); if (tx.IsLazyTransaction == false && (lazyTransactionScratch == null || lazyTransactionScratch.HasDataInBuffer() == false)) { try { _journalWriter.Write(cur4KbPos, pages.Base, pages.NumberOf4Kbs); } catch (Exception e) { _env.Options.SetCatastrophicFailure(ExceptionDispatchInfo.Capture(e)); throw; } } else { if (lazyTransactionScratch == null) { throw new InvalidOperationException("lazyTransactionScratch cannot be null if the transaction is lazy (or a previous one was)"); } lazyTransactionScratch.EnsureSize(_journalWriter.NumberOfAllocated4Kb); lazyTransactionScratch.AddToBuffer(cur4KbPos, pages); // non lazy tx will add itself to the buffer and then flush scratch to journal if (tx.IsLazyTransaction == false || lazyTransactionScratch.NumberOfPages > tx.Environment.ScratchBufferPool.GetAvailablePagesCount() / 2) { try { lazyTransactionScratch.WriteBufferToFile(this, tx); } catch (Exception e) { _env.Options.SetCatastrophicFailure(ExceptionDispatchInfo.Capture(e)); throw; } } else { lazyTransactionScratch.EnsureHasExistingReadTransaction(tx); } } using (_locker2.Lock()) { _pageTranslationTable.SetItems(tx, ptt); // it is important that the last write position will be set // _after_ the PTT update, because a flush that is concurrent // with the write will first get the WritePosIn4KB and then // do the flush based on the PTT. Worst case, we'll flush // more then we need, but won't get into a position where we // think we flushed, and then realize that we didn't. Interlocked.Add(ref _writePosIn4Kb, pages.NumberOf4Kbs); } }
/// <summary> /// write transaction's raw page data into journal /// </summary> public void Write(LowLevelTransaction tx, CompressedPagesResult pages, LazyTransactionBuffer lazyTransactionScratch, int uncompressedPageCount) { var ptt = new Dictionary <long, PagePosition>(NumericEqualityComparer.Instance); var pageWritePos = _writePage; _unusedPagesHashSetPool.Clear(); UpdatePageTranslationTable(tx, _unusedPagesHashSetPool, ptt); lock (_locker) { _writePage += pages.NumberOfPages; Debug.Assert(!_unusedPages.Any(_unusedPagesHashSetPool.Contains)); _unusedPages.AddRange(_unusedPagesHashSetPool); } _unusedPagesHashSetPool.Clear(); var position = pageWritePos * tx.Environment.Options.PageSize; if (tx.IsLazyTransaction == false && (lazyTransactionScratch == null || lazyTransactionScratch.HasDataInBuffer() == false)) { try { _journalWriter.WritePages(position, pages.Base, pages.NumberOfPages); } catch (Exception e) { _env.CatastrophicFailure = ExceptionDispatchInfo.Capture(e); throw; } } else { if (lazyTransactionScratch == null) { throw new InvalidOperationException("lazyTransactionScratch cannot be null if the transaction is lazy (or a previous one was)"); } lazyTransactionScratch.EnsureSize(_journalWriter.NumberOfAllocatedPages); lazyTransactionScratch.AddToBuffer(position, pages, uncompressedPageCount); // non lazy tx will add itself to the buffer and then flush scratch to journal if (tx.IsLazyTransaction == false || lazyTransactionScratch.NumberOfPages > tx.Environment.ScratchBufferPool.GetAvailablePagesCount() / 2) { try { lazyTransactionScratch.WriteBufferToFile(this, tx); } catch (Exception e) { _env.CatastrophicFailure = ExceptionDispatchInfo.Capture(e); throw; } } else { lazyTransactionScratch.EnsureHasExistingReadTransaction(tx); } } lock (_locker) { _pageTranslationTable.SetItems(tx, ptt); } }