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
- ReliableSessionBindingElementImporter.cs
- WindowsEditBoxRange.cs
- AsyncOperationContext.cs
- CultureInfo.cs
- GuidTagList.cs
- XpsPackagingException.cs
- CodeCatchClauseCollection.cs
- XmlC14NWriter.cs
- DesignerActionPropertyItem.cs
- KnownIds.cs
- Schema.cs
- Accessors.cs
- UriScheme.cs
- MenuItemAutomationPeer.cs
- RuntimeConfigurationRecord.cs
- ObservableCollectionDefaultValueFactory.cs
- HtmlWindow.cs
- SendSecurityHeaderElementContainer.cs
- _SingleItemRequestCache.cs
- FontClient.cs
- PreservationFileWriter.cs
- WizardPanel.cs
- MatchingStyle.cs
- FactoryRecord.cs
- Atom10FormatterFactory.cs
- __ConsoleStream.cs
- FloatSumAggregationOperator.cs
- Grid.cs
- FormsAuthenticationUserCollection.cs
- DayRenderEvent.cs
- BufferModeSettings.cs
- FormatStringEditor.cs
- LinqDataSourceSelectEventArgs.cs
- XmlNodeList.cs
- OutputCache.cs
- KeyGesture.cs
- UserNameServiceElement.cs
- StdValidatorsAndConverters.cs
- XmlNullResolver.cs
- ReflectEventDescriptor.cs
- FaultPropagationRecord.cs
- TableSectionStyle.cs
- Solver.cs
- HashMembershipCondition.cs
- TaiwanLunisolarCalendar.cs
- ExtentJoinTreeNode.cs
- mediaclock.cs
- OdbcConnectionStringbuilder.cs
- OptimizerPatterns.cs
- PageAsyncTaskManager.cs
- ObjectViewFactory.cs
- StructuralObject.cs
- DbProviderSpecificTypePropertyAttribute.cs
- TextParagraphCache.cs
- SqlTransaction.cs
- RtfToken.cs
- Range.cs
- LambdaCompiler.ControlFlow.cs
- StructuralObject.cs
- MultiAsyncResult.cs
- WorkflowTraceTransfer.cs
- CodeObjectCreateExpression.cs
- DesignTableCollection.cs
- ISFClipboardData.cs
- BinaryFormatter.cs
- CodeNamespace.cs
- AnnouncementEventArgs.cs
- ControlPropertyNameConverter.cs
- Globals.cs
- XamlStyleSerializer.cs
- ScriptBehaviorDescriptor.cs
- ObjectPersistData.cs
- SQLGuid.cs
- HttpModule.cs
- FactoryRecord.cs
- SystemWebCachingSectionGroup.cs
- glyphs.cs
- WindowCollection.cs
- ScrollProviderWrapper.cs
- DataTableMappingCollection.cs
- OdbcHandle.cs
- XmlNodeReader.cs
- RC2CryptoServiceProvider.cs
- PaperSize.cs
- SystemTcpConnection.cs
- EntityDataSourceChangedEventArgs.cs
- SynchronizedInputPattern.cs
- TailCallAnalyzer.cs
- CompilerGlobalScopeAttribute.cs
- CompilerInfo.cs
- Point.cs
- SuppressMergeCheckAttribute.cs
- FontStretchConverter.cs
- MatrixKeyFrameCollection.cs
- _HelperAsyncResults.cs
- ObjectItemCollectionAssemblyCacheEntry.cs
- FontUnit.cs
- UserControl.cs
- FunctionDefinition.cs
- SecurityUtils.cs