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);
}
}
}
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;
}
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();
}
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;
}
}
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;
}
Aggregations