Package org.codehaus.activemq.service.boundedvm

Source Code of org.codehaus.activemq.service.boundedvm.TransientQueueBoundedMessageContainer

/**
*
* 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.boundedvm;

import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
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.ActiveMQDestination;
import org.codehaus.activemq.message.ActiveMQMessage;
import org.codehaus.activemq.message.ConsumerInfo;
import org.codehaus.activemq.message.MessageAck;
import org.codehaus.activemq.message.util.MemoryBoundedQueue;
import org.codehaus.activemq.message.util.MemoryBoundedQueueManager;
import org.codehaus.activemq.service.MessageContainer;
import org.codehaus.activemq.service.MessageIdentity;
import org.codehaus.activemq.service.QueueListEntry;
import org.codehaus.activemq.service.Service;
import org.codehaus.activemq.service.impl.DefaultQueueList;

import javax.jms.JMSException;
import java.util.List;
import java.util.ListIterator;

/**
* A MessageContainer for transient queues
*
* @version $Revision: 1.6 $
*/
public class TransientQueueBoundedMessageContainer implements MessageContainer, Service, Runnable {
    private MemoryBoundedQueueManager queueManager;
    private ActiveMQDestination destination;
    private SynchronizedBoolean started;
    private MemoryBoundedQueue queue;
    private Thread worker;
    private DefaultQueueList subscriptions;
    private Log log;

    /**
     * Construct this beast
     *
     * @param queueManager
     * @param destination
     */
    public TransientQueueBoundedMessageContainer(MemoryBoundedQueueManager queueManager, ActiveMQDestination destination) {
        this.queueManager = queueManager;
        this.destination = destination;
        this.queue = queueManager.getMemoryBoundedQueue("TRANSIENT_QUEUE:-" + destination.getPhysicalName());
        this.started = new SynchronizedBoolean(false);
        this.subscriptions = new DefaultQueueList();
        this.log = LogFactory.getLog("TransientQueueBoundedMessageContainer:- " + destination);
    }

    /**
     * @return true if this Container has no active subscriptions and there are no messages to dispatch
     */
    public boolean isInactive() {
        return subscriptions.isEmpty() && queue.isEmpty();
    }

    /**
     * Add a consumer to dispatch messages to
     *
     * @param filter
     * @param info
     * @param client
     * @return
     * @throws JMSException
     */
    public TransientQueueSubscription addConsumer(Filter filter, ConsumerInfo info, BrokerClient client)
            throws JMSException {
        TransientQueueSubscription ts = findMatch(info);
        if (ts == null) {
            MemoryBoundedQueue queue = queueManager.getMemoryBoundedQueue(client.toString() + info.getConsumerId());
            ts = new TransientQueueSubscription(client, queue, filter, info);
            subscriptions.add(ts);
        }
        return ts;
    }

    /**
     * Remove a consumer
     *
     * @param info
     * @throws JMSException
     */
    public void removeConsumer(ConsumerInfo info) throws JMSException {
        TransientQueueSubscription ts = findMatch(info);
        if (ts != null) {
            subscriptions.remove(ts);
            //get unacknowledged messages and re-enqueue them
            List list = ts.getUndeliveredMessages();
            for (ListIterator i = list.listIterator(list.size()); i.hasPrevious();) {
                ActiveMQMessage message = (ActiveMQMessage) i.previous();
                message.setJMSRedelivered(true);
                queue.enqueueFirstNoBlock(message);
            }
            list.clear();
            ts.close();
        }
    }

    /**
     * start working
     */
    public void start() {
        if (started.commit(false, true)) {
            worker = new Thread(this, "TransientQueueDispatcher");
            worker.setPriority(Thread.NORM_PRIORITY + 1);
            worker.start();
        }
    }

    /**
     * enqueue a message for dispatching
     *
     * @param message
     */
    public void enqueue(ActiveMQMessage message) {
        queue.enqueue(message);
    }
   
    /**
     * enqueue a message for dispatching
     *
     * @param message
     */
    public void enqueueFirst(ActiveMQMessage message) {
        queue.enqueueFirstNoBlock(message);
    }
   
   

    /**
     * stop working
     */
    public void stop() {
        started.set(false);
        queue.clear();
    }

