package edu.harvard.mcb.leschziner.event; import java.util.Collection; import java.util.Iterator; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import com.hazelcast.core.ICollection; import com.hazelcast.core.ItemListener; import edu.harvard.mcb.leschziner.storage.DefaultStorageEngine; public class BufferedQueue<T> implements BlockingQueue<T>, ICollection<T>, Runnable { // The fast queue we'll absorb events into private final LinkedBlockingQueue<T> bufferQueue; // The slow queue we're buffering against private final BlockingQueue<T> masterQueue; // Thread that grabs elements from the buffer and sends them off private final Thread transferThread; private boolean running; public BufferedQueue(String queueName) { masterQueue = DefaultStorageEngine.getStorageEngine() .getQueue(queueName); bufferQueue = new LinkedBlockingQueue<>(); transferThread = new Thread(this); this.running = true; transferThread.start(); } @Override public boolean add(T target) { return bufferQueue.add(target); } @Override public T poll() { return masterQueue.poll(); } @Override public void addItemListener(ItemListener<T> arg0, boolean arg1) { ((ICollection<T>) masterQueue).addItemListener(arg0, arg1); } @Override public void removeItemListener(ItemListener<T> arg0) { ((ICollection<T>) masterQueue).removeItemListener(arg0); } @Override public boolean addAll(Collection<? extends T> c) { return bufferQueue.addAll(c); } @Override public int remainingCapacity() { return bufferQueue.remainingCapacity(); } @Override public void put(T e) throws InterruptedException { bufferQueue.put(e); } @Override public boolean offer(T e, long timeout, TimeUnit unit) throws InterruptedException { return bufferQueue.offer(e, timeout, unit); } @Override public boolean offer(T e) { return bufferQueue.offer(e); } @Override public int size() { return masterQueue.size(); } @Override public boolean isEmpty() { return masterQueue.isEmpty(); } @Override public T remove() { return masterQueue.remove(); } @Override public T element() { return masterQueue.element(); } @Override public T peek() { return masterQueue.peek(); } @Override public T take() throws InterruptedException { return masterQueue.take(); } @Override public T poll(long timeout, TimeUnit unit) throws InterruptedException { return masterQueue.poll(timeout, unit); } @Override public boolean remove(Object o) { return masterQueue.remove(o); } @Override public boolean contains(Object o) { return masterQueue.contains(o); } @Override public int drainTo(Collection<? super T> c) { return masterQueue.drainTo(c); } @Override public boolean containsAll(Collection<?> c) { return masterQueue.containsAll(c); } @Override public int drainTo(Collection<? super T> c, int maxElements) { return masterQueue.drainTo(c, maxElements); } @Override public boolean removeAll(Collection<?> c) { return masterQueue.removeAll(c); } @Override public boolean retainAll(Collection<?> c) { return masterQueue.retainAll(c); } @Override public void clear() { masterQueue.clear(); } @Override public void run() { while (running) { try { // Grab from the buffer T item = bufferQueue.take(); // Pass it to the master masterQueue.add(item); } catch (InterruptedException e) { // Go around and check that we're still supposed to be // running } } } public void shutdown() { this.running = false; transferThread.interrupt(); } @Override public Iterator<T> iterator() { return masterQueue.iterator(); } @Override public Object[] toArray() { return masterQueue.toArray(); } @Override public <T> T[] toArray(T[] a) { return masterQueue.toArray(a); } @Override public void destroy() { ((ICollection<T>) masterQueue).destroy(); } @Override public Object getId() { return ((ICollection<T>) masterQueue).getId(); } @Override public InstanceType getInstanceType() { return ((ICollection<T>) masterQueue).getInstanceType(); } @Override public String getName() { return ((ICollection<T>) masterQueue).getName(); } }