package freenet.client.async;
import freenet.keys.USK;
import freenet.support.Logger;
/** Proxy class to only pass through latest-slot updates after an onRoundFinished().
* Note that it completely ignores last-known-good updates.
* @author toad
*/
public class USKSparseProxyCallback implements USKProgressCallback {
final USKCallback target;
final USK key;
private long lastEdition;
private long lastSent;
private boolean lastMetadata;
private short lastCodec;
private byte[] lastData;
private boolean lastWasKnownGoodToo;
private boolean roundFinished;
private static volatile boolean logMINOR;
static {
Logger.registerClass(USKSparseProxyCallback.class);
}
public USKSparseProxyCallback(USKCallback cb, USK key) {
target = cb;
lastEdition = -1; // So we see the first one even if it's 0
lastSent = -1;
this.key = key;
if(logMINOR) Logger.minor(this, "Creating sparse proxy callback "+this+" for "+cb+" for "+key);
}
@Override
public void onFoundEdition(long l, USK key,
ClientContext context, boolean metadata, short codec, byte[] data,
boolean newKnownGood, boolean newSlotToo) {
synchronized(this) {
if(l < lastEdition) {
if(!roundFinished) return;
if(!newKnownGood) return;
} else if(l == lastEdition) {
if(newKnownGood) lastWasKnownGoodToo = true;
} else {
lastEdition = l;
lastMetadata = metadata;
lastCodec = codec;
lastData = data;
lastWasKnownGoodToo = newKnownGood;
}
if(!roundFinished) return;
}
target.onFoundEdition(l, key, context, metadata, codec, data, newKnownGood, newSlotToo);
}
@Override
public short getPollingPriorityNormal() {
return target.getPollingPriorityNormal();
}
@Override
public short getPollingPriorityProgress() {
return target.getPollingPriorityProgress();
}
@Override
public void onSendingToNetwork(ClientContext context) {
innerRoundFinished(context, false);
}
@Override
public void onRoundFinished(ClientContext context) {
innerRoundFinished(context, true);
}
private void innerRoundFinished(ClientContext context, boolean finishedRound) {
long ed;
boolean meta;
short codec;
byte[] data;
boolean wasKnownGood;
synchronized(this) {
if(finishedRound)
roundFinished = true;
if(lastSent == lastEdition) return;
lastSent = ed = lastEdition;
meta = lastMetadata;
codec = lastCodec;
data = lastData;
wasKnownGood = lastWasKnownGoodToo;
}
if(ed == -1) {
ed = context.uskManager.lookupLatestSlot(key);
if(ed == -1) return;
meta = false;
codec = -1;
data = null;
wasKnownGood = false;
}
if(ed == -1) return;
target.onFoundEdition(ed, key, context, meta, codec, data, wasKnownGood, wasKnownGood);
}
}