Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / Log / System / IO / Log / FileRecordSequence.cs / 1 / 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.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 (DiagnosticUtility.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. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- XsltArgumentList.cs
- MethodCallConverter.cs
- InstanceHandleConflictException.cs
- DefaultClaimSet.cs
- WorkflowViewService.cs
- SqlDataRecord.cs
- XmlHierarchicalEnumerable.cs
- DataGridViewLinkColumn.cs
- CompilerCollection.cs
- ControlValuePropertyAttribute.cs
- RIPEMD160.cs
- Win32.cs
- CodeGenerationManager.cs
- Int64KeyFrameCollection.cs
- DbCommandTree.cs
- HtmlElement.cs
- CodeGenerator.cs
- PropertyItemInternal.cs
- Vector3DAnimation.cs
- HttpRequestTraceRecord.cs
- SoapReflectionImporter.cs
- MultiSelectRootGridEntry.cs
- ManagementBaseObject.cs
- CancelEventArgs.cs
- MapPathBasedVirtualPathProvider.cs
- EnumUnknown.cs
- XmlTextWriter.cs
- CheckBoxPopupAdapter.cs
- recordstate.cs
- Point.cs
- ConfigurationLoaderException.cs
- RootProfilePropertySettingsCollection.cs
- Panel.cs
- FullTextState.cs
- InvalidAsynchronousStateException.cs
- RestHandlerFactory.cs
- ObjectContext.cs
- TransferRequestHandler.cs
- ISAPIWorkerRequest.cs
- BufferModeSettings.cs
- MouseGestureConverter.cs
- ComboBoxHelper.cs
- ChannelServices.cs
- SwitchLevelAttribute.cs
- StaticExtension.cs
- DropTarget.cs
- MessageHeaderDescriptionCollection.cs
- PassportAuthenticationModule.cs
- Thread.cs
- TextParentUndoUnit.cs
- versioninfo.cs
- XmlStreamStore.cs
- RuleSettingsCollection.cs
- DriveInfo.cs
- DataBinder.cs
- EndOfStreamException.cs
- DesignerLoader.cs
- RuntimeConfig.cs
- WeakReferenceEnumerator.cs
- Stack.cs
- XsdDataContractImporter.cs
- ModelItemCollectionImpl.cs
- ProtocolInformationReader.cs
- RoleGroupCollection.cs
- SqlInfoMessageEvent.cs
- EntityType.cs
- ReferenceList.cs
- NetCodeGroup.cs
- NameValueCollection.cs
- serverconfig.cs
- ToggleProviderWrapper.cs
- ZipPackage.cs
- DataRelationCollection.cs
- XmlCompatibilityReader.cs
- ExceptionRoutedEventArgs.cs
- Assembly.cs
- SiteMapProvider.cs
- SymLanguageVendor.cs
- SmiMetaData.cs
- ClientOptions.cs
- RightsManagementEncryptedStream.cs
- ConfigurationElementProperty.cs
- _ProxyRegBlob.cs
- LoadedOrUnloadedOperation.cs
- Encoder.cs
- XXXOnTypeBuilderInstantiation.cs
- Line.cs
- DbConnectionPoolCounters.cs
- smtpconnection.cs
- GuidTagList.cs
- Signature.cs
- RangeBase.cs
- SmiRequestExecutor.cs
- SHA384Managed.cs
- XmlEventCache.cs
- XmlSchemaInclude.cs
- SaveFileDialog.cs
- XmlAttribute.cs
- FileVersionInfo.cs
- ButtonBaseAutomationPeer.cs