Author: toad
Date: 2006-03-11 20:29:37 +0000 (Sat, 11 Mar 2006)
New Revision: 8233

Modified:
   trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
   trunk/freenet/src/freenet/node/Version.java
   trunk/freenet/src/freenet/node/fcp/ClientPutBase.java
   trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java
   trunk/freenet/src/freenet/node/fcp/ClientPutDir.java
   trunk/freenet/src/freenet/node/fcp/ClientRequest.java
   trunk/freenet/src/freenet/node/fcp/FCPMessage.java
   trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
Log:
528:
Persistence works for ClientPut*Dir's.
But ListPersistentRequests doesn't yet.

Modified: trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java    
2006-03-11 18:46:41 UTC (rev 8232)
+++ trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java    
2006-03-11 20:29:37 UTC (rev 8233)
@@ -412,5 +412,34 @@
                                throw new 
IllegalStateException(String.valueOf(o));
                }
        }
+
+       /**
+        * Opposite of flatten(...).
+        * Note that this can throw a ClassCastException if the vector passed 
in is
+        * bogus (has files pretending to be directories).
+        */
+       public static HashMap unflatten(Vector v) {
+               HashMap manifestElements = new HashMap();
+               for(int i=0;i<v.size();i++) {
+                       ManifestElement oldElement = (ManifestElement)v.get(i);
+                       add(oldElement, oldElement.getName(), manifestElements);
+               }
+               return manifestElements;
+       }

+       private static void add(ManifestElement e, String namePart, HashMap 
target) {
+               int idx = namePart.indexOf('/');
+               if(idx < 0) {
+                       target.put(namePart, new ManifestElement(e, namePart));
+               } else {
+                       String before = namePart.substring(0, idx);
+                       String after = namePart.substring(idx+1);
+                       HashMap hm = (HashMap) (target.get(before));
+                       if(hm == null) {
+                               hm = new HashMap();
+                               target.put(before, hm);
+                       }
+                       add(e, after, hm);
+               }
+       }
 }

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-03-11 18:46:41 UTC (rev 
8232)
+++ trunk/freenet/src/freenet/node/Version.java 2006-03-11 20:29:37 UTC (rev 
8233)
@@ -20,7 +20,7 @@
        public static final String protocolVersion = "1.0";

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

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

Modified: trunk/freenet/src/freenet/node/fcp/ClientPutBase.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutBase.java       2006-03-11 
18:46:41 UTC (rev 8232)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutBase.java       2006-03-11 
20:29:37 UTC (rev 8233)
@@ -219,6 +219,7 @@
                fs.put("MaxRetries", Integer.toString(ctx.maxInsertRetries));
                fs.put("Finished", Boolean.toString(finished));
                fs.put("Succeeded", Boolean.toString(succeeded));
+               fs.put("GetCHKOnly", Boolean.toString(getCHKOnly));
                if(generatedURI != null)
                        fs.put("GeneratedURI", generatedURI.toString(false));
                if(finished && (!succeeded))

Modified: trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java  
2006-03-11 18:46:41 UTC (rev 8232)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java  
2006-03-11 20:29:37 UTC (rev 8233)
@@ -12,6 +12,7 @@
 import freenet.support.BucketFactory;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.PersistentTempBucketFactory;

 /**
  * ClientPutComplexDir
@@ -45,7 +46,7 @@
        /** Total number of bytes of attached data */
        private final long attachedBytes;

-       public ClientPutComplexDirMessage(SimpleFieldSet fs, BucketFactory 
bfTemp, BucketFactory bfPersistent) throws MessageInvalidException {
+       public ClientPutComplexDirMessage(SimpleFieldSet fs, BucketFactory 
bfTemp, PersistentTempBucketFactory bfPersistent) throws 
MessageInvalidException {
                // Parse the standard ClientPutDir headers - URI, etc.
                super(fs);


Modified: trunk/freenet/src/freenet/node/fcp/ClientPutDir.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutDir.java        2006-03-11 
18:46:41 UTC (rev 8232)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutDir.java        2006-03-11 
20:29:37 UTC (rev 8233)
@@ -1,9 +1,12 @@
 package freenet.node.fcp;

 import java.io.BufferedWriter;
+import java.io.File;
 import java.io.IOException;
+import java.net.MalformedURLException;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Vector;

 import freenet.client.FetchException;
 import freenet.client.FetchResult;
@@ -21,15 +24,16 @@
 import freenet.keys.FreenetURI;
 import freenet.support.Bucket;
 import freenet.support.HexUtil;
+import freenet.support.Logger;
 import freenet.support.PaddedEphemerallyEncryptedBucket;
 import freenet.support.SimpleFieldSet;
 import freenet.support.io.FileBucket;

 public class ClientPutDir extends ClientPutBase implements 
ClientEventListener, ClientCallback {

-       private HashMap manifestElements;
-       private SimpleManifestPutter putter;
-       private InserterContext ctx;
+       private final HashMap manifestElements;
+       private final SimpleManifestPutter putter;
+       private final String defaultName;

        public ClientPutDir(FCPConnectionHandler handler, ClientPutDirMessage 
message, 
                        HashMap manifestElements) throws 
IdentifierCollisionException {
@@ -37,23 +41,79 @@
                                message.priorityClass, message.persistenceType, 
message.clientToken, message.global,
                                message.getCHKOnly, message.dontCompress, 
message.maxRetries);
                this.manifestElements = manifestElements;
-               ctx = new InserterContext(client.defaultInsertContext, new 
SimpleEventProducer());
-               ctx.dontCompress = message.dontCompress;
-               ctx.eventProducer.addEventListener(this);
-               ctx.maxInsertRetries = message.maxRetries;
+               this.defaultName = message.defaultName;
+               SimpleManifestPutter p;
                try {
-                       putter = new SimpleManifestPutter(this, 
client.node.chkPutScheduler, client.node.sskPutScheduler,
-                                       manifestElements, priorityClass, uri, 
message.defaultName, ctx, message.getCHKOnly, client);
+                       p = new SimpleManifestPutter(this, 
client.node.chkPutScheduler, client.node.sskPutScheduler,
+                                       manifestElements, priorityClass, uri, 
defaultName, ctx, message.getCHKOnly, client);
                } catch (InserterException e) {
                        onFailure(e, null);
+                       p = null;
                } 
+               putter = p;
                if(persistenceType != PERSIST_CONNECTION)
                        client.register(this);
        }

+       public ClientPutDir(SimpleFieldSet fs, FCPClient client) throws 
PersistenceParseException, IOException {
+               super(fs, client);
+               SimpleFieldSet files = fs.subset("Files");
+               defaultName = fs.get("DefaultName");
+               // Flattened for disk, sort out afterwards
+               Vector v = new Vector();
+               for(int i=0;;i++) {
+                       String num = Integer.toString(i);
+                       SimpleFieldSet subset = files.subset(num);
+                       if(subset == null) break;
+                       // Otherwise serialize
+                       String name = subset.get("Name");
+                       if(name == null)
+                               throw new PersistenceParseException("No Name on 
"+i);
+                       String contentTypeOverride = 
subset.get("Metadata.ContentType");
+                       String uploadFrom = subset.get("UploadFrom");
+                       Bucket data;
+                       Logger.minor(this, "Parsing "+i);
+                       if(uploadFrom == null || 
uploadFrom.equalsIgnoreCase("direct")) {
+                               // Direct (persistent temp bucket)
+                               byte[] key = 
HexUtil.hexToBytes(subset.get("TempBucket.DecryptKey"));
+                               String fnam = subset.get("TempBucket.Filename");
+                               long sz = 
Long.parseLong(subset.get("TempBucket.Size"));
+                               data = 
client.server.node.persistentTempBucketFactory.registerEncryptedBucket(fnam, 
key, sz);
+                               if(data.size() != sz)
+                                       throw new 
PersistenceParseException("Size of bucket is wrong: "+data.size()+" should be 
"+sz);
+                       } else {
+                               // Disk
+                               String f = subset.get("Filename");
+                               if(f == null)
+                                       throw new 
PersistenceParseException("UploadFrom=disk but no name on "+i);
+                               File ff = new File(f);
+                               if(!(ff.exists() && ff.canRead())) {
+                                       Logger.error(this, "File no longer 
exists, cancelling upload: "+ff);
+                                       throw new IOException("File no longer 
exists, cancelling upload: "+ff);
+                               }
+                               data = new FileBucket(ff, true, false, false, 
false);
+                       }
+                       ManifestElement me = new ManifestElement(name, data, 
contentTypeOverride);
+                       v.add(me);
+               }
+               manifestElements = SimpleManifestPutter.unflatten(v);
+               SimpleManifestPutter p;
+               try {
+                       p = new SimpleManifestPutter(this, 
client.node.chkPutScheduler, client.node.sskPutScheduler,
+                                       manifestElements, priorityClass, uri, 
defaultName, ctx, getCHKOnly, client);
+               } catch (InserterException e) {
+                       onFailure(e, null);
+                       p = null;
+               }
+               putter = p;
+               if(!finished)
+                       start();
+       }
+
        public void start() {
                try {
-                       putter.start();
+                       if(putter != null)
+                               putter.start();
                } catch (InserterException e) {
                        onFailure(e, null);
                }
@@ -93,6 +153,7 @@
                // Flatten the hierarchy, it can be reconstructed on restarting.
                // Storing it directly would be a PITA.
                ManifestElement[] elements = 
SimpleManifestPutter.flatten(manifestElements);
+               fs.put("DefaultName", defaultName);
                for(int i=0;i<elements.length;i++) {
                        String num = Integer.toString(i);
                        ManifestElement e = elements[i];
@@ -109,6 +170,7 @@
                                subset.put("UploadFrom", "disk");
                                subset.put("Filename", 
((FileBucket)data).getFile().getPath());
                        } else if(data instanceof 
PaddedEphemerallyEncryptedBucket) {
+                               subset.put("UploadFrom", "direct");
                                // the bucket is a persistent encrypted temp 
bucket
                                PaddedEphemerallyEncryptedBucket bucket = 
(PaddedEphemerallyEncryptedBucket) data;
                                subset.put("TempBucket.DecryptKey", 
HexUtil.bytesToHex(bucket.getKey()));

Modified: trunk/freenet/src/freenet/node/fcp/ClientRequest.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientRequest.java       2006-03-11 
18:46:41 UTC (rev 8232)
+++ trunk/freenet/src/freenet/node/fcp/ClientRequest.java       2006-03-11 
20:29:37 UTC (rev 8233)
@@ -131,6 +131,10 @@
                                ClientPut cp = new ClientPut(fs, client);
                                client.register(cp);
                                return cp;
+                       } else if(type.equals("PUTDIR")) {
+                               ClientPutDir cp = new ClientPutDir(fs, client);
+                               client.register(cp);
+                               return cp;
                        } else {
                                Logger.error(ClientRequest.class, "Unrecognized 
type: "+type);
                                return null;

Modified: trunk/freenet/src/freenet/node/fcp/FCPMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPMessage.java  2006-03-11 18:46:41 UTC 
(rev 8232)
+++ trunk/freenet/src/freenet/node/fcp/FCPMessage.java  2006-03-11 20:29:37 UTC 
(rev 8233)
@@ -6,6 +6,7 @@
 import freenet.node.Node;
 import freenet.support.BucketFactory;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.PersistentTempBucketFactory;

 public abstract class FCPMessage {

@@ -28,7 +29,7 @@
        /**
         * Create a message from a SimpleFieldSet, and the message's name, if 
possible. 
         */
-       public static FCPMessage create(String name, SimpleFieldSet fs, 
BucketFactory bfTemp, BucketFactory bfPersistent) throws 
MessageInvalidException {
+       public static FCPMessage create(String name, SimpleFieldSet fs, 
BucketFactory bfTemp, PersistentTempBucketFactory bfPersistent) throws 
MessageInvalidException {
                if(name.equals(ClientHelloMessage.name))
                        return new ClientHelloMessage(fs);
                if(name.equals(ClientGetMessage.name))

Modified: 
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java     
2006-03-11 18:46:41 UTC (rev 8232)
+++ trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java     
2006-03-11 20:29:37 UTC (rev 8233)
@@ -73,7 +73,7 @@
         */
        public PaddedEphemerallyEncryptedBucket(Bucket bucket, int minSize, 
long knownSize, byte[] key, RandomSource origRandom) throws IOException {
                if(bucket.size() < knownSize)
-                       throw new IOException("Bucket is too small on disk");
+                       throw new IOException("Bucket is too small on disk - 
knownSize="+knownSize+" but bucket.size="+bucket.size()+" for "+bucket);
                this.dataLength = knownSize;
                this.origRandom = origRandom;
                this.bucket = bucket;


Reply via email to