use of org.apache.activemq.artemis.core.transaction.Transaction in project activemq-artemis by apache.
the class PageCursorStressTest method testConsumeLivePageMultiThread.
@Test
public void testConsumeLivePageMultiThread() throws Exception {
final PagingStoreImpl pageStore = lookupPageStore(ADDRESS);
pageStore.startPaging();
final int NUM_TX = 100;
final int MSGS_TX = 100;
final int TOTAL_MSG = NUM_TX * MSGS_TX;
final int messageSize = 1024;
PageCursorProvider cursorProvider = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvider();
System.out.println("cursorProvider = " + cursorProvider);
PageSubscription cursor = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvider().getSubscription(queue.getID());
System.out.println("Cursor: " + cursor);
final StorageManager storage = this.server.getStorageManager();
final AtomicInteger exceptions = new AtomicInteger(0);
Thread t1 = new Thread() {
@Override
public void run() {
try {
int count = 0;
for (int txCount = 0; txCount < NUM_TX; txCount++) {
Transaction tx = null;
if (txCount % 2 == 0) {
tx = new TransactionImpl(storage);
}
RoutingContext ctx = generateCTX(tx);
for (int i = 0; i < MSGS_TX; i++) {
// System.out.println("Sending " + count);
ActiveMQBuffer buffer = RandomUtil.randomBuffer(messageSize, count);
Message msg = new CoreMessage(i, buffer.writerIndex());
msg.putIntProperty("key", count++);
msg.getBodyBuffer().writeBytes(buffer, 0, buffer.writerIndex());
Assert.assertTrue(pageStore.page(msg, ctx.getTransaction(), ctx.getContextListing(ADDRESS), lock));
}
if (tx != null) {
tx.commit();
}
}
} catch (Throwable e) {
e.printStackTrace();
exceptions.incrementAndGet();
}
}
};
t1.start();
LinkedListIterator<PagedReference> iterator = cursor.iterator();
for (int i = 0; i < TOTAL_MSG; i++) {
assertEquals(0, exceptions.get());
PagedReference ref = null;
for (int repeat = 0; repeat < 5; repeat++) {
ref = iterator.next();
if (ref == null) {
Thread.sleep(1000);
} else {
break;
}
}
assertNotNull(ref);
ref.acknowledge();
assertNotNull(ref);
System.out.println("Consuming " + ref.getMessage().getIntProperty("key"));
// assertEquals(i, ref.getMessage().getIntProperty("key").intValue());
}
assertEquals(0, exceptions.get());
}
use of org.apache.activemq.artemis.core.transaction.Transaction in project activemq-artemis by apache.
the class PageCursorStressTest method testRestartWithHoleOnAckAndTransaction.
@Test
public void testRestartWithHoleOnAckAndTransaction() throws Exception {
final int NUM_MESSAGES = 1000;
int numberOfPages = addMessages(NUM_MESSAGES, 10 * 1024);
System.out.println("Number of pages = " + numberOfPages);
PageCursorProvider cursorProvider = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvider();
System.out.println("cursorProvider = " + cursorProvider);
PageSubscription cursor = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvider().getSubscription(queue.getID());
System.out.println("Cursor: " + cursor);
Transaction tx = new TransactionImpl(server.getStorageManager(), 60 * 1000);
LinkedListIterator<PagedReference> iterator = cursor.iterator();
for (int i = 0; i < 100; i++) {
PagedReference msg = iterator.next();
assertEquals(i, msg.getMessage().getIntProperty("key").intValue());
if (i < 10 || i > 20) {
cursor.ackTx(tx, msg);
}
}
tx.commit();
server.stop();
OperationContextImpl.clearContext();
server.start();
cursor = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvider().getSubscription(queue.getID());
tx = new TransactionImpl(server.getStorageManager(), 60 * 1000);
iterator = cursor.iterator();
for (int i = 10; i <= 20; i++) {
PagedReference msg = iterator.next();
assertEquals(i, msg.getMessage().getIntProperty("key").intValue());
cursor.ackTx(tx, msg);
}
for (int i = 100; i < NUM_MESSAGES; i++) {
PagedReference msg = iterator.next();
assertEquals(i, msg.getMessage().getIntProperty("key").intValue());
cursor.ackTx(tx, msg);
}
tx.commit();
server.stop();
createServer();
waitCleanup();
assertEquals(1, lookupPageStore(ADDRESS).getNumberOfPages());
}
use of org.apache.activemq.artemis.core.transaction.Transaction in project activemq-artemis by apache.
the class QueueImpl method iterQueue.
/**
* This is a generic method for any method interacting on the Queue to move or delete messages
* Instead of duplicate the feature we created an abstract class where you pass the logic for
* each message.
*
* @param filter1
* @param messageAction
* @return
* @throws Exception
*/
private synchronized int iterQueue(final int flushLimit, final Filter filter1, QueueIterateAction messageAction) throws Exception {
int count = 0;
int txCount = 0;
Transaction tx = new TransactionImpl(storageManager);
try (LinkedListIterator<MessageReference> iter = iterator()) {
while (iter.hasNext()) {
MessageReference ref = iter.next();
if (ref.isPaged() && queueDestroyed) {
// page cleanup
continue;
}
if (filter1 == null || filter1.match(ref.getMessage())) {
messageAction.actMessage(tx, ref);
iter.remove();
txCount++;
count++;
}
}
if (txCount > 0) {
tx.commit();
tx = new TransactionImpl(storageManager);
txCount = 0;
}
List<MessageReference> cancelled = scheduledDeliveryHandler.cancel(filter1);
for (MessageReference messageReference : cancelled) {
messageAction.actMessage(tx, messageReference);
count++;
txCount++;
}
if (txCount > 0) {
tx.commit();
tx = new TransactionImpl(storageManager);
txCount = 0;
}
if (pageIterator != null && !queueDestroyed) {
while (pageIterator.hasNext()) {
PagedReference reference = pageIterator.next();
pageIterator.remove();
if (filter1 == null || filter1.match(reference.getMessage())) {
count++;
txCount++;
messageAction.actMessage(tx, reference, false);
} else {
addTail(reference, false);
}
if (txCount > 0 && txCount % flushLimit == 0) {
tx.commit();
tx = new TransactionImpl(storageManager);
txCount = 0;
}
}
}
if (txCount > 0) {
tx.commit();
tx = null;
}
if (filter != null && !queueDestroyed && pageSubscription != null) {
scheduleDepage(false);
}
return count;
}
}
use of org.apache.activemq.artemis.core.transaction.Transaction in project activemq-artemis by apache.
the class QueueImpl method expireReferences.
@Override
public synchronized int expireReferences(final Filter filter) throws Exception {
if (isExpirationRedundant()) {
return 0;
}
Transaction tx = new TransactionImpl(storageManager);
int count = 0;
try (LinkedListIterator<MessageReference> iter = iterator()) {
while (iter.hasNext()) {
MessageReference ref = iter.next();
if (filter == null || filter.match(ref.getMessage())) {
incDelivering(ref);
expire(tx, ref);
iter.remove();
refRemoved(ref);
count++;
}
}
tx.commit();
return count;
}
}
use of org.apache.activemq.artemis.core.transaction.Transaction in project activemq-artemis by apache.
the class ScaleDownHandler method scaleDownRegularMessages.
public long scaleDownRegularMessages(final SimpleString address, final Set<Queue> queues, final ClientSession clientSession, final ClientProducer producer) throws Exception {
logger.debug("Scaling down messages on address " + address);
long messageCount = 0;
final HashMap<Queue, QueuesXRefInnerManager> controls = new HashMap<>();
PagingStore pageStore = pagingManager.getPageStore(address);
Transaction tx = new TransactionImpl(storageManager);
pageStore.disableCleanup();
try {
for (Queue queue : queues) {
controls.put(queue, new QueuesXRefInnerManager(clientSession, queue, pageStore));
}
// compile a list of all the relevant queues and queue iterators for this address
for (Queue loopQueue : queues) {
logger.debug("Scaling down messages on address " + address + " / performing loop on queue " + loopQueue);
try (LinkedListIterator<MessageReference> messagesIterator = loopQueue.browserIterator()) {
while (messagesIterator.hasNext()) {
MessageReference messageReference = messagesIterator.next();
Message message = messageReference.getMessage().copy();
logger.debug("Reading message " + message + " from queue " + loopQueue);
Set<QueuesXRefInnerManager> queuesFound = new HashSet<>();
for (Map.Entry<Queue, QueuesXRefInnerManager> controlEntry : controls.entrySet()) {
if (controlEntry.getKey() == loopQueue) {
// no need to lookup on itself, we just add it
queuesFound.add(controlEntry.getValue());
} else if (controlEntry.getValue().lookup(messageReference)) {
logger.debug("Message existed on queue " + controlEntry.getKey().getID() + " removeID=" + controlEntry.getValue().getQueueID());
queuesFound.add(controlEntry.getValue());
}
}
// get the ID for every queue that contains the message
ByteBuffer buffer = ByteBuffer.allocate(queuesFound.size() * 8);
for (QueuesXRefInnerManager control : queuesFound) {
long queueID = control.getQueueID();
buffer.putLong(queueID);
}
message.putBytesProperty(Message.HDR_ROUTE_TO_IDS.toString(), buffer.array());
if (logger.isDebugEnabled()) {
if (messageReference.isPaged()) {
logger.debug("*********************<<<<< Scaling down pdgmessage " + message);
} else {
logger.debug("*********************<<<<< Scaling down message " + message);
}
}
producer.send(address, message);
messageCount++;
messagesIterator.remove();
// We need to perform the ack / removal after sending, otherwise the message could been removed before the send is finished
for (QueuesXRefInnerManager queueFound : queuesFound) {
ackMessageOnQueue(tx, queueFound.getQueue(), messageReference);
}
}
} catch (NoSuchElementException ignored) {
// this could happen through paging browsing
}
}
tx.commit();
for (QueuesXRefInnerManager controlRemoved : controls.values()) {
controlRemoved.close();
}
return messageCount;
} finally {
pageStore.enableCleanup();
pageStore.getCursorProvider().scheduleCleanup();
}
}
Aggregations