package edu.brown.hstore;
import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;
import edu.brown.hstore.internal.FinishTxnMessage;
import edu.brown.hstore.internal.InternalMessage;
import edu.brown.hstore.internal.InternalTxnMessage;
import edu.brown.hstore.internal.PrepareTxnMessage;
import edu.brown.hstore.internal.SetDistributedTxnMessage;
import edu.brown.hstore.internal.WorkFragmentMessage;
import edu.brown.hstore.internal.UtilityWorkMessage;
public class PartitionMessageQueue extends PriorityBlockingQueue<InternalMessage> {
private static final long serialVersionUID = 1L;
// private List<InternalMessage> swap = null;
public PartitionMessageQueue() {
super(100000, WORK_COMPARATOR); // FIXME
}
// @Override
// public int drainTo(Collection<? super InternalMessage> c) {
// assert(c != null);
// InternalMessage msg = null;
// int ctr = 0;
//
// if (this.swap == null) {
// this.swap = new ArrayList<InternalMessage>();
// } else {
// this.swap.clear();
// }
//
// while ((msg = this.poll()) != null) {
// // All new transaction requests must be put in the new collection
// if (msg instanceof InitializeRequestMessage) {
// c.add(msg);
// ctr++;
// // Everything else will get added back in afterwards
// } else {
// this.swap.add(msg);
// }
// } // WHILE
// if (this.swap.isEmpty() == false) this.addAll(this.swap);
// return (ctr);
// }
private static final Comparator<InternalMessage> WORK_COMPARATOR = new Comparator<InternalMessage>() {
@SuppressWarnings("unchecked")
private final Class<? extends InternalMessage> compareOrder[] = (Class<? extends InternalMessage>[])new Class<?>[]{
SetDistributedTxnMessage.class,
PrepareTxnMessage.class,
FinishTxnMessage.class,
WorkFragmentMessage.class,
};
@Override
public int compare(InternalMessage msg0, InternalMessage msg1) {
assert(msg0 != null) : "Unexpected null message [msg0]";
assert(msg1 != null) : "Unexpected null message [msg1]";
Class<?> class0 = msg0.getClass();
Class<?> class1 = msg1.getClass();
boolean isUtl0 = class0.equals(UtilityWorkMessage.TableStatsRequestMessage.class);
boolean isUtl1 = class1.equals(UtilityWorkMessage.TableStatsRequestMessage.class);
if (isUtl0 && !isUtl1) return -1;
if (!isUtl0 && isUtl1) return 1;
// Always compare Transaction Ids first
boolean isTxn0 = (msg0 instanceof InternalTxnMessage);
boolean isTxn1 = (msg1 instanceof InternalTxnMessage);
if (isTxn0 && isTxn1) {
// If they're both for the same txn, then use the compareOrder
Long txnId0 = ((InternalTxnMessage)msg0).getTransactionId();
assert(txnId0 != null) : "Unexpected null txnId for " + msg0;
Long txnId1 = ((InternalTxnMessage)msg1).getTransactionId();
assert(txnId1 != null) : "Unexpected null txnId for " + msg1;
// Compare TxnIds
int result = txnId0.compareTo(txnId1);
if (result != 0) return (result);
// Rank them based on their message type
// This prevents us from removing a txn before it's been added
if (class0.equals(class1) == false) {
for (Class<? extends InternalMessage> clazz : compareOrder) {
boolean isMatch0 = class0.equals(clazz);
boolean isMatch1 = class1.equals(clazz);
if (isMatch0 && !isMatch1) return (-1);
else if (!isMatch0 && isMatch1) return (1);
} // FOR
}
}
else if (isTxn0) {
return (-1);
} else if (isTxn1) {
return (1);
}
// Last Resort: Just use hashCode
return msg0.hashCode() - msg1.hashCode();
}
};
}