use of org.apache.activemq.artemis.core.server.MessageReference in project activemq-artemis by apache.
the class QueueImpl method expireReference.
@Override
public synchronized boolean expireReference(final long messageID) throws Exception {
if (isExpirationRedundant()) {
return false;
}
try (LinkedListIterator<MessageReference> iter = iterator()) {
while (iter.hasNext()) {
MessageReference ref = iter.next();
if (ref.getMessage().getMessageID() == messageID) {
incDelivering(ref);
expire(ref);
iter.remove();
refRemoved(ref);
return true;
}
}
return false;
}
}
use of org.apache.activemq.artemis.core.server.MessageReference in project activemq-artemis by apache.
the class ScaleDownHandler method scaleDownTransactions.
public void scaleDownTransactions(ClientSessionFactory sessionFactory, ResourceManager resourceManager, String user, String password) throws Exception {
ClientSession session = sessionFactory.createSession(user, password, true, false, false, false, 0);
ClientSession queueCreateSession = sessionFactory.createSession(user, password, false, true, true, false, 0);
List<Xid> preparedTransactions = resourceManager.getPreparedTransactions();
Map<String, Long> queueIDs = new HashMap<>();
for (Xid xid : preparedTransactions) {
logger.debug("Scaling down transaction: " + xid);
Transaction transaction = resourceManager.getTransaction(xid);
session.start(xid, XAResource.TMNOFLAGS);
List<TransactionOperation> allOperations = transaction.getAllOperations();
// Get the information of the Prepared TXs so it could replay the TXs
Map<Message, Pair<List<Long>, List<Long>>> queuesToSendTo = new HashMap<>();
for (TransactionOperation operation : allOperations) {
if (operation instanceof PostOfficeImpl.AddOperation) {
PostOfficeImpl.AddOperation addOperation = (PostOfficeImpl.AddOperation) operation;
List<MessageReference> refs = addOperation.getRelatedMessageReferences();
for (MessageReference ref : refs) {
Message message = ref.getMessage();
Queue queue = ref.getQueue();
long queueID;
String queueName = queue.getName().toString();
if (queueIDs.containsKey(queueName)) {
queueID = queueIDs.get(queueName);
} else {
queueID = createQueueIfNecessaryAndGetID(queueCreateSession, queue, message.getAddressSimpleString());
// store it so we don't have to look it up every time
queueIDs.put(queueName, queueID);
}
Pair<List<Long>, List<Long>> queueIds = queuesToSendTo.get(message);
if (queueIds == null) {
queueIds = new Pair<List<Long>, List<Long>>(new ArrayList<Long>(), new ArrayList<Long>());
queuesToSendTo.put(message, queueIds);
}
queueIds.getA().add(queueID);
}
} else if (operation instanceof RefsOperation) {
RefsOperation refsOperation = (RefsOperation) operation;
List<MessageReference> refs = refsOperation.getReferencesToAcknowledge();
for (MessageReference ref : refs) {
Message message = ref.getMessage();
Queue queue = ref.getQueue();
long queueID;
String queueName = queue.getName().toString();
if (queueIDs.containsKey(queueName)) {
queueID = queueIDs.get(queueName);
} else {
queueID = createQueueIfNecessaryAndGetID(queueCreateSession, queue, message.getAddressSimpleString());
// store it so we don't have to look it up every time
queueIDs.put(queueName, queueID);
}
Pair<List<Long>, List<Long>> queueIds = queuesToSendTo.get(message);
if (queueIds == null) {
queueIds = new Pair<List<Long>, List<Long>>(new ArrayList<Long>(), new ArrayList<Long>());
queuesToSendTo.put(message, queueIds);
}
queueIds.getA().add(queueID);
queueIds.getB().add(queueID);
}
}
}
ClientProducer producer = session.createProducer();
for (Map.Entry<Message, Pair<List<Long>, List<Long>>> entry : queuesToSendTo.entrySet()) {
List<Long> ids = entry.getValue().getA();
ByteBuffer buffer = ByteBuffer.allocate(ids.size() * 8);
for (Long id : ids) {
buffer.putLong(id);
}
Message message = entry.getKey();
message.putBytesProperty(Message.HDR_ROUTE_TO_IDS.toString(), buffer.array());
ids = entry.getValue().getB();
if (ids.size() > 0) {
buffer = ByteBuffer.allocate(ids.size() * 8);
for (Long id : ids) {
buffer.putLong(id);
}
message.putBytesProperty(Message.HDR_ROUTE_TO_ACK_IDS.toString(), buffer.array());
}
producer.send(message.getAddressSimpleString().toString(), message);
}
session.end(xid, XAResource.TMSUCCESS);
session.prepare(xid);
}
}
use of org.apache.activemq.artemis.core.server.MessageReference in project activemq-artemis by apache.
the class ScaleDownHandler method scaleDownSNF.
private long scaleDownSNF(final SimpleString address, final Set<Queue> queues, final ClientProducer producer) throws Exception {
long messageCount = 0;
final String propertyEnd;
// If this SNF is towards our targetNodeId
boolean queueOnTarget = address.toString().endsWith(targetNodeId);
if (queueOnTarget) {
propertyEnd = targetNodeId;
} else {
propertyEnd = address.toString().substring(address.toString().lastIndexOf("."));
}
Transaction tx = new TransactionImpl(storageManager);
for (Queue queue : queues) {
// using auto-closeable
try (LinkedListIterator<MessageReference> messagesIterator = queue.browserIterator()) {
// loop through every message of this queue
while (messagesIterator.hasNext()) {
MessageReference messageRef = messagesIterator.next();
Message message = messageRef.getMessage().copy();
/* Here we are taking messages out of a store-and-forward queue and sending them to the corresponding
* address on the scale-down target server. However, we have to take the existing _AMQ_ROUTE_TOsf.*
* property and put its value into the _AMQ_ROUTE_TO property so the message is routed properly.
*/
byte[] oldRouteToIDs = null;
List<SimpleString> propertiesToRemove = new ArrayList<>();
message.removeProperty(Message.HDR_ROUTE_TO_IDS.toString());
for (SimpleString propName : message.getPropertyNames()) {
if (propName.startsWith(Message.HDR_ROUTE_TO_IDS)) {
if (propName.toString().endsWith(propertyEnd)) {
oldRouteToIDs = message.getBytesProperty(propName.toString());
}
propertiesToRemove.add(propName);
}
}
for (SimpleString propertyToRemove : propertiesToRemove) {
message.removeProperty(propertyToRemove.toString());
}
if (queueOnTarget) {
message.putBytesProperty(Message.HDR_ROUTE_TO_IDS.toString(), oldRouteToIDs);
} else {
message.putBytesProperty(Message.HDR_SCALEDOWN_TO_IDS.toString(), oldRouteToIDs);
}
logger.debug("Scaling down message " + message + " from " + address + " to " + message.getAddress() + " on node " + targetNodeId);
producer.send(message.getAddress(), message);
messageCount++;
messagesIterator.remove();
ackMessageOnQueue(tx, queue, messageRef);
}
} catch (NoSuchElementException ignored) {
// this could happen through paging browsing
}
}
tx.commit();
return messageCount;
}
use of org.apache.activemq.artemis.core.server.MessageReference in project activemq-artemis by apache.
the class ScheduledDeliveryHandlerImpl method removeReferenceWithID.
@Override
public MessageReference removeReferenceWithID(final long id) throws ActiveMQException {
synchronized (scheduledReferences) {
Iterator<RefScheduled> iter = scheduledReferences.iterator();
while (iter.hasNext()) {
MessageReference ref = iter.next().getRef();
if (ref.getMessage().getMessageID() == id) {
iter.remove();
metrics.decrementMetrics(ref);
return ref;
}
}
}
return null;
}
use of org.apache.activemq.artemis.core.server.MessageReference in project activemq-artemis by apache.
the class ActiveMQTestBase method assertRefListsIdenticalRefs.
protected void assertRefListsIdenticalRefs(final List<MessageReference> l1, final List<MessageReference> l2) {
if (l1.size() != l2.size()) {
Assert.fail("Lists different sizes: " + l1.size() + ", " + l2.size());
}
Iterator<MessageReference> iter1 = l1.iterator();
Iterator<MessageReference> iter2 = l2.iterator();
while (iter1.hasNext()) {
MessageReference o1 = iter1.next();
MessageReference o2 = iter2.next();
Assert.assertTrue("expected " + o1 + " but was " + o2, o1 == o2);
}
}
Aggregations