Search in sources :

Example 56 with Binding

use of org.apache.activemq.artemis.core.postoffice.Binding in project activemq-artemis by apache.

the class BindingsImpl method routeUsingStrictOrdering.

private void routeUsingStrictOrdering(final Message message, final RoutingContext context, final GroupingHandler groupingGroupingHandler, final SimpleString groupId, final int tries) throws Exception {
    for (Map.Entry<SimpleString, List<Binding>> entry : routingNameBindingMap.entrySet()) {
        SimpleString routingName = entry.getKey();
        List<Binding> bindings = entry.getValue();
        if (bindings == null) {
            // ConcurrentHashMap behaviour!
            continue;
        }
        // concat a full group id, this is for when a binding has multiple bindings
        // NOTE: In case a dev ever change this rule, QueueImpl::unproposed is using this rule to determine if
        // the binding belongs to its Queue before removing it
        SimpleString fullID = groupId.concat(".").concat(routingName);
        // see if there is already a response
        Response resp = groupingGroupingHandler.getProposal(fullID, true);
        if (resp == null) {
            // ok let's find the next binding to propose
            Binding theBinding = getNextBinding(message, routingName, bindings);
            if (theBinding == null) {
                continue;
            }
            resp = groupingGroupingHandler.propose(new Proposal(fullID, theBinding.getClusterName()));
            if (resp == null) {
                logger.debug("it got a timeout on propose, trying again, number of retries: " + tries);
                // it timed out, so we will check it through routeAndcheckNull
                theBinding = null;
            }
            // if our proposal was declined find the correct binding to use
            if (resp != null && resp.getAlternativeClusterName() != null) {
                theBinding = locateBinding(resp.getAlternativeClusterName(), bindings);
            }
            routeAndCheckNull(message, context, resp, theBinding, groupId, tries);
        } else {
            // ok, we need to find the binding and route it
            Binding chosen = locateBinding(resp.getChosenClusterName(), bindings);
            routeAndCheckNull(message, context, resp, chosen, groupId, tries);
        }
    }
}
Also used : Binding(org.apache.activemq.artemis.core.postoffice.Binding) RemoteQueueBinding(org.apache.activemq.artemis.core.server.cluster.RemoteQueueBinding) Response(org.apache.activemq.artemis.core.server.group.impl.Response) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) ArrayList(java.util.ArrayList) List(java.util.List) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ConcurrentMap(java.util.concurrent.ConcurrentMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Proposal(org.apache.activemq.artemis.core.server.group.impl.Proposal)

Example 57 with Binding

use of org.apache.activemq.artemis.core.postoffice.Binding in project activemq-artemis by apache.

the class BindingsImpl method getNextBinding.

/**
 * This code has a race on the assigned value to routing names.
 * <p>
 * This is not that much of an issue because<br>
 * Say you have the same queue name bound into two servers. The routing will load balance between
 * these two servers. This will eventually send more messages to one server than the other
 * (depending if you are using multi-thread), and not lose messages.
 */
private Binding getNextBinding(final Message message, final SimpleString routingName, final List<Binding> bindings) {
    Integer ipos = routingNamePositions.get(routingName);
    int pos = ipos != null ? ipos : 0;
    int length = bindings.size();
    int startPos = pos;
    Binding theBinding = null;
    int lastLowPriorityBinding = -1;
    while (true) {
        Binding binding;
        try {
            binding = bindings.get(pos);
        } catch (IndexOutOfBoundsException e) {
            // This can occur if binding is removed while in route
            if (!bindings.isEmpty()) {
                pos = 0;
                startPos = 0;
                length = bindings.size();
                continue;
            } else {
                break;
            }
        }
        Filter filter = binding.getFilter();
        if (filter == null || filter.match(message)) {
            // unnecessary overhead)
            if (length == 1 || (binding.isConnected() && (messageLoadBalancingType.equals(MessageLoadBalancingType.STRICT) || binding.isHighAcceptPriority(message)))) {
                theBinding = binding;
                pos = incrementPos(pos, length);
                break;
            } else {
                // the localQueue should always have the priority over the secondary bindings
                if (lastLowPriorityBinding == -1 || messageLoadBalancingType.equals(MessageLoadBalancingType.ON_DEMAND) && binding instanceof LocalQueueBinding) {
                    lastLowPriorityBinding = pos;
                }
            }
        }
        pos = incrementPos(pos, length);
        if (pos == startPos) {
            // if no bindings were found, we will apply a secondary level on the routing logic
            if (lastLowPriorityBinding != -1) {
                try {
                    theBinding = bindings.get(lastLowPriorityBinding);
                } catch (IndexOutOfBoundsException e) {
                    // This can occur if binding is removed while in route
                    if (!bindings.isEmpty()) {
                        pos = 0;
                        lastLowPriorityBinding = -1;
                        continue;
                    } else {
                        break;
                    }
                }
                pos = incrementPos(lastLowPriorityBinding, length);
            }
            break;
        }
    }
    if (pos != startPos) {
        routingNamePositions.put(routingName, pos);
    }
    if (messageLoadBalancingType.equals(MessageLoadBalancingType.OFF) && theBinding instanceof RemoteQueueBinding) {
        theBinding = getNextBinding(message, routingName, bindings);
    }
    return theBinding;
}
Also used : Binding(org.apache.activemq.artemis.core.postoffice.Binding) RemoteQueueBinding(org.apache.activemq.artemis.core.server.cluster.RemoteQueueBinding) Filter(org.apache.activemq.artemis.core.filter.Filter) RemoteQueueBinding(org.apache.activemq.artemis.core.server.cluster.RemoteQueueBinding)

Example 58 with Binding

use of org.apache.activemq.artemis.core.postoffice.Binding in project activemq-artemis by apache.

the class BindingsImpl method debugBindings.

private String debugBindings() {
    StringWriter writer = new StringWriter();
    PrintWriter out = new PrintWriter(writer);
    out.println("\n**************************************************");
    out.println("routingNameBindingMap:");
    if (routingNameBindingMap.isEmpty()) {
        out.println("\tEMPTY!");
    }
    for (Map.Entry<SimpleString, List<Binding>> entry : routingNameBindingMap.entrySet()) {
        out.println("\tkey=" + entry.getKey() + ", value(s):");
        for (Binding bind : entry.getValue()) {
            out.println("\t\t" + bind);
        }
        out.println();
    }
    out.println("routingNamePositions:");
    if (routingNamePositions.isEmpty()) {
        out.println("\tEMPTY!");
    }
    for (Map.Entry<SimpleString, Integer> entry : routingNamePositions.entrySet()) {
        out.println("\tkey=" + entry.getKey() + ", value=" + entry.getValue());
    }
    out.println();
    out.println("bindingsMap:");
    if (bindingsMap.isEmpty()) {
        out.println("\tEMPTY!");
    }
    for (Map.Entry<Long, Binding> entry : bindingsMap.entrySet()) {
        out.println("\tkey=" + entry.getKey() + ", value=" + entry.getValue());
    }
    out.println();
    out.println("exclusiveBindings:");
    if (exclusiveBindings.isEmpty()) {
        out.println("\tEMPTY!");
    }
    for (Binding binding : exclusiveBindings) {
        out.println("\t" + binding);
    }
    out.println("####################################################");
    return writer.toString();
}
Also used : Binding(org.apache.activemq.artemis.core.postoffice.Binding) RemoteQueueBinding(org.apache.activemq.artemis.core.server.cluster.RemoteQueueBinding) StringWriter(java.io.StringWriter) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) ArrayList(java.util.ArrayList) List(java.util.List) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ConcurrentMap(java.util.concurrent.ConcurrentMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) PrintWriter(java.io.PrintWriter)

