Author: toad
Date: 2006-03-10 22:35:51 +0000 (Fri, 10 Mar 2006)
New Revision: 8221
Added:
trunk/freenet/src/freenet/client/async/ClientRequester.java
trunk/freenet/src/freenet/node/fcp/ClientPutBase.java
trunk/freenet/src/freenet/node/fcp/ClientPutDir.java
trunk/freenet/src/freenet/node/fcp/ClientPutDirMessage.java
trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
Removed:
trunk/freenet/src/freenet/client/async/ClientRequest.java
Modified:
trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
trunk/freenet/src/freenet/client/async/BaseClientPutter.java
trunk/freenet/src/freenet/client/async/ClientGetter.java
trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
trunk/freenet/src/freenet/client/async/ManifestElement.java
trunk/freenet/src/freenet/client/async/SendableRequest.java
trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
trunk/freenet/src/freenet/node/RequestStarter.java
trunk/freenet/src/freenet/node/Version.java
trunk/freenet/src/freenet/node/fcp/ClientGet.java
trunk/freenet/src/freenet/node/fcp/ClientPut.java
trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java
trunk/freenet/src/freenet/node/fcp/ClientRequest.java
trunk/freenet/src/freenet/node/fcp/FCPConnectionHandler.java
trunk/freenet/src/freenet/node/fcp/FCPMessage.java
Log:
522:
New FCP command: ClientPutDiskDir. (persistence not yet supported)
Refactoring relating to FCP - eliminate a large amount of duplicated code and
modularize.
Modified: trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
===================================================================
--- trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
2006-03-10 18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
2006-03-10 22:35:51 UTC (rev 8221)
@@ -130,6 +130,7 @@
PutWaiter pw = new PutWaiter();
SimpleManifestPutter putter =
new SimpleManifestPutter(pw, node.chkPutScheduler,
node.sskPutScheduler,
SimpleManifestPutter.bucketsByNameToManifestEntries(bucketsByName),
priorityClass, insertURI, defaultName, getInserterContext(), false, this);
+ putter.start();
return pw.waitForCompletion();
}
Modified: trunk/freenet/src/freenet/client/async/BaseClientPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/BaseClientPutter.java
2006-03-10 18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/client/async/BaseClientPutter.java
2006-03-10 22:35:51 UTC (rev 8221)
@@ -1,6 +1,6 @@
package freenet.client.async;
-public abstract class BaseClientPutter extends ClientRequest {
+public abstract class BaseClientPutter extends ClientRequester {
protected BaseClientPutter(short priorityClass, ClientRequestScheduler
chkScheduler, ClientRequestScheduler sskScheduler, Object context) {
super(priorityClass, chkScheduler, sskScheduler, context);
Modified: trunk/freenet/src/freenet/client/async/ClientGetter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientGetter.java 2006-03-10
18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/client/async/ClientGetter.java 2006-03-10
22:35:51 UTC (rev 8221)
@@ -17,7 +17,7 @@
/**
* A high level data request.
*/
-public class ClientGetter extends ClientRequest implements
GetCompletionCallback {
+public class ClientGetter extends ClientRequester implements
GetCompletionCallback {
final ClientCallback client;
final FreenetURI uri;
Deleted: trunk/freenet/src/freenet/client/async/ClientRequest.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientRequest.java 2006-03-10
18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/client/async/ClientRequest.java 2006-03-10
22:35:51 UTC (rev 8221)
@@ -1,118 +0,0 @@
-package freenet.client.async;
-
-import freenet.keys.FreenetURI;
-import freenet.support.Logger;
-
-/** A high level client request. A request (either fetch or put) started
- * by a Client. Has a suitable context and a URI; is fulfilled only when
- * we have followed all the redirects etc, or have an error. Can be
- * retried.
- */
-public abstract class ClientRequest {
-
- // FIXME move the priority classes from RequestStarter here
- protected short priorityClass;
- protected boolean cancelled;
- final ClientRequestScheduler chkScheduler;
- final ClientRequestScheduler sskScheduler;
- protected final Object client;
-
- public short getPriorityClass() {
- return priorityClass;
- }
-
- protected ClientRequest(short priorityClass, ClientRequestScheduler
chkScheduler, ClientRequestScheduler sskScheduler, Object client) {
- this.priorityClass = priorityClass;
- this.chkScheduler = chkScheduler;
- this.sskScheduler = sskScheduler;
- this.client = client;
- }
-
- public void cancel() {
- cancelled = true;
- }
-
- public boolean isCancelled() {
- return cancelled;
- }
-
- public abstract FreenetURI getURI();
-
- public abstract boolean isFinished();
-
- /** Total number of blocks this request has tried to fetch/put. */
- protected int totalBlocks;
- /** Number of blocks we have successfully completed a fetch/put for. */
- protected int successfulBlocks;
- /** Number of blocks which have failed. */
- protected int failedBlocks;
- /** Number of blocks which have failed fatally. */
- protected int fatallyFailedBlocks;
- /** Minimum number of blocks required to succeed for success. */
- protected int minSuccessBlocks;
- /** Has totalBlocks stopped growing? */
- protected boolean blockSetFinalized;
-
- public void blockSetFinalized() {
- synchronized(this) {
- if(blockSetFinalized) return;
- blockSetFinalized = true;
- }
- Logger.minor(this, "Finalized set of blocks for "+this, new
Exception("debug"));
- notifyClients();
- }
-
- public synchronized void addBlock() {
- if(blockSetFinalized)
- Logger.error(this, "addBlock() but set finalized! on
"+this, new Exception("error"));
- totalBlocks++;
- }
-
- public synchronized void addBlocks(int num) {
- if(blockSetFinalized)
- Logger.error(this, "addBlock() but set finalized! on
"+this, new Exception("error"));
- totalBlocks+=num;
- }
-
- public void completedBlock(boolean dontNotify) {
- Logger.minor(this, "Completed block ("+dontNotify+")");
- synchronized(this) {
- successfulBlocks++;
- if(dontNotify) return;
- }
- notifyClients();
- }
-
- public void failedBlock() {
- synchronized(this) {
- failedBlocks++;
- }
- notifyClients();
- }
-
- public void fatallyFailedBlock() {
- synchronized(this) {
- fatallyFailedBlocks++;
- }
- notifyClients();
- }
-
- public synchronized void addMustSucceedBlocks(int blocks) {
- minSuccessBlocks += blocks;
- }
-
- public abstract void notifyClients();
-
- /** Get client context object */
- public Object getClient() {
- return client;
- }
-
- public void setPriorityClass(short newPriorityClass) {
- short oldPriorityClass = priorityClass;
- this.priorityClass = newPriorityClass;
- chkScheduler.reregisterAll(this);
- sskScheduler.reregisterAll(this);
- }
-
-}
Modified: trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
2006-03-10 18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
2006-03-10 22:35:51 UTC (rev 8221)
@@ -141,7 +141,7 @@
continue;
}
Logger.minor(this, "removeFirst() returning
"+req+" ("+rga.getNumber()+")");
- ClientRequest cr = req.getClientRequest();
+ ClientRequester cr = req.getClientRequest();
HashSet v = (HashSet)
allRequestsByClientRequest.get(cr);
v.remove(req);
if(v.isEmpty())
@@ -153,7 +153,7 @@
return null;
}
- public void reregisterAll(ClientRequest request) {
+ public void reregisterAll(ClientRequester request) {
synchronized(this) {
HashSet h = (HashSet)
allRequestsByClientRequest.get(request);
if(h != null) {
Copied: trunk/freenet/src/freenet/client/async/ClientRequester.java (from rev
8220, trunk/freenet/src/freenet/client/async/ClientRequest.java)
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientRequest.java 2006-03-10
18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/client/async/ClientRequester.java 2006-03-10
22:35:51 UTC (rev 8221)
@@ -0,0 +1,117 @@
+package freenet.client.async;
+
+import freenet.keys.FreenetURI;
+import freenet.support.Logger;
+
+/** A high level client request. A request (either fetch or put) started
+ * by a Client. Has a suitable context and a URI; is fulfilled only when
+ * we have followed all the redirects etc, or have an error. Can be
+ * retried.
+ */
+public abstract class ClientRequester {
+
+ // FIXME move the priority classes from RequestStarter here
+ protected short priorityClass;
+ protected boolean cancelled;
+ final ClientRequestScheduler chkScheduler;
+ final ClientRequestScheduler sskScheduler;
+ protected final Object client;
+
+ public short getPriorityClass() {
+ return priorityClass;
+ }
+
+ protected ClientRequester(short priorityClass, ClientRequestScheduler
chkScheduler, ClientRequestScheduler sskScheduler, Object client) {
+ this.priorityClass = priorityClass;
+ this.chkScheduler = chkScheduler;
+ this.sskScheduler = sskScheduler;
+ this.client = client;
+ }
+
+ public void cancel() {
+ cancelled = true;
+ }
+
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ public abstract FreenetURI getURI();
+
+ public abstract boolean isFinished();
+
+ /** Total number of blocks this request has tried to fetch/put. */
+ protected int totalBlocks;
+ /** Number of blocks we have successfully completed a fetch/put for. */
+ protected int successfulBlocks;
+ /** Number of blocks which have failed. */
+ protected int failedBlocks;
+ /** Number of blocks which have failed fatally. */
+ protected int fatallyFailedBlocks;
+ /** Minimum number of blocks required to succeed for success. */
+ protected int minSuccessBlocks;
+ /** Has totalBlocks stopped growing? */
+ protected boolean blockSetFinalized;
+
+ public void blockSetFinalized() {
+ synchronized(this) {
+ if(blockSetFinalized) return;
+ blockSetFinalized = true;
+ }
+ Logger.minor(this, "Finalized set of blocks for "+this, new
Exception("debug"));
+ notifyClients();
+ }
+
+ public synchronized void addBlock() {
+ if(blockSetFinalized)
+ Logger.error(this, "addBlock() but set finalized! on
"+this, new Exception("error"));
+ totalBlocks++;
+ }
+
+ public synchronized void addBlocks(int num) {
+ if(blockSetFinalized)
+ Logger.error(this, "addBlock() but set finalized! on
"+this, new Exception("error"));
+ totalBlocks+=num;
+ }
+
+ public void completedBlock(boolean dontNotify) {
+ Logger.minor(this, "Completed block ("+dontNotify+")");
+ synchronized(this) {
+ successfulBlocks++;
+ if(dontNotify) return;
+ }
+ notifyClients();
+ }
+
+ public void failedBlock() {
+ synchronized(this) {
+ failedBlocks++;
+ }
+ notifyClients();
+ }
+
+ public void fatallyFailedBlock() {
+ synchronized(this) {
+ fatallyFailedBlocks++;
+ }
+ notifyClients();
+ }
+
+ public synchronized void addMustSucceedBlocks(int blocks) {
+ minSuccessBlocks += blocks;
+ }
+
+ public abstract void notifyClients();
+
+ /** Get client context object */
+ public Object getClient() {
+ return client;
+ }
+
+ public void setPriorityClass(short newPriorityClass) {
+ this.priorityClass = newPriorityClass;
+ chkScheduler.reregisterAll(this);
+ sskScheduler.reregisterAll(this);
+ }
+
+}
Modified: trunk/freenet/src/freenet/client/async/ManifestElement.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ManifestElement.java 2006-03-10
18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/client/async/ManifestElement.java 2006-03-10
22:35:51 UTC (rev 8221)
@@ -33,4 +33,8 @@
}
return false;
}
+
+ public void freeData() {
+ data.free();
+ }
}
Modified: trunk/freenet/src/freenet/client/async/SendableRequest.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SendableRequest.java 2006-03-10
18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/client/async/SendableRequest.java 2006-03-10
22:35:51 UTC (rev 8221)
@@ -21,6 +21,6 @@
public Object getClient();
/** Get the ClientRequest */
- public ClientRequest getClientRequest();
+ public ClientRequester getClientRequest();
}
Modified: trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
2006-03-10 18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
2006-03-10 22:35:51 UTC (rev 8221)
@@ -171,6 +171,9 @@
putHandlersWaitingForMetadata = new HashSet();
waitingForBlockSets = new HashSet();
makePutHandlers(manifestElements, putHandlersByName);
+ }
+
+ public void start() throws InserterException {
Iterator it = runningPutHandlers.iterator();
while(it.hasNext()) {
PutHandler ph = (PutHandler) it.next();
Modified: trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
2006-03-10 18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
2006-03-10 22:35:51 UTC (rev 8221)
@@ -270,7 +270,7 @@
return parent.getClient();
}
- public ClientRequest getClientRequest() {
+ public ClientRequester getClientRequest() {
return parent;
}
Modified: trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
2006-03-10 18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
2006-03-10 22:35:51 UTC (rev 8221)
@@ -571,7 +571,7 @@
return ctx.ignoreStore;
}
- public ClientRequest getClientRequest() {
+ public ClientRequester getClientRequest() {
return parent;
}
Modified: trunk/freenet/src/freenet/node/RequestStarter.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestStarter.java 2006-03-10 18:33:19 UTC
(rev 8220)
+++ trunk/freenet/src/freenet/node/RequestStarter.java 2006-03-10 22:35:51 UTC
(rev 8221)
@@ -3,7 +3,7 @@
import java.util.LinkedList;
import java.util.Vector;
-import freenet.client.async.ClientRequest;
+import freenet.client.async.ClientRequester;
import freenet.client.async.RequestScheduler;
import freenet.client.async.SendableRequest;
import freenet.support.Logger;
Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-03-10 18:33:19 UTC (rev
8220)
+++ trunk/freenet/src/freenet/node/Version.java 2006-03-10 22:35:51 UTC (rev
8221)
@@ -20,7 +20,7 @@
public static final String protocolVersion = "1.0";
/** The build number of the current revision */
- private static final int buildNumber = 521;
+ private static final int buildNumber = 522;
/** Oldest build of Fred we will talk to */
private static final int lastGoodBuild = 507;
Modified: trunk/freenet/src/freenet/node/fcp/ClientGet.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientGet.java 2006-03-10 18:33:19 UTC
(rev 8220)
+++ trunk/freenet/src/freenet/node/fcp/ClientGet.java 2006-03-10 22:35:51 UTC
(rev 8221)
@@ -13,6 +13,7 @@
import freenet.client.async.BaseClientPutter;
import freenet.client.async.ClientCallback;
import freenet.client.async.ClientGetter;
+import freenet.client.async.ClientRequester;
import freenet.client.events.ClientEvent;
import freenet.client.events.ClientEventListener;
import freenet.client.events.SplitfileProgressEvent;
@@ -33,22 +34,11 @@
*/
public class ClientGet extends ClientRequest implements ClientCallback,
ClientEventListener {
- private final FreenetURI uri;
private final FetcherContext fctx;
- private final String identifier;
- private final int verbosity;
- /** Original FCPConnectionHandler. Null if persistence != connection */
- private final FCPConnectionHandler origHandler;
- private final FCPClient client;
private final ClientGetter getter;
- private short priorityClass;
private final short returnType;
- private final short persistenceType;
- /** Has the request finished? */
- private boolean finished;
private final File targetFile;
private final File tempFile;
- String clientToken;
/** Bucket passed in to the ClientGetter to return data in. Null unless
returntype=disk */
private final Bucket returnBucket;
@@ -74,22 +64,10 @@
private SimpleProgressMessage progressPending;
public ClientGet(FCPConnectionHandler handler, ClientGetMessage
message) throws IdentifierCollisionException {
- uri = message.uri;
- clientToken = message.clientToken;
- // FIXME
- this.priorityClass = message.priorityClass;
- this.persistenceType = message.persistenceType;
+ super(message.uri, message.identifier, message.verbosity,
handler, message.priorityClass,
+ message.persistenceType, message.clientToken,
message.global);
// Create a Fetcher directly in order to get more fine-grained
control,
// since the client may override a few context elements.
- if(persistenceType == PERSIST_CONNECTION)
- this.origHandler = handler;
- else
- origHandler = null;
- if(message.global) {
- client = handler.server.globalClient;
- } else {
- client = handler.getClient();
- }
fctx = new FetcherContext(client.defaultFetchContext,
FetcherContext.IDENTICAL_MASK, false);
fctx.eventProducer.addEventListener(this);
// ignoreDS
@@ -97,8 +75,6 @@
fctx.ignoreStore = message.ignoreDS;
fctx.maxNonSplitfileRetries = message.maxRetries;
fctx.maxSplitfileBlockRetries = message.maxRetries;
- this.identifier = message.identifier;
- this.verbosity = message.verbosity;
// FIXME do something with verbosity !!
// Has already been checked
fctx.maxOutputLength = message.maxSize;
@@ -141,18 +117,9 @@
* @throws IOException
*/
public ClientGet(SimpleFieldSet fs, FCPClient client2) throws
IOException {
- uri = new FreenetURI(fs.get("URI"));
- identifier = fs.get("Identifier");
- verbosity = Integer.parseInt(fs.get("Verbosity"));
+ super(fs, client2);
priorityClass = Short.parseShort(fs.get("PriorityClass"));
returnType =
ClientGetMessage.parseValidReturnType(fs.get("ReturnType"));
- persistenceType =
ClientRequest.parsePersistence(fs.get("Persistence"));
- if(persistenceType == ClientRequest.PERSIST_CONNECTION)
- throw new IllegalArgumentException("Reading persistent
get with type CONNECTION !!");
- if(!(persistenceType == ClientRequest.PERSIST_FOREVER ||
persistenceType == ClientRequest.PERSIST_REBOOT))
- throw new IllegalArgumentException("Unknown persistence
type "+ClientRequest.persistenceTypeString(persistenceType));
- this.client = client2;
- this.origHandler = null;
String f = fs.get("Filename");
if(f != null)
targetFile = new File(f);
@@ -163,8 +130,6 @@
tempFile = new File(f);
else
tempFile = null;
- clientToken = fs.get("ClientToken");
- finished = Fields.stringToBool(fs.get("Finished"), false);
boolean ignoreDS = Fields.stringToBool(fs.get("IgnoreDS"),
false);
boolean dsOnly = Fields.stringToBool(fs.get("DSOnly"), false);
int maxRetries = Integer.parseInt(fs.get("MaxRetries"));
@@ -349,13 +314,6 @@
finish();
}
- /** Request completed. But we may have to stick around until we are
acked. */
- private void finish() {
- if(persistenceType == ClientRequest.PERSIST_CONNECTION)
- origHandler.finishedClientRequest(this);
- client.finishedClientRequest(this);
- }
-
public void onSuccess(BaseClientPutter state) {
// Ignore
}
@@ -378,30 +336,6 @@
trySendProgress(progress, null);
}
- public boolean isPersistent() {
- return persistenceType != ClientRequest.PERSIST_CONNECTION;
- }
-
- public void dropped() {
- cancel();
- if(allDataPending != null)
- allDataPending.bucket.free();
- }
-
- public String getIdentifier() {
- return identifier;
- }
-
- public void write(BufferedWriter w) throws IOException {
- if(persistenceType == ClientRequest.PERSIST_CONNECTION) {
- Logger.error(this, "Not persisting as
persistenceType="+persistenceType);
- return;
- }
- // Persist the request to disk
- SimpleFieldSet fs = getFieldSet();
- fs.writeTo(w);
- }
-
// This is distinct from the ClientGetMessage code, as later on it will
be radically
// different (it can store detailed state).
public synchronized SimpleFieldSet getFieldSet() {
@@ -412,7 +346,7 @@
fs.put("Verbosity", Integer.toString(verbosity));
fs.put("PriorityClass", Short.toString(priorityClass));
fs.put("ReturnType",
ClientGetMessage.returnTypeString(returnType));
- fs.put("Persistence",
ClientRequest.persistenceTypeString(persistenceType));
+ fs.put("Persistence", persistenceTypeString(persistenceType));
fs.put("ClientName", client.name);
if(targetFile != null)
fs.put("Filename", targetFile.getPath());
@@ -454,21 +388,13 @@
return fs;
}
- public boolean hasFinished() {
- return finished;
+ protected ClientRequester getClientRequest() {
+ return getter;
}
- public boolean isPersistentForever() {
- return persistenceType == ClientRequest.PERSIST_FOREVER;
+ protected void freeData() {
+ if(returnBucket != null)
+ returnBucket.free();
}
- public void setPriorityClass(short priorityClass) {
- this.priorityClass = priorityClass;
- getter.setPriorityClass(priorityClass);
- }
-
- public void setClientToken(String clientToken) {
- this.clientToken = clientToken;
- }
-
}
Modified: trunk/freenet/src/freenet/node/fcp/ClientPut.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPut.java 2006-03-10 18:33:19 UTC
(rev 8220)
+++ trunk/freenet/src/freenet/node/fcp/ClientPut.java 2006-03-10 22:35:51 UTC
(rev 8221)
@@ -1,107 +1,42 @@
package freenet.node.fcp;
-import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
-import java.net.MalformedURLException;
import freenet.client.ClientMetadata;
-import freenet.client.FetchException;
-import freenet.client.FetchResult;
import freenet.client.InsertBlock;
-import freenet.client.InserterContext;
import freenet.client.InserterException;
-import freenet.client.async.BaseClientPutter;
-import freenet.client.async.ClientCallback;
-import freenet.client.async.ClientGetter;
import freenet.client.async.ClientPutter;
-import freenet.client.events.ClientEvent;
-import freenet.client.events.ClientEventListener;
-import freenet.client.events.FinishedCompressionEvent;
-import freenet.client.events.SimpleEventProducer;
-import freenet.client.events.SplitfileProgressEvent;
-import freenet.client.events.StartedCompressionEvent;
-import freenet.keys.FreenetURI;
import freenet.support.Bucket;
import freenet.support.Fields;
import freenet.support.HexUtil;
-import freenet.support.Logger;
import freenet.support.PaddedEphemerallyEncryptedBucket;
import freenet.support.SimpleFieldSet;
import freenet.support.io.FileBucket;
-public class ClientPut extends ClientRequest implements ClientCallback,
ClientEventListener {
+public class ClientPut extends ClientPutBase {
- final FreenetURI uri;
final ClientPutter inserter;
- final InserterContext ctx;
final InsertBlock block;
- /** Original FCP connection handler. Null if persistence != connection.
*/
- final FCPConnectionHandler origHandler;
- /** Client originating this request */
- final FCPClient client;
- final String identifier;
- final boolean getCHKOnly;
- short priorityClass;
- private final short persistenceType;
- final int verbosity;
- /** Has the request finished? */
- private boolean finished;
- /** Client token - opaque string returned to client in PersistentPut */
- private String clientToken;
/** Was this from disk? Purely for PersistentPut */
private final boolean fromDisk;
/** Original filename if from disk, otherwise null. Purely for
PersistentPut. */
private final File origFilename;
- // Verbosity bitmasks
- private int VERBOSITY_SPLITFILE_PROGRESS = 1;
- private int VERBOSITY_COMPRESSION_START_END = 512;
-
- // Stuff waiting for reconnection
- /** Has the request succeeded? */
- private boolean succeeded;
- /** If the request failed, how did it fail? PutFailedMessage is the most
- * convenient way to store this (InserterException has a stack trace!).
- */
- private PutFailedMessage putFailedMessage;
- /** URI generated for the insert. */
- private FreenetURI generatedURI;
- // This could be a SimpleProgress, or it could be started/finished
compression.
- // Not that important, so not saved on persistence.
- // Probably saving it would conflict with later changes (full
persistence at
- // ClientPutter level).
- private FCPMessage progressMessage;
-
public ClientPut(FCPConnectionHandler handler, ClientPutMessage
message) throws IdentifierCollisionException {
- this.verbosity = message.verbosity;
- this.identifier = message.identifier;
- this.getCHKOnly = message.getCHKOnly;
- this.priorityClass = message.priorityClass;
- this.persistenceType = message.persistenceType;
+ super(message.uri, message.identifier, message.verbosity,
handler,
+ message.priorityClass, message.persistenceType,
message.clientToken, message.global,
+ message.getCHKOnly, message.dontCompress,
message.maxRetries);
this.fromDisk = message.fromDisk;
this.origFilename = message.origFilename;
- if(persistenceType == PERSIST_CONNECTION)
- this.origHandler = handler;
- else
- this.origHandler = null;
- if(message.global) {
- client = handler.server.globalClient;
- } else {
- client = handler.getClient();
- }
- ctx = new InserterContext(client.defaultInsertContext, new
SimpleEventProducer());
- ctx.dontCompress = message.dontCompress;
- ctx.eventProducer.addEventListener(this);
- ctx.maxInsertRetries = message.maxRetries;
// Now go through the fields one at a time
- uri = message.uri;
String mimeType = message.contentType;
clientToken = message.clientToken;
block = new InsertBlock(message.bucket, new
ClientMetadata(mimeType), uri);
if(persistenceType != PERSIST_CONNECTION)
client.register(this);
- inserter = new ClientPutter(this, message.bucket, uri, new
ClientMetadata(mimeType), ctx, client.node.chkPutScheduler,
client.node.sskPutScheduler, priorityClass, getCHKOnly, false, client);
+ inserter = new ClientPutter(this, message.bucket, uri, new
ClientMetadata(mimeType),
+ ctx, client.node.chkPutScheduler,
client.node.sskPutScheduler, priorityClass, getCHKOnly, false, client);
if(persistenceType != PERSIST_CONNECTION && handler != null)
sendPendingMessages(handler.outputHandler, true);
}
@@ -114,25 +49,9 @@
* @throws IOException
*/
public ClientPut(SimpleFieldSet fs, FCPClient client2) throws
PersistenceParseException, IOException {
- uri = new FreenetURI(fs.get("URI"));
- identifier = fs.get("Identifier");
- verbosity = Integer.parseInt(fs.get("Verbosity"));
- priorityClass = Short.parseShort(fs.get("PriorityClass"));
- persistenceType =
ClientRequest.parsePersistence(fs.get("Persistence"));
- if(persistenceType == ClientRequest.PERSIST_CONNECTION
- || persistenceType ==
ClientRequest.PERSIST_REBOOT)
- throw new IllegalArgumentException("Reading in
persistent ClientPut, but persistence type =
"+ClientRequest.persistenceTypeString(persistenceType)+" so shouldn't have been
saved in the first place");
- this.client = client2;
- origHandler = null;
+ super(fs, client2);
String mimeType = fs.get("Metadata.ContentType");
- getCHKOnly = Fields.stringToBool(fs.get("CHKOnly"), false);
- boolean dontCompress =
Fields.stringToBool(fs.get("DontCompress"), false);
- int maxRetries = Integer.parseInt(fs.get("MaxRetries"));
- clientToken = fs.get("ClientToken");
fromDisk = Fields.stringToBool(fs.get("FromDisk"), false);
- finished = Fields.stringToBool(fs.get("Finished"), false);
- //finished = false;
- succeeded = Fields.stringToBool(fs.get("Succeeded"), false);
Bucket data;
if(fromDisk) {
origFilename = new File(fs.get("Filename"));
@@ -148,16 +67,7 @@
throw new
PersistenceParseException("Size of bucket is wrong: "+data.size()+" should be
"+sz);
} else data = null;
}
- ctx = new InserterContext(client.defaultInsertContext, new
SimpleEventProducer());
- ctx.dontCompress = dontCompress;
- ctx.eventProducer.addEventListener(this);
- ctx.maxInsertRetries = maxRetries;
block = new InsertBlock(data, new ClientMetadata(mimeType),
uri);
- String genURI = fs.get("GeneratedURI");
- if(genURI != null)
- generatedURI = new FreenetURI(genURI);
- if(finished && (!succeeded))
- putFailedMessage = new
PutFailedMessage(fs.subset("PutFailed"), false);
inserter = new ClientPutter(this, data, uri, new
ClientMetadata(mimeType), ctx, client.node.chkPutScheduler,
client.node.sskPutScheduler, priorityClass, getCHKOnly, false, client);
if(!finished)
start();
@@ -171,175 +81,14 @@
}
}
- public void onLostConnection() {
- if(persistenceType == PERSIST_CONNECTION)
- cancel();
- // otherwise ignore
- }
-
- public void cancel() {
- inserter.cancel();
- }
-
- public void onSuccess(BaseClientPutter state) {
- synchronized(this) {
- progressMessage = null;
- succeeded = true;
- finished = true;
- }
- trySendFinalMessage(null);
+ protected void freeData() {
block.getData().free();
- finish();
}
-
- public void onFailure(InserterException e, BaseClientPutter state) {
- synchronized(this) {
- finished = true;
- putFailedMessage = new PutFailedMessage(e, identifier);
- }
- trySendFinalMessage(null);
- block.getData().free();
- finish();
- }
-
- public void onGeneratedURI(FreenetURI uri, BaseClientPutter state) {
- synchronized(this) {
- if(generatedURI != null && !uri.equals(generatedURI))
- Logger.error(this,
"onGeneratedURI("+uri+","+state+") but already set generatedURI to
"+generatedURI);
- generatedURI = uri;
- }
- trySendGeneratedURIMessage(null);
- }
-
- public void onSuccess(FetchResult result, ClientGetter state) {
- // ignore
- }
-
- public void onFailure(FetchException e, ClientGetter state) {
- // ignore
- }
-
- public void receive(ClientEvent ce) {
- if(finished) return;
- if(ce instanceof SplitfileProgressEvent) {
- if((verbosity & VERBOSITY_SPLITFILE_PROGRESS) ==
VERBOSITY_SPLITFILE_PROGRESS) {
- SimpleProgressMessage progress =
- new SimpleProgressMessage(identifier,
(SplitfileProgressEvent)ce);
- trySendProgressMessage(progress,
VERBOSITY_SPLITFILE_PROGRESS, null);
- }
- } else if(ce instanceof StartedCompressionEvent) {
- if((verbosity & VERBOSITY_COMPRESSION_START_END) ==
VERBOSITY_COMPRESSION_START_END) {
- StartedCompressionMessage msg =
- new
StartedCompressionMessage(identifier, ((StartedCompressionEvent)ce).codec);
- trySendProgressMessage(msg,
VERBOSITY_COMPRESSION_START_END, null);
- }
- } else if(ce instanceof FinishedCompressionEvent) {
- if((verbosity & VERBOSITY_COMPRESSION_START_END) ==
VERBOSITY_COMPRESSION_START_END) {
- FinishedCompressionMessage msg =
- new
FinishedCompressionMessage(identifier, (FinishedCompressionEvent)ce);
- trySendProgressMessage(msg,
VERBOSITY_COMPRESSION_START_END, null);
- }
- }
- }
- private void trySendFinalMessage(FCPConnectionOutputHandler handler) {
-
- FCPMessage msg;
-
- if(succeeded) {
- msg = new PutSuccessfulMessage(identifier,
generatedURI);
- } else {
- msg = putFailedMessage;
- }
-
- if(msg == null) {
- Logger.error(this, "Trying to send null message on
"+this, new Exception("error"));
- } else {
- if(handler != null)
- handler.queue(msg);
- else
- client.queueClientRequestMessage(msg, 0);
- }
- }
-
- private void trySendGeneratedURIMessage(FCPConnectionOutputHandler
handler) {
- FCPMessage msg = new URIGeneratedMessage(generatedURI,
identifier);
- if(handler != null)
- handler.queue(msg);
- else
- client.queueClientRequestMessage(msg, 0);
- }
-
- private void trySendProgressMessage(FCPMessage msg, int verbosity,
FCPConnectionOutputHandler handler) {
- if(persistenceType != PERSIST_CONNECTION)
- progressMessage = msg;
- if(handler != null)
- handler.queue(msg);
- else
- client.queueClientRequestMessage(msg, verbosity);
- }
-
- public void sendPendingMessages(FCPConnectionOutputHandler handler,
boolean includePersistentRequest) {
- if(persistenceType == PERSIST_CONNECTION) {
- Logger.error(this, "WTF?
persistenceType="+persistenceType, new Exception("error"));
- return;
- }
- if(includePersistentRequest) {
- FCPMessage msg = new PersistentPut(identifier, uri,
verbosity, priorityClass, fromDisk, persistenceType, origFilename,
block.clientMetadata.getMIMEType(), client.isGlobalQueue);
- handler.queue(msg);
- }
- if(generatedURI != null)
- trySendGeneratedURIMessage(handler);
- if(progressMessage != null)
- handler.queue(progressMessage);
- if(finished)
- trySendFinalMessage(handler);
- }
-
- /** Request completed. But we may have to stick around until we are
acked. */
- private void finish() {
- if(persistenceType == ClientRequest.PERSIST_CONNECTION)
- origHandler.finishedClientRequest(this);
- client.finishedClientRequest(this);
- }
-
- public boolean isPersistent() {
- return persistenceType != ClientRequest.PERSIST_CONNECTION;
- }
-
- public void dropped() {
- cancel();
- block.getData().free();
- }
-
- public String getIdentifier() {
- return identifier;
- }
-
- public void write(BufferedWriter w) throws IOException {
- if(persistenceType == ClientRequest.PERSIST_CONNECTION) {
- Logger.error(this, "Not persisting as
persistenceType="+persistenceType);
- return;
- }
- // Persist the request to disk
- SimpleFieldSet fs = getFieldSet();
- fs.writeTo(w);
- }
-
- public synchronized SimpleFieldSet getFieldSet() throws IOException {
- SimpleFieldSet fs = new SimpleFieldSet(true); // we will need
multi-level later...
- fs.put("Type", "PUT");
- fs.put("URI", uri.toString(false));
- fs.put("Identifier", identifier);
- fs.put("Verbosity", Integer.toString(verbosity));
- fs.put("PriorityClass", Short.toString(priorityClass));
- fs.put("Persistence",
ClientRequest.persistenceTypeString(persistenceType));
- fs.put("ClientName", client.name);
+ public synchronized SimpleFieldSet getFieldSet() {
+ SimpleFieldSet fs = super.getFieldSet();
fs.put("Metadata.ContentType",
block.clientMetadata.getMIMEType());
fs.put("GetCHKOnly", Boolean.toString(getCHKOnly));
- // finished => persistence of completion state, pending messages
- //fs.put("Finished", Boolean.toString(finished));
- fs.put("ClientToken", clientToken);
fs.put("FromDisk", Boolean.toString(fromDisk));
if(fromDisk) {
fs.put("Filename", origFilename.getPath());
@@ -350,34 +99,20 @@
fs.put("TempBucket.Filename",
((FileBucket)(bucket.getUnderlying())).getName());
fs.put("TempBucket.Size", Long.toString(bucket.size()));
}
- fs.put("DontCompress", Boolean.toString(ctx.dontCompress));
- fs.put("MaxRetries", Integer.toString(ctx.maxInsertRetries));
- fs.put("Finished", Boolean.toString(finished));
- fs.put("Succeeded", Boolean.toString(succeeded));
- if(generatedURI != null)
- fs.put("GeneratedURI", generatedURI.toString(false));
- if(finished && (!succeeded))
- // Should have a putFailedMessage... unless there is a
race condition.
- fs.put("PutFailed",
putFailedMessage.getFieldSet(false));
- fs.put("Global", Boolean.toString(client.isGlobalQueue));
return fs;
}
- public boolean hasFinished() {
- return finished;
+ protected freenet.client.async.ClientRequester getClientRequest() {
+ return inserter;
}
- public boolean isPersistentForever() {
- return persistenceType == ClientRequest.PERSIST_FOREVER;
+ protected FCPMessage persistentTagMessage() {
+ return new PersistentPut(identifier, uri, verbosity,
priorityClass, fromDisk, persistenceType, origFilename,
+ block.clientMetadata.getMIMEType(),
client.isGlobalQueue);
}
- public void setPriorityClass(short priorityClass) {
- this.priorityClass = priorityClass;
- inserter.setPriorityClass(priorityClass);
+ protected String getTypeName() {
+ return "PUT";
}
-
- public void setClientToken(String clientToken) {
- this.clientToken = clientToken;
- }
-
+
}
Added: trunk/freenet/src/freenet/node/fcp/ClientPutBase.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutBase.java 2006-03-10
18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutBase.java 2006-03-10
22:35:51 UTC (rev 8221)
@@ -0,0 +1,233 @@
+package freenet.node.fcp;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+import freenet.client.FetchException;
+import freenet.client.FetchResult;
+import freenet.client.InserterContext;
+import freenet.client.InserterException;
+import freenet.client.async.BaseClientPutter;
+import freenet.client.async.ClientCallback;
+import freenet.client.async.ClientGetter;
+import freenet.client.async.ClientRequester;
+import freenet.client.events.ClientEvent;
+import freenet.client.events.ClientEventListener;
+import freenet.client.events.FinishedCompressionEvent;
+import freenet.client.events.SimpleEventProducer;
+import freenet.client.events.SplitfileProgressEvent;
+import freenet.client.events.StartedCompressionEvent;
+import freenet.keys.FreenetURI;
+import freenet.support.Fields;
+import freenet.support.Logger;
+import freenet.support.SimpleFieldSet;
+
+/**
+ * Base class for ClientPut and ClientPutDir.
+ * Any code which can be shared between the two goes here.
+ */
+public abstract class ClientPutBase extends ClientRequest implements
ClientCallback, ClientEventListener {
+
+ final InserterContext ctx;
+ final boolean getCHKOnly;
+
+ // Verbosity bitmasks
+ private int VERBOSITY_SPLITFILE_PROGRESS = 1;
+ private int VERBOSITY_COMPRESSION_START_END = 512;
+
+ // Stuff waiting for reconnection
+ /** Has the request succeeded? */
+ protected boolean succeeded;
+ /** If the request failed, how did it fail? PutFailedMessage is the most
+ * convenient way to store this (InserterException has a stack trace!).
+ */
+ private PutFailedMessage putFailedMessage;
+ /** URI generated for the insert. */
+ private FreenetURI generatedURI;
+ // This could be a SimpleProgress, or it could be started/finished
compression.
+ // Not that important, so not saved on persistence.
+ // Probably saving it would conflict with later changes (full
persistence at
+ // ClientPutter level).
+ private FCPMessage progressMessage;
+
+ public ClientPutBase(FreenetURI uri, String identifier, int verbosity,
FCPConnectionHandler handler,
+ short priorityClass, short persistenceType, String
clientToken, boolean global, boolean getCHKOnly,
+ boolean dontCompress, int maxRetries) {
+ super(uri, identifier, verbosity, handler, priorityClass,
persistenceType, clientToken, global);
+ this.getCHKOnly = getCHKOnly;
+ ctx = new InserterContext(client.defaultInsertContext, new
SimpleEventProducer());
+ ctx.dontCompress = dontCompress;
+ ctx.eventProducer.addEventListener(this);
+ ctx.maxInsertRetries = maxRetries;
+ }
+
+ public ClientPutBase(SimpleFieldSet fs, FCPClient client2) throws
MalformedURLException {
+ super(fs, client2);
+ getCHKOnly = Fields.stringToBool(fs.get("CHKOnly"), false);
+ boolean dontCompress =
Fields.stringToBool(fs.get("DontCompress"), false);
+ int maxRetries = Integer.parseInt(fs.get("MaxRetries"));
+ clientToken = fs.get("ClientToken");
+ finished = Fields.stringToBool(fs.get("Finished"), false);
+ //finished = false;
+ succeeded = Fields.stringToBool(fs.get("Succeeded"), false);
+ ctx = new InserterContext(client.defaultInsertContext, new
SimpleEventProducer());
+ ctx.dontCompress = dontCompress;
+ ctx.eventProducer.addEventListener(this);
+ ctx.maxInsertRetries = maxRetries;
+ String genURI = fs.get("GeneratedURI");
+ if(genURI != null)
+ generatedURI = new FreenetURI(genURI);
+ if(finished && (!succeeded))
+ putFailedMessage = new
PutFailedMessage(fs.subset("PutFailed"), false);
+ }
+
+ public void onLostConnection() {
+ if(persistenceType == PERSIST_CONNECTION)
+ cancel();
+ // otherwise ignore
+ }
+
+ public void onSuccess(BaseClientPutter state) {
+ synchronized(this) {
+ progressMessage = null;
+ succeeded = true;
+ finished = true;
+ }
+ trySendFinalMessage(null);
+ freeData();
+ finish();
+ }
+
+ public void onFailure(InserterException e, BaseClientPutter state) {
+ synchronized(this) {
+ finished = true;
+ putFailedMessage = new PutFailedMessage(e, identifier);
+ }
+ trySendFinalMessage(null);
+ freeData();
+ finish();
+ }
+
+ public void onGeneratedURI(FreenetURI uri, BaseClientPutter state) {
+ synchronized(this) {
+ if(generatedURI != null && !uri.equals(generatedURI))
+ Logger.error(this,
"onGeneratedURI("+uri+","+state+") but already set generatedURI to
"+generatedURI);
+ generatedURI = uri;
+ }
+ trySendGeneratedURIMessage(null);
+ }
+
+ public void onSuccess(FetchResult result, ClientGetter state) {
+ // ignore
+ }
+
+ public void onFailure(FetchException e, ClientGetter state) {
+ // ignore
+ }
+
+ public void receive(ClientEvent ce) {
+ if(finished) return;
+ if(ce instanceof SplitfileProgressEvent) {
+ if((verbosity & VERBOSITY_SPLITFILE_PROGRESS) ==
VERBOSITY_SPLITFILE_PROGRESS) {
+ SimpleProgressMessage progress =
+ new SimpleProgressMessage(identifier,
(SplitfileProgressEvent)ce);
+ trySendProgressMessage(progress,
VERBOSITY_SPLITFILE_PROGRESS, null);
+ }
+ } else if(ce instanceof StartedCompressionEvent) {
+ if((verbosity & VERBOSITY_COMPRESSION_START_END) ==
VERBOSITY_COMPRESSION_START_END) {
+ StartedCompressionMessage msg =
+ new
StartedCompressionMessage(identifier, ((StartedCompressionEvent)ce).codec);
+ trySendProgressMessage(msg,
VERBOSITY_COMPRESSION_START_END, null);
+ }
+ } else if(ce instanceof FinishedCompressionEvent) {
+ if((verbosity & VERBOSITY_COMPRESSION_START_END) ==
VERBOSITY_COMPRESSION_START_END) {
+ FinishedCompressionMessage msg =
+ new
FinishedCompressionMessage(identifier, (FinishedCompressionEvent)ce);
+ trySendProgressMessage(msg,
VERBOSITY_COMPRESSION_START_END, null);
+ }
+ }
+ }
+
+ private void trySendFinalMessage(FCPConnectionOutputHandler handler) {
+
+ FCPMessage msg;
+
+ if(succeeded) {
+ msg = new PutSuccessfulMessage(identifier,
generatedURI);
+ } else {
+ msg = putFailedMessage;
+ }
+
+ if(msg == null) {
+ Logger.error(this, "Trying to send null message on
"+this, new Exception("error"));
+ } else {
+ if(handler != null)
+ handler.queue(msg);
+ else
+ client.queueClientRequestMessage(msg, 0);
+ }
+ }
+
+ private void trySendGeneratedURIMessage(FCPConnectionOutputHandler
handler) {
+ FCPMessage msg = new URIGeneratedMessage(generatedURI,
identifier);
+ if(handler != null)
+ handler.queue(msg);
+ else
+ client.queueClientRequestMessage(msg, 0);
+ }
+
+ private void trySendProgressMessage(FCPMessage msg, int verbosity,
FCPConnectionOutputHandler handler) {
+ if(persistenceType != PERSIST_CONNECTION)
+ progressMessage = msg;
+ if(handler != null)
+ handler.queue(msg);
+ else
+ client.queueClientRequestMessage(msg, verbosity);
+ }
+
+ public void sendPendingMessages(FCPConnectionOutputHandler handler,
boolean includePersistentRequest) {
+ if(persistenceType == PERSIST_CONNECTION) {
+ Logger.error(this, "WTF?
persistenceType="+persistenceType, new Exception("error"));
+ return;
+ }
+ if(includePersistentRequest) {
+ FCPMessage msg = persistentTagMessage();
+ handler.queue(msg);
+ }
+ if(generatedURI != null)
+ trySendGeneratedURIMessage(handler);
+ if(progressMessage != null)
+ handler.queue(progressMessage);
+ if(finished)
+ trySendFinalMessage(handler);
+ }
+
+ protected abstract FCPMessage persistentTagMessage();
+
+ public SimpleFieldSet getFieldSet() {
+ SimpleFieldSet fs = new SimpleFieldSet(true); // we will need
multi-level later...
+ fs.put("Type", getTypeName());
+ fs.put("URI", uri.toString(false));
+ fs.put("Identifier", identifier);
+ fs.put("Verbosity", Integer.toString(verbosity));
+ fs.put("PriorityClass", Short.toString(priorityClass));
+ fs.put("Persistence",
ClientRequest.persistenceTypeString(persistenceType));
+ fs.put("ClientName", client.name);
+ fs.put("ClientToken", clientToken);
+ fs.put("DontCompress", Boolean.toString(ctx.dontCompress));
+ fs.put("MaxRetries", Integer.toString(ctx.maxInsertRetries));
+ fs.put("Finished", Boolean.toString(finished));
+ fs.put("Succeeded", Boolean.toString(succeeded));
+ if(generatedURI != null)
+ fs.put("GeneratedURI", generatedURI.toString(false));
+ if(finished && (!succeeded))
+ // Should have a putFailedMessage... unless there is a
race condition.
+ fs.put("PutFailed",
putFailedMessage.getFieldSet(false));
+ fs.put("Global", Boolean.toString(client.isGlobalQueue));
+ return fs;
+ }
+
+ protected abstract String getTypeName();
+
+}
Added: trunk/freenet/src/freenet/node/fcp/ClientPutDir.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutDir.java 2006-03-10
18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutDir.java 2006-03-10
22:35:51 UTC (rev 8221)
@@ -0,0 +1,97 @@
+package freenet.node.fcp;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import freenet.client.FetchException;
+import freenet.client.FetchResult;
+import freenet.client.InserterContext;
+import freenet.client.InserterException;
+import freenet.client.async.BaseClientPutter;
+import freenet.client.async.ClientCallback;
+import freenet.client.async.ClientGetter;
+import freenet.client.async.ClientRequester;
+import freenet.client.async.ManifestElement;
+import freenet.client.async.SimpleManifestPutter;
+import freenet.client.events.ClientEvent;
+import freenet.client.events.ClientEventListener;
+import freenet.client.events.SimpleEventProducer;
+import freenet.keys.FreenetURI;
+import freenet.support.SimpleFieldSet;
+
+public class ClientPutDir extends ClientPutBase implements
ClientEventListener, ClientCallback {
+
+ private HashMap manifestElements;
+ private SimpleManifestPutter putter;
+ private InserterContext ctx;
+
+ public ClientPutDir(FCPConnectionHandler handler, ClientPutDirMessage
message,
+ HashMap manifestElements) throws
IdentifierCollisionException {
+ super(message.uri, message.identifier, message.verbosity,
handler,
+ 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;
+ try {
+ putter = new SimpleManifestPutter(this,
client.node.chkPutScheduler, client.node.sskPutScheduler,
+ manifestElements, priorityClass, uri,
message.defaultName, ctx, message.getCHKOnly, client);
+ } catch (InserterException e) {
+ onFailure(e, null);
+ }
+ if(persistenceType != PERSIST_CONNECTION)
+ client.register(this);
+ }
+
+ public void start() {
+ try {
+ putter.start();
+ } catch (InserterException e) {
+ onFailure(e, null);
+ }
+ }
+
+ public void onLostConnection() {
+ if(persistenceType == PERSIST_CONNECTION)
+ cancel();
+ // otherwise ignore
+ }
+
+ protected void freeData() {
+ freeData(manifestElements);
+ }
+
+ private void freeData(HashMap manifestElements) {
+ Iterator i = manifestElements.values().iterator();
+ while(i.hasNext()) {
+ Object o = i.next();
+ if(o instanceof HashMap)
+ freeData((HashMap)o);
+ else {
+ ManifestElement e = (ManifestElement) o;
+ e.freeData();
+ }
+ }
+ }
+
+ protected ClientRequester getClientRequest() {
+ return putter;
+ }
+
+ public SimpleFieldSet getFieldSet() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected FCPMessage persistentTagMessage() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected String getTypeName() {
+ return "PUTDIR";
+ }
+
+}
Added: trunk/freenet/src/freenet/node/fcp/ClientPutDirMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutDirMessage.java 2006-03-10
18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutDirMessage.java 2006-03-10
22:35:51 UTC (rev 8221)
@@ -0,0 +1,124 @@
+package freenet.node.fcp;
+
+import java.net.MalformedURLException;
+
+import freenet.keys.FreenetURI;
+import freenet.node.RequestStarter;
+import freenet.support.Fields;
+import freenet.support.SimpleFieldSet;
+
+/**
+ * Put a directory, rather than a file.
+ * Base class.
+ *
+ * Two forms: ClientPutDiskDir and ClientPutComplexDir
+ *
+ * Both share:
+ * Identifier=<identifier>
+ * Verbosity=<verbosity as ClientPut>
+ * MaxRetries=<max retries as ClientPut>
+ * PriorityClass=<priority class>
+ * URI=<target URI>
+ * GetCHKOnly=<GetCHKOnly as ClientPut>
+ * DontCompress=<DontCompress as ClientPut>
+ * ClientToken=<ClientToken as ClientPut>
+ * Persistence=<Persistence as ClientPut>
+ * Global=<Global as ClientPut>
+ */
+public abstract class ClientPutDirMessage extends FCPMessage {
+
+ final String identifier;
+ final FreenetURI uri;
+ final int verbosity;
+ final int maxRetries;
+ final boolean getCHKOnly;
+ final short priorityClass;
+ final short persistenceType;
+ final boolean dontCompress;
+ final String clientToken;
+ final boolean global;
+ final String defaultName;
+
+ public ClientPutDirMessage(SimpleFieldSet fs) throws
MessageInvalidException {
+ identifier = fs.get("Identifier");
+ defaultName = fs.get("DefaultName");
+ if(identifier == null)
+ throw new
MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "No Identifier",
null);
+ try {
+ String u = fs.get("URI");
+ if(u == null)
+ throw new
MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "No URI",
identifier);
+ uri = new FreenetURI(fs.get("URI"));
+ } catch (MalformedURLException e) {
+ throw new
MessageInvalidException(ProtocolErrorMessage.URI_PARSE_ERROR, e.getMessage(),
identifier);
+ }
+ global = Fields.stringToBool(fs.get("Global"), false);
+ String verbosityString = fs.get("Verbosity");
+ if(verbosityString == null)
+ verbosity = 0;
+ else {
+ try {
+ verbosity = Integer.parseInt(verbosityString,
10);
+ } catch (NumberFormatException e) {
+ throw new
MessageInvalidException(ProtocolErrorMessage.ERROR_PARSING_NUMBER, "Error
parsing Verbosity field: "+e.getMessage(), identifier);
+ }
+ }
+ String maxRetriesString = fs.get("MaxRetries");
+ if(maxRetriesString == null)
+ // default to 0
+ maxRetries = 0;
+ else {
+ try {
+ maxRetries = Integer.parseInt(maxRetriesString,
10);
+ } catch (NumberFormatException e) {
+ throw new
MessageInvalidException(ProtocolErrorMessage.ERROR_PARSING_NUMBER, "Error
parsing MaxSize field: "+e.getMessage(), identifier);
+ }
+ }
+ getCHKOnly = Fields.stringToBool(fs.get("GetCHKOnly"), false);
+ String priorityString = fs.get("PriorityClass");
+ if(priorityString == null) {
+ // defaults to the one just below fproxy
+ priorityClass =
RequestStarter.IMMEDIATE_SPLITFILE_PRIORITY_CLASS;
+ } else {
+ try {
+ priorityClass =
Short.parseShort(priorityString, 10);
+ if(priorityClass <
RequestStarter.MAXIMUM_PRIORITY_CLASS || priorityClass >
RequestStarter.MINIMUM_PRIORITY_CLASS)
+ throw new
MessageInvalidException(ProtocolErrorMessage.INVALID_FIELD, "Valid priorities
are from "+RequestStarter.MAXIMUM_PRIORITY_CLASS+" to
"+RequestStarter.MINIMUM_PRIORITY_CLASS, identifier);
+ } catch (NumberFormatException e) {
+ throw new
MessageInvalidException(ProtocolErrorMessage.ERROR_PARSING_NUMBER, "Error
parsing PriorityClass field: "+e.getMessage(), identifier);
+ }
+ }
+ dontCompress = Fields.stringToBool(fs.get("DontCompress"),
false);
+ String persistenceString = fs.get("Persistence");
+ if(persistenceString == null ||
persistenceString.equalsIgnoreCase("connection")) {
+ // Default: persists until connection loss.
+ persistenceType = ClientRequest.PERSIST_CONNECTION;
+ } else if(persistenceString.equalsIgnoreCase("reboot")) {
+ // Reports to client by name; persists over connection
loss.
+ // Not saved to disk, so dies on reboot.
+ persistenceType = ClientRequest.PERSIST_REBOOT;
+ } else if(persistenceString.equalsIgnoreCase("forever")) {
+ // Same as reboot but saved to disk, persists forever.
+ persistenceType = ClientRequest.PERSIST_FOREVER;
+ } else {
+ throw new
MessageInvalidException(ProtocolErrorMessage.ERROR_PARSING_NUMBER, "Error
parsing Persistence field: "+persistenceString, identifier);
+ }
+ clientToken = fs.get("ClientToken");
+ }
+
+ public SimpleFieldSet getFieldSet() {
+ SimpleFieldSet sfs = new SimpleFieldSet(false);
+ sfs.put("URI", uri.toString());
+ sfs.put("Identifier", identifier);
+ sfs.put("Verbosity", Integer.toString(verbosity));
+ sfs.put("MaxRetries", Integer.toString(maxRetries));
+ sfs.put("ClientToken", clientToken);
+ sfs.put("GetCHKOnly", Boolean.toString(getCHKOnly));
+ sfs.put("PriorityClass", Short.toString(priorityClass));
+ sfs.put("PersistenceType",
ClientRequest.persistenceTypeString(persistenceType));
+ sfs.put("DontCompress", Boolean.toString(dontCompress));
+ sfs.put("Global", Boolean.toString(global));
+ return sfs;
+ }
+
+}
Added: trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
2006-03-10 18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
2006-03-10 22:35:51 UTC (rev 8221)
@@ -0,0 +1,87 @@
+package freenet.node.fcp;
+
+import java.io.File;
+import java.util.HashMap;
+
+import freenet.client.async.ManifestElement;
+import freenet.node.Node;
+import freenet.support.Fields;
+import freenet.support.Logger;
+import freenet.support.SimpleFieldSet;
+import freenet.support.io.FileBucket;
+
+/**
+ * Insert a directory from disk as a manifest.
+ *
+ * ClientPutDiskDirMessage
+ * < generic fields from ClientPutDirMessage >
+ * Filename=<filename>
+ * AllowUnreadableFiles=<unless true, any unreadable files cause the whole
request to fail>
+ * End
+ */
+public class ClientPutDiskDirMessage extends ClientPutDirMessage {
+
+ public static String name = "ClientPutDiskDir";
+
+ final File dirname;
+ final boolean allowUnreadableFiles;
+
+ public ClientPutDiskDirMessage(SimpleFieldSet fs) throws
MessageInvalidException {
+ super(fs);
+ allowUnreadableFiles =
Fields.stringToBool(fs.get("AllowUnreadableFiles"), false);
+ String fnam = fs.get("Filename");
+ if(fnam == null)
+ throw new
MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "Filename missing",
identifier);
+ dirname = new File(fnam);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void run(FCPConnectionHandler handler, Node node)
+ throws MessageInvalidException {
+ // Create a directory listing of Buckets of data, mapped to
ManifestElement's.
+ // Directories are sub-HashMap's.
+ HashMap buckets = makeBucketsByName(dirname);
+ handler.startClientPutDir(this, buckets);
+ }
+
+ /**
+ * Create a map of String -> Bucket for every file in a directory
+ * and its subdirs.
+ * @throws MessageInvalidException
+ */
+ private HashMap makeBucketsByName(File thisdir) throws
MessageInvalidException {
+
+ Logger.minor(this, "Listing directory: "+thisdir);
+
+ HashMap ret = new HashMap();
+
+ File filelist[] = thisdir.listFiles();
+ if(filelist == null)
+ throw new IllegalArgumentException("No such directory");
+ for(int i = 0 ; i < filelist.length ; i++) {
+ // Skip unreadable files and dirs
+ // Skip files nonexistant (dangling symlinks) - check last
+ if (filelist[i].canRead() && filelist[i].exists()) {
+ if (filelist[i].isFile()) {
+ File f = filelist[i];
+
+ FileBucket bucket = new FileBucket(f, true,
false, false, false);
+
+ ret.put(f.getName(), new
ManifestElement(f.getName(), bucket, null));
+ } else if(filelist[i].isDirectory()) {
+ HashMap subdir = makeBucketsByName(new
File(thisdir, filelist[i].getName()));
+ ret.put(filelist[i].getName(), subdir);
+ } else if(!allowUnreadableFiles) {
+ throw new
MessageInvalidException(ProtocolErrorMessage.FILE_NOT_FOUND, "Not directory and
not file: "+filelist[i], identifier);
+ }
+ } else {
+ throw new
MessageInvalidException(ProtocolErrorMessage.FILE_NOT_FOUND, "Not readable or
doesn't exist: "+filelist[i], identifier);
+ }
+ }
+ return ret;
+ }
+
+}
Modified: trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java 2006-03-10
18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java 2006-03-10
22:35:51 UTC (rev 8221)
@@ -147,10 +147,22 @@
SimpleFieldSet sfs = new SimpleFieldSet(false);
sfs.put("URI", uri.toString());
sfs.put("Identifier", identifier);
- sfs.put("DataLength", Long.toString(dataLength));
sfs.put("Verbosity", Integer.toString(verbosity));
sfs.put("MaxRetries", Integer.toString(maxRetries));
sfs.put("Metadata.ContentType", contentType);
+ sfs.put("ClientToken", clientToken);
+ if(fromDisk) {
+ sfs.put("UploadFrom", "disk");
+ sfs.put("Filename", origFilename.getAbsolutePath());
+ } else {
+ sfs.put("UploadFrom", "direct");
+ sfs.put("DataLength", Long.toString(dataLength));
+ }
+ sfs.put("GetCHKOnly", Boolean.toString(getCHKOnly));
+ sfs.put("PriorityClass", Short.toString(priorityClass));
+ sfs.put("PersistenceType",
ClientRequest.persistenceTypeString(persistenceType));
+ sfs.put("DontCompress", Boolean.toString(dontCompress));
+ sfs.put("Global", Boolean.toString(global));
return sfs;
}
Modified: trunk/freenet/src/freenet/node/fcp/ClientRequest.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientRequest.java 2006-03-10
18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/node/fcp/ClientRequest.java 2006-03-10
22:35:51 UTC (rev 8221)
@@ -3,7 +3,10 @@
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
+import java.net.MalformedURLException;
+import freenet.client.async.ClientRequester;
+import freenet.keys.FreenetURI;
import freenet.support.Fields;
import freenet.support.Logger;
import freenet.support.SimpleFieldSet;
@@ -14,17 +17,68 @@
*/
public abstract class ClientRequest {
- /** Lost connection */
- public abstract void onLostConnection();
+ /** URI to fetch, or target URI to insert to */
+ protected final FreenetURI uri;
+ /** Unique request identifier */
+ protected final String identifier;
+ /** Verbosity level. Relevant to all ClientRequests, although they
interpret it
+ * differently. */
+ protected final int verbosity;
+ /** Original FCPConnectionHandler. Null if persistence != connection */
+ protected final FCPConnectionHandler origHandler;
+ /** Client */
+ protected final FCPClient client;
+ /** Priority class */
+ protected short priorityClass;
+ /** Persistence type */
+ protected final short persistenceType;
+ /** Has the request finished? */
+ protected boolean finished;
+ /** Client token (string to feed back to the client on a Persistent*
when he does a
+ * ListPersistentRequests). */
+ protected String clientToken;
+ /** Is the request on the global queue? */
+ protected final boolean global;
- /** Is the request persistent? False = we can drop the request if we
lose the connection */
- public abstract boolean isPersistent();
+ public ClientRequest(FreenetURI uri2, String identifier2, int
verbosity2, FCPConnectionHandler handler,
+ short priorityClass2, short persistenceType2, String
clientToken2, boolean global) {
+ this.uri = uri2;
+ this.identifier = identifier2;
+ this.verbosity = verbosity2;
+ this.finished = false;
+ this.priorityClass = priorityClass2;
+ this.persistenceType = persistenceType2;
+ this.clientToken = clientToken2;
+ this.global = global;
+ if(persistenceType == PERSIST_CONNECTION)
+ this.origHandler = handler;
+ else
+ origHandler = null;
+ if(global) {
+ client = handler.server.globalClient;
+ } else {
+ client = handler.getClient();
+ }
+ }
- /** Completed request dropped off the end without being acknowledged */
- public abstract void dropped();
+ public ClientRequest(SimpleFieldSet fs, FCPClient client2) throws
MalformedURLException {
+ uri = new FreenetURI(fs.get("URI"));
+ identifier = fs.get("Identifier");
+ verbosity = Integer.parseInt(fs.get("Verbosity"));
+ persistenceType =
ClientRequest.parsePersistence(fs.get("Persistence"));
+ if(persistenceType == ClientRequest.PERSIST_CONNECTION)
+ throw new IllegalArgumentException("Reading persistent
get with type CONNECTION !!");
+ if(!(persistenceType == ClientRequest.PERSIST_FOREVER ||
persistenceType == ClientRequest.PERSIST_REBOOT))
+ throw new IllegalArgumentException("Unknown persistence
type "+ClientRequest.persistenceTypeString(persistenceType));
+ this.client = client2;
+ this.origHandler = null;
+ clientToken = fs.get("ClientToken");
+ finished = Fields.stringToBool(fs.get("Finished"), false);
+ global = Fields.stringToBool(fs.get("Global"), false);
+ }
- /** Get identifier string for request */
- public abstract String getIdentifier();
+ /** Lost connection */
+ public abstract void onLostConnection();
/** Send any pending messages for a persistent request e.g. after
reconnecting */
public abstract void sendPendingMessages(FCPConnectionOutputHandler
handler, boolean includePersistentRequest);
@@ -58,12 +112,6 @@
return Short.parseShort(string);
}
- /**
- * Write a persistent request to disk.
- * @throws IOException
- */
- public abstract void write(BufferedWriter w) throws IOException;
-
public static ClientRequest readAndRegister(BufferedReader br,
FCPServer server) throws IOException {
SimpleFieldSet fs = new SimpleFieldSet(br, true);
String clientName = fs.get("ClientName");
@@ -93,14 +141,71 @@
}
}
- public abstract boolean hasFinished();
-
- public abstract boolean isPersistentForever();
+ public void cancel() {
+ getClientRequest().cancel();
+ }
- public abstract void cancel();
+ public boolean isPersistentForever() {
+ return persistenceType == ClientRequest.PERSIST_FOREVER;
+ }
- public abstract void setPriorityClass(short priorityClass);
+ /** Is the request persistent? False = we can drop the request if we
lose the connection */
+ public boolean isPersistent() {
+ return persistenceType != ClientRequest.PERSIST_CONNECTION;
+ }
- public abstract void setClientToken(String clientToken);
+ public boolean hasFinished() {
+ return finished;
+ }
+ /** Get identifier string for request */
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ public void setPriorityClass(short priorityClass) {
+ this.priorityClass = priorityClass;
+ getClientRequest().setPriorityClass(priorityClass);
+ }
+
+ public void setClientToken(String clientToken) {
+ this.clientToken = clientToken;
+ }
+
+ protected abstract ClientRequester getClientRequest();
+
+ /** Completed request dropped off the end without being acknowledged */
+ public void dropped() {
+ cancel();
+ freeData();
+ }
+
+ /** Free cached data bucket(s) */
+ protected abstract void freeData();
+
+ /** Request completed. But we may have to stick around until we are
acked. */
+ protected void finish() {
+ if(persistenceType == ClientRequest.PERSIST_CONNECTION)
+ origHandler.finishedClientRequest(this);
+ client.finishedClientRequest(this);
+ }
+
+ /**
+ * Write a persistent request to disk.
+ * @throws IOException
+ */
+ public void write(BufferedWriter w) throws IOException {
+ if(persistenceType == ClientRequest.PERSIST_CONNECTION) {
+ Logger.error(this, "Not persisting as
persistenceType="+persistenceType);
+ return;
+ }
+ // Persist the request to disk
+ SimpleFieldSet fs = getFieldSet();
+ fs.writeTo(w);
+ }
+
+ /**
+ * Get a SimpleFieldSet representing this request.
+ */
+ public abstract SimpleFieldSet getFieldSet() throws IOException;
}
Modified: trunk/freenet/src/freenet/node/fcp/FCPConnectionHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPConnectionHandler.java
2006-03-10 18:33:19 UTC (rev 8220)
+++ trunk/freenet/src/freenet/node/fcp/FCPConnectionHandler.java
2006-03-10 22:35:51 UTC (rev 8221)
@@ -174,6 +174,44 @@
}
}
+ public void startClientPutDir(ClientPutDiskDirMessage message, HashMap
buckets) {
+ String id = message.identifier;
+ ClientPutDir cp = null;
+ boolean success;
+ boolean persistent = message.persistenceType !=
ClientGet.PERSIST_CONNECTION;
+ synchronized(this) {
+ if(isClosed) return;
+ // We need to track non-persistent requests anyway, so
we may as well check
+ if(persistent)
+ success = true;
+ else
+ success = !requestsByIdentifier.containsKey(id);
+ if(success) {
+ try {
+ cp = new ClientPutDir(this, message,
buckets);
+ } catch (IdentifierCollisionException e) {
+ success = false;
+ }
+ if(!persistent)
+ requestsByIdentifier.put(id, cp);
+ }
+ }
+ if(!success) {
+ Logger.normal(this, "Identifier collision on "+this);
+ FCPMessage msg = new IdentifierCollisionMessage(id);
+ outputHandler.queue(msg);
+ return;
+ } else {
+ // Register before starting, because it may complete
immediately, and if it does,
+ // we may end up with it not being removable because it
wasn't registered!
+ if(cp.isPersistent()) {
+ if(cp.isPersistentForever())
+ server.forceStorePersistentRequests();
+ }
+ cp.start();
+ }
+ }
+
public FCPClient getClient() {
return client;
}
@@ -183,5 +221,5 @@
requestsByIdentifier.remove(get.getIdentifier());
}
}
-
+
}
Modified: trunk/freenet/src/freenet/node/fcp/FCPMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPMessage.java 2006-03-10 18:33:19 UTC
(rev 8220)
+++ trunk/freenet/src/freenet/node/fcp/FCPMessage.java 2006-03-10 22:35:51 UTC
(rev 8221)
@@ -41,6 +41,8 @@
return new WatchGlobal(fs);
if(name.equals(ModifyPersistentRequest.name))
return new ModifyPersistentRequest(fs);
+ if(name.equals(ClientPutDiskDirMessage.name))
+ return new ClientPutDiskDirMessage(fs);
if(name.equals("Void"))
return null;
throw new
MessageInvalidException(ProtocolErrorMessage.INVALID_MESSAGE, "Unknown message
name "+name, null);