Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / Log / System / IO / Log / FileRecordSequence.cs / 1305376 / FileRecordSequence.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.IO.Log { using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Security.AccessControl; using System.Runtime; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Diagnostics; using System.Threading; // FileRecordSequence uses Simple file log to write records to a file. public sealed class FileRecordSequence : IRecordSequence { SimpleFileLog log; bool retryAppend; object syncTailPinned = new object(); bool tailPinnedCalled = false; FileAccess access; FileRecordSequenceHelper frsHelper; long reservedBytes; object syncReservedBytes = new object(); int tailPinnedThreadID = -1; public FileRecordSequence(string path) : this(path, FileAccess.ReadWrite, 0) { } public FileRecordSequence(string path, FileAccess access) : this(path, access, 0) { } [PermissionSetAttribute(SecurityAction.Demand, Name="FullTrust")] public FileRecordSequence(string path, FileAccess access, int size) { if (size < 0) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentOutOfRange("size")); this.access = access; this.log = new SimpleFileLog(Path.GetFullPath(path), size); this.frsHelper = new FileRecordSequenceHelper(this.log); this.reservedBytes = 0; } public SequenceNumber BaseSequenceNumber { get { return this.frsHelper.BaseSequenceNumber; } } public SequenceNumber LastSequenceNumber { get { return this.frsHelper.LastSequenceNumber; } } public long MaximumRecordLength { get { return Int32.MaxValue; } } public long ReservedBytes { get { return this.reservedBytes; } } public bool RetryAppend { get { return this.retryAppend; } set { this.retryAppend = value; } } public SequenceNumber RestartSequenceNumber { get { return this.frsHelper.RestartSequenceNumber; } } public event EventHandlerTailPinned; public void AdvanceBaseSequenceNumber( SequenceNumber newBaseSequenceNumber) { this.frsHelper.AdvanceBaseSequeceNumber(newBaseSequenceNumber); } internal void AddReservation(long reservation) { lock (this.syncReservedBytes) { this.reservedBytes += reservation; } } internal void RemoveReservation(long reservation) { lock (this.syncReservedBytes) { this.reservedBytes -= reservation; } } public SequenceNumber Append( ArraySegment data, SequenceNumber nextUndoRecord, SequenceNumber previousRecord, RecordAppendOptions recordAppendOptions) { return Append(new ArraySegment [] { data }, nextUndoRecord, previousRecord, recordAppendOptions); } public SequenceNumber Append( ArraySegment data, SequenceNumber nextUndoRecord, SequenceNumber previousRecord, RecordAppendOptions recordAppendOptions, ReservationCollection reservations) { return Append(new ArraySegment [] { data }, nextUndoRecord, previousRecord, recordAppendOptions, reservations); } public SequenceNumber Append( IList > data, SequenceNumber nextUndoRecord, SequenceNumber previousRecord, RecordAppendOptions recordAppendOptions) { if (data == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentNull("data")); } if ((this.access & FileAccess.Write) == 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.NotSupported(SR.NotSupported_ReadOnly)); } if(recordAppendOptions > (RecordAppendOptions.ForceAppend | RecordAppendOptions.ForceFlush) || recordAppendOptions < RecordAppendOptions.None) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentOutOfRange("recordAppendOptions")); } SequenceNumber sn; bool forceFlush = (recordAppendOptions & RecordAppendOptions.ForceFlush) != 0; try { sn = frsHelper.Append(data, nextUndoRecord, previousRecord, forceFlush); } catch (SequenceFullException) { RaiseTailPinnedEvent(); if (this.RetryAppend) { sn = frsHelper.Append(data, nextUndoRecord, previousRecord, forceFlush); } else { throw; } } return sn; } public SequenceNumber Append( IList > data, SequenceNumber nextUndoRecord, SequenceNumber previousRecord, RecordAppendOptions recordAppendOptions, ReservationCollection reservations) { int size = 0; if (reservations == null) { return Append(data, nextUndoRecord, previousRecord, recordAppendOptions); } if (data == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentNull("data")); } FileReservationCollection reservationCollection = reservations as FileReservationCollection; if (reservationCollection == null || !reservationCollection.IsMyCollection(this)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.LogRecSeq_InvalidReservationCollection)); } for (int i = 0; i < data.Count; i++) { size += data[i].Count; } long reservation = reservationCollection.GetBestMatchingReservation(size); if (reservation < 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ReservationNotFound()); } bool throwing = true; try { SequenceNumber returnValue = this.Append(data, nextUndoRecord, previousRecord, recordAppendOptions); throwing = false; return returnValue; } finally { if (throwing) { reservationCollection.Add(reservation); } } } public IAsyncResult BeginAppend( ArraySegment data, SequenceNumber nextUndoRecord, SequenceNumber previousRecord, RecordAppendOptions recordAppendOptions, AsyncCallback callback, object state) { return BeginAppend(new ArraySegment [] { data }, nextUndoRecord, previousRecord, recordAppendOptions, callback, state); } public IAsyncResult BeginAppend( ArraySegment data, SequenceNumber nextUndoRecord, SequenceNumber previousRecord, RecordAppendOptions recordAppendOptions, ReservationCollection reservations, AsyncCallback callback, object state) { return BeginAppend(new ArraySegment [] { data }, nextUndoRecord, previousRecord, recordAppendOptions, reservations, callback, state); } public IAsyncResult BeginAppend( IList > data, SequenceNumber nextUndoRecord, SequenceNumber previousRecord, RecordAppendOptions recordAppendOptions, AsyncCallback callback, object state) { SequenceNumber result = Append(data, nextUndoRecord, previousRecord, recordAppendOptions); return new FileRecordSequenceCompletedAsyncResult(result, callback, state, Work.Append); } public IAsyncResult BeginAppend( IList > data, SequenceNumber nextUndoRecord, SequenceNumber previousRecord, RecordAppendOptions recordAppendOptions, ReservationCollection reservations, AsyncCallback callback, object state) { SequenceNumber result = Append(data, nextUndoRecord, previousRecord, recordAppendOptions, reservations); return new FileRecordSequenceCompletedAsyncResult(result, callback, state, Work.Append); } public IAsyncResult BeginFlush( SequenceNumber sequenceNumber, AsyncCallback callback, object state) { SequenceNumber result = this.Flush(sequenceNumber); return new FileRecordSequenceCompletedAsyncResult(result, callback, state, Work.Flush); } public IAsyncResult BeginReserveAndAppend( ArraySegment data, SequenceNumber nextUndoRecord, SequenceNumber previousRecord, RecordAppendOptions recordAppendOptions, ReservationCollection reservationCollection, long[] reservations, AsyncCallback callback, object state) { return BeginReserveAndAppend(new ArraySegment [] { data }, nextUndoRecord, previousRecord, recordAppendOptions, reservationCollection, reservations, callback, state); } public IAsyncResult BeginReserveAndAppend( IList > data, SequenceNumber nextUndoRecord, SequenceNumber previousRecord, RecordAppendOptions recordAppendOptions, ReservationCollection reservationCollection, long[] reservations, AsyncCallback callback, object state) { SequenceNumber result = ReserveAndAppend( data, nextUndoRecord, previousRecord, recordAppendOptions, reservationCollection, reservations); return new FileRecordSequenceCompletedAsyncResult(result, callback, state, Work.ReserveAndAppend); } public IAsyncResult BeginWriteRestartArea( ArraySegment data, SequenceNumber newBaseSeqNum, ReservationCollection reservation, AsyncCallback callback, object state) { return BeginWriteRestartArea(new ArraySegment [] { data }, newBaseSeqNum, reservation, callback, state); } public IAsyncResult BeginWriteRestartArea( IList > data, SequenceNumber newBaseSeqNum, ReservationCollection reservation, AsyncCallback callback, object state) { SequenceNumber result = WriteRestartArea(data, newBaseSeqNum, reservation); return new FileRecordSequenceCompletedAsyncResult(result, callback, state, Work.WriteRestartArea); } public ReservationCollection CreateReservationCollection() { FileReservationCollection collection = new FileReservationCollection(this); return collection; } public void Dispose() { this.log.Close(); } public SequenceNumber EndAppend( IAsyncResult result) { FileRecordSequenceCompletedAsyncResult asyncResult = result as FileRecordSequenceCompletedAsyncResult; if (asyncResult == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.AsyncResult_Invalid)); } if (asyncResult.CompletedWork != Work.Append) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.AsyncResult_Invalid)); } return asyncResult.End(); } public SequenceNumber EndFlush( IAsyncResult result) { FileRecordSequenceCompletedAsyncResult asyncResult = result as FileRecordSequenceCompletedAsyncResult; if (asyncResult == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.AsyncResult_Invalid)); } if (asyncResult.CompletedWork != Work.Flush) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.AsyncResult_Invalid)); } return asyncResult.End(); } public SequenceNumber EndReserveAndAppend( IAsyncResult result) { FileRecordSequenceCompletedAsyncResult asyncResult = result as FileRecordSequenceCompletedAsyncResult; if (asyncResult == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.AsyncResult_Invalid)); } if (asyncResult.CompletedWork != Work.ReserveAndAppend) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.AsyncResult_Invalid)); } return asyncResult.End(); } public SequenceNumber EndWriteRestartArea( IAsyncResult result) { FileRecordSequenceCompletedAsyncResult asyncResult = result as FileRecordSequenceCompletedAsyncResult; if (asyncResult == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.AsyncResult_Invalid)); } if (asyncResult.CompletedWork != Work.WriteRestartArea) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.AsyncResult_Invalid)); } return asyncResult.End(); } public SequenceNumber Flush() { return this.Flush(SequenceNumber.Invalid); } public SequenceNumber Flush(SequenceNumber sequenceNumber) { return this.frsHelper.Flush(sequenceNumber); } // The first thread raises the tail pinned event. // All other threads wait until first thread finishes. private void RaiseTailPinnedEvent() { bool raiseEvent; Monitor.Enter(this.syncTailPinned); try { if (this.tailPinnedCalled) { if(this.tailPinnedThreadID == Thread.CurrentThread.ManagedThreadId) { // This is the same thread where RaiseTailPinnedEvent() was called and user // tried an Append or WriteRestartArea in the TailPinned callback. // Let the first call complete... // Trying to prevent deadlock... return; } else { // This is not the first thread. Wait until the first thread has handled tail pinned raiseEvent = false; Monitor.Wait(this.syncTailPinned); } } else { // First thread. Raise the event. this.tailPinnedCalled = true; raiseEvent = true; this.tailPinnedThreadID = Thread.CurrentThread.ManagedThreadId; } } finally { Monitor.Exit(this.syncTailPinned); } if (raiseEvent) { // First thread raises the event. Signals other waiting threads when done. try { EventHandler handler; handler = this.TailPinned; if (handler != null) { try { handler(this, new TailPinnedEventArgs(this.LastSequenceNumber)); } #pragma warning suppress 56500 // This is a callback exception catch (Exception exception) { if (Fx.IsFatal(exception)) throw; throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(exception); } } } finally { Monitor.Enter(this.syncTailPinned); try { this.tailPinnedCalled = false; this.tailPinnedThreadID = -1; // Signal waiting threads Monitor.PulseAll(this.syncTailPinned); } finally { Monitor.Exit(this.syncTailPinned); } } } } public IEnumerable ReadLogRecords( SequenceNumber start, LogRecordEnumeratorType logRecordEnum) { if ((this.access & FileAccess.Read) == 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.NotSupported(SR.NotSupported_WriteOnly)); } if (logRecordEnum < LogRecordEnumeratorType.User || logRecordEnum > LogRecordEnumeratorType.Next) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentOutOfRange("logRecordEnum")); } return new FileLogRecordEnumerable(this.log, start, logRecordEnum, false); } public IEnumerable ReadRestartAreas() { if ((this.access & FileAccess.Read) == 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.NotSupported(SR.NotSupported_WriteOnly)); } return new FileLogRecordEnumerable( this.log, this.frsHelper.RestartSequenceNumber, LogRecordEnumeratorType.Previous, true); } public SequenceNumber ReserveAndAppend( ArraySegment data, SequenceNumber nextUndoRecord, SequenceNumber previousRecord, RecordAppendOptions recordAppendOptions, ReservationCollection reservationCollection, params long[] reservations) { return ReserveAndAppend(new ArraySegment [] { data }, nextUndoRecord, previousRecord, recordAppendOptions, reservationCollection, reservations); } public SequenceNumber ReserveAndAppend( IList > data, SequenceNumber nextUndoRecord, SequenceNumber previousRecord, RecordAppendOptions recordAppendOptions, ReservationCollection reservationCollection, params long[] reservations) { if (reservationCollection == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentNull("reservationCollection")); } if (reservations == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentNull("reservations")); } FileReservationCollection fileResCollection = null; fileResCollection = reservationCollection as FileReservationCollection; if (fileResCollection == null || !fileResCollection.IsMyCollection(this)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.LogRecSeq_InvalidReservationCollection)); } foreach (long reservationSize in reservations) { if (reservationSize < 0) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentOutOfRange("reservations")); } foreach (long reservationSize in reservations) { fileResCollection.Add(reservationSize); } bool throwing = true; try { SequenceNumber returnValue = Append(data, nextUndoRecord, previousRecord, recordAppendOptions); throwing = false; return returnValue; } finally { if (throwing && fileResCollection != null) { foreach (long reservationSize in reservations) { fileResCollection.Remove(reservationSize); } } } } public SequenceNumber WriteRestartArea( ArraySegment data) { return WriteRestartArea(new ArraySegment [] { data }); } public SequenceNumber WriteRestartArea( ArraySegment data, SequenceNumber newBaseSeqNum) { return WriteRestartArea(new ArraySegment [] { data }, newBaseSeqNum); } public SequenceNumber WriteRestartArea( ArraySegment data, SequenceNumber newBaseSeqNum, ReservationCollection reservations) { return WriteRestartArea(new ArraySegment [] { data }, newBaseSeqNum, reservations); } public SequenceNumber WriteRestartArea( IList > data) { return WriteRestartArea(data, this.BaseSequenceNumber); } public SequenceNumber WriteRestartArea( IList > data, SequenceNumber newBaseSeqNum) { if(newBaseSeqNum == SequenceNumber.Invalid) { newBaseSeqNum = this.BaseSequenceNumber; } try { return this.frsHelper.WriteRestartAreaInternal(data, newBaseSeqNum); } catch (SequenceFullException) { RaiseTailPinnedEvent(); if (this.RetryAppend) { return this.frsHelper.WriteRestartAreaInternal(data, newBaseSeqNum); } else { throw; } } } public SequenceNumber WriteRestartArea( IList > data, SequenceNumber newBaseSeqNum, ReservationCollection reservations) { long size = 0; if(data == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentNull("data")); } if (reservations == null) return WriteRestartArea(data, newBaseSeqNum); FileReservationCollection reservationCollection = reservations as FileReservationCollection; if (reservationCollection == null || !reservationCollection.IsMyCollection(this)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentInvalid(SR.LogRecSeq_InvalidReservationCollection)); } for (int i = 0; i < data.Count; i++) { size = checked(size + data[i].Count); } long reservation = reservationCollection.GetBestMatchingReservation(size); if (reservation < 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ReservationNotFound()); } bool throwing = true; try { SequenceNumber returnValue = WriteRestartArea(data, newBaseSeqNum); throwing = false; return returnValue; } finally { if (throwing) { reservationCollection.Add(reservation); } } } } } // 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
- ModelItemImpl.cs
- Animatable.cs
- ZoneIdentityPermission.cs
- CompilerGeneratedAttribute.cs
- MediaElementAutomationPeer.cs
- ErrorFormatterPage.cs
- ReadContentAsBinaryHelper.cs
- CellCreator.cs
- ScrollableControl.cs
- ThreadInterruptedException.cs
- EntityObject.cs
- DispatchChannelSink.cs
- IndexerNameAttribute.cs
- TextServicesContext.cs
- CellLabel.cs
- WebAdminConfigurationHelper.cs
- FrameworkElement.cs
- UnknownBitmapDecoder.cs
- TreeViewAutomationPeer.cs
- DbBuffer.cs
- DurableInstanceManager.cs
- CreateUserWizardAutoFormat.cs
- SoapIncludeAttribute.cs
- CookieParameter.cs
- UserPersonalizationStateInfo.cs
- HttpProfileGroupBase.cs
- PasswordRecovery.cs
- PackagePart.cs
- DataGridCellsPresenter.cs
- CatalogPart.cs
- CompatibleComparer.cs
- ByteStack.cs
- ResXFileRef.cs
- XmlValueConverter.cs
- HttpHandlerAction.cs
- ClientRuntimeConfig.cs
- ServiceContractGenerationContext.cs
- GridViewActionList.cs
- PreviewPrintController.cs
- CodeGen.cs
- StrongNameUtility.cs
- KeyboardNavigation.cs
- ImageSource.cs
- MultiView.cs
- Button.cs
- MetadataItem_Static.cs
- ListViewInsertedEventArgs.cs
- PtsContext.cs
- BaseCollection.cs
- ToolStripPanelRow.cs
- CompareValidator.cs
- Thumb.cs
- CachedBitmap.cs
- ValueType.cs
- XmlCollation.cs
- DetailsViewInsertEventArgs.cs
- AttributeXamlType.cs
- HMAC.cs
- SymbolMethod.cs
- TagElement.cs
- DataRelationPropertyDescriptor.cs
- EditBehavior.cs
- EventLogHandle.cs
- IImplicitResourceProvider.cs
- SHA384.cs
- AuthenticationManager.cs
- DataGridView.cs
- TreeNodeConverter.cs
- ListDictionaryInternal.cs
- PermissionSetEnumerator.cs
- StatusBarDesigner.cs
- DataTableCollection.cs
- Exceptions.cs
- Typeface.cs
- SessionStateContainer.cs
- BitmapEffectInput.cs
- ValueTypeFixupInfo.cs
- LostFocusEventManager.cs
- ReflectPropertyDescriptor.cs
- PlaceHolder.cs
- ShaderEffect.cs
- LambdaCompiler.Lambda.cs
- FrameSecurityDescriptor.cs
- ObjectCloneHelper.cs
- DataControlFieldHeaderCell.cs
- ProcessHostMapPath.cs
- TagMapInfo.cs
- PeerValidationBehavior.cs
- ServerValidateEventArgs.cs
- HighlightVisual.cs
- SqlXmlStorage.cs
- SQLInt32.cs
- SerializationEventsCache.cs
- WebPartHeaderCloseVerb.cs
- COM2ColorConverter.cs
- TypedTableGenerator.cs
- ConnectionManagementElementCollection.cs
- MembershipAdapter.cs
- ReferenceAssemblyAttribute.cs
- TemplateField.cs