示例#1
0
        /// <summary>
        /// write transaction's raw page data into journal. returns write page position
        /// </summary>
        public long Write(LowLevelTransaction tx, IntPtr[] pages, LazyTransactionBuffer lazyTransactionScratch, int uncompressedPageCount)
        {
            var ptt          = new Dictionary <long, PagePosition>(NumericEqualityComparer.Instance);
            var unused       = new HashSet <PagePosition>();
            var pageWritePos = _writePage;

            UpdatePageTranslationTable(tx, unused, ptt);

            lock (_locker)
            {
                _writePage += pages.Length;
                _pageTranslationTable.SetItems(tx, ptt);

                Debug.Assert(!_unusedPages.Any(unused.Contains));
                _unusedPages.AddRange(unused);
            }

            var position = pageWritePos * tx.Environment.Options.PageSize;

            if (tx.IsLazyTransaction == false && (lazyTransactionScratch == null || lazyTransactionScratch.HasDataInBuffer() == false))
            {
                _journalWriter.WriteGather(position, pages);
            }
            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)
                {
                    lazyTransactionScratch.WriteBufferToFile(this, tx);
                }
                else
                {
                    lazyTransactionScratch.EnsureHasExistingReadTransaction(tx);
                }
            }

            return(pageWritePos);
        }
        public void WriteToJournal(LowLevelTransaction tx, int pageCount)
        {
            var pages = CompressPages(tx, pageCount, _compressionPager);

            if (tx.IsLazyTransaction && _lazyTransactionBuffer == null)
            {
                _lazyTransactionBuffer = new LazyTransactionBuffer(_env.Options);
            }

            if (CurrentFile == null || CurrentFile.AvailablePages < pages.Length)
            {
                _lazyTransactionBuffer?.WriteBufferToFile(CurrentFile, tx);
                CurrentFile = NextFile(pages.Length);
            }

            CurrentFile.Write(tx, pages, _lazyTransactionBuffer, pageCount);

            if (CurrentFile.AvailablePages == 0)
            {
                _lazyTransactionBuffer?.WriteBufferToFile(CurrentFile, tx);
                CurrentFile = null;
            }
        }
示例#3
0
        /// <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));
        }
示例#4
0
        /// <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);
            }
        }
示例#5
0
        /// <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);
            }
        }
示例#6
0
        /// <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);
            }
        }