/// <summary> /// Initializes the request response channel. /// </summary> /// <param name="type">A prefix of the object name for debugging purposes.</param> /// <param name="name">The object name.</param> /// <param name="session">The session in which the links are created.</param> /// <param name="address">The node address.</param> /// <param name="properties">The properties to send in attach performatives.</param> public RequestResponseAmqpLink(string type, string name, AmqpSession session, string address, Fields properties) : base(type) { this.Name = name ?? string.Format(CultureInfo.InvariantCulture, "duplex{0}:{1}:{2}", session.Connection.Identifier, session.Identifier, this.Identifier); this.replyTo = Guid.NewGuid().ToString("N"); try { AmqpLinkSettings senderSettings = new AmqpLinkSettings(); senderSettings.Role = false; senderSettings.LinkName = this.Name + ":sender"; senderSettings.SettleType = SettleMode.SettleOnSend; senderSettings.Source = new Source(); senderSettings.Target = new Target() { Address = address }; senderSettings.Properties = properties; this.sender = new SendingAmqpLink(session, senderSettings); this.sender.SafeAddClosed(OnLinkClosed); AmqpLinkSettings receiverSettings = new AmqpLinkSettings(); receiverSettings.Role = true; receiverSettings.LinkName = this.Name + ":receiver"; receiverSettings.SettleType = SettleMode.SettleOnSend; receiverSettings.Source = new Source() { Address = address }; receiverSettings.TotalLinkCredit = 50; receiverSettings.AutoSendFlow = true; receiverSettings.Target = new Target() { Address = this.replyTo }; if (properties != null) { receiverSettings.Properties = new Fields(); receiverSettings.Properties.Merge(properties); } this.receiver = new ReceivingAmqpLink(session, receiverSettings); this.receiver.RegisterMessageListener(this.OnResponseMessage); this.receiver.SafeAddClosed(OnLinkClosed); } catch { this.sender?.SafeClose(); this.receiver?.SafeClose(); throw; } this.inflightRequests = new WorkCollection <MessageId, RequestAsyncResult, AmqpMessage>(); }
static void OnRequestCredit(object state) { try { SendingAmqpLink thisPtr = (SendingAmqpLink)state; if (thisPtr.State == AmqpObjectState.OpenSent || thisPtr.State == AmqpObjectState.Opened) { thisPtr.SendFlow(true); } } catch (Exception exception) when(!Fx.IsFatal(exception)) { } }
public SendAsyncResult( SendingAmqpLink link, AmqpMessage message, ArraySegment <byte> deliveryTag, ArraySegment <byte> txnId, TimeSpan timeout, AsyncCallback callback, object state) : base(timeout, callback, state) { this.link = link; this.message = message; this.deliveryTag = deliveryTag; this.txnId = txnId; this.link.inflightSends.StartWork(deliveryTag, this); }
AmqpLink ILinkFactory.CreateLink(AmqpSession session, AmqpLinkSettings settings) { AmqpLink link; if (settings.IsReceiver()) { link = new ReceivingAmqpLink(session, settings); } else { link = new SendingAmqpLink(session, settings); } AmqpTrace.Provider.AmqpLogOperationInformational(this, TraceOperation.Create, link); return(link); }
/// <summary> /// Opens an <see cref="AmqpLink"/> to a node at the given address. /// </summary> /// <typeparam name="T">The type of link. Only <see cref="SendingAmqpLink"/> and <see cref="ReceivingAmqpLink"/> are supported.</typeparam> /// <param name="name">The link name.</param> /// <param name="address">The node address.</param> /// <returns>A task that returns a link on completion.</returns> public async Task <T> OpenLinkAsync <T>(string name, string address) where T : AmqpLink { AmqpLink link; Type linkType = typeof(T); AmqpLinkSettings linkSettings = new AmqpLinkSettings(); linkSettings.LinkName = name; if (linkType == typeof(SendingAmqpLink)) { linkSettings.Role = false; linkSettings.Source = new Source(); linkSettings.Target = new Target() { Address = address }; link = new SendingAmqpLink(linkSettings); } else if (linkType == typeof(ReceivingAmqpLink)) { linkSettings.Role = true; linkSettings.Source = new Source() { Address = address }; linkSettings.TotalLinkCredit = AmqpConstants.DefaultLinkCredit; linkSettings.AutoSendFlow = true; linkSettings.Target = new Target(); link = new ReceivingAmqpLink(linkSettings); } else { throw new NotSupportedException(linkType.Name); } try { link.AttachTo(this); await link.OpenAsync().ConfigureAwait(false); return(link as T); } catch { link.SafeClose(); throw; } }
public RequestResponseAmqpLink(AmqpSession session, AmqpLinkSettings settings) : base("requestresponseamqplink") { this.Name = string.Format(CultureInfo.InvariantCulture, "{0}:{1}:{2}", session.Connection.Identifier, session.Identifier, this.Identifier); this.replyTo = Guid.NewGuid().ToString("N"); AmqpLinkSettings senderSettings = new AmqpLinkSettings(); senderSettings.Role = false; senderSettings.LinkName = this.Name + ":sender"; senderSettings.SettleType = settings.SettleType; senderSettings.Source = new Source() { Address = Guid.NewGuid().ToString("N") }; senderSettings.Target = settings.Target; senderSettings.Properties = settings.Properties; this.sender = new SendingAmqpLink(session, senderSettings); this.sender.Closed += new EventHandler(OnLinkClosed); AmqpLinkSettings receiverSettings = new AmqpLinkSettings(); receiverSettings.Role = true; receiverSettings.LinkName = this.Name + ":receiver"; receiverSettings.SettleType = settings.SettleType; receiverSettings.Source = settings.Source; receiverSettings.TotalLinkCredit = settings.TotalLinkCredit; receiverSettings.TotalCacheSizeInBytes = settings.TotalCacheSizeInBytes; receiverSettings.AutoSendFlow = settings.AutoSendFlow; receiverSettings.Target = new Target() { Address = this.replyTo }; receiverSettings.Properties = settings.Properties; this.receiver = new ReceivingAmqpLink(session, receiverSettings); this.receiver.SetTotalLinkCredit(receiverSettings.TotalLinkCredit, applyNow: true); this.receiver.RegisterMessageListener(this.OnResponseMessage); this.receiver.Closed += new EventHandler(OnLinkClosed); this.inflightRequests = new WorkCollection <MessageId, RequestAsyncResult, AmqpMessage>(); }
public DuplexAmqpLink(SendingAmqpLink sender, ReceivingAmqpLink receiver) : base("duplex") { AmqpTrace.Provider.AmqpLogOperationInformational(this, TraceOperation.Create, "Create"); this.sender = sender; this.receiver = receiver; this.sender.SafeAddClosed(this.OnLinkClosed); this.receiver.SafeAddClosed(this.OnLinkClosed); // TODO: ////if (this.sender.State != AmqpObjectState.Opened) ////{ //// this.SafeClose(); //// throw Fx.Exception.AsWarning(new ArgumentException("Sender wasn't open", "sender")); ////} ////if (this.receiver.State != AmqpObjectState.Opened) ////{ //// this.SafeClose(); //// throw Fx.Exception.AsWarning(new ArgumentException("Reciever wasn't open", "receiver")); ////} }
public DuplexAmqpLink(AmqpSession session, AmqpLinkSettings settings) : base("duplex") { AmqpTrace.Provider.AmqpLogOperationInformational(this, TraceOperation.Create, "Create"); var senderSettings = new AmqpLinkSettings { Role = false, LinkName = settings.LinkName + ":out", SettleType = settings.SettleType, Source = new Source(), TotalLinkCredit = settings.TotalLinkCredit, AutoSendFlow = settings.AutoSendFlow, Target = settings.Target, Properties = settings.Properties }; this.sender = new SendingAmqpLink(session, senderSettings); var receiverSettings = new AmqpLinkSettings { Role = true, LinkName = settings.LinkName + ":in", SettleType = settings.SettleType, Source = settings.Source, TotalLinkCredit = settings.TotalLinkCredit, AutoSendFlow = settings.AutoSendFlow, Target = new Target(), Properties = settings.Properties }; this.receiver = new ReceivingAmqpLink(session, receiverSettings); this.receiver.SetTotalLinkCredit(receiverSettings.TotalLinkCredit, true); // WHY set both here AND on settings? Follow up with Xin. this.sender.SafeAddClosed(this.OnLinkClosed); this.receiver.SafeAddClosed(this.OnLinkClosed); }