Exemple #1
0
        public Page GetReadOnlyPage(long pageNumber)
        {
            Page p;

            PageFromScratchBuffer value;

            if (_scratchPagesTable.TryGetValue(pageNumber, out value))
            {
                PagerState state = null;
                if (_scratchPagerStates != null)
                {
                    var lastUsed = lastScratchFileUsed;
                    if (lastUsed.FileNumber == value.ScratchFileNumber)
                    {
                        state = lastUsed.State;
                    }
                    else
                    {
                        state = _scratchPagerStates[value.ScratchFileNumber];
                        lastScratchFileUsed = new PagerStateCacheItem(value.ScratchFileNumber, state);
                    }
                }

                p = _env.ScratchBufferPool.ReadPage(value.ScratchFileNumber, value.PositionInScratchBuffer, state);
            }
            else
            {
                p = _journal.ReadPage(this, pageNumber, _scratchPagerStates) ?? _dataPager.Read(pageNumber);
            }

            Debug.Assert(p != null && p.PageNumber == pageNumber, string.Format("Requested ReadOnly page #{0}. Got #{1} from {2}", pageNumber, p.PageNumber, p.Source));

            return(p);
        }
Exemple #2
0
        public static Dictionary <long, JournalFile.PagePosition> GetTransactionToPageTranslation(this TransactionHeader current, IVirtualPager pager, ref int currentPage)
        {
            var tempTransactionPageTranslaction = new Dictionary <long, JournalFile.PagePosition>();

            for (var i = 0; i < current.PageCount; i++)
            {
                Debug.Assert(pager.Disposed == false);

                var page = pager.Read(currentPage);

                tempTransactionPageTranslaction[page.PageNumber] = new JournalFile.PagePosition
                {
                    JournalPos    = currentPage,
                    TransactionId = current.TransactionId
                };

                if (page.IsOverflow)
                {
                    var numOfPages = pager.GetNumberOfOverflowPages(page.OverflowSize);
                    currentPage += numOfPages;
                }
                else
                {
                    currentPage++;
                }
            }
            return(tempTransactionPageTranslaction);
        }
Exemple #3
0
        public void ReadTransactions(IEnumerable <TransactionToShip> shippedTransactions)
        {
            foreach (var transaction in shippedTransactions.OrderBy(x => x.Header.TransactionId))
            {
                ReadFromShippedTransaction(transaction);
            }

            var pageData = new byte *[_pageNumbers.Count];

            _pageNumbers.ForEach(pageNumber => pageData[pageNumber] = _pager.Read(pageNumber).Base);
            RawPageData = pageData;
        }
Exemple #4
0
        public Page GetReadOnlyPage(long pageNumber)
        {
            PageFromScratchBuffer value;
            Page p;

            if (_scratchPagesTable.TryGetValue(pageNumber, out value))
            {
                p = _env.ScratchBufferPool.ReadPage(value.ScratchFileNumber, value.PositionInScratchBuffer, _scratchPagerStates != null ? _scratchPagerStates[value.ScratchFileNumber] : null);
            }
            else
            {
                p = _journal.ReadPage(this, pageNumber, _scratchPagerStates) ?? _dataPager.Read(pageNumber);
            }

            Debug.Assert(p != null && p.PageNumber == pageNumber, string.Format("Requested ReadOnly page #{0}. Got #{1} from {2}", pageNumber, p.PageNumber, p.Source));

            return(p);
        }
Exemple #5
0
        private bool TryReadAndValidateHeader(StorageEnvironmentOptions options, out TransactionHeader *current)
        {
            current = (TransactionHeader *)_pager.Read(_readingPage).Base;

            if (current->HeaderMarker != Constants.TransactionHeaderMarker)
            {
                // not a transaction page,

                // if the header marker is zero, we are probably in the area at the end of the log file, and have no additional log records
                // to read from it. This can happen if the next transaction was too big to fit in the current log file. We stop reading
                // this log file and move to the next one.

                RequireHeaderUpdate = current->HeaderMarker != 0;
                if (RequireHeaderUpdate)
                {
                    options.InvokeRecoveryError(this,
                                                "Transaction " + current->TransactionId +
                                                " header marker was set to garbage value, file is probably corrupted", null);
                }

                return(false);
            }

            ValidateHeader(current, LastTransactionHeader);

            if (current->TxMarker.HasFlag(TransactionMarker.Commit) == false)
            {
                // uncommitted transaction, probably
                RequireHeaderUpdate = true;
                options.InvokeRecoveryError(this,
                                            "Transaction " + current->TransactionId +
                                            " was not committed", null);
                return(false);
            }

            _readingPage++;
            return(true);
        }
Exemple #6
0
 public Page ReadPage(long p, PagerState pagerState = null)
 {
     return(_scratchPager.Read(p, pagerState));
 }
