Author: saces
Date: 2009-04-20 21:21:11 +0000 (Mon, 20 Apr 2009)
New Revision: 27121
Modified:
trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
Log:
teach the SFI how to fetch the new metadata format (ARCHIVE_METADATA_REDIRECT)
needs review
Modified: trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
2009-04-20 21:16:19 UTC (rev 27120)
+++ trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
2009-04-20 21:21:11 UTC (rev 27121)
@@ -114,7 +114,7 @@
/** Copy constructor, modifies a few given fields, don't call
schedule().
* Used for things like slave fetchers for MultiLevelMetadata,
therefore does not remember returnBucket,
* metaStrings etc. */
- public SingleFileFetcher(SingleFileFetcher fetcher, boolean persistent,
boolean deleteFetchContext, Metadata newMeta, GetCompletionCallback callback,
FetchContext ctx2, ObjectContainer container, ClientContext context) throws
FetchException {
+ public SingleFileFetcher(SingleFileFetcher fetcher, boolean persistent,
boolean deleteFetchContext, Metadata newMeta, ArrayList<String> metaStrings2,
GetCompletionCallback callback, FetchContext ctx2, ObjectContainer container,
ClientContext context) throws FetchException {
// Don't add a block, we have already fetched the data, we are
just handling the metadata in a different fetcher.
super(persistent ? fetcher.key.cloneKey() : fetcher.key,
fetcher.maxRetries, ctx2, fetcher.parent, callback, false, true, fetcher.token,
container, context, deleteFetchContext);
if(logMINOR) Logger.minor(this, "Creating SingleFileFetcher for
"+fetcher.key+" meta="+fetcher.metaStrings.toString(), new Exception("debug"));
@@ -128,7 +128,7 @@
this.archiveMetadata = null;
this.clientMetadata = (fetcher.clientMetadata != null ?
fetcher.clientMetadata.clone() : new ClientMetadata());
this.metadata = newMeta;
- this.metaStrings = new ArrayList<String>();
+ this.metaStrings = metaStrings2;
this.addedMetaStrings = 0;
this.recursionLevel = fetcher.recursionLevel + 1;
if(recursionLevel > ctx.maxRecursionLevel)
@@ -471,6 +471,83 @@
}
metadataBucket.free();
continue;
+ } else if(metadata.isArchiveMetadataRedirect()) {
+ if(logMINOR) Logger.minor(this, "Is
archive-metadata");
+ // Fetch it from the archive
+ if(ah == null)
+ throw new
FetchException(FetchException.UNKNOWN_METADATA, "Archive redirect not in an
archive manifest");
+ String filename =
metadata.getArchiveInternalName();
+ if(logMINOR) Logger.minor(this, "Fetching
"+filename);
+ Bucket dataBucket = ah.get(filename, actx,
context.archiveManager);
+ if(dataBucket != null) {
+ if(logMINOR) Logger.minor(this,
"Returning data");
+ final Metadata newMetadata;
+ try {
+
+ newMetadata =
Metadata.construct(dataBucket);
+ dataBucket.free();
+ } catch (IOException e) {
+ throw new
FetchException(FetchException.BUCKET_ERROR);
+ }
+ continueWithNewMetadata(newMetadata,
this.rcb, container, context);
+ return;
+ } else {
+ if(logMINOR) Logger.minor(this,
"Fetching archive (thisKey="+thisKey+ ')');
+ // Metadata cannot contain pointers to
files which don't exist.
+ // We enforce this in ArchiveHandler.
+ // Therefore, the archive needs to be
fetched.
+ final boolean persistent =
this.persistent;
+ fetchArchive(true, archiveMetadata,
filename, new ArchiveExtractCallback() {
+ public void gotBucket(Bucket
data, ObjectContainer container, ClientContext context) {
+ if(persistent)
+
container.activate(SingleFileFetcher.this, 1);
+ if(logMINOR)
Logger.minor(this, "Returning data");
+ final Metadata
newMetadata;
+ try {
+
+ newMetadata =
Metadata.construct(data);
+
continueWithNewMetadata(newMetadata, SingleFileFetcher.this.rcb, container,
context);
+ } catch (IOException e)
{
+ onFailure(new
FetchException(FetchException.BUCKET_ERROR), false, container, context);
+ } catch
(MetadataParseException e) {
+ onFailure(new
FetchException(FetchException.INVALID_METADATA), false, container, context);
+ } catch (FetchException
e) {
+ onFailure(e,
false, container, context);
+ } finally {
+ data.free();
+ }
+ if(persistent)
+
container.deactivate(SingleFileFetcher.this, 1);
+ }
+ public void
notInArchive(ObjectContainer container, ClientContext context) {
+ if(persistent)
+
container.activate(SingleFileFetcher.this, 1);
+ onFailure(new
FetchException(FetchException.NOT_IN_ARCHIVE), false, container, context);
+ if(persistent)
+
container.deactivate(SingleFileFetcher.this, 1);
+ }
+ public void
onFailed(ArchiveRestartException e, ObjectContainer container, ClientContext
context) {
+ if(persistent)
+
container.activate(SingleFileFetcher.this, 1);
+
SingleFileFetcher.this.onFailure(new FetchException(e), false, container,
context);
+ if(persistent)
+
container.deactivate(SingleFileFetcher.this, 1);
+ }
+ public void
onFailed(ArchiveFailureException e, ObjectContainer container, ClientContext
context) {
+ if(persistent)
+
container.activate(SingleFileFetcher.this, 1);
+
SingleFileFetcher.this.onFailure(new FetchException(e), false, container,
context);
+ if(persistent)
+
container.deactivate(SingleFileFetcher.this, 1);
+ }
+ public void
removeFrom(ObjectContainer container) {
+ container.delete(this);
+ }
+ }, container, context);
+ removeMetadata(container);
+ // Will call back into this function
when it has been fetched.
+ return;
+ }
} else if(metadata.isArchiveInternalRedirect()) {
if(logMINOR) Logger.minor(this, "Is
archive-internal redirect");
clientMetadata.mergeNoOverwrite(metadata.getClientMetadata());
@@ -576,18 +653,7 @@
if(logMINOR) Logger.minor(this, "Is multi-level
metadata");
// Fetch on a second SingleFileFetcher, like
with archives.
metadata.setSimpleRedirect();
- final SingleFileFetcher f = new
SingleFileFetcher(this, persistent, false, metadata, new
MultiLevelMetadataCallback(), ctx, container, context);
- // Clear our own metadata so it can be garbage
collected, it will be replaced by whatever is fetched.
- // The new fetcher has our metadata so we don't
need to removeMetadata().
- this.metadata = null;
- if(persistent) container.store(this);
- if(persistent) container.store(f);
-
- // We must transition to the sub-fetcher so
that if the request is cancelled, it will get deleted.
- parent.onTransition(this, f, container);
-
- f.wrapHandleMetadata(true, container, context);
- if(persistent) container.deactivate(f, 1);
+ continueWithNewMetadata(metadata, new
MultiLevelMetadataCallback(), container, context);
return;
} else if(metadata.isSingleFileRedirect()) {
if(logMINOR) Logger.minor(this, "Is single-file
redirect");
@@ -768,6 +834,22 @@
}
}
}
+
+ private void continueWithNewMetadata(Metadata newMetadata,
GetCompletionCallback callback, ObjectContainer container, ClientContext
context) throws FetchException {
+ final SingleFileFetcher f = new SingleFileFetcher(this,
persistent, false, newMetadata, metaStrings, callback, ctx, container, context);
+ // Clear our own metadata so it can be garbage collected, it
will be replaced by whatever is fetched.
+ // The new fetcher has our metadata so we don't need to
removeMetadata().
+ metadata = null;
+ if(persistent) container.store(this);
+ if(persistent) container.store(f);
+
+ // We must transition to the sub-fetcher so that if the request
is cancelled, it will get deleted.
+ parent.onTransition(this, f, container);
+
+ f.wrapHandleMetadata(true, container, context);
+ if(persistent) container.deactivate(f, 1);
+ return;
+ }
private String removeMetaString() {
String name = metaStrings.remove(0);
@@ -792,7 +874,7 @@
Metadata newMeta = (Metadata) meta.clone();
newMeta.setSimpleRedirect();
final SingleFileFetcher f;
- f = new SingleFileFetcher(this, persistent, true, newMeta, new
ArchiveFetcherCallback(forData, element, callback), new FetchContext(ctx,
FetchContext.SET_RETURN_ARCHIVES, true, null), container, context);
+ f = new SingleFileFetcher(this, persistent, true, newMeta, new
ArrayList<String>(), new ArchiveFetcherCallback(forData, element, callback),
new FetchContext(ctx, FetchContext.SET_RETURN_ARCHIVES, true, null), container,
context);
if(persistent) container.store(f);
if(logMINOR) Logger.minor(this, "fetchArchive(): "+f);
// Fetch the archive. The archive fetcher callback will unpack
it, and either call the element
_______________________________________________
cvs mailing list
[email protected]
http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs