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;