blob: 86a307a3ac5b0fc390f4ebe72fdd462342c288d8 [file] [log] [blame]
#--
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#++
module Qpid::Proton
# The base for both Sender and Receiver, providing common functionality
# between both ends.
#
# A Link has a single parent Qpid::Proton::Session instance.
#
class Link < Endpoint
# The sender will send all deliveries initially unsettled.
SND_UNSETTLED = Cproton::PN_SND_UNSETTLED
# The sender will send all deliveries settled to the receiver.
SND_SETTLED = Cproton::PN_SND_SETTLED
# The sender may send a mixture of settled and unsettled deliveries.
SND_MIXED = Cproton::PN_SND_MIXED
# The receiver will settle deliveries regardless of what the sender does.
RCV_FIRST = Cproton::PN_RCV_FIRST
# The receiver will only settle deliveries after the sender settles.
RCV_SECOND = Cproton::PN_RCV_SECOND
# @private
include Util::SwigHelper
# @private
PROTON_METHOD_PREFIX = "pn_link"
# @!attribute [r] state
#
# Returns the endpoint state flags.
#
proton_caller :state
# @!method open
#
# Opens the link. Once this operation has completed, the state flag will be
# set.
#
# @see Endpoint::LOCAL_ACTIVE
proton_caller :open
# @!method close
#
# Closes the link.
#
# Once this operation has completed, the state flag will be set.
# This may be called without first calling #open, which is the equivalent to
# calling #open and then #close.
#
# @see Endpoint::LOCAL_CLOSED
proton_caller :close
# @!method detach
#
# Detaches the link.
proton_caller :detach
# Advance the current delivery to the next on the link.
#
# For sending links, this operation is used to finish sending message data
# for the current outgoing delivery and move on to the next outgoing
# delivery (if any).
#
# For receiving links, this operatoin is used to finish accessing message
# data from the current incoming delivery and move on to the next incoming
# delivery (if any).
#
# @return [Boolean] True if the current delivery was changed.
#
# @see #current
#
proton_caller :advance
proton_caller :unsettled
# @!attribute [r] credit
#
# Returns the credit balance for a link.
#
# Links use a credit based flow control scheme. Every receiver maintains a
# credit balance that corresponds to the number of deliveries that the
# receiver can accept at any given moment.
#
# As more capacity becomes available at the receiver, it adds credit to this
# balance and communicates the new balance to the sender. Whenever a
# delivery is sent/received, the credit balance maintained by the link is
# decremented by one.
#
# Once the credit balance at the sender reaches zero, the sender must pause
# sending until more credit is obtained from the receiver.
#
# NOte that a sending link may still be used to send deliveries eve if
# credit reaches zero. However those deliveries will end up being buffer by
# the link until enough credit is obtained from the receiver to send them
# over the wire. In this case the balance reported will go negative.
#
# @return [Fixnum] The credit balance.
#
# @see #flow
#
proton_caller :credit
# @!attribute [r] remote_credit
#
# Returns the remote view of the credit.
#
# The remote view of the credit for a link differs from the local view of
# credit for a link by the number of queued deliveries. In other words,
# remote credit is defined as credit - queued.
#
# @see #queued
# @see #credit
#
# @return [Fixnum] The remove view of the credit.
#
proton_caller :remote_credit
# @!attribute [r] available
#
# Returns the available deliveries hint for a link.
#
# The available count for a link provides a hint as to the number of
# deliveries that might be able to be sent if sufficient credit were issued
# by the receiving link endpoint.
#
# @return [Fixnum] The available deliveries hint.
#
# @see Sender#offered
#
proton_caller :available
# @!attribute [r] queued
#
# Returns the number of queued deliveries for a link.
#
# Links may queue deliveries for a number of reasons. For example, there may
# be insufficient credit to send them to the receiver, or they simply may
# not have yet had a chance to be written to the wire.
#
# @return [Fixnum] The number of queued deliveries.
#
# @see #credit
#
proton_caller :queued
# @!attribute [r] name
#
# Returns the name of the link.
#
# @return [String] The name.
#
proton_caller :name
# @!attribute [r] sender?
#
# Returns if the link is a sender.
#
# @return [Boolean] True if the link is a sender.
#
proton_reader :sender, :is_or_get => :is
# @!attribute [r] receiver?
#
# Returns if the link is a receiver.
#
# @return [Boolean] True if the link is a receiver.
#
proton_reader :receiver, :is_or_get => :is
# @private
proton_reader :attachments
# Drains excess credit.
#
# When a link is in drain mode, the sender must use all excess credit
# immediately and release any excess credit back to the receiver if there
# are no deliveries available to send.
#
# When invoked on a Sender that is in drain mode, this operation will
# release all excess credit back to the receiver and return the number of
# credits released back to the sender. If the link is not in drain mode,
# this operation is a noop.
#
# When invoked on a Receiver, this operation will return and reset the
# number of credits the sender has released back to it.
#
# @return [Fixnum] The number of credits drained.
#
proton_caller :drained
# @private
include Util::Wrapper
# @private
def self.wrap(impl)
return nil if impl.nil?
result = self.fetch_instance(impl, :pn_link_attachments)
return result unless result.nil?
if Cproton.pn_link_is_sender(impl)
return Sender.new(impl)
elsif Cproton.pn_link_is_receiver(impl)
return Receiver.new(impl)
end
end
# @private
def initialize(impl)
@impl = impl
self.class.store_instance(self, :pn_link_attachments)
end
# Returns additional error information.
#
# Whenever a link operation fails (i.e., returns an error code) additional
# error details can be obtained from this method. Ther error object that is
# returned may also be used to clear the error condition.
#
# @return [Error] The error.
#
def error
Cproton.pn_link_error(@impl)
end
# Returns the next link that matches the given state mask.
#
# @param state_mask [Fixnum] The state mask.
#
# @return [Sender, Receiver] The next link.
#
def next(state_mask)
return Link.wrap(Cproton.pn_link_next(@impl, state_mask))
end
# Returns the locally defined source terminus.
#
# @return [Terminus] The terminus
def source
Terminus.new(Cproton.pn_link_source(@impl))
end
# Returns the locally defined target terminus.
#
# @return [Terminus] The terminus.
#
def target
Terminus.new(Cproton.pn_link_target(@impl))
end
# Returns a representation of the remotely defined source terminus.
#
# @return [Terminus] The terminus.
#
def remote_source
Terminus.new(Cproton.pn_link_remote_source(@impl))
end
# Returns a representation of the remotely defined target terminus.
#
# @return [Terminus] The terminus.
#
def remote_target
Terminus.new(Cproton.pn_link_remote_target(@impl))
end
# Returns the parent session.
#
# @return [Session] The session.
#
def session
Session.wrap(Cproton.pn_link_session(@impl))
end
# Returns the parent connection.
#
# @return [Connection] The connection.
#
def connection
self.session.connection
end
# Returns the parent delivery.
#
# @return [Delivery] The delivery.
#
def delivery(tag)
Delivery.new(Cproton.pn_delivery(@impl, tag))
end
# Returns the current delivery.
#
# Each link maintains a sequence of deliveries in the order they were
# created, along with a reference to the *current* delivery. All send and
# receive operations on a link take place on the *current* delivery. If a
# link has no current delivery, the current delivery is automatically
# pointed to the *next* delivery created on the link.
#
# Once initialized, the current delivery remains the same until it is
# changed by advancing, or until it is settled.
#
# @see #next
# @see Delivery#settle
#
# @return [Delivery] The current delivery.
#
def current
Delivery.wrap(Cproton.pn_link_current(@impl))
end
# Sets the local sender settle mode.
#
# @param mode [Fixnum] The settle mode.
#
# @see #SND_UNSETTLED
# @see #SND_SETTLED
# @see #SND_MIXED
#
def snd_settle_mode=(mode)
Cproton.pn_link_set_snd_settle_mode(@impl, mode)
end
# Returns the local sender settle mode.
#
# @return [Fixnum] The local sender settle mode.
#
# @see #snd_settle_mode
#
def snd_settle_mode
Cproton.pn_link_snd_settle_mode(@impl)
end
# Sets the local receiver settle mode.
#
# @param mode [Fixnum] The settle mode.
#
# @see #RCV_FIRST
# @see #RCV_SECOND
#
def rcv_settle_mode=(mode)
Cproton.pn_link_set_rcv_settle_mode(@impl, mode)
end
# Returns the local receiver settle mode.
#
# @return [Fixnum] The local receiver settle mode.
#
def rcv_settle_mode
Cproton.pn_link_rcv_settle_mode(@impl)
end
# @private
def _local_condition
Cproton.pn_link_condition(@impl)
end
# @private
def _remote_condition
Cproton.pn_link_remote_condition(@impl)
end
def ==(other)
other.respond_to?(:impl) &&
(Cproton.pni_address_of(other.impl) == Cproton.pni_address_of(@impl))
end
end
end