Example 59 with Binding

use of org.apache.activemq.artemis.core.postoffice.Binding in project activemq-artemis by apache.

the class BindingsImpl method redistribute.

@Override
public boolean redistribute(final Message message, final Queue originatingQueue, final RoutingContext context) throws Exception {
    if (messageLoadBalancingType.equals(MessageLoadBalancingType.STRICT) || messageLoadBalancingType.equals(MessageLoadBalancingType.OFF)) {
        return false;
    }
    if (logger.isTraceEnabled()) {
        logger.trace("Redistributing message " + message);
    }
    SimpleString routingName = originatingQueue.getName();
    List<Binding> bindings = routingNameBindingMap.get(routingName);
    if (bindings == null) {
        // ConcurrentHashMap behaviour!
        return false;
    }
    Integer ipos = routingNamePositions.get(routingName);
    int pos = ipos != null ? ipos.intValue() : 0;
    int length = bindings.size();
    int startPos = pos;
    Binding theBinding = null;
    // TODO - combine this with similar logic in route()
    while (true) {
        Binding binding;
        try {
            binding = bindings.get(pos);
        } catch (IndexOutOfBoundsException e) {
            // This can occur if binding is removed while in route
            if (!bindings.isEmpty()) {
                pos = 0;
                startPos = 0;
                length = bindings.size();
                continue;
            } else {
                break;
            }
        }
        pos = incrementPos(pos, length);
        Filter filter = binding.getFilter();
        boolean highPrior = binding.isHighAcceptPriority(message);
        if (highPrior && binding.getBindable() != originatingQueue && (filter == null || filter.match(message))) {
            theBinding = binding;
            break;
        }
        if (pos == startPos) {
            break;
        }
    }
    routingNamePositions.put(routingName, pos);
    if (theBinding != null) {
        theBinding.route(message, context);
        return true;
    } else {
        return false;
    }
}
Also used : Binding(org.apache.activemq.artemis.core.postoffice.Binding) RemoteQueueBinding(org.apache.activemq.artemis.core.server.cluster.RemoteQueueBinding) Filter(org.apache.activemq.artemis.core.filter.Filter) SimpleString(org.apache.activemq.artemis.api.core.SimpleString)

