001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.memory.list;
018
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.Iterator;
022import java.util.List;
023import java.util.Map;
024import java.util.Set;
025import org.apache.activemq.broker.region.MessageReference;
026import org.apache.activemq.broker.region.Subscription;
027import org.apache.activemq.command.ActiveMQDestination;
028import org.apache.activemq.command.ActiveMQMessage;
029import org.apache.activemq.command.Message;
030import org.apache.activemq.filter.DestinationMap;
031import org.apache.activemq.memory.buffer.MessageBuffer;
032import org.apache.activemq.memory.buffer.MessageQueue;
033import org.apache.activemq.memory.buffer.OrderBasedMessageBuffer;
034
035/**
036 * An implementation of {@link MessageList} which maintains a separate message
037 * list for each destination to reduce contention on the list and to speed up
038 * recovery times by only recovering the interested topics.
039 * 
040 * 
041 */
042public class DestinationBasedMessageList implements MessageList {
043
044    private MessageBuffer messageBuffer;
045    private Map<ActiveMQDestination, MessageQueue> queueIndex = new HashMap<ActiveMQDestination, MessageQueue>();
046    private DestinationMap subscriptionIndex = new DestinationMap();
047    private Object lock = new Object();
048
049    public DestinationBasedMessageList(int maximumSize) {
050        this(new OrderBasedMessageBuffer(maximumSize));
051    }
052    
053    public DestinationBasedMessageList(MessageBuffer buffer) {
054        messageBuffer = buffer;
055    }
056
057    public void add(MessageReference node) {
058        ActiveMQMessage message = (ActiveMQMessage) node.getMessageHardRef();
059        ActiveMQDestination destination = message.getDestination();
060        MessageQueue queue = null;
061        synchronized (lock) {
062            queue = queueIndex.get(destination);
063            if (queue == null) {
064                queue = messageBuffer.createMessageQueue();
065                queueIndex.put(destination, queue);
066                subscriptionIndex.put(destination, queue);
067            }
068        }
069        queue.add(node);
070    }
071
072    public List<MessageReference> getMessages(Subscription sub) {
073        return getMessages(sub.getConsumerInfo().getDestination());
074    }
075    
076    public  List<MessageReference> getMessages(ActiveMQDestination destination) {
077        Set set = null;
078        synchronized (lock) {
079            set = subscriptionIndex.get(destination);
080        }
081        List<MessageReference> answer = new ArrayList<MessageReference>();
082        for (Iterator iter = set.iterator(); iter.hasNext();) {
083            MessageQueue queue = (MessageQueue) iter.next();
084            queue.appendMessages(answer);
085        }
086        return answer;
087    }
088    
089    public Message[] browse(ActiveMQDestination destination) {
090        List<MessageReference> result = getMessages(destination);
091        return result.toArray(new Message[result.size()]);
092    }
093
094
095    public void clear() {
096        messageBuffer.clear();
097    }
098}