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); }
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); }
/// <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; }
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); }
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); } } }
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); } }
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); }
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); }