Author: toad
Date: 2006-05-18 19:13:36 +0000 (Thu, 18 May 2006)
New Revision: 8774

Added:
   trunk/freenet/src/freenet/client/MetadataUnresolvedException.java
Modified:
   trunk/freenet/src/freenet/client/ArchiveManager.java
   trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
   trunk/freenet/src/freenet/client/Metadata.java
   trunk/freenet/src/freenet/client/async/ClientPutState.java
   trunk/freenet/src/freenet/client/async/ClientPutter.java
   trunk/freenet/src/freenet/client/async/MultiPutCompletionCallback.java
   trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
   trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
   trunk/freenet/src/freenet/client/async/SingleFileInserter.java
   trunk/freenet/src/freenet/client/async/SplitFileInserter.java
   trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java
   trunk/freenet/src/freenet/client/async/USKInserter.java
   trunk/freenet/src/freenet/node/Version.java
   trunk/freenet/src/freenet/node/fcp/ClientPut.java
Log:
723: Automatically chain manifests to avoid size limitations. => much bigger 
freesites are now possible.
Small freesite inserting tested, medium size insert not tested yet i.e. this 
may not work.

Modified: trunk/freenet/src/freenet/client/ArchiveManager.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveManager.java        2006-05-18 
15:30:32 UTC (rev 8773)
+++ trunk/freenet/src/freenet/client/ArchiveManager.java        2006-05-18 
19:13:36 UTC (rev 8774)
@@ -274,16 +274,43 @@
                }
                Metadata metadata = new Metadata(dir);
                TempStoreElement element = makeTempStoreBucket(-1);
