public void DisposeDelivery(Delivery delivery, bool settled, DeliveryState state) { if (delivery.Settled) { this.Settle(); return; } Utils.Trace(TraceLevel.Verbose, "{0}: Dispose delivery {1}, settled:{2}.", this, delivery.DeliveryId.Value, settled); delivery.Settled = settled; delivery.State = state; delivery.StateChanged = true; int deliveryIndex = this.GetBufferIndex(delivery.DeliveryId.Value); Delivery oldDelivery = this.deliveryBuffer[deliveryIndex]; // replace the placeholder with the real delivery if (!object.ReferenceEquals(delivery, oldDelivery)) { this.deliveryBuffer[deliveryIndex] = delivery; } bool sendDispositionNow = !delivery.Batchable || Interlocked.Increment(ref this.needDispositionCount) >= this.dispositionThreshold; if (sendDispositionNow) { Interlocked.Exchange(ref this.needDispositionCount, 0); } this.SendDisposition(sendDispositionNow); }
public void SendDelivery(Delivery delivery) { this.outgoingChannel.SendDelivery(delivery); }
public void DisposeDelivery(AmqpLink link, Delivery delivery, bool settled, DeliveryState state) { if (link.IsReceiver) { this.incomingChannel.DisposeDelivery(delivery, settled, state); } else { this.outgoingChannel.DisposeDelivery(delivery, settled, state); } }
protected abstract void OnProcessTransfer(Delivery delivery, Transfer transfer);
bool OnSendDelivery(Delivery delivery) { // TODO: need lock here? if (!delivery.DeliveryId.HasValue && !this.TryAddDelivery(delivery)) { Utils.Trace(TraceLevel.Verbose, "{0}: Buffer full", this); return false; } bool more = true; while (more) { lock (this.SyncRoot) { if (this.remoteIncomingWindow == 0) { Utils.Trace(TraceLevel.Verbose, "{0}: Window closed", this); return false; } this.nextOutgoingId.Increment(); if (this.remoteIncomingWindow != uint.MaxValue) { --this.remoteIncomingWindow; --this.outgoingWindow; } } Transfer transfer = delivery.GetTransfer(this.maxFrameSize, delivery.Link.LocalHandle.Value, out more); transfer.DeliveryId = delivery.DeliveryId; if (delivery.Settled && !more) { // We want to settle the delivery after network write completes this.Session.SendCommand(transfer, this.onSettledDeliveryComplete, delivery); } else { this.Session.SendCommand(transfer); } } return true; }
protected override void OnProcessTransfer(Delivery delivery, Transfer transfer) { throw new AmqpException(AmqpError.NotAllowed); }
// up-down: from application to link to session (to send a disposition) public void DisposeDelivery(Delivery delivery, bool settled, DeliveryState state) { Utils.Trace(TraceLevel.Verbose, "{0}: Dispose delivery (id={1}, settle={2}, state={3}).", this, delivery.DeliveryId, settled, state); if (settled && !delivery.Settled) { lock (this.syncRoot) { if (!this.unsettledMap.Remove(delivery.DeliveryTag)) { delivery.State = new Rejected() { Error = AmqpError.NotFound }; delivery.Complete(); return; } } } this.Session.DisposeDelivery(this, delivery, settled, state); if (delivery.Settled) { delivery.Complete(); this.CheckFlow(); } }
bool TrySendDelivery(Delivery delivery) { Fx.Assert(delivery.DeliveryTag.Array != null, "delivery-tag must be set."); Fx.Assert(delivery.BytesTransfered == 0, "delivery has partially transfered."); Fx.Assert(delivery.Link == null, "delivery belongs to a different link."); // check link credit first bool canSend = false; lock (this.syncRoot) { canSend = this.TryChargeCredit(); } if (!canSend) { Utils.Trace(TraceLevel.Verbose, "{0}: Insufficient link credit. credit:{1}", this, this.linkCredit); return false; } delivery.Link = this; delivery.Settled = this.settings.SettleType == SettleMode.SettleOnSend; delivery.State = this.defaultOutcome; if (!delivery.Settled) { lock (this.syncRoot) { this.unsettledMap.Add(delivery.DeliveryTag, delivery); } } this.Session.SendDelivery(delivery); return true; }
public void SendDelivery(Delivery delivery) { this.pendingDeliveries.DoWork(delivery); }
protected void AbortDelivery(Delivery delivery) { delivery.State = AmqpConstants.ReleasedOutcome; delivery.Complete(); }
public void ProcessTransfer(Delivery delivery, Transfer transfer) { Utils.Trace(TraceLevel.Verbose, "{0}: Receive a transfer(id:{1}, settled:{2}).", this, transfer.DeliveryId, transfer.Settled()); if (delivery != null) { // handle new delivery bool creditAvailable = true; lock (this.syncRoot) { creditAvailable = this.TryChargeCredit(); } if (!creditAvailable) { Utils.Trace(TraceLevel.Verbose, "{0}: The transfer {1} was rejected due to insufficient link credit.", this, transfer.DeliveryId.Value); this.TryClose(new AmqpException(AmqpError.TransferLimitExceeded)); } else { delivery.Link = this; delivery.DeliveryId = transfer.DeliveryId.Value; delivery.DeliveryTag = transfer.DeliveryTag; delivery.Settled = transfer.Settled(); delivery.Batchable = transfer.Batchable(); TransactionalState txnState = transfer.State as TransactionalState; if (txnState != null) { delivery.TxnId = txnState.TxnId; } if (!delivery.Settled) { lock (this.syncRoot) { this.unsettledMap.Add(delivery.DeliveryTag, delivery); } } } } else { this.Session.OnAcceptIncomingTransfer(); } this.OnProcessTransfer(delivery, transfer); }
// bottom-up: from session disposition to link to application public void OnDisposeDelivery(Delivery delivery) { if (delivery.Settled) { lock (this.syncRoot) { this.unsettledMap.Remove(delivery.DeliveryTag); } delivery.Complete(); this.CheckFlow(); } }
public bool TryGetDelivery(ArraySegment<byte> deliveryTag, out Delivery delivery) { return this.unsettledMap.TryGetValue(deliveryTag, out delivery); }
protected bool TryAddDelivery(Delivery delivery) { if (this.nextDeliveryId >= (this.unsettledLwm + this.deliveryBuffer.Length)) { // buffer full return false; } int index = this.GetBufferIndex(this.nextDeliveryId.Value); if (this.deliveryBuffer[index] != null) { throw new InvalidOperationException(SRClient.DeliveryIDInUse); } delivery.DeliveryId = this.nextDeliveryId.Value; this.nextDeliveryId.Increment(); if (!delivery.Settled) { this.deliveryBuffer[index] = delivery; } return true; }
public bool TryGetDelivery(ArraySegment <byte> deliveryTag, out Delivery delivery) { return(this.unsettledMap.TryGetValue(deliveryTag, out delivery)); }
public void SendDelivery(Delivery delivery) { this.inflightDeliveries.DoWork(delivery); }
protected override void OnProcessTransfer(Delivery delivery, Transfer transfer) { Fx.Assert(delivery == null || object.ReferenceEquals(delivery, this.currentDelivery), "The delivery must be null or must be the same as the current message."); this.currentDelivery.AddPayload(transfer.Payload); if (!transfer.More()) { Utils.Trace(TraceLevel.Debug, "{0}: Complete a message with payload from {1} transfers.", this, this.currentDelivery.Count); AmqpMessage message = this.currentDelivery.GetMessage(); this.currentDelivery = null; this.OnReceiveMessage(message); } }