Пример #1
0
        internal EndTransactionLogRecord FindUnstableTransaction(EndTransactionLogRecord record)
        {
            Utility.Assert(
                record.Transaction.IsAtomicOperation == false,
                "record.Transaction.IsAtomicOperation == false");
            Utility.Assert(
                LogRecord.IsInvalidRecord(record.ParentTransactionRecord) == true,
                "LogRecord.IsInvalidRecord(record.ParentTransactionRecord) == true");

            int i;

            lock (this.txmapLock)
            {
                for (i = this.unstableTransactions.Count - 1; i >= 0; i--)
                {
                    if (this.unstableTransactions[i].Transaction == record.Transaction)
                    {
                        record = this.unstableTransactions[i];
                        break;
                    }
                }
            }

            Utility.Assert(
                i >= 0,
                "Transaction associated with the end transaction log record is not presnet in unstable transactions");
            return(record);
        }
Пример #2
0
        private static LogRecord ReadFromOperationData(OperationData operationData)
        {
            LogRecord     record;
            long          lsn;
            const ulong   RecordPosition = InvalidRecordPosition;
            LogRecordType recordType;
            var           index = -1;

            using (var reader = new BinaryReader(IncrementIndexAndGetMemoryStreamAt(operationData, ref index)))
            {
                // Logical metadata section.
                var startingPosition = reader.BaseStream.Position;
                var sizeOfSection    = reader.ReadInt32();
                var endPosition      = startingPosition + sizeOfSection;

                // Logical metadata read.
                recordType = (LogRecordType)reader.ReadUInt32();
                lsn        = reader.ReadInt64();

                // Jump to the end of the section ignoring fields that are not understood.
                Utility.Assert(endPosition >= reader.BaseStream.Position, "Could not have read more than section size.");
                reader.BaseStream.Position = endPosition;
            }

            switch (recordType)
            {
            case LogRecordType.BeginTransaction:
                record = new BeginTransactionOperationLogRecord(recordType, RecordPosition, lsn);
                break;

            case LogRecordType.Operation:
                record = new OperationLogRecord(recordType, RecordPosition, lsn);
                break;

            case LogRecordType.EndTransaction:
                record = new EndTransactionLogRecord(recordType, RecordPosition, lsn);
                break;

            case LogRecordType.Barrier:
                record = new BarrierLogRecord(recordType, RecordPosition, lsn);
                break;

            case LogRecordType.UpdateEpoch:
                record = new UpdateEpochLogRecord(recordType, RecordPosition, lsn);
                break;

            case LogRecordType.Backup:
                record = new BackupLogRecord(recordType, RecordPosition, lsn);
                break;

            default:
                Utility.CodingError(
                    "Unexpected record type received during replication/copy processing {0}",
                    recordType);
                return(null);
            }

            record.ReadLogical(operationData, ref index);
            return(record);
        }
Пример #3
0
        /// <summary>
        /// Process the end transaction log record.
        /// </summary>
        /// <param name="endTransactionLogRecord">The end transaction record to be processed.</param>
        /// <param name="isRecoverableRecord">Is this a recoverable record.</param>
        private void ProcessLogRecord(EndTransactionLogRecord endTransactionLogRecord, out bool isRecoverableRecord)
        {
            this.LastLogicalSequenceNumber++;

            Utility.Assert(
                endTransactionLogRecord.Lsn == this.LastLogicalSequenceNumber,
                "endTransactionRecord.LastLogicalSequenceNumber == lsn");
            this.TransactionsMap.CompleteTransaction(endTransactionLogRecord);

            if (Mode.Recovery == this.mode)
            {
                Utility.Assert(
                    endTransactionLogRecord.IsEnlistedTransaction == true ||
                    endTransactionLogRecord.RecordPosition
                    < this.recoveredLastCompletedBeginCheckpointRecord.RecordPosition,
                    EndTransactionProcessingAssertMessage,
                    endTransactionLogRecord.RecordPosition, this.recoveredLastCompletedBeginCheckpointRecord.RecordPosition);
            }
            else
            {
                Utility.Assert(
                    LogRecord.InvalidRecordPosition == endTransactionLogRecord.RecordPosition,
                    "LogRecord.INVALID_RECORD_POSITION == endTransactionLogRecord.RecordPosition ({0})",
                    endTransactionLogRecord);
            }

            isRecoverableRecord = endTransactionLogRecord.IsEnlistedTransaction == true;
        }