Exemple #7
0
        public bool ReadOneTransaction(StorageEnvironmentOptions options, bool checkCrc = true)
        {
            if (_readingPage >= _pager.NumberOfAllocatedPages)
            {
                return(false);
            }

            if (MaxPageToRead != null && _readingPage >= MaxPageToRead.Value)
            {
                return(false);
            }

            TransactionHeader *current;

            if (!TryReadAndValidateHeader(options, out current))
            {
                return(false);
            }

            var transactionSize = GetNumberOfPagesFromSize(current->Compressed ? current->CompressedSize : current->UncompressedSize);

            if (current->TransactionId <= _lastSyncedTransactionId)
            {
                LastTransactionHeader = current;
                _readingPage         += transactionSize;
                return(true);                // skipping
            }

            if (checkCrc && !ValidatePagesCrc(options, transactionSize, current))
            {
                return(false);
            }

            _recoveryPager.EnsureContinuous(null, _recoveryPage, (current->PageCount + current->OverflowPageCount) + 1);
            var dataPage = _recoveryPager.AcquirePagePointer(_recoveryPage);

            UnmanagedMemory.Set(dataPage, 0, (current->PageCount + current->OverflowPageCount) * AbstractPager.PageSize);
            if (current->Compressed)
            {
                if (TryDecompressTransactionPages(options, current, dataPage) == false)
                {
                    return(false);
                }
            }
            else
            {
                Memory.Copy(dataPage, _pager.AcquirePagePointer(_readingPage), (current->PageCount + current->OverflowPageCount) * AbstractPager.PageSize);
            }

            var tempTransactionPageTranslaction = new Dictionary <long, RecoveryPagePosition>();

            for (var i = 0; i < current->PageCount; i++)
            {
                Debug.Assert(_pager.Disposed == false);
                Debug.Assert(_recoveryPager.Disposed == false);

                var page = _recoveryPager.Read(_recoveryPage);

                var pagePosition = new RecoveryPagePosition
                {
                    JournalPos    = _recoveryPage,
                    TransactionId = current->TransactionId
                };

                if (page.IsOverflow)
                {
                    var numOfPages = _recoveryPager.GetNumberOfOverflowPages(page.OverflowSize);

                    pagePosition.IsOverflow            = true;
                    pagePosition.NumberOfOverflowPages = numOfPages;

                    _recoveryPage += numOfPages;
                }
                else
                {
                    _recoveryPage++;
                }

                tempTransactionPageTranslaction[page.PageNumber] = pagePosition;
            }

            _readingPage += transactionSize;

            LastTransactionHeader = current;

            foreach (var pagePosition in tempTransactionPageTranslaction)
            {
                _transactionPageTranslation[pagePosition.Key] = pagePosition.Value;

                if (pagePosition.Value.IsOverflow)
                {
                    Debug.Assert(pagePosition.Value.NumberOfOverflowPages != -1);

                    for (int i = 1; i < pagePosition.Value.NumberOfOverflowPages; i++)
                    {
                        _transactionPageTranslation.Remove(pagePosition.Key + i);
                    }
                }
            }

            return(true);
        }
Exemple #8
0
 public Page ReadPage(Transaction tx, long p, PagerState pagerState = null)
 {
     return(_scratchPager.Read(tx, p, pagerState));
 }
Exemple #9
0
        public bool ReadOneTransaction(StorageEnvironmentOptions options, bool checkCrc = true)
        {
            if (_readingPage >= _pager.NumberOfAllocatedPages)
            {
                return(false);
            }

            TransactionHeader *current;

            if (!TryReadAndValidateHeader(options, out current))
            {
                return(false);
            }

            var compressedPages = (current->CompressedSize / AbstractPager.PageSize) + (current->CompressedSize % AbstractPager.PageSize == 0 ? 0 : 1);

            if (current->TransactionId <= _lastSyncedTransactionId)
            {
                LastTransactionHeader = current;
                _readingPage         += compressedPages;
                return(true); // skipping
            }

            if (checkCrc)
            {
                uint crc = Crc.Value(_pager.AcquirePagePointer(_readingPage), 0, compressedPages * AbstractPager.PageSize);

                if (crc != current->Crc)
                {
                    RequireHeaderUpdate = true;
                    options.InvokeRecoveryError(this, "Invalid CRC signature for transaction " + current->TransactionId, null);

                    return(false);
                }
            }

            _recoveryPager.EnsureContinuous(null, _recoveryPage, (current->PageCount + current->OverflowPageCount) + 1);
            var dataPage = _recoveryPager.AcquirePagePointer(_recoveryPage);

            NativeMethods.memset(dataPage, 0, (current->PageCount + current->OverflowPageCount) * AbstractPager.PageSize);
            try
            {
                LZ4.Decode64(_pager.AcquirePagePointer(_readingPage), current->CompressedSize, dataPage, current->UncompressedSize, true);
            }
            catch (Exception e)
            {
                options.InvokeRecoveryError(this, "Could not de-compress, invalid data", e);
                RequireHeaderUpdate = true;

                return(false);
            }

            var tempTransactionPageTranslaction = new Dictionary <long, JournalFile.PagePosition>();

            for (var i = 0; i < current->PageCount; i++)
            {
                Debug.Assert(_pager.Disposed == false);
                Debug.Assert(_recoveryPager.Disposed == false);

                var page = _recoveryPager.Read(_recoveryPage);

                tempTransactionPageTranslaction[page.PageNumber] = new JournalFile.PagePosition
                {
                    JournalPos    = _recoveryPage,
                    TransactionId = current->TransactionId
                };

                if (page.IsOverflow)
                {
                    var numOfPages = _recoveryPager.GetNumberOfOverflowPages(page.OverflowSize);
                    _recoveryPage += numOfPages;
                }
                else
                {
                    _recoveryPage++;
                }
            }

            _readingPage += compressedPages;

            LastTransactionHeader = current;

            foreach (var pagePosition in tempTransactionPageTranslaction)
            {
                _transactionPageTranslation[pagePosition.Key] = pagePosition.Value;
            }

            return(true);
        }