Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / Log / System / IO / Log / LogLogRecordEnumerator.cs / 1305376 / LogLogRecordEnumerator.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.IO.Log { using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; // Although we would normally not make an enumerator like this // thread-safe, we do so because we are dealing in unmanaged // memory. Specifically, we construct an UnmanagedMemoryStream // around a pointer that comes back from ReadLogRecord and // ReadNextLogRecord (in LogLogRecord). This is fine, so long as // we know that memory is valid. That memory is valid as long as // the read context is valid. When the read context moves on, or // becomes invalid, we must "detach" the current record, copying // the data into a managed array. // // Of necessity, we allocate the read context before the record, // and detach the record before freeing or moving the read // context. What if some malicious person engineered a ---- // condition between the allocate/move and the detach? In this // case, a log record might wind up un-detached, but pointing at // invalid memory. This is NOT GOOD. Hence the thread-safety. // class LogLogRecordEnumerator : IEnumerator{ enum State { BeforeFirst, Valid, AfterLast, Disposed } LogRecordSequence recordSequence; CLFS_CONTEXT_MODE mode; ulong startLsn; State state; object syncRoot; SafeReadContext readContext; LogLogRecord current; internal LogLogRecordEnumerator(LogRecordSequence recordSequence, CLFS_CONTEXT_MODE mode, ulong startLsn) { this.recordSequence = recordSequence; this.mode = mode; this.startLsn = startLsn; this.syncRoot = new object(); this.state = State.BeforeFirst; } object IEnumerator.Current { get { return this.Current; } } public LogRecord Current { get { lock(this.syncRoot) { if (this.state == State.Disposed) #pragma warning suppress 56503 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ObjectDisposed()); // IEnumerable interface contract for "current" member can throw InvalidOperationException. Suppressing this warning. if (this.state == State.BeforeFirst) #pragma warning suppress 56503 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.EnumNotStarted()); if (this.state == State.AfterLast) #pragma warning suppress 56503 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.EnumEnded()); return this.current; } } } public void Dispose() { lock(this.syncRoot) { if (this.current != null) { this.current.Detach(); this.current = null; } if ((this.readContext != null) && (!this.readContext.IsInvalid)) { this.readContext.Close(); } this.state = State.Disposed; } } public bool MoveNext() { lock(this.syncRoot) { if (this.state == State.Disposed) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ObjectDisposed()); if (this.state == State.AfterLast) return false; if (this.readContext == null) { return ReadLogRecord(); } else { if (this.current != null) this.current.Detach(); return ReadNextLogRecord(); } } } bool ReadLogRecord() { if (!((this.readContext == null || this.readContext.IsInvalid) && (this.current == 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 only call this for first record!"); } unsafe { byte *readBuffer; int bufferLength; byte recordType; ulong lsnUser; ulong lsnPrevious; if (!UnsafeNativeMethods.ReadLogRecordSync( this.recordSequence.MarshalContext, ref this.startLsn, this.mode, out readBuffer, out bufferLength, out recordType, out lsnUser, out lsnPrevious, out this.readContext)) { this.state = State.AfterLast; return false; } if ((recordType & Const.ClfsDataRecord) != 0) { this.current = new LogLogRecord( new SequenceNumber(this.startLsn), new SequenceNumber(lsnUser), new SequenceNumber(lsnPrevious), readBuffer, bufferLength); this.state = State.Valid; return true; } else { return ReadNextLogRecord(); } } } bool ReadNextLogRecord() { if (this.readContext == null || this.readContext.IsInvalid) { // 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 only be called for records after the first!"); } unsafe { byte *readBuffer; int bufferLength; byte recordType = Const.ClfsDataRecord; ulong lsnUser; ulong lsnPrevious; ulong lsnRecord; if (!UnsafeNativeMethods.ReadNextLogRecordSync( this.readContext, out readBuffer, out bufferLength, ref recordType, out lsnUser, out lsnPrevious, out lsnRecord)) { this.state = State.AfterLast; return false; } this.current = new LogLogRecord( new SequenceNumber(lsnRecord), new SequenceNumber(lsnUser), new SequenceNumber(lsnPrevious), readBuffer, bufferLength); this.state = State.Valid; return true; } } public void Reset() { lock (this.syncRoot) { if (this.state == State.Disposed) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ObjectDisposed()); if (this.current != null) { this.current.Detach(); this.current = null; } if ((this.readContext != null) && (!this.readContext.IsInvalid)) { this.readContext.Close(); this.readContext = null; } this.state = State.BeforeFirst; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.IO.Log { using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; // Although we would normally not make an enumerator like this // thread-safe, we do so because we are dealing in unmanaged // memory. Specifically, we construct an UnmanagedMemoryStream // around a pointer that comes back from ReadLogRecord and // ReadNextLogRecord (in LogLogRecord). This is fine, so long as // we know that memory is valid. That memory is valid as long as // the read context is valid. When the read context moves on, or // becomes invalid, we must "detach" the current record, copying // the data into a managed array. // // Of necessity, we allocate the read context before the record, // and detach the record before freeing or moving the read // context. What if some malicious person engineered a ---- // condition between the allocate/move and the detach? In this // case, a log record might wind up un-detached, but pointing at // invalid memory. This is NOT GOOD. Hence the thread-safety. // class LogLogRecordEnumerator : IEnumerator { enum State { BeforeFirst, Valid, AfterLast, Disposed } LogRecordSequence recordSequence; CLFS_CONTEXT_MODE mode; ulong startLsn; State state; object syncRoot; SafeReadContext readContext; LogLogRecord current; internal LogLogRecordEnumerator(LogRecordSequence recordSequence, CLFS_CONTEXT_MODE mode, ulong startLsn) { this.recordSequence = recordSequence; this.mode = mode; this.startLsn = startLsn; this.syncRoot = new object(); this.state = State.BeforeFirst; } object IEnumerator.Current { get { return this.Current; } } public LogRecord Current { get { lock(this.syncRoot) { if (this.state == State.Disposed) #pragma warning suppress 56503 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ObjectDisposed()); // IEnumerable interface contract for "current" member can throw InvalidOperationException. Suppressing this warning. if (this.state == State.BeforeFirst) #pragma warning suppress 56503 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.EnumNotStarted()); if (this.state == State.AfterLast) #pragma warning suppress 56503 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.EnumEnded()); return this.current; } } } public void Dispose() { lock(this.syncRoot) { if (this.current != null) { this.current.Detach(); this.current = null; } if ((this.readContext != null) && (!this.readContext.IsInvalid)) { this.readContext.Close(); } this.state = State.Disposed; } } public bool MoveNext() { lock(this.syncRoot) { if (this.state == State.Disposed) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ObjectDisposed()); if (this.state == State.AfterLast) return false; if (this.readContext == null) { return ReadLogRecord(); } else { if (this.current != null) this.current.Detach(); return ReadNextLogRecord(); } } } bool ReadLogRecord() { if (!((this.readContext == null || this.readContext.IsInvalid) && (this.current == 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 only call this for first record!"); } unsafe { byte *readBuffer; int bufferLength; byte recordType; ulong lsnUser; ulong lsnPrevious; if (!UnsafeNativeMethods.ReadLogRecordSync( this.recordSequence.MarshalContext, ref this.startLsn, this.mode, out readBuffer, out bufferLength, out recordType, out lsnUser, out lsnPrevious, out this.readContext)) { this.state = State.AfterLast; return false; } if ((recordType & Const.ClfsDataRecord) != 0) { this.current = new LogLogRecord( new SequenceNumber(this.startLsn), new SequenceNumber(lsnUser), new SequenceNumber(lsnPrevious), readBuffer, bufferLength); this.state = State.Valid; return true; } else { return ReadNextLogRecord(); } } } bool ReadNextLogRecord() { if (this.readContext == null || this.readContext.IsInvalid) { // 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 only be called for records after the first!"); } unsafe { byte *readBuffer; int bufferLength; byte recordType = Const.ClfsDataRecord; ulong lsnUser; ulong lsnPrevious; ulong lsnRecord; if (!UnsafeNativeMethods.ReadNextLogRecordSync( this.readContext, out readBuffer, out bufferLength, ref recordType, out lsnUser, out lsnPrevious, out lsnRecord)) { this.state = State.AfterLast; return false; } this.current = new LogLogRecord( new SequenceNumber(lsnRecord), new SequenceNumber(lsnUser), new SequenceNumber(lsnPrevious), readBuffer, bufferLength); this.state = State.Valid; return true; } } public void Reset() { lock (this.syncRoot) { if (this.state == State.Disposed) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ObjectDisposed()); if (this.current != null) { this.current.Detach(); this.current = null; } if ((this.readContext != null) && (!this.readContext.IsInvalid)) { this.readContext.Close(); this.readContext = null; } this.state = State.BeforeFirst; } } } } // 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
- MenuItemStyleCollectionEditor.cs
- GiveFeedbackEvent.cs
- NonBatchDirectoryCompiler.cs
- QilStrConcatenator.cs
- ReflectionUtil.cs
- OracleBinary.cs
- XmlSchemaAny.cs
- BitmapEncoder.cs
- initElementDictionary.cs
- WindowsFormsHelpers.cs
- Color.cs
- ValidatorCompatibilityHelper.cs
- PackagePartCollection.cs
- XPathScanner.cs
- JpegBitmapDecoder.cs
- GridViewAutoFormat.cs
- TypeToArgumentTypeConverter.cs
- Utility.cs
- ConfigurationValidatorBase.cs
- StorageMappingFragment.cs
- XmlCodeExporter.cs
- AssociativeAggregationOperator.cs
- Psha1DerivedKeyGeneratorHelper.cs
- SHA512.cs
- ObjectDataSource.cs
- NullableLongMinMaxAggregationOperator.cs
- CharEntityEncoderFallback.cs
- SQLDecimal.cs
- SchemaNames.cs
- IndependentAnimationStorage.cs
- AuthorizationContext.cs
- HandleTable.cs
- EnumValAlphaComparer.cs
- ToolboxItemSnapLineBehavior.cs
- XmlAttributeOverrides.cs
- FieldToken.cs
- ImageCodecInfoPrivate.cs
- BindingMAnagerBase.cs
- WarningException.cs
- _Rfc2616CacheValidators.cs
- Label.cs
- SmiEventSink_Default.cs
- InteropBitmapSource.cs
- PiiTraceSource.cs
- WebPartDisplayModeCollection.cs
- MailHeaderInfo.cs
- ApplicationFileCodeDomTreeGenerator.cs
- PolyLineSegmentFigureLogic.cs
- SettingsContext.cs
- HandlerMappingMemo.cs
- ImageBrush.cs
- UserControlBuildProvider.cs
- EdmConstants.cs
- ModelTreeEnumerator.cs
- UnsafeNativeMethodsTablet.cs
- BuildTopDownAttribute.cs
- SmiEventSink_DeferedProcessing.cs
- SmtpNetworkElement.cs
- ExeContext.cs
- MailDefinition.cs
- NavigatorOutput.cs
- GCHandleCookieTable.cs
- RadialGradientBrush.cs
- CompoundFileReference.cs
- ParentControlDesigner.cs
- StringExpressionSet.cs
- ForwardPositionQuery.cs
- XmlDictionary.cs
- FormatSettings.cs
- RuntimeEnvironment.cs
- PolyBezierSegment.cs
- followingquery.cs
- Identity.cs
- MenuAdapter.cs
- tooltip.cs
- MarshalByValueComponent.cs
- Point3DAnimationUsingKeyFrames.cs
- SelectedDatesCollection.cs
- GenericIdentity.cs
- TextEditorCopyPaste.cs
- DataGrid.cs
- ToolboxItemCollection.cs
- IndexedString.cs
- FrameAutomationPeer.cs
- GroupStyle.cs
- ByteStreamMessageUtility.cs
- NoPersistHandle.cs
- URLEditor.cs
- Version.cs
- LocatorPartList.cs
- CompositeFontInfo.cs
- SqlNotificationRequest.cs
- ScriptMethodAttribute.cs
- _HeaderInfo.cs
- CompiledIdentityConstraint.cs
- WebPartDisplayModeCancelEventArgs.cs
- MsmqIntegrationProcessProtocolHandler.cs
- CachedCompositeFamily.cs
- BaseResourcesBuildProvider.cs
- PngBitmapEncoder.cs