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

Reply via email to