mirror of https://github.com/apache/activemq.git
[AMQ-9234] Remove JournalJDBC store and activeio dependency (#993)
This commit is contained in:
parent
1fdccd9cf4
commit
5ca71dfee6
|
@ -49,10 +49,6 @@
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>activemq-kahadb-store</artifactId>
|
<artifactId>activemq-kahadb-store</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- geronimo -->
|
<!-- geronimo -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -53,11 +53,6 @@
|
||||||
<artifactId>derbytools</artifactId>
|
<artifactId>derbytools</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- =============================== -->
|
<!-- =============================== -->
|
||||||
<!-- Testing Dependencies -->
|
<!-- Testing Dependencies -->
|
||||||
|
|
|
@ -1,429 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.store.journal;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.activeio.journal.RecordLocation;
|
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.JournalQueueAck;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.command.MessageAck;
|
|
||||||
import org.apache.activemq.command.MessageId;
|
|
||||||
import org.apache.activemq.filter.NonCachedMessageEvaluationContext;
|
|
||||||
import org.apache.activemq.store.IndexListener;
|
|
||||||
import org.apache.activemq.store.MessageRecoveryListener;
|
|
||||||
import org.apache.activemq.store.MessageStore;
|
|
||||||
import org.apache.activemq.store.PersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.AbstractMessageStore;
|
|
||||||
import org.apache.activemq.transaction.Synchronization;
|
|
||||||
import org.apache.activemq.usage.MemoryUsage;
|
|
||||||
import org.apache.activemq.util.Callback;
|
|
||||||
import org.apache.activemq.util.TransactionTemplate;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A MessageStore that uses a Journal to store it's messages.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class JournalMessageStore extends AbstractMessageStore {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(JournalMessageStore.class);
|
|
||||||
|
|
||||||
protected final JournalPersistenceAdapter peristenceAdapter;
|
|
||||||
protected final JournalTransactionStore transactionStore;
|
|
||||||
protected final MessageStore longTermStore;
|
|
||||||
protected final TransactionTemplate transactionTemplate;
|
|
||||||
protected RecordLocation lastLocation;
|
|
||||||
protected Set<RecordLocation> inFlightTxLocations = new HashSet<RecordLocation>();
|
|
||||||
|
|
||||||
private Map<MessageId, Message> messages = new LinkedHashMap<MessageId, Message>();
|
|
||||||
private List<MessageAck> messageAcks = new ArrayList<MessageAck>();
|
|
||||||
|
|
||||||
/** A MessageStore that we can use to retrieve messages quickly. */
|
|
||||||
private Map<MessageId, Message> cpAddedMessageIds;
|
|
||||||
|
|
||||||
|
|
||||||
private MemoryUsage memoryUsage;
|
|
||||||
|
|
||||||
public JournalMessageStore(JournalPersistenceAdapter adapter, MessageStore checkpointStore, ActiveMQDestination destination) {
|
|
||||||
super(destination);
|
|
||||||
this.peristenceAdapter = adapter;
|
|
||||||
this.transactionStore = adapter.getTransactionStore();
|
|
||||||
this.longTermStore = checkpointStore;
|
|
||||||
this.transactionTemplate = new TransactionTemplate(adapter, new ConnectionContext(new NonCachedMessageEvaluationContext()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setMemoryUsage(MemoryUsage memoryUsage) {
|
|
||||||
this.memoryUsage=memoryUsage;
|
|
||||||
longTermStore.setMemoryUsage(memoryUsage);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not synchronized since the Journal has better throughput if you increase
|
|
||||||
* the number of concurrent writes that it is doing.
|
|
||||||
*/
|
|
||||||
public void addMessage(final ConnectionContext context, final Message message) throws IOException {
|
|
||||||
|
|
||||||
final MessageId id = message.getMessageId();
|
|
||||||
|
|
||||||
final boolean debug = LOG.isDebugEnabled();
|
|
||||||
message.incrementReferenceCount();
|
|
||||||
|
|
||||||
final RecordLocation location = peristenceAdapter.writeCommand(message, message.isResponseRequired());
|
|
||||||
if (!context.isInTransaction()) {
|
|
||||||
if (debug) {
|
|
||||||
LOG.debug("Journalled message add for: " + id + ", at: " + location);
|
|
||||||
}
|
|
||||||
addMessage(context, message, location);
|
|
||||||
} else {
|
|
||||||
if (debug) {
|
|
||||||
LOG.debug("Journalled transacted message add for: " + id + ", at: " + location);
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
inFlightTxLocations.add(location);
|
|
||||||
}
|
|
||||||
transactionStore.addMessage(this, message, location);
|
|
||||||
context.getTransaction().addSynchronization(new Synchronization() {
|
|
||||||
public void afterCommit() throws Exception {
|
|
||||||
if (debug) {
|
|
||||||
LOG.debug("Transacted message add commit for: " + id + ", at: " + location);
|
|
||||||
}
|
|
||||||
synchronized (JournalMessageStore.this) {
|
|
||||||
inFlightTxLocations.remove(location);
|
|
||||||
addMessage(context, message, location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void afterRollback() throws Exception {
|
|
||||||
if (debug) {
|
|
||||||
LOG.debug("Transacted message add rollback for: " + id + ", at: " + location);
|
|
||||||
}
|
|
||||||
synchronized (JournalMessageStore.this) {
|
|
||||||
inFlightTxLocations.remove(location);
|
|
||||||
}
|
|
||||||
message.decrementReferenceCount();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addMessage(ConnectionContext context, final Message message, final RecordLocation location) {
|
|
||||||
synchronized (this) {
|
|
||||||
lastLocation = location;
|
|
||||||
MessageId id = message.getMessageId();
|
|
||||||
messages.put(id, message);
|
|
||||||
message.getMessageId().setFutureOrSequenceLong(0l);
|
|
||||||
if (indexListener != null) {
|
|
||||||
indexListener.onAdd(new IndexListener.MessageContext(context, message, null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void replayAddMessage(ConnectionContext context, Message message) {
|
|
||||||
try {
|
|
||||||
// Only add the message if it has not already been added.
|
|
||||||
Message t = longTermStore.getMessage(message.getMessageId());
|
|
||||||
if (t == null) {
|
|
||||||
longTermStore.addMessage(context, message);
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
LOG.warn("Could not replay add for message '" + message.getMessageId() + "'. Message may have already been added. reason: " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public void removeMessage(ConnectionContext context, final MessageAck ack) throws IOException {
|
|
||||||
final boolean debug = LOG.isDebugEnabled();
|
|
||||||
JournalQueueAck remove = new JournalQueueAck();
|
|
||||||
remove.setDestination(destination);
|
|
||||||
remove.setMessageAck(ack);
|
|
||||||
|
|
||||||
final RecordLocation location = peristenceAdapter.writeCommand(remove, ack.isResponseRequired());
|
|
||||||
if (!context.isInTransaction()) {
|
|
||||||
if (debug) {
|
|
||||||
LOG.debug("Journalled message remove for: " + ack.getLastMessageId() + ", at: " + location);
|
|
||||||
}
|
|
||||||
removeMessage(ack, location);
|
|
||||||
} else {
|
|
||||||
if (debug) {
|
|
||||||
LOG.debug("Journalled transacted message remove for: " + ack.getLastMessageId() + ", at: " + location);
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
inFlightTxLocations.add(location);
|
|
||||||
}
|
|
||||||
transactionStore.removeMessage(this, ack, location);
|
|
||||||
context.getTransaction().addSynchronization(new Synchronization() {
|
|
||||||
public void afterCommit() throws Exception {
|
|
||||||
if (debug) {
|
|
||||||
LOG.debug("Transacted message remove commit for: " + ack.getLastMessageId() + ", at: " + location);
|
|
||||||
}
|
|
||||||
synchronized (JournalMessageStore.this) {
|
|
||||||
inFlightTxLocations.remove(location);
|
|
||||||
removeMessage(ack, location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void afterRollback() throws Exception {
|
|
||||||
if (debug) {
|
|
||||||
LOG.debug("Transacted message remove rollback for: " + ack.getLastMessageId() + ", at: " + location);
|
|
||||||
}
|
|
||||||
synchronized (JournalMessageStore.this) {
|
|
||||||
inFlightTxLocations.remove(location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final void removeMessage(final MessageAck ack, final RecordLocation location) {
|
|
||||||
synchronized (this) {
|
|
||||||
lastLocation = location;
|
|
||||||
MessageId id = ack.getLastMessageId();
|
|
||||||
Message message = messages.remove(id);
|
|
||||||
if (message == null) {
|
|
||||||
messageAcks.add(ack);
|
|
||||||
} else {
|
|
||||||
message.decrementReferenceCount();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void replayRemoveMessage(ConnectionContext context, MessageAck messageAck) {
|
|
||||||
try {
|
|
||||||
// Only remove the message if it has not already been removed.
|
|
||||||
Message t = longTermStore.getMessage(messageAck.getLastMessageId());
|
|
||||||
if (t != null) {
|
|
||||||
longTermStore.removeMessage(context, messageAck);
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
LOG.warn("Could not replay acknowledge for message '" + messageAck.getLastMessageId() + "'. Message may have already been acknowledged. reason: " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public RecordLocation checkpoint() throws IOException {
|
|
||||||
return checkpoint(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public RecordLocation checkpoint(final Callback postCheckpointTest) throws IOException {
|
|
||||||
|
|
||||||
final List<MessageAck> cpRemovedMessageLocations;
|
|
||||||
final List<RecordLocation> cpActiveJournalLocations;
|
|
||||||
final int maxCheckpointMessageAddSize = peristenceAdapter.getMaxCheckpointMessageAddSize();
|
|
||||||
|
|
||||||
// swap out the message hash maps..
|
|
||||||
synchronized (this) {
|
|
||||||
cpAddedMessageIds = this.messages;
|
|
||||||
cpRemovedMessageLocations = this.messageAcks;
|
|
||||||
|
|
||||||
cpActiveJournalLocations = new ArrayList<RecordLocation>(inFlightTxLocations);
|
|
||||||
|
|
||||||
this.messages = new LinkedHashMap<MessageId, Message>();
|
|
||||||
this.messageAcks = new ArrayList<MessageAck>();
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionTemplate.run(new Callback() {
|
|
||||||
public void execute() throws Exception {
|
|
||||||
|
|
||||||
int size = 0;
|
|
||||||
|
|
||||||
PersistenceAdapter persitanceAdapter = transactionTemplate.getPersistenceAdapter();
|
|
||||||
ConnectionContext context = transactionTemplate.getContext();
|
|
||||||
|
|
||||||
// Checkpoint the added messages.
|
|
||||||
synchronized (JournalMessageStore.this) {
|
|
||||||
Iterator<Message> iterator = cpAddedMessageIds.values().iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Message message = iterator.next();
|
|
||||||
try {
|
|
||||||
longTermStore.addMessage(context, message);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
LOG.warn("Message could not be added to long term store: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
size += message.getSize();
|
|
||||||
message.decrementReferenceCount();
|
|
||||||
// Commit the batch if it's getting too big
|
|
||||||
if (size >= maxCheckpointMessageAddSize) {
|
|
||||||
persitanceAdapter.commitTransaction(context);
|
|
||||||
persitanceAdapter.beginTransaction(context);
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
persitanceAdapter.commitTransaction(context);
|
|
||||||
persitanceAdapter.beginTransaction(context);
|
|
||||||
|
|
||||||
// Checkpoint the removed messages.
|
|
||||||
Iterator<MessageAck> iterator = cpRemovedMessageLocations.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
try {
|
|
||||||
MessageAck ack = iterator.next();
|
|
||||||
longTermStore.removeMessage(transactionTemplate.getContext(), ack);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
LOG.debug("Message could not be removed from long term store: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postCheckpointTest != null) {
|
|
||||||
postCheckpointTest.execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
synchronized (this) {
|
|
||||||
cpAddedMessageIds = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cpActiveJournalLocations.size() > 0) {
|
|
||||||
Collections.sort(cpActiveJournalLocations);
|
|
||||||
return cpActiveJournalLocations.get(0);
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
return lastLocation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public Message getMessage(MessageId identity) throws IOException {
|
|
||||||
Message answer = null;
|
|
||||||
|
|
||||||
synchronized (this) {
|
|
||||||
// Do we have a still have it in the journal?
|
|
||||||
answer = messages.get(identity);
|
|
||||||
if (answer == null && cpAddedMessageIds != null) {
|
|
||||||
answer = cpAddedMessageIds.get(identity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (answer != null) {
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If all else fails try the long term message store.
|
|
||||||
return longTermStore.getMessage(identity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replays the checkpointStore first as those messages are the oldest ones,
|
|
||||||
* then messages are replayed from the transaction log and then the cache is
|
|
||||||
* updated.
|
|
||||||
*
|
|
||||||
* @param listener
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public void recover(final MessageRecoveryListener listener) throws Exception {
|
|
||||||
peristenceAdapter.checkpoint(true, true);
|
|
||||||
longTermStore.recover(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() throws Exception {
|
|
||||||
if (this.memoryUsage != null) {
|
|
||||||
this.memoryUsage.addUsageListener(peristenceAdapter);
|
|
||||||
}
|
|
||||||
longTermStore.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() throws Exception {
|
|
||||||
longTermStore.stop();
|
|
||||||
if (this.memoryUsage != null) {
|
|
||||||
this.memoryUsage.removeUsageListener(peristenceAdapter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Returns the longTermStore.
|
|
||||||
*/
|
|
||||||
public MessageStore getLongTermMessageStore() {
|
|
||||||
return longTermStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see org.apache.activemq.store.MessageStore#removeAllMessages(ConnectionContext)
|
|
||||||
*/
|
|
||||||
public void removeAllMessages(ConnectionContext context) throws IOException {
|
|
||||||
peristenceAdapter.checkpoint(true, true);
|
|
||||||
longTermStore.removeAllMessages(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addMessageReference(ConnectionContext context, MessageId messageId, long expirationTime, String messageRef) throws IOException {
|
|
||||||
throw new IOException("The journal does not support message references.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessageReference(MessageId identity) throws IOException {
|
|
||||||
throw new IOException("The journal does not support message references.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
* @see org.apache.activemq.store.MessageStore#getMessageCount()
|
|
||||||
*/
|
|
||||||
public int getMessageCount() throws IOException {
|
|
||||||
peristenceAdapter.checkpoint(true, true);
|
|
||||||
return longTermStore.getMessageCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getMessageSize() throws IOException {
|
|
||||||
peristenceAdapter.checkpoint(true, true);
|
|
||||||
return longTermStore.getMessageSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void recoverNextMessages(int maxReturned, MessageRecoveryListener listener) throws Exception {
|
|
||||||
peristenceAdapter.checkpoint(true, true);
|
|
||||||
longTermStore.recoverNextMessages(maxReturned, listener);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resetBatching() {
|
|
||||||
longTermStore.resetBatching();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBatch(MessageId messageId) throws Exception {
|
|
||||||
peristenceAdapter.checkpoint(true, true);
|
|
||||||
longTermStore.setBatch(messageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,816 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.store.journal;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.FutureTask;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.concurrent.ThreadFactory;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import org.apache.activeio.journal.InvalidRecordLocationException;
|
|
||||||
import org.apache.activeio.journal.Journal;
|
|
||||||
import org.apache.activeio.journal.JournalEventListener;
|
|
||||||
import org.apache.activeio.journal.RecordLocation;
|
|
||||||
import org.apache.activeio.packet.ByteArrayPacket;
|
|
||||||
import org.apache.activeio.packet.Packet;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.BrokerServiceAware;
|
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
|
||||||
import org.apache.activemq.broker.scheduler.JobSchedulerStore;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
|
||||||
import org.apache.activemq.command.DataStructure;
|
|
||||||
import org.apache.activemq.command.JournalQueueAck;
|
|
||||||
import org.apache.activemq.command.JournalTopicAck;
|
|
||||||
import org.apache.activemq.command.JournalTrace;
|
|
||||||
import org.apache.activemq.command.JournalTransaction;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.command.MessageAck;
|
|
||||||
import org.apache.activemq.command.ProducerId;
|
|
||||||
import org.apache.activemq.filter.NonCachedMessageEvaluationContext;
|
|
||||||
import org.apache.activemq.openwire.OpenWireFormat;
|
|
||||||
import org.apache.activemq.store.MessageStore;
|
|
||||||
import org.apache.activemq.store.PersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.TopicMessageStore;
|
|
||||||
import org.apache.activemq.store.TransactionStore;
|
|
||||||
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.journal.JournalTransactionStore.Tx;
|
|
||||||
import org.apache.activemq.store.journal.JournalTransactionStore.TxOperation;
|
|
||||||
import org.apache.activemq.thread.Scheduler;
|
|
||||||
import org.apache.activemq.thread.Task;
|
|
||||||
import org.apache.activemq.thread.TaskRunner;
|
|
||||||
import org.apache.activemq.thread.TaskRunnerFactory;
|
|
||||||
import org.apache.activemq.usage.SystemUsage;
|
|
||||||
import org.apache.activemq.usage.Usage;
|
|
||||||
import org.apache.activemq.usage.UsageListener;
|
|
||||||
import org.apache.activemq.util.ByteSequence;
|
|
||||||
import org.apache.activemq.util.IOExceptionSupport;
|
|
||||||
import org.apache.activemq.util.ThreadPoolUtils;
|
|
||||||
import org.apache.activemq.wireformat.WireFormat;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of {@link PersistenceAdapter} designed for use with a
|
|
||||||
* {@link Journal} and then check pointing asynchronously on a timeout with some
|
|
||||||
* other long term persistent storage.
|
|
||||||
*
|
|
||||||
* @deprecated - Deprecated for removal as this PersistenceAdapter is no longer used and
|
|
||||||
* replaced by the JDBCPersistenceAdapter.
|
|
||||||
*
|
|
||||||
* @org.apache.xbean.XBean
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
public class JournalPersistenceAdapter implements PersistenceAdapter, JournalEventListener, UsageListener, BrokerServiceAware {
|
|
||||||
|
|
||||||
private BrokerService brokerService;
|
|
||||||
|
|
||||||
protected Scheduler scheduler;
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(JournalPersistenceAdapter.class);
|
|
||||||
|
|
||||||
private Journal journal;
|
|
||||||
private PersistenceAdapter longTermPersistence;
|
|
||||||
|
|
||||||
private final WireFormat wireFormat = new OpenWireFormat();
|
|
||||||
|
|
||||||
private final ConcurrentMap<ActiveMQQueue, JournalMessageStore> queues = new ConcurrentHashMap<ActiveMQQueue, JournalMessageStore>();
|
|
||||||
private final ConcurrentMap<ActiveMQTopic, JournalTopicMessageStore> topics = new ConcurrentHashMap<ActiveMQTopic, JournalTopicMessageStore>();
|
|
||||||
|
|
||||||
private SystemUsage usageManager;
|
|
||||||
private long checkpointInterval = 1000 * 60 * 5;
|
|
||||||
private long lastCheckpointRequest = System.currentTimeMillis();
|
|
||||||
private long lastCleanup = System.currentTimeMillis();
|
|
||||||
private int maxCheckpointWorkers = 10;
|
|
||||||
private int maxCheckpointMessageAddSize = 1024 * 1024;
|
|
||||||
|
|
||||||
private final JournalTransactionStore transactionStore = new JournalTransactionStore(this);
|
|
||||||
private ThreadPoolExecutor checkpointExecutor;
|
|
||||||
|
|
||||||
private TaskRunner checkpointTask;
|
|
||||||
private CountDownLatch nextCheckpointCountDownLatch = new CountDownLatch(1);
|
|
||||||
private boolean fullCheckPoint;
|
|
||||||
|
|
||||||
private final AtomicBoolean started = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
private final Runnable periodicCheckpointTask = createPeriodicCheckpointTask();
|
|
||||||
|
|
||||||
private TaskRunnerFactory taskRunnerFactory;
|
|
||||||
private File directory;
|
|
||||||
|
|
||||||
public JournalPersistenceAdapter() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public JournalPersistenceAdapter(Journal journal, PersistenceAdapter longTermPersistence, TaskRunnerFactory taskRunnerFactory) throws IOException {
|
|
||||||
setJournal(journal);
|
|
||||||
setTaskRunnerFactory(taskRunnerFactory);
|
|
||||||
setPersistenceAdapter(longTermPersistence);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTaskRunnerFactory(TaskRunnerFactory taskRunnerFactory) {
|
|
||||||
this.taskRunnerFactory = taskRunnerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJournal(Journal journal) {
|
|
||||||
this.journal = journal;
|
|
||||||
journal.setJournalEventListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPersistenceAdapter(PersistenceAdapter longTermPersistence) {
|
|
||||||
this.longTermPersistence = longTermPersistence;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Runnable createPeriodicCheckpointTask() {
|
|
||||||
return new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
long lastTime = 0;
|
|
||||||
synchronized (this) {
|
|
||||||
lastTime = lastCheckpointRequest;
|
|
||||||
}
|
|
||||||
if (System.currentTimeMillis() > lastTime + checkpointInterval) {
|
|
||||||
checkpoint(false, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param usageManager The UsageManager that is controlling the
|
|
||||||
* destination's memory usage.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setUsageManager(SystemUsage usageManager) {
|
|
||||||
this.usageManager = usageManager;
|
|
||||||
longTermPersistence.setUsageManager(usageManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<ActiveMQDestination> getDestinations() {
|
|
||||||
Set<ActiveMQDestination> destinations = new HashSet<ActiveMQDestination>(longTermPersistence.getDestinations());
|
|
||||||
destinations.addAll(queues.keySet());
|
|
||||||
destinations.addAll(topics.keySet());
|
|
||||||
return destinations;
|
|
||||||
}
|
|
||||||
|
|
||||||
private MessageStore createMessageStore(ActiveMQDestination destination) throws IOException {
|
|
||||||
if (destination.isQueue()) {
|
|
||||||
return createQueueMessageStore((ActiveMQQueue)destination);
|
|
||||||
} else {
|
|
||||||
return createTopicMessageStore((ActiveMQTopic)destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MessageStore createQueueMessageStore(ActiveMQQueue destination) throws IOException {
|
|
||||||
JournalMessageStore store = queues.get(destination);
|
|
||||||
if (store == null) {
|
|
||||||
MessageStore checkpointStore = longTermPersistence.createQueueMessageStore(destination);
|
|
||||||
store = new JournalMessageStore(this, checkpointStore, destination);
|
|
||||||
queues.put(destination, store);
|
|
||||||
}
|
|
||||||
return store;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TopicMessageStore createTopicMessageStore(ActiveMQTopic destinationName) throws IOException {
|
|
||||||
JournalTopicMessageStore store = topics.get(destinationName);
|
|
||||||
if (store == null) {
|
|
||||||
TopicMessageStore checkpointStore = longTermPersistence.createTopicMessageStore(destinationName);
|
|
||||||
store = new JournalTopicMessageStore(this, checkpointStore, destinationName);
|
|
||||||
topics.put(destinationName, store);
|
|
||||||
}
|
|
||||||
return store;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleanup method to remove any state associated with the given destination
|
|
||||||
*
|
|
||||||
* @param destination Destination to forget
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void removeQueueMessageStore(ActiveMQQueue destination) {
|
|
||||||
queues.remove(destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleanup method to remove any state associated with the given destination
|
|
||||||
*
|
|
||||||
* @param destination Destination to forget
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void removeTopicMessageStore(ActiveMQTopic destination) {
|
|
||||||
topics.remove(destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TransactionStore createTransactionStore() throws IOException {
|
|
||||||
return transactionStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getLastMessageBrokerSequenceId() throws IOException {
|
|
||||||
return longTermPersistence.getLastMessageBrokerSequenceId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beginTransaction(ConnectionContext context) throws IOException {
|
|
||||||
longTermPersistence.beginTransaction(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void commitTransaction(ConnectionContext context) throws IOException {
|
|
||||||
longTermPersistence.commitTransaction(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void rollbackTransaction(ConnectionContext context) throws IOException {
|
|
||||||
longTermPersistence.rollbackTransaction(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void start() throws Exception {
|
|
||||||
if (!started.compareAndSet(false, true)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( brokerService!=null ) {
|
|
||||||
wireFormat.setVersion(brokerService.getStoreOpenWireVersion());
|
|
||||||
}
|
|
||||||
|
|
||||||
checkpointTask = taskRunnerFactory.createTaskRunner(new Task() {
|
|
||||||
@Override
|
|
||||||
public boolean iterate() {
|
|
||||||
return doCheckpoint();
|
|
||||||
}
|
|
||||||
}, "ActiveMQ Journal Checkpoint Worker");
|
|
||||||
|
|
||||||
checkpointExecutor = new ThreadPoolExecutor(maxCheckpointWorkers, maxCheckpointWorkers, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
|
|
||||||
@Override
|
|
||||||
public Thread newThread(Runnable runable) {
|
|
||||||
Thread t = new Thread(runable, "Journal checkpoint worker");
|
|
||||||
t.setPriority(7);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// checkpointExecutor.allowCoreThreadTimeOut(true);
|
|
||||||
|
|
||||||
this.usageManager.getMemoryUsage().addUsageListener(this);
|
|
||||||
|
|
||||||
if (longTermPersistence instanceof JDBCPersistenceAdapter) {
|
|
||||||
// Disabled periodic clean up as it deadlocks with the checkpoint
|
|
||||||
// operations.
|
|
||||||
((JDBCPersistenceAdapter)longTermPersistence).setCleanupPeriod(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
longTermPersistence.start();
|
|
||||||
createTransactionStore();
|
|
||||||
recover();
|
|
||||||
|
|
||||||
// Do a checkpoint periodically.
|
|
||||||
this.scheduler = new Scheduler("Journal Scheduler");
|
|
||||||
this.scheduler.start();
|
|
||||||
this.scheduler.executePeriodically(periodicCheckpointTask, checkpointInterval / 10);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stop() throws Exception {
|
|
||||||
|
|
||||||
this.usageManager.getMemoryUsage().removeUsageListener(this);
|
|
||||||
if (!started.compareAndSet(true, false)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.scheduler.cancel(periodicCheckpointTask);
|
|
||||||
this.scheduler.stop();
|
|
||||||
|
|
||||||
// Take one final checkpoint and stop checkpoint processing.
|
|
||||||
checkpoint(true, true);
|
|
||||||
checkpointTask.shutdown();
|
|
||||||
ThreadPoolUtils.shutdown(checkpointExecutor);
|
|
||||||
checkpointExecutor = null;
|
|
||||||
|
|
||||||
queues.clear();
|
|
||||||
topics.clear();
|
|
||||||
|
|
||||||
IOException firstException = null;
|
|
||||||
try {
|
|
||||||
journal.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
firstException = IOExceptionSupport.create("Failed to close journals: " + e, e);
|
|
||||||
}
|
|
||||||
longTermPersistence.stop();
|
|
||||||
|
|
||||||
if (firstException != null) {
|
|
||||||
throw firstException;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Properties
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
public PersistenceAdapter getLongTermPersistence() {
|
|
||||||
return longTermPersistence;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Returns the wireFormat.
|
|
||||||
*/
|
|
||||||
public WireFormat getWireFormat() {
|
|
||||||
return wireFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation methods
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Journal give us a call back so that we can move old data out of the
|
|
||||||
* journal. Taking a checkpoint does this for us.
|
|
||||||
*
|
|
||||||
* @see org.apache.activemq.journal.JournalEventListener#overflowNotification(org.apache.activemq.journal.RecordLocation)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void overflowNotification(RecordLocation safeLocation) {
|
|
||||||
checkpoint(false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When we checkpoint we move all the journalled data to long term storage.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void checkpoint(boolean sync, boolean fullCheckpoint) {
|
|
||||||
try {
|
|
||||||
if (journal == null) {
|
|
||||||
throw new IllegalStateException("Journal is closed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
CountDownLatch latch = null;
|
|
||||||
synchronized (this) {
|
|
||||||
latch = nextCheckpointCountDownLatch;
|
|
||||||
lastCheckpointRequest = now;
|
|
||||||
if (fullCheckpoint) {
|
|
||||||
this.fullCheckPoint = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkpointTask.wakeup();
|
|
||||||
|
|
||||||
if (sync) {
|
|
||||||
LOG.debug("Waking for checkpoint to complete.");
|
|
||||||
latch.await();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
LOG.warn("Request to start checkpoint failed: " + e, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkpoint(boolean sync) {
|
|
||||||
checkpoint(sync, sync);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This does the actual checkpoint.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean doCheckpoint() {
|
|
||||||
CountDownLatch latch = null;
|
|
||||||
boolean fullCheckpoint;
|
|
||||||
synchronized (this) {
|
|
||||||
latch = nextCheckpointCountDownLatch;
|
|
||||||
nextCheckpointCountDownLatch = new CountDownLatch(1);
|
|
||||||
fullCheckpoint = this.fullCheckPoint;
|
|
||||||
this.fullCheckPoint = false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
|
|
||||||
LOG.debug("Checkpoint started.");
|
|
||||||
RecordLocation newMark = null;
|
|
||||||
|
|
||||||
ArrayList<FutureTask<RecordLocation>> futureTasks = new ArrayList<FutureTask<RecordLocation>>(queues.size() + topics.size());
|
|
||||||
|
|
||||||
//
|
|
||||||
// We do many partial checkpoints (fullCheckpoint==false) to move
|
|
||||||
// topic messages
|
|
||||||
// to long term store as soon as possible.
|
|
||||||
//
|
|
||||||
// We want to avoid doing that for queue messages since removes the
|
|
||||||
// come in the same
|
|
||||||
// checkpoint cycle will nullify the previous message add.
|
|
||||||
// Therefore, we only
|
|
||||||
// checkpoint queues on the fullCheckpoint cycles.
|
|
||||||
//
|
|
||||||
if (fullCheckpoint) {
|
|
||||||
Iterator<JournalMessageStore> iterator = queues.values().iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
try {
|
|
||||||
final JournalMessageStore ms = iterator.next();
|
|
||||||
FutureTask<RecordLocation> task = new FutureTask<RecordLocation>(new Callable<RecordLocation>() {
|
|
||||||
@Override
|
|
||||||
public RecordLocation call() throws Exception {
|
|
||||||
return ms.checkpoint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
futureTasks.add(task);
|
|
||||||
checkpointExecutor.execute(task);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error("Failed to checkpoint a message store: " + e, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator<JournalTopicMessageStore> iterator = topics.values().iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
try {
|
|
||||||
final JournalTopicMessageStore ms = iterator.next();
|
|
||||||
FutureTask<RecordLocation> task = new FutureTask<RecordLocation>(new Callable<RecordLocation>() {
|
|
||||||
@Override
|
|
||||||
public RecordLocation call() throws Exception {
|
|
||||||
return ms.checkpoint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
futureTasks.add(task);
|
|
||||||
checkpointExecutor.execute(task);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error("Failed to checkpoint a message store: " + e, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (Iterator<FutureTask<RecordLocation>> iter = futureTasks.iterator(); iter.hasNext();) {
|
|
||||||
FutureTask<RecordLocation> ft = iter.next();
|
|
||||||
RecordLocation mark = ft.get();
|
|
||||||
// We only set a newMark on full checkpoints.
|
|
||||||
if (fullCheckpoint) {
|
|
||||||
if (mark != null && (newMark == null || newMark.compareTo(mark) < 0)) {
|
|
||||||
newMark = mark;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
LOG.error("Failed to checkpoint a message store: " + e, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fullCheckpoint) {
|
|
||||||
try {
|
|
||||||
if (newMark != null) {
|
|
||||||
LOG.debug("Marking journal at: " + newMark);
|
|
||||||
journal.setMark(newMark, true);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error("Failed to mark the Journal: " + e, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (longTermPersistence instanceof JDBCPersistenceAdapter) {
|
|
||||||
// We may be check pointing more often than the
|
|
||||||
// checkpointInterval if under high use
|
|
||||||
// But we don't want to clean up the db that often.
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
if (now > lastCleanup + checkpointInterval) {
|
|
||||||
lastCleanup = now;
|
|
||||||
((JDBCPersistenceAdapter)longTermPersistence).cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.debug("Checkpoint done.");
|
|
||||||
} finally {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
return this.fullCheckPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param location
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public DataStructure readCommand(RecordLocation location) throws IOException {
|
|
||||||
try {
|
|
||||||
Packet packet = journal.read(location);
|
|
||||||
return (DataStructure)wireFormat.unmarshal(toByteSequence(packet));
|
|
||||||
} catch (InvalidRecordLocationException e) {
|
|
||||||
throw createReadException(location, e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw createReadException(location, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move all the messages that were in the journal into long term storage. We
|
|
||||||
* just replay and do a checkpoint.
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
* @throws IOException
|
|
||||||
* @throws InvalidRecordLocationException
|
|
||||||
* @throws IllegalStateException
|
|
||||||
*/
|
|
||||||
private void recover() throws IllegalStateException, InvalidRecordLocationException, IOException, IOException {
|
|
||||||
|
|
||||||
RecordLocation pos = null;
|
|
||||||
int transactionCounter = 0;
|
|
||||||
|
|
||||||
LOG.info("Journal Recovery Started from: " + journal);
|
|
||||||
ConnectionContext context = new ConnectionContext(new NonCachedMessageEvaluationContext());
|
|
||||||
|
|
||||||
// While we have records in the journal.
|
|
||||||
while ((pos = journal.getNextRecordLocation(pos)) != null) {
|
|
||||||
Packet data = journal.read(pos);
|
|
||||||
DataStructure c = (DataStructure)wireFormat.unmarshal(toByteSequence(data));
|
|
||||||
|
|
||||||
if (c instanceof Message) {
|
|
||||||
Message message = (Message)c;
|
|
||||||
JournalMessageStore store = (JournalMessageStore)createMessageStore(message.getDestination());
|
|
||||||
if (message.isInTransaction()) {
|
|
||||||
transactionStore.addMessage(store, message, pos);
|
|
||||||
} else {
|
|
||||||
store.replayAddMessage(context, message);
|
|
||||||
transactionCounter++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (c.getDataStructureType()) {
|
|
||||||
case JournalQueueAck.DATA_STRUCTURE_TYPE: {
|
|
||||||
JournalQueueAck command = (JournalQueueAck)c;
|
|
||||||
JournalMessageStore store = (JournalMessageStore)createMessageStore(command.getDestination());
|
|
||||||
if (command.getMessageAck().isInTransaction()) {
|
|
||||||
transactionStore.removeMessage(store, command.getMessageAck(), pos);
|
|
||||||
} else {
|
|
||||||
store.replayRemoveMessage(context, command.getMessageAck());
|
|
||||||
transactionCounter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case JournalTopicAck.DATA_STRUCTURE_TYPE: {
|
|
||||||
JournalTopicAck command = (JournalTopicAck)c;
|
|
||||||
JournalTopicMessageStore store = (JournalTopicMessageStore)createMessageStore(command.getDestination());
|
|
||||||
if (command.getTransactionId() != null) {
|
|
||||||
transactionStore.acknowledge(store, command, pos);
|
|
||||||
} else {
|
|
||||||
store.replayAcknowledge(context, command.getClientId(), command.getSubscritionName(), command.getMessageId());
|
|
||||||
transactionCounter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case JournalTransaction.DATA_STRUCTURE_TYPE: {
|
|
||||||
JournalTransaction command = (JournalTransaction)c;
|
|
||||||
try {
|
|
||||||
// Try to replay the packet.
|
|
||||||
switch (command.getType()) {
|
|
||||||
case JournalTransaction.XA_PREPARE:
|
|
||||||
transactionStore.replayPrepare(command.getTransactionId());
|
|
||||||
break;
|
|
||||||
case JournalTransaction.XA_COMMIT:
|
|
||||||
case JournalTransaction.LOCAL_COMMIT:
|
|
||||||
Tx tx = transactionStore.replayCommit(command.getTransactionId(), command.getWasPrepared());
|
|
||||||
if (tx == null) {
|
|
||||||
break; // We may be trying to replay a commit
|
|
||||||
}
|
|
||||||
// that
|
|
||||||
// was already committed.
|
|
||||||
|
|
||||||
// Replay the committed operations.
|
|
||||||
tx.getOperations();
|
|
||||||
for (Iterator iter = tx.getOperations().iterator(); iter.hasNext();) {
|
|
||||||
TxOperation op = (TxOperation)iter.next();
|
|
||||||
if (op.operationType == TxOperation.ADD_OPERATION_TYPE) {
|
|
||||||
op.store.replayAddMessage(context, (Message)op.data);
|
|
||||||
}
|
|
||||||
if (op.operationType == TxOperation.REMOVE_OPERATION_TYPE) {
|
|
||||||
op.store.replayRemoveMessage(context, (MessageAck)op.data);
|
|
||||||
}
|
|
||||||
if (op.operationType == TxOperation.ACK_OPERATION_TYPE) {
|
|
||||||
JournalTopicAck ack = (JournalTopicAck)op.data;
|
|
||||||
((JournalTopicMessageStore)op.store).replayAcknowledge(context, ack.getClientId(), ack.getSubscritionName(), ack.getMessageId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
transactionCounter++;
|
|
||||||
break;
|
|
||||||
case JournalTransaction.LOCAL_ROLLBACK:
|
|
||||||
case JournalTransaction.XA_ROLLBACK:
|
|
||||||
transactionStore.replayRollback(command.getTransactionId());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IOException("Invalid journal command type: " + command.getType());
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOG.error("Recovery Failure: Could not replay: " + c + ", reason: " + e, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case JournalTrace.DATA_STRUCTURE_TYPE:
|
|
||||||
JournalTrace trace = (JournalTrace)c;
|
|
||||||
LOG.debug("TRACE Entry: " + trace.getMessage());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG.error("Unknown type of record in transaction log which will be discarded: " + c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RecordLocation location = writeTraceMessage("RECOVERED", true);
|
|
||||||
journal.setMark(location, true);
|
|
||||||
|
|
||||||
LOG.info("Journal Recovered: " + transactionCounter + " message(s) in transactions recovered.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private IOException createReadException(RecordLocation location, Exception e) {
|
|
||||||
return IOExceptionSupport.create("Failed to read to journal for: " + location + ". Reason: " + e, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected IOException createWriteException(DataStructure packet, Exception e) {
|
|
||||||
return IOExceptionSupport.create("Failed to write to journal for: " + packet + ". Reason: " + e, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected IOException createWriteException(String command, Exception e) {
|
|
||||||
return IOExceptionSupport.create("Failed to write to journal for command: " + command + ". Reason: " + e, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected IOException createRecoveryFailedException(Exception e) {
|
|
||||||
return IOExceptionSupport.create("Failed to recover from journal. Reason: " + e, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param command
|
|
||||||
* @param sync
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public RecordLocation writeCommand(DataStructure command, boolean sync) throws IOException {
|
|
||||||
if (started.get()) {
|
|
||||||
try {
|
|
||||||
return journal.write(toPacket(wireFormat.marshal(command)), sync);
|
|
||||||
} catch (IOException ioe) {
|
|
||||||
LOG.error("Cannot write to the journal", ioe);
|
|
||||||
brokerService.handleIOException(ioe);
|
|
||||||
throw ioe;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new IOException("closed");
|
|
||||||
}
|
|
||||||
|
|
||||||
private RecordLocation writeTraceMessage(String message, boolean sync) throws IOException {
|
|
||||||
JournalTrace trace = new JournalTrace();
|
|
||||||
trace.setMessage(message);
|
|
||||||
return writeCommand(trace, sync);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUsageChanged(Usage usage, int oldPercentUsage, int newPercentUsage) {
|
|
||||||
newPercentUsage = (newPercentUsage / 10) * 10;
|
|
||||||
oldPercentUsage = (oldPercentUsage / 10) * 10;
|
|
||||||
if (newPercentUsage >= 70 && oldPercentUsage < newPercentUsage) {
|
|
||||||
boolean sync = newPercentUsage >= 90;
|
|
||||||
checkpoint(sync, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public JournalTransactionStore getTransactionStore() {
|
|
||||||
return transactionStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteAllMessages() throws IOException {
|
|
||||||
try {
|
|
||||||
JournalTrace trace = new JournalTrace();
|
|
||||||
trace.setMessage("DELETED");
|
|
||||||
RecordLocation location = journal.write(toPacket(wireFormat.marshal(trace)), false);
|
|
||||||
journal.setMark(location, true);
|
|
||||||
LOG.info("Journal deleted: ");
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw e;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
throw IOExceptionSupport.create(e);
|
|
||||||
}
|
|
||||||
longTermPersistence.deleteAllMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SystemUsage getUsageManager() {
|
|
||||||
return usageManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMaxCheckpointMessageAddSize() {
|
|
||||||
return maxCheckpointMessageAddSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMaxCheckpointMessageAddSize(int maxCheckpointMessageAddSize) {
|
|
||||||
this.maxCheckpointMessageAddSize = maxCheckpointMessageAddSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMaxCheckpointWorkers() {
|
|
||||||
return maxCheckpointWorkers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMaxCheckpointWorkers(int maxCheckpointWorkers) {
|
|
||||||
this.maxCheckpointWorkers = maxCheckpointWorkers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCheckpointInterval() {
|
|
||||||
return checkpointInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCheckpointInterval(long checkpointInterval) {
|
|
||||||
this.checkpointInterval = checkpointInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUseExternalMessageReferences() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUseExternalMessageReferences(boolean enable) {
|
|
||||||
if (enable) {
|
|
||||||
throw new IllegalArgumentException("The journal does not support message references.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Packet toPacket(ByteSequence sequence) {
|
|
||||||
return new ByteArrayPacket(new org.apache.activeio.packet.ByteSequence(sequence.data, sequence.offset, sequence.length));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ByteSequence toByteSequence(Packet packet) {
|
|
||||||
org.apache.activeio.packet.ByteSequence sequence = packet.asByteSequence();
|
|
||||||
return new ByteSequence(sequence.getData(), sequence.getOffset(), sequence.getLength());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBrokerName(String brokerName) {
|
|
||||||
longTermPersistence.setBrokerName(brokerName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "JournalPersistenceAdapter(" + longTermPersistence + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDirectory(File dir) {
|
|
||||||
this.directory=dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public File getDirectory(){
|
|
||||||
return directory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long size(){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBrokerService(BrokerService brokerService) {
|
|
||||||
this.brokerService = brokerService;
|
|
||||||
PersistenceAdapter pa = getLongTermPersistence();
|
|
||||||
if( pa instanceof BrokerServiceAware ) {
|
|
||||||
((BrokerServiceAware)pa).setBrokerService(brokerService);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getLastProducerSequenceId(ProducerId id) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void allowIOResumption() {
|
|
||||||
longTermPersistence.allowIOResumption();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JobSchedulerStore createJobSchedulerStore() throws IOException, UnsupportedOperationException {
|
|
||||||
return longTermPersistence.createJobSchedulerStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,274 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.store.journal;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.apache.activeio.journal.Journal;
|
|
||||||
import org.apache.activeio.journal.active.JournalImpl;
|
|
||||||
import org.apache.activeio.journal.active.JournalLockedException;
|
|
||||||
import org.apache.activemq.broker.Locker;
|
|
||||||
import org.apache.activemq.store.PersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.PersistenceAdapterFactory;
|
|
||||||
import org.apache.activemq.store.jdbc.DataSourceServiceSupport;
|
|
||||||
import org.apache.activemq.store.jdbc.JDBCAdapter;
|
|
||||||
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.jdbc.Statements;
|
|
||||||
import org.apache.activemq.thread.TaskRunnerFactory;
|
|
||||||
import org.apache.activemq.util.ServiceStopper;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory class that can create PersistenceAdapter objects.
|
|
||||||
*
|
|
||||||
* @deprecated Deprecated for removal as this PersistenceAdapter is no longer used and
|
|
||||||
* replaced by the JDBCPersistenceAdapter.
|
|
||||||
*
|
|
||||||
* @org.apache.xbean.XBean
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
public class JournalPersistenceAdapterFactory extends DataSourceServiceSupport implements PersistenceAdapterFactory {
|
|
||||||
|
|
||||||
private static final int JOURNAL_LOCKED_WAIT_DELAY = 10 * 1000;
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(JournalPersistenceAdapterFactory.class);
|
|
||||||
|
|
||||||
private long checkpointInterval = 1000 * 60 * 5;
|
|
||||||
private int journalLogFileSize = 1024 * 1024 * 20;
|
|
||||||
private int journalLogFiles = 2;
|
|
||||||
private TaskRunnerFactory taskRunnerFactory;
|
|
||||||
private Journal journal;
|
|
||||||
private boolean useJournal = true;
|
|
||||||
private boolean useQuickJournal;
|
|
||||||
private File journalArchiveDirectory;
|
|
||||||
private boolean failIfJournalIsLocked;
|
|
||||||
private int journalThreadPriority = Thread.MAX_PRIORITY;
|
|
||||||
private JDBCPersistenceAdapter jdbcPersistenceAdapter = new JDBCPersistenceAdapter();
|
|
||||||
private boolean useDedicatedTaskRunner;
|
|
||||||
|
|
||||||
public PersistenceAdapter createPersistenceAdapter() throws IOException {
|
|
||||||
jdbcPersistenceAdapter.setDataSource(getDataSource());
|
|
||||||
|
|
||||||
if (!useJournal) {
|
|
||||||
return jdbcPersistenceAdapter;
|
|
||||||
}
|
|
||||||
JournalPersistenceAdapter result = new JournalPersistenceAdapter(getJournal(), jdbcPersistenceAdapter, getTaskRunnerFactory());
|
|
||||||
result.setDirectory(getDataDirectoryFile());
|
|
||||||
result.setCheckpointInterval(getCheckpointInterval());
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getJournalLogFiles() {
|
|
||||||
return journalLogFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the number of journal log files to use
|
|
||||||
*/
|
|
||||||
public void setJournalLogFiles(int journalLogFiles) {
|
|
||||||
this.journalLogFiles = journalLogFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getJournalLogFileSize() {
|
|
||||||
return journalLogFileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the size of the journal log files
|
|
||||||
* When set using Xbean, values of the form "20 Mb", "1024kb", and "1g" can be used
|
|
||||||
* @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.MemoryIntPropertyEditor"
|
|
||||||
*/
|
|
||||||
public void setJournalLogFileSize(int journalLogFileSize) {
|
|
||||||
this.journalLogFileSize = journalLogFileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JDBCPersistenceAdapter getJdbcAdapter() {
|
|
||||||
return jdbcPersistenceAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJdbcAdapter(JDBCPersistenceAdapter jdbcAdapter) {
|
|
||||||
this.jdbcPersistenceAdapter = jdbcAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUseJournal() {
|
|
||||||
return useJournal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCheckpointInterval() {
|
|
||||||
return checkpointInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCheckpointInterval(long checkpointInterval) {
|
|
||||||
this.checkpointInterval = checkpointInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables or disables the use of the journal. The default is to use the
|
|
||||||
* journal
|
|
||||||
*
|
|
||||||
* @param useJournal
|
|
||||||
*/
|
|
||||||
public void setUseJournal(boolean useJournal) {
|
|
||||||
this.useJournal = useJournal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUseDedicatedTaskRunner() {
|
|
||||||
return useDedicatedTaskRunner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUseDedicatedTaskRunner(boolean useDedicatedTaskRunner) {
|
|
||||||
this.useDedicatedTaskRunner = useDedicatedTaskRunner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TaskRunnerFactory getTaskRunnerFactory() {
|
|
||||||
if (taskRunnerFactory == null) {
|
|
||||||
taskRunnerFactory = new TaskRunnerFactory("Persistence Adaptor Task", journalThreadPriority,
|
|
||||||
true, 1000, isUseDedicatedTaskRunner());
|
|
||||||
}
|
|
||||||
return taskRunnerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTaskRunnerFactory(TaskRunnerFactory taskRunnerFactory) {
|
|
||||||
this.taskRunnerFactory = taskRunnerFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Journal getJournal() throws IOException {
|
|
||||||
if (journal == null) {
|
|
||||||
createJournal();
|
|
||||||
}
|
|
||||||
return journal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJournal(Journal journal) {
|
|
||||||
this.journal = journal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getJournalArchiveDirectory() {
|
|
||||||
if (journalArchiveDirectory == null && useQuickJournal) {
|
|
||||||
journalArchiveDirectory = new File(getDataDirectoryFile(), "journal");
|
|
||||||
}
|
|
||||||
return journalArchiveDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setJournalArchiveDirectory(File journalArchiveDirectory) {
|
|
||||||
this.journalArchiveDirectory = journalArchiveDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUseQuickJournal() {
|
|
||||||
return useQuickJournal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables or disables the use of quick journal, which keeps messages in the
|
|
||||||
* journal and just stores a reference to the messages in JDBC. Defaults to
|
|
||||||
* false so that messages actually reside long term in the JDBC database.
|
|
||||||
*/
|
|
||||||
public void setUseQuickJournal(boolean useQuickJournal) {
|
|
||||||
this.useQuickJournal = useQuickJournal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JDBCAdapter getAdapter() throws IOException {
|
|
||||||
return jdbcPersistenceAdapter.getAdapter();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAdapter(JDBCAdapter adapter) {
|
|
||||||
jdbcPersistenceAdapter.setAdapter(adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Statements getStatements() {
|
|
||||||
return jdbcPersistenceAdapter.getStatements();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatements(Statements statements) {
|
|
||||||
jdbcPersistenceAdapter.setStatements(statements);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether or not an exclusive database lock should be used to enable
|
|
||||||
* JDBC Master/Slave. Enabled by default.
|
|
||||||
*/
|
|
||||||
public void setUseDatabaseLock(boolean useDatabaseLock) {
|
|
||||||
jdbcPersistenceAdapter.setUseLock(useDatabaseLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCreateTablesOnStartup() {
|
|
||||||
return jdbcPersistenceAdapter.isCreateTablesOnStartup();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether or not tables are created on startup
|
|
||||||
*/
|
|
||||||
public void setCreateTablesOnStartup(boolean createTablesOnStartup) {
|
|
||||||
jdbcPersistenceAdapter.setCreateTablesOnStartup(createTablesOnStartup);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getJournalThreadPriority() {
|
|
||||||
return journalThreadPriority;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the thread priority of the journal thread
|
|
||||||
*/
|
|
||||||
public void setJournalThreadPriority(int journalThreadPriority) {
|
|
||||||
this.journalThreadPriority = journalThreadPriority;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
protected void createJournal() throws IOException {
|
|
||||||
File journalDir = new File(getDataDirectoryFile(), "journal").getCanonicalFile();
|
|
||||||
if (failIfJournalIsLocked) {
|
|
||||||
journal = new JournalImpl(journalDir, journalLogFiles, journalLogFileSize,
|
|
||||||
getJournalArchiveDirectory());
|
|
||||||
} else {
|
|
||||||
while (true) {
|
|
||||||
try {
|
|
||||||
journal = new JournalImpl(journalDir, journalLogFiles, journalLogFileSize,
|
|
||||||
getJournalArchiveDirectory());
|
|
||||||
break;
|
|
||||||
} catch (JournalLockedException e) {
|
|
||||||
LOG.info("Journal is locked... waiting " + (JOURNAL_LOCKED_WAIT_DELAY / 1000)
|
|
||||||
+ " seconds for the journal to be unlocked.");
|
|
||||||
try {
|
|
||||||
Thread.sleep(JOURNAL_LOCKED_WAIT_DELAY);
|
|
||||||
} catch (InterruptedException e1) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Locker createDefaultLocker() throws IOException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doStop(ServiceStopper stopper) throws Exception {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doStart() throws Exception {}
|
|
||||||
}
|
|
|
@ -1,242 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.store.journal;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.apache.activeio.journal.RecordLocation;
|
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
|
||||||
import org.apache.activemq.command.JournalTopicAck;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.command.MessageAck;
|
|
||||||
import org.apache.activemq.command.MessageId;
|
|
||||||
import org.apache.activemq.command.SubscriptionInfo;
|
|
||||||
import org.apache.activemq.store.MessageRecoveryListener;
|
|
||||||
import org.apache.activemq.store.MessageStoreSubscriptionStatistics;
|
|
||||||
import org.apache.activemq.store.TopicMessageStore;
|
|
||||||
import org.apache.activemq.transaction.Synchronization;
|
|
||||||
import org.apache.activemq.util.Callback;
|
|
||||||
import org.apache.activemq.util.SubscriptionKey;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A MessageStore that uses a Journal to store it's messages.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class JournalTopicMessageStore extends JournalMessageStore implements TopicMessageStore {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(JournalTopicMessageStore.class);
|
|
||||||
|
|
||||||
private TopicMessageStore longTermStore;
|
|
||||||
private HashMap<SubscriptionKey, MessageId> ackedLastAckLocations = new HashMap<SubscriptionKey, MessageId>();
|
|
||||||
|
|
||||||
public JournalTopicMessageStore(JournalPersistenceAdapter adapter, TopicMessageStore checkpointStore,
|
|
||||||
ActiveMQTopic destinationName) {
|
|
||||||
super(adapter, checkpointStore, destinationName);
|
|
||||||
this.longTermStore = checkpointStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void recoverSubscription(String clientId, String subscriptionName, MessageRecoveryListener listener)
|
|
||||||
throws Exception {
|
|
||||||
this.peristenceAdapter.checkpoint(true, true);
|
|
||||||
longTermStore.recoverSubscription(clientId, subscriptionName, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void recoverNextMessages(String clientId, String subscriptionName, int maxReturned,
|
|
||||||
MessageRecoveryListener listener) throws Exception {
|
|
||||||
this.peristenceAdapter.checkpoint(true, true);
|
|
||||||
longTermStore.recoverNextMessages(clientId, subscriptionName, maxReturned, listener);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SubscriptionInfo lookupSubscription(String clientId, String subscriptionName) throws IOException {
|
|
||||||
return longTermStore.lookupSubscription(clientId, subscriptionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addSubscription(SubscriptionInfo subscriptionInfo, boolean retroactive) throws IOException {
|
|
||||||
this.peristenceAdapter.checkpoint(true, true);
|
|
||||||
longTermStore.addSubscription(subscriptionInfo, retroactive);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addMessage(ConnectionContext context, Message message) throws IOException {
|
|
||||||
super.addMessage(context, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void acknowledge(ConnectionContext context, String clientId, String subscriptionName,
|
|
||||||
final MessageId messageId, MessageAck originalAck) throws IOException {
|
|
||||||
final boolean debug = LOG.isDebugEnabled();
|
|
||||||
|
|
||||||
JournalTopicAck ack = new JournalTopicAck();
|
|
||||||
ack.setDestination(destination);
|
|
||||||
ack.setMessageId(messageId);
|
|
||||||
ack.setMessageSequenceId(messageId.getBrokerSequenceId());
|
|
||||||
ack.setSubscritionName(subscriptionName);
|
|
||||||
ack.setClientId(clientId);
|
|
||||||
ack.setTransactionId(context.getTransaction() != null
|
|
||||||
? context.getTransaction().getTransactionId() : null);
|
|
||||||
final RecordLocation location = peristenceAdapter.writeCommand(ack, false);
|
|
||||||
|
|
||||||
final SubscriptionKey key = new SubscriptionKey(clientId, subscriptionName);
|
|
||||||
if (!context.isInTransaction()) {
|
|
||||||
if (debug) {
|
|
||||||
LOG.debug("Journalled acknowledge for: " + messageId + ", at: " + location);
|
|
||||||
}
|
|
||||||
acknowledge(messageId, location, key);
|
|
||||||
} else {
|
|
||||||
if (debug) {
|
|
||||||
LOG.debug("Journalled transacted acknowledge for: " + messageId + ", at: " + location);
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
inFlightTxLocations.add(location);
|
|
||||||
}
|
|
||||||
transactionStore.acknowledge(this, ack, location);
|
|
||||||
context.getTransaction().addSynchronization(new Synchronization() {
|
|
||||||
@Override
|
|
||||||
public void afterCommit() throws Exception {
|
|
||||||
if (debug) {
|
|
||||||
LOG.debug("Transacted acknowledge commit for: " + messageId + ", at: " + location);
|
|
||||||
}
|
|
||||||
synchronized (JournalTopicMessageStore.this) {
|
|
||||||
inFlightTxLocations.remove(location);
|
|
||||||
acknowledge(messageId, location, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterRollback() throws Exception {
|
|
||||||
if (debug) {
|
|
||||||
LOG.debug("Transacted acknowledge rollback for: " + messageId + ", at: " + location);
|
|
||||||
}
|
|
||||||
synchronized (JournalTopicMessageStore.this) {
|
|
||||||
inFlightTxLocations.remove(location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void replayAcknowledge(ConnectionContext context, String clientId, String subscritionName,
|
|
||||||
MessageId messageId) {
|
|
||||||
try {
|
|
||||||
SubscriptionInfo sub = longTermStore.lookupSubscription(clientId, subscritionName);
|
|
||||||
if (sub != null) {
|
|
||||||
longTermStore.acknowledge(context, clientId, subscritionName, messageId, null);
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
LOG.debug("Could not replay acknowledge for message '" + messageId
|
|
||||||
+ "'. Message may have already been acknowledged. reason: " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param messageId
|
|
||||||
* @param location
|
|
||||||
* @param key
|
|
||||||
*/
|
|
||||||
protected void acknowledge(MessageId messageId, RecordLocation location, SubscriptionKey key) {
|
|
||||||
synchronized (this) {
|
|
||||||
lastLocation = location;
|
|
||||||
ackedLastAckLocations.put(key, messageId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RecordLocation checkpoint() throws IOException {
|
|
||||||
|
|
||||||
final HashMap<SubscriptionKey, MessageId> cpAckedLastAckLocations;
|
|
||||||
|
|
||||||
// swap out the hash maps..
|
|
||||||
synchronized (this) {
|
|
||||||
cpAckedLastAckLocations = this.ackedLastAckLocations;
|
|
||||||
this.ackedLastAckLocations = new HashMap<SubscriptionKey, MessageId>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.checkpoint(new Callback() {
|
|
||||||
@Override
|
|
||||||
public void execute() throws Exception {
|
|
||||||
|
|
||||||
// Checkpoint the acknowledged messages.
|
|
||||||
Iterator<SubscriptionKey> iterator = cpAckedLastAckLocations.keySet().iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
SubscriptionKey subscriptionKey = iterator.next();
|
|
||||||
MessageId identity = cpAckedLastAckLocations.get(subscriptionKey);
|
|
||||||
MessageAck ack = new MessageAck();
|
|
||||||
ack.setMessageID(identity);
|
|
||||||
longTermStore.acknowledge(transactionTemplate.getContext(), subscriptionKey.clientId,
|
|
||||||
subscriptionKey.subscriptionName, identity, ack);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Returns the longTermStore.
|
|
||||||
*/
|
|
||||||
public TopicMessageStore getLongTermTopicMessageStore() {
|
|
||||||
return longTermStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteSubscription(String clientId, String subscriptionName) throws IOException {
|
|
||||||
longTermStore.deleteSubscription(clientId, subscriptionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SubscriptionInfo[] getAllSubscriptions() throws IOException {
|
|
||||||
return longTermStore.getAllSubscriptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMessageCount(String clientId, String subscriberName) throws IOException {
|
|
||||||
this.peristenceAdapter.checkpoint(true, true);
|
|
||||||
return longTermStore.getMessageCount(clientId, subscriberName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMessageSize(String clientId, String subscriberName) throws IOException {
|
|
||||||
this.peristenceAdapter.checkpoint(true, true);
|
|
||||||
return longTermStore.getMessageSize(clientId, subscriberName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resetBatching(String clientId, String subscriptionName) {
|
|
||||||
longTermStore.resetBatching(clientId, subscriptionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final MessageStoreSubscriptionStatistics stats = new MessageStoreSubscriptionStatistics(false);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MessageStoreSubscriptionStatistics getMessageStoreSubStatistics() {
|
|
||||||
return stats;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,350 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.store.journal;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import javax.transaction.xa.XAException;
|
|
||||||
import org.apache.activeio.journal.RecordLocation;
|
|
||||||
import org.apache.activemq.command.JournalTopicAck;
|
|
||||||
import org.apache.activemq.command.JournalTransaction;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.command.MessageAck;
|
|
||||||
import org.apache.activemq.command.TransactionId;
|
|
||||||
import org.apache.activemq.command.XATransactionId;
|
|
||||||
import org.apache.activemq.store.TransactionRecoveryListener;
|
|
||||||
import org.apache.activemq.store.TransactionStore;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public class JournalTransactionStore implements TransactionStore {
|
|
||||||
|
|
||||||
private final JournalPersistenceAdapter peristenceAdapter;
|
|
||||||
private final Map<Object, Tx> inflightTransactions = new LinkedHashMap<Object, Tx>();
|
|
||||||
private final Map<TransactionId, Tx> preparedTransactions = new LinkedHashMap<TransactionId, Tx>();
|
|
||||||
private boolean doingRecover;
|
|
||||||
|
|
||||||
public static class TxOperation {
|
|
||||||
|
|
||||||
static final byte ADD_OPERATION_TYPE = 0;
|
|
||||||
static final byte REMOVE_OPERATION_TYPE = 1;
|
|
||||||
static final byte ACK_OPERATION_TYPE = 3;
|
|
||||||
|
|
||||||
public byte operationType;
|
|
||||||
public JournalMessageStore store;
|
|
||||||
public Object data;
|
|
||||||
|
|
||||||
public TxOperation(byte operationType, JournalMessageStore store, Object data) {
|
|
||||||
this.operationType = operationType;
|
|
||||||
this.store = store;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Operations
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static class Tx {
|
|
||||||
|
|
||||||
private final RecordLocation location;
|
|
||||||
private final ArrayList<TxOperation> operations = new ArrayList<TxOperation>();
|
|
||||||
|
|
||||||
public Tx(RecordLocation location) {
|
|
||||||
this.location = location;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(JournalMessageStore store, Message msg) {
|
|
||||||
operations.add(new TxOperation(TxOperation.ADD_OPERATION_TYPE, store, msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(JournalMessageStore store, MessageAck ack) {
|
|
||||||
operations.add(new TxOperation(TxOperation.REMOVE_OPERATION_TYPE, store, ack));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(JournalTopicMessageStore store, JournalTopicAck ack) {
|
|
||||||
operations.add(new TxOperation(TxOperation.ACK_OPERATION_TYPE, store, ack));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Message[] getMessages() {
|
|
||||||
ArrayList<Object> list = new ArrayList<Object>();
|
|
||||||
for (Iterator<TxOperation> iter = operations.iterator(); iter.hasNext();) {
|
|
||||||
TxOperation op = iter.next();
|
|
||||||
if (op.operationType == TxOperation.ADD_OPERATION_TYPE) {
|
|
||||||
list.add(op.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Message rc[] = new Message[list.size()];
|
|
||||||
list.toArray(rc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageAck[] getAcks() {
|
|
||||||
ArrayList<Object> list = new ArrayList<Object>();
|
|
||||||
for (Iterator<TxOperation> iter = operations.iterator(); iter.hasNext();) {
|
|
||||||
TxOperation op = iter.next();
|
|
||||||
if (op.operationType == TxOperation.REMOVE_OPERATION_TYPE) {
|
|
||||||
list.add(op.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MessageAck rc[] = new MessageAck[list.size()];
|
|
||||||
list.toArray(rc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<TxOperation> getOperations() {
|
|
||||||
return operations;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public JournalTransactionStore(JournalPersistenceAdapter adapter) {
|
|
||||||
this.peristenceAdapter = adapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws IOException
|
|
||||||
* @see org.apache.activemq.store.TransactionStore#prepare(TransactionId)
|
|
||||||
*/
|
|
||||||
public void prepare(TransactionId txid) throws IOException {
|
|
||||||
Tx tx = null;
|
|
||||||
synchronized (inflightTransactions) {
|
|
||||||
tx = inflightTransactions.remove(txid);
|
|
||||||
}
|
|
||||||
if (tx == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
peristenceAdapter.writeCommand(new JournalTransaction(JournalTransaction.XA_PREPARE, txid, false),
|
|
||||||
true);
|
|
||||||
synchronized (preparedTransactions) {
|
|
||||||
preparedTransactions.put(txid, tx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws IOException
|
|
||||||
* @see org.apache.activemq.store.TransactionStore#prepare(TransactionId)
|
|
||||||
*/
|
|
||||||
public void replayPrepare(TransactionId txid) throws IOException {
|
|
||||||
Tx tx = null;
|
|
||||||
synchronized (inflightTransactions) {
|
|
||||||
tx = inflightTransactions.remove(txid);
|
|
||||||
}
|
|
||||||
if (tx == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
synchronized (preparedTransactions) {
|
|
||||||
preparedTransactions.put(txid, tx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Tx getTx(Object txid, RecordLocation location) {
|
|
||||||
Tx tx = null;
|
|
||||||
synchronized (inflightTransactions) {
|
|
||||||
tx = inflightTransactions.get(txid);
|
|
||||||
}
|
|
||||||
if (tx == null) {
|
|
||||||
tx = new Tx(location);
|
|
||||||
inflightTransactions.put(txid, tx);
|
|
||||||
}
|
|
||||||
return tx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws XAException
|
|
||||||
* @see org.apache.activemq.store.TransactionStore#commit(org.apache.activemq.service.Transaction)
|
|
||||||
*/
|
|
||||||
public void commit(TransactionId txid, boolean wasPrepared, Runnable preCommit,Runnable postCommit) throws IOException {
|
|
||||||
Tx tx;
|
|
||||||
if (preCommit != null) {
|
|
||||||
preCommit.run();
|
|
||||||
}
|
|
||||||
if (wasPrepared) {
|
|
||||||
synchronized (preparedTransactions) {
|
|
||||||
tx = preparedTransactions.remove(txid);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (inflightTransactions) {
|
|
||||||
tx = inflightTransactions.remove(txid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tx == null) {
|
|
||||||
if (postCommit != null) {
|
|
||||||
postCommit.run();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (txid.isXATransaction()) {
|
|
||||||
peristenceAdapter.writeCommand(new JournalTransaction(JournalTransaction.XA_COMMIT, txid,
|
|
||||||
wasPrepared), true);
|
|
||||||
} else {
|
|
||||||
peristenceAdapter.writeCommand(new JournalTransaction(JournalTransaction.LOCAL_COMMIT, txid,
|
|
||||||
wasPrepared), true);
|
|
||||||
}
|
|
||||||
if (postCommit != null) {
|
|
||||||
postCommit.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws XAException
|
|
||||||
* @see org.apache.activemq.store.TransactionStore#commit(org.apache.activemq.service.Transaction)
|
|
||||||
*/
|
|
||||||
public Tx replayCommit(TransactionId txid, boolean wasPrepared) throws IOException {
|
|
||||||
if (wasPrepared) {
|
|
||||||
synchronized (preparedTransactions) {
|
|
||||||
return preparedTransactions.remove(txid);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (inflightTransactions) {
|
|
||||||
return inflightTransactions.remove(txid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws IOException
|
|
||||||
* @see org.apache.activemq.store.TransactionStore#rollback(TransactionId)
|
|
||||||
*/
|
|
||||||
public void rollback(TransactionId txid) throws IOException {
|
|
||||||
Tx tx = null;
|
|
||||||
synchronized (inflightTransactions) {
|
|
||||||
tx = inflightTransactions.remove(txid);
|
|
||||||
}
|
|
||||||
if (tx != null) {
|
|
||||||
synchronized (preparedTransactions) {
|
|
||||||
tx = preparedTransactions.remove(txid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tx != null) {
|
|
||||||
if (txid.isXATransaction()) {
|
|
||||||
peristenceAdapter.writeCommand(new JournalTransaction(JournalTransaction.XA_ROLLBACK, txid,
|
|
||||||
false), true);
|
|
||||||
} else {
|
|
||||||
peristenceAdapter.writeCommand(new JournalTransaction(JournalTransaction.LOCAL_ROLLBACK,
|
|
||||||
txid, false), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws IOException
|
|
||||||
* @see org.apache.activemq.store.TransactionStore#rollback(TransactionId)
|
|
||||||
*/
|
|
||||||
public void replayRollback(TransactionId txid) throws IOException {
|
|
||||||
boolean inflight = false;
|
|
||||||
synchronized (inflightTransactions) {
|
|
||||||
inflight = inflightTransactions.remove(txid) != null;
|
|
||||||
}
|
|
||||||
if (inflight) {
|
|
||||||
synchronized (preparedTransactions) {
|
|
||||||
preparedTransactions.remove(txid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void recover(TransactionRecoveryListener listener) throws IOException {
|
|
||||||
// All the in-flight transactions get rolled back..
|
|
||||||
synchronized (inflightTransactions) {
|
|
||||||
inflightTransactions.clear();
|
|
||||||
}
|
|
||||||
this.doingRecover = true;
|
|
||||||
try {
|
|
||||||
Map<TransactionId, Tx> txs = null;
|
|
||||||
synchronized (preparedTransactions) {
|
|
||||||
txs = new LinkedHashMap<TransactionId, Tx>(preparedTransactions);
|
|
||||||
}
|
|
||||||
for (Iterator<TransactionId> iter = txs.keySet().iterator(); iter.hasNext();) {
|
|
||||||
Object txid = iter.next();
|
|
||||||
Tx tx = txs.get(txid);
|
|
||||||
listener.recover((XATransactionId)txid, tx.getMessages(), tx.getAcks());
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
this.doingRecover = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param message
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
void addMessage(JournalMessageStore store, Message message, RecordLocation location) throws IOException {
|
|
||||||
Tx tx = getTx(message.getTransactionId(), location);
|
|
||||||
tx.add(store, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ack
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public void removeMessage(JournalMessageStore store, MessageAck ack, RecordLocation location)
|
|
||||||
throws IOException {
|
|
||||||
Tx tx = getTx(ack.getTransactionId(), location);
|
|
||||||
tx.add(store, ack);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void acknowledge(JournalTopicMessageStore store, JournalTopicAck ack, RecordLocation location) {
|
|
||||||
Tx tx = getTx(ack.getTransactionId(), location);
|
|
||||||
tx.add(store, ack);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RecordLocation checkpoint() throws IOException {
|
|
||||||
// Nothing really to checkpoint.. since, we don't
|
|
||||||
// checkpoint tx operations in to long term store until they are
|
|
||||||
// committed.
|
|
||||||
// But we keep track of the first location of an operation
|
|
||||||
// that was associated with an active tx. The journal can not
|
|
||||||
// roll over active tx records.
|
|
||||||
RecordLocation rc = null;
|
|
||||||
synchronized (inflightTransactions) {
|
|
||||||
for (Iterator<Tx> iter = inflightTransactions.values().iterator(); iter.hasNext();) {
|
|
||||||
Tx tx = iter.next();
|
|
||||||
RecordLocation location = tx.location;
|
|
||||||
if (rc == null || rc.compareTo(location) < 0) {
|
|
||||||
rc = location;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
synchronized (preparedTransactions) {
|
|
||||||
for (Iterator<Tx> iter = preparedTransactions.values().iterator(); iter.hasNext();) {
|
|
||||||
Tx tx = iter.next();
|
|
||||||
RecordLocation location = tx.location;
|
|
||||||
if (rc == null || rc.compareTo(location) < 0) {
|
|
||||||
rc = location;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDoingRecover() {
|
|
||||||
return doingRecover;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Message persistence using a high performance transaction log via the Journal interface.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -39,11 +39,6 @@
|
||||||
<groupId>org.apache.activemq</groupId>
|
<groupId>org.apache.activemq</groupId>
|
||||||
<artifactId>activemq-broker</artifactId>
|
<artifactId>activemq-broker</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.activemq.protobuf</groupId>
|
<groupId>org.apache.activemq.protobuf</groupId>
|
||||||
<artifactId>activemq-protobuf</artifactId>
|
<artifactId>activemq-protobuf</artifactId>
|
||||||
|
|
|
@ -56,7 +56,6 @@
|
||||||
<bundle dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.xpp3/${xpp3-bundle-version}</bundle>
|
<bundle dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.xpp3/${xpp3-bundle-version}</bundle>
|
||||||
<bundle dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.xstream/${xstream-bundle-version}</bundle>
|
<bundle dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.xstream/${xstream-bundle-version}</bundle>
|
||||||
<bundle dependency="true">mvn:org.apache.aries/org.apache.aries.util/${aries-version}</bundle>
|
<bundle dependency="true">mvn:org.apache.aries/org.apache.aries.util/${aries-version}</bundle>
|
||||||
<bundle dependency="true">mvn:org.apache.activemq/activeio-core/${activeio-version}</bundle>
|
|
||||||
<bundle dependency="true">mvn:org.codehaus.jettison/jettison/${jettison-version}</bundle>
|
<bundle dependency="true">mvn:org.codehaus.jettison/jettison/${jettison-version}</bundle>
|
||||||
<bundle dependency="true">mvn:com.fasterxml.jackson.core/jackson-core/${jackson-version}</bundle>
|
<bundle dependency="true">mvn:com.fasterxml.jackson.core/jackson-core/${jackson-version}</bundle>
|
||||||
<bundle dependency="true">mvn:com.fasterxml.jackson.core/jackson-databind/${jackson-version}</bundle>
|
<bundle dependency="true">mvn:com.fasterxml.jackson.core/jackson-databind/${jackson-version}</bundle>
|
||||||
|
|
|
@ -40,11 +40,6 @@
|
||||||
<artifactId>activemq-broker</artifactId>
|
<artifactId>activemq-broker</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.activemq.protobuf</groupId>
|
<groupId>org.apache.activemq.protobuf</groupId>
|
||||||
<artifactId>activemq-protobuf</artifactId>
|
<artifactId>activemq-protobuf</artifactId>
|
||||||
|
|
|
@ -174,7 +174,6 @@
|
||||||
javax.resource*;resolution:=optional,
|
javax.resource*;resolution:=optional,
|
||||||
javax.servlet*;resolution:=optional,
|
javax.servlet*;resolution:=optional,
|
||||||
com.thoughtworks.xstream*;resolution:=optional,
|
com.thoughtworks.xstream*;resolution:=optional,
|
||||||
org.apache.activeio*;resolution:=optional,
|
|
||||||
org.apache.camel*;version="${camel-version-range}";resolution:=optional,
|
org.apache.camel*;version="${camel-version-range}";resolution:=optional,
|
||||||
org.apache.camel.spring.handler;version="${camel-version-range}";resolution:=optional,
|
org.apache.camel.spring.handler;version="${camel-version-range}";resolution:=optional,
|
||||||
org.apache.camel.spring.xml.handler;version="${camel-version-range}";resolution:=optional,
|
org.apache.camel.spring.xml.handler;version="${camel-version-range}";resolution:=optional,
|
||||||
|
|
|
@ -69,11 +69,6 @@
|
||||||
<artifactId>activemq-kahadb-store</artifactId>
|
<artifactId>activemq-kahadb-store</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- add the optional replication deps -->
|
<!-- add the optional replication deps -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.store;
|
|
||||||
|
|
||||||
import org.apache.activemq.store.journal.JournalPersistenceAdapterFactory;
|
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a default persistence model using the Journal and JDBC
|
|
||||||
*
|
|
||||||
* @org.apache.xbean.XBean element="journaledJDBC"
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class PersistenceAdapterFactoryBean extends JournalPersistenceAdapterFactory implements FactoryBean {
|
|
||||||
|
|
||||||
private PersistenceAdapter persistenceAdaptor;
|
|
||||||
|
|
||||||
public Object getObject() throws Exception {
|
|
||||||
if (persistenceAdaptor == null) {
|
|
||||||
persistenceAdaptor = createPersistenceAdapter();
|
|
||||||
}
|
|
||||||
return persistenceAdaptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class getObjectType() {
|
|
||||||
return PersistenceAdapter.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSingleton() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -42,10 +42,6 @@
|
||||||
<groupId>org.apache.activemq</groupId>
|
<groupId>org.apache.activemq</groupId>
|
||||||
<artifactId>activemq-console</artifactId>
|
<artifactId>activemq-console</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.activemq</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.derby</groupId>
|
<groupId>org.apache.derby</groupId>
|
||||||
<artifactId>derby</artifactId>
|
<artifactId>derby</artifactId>
|
||||||
|
|
|
@ -43,10 +43,6 @@
|
||||||
<groupId>org.apache.activemq</groupId>
|
<groupId>org.apache.activemq</groupId>
|
||||||
<artifactId>activemq-console</artifactId>
|
<artifactId>activemq-console</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.activemq</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.derby</groupId>
|
<groupId>org.apache.derby</groupId>
|
||||||
<artifactId>derby</artifactId>
|
<artifactId>derby</artifactId>
|
||||||
|
|
|
@ -46,10 +46,6 @@
|
||||||
<groupId>org.apache.activemq</groupId>
|
<groupId>org.apache.activemq</groupId>
|
||||||
<artifactId>activemq-console</artifactId>
|
<artifactId>activemq-console</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.activemq</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.derby</groupId>
|
<groupId>org.apache.derby</groupId>
|
||||||
<artifactId>derby</artifactId>
|
<artifactId>derby</artifactId>
|
||||||
|
|
|
@ -74,11 +74,6 @@
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.fusesource.mqtt-client</groupId>
|
<groupId>org.fusesource.mqtt-client</groupId>
|
||||||
<artifactId>mqtt-client</artifactId>
|
<artifactId>mqtt-client</artifactId>
|
||||||
|
|
|
@ -50,7 +50,6 @@ import org.apache.activemq.store.PersistenceAdapter;
|
||||||
import org.apache.activemq.store.jdbc.DefaultDatabaseLocker;
|
import org.apache.activemq.store.jdbc.DefaultDatabaseLocker;
|
||||||
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
||||||
import org.apache.activemq.store.jdbc.adapter.TransactDatabaseLocker;
|
import org.apache.activemq.store.jdbc.adapter.TransactDatabaseLocker;
|
||||||
import org.apache.activemq.store.journal.JournalPersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.memory.MemoryPersistenceAdapter;
|
import org.apache.activemq.store.memory.MemoryPersistenceAdapter;
|
||||||
import org.apache.activemq.transport.tcp.TcpTransportServer;
|
import org.apache.activemq.transport.tcp.TcpTransportServer;
|
||||||
import org.apache.activemq.usage.SystemUsage;
|
import org.apache.activemq.usage.SystemUsage;
|
||||||
|
@ -87,43 +86,6 @@ public class ConfigTest {
|
||||||
* for succeeding creation. It uses the first created directory as the root.
|
* for succeeding creation. It uses the first created directory as the root.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* This tests creating a journal persistence adapter using the persistence
|
|
||||||
* adapter factory bean
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testJournaledJDBCConfig() throws Exception {
|
|
||||||
|
|
||||||
File journalFile = new File(JOURNAL_ROOT + "testJournaledJDBCConfig/journal");
|
|
||||||
recursiveDelete(journalFile);
|
|
||||||
|
|
||||||
File derbyFile = new File(DERBY_ROOT + "testJournaledJDBCConfig/derbydb"); // Default
|
|
||||||
recursiveDelete(derbyFile);
|
|
||||||
|
|
||||||
BrokerService broker;
|
|
||||||
broker = createBroker(new FileSystemResource(CONF_ROOT + "journaledjdbc-example.xml"));
|
|
||||||
try {
|
|
||||||
assertEquals("Broker Config Error (brokerName)", "brokerJournaledJDBCConfigTest", broker.getBrokerName());
|
|
||||||
|
|
||||||
PersistenceAdapter adapter = broker.getPersistenceAdapter();
|
|
||||||
|
|
||||||
assertTrue("Should have created a journal persistence adapter", adapter instanceof JournalPersistenceAdapter);
|
|
||||||
assertTrue("Should have created a derby directory at " + derbyFile.getAbsolutePath(), derbyFile.exists());
|
|
||||||
assertTrue("Should have created a journal directory at " + journalFile.getAbsolutePath(), journalFile.exists());
|
|
||||||
|
|
||||||
// Check persistence factory configurations
|
|
||||||
broker.getPersistenceAdapter();
|
|
||||||
|
|
||||||
assertTrue(broker.getSystemUsage().getStoreUsage().getStore() instanceof JournalPersistenceAdapter);
|
|
||||||
|
|
||||||
LOG.info("Success");
|
|
||||||
} finally {
|
|
||||||
if (broker != null) {
|
|
||||||
broker.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testJdbcLockConfigOverride() throws Exception {
|
public void testJdbcLockConfigOverride() throws Exception {
|
||||||
|
|
||||||
|
@ -291,32 +253,6 @@ public class ConfigTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This tests creating a journal persistence adapter using xbeans-spring
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testJournalConfig() throws Exception {
|
|
||||||
File journalFile = new File(JOURNAL_ROOT + "testJournalConfig/journal");
|
|
||||||
recursiveDelete(journalFile);
|
|
||||||
|
|
||||||
BrokerService broker;
|
|
||||||
broker = createBroker(new FileSystemResource(CONF_ROOT + "journal-example.xml"));
|
|
||||||
try {
|
|
||||||
assertEquals("Broker Config Error (brokerName)", "brokerJournalConfigTest", broker.getBrokerName());
|
|
||||||
|
|
||||||
PersistenceAdapter adapter = broker.getPersistenceAdapter();
|
|
||||||
|
|
||||||
assertTrue("Should have created a journal persistence adapter", adapter instanceof JournalPersistenceAdapter);
|
|
||||||
assertTrue("Should have created a journal directory at " + journalFile.getAbsolutePath(), journalFile.exists());
|
|
||||||
|
|
||||||
LOG.info("Success");
|
|
||||||
} finally {
|
|
||||||
if (broker != null) {
|
|
||||||
broker.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This tests creating a memory persistence adapter using xbeans-spring
|
* This tests creating a memory persistence adapter using xbeans-spring
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -61,13 +61,6 @@ public class InactiveDurableTopicTest extends TestCase {
|
||||||
broker = new BrokerService();
|
broker = new BrokerService();
|
||||||
|
|
||||||
//broker.setPersistenceAdapter(new KahaPersistenceAdapter());
|
//broker.setPersistenceAdapter(new KahaPersistenceAdapter());
|
||||||
/*
|
|
||||||
* JournalPersistenceAdapterFactory factory = new
|
|
||||||
* JournalPersistenceAdapterFactory();
|
|
||||||
* factory.setDataDirectoryFile(broker.getDataDirectory());
|
|
||||||
* factory.setTaskRunnerFactory(broker.getTaskRunnerFactory());
|
|
||||||
* factory.setUseJournal(false); broker.setPersistenceFactory(factory);
|
|
||||||
*/
|
|
||||||
broker.addConnector(ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL);
|
broker.addConnector(ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL);
|
||||||
broker.start();
|
broker.start();
|
||||||
connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_BROKER_URL);
|
connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_BROKER_URL);
|
||||||
|
|
|
@ -58,13 +58,7 @@ public class InactiveQueueTest extends TestCase {
|
||||||
|
|
||||||
// broker.setPersistenceAdapter(new KahaPersistenceAdapter(new File
|
// broker.setPersistenceAdapter(new KahaPersistenceAdapter(new File
|
||||||
// ("TEST_STUFD")));
|
// ("TEST_STUFD")));
|
||||||
/*
|
|
||||||
* JournalPersistenceAdapterFactory factory = new
|
|
||||||
* JournalPersistenceAdapterFactory();
|
|
||||||
* factory.setDataDirectoryFile(broker.getDataDirectory());
|
|
||||||
* factory.setTaskRunnerFactory(broker.getTaskRunnerFactory());
|
|
||||||
* factory.setUseJournal(false); broker.setPersistenceFactory(factory);
|
|
||||||
*/
|
|
||||||
broker.addConnector(ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL);
|
broker.addConnector(ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL);
|
||||||
broker.start();
|
broker.start();
|
||||||
connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_BROKER_URL);
|
connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_BROKER_URL);
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.journal.JournalPersistenceAdapterFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class JournalDurableSubscriptionTest extends DurableSubscriptionTestSupport {
|
|
||||||
|
|
||||||
protected PersistenceAdapter createPersistenceAdapter() throws IOException {
|
|
||||||
File dataDir = new File("target/test-data/durableJournal");
|
|
||||||
JournalPersistenceAdapterFactory factory = new JournalPersistenceAdapterFactory();
|
|
||||||
factory.setDataDirectoryFile(dataDir);
|
|
||||||
factory.setUseJournal(true);
|
|
||||||
factory.setJournalLogFileSize(1024 * 64);
|
|
||||||
return factory.createPersistenceAdapter();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.xbean;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerFactory;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.store.PersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class JDBCPersistenceXBeanConfigTest extends TestCase {
|
|
||||||
|
|
||||||
protected BrokerService brokerService;
|
|
||||||
|
|
||||||
public void testConfiguredCorrectly() throws Exception {
|
|
||||||
|
|
||||||
PersistenceAdapter persistenceAdapter = brokerService.getPersistenceAdapter();
|
|
||||||
assertNotNull(persistenceAdapter);
|
|
||||||
assertTrue(persistenceAdapter instanceof JDBCPersistenceAdapter);
|
|
||||||
|
|
||||||
JDBCPersistenceAdapter jpa = (JDBCPersistenceAdapter)persistenceAdapter;
|
|
||||||
assertEquals("BROKER1.", jpa.getStatements().getTablePrefix());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
brokerService = createBroker();
|
|
||||||
brokerService.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
if (brokerService != null) {
|
|
||||||
brokerService.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
String uri = "org/apache/activemq/xbean/jdbc-persistence-test.xml";
|
|
||||||
return BrokerFactory.createBroker(new URI("xbean:" + uri));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -32,10 +32,13 @@
|
||||||
|
|
||||||
<broker useJmx="true" deleteAllMessagesOnStartup="true" systemUsage="#memory-manager" xmlns="http://activemq.apache.org/schema/core">
|
<broker useJmx="true" deleteAllMessagesOnStartup="true" systemUsage="#memory-manager" xmlns="http://activemq.apache.org/schema/core">
|
||||||
|
|
||||||
<persistenceFactory>
|
<persistenceAdapter>
|
||||||
<journalPersistenceAdapterFactory
|
<kahaDB directory="target/activemq-data/loadtester/kahadb"
|
||||||
useQuickJournal="false" journalLogFiles="2" dataDirectory="loadtest"/>
|
cleanupInterval="300000" checkpointInterval="50000"
|
||||||
</persistenceFactory>
|
journalMaxWriteBatchSize="62k"
|
||||||
|
journalMaxFileLength="1g"
|
||||||
|
indexCacheSize="100000" indexWriteBatchSize="100000"/>
|
||||||
|
</persistenceAdapter>
|
||||||
|
|
||||||
<transportConnectors>
|
<transportConnectors>
|
||||||
<transportConnector uri="tcp://localhost:0"/>
|
<transportConnector uri="tcp://localhost:0"/>
|
||||||
|
@ -43,19 +46,5 @@
|
||||||
|
|
||||||
</broker>
|
</broker>
|
||||||
|
|
||||||
<!-- The Derby Datasource that will be used by the Broker -->
|
|
||||||
<!--
|
|
||||||
<bean id="postgres-ds" class="org.postgresql.ds.PGPoolingDataSource" destroy-method="close">
|
|
||||||
<property name="serverName" value="localhost"/>
|
|
||||||
<property name="databaseName" value="activemq"/>
|
|
||||||
<property name="portNumber" value="0"/>
|
|
||||||
<property name="user" value="activemq"/>
|
|
||||||
<property name="password" value="activemq"/>
|
|
||||||
<property name="dataSourceName" value="postgres"/>
|
|
||||||
<property name="initialConnections" value="1"/>
|
|
||||||
<property name="maxConnections" value="10"/>
|
|
||||||
</bean>
|
|
||||||
-->
|
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
<!-- END SNIPPET: xbean -->
|
<!-- END SNIPPET: xbean -->
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<beans
|
|
||||||
xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:amq="http://activemq.apache.org/schema/core"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
|
|
||||||
|
|
||||||
<amq:broker brokerName="brokerJournalConfigTest" persistent="true" useShutdownHook="false" deleteAllMessagesOnStartup="true">
|
|
||||||
|
|
||||||
<amq:persistenceAdapter>
|
|
||||||
<amq:journalPersistenceAdapter>
|
|
||||||
<amq:journal>
|
|
||||||
<ref bean="myJournalImpl"/>
|
|
||||||
</amq:journal>
|
|
||||||
|
|
||||||
<amq:persistenceAdapter>
|
|
||||||
<amq:memoryPersistenceAdapter createTransactionStore="true"/>
|
|
||||||
</amq:persistenceAdapter>
|
|
||||||
|
|
||||||
<amq:taskRunnerFactory>
|
|
||||||
<bean id="myTaskRunnerFactory" class="org.apache.activemq.thread.TaskRunnerFactory"/>
|
|
||||||
</amq:taskRunnerFactory>
|
|
||||||
</amq:journalPersistenceAdapter>
|
|
||||||
</amq:persistenceAdapter>
|
|
||||||
|
|
||||||
<amq:transportConnectors>
|
|
||||||
<amq:transportConnector uri="tcp://localhost:61635"/>
|
|
||||||
</amq:transportConnectors>
|
|
||||||
|
|
||||||
</amq:broker>
|
|
||||||
|
|
||||||
<!-- The journal implementation that will be used -->
|
|
||||||
<bean id="myJournalImpl" class="org.apache.activeio.journal.active.JournalImpl">
|
|
||||||
<constructor-arg index="0">
|
|
||||||
<bean id="myFile" class="java.io.File">
|
|
||||||
<constructor-arg index="0">
|
|
||||||
<value>target/test-data/testJournalConfig/journal</value>
|
|
||||||
</constructor-arg>
|
|
||||||
</bean>
|
|
||||||
</constructor-arg>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
</beans>
|
|
|
@ -1,36 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<beans
|
|
||||||
xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:amq="http://activemq.apache.org/schema/core"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
|
|
||||||
|
|
||||||
<amq:broker brokerName="brokerJournaledJDBCConfigTest" persistent="true" useShutdownHook="false" deleteAllMessagesOnStartup="true">
|
|
||||||
|
|
||||||
<amq:persistenceFactory>
|
|
||||||
<amq:journalPersistenceAdapterFactory journalLogFiles="4" journalLogFileSize="32768" dataDirectory="target/test-data/testJournaledJDBCConfig" />
|
|
||||||
</amq:persistenceFactory>
|
|
||||||
<amq:transportConnectors>
|
|
||||||
<amq:transportConnector uri="tcp://localhost:61635"/>
|
|
||||||
</amq:transportConnectors>
|
|
||||||
|
|
||||||
</amq:broker>
|
|
||||||
</beans>
|
|
|
@ -26,13 +26,17 @@
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
||||||
|
|
||||||
<!-- Default configuration -->
|
<!-- Default configuration -->
|
||||||
<broker id="default" useJmx="false" xmlns="http://activemq.apache.org/schema/core">
|
<broker id="default" useJmx="false" xmlns="http://activemq.apache.org/schema/core" deleteAllMessagesOnStartup="true">
|
||||||
|
|
||||||
<persistenceFactory>
|
<persistenceAdapter>
|
||||||
<journalPersistenceAdapterFactory journalLogFiles="2" dataDirectory="target/foo"/>
|
<kahaDB directory="target/activemq-data/command/kahadb"
|
||||||
</persistenceFactory>
|
cleanupInterval="300000" checkpointInterval="50000"
|
||||||
|
journalMaxWriteBatchSize="62k"
|
||||||
|
journalMaxFileLength="1g"
|
||||||
|
indexCacheSize="100000" indexWriteBatchSize="100000"/>
|
||||||
|
</persistenceAdapter>
|
||||||
|
|
||||||
<transportConnectors>
|
<transportConnectors>
|
||||||
<transportConnector uri="tcp://localhost:61616" />
|
<transportConnector uri="tcp://localhost:61616" />
|
||||||
</transportConnectors>
|
</transportConnectors>
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
|
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
|
||||||
|
|
||||||
<broker useJmx="true" xmlns="http://activemq.apache.org/schema/core">
|
<broker useJmx="true" xmlns="http://activemq.apache.org/schema/core" deleteAllMessagesOnStartup="true">
|
||||||
|
|
||||||
<!-- In ActiveMQ 4, you can setup destination policies -->
|
<!-- In ActiveMQ 4, you can setup destination policies -->
|
||||||
<destinationPolicy>
|
<destinationPolicy>
|
||||||
<policyMap><policyEntries>
|
<policyMap><policyEntries>
|
||||||
|
|
||||||
|
@ -55,13 +55,13 @@
|
||||||
-->
|
-->
|
||||||
</networkConnectors>
|
</networkConnectors>
|
||||||
|
|
||||||
<persistenceFactory>
|
<persistenceAdapter>
|
||||||
<journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="../data"/>
|
<kahaDB directory="target/activemq-data/usecases/kahadb"
|
||||||
<!-- To use a different datasource, use the following syntax : -->
|
cleanupInterval="300000" checkpointInterval="50000"
|
||||||
<!--
|
journalMaxWriteBatchSize="62k"
|
||||||
<journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="../data" dataSource="#postgres-ds"/>
|
journalMaxFileLength="1g"
|
||||||
-->
|
indexCacheSize="100000" indexWriteBatchSize="100000"/>
|
||||||
</persistenceFactory>
|
</persistenceAdapter>
|
||||||
|
|
||||||
<transportConnectors>
|
<transportConnectors>
|
||||||
<transportConnector uri="tcp://localhost:61616" discoveryUri="multicast://default"/>
|
<transportConnector uri="tcp://localhost:61616" discoveryUri="multicast://default"/>
|
||||||
|
@ -69,40 +69,5 @@
|
||||||
|
|
||||||
</broker>
|
</broker>
|
||||||
|
|
||||||
<!-- This xbean configuration file supports all the standard spring xml configuration options -->
|
|
||||||
|
|
||||||
<!-- Postgres DataSource Sample Setup -->
|
|
||||||
<!--
|
|
||||||
<bean id="postgres-ds" class="org.postgresql.ds.PGPoolingDataSource" destroy-method="close">
|
|
||||||
<property name="serverName" value="localhost"/>
|
|
||||||
<property name="databaseName" value="activemq"/>
|
|
||||||
<property name="portNumber" value="0"/>
|
|
||||||
<property name="user" value="activemq"/>
|
|
||||||
<property name="password" value="activemq"/>
|
|
||||||
<property name="dataSourceName" value="postgres"/>
|
|
||||||
<property name="initialConnections" value="1"/>
|
|
||||||
<property name="maxConnections" value="10"/>
|
|
||||||
</bean>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- MySql DataSource Sample Setup -->
|
|
||||||
<!--
|
|
||||||
<bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
|
|
||||||
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
|
|
||||||
<property name="url" value="jdbc:mysql://localhost/activemq"/>
|
|
||||||
<property name="username" value="activemq"/>
|
|
||||||
<property name="password" value="activemq"/>
|
|
||||||
<property name="poolPreparedStatements" value="true"/>
|
|
||||||
</bean>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- Embedded Derby DataSource Sample Setup -->
|
|
||||||
<!--
|
|
||||||
<bean id="derby-ds" class="org.apache.derby.jdbc.EmbeddedDataSource">
|
|
||||||
<property name="databaseName" value="derbydb"/>
|
|
||||||
<property name="createDatabase" value="create"/>
|
|
||||||
</bean>
|
|
||||||
-->
|
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
<!-- END SNIPPET: xbean -->
|
<!-- END SNIPPET: xbean -->
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
||||||
|
|
||||||
<broker useJmx="true" xmlns="http://activemq.apache.org/schema/core">
|
<broker useJmx="true" xmlns="http://activemq.apache.org/schema/core" deleteAllMessagesOnStartup="true">
|
||||||
|
|
||||||
<networkConnectors>
|
<networkConnectors>
|
||||||
<!--
|
<!--
|
||||||
|
@ -36,14 +36,13 @@
|
||||||
-->
|
-->
|
||||||
</networkConnectors>
|
</networkConnectors>
|
||||||
|
|
||||||
<persistenceFactory>
|
<persistenceAdapter>
|
||||||
<journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="${basedir}/target" />
|
<kahaDB directory="target/activemq-data/xbean/kahadb"
|
||||||
|
cleanupInterval="300000" checkpointInterval="50000"
|
||||||
<!-- To use a different dataSource, use the following syntax : -->
|
journalMaxWriteBatchSize="62k"
|
||||||
<!--
|
journalMaxFileLength="1g"
|
||||||
<journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="${basedir}/activemq-data" dataSource="#mysql-ds"/>
|
indexCacheSize="100000" indexWriteBatchSize="100000"/>
|
||||||
-->
|
</persistenceAdapter>
|
||||||
</persistenceFactory>
|
|
||||||
|
|
||||||
<transportConnectors>
|
<transportConnectors>
|
||||||
<transportConnector uri="tcp://localhost:61636" />
|
<transportConnector uri="tcp://localhost:61636" />
|
||||||
|
@ -51,15 +50,5 @@
|
||||||
|
|
||||||
</broker>
|
</broker>
|
||||||
|
|
||||||
<!-- MySql DataSource Sample Setup -->
|
|
||||||
<!--
|
|
||||||
<bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
|
|
||||||
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
|
|
||||||
<property name="url" value="jdbc:mysql://localhost/activemq?relaxAutoCommit=true"/>
|
|
||||||
<property name="username" value="activemq"/>
|
|
||||||
<property name="password" value="activemq"/>
|
|
||||||
<property name="poolPreparedStatements" value="true"/>
|
|
||||||
</bean>
|
|
||||||
-->
|
|
||||||
</beans>
|
</beans>
|
||||||
<!-- END SNIPPET: example -->
|
<!-- END SNIPPET: example -->
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
||||||
|
|
||||||
<!-- for easier integration with the JUnit tests, lets not start the broker when the ApplicationContext starts -->
|
<!-- for easier integration with the JUnit tests, lets not start the broker when the ApplicationContext starts -->
|
||||||
<broker useJmx="true" start="false" xmlns="http://activemq.apache.org/schema/core">
|
<broker useJmx="true" start="false" xmlns="http://activemq.apache.org/schema/core" deleteAllMessagesOnStartup="true">
|
||||||
<destinationPolicy>
|
<destinationPolicy>
|
||||||
<policyMap>
|
<policyMap>
|
||||||
<policyEntries>
|
<policyEntries>
|
||||||
|
@ -43,14 +43,17 @@
|
||||||
</policyMap>
|
</policyMap>
|
||||||
</destinationPolicy>
|
</destinationPolicy>
|
||||||
|
|
||||||
|
<persistenceAdapter>
|
||||||
<persistenceFactory>
|
<kahaDB directory="target/activemq-data/xbean-2/kahadb"
|
||||||
<journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="${basedir}/target/data" />
|
cleanupInterval="300000" checkpointInterval="50000"
|
||||||
</persistenceFactory>
|
journalMaxWriteBatchSize="62k"
|
||||||
|
journalMaxFileLength="1g"
|
||||||
|
indexCacheSize="100000" indexWriteBatchSize="100000"/>
|
||||||
|
</persistenceAdapter>
|
||||||
|
|
||||||
<transportConnectors>
|
<transportConnectors>
|
||||||
<transportConnector uri="tcp://localhost:61616" />
|
<transportConnector uri="tcp://localhost:61616" />
|
||||||
</transportConnectors>
|
</transportConnectors>
|
||||||
|
|
||||||
</broker>
|
</broker>
|
||||||
</beans>
|
</beans>
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- this file can only be parsed using the xbean-spring library -->
|
|
||||||
<!-- START SNIPPET: xbean -->
|
|
||||||
<beans
|
|
||||||
xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:amq="http://activemq.apache.org/schema/core"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
|
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
|
||||||
|
|
||||||
<broker useJmx="false" xmlns="http://activemq.apache.org/schema/core">
|
|
||||||
|
|
||||||
<persistenceFactory>
|
|
||||||
<journalPersistenceAdapterFactory useJournal="false">
|
|
||||||
<statements>
|
|
||||||
<statements tablePrefix="BROKER1."/>
|
|
||||||
</statements>
|
|
||||||
</journalPersistenceAdapterFactory>
|
|
||||||
</persistenceFactory>
|
|
||||||
|
|
||||||
</broker>
|
|
||||||
|
|
||||||
</beans>
|
|
||||||
<!-- END SNIPPET: xbean -->
|
|
|
@ -171,16 +171,6 @@
|
||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>javax.servlet</groupId>
|
|
||||||
<artifactId>servlet-api</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.activemq</groupId>
|
<groupId>org.apache.activemq</groupId>
|
||||||
<artifactId>activemq-jaas</artifactId>
|
<artifactId>activemq-jaas</artifactId>
|
||||||
|
|
|
@ -37,10 +37,6 @@
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>activemq-all</artifactId>
|
<artifactId>activemq-all</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>${project.groupId}</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>activemq-client</artifactId>
|
<artifactId>activemq-client</artifactId>
|
||||||
|
|
|
@ -184,7 +184,6 @@
|
||||||
<include>${pom.groupId}:activemq-pool</include>
|
<include>${pom.groupId}:activemq-pool</include>
|
||||||
<include>${pom.groupId}:activemq-partition</include>
|
<include>${pom.groupId}:activemq-partition</include>
|
||||||
<include>${pom.groupId}:activemq-shiro</include>
|
<include>${pom.groupId}:activemq-shiro</include>
|
||||||
<include>${pom.groupId}:activeio-core</include>
|
|
||||||
<include>commons-beanutils:commons-beanutils</include>
|
<include>commons-beanutils:commons-beanutils</include>
|
||||||
<include>commons-collections:commons-collections</include>
|
<include>commons-collections:commons-collections</include>
|
||||||
<include>commons-io:commons-io</include>
|
<include>commons-io:commons-io</include>
|
||||||
|
|
|
@ -134,15 +134,6 @@
|
||||||
<kahaDB directory="${activemq.data}/dynamic-broker1/kahadb" indexWriteBatchSize="1000" enableIndexWriteAsync="true" enableJournalDiskSyncs="false" />
|
<kahaDB directory="${activemq.data}/dynamic-broker1/kahadb" indexWriteBatchSize="1000" enableIndexWriteAsync="true" enableJournalDiskSyncs="false" />
|
||||||
</persistenceAdapter>
|
</persistenceAdapter>
|
||||||
|
|
||||||
<!--
|
|
||||||
Configure the following if you wish to use journaled JDBC for message
|
|
||||||
persistence.
|
|
||||||
|
|
||||||
<persistenceFactory>
|
|
||||||
<journalPersistenceAdapterFactory dataDirectory="${activemq.data}" dataSource="#postgres-ds"/>
|
|
||||||
</persistenceFactory>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Configure the following if you wish to use non-journaled JDBC for message
|
Configure the following if you wish to use non-journaled JDBC for message
|
||||||
persistence.
|
persistence.
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<broker xmlns="http://activemq.apache.org/schema/core" useJmx="false">
|
<broker xmlns="http://activemq.apache.org/schema/core" useJmx="false">
|
||||||
|
|
||||||
<persistenceFactory>
|
<persistenceFactory>
|
||||||
<journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="../data"/>
|
<kahaDB directory="${activemq.data}/kahadb"/>
|
||||||
</persistenceFactory>
|
</persistenceFactory>
|
||||||
|
|
||||||
<transportConnectors>
|
<transportConnectors>
|
||||||
|
|
13
pom.xml
13
pom.xml
|
@ -34,7 +34,6 @@
|
||||||
<!-- for reproducible builds -->
|
<!-- for reproducible builds -->
|
||||||
<project.build.outputTimestamp>2023-03-28T14:10:59Z</project.build.outputTimestamp>
|
<project.build.outputTimestamp>2023-03-28T14:10:59Z</project.build.outputTimestamp>
|
||||||
|
|
||||||
<activeio-version>3.1.4</activeio-version>
|
|
||||||
<siteId>activemq-${project.version}</siteId>
|
<siteId>activemq-${project.version}</siteId>
|
||||||
<projectName>Apache ActiveMQ</projectName>
|
<projectName>Apache ActiveMQ</projectName>
|
||||||
<!-- base url for site deployment. See distribution management for full url. Override this in settings.xml for staging -->
|
<!-- base url for site deployment. See distribution management for full url. Override this in settings.xml for staging -->
|
||||||
|
@ -415,18 +414,6 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<type>war</type>
|
<type>war</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.activemq</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
<version>${activeio-version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.activemq</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
<version>${activeio-version}</version>
|
|
||||||
<type>test-jar</type>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.activemq</groupId>
|
<groupId>org.apache.activemq</groupId>
|
||||||
<artifactId>activemq-openwire-generator</artifactId>
|
<artifactId>activemq-openwire-generator</artifactId>
|
||||||
|
|
Loading…
Reference in New Issue