@Override @Before public void setUp() throws Exception { super.setUp(); server = internalCreateServer(); server.createAddressInfo(new AddressInfo(ADDRESS, RoutingType.ANYCAST)); Queue queue = server.createQueue(ADDRESS, RoutingType.ANYCAST, ADDRESS, null, true, false); queue.getPageSubscription().getPagingStore().startPaging(); for (int i = 0; i < 10; i++) { queue.getPageSubscription().getPagingStore().forceAnotherPage(); } final ClientSessionFactory sf = createSessionFactory(locator); ClientSession session = sf.createSession(null, null, false, true, true, false, 0); ClientProducer prod = session.createProducer(ADDRESS); for (int i = 0; i < 500; i++) { ClientMessage msg = session.createMessage(true); msg.putIntProperty("key", i); prod.send(msg); if (i > 0 && i % 10 == 0) { session.commit(); } } session.close(); locator.close(); server.stop(); internalCreateServer(); }
// HORNETQ- 1084 @Test public void testBasicSendWithDLAButNoBinding() throws Exception { SimpleString dla = new SimpleString("DLA"); SimpleString qName = new SimpleString("q1"); AddressSettings addressSettings = new AddressSettings().setMaxDeliveryAttempts(1).setDeadLetterAddress(dla); server.getAddressSettingsRepository().addMatch(qName.toString(), addressSettings); // SimpleString dlq = new SimpleString("DLQ1"); // clientSession.createQueue(dla, dlq, null, false); clientSession.createQueue(qName, qName, null, false); ClientProducer producer = clientSession.createProducer(qName); producer.send(createTextMessage(clientSession, "heyho!")); clientSession.start(); ClientConsumer clientConsumer = clientSession.createConsumer(qName); ClientMessage m = clientConsumer.receive(500); m.acknowledge(); Assert.assertNotNull(m); Assert.assertEquals(m.getBodyBuffer().readString(), "heyho!"); // force a cancel clientSession.rollback(); m = clientConsumer.receiveImmediate(); Assert.assertNull(m); clientConsumer.close(); Queue q = (Queue) server.getPostOffice().getBinding(qName).getBindable(); Assert.assertEquals(0, q.getDeliveringCount()); }
@Override public CompositeData[] browse(String filterStr) throws Exception { checkStarted(); clearIO(); try { int pageSize = addressSettingsRepository .getMatch(queue.getName().toString()) .getManagementBrowsePageSize(); int currentPageSize = 0; ArrayList<CompositeData> c = new ArrayList<>(); Filter filter = FilterImpl.createFilter(filterStr); queue.flushExecutor(); try (LinkedListIterator<MessageReference> iterator = queue.totalIterator()) { while (iterator.hasNext() && currentPageSize++ < pageSize) { MessageReference ref = iterator.next(); if (filter == null || filter.match(ref.getMessage())) { c.add(OpenTypeSupport.convert(ref)); } } CompositeData[] rc = new CompositeData[c.size()]; c.toArray(rc); return rc; } } catch (ActiveMQException e) { throw new IllegalStateException(e.getMessage()); } finally { blockOnIO(); } }
@Override public Map<String, Object>[] listMessages(final String filterStr) throws Exception { checkStarted(); clearIO(); try { Filter filter = FilterImpl.createFilter(filterStr); List<Map<String, Object>> messages = new ArrayList<>(); queue.flushExecutor(); try (LinkedListIterator<MessageReference> iterator = queue.totalIterator()) { while (iterator.hasNext()) { MessageReference ref = iterator.next(); if (filter == null || filter.match(ref.getMessage())) { Message message = ref.getMessage(); messages.add(message.toMap()); } } return messages.toArray(new Map[messages.size()]); } } catch (ActiveMQException e) { throw new IllegalStateException(e.getMessage()); } finally { blockOnIO(); } }
/** * This generates a map for use on the recalculation and recovery of pending maps after reloading * it * * @param queues * @param pendingNonTXPageCounter * @param txRecoverCounter * @return * @throws Exception */ private Map<SimpleString, Map<Long, Map<Long, List<PageCountPending>>>> generateMapsOnPendingCount( Map<Long, Queue> queues, List<PageCountPending> pendingNonTXPageCounter, Transaction txRecoverCounter) throws Exception { Map<SimpleString, Map<Long, Map<Long, List<PageCountPending>>>> perAddressMap = new HashMap<>(); for (PageCountPending pgCount : pendingNonTXPageCounter) { long queueID = pgCount.getQueueID(); long pageID = pgCount.getPageID(); // We first figure what Queue is based on the queue id Queue queue = queues.get(queueID); if (queue == null) { logger.debug( "removing pending page counter id = " + pgCount.getID() + " as queueID=" + pgCount.getID() + " no longer exists"); // this means the queue doesn't exist any longer, we will remove it from the storage storageManager.deletePendingPageCounter(txRecoverCounter.getID(), pgCount.getID()); txRecoverCounter.setContainsPersistent(); continue; } // Level 1 on the structure, per address SimpleString address = queue.getAddress(); Map<Long, Map<Long, List<PageCountPending>>> perPageMap = perAddressMap.get(address); if (perPageMap == null) { perPageMap = new HashMap<>(); perAddressMap.put(address, perPageMap); } Map<Long, List<PageCountPending>> perQueueMap = perPageMap.get(pageID); if (perQueueMap == null) { perQueueMap = new HashMap<>(); perPageMap.put(pageID, perQueueMap); } List<PageCountPending> pendingCounters = perQueueMap.get(queueID); if (pendingCounters == null) { pendingCounters = new LinkedList<>(); perQueueMap.put(queueID, pendingCounters); } pendingCounters.add(pgCount); perQueueMap.put(queueID, pendingCounters); } return perAddressMap; }
@Override public void connectionFailed( final ActiveMQException me, boolean failedOver, String scaleDownTargetNodeID) { ActiveMQServerLogger.LOGGER.bridgeConnectionFailed(failedOver); synchronized (connectionGuard) { keepConnecting = true; } try { if (producer != null) { producer.close(); } cleanUpSessionFactory(csf); } catch (Throwable dontCare) { } try { session.cleanUp(false); } catch (Throwable dontCare) { } if (scaleDownTargetNodeID != null && !scaleDownTargetNodeID.equals(nodeUUID.toString())) { synchronized (this) { try { logger.debug( "Moving " + queue.getMessageCount() + " messages from " + queue.getName() + " to " + scaleDownTargetNodeID); ((QueueImpl) queue) .moveReferencesBetweenSnFQueues(SimpleString.toSimpleString(scaleDownTargetNodeID)); // stop the bridge from trying to reconnect and clean up all the bindings fail(true); } catch (Exception e) { ActiveMQServerLogger.LOGGER.warn(e.getMessage(), e); } } } else if (scaleDownTargetNodeID != null) { // the disconnected node is scaling down to me, no need to reconnect to it logger.debug( "Received scaleDownTargetNodeID: " + scaleDownTargetNodeID + "; cancelling reconnect."); fail(true); } else { logger.debug("Received invalid scaleDownTargetNodeID: " + scaleDownTargetNodeID); fail(me.getType() == ActiveMQExceptionType.DISCONNECTED); } tryScheduleRetryReconnect(me.getType()); }
@Override public String toManagementString() { return this.getClass().getSimpleName() + " [name=" + name + ", queue=" + queue.getName() + "/" + queue.getID() + "]"; }
@Override public void handleAddMessage(Map<Long, Map<Long, AddMessageRecord>> queueMap) throws Exception { for (Map.Entry<Long, Map<Long, AddMessageRecord>> entry : queueMap.entrySet()) { long queueID = entry.getKey(); Map<Long, AddMessageRecord> queueRecords = entry.getValue(); Queue queue = this.queues.get(queueID); if (queue == null) { if (queueRecords.values().size() != 0) { ActiveMQServerLogger.LOGGER.journalCannotFindQueueForMessage(queueID); } continue; } // Redistribution could install a Redistributor while we are still loading records, what will // be an issue with // prepared ACKs // We make sure te Queue is paused before we reroute values. queue.pause(); Collection<AddMessageRecord> valueRecords = queueRecords.values(); long currentTime = System.currentTimeMillis(); for (AddMessageRecord record : valueRecords) { long scheduledDeliveryTime = record.getScheduledDeliveryTime(); if (scheduledDeliveryTime != 0 && scheduledDeliveryTime <= currentTime) { scheduledDeliveryTime = 0; record.getMessage().removeProperty(Message.HDR_SCHEDULED_DELIVERY_TIME); } if (scheduledDeliveryTime != 0) { record .getMessage() .putLongProperty(Message.HDR_SCHEDULED_DELIVERY_TIME, scheduledDeliveryTime); } MessageReference ref = postOffice.reroute(record.getMessage(), queue, null); ref.setDeliveryCount(record.getDeliveryCount()); if (scheduledDeliveryTime != 0) { record.getMessage().removeProperty(Message.HDR_SCHEDULED_DELIVERY_TIME); } } } }
@Override public void postLoad( Journal messageJournal, ResourceManager resourceManager, Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap) throws Exception { for (Queue queue : queues.values()) { queue.resume(); } if (System.getProperty("org.apache.activemq.opt.directblast") != null) { messageJournal.runDirectJournalBlast(); } }
@Override public int moveMessages( final int flushLimit, final String filterStr, final String otherQueueName, final boolean rejectDuplicates) throws Exception { checkStarted(); clearIO(); try { Filter filter = FilterImpl.createFilter(filterStr); Binding binding = postOffice.getBinding(new SimpleString(otherQueueName)); if (binding == null) { throw ActiveMQMessageBundle.BUNDLE.noQueueFound(otherQueueName); } int retValue = queue.moveReferences(flushLimit, filter, binding.getAddress(), rejectDuplicates); return retValue; } finally { blockOnIO(); } }
@Override public String listConsumersAsJSON() throws Exception { checkStarted(); clearIO(); try { Collection<Consumer> consumers = queue.getConsumers(); JSONArray jsonArray = new JSONArray(); for (Consumer consumer : consumers) { if (consumer instanceof ServerConsumer) { ServerConsumer serverConsumer = (ServerConsumer) consumer; JSONObject obj = new JSONObject(); obj.put("consumerID", serverConsumer.getID()); obj.put("connectionID", serverConsumer.getConnectionID().toString()); obj.put("sessionID", serverConsumer.getSessionID()); obj.put("browseOnly", serverConsumer.isBrowseOnly()); obj.put("creationTime", serverConsumer.getCreationTime()); jsonArray.put(obj); } } return jsonArray.toString(); } finally { blockOnIO(); } }
private void internalCancelReferences() { cancelRefs(); if (queue != null) { queue.deliverAsync(); } }
@Override public boolean retryMessage(final long messageID) throws Exception { checkStarted(); clearIO(); try { Filter singleMessageFilter = new Filter() { @Override public boolean match(ServerMessage message) { return message.getMessageID() == messageID; } @Override public SimpleString getFilterString() { return new SimpleString("custom filter for MESSAGEID= messageID"); } }; return queue.retryMessages(singleMessageFilter) > 0; } finally { blockOnIO(); } }
@Override public long countMessages(final String filterStr) throws Exception { checkStarted(); clearIO(); try { Filter filter = FilterImpl.createFilter(filterStr); if (filter == null) { return getMessageCount(); } else { try (LinkedListIterator<MessageReference> iterator = queue.totalIterator()) { int count = 0; while (iterator.hasNext()) { MessageReference ref = iterator.next(); if (filter.match(ref.getMessage())) { count++; } } return count; } } } finally { blockOnIO(); } }
@Override public void handlePreparedAcknowledge( long messageID, List<MessageReference> referencesToAck, long queueID) throws Exception { Queue queue = queues.get(queueID); if (queue == null) { throw new IllegalStateException("Cannot find queue with id " + queueID); } MessageReference removed = queue.removeReferenceWithID(messageID); if (removed == null) { ActiveMQServerLogger.LOGGER.journalErrorRemovingRef(messageID); } else { referencesToAck.add(removed); } }
@Override public String getName() { clearIO(); try { return queue.getName().toString(); } finally { blockOnIO(); } }
@Override public String sendMessage( final Map<String, String> headers, final int type, final String body, final String userID, boolean durable, final String user, final String password) throws Exception { securityStore.check( queue.getAddress(), CheckType.SEND, new SecurityAuth() { @Override public String getUsername() { return user; } @Override public String getPassword() { return password; } @Override public RemotingConnection getRemotingConnection() { return null; } }); ServerMessageImpl message = new ServerMessageImpl(storageManager.generateID(), 50); for (String header : headers.keySet()) { message.putStringProperty(new SimpleString(header), new SimpleString(headers.get(header))); } message.setType((byte) type); message.setDurable(durable); message.setTimestamp(System.currentTimeMillis()); message.setUserID(new UUID(UUID.TYPE_TIME_BASED, UUID.stringToBytes(userID))); if (body != null) { message.getBodyBuffer().writeBytes(Base64.decode(body)); } message.setAddress(queue.getAddress()); postOffice.route(message, null, true); return "" + message.getMessageID(); }
/** * This is done to prevent non tx to get out of sync in case of failures * * @param tx * @param page * @param ctx * @throws Exception */ private void applyPageCounters(Transaction tx, Page page, RouteContextList ctx) throws Exception { List<org.apache.activemq.artemis.core.server.Queue> durableQueues = ctx.getDurableQueues(); List<org.apache.activemq.artemis.core.server.Queue> nonDurableQueues = ctx.getNonDurableQueues(); for (org.apache.activemq.artemis.core.server.Queue q : durableQueues) { if (tx == null) { // non transactional writes need an intermediate place // to avoid the counter getting out of sync q.getPageSubscription().getCounter().pendingCounter(page, 1); } else { // null tx is treated through pending counters q.getPageSubscription().getCounter().increment(tx, 1); } } for (org.apache.activemq.artemis.core.server.Queue q : nonDurableQueues) { q.getPageSubscription().getCounter().increment(tx, 1); } }
protected void fail(final boolean permanently) { logger.debug(this + "\n\t::fail being called, permanently=" + permanently); if (queue != null) { try { if (logger.isTraceEnabled()) { logger.trace("Removing consumer on fail " + this + " from queue " + queue); } queue.removeConsumer(this); } catch (Exception dontcare) { logger.debug(dontcare); } } cancelRefs(); if (queue != null) { queue.deliverAsync(); } }
@Override public boolean isPaused() throws Exception { checkStarted(); clearIO(); try { return queue.isPaused(); } finally { blockOnIO(); } }
@Override public boolean expireMessage(final long messageID) throws Exception { checkStarted(); clearIO(); try { return queue.expireReference(messageID); } finally { blockOnIO(); } }
@Override public int retryMessages() throws Exception { checkStarted(); clearIO(); try { return queue.retryMessages(null); } finally { blockOnIO(); } }
/** * @param queue * @return * @throws Exception */ private PageSubscriptionCounter locateCounter(Queue queue) throws Exception { PageSubscription subscription = server .getPagingManager() .getPageStore(new SimpleString("A1")) .getCursorProvider() .getSubscription(queue.getID()); PageSubscriptionCounter counter = subscription.getCounter(); return counter; }
@Override public void resetMessagesAcknowledged() throws Exception { checkStarted(); clearIO(); try { queue.resetMessagesAcknowledged(); } finally { blockOnIO(); } }
@Override public long getScheduledCount() { checkStarted(); clearIO(); try { return queue.getScheduledCount(); } finally { blockOnIO(); } }
@Override public void flushExecutor() { checkStarted(); clearIO(); try { queue.flushExecutor(); } finally { blockOnIO(); } }
@Override public boolean sendMessageToDeadLetterAddress(final long messageID) throws Exception { checkStarted(); clearIO(); try { return queue.sendMessageToDeadLetterAddress(messageID); } finally { blockOnIO(); } }
@Override public void resume() { checkStarted(); clearIO(); try { queue.resume(); } finally { blockOnIO(); } }
@Override public long getMessagesAcknowledged() { checkStarted(); clearIO(); try { return queue.getMessagesAcknowledged(); } finally { blockOnIO(); } }
protected Map<String, Object>[] getFirstMessage() throws Exception { checkStarted(); clearIO(); try { List<Map<String, Object>> messages = new ArrayList<>(); queue.flushExecutor(); try (LinkedListIterator<MessageReference> iterator = queue.totalIterator()) { // returns just the first, as it's the first only if (iterator.hasNext()) { MessageReference ref = iterator.next(); Message message = ref.getMessage(); messages.add(message.toMap()); } return messages.toArray(new Map[1]); } } finally { blockOnIO(); } }