mirror of https://github.com/apache/activemq.git
Setting the Store based cursor as the default for Durable Subscribers
git-svn-id: https://svn.apache.org/repos/asf/incubator/activemq/trunk@480731 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
789d4e5541
commit
4597dddf79
|
@ -47,6 +47,7 @@ import org.apache.activemq.broker.region.DestinationInterceptor;
|
||||||
import org.apache.activemq.broker.region.RegionBroker;
|
import org.apache.activemq.broker.region.RegionBroker;
|
||||||
import org.apache.activemq.broker.region.policy.PendingDurableSubscriberMessageStoragePolicy;
|
import org.apache.activemq.broker.region.policy.PendingDurableSubscriberMessageStoragePolicy;
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
import org.apache.activemq.broker.region.policy.PolicyMap;
|
||||||
|
import org.apache.activemq.broker.region.policy.StorePendingDurableSubscriberMessageStoragePolicy;
|
||||||
import org.apache.activemq.broker.region.policy.VMPendingDurableSubscriberMessageStoragePolicy;
|
import org.apache.activemq.broker.region.policy.VMPendingDurableSubscriberMessageStoragePolicy;
|
||||||
import org.apache.activemq.broker.region.virtual.VirtualDestination;
|
import org.apache.activemq.broker.region.virtual.VirtualDestination;
|
||||||
import org.apache.activemq.broker.region.virtual.VirtualDestinationInterceptor;
|
import org.apache.activemq.broker.region.virtual.VirtualDestinationInterceptor;
|
||||||
|
@ -140,7 +141,8 @@ public class BrokerService implements Service, Serializable {
|
||||||
private ActiveMQDestination[] destinations;
|
private ActiveMQDestination[] destinations;
|
||||||
private Store tempDataStore;
|
private Store tempDataStore;
|
||||||
private int persistenceThreadPriority = Thread.MAX_PRIORITY;
|
private int persistenceThreadPriority = Thread.MAX_PRIORITY;
|
||||||
private PendingDurableSubscriberMessageStoragePolicy pendingDurableSubscriberPolicy = new VMPendingDurableSubscriberMessageStoragePolicy();
|
//private PendingDurableSubscriberMessageStoragePolicy pendingDurableSubscriberPolicy = new VMPendingDurableSubscriberMessageStoragePolicy();
|
||||||
|
private PendingDurableSubscriberMessageStoragePolicy pendingDurableSubscriberPolicy = new StorePendingDurableSubscriberMessageStoragePolicy();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -383,6 +385,7 @@ public class BrokerService implements Service, Serializable {
|
||||||
startDestinations();
|
startDestinations();
|
||||||
|
|
||||||
addShutdownHook();
|
addShutdownHook();
|
||||||
|
log.info("Using Persistence Adaptor " + getPersistenceAdapter());
|
||||||
if (deleteAllMessagesOnStartup) {
|
if (deleteAllMessagesOnStartup) {
|
||||||
deleteAllMessages();
|
deleteAllMessages();
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,9 @@ public class DurableTopicSubscription extends PrefetchSubscription {
|
||||||
if( active || keepDurableSubsActive ) {
|
if( active || keepDurableSubsActive ) {
|
||||||
Topic topic = (Topic) destination;
|
Topic topic = (Topic) destination;
|
||||||
topic.activate(context, this);
|
topic.activate(context, this);
|
||||||
|
if (pending.isEmpty(topic)) {
|
||||||
|
topic.recoverRetroactiveMessages(context, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
dispatchMatched();
|
dispatchMatched();
|
||||||
}
|
}
|
||||||
|
@ -82,6 +85,13 @@ public class DurableTopicSubscription extends PrefetchSubscription {
|
||||||
synchronized(pending) {
|
synchronized(pending) {
|
||||||
pending.start();
|
pending.start();
|
||||||
}
|
}
|
||||||
|
//If nothing was in the persistent store, then try to use the recovery policy.
|
||||||
|
if (pending.isEmpty()) {
|
||||||
|
for (Iterator iter = destinations.values().iterator(); iter.hasNext();) {
|
||||||
|
Topic topic = (Topic) iter.next();
|
||||||
|
topic.recoverRetroactiveMessages(context, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
dispatchMatched();
|
dispatchMatched();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,7 +146,6 @@ public class Topic implements Destination {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void activate(ConnectionContext context, final DurableTopicSubscription subscription) throws Exception {
|
public void activate(ConnectionContext context, final DurableTopicSubscription subscription) throws Exception {
|
||||||
|
|
||||||
// synchronize with dispatch method so that no new messages are sent
|
// synchronize with dispatch method so that no new messages are sent
|
||||||
// while
|
// while
|
||||||
// we are recovering a subscription to avoid out of order messages.
|
// we are recovering a subscription to avoid out of order messages.
|
||||||
|
@ -210,15 +209,7 @@ public class Topic implements Destination {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if( true && subscription.getConsumerInfo().isRetroactive() ) {
|
|
||||||
// If nothing was in the persistent store, then try to use the recovery policy.
|
|
||||||
if( subscription.getEnqueueCounter() == 0 ) {
|
|
||||||
subscriptionRecoveryPolicy.recover(context, this, subscription);
|
|
||||||
} else {
|
|
||||||
// TODO: implement something like
|
|
||||||
// subscriptionRecoveryPolicy.recoverNonPersistent(context, this, sub);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -234,6 +225,14 @@ public class Topic implements Destination {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void recoverRetroactiveMessages(ConnectionContext context,Subscription subscription) throws Exception{
|
||||||
|
if(subscription.getConsumerInfo().isRetroactive()){
|
||||||
|
subscriptionRecoveryPolicy.recover(context,this,subscription);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void send(final ConnectionContext context, final Message message) throws Exception {
|
public void send(final ConnectionContext context, final Message message) throws Exception {
|
||||||
|
|
||||||
// There is delay between the client sending it and it arriving at the
|
// There is delay between the client sending it and it arriving at the
|
||||||
|
|
|
@ -67,6 +67,10 @@ public class AbstractPendingMessageCursor implements PendingMessageCursor{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty(Destination destination) {
|
||||||
|
return isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
public MessageReference next(){
|
public MessageReference next(){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,13 @@ public interface PendingMessageCursor extends Service{
|
||||||
*/
|
*/
|
||||||
public boolean isEmpty();
|
public boolean isEmpty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if a Destination is Empty for this cursor
|
||||||
|
* @param destination
|
||||||
|
* @return true id the Destination is empty
|
||||||
|
*/
|
||||||
|
public boolean isEmpty(Destination destination);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reset the cursor
|
* reset the cursor
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.apache.activemq.advisory.AdvisorySupport;
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
import org.apache.activemq.broker.ConnectionContext;
|
||||||
import org.apache.activemq.broker.region.Destination;
|
import org.apache.activemq.broker.region.Destination;
|
||||||
import org.apache.activemq.broker.region.MessageReference;
|
import org.apache.activemq.broker.region.MessageReference;
|
||||||
|
@ -85,6 +86,7 @@ public class StoreDurableSubscriberCursor extends AbstractPendingMessageCursor{
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public synchronized void add(ConnectionContext context,Destination destination) throws Exception{
|
public synchronized void add(ConnectionContext context,Destination destination) throws Exception{
|
||||||
|
if(destination!=null&&!AdvisorySupport.isAdvisoryTopic(destination.getActiveMQDestination())){
|
||||||
TopicStorePrefetch tsp=new TopicStorePrefetch((Topic)destination,clientId,subscriberName);
|
TopicStorePrefetch tsp=new TopicStorePrefetch((Topic)destination,clientId,subscriberName);
|
||||||
tsp.setMaxBatchSize(getMaxBatchSize());
|
tsp.setMaxBatchSize(getMaxBatchSize());
|
||||||
tsp.setUsageManager(usageManager);
|
tsp.setUsageManager(usageManager);
|
||||||
|
@ -95,6 +97,7 @@ public class StoreDurableSubscriberCursor extends AbstractPendingMessageCursor{
|
||||||
pendingCount+=tsp.size();
|
pendingCount+=tsp.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* remove a destination
|
* remove a destination
|
||||||
|
@ -117,6 +120,15 @@ public class StoreDurableSubscriberCursor extends AbstractPendingMessageCursor{
|
||||||
return pendingCount<=0;
|
return pendingCount<=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty(Destination destination) {
|
||||||
|
boolean result = true;
|
||||||
|
TopicStorePrefetch tsp=(TopicStorePrefetch)topics.get(destination);
|
||||||
|
if(tsp!=null){
|
||||||
|
result = tsp.size() <= 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Informs the Broker if the subscription needs to intervention to recover it's state e.g. DurableTopicSubscriber
|
* Informs the Broker if the subscription needs to intervention to recover it's state e.g. DurableTopicSubscriber
|
||||||
* may do
|
* may do
|
||||||
|
|
|
@ -88,4 +88,6 @@ public interface JDBCAdapter{
|
||||||
|
|
||||||
public void doRecoverNextMessages(TransactionContext c,ActiveMQDestination destination,long nextSeq,int maxReturned,
|
public void doRecoverNextMessages(TransactionContext c,ActiveMQDestination destination,long nextSeq,int maxReturned,
|
||||||
JDBCMessageRecoveryListener listener) throws Exception;
|
JDBCMessageRecoveryListener listener) throws Exception;
|
||||||
|
|
||||||
|
public long doGetLastAckedDurableSubscriberMessageId(TransactionContext c,ActiveMQDestination destination,String clientId, String subscriberName) throws SQLException,IOException;
|
||||||
}
|
}
|
|
@ -99,7 +99,8 @@ public class JDBCTopicMessageStore extends JDBCMessageStore implements TopicMess
|
||||||
String subcriberId=getSubscriptionKey(clientId,subscriptionName);
|
String subcriberId=getSubscriptionKey(clientId,subscriptionName);
|
||||||
AtomicLong last=(AtomicLong)subscriberLastMessageMap.get(subcriberId);
|
AtomicLong last=(AtomicLong)subscriberLastMessageMap.get(subcriberId);
|
||||||
if(last==null){
|
if(last==null){
|
||||||
last=new AtomicLong(-1);
|
long lastAcked = adapter.doGetLastAckedDurableSubscriberMessageId(c,destination,clientId,subscriptionName);
|
||||||
|
last=new AtomicLong(lastAcked);
|
||||||
subscriberLastMessageMap.put(subcriberId,last);
|
subscriberLastMessageMap.put(subcriberId,last);
|
||||||
}
|
}
|
||||||
final AtomicLong finalLast=last;
|
final AtomicLong finalLast=last;
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class Statements {
|
||||||
private String lockUpdateStatement;
|
private String lockUpdateStatement;
|
||||||
private String nextDurableSubscriberMessageStatement;
|
private String nextDurableSubscriberMessageStatement;
|
||||||
private String durableSubscriberMessageCountStatement;
|
private String durableSubscriberMessageCountStatement;
|
||||||
private String nextDurableSubscriberMessageIdStatement;
|
private String lastAckedDurableSubscriberMessageStatement;
|
||||||
private String destinationMessageCountStatement;
|
private String destinationMessageCountStatement;
|
||||||
private String findNextMessagesStatement;
|
private String findNextMessagesStatement;
|
||||||
private boolean useLockCreateWhereClause;
|
private boolean useLockCreateWhereClause;
|
||||||
|
@ -323,6 +323,18 @@ public class Statements {
|
||||||
return findNextMessagesStatement;
|
return findNextMessagesStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the lastAckedDurableSubscriberMessageStatement
|
||||||
|
*/
|
||||||
|
public String getLastAckedDurableSubscriberMessageStatement(){
|
||||||
|
if(lastAckedDurableSubscriberMessageStatement==null) {
|
||||||
|
lastAckedDurableSubscriberMessageStatement = "SELECT MAX(LAST_ACKED_ID) FROM " + getFullAckTableName()
|
||||||
|
+ " WHERE CONTAINER=? AND CLIENT_ID=? AND SUB_NAME=?";
|
||||||
|
}
|
||||||
|
return lastAckedDurableSubscriberMessageStatement;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String getFullMessageTableName() {
|
public String getFullMessageTableName() {
|
||||||
return getTablePrefix() + getMessageTableName();
|
return getTablePrefix() + getMessageTableName();
|
||||||
|
@ -592,19 +604,6 @@ public class Statements {
|
||||||
this.durableSubscriberMessageCountStatement=durableSubscriberMessageCountStatement;
|
this.durableSubscriberMessageCountStatement=durableSubscriberMessageCountStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param nextDurableSubscriberMessageIdStatement the nextDurableSubscriberMessageIdStatement to set
|
|
||||||
*/
|
|
||||||
public void setNextDurableSubscriberMessageIdStatement(String nextDurableSubscriberMessageIdStatement){
|
|
||||||
this.nextDurableSubscriberMessageIdStatement=nextDurableSubscriberMessageIdStatement;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param findNextMessagesStatement the findNextMessagesStatement to set
|
* @param findNextMessagesStatement the findNextMessagesStatement to set
|
||||||
*/
|
*/
|
||||||
|
@ -622,4 +621,14 @@ public class Statements {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param lastAckedDurableSubscriberMessageStatement the lastAckedDurableSubscriberMessageStatement to set
|
||||||
|
*/
|
||||||
|
public void setLastAckedDurableSubscriberMessageStatement(String lastAckedDurableSubscriberMessageStatement){
|
||||||
|
this.lastAckedDurableSubscriberMessageStatement=lastAckedDurableSubscriberMessageStatement;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -545,6 +545,28 @@ public class DefaultJDBCAdapter implements JDBCAdapter{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long doGetLastAckedDurableSubscriberMessageId(TransactionContext c,ActiveMQDestination destination,String clientId, String subscriberName) throws SQLException,IOException{
|
||||||
|
PreparedStatement s=null;
|
||||||
|
ResultSet rs=null;
|
||||||
|
long result = -1;
|
||||||
|
try{
|
||||||
|
s=c.getConnection().prepareStatement(statements.getLastAckedDurableSubscriberMessageStatement());
|
||||||
|
s.setString(1,destination.getQualifiedName());
|
||||||
|
s.setString(2,clientId);
|
||||||
|
s.setString(3,subscriberName);
|
||||||
|
rs=s.executeQuery();
|
||||||
|
if(rs.next()){
|
||||||
|
result=rs.getLong(1);
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
s.close();
|
||||||
|
}finally{
|
||||||
|
close(rs);
|
||||||
|
close(s);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static private void close(PreparedStatement s){
|
static private void close(PreparedStatement s){
|
||||||
try{
|
try{
|
||||||
s.close();
|
s.close();
|
||||||
|
|
|
@ -112,6 +112,7 @@ public class KahaTopicMessageStore extends KahaMessageStore implements TopicMess
|
||||||
if(!subscriberContainer.containsKey(key)){
|
if(!subscriberContainer.containsKey(key)){
|
||||||
subscriberContainer.put(key,info);
|
subscriberContainer.put(key,info);
|
||||||
}
|
}
|
||||||
|
//add the subscriber
|
||||||
ListContainer container=addSubscriberMessageContainer(key);
|
ListContainer container=addSubscriberMessageContainer(key);
|
||||||
if(retroactive){
|
if(retroactive){
|
||||||
for(StoreEntry entry=ackContainer.getFirst();entry!=null;){
|
for(StoreEntry entry=ackContainer.getFirst();entry!=null;){
|
||||||
|
@ -124,24 +125,9 @@ public class KahaTopicMessageStore extends KahaMessageStore implements TopicMess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void deleteSubscription(String clientId,String subscriptionName){
|
public synchronized void deleteSubscription(String clientId,String subscriptionName) throws IOException{
|
||||||
String key=getSubscriptionKey(clientId,subscriptionName);
|
String key=getSubscriptionKey(clientId,subscriptionName);
|
||||||
subscriberContainer.remove(key);
|
removeSubscriberMessageContainer(key);
|
||||||
TopicSubContainer container=(TopicSubContainer)subscriberMessages.get(key);
|
|
||||||
for(Iterator i=container.getListContainer().iterator();i.hasNext();){
|
|
||||||
ConsumerMessageRef ref=(ConsumerMessageRef)i.next();
|
|
||||||
if(ref!=null){
|
|
||||||
TopicSubAck tsa=(TopicSubAck)ackContainer.get(ref.getAckEntry());
|
|
||||||
if(tsa!=null){
|
|
||||||
if(tsa.decrementCount()<=0){
|
|
||||||
ackContainer.remove(ref.getAckEntry());
|
|
||||||
messageContainer.remove(tsa.getMessageEntry());
|
|
||||||
}else{
|
|
||||||
ackContainer.update(ref.getAckEntry(),tsa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recoverSubscription(String clientId,String subscriptionName,MessageRecoveryListener listener)
|
public void recoverSubscription(String clientId,String subscriptionName,MessageRecoveryListener listener)
|
||||||
|
@ -225,6 +211,26 @@ public class KahaTopicMessageStore extends KahaMessageStore implements TopicMess
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void removeSubscriberMessageContainer(Object key) throws IOException {
|
||||||
|
subscriberContainer.remove(key);
|
||||||
|
TopicSubContainer container=(TopicSubContainer)subscriberMessages.remove(key);
|
||||||
|
for(Iterator i=container.getListContainer().iterator();i.hasNext();){
|
||||||
|
ConsumerMessageRef ref=(ConsumerMessageRef)i.next();
|
||||||
|
if(ref!=null){
|
||||||
|
TopicSubAck tsa=(TopicSubAck)ackContainer.get(ref.getAckEntry());
|
||||||
|
if(tsa!=null){
|
||||||
|
if(tsa.decrementCount()<=0){
|
||||||
|
ackContainer.remove(ref.getAckEntry());
|
||||||
|
messageContainer.remove(tsa.getMessageEntry());
|
||||||
|
}else{
|
||||||
|
ackContainer.update(ref.getAckEntry(),tsa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
store.deleteListContainer(key,"topic-subs");
|
||||||
|
}
|
||||||
|
|
||||||
public int getMessageCount(String clientId,String subscriberName) throws IOException{
|
public int getMessageCount(String clientId,String subscriberName) throws IOException{
|
||||||
String key=getSubscriptionKey(clientId,subscriberName);
|
String key=getSubscriptionKey(clientId,subscriberName);
|
||||||
TopicSubContainer container=(TopicSubContainer)subscriberMessages.get(key);
|
TopicSubContainer container=(TopicSubContainer)subscriberMessages.get(key);
|
||||||
|
|
|
@ -132,24 +132,9 @@ public class RapidTopicMessageStore extends RapidMessageStore implements TopicMe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void deleteSubscription(String clientId,String subscriptionName){
|
public synchronized void deleteSubscription(String clientId,String subscriptionName) throws IOException{
|
||||||
String key=getSubscriptionKey(clientId,subscriptionName);
|
String key=getSubscriptionKey(clientId,subscriptionName);
|
||||||
subscriberContainer.remove(key);
|
removeSubscriberMessageContainer(key);
|
||||||
TopicSubContainer container=(TopicSubContainer)subscriberMessages.get(key);
|
|
||||||
for(Iterator i=container.getListContainer().iterator();i.hasNext();){
|
|
||||||
ConsumerMessageRef ref=(ConsumerMessageRef)i.next();
|
|
||||||
if(ref!=null){
|
|
||||||
TopicSubAck tsa=(TopicSubAck)ackContainer.get(ref.getAckEntry());
|
|
||||||
if(tsa!=null){
|
|
||||||
if(tsa.decrementCount()<=0){
|
|
||||||
ackContainer.remove(ref.getAckEntry());
|
|
||||||
messageContainer.remove(tsa.getMessageEntry());
|
|
||||||
}else{
|
|
||||||
ackContainer.update(ref.getAckEntry(),tsa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recoverSubscription(String clientId,String subscriptionName,MessageRecoveryListener listener)
|
public void recoverSubscription(String clientId,String subscriptionName,MessageRecoveryListener listener)
|
||||||
|
@ -222,6 +207,26 @@ public class RapidTopicMessageStore extends RapidMessageStore implements TopicMe
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void removeSubscriberMessageContainer(Object key) throws IOException {
|
||||||
|
subscriberContainer.remove(key);
|
||||||
|
TopicSubContainer container=(TopicSubContainer)subscriberMessages.remove(key);
|
||||||
|
for(Iterator i=container.getListContainer().iterator();i.hasNext();){
|
||||||
|
ConsumerMessageRef ref=(ConsumerMessageRef)i.next();
|
||||||
|
if(ref!=null){
|
||||||
|
TopicSubAck tsa=(TopicSubAck)ackContainer.get(ref.getAckEntry());
|
||||||
|
if(tsa!=null){
|
||||||
|
if(tsa.decrementCount()<=0){
|
||||||
|
ackContainer.remove(ref.getAckEntry());
|
||||||
|
messageContainer.remove(tsa.getMessageEntry());
|
||||||
|
}else{
|
||||||
|
ackContainer.update(ref.getAckEntry(),tsa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
store.deleteListContainer(key,"topic-subs");
|
||||||
|
}
|
||||||
|
|
||||||
public int getMessageCount(String clientId,String subscriberName) throws IOException{
|
public int getMessageCount(String clientId,String subscriberName) throws IOException{
|
||||||
String key=getSubscriptionKey(clientId,subscriberName);
|
String key=getSubscriptionKey(clientId,subscriberName);
|
||||||
TopicSubContainer container=(TopicSubContainer)subscriberMessages.get(key);
|
TopicSubContainer container=(TopicSubContainer)subscriberMessages.get(key);
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
|
||||||
|
* file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||||
|
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.activemq.usecases;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.apache.activemq.store.PersistenceAdapter;
|
||||||
|
import org.apache.activemq.store.kahadaptor.KahaPersistenceAdapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @version $Revision: 1.1.1.1 $
|
||||||
|
*/
|
||||||
|
public class KahaDurableSubscriptionTest extends DurableSubscriptionTestSupport{
|
||||||
|
|
||||||
|
protected PersistenceAdapter createPersistenceAdapter() throws IOException{
|
||||||
|
File dataDir=new File("target/test-data/durableKaha");
|
||||||
|
KahaPersistenceAdapter adaptor=new KahaPersistenceAdapter(dataDir);
|
||||||
|
return adaptor;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue