예제 #1
0
        /// <summary>
        /// Append an object to the journal wrapped with a JournalEntry
        /// </summary>
        /// <returns>The id of the entry appended</returns>
        public ulong Append(Command item)
        {
            var entry = new JournalEntry <Command>(_nextEntryId, item, item.Timestamp);

            _writer.Write(entry);
            return(_nextEntryId++);
        }
예제 #2
0
        /// <summary>
        /// Append an object to the journal wrapped with a JournalEntry
        /// </summary>
        /// <returns>The id of the entry appended</returns>
        public ulong Append(Command item)
        {
            var ts    = Execution.Current.Now;
            var entry = new JournalEntry <Command>(_nextEntryId, item, ts);

            _writer.Write(entry);
            return(_nextEntryId++);
        }
예제 #3
0
        /// <summary>
        /// Write a buffer of transactions (from lazy, usually) to the file
        /// </summary>
        public void Write(long posBy4Kb, byte *p, int numberOf4Kbs)
        {
            int posBy4Kbs = 0;

            while (posBy4Kbs < numberOf4Kbs)
            {
                var readTxHeader = (TransactionHeader *)(p + (posBy4Kbs * 4 * Constants.Size.Kilobyte));
                var totalSize    = readTxHeader->CompressedSize != -1 ? readTxHeader->CompressedSize +
                                   sizeof(TransactionHeader) : readTxHeader->UncompressedSize + sizeof(TransactionHeader);
                var roundTo4Kb = (totalSize / (4 * Constants.Size.Kilobyte)) +
                                 (totalSize % (4 * Constants.Size.Kilobyte) == 0 ? 0 : 1);
                if (roundTo4Kb > int.MaxValue)
                {
                    MathFailure(numberOf4Kbs);
                }

                // We skip to the next transaction header.
                posBy4Kbs += (int)roundTo4Kb;

                Debug.Assert(readTxHeader->HeaderMarker == Constants.TransactionHeaderMarker);
                _transactionHeaders.Add(*readTxHeader);
            }

            JournalWriter.Write(posBy4Kb, p, numberOf4Kbs);
        }
예제 #4
0
        /// <summary>
        /// Write a buffer of transactions (from lazy, usually) to the file
        /// </summary>
        public void Write(long posBy4Kb, byte *p, int numberOf4Kbs)
        {
            int posBy4Kbs = 0;

            while (posBy4Kbs < numberOf4Kbs)
            {
                var readTxHeader = (TransactionHeader *)(p + (posBy4Kbs * 4 * Constants.Size.Kilobyte));
                var totalSize    = readTxHeader->CompressedSize != -1 ? readTxHeader->CompressedSize +
                                   sizeof(TransactionHeader) : readTxHeader->UncompressedSize + sizeof(TransactionHeader);
                var roundTo4Kb = (totalSize / (4 * Constants.Size.Kilobyte)) +
                                 (totalSize % (4 * Constants.Size.Kilobyte) == 0 ? 0 : 1);
                if (roundTo4Kb > int.MaxValue)
                {
                    MathFailure(numberOf4Kbs);
                }

                // We skip to the next transaction header.
                posBy4Kbs += (int)roundTo4Kb;
                if (_transactionHeaders.Length == _numberOfTransactionHeaders)
                {
                    var temp = ArrayPool <TransactionHeader> .Shared.Rent(_transactionHeaders.Length * 2);

                    Array.Copy(_transactionHeaders, temp, _transactionHeaders.Length);
                    ArrayPool <TransactionHeader> .Shared.Return(_transactionHeaders);

                    _transactionHeaders = temp;
                }
                Debug.Assert(readTxHeader->HeaderMarker == Constants.TransactionHeaderMarker);
                _transactionHeaders[_numberOfTransactionHeaders++] = *readTxHeader;
            }

            JournalWriter.Write(posBy4Kb, p, numberOf4Kbs);
        }
예제 #5
0
 void WriteBackground()
 {
     _closeWaitHandle.Reset();
     while (!_queue.IsCompleted)
     {
         JournalEntry item;
         if (_queue.TryTake(out item, Timeout.Infinite))
         {
             _decoratedWriter.Write(item);
         }
     }
     _closeWaitHandle.Set();
 }
예제 #6
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);
            }
        }
예제 #7
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);
            }
        }