}
}
public VeryLongInteger retrieveHash(final BlockInfo bi, int ttl, int uid, boolean cacheResult) throws IOException,
RetrievalException {
VeryLongInteger lo = _hs.getHash(bi.getHashHashKey());
if (lo != null) {
return lo;
}
HashSet exclude = new HashSet(); // We don't want to bother the seeds with
// requests for hashes
exclude.addAll(_seedNodes);
while (true) {
Peer best = _rt.findClosest(bi.getHashHashKey(), exclude);
if ((ttl == 0) || (best == null) || (bi.getHashHashKey().closerTo(_rt.getPeer().getHash(), best.getHash()))) {
// We are going to download and retrieve it ourselves
VeryLongInteger dataHash = retrieveHashFromServer(bi);
_hs.put(bi.getHashHashKey(), dataHash);
return dataHash;
}
// Ok, we are going to try forwarding it to the next closest peer
_usm.send(best, DMT.createRequestHash(uid, bi, ttl - 1));
Message requestHashAck = _usm.waitFor(MessageFilter.create(5000, DMT.requestHashAck).addType(
DMT.rejectDueToLoop).setField(DMT.UID, uid));
if (requestHashAck == null) {
exclude.add(best);
_rt.recontactPeer(best);
continue;
}
if (requestHashAck.getSpec().equals(DMT.rejectDueToLoop)) {
Logger.warning("requestHash (uid: " + uid + ") rejected by " + requestHashAck.getSource()
+ " due to loop");
exclude.add(best);
continue;
}
Message replyHash = _usm.waitFor(MessageFilter.create(30000, DMT.replyHash).setField(DMT.UID, uid));
if (replyHash == null) {
Logger.info("Timed out waiting for replyHash from " + best);
ttl = 0;
continue;
}
VeryLongInteger dataHash = (VeryLongInteger) replyHash.getObject(DMT.HASH);
if (cacheResult) {
_hs.put(bi.getHashHashKey(), dataHash);
}
return dataHash;
}