/**
*
* Copyright 2004 Protique Ltd
*
* Licensed 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.codehaus.activemq.service.impl;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.jms.JMSException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.activemq.broker.BrokerClient;
import org.codehaus.activemq.filter.Filter;
import org.codehaus.activemq.message.ConsumerInfo;
import org.codehaus.activemq.message.MessageAck;
import org.codehaus.activemq.service.DeadLetterPolicy;
import org.codehaus.activemq.service.Dispatcher;
import org.codehaus.activemq.service.QueueListEntry;
import org.codehaus.activemq.service.RedeliveryPolicy;
import org.codehaus.activemq.service.TopicMessageContainer;
import org.codehaus.activemq.service.TransactionManager;
import org.codehaus.activemq.service.TransactionTask;
/**
* Represents a durable topic subscription where the consumer has a unique
* clientID used to persist the messages across both Broker restarts and
* JMS client restarts
*
* @version $Revision: 1.3 $
*/
public class DurableTopicSubscription extends SubscriptionImpl {
private static final Log log = LogFactory.getLog(DurableTopicSubscription.class);
private String persistentKey;
public DurableTopicSubscription(Dispatcher dispatcher, BrokerClient client, ConsumerInfo info, Filter filter, RedeliveryPolicy redeliveryPolicy,DeadLetterPolicy deadLetterPolicy) {
super(dispatcher, client, info, filter, redeliveryPolicy,deadLetterPolicy);
}
public synchronized void messageConsumed(MessageAck ack) throws JMSException {
if (ack.isExpired() || (!ack.isMessageRead() && !isBrowser())) {
super.messageConsumed(ack);
}
else {
final Map lastMessagePointersPerContainer = new HashMap();
//remove up to this message
boolean found = false;
QueueListEntry queueEntry = messagePtrs.getFirstEntry();
while (queueEntry != null) {
final MessagePointer pointer = (MessagePointer) queueEntry.getElement();
messagePtrs.remove(queueEntry);
lastMessagePointersPerContainer.put(pointer.getContainer(), pointer);
unconsumedMessagesDispatched.decrement();
TransactionManager.getContexTransaction().addPostRollbackTask(new TransactionTask(){
public void execute() throws Throwable {
unconsumedMessagesDispatched.increment();
MessagePointer p = new MessagePointer(pointer.getContainer(), pointer.getMessageIdentity());
p.setRedelivered(true);
messagePtrs.add(p);
dispatch.wakeup(DurableTopicSubscription.this);
lastMessageIdentity = pointer.getMessageIdentity();
}
});
TransactionManager.getContexTransaction().addPostCommitTask(new TransactionTask(){
public void execute() throws Throwable {
// now lets tell each container to update its lastAcknowlegedMessageID
for (Iterator iter = lastMessagePointersPerContainer.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
TopicMessageContainer container = (TopicMessageContainer) entry.getKey();
MessagePointer pointer = (MessagePointer) entry.getValue();
container.setLastAcknowledgedMessageID(DurableTopicSubscription.this, pointer.getMessageIdentity());
}
}
});
if (pointer.getMessageIdentity().equals(ack.getMessageIdentity())) {
found = true;
break;
}
queueEntry = messagePtrs.getNextEntry(queueEntry);
}
if (!found) {
log.warn("Did not find a matching message for identity: " + ack.getMessageIdentity());
}
//System.out.println("Message consumed. Remaining: " + messagePtrs.size() + " unconsumedMessagesDispatched: " + unconsumedMessagesDispatched.get());
dispatch.wakeup(this);
}
}
public String getPersistentKey() {
if (persistentKey == null) {
persistentKey = "[" + getClientId() + ":" + getSubscriberName() + "]";
}
return persistentKey;
}
}