Пример #4
0
        internal async Task <EndTransactionLogRecord> EndTransactionAsync(
            TransactionBase transaction,
            bool isCommitted,
            bool isThisReplicaTransaction)
        {
            var record = new EndTransactionLogRecord(
                transaction,
                isCommitted,
                isThisReplicaTransaction);

            await this.ProcessLogicalRecordOnPrimaryAsync(record).ConfigureAwait(false);

            return(record);
        }
Пример #5
0
        internal void CompleteTransaction(EndTransactionLogRecord record)
        {
            Utility.Assert(
                record.Transaction.IsAtomicOperation == false,
                "record.Transaction.IsAtomicOperation == false");

            lock (this.txmapLock)
            {
                if (this.latestRecords.ContainsKey(record.Transaction.Id))
                {
                    record.IsEnlistedTransaction   = this.latestRecords[record.Transaction.Id].IsEnlistedTransaction;
                    record.ParentTransactionRecord = this.latestRecords[record.Transaction.Id];
                    record.ParentTransactionRecord.ChildTransactionRecord = record;
                    this.latestRecords.Remove(record.Transaction.Id);
                }
                else
                {
                    Utility.Assert(record.IsEnlistedTransaction == false, "record.IsEnlistedTransaction == false");
                    record.ParentTransactionRecord = null;
                }

                BeginTransactionOperationLogRecord beginTransactionRecord = null;
                if (this.transactionIdPendingTransactionsPair.ContainsKey(record.Transaction.Id))
                {
                    beginTransactionRecord = this.transactionIdPendingTransactionsPair[record.Transaction.Id];
                    this.lsnPendingTransactionsPair.Remove(
                        this.transactionIdPendingTransactionsPair[record.Transaction.Id].Lsn.LSN);
                    this.transactionIdPendingTransactionsPair.Remove(record.Transaction.Id);
                }

                Utility.Assert(
                    (record.IsEnlistedTransaction == true) == (beginTransactionRecord != null),
                    "(record.IsEnlistedTransaction == true) == (beginTransactionRecord != null)");
                if (beginTransactionRecord != null)
                {
                    this.AddUnstableTransactionCallerHoldsLock(beginTransactionRecord, record);
                }
            }
        }
Пример #6
0
        private void AddUnstableTransactionCallerHoldsLock(
            BeginTransactionOperationLogRecord beginTransactionRecord,
            EndTransactionLogRecord endTransactionRecord)
        {
            Utility.Assert(
                beginTransactionRecord.IsSingleOperationTransaction == false,
                "beginTransactionRecord.IsSingleOperationTransaction == false");

            // Transactions tend to complete in order
            int i;

            for (i = this.completedTransactions.Count - 1; i >= 0; i--)
            {
                if (this.completedTransactions[i].Lsn < beginTransactionRecord.Lsn)
                {
                    this.completedTransactions.Insert(i + 1, beginTransactionRecord);
                    break;
                }
            }

            if (i == -1)
            {
                this.completedTransactions.Insert(0, beginTransactionRecord);
            }

            for (i = this.unstableTransactions.Count - 1; i >= 0; i--)
            {
                if (this.unstableTransactions[i].Lsn < endTransactionRecord.Lsn)
                {
                    this.unstableTransactions.Insert(i + 1, endTransactionRecord);
                    break;
                }
            }

            if (i == -1)
            {
                this.unstableTransactions.Insert(0, endTransactionRecord);
            }
        }
