@Override protected void refRemoved(MessageReference ref) { if (isNonDestructive()) { removeIfCurrent(ref); } super.refRemoved(ref); }
@Override public synchronized void addTail(final MessageReference ref, final boolean direct) { if (scheduleIfPossible(ref)) { return; } final SimpleString prop = ref.getLastValueProperty(); if (prop != null) { HolderReference hr = map.get(prop); if (hr != null) { // We need to overwrite the old ref with the new one and ack the old one replaceLVQMessage(ref, hr); } else { hr = new HolderReference(prop, ref); map.put(prop, hr); super.addTail(hr, direct); } } else { super.addTail(ref, direct); } }
public void testNonDestructiveLVQTombstone(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier) throws Exception { int tombstoneTimeToLive = 500; QueueBinding queueBinding = (QueueBinding) server.getPostOffice().getBinding(SimpleString.toSimpleString(NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME)); LastValueQueue lastValueQueue = (LastValueQueue)queueBinding.getQueue(); //Send again sendLVQ(producerConnectionSupplier, NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString()); assertEquals("Ensure Message count", 1, lastValueQueue.getMessageCount()); //Simulate a small pause, else both messages could be consumed if consumer is fast enough Thread.sleep(10); //Consume Once More receiveLVQ(consumerConnectionSupplier, NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString()); //Send Tombstone sendLVQTombstone(producerConnectionSupplier, NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString(), tombstoneTimeToLive); assertEquals("Ensure Message count", 1, lastValueQueue.getMessageCount()); //Simulate a small pause, else both messages could be consumed if consumer is fast enough Thread.sleep(10); //Consume Tombstone ensuring Tombstone exists receiveLVQTombstone(consumerConnectionSupplier, NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString()); //Consume Again ensuring Tombstone exists as should not have expired receiveLVQTombstone(consumerConnectionSupplier, NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString()); assertEquals("Ensure Message count", 1, lastValueQueue.getLastValueKeys().size()); //Ensure enough time elapsed for expiration and expiry thread to have run. Thread.sleep(tombstoneTimeToLive * 3); // Consume again testing tombstone has been removed receiveLVQAssertEmpty(consumerConnectionSupplier, NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME); assertEquals("Ensure Message count", 0, lastValueQueue.getMessageCount()); assertEquals("Ensure Message count", 0, lastValueQueue.getLastValueKeys().size()); }
@Deprecated @Override public Queue createQueue(final long persistenceID, final SimpleString address, final SimpleString name, final Filter filter, final PageSubscription pageSubscription, final SimpleString user, final boolean durable, final boolean temporary, final boolean autoCreated) throws Exception { // Add default address info if one doesn't exist postOffice.addAddressInfo(new AddressInfo(address)); AddressSettings addressSettings = addressSettingsRepository.getMatch(address.toString()); Queue queue; if (lastValueKey(addressSettings) != null) { queue = new LastValueQueue(persistenceID, address, name, filter, pageSubscription, user, durable, temporary, autoCreated, ActiveMQDefaultConfiguration.getDefaultRoutingType(), ActiveMQDefaultConfiguration.getDefaultMaxQueueConsumers(), ActiveMQDefaultConfiguration.getDefaultExclusive(), ActiveMQDefaultConfiguration.getDefaultConsumersBeforeDispatch(), ActiveMQDefaultConfiguration.getDefaultDelayBeforeDispatch(), ActiveMQDefaultConfiguration.getDefaultPurgeOnNoConsumers(), lastValueKey(addressSettings), ActiveMQDefaultConfiguration.getDefaultNonDestructive(), false, scheduledExecutor, postOffice, storageManager, addressSettingsRepository, executorFactory.getExecutor(), server, this); } else { queue = new QueueImpl(persistenceID, address, name, filter, pageSubscription, user, durable, temporary, autoCreated, scheduledExecutor, postOffice, storageManager, addressSettingsRepository, executorFactory.getExecutor(), server, this); } server.getCriticalAnalyzer().add(queue); return queue; }
private void replaceLVQMessage(MessageReference ref, HolderReference hr) { MessageReference oldRef = hr.getReference(); referenceHandled(ref); try { oldRef.acknowledge(null, AckReason.REPLACED, null); } catch (Exception e) { ActiveMQServerLogger.LOGGER.errorAckingOldReference(e); } hr.setReference(ref); }
@Override public synchronized void addHead(final MessageReference ref, boolean scheduling) { SimpleString lastValueProp = ref.getLastValueProperty(); if (lastValueProp != null) { HolderReference hr = map.get(lastValueProp); if (hr != null) { if (scheduling) { // We need to overwrite the old ref with the new one and ack the old one replaceLVQMessage(ref, hr); } else { // We keep the current ref and ack the one we are returning super.referenceHandled(ref); try { super.acknowledge(ref); } catch (Exception e) { ActiveMQServerLogger.LOGGER.errorAckingOldReference(e); } } } else { hr = new HolderReference(lastValueProp, ref); map.put(lastValueProp, hr); super.addHead(hr, scheduling); } } else { super.addHead(ref, scheduling); } }
@Override public Queue createQueueWith(final QueueConfig config) { final Queue queue; if (lastValueKey(config) != null) { queue = new LastValueQueue(config.id(), config.address(), config.name(), config.filter(), config.pageSubscription(), config.user(), config.isDurable(), config.isTemporary(), config.isAutoCreated(), config.deliveryMode(), config.maxConsumers(), config.isExclusive(), config.consumersBeforeDispatch(), config.delayBeforeDispatch(), config.isPurgeOnNoConsumers(), lastValueKey(config), config.isNonDestructive(), config.isConfigurationManaged(), scheduledExecutor, postOffice, storageManager, addressSettingsRepository, executorFactory.getExecutor(), server, this); } else { queue = new QueueImpl(config.id(), config.address(), config.name(), config.filter(), config.pageSubscription(), config.user(), config.isDurable(), config.isTemporary(), config.isAutoCreated(), config.deliveryMode(), config.maxConsumers(), config.isExclusive(), config.isNonDestructive(), config.consumersBeforeDispatch(), config.delayBeforeDispatch(), config.isPurgeOnNoConsumers(), config.isConfigurationManaged(), scheduledExecutor, postOffice, storageManager, addressSettingsRepository, executorFactory.getExecutor(), server, this); } server.getCriticalAnalyzer().add(queue); return queue; }
@Override public void acknowledge(final MessageReference ref, final AckReason reason, final ServerConsumer consumer) throws Exception { if (isNonDestructive() && reason == AckReason.EXPIRED || reason == AckReason.KILLED ) { removeIfCurrent(ref); } super.acknowledge(ref, reason, consumer); }