Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / Log / System / IO / Log / LogWriteRestartAreaState.cs / 1305376 / LogWriteRestartAreaState.cs
//------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.IO.Log
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
internal struct LogWriteRestartAreaState
{
enum State
{
Unprepared = 0,
Prepared,
AwaitCompletion,
AwaitPolicyCompletion,
AwaitSecondCompletion,
Completed
}
//===========================================================
// Inputs
//===========================================================
IList> data;
long totalRecordSize;
ulong newBaseLsn;
LogReservationCollection reservationCollection;
LogRecordSequence recordSequence;
LogWriteRestartAreaAsyncResult asyncResult;
//============================================================
// Internal State
//===========================================================
State currentState;
Exception exceptionResult;
object boxedResultLsn;
byte[] restartArea;
long reservationSize;
int flags;
//============================================================
// Pinned State
//============================================================
GCHandle pinnedResultHandle;
//===========================================================
// Parameters
//============================================================
public LogWriteRestartAreaAsyncResult AsyncResult
{
/* get { return this.asyncResult; } */
set { this.asyncResult = value; }
}
public IList> Data
{
/* get { return this.data; } */
set { this.data = value; }
}
public ulong NewBaseLsn
{
/* get { return this.newBaseLsn; } */
set { this.newBaseLsn = value; }
}
public LogRecordSequence RecordSequence
{
/* get { return this.recordSequence; } */
set { this.recordSequence = value; }
}
public LogReservationCollection ReservationCollection
{
/* get { return this.reservationCollection; } */
set { this.reservationCollection = value; }
}
public long TotalRecordSize
{
/* get { return this.totalRecordSize; } */
set { this.totalRecordSize = value; }
}
//===========================================================
// Results
//===========================================================
public ulong ResultLsn
{
get { return (ulong)(this.boxedResultLsn); }
}
//===============================================================
// Execution: State Machine
//================================================================
public void Start()
{
if (this.currentState != State.Unprepared)
{
// An internal consistency check has failed. The indicates a bug in IO.Log's internal processing
// Rather than proceeding with non-deterministic execution and risking the loss or corruption of
// log records, we failfast the process.
DiagnosticUtility.FailFast("Calling Start twice (write restart area)");
}
Prepare();
bool complete = false;
try
{
// We use our boxed LSN as a syncRoot, since nobody else
// is ever going to see it. We take the lock here to
// avoid ----s with IO completion.
//
lock(this.boxedResultLsn)
{
Pin();
this.currentState = State.AwaitCompletion;
uint errorCode = WriteLogRestartArea();
if (errorCode == Error.ERROR_IO_PENDING)
{
return;
}
else
{
AwaitCompletion_Complete(errorCode);
}
// Make sure to check for completion BEFORE
// leaving the lock, or there's a ---- with IO
// completion that may cause double-completes.
//
complete = (this.currentState == State.Completed);
}
}
#pragma warning suppress 56500 // We will be terminating the process with any exception in this call
catch(Exception e)
{
// The code in the try block should not throw any exceptions.
// If an exception is caught here, IO.Log may be in an unknown state.
// We prefer to failfast instead of risking the possibility of log corruption.
// Any client code using IO.Log must have a recovery model that can deal
// with appdomain and process failures.
DiagnosticUtility.InvokeFinalHandler(e);
}
if (complete)
{
if (this.asyncResult != null)
{
this.asyncResult.Complete(true, this.exceptionResult);
}
else if (this.exceptionResult != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(this.exceptionResult);
}
}
else
{
if (this.asyncResult == null)
{
// An internal consistency check has failed. The indicates a bug in IO.Log's internal processing
// Rather than proceeding with non-deterministic execution and risking the loss or corruption of
// log records, we failfast the process.
DiagnosticUtility.FailFast("What am I doing returning early without an AsyncResult?");
}
}
}
public void IOComplete(uint errorCode)
{
if (this.asyncResult == null)
{
// An internal consistency check has failed. The indicates a bug in IO.Log's internal processing
// Rather than proceeding with non-deterministic execution and risking the loss or corruption of
// log records, we failfast the process.
DiagnosticUtility.FailFast("What am I doing in IO completion without an AsyncResult?");
}
try
{
bool complete = false;
// We use our boxed LSN as a syncRoot, since nobody
// else is ever going to see it.
//
lock(this.boxedResultLsn)
{
switch(this.currentState)
{
case State.AwaitCompletion:
AwaitCompletion_Complete(errorCode);
break;
case State.AwaitPolicyCompletion:
AwaitPolicyCompletion_Complete(errorCode);
break;
case State.AwaitSecondCompletion:
AwaitSecondCompletion_Complete(errorCode);
break;
default:
// An internal consistency check has failed. The indicates a bug in IO.Log's internal processing
// Rather than proceeding with non-deterministic execution and risking the loss or corruption of
// log records, we failfast the process.
DiagnosticUtility.FailFast("Invalid state for IO completion");
break;
}
// Make sure to check for completion BEFORE
// leaving the lock, or there's a ---- with IO
// completion that may cause double-completes.
//
complete = (this.currentState == State.Completed);
}
if (complete)
{
this.asyncResult.Complete(false, this.exceptionResult);
}
}
#pragma warning suppress 56500 // We will be terminating the process with any exception in this call
catch(Exception e)
{
// The code in the try block should not throw any exceptions.
// If an exception is caught here, IO.Log may be in an unknown state.
// We prefer to failfast instead of risking the possibility of log corruption.
// Any client code using IO.Log must have a recovery model that can deal
// with appdomain and process failures.
DiagnosticUtility.InvokeFinalHandler(e);
}
}
void AwaitCompletion_Complete(uint errorCode)
{
Unpin();
if (errorCode == Error.ERROR_SUCCESS)
{
Complete(null);
}
else if ((errorCode == Error.ERROR_NO_SYSTEM_RESOURCES) && (this.recordSequence.RetryAppend))
{
this.currentState = State.AwaitPolicyCompletion;
errorCode = InvokePolicyEngine();
if (errorCode == Error.ERROR_IO_PENDING)
{
return;
}
AwaitPolicyCompletion_Complete(errorCode);
}
else
{
Complete(UnsafeNativeMethods.WriteLogRestartAreaFilter(errorCode));
}
}
void AwaitPolicyCompletion_Complete(uint errorCode)
{
if (errorCode == Error.ERROR_SUCCESS)
{
Pin();
this.currentState = State.AwaitSecondCompletion;
errorCode = WriteLogRestartArea();
if (errorCode == Error.ERROR_IO_PENDING)
{
return;
}
AwaitSecondCompletion_Complete(errorCode);
}
else
{
Complete(UnsafeNativeMethods.WriteLogRestartAreaFilter(errorCode));
}
}
void AwaitSecondCompletion_Complete(uint errorCode)
{
Unpin();
if (errorCode == Error.ERROR_SUCCESS)
{
Complete(null);
}
else
{
Complete(UnsafeNativeMethods.WriteLogRestartAreaFilter(errorCode));
}
}
// Get everything ready to run. Only call this once, unlike Pin.
//
void Prepare()
{
if (this.currentState != State.Unprepared)
{
// An internal consistency check has failed. The indicates a bug in IO.Log's internal processing
// Rather than proceeding with non-deterministic execution and risking the loss or corruption of
// log records, we failfast the process.
DiagnosticUtility.FailFast("Calling Prepare Twice");
}
// Box the result LSN.
//
ulong resultLsn = 0;
this.boxedResultLsn = (object)(resultLsn);
// Determine if we are writing from reservation.
// Get the best matching reservation if so. Allocate padding
// if necessary.
//
int paddingSize = 0;
if (this.reservationCollection != null)
{
this.reservationSize = this.reservationCollection.GetMatchingReservation(this.totalRecordSize);
if (this.reservationSize < this.totalRecordSize)
{
// An internal consistency check has failed. The indicates a bug in IO.Log's internal processing
// Rather than proceeding with non-deterministic execution and risking the loss or corruption of
// log records, we failfast the process.
DiagnosticUtility.FailFast("Somehow got a smaller reservation");
}
if (this.reservationSize <= 0)
{
// An internal consistency check has failed. The indicates a bug in IO.Log's internal processing
// Rather than proceeding with non-deterministic execution and risking the loss or corruption of
// log records, we failfast the process.
DiagnosticUtility.FailFast("Reservation size must be bigger than zero");
}
paddingSize = checked((int)(this.reservationSize -
this.totalRecordSize));
this.flags = Const.CLFS_FLAG_USE_RESERVATION;
}
// Allocate a new LogLogRecordHeader and set it up
// correctly.
//
byte[] headerBytes = new byte[LogLogRecordHeader.Size + paddingSize];
LogLogRecordHeader header = new LogLogRecordHeader(headerBytes);
header.MajorVersion = LogLogRecordHeader.CurrentMajorVersion;
header.MinorVersion = LogLogRecordHeader.CurrentMinorVersion;
header.Padding = (paddingSize != 0);
if (paddingSize != 0)
{
LogLogRecordHeader.EncodePaddingSize(headerBytes,
LogLogRecordHeader.Size,
paddingSize);
}
// Now we write-gather here, since WriteLogRestartArea does
// not support write-gather.
//
// (NOTE: totalRecordSize includes the size of the header,
// for consistency with reservations...)
//
long restartAreaSize = this.totalRecordSize + paddingSize;
this.restartArea = new byte[restartAreaSize];
restartAreaSize = 0;
Array.Copy(header.Bits,
0,
this.restartArea,
restartAreaSize,
header.Bits.Length);
restartAreaSize += header.Bits.Length;
for (int i = 0; i < this.data.Count; i++)
{
ArraySegment segment = this.data[i];
Array.Copy(segment.Array,
segment.Offset,
this.restartArea,
restartAreaSize,
segment.Count);
restartAreaSize += segment.Count;
}
if (restartAreaSize != this.restartArea.Length)
{
// An internal consistency check has failed. The indicates a bug in IO.Log's internal processing
// Rather than proceeding with non-deterministic execution and risking the loss or corruption of
// log records, we failfast the process.
DiagnosticUtility.FailFast("Did not do restartArea gather correctly");
}
this.currentState = State.Prepared;
}
void Pin()
{
if (this.pinnedResultHandle.IsAllocated)
{
// An internal consistency check has failed. The indicates a bug in IO.Log's internal processing
// Rather than proceeding with non-deterministic execution and risking the loss or corruption of
// log records, we failfast the process.
DiagnosticUtility.FailFast("Already pinned");
}
this.pinnedResultHandle = GCHandle.Alloc(this.boxedResultLsn,
GCHandleType.Pinned);
}
void Unpin()
{
if (!this.pinnedResultHandle.IsAllocated)
{
// An internal consistency check has failed. The indicates a bug in IO.Log's internal processing
// Rather than proceeding with non-deterministic execution and risking the loss or corruption of
// log records, we failfast the process.
DiagnosticUtility.FailFast("Already unpinned");
}
this.pinnedResultHandle.Free();
}
// Finish up. Synchronize the reservation collection, in the
// case of failure and success, capture the error (if any),
// and change state to completed.
//
void Complete(Exception error)
{
if (this.pinnedResultHandle.IsAllocated)
{
// An internal consistency check has failed. The indicates a bug in IO.Log's internal processing
// Rather than proceeding with non-deterministic execution and risking the loss or corruption of
// log records, we failfast the process.
DiagnosticUtility.FailFast("Must unpin before completing");
}
if (error != null)
{
// If we were writing from reservation, then we need
// to put the reservation back...
//
if (this.reservationCollection != null)
{
this.reservationCollection.InternalAddReservation(this.reservationSize);
this.reservationSize = 0;
}
}
this.exceptionResult = error;
this.currentState = State.Completed;
}
uint WriteLogRestartArea()
{
uint errorCode = Error.ERROR_SUCCESS;
// Ensure we are packed now
//
if (this.asyncResult != null)
{
this.asyncResult.Pack(this.boxedResultLsn);
}
try
{
unsafe
{
NativeOverlapped* overlapped;
if (this.asyncResult != null)
{
overlapped = this.asyncResult.NativeOverlapped;
if (overlapped == null)
{
// An internal consistency check has failed. The indicates a bug in IO.Log's internal processing
// Rather than proceeding with non-deterministic execution and risking the loss or corruption of
// log records, we failfast the process.
DiagnosticUtility.FailFast("Should have packed the async result already");
}
}
else
{
overlapped = null;
}
fixed (byte* pRestartArea = this.restartArea)
{
if (this.newBaseLsn != UInt64.MaxValue)
{
errorCode = UnsafeNativeMethods.WriteLogRestartArea(
this.recordSequence.MarshalContext,
pRestartArea,
this.restartArea.Length,
ref this.newBaseLsn,
this.flags,
IntPtr.Zero,
this.pinnedResultHandle.AddrOfPinnedObject(),
overlapped);
}
else
{
errorCode = UnsafeNativeMethods.WriteLogRestartAreaNoBase(
this.recordSequence.MarshalContext,
pRestartArea,
this.restartArea.Length,
this.flags,
IntPtr.Zero,
this.pinnedResultHandle.AddrOfPinnedObject(),
overlapped);
}
}
}
}
finally
{
if (this.asyncResult != null &&
errorCode != Error.ERROR_IO_PENDING)
{
this.asyncResult.Free();
}
}
return errorCode;
}
uint InvokePolicyEngine()
{
HandleLogFullCallback callback = null;
if (this.asyncResult != null)
{
callback = new HandleLogFullCallback(this.asyncResult.IOCompleted);
}
LogManagementAsyncResult logManagement;
logManagement = this.recordSequence.LogStore.LogManagement;
return logManagement.HandleLogFull(callback);
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ListViewGroupItemCollection.cs
- LassoHelper.cs
- DispatcherObject.cs
- StateValidator.cs
- BitVector32.cs
- WindowsTokenRoleProvider.cs
- WaitHandleCannotBeOpenedException.cs
- ServiceOperationParameter.cs
- CallbackDebugBehavior.cs
- XmlLanguage.cs
- ButtonBaseAdapter.cs
- DataFormats.cs
- KernelTypeValidation.cs
- XsltConvert.cs
- XsltArgumentList.cs
- _AuthenticationState.cs
- GridViewUpdatedEventArgs.cs
- DataRowComparer.cs
- EventRoute.cs
- WriteableBitmap.cs
- DesigntimeLicenseContextSerializer.cs
- WorkflowMarkupSerializerMapping.cs
- QilFunction.cs
- GenericXmlSecurityToken.cs
- SmtpTransport.cs
- Html32TextWriter.cs
- RpcAsyncResult.cs
- XmlTextAttribute.cs
- TypeDescriptionProviderAttribute.cs
- HtmlInputButton.cs
- ComponentGuaranteesAttribute.cs
- XmlSchemaObject.cs
- StreamSecurityUpgradeInitiator.cs
- ExtendedPropertyCollection.cs
- SqlConnectionStringBuilder.cs
- FilteredSchemaElementLookUpTable.cs
- Color.cs
- DataGridItemEventArgs.cs
- DragDropHelper.cs
- RequestQueryParser.cs
- JsonMessageEncoderFactory.cs
- CardSpaceException.cs
- Positioning.cs
- SqlNotificationEventArgs.cs
- MetadataArtifactLoader.cs
- UseLicense.cs
- NoResizeHandleGlyph.cs
- IgnoreFlushAndCloseStream.cs
- ExpressionConverter.cs
- DeflateStreamAsyncResult.cs
- ByteStream.cs
- WbmpConverter.cs
- Point3DKeyFrameCollection.cs
- PagesSection.cs
- XslTransform.cs
- PersonalizationAdministration.cs
- DBNull.cs
- DeflateEmulationStream.cs
- SwitchLevelAttribute.cs
- ContentPlaceHolder.cs
- WebPartTransformer.cs
- MenuEventArgs.cs
- TrackingQuery.cs
- WebHttpDispatchOperationSelector.cs
- AuthenticationModuleElementCollection.cs
- ZipIOCentralDirectoryFileHeader.cs
- ResourceExpressionEditor.cs
- XsdCachingReader.cs
- ActivityBindForm.cs
- SqlDuplicator.cs
- arabicshape.cs
- TwoPhaseCommitProxy.cs
- CompositeCollectionView.cs
- UnauthorizedAccessException.cs
- ToolStripOverflow.cs
- Bitmap.cs
- MaterializeFromAtom.cs
- SecurityDocument.cs
- ImageSourceConverter.cs
- XMLSchema.cs
- ContractUtils.cs
- TreeViewItemAutomationPeer.cs
- X509ThumbprintKeyIdentifierClause.cs
- ValueUtilsSmi.cs
- IisTraceWebEventProvider.cs
- ConnectionStringSettings.cs
- Schedule.cs
- GlobalItem.cs
- DataServices.cs
- PagedDataSource.cs
- Track.cs
- AstTree.cs
- InternalConfigSettingsFactory.cs
- ScrollChrome.cs
- StoreItemCollection.cs
- LambdaValue.cs
- X509Certificate2Collection.cs
- _NegoStream.cs
- _OverlappedAsyncResult.cs
- EnumType.cs