예제 #1
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);
        }
예제 #2
0
        /// <summary>
        /// Creates or finds the log stream.
        /// If being created either initializes the log with default log records or records from backup log.
        /// </summary>
        /// <param name="openMode">Open mode of the replica.</param>
        /// <returns>Task that represents the asynchronous open operation.</returns>
        internal async Task <PhysicalLogReader> OpenAsync(ReplicaOpenMode openMode)
        {
            // TODO: Anurag: do we plumb c.token up?
            this.LogicalLog = await this.CreateLogFileAsync(openMode == ReplicaOpenMode.New, CancellationToken.None).ConfigureAwait(false);

            var logLogLength = this.LogicalLog.Length;

            if (logLogLength <= sizeof(int))
            {
                // No usable content in the log
                if (this.LogicalLog.WritePosition > 0)
                {
                    await this.LogicalLog.TruncateTail(0, CancellationToken.None).ConfigureAwait(false);

                    // Remove all contents and reset write cursor back to 0
                    Utility.Assert(this.LogicalLog.Length == 0, "this.logicalLog.Length == 0");
                    Utility.Assert(this.LogicalLog.WritePosition == 0, "this.logicalLog.WritePosition == 0");
                }

                using (
                    var logWriter = new PhysicalLogWriter(
                        this.LogicalLog,
                        this.emptyCallbackManager,
                        this.Tracer,
                        this.MaxWriteCacheSizeInMB,
                        this.IncomingBytesRateCounterWriter,
                        this.LogFlushBytesRateCounterWriter,
                        this.BytesPerFlushCounterWriter,
                        this.AvgFlushLatencyCounterWriter,
                        this.AvgSerializationLatencyCounterWriter,
                        false))
                {
                    var zeroIndexRecord = IndexingLogRecord.CreateZeroIndexingLogRecord();
                    logWriter.InsertBufferedRecord(zeroIndexRecord);
                    logWriter.InsertBufferedRecord(UpdateEpochLogRecord.CreateZeroUpdateEpochLogRecord());
                    var zeroBeginCheckpointRecord =
                        BeginCheckpointLogRecord.CreateZeroBeginCheckpointLogRecord();
                    logWriter.InsertBufferedRecord(zeroBeginCheckpointRecord);
                    logWriter.InsertBufferedRecord(BarrierLogRecord.CreateOneBarrierLogRecord());
                    var oneEndCheckpointRecord =
                        EndCheckpointLogRecord.CreateOneEndCheckpointLogRecord(
                            zeroBeginCheckpointRecord,
                            zeroIndexRecord);
                    logWriter.InsertBufferedRecord(oneEndCheckpointRecord);
                    var endCompleteCheckpointRecord =
                        new CompleteCheckpointLogRecord(
                            LogicalSequenceNumber.OneLsn,
                            zeroIndexRecord,
                            oneEndCheckpointRecord);
                    logWriter.InsertBufferedRecord(endCompleteCheckpointRecord);
                    await logWriter.FlushAsync("OpenAsync").ConfigureAwait(false);

                    // This additional await is required to ensure the log record was indeed flushed.
                    // Without this, the flushasync could succeed, but the log record flush could have failed due to a write error
                    await endCompleteCheckpointRecord.AwaitFlush().ConfigureAwait(false);
                }
            }

            return(new PhysicalLogReader(this));
        }
예제 #3
0
 private void OnBarrierBufferedCallerHoldsLock(
     BarrierLogRecord record,
     bool isPrimary)
 {
     FabricEvents.Events.AcceptBarrier(this.tracer.Type, record.Lsn.LSN);
     AddCheckpointIfNeeded(isPrimary);
     this.LogManager.FlushAsync("BarrierRecordAppended").IgnoreExceptionVoid();
 }
예제 #4
0
 public void Reuse()
 {
     this.numberOfLogicalRecordsBeingProcessed  = 1;
     this.numberOfPhysicalRecordsBeingProcessed = 1;
     this.physicalRecordsProcessingTcs          = new TaskCompletionSource <PhysicalLogRecord>();
     this.logicalRecordsProcessingTcs           = new TaskCompletionSource <LogicalLogRecord>();
     this.LastAppliedBarrierRecord = BarrierLogRecord.CreateOneBarrierLogRecord();
     this.serviceException         = null;
     this.logException             = null;
 }
예제 #5
0
        /// <summary>
        /// Process the barrier log record.
        /// </summary>
        /// <param name="barrierLogRecord">The barrier record to be processed.</param>
        /// <param name="isRecoverableRecord">Is this a recoverable record.</param>
        private void ProcessLogRecord(BarrierLogRecord barrierLogRecord, out bool isRecoverableRecord)
        {
            isRecoverableRecord = true;

            this.LastLogicalSequenceNumber++;

            Utility.Assert(
                barrierLogRecord.Lsn == this.LastLogicalSequenceNumber,
                "barrierRecord.LastLogicalSequenceNumber == lsn");
            this.LastStableLsn = barrierLogRecord.LastStableLsn;

            this.TransactionsMap.RemoveStableTransactions(this.LastStableLsn);
        }
예제 #6
0
        public void AppendBarrier(
            BarrierLogRecord barrierLogRecord,
            bool isPrimary)
        {
            if (isPrimary == true)
            {
                ReplicateAndLog(barrierLogRecord, null);
                return;
            }

            AppendWithoutReplication(
                barrierLogRecord,
                null);
        }
예제 #7
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);
        }