package com.venky.swf.plugins.background.core;
import java.util.AbstractQueue;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import com.venky.cache.Cache;
import com.venky.core.util.Bucket;
import com.venky.core.util.ObjectUtil;
import com.venky.swf.plugins.background.core.Task.NormalizedWeightScheme;
import com.venky.swf.plugins.background.core.Task.Priority;
import com.venky.swf.plugins.background.core.Task.PriorityWeightScheme;
import com.venky.swf.routing.Config;
public class WeightedPriorityQueue extends AbstractQueue<TaskHolder> {
private static PriorityWeightScheme getPriorityWeightScheme(){
String className = Config.instance().getProperty("com.venky.swf.plugins.background.core.priorityWeightScheme.class");
PriorityWeightScheme scheme = null;
if (!ObjectUtil.isVoid(className)){
try {
scheme = (PriorityWeightScheme) Class.forName(className).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
scheme = null;
}
}
if (scheme == null) {
scheme = new PriorityWeightScheme() {};
}
return scheme;
}
public WeightedPriorityQueue(){
this(getPriorityWeightScheme());
}
private NormalizedWeightScheme scheme = null;
public WeightedPriorityQueue(PriorityWeightScheme scheme){
super();
this.scheme = new NormalizedWeightScheme(scheme);
}
private Cache<Priority,Bucket> priorityPollingStatistics = new Cache<Task.Priority, Bucket>() {
private static final long serialVersionUID = -8600630938699962417L;
@Override
protected Bucket getValue(Priority k) {
return new Bucket();
}
};
private Cache<Priority, Queue<TaskHolder>> cache = new Cache<Task.Priority, Queue<TaskHolder>>(0,0) {
private static final long serialVersionUID = 1L;
@Override
protected Queue<TaskHolder> getValue(Priority k) {
return new LinkedList<>();
}
};
@Override
public boolean offer(TaskHolder e) {
return cache.get(e.getPriority()).offer(e);
}
private Priority getNextPriorityToPoll(){
Priority ret = null;
Priority firstNonEmptyQueue = null;
for (Priority p : Priority.values()) {
if (!cache.get(p).isEmpty()){
if (firstNonEmptyQueue == null){
firstNonEmptyQueue = p;
}
if (priorityPollingStatistics.get(p).intValue() < scheme.getWeight(p)){
ret = p;
break;
}
}
}
if (ret == null) {
priorityPollingStatistics.clear();
if (firstNonEmptyQueue != null) {
ret = firstNonEmptyQueue;
}else {
ret = Priority.HIGH;
}
}
return ret;
}
@Override
public TaskHolder poll() {
synchronized (cache) {
TaskHolder polled = null;
Priority p = getNextPriorityToPoll();
Queue<TaskHolder> q = cache.get(p);
polled = q.poll();
if (polled != null) {
priorityPollingStatistics.get(p).increment();
}
return polled;
}
}
@Override
public TaskHolder peek() {
synchronized (cache) {
Priority p = getNextPriorityToPoll();
Queue<TaskHolder> q = cache.get(p);
return q.peek();
}
}
@Override
public Iterator<TaskHolder> iterator() {
return new Iterator<TaskHolder>() {
@Override
public boolean hasNext() {
return WeightedPriorityQueue.this.peek() != null;
}
@Override
public TaskHolder next() {
return WeightedPriorityQueue.this.poll() ;
}
};
}
@Override
public int size() {
int size = 0 ;
for (Priority p : cache.keySet()){
size+= cache.get(p).size();
}
return size;
}
}