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 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.
//------------------------------------------------------------
// 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
- Binding.cs
- SourceItem.cs
- StretchValidation.cs
- UIElementIsland.cs
- DriveInfo.cs
- OleCmdHelper.cs
- ExpressionBindingCollection.cs
- CodeSubDirectory.cs
- LogExtentCollection.cs
- CalendarDataBindingHandler.cs
- ValidationEventArgs.cs
- DoubleAnimation.cs
- VectorCollection.cs
- Models.cs
- XPathParser.cs
- DataColumnChangeEvent.cs
- GridEntryCollection.cs
- OrCondition.cs
- HttpProfileGroupBase.cs
- XmlDataLoader.cs
- EventsTab.cs
- DynamicPhysicalDiscoSearcher.cs
- XXXInfos.cs
- PathData.cs
- _FtpDataStream.cs
- ProtocolsConfiguration.cs
- WebColorConverter.cs
- Schedule.cs
- DashStyle.cs
- DesigntimeLicenseContextSerializer.cs
- TypeDescriptionProvider.cs
- SocketElement.cs
- _OSSOCK.cs
- SQLInt32Storage.cs
- Formatter.cs
- BindingBase.cs
- ColumnResizeUndoUnit.cs
- CheckedPointers.cs
- DataSourceDescriptorCollection.cs
- MetadataProperty.cs
- COM2PropertyDescriptor.cs
- Lookup.cs
- ClaimComparer.cs
- AbandonedMutexException.cs
- PolyLineSegment.cs
- ListViewDataItem.cs
- Boolean.cs
- FixUpCollection.cs
- EntityClientCacheEntry.cs
- VideoDrawing.cs
- TableLayoutPanelCellPosition.cs
- Vector.cs
- PeerTransportCredentialType.cs
- ImageAttributes.cs
- ClientBuildManager.cs
- TransformedBitmap.cs
- FileDialogPermission.cs
- ZipIOEndOfCentralDirectoryBlock.cs
- HttpProtocolReflector.cs
- TrackingRecord.cs
- DataMisalignedException.cs
- SiteMapDesignerDataSourceView.cs
- UnsafeNativeMethods.cs
- ExpandedWrapper.cs
- SqlBulkCopy.cs
- Html32TextWriter.cs
- ImageBrush.cs
- XmlSchemaGroupRef.cs
- GetWinFXPath.cs
- LinkConverter.cs
- SupportingTokenSecurityTokenResolver.cs
- MultiPropertyDescriptorGridEntry.cs
- WindowsGraphics.cs
- ControlsConfig.cs
- VariableQuery.cs
- AccessKeyManager.cs
- LambdaCompiler.ControlFlow.cs
- MemoryFailPoint.cs
- FtpCachePolicyElement.cs
- EntityTypeEmitter.cs
- ScalarRestriction.cs
- InheritanceContextChangedEventManager.cs
- OleDbErrorCollection.cs
- EntityContainerRelationshipSetEnd.cs
- BindingCompleteEventArgs.cs
- PointUtil.cs
- IsolatedStorageFile.cs
- SmtpNegotiateAuthenticationModule.cs
- GenerateTemporaryAssemblyTask.cs
- MaxValueConverter.cs
- CodeEventReferenceExpression.cs
- EntityClassGenerator.cs
- WebServiceFault.cs
- FormatConvertedBitmap.cs
- AudioFormatConverter.cs
- TargetControlTypeCache.cs
- WebPartZone.cs
- SafeTimerHandle.cs
- GeometryGroup.cs
- QueuedDeliveryRequirementsMode.cs