mirror of https://github.com/apache/activemq.git
resolve https://issues.apache.org/activemq/browse/AMQ-2980 for kahaDB
git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@1022890 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
87eba29520
commit
9705671546
|
@ -717,7 +717,7 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
|
||||||
public int getMessageCount(String clientId, String subscriptionName) throws IOException {
|
public int getMessageCount(String clientId, String subscriptionName) throws IOException {
|
||||||
final String subscriptionKey = subscriptionKey(clientId, subscriptionName);
|
final String subscriptionKey = subscriptionKey(clientId, subscriptionName);
|
||||||
final SubscriptionInfo info = lookupSubscription(clientId, subscriptionName);
|
final SubscriptionInfo info = lookupSubscription(clientId, subscriptionName);
|
||||||
indexLock.readLock().lock();
|
indexLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
return pageFile.tx().execute(new Transaction.CallableClosure<Integer, IOException>() {
|
return pageFile.tx().execute(new Transaction.CallableClosure<Integer, IOException>() {
|
||||||
public Integer execute(Transaction tx) throws IOException {
|
public Integer execute(Transaction tx) throws IOException {
|
||||||
|
@ -727,8 +727,8 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
|
||||||
// The subscription might not exist.
|
// The subscription might not exist.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
MessageOrderCursor moc = new MessageOrderCursor(cursorPos + 1);
|
sd.orderIndex.resetCursorPosition();
|
||||||
|
sd.orderIndex.setBatch(tx, cursorPos);
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
try {
|
try {
|
||||||
String selector = info.getSelector();
|
String selector = info.getSelector();
|
||||||
|
@ -736,7 +736,7 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
|
||||||
if (selector != null) {
|
if (selector != null) {
|
||||||
selectorExpression = SelectorParser.parse(selector);
|
selectorExpression = SelectorParser.parse(selector);
|
||||||
}
|
}
|
||||||
for (Iterator<Entry<Long, MessageKeys>> iterator = sd.orderIndex.iterator(tx, moc); iterator
|
for (Iterator<Entry<Long, MessageKeys>> iterator = sd.orderIndex.iterator(tx); iterator
|
||||||
.hasNext();) {
|
.hasNext();) {
|
||||||
Entry<Long, MessageKeys> entry = iterator.next();
|
Entry<Long, MessageKeys> entry = iterator.next();
|
||||||
if (selectorExpression != null) {
|
if (selectorExpression != null) {
|
||||||
|
@ -757,7 +757,7 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}finally {
|
}finally {
|
||||||
indexLock.readLock().unlock();
|
indexLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -786,15 +786,19 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
|
||||||
public void recoverNextMessages(String clientId, String subscriptionName, final int maxReturned,
|
public void recoverNextMessages(String clientId, String subscriptionName, final int maxReturned,
|
||||||
final MessageRecoveryListener listener) throws Exception {
|
final MessageRecoveryListener listener) throws Exception {
|
||||||
final String subscriptionKey = subscriptionKey(clientId, subscriptionName);
|
final String subscriptionKey = subscriptionKey(clientId, subscriptionName);
|
||||||
indexLock.readLock().lock();
|
indexLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
pageFile.tx().execute(new Transaction.Closure<Exception>() {
|
pageFile.tx().execute(new Transaction.Closure<Exception>() {
|
||||||
public void execute(Transaction tx) throws Exception {
|
public void execute(Transaction tx) throws Exception {
|
||||||
StoredDestination sd = getStoredDestination(dest, tx);
|
StoredDestination sd = getStoredDestination(dest, tx);
|
||||||
|
sd.orderIndex.resetCursorPosition();
|
||||||
MessageOrderCursor moc = sd.subscriptionCursors.get(subscriptionKey);
|
MessageOrderCursor moc = sd.subscriptionCursors.get(subscriptionKey);
|
||||||
if (moc == null) {
|
if (moc == null) {
|
||||||
long pos = sd.subscriptionAcks.get(tx, subscriptionKey);
|
long pos = sd.subscriptionAcks.get(tx, subscriptionKey);
|
||||||
moc = new MessageOrderCursor(pos+1);
|
sd.orderIndex.setBatch(tx, pos);
|
||||||
|
moc = sd.orderIndex.cursor;
|
||||||
|
} else {
|
||||||
|
sd.orderIndex.cursor.sync(moc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry<Long, MessageKeys> entry = null;
|
Entry<Long, MessageKeys> entry = null;
|
||||||
|
@ -813,11 +817,14 @@ public class KahaDBStore extends MessageDatabase implements PersistenceAdapter {
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
MessageOrderCursor copy = sd.orderIndex.cursor.copy();
|
MessageOrderCursor copy = sd.orderIndex.cursor.copy();
|
||||||
sd.subscriptionCursors.put(subscriptionKey, copy);
|
sd.subscriptionCursors.put(subscriptionKey, copy);
|
||||||
|
if (LOG.isDebugEnabled()) {
|
||||||
|
LOG.debug("updated moc: " + copy + ", recovered: " + counter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}finally {
|
}finally {
|
||||||
indexLock.readLock().unlock();
|
indexLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1875,6 +1875,18 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
|
||||||
lowPriorityCursorPosition++;
|
lowPriorityCursorPosition++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "MessageOrderCursor:[def:" + defaultCursorPosition
|
||||||
|
+ ", low:" + lowPriorityCursorPosition
|
||||||
|
+ ", high:" + highPriorityCursorPosition + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sync(MessageOrderCursor other) {
|
||||||
|
this.defaultCursorPosition=other.defaultCursorPosition;
|
||||||
|
this.lowPriorityCursorPosition=other.lowPriorityCursorPosition;
|
||||||
|
this.highPriorityCursorPosition=other.highPriorityCursorPosition;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageOrderIndex{
|
class MessageOrderIndex{
|
||||||
|
@ -2010,11 +2022,11 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
|
||||||
|
|
||||||
void getDeleteList(Transaction tx, ArrayList<Entry<Long, MessageKeys>> deletes, Long sequenceId)
|
void getDeleteList(Transaction tx, ArrayList<Entry<Long, MessageKeys>> deletes, Long sequenceId)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
if (defaultPriorityIndex.containsKey(tx, sequenceId)) {
|
||||||
getDeleteList(tx, deletes, defaultPriorityIndex, sequenceId);
|
getDeleteList(tx, deletes, defaultPriorityIndex, sequenceId);
|
||||||
if (highPriorityIndex != null) {
|
} else if (highPriorityIndex != null && highPriorityIndex.containsKey(tx, sequenceId)) {
|
||||||
getDeleteList(tx, deletes, highPriorityIndex, sequenceId);
|
getDeleteList(tx, deletes, highPriorityIndex, sequenceId);
|
||||||
}
|
} else if (lowPriorityIndex != null && lowPriorityIndex.containsKey(tx, sequenceId)) {
|
||||||
if (lowPriorityIndex != null) {
|
|
||||||
getDeleteList(tx, deletes, lowPriorityIndex, sequenceId);
|
getDeleteList(tx, deletes, lowPriorityIndex, sequenceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2073,7 +2085,6 @@ public class MessageDatabase extends ServiceSupport implements BrokerServiceAwar
|
||||||
final Iterator<Entry<Long, MessageKeys>>highIterator;
|
final Iterator<Entry<Long, MessageKeys>>highIterator;
|
||||||
final Iterator<Entry<Long, MessageKeys>>defaultIterator;
|
final Iterator<Entry<Long, MessageKeys>>defaultIterator;
|
||||||
final Iterator<Entry<Long, MessageKeys>>lowIterator;
|
final Iterator<Entry<Long, MessageKeys>>lowIterator;
|
||||||
Long lastKey;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import javax.jms.Topic;
|
||||||
import javax.jms.TopicSubscriber;
|
import javax.jms.TopicSubscriber;
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||||
|
import org.apache.activemq.ActiveMQPrefetchPolicy;
|
||||||
import org.apache.activemq.CombinationTestSupport;
|
import org.apache.activemq.CombinationTestSupport;
|
||||||
import org.apache.activemq.broker.BrokerService;
|
import org.apache.activemq.broker.BrokerService;
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
||||||
|
@ -49,6 +50,7 @@ abstract public class MessagePriorityTest extends CombinationTestSupport {
|
||||||
Session sess;
|
Session sess;
|
||||||
|
|
||||||
public boolean useCache;
|
public boolean useCache;
|
||||||
|
public int prefetchVal = 500;
|
||||||
|
|
||||||
int MSG_NUM = 1000;
|
int MSG_NUM = 1000;
|
||||||
int HIGH_PRI = 7;
|
int HIGH_PRI = 7;
|
||||||
|
@ -59,6 +61,7 @@ abstract public class MessagePriorityTest extends CombinationTestSupport {
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
broker = new BrokerService();
|
broker = new BrokerService();
|
||||||
broker.setBrokerName("priorityTest");
|
broker.setBrokerName("priorityTest");
|
||||||
|
broker.setAdvisorySupport(false);
|
||||||
adapter = createPersistenceAdapter(true);
|
adapter = createPersistenceAdapter(true);
|
||||||
broker.setPersistenceAdapter(adapter);
|
broker.setPersistenceAdapter(adapter);
|
||||||
PolicyEntry policy = new PolicyEntry();
|
PolicyEntry policy = new PolicyEntry();
|
||||||
|
@ -71,6 +74,10 @@ abstract public class MessagePriorityTest extends CombinationTestSupport {
|
||||||
broker.waitUntilStarted();
|
broker.waitUntilStarted();
|
||||||
|
|
||||||
factory = new ActiveMQConnectionFactory("vm://priorityTest");
|
factory = new ActiveMQConnectionFactory("vm://priorityTest");
|
||||||
|
ActiveMQPrefetchPolicy prefetch = new ActiveMQPrefetchPolicy();
|
||||||
|
prefetch.setAll(prefetchVal);
|
||||||
|
factory.setPrefetchPolicy(prefetch);
|
||||||
|
factory.setWatchTopicAdvisories(false);
|
||||||
conn = factory.createConnection();
|
conn = factory.createConnection();
|
||||||
conn.setClientID("priority");
|
conn.setClientID("priority");
|
||||||
conn.start();
|
conn.start();
|
||||||
|
@ -160,6 +167,10 @@ abstract public class MessagePriorityTest extends CombinationTestSupport {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void initCombosForTestDurableSubs() {
|
||||||
|
addCombinationValues("prefetchVal", new Object[] {new Integer(1000), new Integer(MSG_NUM/4)});
|
||||||
|
}
|
||||||
|
|
||||||
public void testDurableSubs() throws Exception {
|
public void testDurableSubs() throws Exception {
|
||||||
ActiveMQTopic topic = (ActiveMQTopic)sess.createTopic("TEST");
|
ActiveMQTopic topic = (ActiveMQTopic)sess.createTopic("TEST");
|
||||||
TopicSubscriber sub = sess.createDurableSubscriber(topic, "priority");
|
TopicSubscriber sub = sess.createDurableSubscriber(topic, "priority");
|
||||||
|
@ -176,11 +187,45 @@ abstract public class MessagePriorityTest extends CombinationTestSupport {
|
||||||
|
|
||||||
sub = sess.createDurableSubscriber(topic, "priority");
|
sub = sess.createDurableSubscriber(topic, "priority");
|
||||||
for (int i = 0; i < MSG_NUM * 2; i++) {
|
for (int i = 0; i < MSG_NUM * 2; i++) {
|
||||||
Message msg = sub.receive(1000);
|
Message msg = sub.receive(5000);
|
||||||
assertNotNull("Message " + i + " was null", msg);
|
assertNotNull("Message " + i + " was null", msg);
|
||||||
assertEquals("Message " + i + " has wrong priority", i < MSG_NUM ? HIGH_PRI : LOW_PRI, msg.getJMSPriority());
|
assertEquals("Message " + i + " has wrong priority", i < MSG_NUM ? HIGH_PRI : LOW_PRI, msg.getJMSPriority());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void initCombosForTestDurableSubsReconnect() {
|
||||||
|
addCombinationValues("prefetchVal", new Object[] {new Integer(1000), new Integer(MSG_NUM/2)});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDurableSubsReconnect() throws Exception {
|
||||||
|
ActiveMQTopic topic = (ActiveMQTopic)sess.createTopic("TEST");
|
||||||
|
final String subName = "priorityDisconnect";
|
||||||
|
TopicSubscriber sub = sess.createDurableSubscriber(topic, subName);
|
||||||
|
sub.close();
|
||||||
|
|
||||||
|
ProducerThread lowPri = new ProducerThread(topic, MSG_NUM, LOW_PRI);
|
||||||
|
ProducerThread highPri = new ProducerThread(topic, MSG_NUM, HIGH_PRI);
|
||||||
|
|
||||||
|
lowPri.start();
|
||||||
|
highPri.start();
|
||||||
|
|
||||||
|
lowPri.join();
|
||||||
|
highPri.join();
|
||||||
|
|
||||||
|
|
||||||
|
final int closeFrequency = MSG_NUM/4;
|
||||||
|
sub = sess.createDurableSubscriber(topic, subName);
|
||||||
|
for (int i = 0; i < MSG_NUM * 2; i++) {
|
||||||
|
Message msg = sub.receive(5000);
|
||||||
|
assertNotNull("Message " + i + " was null", msg);
|
||||||
|
assertEquals("Message " + i + " has wrong priority", i < MSG_NUM ? HIGH_PRI : LOW_PRI, msg.getJMSPriority());
|
||||||
|
if (i>0 && i%closeFrequency==0) {
|
||||||
|
LOG.info("Closing durable sub.. on: " + i);
|
||||||
|
sub.close();
|
||||||
|
sub = sess.createDurableSubscriber(topic, subName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,4 +40,9 @@ public class JDBCMessagePriorityTest extends MessagePriorityTest {
|
||||||
return suite(JDBCMessagePriorityTest.class);
|
return suite(JDBCMessagePriorityTest.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pending fix...
|
||||||
|
@Override
|
||||||
|
public void testDurableSubsReconnect() throws Exception {
|
||||||
|
// TODO: fix jdbc durable sub recovery
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue