Author: toad
Date: 2005-10-26 18:55:15 +0000 (Wed, 26 Oct 2005)
New Revision: 7453
Modified:
trunk/freenet/src/freenet/client/ArchiveContext.java
trunk/freenet/src/freenet/client/ArchiveElement.java
trunk/freenet/src/freenet/client/ArchiveHandler.java
trunk/freenet/src/freenet/client/FetchException.java
trunk/freenet/src/freenet/client/FetchResult.java
trunk/freenet/src/freenet/client/Fetcher.java
trunk/freenet/src/freenet/keys/ClientKey.java
trunk/freenet/src/freenet/keys/FreenetURI.java
Log:
Major simplifications through recursiveness.
Modified: trunk/freenet/src/freenet/client/ArchiveContext.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveContext.java 2005-10-26
00:54:42 UTC (rev 7452)
+++ trunk/freenet/src/freenet/client/ArchiveContext.java 2005-10-26
18:55:15 UTC (rev 7453)
@@ -3,6 +3,7 @@
import java.util.HashSet;
import freenet.keys.ClientKey;
+import freenet.keys.FreenetURI;
/**
* Object passed down a full fetch, including all the recursion.
Modified: trunk/freenet/src/freenet/client/ArchiveElement.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveElement.java 2005-10-26
00:54:42 UTC (rev 7452)
+++ trunk/freenet/src/freenet/client/ArchiveElement.java 2005-10-26
18:55:15 UTC (rev 7453)
@@ -20,7 +20,7 @@
}
final ArchiveManager manager;
- final FreenetURI key;
+ final ClientKey key;
final String filename;
final short archiveType;
@@ -33,9 +33,10 @@
* @throws FetchException If we could not fetch the key.
* @throws MetadataParseException If the key's metadata was invalid.
*/
- public Bucket get(ArchiveContext archiveContext, FetcherContext
fetchContext, boolean inSplitZipManifest) throws ArchiveFailureException,
MetadataParseException, FetchException, ArchiveRestartException {
+ public Bucket get(ArchiveContext archiveContext, FetcherContext
fetchContext, boolean inSplitZipManifest)
+ throws ArchiveFailureException, MetadataParseException, FetchException,
ArchiveRestartException {
- archiveContext.doLoopDetection(ckey);
+ archiveContext.doLoopDetection(key);
// AFTER the loop check (possible deadlocks)
synchronized(this) {
// Synchronized during I/O to avoid doing it twice
Modified: trunk/freenet/src/freenet/client/ArchiveHandler.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveHandler.java 2005-10-26
00:54:42 UTC (rev 7452)
+++ trunk/freenet/src/freenet/client/ArchiveHandler.java 2005-10-26
18:55:15 UTC (rev 7453)
@@ -1,6 +1,7 @@
package freenet.client;
import freenet.keys.ClientKey;
+import freenet.keys.FreenetURI;
import freenet.support.Bucket;
/**
@@ -9,10 +10,10 @@
class ArchiveHandler {
private ArchiveManager manager;
- private ClientKey key;
+ private FreenetURI key;
private short archiveType;
- public ArchiveHandler(ArchiveManager manager, ClientKey key, short
archiveType) {
+ public ArchiveHandler(ArchiveManager manager, FreenetURI key, short
archiveType) {
this.manager = manager;
this.key = key;
this.archiveType = archiveType;
@@ -24,8 +25,10 @@
/**
* Get the metadata for this ZIP manifest, as a Bucket.
+ * @throws FetchException If the container could not be fetched.
+ * @throws MetadataParseException If there was an error parsing
intermediary metadata.
*/
- public Bucket getMetadata(ArchiveContext archiveContext, FetcherContext
fetchContext) throws ArchiveFailureException, ArchiveRestartException {
+ public Bucket getMetadata(ArchiveContext archiveContext, FetcherContext
fetchContext) throws ArchiveFailureException, ArchiveRestartException,
MetadataParseException, FetchException {
return get(".metadata", archiveContext, fetchContext, false);
}
@@ -36,8 +39,10 @@
* @param inSplitZipManifest If true, indicates that the key points to
a splitfile zip manifest,
* which means that we need to pass a flag to the fetcher to tell it to
pretend it was a straight
* splitfile.
+ * @throws FetchException
+ * @throws MetadataParseException
*/
- public synchronized Bucket get(String internalName, ArchiveContext
archiveContext, FetcherContext fetchContext, boolean inSplitZipManifest) throws
ArchiveFailureException, ArchiveRestartException {
+ public synchronized Bucket get(String internalName, ArchiveContext
archiveContext, FetcherContext fetchContext, boolean inSplitZipManifest) throws
ArchiveFailureException, ArchiveRestartException, MetadataParseException,
FetchException {
ArchiveElement element =
manager.makeElement(key, internalName, archiveType);
return element.get(archiveContext, fetchContext,
inSplitZipManifest);
Modified: trunk/freenet/src/freenet/client/FetchException.java
===================================================================
--- trunk/freenet/src/freenet/client/FetchException.java 2005-10-26
00:54:42 UTC (rev 7452)
+++ trunk/freenet/src/freenet/client/FetchException.java 2005-10-26
18:55:15 UTC (rev 7453)
@@ -36,4 +36,8 @@
static final int TOO_MANY_METADATA_LEVELS = 7;
/** Too many archive restarts */
static final int TOO_MANY_ARCHIVE_RESTARTS = 8;
+ /** Too deep recursion */
+ static final int TOO_MUCH_RECURSION = 9;
+ /** Tried to access an archive file but not in an archive */
+ static final int NOT_IN_ARCHIVE = 10;
}
Modified: trunk/freenet/src/freenet/client/FetchResult.java
===================================================================
--- trunk/freenet/src/freenet/client/FetchResult.java 2005-10-26 00:54:42 UTC
(rev 7452)
+++ trunk/freenet/src/freenet/client/FetchResult.java 2005-10-26 18:55:15 UTC
(rev 7453)
@@ -10,21 +10,14 @@
*/
public class FetchResult {
- final boolean succeeded;
final ClientMetadata metadata;
final Bucket data;
public FetchResult(ClientMetadata dm, Bucket fetched) {
metadata = dm;
data = fetched;
- succeeded = true;
}
- /** Did it succeed? */
- public boolean succeeded() {
- return succeeded;
- }
-
/** If so, get the MIME type */
public String getMimeType() {
return metadata.getMIMEType();
Modified: trunk/freenet/src/freenet/client/Fetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/Fetcher.java 2005-10-26 00:54:42 UTC
(rev 7452)
+++ trunk/freenet/src/freenet/client/Fetcher.java 2005-10-26 18:55:15 UTC
(rev 7453)
@@ -1,6 +1,7 @@
package freenet.client;
import java.io.IOException;
+import java.util.LinkedList;
import freenet.keys.ClientKey;
import freenet.keys.FreenetURI;
@@ -28,7 +29,8 @@
public FetchResult run() throws FetchException {
for(int i=0;i<ctx.maxArchiveRestarts;i++) {
try {
- return realRun(false);
+ ClientMetadata dm = new ClientMetadata();
+ return realRun(dm, 0, origURI);
} catch (ArchiveRestartException e) {
archiveContext = new ArchiveContext();
continue;
@@ -44,144 +46,107 @@
}
/**
- * Run the actual fetch.
- * @param overrideZipManifest
- * @return The result of the fetch - successful or not.
- * @throws FetchException
- * @throws MetadataParseException
- * @throws ArchiveFailureException
+ * Fetch a key.
+ * @param dm The client metadata object to accumulate client metadata
in.
+ * @param recursionLevel The recursion level. Incremented every time we
enter
+ * realRun(). If it goes above a certain limit, we throw a
FetchException.
+ * @param uri The URI to fetch.
+ * @return The data, complete with client metadata.
+ * @throws FetchException If we could not fetch the data.
+ * @throws MetadataParseException If we could not parse the metadata.
+ * @throws ArchiveFailureException If we could not extract data from an
archive.
*/
- public FetchResult realRun(boolean overrideZipManifest) throws
FetchException, ArchiveRestartException, MetadataParseException,
ArchiveFailureException {
- FreenetURI uri = origURI;
- ClientKey key = ClientKey.get(origURI);
- ClientMetadata dm = new ClientMetadata();
- ArchiveHandler zip = null;
+ FetchResult realRun(ClientMetadata dm, int recursionLevel, FreenetURI
uri)
+ throws FetchException, MetadataParseException, ArchiveFailureException {
+ ClientKey key = ClientKey.getBaseKey(uri);
+ LinkedList metaStrings = uri.listMetaStrings();
- for(int i=0;i<ctx.maxRedirects;i++) {
- // We have moved on to a new key, so we are not in the
same ZIP
- zip = null;
-
- // Fetch the first key
- KeyBlock block = ctx.client.getKey(key);
-
- byte[] data;
+ recursionLevel++;
+ if(recursionLevel > ctx.maxRecursionLevel)
+ throw new
FetchException(FetchException.TOO_MUCH_RECURSION);
+
+ // Do the fetch
+ KeyBlock block = ctx.client.getKey(key);
+
+ byte[] data;
+ try {
+ data = block.decode(key);
+ } catch (KeyDecodeException e1) {
+ throw new
FetchException(FetchException.BLOCK_DECODE_ERROR);
+ }
+
+ if(!key.isMetadata()) {
+ // Just return the data
try {
- data = block.decode(key);
- } catch (KeyDecodeException e1) {
- throw new
FetchException(FetchException.BLOCK_DECODE_ERROR);
+ return new FetchResult(dm,
BucketTools.makeImmutableBucket(ctx.bucketFactory, data));
+ } catch (IOException e) {
+ Logger.error(this, "Could not capture data -
disk full?: "+e, e);
}
-
- if(!key.isMetadata()) {
- // Just return the data
- try {
- return new FetchResult(dm,
BucketTools.makeImmutableBucket(ctx.bucketFactory, data));
- } catch (IOException e) {
- Logger.error(this, "Could not capture
data - disk full?: "+e, e);
- }
+ }
+
+ // Otherwise we need to parse the metadata
+
+ Metadata metadata = Metadata.construct(data);
+
+ return runMetadata(recursionLevel, key, metaStrings, metadata,
null, key.toURI());
+ }
+
+ /**
+ * Fetch data, from metadata.
+ * @param recursionLevel The recursion level, from above. Not
incremented here, as we will
+ * go through realRun() if the key changes, so the number of passes
here is severely limited.
+ * @param key The key being fetched.
+ * @param metaStrings List of unused meta strings (to be used by
manifests).
+ * @param metadata The parsed metadata to process.
+ * @param container The container in which this metadata is found.
+ * @return
+ * @throws MetadataParseException If we could not parse metadata from a
sub-document. Will be
+ * converted to a FetchException above.
+ * @throws ArchiveFailureException If extracting data from an archive
failed.
+ * @throws FetchException If the fetch failed for some reason.
+ */
+ private FetchResult runMetadata(ClientMetadata dm, int recursionLevel,
ClientKey key, LinkedList metaStrings, Metadata metadata, ArchiveHandler
container, FreenetURI thisKey) throws MetadataParseException, FetchException,
ArchiveFailureException {
+
+ if(metadata.isSimpleManifest()) {
+ String name = (String) metaStrings.removeFirst();
+ // Since metadata is a document, we just replace
metadata here
+ if(name == null) {
+ metadata = metadata.getDefaultDocument();
+ } else {
+ metadata = metadata.getDocument(name);
+ thisKey = (FreenetURI) thisKey.clone();
+ thisKey = thisKey.pushMetaString(name);
}
-
- // Else need to parse the metadata
- // This will throw if it finds an error, including
semi-errors
- // such as too-big-indirect-metadata
- Metadata metadata = Metadata.construct(data);
- if(overrideZipManifest) {
- if(metadata.isArchiveManifest())
- metadata.setSimpleRedirect();
- else
- throw new
ArchiveRestartException("Override zip manifest set but not a zip manifest!");
+ return runMetadata(dm, recursionLevel, key,
metaStrings, metadata, container, thisKey);
+ } else if(metadata.isArchiveManifest()) {
+ container = ctx.archiveManager.makeHandler(key,
metadata.getArchiveType());
+ Bucket metadataBucket =
container.getMetadata(archiveContext, ctx);
+ metadata = Metadata.construct(metadataBucket);
+ return runMetadata(dm, recursionLevel+1, key,
metaStrings, metadata, container, thisKey);
+ } else if(metadata.isArchiveInternalRedirect()) {
+ if(container == null)
+ throw new
FetchException(FetchException.NOT_IN_ARCHIVE);
+ else {
+ // FIXME
+ Bucket result =
container.get(metadata.getZIPInternalName(), archiveContext, ctx, false);
+
dm.mergeNoOverwrite(metadata.getClientMetadata());
+ return new FetchResult(dm, result);
}
-
- while(true) {
-
- /** Is set false every time we get a new key. */
- boolean inSplitZipManifest = false;
-
- if(metadata == null && key != null) {
- // Try next key
- break;
- }
-
- if(metadata.isSimpleManifest()) {
- // Need a name from the URI
- String name = uri.getMetaString();
-
- // Since metadata is a document, we
just replace metadata here
- if(name == null) {
- metadata =
metadata.getDefaultDocument();
- } else {
- metadata =
metadata.getDocument(name);
- uri = uri.popMetaString();
- }
- continue; // process the new metadata
- } else if(metadata.isSingleFileRedirect()) {
- key =
ClientKey.get(metadata.getSingleTarget());
- if(metadata.isArchiveManifest()) {
- zip =
ctx.archiveManager.makeHandler(key, metadata.getArchiveType());
- Bucket metadataBucket =
zip.getMetadata(archiveContext, ctx);
- metadata =
Metadata.construct(metadataBucket);
- continue;
- }
- metadata = null;
-
dm.mergeNoOverwrite(metadata.getClientMetadata());
- continue;
- } else if(metadata.isArchiveInternalRedirect()
&& zip != null) {
- /** This is the whole document:
- * Metadata: ZIP manifest -> fetch ZIP
file, read .metadata
- * .metadata: simple manifest -> look
up filename ->
- * filename's document -> is
ZIP-internal-redirect
- * Only valid if we are in a ZIP
manifest.
- *
- * Now, retreive the data
- */
- Bucket result =
zip.get(metadata.getZIPInternalName(), archiveContext, ctx, inSplitZipManifest);
-
dm.mergeNoOverwrite(metadata.getClientMetadata());
- return new FetchResult(dm, result);
- } else if(metadata.isSplitfile()) {
-
- if(metadata.isArchiveManifest()) {
- // Check the cache first
- zip =
ctx.archiveManager.makeHandler(key, metadata.getArchiveType());
- // Future
ArchiveInternalRedirects will point to *self*
- inSplitZipManifest = true;
- Bucket metadataBucket =
zip.getMetadata(archiveContext, null);
- if(metadataBucket != null) {
- metadata =
Metadata.construct(metadataBucket);
- continue;
- }
- }
-
- int j;
- for(j=0;j<ctx.maxLevels;j++) {
- SplitFetcher sf = new
SplitFetcher(metadata, ctx.maxTempLength, archiveContext, ctx);
- Bucket sfResult = sf.fetch();
// will throw in event of error
-
-
if(metadata.isSimpleSplitfile()) {
- return new
FetchResult(metadata.getClientMetadata(), sfResult);
- } else
if(metadata.isMultiLevelMetadata()) {
- metadata =
Metadata.construct(sfResult);
-
if(!metadata.isMultiLevelMetadata())
- break; // try
the new metadata
- } else
if(metadata.isArchiveManifest()) {
- // Use the new metadata
- // ZIP points to
current key
- Bucket metadataBucket =
zip.getMetadata(archiveContext, ctx);
- metadata =
Metadata.construct(metadataBucket);
- break;
- } else {
- throw new
FetchException(FetchException.UNKNOWN_SPLITFILE_METADATA);
- }
- } // loop (splitfile levels)
- if(j>=ctx.maxLevels) {
- throw new
FetchException(FetchException.TOO_MANY_METADATA_LEVELS);
- // Too many levels
- // FIXME: throw something
- }
- } else {
- throw new
FetchException(FetchException.UNKNOWN_METADATA);
- }
- } // loop (metadata)
+ } else if(metadata.isMultiLevelMetadata()) {
+ // Doesn't have to be a splitfile; could be from a ZIP
or a plain file.
+ metadata.setSimpleRedirect();
+ FetchResult res = runMetadata(dm, recursionLevel, key,
metaStrings, metadata, container);
+ metadata = Metadata.construct(res.data);
+ return runMetadata(dm, recursionLevel, key,
metaStrings, metadata, container);
+ } else if(metadata.isSingleFileRedirect()) {
+ FreenetURI uri = metadata.getSingleTarget();
+ dm.mergeNoOverwrite(metadata.getClientMetadata());
+ return realRun(dm, recursionLevel, uri);
+ } else if(metadata.isSplitfile()) {
+ SplitFetcher sf = new SplitFetcher(metadata,
ctx.maxTempLength, archiveContext, ctx);
+ Bucket sfResult = sf.fetch(); // will throw in event of
error
+ return new FetchResult(dm, sfResult);
}
- // Too many redirects
- throw new FetchException(FetchException.TOO_MANY_REDIRECTS);
}
+
}
Modified: trunk/freenet/src/freenet/keys/ClientKey.java
===================================================================
--- trunk/freenet/src/freenet/keys/ClientKey.java 2005-10-26 00:54:42 UTC
(rev 7452)
+++ trunk/freenet/src/freenet/keys/ClientKey.java 2005-10-26 18:55:15 UTC
(rev 7453)
@@ -6,7 +6,7 @@
*/
public abstract class ClientKey {
- public static ClientKey get(FreenetURI origURI) {
+ public static ClientKey getBaseKey(FreenetURI origURI) {
// TODO Auto-generated method stub
return null;
}
Modified: trunk/freenet/src/freenet/keys/FreenetURI.java
===================================================================
--- trunk/freenet/src/freenet/keys/FreenetURI.java 2005-10-26 00:54:42 UTC
(rev 7452)
+++ trunk/freenet/src/freenet/keys/FreenetURI.java 2005-10-26 18:55:15 UTC
(rev 7453)
@@ -1,6 +1,7 @@
package freenet.keys;
import java.net.MalformedURLException;
+import java.util.LinkedList;
import java.util.StringTokenizer;
import java.util.Vector;
@@ -343,4 +344,13 @@
public byte[] getExtra() {
return extra;
}
+
+ public LinkedList listMetaStrings() {
+ LinkedList l = new LinkedList();
+ if(metaStr != null) {
+ for(int i=0;i<metaStr.length;i++)
+ l.addLast(metaStr[i]);
+ }
+ return l;
+ }
}
_______________________________________________
cvs mailing list
[email protected]
http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs