package org.rzo.netty.ahessian.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.jboss.netty.util.Timeout;
import org.jboss.netty.util.Timer;
import org.jboss.netty.util.TimerTask;
import org.rzo.netty.ahessian.Constants;
public class TimedBlockingPriorityQueue<T> implements MyBlockingQueue<T>
{
int _defaultGroup = 0;
LinkedList<T>[] _queues;
int[] _sizes;
long[] _timeouts;
Map <T, Timeout> _timers = new HashMap<T, Timeout>();
Timer _timer;
Lock _lock = new ReentrantLock();
Condition _hasData = _lock.newCondition();
volatile boolean waiting = false;
int _size = 0;
String _name = "?";
T _last = null;
public TimedBlockingPriorityQueue(Map<String, Object> options, Timer timer, String name)
{
_name = name;
List<Integer> groups = new ArrayList<Integer>();
_timer = timer;
for (String key : options.keySet())
{
if (key.startsWith("group."))
try {
String rest = key.substring(key.indexOf('.')+1);
int x = Integer.parseInt(rest.substring(0, rest.indexOf('.')));
if (!groups.contains(x))
groups.add(x);
}
catch (Exception ex)
{
Constants.ahessianLogger.warn("", ex);
}
}
if (!groups.contains(0))
groups.add(0);
Collections.sort(groups);
int size = groups.get(groups.size()-1)+1;
_queues = new LinkedList[size];
_timeouts = new long[size];
_sizes = new int[size];
for (int i=0; i<size; i++)
{
int queueSize = options.containsKey("group."+i+".size") ? (Integer)options.get("group."+i+".size") : Integer.MAX_VALUE;
_queues[i] = new LinkedList<T>();
_sizes[i] = queueSize;
Object timeout = options.get("group."+i+".timeout");
long longTimeout = (long)-1;
if (timeout instanceof Number)
longTimeout = ((Number)timeout).longValue();
_timeouts[i] = longTimeout;
}
}
public TimedBlockingPriorityQueue(String name)
{
_name = name;
_queues = new LinkedList[1];
_timeouts = new long[1];
_sizes = new int[1];
_queues[0] = new LinkedList();
_timeouts[0] = -1;
_sizes[0] = Integer.MAX_VALUE;
}
public boolean add(Object e)
{
throw new RuntimeException("Unimplemented");
}
public T element()
{
throw new RuntimeException("Unimplemented");
}
public boolean offer(T e)
{
return offer(e, _defaultGroup);
}
public boolean offer(final T e, int group)
{
_lock.lock();
//if (_size == 0)
//System.out.println("LRUQueue not empty: "+ _name);
_size++;
if (group >= _queues.length)
{
Constants.ahessianLogger.warn("group "+group+" not defined -> using group 0");
group = 0;
}
boolean result = false;
final LinkedList<T> q = _queues[group];
result = q.offer((T) e);
if (q.size() >= _sizes[group])
{
// if queue is full remove an element and undo its timer
T o = q.remove();
Timeout timer = _timers.remove(o);
if (timer != null)
timer.cancel();
Constants.ahessianLogger.warn("queue overflow -> removed "+e);
}
if (result)
_last = e;
if (_timer != null && result && _timeouts[group] > 0)
{
Timeout timer = _timer.newTimeout(new TimerTask()
{
public void run(Timeout arg0) throws Exception
{
_lock.lock();
q.remove(e);
Constants.ahessianLogger.warn("message timed out -> removed from queue "+e);
_lock.unlock();
}
}, _timeouts[group], TimeUnit.MILLISECONDS);
}
if (result && waiting)
try
{
_hasData.signal();
}
catch (Exception ex)
{
Constants.ahessianLogger.warn("", ex);
}
_lock.unlock();
return result;
}
public T poll()
{
T result = null;
for (int i=_queues.length-1; i>=0; i--)
{
result = poll(i);
if (result != null)
{
_size--;
return result;
}
}
return null;
}
public T poll(int group)
{
LinkedList<T> q = _queues[group];
T result = null;
if (q != null)
{
result = q.poll();
if (result != null)
{
Timeout timer = _timers.remove(result);
if (timer != null)
timer.cancel();
}
}
return result;
}
public T peek()
{
throw new RuntimeException("Unimplemented");
}
public T remove()
{
throw new RuntimeException("Unimplemented");
}
public boolean addAll(Collection c)
{
throw new RuntimeException("Unimplemented");
}
public void clear()
{
_lock.lock();
for (int i=0; i<_queues.length; i++)
{
clear(i);
}
_lock.unlock();
}
public void clear(int group)
{
_lock.lock();
if (_queues[group] != null)
_queues[group].clear();
_lock.unlock();
}
public boolean contains(Object o)
{
throw new RuntimeException("Unimplemented");
}
public boolean containsAll(Collection c)
{
throw new RuntimeException("Unimplemented");
}
public boolean isEmpty()
{
throw new RuntimeException("Unimplemented");
}
public Iterator iterator()
{
throw new RuntimeException("Unimplemented");
}
public boolean remove(Object o)
{
throw new RuntimeException("Unimplemented");
}
public boolean remove(T o, Integer group)
{
if (_queues[group] != null)
return _queues[group].remove(o);
return false;
}
public boolean removeAll(Collection c)
{
throw new RuntimeException("Unimplemented");
}
public boolean retainAll(Collection c)
{
throw new RuntimeException("Unimplemented");
}
public int size()
{
return _size;
}
public T[] toArray()
{
throw new RuntimeException("Unimplemented");
}
public T[] toArray(Object[] a)
{
throw new RuntimeException("Unimplemented");
}
public int drainTo(Collection c)
{
throw new RuntimeException("Unimplemented");
}
public int drainTo(Collection c, int maxElements)
{
throw new RuntimeException("Unimplemented");
}
public boolean offer(Object e, long timeout, TimeUnit unit) throws InterruptedException
{
throw new RuntimeException("Unimplemented");
}
public T poll(long timeout, TimeUnit unit) throws InterruptedException
{
throw new RuntimeException("Unimplemented");
}
public void put(T e) throws InterruptedException
{
put(e, _defaultGroup);
}
public void put(T e, Integer group)
{
offer(e, group);
}
public int remainingCapacity()
{
throw new RuntimeException("Unimplemented");
}
public T take() throws InterruptedException
{
T result = null;
_lock.lock();
do
{
result = poll();
if (result == null)
try
{
waiting = true;
_hasData.await();
}
finally
{
waiting = false;
}
}
while (result == null);
if (result == _last)
_last = null;
_lock.unlock();
//if (_size == 0)
// System.out.println("LRUQueue empty: "+_name);
return result;
}
public long getTimeout(Integer group)
{
if (group < _timeouts.length)
return _timeouts[group];
return -1;
}
public T getLast()
{
return _last;
}
}