/** * A non-authoritative hint that a specific edition *might* exist. At the moment, we just fetch * the block. We do not fetch the contents, and it is possible that USKFetcher's are also fetching * the block. FIXME would it be more efficient to pass it along to a USKFetcher? * * @param context * @throws MalformedURLException If the uri passed in is not a USK. */ public void hintUpdate(FreenetURI uri, ClientContext context, short priority) throws MalformedURLException { if (uri.getSuggestedEdition() < lookupLatestSlot(USK.create(uri))) { if (logMINOR) Logger.minor( this, "Ignoring hint because edition is " + uri.getSuggestedEdition() + " but latest is " + lookupLatestSlot(USK.create(uri))); return; } uri = uri.sskForUSK(); if (logMINOR) Logger.minor(this, "Doing hint fetch for " + uri); final ClientGetter get = new ClientGetter( new NullClientCallback(), uri, new FetchContext(backgroundFetchContext, FetchContext.IDENTICAL_MASK, false, null), priority, rcBulk, new NullBucket(), null, null); try { get.start(null, context); } catch (FetchException e) { if (logMINOR) Logger.minor(this, "Cannot start hint fetch for " + uri + " : " + e, e); // Ignore } }
/** * Simply check whether the block exists, in such a way that we don't fetch the full content. If * it does exist then the USK tracker, and therefore any fetchers, will be updated. You can pass * either an SSK or a USK. */ public void hintCheck( FreenetURI uri, final Object token, ClientContext context, short priority, final HintCallback cb) throws MalformedURLException { final FreenetURI origURI = uri; if (uri.isUSK()) uri = uri.sskForUSK(); if (logMINOR) Logger.minor(this, "Doing hint fetch for " + uri); final ClientGetter get = new ClientGetter( new ClientGetCallback() { @Override public void onMajorProgress(ObjectContainer container) { // Ignore } @Override public void onSuccess( FetchResult result, ClientGetter state, ObjectContainer container) { cb.success(origURI, token); } @Override public void onFailure( FetchException e, ClientGetter state, ObjectContainer container) { if (e.isDataFound()) cb.success(origURI, token); else if (e.isDNF()) cb.dnf(origURI, token, e); else cb.failed(origURI, token, e); } }, uri, new FetchContext(backgroundFetchContext, FetchContext.IDENTICAL_MASK, false, null), priority, rcBulk, new NullBucket(), null, null); try { get.start(null, context); } catch (FetchException e) { if (logMINOR) Logger.minor(this, "Cannot start hint fetch for " + uri + " : " + e, e); if (e.isDataFound()) cb.success(origURI, token); else if (e.isDNF()) cb.dnf(origURI, token, e); else cb.failed(origURI, token, e); } }
/** * A non-authoritative hint that a specific edition *might* exist. At the moment, we just fetch * the block. We do not fetch the contents, and it is possible that USKFetcher's are also fetching * the block. FIXME would it be more efficient to pass it along to a USKFetcher? * * @param usk * @param edition * @param context */ public void hintUpdate(USK usk, long edition, ClientContext context) { if (edition < lookupLatestSlot(usk)) return; FreenetURI uri = usk.copy(edition).getURI().sskForUSK(); final ClientGetter get = new ClientGetter( new NullClientCallback(), uri, new FetchContext(backgroundFetchContext, FetchContext.IDENTICAL_MASK, false, null), RequestStarter.UPDATE_PRIORITY_CLASS, rcBulk, new NullBucket(), null, null); try { get.start(null, context); } catch (FetchException e) { // Ignore } }
@Override public void run() { if (logDEBUG) Logger.debug(this, "Running prefetch checker..."); ArrayList<USK> toFetch = null; long now = System.currentTimeMillis(); boolean empty = true; synchronized (USKManager.this) { for (Map.Entry<USK, Long> entry : temporaryBackgroundFetchersPrefetch.entrySet()) { empty = false; if (entry.getValue() > 0 && now - entry.getValue() >= PREFETCH_DELAY) { if (toFetch == null) toFetch = new ArrayList<USK>(); USK clear = entry.getKey(); long l = lookupLatestSlot(clear); if (lookupKnownGood(clear) < l) toFetch.add(clear.copy(l)); entry.setValue(-1L); // Reset counter until new data comes in } else { if (logMINOR) Logger.minor( this, "Not prefetching: " + entry.getKey() + " : " + entry.getValue()); } } } if (toFetch == null) return; for (final USK key : toFetch) { final long l = key.suggestedEdition; if (logMINOR) Logger.minor( this, "Prefetching content for background fetch for edition " + l + " on " + key); FetchContext fctx = new FetchContext(realFetchContext, FetchContext.IDENTICAL_MASK, false, null); final ClientGetter get = new ClientGetter( new ClientGetCallback() { @Override public void onFailure( FetchException e, ClientGetter state, ObjectContainer container) { if (e.newURI != null) { if (logMINOR) Logger.minor(this, "Prefetch succeeded with redirect for " + key); updateKnownGood(key, l, context); return; } else { if (logMINOR) Logger.minor(this, "Prefetch failed later: " + e + " for " + key, e); // Ignore } } @Override public void onSuccess( FetchResult result, ClientGetter state, ObjectContainer container) { if (logMINOR) Logger.minor(this, "Prefetch succeeded for " + key); result.asBucket().free(); updateKnownGood(key, l, context); } @Override public void onMajorProgress(ObjectContainer container) { // Ignore } }, key.getURI().sskForUSK() /* FIXME add getSSKURI() */, fctx, RequestStarter.UPDATE_PRIORITY_CLASS, rcBulk, new NullBucket(), null, null); try { get.start(null, context); } catch (FetchException e) { if (logMINOR) Logger.minor(this, "Prefetch failed: " + e, e); // Ignore } } if (!empty) schedulePrefetchChecker(); }