package com.jivesoftware.os.amza.client.http;
import com.google.common.primitives.UnsignedBytes;
import com.jivesoftware.os.amza.api.stream.KeyValueStream;
import java.util.Arrays;
/**
*
* @author jonathan.colt
*/
class QuorumScan {
private final boolean[] used;
private final byte[][] prefix;
private final byte[][] key;
private final byte[][] value;
private final long[] timestamp;
private final boolean[] tombstoned;
private final long[] version;
QuorumScan(int streamerCount) {
this.used = new boolean[streamerCount];
Arrays.fill(this.used, true);
this.prefix = new byte[streamerCount][];
this.key = new byte[streamerCount][];
this.value = new byte[streamerCount][];
this.timestamp = new long[streamerCount];
this.tombstoned = new boolean[streamerCount];
this.version = new long[streamerCount];
}
boolean used(int index) {
return used[index];
}
void fill(int index, byte[] prefix, byte[] key, byte[] value, long timestamp, boolean tombstoned, long version) throws Exception {
this.used[index] = false;
this.prefix[index] = prefix;
this.key[index] = key;
this.value[index] = value;
this.timestamp[index] = timestamp;
this.tombstoned[index] = tombstoned;
this.version[index] = version;
}
boolean stream(int wi, KeyValueStream stream) throws Exception {
this.used[wi] = true;
return stream.stream(this.prefix[wi],
this.key[wi],
this.value[wi],
this.timestamp[wi],
this.tombstoned[wi],
this.version[wi]);
}
int findWinningIndex() {
int wi = -1;
for (int i = 0; i < used.length; i++) {
if (used[i]) {
} else if (wi == -1) {
wi = i;
} else {
wi = winner(wi, i);
}
}
return wi;
}
// Smallest lex ordered key with largest timestamp and largest version
private int winner(int indexA, int indexB) {
if (used[indexA] && used[indexB]) {
return -1;
} else if (used[indexA]) {
return indexB;
} else if (used[indexB]) {
return indexA;
} else {
int c = UnsignedBytes.lexicographicalComparator().compare(key[indexA], key[indexB]);
if (c == 0) {
c = Long.compare(timestamp[indexA], timestamp[indexB]);
if (c == 0) {
c = Long.compare(version[indexA], version[indexB]);
if (c <= 0) {
used[indexA] = true;
return indexB;
} else {
used[indexB] = true;
return indexA;
}
} else if (c < 0) {
used[indexA] = true;
return indexB;
} else {
used[indexB] = true;
return indexA;
}
} else if (c < 0) {
return indexA;
} else {
return indexB;
}
}
}
}