Package com.brienwheeler.svc.monitor.telemetry.impl

Source Code of com.brienwheeler.svc.monitor.telemetry.impl.AsynchronousTelemetryInfoProcessor$TelemetryInfoProcessThread

/*
* The MIT License (MIT)
*
* Copyright (c) 2013 Brien L. Wheeler (brienwheeler@yahoo.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.brienwheeler.svc.monitor.telemetry.impl;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.brienwheeler.lib.concurrent.StoppableThread;
import com.brienwheeler.lib.monitor.telemetry.ITelemetryInfoProcessor;
import com.brienwheeler.lib.monitor.telemetry.TelemetryInfo;
import com.brienwheeler.lib.svc.GracefulShutdown;
import com.brienwheeler.lib.svc.ServiceState;
import com.brienwheeler.lib.util.ValidationUtils;

public class AsynchronousTelemetryInfoProcessor extends TelemetryServiceBase
    implements ITelemetryInfoProcessor
{
  public static enum QueueFullPolicy {
    DISCARD_OLDEST,
    DISCARD_OFFERED,
  }
 
  public static enum ShutdownBehavior {
    DISCARD,
    PROCESS,
  }
 
  protected final Log log = LogFactory.getLog(getClass());
 
  private final AtomicReference<StoppableThread> backgroundThread =
      new AtomicReference<StoppableThread>();
  private final AtomicReference<BlockingQueue<TelemetryInfo>> queue =
      new AtomicReference<BlockingQueue<TelemetryInfo>>();
  private final AtomicReference<QueueFullPolicy> queueFullPolicy =
      new AtomicReference<QueueFullPolicy>(QueueFullPolicy.DISCARD_OLDEST);
  private final AtomicReference<ShutdownBehavior> shutdownBehavior =
      new AtomicReference<ShutdownBehavior>(ShutdownBehavior.PROCESS);
  private int maxCapacity = Integer.MAX_VALUE;
 
  public void setQueueFullPolicy(QueueFullPolicy queueFullPolicy)
  {
    ValidationUtils.assertNotNull(queueFullPolicy, "queueFullPolicy cannot be null");
    ensureState(ServiceState.STOPPED, "can't change QueueFullPolicy when not STOPPED");
    this.queueFullPolicy.set(queueFullPolicy);
  }

  public void setShutdownBehavior(ShutdownBehavior shutdownBehavior)
  {
    ValidationUtils.assertNotNull(shutdownBehavior, "shutdownBehavior cannot be null");
    ensureState(ServiceState.STOPPED, "can't change ShutdownBehavior when not STOPPED");
    this.shutdownBehavior.set(shutdownBehavior);
  }

  public void setMaxCapacity(int maxCapacity)
  {
    ValidationUtils.assertTrue(maxCapacity > 0, "maxCapacity must be greater than zero");
    ensureState(ServiceState.STOPPED, "can't change MaxCapacity when not STOPPED");
    this.maxCapacity = maxCapacity;
  }
 
  @Override
  protected void onStart() throws InterruptedException
  {
    super.onStart();
   
    LinkedBlockingQueue<TelemetryInfo> queue = new LinkedBlockingQueue<TelemetryInfo>(maxCapacity);
    this.queue.set(queue);
   
    TelemetryInfoProcessThread backgroundThread = new TelemetryInfoProcessThread(queue);
    this.backgroundThread.set(backgroundThread);
    backgroundThread.start();
  }


  @Override
  protected void onStop() throws InterruptedException
  {
    backgroundThread.get().shutdown();
    super.onStop();
  }


  @Override
  @GracefulShutdown
  public void process(TelemetryInfo telemetryInfo)
  {
    telemetryInfo.checkPublished();

    BlockingQueue<TelemetryInfo> queue = this.queue.get();
   
    switch (queueFullPolicy.get())
    {
      case DISCARD_OFFERED :
        queue.offer(telemetryInfo);
        // return regardless of success
        return;
       
      case DISCARD_OLDEST :
        while (!queue.offer(telemetryInfo))
        {
          // if offer failed, remove and discard one element from queue and try
          // again
          queue.poll();
        }
        return;
    }
  }

  // testability
  protected void beforeTake()
  {
  }
 
  // testability
  protected void afterProcess()
  {
  }
 
  class TelemetryInfoProcessThread extends StoppableThread
  {
    private final BlockingQueue<TelemetryInfo> queue;
   
    TelemetryInfoProcessThread(BlockingQueue<TelemetryInfo> queue)
    {
      super(AsynchronousTelemetryInfoProcessor.class.getSimpleName(), log);
      this.queue = queue;
    }
   
    @Override
    public void onRun()
    {
      while (!isShutdown())
      {
        try {
          beforeTake();
          TelemetryInfo telemetryInfo = queue.take();
          callProcessors(telemetryInfo);
          afterProcess();
        }
        catch (InterruptedException e) {
          // probably isShutdown(), continue and check
          Thread.currentThread().interrupt();
        }
      }
     
      switch (shutdownBehavior.get())
      {
        case DISCARD :
          log.info("discarding " + queue.size() + " queued TelemetryInfo at shutdown");
          break;
         
        case PROCESS :
          log.info("processing " + queue.size() + " queued TelemetryInfo at shutdown");
          for (TelemetryInfo telemetryInfo : queue)
            callProcessors(telemetryInfo);
          break;
      }
     
      queue.clear();
      return;
    }
  }
}
TOP

Related Classes of com.brienwheeler.svc.monitor.telemetry.impl.AsynchronousTelemetryInfoProcessor$TelemetryInfoProcessThread

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.