Package com.nokia.dempsy.messagetransport.blockingqueue

Source Code of com.nokia.dempsy.messagetransport.blockingqueue.BlockingQueueAdaptor

/*
* Copyright 2012 the original author or authors.
*
* 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 com.nokia.dempsy.messagetransport.blockingqueue;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.nokia.dempsy.messagetransport.Destination;
import com.nokia.dempsy.messagetransport.Listener;
import com.nokia.dempsy.messagetransport.MessageTransportException;
import com.nokia.dempsy.messagetransport.OverflowHandler;
import com.nokia.dempsy.messagetransport.Receiver;
import com.nokia.dempsy.monitoring.StatsCollector;

/**
* <p>The Message transport default library comes with this BlockingQueue implementation.</p>
*
* <p>This class represents both the MessageTransportSender and the concrete Adaptor (since
* BlockingQueues don't span process spaces). You need to initialize it with the BlockingQueue
* to use, as well as the MessageTransportListener to send messages to.</p>
*
* <p>Optionally you can provide it with a name that will be used in the thread that's started
* to read messages from the queue.</p>
*/
public class BlockingQueueAdaptor implements Runnable, Receiver
{
   private static Logger logger = LoggerFactory.getLogger(BlockingQueueAdaptor.class);
  
   private Thread running;
   private String name;
   private AtomicReference<Listener> listener = new AtomicReference<Listener>();
   private AtomicBoolean shutdown = new AtomicBoolean(false);
   private BlockingQueueDestination destination = null;
   private OverflowHandler overflowHandler = null;
   private boolean failFast = false; // this has been the default - since it's equivalent to there being no overflowHandler
   private boolean explicitFailFast = false;
  
   /**
    * <p>This method starts a background thread that reads messages from the queue and sends
    * them to a registered MessageTransportListener.</p>
    *
    * <p>This method is tagged with a @PostConstruct but outside of a dependency injection
    * container that's set up to manage default java lifecycle, it needs to be called
    * explicitly.</p>
    *
    * <p>Alternatively you can manage the threading yourself since a BlockingQueueAdaptor
    * itself is the Runnable that's started.</p>
    *
    * @throws MessageTransportException if the BlockingQueue implementation isn't set or
    * if the listener to send the messages to isn't set.
    */
   @Override
   public synchronized void start() throws MessageTransportException
   {
      // check to see that the overflowHandler and the failFast setting are consistent.
      if (!failFast && overflowHandler != null)
         logger.warn("BlockingQueueAdaptor is configured with an OverflowHandler that will never be used because it's also configured to NOT 'fail fast' so it will always block waiting for messages to be processed.");

      running = name == null ? new Thread(this) : new Thread(this,name);
      running.setDaemon(true);
      running.start();
   }
  
   @Override
   public synchronized void stop()
   {
      synchronized(this)
      {
         shutdown.set(true);
         if (running != null)
            running.interrupt();
      }
   }
  
   @Override
   public void run()
   {
      synchronized(this)
      {
         if (running == null)
            // this is done in case start() wasn't used to start this thread.
            running = Thread.currentThread();
         else if (running != Thread.currentThread())
         {
            logger.error(BlockingQueueAdaptor.class.getSimpleName() + " was started in a Runnable more than once. Exiting the additional thread.");
            return;
         }
      }
     
      while (!shutdown.get())
      {
         try
         {
            byte[] val = destination.queue.take();
            Listener curListener = listener.get();
           
            boolean messageSuccess = curListener == null ? false : curListener.onMessage(val, failFast);
            if (overflowHandler != null && !messageSuccess)
               overflowHandler.overflow(val);
         }
         catch (InterruptedException ie)
         {
            // if we were interrupted we're probably stopping.
            if (!shutdown.get())
               logger.warn("Superfluous interrupt.",ie);
         }
         catch (Throwable err)
         {
            logger.error("Exception while handling message.",err);
         }
      }
   }
  
   /**
    * Sets the name of this BlockingQueueAdaptor which is currently used in the
    * start method as the name of the Thread that's created.
    *
    * @param name is the name to set the BlockingQueueAdaptor to.
    */
   public void setName(String name)
   {
      this.name = name;
   }
  
   /**
    * A BlockingQueueAdaptor requires a MessageTransportListener to be set in order
    * to adapt a client side.
    *
    * @param listener is the MessageTransportListener to push messages to when they
    * come in.
    */
   @Override
   public void setListener(Listener listener){ this.listener.set(listener)}
  
   /**
    * When an overflow handler is set the Adaptor indicates that a 'failFast' should happen
    * and any failed message deliveries end up passed to the overflow handler.
    */
   public void setOverflowHandler(OverflowHandler handler) { this.overflowHandler = handler; if (!explicitFailFast) failFast = (handler != null); }
  
   public void setFailFast(boolean failFast)
   {
      explicitFailFast = true;
      this.failFast = failFast;
   }

   public BlockingQueue<byte[]> getQueue() { return destination == null ? null : destination.queue; }

   public void setQueue(BlockingQueue<byte[]> queue) { this.destination = new BlockingQueueDestination(queue); }
  
   @Override
   public Destination getDestination() { return this.destination; }

   @Override
   public void setStatsCollector(StatsCollector statsCollector) { }

}
TOP

Related Classes of com.nokia.dempsy.messagetransport.blockingqueue.BlockingQueueAdaptor

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.