public static void ReleaseAll(Delivery delivery, Error error) { Outcome outcome; if (error == null) { outcome = new Released(); } else { outcome = new Rejected() { Error = error }; } while (delivery != null) { if (delivery.OnOutcome != null) { delivery.OnOutcome(delivery.Message, outcome, delivery.UserToken); } delivery.Buffer.ReleaseReference(); delivery = (Delivery)delivery.Next; } }
internal void DisposeDelivery(bool role, Delivery delivery, DeliveryState state, bool settled) { Delivery current = null; lock (this.ThisLock) { LinkedList deliveryList = role ? this.incomingList : this.outgoingList; current = (Delivery)deliveryList.First; while (current != null) { if (current == delivery) { if (settled) { deliveryList.Remove(current); } break; } current = (Delivery)current.Next; } } if (current != null) { current.Settled = settled; current.State = state; Dispose dispose = new Dispose() { Role = role, First = current.DeliveryId, Settled = settled, State = state }; this.SendCommand(dispose); } }
void WriteDelivery(Delivery delivery) { while (delivery != null) { delivery.Handle = this.Handle; try { bool settled = delivery.Settled; this.Session.SendDelivery(delivery); if (settled && delivery.OnOutcome != null) { delivery.OnOutcome(delivery.Message, new Accepted(), delivery.UserToken); } } catch { this.writing = false; throw; } lock (this.ThisLock) { delivery = (Delivery)this.outgoingList.First; if (delivery == null) { this.writing = false; } else if (this.credit > 0) { this.outgoingList.Remove(delivery); delivery.Tag = Delivery.GetDeliveryTag(this.deliveryCount); this.credit--; this.deliveryCount++; } else { delivery = null; this.writing = false; } } } }
internal void Send(Message message, DeliveryState deliveryState, OutcomeCallback callback, object state) { const int reservedBytes = 40; #if NETFX || NETFX40 || DOTNET var buffer = message.Encode(this.Session.Connection.BufferManager, reservedBytes); #else var buffer = message.Encode(reservedBytes); #endif if (buffer.Length < 1) { throw new ArgumentException("Cannot send an empty message."); } Delivery delivery = new Delivery() { Message = message, Buffer = buffer, ReservedBufferSize = reservedBytes, State = deliveryState, Link = this, OnOutcome = callback, UserToken = state, Settled = this.settleMode == SenderSettleMode.Settled || callback == null }; lock (this.ThisLock) { this.ThrowIfDetaching("Send"); if (this.credit <= 0 || this.writing) { this.outgoingList.Add(delivery); return; } delivery.Tag = Delivery.GetDeliveryTag(this.deliveryCount); this.credit--; this.deliveryCount++; this.writing = true; } this.WriteDelivery(delivery); }
internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer) { throw new InvalidOperationException(); }
internal override void OnDeliveryStateChanged(Delivery delivery) { // some broker may not settle the message when sending dispositions if (!delivery.Settled) { this.Session.DisposeDelivery(false, delivery, new Accepted(), true); } if (delivery.OnOutcome != null) { Outcome outcome = delivery.State as Outcome; #if NETFX || NETFX40 || DOTNET if (delivery.State != null && delivery.State is Amqp.Transactions.TransactionalState) { outcome = ((Amqp.Transactions.TransactionalState)delivery.State).Outcome; } #endif delivery.OnOutcome(delivery.Message, outcome, delivery.UserToken); } }
internal abstract void OnDeliveryStateChanged(Delivery delivery);
void WriteDelivery(Delivery delivery) { // Must be called under lock. Delivery must be on list already while (this.outgoingWindow > 0 && delivery != null) { --this.outgoingWindow; Transfer transfer = new Transfer() { Handle = delivery.Handle }; bool first = delivery.BytesTransfered == 0; if (first) { // initialize properties for first transfer delivery.DeliveryId = this.outgoingDeliveryId++; transfer.DeliveryTag = delivery.Tag; transfer.DeliveryId = delivery.DeliveryId; transfer.State = delivery.State; transfer.MessageFormat = 0; transfer.Settled = delivery.Settled; transfer.Batchable = true; } int len = this.connection.SendCommand(this.channel, transfer, first, delivery.Buffer, delivery.ReservedBufferSize); delivery.BytesTransfered += len; if (delivery.Buffer.Length == 0) { delivery.Buffer.ReleaseReference(); Delivery next = (Delivery)delivery.Next; if (delivery.Settled) { this.outgoingList.Remove(delivery); } delivery = next; } } }
internal override void OnDeliveryStateChanged(Delivery delivery) { }
internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer) { if (delivery == null) { delivery = this.deliveryCurrent; AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length); } else { buffer.AddReference(); delivery.Buffer = buffer; lock (this.ThisLock) { this.OnDelivery(transfer.DeliveryId); } } if (!transfer.More) { this.deliveryCurrent = null; delivery.Message = Message.Decode(delivery.Buffer); Waiter waiter; MessageCallback callback = this.onMessage; lock (this.ThisLock) { waiter = (Waiter)this.waiterList.First; if (waiter != null) { this.waiterList.Remove(waiter); } else if (callback == null) { this.receivedMessages.Add(new MessageNode() { Message = delivery.Message }); return; } } while (waiter != null) { if (waiter.Signal(delivery.Message)) { this.OnDeliverMessage(); return; } lock (this.ThisLock) { waiter = (Waiter)this.waiterList.First; if (waiter != null) { this.waiterList.Remove(waiter); } else if (callback == null) { this.receivedMessages.Add(new MessageNode() { Message = delivery.Message }); return; } } } Fx.Assert(waiter == null, "waiter must be null now"); Fx.Assert(callback != null, "callback must not be null now"); callback(this, delivery.Message); this.OnDeliverMessage(); } else { this.deliveryCurrent = delivery; } }
internal void Send(Message message, DeliveryState deliveryState, OutcomeCallback callback, object state) { var buffer = message.Encode(); if (buffer.Length < 1) { throw new ArgumentException("Cannot send an empty message."); } Delivery delivery = new Delivery() { Message = message, Buffer = buffer, State = deliveryState, Link = this, OnOutcome = callback, UserToken = state, Settled = this.settleMode == SenderSettleMode.Settled || callback == null }; lock (this.ThisLock) { this.ThrowIfDetaching("Send"); if (this.credit <= 0 || this.writing) { this.outgoingList.Add(delivery); return; } delivery.Tag = GetDeliveryTag(this.deliveryCount); this.credit--; this.deliveryCount++; this.writing = true; } this.WriteDelivery(delivery); }
internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer) { if (!transfer.More) { Waiter waiter; MessageCallback callback; lock (this.ThisLock) { if (delivery == null) { // multi-transfer delivery delivery = this.deliveryCurrent; this.deliveryCurrent = null; Fx.Assert(delivery != null, "Must have a delivery in the queue"); AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length); delivery.Message = Message.Decode(delivery.Buffer); delivery.Buffer = null; } else { // single tranfer delivery this.OnDelivery(transfer.DeliveryId); delivery.Message = Message.Decode(buffer); } callback = this.onMessage; waiter = (Waiter)this.waiterList.First; if (waiter != null) { this.waiterList.Remove(waiter); } if (waiter == null && callback == null) { this.receivedMessages.Add(new MessageNode() { Message = delivery.Message }); return; } } while (waiter != null) { if (waiter.Signal(delivery.Message)) { this.OnDeliverMessage(); return; } lock (this.ThisLock) { waiter = (Waiter)this.waiterList.First; if (waiter != null) { this.waiterList.Remove(waiter); } else if (callback == null) { this.receivedMessages.Add(new MessageNode() { Message = delivery.Message }); return; } } } Fx.Assert(waiter == null, "waiter must be null now"); Fx.Assert(callback != null, "callback must not be null now"); callback(this, delivery.Message); this.OnDeliverMessage(); } else { lock (this.ThisLock) { if (delivery == null) { delivery = this.deliveryCurrent; Fx.Assert(delivery != null, "Must have a current delivery"); AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length); } else { this.OnDelivery(transfer.DeliveryId); delivery.Buffer = new ByteBuffer(buffer.Length * 2, true); AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length); this.deliveryCurrent = delivery; } } } }
internal override void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer) { if (delivery == null) { delivery = this.deliveryCurrent; AmqpBitConverter.WriteBytes(delivery.Buffer, buffer.Buffer, buffer.Offset, buffer.Length); } else { buffer.AddReference(); delivery.Buffer = buffer; lock (this.ThisLock) { this.OnDelivery(transfer.DeliveryId); } } if (!transfer.More) { this.deliveryCurrent = null; delivery.Message = Message.Decode(delivery.Buffer); IHandler handler = this.Session.Connection.Handler; if (handler != null && handler.CanHandle(EventId.ReceiveDelivery)) { handler.Handle(Event.Create(EventId.ReceiveDelivery, this.Session.Connection, this.Session, this, context: delivery)); } Waiter waiter; MessageCallback callback = this.onMessage; lock (this.ThisLock) { waiter = (Waiter)this.waiterList.First; if (waiter != null) { this.waiterList.Remove(waiter); } else if (callback == null) { this.receivedMessages.Add(new MessageNode() { Message = delivery.Message }); return; } } while (waiter != null) { if (waiter.Signal(delivery.Message)) { return; } lock (this.ThisLock) { waiter = (Waiter)this.waiterList.First; if (waiter != null) { this.waiterList.Remove(waiter); } else if (callback == null) { this.receivedMessages.Add(new MessageNode() { Message = delivery.Message }); return; } } } Fx.Assert(waiter == null, "waiter must be null now"); Fx.Assert(callback != null, "callback must not be null now"); callback(this, delivery.Message); } else { this.deliveryCurrent = delivery; } }
internal void SendDelivery(Delivery delivery) { lock (this.ThisLock) { this.outgoingList.Add(delivery); this.WriteDelivery(delivery); } }
void OnTransfer(Transfer transfer, ByteBuffer buffer) { bool newDelivery; lock (this.ThisLock) { if (this.incomingWindow-- == 0) { this.SendFlow(new Flow()); } this.nextIncomingId++; newDelivery = transfer.HasDeliveryId && transfer.DeliveryId > this.incomingDeliveryId; if (newDelivery) { this.incomingDeliveryId = transfer.DeliveryId; } } Link link = this.GetLink(transfer.Handle); Delivery delivery = null; if (newDelivery) { delivery = new Delivery() { DeliveryId = transfer.DeliveryId, Link = link, Tag = transfer.DeliveryTag, Settled = transfer.Settled, State = transfer.State }; if (!delivery.Settled) { lock (this.ThisLock) { this.incomingList.Add(delivery); } } } link.OnTransfer(delivery, transfer, buffer); }
internal abstract void OnTransfer(Delivery delivery, Transfer transfer, ByteBuffer buffer);