Author: toad
Date: 2006-03-25 16:36:47 +0000 (Sat, 25 Mar 2006)
New Revision: 8312
Added:
trunk/freenet/src/freenet/client/async/USKInserter.java
trunk/freenet/src/freenet/keys/InsertableUSK.java
Modified:
trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
trunk/freenet/src/freenet/client/InserterContext.java
trunk/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
trunk/freenet/src/freenet/client/async/ClientPutState.java
trunk/freenet/src/freenet/client/async/ClientPutter.java
trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
trunk/freenet/src/freenet/client/async/MultiPutCompletionCallback.java
trunk/freenet/src/freenet/client/async/PutCompletionCallback.java
trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
trunk/freenet/src/freenet/client/async/SingleFileInserter.java
trunk/freenet/src/freenet/client/async/SplitFileInserter.java
trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java
trunk/freenet/src/freenet/client/async/USKFetcher.java
trunk/freenet/src/freenet/client/async/USKManager.java
trunk/freenet/src/freenet/keys/InsertableClientSSK.java
trunk/freenet/src/freenet/keys/USK.java
trunk/freenet/src/freenet/node/Node.java
trunk/freenet/src/freenet/node/Version.java
Log:
571:
USK insert support (over FCP).
Also some USK bugfixes.
Modified: trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
===================================================================
--- trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
2006-03-25 15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
2006-03-25 16:36:47 UTC (rev 8312)
@@ -145,11 +145,13 @@
SPLITFILE_THREADS, SPLITFILE_BLOCK_RETRIES,
NON_SPLITFILE_RETRIES,
FETCH_SPLITFILES, FOLLOW_REDIRECTS,
LOCAL_REQUESTS_ONLY,
MAX_SPLITFILE_BLOCKS_PER_SEGMENT,
MAX_SPLITFILE_CHECK_BLOCKS_PER_SEGMENT,
- random, archiveManager, bucketFactory,
globalEventProducer, cacheLocalRequests, node.uskManager);
+ random, archiveManager, bucketFactory,
globalEventProducer,
+ cacheLocalRequests, node.uskManager);
}
public InserterContext getInserterContext() {
return new InserterContext(bucketFactory, random,
INSERT_RETRIES, CONSECUTIVE_RNFS_ASSUME_SUCCESS,
- SPLITFILE_INSERT_THREADS,
SPLITFILE_BLOCKS_PER_SEGMENT, SPLITFILE_CHECK_BLOCKS_PER_SEGMENT,
globalEventProducer, cacheLocalRequests);
+ SPLITFILE_INSERT_THREADS,
SPLITFILE_BLOCKS_PER_SEGMENT, SPLITFILE_CHECK_BLOCKS_PER_SEGMENT,
+ globalEventProducer, cacheLocalRequests,
node.uskManager);
}
}
Modified: trunk/freenet/src/freenet/client/InserterContext.java
===================================================================
--- trunk/freenet/src/freenet/client/InserterContext.java 2006-03-25
15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/InserterContext.java 2006-03-25
16:36:47 UTC (rev 8312)
@@ -1,5 +1,6 @@
package freenet.client;
+import freenet.client.async.USKManager;
import freenet.client.events.ClientEventProducer;
import freenet.client.events.SimpleEventProducer;
import freenet.crypt.RandomSource;
@@ -21,11 +22,13 @@
public final ClientEventProducer eventProducer;
/** Interesting tradeoff, see comments at top of Node.java. */
public final boolean cacheLocalRequests;
+ public final USKManager uskManager;
public InserterContext(BucketFactory bf, RandomSource random,
int maxRetries, int rnfsToSuccess, int maxThreads, int
splitfileSegmentDataBlocks, int splitfileSegmentCheckBlocks,
- ClientEventProducer eventProducer, boolean
cacheLocalRequests) {
+ ClientEventProducer eventProducer, boolean
cacheLocalRequests, USKManager uskManager) {
this.bf = bf;
+ this.uskManager = uskManager;
this.random = random;
dontCompress = false;
splitfileAlgorithm = Metadata.SPLITFILE_ONION_STANDARD;
@@ -39,6 +42,7 @@
}
public InserterContext(InserterContext ctx) {
+ this.uskManager = ctx.uskManager;
this.bf = ctx.bf;
this.random = ctx.random;
this.dontCompress = ctx.dontCompress;
@@ -53,6 +57,7 @@
}
public InserterContext(InserterContext ctx, SimpleEventProducer
producer) {
+ this.uskManager = ctx.uskManager;
this.bf = ctx.bf;
this.random = ctx.random;
this.dontCompress = ctx.dontCompress;
Modified: trunk/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
2006-03-25 15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
2006-03-25 16:36:47 UTC (rev 8312)
@@ -84,8 +84,7 @@
}
public boolean ignoreStore() {
- // TODO Auto-generated method stub
- return false;
+ return ctx.ignoreStore;
}
public synchronized void cancel() {
Modified: trunk/freenet/src/freenet/client/async/ClientPutState.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientPutState.java 2006-03-25
15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/ClientPutState.java 2006-03-25
16:36:47 UTC (rev 8312)
@@ -1,5 +1,7 @@
package freenet.client.async;
+import freenet.client.InserterException;
+
/**
* ClientPutState
*
@@ -11,4 +13,5 @@
public abstract void cancel();
+ public abstract void schedule() throws InserterException;
}
Modified: trunk/freenet/src/freenet/client/async/ClientPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientPutter.java 2006-03-25
15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/ClientPutter.java 2006-03-25
16:36:47 UTC (rev 8312)
@@ -6,6 +6,7 @@
import freenet.client.InserterException;
import freenet.client.Metadata;
import freenet.client.events.SplitfileProgressEvent;
+import freenet.keys.BaseClientKey;
import freenet.keys.ClientKey;
import freenet.keys.FreenetURI;
import freenet.support.Bucket;
@@ -78,7 +79,7 @@
client.onFailure(e, this);
}
- public void onEncode(ClientKey key, ClientPutState state) {
+ public void onEncode(BaseClientKey key, ClientPutState state) {
this.uri = key.getURI();
client.onGeneratedURI(uri, this);
}
Modified: trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
2006-03-25 15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
2006-03-25 16:36:47 UTC (rev 8312)
@@ -32,16 +32,18 @@
private final SortedVectorByNumber[] priorities;
// we have one for inserts and one for requests
final boolean isInsertScheduler;
+ final boolean isSSKScheduler;
final RandomSource random;
private final HashMap allRequestsByClientRequest;
private final RequestStarter starter;
private final Node node;
- public ClientRequestScheduler(boolean forInserts, RandomSource random,
RequestStarter starter, Node node) {
+ public ClientRequestScheduler(boolean forInserts, boolean forSSKs,
RandomSource random, RequestStarter starter, Node node) {
this.starter = starter;
this.random = random;
this.node = node;
this.isInsertScheduler = forInserts;
+ this.isSSKScheduler = forSSKs;
priorities = new
SortedVectorByNumber[RequestStarter.NUMBER_OF_PRIORITY_CLASSES];
allRequestsByClientRequest = new HashMap();
}
Modified: trunk/freenet/src/freenet/client/async/MultiPutCompletionCallback.java
===================================================================
--- trunk/freenet/src/freenet/client/async/MultiPutCompletionCallback.java
2006-03-25 15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/MultiPutCompletionCallback.java
2006-03-25 16:36:47 UTC (rev 8312)
@@ -5,6 +5,7 @@
import freenet.client.InserterException;
import freenet.client.Metadata;
+import freenet.keys.BaseClientKey;
import freenet.keys.ClientKey;
import freenet.support.Logger;
@@ -90,7 +91,7 @@
return parent;
}
- public void onEncode(ClientKey key, ClientPutState state) {
+ public void onEncode(BaseClientKey key, ClientPutState state) {
synchronized(this) {
if(state != generator) return;
}
@@ -134,4 +135,8 @@
cb.onBlockSetFinished(this);
}
+ public void schedule() throws InserterException {
+ // Do nothing
+ }
+
}
Modified: trunk/freenet/src/freenet/client/async/PutCompletionCallback.java
===================================================================
--- trunk/freenet/src/freenet/client/async/PutCompletionCallback.java
2006-03-25 15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/PutCompletionCallback.java
2006-03-25 16:36:47 UTC (rev 8312)
@@ -2,7 +2,9 @@
import freenet.client.InserterException;
import freenet.client.Metadata;
+import freenet.keys.BaseClientKey;
import freenet.keys.ClientKey;
+import freenet.keys.USK;
/**
* Callback called when part of a put request completes.
@@ -13,7 +15,7 @@
public void onFailure(InserterException e, ClientPutState state);
- public void onEncode(ClientKey key, ClientPutState state);
+ public void onEncode(BaseClientKey usk, ClientPutState state);
public void onTransition(ClientPutState oldState, ClientPutState
newState);
Modified: trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
2006-03-25 15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
2006-03-25 16:36:47 UTC (rev 8312)
@@ -13,6 +13,7 @@
import freenet.client.InserterException;
import freenet.client.Metadata;
import freenet.client.events.SplitfileProgressEvent;
+import freenet.keys.BaseClientKey;
import freenet.keys.ClientKey;
import freenet.keys.FreenetURI;
import freenet.support.Bucket;
@@ -84,7 +85,7 @@
fail(e);
}
- public void onEncode(ClientKey key, ClientPutState state) {
+ public void onEncode(BaseClientKey key, ClientPutState state) {
if(metadata == null) {
// Don't have metadata yet
// Do have key
@@ -355,7 +356,7 @@
fail(e);
}
- public void onEncode(ClientKey key, ClientPutState state) {
+ public void onEncode(BaseClientKey key, ClientPutState state) {
this.finalURI = key.getURI();
Logger.minor(this, "Got metadata key: "+finalURI);
cb.onGeneratedURI(finalURI, this);
Modified: trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
2006-03-25 15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
2006-03-25 16:36:47 UTC (rev 8312)
@@ -522,7 +522,7 @@
}
private static ClientGetState uskCreate(ClientGetter parent,
GetCompletionCallback cb, ClientMetadata clientMetadata, USK usk, LinkedList
metaStrings, FetcherContext ctx, ArchiveContext actx, int maxRetries, int
recursionLevel, boolean dontTellClientGet, Object token, boolean isEssential,
Bucket returnBucket) throws FetchException {
- if(usk.suggestedEdition > 0) {
+ if(usk.suggestedEdition >= 0) {
// Return the latest known version but at least
suggestedEdition.
long edition = ctx.uskManager.lookup(usk);
if(edition <= usk.suggestedEdition) {
@@ -583,7 +583,7 @@
this.returnBucket = returnBucket;
}
- public void onFoundEdition(long l, USK usk) {
+ public void onFoundEdition(long l, USK newUSK) {
ClientSSK key = usk.getSSK(l);
try {
if(l == Math.abs(usk.suggestedEdition)) {
@@ -592,7 +592,7 @@
token, false,
returnBucket);
sf.schedule();
} else {
- cb.onFailure(new
FetchException(FetchException.PERMANENT_REDIRECT,
usk.copy(l).getURI().addMetaStrings(metaStrings)), null);
+ cb.onFailure(new
FetchException(FetchException.PERMANENT_REDIRECT,
newUSK.getURI().addMetaStrings(metaStrings)), null);
}
} catch (FetchException e) {
cb.onFailure(e, null);
Modified: trunk/freenet/src/freenet/client/async/SingleFileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileInserter.java
2006-03-25 15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/SingleFileInserter.java
2006-03-25 16:36:47 UTC (rev 8312)
@@ -1,6 +1,7 @@
package freenet.client.async;
import java.io.IOException;
+import java.net.MalformedURLException;
import freenet.client.InsertBlock;
import freenet.client.InserterContext;
@@ -8,6 +9,7 @@
import freenet.client.Metadata;
import freenet.client.events.FinishedCompressionEvent;
import freenet.client.events.StartedCompressionEvent;
+import freenet.keys.BaseClientKey;
import freenet.keys.CHKBlock;
import freenet.keys.ClientCHKBlock;
import freenet.keys.ClientKey;
@@ -96,12 +98,12 @@
long origSize = data.size();
String type = block.desiredURI.getKeyType().toUpperCase();
- if(type.equals("SSK") || type.equals("KSK")) {
+ if(type.equals("SSK") || type.equals("KSK") ||
type.equals("USK")) {
blockSize = SSKBlock.DATA_LENGTH;
} else if(type.equals("CHK")) {
blockSize = CHKBlock.DATA_LENGTH;
} else {
- throw new
InserterException(InserterException.INVALID_URI);
+ throw new
InserterException(InserterException.INVALID_URI, "Unknown key type: "+type,
null);
}
Compressor bestCodec = null;
@@ -162,7 +164,8 @@
if((block.clientMetadata == null ||
block.clientMetadata.isTrivial())) {
if(data.size() < blockSize) {
// Just insert it
- SingleBlockInserter bi = new
SingleBlockInserter(parent, data, codecNumber, block.desiredURI, ctx, cb,
metadata, (int)block.getData().size(), -1, getCHKOnly, true);
+ ClientPutState bi =
+ createInserter(parent, data,
codecNumber, block.desiredURI, ctx, cb, metadata, (int)block.getData().size(),
-1, getCHKOnly, true);
cb.onTransition(this, bi);
bi.schedule();
cb.onBlockSetFinished(this);
@@ -189,7 +192,7 @@
} catch (IOException e) {
throw new
InserterException(InserterException.BUCKET_ERROR, e, null);
}
- SingleBlockInserter metaPutter = new
SingleBlockInserter(parent, metadataBucket, (short) -1, block.desiredURI, ctx,
mcb, true, (int)origSize, -1, getCHKOnly, true);
+ ClientPutState metaPutter =
createInserter(parent, metadataBucket, (short) -1, block.desiredURI, ctx, mcb,
true, (int)origSize, -1, getCHKOnly, true);
mcb.addURIGenerator(metaPutter);
mcb.add(dataPutter);
cb.onTransition(this, mcb);
@@ -219,6 +222,22 @@
return;
}
+ private ClientPutState createInserter(BaseClientPutter parent, Bucket
data, short compressionCodec, FreenetURI uri,
+ InserterContext ctx, PutCompletionCallback cb, boolean
isMetadata, int sourceLength, int token, boolean getCHKOnly,
+ boolean addToParent) throws InserterException {
+ if(uri.getKeyType().equals("USK")) {
+ try {
+ return new USKInserter(parent, data,
compressionCodec, uri, ctx, cb, isMetadata, sourceLength, token,
+ getCHKOnly, addToParent);
+ } catch (MalformedURLException e) {
+ throw new
InserterException(InserterException.INVALID_URI, e, null);
+ }
+ } else {
+ return new SingleBlockInserter(parent, data,
compressionCodec, uri, ctx, cb, isMetadata, sourceLength, token,
+ getCHKOnly, addToParent);
+ }
+ }
+
/**
* When we get the metadata, start inserting it to our target key.
* When we have inserted both the metadata and the splitfile,
@@ -323,7 +342,7 @@
return parent;
}
- public void onEncode(ClientKey key, ClientPutState state) {
+ public void onEncode(BaseClientKey key, ClientPutState state) {
if(state == metadataPutter)
cb.onEncode(key, this);
}
@@ -346,6 +365,10 @@
}
cb.onBlockSetFinished(this);
}
+
+ public void schedule() throws InserterException {
+ // Do nothing
+ }
}
@@ -356,4 +379,8 @@
public void cancel() {
cancelled = true;
}
+
+ public void schedule() throws InserterException {
+ start();
+ }
}
Modified: trunk/freenet/src/freenet/client/async/SplitFileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileInserter.java
2006-03-25 15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/SplitFileInserter.java
2006-03-25 16:36:47 UTC (rev 8312)
@@ -268,4 +268,8 @@
segments[i].cancel();
}
+ public void schedule() throws InserterException {
+ start();
+ }
+
}
Modified: trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java
2006-03-25 15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java
2006-03-25 16:36:47 UTC (rev 8312)
@@ -7,6 +7,7 @@
import freenet.client.InserterContext;
import freenet.client.InserterException;
import freenet.client.Metadata;
+import freenet.keys.BaseClientKey;
import freenet.keys.ClientCHKBlock;
import freenet.keys.ClientKey;
import freenet.keys.FreenetURI;
@@ -117,7 +118,7 @@
parent.segmentFinished(this);
}
- public void onEncode(ClientKey key, ClientPutState state) {
+ public void onEncode(BaseClientKey key, ClientPutState state) {
SingleBlockInserter sbi = (SingleBlockInserter)state;
int x = sbi.token;
FreenetURI uri = key.getURI();
Modified: trunk/freenet/src/freenet/client/async/USKFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/USKFetcher.java 2006-03-25
15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/USKFetcher.java 2006-03-25
16:36:47 UTC (rev 8312)
@@ -72,7 +72,7 @@
/** Cancelled? */
private boolean cancelled;
-
+
final ClientRequester parent;
public synchronized boolean addCallback(USKFetcherCallback cb) {
@@ -169,6 +169,8 @@
/** Keep going forever? */
private final boolean backgroundPoll;
+ private boolean started = false;
+
USKFetcher(USK origUSK, USKManager manager, FetcherContext ctx,
ClientRequester parent, int minFailures, boolean pollForever) {
this.parent = parent;
this.origUSK = origUSK;
@@ -187,13 +189,15 @@
Logger.minor(this, "DNF: "+att);
boolean finished = false;
synchronized(this) {
+ if(completed || cancelled) return;
lastFetchedEdition = Math.max(lastFetchedEdition,
att.number);
runningAttempts.remove(att);
if(runningAttempts.isEmpty()) {
long curLatest = uskManager.lookup(origUSK);
Logger.minor(this, "latest: "+curLatest+", last
fetched: "+lastFetchedEdition+", curLatest+MIN_FAILURES:
"+(curLatest+minFailures));
- if(curLatest + minFailures >=
lastFetchedEdition) {
+ if(started) {
finished = true;
+ completed = true;
}
} else
Logger.minor(this, "Remaining:
"+runningAttempts.size());
@@ -206,6 +210,7 @@
private void finishSuccess() {
if(backgroundPoll) {
synchronized(this) {
+ started = false; // don't finish before have
rescheduled
long valAtEnd = uskManager.lookup(origUSK);
if(valAtEnd > valueAtSchedule) {
// Have advanced.
@@ -255,6 +260,7 @@
void onSuccess(USKAttempt att, boolean dontUpdate) {
LinkedList l = null;
synchronized(this) {
+ if(completed || cancelled) return;
runningAttempts.remove(att);
long curLatest = att.number;
if(!dontUpdate)
@@ -353,6 +359,7 @@
for(long i=startPoint;i<startPoint+minFailures;i++)
add(i);
attempts = (USKAttempt[]) runningAttempts.toArray(new
USKAttempt[runningAttempts.size()]);
+ started = true;
}
if(!cancelled)
for(int i=0;i<attempts.length;i++)
Added: trunk/freenet/src/freenet/client/async/USKInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/USKInserter.java 2006-03-25
15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/USKInserter.java 2006-03-25
16:36:47 UTC (rev 8312)
@@ -0,0 +1,195 @@
+package freenet.client.async;
+
+import java.net.MalformedURLException;
+
+import freenet.client.InserterContext;
+import freenet.client.InserterException;
+import freenet.client.Metadata;
+import freenet.keys.BaseClientKey;
+import freenet.keys.FreenetURI;
+import freenet.keys.InsertableUSK;
+import freenet.keys.USK;
+import freenet.support.Bucket;
+import freenet.support.Logger;
+
+/**
+ * Insert a USK. The algorithm is simply to do a thorough search for the
latest edition, and insert at the
+ * following slot. Thereafter, if we get a collision, increment our slot; if
we get more than 5 consecutive
+ * collisions, search for the latest slot again.
+ */
+public class USKInserter implements ClientPutState, USKFetcherCallback,
PutCompletionCallback {
+
+ // Stuff to be passed on to the SingleBlockInserter
+ final BaseClientPutter parent;
+ final Bucket data;
+ final short compressionCodec;
+ final InserterContext ctx;
+ final PutCompletionCallback cb;
+ final boolean isMetadata;
+ final int sourceLength;
+ final int token;
+ final boolean getCHKOnly;
+
+ final InsertableUSK privUSK;
+ final USK pubUSK;
+ /** Scanning for latest slot */
+ private USKFetcher fetcher;
+ /** Insert the actual SSK */
+ private SingleBlockInserter sbi;
+ private long edition;
+ /** Number of collisions while trying to insert so far */
+ private int consecutiveCollisions = 0;
+ private boolean finished;
+ /** After attempting inserts on this many slots, go back to the Fetcher
*/
+ private static final long MAX_TRIED_SLOTS = 10;
+
+ public void schedule() throws InserterException {
+ // Caller calls schedule()
+ // schedule() calls scheduleFetcher()
+ // scheduleFetcher() creates a Fetcher (set up to tell us about
author-errors as well as valid inserts)
+ // (and starts it)
+ // when this completes, onFoundEdition() calls scheduleInsert()
+ // scheduleInsert() starts a SingleBlockInserter
+ // if that succeeds, we complete
+ // if that fails, we increment our index and try again (in the
callback)
+ // if that continues to fail 5 times, we go back to
scheduleFetcher()
+ scheduleFetcher();
+ }
+
+ /**
+ * Schedule a Fetcher to find us the latest inserted key of the USK.
+ * The Fetcher must be insert-mode, in other words, it must know that
we want the latest edition,
+ * including author errors and so on.
+ */
+ private void scheduleFetcher() {
+ Logger.minor(this, "scheduling fetcher for "+pubUSK.getURI());
+ synchronized(this) {
+ if(finished) return;
+ fetcher =
ctx.uskManager.getFetcherForInsertDontSchedule(pubUSK, this);
+ }
+ fetcher.schedule();
+ }
+
+ public void onFoundEdition(long l, USK key) {
+ edition = Math.max(l, edition);
+ consecutiveCollisions = 0;
+ fetcher = null;
+ scheduleInsert();
+ }
+
+ private void scheduleInsert() {
+ synchronized(this) {
+ if(finished) return;
+ long edNo = Math.max(edition,
ctx.uskManager.lookup(pubUSK))+1;
+ edition = edNo;
+ Logger.minor(this, "scheduling insert for
"+pubUSK.getURI()+" "+edition);
+ try {
+ sbi = new SingleBlockInserter(parent, data,
compressionCodec, privUSK.getInsertableSSK(edition).getInsertURI(),
+ ctx, this, isMetadata,
sourceLength, token, getCHKOnly, false);
+ } catch (InserterException e) {
+ cb.onFailure(e, this);
+ return;
+ }
+ }
+ try {
+ sbi.schedule();
+ } catch (InserterException e) {
+ cb.onFailure(e, this);
+ }
+ }
+
+ public void onSuccess(ClientPutState state) {
+ cb.onEncode(pubUSK.copy(edition), this);
+ cb.onSuccess(this);
+ synchronized(this) {
+ finished = true;
+ sbi = null;
+ }
+ FreenetURI targetURI = pubUSK.copy(edition).getURI();
+ FreenetURI realURI = ((SingleBlockInserter)state).getURI();
+ if(!targetURI.equals(realURI))
+ Logger.error(this, "URI should be "+targetURI+"
actually is "+realURI);
+ else
+ Logger.minor(this, "URI should be "+targetURI+"
actually is "+realURI);
+ // FINISHED!!!! Yay!!!
+ }
+
+ public void onFailure(InserterException e, ClientPutState state) {
+ sbi = null;
+ if(e.getMode() == InserterException.COLLISION) {
+ // Try the next slot
+ edition++;
+ if(consecutiveCollisions++ > MAX_TRIED_SLOTS)
+ scheduleFetcher();
+ else
+ scheduleInsert();
+ } else {
+ cb.onFailure(e, state);
+ }
+ }
+
+ public USKInserter(BaseClientPutter parent, Bucket data, short
compressionCodec, FreenetURI uri,
+ InserterContext ctx, PutCompletionCallback cb, boolean
isMetadata, int sourceLength, int token,
+ boolean getCHKOnly, boolean addToParent) throws
MalformedURLException {
+ edition = -1;
+ this.parent = parent;
+ this.data = data;
+ this.compressionCodec = compressionCodec;
+ this.ctx = ctx;
+ this.cb = cb;
+ this.isMetadata = isMetadata;
+ this.sourceLength = sourceLength;
+ this.token = token;
+ this.getCHKOnly = getCHKOnly;
+ if(addToParent) {
+ parent.addBlock();
+ parent.addMustSucceedBlocks(1);
+ parent.notifyClients();
+ }
+ privUSK = InsertableUSK.create(uri);
+ pubUSK = privUSK.getUSK();
+ }
+
+ public BaseClientPutter getParent() {
+ return parent;
+ }
+
+ public synchronized void cancel() {
+ finished = true;
+ if(fetcher != null)
+ fetcher.cancel();
+ if(sbi != null)
+ sbi.cancel();
+ cb.onFailure(new
InserterException(InserterException.CANCELLED), this);
+ }
+
+ public void onFailure() {
+ Logger.error(this, "Fetcher failed", new Exception("debug"));
+ scheduleInsert();
+ }
+
+ public void onCancelled() {
+ if(finished) return;
+ Logger.error(this, "Unexpected onCancelled()", new
Exception("error"));
+ cancel();
+ }
+
+ public void onEncode(BaseClientKey key, ClientPutState state) {
+ // Ignore
+ }
+
+ public void onTransition(ClientPutState oldState, ClientPutState
newState) {
+ // Shouldn't happen
+ Logger.error(this, "Got
onTransition("+oldState+","+newState+")");
+ }
+
+ public void onMetadata(Metadata m, ClientPutState state) {
+ // Shouldn't happen
+ Logger.error(this, "Got onMetadata("+m+","+state+")");
+ }
+
+ public void onBlockSetFinished(ClientPutState state) {
+ // Ignore
+ }
+
+}
Modified: trunk/freenet/src/freenet/client/async/USKManager.java
===================================================================
--- trunk/freenet/src/freenet/client/async/USKManager.java 2006-03-25
15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/client/async/USKManager.java 2006-03-25
16:36:47 UTC (rev 8312)
@@ -91,13 +91,20 @@
return f;
}
+ public USKFetcher getFetcherForInsertDontSchedule(USK usk,
USKFetcherCallback cb) {
+ USKFetcher f = new USKFetcher(usk, this,
backgroundFetchContext,
+ new USKFetcherWrapper(usk, chkRequestScheduler,
sskRequestScheduler), 3, false);
+ f.addCallback(cb);
+ return f;
+ }
+
public void startTemporaryBackgroundFetcher(USK usk) {
USK clear = usk.clearCopy();
USKFetcher sched = null;
synchronized(this) {
USKFetcher f = (USKFetcher)
backgroundFetchersByClearUSK.get(clear);
if(f == null) {
- f = new USKFetcher(usk, this,
backgroundFetchContext, new USKFetcherWrapper(usk, chkRequestScheduler,
sskRequestScheduler), 10, false);
+ f = new USKFetcher(usk, this,
backgroundFetchContext, new USKFetcherWrapper(usk, chkRequestScheduler,
sskRequestScheduler), 10, true);
sched = f;
backgroundFetchersByClearUSK.put(clear, f);
}
@@ -157,7 +164,7 @@
if(runBackgroundFetch) {
USKFetcher f = (USKFetcher)
backgroundFetchersByClearUSK.get(clear);
if(f == null) {
- f = new USKFetcher(origUSK, this,
backgroundFetchContext, new USKFetcherWrapper(origUSK, chkRequestScheduler,
sskRequestScheduler), 10, false);
+ f = new USKFetcher(origUSK, this,
backgroundFetchContext, new USKFetcherWrapper(origUSK, chkRequestScheduler,
sskRequestScheduler), 10, true);
sched = f;
backgroundFetchersByClearUSK.put(clear,
f);
}
Modified: trunk/freenet/src/freenet/keys/InsertableClientSSK.java
===================================================================
--- trunk/freenet/src/freenet/keys/InsertableClientSSK.java 2006-03-25
15:24:17 UTC (rev 8311)
+++ trunk/freenet/src/freenet/keys/InsertableClientSSK.java 2006-03-25
16:36:47 UTC (rev 8312)
@@ -39,6 +39,8 @@
throw new MalformedURLException();
if(uri.getDocName() == null || uri.getDocName().length() == 0)
throw new MalformedURLException("SSK URIs must have a
document name (to avoid ambiguity)");
+ if(uri.getExtra() != null)
+ throw new MalformedURLException("Insertable SSK URIs
must NOT have ,extra - inserting from a pubkey rather than the privkey
perhaps?");
DSAGroup g = Global.DSAgroupBigA;
DSAPrivateKey privKey = new DSAPrivateKey(new
NativeBigInteger(1, uri.getKeyVal()));
DSAPublicKey pubKey = new DSAPublicKey(g, privKey);
Added: trunk/freenet/src/freenet/keys/InsertableUSK.java
===================================================================
--- trunk/freenet/src/freenet/keys/InsertableUSK.java 2006-03-25 15:24:17 UTC
(rev 8311)
+++ trunk/freenet/src/freenet/keys/InsertableUSK.java 2006-03-25 16:36:47 UTC
(rev 8312)
@@ -0,0 +1,83 @@
+package freenet.keys;
+
+import java.net.MalformedURLException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import net.i2p.util.NativeBigInteger;
+
+import freenet.crypt.DSAGroup;
+import freenet.crypt.DSAPrivateKey;
+import freenet.crypt.DSAPublicKey;
+import freenet.crypt.Global;
+import freenet.support.Logger;
+
+/**
+ * An insertable USK.
+ *
+ * Changes from an ordinary USK:
+ * - It has a private key
+ * - getURI() doesn't include ,extra
+ * - constructor from URI doesn't need or want ,extra
+ * - It has a getUSK() method which gets the public USK
+ */
+public class InsertableUSK extends USK {
+
+ public final DSAPrivateKey privKey;
+ public final DSAGroup group;
+
+ public static InsertableUSK create(FreenetURI uri) throws
MalformedURLException {
+ if(!uri.getKeyType().equalsIgnoreCase("USK"))
+ throw new MalformedURLException();
+ if(uri.getDocName() == null || uri.getDocName().length() == 0)
+ throw new MalformedURLException("USK URIs must have a
document name (to avoid ambiguity)");
+ DSAGroup g = Global.DSAgroupBigA;
+ DSAPrivateKey privKey = new DSAPrivateKey(new
NativeBigInteger(1, uri.getKeyVal()));
+ DSAPublicKey pubKey = new DSAPublicKey(g, privKey);
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException e) {
+ throw new Error(e);
+ }
+ md.update(pubKey.asBytes());
+ return new InsertableUSK(uri.getDocName(), md.digest(),
uri.getCryptoKey(), privKey, g, uri.getSuggestedEdition());
+ }
+
+ InsertableUSK(String docName, byte[] pubKeyHash, byte[] cryptoKey,
DSAPrivateKey key, DSAGroup group, long suggestedEdition) throws
MalformedURLException {
+ super(pubKeyHash, cryptoKey, docName, suggestedEdition);
+ if(cryptoKey.length != ClientSSK.CRYPTO_KEY_LENGTH)
+ throw new MalformedURLException("Decryption key wrong
length: "+cryptoKey.length+" should be "+ClientSSK.CRYPTO_KEY_LENGTH);
+ this.privKey = key;
+ this.group = group;
+ }
+
+ public FreenetURI getURI() {
+ return new FreenetURI(pubKeyHash, cryptoKey, null, siteName,
suggestedEdition);
+ }
+
+ public USK getUSK() {
+ return new USK(pubKeyHash, cryptoKey, siteName,
suggestedEdition);
+ }
+
+ public InsertableClientSSK getInsertableSSK(long ver) {
+ try {
+ return new InsertableClientSSK(siteName + SEPARATOR +
ver, pubKeyHash,
+ new DSAPublicKey(group, privKey),
privKey, cryptoKey);
+ } catch (MalformedURLException e) {
+ Logger.error(this, "Caught "+e+" should not be possible
in USK.getSSK", e);
+ throw new Error(e);
+ }
+ }
+
+ public InsertableUSK privCopy(long edition) {
+ if(edition == suggestedEdition) return this;
+ try {
+ return new InsertableUSK(siteName, pubKeyHash,
cryptoKey, privKey, group, edition);
+ } catch (MalformedURLException e) {
+ throw new Error(e);
+ }
+ }
+
+
+}
Modified: trunk/freenet/src/freenet/keys/USK.java
===================================================================
--- trunk/freenet/src/freenet/keys/USK.java 2006-03-25 15:24:17 UTC (rev
8311)
+++ trunk/freenet/src/freenet/keys/USK.java 2006-03-25 16:36:47 UTC (rev
8312)
@@ -21,7 +21,7 @@
* I chose "-", because it makes it ludicrously easy to go from the USK
form to the
* SSK form, and we don't need to go vice versa.
*/
- private static final String SEPARATOR = "-";
+ static protected final String SEPARATOR = "-";
/** Public key hash */
public final byte[] pubKeyHash;
/** Encryption key */
@@ -52,7 +52,7 @@
this(uri.getRoutingKey(), uri.getCryptoKey(), uri.getExtra(),
uri.getDocName(), uri.getSuggestedEdition());
}
- private USK(byte[] pubKeyHash2, byte[] cryptoKey2, String siteName2,
long suggestedEdition2) {
+ protected USK(byte[] pubKeyHash2, byte[] cryptoKey2, String siteName2,
long suggestedEdition2) {
this.pubKeyHash = pubKeyHash2;
this.cryptoKey = cryptoKey2;
this.siteName = siteName2;
Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java 2006-03-25 15:24:17 UTC (rev
8311)
+++ trunk/freenet/src/freenet/node/Node.java 2006-03-25 16:36:47 UTC (rev
8312)
@@ -851,28 +851,28 @@
archiveManager = new ArchiveManager(MAX_ARCHIVE_HANDLERS,
MAX_CACHED_ARCHIVE_DATA, MAX_ARCHIVE_SIZE, MAX_ARCHIVED_FILE_SIZE,
MAX_CACHED_ELEMENTS, random, tempFilenameGenerator);
chkRequestThrottle = new RequestThrottle(5000, 2.0F);
- chkRequestStarter = new RequestStarter(this,
chkRequestThrottle, "Request starter ("+portNumber+")");
- chkFetchScheduler = new ClientRequestScheduler(false, random,
chkRequestStarter, this);
+ chkRequestStarter = new RequestStarter(this,
chkRequestThrottle, "CHK Request starter ("+portNumber+")");
+ chkFetchScheduler = new ClientRequestScheduler(false, false,
random, chkRequestStarter, this);
chkRequestStarter.setScheduler(chkFetchScheduler);
chkRequestStarter.start();
//insertThrottle = new ChainedRequestThrottle(10000, 2.0F,
requestThrottle);
// FIXME reenable the above
chkInsertThrottle = new RequestThrottle(10000, 2.0F);
- chkInsertStarter = new RequestStarter(this, chkInsertThrottle,
"Insert starter ("+portNumber+")");
- chkPutScheduler = new ClientRequestScheduler(true, random,
chkInsertStarter, this);
+ chkInsertStarter = new RequestStarter(this, chkInsertThrottle,
"CHK Insert starter ("+portNumber+")");
+ chkPutScheduler = new ClientRequestScheduler(true, false,
random, chkInsertStarter, this);
chkInsertStarter.setScheduler(chkPutScheduler);
chkInsertStarter.start();
sskRequestThrottle = new RequestThrottle(5000, 2.0F);
- sskRequestStarter = new RequestStarter(this,
sskRequestThrottle, "Request starter ("+portNumber+")");
- sskFetchScheduler = new ClientRequestScheduler(false, random,
sskRequestStarter, this);
+ sskRequestStarter = new RequestStarter(this,
sskRequestThrottle, "SSK Request starter ("+portNumber+")");
+ sskFetchScheduler = new ClientRequestScheduler(false, true,
random, sskRequestStarter, this);
sskRequestStarter.setScheduler(sskFetchScheduler);
sskRequestStarter.start();
//insertThrottle = new ChainedRequestThrottle(10000, 2.0F,
requestThrottle);
// FIXME reenable the above
sskInsertThrottle = new RequestThrottle(10000, 2.0F);
- sskInsertStarter = new RequestStarter(this, sskInsertThrottle,
"Insert starter ("+portNumber+")");
- sskPutScheduler = new ClientRequestScheduler(true, random,
sskInsertStarter, this);
+ sskInsertStarter = new RequestStarter(this, sskInsertThrottle,
"SSK Insert starter ("+portNumber+")");
+ sskPutScheduler = new ClientRequestScheduler(true, true,
random, sskInsertStarter, this);
sskInsertStarter.setScheduler(sskPutScheduler);
sskInsertStarter.start();
Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-03-25 15:24:17 UTC (rev
8311)
+++ trunk/freenet/src/freenet/node/Version.java 2006-03-25 16:36:47 UTC (rev
8312)
@@ -20,7 +20,7 @@
public static final String protocolVersion = "1.0";
/** The build number of the current revision */
- private static final int buildNumber = 570;
+ private static final int buildNumber = 571;
/** Oldest build of Fred we will talk to */
private static final int lastGoodBuild = 507;