예제 #1
0
        protected override void Read(BinaryReader br, bool isPhysicalRead)
        {
            base.Read(br, isPhysicalRead);

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

            var dataLossNumber      = br.ReadInt64();
            var configurationNumber = br.ReadInt64();

            this.logHeadEpoch = new Epoch(dataLossNumber, configurationNumber);
            this.logHeadLsn   = new LogicalSequenceNumber(br.ReadInt64());
            this.logHeadPsn   = new PhysicalSequenceNumber(br.ReadInt64());
            if (isPhysicalRead == true)
            {
                this.logHeadRecordOffset = br.ReadUInt64();
            }

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

            this.UpdateApproximateDiskSize();
            return;
        }
예제 #2
0
        internal PhysicalLogWriter(
            ILogicalLog logicalLogStream,
            PhysicalLogWriterCallbackManager callbackManager,
            ITracer tracer,
            int maxWriteCacheSizeInMB,
            IncomingBytesRateCounterWriter incomingBytesRateCounterWriter,
            LogFlushBytesRateCounterWriter logFlushBytesRateCounterWriter,
            AvgBytesPerFlushCounterWriter bytesPerFlushCounterWriter,
            AvgFlushLatencyCounterWriter avgFlushLatencyCounterWriter,
            AvgSerializationLatencyCounterWriter avgSerializationLatencyCounterWriter,
            bool recomputeRecordOffsets)
        {
            Utility.Assert(callbackManager != null, "PhysicalLogWriter cannot accept null callback managers");

            this.maxWriteCacheSizeInBytes = maxWriteCacheSizeInMB * 1024 * 1024;
            this.Init(tracer, null);
            this.logicalLogStream                     = logicalLogStream;
            this.callbackManager                      = callbackManager;
            this.currentLogTailPosition               = (ulong)logicalLogStream.WritePosition;
            this.currentLogTailRecord                 = LogRecord.InvalidLogRecord;
            this.currentLogTailPsn                    = new PhysicalSequenceNumber(-1);
            this.lastPhysicalRecord                   = null;
            this.incomingBytesRateCounterWriter       = incomingBytesRateCounterWriter;
            this.logFlushBytesRateCounterWriter       = logFlushBytesRateCounterWriter;
            this.bytesPerFlushCounterWriter           = bytesPerFlushCounterWriter;
            this.avgFlushLatencyCounterWriter         = avgFlushLatencyCounterWriter;
            this.avgSerializationLatencyCounterWriter = avgSerializationLatencyCounterWriter;
            this.recordWriter           = new BinaryWriter(new MemoryStream());
            this.recomputeRecordOffsets = recomputeRecordOffsets;
        }
예제 #3
0
        internal void ProcessFlushedRecords(LoggedRecords flushedRecords)
        {
            lock (this.callbackLock)
            {
                if (this.isCallingback == false)
                {
                    Utility.Assert(this.loggedRecords == null, "this.loggedRecords == null");
                    this.isCallingback = true;
                }
                else
                {
                    if (this.loggedRecords == null)
                    {
                        this.loggedRecords = new List <LoggedRecords>();
                    }

                    this.loggedRecords.Add(flushedRecords);
                    return;
                }
            }

            var records = new List <LoggedRecords>();

            records.Add(flushedRecords);
            if (this.flushedPsn == PhysicalSequenceNumber.InvalidPsn)
            {
                this.flushedPsn = flushedRecords.Records[0].Psn;
            }

            Task.Factory.StartNew(this.InvokeFlushedRecordsCallback, records).IgnoreExceptionVoid();
            return;
        }
예제 #4
0
        private void InvokeFlushedRecordsCallback(object state)
        {
            var flushedRecords = (List <LoggedRecords>)state;
            var callback       = this.flushedRecordsCallback;

            while (true)
            {
                foreach (var loggedRecords in flushedRecords)
                {
                    var records   = loggedRecords.Records;
                    var exception = loggedRecords.Exception;
                    if (exception != null)
                    {
                        foreach (var record in records)
                        {
                            this.TraceLoggingException(record, exception);
                        }
                    }
                    else
                    {
                        Utility.Assert(
                            this.flushedPsn == records[0].Psn,
                            "this.flushedPsn {0} == records[0].Psn {1}",
                            this.flushedPsn, records[0].Psn);

                        this.flushedPsn += records.Count;
                    }

                    try
                    {
                        callback(loggedRecords);
                    }
                    catch (Exception e)
                    {
                        Utility.ProcessUnexpectedException(
                            "PhysicalLogWriterCallbackManager::InvokeFlushedRecordsCallback",
                            this.tracer,
                            "invoking flushed records callback",
                            e);
                    }
                }

                lock (this.callbackLock)
                {
                    Utility.Assert(this.isCallingback == true, "this.isCallingback == true");
                    if (this.loggedRecords == null)
                    {
                        this.isCallingback = false;
                        break;
                    }

                    flushedRecords     = this.loggedRecords;
                    this.loggedRecords = null;
                }
            }

            return;
        }
