private OperationData WriteRecord(LogRecord record, ulong bytesWritten)
        {
            // GopalK: The order of the following instructions is very important
            Utility.Assert(
                this.currentLogTailPosition + bytesWritten == (ulong)this.logicalLogStream.WritePosition,
                "this.currentLogTailPosition == (ulong) this.logicalLogStream.WritePosition");

            // Update record position
            var recordPosition = this.currentLogTailPosition + bytesWritten;

            record.RecordPosition = recordPosition;

            // Write record
            return(LogRecord.WriteRecord(record, this.recordWriter, true, true, this.recomputeRecordOffsets));
        }
Exemple #2
0
        /// <summary>
        /// Write the backup log file.
        /// </summary>
        /// <param name="stream">Backup log stream.</param>
        /// <param name="logRecords">The log records.</param>
        /// <param name="cancellationToken">Token used to signal cancellation.</param>
        /// <returns>Task that represents the asynchronous operation.</returns>
        private async Task WriteLogRecordsAsync(
            Stream stream,
            IncrementalBackupLogRecordAsyncEnumerator logRecords,
            CancellationToken cancellationToken)
        {
            using (var memoryStream = new MemoryStream(InitialSizeOfMemoryStream))
                using (var binaryWriter = new BinaryWriter(memoryStream))
                    using (var recordWriter = new BinaryWriter(new MemoryStream()))
                    {
                        // Reserve an 'int' at the start to store the size of the block
                        memoryStream.Position += sizeof(int);

                        while (true == await logRecords.MoveNextAsync(cancellationToken).ConfigureAwait(false))
                        {
                            var record = logRecords.Current;

                            var operationData = LogRecord.WriteRecord(record, recordWriter, isPhysicalWrite: false, setRecordLength: false);

                            // TODO: Fix this by using operationdata in this class
                            foreach (var buffer in operationData)
                            {
                                binaryWriter.Write(buffer.Array, buffer.Offset, buffer.Count);
                            }

                            this.Count++;

                            // Flush the block after it's large enough.
                            if (memoryStream.Position >= MinimumIntermediateFlushSize)
                            {
                                await this.WriteLogRecordBlockAsync(stream, memoryStream, binaryWriter, cancellationToken).ConfigureAwait(false);
                            }

                            // Check for cancellation.
                            cancellationToken.ThrowIfCancellationRequested();
                        }

                        // Flush the block, if there's any remaining data (ignoring the block size 'int' at the start).
                        if (memoryStream.Position > sizeof(int))
                        {
                            await this.WriteLogRecordBlockAsync(stream, memoryStream, binaryWriter, cancellationToken).ConfigureAwait(false);
                        }

                        await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
                    }
        }
Exemple #3
0
        /// <summary>
        /// Write the backup log file.
        /// </summary>
        /// <param name="stream">Backup log stream.</param>
        /// <param name="logRecords">The log records.</param>
        /// <param name="cancellationToken">Token used to signal cancellation.</param>
        /// <returns>Task that represents the asynchronous operation.</returns>
        private async Task WriteLogRecordsAsync(
            Stream stream,
            IAsyncEnumerator <LogRecord> logRecords,
            CancellationToken cancellationToken)
        {
            var firstIndexingRecordProcessed = false;

            using (var memoryStream = new MemoryStream(InitialSizeOfMemoryStream))
                using (var binaryWriter = new BinaryWriter(memoryStream))
                    using (var recordWriter = new BinaryWriter(new MemoryStream()))
                    {
                        // Reserve an 'int' at the start to store the size of the block
                        memoryStream.Position += sizeof(int);

                        while (true == await logRecords.MoveNextAsync(cancellationToken).ConfigureAwait(false))
                        {
                            var record = logRecords.Current;

                            var indexingLogRecord = record as IndexingLogRecord;
                            if (indexingLogRecord != null)
                            {
                                if (false == firstIndexingRecordProcessed)
                                {
                                    this.IndexingRecordEpoch = indexingLogRecord.CurrentEpoch;
                                    this.IndexingRecordLsn   = indexingLogRecord.Lsn;

                                    firstIndexingRecordProcessed = true;
                                }

                                this.LastBackedUpEpoch = indexingLogRecord.CurrentEpoch;
                            }

                            var updateEpochLogRecord = record as UpdateEpochLogRecord;
                            if (updateEpochLogRecord != null)
                            {
                                this.LastBackedUpEpoch = updateEpochLogRecord.Epoch;
                            }

                            this.LastBackedUpLsn = record.Lsn;

                            var operationData = LogRecord.WriteRecord(record, recordWriter, isPhysicalWrite: false, setRecordLength: false);

                            // TODO: Fix this by using operationdata in this class
                            foreach (var buffer in operationData)
                            {
                                binaryWriter.Write(buffer.Array, buffer.Offset, buffer.Count);
                            }

                            this.Count++;

                            // Flush the block after it's large enough.
                            if (memoryStream.Position >= MinimumIntermediateFlushSize)
                            {
                                await this.WriteLogRecordBlockAsync(stream, memoryStream, binaryWriter, cancellationToken).ConfigureAwait(false);
                            }

                            // Check for cancellation.
                            cancellationToken.ThrowIfCancellationRequested();
                        }

                        // Flush the block, if there's any remaining data (ignoring the block size 'int' at the start).
                        if (memoryStream.Position > sizeof(int))
                        {
                            await this.WriteLogRecordBlockAsync(stream, memoryStream, binaryWriter, cancellationToken).ConfigureAwait(false);
                        }

                        await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
                    }

            // If no logical record is being backed up, lastBackedupLsn can be Invalid.
            if (this.LastBackedUpLsn == LogicalSequenceNumber.InvalidLsn)
            {
                this.LastBackedUpLsn = this.IndexingRecordLsn;
            }

            Utility.Assert(true == firstIndexingRecordProcessed, "Indexing log record must have been processed.");

            Utility.Assert(
                this.IndexingRecordEpoch.CompareTo(LoggingReplicator.InvalidEpoch) > 0,
                "Indexing record epoch has not been set.");
            Utility.Assert(
                this.LastBackedUpEpoch.CompareTo(LoggingReplicator.InvalidEpoch) > 0,
                "Ending epoch has not been set.");

            Utility.Assert(
                this.IndexingRecordLsn != LogicalSequenceNumber.InvalidLsn,
                "Indexing record lsn has not been set.");
            Utility.Assert(this.LastBackedUpLsn != LogicalSequenceNumber.InvalidLsn, "Ending lsn has not been set.");
        }