Author: toad
Date: 2006-02-03 01:34:42 +0000 (Fri, 03 Feb 2006)
New Revision: 7994
Added:
trunk/freenet/src/freenet/support/ReadOnlyFileSliceBucket.java
Modified:
trunk/freenet/src/freenet/node/Version.java
trunk/freenet/src/freenet/support/BucketTools.java
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
trunk/freenet/src/freenet/support/io/FileBucket.java
Log:
430:
Optimizations mostly related to memory usage:
- Don't keep a Mersenne Twister for every single padded encrypted bucket's
entire lifetime. They are quite big!
- Don't copy data from a file bucket to individual data buckets.
-- Reduces disk usage from 150% of file size to 50% of file size on insert.
-- Speeds up starting an insert.
-- Saves a load of memory.
Result:
~ 50MB for 3x 110MB files inserting at once (maybe a bit higher during encode
if you start all of them at once).
Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-02-02 19:10:00 UTC (rev
7993)
+++ trunk/freenet/src/freenet/node/Version.java 2006-02-03 01:34:42 UTC (rev
7994)
@@ -20,7 +20,7 @@
public static final String protocolVersion = "1.0";
/** The build number of the current revision */
- private static final int buildNumber = 429;
+ private static final int buildNumber = 430;
/** Oldest build of Fred we will talk to */
private static final int lastGoodBuild = 403;
Modified: trunk/freenet/src/freenet/support/BucketTools.java
===================================================================
--- trunk/freenet/src/freenet/support/BucketTools.java 2006-02-02 19:10:00 UTC
(rev 7993)
+++ trunk/freenet/src/freenet/support/BucketTools.java 2006-02-03 01:34:42 UTC
(rev 7994)
@@ -15,6 +15,8 @@
import java.util.ArrayList;
import java.util.List;
+import freenet.support.io.FileBucket;
+
/**
* Helper functions for working with Buckets.
*/
@@ -439,6 +441,9 @@
* the provided bucket, or writing to created buckets.
*/
public static Bucket[] split(Bucket origData, int splitSize,
BucketFactory bf) throws IOException {
+ if(origData instanceof FileBucket) {
+ return ((FileBucket)origData).split(splitSize);
+ }
long length = origData.size();
if(length > ((long)Integer.MAX_VALUE) * splitSize)
throw new IllegalArgumentException("Way too big!:
"+length+" for "+splitSize);
Modified:
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
2006-02-02 19:10:00 UTC (rev 7993)
+++ trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
2006-02-03 01:34:42 UTC (rev 7994)
@@ -20,7 +20,7 @@
private final Bucket bucket;
private final int minPaddedSize;
- private final MersenneTwister paddingSource;
+ private final RandomSource origRandom;
private final Rijndael aes;
private long dataLength;
private boolean readOnly;
@@ -35,6 +35,7 @@
* @throws UnsupportedCipherException
*/
public PaddedEphemerallyEncryptedBucket(Bucket bucket, int minSize,
RandomSource origRandom) throws UnsupportedCipherException {
+ this.origRandom = origRandom;
this.bucket = bucket;
if(bucket.size() != 0) throw new
IllegalArgumentException("Bucket must be empty");
aes = new Rijndael(256, 256);
@@ -44,7 +45,6 @@
// Might as well blank it
for(int i=0;i<key.length;i++) key[i] = 0;
this.minPaddedSize = minSize;
- paddingSource = new MersenneTwister(origRandom.nextLong());
readOnly = false;
lastOutputStream = 0;
}
@@ -107,6 +107,7 @@
return;
}
synchronized(PaddedEphemerallyEncryptedBucket.this) {
+ MersenneTwister paddingSource = new
MersenneTwister(origRandom.nextLong());
long finalLength = paddedLength();
long padding = finalLength - dataLength;
byte[] buf = new byte[4096];
Added: trunk/freenet/src/freenet/support/ReadOnlyFileSliceBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/ReadOnlyFileSliceBucket.java
2006-02-02 19:10:00 UTC (rev 7993)
+++ trunk/freenet/src/freenet/support/ReadOnlyFileSliceBucket.java
2006-02-03 01:34:42 UTC (rev 7994)
@@ -0,0 +1,103 @@
+package freenet.support;
+
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+
+/**
+ * FIXME: implement a hash verifying version of this.
+ */
+public class ReadOnlyFileSliceBucket implements Bucket {
+
+ private final File file;
+ private final long startAt;
+ private final long length;
+
+ public ReadOnlyFileSliceBucket(File f, long startAt, long length) {
+ this.file = f;
+ this.startAt = startAt;
+ this.length = length;
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ throw new IOException("Bucket is read-only");
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return new MyInputStream();
+ }
+
+ public String getName() {
+ return "ROFS:"+file.getAbsolutePath()+":"+startAt+":"+length;
+ }
+
+ public long size() {
+ return length;
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ public void setReadOnly() {
+ // Do nothing
+ }
+
+ class MyInputStream extends InputStream {
+
+ private RandomAccessFile f;
+ private long ptr; // relative to startAt
+
+ MyInputStream() throws IOException {
+ try {
+ this.f = new RandomAccessFile(file,"r");
+ f.seek(startAt);
+ if(f.length() < (startAt+length))
+ throw new
ReadOnlyFileSliceBucketException("File truncated? Length "+f.length()+" but
start at "+startAt+" for "+length+" bytes");
+ ptr = 0;
+ } catch (FileNotFoundException e) {
+ throw new ReadOnlyFileSliceBucketException(e);
+ }
+ }
+
+ public int read() throws IOException {
+ if(ptr > length)
+ throw new EOFException();
+ int x = f.read();
+ ptr++;
+ return x;
+ }
+
+ public int read(byte[] buf, int offset, int len) throws
IOException {
+ if(ptr > length)
+ throw new EOFException();
+ len = (int) Math.min(len, length - ptr);
+ int x = f.read(buf, offset, len);
+ ptr += x;
+ return x;
+ }
+
+ public int read(byte[] buf) throws IOException {
+ return read(buf, 0, buf.length);
+ }
+
+ }
+
+ public class ReadOnlyFileSliceBucketException extends IOException {
+
+ public ReadOnlyFileSliceBucketException(FileNotFoundException
e) {
+ super("File not found: "+e.getMessage());
+ initCause(e);
+ }
+
+ public ReadOnlyFileSliceBucketException(String string) {
+ super(string);
+ }
+
+ }
+
+}
Modified: trunk/freenet/src/freenet/support/io/FileBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/FileBucket.java 2006-02-02
19:10:00 UTC (rev 7993)
+++ trunk/freenet/src/freenet/support/io/FileBucket.java 2006-02-03
01:34:42 UTC (rev 7994)
@@ -11,6 +11,7 @@
import freenet.crypt.RandomSource;
import freenet.support.Bucket;
import freenet.support.Logger;
+import freenet.support.ReadOnlyFileSliceBucket;
/**
* A file Bucket is an implementation of Bucket that writes to a file.
@@ -299,4 +300,19 @@
public void dontDeleteOnFinalize() {
deleteOnFinalize = false;
}
+
+ public Bucket[] split(int splitSize) {
+ if(length > ((long)Integer.MAX_VALUE) * splitSize)
+ throw new IllegalArgumentException("Way too big!:
"+length+" for "+splitSize);
+ int bucketCount = (int) (length / splitSize);
+ if(length % splitSize > 0) bucketCount++;
+ Bucket[] buckets = new Bucket[bucketCount];
+ for(int i=0;i<buckets.length;i++) {
+ long startAt = i * splitSize;
+ long endAt = Math.min((i+1) * splitSize, length);
+ long len = endAt - startAt;
+ buckets[i] = new ReadOnlyFileSliceBucket(file, startAt,
len);
+ }
+ return buckets;
+ }
}