예제 #5
0
 internal LogHeadRecord(LogRecordType recordType, ulong recordPosition, long lsn)
     : base(recordType, recordPosition, lsn)
 {
     this.logHeadEpoch        = LogicalSequenceNumber.InvalidEpoch;
     this.logHeadLsn          = LogicalSequenceNumber.InvalidLsn;
     this.logHeadPsn          = PhysicalSequenceNumber.InvalidPsn;
     this.logHeadRecordOffset = InvalidPhysicalRecordOffset;
     this.logHeadRecord       = IndexingLogRecord.InvalidIndexingLogRecord;
 }
예제 #6
0
        // Used by the replicator to disable tracing
        internal PhysicalLogWriterCallbackManager(Action <LoggedRecords> flushedRecordsCallback)
        {
            this.flushedRecordsCallback = flushedRecordsCallback;
            this.tracer     = null;
            this.isDisposed = false;

            this.isCallingback = false;
            this.loggedRecords = null;
            this.flushedPsn    = PhysicalSequenceNumber.InvalidPsn;
        }
예제 #7
0
        internal static void Assert(bool condition, string format, PhysicalSequenceNumber param1, PhysicalSequenceNumber param2)
        {
            if (condition == false)
            {
                var failFastMessage = string.Format(System.Globalization.CultureInfo.InvariantCulture, format, param1, param2);
                FailFast(failFastMessage);

                // AMW - Force break into debugger for ease of debugging
                Debugger.Break();
            }
        }
예제 #8
0
        internal LogHeadRecord(
            LogRecordType recordType,
            IndexingLogRecord logHeadRecord,
            LogicalSequenceNumber lsn,
            PhysicalLogRecord lastLinkedPhysicalRecord)
            : base(recordType, lsn, lastLinkedPhysicalRecord)
        {
            this.logHeadEpoch        = logHeadRecord.CurrentEpoch;
            this.logHeadLsn          = logHeadRecord.Lsn;
            this.logHeadPsn          = logHeadRecord.Psn;
            this.logHeadRecordOffset = InvalidPhysicalRecordOffset;
            this.logHeadRecord       = logHeadRecord;

            this.UpdateApproximateDiskSize();
        }
예제 #9
0
        private void SetTailRecord(LogRecord tailRecord)
        {
            this.currentLogTailPosition = tailRecord.RecordPosition + tailRecord.RecordSize;
            this.currentLogTailRecord   = tailRecord;
            this.currentLogTailPsn      = tailRecord.Psn;
            var physicalRecord = tailRecord as PhysicalLogRecord;

            this.lastPhysicalRecord = (physicalRecord == null) ? tailRecord.PreviousPhysicalRecord : physicalRecord;
            Utility.Assert(
                this.lastPhysicalRecord != PhysicalLogRecord.InvalidPhysicalLogRecord,
                "this.lastPhysicalRecord ({0}) != PhysicalLogRecord.InvalidPhysicalLogRecord",
                this.lastPhysicalRecord);

            return;
        }
예제 #10
0
        protected LogRecord(LogRecordType recordType)
        {
            this.recordType = recordType;
            this.lsn        = LogicalSequenceNumber.InvalidLsn;
            this.psn        = PhysicalSequenceNumber.InvalidPsn;
            this.previousPhysicalRecordOffset = InvalidPhysicalRecordOffset;

            this.recordLength           = InvalidRecordLength;
            this.recordPosition         = InvalidRecordPosition;
            this.previousPhysicalRecord = PhysicalLogRecord.InvalidPhysicalLogRecord;
            this.flushedTask            = new CompletionTask();
            this.appliedTask            = new CompletionTask();
            this.processedTask          = new CompletionTask();

            this.UpdateApproximateDiskSize();
        }
예제 #11
0
        protected LogRecord()
        {
            this.recordType = LogRecordType.Invalid;
            this.lsn        = LogicalSequenceNumber.InvalidLsn;
            this.psn        = PhysicalSequenceNumber.InvalidPsn;
            this.previousPhysicalRecordOffset = InvalidPhysicalRecordOffset;

            this.recordPosition         = InvalidRecordPosition;
            this.recordLength           = InvalidRecordLength;
            this.previousPhysicalRecord = null;
            this.flushedTask            = this.invalidCompletionTask;
            this.appliedTask            = this.invalidCompletionTask;
            this.processedTask          = this.invalidCompletionTask;

            this.ApproximateSizeOnDisk = 0;
        }
예제 #12
0
        protected LogRecord(LogRecordType recordType, ulong recordPosition, long lsn)
        {
            this.recordType = recordType;
            this.lsn        = new LogicalSequenceNumber(lsn);
            this.psn        = PhysicalSequenceNumber.InvalidPsn;
            this.previousPhysicalRecordOffset = InvalidPhysicalRecordOffset;

            this.recordPosition         = recordPosition;
            this.recordLength           = InvalidRecordLength;
            this.previousPhysicalRecord = PhysicalLogRecord.InvalidPhysicalLogRecord;
            this.flushedTask            = new CompletionTask();
            this.appliedTask            = new CompletionTask();
            this.processedTask          = new CompletionTask();

            this.ApproximateSizeOnDisk = 0;
        }
