| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- //----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //----------------------------------------------------------------------------
- namespace System.ServiceModel.Channels
- {
- using System.Runtime;
- sealed class ReliableInputConnection
- {
- bool isLastKnown = false;
- bool isSequenceClosed = false;
- Int64 last = 0;
- SequenceRangeCollection ranges = SequenceRangeCollection.Empty;
- ReliableMessagingVersion reliableMessagingVersion;
- InterruptibleWaitObject shutdownWaitObject = new InterruptibleWaitObject(false);
- bool terminated = false;
- InterruptibleWaitObject terminateWaitObject = new InterruptibleWaitObject(false, false);
- public ReliableInputConnection()
- {
- }
- public bool AllAdded
- {
- get
- {
- return (this.ranges.Count == 1
- && this.ranges[0].Lower == 1
- && this.ranges[0].Upper == this.last)
- || this.isLastKnown;
- }
- }
- public bool IsLastKnown
- {
- get
- {
- return this.last != 0 || this.isLastKnown;
- }
- }
- public bool IsSequenceClosed
- {
- get
- {
- return this.isSequenceClosed;
- }
- }
- public Int64 Last
- {
- get
- {
- return this.last;
- }
- }
- public SequenceRangeCollection Ranges
- {
- get
- {
- return this.ranges;
- }
- }
- public ReliableMessagingVersion ReliableMessagingVersion
- {
- set
- {
- this.reliableMessagingVersion = value;
- }
- }
- public void Abort(ChannelBase channel)
- {
- this.shutdownWaitObject.Abort(channel);
- this.terminateWaitObject.Abort(channel);
- }
- public bool CanMerge(Int64 sequenceNumber)
- {
- return ReliableInputConnection.CanMerge(sequenceNumber, this.ranges);
- }
- // Returns true if merging the number will not increase the number of ranges past MaxSequenceRanges.
- public static bool CanMerge(Int64 sequenceNumber, SequenceRangeCollection ranges)
- {
- if (ranges.Count < ReliableMessagingConstants.MaxSequenceRanges)
- {
- return true;
- }
- ranges = ranges.MergeWith(sequenceNumber);
- return ranges.Count <= ReliableMessagingConstants.MaxSequenceRanges;
- }
- public void Fault(ChannelBase channel)
- {
- this.shutdownWaitObject.Fault(channel);
- this.terminateWaitObject.Fault(channel);
- }
- public bool IsValid(Int64 sequenceNumber, bool isLast)
- {
- if (this.reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
- {
- if (isLast)
- {
- if (this.last == 0)
- {
- if (this.ranges.Count > 0)
- {
- return sequenceNumber > this.ranges[this.ranges.Count - 1].Upper;
- }
- else
- {
- return true;
- }
- }
- else
- {
- return sequenceNumber == this.last;
- }
- }
- else if (this.last > 0)
- {
- return sequenceNumber < this.last;
- }
- }
- else
- {
- if (this.isLastKnown)
- {
- return this.ranges.Contains(sequenceNumber);
- }
- }
- return true;
- }
- public void Merge(Int64 sequenceNumber, bool isLast)
- {
- this.ranges = this.ranges.MergeWith(sequenceNumber);
- if (isLast)
- this.last = sequenceNumber;
- if (this.AllAdded)
- this.shutdownWaitObject.Set();
- }
- public bool SetCloseSequenceLast(Int64 last)
- {
- WsrmUtilities.AssertWsrm11(this.reliableMessagingVersion);
- bool validLast;
- if ((last < 1) || (this.ranges.Count == 0))
- {
- validLast = true;
- }
- else
- {
- validLast = last >= this.ranges[this.ranges.Count - 1].Upper;
- }
- if (validLast)
- {
- this.isSequenceClosed = true;
- this.SetLast(last);
- }
- return validLast;
- }
- void SetLast(Int64 last)
- {
- if (this.isLastKnown)
- {
- throw Fx.AssertAndThrow("Last can only be set once.");
- }
- this.last = last;
- this.isLastKnown = true;
- this.shutdownWaitObject.Set();
- }
- // Two error cases:
- // (1) The sequence contains holes.
- // (2) TerminateSequence.LastMsgNumber < last received message number.
- // In both cases the channel should be faulted. In case (2) the channel should send a fault.
- public bool SetTerminateSequenceLast(Int64 last, out bool isLastLargeEnough)
- {
- WsrmUtilities.AssertWsrm11(this.reliableMessagingVersion);
- isLastLargeEnough = true;
- // unspecified last
- if (last < 1)
- {
- return false;
- }
- int rangeCount = this.ranges.Count;
- Int64 lastReceived = (rangeCount > 0) ? this.ranges[rangeCount - 1].Upper : 0;
- // last is too small to be valid
- if (last < lastReceived)
- {
- isLastLargeEnough = false;
- return false;
- }
- // there is a hole in the sequence
- if ((rangeCount > 1) || (last > lastReceived))
- {
- return false;
- }
- this.SetLast(last);
- return true;
- }
- public bool Terminate()
- {
- if ((this.reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
- || this.isSequenceClosed)
- {
- if (!this.terminated && this.AllAdded)
- {
- this.terminateWaitObject.Set();
- this.terminated = true;
- }
- return this.terminated;
- }
- return this.isLastKnown;
- }
- public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
- {
- OperationWithTimeoutBeginCallback[] beginCallbacks
- = new OperationWithTimeoutBeginCallback[] { shutdownWaitObject.BeginWait, terminateWaitObject.BeginWait };
- OperationEndCallback[] endCallbacks
- = new OperationEndCallback[] { shutdownWaitObject.EndWait, terminateWaitObject.EndWait };
- return OperationWithTimeoutComposer.BeginComposeAsyncOperations(timeout, beginCallbacks, endCallbacks, callback, state);
- }
- public void Close(TimeSpan timeout)
- {
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- this.shutdownWaitObject.Wait(timeoutHelper.RemainingTime());
- this.terminateWaitObject.Wait(timeoutHelper.RemainingTime());
- }
- public void EndClose(IAsyncResult result)
- {
- OperationWithTimeoutComposer.EndComposeAsyncOperations(result);
- }
- }
- }
|