Example 60 with Binding

use of org.apache.activemq.artemis.core.postoffice.Binding in project activemq-artemis by apache.

the class ActiveMQServerControlImpl method closeConsumerConnectionsForAddress.

@Override
public boolean closeConsumerConnectionsForAddress(final String address) {
    boolean closed = false;
    checkStarted();
    clearIO();
    try {
        for (Binding binding : postOffice.getMatchingBindings(SimpleString.toSimpleString(address)).getBindings()) {
            if (binding instanceof LocalQueueBinding) {
                Queue queue = ((LocalQueueBinding) binding).getQueue();
                for (Consumer consumer : queue.getConsumers()) {
                    if (consumer instanceof ServerConsumer) {
                        ServerConsumer serverConsumer = (ServerConsumer) consumer;
                        RemotingConnection connection = null;
                        for (RemotingConnection potentialConnection : remotingService.getConnections()) {
                            if (potentialConnection.getID().toString().equals(serverConsumer.getConnectionID())) {
                                connection = potentialConnection;
                            }
                        }
                        if (connection != null) {
                            remotingService.removeConnection(connection.getID());
                            connection.fail(ActiveMQMessageBundle.BUNDLE.consumerConnectionsClosedByManagement(address));
                            closed = true;
                        }
                    }
                }
            }
        }
    } catch (Exception e) {
        ActiveMQServerLogger.LOGGER.failedToCloseConsumerConnectionsForAddress(address, e);
    } finally {
        blockOnIO();
    }
    return closed;
}
Also used : Binding(org.apache.activemq.artemis.core.postoffice.Binding) LocalQueueBinding(org.apache.activemq.artemis.core.postoffice.impl.LocalQueueBinding) LocalQueueBinding(org.apache.activemq.artemis.core.postoffice.impl.LocalQueueBinding) Consumer(org.apache.activemq.artemis.core.server.Consumer) ServerConsumer(org.apache.activemq.artemis.core.server.ServerConsumer) RemotingConnection(org.apache.activemq.artemis.spi.core.protocol.RemotingConnection) ServerConsumer(org.apache.activemq.artemis.core.server.ServerConsumer) Queue(org.apache.activemq.artemis.core.server.Queue) ActiveMQException(org.apache.activemq.artemis.api.core.ActiveMQException) ListenerNotFoundException(javax.management.ListenerNotFoundException) ActiveMQAddressDoesNotExistException(org.apache.activemq.artemis.api.core.ActiveMQAddressDoesNotExistException)

Aggregations

Binding (org.apache.activemq.artemis.core.postoffice.Binding)81 SimpleString (org.apache.activemq.artemis.api.core.SimpleString)52 LocalQueueBinding (org.apache.activemq.artemis.core.postoffice.impl.LocalQueueBinding)29 QueueBinding (org.apache.activemq.artemis.core.postoffice.QueueBinding)28 Test (org.junit.Test)25 Bindings (org.apache.activemq.artemis.core.postoffice.Bindings)24 Queue (org.apache.activemq.artemis.core.server.Queue)24 ClientSession (org.apache.activemq.artemis.api.core.client.ClientSession)18 RemoteQueueBinding (org.apache.activemq.artemis.core.server.cluster.RemoteQueueBinding)17 ArrayList (java.util.ArrayList)12 Filter (org.apache.activemq.artemis.core.filter.Filter)10 DivertBinding (org.apache.activemq.artemis.core.postoffice.impl.DivertBinding)10 ClientMessage (org.apache.activemq.artemis.api.core.client.ClientMessage)9 ClientProducer (org.apache.activemq.artemis.api.core.client.ClientProducer)9 Map (java.util.Map)8 CountDownLatch (java.util.concurrent.CountDownLatch)8 QueueQueryResult (org.apache.activemq.artemis.core.server.QueueQueryResult)8 ActiveMQException (org.apache.activemq.artemis.api.core.ActiveMQException)7 PostOffice (org.apache.activemq.artemis.core.postoffice.PostOffice)7 ActiveMQServer (org.apache.activemq.artemis.core.server.ActiveMQServer)7