Пример #7
0
        internal EndTransactionLogRecord ReifyTransaction(EndTransactionLogRecord record)
        {
            Utility.Assert(
                record.Transaction.IsAtomicOperation == false,
                "record.Transaction.IsAtomicOperation == false");
            Utility.Assert(
                LogRecord.IsInvalidRecord(record.ParentTransactionRecord) == true,
                "LogRecord.IsInvalidRecord(record.ParentTransactionRecord) == true");

            BeginTransactionOperationLogRecord reifiedBeginTransactionRecord = null;
            EndTransactionLogRecord            reifiedEndTransactionRecord   = null;

            int i;

            lock (this.txmapLock)
            {
                for (i = this.completedTransactions.Count - 1; i >= 0; i--)
                {
                    if (this.completedTransactions[i].Transaction == record.Transaction)
                    {
                        reifiedBeginTransactionRecord = this.completedTransactions[i];
                        Utility.Assert(
                            reifiedBeginTransactionRecord.IsSingleOperationTransaction == false,
                            "reifiedBeginTransactionRecord.IsSingleOperationTransaction == false");
                        this.completedTransactions.RemoveAt(i);
                        break;
                    }
                }

                Utility.Assert(i > -1, "Begin transaction record is not present in completed transactions");

                for (i = this.unstableTransactions.Count - 1; i >= 0; i--)
                {
                    if (this.unstableTransactions[i].Transaction == record.Transaction)
                    {
                        reifiedEndTransactionRecord = this.unstableTransactions[i];
                        this.unstableTransactions.RemoveAt(i);
                        break;
                    }
                }

                Utility.Assert(i > -1, "End transaction record is not present in unstable transactions");

                this.latestRecords[record.Transaction.Id] = reifiedEndTransactionRecord.ParentTransactionRecord;
                reifiedEndTransactionRecord.ParentTransactionRecord.ChildTransactionRecord =
                    TransactionLogRecord.InvalidTransactionLogRecord;

                TransactionLogRecord parentRecord = reifiedEndTransactionRecord;
                BeginTransactionOperationLogRecord chainedBeginTransactionRecord;
                do
                {
                    parentRecord = parentRecord.ParentTransactionRecord;
                    chainedBeginTransactionRecord = parentRecord as BeginTransactionOperationLogRecord;
                } while (chainedBeginTransactionRecord == null);

                Utility.Assert(
                    reifiedBeginTransactionRecord == chainedBeginTransactionRecord,
                    "reifiedBeginTransactionRecord == chainedBeginTransactionRecord");
                Utility.Assert(
                    reifiedBeginTransactionRecord.IsEnlistedTransaction,
                    "reifiedBeginTransactionRecord.IsEnlistedTransaction == true");
                this.transactionIdPendingTransactionsPair[reifiedBeginTransactionRecord.Transaction.Id] =
                    reifiedBeginTransactionRecord;
                this.lsnPendingTransactionsPair[reifiedBeginTransactionRecord.Lsn.LSN] = reifiedBeginTransactionRecord;
            }

            return(reifiedEndTransactionRecord);
        }
Пример #8
0
        private static LogRecord ReadRecord(BinaryReader br, ulong recordPosition, bool isPhysicalRead)
        {
            LogRecord     record;
            var           lsn = LogicalSequenceNumber.InvalidLsn.LSN;
            LogRecordType recordType;

            // Metadata section.
            var startingPosition = br.BaseStream.Position;
            var sizeOfSection    = br.ReadInt32();
            var endPosition      = startingPosition + sizeOfSection;

            // Read Logical Metadata
            recordType = (LogRecordType)br.ReadUInt32();

            switch (recordType)
            {
            case LogRecordType.BeginTransaction:
                record = new BeginTransactionOperationLogRecord(recordType, recordPosition, lsn);
                break;

            case LogRecordType.Operation:
                record = new OperationLogRecord(recordType, recordPosition, lsn);
                break;

            case LogRecordType.EndTransaction:
                record = new EndTransactionLogRecord(recordType, recordPosition, lsn);
                break;

            case LogRecordType.Barrier:
                record = new BarrierLogRecord(recordType, recordPosition, lsn);
                break;

            case LogRecordType.UpdateEpoch:
                record = new UpdateEpochLogRecord(recordType, recordPosition, lsn);
                break;

            case LogRecordType.Backup:
                record = new BackupLogRecord(recordType, recordPosition, lsn);
                break;

            case LogRecordType.BeginCheckpoint:
                record = new BeginCheckpointLogRecord(recordType, recordPosition, lsn);
                break;

            case LogRecordType.EndCheckpoint:
                record = new EndCheckpointLogRecord(recordType, recordPosition, lsn);
                break;

            case LogRecordType.Indexing:
                record = new IndexingLogRecord(recordType, recordPosition, lsn);
                break;

            case LogRecordType.TruncateHead:
                record = new TruncateHeadLogRecord(recordType, recordPosition, lsn);
                break;

            case LogRecordType.TruncateTail:
                record = new TruncateTailLogRecord(recordType, recordPosition, lsn);
                break;

            case LogRecordType.Information:
                record = new InformationLogRecord(recordType, recordPosition, lsn);
                break;

            case LogRecordType.CompleteCheckpoint:
                record = new CompleteCheckpointLogRecord(recordType, recordPosition, lsn);
                break;

            default:
                Utility.CodingError("Unexpected record type {0}", recordType);
                return(null);
            }

            record.lsn = new LogicalSequenceNumber(br.ReadInt64());

            // Jump to the end of the section ignoring fields that are not understood.
            Utility.Assert(endPosition >= br.BaseStream.Position, "Could not have read more than section size.");
            br.BaseStream.Position = endPosition;

            record.Read(br, isPhysicalRead);

            return(record);
        }