mirror of https://github.com/apache/activemq.git
Patch applied for https://issues.apache.org/activemq/browse/AMQ-1795
git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@667105 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4a052d20b1
commit
6f69f1914a
|
@ -1226,7 +1226,11 @@ public class ActiveMQConnection implements Connection, TopicConnection, QueueCon
|
||||||
if (er.getException() instanceof JMSException) {
|
if (er.getException() instanceof JMSException) {
|
||||||
throw (JMSException)er.getException();
|
throw (JMSException)er.getException();
|
||||||
} else {
|
} else {
|
||||||
|
try {
|
||||||
throw JMSExceptionSupport.create(er.getException());
|
throw JMSExceptionSupport.create(er.getException());
|
||||||
|
}catch(Throwable e) {
|
||||||
|
LOG.error("Caught an exception trying to create a JMSException",e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
|
|
|
@ -71,6 +71,7 @@ public class AsyncDataManager {
|
||||||
public static final String DEFAULT_ARCHIVE_DIRECTORY = "data-archive";
|
public static final String DEFAULT_ARCHIVE_DIRECTORY = "data-archive";
|
||||||
public static final String DEFAULT_FILE_PREFIX = "data-";
|
public static final String DEFAULT_FILE_PREFIX = "data-";
|
||||||
public static final int DEFAULT_MAX_FILE_LENGTH = 1024 * 1024 * 32;
|
public static final int DEFAULT_MAX_FILE_LENGTH = 1024 * 1024 * 32;
|
||||||
|
public static final int DEFAULT_CLEANUP_INTERVAL = 1000 * 30;
|
||||||
|
|
||||||
private static final Log LOG = LogFactory.getLog(AsyncDataManager.class);
|
private static final Log LOG = LogFactory.getLog(AsyncDataManager.class);
|
||||||
|
|
||||||
|
@ -188,7 +189,7 @@ public class AsyncDataManager {
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Scheduler.executePeriodically(cleanupTask, 1000 * 30);
|
Scheduler.executePeriodically(cleanupTask, DEFAULT_CLEANUP_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lock() throws IOException {
|
public void lock() throws IOException {
|
||||||
|
@ -272,6 +273,7 @@ public class AsyncDataManager {
|
||||||
if (currentWriteFile != null) {
|
if (currentWriteFile != null) {
|
||||||
currentWriteFile.linkAfter(nextWriteFile);
|
currentWriteFile.linkAfter(nextWriteFile);
|
||||||
if (currentWriteFile.isUnused()) {
|
if (currentWriteFile.isUnused()) {
|
||||||
|
System.err.println("remove current file unused:" + currentWriteFile);
|
||||||
removeDataFile(currentWriteFile);
|
removeDataFile(currentWriteFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,7 +300,7 @@ public class AsyncDataManager {
|
||||||
DataFile dataFile = fileMap.get(key);
|
DataFile dataFile = fileMap.get(key);
|
||||||
if (dataFile == null) {
|
if (dataFile == null) {
|
||||||
LOG.error("Looking for key " + key + " but not found in fileMap: " + fileMap);
|
LOG.error("Looking for key " + key + " but not found in fileMap: " + fileMap);
|
||||||
throw new IOException("Could not locate data file " + filePrefix + "-" + item.getDataFileId());
|
throw new IOException("Could not locate data file " + filePrefix + item.getDataFileId());
|
||||||
}
|
}
|
||||||
return dataFile;
|
return dataFile;
|
||||||
}
|
}
|
||||||
|
@ -308,7 +310,7 @@ public class AsyncDataManager {
|
||||||
DataFile dataFile = fileMap.get(key);
|
DataFile dataFile = fileMap.get(key);
|
||||||
if (dataFile == null) {
|
if (dataFile == null) {
|
||||||
LOG.error("Looking for key " + key + " but not found in fileMap: " + fileMap);
|
LOG.error("Looking for key " + key + " but not found in fileMap: " + fileMap);
|
||||||
throw new IOException("Could not locate data file " + filePrefix + "-" + item.getDataFileId());
|
throw new IOException("Could not locate data file " + filePrefix + item.getDataFileId());
|
||||||
}
|
}
|
||||||
return dataFile.getFile();
|
return dataFile.getFile();
|
||||||
}
|
}
|
||||||
|
@ -411,7 +413,9 @@ public class AsyncDataManager {
|
||||||
purgeList.add(dataFile);
|
purgeList.add(dataFile);
|
||||||
}
|
}
|
||||||
for (DataFile dataFile : purgeList) {
|
for (DataFile dataFile : purgeList) {
|
||||||
forceRemoveDataFile(dataFile);
|
if (dataFile.getDataFileId() != currentWriteFile.getDataFileId()) {
|
||||||
|
forceRemoveDataFile(dataFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,11 +467,11 @@ public class AsyncDataManager {
|
||||||
dataFile.unlink();
|
dataFile.unlink();
|
||||||
if (archiveDataLogs) {
|
if (archiveDataLogs) {
|
||||||
dataFile.move(getDirectoryArchive());
|
dataFile.move(getDirectoryArchive());
|
||||||
LOG.debug("moced data file " + dataFile + " to "
|
LOG.debug("moved data file " + dataFile + " to "
|
||||||
+ getDirectoryArchive());
|
+ getDirectoryArchive());
|
||||||
} else {
|
} else {
|
||||||
boolean result = dataFile.delete();
|
boolean result = dataFile.delete();
|
||||||
LOG.debug("discarding data file " + dataFile
|
LOG.info("discarding data file " + dataFile
|
||||||
+ (result ? "successful " : "failed"));
|
+ (result ? "successful " : "failed"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,7 @@ public class AMQMessageStore implements MessageStore {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
LOG.debug("Journalled message add for: " + id + ", at: " + location);
|
LOG.debug("Journalled message add for: " + id + ", at: " + location);
|
||||||
}
|
}
|
||||||
|
this.peristenceAdapter.addInProgressDataFile(this, location.getDataFileId());
|
||||||
addMessage(message, location);
|
addMessage(message, location);
|
||||||
} else {
|
} else {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
|
@ -164,7 +165,6 @@ public class AMQMessageStore implements MessageStore {
|
||||||
try {
|
try {
|
||||||
lastLocation = location;
|
lastLocation = location;
|
||||||
messages.put(message.getMessageId(), data);
|
messages.put(message.getMessageId(), data);
|
||||||
this.peristenceAdapter.addInProgressDataFile(this, location.getDataFileId());
|
|
||||||
}finally {
|
}finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,13 +90,11 @@ public class AMQPersistenceAdapter implements PersistenceAdapter, UsageListener,
|
||||||
private static final boolean BROKEN_FILE_LOCK;
|
private static final boolean BROKEN_FILE_LOCK;
|
||||||
private static final boolean DISABLE_LOCKING;
|
private static final boolean DISABLE_LOCKING;
|
||||||
private static final int JOURNAL_LOCKED_WAIT_DELAY = 10 * 1000;
|
private static final int JOURNAL_LOCKED_WAIT_DELAY = 10 * 1000;
|
||||||
|
|
||||||
private AsyncDataManager asyncDataManager;
|
private AsyncDataManager asyncDataManager;
|
||||||
private ReferenceStoreAdapter referenceStoreAdapter;
|
private ReferenceStoreAdapter referenceStoreAdapter;
|
||||||
private TaskRunnerFactory taskRunnerFactory;
|
private TaskRunnerFactory taskRunnerFactory;
|
||||||
private WireFormat wireFormat = new OpenWireFormat();
|
private WireFormat wireFormat = new OpenWireFormat();
|
||||||
private SystemUsage usageManager;
|
private SystemUsage usageManager;
|
||||||
private long cleanupInterval = 1000 * 30;
|
|
||||||
private long checkpointInterval = 1000 * 60;
|
private long checkpointInterval = 1000 * 60;
|
||||||
private int maxCheckpointMessageAddSize = 1024 * 4;
|
private int maxCheckpointMessageAddSize = 1024 * 4;
|
||||||
private AMQTransactionStore transactionStore = new AMQTransactionStore(this);
|
private AMQTransactionStore transactionStore = new AMQTransactionStore(this);
|
||||||
|
@ -116,6 +114,7 @@ public class AMQPersistenceAdapter implements PersistenceAdapter, UsageListener,
|
||||||
private boolean persistentIndex=true;
|
private boolean persistentIndex=true;
|
||||||
private boolean useNio = true;
|
private boolean useNio = true;
|
||||||
private boolean archiveDataLogs=false;
|
private boolean archiveDataLogs=false;
|
||||||
|
private long cleanupInterval = AsyncDataManager.DEFAULT_CLEANUP_INTERVAL;
|
||||||
private int maxFileLength = AsyncDataManager.DEFAULT_MAX_FILE_LENGTH;
|
private int maxFileLength = AsyncDataManager.DEFAULT_MAX_FILE_LENGTH;
|
||||||
private int indexBinSize = HashIndex.DEFAULT_BIN_SIZE;
|
private int indexBinSize = HashIndex.DEFAULT_BIN_SIZE;
|
||||||
private int indexKeySize = HashIndex.DEFAULT_KEY_SIZE;
|
private int indexKeySize = HashIndex.DEFAULT_KEY_SIZE;
|
||||||
|
@ -425,8 +424,12 @@ public class AMQPersistenceAdapter implements PersistenceAdapter, UsageListener,
|
||||||
}
|
}
|
||||||
Integer lastDataFile = asyncDataManager.getCurrentDataFileId();
|
Integer lastDataFile = asyncDataManager.getCurrentDataFileId();
|
||||||
inProgress.add(lastDataFile);
|
inProgress.add(lastDataFile);
|
||||||
Set<Integer> inUse = new HashSet<Integer>(referenceStoreAdapter.getReferenceFileIdsInUse());
|
inProgress.addAll(referenceStoreAdapter.getReferenceFileIdsInUse());
|
||||||
asyncDataManager.consolidateDataFilesNotIn(inUse, inProgress);
|
Location lastActiveTx = transactionStore.checkpoint();
|
||||||
|
if (lastActiveTx != null) {
|
||||||
|
lastDataFile = Math.min(lastDataFile, lastActiveTx.getDataFileId());
|
||||||
|
}
|
||||||
|
asyncDataManager.consolidateDataFilesNotIn(inProgress, lastDataFile - 1);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Could not cleanup data files: " + e, e);
|
LOG.error("Could not cleanup data files: " + e, e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ public class AMQPersistenceAdapterFactory implements PersistenceAdapterFactory {
|
||||||
private boolean persistentIndex=true;
|
private boolean persistentIndex=true;
|
||||||
private boolean useNio = true;
|
private boolean useNio = true;
|
||||||
private int maxFileLength = AsyncDataManager.DEFAULT_MAX_FILE_LENGTH;
|
private int maxFileLength = AsyncDataManager.DEFAULT_MAX_FILE_LENGTH;
|
||||||
|
private long cleanupInterval = AsyncDataManager.DEFAULT_CLEANUP_INTERVAL;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,9 +61,18 @@ public class AMQPersistenceAdapterFactory implements PersistenceAdapterFactory {
|
||||||
result.setReferenceStoreAdapter(getReferenceStoreAdapter());
|
result.setReferenceStoreAdapter(getReferenceStoreAdapter());
|
||||||
result.setUseNio(isUseNio());
|
result.setUseNio(isUseNio());
|
||||||
result.setMaxFileLength(getMaxFileLength());
|
result.setMaxFileLength(getMaxFileLength());
|
||||||
|
result.setCleanupInterval(getCleanupInterval());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getCleanupInterval() {
|
||||||
|
return cleanupInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCleanupInterval(long val) {
|
||||||
|
cleanupInterval = val;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the dataDirectory
|
* @return the dataDirectory
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,9 +18,12 @@
|
||||||
package org.apache.activemq.store.amq;
|
package org.apache.activemq.store.amq;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.activemq.command.JournalTopicAck;
|
import org.apache.activemq.command.JournalTopicAck;
|
||||||
import org.apache.activemq.command.JournalTransaction;
|
import org.apache.activemq.command.JournalTransaction;
|
||||||
|
@ -230,13 +233,13 @@ public class AMQTransactionStore implements TransactionStore {
|
||||||
// But we keep track of the first location of an operation
|
// But we keep track of the first location of an operation
|
||||||
// that was associated with an active tx. The journal can not
|
// that was associated with an active tx. The journal can not
|
||||||
// roll over active tx records.
|
// roll over active tx records.
|
||||||
Location rc = null;
|
Location minimumLocationInUse = null;
|
||||||
synchronized (inflightTransactions) {
|
synchronized (inflightTransactions) {
|
||||||
for (Iterator<AMQTx> iter = inflightTransactions.values().iterator(); iter.hasNext();) {
|
for (Iterator<AMQTx> iter = inflightTransactions.values().iterator(); iter.hasNext();) {
|
||||||
AMQTx tx = iter.next();
|
AMQTx tx = iter.next();
|
||||||
Location location = tx.getLocation();
|
Location location = tx.getLocation();
|
||||||
if (rc == null || rc.compareTo(location) < 0) {
|
if (minimumLocationInUse == null || location.compareTo(minimumLocationInUse) < 0) {
|
||||||
rc = location;
|
minimumLocationInUse = location;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,11 +247,11 @@ public class AMQTransactionStore implements TransactionStore {
|
||||||
for (Iterator<AMQTx> iter = preparedTransactions.values().iterator(); iter.hasNext();) {
|
for (Iterator<AMQTx> iter = preparedTransactions.values().iterator(); iter.hasNext();) {
|
||||||
AMQTx tx = iter.next();
|
AMQTx tx = iter.next();
|
||||||
Location location = tx.getLocation();
|
Location location = tx.getLocation();
|
||||||
if (rc == null || rc.compareTo(location) < 0) {
|
if (minimumLocationInUse == null || location.compareTo(minimumLocationInUse) < 0) {
|
||||||
rc = location;
|
minimumLocationInUse = location;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
return minimumLocationInUse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -234,8 +234,8 @@ public class KahaReferenceStoreAdapter extends KahaPersistenceAdapter implements
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @see org.apache.activemq.store.ReferenceStoreAdapter#getReferenceFileIdsInUse()
|
* @see org.apache.activemq.store.ReferenceStoreAdapter#getReferenceFileIdsInUse()
|
||||||
*/
|
*/
|
||||||
public Set<Integer> getReferenceFileIdsInUse() throws IOException {
|
public synchronized Set<Integer> getReferenceFileIdsInUse() throws IOException {
|
||||||
return recordReferences.keySet();
|
return new HashSet<Integer>(recordReferences.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,41 +1,41 @@
|
||||||
/**
|
/**
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
* this work for additional information regarding copyright ownership.
|
* this work for additional information regarding copyright ownership.
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
* 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 not use this file except in compliance with
|
||||||
* the License. You may obtain a copy of the License at
|
* the License. You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.activemq.bugs;
|
package org.apache.activemq.bugs;
|
||||||
|
|
||||||
import javax.jms.Connection;
|
import javax.jms.Connection;
|
||||||
import javax.jms.MessageProducer;
|
import javax.jms.MessageProducer;
|
||||||
import javax.jms.ObjectMessage;
|
import javax.jms.ObjectMessage;
|
||||||
import javax.jms.Session;
|
import javax.jms.Session;
|
||||||
|
|
||||||
public class MessageSender {
|
public class MessageSender {
|
||||||
private MessageProducer producer;
|
private MessageProducer producer;
|
||||||
private Session session;
|
private Session session;
|
||||||
|
|
||||||
public MessageSender(String queueName, Connection connection, boolean useTransactedSession) throws Exception {
|
public MessageSender(String queueName, Connection connection, boolean useTransactedSession, boolean topic) throws Exception {
|
||||||
session = useTransactedSession ? connection.createSession(true, Session.SESSION_TRANSACTED) : connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
session = useTransactedSession ? connection.createSession(true, Session.SESSION_TRANSACTED) : connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
producer = session.createProducer(session.createQueue(queueName));
|
producer = session.createProducer(topic ? session.createTopic(queueName) : session.createQueue(queueName));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void send(String payload) throws Exception {
|
public void send(String payload) throws Exception {
|
||||||
ObjectMessage message = session.createObjectMessage();
|
ObjectMessage message = session.createObjectMessage();
|
||||||
message.setObject(payload);
|
message.setObject(payload);
|
||||||
producer.send(message);
|
producer.send(message);
|
||||||
if (session.getTransacted()) {
|
if (session.getTransacted()) {
|
||||||
session.commit();
|
session.commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,312 @@
|
||||||
|
/**
|
||||||
|
* 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.bugs;
|
||||||
|
|
||||||
|
import javax.jms.Connection;
|
||||||
|
import javax.jms.JMSException;
|
||||||
|
import javax.jms.Message;
|
||||||
|
import javax.jms.MessageConsumer;
|
||||||
|
import javax.jms.MessageListener;
|
||||||
|
import javax.jms.ObjectMessage;
|
||||||
|
import javax.jms.Session;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||||
|
import org.apache.activemq.broker.BrokerService;
|
||||||
|
import org.apache.activemq.store.amq.AMQPersistenceAdapterFactory;
|
||||||
|
import org.apache.activemq.usage.SystemUsage;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try and replicate:
|
||||||
|
* Caused by: java.io.IOException: Could not locate data file data--188
|
||||||
|
* at org.apache.activemq.kaha.impl.async.AsyncDataManager.getDataFile(AsyncDataManager.java:302)
|
||||||
|
* at org.apache.activemq.kaha.impl.async.AsyncDataManager.read(AsyncDataManager.java:614)
|
||||||
|
* at org.apache.activemq.store.amq.AMQPersistenceAdapter.readCommand(AMQPersistenceAdapter.java:523)
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MissingDataFileTest extends TestCase {
|
||||||
|
|
||||||
|
private static final Log LOG = LogFactory.getLog(MissingDataFileTest.class);
|
||||||
|
|
||||||
|
private static int counter = 300;
|
||||||
|
|
||||||
|
private static int hectorToHaloCtr;
|
||||||
|
private static int xenaToHaloCtr;
|
||||||
|
private static int troyToHaloCtr;
|
||||||
|
|
||||||
|
private static int haloToHectorCtr;
|
||||||
|
private static int haloToXenaCtr;
|
||||||
|
private static int haloToTroyCtr;
|
||||||
|
|
||||||
|
private String hectorToHalo = "hectorToHalo";
|
||||||
|
private String xenaToHalo = "xenaToHalo";
|
||||||
|
private String troyToHalo = "troyToHalo";
|
||||||
|
|
||||||
|
private String haloToHector = "haloToHector";
|
||||||
|
private String haloToXena = "haloToXena";
|
||||||
|
private String haloToTroy = "haloToTroy";
|
||||||
|
|
||||||
|
|
||||||
|
private BrokerService broker;
|
||||||
|
|
||||||
|
private Connection hectorConnection;
|
||||||
|
private Connection xenaConnection;
|
||||||
|
private Connection troyConnection;
|
||||||
|
private Connection haloConnection;
|
||||||
|
|
||||||
|
private final Object lock = new Object();
|
||||||
|
final boolean useTopic = false;
|
||||||
|
final boolean useSleep = true;
|
||||||
|
|
||||||
|
protected static final String payload = new String(new byte[500]);
|
||||||
|
|
||||||
|
public Connection createConnection() throws JMSException {
|
||||||
|
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
|
||||||
|
return factory.createConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session createSession(Connection connection, boolean transacted) throws JMSException {
|
||||||
|
return connection.createSession(transacted, Session.AUTO_ACKNOWLEDGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startBroker() throws Exception {
|
||||||
|
broker = new BrokerService();
|
||||||
|
broker.setDeleteAllMessagesOnStartup(true);
|
||||||
|
broker.setPersistent(true);
|
||||||
|
broker.setUseJmx(true);
|
||||||
|
broker.addConnector("tcp://localhost:61616").setName("Default");
|
||||||
|
|
||||||
|
SystemUsage systemUsage;
|
||||||
|
systemUsage = new SystemUsage();
|
||||||
|
systemUsage.getMemoryUsage().setLimit(1024 * 10); // Just a few messags
|
||||||
|
broker.setSystemUsage(systemUsage);
|
||||||
|
|
||||||
|
AMQPersistenceAdapterFactory factory = (AMQPersistenceAdapterFactory) broker.getPersistenceFactory();
|
||||||
|
factory.setMaxFileLength(2*1024); // ~4 messages
|
||||||
|
factory.setCleanupInterval(5000); // every few second
|
||||||
|
|
||||||
|
broker.start();
|
||||||
|
LOG.info("Starting broker..");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
hectorConnection.close();
|
||||||
|
xenaConnection.close();
|
||||||
|
troyConnection.close();
|
||||||
|
haloConnection.close();
|
||||||
|
broker.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testForNoDataFoundError() throws Exception {
|
||||||
|
|
||||||
|
startBroker();
|
||||||
|
hectorConnection = createConnection();
|
||||||
|
Thread hectorThread = buildProducer(hectorConnection, hectorToHalo, false, useTopic);
|
||||||
|
Receiver hHectorReceiver = new Receiver() {
|
||||||
|
public void receive(String s) throws Exception {
|
||||||
|
haloToHectorCtr++;
|
||||||
|
if (haloToHectorCtr >= counter) {
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
possiblySleep(haloToHectorCtr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
buildReceiver(hectorConnection, haloToHector, false, hHectorReceiver, useTopic);
|
||||||
|
|
||||||
|
troyConnection = createConnection();
|
||||||
|
Thread troyThread = buildProducer(troyConnection, troyToHalo);
|
||||||
|
Receiver hTroyReceiver = new Receiver() {
|
||||||
|
public void receive(String s) throws Exception {
|
||||||
|
haloToTroyCtr++;
|
||||||
|
if (haloToTroyCtr >= counter) {
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
possiblySleep(haloToTroyCtr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
buildReceiver(hectorConnection, haloToTroy, false, hTroyReceiver, false);
|
||||||
|
|
||||||
|
xenaConnection = createConnection();
|
||||||
|
Thread xenaThread = buildProducer(xenaConnection, xenaToHalo);
|
||||||
|
Receiver hXenaReceiver = new Receiver() {
|
||||||
|
public void receive(String s) throws Exception {
|
||||||
|
haloToXenaCtr++;
|
||||||
|
if (haloToXenaCtr >= counter) {
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
possiblySleep(haloToXenaCtr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
buildReceiver(xenaConnection, haloToXena, false, hXenaReceiver, false);
|
||||||
|
|
||||||
|
haloConnection = createConnection();
|
||||||
|
final MessageSender hectorSender = buildTransactionalProducer(haloToHector, haloConnection, false);
|
||||||
|
final MessageSender troySender = buildTransactionalProducer(haloToTroy, haloConnection, false);
|
||||||
|
final MessageSender xenaSender = buildTransactionalProducer(haloToXena, haloConnection, false);
|
||||||
|
Receiver hectorReceiver = new Receiver() {
|
||||||
|
public void receive(String s) throws Exception {
|
||||||
|
hectorToHaloCtr++;
|
||||||
|
troySender.send(payload);
|
||||||
|
if (hectorToHaloCtr >= counter) {
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
|
possiblySleep(hectorToHaloCtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Receiver xenaReceiver = new Receiver() {
|
||||||
|
public void receive(String s) throws Exception {
|
||||||
|
xenaToHaloCtr++;
|
||||||
|
hectorSender.send(payload);
|
||||||
|
if (xenaToHaloCtr >= counter) {
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
possiblySleep(xenaToHaloCtr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Receiver troyReceiver = new Receiver() {
|
||||||
|
public void receive(String s) throws Exception {
|
||||||
|
troyToHaloCtr++;
|
||||||
|
xenaSender.send(payload);
|
||||||
|
if (troyToHaloCtr >= counter) {
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
buildReceiver(haloConnection, hectorToHalo, true, hectorReceiver, false);
|
||||||
|
buildReceiver(haloConnection, xenaToHalo, true, xenaReceiver, false);
|
||||||
|
buildReceiver(haloConnection, troyToHalo, true, troyReceiver, false);
|
||||||
|
|
||||||
|
haloConnection.start();
|
||||||
|
|
||||||
|
troyConnection.start();
|
||||||
|
troyThread.start();
|
||||||
|
|
||||||
|
xenaConnection.start();
|
||||||
|
xenaThread.start();
|
||||||
|
|
||||||
|
hectorConnection.start();
|
||||||
|
hectorThread.start();
|
||||||
|
waitForMessagesToBeDelivered();
|
||||||
|
// number of messages received should match messages sent
|
||||||
|
assertEquals(hectorToHaloCtr, counter);
|
||||||
|
LOG.info("hectorToHalo received " + hectorToHaloCtr + " messages");
|
||||||
|
assertEquals(xenaToHaloCtr, counter);
|
||||||
|
LOG.info("xenaToHalo received " + xenaToHaloCtr + " messages");
|
||||||
|
assertEquals(troyToHaloCtr, counter);
|
||||||
|
LOG.info("troyToHalo received " + troyToHaloCtr + " messages");
|
||||||
|
assertEquals(haloToHectorCtr, counter);
|
||||||
|
LOG.info("haloToHector received " + haloToHectorCtr + " messages");
|
||||||
|
assertEquals(haloToXenaCtr, counter);
|
||||||
|
LOG.info("haloToXena received " + haloToXenaCtr + " messages");
|
||||||
|
assertEquals(haloToTroyCtr, counter);
|
||||||
|
LOG.info("haloToTroy received " + haloToTroyCtr + " messages");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void possiblySleep(int count) throws InterruptedException {
|
||||||
|
if (useSleep) {
|
||||||
|
if (count % 100 == 0) {
|
||||||
|
Thread.sleep(5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void waitForMessagesToBeDelivered() {
|
||||||
|
// let's give the listeners enough time to read all messages
|
||||||
|
long maxWaitTime = counter * 1000;
|
||||||
|
long waitTime = maxWaitTime;
|
||||||
|
long start = (maxWaitTime <= 0) ? 0 : System.currentTimeMillis();
|
||||||
|
|
||||||
|
synchronized (lock) {
|
||||||
|
boolean hasMessages = true;
|
||||||
|
while (hasMessages && waitTime >= 0) {
|
||||||
|
try {
|
||||||
|
lock.wait(200);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOG.error(e);
|
||||||
|
}
|
||||||
|
// check if all messages have been received
|
||||||
|
hasMessages = hectorToHaloCtr < counter || xenaToHaloCtr < counter || troyToHaloCtr < counter || haloToHectorCtr < counter || haloToXenaCtr < counter
|
||||||
|
|| haloToTroyCtr < counter;
|
||||||
|
waitTime = maxWaitTime - (System.currentTimeMillis() - start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageSender buildTransactionalProducer(String queueName, Connection connection, boolean isTopic) throws Exception {
|
||||||
|
|
||||||
|
return new MessageSender(queueName, connection, true, isTopic);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thread buildProducer(Connection connection, final String queueName) throws Exception {
|
||||||
|
return buildProducer(connection, queueName, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thread buildProducer(Connection connection, final String queueName, boolean transacted, boolean isTopic) throws Exception {
|
||||||
|
final MessageSender producer = new MessageSender(queueName, connection, transacted, isTopic);
|
||||||
|
Thread thread = new Thread() {
|
||||||
|
public synchronized void run() {
|
||||||
|
for (int i = 0; i < counter; i++) {
|
||||||
|
try {
|
||||||
|
producer.send(payload );
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("on " + queueName + " send", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildReceiver(Connection connection, final String queueName, boolean transacted, final Receiver receiver, boolean isTopic) throws Exception {
|
||||||
|
final Session session = transacted ? connection.createSession(true, Session.SESSION_TRANSACTED) : connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
|
MessageConsumer inputMessageConsumer = session.createConsumer(isTopic ? session.createTopic(queueName) : session.createQueue(queueName));
|
||||||
|
MessageListener messageListener = new MessageListener() {
|
||||||
|
|
||||||
|
public void onMessage(Message message) {
|
||||||
|
try {
|
||||||
|
ObjectMessage objectMessage = (ObjectMessage)message;
|
||||||
|
String s = (String)objectMessage.getObject();
|
||||||
|
receiver.receive(s);
|
||||||
|
if (session.getTransacted()) {
|
||||||
|
session.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
inputMessageConsumer.setMessageListener(messageListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,286 +1,286 @@
|
||||||
/**
|
/**
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
* this work for additional information regarding copyright ownership.
|
* this work for additional information regarding copyright ownership.
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
* 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 not use this file except in compliance with
|
||||||
* the License. You may obtain a copy of the License at
|
* the License. You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.activemq.bugs;
|
package org.apache.activemq.bugs;
|
||||||
|
|
||||||
import javax.jms.Connection;
|
import javax.jms.Connection;
|
||||||
import javax.jms.JMSException;
|
import javax.jms.JMSException;
|
||||||
import javax.jms.Message;
|
import javax.jms.Message;
|
||||||
import javax.jms.MessageConsumer;
|
import javax.jms.MessageConsumer;
|
||||||
import javax.jms.MessageListener;
|
import javax.jms.MessageListener;
|
||||||
import javax.jms.ObjectMessage;
|
import javax.jms.ObjectMessage;
|
||||||
import javax.jms.Session;
|
import javax.jms.Session;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||||
import org.apache.activemq.broker.BrokerService;
|
import org.apache.activemq.broker.BrokerService;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* simulate message flow which cause the following exception in the broker
|
* simulate message flow which cause the following exception in the broker
|
||||||
* (exception logged by client) <p/> 2007-07-24 13:51:23,624
|
* (exception logged by client) <p/> 2007-07-24 13:51:23,624
|
||||||
* com.easynet.halo.Halo ERROR (LoggingErrorHandler.java: 23) JMS failure
|
* com.easynet.halo.Halo ERROR (LoggingErrorHandler.java: 23) JMS failure
|
||||||
* javax.jms.JMSException: Transaction 'TX:ID:dmt-53625-1185281414694-1:0:344'
|
* javax.jms.JMSException: Transaction 'TX:ID:dmt-53625-1185281414694-1:0:344'
|
||||||
* has not been started. at
|
* has not been started. at
|
||||||
* org.apache.activemq.broker.TransactionBroker.getTransaction(TransactionBroker.java:230)
|
* org.apache.activemq.broker.TransactionBroker.getTransaction(TransactionBroker.java:230)
|
||||||
* This appears to be consistent in a MacBook. Haven't been able to replicate it
|
* This appears to be consistent in a MacBook. Haven't been able to replicate it
|
||||||
* on Windows though
|
* on Windows though
|
||||||
*/
|
*/
|
||||||
public class TransactionNotStartedErrorTest extends TestCase {
|
public class TransactionNotStartedErrorTest extends TestCase {
|
||||||
|
|
||||||
private static final Log LOG = LogFactory.getLog(TransactionNotStartedErrorTest.class);
|
private static final Log LOG = LogFactory.getLog(TransactionNotStartedErrorTest.class);
|
||||||
|
|
||||||
private static int counter = 500;
|
private static int counter = 500;
|
||||||
|
|
||||||
private static int hectorToHaloCtr;
|
private static int hectorToHaloCtr;
|
||||||
private static int xenaToHaloCtr;
|
private static int xenaToHaloCtr;
|
||||||
private static int troyToHaloCtr;
|
private static int troyToHaloCtr;
|
||||||
|
|
||||||
private static int haloToHectorCtr;
|
private static int haloToHectorCtr;
|
||||||
private static int haloToXenaCtr;
|
private static int haloToXenaCtr;
|
||||||
private static int haloToTroyCtr;
|
private static int haloToTroyCtr;
|
||||||
|
|
||||||
private String hectorToHalo = "hectorToHalo";
|
private String hectorToHalo = "hectorToHalo";
|
||||||
private String xenaToHalo = "xenaToHalo";
|
private String xenaToHalo = "xenaToHalo";
|
||||||
private String troyToHalo = "troyToHalo";
|
private String troyToHalo = "troyToHalo";
|
||||||
|
|
||||||
private String haloToHector = "haloToHector";
|
private String haloToHector = "haloToHector";
|
||||||
private String haloToXena = "haloToXena";
|
private String haloToXena = "haloToXena";
|
||||||
private String haloToTroy = "haloToTroy";
|
private String haloToTroy = "haloToTroy";
|
||||||
|
|
||||||
|
|
||||||
private BrokerService broker;
|
private BrokerService broker;
|
||||||
|
|
||||||
private Connection hectorConnection;
|
private Connection hectorConnection;
|
||||||
private Connection xenaConnection;
|
private Connection xenaConnection;
|
||||||
private Connection troyConnection;
|
private Connection troyConnection;
|
||||||
private Connection haloConnection;
|
private Connection haloConnection;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
|
|
||||||
public Connection createConnection() throws JMSException {
|
public Connection createConnection() throws JMSException {
|
||||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
|
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
|
||||||
return factory.createConnection();
|
return factory.createConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Session createSession(Connection connection, boolean transacted) throws JMSException {
|
public Session createSession(Connection connection, boolean transacted) throws JMSException {
|
||||||
return connection.createSession(transacted, Session.AUTO_ACKNOWLEDGE);
|
return connection.createSession(transacted, Session.AUTO_ACKNOWLEDGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startBroker() throws Exception {
|
public void startBroker() throws Exception {
|
||||||
broker = new BrokerService();
|
broker = new BrokerService();
|
||||||
broker.setDeleteAllMessagesOnStartup(true);
|
broker.setDeleteAllMessagesOnStartup(true);
|
||||||
broker.setPersistent(true);
|
broker.setPersistent(true);
|
||||||
broker.setUseJmx(true);
|
broker.setUseJmx(true);
|
||||||
broker.addConnector("tcp://localhost:61616").setName("Default");
|
broker.addConnector("tcp://localhost:61616").setName("Default");
|
||||||
broker.start();
|
broker.start();
|
||||||
LOG.info("Starting broker..");
|
LOG.info("Starting broker..");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
hectorConnection.close();
|
hectorConnection.close();
|
||||||
xenaConnection.close();
|
xenaConnection.close();
|
||||||
troyConnection.close();
|
troyConnection.close();
|
||||||
haloConnection.close();
|
haloConnection.close();
|
||||||
broker.stop();
|
broker.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTransactionNotStartedError() throws Exception {
|
public void testTransactionNotStartedError() throws Exception {
|
||||||
startBroker();
|
startBroker();
|
||||||
hectorConnection = createConnection();
|
hectorConnection = createConnection();
|
||||||
Thread hectorThread = buildProducer(hectorConnection, hectorToHalo);
|
Thread hectorThread = buildProducer(hectorConnection, hectorToHalo);
|
||||||
Receiver hHectorReceiver = new Receiver() {
|
Receiver hHectorReceiver = new Receiver() {
|
||||||
public void receive(String s) throws Exception {
|
public void receive(String s) throws Exception {
|
||||||
haloToHectorCtr++;
|
haloToHectorCtr++;
|
||||||
if (haloToHectorCtr >= counter) {
|
if (haloToHectorCtr >= counter) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.notifyAll();
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
buildReceiver(hectorConnection, haloToHector, false, hHectorReceiver);
|
buildReceiver(hectorConnection, haloToHector, false, hHectorReceiver);
|
||||||
|
|
||||||
troyConnection = createConnection();
|
troyConnection = createConnection();
|
||||||
Thread troyThread = buildProducer(troyConnection, troyToHalo);
|
Thread troyThread = buildProducer(troyConnection, troyToHalo);
|
||||||
Receiver hTroyReceiver = new Receiver() {
|
Receiver hTroyReceiver = new Receiver() {
|
||||||
public void receive(String s) throws Exception {
|
public void receive(String s) throws Exception {
|
||||||
haloToTroyCtr++;
|
haloToTroyCtr++;
|
||||||
if (haloToTroyCtr >= counter) {
|
if (haloToTroyCtr >= counter) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.notifyAll();
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
buildReceiver(hectorConnection, haloToTroy, false, hTroyReceiver);
|
buildReceiver(hectorConnection, haloToTroy, false, hTroyReceiver);
|
||||||
|
|
||||||
xenaConnection = createConnection();
|
xenaConnection = createConnection();
|
||||||
Thread xenaThread = buildProducer(xenaConnection, xenaToHalo);
|
Thread xenaThread = buildProducer(xenaConnection, xenaToHalo);
|
||||||
Receiver hXenaReceiver = new Receiver() {
|
Receiver hXenaReceiver = new Receiver() {
|
||||||
public void receive(String s) throws Exception {
|
public void receive(String s) throws Exception {
|
||||||
haloToXenaCtr++;
|
haloToXenaCtr++;
|
||||||
if (haloToXenaCtr >= counter) {
|
if (haloToXenaCtr >= counter) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.notifyAll();
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
buildReceiver(xenaConnection, haloToXena, false, hXenaReceiver);
|
buildReceiver(xenaConnection, haloToXena, false, hXenaReceiver);
|
||||||
|
|
||||||
haloConnection = createConnection();
|
haloConnection = createConnection();
|
||||||
final MessageSender hectorSender = buildTransactionalProducer(haloToHector, haloConnection);
|
final MessageSender hectorSender = buildTransactionalProducer(haloToHector, haloConnection);
|
||||||
final MessageSender troySender = buildTransactionalProducer(haloToTroy, haloConnection);
|
final MessageSender troySender = buildTransactionalProducer(haloToTroy, haloConnection);
|
||||||
final MessageSender xenaSender = buildTransactionalProducer(haloToXena, haloConnection);
|
final MessageSender xenaSender = buildTransactionalProducer(haloToXena, haloConnection);
|
||||||
Receiver hectorReceiver = new Receiver() {
|
Receiver hectorReceiver = new Receiver() {
|
||||||
public void receive(String s) throws Exception {
|
public void receive(String s) throws Exception {
|
||||||
hectorToHaloCtr++;
|
hectorToHaloCtr++;
|
||||||
troySender.send("halo to troy because of hector");
|
troySender.send("halo to troy because of hector");
|
||||||
if (hectorToHaloCtr >= counter) {
|
if (hectorToHaloCtr >= counter) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.notifyAll();
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Receiver xenaReceiver = new Receiver() {
|
Receiver xenaReceiver = new Receiver() {
|
||||||
public void receive(String s) throws Exception {
|
public void receive(String s) throws Exception {
|
||||||
xenaToHaloCtr++;
|
xenaToHaloCtr++;
|
||||||
hectorSender.send("halo to hector because of xena");
|
hectorSender.send("halo to hector because of xena");
|
||||||
if (xenaToHaloCtr >= counter) {
|
if (xenaToHaloCtr >= counter) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.notifyAll();
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Receiver troyReceiver = new Receiver() {
|
Receiver troyReceiver = new Receiver() {
|
||||||
public void receive(String s) throws Exception {
|
public void receive(String s) throws Exception {
|
||||||
troyToHaloCtr++;
|
troyToHaloCtr++;
|
||||||
xenaSender.send("halo to xena because of troy");
|
xenaSender.send("halo to xena because of troy");
|
||||||
if (troyToHaloCtr >= counter) {
|
if (troyToHaloCtr >= counter) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.notifyAll();
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
buildReceiver(haloConnection, hectorToHalo, true, hectorReceiver);
|
buildReceiver(haloConnection, hectorToHalo, true, hectorReceiver);
|
||||||
buildReceiver(haloConnection, xenaToHalo, true, xenaReceiver);
|
buildReceiver(haloConnection, xenaToHalo, true, xenaReceiver);
|
||||||
buildReceiver(haloConnection, troyToHalo, true, troyReceiver);
|
buildReceiver(haloConnection, troyToHalo, true, troyReceiver);
|
||||||
|
|
||||||
haloConnection.start();
|
haloConnection.start();
|
||||||
|
|
||||||
troyConnection.start();
|
troyConnection.start();
|
||||||
troyThread.start();
|
troyThread.start();
|
||||||
|
|
||||||
xenaConnection.start();
|
xenaConnection.start();
|
||||||
xenaThread.start();
|
xenaThread.start();
|
||||||
|
|
||||||
hectorConnection.start();
|
hectorConnection.start();
|
||||||
hectorThread.start();
|
hectorThread.start();
|
||||||
waitForMessagesToBeDelivered();
|
waitForMessagesToBeDelivered();
|
||||||
// number of messages received should match messages sent
|
// number of messages received should match messages sent
|
||||||
assertEquals(hectorToHaloCtr, counter);
|
assertEquals(hectorToHaloCtr, counter);
|
||||||
LOG.info("hectorToHalo received " + hectorToHaloCtr + " messages");
|
LOG.info("hectorToHalo received " + hectorToHaloCtr + " messages");
|
||||||
assertEquals(xenaToHaloCtr, counter);
|
assertEquals(xenaToHaloCtr, counter);
|
||||||
LOG.info("xenaToHalo received " + xenaToHaloCtr + " messages");
|
LOG.info("xenaToHalo received " + xenaToHaloCtr + " messages");
|
||||||
assertEquals(troyToHaloCtr, counter);
|
assertEquals(troyToHaloCtr, counter);
|
||||||
LOG.info("troyToHalo received " + troyToHaloCtr + " messages");
|
LOG.info("troyToHalo received " + troyToHaloCtr + " messages");
|
||||||
assertEquals(haloToHectorCtr, counter);
|
assertEquals(haloToHectorCtr, counter);
|
||||||
LOG.info("haloToHector received " + haloToHectorCtr + " messages");
|
LOG.info("haloToHector received " + haloToHectorCtr + " messages");
|
||||||
assertEquals(haloToXenaCtr, counter);
|
assertEquals(haloToXenaCtr, counter);
|
||||||
LOG.info("haloToXena received " + haloToXenaCtr + " messages");
|
LOG.info("haloToXena received " + haloToXenaCtr + " messages");
|
||||||
assertEquals(haloToTroyCtr, counter);
|
assertEquals(haloToTroyCtr, counter);
|
||||||
LOG.info("haloToTroy received " + haloToTroyCtr + " messages");
|
LOG.info("haloToTroy received " + haloToTroyCtr + " messages");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void waitForMessagesToBeDelivered() {
|
protected void waitForMessagesToBeDelivered() {
|
||||||
// let's give the listeners enough time to read all messages
|
// let's give the listeners enough time to read all messages
|
||||||
long maxWaitTime = counter * 3000;
|
long maxWaitTime = counter * 3000;
|
||||||
long waitTime = maxWaitTime;
|
long waitTime = maxWaitTime;
|
||||||
long start = (maxWaitTime <= 0) ? 0 : System.currentTimeMillis();
|
long start = (maxWaitTime <= 0) ? 0 : System.currentTimeMillis();
|
||||||
|
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
boolean hasMessages = true;
|
boolean hasMessages = true;
|
||||||
while (hasMessages && waitTime >= 0) {
|
while (hasMessages && waitTime >= 0) {
|
||||||
try {
|
try {
|
||||||
lock.wait(200);
|
lock.wait(200);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.error(e);
|
LOG.error(e);
|
||||||
}
|
}
|
||||||
// check if all messages have been received
|
// check if all messages have been received
|
||||||
hasMessages = hectorToHaloCtr < counter || xenaToHaloCtr < counter || troyToHaloCtr < counter || haloToHectorCtr < counter || haloToXenaCtr < counter
|
hasMessages = hectorToHaloCtr < counter || xenaToHaloCtr < counter || troyToHaloCtr < counter || haloToHectorCtr < counter || haloToXenaCtr < counter
|
||||||
|| haloToTroyCtr < counter;
|
|| haloToTroyCtr < counter;
|
||||||
waitTime = maxWaitTime - (System.currentTimeMillis() - start);
|
waitTime = maxWaitTime - (System.currentTimeMillis() - start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageSender buildTransactionalProducer(String queueName, Connection connection) throws Exception {
|
public MessageSender buildTransactionalProducer(String queueName, Connection connection) throws Exception {
|
||||||
|
|
||||||
return new MessageSender(queueName, connection, true);
|
return new MessageSender(queueName, connection, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Thread buildProducer(Connection connection, final String queueName) throws Exception {
|
public Thread buildProducer(Connection connection, final String queueName) throws Exception {
|
||||||
|
|
||||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
final MessageSender producer = new MessageSender(queueName, connection, false);
|
final MessageSender producer = new MessageSender(queueName, connection, false, false);
|
||||||
Thread thread = new Thread() {
|
Thread thread = new Thread() {
|
||||||
|
|
||||||
public synchronized void run() {
|
public synchronized void run() {
|
||||||
for (int i = 0; i < counter; i++) {
|
for (int i = 0; i < counter; i++) {
|
||||||
try {
|
try {
|
||||||
producer.send(queueName);
|
producer.send(queueName);
|
||||||
if (session.getTransacted()) {
|
if (session.getTransacted()) {
|
||||||
session.commit();
|
session.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("on " + queueName + " send", e);
|
throw new RuntimeException("on " + queueName + " send", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buildReceiver(Connection connection, final String queueName, boolean transacted, final Receiver receiver) throws Exception {
|
public void buildReceiver(Connection connection, final String queueName, boolean transacted, final Receiver receiver) throws Exception {
|
||||||
final Session session = transacted ? connection.createSession(true, Session.SESSION_TRANSACTED) : connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
final Session session = transacted ? connection.createSession(true, Session.SESSION_TRANSACTED) : connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
MessageConsumer inputMessageConsumer = session.createConsumer(session.createQueue(queueName));
|
MessageConsumer inputMessageConsumer = session.createConsumer(session.createQueue(queueName));
|
||||||
MessageListener messageListener = new MessageListener() {
|
MessageListener messageListener = new MessageListener() {
|
||||||
|
|
||||||
public void onMessage(Message message) {
|
public void onMessage(Message message) {
|
||||||
try {
|
try {
|
||||||
ObjectMessage objectMessage = (ObjectMessage)message;
|
ObjectMessage objectMessage = (ObjectMessage)message;
|
||||||
String s = (String)objectMessage.getObject();
|
String s = (String)objectMessage.getObject();
|
||||||
receiver.receive(s);
|
receiver.receive(s);
|
||||||
if (session.getTransacted()) {
|
if (session.getTransacted()) {
|
||||||
session.commit();
|
session.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
inputMessageConsumer.setMessageListener(messageListener);
|
inputMessageConsumer.setMessageListener(messageListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@ public class AMQStoreDurableTopicTest extends SimpleDurableTopicTest {
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
numberofProducers=1;
|
numberofProducers=1;
|
||||||
numberOfConsumers=1;
|
numberOfConsumers=1;
|
||||||
this.consumerSleepDuration=0;
|
|
||||||
super.setUp();
|
super.setUp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,9 @@ import javax.jms.ConnectionFactory;
|
||||||
import javax.jms.DeliveryMode;
|
import javax.jms.DeliveryMode;
|
||||||
import javax.jms.Destination;
|
import javax.jms.Destination;
|
||||||
import javax.jms.JMSException;
|
import javax.jms.JMSException;
|
||||||
|
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||||
|
import org.apache.activemq.broker.BrokerService;
|
||||||
|
import org.apache.activemq.store.amq.AMQPersistenceAdapterFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @version $Revision: 1.3 $
|
* @version $Revision: 1.3 $
|
||||||
|
@ -28,12 +31,22 @@ public class SimpleDurableTopicTest extends SimpleTopicTest {
|
||||||
|
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
numberOfDestinations=1;
|
numberOfDestinations=1;
|
||||||
numberOfConsumers = 1;
|
numberOfConsumers = 4;
|
||||||
numberofProducers = 1;
|
numberofProducers = 1;
|
||||||
sampleCount=1000;
|
sampleCount=1000;
|
||||||
playloadSize = 1024;
|
playloadSize = 1024;
|
||||||
super.setUp();
|
super.setUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void configureBroker(BrokerService answer,String uri) throws Exception {
|
||||||
|
AMQPersistenceAdapterFactory persistenceFactory = new AMQPersistenceAdapterFactory();
|
||||||
|
persistenceFactory.setMaxFileLength(1024*16);
|
||||||
|
answer.setPersistenceFactory(persistenceFactory);
|
||||||
|
answer.setDeleteAllMessagesOnStartup(true);
|
||||||
|
answer.addConnector(uri);
|
||||||
|
answer.setUseShutdownHook(false);
|
||||||
|
}
|
||||||
|
|
||||||
protected PerfProducer createProducer(ConnectionFactory fac, Destination dest, int number, byte payload[]) throws JMSException {
|
protected PerfProducer createProducer(ConnectionFactory fac, Destination dest, int number, byte payload[]) throws JMSException {
|
||||||
PerfProducer pp = new PerfProducer(fac, dest, payload);
|
PerfProducer pp = new PerfProducer(fac, dest, payload);
|
||||||
pp.setDeliveryMode(DeliveryMode.PERSISTENT);
|
pp.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||||
|
@ -42,7 +55,13 @@ public class SimpleDurableTopicTest extends SimpleTopicTest {
|
||||||
|
|
||||||
protected PerfConsumer createConsumer(ConnectionFactory fac, Destination dest, int number) throws JMSException {
|
protected PerfConsumer createConsumer(ConnectionFactory fac, Destination dest, int number) throws JMSException {
|
||||||
PerfConsumer result = new PerfConsumer(fac, dest, "subs:" + number);
|
PerfConsumer result = new PerfConsumer(fac, dest, "subs:" + number);
|
||||||
result.setInitialDelay(20000);
|
result.setInitialDelay(2000);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ActiveMQConnectionFactory createConnectionFactory(String uri) throws Exception {
|
||||||
|
ActiveMQConnectionFactory result = super.createConnectionFactory(uri);
|
||||||
|
result.setSendAcksAsync(false);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,6 @@ public class SimpleNetworkTest extends SimpleTopicTest {
|
||||||
LOG.info("Testing against destination: " + destination);
|
LOG.info("Testing against destination: " + destination);
|
||||||
for (int i = 0; i < numberOfConsumers; i++) {
|
for (int i = 0; i < numberOfConsumers; i++) {
|
||||||
consumers[i] = createConsumer(consumerFactory, destination, i);
|
consumers[i] = createConsumer(consumerFactory, destination, i);
|
||||||
consumers[i].setSleepDuration(consumerSleepDuration);
|
|
||||||
consumers[i].start();
|
consumers[i].start();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < numberofProducers; i++) {
|
for (int i = 0; i < numberofProducers; i++) {
|
||||||
|
|
|
@ -18,18 +18,13 @@ package org.apache.activemq.perf;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.jms.ConnectionFactory;
|
import javax.jms.ConnectionFactory;
|
||||||
import javax.jms.DeliveryMode;
|
import javax.jms.DeliveryMode;
|
||||||
import javax.jms.Destination;
|
import javax.jms.Destination;
|
||||||
import javax.jms.JMSException;
|
import javax.jms.JMSException;
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
import org.apache.activemq.broker.BrokerService;
|
||||||
import org.apache.activemq.broker.region.policy.NoSubscriptionRecoveryPolicy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
import org.apache.activemq.broker.region.policy.PolicyMap;
|
||||||
import org.apache.activemq.broker.region.policy.VMPendingQueueMessageStoragePolicy;
|
|
||||||
import org.apache.activemq.broker.region.policy.VMPendingSubscriberMessageStoragePolicy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @version $Revision: 1.3 $
|
* @version $Revision: 1.3 $
|
||||||
|
@ -37,18 +32,24 @@ import org.apache.activemq.broker.region.policy.VMPendingSubscriberMessageStorag
|
||||||
public class SimpleNonPersistentQueueTest extends SimpleQueueTest {
|
public class SimpleNonPersistentQueueTest extends SimpleQueueTest {
|
||||||
|
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
numberOfConsumers = 10;
|
numberOfConsumers = 1;
|
||||||
numberofProducers = 10;
|
numberofProducers = 1;
|
||||||
//this.consumerSleepDuration=100;
|
|
||||||
super.setUp();
|
super.setUp();
|
||||||
}
|
}
|
||||||
protected PerfProducer createProducer(ConnectionFactory fac, Destination dest, int number, byte[] payload) throws JMSException {
|
protected PerfProducer createProducer(ConnectionFactory fac, Destination dest, int number, byte[] payload) throws JMSException {
|
||||||
PerfProducer pp = new PerfProducer(fac, dest, payload);
|
PerfProducer pp = new PerfProducer(fac, dest, payload);
|
||||||
pp.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
pp.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||||
//pp.setTimeToLive(100);
|
pp.setTimeToLive(100);
|
||||||
return pp;
|
return pp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected PerfConsumer createConsumer(ConnectionFactory fac, Destination dest, int number) throws JMSException {
|
||||||
|
PerfConsumer result = new PerfConsumer(fac, dest);
|
||||||
|
result.setInitialDelay(20*1000);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
protected void configureBroker(BrokerService answer,String uri) throws Exception {
|
protected void configureBroker(BrokerService answer,String uri) throws Exception {
|
||||||
answer.setPersistent(false);
|
answer.setPersistent(false);
|
||||||
final List<PolicyEntry> policyEntries = new ArrayList<PolicyEntry>();
|
final List<PolicyEntry> policyEntries = new ArrayList<PolicyEntry>();
|
||||||
|
@ -65,4 +66,5 @@ public class SimpleNonPersistentQueueTest extends SimpleQueueTest {
|
||||||
answer.setDestinationPolicy(policyMap);
|
answer.setDestinationPolicy(policyMap);
|
||||||
super.configureBroker(answer, uri);
|
super.configureBroker(answer, uri);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,9 +55,7 @@ public class SimpleTopicTest extends TestCase {
|
||||||
protected byte[] array;
|
protected byte[] array;
|
||||||
protected ConnectionFactory factory;
|
protected ConnectionFactory factory;
|
||||||
|
|
||||||
protected long consumerSleepDuration=0;
|
/**
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up a test where the producer and consumer have their own connection.
|
* Sets up a test where the producer and consumer have their own connection.
|
||||||
*
|
*
|
||||||
* @see junit.framework.TestCase#setUp()
|
* @see junit.framework.TestCase#setUp()
|
||||||
|
@ -84,7 +82,6 @@ public class SimpleTopicTest extends TestCase {
|
||||||
LOG.info("Testing against destination: " + destination);
|
LOG.info("Testing against destination: " + destination);
|
||||||
for (int i = 0; i < numberOfConsumers; i++) {
|
for (int i = 0; i < numberOfConsumers; i++) {
|
||||||
consumers[consumerCount] = createConsumer(factory, destination, consumerCount);
|
consumers[consumerCount] = createConsumer(factory, destination, consumerCount);
|
||||||
consumers[consumerCount].setSleepDuration(consumerSleepDuration);
|
|
||||||
consumerCount++;
|
consumerCount++;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < numberofProducers; i++) {
|
for (int i = 0; i < numberofProducers; i++) {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#
|
#
|
||||||
# The logging properties used during tests..
|
# The logging properties used during tests..
|
||||||
#
|
#
|
||||||
log4j.rootLogger=INFO, out
|
log4j.rootLogger=INFO, out, stdout
|
||||||
|
|
||||||
log4j.logger.org.apache.activemq.spring=WARN
|
log4j.logger.org.apache.activemq.spring=WARN
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue