package org.limewire.mojito.manager;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.limewire.concurrent.OnewayExchanger;
import org.limewire.mojito.Context;
import org.limewire.mojito.KUID;
import org.limewire.mojito.handler.response.FindNodeResponseHandler;
import org.limewire.mojito.result.FindNodeResult;
/**
* A worker thread that continuously refreshes buckets provided by the BootstrapProcess.
*/
class BootstrapWorker implements Runnable {
private static final Log LOG = LogFactory.getLog(BootstrapWorker.class);
private final BootstrapProcess process;
private final Context context;
private volatile OnewayExchanger<FindNodeResult, ExecutionException> exchanger;
private final AtomicBoolean shutdown = new AtomicBoolean();
BootstrapWorker(Context context, BootstrapProcess process){
this.process = process;
this.context = context;
}
public void run() {
LOG.debug("starting worker");
while(!shutdown.get()) {
KUID nextBucket = process.getNextBucket();
if (LOG.isDebugEnabled())
LOG.debug(this+" will refresh "+nextBucket);
if (nextBucket == null)
return;
refreshBucket(nextBucket);
}
}
private void refreshBucket(KUID randomId) {
OnewayExchanger<FindNodeResult, ExecutionException> c
= new OnewayExchanger<FindNodeResult, ExecutionException>(true);
FindNodeResponseHandler handler
= new FindNodeResponseHandler(context, randomId);
handler.start(c);
exchanger = c;
FindNodeResult value = null;
try {
value = c.get();
} catch (InterruptedException ignore) {}
catch (CancellationException cancelled) {
if (!shutdown.get())
throw new IllegalStateException(cancelled);
}
catch (ExecutionException ee) {
LOG.info("ExecutionException", ee);
process.handleExecutionException(ee);
}
if (value == null)
return;
if (LOG.isTraceEnabled()) {
LOG.trace("Finished Bucket refresh: " + value);
}
process.refreshDone(value.getRouteTableFailureCount(), !value.getPath().isEmpty());
}
public void shutdown() {
if (shutdown.getAndSet(true))
return;
OnewayExchanger<FindNodeResult, ExecutionException> e = exchanger;
if (e != null)
e.cancel();
}
}