public void OnLinkClosed(AmqpLink link) { int settledCount = 0; lock (this.syncRoot) { Delivery current = this.firstUnsettled; while (current != null) { Delivery delivery = current; current = current.Next; if (delivery.Link == link) { Delivery.Remove(ref this.firstUnsettled, ref this.lastUnsettled, delivery); settledCount++; } } } if (settledCount > 0) { this.OnWindowMoved(settledCount); } }
void SendDisposition() { List <DispositionInfo> disposedDeliveries = new List <DispositionInfo>(); int settledCount = 0; lock (this.syncRoot) { Delivery current = this.firstUnsettled; Delivery firstChanged = null; uint? lastId = null; while (current != null) { if (current.StateChanged) { if (firstChanged == null) { firstChanged = current; } else { if (current.Settled == firstChanged.Settled && CanBatch(current.State as Outcome, firstChanged.State as Outcome)) { lastId = current.DeliveryId.Value; } else { disposedDeliveries.Add(new DispositionInfo() { First = firstChanged, Last = lastId }); firstChanged = current; lastId = null; } } // Move next and remove if settled if (current.Settled) { Delivery temp = current; current = current.Next; ++settledCount; Delivery.Remove(ref this.firstUnsettled, ref this.lastUnsettled, temp); } else { current.StateChanged = false; current = current.Next; } } else { if (firstChanged != null) { disposedDeliveries.Add(new DispositionInfo() { First = firstChanged, Last = lastId }); firstChanged = null; lastId = null; } current = current.Next; } } if (firstChanged != null) { disposedDeliveries.Add(new DispositionInfo() { First = firstChanged, Last = lastId }); } this.sendingDisposition = false; } if (disposedDeliveries.Count > 0) { foreach (var info in disposedDeliveries) { this.SendDisposition(info); } } if (settledCount > 0) { this.OnWindowMoved(settledCount); } }
public void DisposeDelivery(Delivery delivery, bool settled, DeliveryState state, bool noFlush) { if (delivery.Settled) { this.OnWindowMoved(1); return; } bool scheduleTimer = false; Delivery toDispose = null; lock (this.syncRoot) { delivery.StateChanged = true; delivery.Settled = settled; delivery.State = state; if (!delivery.Batchable) { delivery.StateChanged = false; toDispose = delivery; if (delivery.Settled) { Delivery.Remove(ref this.firstUnsettled, ref this.lastUnsettled, delivery); } } else if (this.sendingDisposition || noFlush) { return; } else if (this.session.settings.DispositionInterval == TimeSpan.Zero || ++this.needDispositionCount >= this.session.settings.DispositionThreshold) { this.sendingDisposition = true; this.needDispositionCount = 0; } else if (!this.timerScheduled) { this.timerScheduled = true; scheduleTimer = true; } } if (toDispose != null) { this.SendDisposition(new DispositionInfo() { First = toDispose }); if (delivery.Settled) { this.OnWindowMoved(1); } } else if (scheduleTimer) { if (this.dispositionTimer == null) { this.dispositionTimer = new Timer( s => DispositionTimerCallback(s), this, this.session.settings.DispositionInterval, Timeout.InfiniteTimeSpan); } else { this.dispositionTimer.Change(this.session.settings.DispositionInterval, Timeout.InfiniteTimeSpan); } } else { this.SendDisposition(); } }
public void OnReceiveDisposition(Disposition disposition) { SequenceNumber first = disposition.First.Value; SequenceNumber last = disposition.Last ?? first; if (last < first) { // Should be a protocol error return; } List <Delivery> disposedDeliveries = new List <Delivery>(); int settledCount = 0; lock (this.syncRoot) { if (first >= this.nextDeliveryId) { return; } if (last > this.nextDeliveryId) { last = this.nextDeliveryId; } bool settled = disposition.Settled(); Delivery current = this.firstUnsettled; while (current != null) { SequenceNumber sn = current.DeliveryId.Value; if (sn < first) { current = current.Next; } else if (sn > last) { break; } else { Delivery delivery = current; current = current.Next; delivery.Settled = settled; delivery.State = disposition.State; if (settled) { ++settledCount; Delivery.Remove(ref this.firstUnsettled, ref this.lastUnsettled, delivery); } disposedDeliveries.Add(delivery); } } } if (disposedDeliveries.Count > 0) { foreach (Delivery delivery in disposedDeliveries) { delivery.Link.OnDisposeDelivery(delivery); } if (settledCount > 0) { this.OnWindowMoved(settledCount); } } }