Author: nextgens
Date: 2006-02-03 22:29:13 +0000 (Fri, 03 Feb 2006)
New Revision: 7997
Added:
branches/freenet-freejvms/src/freenet/crypt/DSA.java
branches/freenet-freejvms/src/freenet/crypt/DSAGroupGenerator.java
branches/freenet-freejvms/src/freenet/crypt/DSAPrivateKey.java
branches/freenet-freejvms/src/freenet/crypt/DSAPublicKey.java
branches/freenet-freejvms/src/freenet/keys/ClientKeyBlock.java
branches/freenet-freejvms/src/freenet/keys/ClientSSK.java
branches/freenet-freejvms/src/freenet/keys/ClientSSKBlock.java
branches/freenet-freejvms/src/freenet/keys/NodeSSK.java
branches/freenet-freejvms/src/freenet/keys/SSKBlock.java
branches/freenet-freejvms/src/freenet/keys/SSKDecodeException.java
branches/freenet-freejvms/src/freenet/keys/SSKVerifyException.java
branches/freenet-freejvms/src/freenet/node/TestnetStatusUploader.java
Modified:
branches/freenet-freejvms/.classpath
branches/freenet-freejvms/build.xml
branches/freenet-freejvms/run.sh
branches/freenet-freejvms/src/freenet/client/ArchiveManager.java
branches/freenet-freejvms/src/freenet/client/Fetcher.java
branches/freenet-freejvms/src/freenet/client/HighLevelSimpleClientImpl.java
branches/freenet-freejvms/src/freenet/client/Metadata.java
branches/freenet-freejvms/src/freenet/keys/CHKBlock.java
branches/freenet-freejvms/src/freenet/keys/ClientCHK.java
branches/freenet-freejvms/src/freenet/keys/ClientCHKBlock.java
branches/freenet-freejvms/src/freenet/keys/ClientKey.java
branches/freenet-freejvms/src/freenet/keys/Key.java
branches/freenet-freejvms/src/freenet/keys/KeyBlock.java
branches/freenet-freejvms/src/freenet/keys/NodeCHK.java
branches/freenet-freejvms/src/freenet/node/Node.java
branches/freenet-freejvms/src/freenet/node/QueuedDataRequest.java
branches/freenet-freejvms/src/freenet/node/QueueingSimpleLowLevelClient.java
branches/freenet-freejvms/src/freenet/node/RealNodeRequestInsertTest.java
branches/freenet-freejvms/src/freenet/node/RequestStarterClient.java
branches/freenet-freejvms/src/freenet/node/SimpleLowLevelClient.java
branches/freenet-freejvms/src/freenet/node/TestnetHandler.java
branches/freenet-freejvms/src/freenet/node/TextModeClientInterface.java
branches/freenet-freejvms/src/freenet/node/Version.java
branches/freenet-freejvms/src/freenet/store/DataStore.java
Log:
Build 309 : merged changes from trunk since 7751
Modified: branches/freenet-freejvms/.classpath
===================================================================
--- branches/freenet-freejvms/.classpath 2006-02-03 21:46:40 UTC (rev
7996)
+++ branches/freenet-freejvms/.classpath 2006-02-03 22:29:13 UTC (rev
7997)
@@ -2,6 +2,6 @@
<classpath>
<classpathentry
excluding="test/**|org/spaceroots/mantissa/random/MersenneTwisterTest.java"
kind="src" path="src"/>
<classpathentry kind="con"
path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="lib"
path="/usr/src/cvs/freenet-stable/lib/freenet-ext.jar"/>
+ <classpathentry kind="lib" path="lib/freenet-ext.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
Modified: branches/freenet-freejvms/build.xml
===================================================================
--- branches/freenet-freejvms/build.xml 2006-02-03 21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/build.xml 2006-02-03 22:29:13 UTC (rev 7997)
@@ -6,31 +6,44 @@
This file builds freenet...
Possible targets: compile, dist (default), clean
</description>
- <!-- set global properties for this build -->
- <property name="src" location="src"/>
- <property name="build" location="build"/>
-
+
+<!-- set global properties for this build -->
+ <property name="src" location="src"/>
+ <property name="build" location="build"/>
+ <property name="lib" location="lib"/>
+ <property name="freenet-ext.location"
location="${lib}/freenet-ext.jar"/>
+
+<target name="mkdir">
+ <mkdir dir="${build}"/>
+ <mkdir dir="${lib}"/>
+</target>
+
+<target name="env" depends="mkdir" description="Learn about the environment">
+ <available file="${lib}/freenet-ext.jar" property="freenet-ext.present"/>
+</target>
+
+ <target name="get-extjar" depends="env" unless="freenet-ext.present"
+ description="Download some external libraries which Freenet relies on">
+ <mkdir dir="${lib}"/>
+ <get src="http://downloads.freenetproject.org/alpha/freenet-ext.jar"
+ dest="${freenet-ext.location}"
+ verbose="true"
+ usetimestamp="true"/>
+ <property name="freenet-ext.present" value="true"/>
+ </target>
<!-- ================================================== -->
- <target name="compile">
-
+ <target name="compile" depends="get-extjar">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
- <mkdir dir="${build}"/>
<!-- FIXME: remove the debug and replace with optimize -->
- <javac srcdir="${src}" destdir="${build}" source="1.4" debug="on"
optimize="on">
- <classpath>
- <pathelement location="freenet-ext.jar"/>
- <pathelement location="gnu-crypto.jar"/>
- <pathelement location="javax-security.jar"/>
- <pathelement location="javax-crypto.jar"/>
- </classpath>
+ <javac srcdir="${src}" destdir="${build}" debug="on" optimize="on"
source="1.4">
+ <classpath>
+ <pathelement location="${freenet-ext.location}"/>
+ </classpath>
<!-- following a very temporary list of files to be build -->
- <include name="*.class"/>
<include name="org/**/*.java"/>
- <include name="com/**/*.java"/>
- <include name="com/onionnetworks/**/*.class"/>
<include name="freenet/**/*.java"/>
<include name="net/i2p/util/*.java"/>
<exclude name="org/**/MersenneTwisterTest.java"/>
@@ -44,7 +57,7 @@
<!-- Create the distribution directory -->
<!--<mkdir dir="."/>-->
<!-- Put everything in ${build} into the freenet-${DSTAMP}.jar file -->
- <jar jarfile="freenet-cvs-snapshot.jar" basedir="${build}">
+ <jar jarfile="${lib}/freenet-cvs-snapshot.jar" basedir="${build}">
<manifest>
<attribute name="Main-Class" value="freenet/node/Node"/>
<attribute name="Built-By" value="${user.name}"/>
@@ -65,5 +78,10 @@
<delete dir="${build}"/>
<!--<delete><fileset dir="src" includes="**/*.class"/></delete>-->
</target>
+ <target name="distclean" description="Delete class files, lib dir and docs
dir.">
+ <delete dir="${build}"/>
+ <delete dir="${lib}"/>
+ <!--<delete><fileset dir="src" includes="**/*.class"/></delete>-->
+ </target>
</project>
Modified: branches/freenet-freejvms/run.sh
===================================================================
--- branches/freenet-freejvms/run.sh 2006-02-03 21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/run.sh 2006-02-03 22:29:13 UTC (rev 7997)
@@ -1,3 +1,7 @@
+echo "Compiling freenet-ext.jar"
gcj -c -g -fjni -Ifreenet-cvs-snapshot.jar -Ifreenet-ext.jar
-Ignu-crypto-der.jar -Ignu-crypto.jar -o freenet-ext.o freenet-ext.jar
+echo "Compiling freenet-cvs-snapshot.jar"
gcj -c -g -fjni -Ifreenet-cvs-snapshot.jar -Ifreenet-ext.jar
-Ignu-crypto-der.jar -Ignu-crypto.jar -o freenet.o freenet-cvs-snapshot.jar
+echo "Linking"
gcj -fjni -combine -g -Ifreenet-cvs-snapshot.jar -Ifreenet-ext.jar
-Ignu-crypto-der.jar -Ignu-crypto.jar --main=freenet.node.Node -o freenet
-Lbin/lib/linux/x86/ -Lbin/net/i2p/util/ -lfec16 -lfec8 -ljbigi-linux-athlon
-lgmp freenet-ext.o freenet.o
+echo "Done"
Modified: branches/freenet-freejvms/src/freenet/client/ArchiveManager.java
===================================================================
--- branches/freenet-freejvms/src/freenet/client/ArchiveManager.java
2006-02-03 21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/client/ArchiveManager.java
2006-02-03 22:29:13 UTC (rev 7997)
@@ -111,9 +111,10 @@
* @param archiveType The archive type, defined in Metadata.
* @return An archive handler.
*/
- public synchronized ArchiveHandler makeHandler(FreenetURI key, short
archiveType) {
+ public synchronized ArchiveHandler makeHandler(FreenetURI key, short
archiveType, boolean returnNullIfNotFound) {
ArchiveHandler handler = getCached(key);
if(handler != null) return handler;
+ if(returnNullIfNotFound) return null;
handler = new ArchiveStoreContext(this, key, archiveType);
putCached(key, handler);
return handler;
Modified: branches/freenet-freejvms/src/freenet/client/Fetcher.java
===================================================================
--- branches/freenet-freejvms/src/freenet/client/Fetcher.java 2006-02-03
21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/client/Fetcher.java 2006-02-03
22:29:13 UTC (rev 7997)
@@ -7,7 +7,9 @@
import freenet.client.events.DecodedBlockEvent;
import freenet.client.events.FetchedMetadataEvent;
import freenet.client.events.GotBlockEvent;
+import freenet.keys.ClientCHK;
import freenet.keys.ClientKey;
+import freenet.keys.ClientKeyBlock;
import freenet.keys.FreenetURI;
import freenet.keys.KeyBlock;
import freenet.keys.KeyDecodeException;
@@ -107,7 +109,7 @@
throw new
FetchException(FetchException.TOO_MUCH_RECURSION, ""+recursionLevel+" should be
< "+ctx.maxRecursionLevel);
// Do the fetch
- KeyBlock block;
+ ClientKeyBlock block;
try {
block = ctx.client.getKey(key, localOnly,
ctx.starterClient, ctx.cacheLocalRequests);
} catch (LowLevelGetException e) {
@@ -138,7 +140,7 @@
Bucket data;
try {
- data = block.decode(key, ctx.bucketFactory, (int)
(Math.min(ctx.maxTempLength, Integer.MAX_VALUE)));
+ data = block.decode(ctx.bucketFactory, (int)
(Math.min(ctx.maxTempLength, Integer.MAX_VALUE)));
} catch (KeyDecodeException e1) {
throw new
FetchException(FetchException.BLOCK_DECODE_ERROR, e1.getMessage());
} catch (IOException e) {
@@ -148,7 +150,7 @@
ctx.eventProducer.produceEvent(new DecodedBlockEvent(key));
- if(!key.isMetadata()) {
+ if(!block.isMetadata()) {
// Just return the data
return new FetchResult(dm, data);
}
@@ -202,7 +204,7 @@
}
return runMetadata(dm, recursionLevel, key,
metaStrings, metadata, container, thisKey, dontEnterImplicitArchives,
localOnly);
} else if(metadata.isArchiveManifest()) {
- container = ctx.archiveManager.makeHandler(thisKey,
metadata.getArchiveType());
+ container = ctx.archiveManager.makeHandler(thisKey,
metadata.getArchiveType(), false);
Bucket metadataBucket =
container.getMetadata(archiveContext, ctx, dm, recursionLevel, true);
try {
metadata = Metadata.construct(metadataBucket);
@@ -223,7 +225,7 @@
*/
if((!dontEnterImplicitArchives) &&
ArchiveManager.isUsableArchiveType(dm.getMIMEType()) &&
(!metaStrings.isEmpty())) {
// Possible implicit archive inside
archive?
- container =
ctx.archiveManager.makeHandler(thisKey,
ArchiveManager.getArchiveType(dm.getMIMEType()));
+ container =
ctx.archiveManager.makeHandler(thisKey,
ArchiveManager.getArchiveType(dm.getMIMEType()), false);
Bucket metadataBucket =
container.getMetadata(archiveContext, ctx, dm, recursionLevel, true);
try {
metadata =
Metadata.construct(metadataBucket);
@@ -250,17 +252,16 @@
FreenetURI uri = metadata.getSingleTarget();
dm.mergeNoOverwrite(metadata.getClientMetadata());
if((!dontEnterImplicitArchives) &&
ArchiveManager.isUsableArchiveType(dm.getMIMEType()) &&
(!metaStrings.isEmpty())) {
+ // Is probably an implicit archive.
ClientKey target;
try {
target = ClientKey.getBaseKey(uri);
} catch (MalformedURLException e1) {
throw new
FetchException(FetchException.INVALID_URI, "Invalid URI: "+uri);
}
- if(!(target.isMetadata())) {
- // Target *is not* metadata.
- // Therefore target is a usable archive.
- // We might not have to fetch it.
- container =
ctx.archiveManager.makeHandler(uri,
ArchiveManager.getArchiveType(dm.getMIMEType()));
+ // Probably a usable archive as-is. We may not
have to fetch it.
+ container = ctx.archiveManager.makeHandler(uri,
ArchiveManager.getArchiveType(dm.getMIMEType()), true);
+ if(container != null) {
Bucket metadataBucket =
container.getMetadata(archiveContext, ctx, dm, recursionLevel, true);
try {
metadata =
Metadata.construct(metadataBucket);
@@ -268,7 +269,7 @@
throw new
FetchException(FetchException.BUCKET_ERROR);
}
return runMetadata(dm,
recursionLevel+1, key, metaStrings, metadata, container, thisKey,
dontEnterImplicitArchives, localOnly);
- }
+ } // else just fetch it, create context later
}
FetchResult fr = realRun(dm, recursionLevel, uri,
dontEnterImplicitArchives, localOnly);
if(metadata.compressed) {
@@ -293,7 +294,7 @@
dm.mergeNoOverwrite(metadata.getClientMetadata()); //
even splitfiles can have mime types!
if((!dontEnterImplicitArchives) &&
ArchiveManager.isUsableArchiveType(dm.getMIMEType()) &&
(!metaStrings.isEmpty())) {
// We know target is not metadata.
- container =
ctx.archiveManager.makeHandler(thisKey,
ArchiveManager.getArchiveType(dm.getMIMEType()));
+ container =
ctx.archiveManager.makeHandler(thisKey,
ArchiveManager.getArchiveType(dm.getMIMEType()), false);
Bucket metadataBucket =
container.getMetadata(archiveContext, ctx, dm, recursionLevel, true);
try {
metadata =
Metadata.construct(metadataBucket);
Modified:
branches/freenet-freejvms/src/freenet/client/HighLevelSimpleClientImpl.java
===================================================================
--- branches/freenet-freejvms/src/freenet/client/HighLevelSimpleClientImpl.java
2006-02-03 21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/client/HighLevelSimpleClientImpl.java
2006-02-03 22:29:13 UTC (rev 7997)
@@ -103,6 +103,13 @@
return i.run(insert, false, getCHKOnly, false);
}
+ public FreenetURI insert(InsertBlock insert, boolean getCHKOnly,
boolean metadata) throws InserterException {
+ InserterContext context = new InserterContext(client,
bucketFactory, random, INSERT_RETRIES, CONSECUTIVE_RNFS_ASSUME_SUCCESS,
+ SPLITFILE_INSERT_THREADS,
SPLITFILE_BLOCKS_PER_SEGMENT, SPLITFILE_CHECK_BLOCKS_PER_SEGMENT,
globalEventProducer, insertStarter, cacheLocalRequests);
+ FileInserter i = new FileInserter(context);
+ return i.run(insert, metadata, getCHKOnly, false);
+ }
+
public void addGlobalHook(ClientEventListener listener) {
globalEventProducer.addEventListener(listener);
}
Modified: branches/freenet-freejvms/src/freenet/client/Metadata.java
===================================================================
--- branches/freenet-freejvms/src/freenet/client/Metadata.java 2006-02-03
21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/client/Metadata.java 2006-02-03
22:29:13 UTC (rev 7997)
@@ -236,11 +236,99 @@
}
/**
+ * Create an empty Metadata object
+ */
+ private Metadata() {
+ // Should be followed by addRedirectionManifest
+ }
+
+ /**
+ * Create a Metadata object and add data for redirection to it.
+ *
+ * @param dir A map of names (string) to either files (same string) or
+ * directories (more HashMap's)
+ * @throws MalformedURLException One of the URI:s were malformed
+ */
+ private void addRedirectionManifest(HashMap dir) throws
MalformedURLException {
+ // Simple manifest - contains actual redirects.
+ // Not zip manifest, which is basically a redirect.
+ documentType = SIMPLE_MANIFEST;
+ noMIME = true;
+ //mimeType = null;
+ //clientMetadata = new ClientMetadata(null);
+ manifestEntries = new HashMap();
+ int count = 0;
+ for(Iterator i = dir.keySet().iterator();i.hasNext();) {
+ String key = (String) i.next();
+ count++;
+ Object o = dir.get(key);
+ Metadata target;
+ if(o instanceof String) {
+ // External redirect
+ FreenetURI uri = new FreenetURI((String)o);
+ target = new Metadata(SIMPLE_REDIRECT, uri,
null);
+ } else if(o instanceof HashMap) {
+ target = new Metadata();
+ target.addRedirectionManifest((HashMap)o);
+ } else throw new IllegalArgumentException("Not String
nor HashMap: "+o);
+ byte[] data = target.writeToByteArray();
+ manifestEntries.put(key, data);
+ }
+ manifestEntryCount = count;
+
+ }
+
+ /**
+ * Create a Metadata object and add data for redirection to it.
+ *
+ * @param dir A map of names (string) to either files (same string) or
+ * directories (more HashMap's)
+ * @throws MalformedURLException One of the URI:s were malformed
+ */
+ public static Metadata mkRedirectionManifest(HashMap dir) throws
MalformedURLException {
+ Metadata ret = new Metadata();
+ ret.addRedirectionManifest(dir);
+ return ret;
+ }
+
+ /**
* Create a Metadata object for an archive which does not have its own
* metadata.
* @param dir A map of names (string) to either files (same string) or
* directories (more HashMap's)
*/
+ public void addManifest(HashMap dir) {
+ // Simple manifest - contains actual redirects.
+ // Not zip manifest, which is basically a redirect.
+ documentType = SIMPLE_MANIFEST;
+ noMIME = true;
+ //mimeType = null;
+ //clientMetadata = new ClientMetadata(null);
+ manifestEntries = new HashMap();
+ int count = 0;
+ for(Iterator i = dir.keySet().iterator();i.hasNext();) {
+ String key = (String) i.next();
+ count++;
+ Object o = dir.get(key);
+ Metadata target;
+ if(o instanceof String) {
+ // Zip internal redirect
+ target = new Metadata(ZIP_INTERNAL_REDIRECT,
key);
+ } else if(o instanceof HashMap) {
+ target = new Metadata((HashMap)o);
+ } else throw new IllegalArgumentException("Not String
nor HashMap: "+o);
+ byte[] data = target.writeToByteArray();
+ manifestEntries.put(key, data);
+ }
+ manifestEntryCount = count;
+ }
+
+ /**
+ * Create a Metadata object for an archive which does not have its own
+ * metadata.
+ * @param dir A map of names (string) to either files (same string) or
+ * directories (more HashMap's)
+ */
Metadata(HashMap dir) {
// Simple manifest - contains actual redirects.
// Not zip manifest, which is basically a redirect.
Copied: branches/freenet-freejvms/src/freenet/crypt/DSA.java (from rev 7751,
trunk/freenet/src/freenet/crypt/DSA.java)
Copied: branches/freenet-freejvms/src/freenet/crypt/DSAGroupGenerator.java
(from rev 7751, trunk/freenet/src/freenet/crypt/DSAGroupGenerator.java)
Copied: branches/freenet-freejvms/src/freenet/crypt/DSAPrivateKey.java (from
rev 7751, trunk/freenet/src/freenet/crypt/DSAPrivateKey.java)
Copied: branches/freenet-freejvms/src/freenet/crypt/DSAPublicKey.java (from rev
7751, trunk/freenet/src/freenet/crypt/DSAPublicKey.java)
Modified: branches/freenet-freejvms/src/freenet/keys/CHKBlock.java
===================================================================
--- branches/freenet-freejvms/src/freenet/keys/CHKBlock.java 2006-02-03
21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/keys/CHKBlock.java 2006-02-03
22:29:13 UTC (rev 7997)
@@ -44,7 +44,6 @@
final short hashIdentifier;
final NodeCHK chk;
public static final int MAX_LENGTH_BEFORE_COMPRESSION = Integer.MAX_VALUE;
- final static int HASH_SHA256 = 1;
public String toString() {
return super.toString()+": chk="+chk;
Modified: branches/freenet-freejvms/src/freenet/keys/ClientCHK.java
===================================================================
--- branches/freenet-freejvms/src/freenet/keys/ClientCHK.java 2006-02-03
21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/keys/ClientCHK.java 2006-02-03
22:29:13 UTC (rev 7997)
@@ -119,18 +119,17 @@
","+cryptoAlgorithm;
}
+ public Key getNodeKey() {
+ return getNodeCHK();
+ }
+ public NodeCHK getNodeCHK() {
+ if(nodeKey == null)
+ nodeKey = new NodeCHK(routingKey);
+ return nodeKey;
+ }
+
/**
- * @return a NodeCHK corresponding to this key. Basically keep the
- * routingKey and lose everything else.
- */
- public NodeCHK getNodeCHK() {
- if(nodeKey == null)
- nodeKey = new NodeCHK(routingKey);
- return nodeKey;
- }
-
- /**
* @return URI form of this key.
*/
public FreenetURI getURI() {
Modified: branches/freenet-freejvms/src/freenet/keys/ClientCHKBlock.java
===================================================================
--- branches/freenet-freejvms/src/freenet/keys/ClientCHKBlock.java
2006-02-03 21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/keys/ClientCHKBlock.java
2006-02-03 22:29:13 UTC (rev 7997)
@@ -3,6 +3,7 @@
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
import org.spaceroots.mantissa.random.MersenneTwister;
@@ -10,10 +11,14 @@
import freenet.crypt.PCFBMode;
import freenet.crypt.UnsupportedCipherException;
import freenet.crypt.ciphers.Rijndael;
+import freenet.node.Node;
import freenet.support.ArrayBucket;
import freenet.support.ArrayBucketFactory;
import freenet.support.Bucket;
+import freenet.support.BucketFactory;
import freenet.support.BucketTools;
+import freenet.support.Logger;
+import freenet.support.SimpleReadOnlyArrayBucket;
import freenet.support.compress.CompressionOutputSizeException;
import freenet.support.compress.Compressor;
import freenet.support.compress.DecompressException;
@@ -31,9 +36,9 @@
/**
* @author amphibian
*
- * Client CHKBlock - provides functions for decoding, holds a key.
+ * Client CHKBlock - provides functions for decoding, holds a client-key.
*/
-public class ClientCHKBlock extends CHKBlock {
+public class ClientCHKBlock extends CHKBlock implements ClientKeyBlock {
public static final long MAX_COMPRESSED_DATA_LENGTH = NodeCHK.BLOCK_SIZE -
4;
final ClientCHK key;
@@ -63,6 +68,82 @@
}
/**
+ * Decode into RAM, if short.
+ * @throws CHKDecodeException
+ */
+ public byte[] memoryDecode() throws CHKDecodeException {
+ try {
+ ArrayBucket a = (ArrayBucket) decode(new
ArrayBucketFactory(), 32*1024);
+ return BucketTools.toByteArray(a); // FIXME
+ } catch (IOException e) {
+ throw new Error(e);
+ }
+ }
+
+ public Bucket decode(ClientKey key, BucketFactory bf, int maxLength)
throws KeyDecodeException, IOException {
+ if(!(key instanceof ClientCHK))
+ throw new KeyDecodeException("Not a CHK!: "+key);
+ return decode((ClientCHK)key, bf, maxLength);
+ }
+
+ /**
+ * Decode the CHK and recover the original data
+ * @return the original data
+ * @throws IOException If there is a bucket error.
+ */
+ public Bucket decode(BucketFactory bf, int maxLength) throws
CHKDecodeException, IOException {
+ // Overall hash already verified, so first job is to decrypt.
+ if(key.cryptoAlgorithm != ClientCHK.ALGO_AES_PCFB_256)
+ throw new UnsupportedOperationException();
+ BlockCipher cipher;
+ try {
+ cipher = new Rijndael(256, 256);
+ } catch (UnsupportedCipherException e) {
+ // FIXME - log this properly
+ throw new Error(e);
+ }
+ byte[] cryptoKey = key.cryptoKey;
+ if(cryptoKey.length < Node.SYMMETRIC_KEY_LENGTH)
+ throw new CHKDecodeException("Crypto key too short");
+ cipher.initialize(key.cryptoKey);
+ PCFBMode pcfb = new PCFBMode(cipher);
+ byte[] hbuf = new byte[header.length-2];
+ System.arraycopy(header, 2, hbuf, 0, header.length-2);
+ byte[] dbuf = new byte[data.length];
+ System.arraycopy(data, 0, dbuf, 0, data.length);
+ // Decipher header first - functions as IV
+ pcfb.blockDecipher(hbuf, 0, hbuf.length);
+ pcfb.blockDecipher(dbuf, 0, dbuf.length);
+ // Check: Decryption key == hash of data (not including header)
+ MessageDigest md256;
+ try {
+ md256 = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException e1) {
+ // FIXME: log this properly?
+ throw new Error(e1);
+ }
+ byte[] dkey = md256.digest(dbuf);
+ if(!java.util.Arrays.equals(dkey, key.cryptoKey)) {
+ throw new CHKDecodeException("Check failed: decrypt key ==
H(data)");
+ }
+ // Check: IV == hash of decryption key
+ byte[] predIV = md256.digest(dkey);
+ // Extract the IV
+ byte[] iv = new byte[32];
+ System.arraycopy(hbuf, 0, iv, 0, 32);
+ if(!Arrays.equals(iv, predIV))
+ throw new CHKDecodeException("Check failed: Decrypted IV ==
H(decryption key)");
+ // Checks complete
+ int size = ((hbuf[32] & 0xff) << 8) + (hbuf[33] & 0xff);
+ if(size > 32768 || size < 0)
+ throw new CHKDecodeException("Invalid size: "+size);
+ byte[] output = new byte[size];
+ // No particular reason to check the padding, is there?
+ System.arraycopy(dbuf, 0, output, 0, size);
+ return Key.decompress(key, output, bf, maxLength,
key.compressionAlgorithm, Math.min(maxLength, MAX_LENGTH_BEFORE_COMPRESSION));
+ }
+
+ /**
* Encode a Bucket of data to a CHKBlock.
* @param sourceData The bucket of data to encode. Can be arbitrarily
large.
* @param asMetadata Is this a metadata key?
@@ -239,4 +320,8 @@
return key;
}
+ public boolean isMetadata() {
+ return key.isMetadata();
+ }
+
}
Modified: branches/freenet-freejvms/src/freenet/keys/ClientKey.java
===================================================================
--- branches/freenet-freejvms/src/freenet/keys/ClientKey.java 2006-02-03
21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/keys/ClientKey.java 2006-02-03
22:29:13 UTC (rev 7997)
@@ -13,12 +13,13 @@
return new ClientCHK(origURI);
throw new UnsupportedOperationException("Unknown keytype from
"+origURI);
}
+
+ public abstract FreenetURI getURI();
/**
- * Does the key contain metadata? If not, it contains real data.
+ * @return a NodeCHK corresponding to this key. Basically keep the
+ * routingKey and lose everything else.
*/
- public abstract boolean isMetadata();
+ public abstract Key getNodeKey();
- public abstract FreenetURI getURI();
-
}
Copied: branches/freenet-freejvms/src/freenet/keys/ClientKeyBlock.java (from
rev 7751, trunk/freenet/src/freenet/keys/ClientKeyBlock.java)
Copied: branches/freenet-freejvms/src/freenet/keys/ClientSSK.java (from rev
7751, trunk/freenet/src/freenet/keys/ClientSSK.java)
Copied: branches/freenet-freejvms/src/freenet/keys/ClientSSKBlock.java (from
rev 7751, trunk/freenet/src/freenet/keys/ClientSSKBlock.java)
Modified: branches/freenet-freejvms/src/freenet/keys/Key.java
===================================================================
--- branches/freenet-freejvms/src/freenet/keys/Key.java 2006-02-03 21:46:40 UTC
(rev 7996)
+++ branches/freenet-freejvms/src/freenet/keys/Key.java 2006-02-03 22:29:13 UTC
(rev 7997)
@@ -3,8 +3,18 @@
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import freenet.io.WritableToDataOutputStream;
+import freenet.support.Bucket;
+import freenet.support.BucketFactory;
+import freenet.support.BucketTools;
+import freenet.support.Fields;
+import freenet.support.Logger;
+import freenet.support.SimpleReadOnlyArrayBucket;
+import freenet.support.compress.CompressionOutputSizeException;
+import freenet.support.compress.Compressor;
/**
* @author amphibian
@@ -13,9 +23,20 @@
*/
public abstract class Key implements WritableToDataOutputStream {
+ final int hash;
+ double cachedNormalizedDouble;
+ /** Whatever its type, it will need a routingKey ! */
+ final byte[] routingKey;
+
/** 32 bytes for hash, 2 bytes for type */
public static final short KEY_SIZE_ON_DISK = 34;
+ protected Key(byte[] routingKey) {
+ this.routingKey = routingKey;
+ hash = Fields.hashCode(routingKey);
+ cachedNormalizedDouble = -1;
+ }
+
/**
* Write to disk.
* Take up exactly 22 bytes.
@@ -36,10 +57,59 @@
throw new IOException("Unrecognized format: "+type);
}
+
/**
* Convert the key to a double between 0.0 and 1.0.
* Normally we will hash the key first, in order to
* make chosen-key attacks harder.
*/
- public abstract double toNormalizedDouble();
+ public synchronized double toNormalizedDouble() {
+ if(cachedNormalizedDouble > 0) return cachedNormalizedDouble;
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException e) {
+ throw new Error(e);
+ }
+ md.update(routingKey);
+ int TYPE = getType();
+ md.update((byte)(TYPE >> 8));
+ md.update((byte)TYPE);
+ byte[] digest = md.digest();
+ long asLong = Math.abs(Fields.bytesToLong(digest));
+ // Math.abs can actually return negative...
+ if(asLong == Long.MIN_VALUE)
+ asLong = Long.MAX_VALUE;
+ cachedNormalizedDouble = ((double)asLong)/((double)Long.MAX_VALUE);
+ return cachedNormalizedDouble;
+ }
+
+ public abstract short getType();
+
+ public int hashCode() {
+ return hash;
+ }
+
+ static Bucket decompress(ClientCHK key, byte[] output, BucketFactory bf,
int maxLength, short compressionAlgorithm, int maxDecompressedLength) throws
CHKDecodeException, IOException {
+ if(key.isCompressed()) {
+ Logger.minor(key, "Decompressing in decode: "+key.getURI()+"
with codec "+compressionAlgorithm);
+ if(output.length < 5) throw new CHKDecodeException("No bytes to
decompress");
+ // Decompress
+ // First get the length
+ int len = ((((((output[0] & 0xff) << 8) + (output[1] & 0xff)) <<
8) + (output[2] & 0xff)) << 8) +
+ (output[3] & 0xff);
+ if(len > maxDecompressedLength)
+ throw new CHKDecodeException("Invalid precompressed size:
"+len);
+ Compressor decompressor =
Compressor.getCompressionAlgorithmByMetadataID(compressionAlgorithm);
+ Bucket inputBucket = new SimpleReadOnlyArrayBucket(output, 4,
output.length-4);
+ try {
+ return decompressor.decompress(inputBucket, bf,
maxLength);
+ } catch (CompressionOutputSizeException e) {
+ throw new CHKDecodeException("Too big");
+ }
+ } else {
+ return BucketTools.makeImmutableBucket(bf, output);
+ }
+ }
+
}
Modified: branches/freenet-freejvms/src/freenet/keys/KeyBlock.java
===================================================================
--- branches/freenet-freejvms/src/freenet/keys/KeyBlock.java 2006-02-03
21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/keys/KeyBlock.java 2006-02-03
22:29:13 UTC (rev 7997)
@@ -10,11 +10,6 @@
*/
public interface KeyBlock {
- /** Decode with the key
- * @param key The ClientKey to use to decode the block.
- * @param factory The BucketFactory to use to create the Bucket to
return the data in.
- * @param maxLength The maximum size of the returned data in bytes.
- */
- Bucket decode(ClientKey key, BucketFactory factory, int maxLength)
throws KeyDecodeException, IOException;
-
+ final static int HASH_SHA256 = 1;
+
}
Modified: branches/freenet-freejvms/src/freenet/keys/NodeCHK.java
===================================================================
--- branches/freenet-freejvms/src/freenet/keys/NodeCHK.java 2006-02-03
21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/keys/NodeCHK.java 2006-02-03
22:29:13 UTC (rev 7997)
@@ -27,21 +27,16 @@
*/
public class NodeCHK extends Key {
- final int hash;
- double cachedNormalizedDouble;
-
public NodeCHK(byte[] routingKey2) {
- routingKey = routingKey2;
+ super(routingKey2);
if(routingKey2.length != KEY_LENGTH)
throw new IllegalArgumentException("Wrong length:
"+routingKey2.length+" should be "+KEY_LENGTH);
- hash = Fields.hashCode(routingKey);
- cachedNormalizedDouble = -1;
}
static final int KEY_LENGTH = 32;
- byte[] routingKey;
- public static final short TYPE = 0x0302;
+ // 01 = CHK, 01 = first version of CHK
+ public static final short TYPE = 0x0101;
/** The size of the data */
public static final int BLOCK_SIZE = 32768;
@@ -64,10 +59,6 @@
return new NodeCHK(buf);
}
- public int hashCode() {
- return hash;
- }
-
public boolean equals(Object key) {
if(key instanceof NodeCHK) {
NodeCHK chk = (NodeCHK) key;
@@ -99,4 +90,7 @@
cachedNormalizedDouble = ((double)asLong)/((double)Long.MAX_VALUE);
return cachedNormalizedDouble;
}
+ public short getType() {
+ return TYPE;
+ }
}
Copied: branches/freenet-freejvms/src/freenet/keys/NodeSSK.java (from rev 7751,
trunk/freenet/src/freenet/keys/NodeSSK.java)
Copied: branches/freenet-freejvms/src/freenet/keys/SSKBlock.java (from rev
7751, trunk/freenet/src/freenet/keys/SSKBlock.java)
Copied: branches/freenet-freejvms/src/freenet/keys/SSKDecodeException.java
(from rev 7751, trunk/freenet/src/freenet/keys/SSKDecodeException.java)
Copied: branches/freenet-freejvms/src/freenet/keys/SSKVerifyException.java
(from rev 7751, trunk/freenet/src/freenet/keys/SSKVerifyException.java)
Modified: branches/freenet-freejvms/src/freenet/node/Node.java
===================================================================
--- branches/freenet-freejvms/src/freenet/node/Node.java 2006-02-03
21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/node/Node.java 2006-02-03
22:29:13 UTC (rev 7997)
@@ -45,6 +45,7 @@
import freenet.keys.ClientCHK;
import freenet.keys.ClientCHKBlock;
import freenet.keys.ClientKey;
+import freenet.keys.ClientKeyBlock;
import freenet.keys.KeyBlock;
import freenet.keys.NodeCHK;
import freenet.store.BaseFreenetStore;
@@ -178,6 +179,7 @@
final RequestStarter insertStarter;
final File downloadDir;
final TestnetHandler testnetHandler;
+ final TestnetStatusUploader statusUploader;
// Client stuff that needs to be configged - FIXME
static final int MAX_ARCHIVE_HANDLERS = 200; // don't take up much RAM...
FIXME
@@ -186,7 +188,6 @@
static final long MAX_ARCHIVED_FILE_SIZE = 1024*1024; // arbitrary... FIXME
static final int MAX_CACHED_ELEMENTS = 1024; // equally arbitrary! FIXME
hopefully we can cache many of these though
-
/**
* Read all storable settings (identity etc) from the node file.
* @param filename The name of the file to read from.
@@ -343,10 +344,12 @@
testnetEnabled = true;
testnetPort = 1024 + (port-1024+1000) % (65536 - 1024);
testnetHandler = new TestnetHandler(this, testnetPort);
+ statusUploader = new TestnetStatusUploader(this, 180000);
} else {
testnetEnabled = false;
testnetPort = -1;
testnetHandler = null;
+ statusUploader = null;
}
portNumber = port;
startupTime = System.currentTimeMillis();
@@ -447,14 +450,14 @@
usm.start();
}
- public KeyBlock getKey(ClientKey key, boolean localOnly,
RequestStarterClient client, boolean cache) throws LowLevelGetException {
+ public ClientKeyBlock getKey(ClientKey key, boolean localOnly,
RequestStarterClient client, boolean cache) throws LowLevelGetException {
if(localOnly)
return realGetKey(key, localOnly, cache);
else
return client.getKey(key, localOnly, cache);
}
- public KeyBlock realGetKey(ClientKey key, boolean localOnly, boolean
cache) throws LowLevelGetException {
+ public ClientKeyBlock realGetKey(ClientKey key, boolean localOnly, boolean
cache) throws LowLevelGetException {
if(key instanceof ClientCHK)
return realGetCHK((ClientCHK)key, localOnly, cache);
else
@@ -950,7 +953,8 @@
*/
public String getStatus() {
StringBuffer sb = new StringBuffer();
- sb.append(peers.getStatus());
+ if (peers != null)
+ sb.append(peers.getStatus());
sb.append("\nInserts: ");
int x = insertSenders.size();
sb.append(x);
Modified: branches/freenet-freejvms/src/freenet/node/QueuedDataRequest.java
===================================================================
--- branches/freenet-freejvms/src/freenet/node/QueuedDataRequest.java
2006-02-03 21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/node/QueuedDataRequest.java
2006-02-03 22:29:13 UTC (rev 7997)
@@ -1,6 +1,7 @@
package freenet.node;
import freenet.keys.ClientKey;
+import freenet.keys.ClientKeyBlock;
import freenet.keys.KeyBlock;
public class QueuedDataRequest extends QueuedRequest {
@@ -17,7 +18,7 @@
this.cache = cache;
}
- public KeyBlock waitAndFetch() throws LowLevelGetException {
+ public ClientKeyBlock waitAndFetch() throws LowLevelGetException {
waitForSendClearance();
return client.realGetKey(key, localOnly, cache);
}
Modified:
branches/freenet-freejvms/src/freenet/node/QueueingSimpleLowLevelClient.java
===================================================================
---
branches/freenet-freejvms/src/freenet/node/QueueingSimpleLowLevelClient.java
2006-02-03 21:46:40 UTC (rev 7996)
+++
branches/freenet-freejvms/src/freenet/node/QueueingSimpleLowLevelClient.java
2006-02-03 22:29:13 UTC (rev 7997)
@@ -3,12 +3,13 @@
import freenet.client.InsertBlock;
import freenet.keys.ClientCHKBlock;
import freenet.keys.ClientKey;
+import freenet.keys.ClientKeyBlock;
import freenet.keys.KeyBlock;
interface QueueingSimpleLowLevelClient extends SimpleLowLevelClient {
/** Unqueued version. Only call from QueuedDataRequest ! */
- KeyBlock realGetKey(ClientKey key, boolean localOnly, boolean cache)
throws LowLevelGetException;
+ ClientKeyBlock realGetKey(ClientKey key, boolean localOnly, boolean
cache) throws LowLevelGetException;
/** Ditto */
void realPutCHK(ClientCHKBlock block, boolean cache) throws
LowLevelPutException;
Modified:
branches/freenet-freejvms/src/freenet/node/RealNodeRequestInsertTest.java
===================================================================
--- branches/freenet-freejvms/src/freenet/node/RealNodeRequestInsertTest.java
2006-02-03 21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/node/RealNodeRequestInsertTest.java
2006-02-03 22:29:13 UTC (rev 7997)
@@ -179,7 +179,7 @@
byte[] encData = block.getData();
byte[] encHeaders = block.getHeader();
ClientCHKBlock newBlock = new ClientCHKBlock(encData,
encHeaders, chk, true);
- Logger.error(RealNodeRequestInsertTest.class, "Decoded: "+new
String(newBlock.memoryDecode(chk)));
+ Logger.error(RealNodeRequestInsertTest.class, "Decoded: "+new
String(newBlock.memoryDecode()));
Logger.error(RealNodeRequestInsertTest.class,"CHK:
"+chk.getURI());
Logger.error(RealNodeRequestInsertTest.class,"Headers:
"+HexUtil.bytesToHex(block.getHeader()));
randomNode.putCHK(block, starters[node1], true);
@@ -196,7 +196,7 @@
Logger.error(RealNodeRequestInsertTest.class, "Fetch
FAILED from "+node2);
requestsAvg.report(0.0);
} else {
- byte[] results = block.memoryDecode(chk);
+ byte[] results = block.memoryDecode();
requestsAvg.report(1.0);
if(Arrays.equals(results, data)) {
Logger.error(RealNodeRequestInsertTest.class, "Fetch
succeeded: "+new String(results));
Modified: branches/freenet-freejvms/src/freenet/node/RequestStarterClient.java
===================================================================
--- branches/freenet-freejvms/src/freenet/node/RequestStarterClient.java
2006-02-03 21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/node/RequestStarterClient.java
2006-02-03 22:29:13 UTC (rev 7997)
@@ -5,6 +5,7 @@
import freenet.crypt.RandomSource;
import freenet.keys.ClientCHKBlock;
import freenet.keys.ClientKey;
+import freenet.keys.ClientKeyBlock;
import freenet.keys.KeyBlock;
import freenet.support.DoublyLinkedList;
import freenet.support.UpdatableSortedLinkedListItemImpl;
@@ -42,7 +43,7 @@
* Blocking fetch of a key.
* @throws LowLevelGetException If the fetch failed for some reason.
*/
- public KeyBlock getKey(ClientKey key, boolean localOnly, boolean cache)
throws LowLevelGetException {
+ public ClientKeyBlock getKey(ClientKey key, boolean localOnly, boolean
cache) throws LowLevelGetException {
QueuedDataRequest qdr = new QueuedDataRequest(key, localOnly,
cache, client);
addRequest(qdr);
return qdr.waitAndFetch();
Modified: branches/freenet-freejvms/src/freenet/node/SimpleLowLevelClient.java
===================================================================
--- branches/freenet-freejvms/src/freenet/node/SimpleLowLevelClient.java
2006-02-03 21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/node/SimpleLowLevelClient.java
2006-02-03 22:29:13 UTC (rev 7997)
@@ -2,6 +2,7 @@
import freenet.keys.ClientCHKBlock;
import freenet.keys.ClientKey;
+import freenet.keys.ClientKeyBlock;
import freenet.keys.KeyBlock;
/**
@@ -19,7 +20,7 @@
* @param cache If false, don't cache the data. See the comments at the top
* of Node.java.
*/
- public KeyBlock getKey(ClientKey key, boolean localOnly,
RequestStarterClient client, boolean cache) throws LowLevelGetException;
+ public ClientKeyBlock getKey(ClientKey key, boolean localOnly,
RequestStarterClient client, boolean cache) throws LowLevelGetException;
/**
* Insert a key.
Modified: branches/freenet-freejvms/src/freenet/node/TestnetHandler.java
===================================================================
--- branches/freenet-freejvms/src/freenet/node/TestnetHandler.java
2006-02-03 21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/node/TestnetHandler.java
2006-02-03 22:29:13 UTC (rev 7997)
@@ -115,7 +115,12 @@
return;
}
node.fileLoggerHook.sendLogByContainedDate(d.getTime(), os);
- } else {
+ } else if(command.equalsIgnoreCase("STATUS")) {
+ Logger.minor(this, "Sending status");
+ OutputStreamWriter osw = new
OutputStreamWriter(os, "ISO-8859-1");
+ osw.write(node.getStatus());
+ osw.close();
+ }else {
Logger.error(this, "Unknown testnet
command: "+command);
}
} catch (IOException e) {
Copied: branches/freenet-freejvms/src/freenet/node/TestnetStatusUploader.java
(from rev 7751, trunk/freenet/src/freenet/node/TestnetStatusUploader.java)
Modified:
branches/freenet-freejvms/src/freenet/node/TextModeClientInterface.java
===================================================================
--- branches/freenet-freejvms/src/freenet/node/TextModeClientInterface.java
2006-02-03 21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/node/TextModeClientInterface.java
2006-02-03 22:29:13 UTC (rev 7997)
@@ -2,6 +2,7 @@
import java.io.BufferedReader;
import java.io.DataInputStream;
+import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
@@ -10,15 +11,19 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
+import java.util.HashMap;
import java.util.Hashtable;
+import java.util.Iterator;
import freenet.client.ClientMetadata;
import freenet.client.DefaultMIMETypes;
import freenet.client.FetchException;
import freenet.client.FetchResult;
import freenet.client.HighLevelSimpleClient;
+import freenet.client.HighLevelSimpleClientImpl;
import freenet.client.InsertBlock;
import freenet.client.InserterException;
+import freenet.client.Metadata;
import freenet.client.events.EventDumper;
import freenet.crypt.RandomSource;
import freenet.io.comm.PeerParseException;
@@ -92,6 +97,8 @@
System.out.println("PUTFILE:<filename> - Put a file from disk.");
System.out.println("GETFILE:<filename> - Fetch a key and put it in a
file. If the key includes a filename we will use it but we will not overwrite
local files.");
System.out.println("GETCHKFILE:<filename> - Get the key that would be
returned if we inserted the file.");
+ System.out.println("PUTDIR:<path>[#<defaultfile>] - Put the entire
directory from disk.");
+ System.out.println("GETCHKDIR:<path>[#<defaultfile>] - Get the key
that would be returned if we'd put the entire directory from disk.");
// System.out.println("PUBLISH:<name> - create a publish/subscribe
stream called <name>");
// System.out.println("PUSH:<name>:<text> - publish a single line of
text to the stream named");
// System.out.println("SUBSCRIBE:<key> - subscribe to a
publish/subscribe stream by key");
@@ -250,6 +257,85 @@
}
System.out.println("URI: "+uri);
+
////////////////////////////////////////////////////////////////////////////////
+ } else if(uline.startsWith("PUTDIR:") || (getCHKOnly =
uline.startsWith("GETCHKDIR:"))) {
+ // TODO: Check for errors?
+ if(getCHKOnly) {
+ line = line.substring(("GETCHKDIR:").length());
+ } else {
+ line = line.substring("PUTDIR:".length());
+ }
+
+ line = line.trim();
+
+ if(line.length() < 1) {
+ printHeader();
+ return;
+ }
+
+ String defaultFile = null;
+
+ // set default file?
+ if (line.matches("^.*#.*$")) {
+ defaultFile = line.split("#")[1];
+ line = line.split("#")[0];
+ }
+
+ // Get files as name and keys
+ HashMap manifestBase = dirPut(line, getCHKOnly);
+
+ // Set defaultfile
+ if (defaultFile != null) {
+ HashMap currPos = manifestBase;
+ String splitpath[] = defaultFile.split("/");
+ int i = 0;
+ for( ; i < (splitpath.length - 1) ; i++)
+ currPos = (HashMap)currPos.get(splitpath[i]);
+
+ if (currPos.get(splitpath[i]) != null) {
+ // Add key as default
+ manifestBase.put("", currPos.get(splitpath[i]));
+ System.out.println("Using default key: " +
currPos.get(splitpath[i]));
+ }else{
+ System.err.println("Default key not found. No
default document.");
+ }
+ //getchkdir:/home/cyberdo/fort/new#filelist
+ }
+
+ // Create metadata
+ Metadata med = Metadata.mkRedirectionManifest(manifestBase);
+ ClientMetadata md = med.getClientMetadata();
+
+ // Extract binary data from metadata
+ ArrayBucket metabucket = new ArrayBucket();
+ DataOutputStream mdos = new DataOutputStream(
metabucket.getOutputStream() );
+ med.writeTo(mdos);
+ mdos.close();
+
+ // Insert metadata
+ InsertBlock block = new InsertBlock(metabucket, md,
FreenetURI.EMPTY_CHK_URI);
+
+ FreenetURI uri;
+ try {
+ uri = ((HighLevelSimpleClientImpl)client).insert(block,
getCHKOnly, true);
+ } catch (InserterException e) {
+ System.out.println("Error: "+e.getMessage());
+ if(e.uri != null)
+ System.out.println("URI would have been: "+e.uri);
+ int mode = e.getMode();
+ if(mode == InserterException.FATAL_ERRORS_IN_BLOCKS || mode ==
InserterException.TOO_MANY_RETRIES_IN_BLOCKS) {
+ System.out.println("Splitfile-specific
error:\n"+e.errorCodes.toVerboseString());
+ }
+ return;
+ }
+
+ String filelist = dirPutToList(manifestBase, "");
+
System.out.println("=======================================================");
+ System.out.println(filelist);
+
System.out.println("=======================================================");
+ System.out.println("URI: "+uri);
+
System.out.println("=======================================================");
+
} else if(uline.startsWith("PUTFILE:") || (getCHKOnly =
uline.startsWith("GETCHKFILE:"))) {
// Just insert to local store
if(getCHKOnly) {
@@ -358,6 +444,101 @@
}
}
+
+ private String dirPutToList(HashMap dir, String basedir) {
+ String ret = "";
+ for(Iterator i = dir.keySet().iterator();i.hasNext();) {
+ String key = (String) i.next();
+ Object o = dir.get(key);
+ Metadata target;
+ if(o instanceof String) {
+ // File
+ ret += basedir + key + "\n";
+ } else if(o instanceof HashMap) {
+ ret += dirPutToList((HashMap)o, basedir + key +
"//");
+ } else throw new IllegalArgumentException("Not String
nor HashMap: "+o);
+ }
+ return ret;
+ }
+
+ private HashMap dirPut(String directory, boolean getCHKOnly) {
+ if (!directory.endsWith("/"))
+ directory = directory + "/";
+ File thisdir = new File(directory);
+
+ HashMap ret = new HashMap();
+
+ File filelist[] = thisdir.listFiles();
+ for(int i = 0 ; i < filelist.length ; i++)
+ if (filelist[i].isFile()) {
+ FreenetURI uri = null;
+ File f = filelist[i];
+ String line = f.getAbsolutePath();
+ // To ease cleanup, the following code is taken from
above
+ // Except for the uri-declaration above.
+ // Somelines is also commented out
+
//////////////////////////////////////////////////////////////////////////////////////
+ System.out.println("Attempting to read file "+line);
+ long startTime = System.currentTimeMillis();
+ try {
+ if(!(f.exists() && f.canRead())) {
+ throw new FileNotFoundException();
+ }
+
+ // Guess MIME type
+ String mimeType = DefaultMIMETypes.guessMIMEType(line);
+ System.out.println("Using MIME type: "+mimeType);
+
+ FileBucket fb = new FileBucket(f, true, false, false);
+ InsertBlock block = new InsertBlock(fb, new
ClientMetadata(mimeType), FreenetURI.EMPTY_CHK_URI);
+
+ startTime = System.currentTimeMillis();
+ // Declaration is moved out!!!!!!!!!!!!
+ uri = client.insert(block, getCHKOnly);
+
+ // FIXME depends on CHK's still being renamable
+ //uri = uri.setDocName(f.getName());
+
+ System.out.println("URI: "+uri);
+ long endTime = System.currentTimeMillis();
+ long sz = f.length();
+ double rate = 1000.0 * sz / (endTime-startTime);
+ System.out.println("Upload rate: "+rate+" bytes / second");
+ } catch (FileNotFoundException e1) {
+ System.out.println("File not found");
+ } catch (InserterException e) {
+ System.out.println("Finished insert but:
"+e.getMessage());
+ if(e.uri != null) {
+ System.out.println("URI would have been:
"+e.uri);
+ long endTime = System.currentTimeMillis();
+ long sz = f.length();
+ double rate = 1000.0 * sz / (endTime-startTime);
+ System.out.println("Upload rate: "+rate+" bytes /
second");
+ }
+ if(e.errorCodes != null) {
+ System.out.println("Splitfile errors
breakdown:");
+
System.out.println(e.errorCodes.toVerboseString());
+ }
+ } catch (Throwable t) {
+ System.out.println("Insert threw: "+t);
+ t.printStackTrace();
+ }
+
//////////////////////////////////////////////////////////////////////////////////////
+
+ if (uri != null)
+ ret.put(filelist[i].getName(), uri.toString(false));
+ else
+ System.err.println("Could not insert file.");
+ //ret.put(filelist[i].getName(), null);
+ } else {
+ HashMap subdir = dirPut(filelist[i].getAbsolutePath(),
getCHKOnly);
+ ret.put(filelist[i].getName(), subdir);
+ }
+
+ return ret;
+ }
+
+
/**
* @return A block of text, input from stdin, ending with a
* . on a line by itself. Does some mangling for a fieldset if
Modified: branches/freenet-freejvms/src/freenet/node/Version.java
===================================================================
--- branches/freenet-freejvms/src/freenet/node/Version.java 2006-02-03
21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/node/Version.java 2006-02-03
22:29:13 UTC (rev 7997)
@@ -20,7 +20,7 @@
public static final String protocolVersion = "1.0";
/** The build number of the current revision */
- public static final int buildNumber = 305;
+ public static final int buildNumber = 309;
/** Oldest build of Fred we will talk to */
public static final int lastGoodBuild = 305;
Modified: branches/freenet-freejvms/src/freenet/store/DataStore.java
===================================================================
--- branches/freenet-freejvms/src/freenet/store/DataStore.java 2006-02-03
21:46:40 UTC (rev 7996)
+++ branches/freenet-freejvms/src/freenet/store/DataStore.java 2006-02-03
22:29:13 UTC (rev 7997)
@@ -27,8 +27,22 @@
public class DataStore extends Store {
- public static final String VERSION = "$Id: DataStore.java,v 1.5 2005/08/20
21:21:21 amphibian Exp $";
+ public class ATimeComparator implements Comparator {
+ public int compare(Object arg0, Object arg1) {
+ DataBlock db0 = (DataBlock) arg0;
+ DataBlock db1 = (DataBlock) arg1;
+ long a0 = db0.getLastAccessTime();
+ long a1 = db1.getLastAccessTime();
+ if(a0 < a1) return -1;
+ if(a0 > a1) return 1;
+ return 0;
+ }
+
+ }
+
+ public static final String VERSION = "$Id: DataStore.java,v 1.5
2005/08/20 21:21:21 amphibian Exp $";
+
private RandomAccessFile _index;
private final int blockSize;
@@ -55,6 +69,8 @@
_index.seek(0);
int recordNum = 0;
+ Vector v = new Vector();
+
try {
while (_index.getFilePointer() < _index.length()) {
@@ -65,14 +81,19 @@
getKeyMap().put(dataBlock.getKey(), dataBlock);
getRecordNumberList().add(recordNum, dataBlock);
-
- updateLastAccess(dataBlock);
+ v.add(dataBlock);
recordNum++;
}
} catch (EOFException e) {
// Chopped off in the middle of a key
Logger.normal(this, "Store index truncated");
return;
+ } finally {
+ DataBlock[] blocks = (DataBlock[]) v.toArray(new
DataBlock[v.size()]);
+ Arrays.sort(blocks, new ATimeComparator());
+ for(int i=0;i<blocks.length;i++) {
+ updateLastAccess(blocks[i]);
+ }
}
}