package edu.berkeley.thebes.hat.server.dependencies; import com.google.common.collect.ComparisonChain; import com.google.common.collect.Sets; import edu.berkeley.thebes.common.clustering.RoutingHash; import edu.berkeley.thebes.common.config.Config; import edu.berkeley.thebes.common.data.DataItem; import edu.berkeley.thebes.common.data.Version; import edu.berkeley.thebes.common.thrift.ServerAddress; import java.util.Collection; import java.util.List; import java.util.Set; public class PendingWrite implements Comparable<PendingWrite> { private final String key; private final Version transactionVersion; private int numKeysForThisReplica; private Set<Integer> replicaIndicesInvolved; private List<String> transactionKeys; private boolean obsoleted; public PendingWrite(String key, DataItem value, boolean obsoleted) { if (value.getTransactionKeys().isEmpty()) { throw new IllegalStateException("Pending writes must be waiting on at least one other key."); } this.key = key; this.transactionVersion = value.getVersion(); this.transactionKeys = value.getTransactionKeys(); this.obsoleted = obsoleted; examineReplicasInvolved(key, value.getTransactionKeys()); } /** Computes numKeysForThisReplica and replicaIndicesInvolved */ private void examineReplicasInvolved(String key, List<String> transactionKeys) { int numServers = Config.getServersInCluster().size(); Set<Integer> serversInTransaction = Sets.newHashSet(); int myIndex = RoutingHash.hashKey(key, numServers); this.numKeysForThisReplica = 0; for (String transKey : transactionKeys) { int i = RoutingHash.hashKey(transKey, numServers); serversInTransaction.add(i); if (i == myIndex) { numKeysForThisReplica ++; } } if (!serversInTransaction.contains(myIndex)) { System.err.println("WARNINGG: " + serversInTransaction + " does not include me! " + myIndex + " (" + key + " / " + transactionKeys + ")"); } replicaIndicesInvolved = serversInTransaction; } public Set<Integer> getReplicaIndicesInvolved() { return replicaIndicesInvolved; } public int getNumKeysForThisReplica() { return numKeysForThisReplica; } public String getKey() { return key; } public Version getVersion() { return transactionVersion; } public boolean isObsoleted() { return obsoleted; } @Override public int compareTo(PendingWrite o) { return ComparisonChain.start() .compare(getKey(), o.getKey()) .compare(getVersion(), o.getVersion()) .result(); } public String toString() { return String.format("[Key: %s, Version: %s, Deps: %s / LocalKeys: %d, Replicas: %d", key, transactionVersion, transactionKeys, numKeysForThisReplica, replicaIndicesInvolved.size()); } }