* @throws InvalidRecordLocationException
* @throws IllegalStateException
*/
private void recover() throws IllegalStateException, InvalidRecordLocationException, IOException, JMSException {
RecordLocation pos = null;
int transactionCounter = 0;
log.info("Journal Recovery Started.");
// While we have records in the journal.
while ((pos = journal.getNextRecordLocation(pos)) != null) {
org.activeio.Packet data = journal.read(pos);
DataInputStream is = new DataInputStream(new PacketInputStream(data));
// Read the destination and packate from the record.
String destination = null;
Packet packet = null;
try {
byte type = is.readByte();
switch (type) {
case PACKET_RECORD_TYPE:
// Is the current packet part of the destination?
destination = is.readUTF();
packet = wireFormat.readPacket(data);
// Try to replay the packet.
if (packet instanceof ActiveMQMessage) {
ActiveMQMessage msg = (ActiveMQMessage) packet;
JournalMessageStore store = (JournalMessageStore) createMessageStore(destination, msg.getJMSActiveMQDestination().isQueue());
try {
// Only add the message if it has not allready been added.
ActiveMQMessage t = store.getLongTermMessageStore().getMessage(msg.getJMSMessageIdentity());
if( t==null ) {
store.getLongTermMessageStore().addMessage(msg);
transactionCounter++;
}
}
catch (Throwable e) {
log.error("Recovery Failure: Could not add message: " + msg.getJMSMessageIdentity().getMessageID() + ", reason: " + e, e);
}
}
else if (packet instanceof MessageAck) {
MessageAck ack = (MessageAck) packet;
JournalMessageStore store = (JournalMessageStore) createMessageStore(destination, ack.getDestination().isQueue());
try {
// Only remove the message if it has not allready been removed.
ActiveMQMessage t = store.getLongTermMessageStore().getMessage(ack.getMessageIdentity());
if( t!=null ) {
store.getLongTermMessageStore().removeMessage(ack);
transactionCounter++;
}
}
catch (Throwable e) {
log.error("Recovery Failure: Could not remove message: " + ack.getMessageIdentity().getMessageID() + ", reason: " + e, e);
}
}
else {
log.error("Unknown type of packet in transaction log which will be discarded: " + packet);
}
break;
case TX_COMMAND_RECORD_TYPE:
TxCommand command = new TxCommand();
command.setType(is.readByte());
command.setWasPrepared(is.readBoolean());
switch(command.getType()) {
case TxCommand.LOCAL_COMMIT:
case TxCommand.LOCAL_ROLLBACK:
command.setTransactionId(is.readUTF());
break;
default:
command.setTransactionId(ActiveMQXid.read(is));
break;
}
try {
// Try to replay the packet.
switch(command.getType()) {
case TxCommand.XA_PREPARE:
transactionStore.checkpointStore.prepare(command.getTransactionId());
break;
case TxCommand.XA_COMMIT:
case TxCommand.LOCAL_COMMIT:
transactionStore.checkpointStore.commit(command.getTransactionId(), command.getWasPrepared());
break;
case TxCommand.LOCAL_ROLLBACK:
case TxCommand.XA_ROLLBACK:
transactionStore.checkpointStore.rollback(command.getTransactionId());
break;
}
} catch (XAException e) {
log.error("Recovery Failure: Could not replay: " + command + ", reason: " + e, e);
}
break;
case ACK_RECORD_TYPE:
destination = is.readUTF();
String subscription = is.readUTF();
String messageId = is.readUTF();
JournalTopicMessageStore store = (JournalTopicMessageStore) createMessageStore(destination, false);
try {
store.getLongTermTopicMessageStore().setLastAcknowledgedMessageIdentity(subscription, new MessageIdentity(messageId));
}
catch (Throwable e) {
log.error("Recovery Failure: Could not ack message: " + messageId + ", reason: " + e, e);
}
case COMMAND_RECORD_TYPE:
break;
default:
log.error("Unknown type of record in transaction log which will be discarded: " + type);
break;
}
}
finally {
is.close();
}
}
RecordLocation location = writeCommand("RECOVERED", true);
journal.setMark(location, true);
log.info("Journal Recovered: " + transactionCounter + " message(s) in transactions recovered.");
}