Package org.hornetq.core.server.impl

Source Code of org.hornetq.core.server.impl.ScheduledDeliveryHandlerImpl$ScheduledDeliveryRunnable

/*
* Copyright 2009 Red Hat, Inc.
* Red Hat 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.hornetq.core.server.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.hornetq.core.filter.Filter;
import org.hornetq.core.logging.Logger;
import org.hornetq.core.server.MessageReference;
import org.hornetq.core.server.Queue;
import org.hornetq.core.server.ScheduledDeliveryHandler;

/**
* Handles scheduling deliveries to a queue at the correct time.
*
* @author <a href="mailto:tim.fox@jboss.com">Tim Fox</a>
* @author <a href="ataylor@redhat.com">Andy Taylor</a>
* @author <a href="jmesnil@redhat.com">Jeff Mesnil</a>
* @author <a href="clebert.suconic@jboss.com">Clebert Suconic</a>
*/
public class ScheduledDeliveryHandlerImpl implements ScheduledDeliveryHandler
{
   private static final Logger log = Logger.getLogger(ScheduledDeliveryHandlerImpl.class);

   private static final boolean trace = ScheduledDeliveryHandlerImpl.log.isTraceEnabled();

   private final ScheduledExecutorService scheduledExecutor;
  
   private final Object lockDelivery = new Object();
  
   private LinkedList<MessageReference> scheduledReferences = new LinkedList<MessageReference>();

   public ScheduledDeliveryHandlerImpl(final ScheduledExecutorService scheduledExecutor)
   {
      this.scheduledExecutor = scheduledExecutor;
   }

   public boolean checkAndSchedule(final MessageReference ref, final boolean tail)
   {
      long deliveryTime = ref.getScheduledDeliveryTime();

      if (deliveryTime > 0 && scheduledExecutor != null)
      {
         if (ScheduledDeliveryHandlerImpl.trace)
         {
            ScheduledDeliveryHandlerImpl.log.trace("Scheduling delivery for " + ref + " to occur at " + deliveryTime);
         }

         ScheduledDeliveryRunnable runnable = new ScheduledDeliveryRunnable(ref.getScheduledDeliveryTime());

         synchronized (scheduledReferences)
         {
            if (tail)
            {
               // We do the opposite what the parameter says as the Runnable will always add it to the head
               scheduledReferences.addFirst(ref);
            }
            else
            {
               // We do the opposite what the parameter says as the Runnable will always add it to the head
               scheduledReferences.add(ref);
            }
         }

         scheduleDelivery(runnable, deliveryTime);

         return true;
      }
      return false;
   }

   public int getScheduledCount()
   {
      synchronized (scheduledReferences)
      {
         return scheduledReferences.size();
      }
   }

   public List<MessageReference> getScheduledReferences()
   {
      List<MessageReference> refs = new ArrayList<MessageReference>();

      synchronized (scheduledReferences)
      {
         refs.addAll(scheduledReferences);
      }
      return refs;
   }

   public List<MessageReference> cancel(final Filter filter)
   {
      List<MessageReference> refs = new ArrayList<MessageReference>();

      synchronized (scheduledReferences)
      {
         Iterator<MessageReference> iter = scheduledReferences.iterator();
        
         while (iter.hasNext())
         {
            MessageReference ref = iter.next();
            if (filter == null || filter.match(ref.getMessage()))
            {
               iter.remove();
               refs.add(ref);
            }
         }
      }
      return refs;
   }

   public MessageReference removeReferenceWithID(final long id)
   {
      synchronized (scheduledReferences)
      {
         Iterator<MessageReference> iter = scheduledReferences.iterator();
         while (iter.hasNext())
         {
            MessageReference ref = iter.next();
            if (ref.getMessage().getMessageID() == id)
            {
               iter.remove();
               return ref;
            }
         }
      }
     
      return null;
   }

   private void scheduleDelivery(final ScheduledDeliveryRunnable runnable, final long deliveryTime)
   {
      long now = System.currentTimeMillis();

      long delay = deliveryTime - now;
     
      if (delay < 0)
      {
         delay = 0;
      }

      scheduledExecutor.schedule(runnable, delay, TimeUnit.MILLISECONDS);
   }

   private class ScheduledDeliveryRunnable implements Runnable
   {
      private final long scheduledTime;

      public ScheduledDeliveryRunnable(final long scheduledTime)
      {
         this.scheduledTime = scheduledTime;
      }

      public void run()
      {
         HashSet<Queue> queues = new HashSet<Queue>();
         LinkedList<MessageReference> references = new LinkedList<MessageReference>();

         synchronized (lockDelivery)
         {
            synchronized (scheduledReferences)
            {
              
               Iterator<MessageReference> iter = scheduledReferences.iterator();
               while (iter.hasNext())
               {
                  MessageReference reference = iter.next();
                  if (reference.getScheduledDeliveryTime() <= this.scheduledTime)
                  {
                     iter.remove();
  
                     reference.setScheduledDeliveryTime(0);
                    
                     references.add(reference);
                    
                     queues.add(reference.getQueue());
                  }
               }
            }
           
            for (MessageReference reference : references)
            {
               Queue queue = reference.getQueue();
               synchronized (queue)
               {
                  queue.resetAllIterators();
                  queue.addHead(reference);
               }
            }
           
            // Just to speed up GC
            references.clear();
           
            for (Queue queue : queues)
            {
               synchronized (queue)
               {
                  queue.deliverAsync();
               }
            }
         }
      }
   }
}
TOP

Related Classes of org.hornetq.core.server.impl.ScheduledDeliveryHandlerImpl$ScheduledDeliveryRunnable

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.