Package ch.ethz.inf.vs.californium.network.deduplication

Source Code of ch.ethz.inf.vs.californium.network.deduplication.SweepDeduplicator$SweepAlgorithm

package ch.ethz.inf.vs.californium.network.deduplication;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import ch.ethz.inf.vs.californium.network.Exchange;
import ch.ethz.inf.vs.californium.network.Exchange.KeyMID;
import ch.ethz.inf.vs.californium.network.config.NetworkConfig;
import ch.ethz.inf.vs.californium.network.config.NetworkConfigDefaults;

/**
* This deduplicator uses a hash map to store incoming messages. The
* deduplicator periodically iterates through all entries and removes obsolete
* messages (exchanges).
*/
public class SweepDeduplicator implements Deduplicator {

  /** The logger. */
  private final static Logger LOGGER = Logger.getLogger(SweepDeduplicator.class.getCanonicalName());
 
  /** The hash map with all incoming messages. */
  private ConcurrentHashMap<KeyMID, Exchange> incommingMessages;
 
  private NetworkConfig config;
  private SweepAlgorithm algorithm;
 
  private ScheduledExecutorService executor;
 
  private boolean started = false;
 
  public SweepDeduplicator(NetworkConfig config) {
    this.config = config;
    incommingMessages = new ConcurrentHashMap<KeyMID, Exchange>();
    algorithm = new SweepAlgorithm();
  }
 
  public void start() {
    started = true;
    algorithm.schedule();
  }
 
  public void stop() {
    started = false;
    algorithm.cancel();
  }
 
  public void setExecutor(ScheduledExecutorService executor) {
    stop();
    this.executor = executor;
    if (started)
      start();
  }
 
  /**
   * If the message with the specified {@link KeyMID} has already arrived
   * before, this method returns the corresponding exchange. If this
   * KeyMID has not yet arrived, this methos returns null, indicating that
   * the message with the KeyMID is not a duplicate.
   */
  public Exchange findPrevious(KeyMID key, Exchange exchange) {
    Exchange previous = incommingMessages.putIfAbsent(key, exchange);
    return previous;
  }
 
  public Exchange find(KeyMID key) {
    return incommingMessages.get(key);
  }
 
  public void clear() {
    incommingMessages.clear();
  }
 
  /**
   * The sweep algorithm periodically iterate through the hash map and removes
   * obsolete entries.
   */
  private class SweepAlgorithm implements Runnable {

    private ScheduledFuture<?> future;
   
    /**
     * This method wraps the method sweep() to catch any Exceptions that
     * might be thrown.
     */
    @Override
    public void run() {
      try {
        LOGGER.finest("Start Mark-And-Sweep with "+incommingMessages.size()+" entries");
        sweep();
       
      } catch (Throwable t) {
        LOGGER.log(Level.WARNING, "Exception in Mark-and-Sweep algorithm", t);
     
      } finally {
        try {
          schedule();
        } catch (Throwable t) {
          LOGGER.log(Level.WARNING, "Exception while scheduling Mark-and-Sweep algorithm", t);
        }
      }
    }
   
    /**
     * Iterate through all entries and remove the obsolete ones.
     */
    private void sweep() {
      int lifecycle = config.getInt(NetworkConfigDefaults.EXCHANGE_LIFECYCLE);
      long oldestAllowed = System.currentTimeMillis() - lifecycle;
     
      // Notice that the guarantees from the ConcurrentHashMap guarantee
      // the correctness for this iteration.
      for (Map.Entry<?,Exchange> entry:incommingMessages.entrySet()) {
        Exchange exchange = entry.getValue();
        if (exchange.getTimestamp() < oldestAllowed) {
         
          // TODO: Only remove if no observe option!!! Should we take ts of last message?
          // Use exchange.isCompleted()
         
          LOGGER.finer("Mark-And-Sweep removes "+entry.getKey());
          incommingMessages.remove(entry.getKey());
        }
      }
    }
   
    /**
     * Reschedule this task again.
     */
    private void schedule() {
      long period = config.getLong(NetworkConfigDefaults.MARK_AND_SWEEP_INTERVAL);
      future = executor.schedule(this, period, TimeUnit.MILLISECONDS);
    }
   
    /**
     * Cancel the schedule for this algorithm.
     */
    private void cancel() {
      if (future != null)
        future.cancel(true);
    }
   
  }
}
TOP

Related Classes of ch.ethz.inf.vs.californium.network.deduplication.SweepDeduplicator$SweepAlgorithm

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.