Code:
/ 4.0 / 4.0 / 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. //------------------------------------------------------------ // 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 EventHandler TailPinned; 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
- StandardOleMarshalObject.cs
- DataStorage.cs
- KeyEvent.cs
- OrderPreservingPipeliningMergeHelper.cs
- RoleBoolean.cs
- SystemWebCachingSectionGroup.cs
- PropertyChangedEventArgs.cs
- BroadcastEventHelper.cs
- FileUtil.cs
- CompositeTypefaceMetrics.cs
- SystemResourceHost.cs
- PropertyKey.cs
- UnhandledExceptionEventArgs.cs
- WebBrowsableAttribute.cs
- HostedTcpTransportManager.cs
- ResourceProviderFactory.cs
- XmlEncoding.cs
- HtmlInputHidden.cs
- StringPropertyBuilder.cs
- RangeValidator.cs
- DispatcherObject.cs
- OrthographicCamera.cs
- EllipseGeometry.cs
- Visitor.cs
- GeneralTransform3DTo2DTo3D.cs
- LinkedResourceCollection.cs
- FixedPageStructure.cs
- AddInIpcChannel.cs
- CountAggregationOperator.cs
- RemoteWebConfigurationHostStream.cs
- ThumbButtonInfo.cs
- MILUtilities.cs
- PagesChangedEventArgs.cs
- TypeCodeDomSerializer.cs
- ServiceHostingEnvironment.cs
- PlatformCulture.cs
- XamlToRtfWriter.cs
- ObjectContext.cs
- DataGridViewHeaderCell.cs
- DecoderNLS.cs
- DataColumn.cs
- Operator.cs
- ColorTranslator.cs
- ResourcePool.cs
- GridViewColumn.cs
- EntityParameter.cs
- AnnotationResourceCollection.cs
- LayoutTable.cs
- HtmlElementCollection.cs
- ProtocolsSection.cs
- DetailsViewModeEventArgs.cs
- WriteFileContext.cs
- UrlPropertyAttribute.cs
- FrameworkTemplate.cs
- CoreChannel.cs
- ProviderSettingsCollection.cs
- BaseDataList.cs
- CachedResourceDictionaryExtension.cs
- EmptyEnumerable.cs
- WindowsSysHeader.cs
- AbandonedMutexException.cs
- counter.cs
- SchemaTableColumn.cs
- InkCanvas.cs
- DataGridCaption.cs
- CalendarDataBindingHandler.cs
- SmtpFailedRecipientException.cs
- ProxyElement.cs
- ToolstripProfessionalRenderer.cs
- NullableIntSumAggregationOperator.cs
- ViewStateException.cs
- RelationshipFixer.cs
- TextServicesContext.cs
- _Rfc2616CacheValidators.cs
- WebWorkflowRole.cs
- MobileResource.cs
- CannotUnloadAppDomainException.cs
- TypeForwardedToAttribute.cs
- RichTextBoxConstants.cs
- DbConnectionPoolCounters.cs
- WorkBatch.cs
- HexParser.cs
- FontCacheLogic.cs
- CodeArrayIndexerExpression.cs
- PageAsyncTaskManager.cs
- TransactionInformation.cs
- CodeStatement.cs
- MailHeaderInfo.cs
- _Rfc2616CacheValidators.cs
- InternalConfigSettingsFactory.cs
- MD5CryptoServiceProvider.cs
- Transactions.cs
- HttpModuleActionCollection.cs
- ConnectionsZone.cs
- StringResourceManager.cs
- DefaultSerializationProviderAttribute.cs
- AndCondition.cs
- Font.cs
- CollectionContainer.cs
- CreatingCookieEventArgs.cs