-               try {
-                       OutputStream os = element.bucket.getOutputStream();
-                       metadata.writeTo(new DataOutputStream(os));
-                       os.close();
-               } catch (IOException e) {
-                       throw new ArchiveFailureException("Failed to create 
metadata: "+e, e);
+               int x = 0;
+               while(true) {
+                       try {
+                               byte[] buf = metadata.writeToByteArray();
+                               OutputStream os = 
element.bucket.getOutputStream();
+                               os.write(buf);
+                               os.close();
+                               addStoreElement(ctx, key, ".metadata", element);
+                               break;
+                       } catch (MetadataUnresolvedException e) {
+                               try {
+                                       x = resolve(e, x, element, ctx, key);
+                               } catch (IOException e1) {
+                                       throw new 
ArchiveFailureException("Failed to create metadata: "+e1, e1);
+                               }
+                       } catch (IOException e1) {
+                               throw new ArchiveFailureException("Failed to 
create metadata: "+e1, e1);
+                       }
                }
-               addStoreElement(ctx, key, ".metadata", element);
        }

+       private int resolve(MetadataUnresolvedException e, int x, 
TempStoreElement element, ArchiveStoreContext ctx, FreenetURI key) throws 
IOException {
+               Metadata[] m = e.mustResolve;
+               for(int i=0;i<m.length;i++) {
+                       try {
+                               byte[] buf = m[i].writeToByteArray();
+                               OutputStream os = 
element.bucket.getOutputStream();
+                               os.write(buf);
+                               os.close();
+                               addStoreElement(ctx, key, ".metadata-"+(x++), 
element);
+                       } catch (MetadataUnresolvedException e1) {
+                               x = resolve(e, x, element, ctx, key);
+                       }
+               }
+               return x;
+       }
+
        private void addToDirectory(HashMap dir, String name, String prefix) 
throws ArchiveFailureException {
                int x = name.indexOf('/');
                if(x < 0) {

Modified: trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
===================================================================
--- trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2006-05-18 15:30:32 UTC (rev 8773)
+++ trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2006-05-18 19:13:36 UTC (rev 8774)
@@ -127,8 +127,11 @@
                try {
                        b = BucketTools.makeImmutableBucket(bucketFactory, 
m.writeToByteArray());
                } catch (IOException e) {
-                       Logger.error(this, "Bucket error: "+e);
+                       Logger.error(this, "Bucket error: "+e, e);
                        throw new 
InserterException(InserterException.INTERNAL_ERROR, e, null);
+               } catch (MetadataUnresolvedException e) {
+                       Logger.error(this, "Impossible error: "+e, e);
+                       throw new 
InserterException(InserterException.INTERNAL_ERROR, e, null);
                }
                ClientKey k;
                InsertBlock block = new InsertBlock(b, null, insertURI);

Modified: trunk/freenet/src/freenet/client/Metadata.java
===================================================================
--- trunk/freenet/src/freenet/client/Metadata.java      2006-05-18 15:30:32 UTC 
(rev 8773)
+++ trunk/freenet/src/freenet/client/Metadata.java      2006-05-18 19:13:36 UTC 
(rev 8774)
@@ -9,11 +9,15 @@
 import java.net.MalformedURLException;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Vector;

 import freenet.keys.BaseClientKey;
 import freenet.keys.ClientCHK;
 import freenet.keys.FreenetURI;
 import freenet.support.Bucket;
+import freenet.support.BucketFactory;
+import freenet.support.BucketTools;
 import freenet.support.Fields;
 import freenet.support.Logger;

@@ -26,6 +30,9 @@
        /** Soft limit, to avoid memory DoS */
        static final int MAX_SPLITFILE_BLOCKS = 100*1000;

+       // URI at which this Metadata has been/will be inserted.
+       FreenetURI resolvedURI;
+       
        // Actual parsed data

        // document type
@@ -569,8 +576,9 @@

        /**
         * Write the data to a byte array.
+        * @throws MetadataUnresolvedException 
         */
-       public byte[] writeToByteArray() {
+       public byte[] writeToByteArray() throws MetadataUnresolvedException {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                DataOutputStream dos = new DataOutputStream(baos);
                try {
@@ -710,8 +718,9 @@
        }

        /** Write the metadata as binary. 
-        * @throws IOException If an I/O error occurred while writing the data. 
*/
-       public void writeTo(DataOutputStream dos) throws IOException {
+        * @throws IOException If an I/O error occurred while writing the data. 
+        * @throws MetadataUnresolvedException */
+       public void writeTo(DataOutputStream dos) throws IOException, 
MetadataUnresolvedException {
                dos.writeLong(FREENET_METADATA_MAGIC);
                dos.writeShort(0); // version
                dos.writeByte(documentType);
@@ -783,6 +792,8 @@

                if(documentType == SIMPLE_MANIFEST) {
                        dos.writeInt(manifestEntryCount);
+                       boolean kill = false;
+                       LinkedList unresolvedMetadata = null;
                        for(Iterator 
i=manifestEntries.keySet().iterator();i.hasNext();) {
                                String name = (String) i.next();
                                byte[] nameData = name.getBytes("UTF-8");
@@ -790,11 +801,35 @@
                                dos.writeShort(nameData.length);
                                dos.write(nameData);
                                Metadata meta = (Metadata) 
manifestEntries.get(name);
-                               byte[] data = meta.writeToByteArray();
-                               if(data.length > Short.MAX_VALUE) throw new 
IllegalArgumentException("Manifest data too long");
-                               dos.writeShort(data.length);
-                               dos.write(data);
+                               try {
+                                       byte[] data = meta.writeToByteArray();
+                                       if(data.length > Short.MAX_VALUE) {
+                                               FreenetURI uri = 
meta.resolvedURI;
+                                               if(uri != null) {
+                                                       meta = new 
Metadata(SIMPLE_REDIRECT, uri, null);
+                                                       data = 
meta.writeToByteArray();
+                                               } else {
+                                                       kill = true;
+                                                       if(unresolvedMetadata 
== null)
+                                                               
unresolvedMetadata = new LinkedList();
+                                                       
unresolvedMetadata.addLast(meta);
+                                               }
+                                       }
+                                       dos.writeShort(data.length);
+                                       dos.write(data);
+                               } catch (MetadataUnresolvedException e) {
+                                       Metadata[] m = e.mustResolve;
+                                       if(unresolvedMetadata == null)
+                                               unresolvedMetadata = new 
LinkedList();
+                                       for(int j=0;j<m.length;j++)
+                                               
unresolvedMetadata.addFirst(m[j]);
+                               }
                        }
+                       if(kill) {
+                               Metadata[] meta = 
+                                       (Metadata[]) 
unresolvedMetadata.toArray(new Metadata[unresolvedMetadata.size()]);
+                               throw new MetadataUnresolvedException(meta, 
"Manifest data too long and not resolved");
+                       }
                }

                if(documentType == ZIP_INTERNAL_REDIRECT) {
@@ -843,4 +878,17 @@
        public long uncompressedDataLength() {
                return this.decompressedLength;
        }
+       
+       public FreenetURI getResolvedURI() {
+               return resolvedURI;
+       }
+       
+       public void resolve(FreenetURI uri) {
+               this.resolvedURI = uri;
+       }
+
+       public Bucket toBucket(BucketFactory bf) throws 
MetadataUnresolvedException, IOException {
+               byte[] buf = writeToByteArray();
+               return BucketTools.makeImmutableBucket(bf, buf);
+       }
 }

Added: trunk/freenet/src/freenet/client/MetadataUnresolvedException.java
===================================================================
--- trunk/freenet/src/freenet/client/MetadataUnresolvedException.java   
2006-05-18 15:30:32 UTC (rev 8773)
+++ trunk/freenet/src/freenet/client/MetadataUnresolvedException.java   
2006-05-18 19:13:36 UTC (rev 8774)
@@ -0,0 +1,12 @@
+package freenet.client;
+
+public class MetadataUnresolvedException extends Exception {
+
+       public final Metadata[] mustResolve;
+       
+       MetadataUnresolvedException(Metadata[] mustResolve, String message) {
+               super(message);
+               this.mustResolve = mustResolve;
+       }
+
+}

Modified: trunk/freenet/src/freenet/client/async/ClientPutState.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientPutState.java  2006-05-18 
15:30:32 UTC (rev 8773)
+++ trunk/freenet/src/freenet/client/async/ClientPutState.java  2006-05-18 
19:13:36 UTC (rev 8774)
@@ -14,4 +14,6 @@
        public abstract void cancel();

        public abstract void schedule() throws InserterException;
+       
+       public Object getToken();
 }

Modified: trunk/freenet/src/freenet/client/async/ClientPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientPutter.java    2006-05-18 
15:30:32 UTC (rev 8773)
+++ trunk/freenet/src/freenet/client/async/ClientPutter.java    2006-05-18 
19:13:36 UTC (rev 8774)
@@ -54,7 +54,7 @@
        public void start() throws InserterException {
                try {
                        currentState =
-                               new SingleFileInserter(this, this, new 
InsertBlock(data, cm, targetURI), isMetadata, ctx, false, getCHKOnly, false);
+                               new SingleFileInserter(this, this, new 
InsertBlock(data, cm, targetURI), isMetadata, ctx, false, getCHKOnly, false, 
null);
                        ((SingleFileInserter)currentState).start();
                } catch (InserterException e) {
                        finished = true;

Modified: trunk/freenet/src/freenet/client/async/MultiPutCompletionCallback.java
===================================================================
--- trunk/freenet/src/freenet/client/async/MultiPutCompletionCallback.java      
2006-05-18 15:30:32 UTC (rev 8773)
+++ trunk/freenet/src/freenet/client/async/MultiPutCompletionCallback.java      
2006-05-18 19:13:36 UTC (rev 8774)
@@ -21,12 +21,14 @@
        private InserterException e;
        private boolean finished;
        private boolean started;
+       public final Object token;

-       public MultiPutCompletionCallback(PutCompletionCallback cb, 
BaseClientPutter parent) {
+       public MultiPutCompletionCallback(PutCompletionCallback cb, 
BaseClientPutter parent, Object token) {
                this.cb = cb;
                this.waitingFor = new LinkedList();
                this.waitingForBlockSet = new LinkedList();
                this.parent = parent;
+               this.token = token;
                finished = false;
        }

@@ -144,4 +146,8 @@
                // Do nothing
        }

+       public Object getToken() {
+               return token;
+       }
+
 }

Modified: trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java    
2006-05-18 15:30:32 UTC (rev 8773)
+++ trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java    
2006-05-18 19:13:36 UTC (rev 8774)
@@ -12,6 +12,7 @@
 import freenet.client.InserterContext;
 import freenet.client.InserterException;
 import freenet.client.Metadata;
+import freenet.client.MetadataUnresolvedException;
 import freenet.client.events.SplitfileProgressEvent;
 import freenet.keys.BaseClientKey;
 import freenet.keys.FreenetURI;
@@ -31,7 +32,7 @@
                        InsertBlock block = 
                                new InsertBlock(data, cm, 
FreenetURI.EMPTY_CHK_URI);
                        this.origSFI =
-                               new SingleFileInserter(this, this, block, 
false, ctx, false, getCHKOnly, true);
+                               new SingleFileInserter(this, this, block, 
false, ctx, false, getCHKOnly, true, null);
                        currentState = origSFI;
                        metadata = null;
                }
@@ -167,11 +168,12 @@
        private final boolean getCHKOnly;
        private boolean insertedAllFiles;
        private boolean insertedManifest;
-       private ClientPutState currentMetadataInserterState;
+       private final HashMap metadataPuttersByMetadata;
        private final String defaultName;
        private int numberOfFiles;
        private long totalSize;
        private boolean metadataBlockSetFinalized;
+       private Metadata baseMetadata;
        private final static String[] defaultDefaultNames =
                new String[] { "index.html", "index.htm", "default.html", 
"default.htm" };

@@ -188,6 +190,7 @@
                runningPutHandlers = new HashSet();
                putHandlersWaitingForMetadata = new HashSet();
                waitingForBlockSets = new HashSet();
+               metadataPuttersByMetadata = new HashMap();
                makePutHandlers(manifestElements, putHandlersByName);
        }

@@ -277,27 +280,71 @@
                                }
                        }
                }
-               Metadata meta =
+               baseMetadata =
                        
Metadata.mkRedirectionManifestWithMetadata(namesToByteArrays);
-               Bucket bucket;
-               try {
-                       bucket = BucketTools.makeImmutableBucket(ctx.bf, 
meta.writeToByteArray());
-               } catch (IOException e) {
-                       fail(new 
InserterException(InserterException.BUCKET_ERROR, e, null));
-                       return;
+               resolveAndStartBase();
+       }
+       
+       private void resolveAndStartBase() {
+               Bucket bucket = null;
+               synchronized(this) {
+                       
if(this.metadataPuttersByMetadata.containsKey(baseMetadata)) return;
                }
+               while(true) {
+                       try {
+                               bucket = 
BucketTools.makeImmutableBucket(ctx.bf, baseMetadata.writeToByteArray());
+                               break;
+                       } catch (IOException e) {
+                               fail(new 
InserterException(InserterException.BUCKET_ERROR, e, null));
+                               return;
+                       } catch (MetadataUnresolvedException e) {
+                               try {
+                                       resolve(e);
+                               } catch (IOException e1) {
+                                       fail(new 
InserterException(InserterException.BUCKET_ERROR, e, null));
+                                       return;
+                               } catch (InserterException e2) {
+                                       fail(e2);
+                               }
+                       }
+               }
+               if(bucket == null) return;
                InsertBlock block =
                        new InsertBlock(bucket, null, targetURI);
                try {
                        SingleFileInserter metadataInserter = 
-                               new SingleFileInserter(this, this, block, true, 
ctx, false, getCHKOnly, false);
-                       this.currentMetadataInserterState = metadataInserter;
+                               new SingleFileInserter(this, this, block, true, 
ctx, false, getCHKOnly, false, baseMetadata);
+                       Logger.minor(this, "Inserting main metadata: 
"+metadataInserter);
+                       this.metadataPuttersByMetadata.put(baseMetadata, 
metadataInserter);
                        metadataInserter.start();
                } catch (InserterException e) {
                        fail(e);
                }
        }
-       
+
+       private void resolve(MetadataUnresolvedException e) throws 
InserterException, IOException {
+               Metadata[] metas = e.mustResolve;
+               for(int i=0;i<metas.length;i++) {
+                       Metadata m = metas[i];
+                       synchronized(this) {
+                               if(metadataPuttersByMetadata.containsKey(m)) 
continue;
+                       }
+                       try {
+                               Bucket b = m.toBucket(ctx.bf);
+                               InsertBlock ib = new InsertBlock(b, null, 
FreenetURI.EMPTY_CHK_URI);
+                               SingleFileInserter metadataInserter = 
+                                       new SingleFileInserter(this, this, ib, 
true, ctx, false, getCHKOnly, false, m);
+                               Logger.minor(this, "Inserting subsidiary 
metadata: "+metadataInserter+" for "+m);
+                               synchronized(this) {
+                                       this.metadataPuttersByMetadata.put(m, 
metadataInserter);
+                               }
+                               metadataInserter.start();
+                       } catch (MetadataUnresolvedException e1) {
+                               resolve(e1);
+                       }
+               }
+       }
+
        private void namesToByteArrays(HashMap putHandlersByName, HashMap 
namesToByteArrays) {
                Iterator i = putHandlersByName.keySet().iterator();
                while(i.hasNext()) {
@@ -358,8 +405,13 @@
        }

        public void onSuccess(ClientPutState state) {
-               Logger.minor(this, "Inserted manifest successfully on "+this);
                synchronized(this) {
+                       metadataPuttersByMetadata.remove(state.getToken());
+                       if(!metadataPuttersByMetadata.isEmpty()) {
+                               Logger.minor(this, "Still running metadata 
putters: "+metadataPuttersByMetadata.size());
+                               return;
+                       }
+                       Logger.minor(this, "Inserted manifest successfully on 
"+this);
                        insertedManifest = true;
                        if(finished) {
                                Logger.minor(this, "Already finished");
@@ -375,27 +427,31 @@
        }

        public void onFailure(InserterException e, ClientPutState state) {
-               // FIXME check state == currentMetadataInserterState ??
                fail(e);
        }

        public void onEncode(BaseClientKey key, ClientPutState state) {
-               this.finalURI = key.getURI();
-               Logger.minor(this, "Got metadata key: "+finalURI);
-               cb.onGeneratedURI(finalURI, this);
+               if(state.getToken() == baseMetadata) {
+                       this.finalURI = key.getURI();
+                       Logger.minor(this, "Got metadata key: "+finalURI);
+                       cb.onGeneratedURI(finalURI, this);
+               } else {
+                       // It's a sub-Metadata
+                       Metadata m = (Metadata) state.getToken();
+                       m.resolve(key.getURI());
+                       Logger.minor(this, "Resolved "+m+" : "+key.getURI());
+                       resolveAndStartBase();
+               }
        }

        public void onTransition(ClientPutState oldState, ClientPutState 
newState) {
-               if(oldState == currentMetadataInserterState)
-                       currentMetadataInserterState = newState;
-               else
-                       Logger.error(this, "Current state = 
"+currentMetadataInserterState+" called onTransition(old="+oldState+", 
new="+newState+")", 
-                                       new Exception("debug"));
+               synchronized(this) {
+                       Logger.minor(this, "Transition: "+oldState+" -> 
"+newState);
+               }
        }

        public void onMetadata(Metadata m, ClientPutState state) {
-               Logger.error(this, "Got metadata from "+state+" on "+this+" 
(metadata inserter = "+currentMetadataInserterState);
-               fail(new InserterException(InserterException.INTERNAL_ERROR));
+               // Ignore
        }

        public void notifyClients() {

Modified: trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleBlockInserter.java     
2006-05-18 15:30:32 UTC (rev 8773)
+++ trunk/freenet/src/freenet/client/async/SingleBlockInserter.java     
2006-05-18 19:13:36 UTC (rev 8774)
@@ -39,13 +39,15 @@
        private ClientKey key;
        private WeakReference refToClientKeyBlock;
        final int token; // for e.g. splitfiles
+       private final Object tokenObject;
        final boolean isMetadata;
        final boolean getCHKOnly;
        final int sourceLength;
        private int consecutiveRNFs;

-       public SingleBlockInserter(BaseClientPutter parent, Bucket data, short 
compressionCodec, FreenetURI uri, InserterContext ctx, PutCompletionCallback 
cb, boolean isMetadata, int sourceLength, int token, boolean getCHKOnly, 
boolean addToParent, boolean dontSendEncoded) throws InserterException {
+       public SingleBlockInserter(BaseClientPutter parent, Bucket data, short 
compressionCodec, FreenetURI uri, InserterContext ctx, PutCompletionCallback 
cb, boolean isMetadata, int sourceLength, int token, boolean getCHKOnly, 
boolean addToParent, boolean dontSendEncoded, Object tokenObject) throws 
InserterException {
                this.consecutiveRNFs = 0;
+               this.tokenObject = tokenObject;
                this.token = token;
                this.parent = parent;
                this.dontSendEncoded = dontSendEncoded;
@@ -278,4 +280,8 @@
                return parent;
        }

+       public Object getToken() {
+               return tokenObject;
+       }
+
 }

Modified: trunk/freenet/src/freenet/client/async/SingleFileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileInserter.java      
2006-05-18 15:30:32 UTC (rev 8773)
+++ trunk/freenet/src/freenet/client/async/SingleFileInserter.java      
2006-05-18 19:13:36 UTC (rev 8774)
@@ -7,6 +7,7 @@
 import freenet.client.InserterContext;
 import freenet.client.InserterException;
 import freenet.client.Metadata;
+import freenet.client.MetadataUnresolvedException;
 import freenet.client.events.FinishedCompressionEvent;
 import freenet.client.events.StartedCompressionEvent;
 import freenet.keys.BaseClientKey;
@@ -42,6 +43,7 @@
         * update our parent to point to us as current put-stage. */
        private boolean cancelled = false;
        private boolean reportMetadataOnly;
+       public final Object token;

        /**
         * @param parent
@@ -56,8 +58,9 @@
         */
        SingleFileInserter(BaseClientPutter parent, PutCompletionCallback cb, 
InsertBlock block, 
                        boolean metadata, InserterContext ctx, boolean 
dontCompress, 
-                       boolean getCHKOnly, boolean reportMetadataOnly) throws 
InserterException {
+                       boolean getCHKOnly, boolean reportMetadataOnly, Object 
token) throws InserterException {
                this.reportMetadataOnly = reportMetadataOnly;
+               this.token = token;
                this.parent = parent;
                this.block = block;
                this.ctx = ctx;
@@ -150,6 +153,7 @@

                if(parent == cb) {
                        ctx.eventProducer.produceEvent(new 
FinishedCompressionEvent(bestCodec == null ? -1 : 
bestCodec.codecNumberForMetadata(), origSize, data.size()));
+                       Logger.minor(this, "Compressed "+origSize+" to 
"+data.size()+" on "+this);
                }

                // Compressed data
@@ -174,7 +178,7 @@
                if (data.size() < ClientCHKBlock.MAX_COMPRESSED_DATA_LENGTH) {
                        // Insert single block, then insert pointer to it
                        if(reportMetadataOnly) {
-                               SingleBlockInserter dataPutter = new 
SingleBlockInserter(parent, data, codecNumber, FreenetURI.EMPTY_CHK_URI, ctx, 
cb, metadata, (int)origSize, -1, getCHKOnly, true, true);
+                               SingleBlockInserter dataPutter = new 
SingleBlockInserter(parent, data, codecNumber, FreenetURI.EMPTY_CHK_URI, ctx, 
cb, metadata, (int)origSize, -1, getCHKOnly, true, true, token);
                                Metadata meta = new 
Metadata(Metadata.SIMPLE_REDIRECT, dataPutter.getURI(), block.clientMetadata);
                                cb.onMetadata(meta, this);
                                cb.onTransition(this, dataPutter);
@@ -182,14 +186,19 @@
                                cb.onBlockSetFinished(this);
                        } else {
                                MultiPutCompletionCallback mcb = 
-                                       new MultiPutCompletionCallback(cb, 
parent);
-                               SingleBlockInserter dataPutter = new 
SingleBlockInserter(parent, data, codecNumber, FreenetURI.EMPTY_CHK_URI, ctx, 
mcb, metadata, (int)origSize, -1, getCHKOnly, true, false);
+                                       new MultiPutCompletionCallback(cb, 
parent, token);
+                               SingleBlockInserter dataPutter = new 
SingleBlockInserter(parent, data, codecNumber, FreenetURI.EMPTY_CHK_URI, ctx, 
mcb, metadata, (int)origSize, -1, getCHKOnly, true, false, token);
                                Metadata meta = new 
Metadata(Metadata.SIMPLE_REDIRECT, dataPutter.getURI(), block.clientMetadata);
                                Bucket metadataBucket;
                                try {
                                        metadataBucket = 
BucketTools.makeImmutableBucket(ctx.bf, meta.writeToByteArray());
                                } catch (IOException e) {
+                                       Logger.error(this, "Caught "+e, e);
                                        throw new 
InserterException(InserterException.BUCKET_ERROR, e, null);
+                               } catch (MetadataUnresolvedException e) {
+                                       // Impossible, we're not inserting a 
manifest.
+                                       Logger.error(this, "Caught "+e, e);
+                                       throw new 
InserterException(InserterException.INTERNAL_ERROR, "Got 
MetadataUnresolvedException in SingleFileInserter: "+e.toString(), null);
                                }
                                ClientPutState metaPutter = 
createInserter(parent, metadataBucket, (short) -1, block.desiredURI, ctx, mcb, 
true, (int)origSize, -1, getCHKOnly, true);
                                mcb.addURIGenerator(metaPutter);
@@ -208,12 +217,12 @@
                // insert it. Then when the splitinserter has finished, and the
                // metadata insert has finished too, tell the master callback.
                if(reportMetadataOnly) {
-                       SplitFileInserter sfi = new SplitFileInserter(parent, 
cb, data, bestCodec, block.clientMetadata, ctx, getCHKOnly, metadata);
+                       SplitFileInserter sfi = new SplitFileInserter(parent, 
cb, data, bestCodec, block.clientMetadata, ctx, getCHKOnly, metadata, token);
                        cb.onTransition(this, sfi);
                        sfi.start();
                } else {
                        SplitHandler sh = new SplitHandler();
-                       SplitFileInserter sfi = new SplitFileInserter(parent, 
sh, data, bestCodec, block.clientMetadata, ctx, getCHKOnly, metadata);
+                       SplitFileInserter sfi = new SplitFileInserter(parent, 
sh, data, bestCodec, block.clientMetadata, ctx, getCHKOnly, metadata, token);
                        sh.sfi = sfi;
                        cb.onTransition(this, sh);
                        sfi.start();
@@ -227,13 +236,13 @@
                if(uri.getKeyType().equals("USK")) {
                        try {
                                return new USKInserter(parent, data, 
compressionCodec, uri, ctx, cb, isMetadata, sourceLength, token, 
-                                       getCHKOnly, addToParent);
+                                       getCHKOnly, addToParent, this.token);
                        } catch (MalformedURLException e) {
                                throw new 
InserterException(InserterException.INVALID_URI, e, null);
                        }
                } else {
                        return new SingleBlockInserter(parent, data, 
compressionCodec, uri, ctx, cb, isMetadata, sourceLength, token, 
-                               getCHKOnly, addToParent, false);
+                               getCHKOnly, addToParent, false, this.token);
                }
        }

@@ -307,10 +316,16 @@
                                                InserterException ex = new 
InserterException(InserterException.BUCKET_ERROR, e, null);
                                                fail(ex);
                                                return;
+                                       } catch (MetadataUnresolvedException e) 
{
+                                               Logger.error(this, "Impossible: 
"+e, e);
+                                               InserterException ex = new 
InserterException(InserterException.INTERNAL_ERROR, 
"MetadataUnresolvedException in SingleFileInserter.SplitHandler: "+e, null);
+                                               ex.initCause(e);
+                                               fail(ex);
+                                               return;
                                        }
                                        InsertBlock newBlock = new 
InsertBlock(metadataBucket, null, block.desiredURI);
                                        try {
-                                               metadataPutter = new 
SingleFileInserter(parent, this, newBlock, true, ctx, false, getCHKOnly, false);
+                                               metadataPutter = new 
SingleFileInserter(parent, this, newBlock, true, ctx, false, getCHKOnly, false, 
token);
                                                Logger.minor(this, "Putting 
metadata on "+metadataPutter);
                                        } catch (InserterException e) {
                                                cb.onFailure(e, this);
@@ -368,6 +383,10 @@
                public void schedule() throws InserterException {
                        // Do nothing
                }
+
+               public Object getToken() {
+                       return token;
+               }

        }

@@ -382,4 +401,8 @@
        public void schedule() throws InserterException {
                start();
        }
+
+       public Object getToken() {
+               return token;
+       }
 }

Modified: trunk/freenet/src/freenet/client/async/SplitFileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileInserter.java       
2006-05-18 15:30:32 UTC (rev 8773)
+++ trunk/freenet/src/freenet/client/async/SplitFileInserter.java       
2006-05-18 19:13:36 UTC (rev 8774)
@@ -34,9 +34,11 @@
        final ClientMetadata cm;
        final boolean isMetadata;
        private boolean finished;
+       public final Object token;

-       public SplitFileInserter(BaseClientPutter put, PutCompletionCallback 
cb, Bucket data, Compressor bestCodec, ClientMetadata clientMetadata, 
InserterContext ctx, boolean getCHKOnly, boolean isMetadata) throws 
InserterException {
+       public SplitFileInserter(BaseClientPutter put, PutCompletionCallback 
cb, Bucket data, Compressor bestCodec, ClientMetadata clientMetadata, 
InserterContext ctx, boolean getCHKOnly, boolean isMetadata, Object token) 
throws InserterException {
                this.parent = put;
+               this.token = token;
                this.finished = false;
                this.isMetadata = isMetadata;
                this.cm = clientMetadata;
@@ -272,4 +274,8 @@
                start();
        }

+       public Object getToken() {
+               return token;
+       }
+
 }

Modified: trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java        
2006-05-18 15:30:32 UTC (rev 8773)
+++ trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java        
2006-05-18 19:13:36 UTC (rev 8774)
@@ -55,7 +55,7 @@
        public void start() throws InserterException {
                for(int i=0;i<dataBlockInserters.length;i++) {
                        dataBlockInserters[i] = 
-                               new SingleBlockInserter(parent.parent, 
dataBlocks[i], (short)-1, FreenetURI.EMPTY_CHK_URI, blockInsertContext, this, 
false, ClientCHKBlock.DATA_LENGTH, i, getCHKOnly, false, false);
+                               new SingleBlockInserter(parent.parent, 
dataBlocks[i], (short)-1, FreenetURI.EMPTY_CHK_URI, blockInsertContext, this, 
false, ClientCHKBlock.DATA_LENGTH, i, getCHKOnly, false, false, parent.token);
                        dataBlockInserters[i].schedule();
                }
                if(splitfileAlgo == null) {
@@ -81,7 +81,7 @@
                        // Start the inserts
                        for(int i=0;i<checkBlockInserters.length;i++) {
                                checkBlockInserters[i] = 
-                                       new SingleBlockInserter(parent.parent, 
checkBlocks[i], (short)-1, FreenetURI.EMPTY_CHK_URI, blockInsertContext, this, 
false, ClientCHKBlock.DATA_LENGTH, i + dataBlocks.length, getCHKOnly, false, 
false);
+                                       new SingleBlockInserter(parent.parent, 
checkBlocks[i], (short)-1, FreenetURI.EMPTY_CHK_URI, blockInsertContext, this, 
false, ClientCHKBlock.DATA_LENGTH, i + dataBlocks.length, getCHKOnly, false, 
false, parent.token);
                                checkBlockInserters[i].schedule();
                        }
                        // Tell parent only after have started the inserts.

Modified: trunk/freenet/src/freenet/client/async/USKInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/USKInserter.java     2006-05-18 
15:30:32 UTC (rev 8773)
+++ trunk/freenet/src/freenet/client/async/USKInserter.java     2006-05-18 
19:13:36 UTC (rev 8774)
@@ -32,6 +32,7 @@
        final int sourceLength;
        final int token;
        final boolean getCHKOnly;
+       public final Object tokenObject;

        final InsertableUSK privUSK;
        final USK pubUSK;
@@ -108,7 +109,7 @@
                        Logger.minor(this, "scheduling insert for 
"+pubUSK.getURI()+" "+edition);
                        try {
                                sbi = new SingleBlockInserter(parent, data, 
compressionCodec, privUSK.getInsertableSSK(edition).getInsertURI(),
-                                               ctx, this, isMetadata, 
sourceLength, token, getCHKOnly, false, true /* we don't use it */);
+                                               ctx, this, isMetadata, 
sourceLength, token, getCHKOnly, false, true /* we don't use it */, 
tokenObject);
                        } catch (InserterException e) {
                                cb.onFailure(e, this);
                                return;
@@ -155,7 +156,8 @@

        public USKInserter(BaseClientPutter parent, Bucket data, short 
compressionCodec, FreenetURI uri, 
                        InserterContext ctx, PutCompletionCallback cb, boolean 
isMetadata, int sourceLength, int token, 
-                       boolean getCHKOnly, boolean addToParent) throws 
MalformedURLException {
+                       boolean getCHKOnly, boolean addToParent, Object 
tokenObject) throws MalformedURLException {
+               this.tokenObject = tokenObject;
                this.parent = parent;
                this.data = data;
                this.compressionCodec = compressionCodec;
@@ -217,4 +219,8 @@
                // Ignore
        }

+       public Object getToken() {
+               return tokenObject;
+       }
+
 }

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-05-18 15:30:32 UTC (rev 
8773)
+++ trunk/freenet/src/freenet/node/Version.java 2006-05-18 19:13:36 UTC (rev 
8774)
@@ -18,7 +18,7 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       private static final int buildNumber = 722;
+       private static final int buildNumber = 723;

        /** Oldest build of Fred we will talk to */
        private static final int lastGoodBuild = 698;

Modified: trunk/freenet/src/freenet/node/fcp/ClientPut.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPut.java   2006-05-18 15:30:32 UTC 
(rev 8773)
+++ trunk/freenet/src/freenet/node/fcp/ClientPut.java   2006-05-18 19:13:36 UTC 
(rev 8774)
@@ -6,6 +6,7 @@
 import freenet.client.ClientMetadata;
 import freenet.client.InserterException;
 import freenet.client.Metadata;
+import freenet.client.MetadataUnresolvedException;
 import freenet.client.async.ClientPutter;
 import freenet.keys.FreenetURI;
 import freenet.support.Bucket;
@@ -46,7 +47,18 @@
                        this.targetURI = message.redirectTarget;
                        Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, 
targetURI, cm);
                        cm = null;
-                       byte[] d = m.writeToByteArray();
+                       byte[] d;
+                       try {
+                               d = m.writeToByteArray();
+                       } catch (MetadataUnresolvedException e) {
+                               // Impossible
+                               Logger.error(this, "Impossible: "+e, e);
+                               onFailure(new 
InserterException(InserterException.INTERNAL_ERROR, "Impossible: "+e+" in 
ClientPut", null), null);
+                               this.data = null;
+                               clientMetadata = null;
+                               inserter = null;
+                               return;
+                       }
                        data = new SimpleReadOnlyArrayBucket(d);
                        isMetadata = true;
                } else
@@ -115,7 +127,19 @@
                        targetURI = new FreenetURI(target);
                        Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, 
targetURI, cm);
                        cm = null;
-                       byte[] d = m.writeToByteArray();
+                       byte[] d;
+                       try {
+                               d = m.writeToByteArray();
+                       } catch (MetadataUnresolvedException e) {
+                               // Impossible
+                               Logger.error(this, "Impossible: "+e, e);
+                               onFailure(new 
InserterException(InserterException.INTERNAL_ERROR, "Impossible: "+e+" in 
ClientPut", null), null);
+                               this.data = null;
+                               clientMetadata = null;
+                               origFilename = null;
+                               inserter = null;
+                               return;
+                       }
                        data = new SimpleReadOnlyArrayBucket(d);
                        origFilename = null;
                        isMetadata = true;


Reply via email to