예제 #1
0
            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);
            }
예제 #2
0
 public void SendDelivery(Delivery delivery)
 {
     this.outgoingChannel.SendDelivery(delivery);
 }
예제 #3
0
 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);
     }
 }
예제 #4
0
 protected abstract void OnProcessTransfer(Delivery delivery, Transfer transfer);
예제 #5
0
            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;
            }
예제 #6
0
 protected override void OnProcessTransfer(Delivery delivery, Transfer transfer)
 {
     throw new AmqpException(AmqpError.NotAllowed);
 }
예제 #7
0
        // 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();
            }
        }
예제 #8
0
        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;
        }
예제 #9
0
 public void SendDelivery(Delivery delivery)
 {
     this.pendingDeliveries.DoWork(delivery);
 }
예제 #10
0
 protected void AbortDelivery(Delivery delivery)
 {
     delivery.State = AmqpConstants.ReleasedOutcome;
     delivery.Complete();
 }
예제 #11
0
 protected abstract void OnProcessTransfer(Delivery delivery, Transfer transfer);
예제 #12
0
        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);
        }
예제 #13
0
        // 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();
            }
        }
예제 #14
0
 public bool TryGetDelivery(ArraySegment<byte> deliveryTag, out Delivery delivery)
 {
     return this.unsettledMap.TryGetValue(deliveryTag, out delivery);
 }
예제 #15
0
            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;
            }
예제 #16
0
 public bool TryGetDelivery(ArraySegment <byte> deliveryTag, out Delivery delivery)
 {
     return(this.unsettledMap.TryGetValue(deliveryTag, out delivery));
 }
예제 #17
0
 public void SendDelivery(Delivery delivery)
 {
     this.inflightDeliveries.DoWork(delivery);
 }
예제 #18
0
 protected void AbortDelivery(Delivery delivery)
 {
     delivery.State = AmqpConstants.ReleasedOutcome;
     delivery.Complete();
 }
예제 #19
0
 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);
     }
 }
예제 #20
0
 public void SendDelivery(Delivery delivery)
 {
     this.pendingDeliveries.DoWork(delivery);
 }