/** * 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.broker.region.cursors; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.apache.activemq.broker.ConnectionContext; import org.apache.activemq.broker.region.Destination; import org.apache.activemq.broker.region.MessageReference; import org.apache.activemq.broker.region.QueueMessageReference; /** * hold pending messages in a linked list (messages awaiting disptach to a * consumer) cursor * * */ public class VMPendingMessageCursor extends AbstractPendingMessageCursor { private final PendingList list; private Iterator<MessageReference> iter; public VMPendingMessageCursor(boolean prioritizedMessages) { super(prioritizedMessages); if (this.prioritizedMessages) { this.list= new PrioritizedPendingList(); }else { this.list = new OrderedPendingList(); } } @Override public synchronized List<MessageReference> remove(ConnectionContext context, Destination destination) throws Exception { List<MessageReference> rc = new ArrayList<MessageReference>(); for (Iterator<MessageReference> iterator = list.iterator(); iterator.hasNext();) { MessageReference r = iterator.next(); if (r.getRegionDestination() == destination) { r.decrementReferenceCount(); rc.add(r); iterator.remove(); } } return rc; } /** * @return true if there are no pending messages */ @Override public synchronized boolean isEmpty() { if (list.isEmpty()) { return true; } else { for (Iterator<MessageReference> iterator = list.iterator(); iterator.hasNext();) { MessageReference node = iterator.next(); if (node == QueueMessageReference.NULL_MESSAGE) { continue; } if (!node.isDropped()) { return false; } // We can remove dropped references. iterator.remove(); } return true; } } /** * reset the cursor */ @Override public synchronized void reset() { iter = list.iterator(); last = null; } /** * add message to await dispatch * * @param node */ @Override public synchronized boolean tryAddMessageLast(MessageReference node, long maxWait) { node.incrementReferenceCount(); list.addMessageLast(node); return true; } /** * add message to await dispatch * * @param node */ @Override public synchronized void addMessageFirst(MessageReference node) { node.incrementReferenceCount(); list.addMessageFirst(node); } /** * @return true if there pending messages to dispatch */ @Override public synchronized boolean hasNext() { return iter.hasNext(); } /** * @return the next pending message */ @Override public synchronized MessageReference next() { last = iter.next(); if (last != null) { last.incrementReferenceCount(); } return last; } /** * remove the message at the cursor position */ @Override public synchronized void remove() { if (last != null) { last.decrementReferenceCount(); } iter.remove(); } /** * @return the number of pending messages */ @Override public synchronized int size() { return list.size(); } @Override public synchronized long messageSize() { return list.messageSize(); } /** * clear all pending messages */ @Override public synchronized void clear() { for (Iterator<MessageReference> i = list.iterator(); i.hasNext();) { MessageReference ref = i.next(); ref.decrementReferenceCount(); } list.clear(); } @Override public synchronized void remove(MessageReference node) { list.remove(node); node.decrementReferenceCount(); } /** * Page in a restricted number of messages * * @param maxItems * @return a list of paged in messages */ @Override public LinkedList<MessageReference> pageInList(int maxItems) { LinkedList<MessageReference> result = new LinkedList<MessageReference>(); for (Iterator<MessageReference>i = list.iterator();i.hasNext();) { MessageReference ref = i.next(); ref.incrementReferenceCount(); result.add(ref); if (result.size() >= maxItems) { break; } } return result; } @Override public boolean isTransient() { return true; } @Override public void destroy() throws Exception { super.destroy(); clear(); } }