use of org.apache.activemq.artemis.core.transaction.Transaction in project activemq-artemis by apache.
the class QueueImpl method deleteReference.
@Override
public synchronized boolean deleteReference(final long messageID) throws Exception {
boolean deleted = false;
Transaction tx = new TransactionImpl(storageManager);
try (LinkedListIterator<MessageReference> iter = iterator()) {
while (iter.hasNext()) {
MessageReference ref = iter.next();
if (ref.getMessage().getMessageID() == messageID) {
incDelivering(ref);
acknowledge(tx, ref);
iter.remove();
refRemoved(ref);
deleted = true;
break;
}
}
if (!deleted) {
// Look in scheduled deliveries
deleted = scheduledDeliveryHandler.removeReferenceWithID(messageID) != null ? true : false;
}
tx.commit();
return deleted;
}
}
use of org.apache.activemq.artemis.core.transaction.Transaction in project activemq-artemis by apache.
the class QueueImpl method move.
private void move(final Transaction originalTX, final SimpleString address, final Binding binding, final MessageReference ref, final boolean rejectDuplicate, final AckReason reason) throws Exception {
Transaction tx;
if (originalTX != null) {
tx = originalTX;
} else {
// if no TX we create a new one to commit at the end
tx = new TransactionImpl(storageManager);
}
Message copyMessage = makeCopy(ref, reason == AckReason.EXPIRED);
copyMessage.setAddress(address);
postOffice.route(copyMessage, tx, false, rejectDuplicate, binding);
acknowledge(tx, ref, reason);
if (originalTX == null) {
tx.commit();
}
}
use of org.apache.activemq.artemis.core.transaction.Transaction in project activemq-artemis by apache.
the class QueueImpl method deleteQueue.
@Override
public void deleteQueue(boolean removeConsumers) throws Exception {
synchronized (this) {
if (this.queueDestroyed)
return;
this.queueDestroyed = true;
}
Transaction tx = new BindingsTransactionImpl(storageManager);
try {
deleteAllReferences();
destroyPaging();
postOffice.removeBinding(name, tx, true);
if (removeConsumers) {
for (ConsumerHolder consumerHolder : consumerList) {
consumerHolder.consumer.disconnect();
}
}
if (isDurable()) {
storageManager.deleteQueueBinding(tx.getID(), getID());
tx.setContainsPersistent();
}
if (slowConsumerReaperFuture != null) {
slowConsumerReaperFuture.cancel(false);
}
tx.commit();
} catch (Exception e) {
tx.rollback();
throw e;
} finally {
if (factory != null) {
factory.queueRemoved(this);
}
}
}
use of org.apache.activemq.artemis.core.transaction.Transaction 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.transaction.Transaction 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;
}
Aggregations