예제 #13
0
        internal virtual bool FreePreviousLinksLowerThanPsn(PhysicalSequenceNumber newHeadPsn)
        {
            if (this.previousPhysicalRecord != null &&
                this.previousPhysicalRecord.Psn < newHeadPsn)
            {
                Utility.Assert(
                    this.previousPhysicalRecordOffset != InvalidPhysicalRecordOffset,
                    "FreePreviousLinksLowerThanPsn: PreviousPhysicalRecordOffset is invalid. Record LSN is {0}",
                    this.lsn.LSN);

                this.previousPhysicalRecord = (this.previousPhysicalRecordOffset == 0)
                    ? null
                    : PhysicalLogRecord.InvalidPhysicalLogRecord;
            }

            return(false);
        }
예제 #14
0
        internal override bool FreePreviousLinksLowerThanPsn(PhysicalSequenceNumber newHeadPsn)
        {
            bool ret = base.FreePreviousLinksLowerThanPsn(newHeadPsn);

            if (this.linkedPhysicalRecord != null &&
                this.linkedPhysicalRecord.Psn < newHeadPsn)
            {
                Utility.Assert(
                    this.linkedPhysicalRecordOffset != InvalidPhysicalRecordOffset,
                    "FreePreviousLinksLowerThanPsn: PreviousPhysicalRecordOffset is invalid. Record LSN is {0}");

                this.linkedPhysicalRecord = (this.linkedPhysicalRecordOffset == 0)
                    ? null
                    : PhysicalLogRecord.InvalidPhysicalLogRecord;

                return(true);
            }

            return(ret);
        }
예제 #15
0
        internal override bool FreePreviousLinksLowerThanPsn(PhysicalSequenceNumber newHeadPsn)
        {
            bool ret = base.FreePreviousLinksLowerThanPsn(newHeadPsn);

            if ((this.lastCompletedBeginCheckpointRecord != null) &&
                (this.lastCompletedBeginCheckpointRecord.Psn < newHeadPsn))
            {
                Utility.Assert(
                    this.lastCompletedBeginCheckpointRecordOffset != InvalidPhysicalRecordOffset,
                    "this.lastCompletedBeginCheckpointRecordOffset != PhysicalLogRecord.INVALID_PHYSICAL_RECORD_OFFSET");

                this.lastCompletedBeginCheckpointRecord = this.lastCompletedBeginCheckpointRecordOffset == 0
                    ? null
                    : BeginCheckpointLogRecord.InvalidBeginCheckpointLogRecord;

                return(true);
            }

            return(ret);
        }
        internal override bool FreePreviousLinksLowerThanPsn(PhysicalSequenceNumber newHeadPsn)
        {
            bool ret = base.FreePreviousLinksLowerThanPsn(newHeadPsn);

            if (this.earliestPendingTransaction != null &&
                this.earliestPendingTransaction.Psn < newHeadPsn)
            {
                Utility.Assert(
                    this.earliestPendingTransactionOffset != LogicalLogRecord.InvalidLogicalRecordOffset,
                    "FreePreviousLinksLowerThanPsn: Earliest pending transaction offset cannot be invalid for checkpoint record lsn: {0}, psn: {1}",
                    Lsn,
                    Psn);

                this.earliestPendingTransaction = BeginTransactionOperationLogRecord.InvalidBeginTransactionLogRecord;
                Interlocked.Increment(ref this.earliestPendingTransactionInvalidated);
                return(true);
            }

            return(ret);
        }
예제 #17
0
        internal override bool FreePreviousLinksLowerThanPsn(PhysicalSequenceNumber newHeadPsn)
        {
            bool ret = base.FreePreviousLinksLowerThanPsn(newHeadPsn);

            if (this.logHeadRecord != null &&
                this.logHeadRecord.Psn < newHeadPsn)
            {
                Utility.Assert(
                    this.logHeadRecordOffset != InvalidPhysicalRecordOffset,
                    "this.logHeadRecordOffset must be valid");

                this.logHeadRecord =
                    (this.logHeadRecordOffset == 0) ?
                    null :
                    IndexingLogRecord.InvalidIndexingLogRecord;

                return(true);
            }

            return(ret);
        }
예제 #18
0
        protected virtual void Read(BinaryReader br, bool isPhysical)
        {
            if (isPhysical)
            {
                // Metadata section.
                var startingPosition = br.BaseStream.Position;
                var sizeOfSection    = br.ReadInt32();
                var endPosition      = startingPosition + sizeOfSection;

                // Read Physical metadata section
                this.psn = new PhysicalSequenceNumber(br.ReadInt64());
                this.previousPhysicalRecordOffset = br.ReadUInt64();

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

                if (this.previousPhysicalRecordOffset == 0)
                {
                    this.previousPhysicalRecord = null;
                }
            }
        }