    /**
     * close down this container
     *
     * @throws JMSException
     */
    public void close() throws JMSException {
        if (started.get()) {
            stop();
        }
        queue.close();
        QueueListEntry entry = subscriptions.getFirstEntry();
        while (entry != null) {
            TransientQueueSubscription ts = (TransientQueueSubscription) entry.getElement();
            ts.close();
            entry = subscriptions.getNextEntry(entry);
        }
        subscriptions.clear();
    }

    /**
     * do some dispatching
     */
    public void run() {
        boolean dispatched = false;
        boolean targeted = false;
        ActiveMQMessage message = null;
        try {
            while (started.get()) {
                dispatched = false;
                targeted = false;
                if (!subscriptions.isEmpty()) {
                    message = (ActiveMQMessage) queue.dequeue(2000);
                    if (message != null) {
                        if (!message.isExpired()) {
                            QueueListEntry entry = subscriptions.getFirstEntry();
                            while (entry != null) {
                                TransientQueueSubscription ts = (TransientQueueSubscription) entry.getElement();
                                if (ts.isTarget(message)) {
                                    targeted = true;
                                    if (ts.canAcceptMessages()) {
                                        ts.doDispatch(message);
                                        message = null;
                                        dispatched = true;
                                        subscriptions.rotate();
                                        break;
                                    }
                                }
                                entry = subscriptions.getNextEntry(entry);
                            }
                        }
                        else {
                            //expire message
                            if (log.isDebugEnabled()) {
                                log.debug("expired message: " + message);
                            }
                            message = null;
                        }
                    }
                }
                if (!dispatched) {
                    if (message != null) {
                        if (targeted) {
                            queue.enqueueFirstNoBlock(message);
                        }
                        else {
                            //no matching subscribers - dump to end and hope one shows up ...
                            queue.enqueueNoBlock(message);
                        }
                    }
                    Thread.sleep(250);
                }
            }
        }
        catch (Exception e) {
            stop();
            log.warn("stop dispatching", e);
        }
    }


    private TransientQueueSubscription findMatch(ConsumerInfo info) throws JMSException {
        TransientQueueSubscription result = null;
        QueueListEntry entry = subscriptions.getFirstEntry();
        while (entry != null) {
            TransientQueueSubscription ts = (TransientQueueSubscription) entry.getElement();
            if (ts.getConsumerInfo().equals(info)) {
                result = ts;
                break;
            }
            entry = subscriptions.getNextEntry(entry);
        }
        return result;
    }

    /**
     * @return the destination associated with this container
     */
    public ActiveMQDestination getDestination() {
        return destination;
    }

    /**
     * @return the destination name
     */
    public String getDestinationName() {
        return destination.getPhysicalName();
    }


    /**
     * @param msg
     * @return
     * @throws JMSException
     */
    public MessageIdentity addMessage(ActiveMQMessage msg) throws JMSException {
        return null;
    }

    /**
     * @param messageIdentity
     * @param ack
     * @throws JMSException
     */
    public void delete(MessageIdentity messageIdentity, MessageAck ack) throws JMSException {
    }

    /**
     * @param messageIdentity
     * @return
     * @throws JMSException
     */
    public ActiveMQMessage getMessage(MessageIdentity messageIdentity) throws JMSException {
        return null;
    }

    /**
     * @param messageIdentity
     * @throws JMSException
     */
    public void registerMessageInterest(MessageIdentity messageIdentity) throws JMSException {
    }

    /**
     * @param messageIdentity
     * @param ack
     * @throws JMSException
     */
    public void unregisterMessageInterest(MessageIdentity messageIdentity, MessageAck ack) throws JMSException {
    }

    /**
     * @param messageIdentity
     * @return
     * @throws JMSException
     */
    public boolean containsMessage(MessageIdentity messageIdentity) throws JMSException {
        return false;
    }

    protected boolean hasActiveSubscribers() {
        return !subscriptions.isEmpty();
    }

    protected void clear() {
        queue.clear();
    }

    protected void removeExpiredMessages() {
        long currentTime = System.currentTimeMillis();
        List list = queue.getContents();
        for (int i = 0; i < list.size(); i++) {
            ActiveMQMessage msg = (ActiveMQMessage) list.get(i);
            if (msg.isExpired(currentTime)) {
                queue.remove(msg);
                if (log.isDebugEnabled()) {
                    log.debug("expired message: " + msg);
                }
            }
        }
    }
}
TOP

Related Classes of org.codehaus.activemq.service.boundedvm.TransientQueueBoundedMessageContainer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.