Author: toad
Date: 2005-11-11 21:55:47 +0000 (Fri, 11 Nov 2005)
New Revision: 7529

Modified:
   trunk/freenet/src/freenet/client/BlockFetcher.java
   trunk/freenet/src/freenet/client/BlockInserter.java
   trunk/freenet/src/freenet/client/DefaultMIMETypes.java
   trunk/freenet/src/freenet/client/FECCodec.java
   trunk/freenet/src/freenet/client/FetchException.java
   trunk/freenet/src/freenet/client/FetcherContext.java
   trunk/freenet/src/freenet/client/FileInserter.java
   trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
   trunk/freenet/src/freenet/client/InsertBlock.java
   trunk/freenet/src/freenet/client/InserterContext.java
   trunk/freenet/src/freenet/client/InserterException.java
   trunk/freenet/src/freenet/client/Metadata.java
   trunk/freenet/src/freenet/client/RetryTracker.java
   trunk/freenet/src/freenet/client/SplitFetcher.java
   trunk/freenet/src/freenet/client/SplitInserter.java
   trunk/freenet/src/freenet/client/StandardOnionFECCodec.java
   trunk/freenet/src/freenet/client/StdSplitfileBlock.java
   trunk/freenet/src/freenet/node/Version.java
   trunk/freenet/src/freenet/support/Fields.java
Log:
166 (mandatory):
Fixed FEC splitfiles. I think. :)

Modified: trunk/freenet/src/freenet/client/BlockFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/BlockFetcher.java  2005-11-11 18:57:07 UTC 
(rev 7528)
+++ trunk/freenet/src/freenet/client/BlockFetcher.java  2005-11-11 21:55:47 UTC 
(rev 7529)
@@ -50,6 +50,7 @@
                                        (!this.segment.nonFullBlocksAllowed) || 
dontEnterImplicitArchives);
                        actuallyFetched = true;
                        fetchedData = fr.data;
+                       Logger.minor(this, "Fetched "+fetchedData.size()+" 
bytes on "+this);
                        tracker.success(this);
                } catch (MetadataParseException e) {
                        fatalError(e, FetchException.INVALID_METADATA);
@@ -95,7 +96,7 @@
        }

        private void fatalError(Throwable e, int code) {
-               Logger.normal(this, "Giving up on block: "+this+": "+e);
+               Logger.error(this, "Giving up on block: "+this+": "+e, e);
                tracker.fatalError(this, code);
        }


Modified: trunk/freenet/src/freenet/client/BlockInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/BlockInserter.java 2005-11-11 18:57:07 UTC 
(rev 7528)
+++ trunk/freenet/src/freenet/client/BlockInserter.java 2005-11-11 21:55:47 UTC 
(rev 7529)
@@ -28,10 +28,13 @@
                this.ctx = ctx;
                block = new InsertBlock(bucket, null, FreenetURI.EMPTY_CHK_URI);
                this.getCHKOnly = getCHKOnly;
+               Logger.minor(this, "Created "+this);
        }

        public synchronized void setData(Bucket data) {
                if(this.fetchedData != null) throw new 
IllegalArgumentException("Cannot set data when already have data");
+               block.data = data;
+               super.setData(data);
        }

        public void kill() {
@@ -48,9 +51,11 @@

        public void run() {
                try {
+                       if(fetchedData == null)
+                               throw new NullPointerException();
                        realRun();
                } catch (Throwable t) {
-                       Logger.error(this, "Caught "+t, t);
+                       Logger.error(this, "Caught "+t+" on "+this, t);
                        fatalError(t, InserterException.INTERNAL_ERROR);
                } finally {
                        completedTries++;

Modified: trunk/freenet/src/freenet/client/DefaultMIMETypes.java
===================================================================
--- trunk/freenet/src/freenet/client/DefaultMIMETypes.java      2005-11-11 
18:57:07 UTC (rev 7528)
+++ trunk/freenet/src/freenet/client/DefaultMIMETypes.java      2005-11-11 
21:55:47 UTC (rev 7529)
@@ -57,7 +57,6 @@
                addMIMEType(number, type);
                Short t = new Short(number);
                if(extensions != null) {
-                       boolean first = true;
                        for(int i=0;i<extensions.length;i++) {
                                String ext = extensions[i].toLowerCase();
                                if(mimeTypesByExtension.containsKey(ext)) {

Modified: trunk/freenet/src/freenet/client/FECCodec.java
===================================================================
--- trunk/freenet/src/freenet/client/FECCodec.java      2005-11-11 18:57:07 UTC 
(rev 7528)
+++ trunk/freenet/src/freenet/client/FECCodec.java      2005-11-11 21:55:47 UTC 
(rev 7529)
@@ -13,22 +13,6 @@
  */
 abstract class FECCodec {

-       public static int getCodecMaxSegmentDataBlocks(short splitfileType) {
-               if(splitfileType == Metadata.SPLITFILE_NONREDUNDANT)
-                       return -1;
-               if(splitfileType == Metadata.SPLITFILE_ONION_STANDARD)
-                       return 128;
-               throw new IllegalArgumentException();
-       }
-
-       public static int getCodecMaxSegmentCheckBlocks(short splitfileType) {
-               if(splitfileType == Metadata.SPLITFILE_NONREDUNDANT)
-                       return -1;
-               if(splitfileType == Metadata.SPLITFILE_ONION_STANDARD)
-                       return 64;
-               throw new IllegalArgumentException();
-       }
-       
        /**
         * Get a codec where we know both the number of data blocks and the 
number
         * of check blocks, and the codec type. Normally for decoding.

Modified: trunk/freenet/src/freenet/client/FetchException.java
===================================================================
--- trunk/freenet/src/freenet/client/FetchException.java        2005-11-11 
18:57:07 UTC (rev 7528)
+++ trunk/freenet/src/freenet/client/FetchException.java        2005-11-11 
21:55:47 UTC (rev 7529)
@@ -96,6 +96,10 @@
                        return "Invalid URI";
                case TOO_BIG:
                        return "Too big";
+               case TOO_BIG_METADATA:
+                       return "Metadata too big";
+               case TOO_MANY_BLOCKS_PER_SEGMENT:
+                       return "Too many blocks per segment";
                default:
                        return "Unknown fetch error code: "+mode;
                }
@@ -147,4 +151,6 @@
        public static final int TOO_BIG = 21;
        /** Metadata too big */
        public static final int TOO_BIG_METADATA = 22;
+       /** Splitfile has too big segments */
+       public static final int TOO_MANY_BLOCKS_PER_SEGMENT = 23;
 }

Modified: trunk/freenet/src/freenet/client/FetcherContext.java
===================================================================
--- trunk/freenet/src/freenet/client/FetcherContext.java        2005-11-11 
18:57:07 UTC (rev 7528)
+++ trunk/freenet/src/freenet/client/FetcherContext.java        2005-11-11 
21:55:47 UTC (rev 7529)
@@ -32,12 +32,16 @@
         * Set by the splitfile metadata and the mask constructor, so we don't 
need to pass it in. */
        final boolean splitfileUseLengths;
        final int maxMetadataSize;
+       final int maxDataBlocksPerSegment;
+       final int maxCheckBlocksPerSegment;

+       
        public FetcherContext(SimpleLowLevelClient client, long curMaxLength, 
                        long curMaxTempLength, int maxMetadataSize, int 
maxRecursionLevel, int maxArchiveRestarts,
                        boolean dontEnterImplicitArchives, int 
maxSplitfileThreads,
                        int maxSplitfileBlockRetries, int 
maxNonSplitfileRetries,
                        boolean allowSplitfiles, boolean followRedirects, 
boolean localRequestOnly,
+                       int maxDataBlocksPerSegment, int 
maxCheckBlocksPerSegment,
                        RandomSource random, ArchiveManager archiveManager, 
BucketFactory bucketFactory,
                        ClientEventProducer producer) {
                this.client = client;
@@ -58,6 +62,8 @@
                this.localRequestOnly = localRequestOnly;
                this.splitfileUseLengths = false;
                this.eventProducer = producer;
+               this.maxDataBlocksPerSegment = maxDataBlocksPerSegment;
+               this.maxCheckBlocksPerSegment = maxCheckBlocksPerSegment;
        }

        public FetcherContext(FetcherContext ctx, int maskID) {
@@ -80,6 +86,8 @@
                        this.localRequestOnly = ctx.localRequestOnly;
                        this.splitfileUseLengths = false;
                        this.eventProducer = ctx.eventProducer;
+                       this.maxDataBlocksPerSegment = 0;
+                       this.maxCheckBlocksPerSegment = 0;
                } else if(maskID == SPLITFILE_DEFAULT_MASK) {
                        this.client = ctx.client;
                        this.maxOutputLength = ctx.maxOutputLength;
@@ -99,6 +107,8 @@
                        this.localRequestOnly = ctx.localRequestOnly;
                        this.splitfileUseLengths = false;
                        this.eventProducer = ctx.eventProducer;
+                       this.maxDataBlocksPerSegment = 
ctx.maxDataBlocksPerSegment;
+                       this.maxCheckBlocksPerSegment = 
ctx.maxCheckBlocksPerSegment;
                } else if(maskID == SPLITFILE_USE_LENGTHS_MASK) {
                        this.client = ctx.client;
                        this.maxOutputLength = ctx.maxOutputLength;
@@ -118,6 +128,8 @@
                        this.localRequestOnly = ctx.localRequestOnly;
                        this.splitfileUseLengths = true;
                        this.eventProducer = ctx.eventProducer;
+                       this.maxDataBlocksPerSegment = 
ctx.maxDataBlocksPerSegment;
+                       this.maxCheckBlocksPerSegment = 
ctx.maxCheckBlocksPerSegment;
                } else throw new IllegalArgumentException();
        }


Modified: trunk/freenet/src/freenet/client/FileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/FileInserter.java  2005-11-11 18:57:07 UTC 
(rev 7528)
+++ trunk/freenet/src/freenet/client/FileInserter.java  2005-11-11 21:55:47 UTC 
(rev 7529)
@@ -33,6 +33,8 @@
         * @throws InserterException 
         */
        public FreenetURI run(InsertBlock block, boolean metadata, boolean 
getCHKOnly) throws InserterException {
+               if(block.data == null)
+                       throw new NullPointerException();
                if(!block.desiredURI.toString(false).equals("CHK@"))
                        throw new 
InserterException(InserterException.INVALID_URI);


Modified: trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
===================================================================
--- trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2005-11-11 18:57:07 UTC (rev 7528)
+++ trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2005-11-11 21:55:47 UTC (rev 7529)
@@ -43,6 +43,12 @@
        static final boolean LOCAL_REQUESTS_ONLY = false;
        static final int SPLITFILE_INSERT_THREADS = 10;
        static final int SPLITFILE_INSERT_RETRIES = 0;
+       // going by memory usage only; 4kB per stripe
+       static final int MAX_SPLITFILE_BLOCKS_PER_SEGMENT = 1024;
+       static final int MAX_SPLITFILE_CHECK_BLOCKS_PER_SEGMENT = 1536;
+       // ~ 70kB/sec encode, 16MB segments
+       static final int SPLITFILE_BLOCKS_PER_SEGMENT = 512;
+       static final int SPLITFILE_CHECK_BLOCKS_PER_SEGMENT = 768;


        public HighLevelSimpleClientImpl(SimpleLowLevelClient client, 
ArchiveManager mgr, BucketFactory bf, RandomSource r) {
@@ -74,13 +80,15 @@
                                MAX_RECURSION, MAX_ARCHIVE_RESTARTS, 
DONT_ENTER_IMPLICIT_ARCHIVES, 
                                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);
                Fetcher f = new Fetcher(uri, context);
                return f.run();
        }

        public FreenetURI insert(InsertBlock insert, boolean getCHKOnly) throws 
InserterException {
-               InserterContext context = new InserterContext(client, 
bucketFactory, random, SPLITFILE_INSERT_RETRIES, SPLITFILE_INSERT_THREADS, 
globalEventProducer);
+               InserterContext context = new InserterContext(client, 
bucketFactory, random, SPLITFILE_INSERT_RETRIES, 
+                               SPLITFILE_INSERT_THREADS, 
SPLITFILE_BLOCKS_PER_SEGMENT, SPLITFILE_CHECK_BLOCKS_PER_SEGMENT, 
globalEventProducer);
                FileInserter i = new FileInserter(context);
                return i.run(insert, false, getCHKOnly);
        }

Modified: trunk/freenet/src/freenet/client/InsertBlock.java
===================================================================
--- trunk/freenet/src/freenet/client/InsertBlock.java   2005-11-11 18:57:07 UTC 
(rev 7528)
+++ trunk/freenet/src/freenet/client/InsertBlock.java   2005-11-11 21:55:47 UTC 
(rev 7529)
@@ -8,7 +8,7 @@
  */
 public class InsertBlock {

-       final Bucket data;
+       Bucket data;
        final FreenetURI desiredURI;
        final ClientMetadata clientMetadata;


Modified: trunk/freenet/src/freenet/client/InserterContext.java
===================================================================
--- trunk/freenet/src/freenet/client/InserterContext.java       2005-11-11 
18:57:07 UTC (rev 7528)
+++ trunk/freenet/src/freenet/client/InserterContext.java       2005-11-11 
21:55:47 UTC (rev 7529)
@@ -16,10 +16,13 @@
        final short splitfileAlgorithm;
        final int maxInsertBlockRetries;
        final int maxSplitInsertThreads;
+       final int splitfileSegmentDataBlocks;
+       final int splitfileSegmentCheckBlocks;
        final ClientEventProducer eventProducer;

        public InserterContext(SimpleLowLevelClient client, BucketFactory bf, 
RandomSource random,
-                       int maxRetries, int maxThreads, ClientEventProducer 
eventProducer) {
+                       int maxRetries, int maxThreads, int 
splitfileSegmentDataBlocks, int splitfileSegmentCheckBlocks,
+                       ClientEventProducer eventProducer) {
                this.client = client;
                this.bf = bf;
                this.random = random;
@@ -28,6 +31,8 @@
                this.maxInsertBlockRetries = maxRetries;
                this.maxSplitInsertThreads = maxThreads;
                this.eventProducer = eventProducer;
+               this.splitfileSegmentDataBlocks = splitfileSegmentDataBlocks;
+               this.splitfileSegmentCheckBlocks = splitfileSegmentCheckBlocks;
        }

 }

Modified: trunk/freenet/src/freenet/client/InserterException.java
===================================================================
--- trunk/freenet/src/freenet/client/InserterException.java     2005-11-11 
18:57:07 UTC (rev 7528)
+++ trunk/freenet/src/freenet/client/InserterException.java     2005-11-11 
21:55:47 UTC (rev 7529)
@@ -19,14 +19,14 @@
        public InserterException(int m, String msg) {
                super(getMessage(m)+": "+msg);
                mode = m;
-               Logger.minor(this, "Creating InserterException: 
"+getMessage(mode)+": "+msg);
+               Logger.minor(this, "Creating InserterException: 
"+getMessage(mode)+": "+msg, this);
                errorCodes = null;
        }

        public InserterException(int m) {
                super(getMessage(m));
                mode = m;
-               Logger.minor(this, "Creating InserterException: 
"+getMessage(mode));
+               Logger.minor(this, "Creating InserterException: 
"+getMessage(mode), this);
                errorCodes = null;
        }

@@ -41,7 +41,7 @@
        public InserterException(int mode, FailureCodeTracker errorCodes) {
                super(getMessage(mode));
                this.mode = mode;
-               Logger.minor(this, "Creating InserterException: 
"+getMessage(mode));
+               Logger.minor(this, "Creating InserterException: 
"+getMessage(mode), this);
                this.errorCodes = errorCodes;
        }


Modified: trunk/freenet/src/freenet/client/Metadata.java
===================================================================
--- trunk/freenet/src/freenet/client/Metadata.java      2005-11-11 18:57:07 UTC 
(rev 7528)
+++ trunk/freenet/src/freenet/client/Metadata.java      2005-11-11 21:55:47 UTC 
(rev 7529)
@@ -13,6 +13,7 @@
 import freenet.keys.ClientKey;
 import freenet.keys.FreenetURI;
 import freenet.support.Bucket;
+import freenet.support.Fields;
 import freenet.support.Logger;


@@ -300,7 +301,7 @@
                        throw new IllegalArgumentException();
        }

-       public Metadata(short algo, FreenetURI[] dataURIs, FreenetURI[] 
checkURIs, ClientMetadata cm, long dataLength, short compressionAlgo) {
+       public Metadata(short algo, FreenetURI[] dataURIs, FreenetURI[] 
checkURIs, int segmentSize, int checkSegmentSize, ClientMetadata cm, long 
dataLength, short compressionAlgo) {
                documentType = SIMPLE_REDIRECT;
                splitfile = true;
                splitfileAlgorithm = algo;
@@ -315,6 +316,7 @@
                        setMIMEType(cm.getMIMEType());
                else
                        setMIMEType(DefaultMIMETypes.DEFAULT_MIME_TYPE);
+               splitfileParams = Fields.intsToBytes(new int[] { segmentSize, 
checkSegmentSize } );
        }

        /**

Modified: trunk/freenet/src/freenet/client/RetryTracker.java
===================================================================
--- trunk/freenet/src/freenet/client/RetryTracker.java  2005-11-11 18:57:07 UTC 
(rev 7528)
+++ trunk/freenet/src/freenet/client/RetryTracker.java  2005-11-11 21:55:47 UTC 
(rev 7529)
@@ -173,7 +173,6 @@
         * we have run out of retries.
         */
        public synchronized void nonfatalError(SplitfileBlock block, int 
reasonCode) {
-               if(killed) return;
                nonfatalErrors.inc(reasonCode);
                runningBlocks.remove(block);
                int levelNumber = block.getRetryCount();
@@ -194,7 +193,6 @@
         * @param reasonCode A client-specific code indicating the type of 
failure.
         */
        public synchronized void fatalError(SplitfileBlock block, int 
reasonCode) {
-               if(killed) return;
                fatalErrors.inc(reasonCode);
                runningBlocks.remove(block);
                failedBlocksFatalErrors.add(block);
@@ -213,6 +211,7 @@
                        Logger.minor(this, "Only block running: 
"+runningBlocks.toArray()[0]);
                if((succeededBlocks.size() >= targetSuccesses)
                                || (runningBlocks.isEmpty() && levels.isEmpty() 
&& finishOnEmpty)) {
+                       killed = true;
                        Logger.minor(this, "Finishing");
                        SplitfileBlock[] running = runningBlocks();
                        for(int i=0;i<running.length;i++) {

Modified: trunk/freenet/src/freenet/client/SplitFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/SplitFetcher.java  2005-11-11 18:57:07 UTC 
(rev 7528)
+++ trunk/freenet/src/freenet/client/SplitFetcher.java  2005-11-11 21:55:47 UTC 
(rev 7529)
@@ -10,6 +10,8 @@
 import freenet.keys.FreenetURI;
 import freenet.keys.NodeCHK;
 import freenet.support.Bucket;
+import freenet.support.Fields;
+import freenet.support.Logger;

 /**
  * Class to fetch a splitfile.
@@ -55,7 +57,7 @@
        /** Accept non-full splitfile chunks? */
        private boolean splitUseLengths;

-       public SplitFetcher(Metadata metadata, ArchiveContext archiveContext, 
FetcherContext ctx, int recursionLevel) throws MetadataParseException {
+       public SplitFetcher(Metadata metadata, ArchiveContext archiveContext, 
FetcherContext ctx, int recursionLevel) throws MetadataParseException, 
FetchException {
                actx = archiveContext;
                fctx = ctx;
                overrideLength = metadata.dataLength;
@@ -71,13 +73,20 @@
                        checkBlocksPerSegment = -1;
                        segmentCount = 1;
                } else if(splitfileType == Metadata.SPLITFILE_ONION_STANDARD) {
-                       blocksPerSegment = 128;
-                       checkBlocksPerSegment = 64;
+                       byte[] params = metadata.splitfileParams;
+                       if(params == null || params.length < 8)
+                               throw new MetadataParseException("No splitfile 
params");
+                       blocksPerSegment = Fields.bytesToInt(params, 0);
+                       checkBlocksPerSegment = Fields.bytesToInt(params, 4);
+                       if(blocksPerSegment > ctx.maxDataBlocksPerSegment
+                                       || checkBlocksPerSegment > 
ctx.maxCheckBlocksPerSegment)
+                               throw new 
FetchException(FetchException.TOO_MANY_BLOCKS_PER_SEGMENT, "Too many blocks per 
segment: "+blocksPerSegment+" data, "+checkBlocksPerSegment+" check");
                        segmentCount = (splitfileDataBlocks.length / 
blocksPerSegment) +
                                (splitfileDataBlocks.length % blocksPerSegment 
== 0 ? 0 : 1);
                        // Onion, 128/192.
                        // Will be segmented.
                } else throw new MetadataParseException("Unknown splitfile 
format: "+splitfileType);
+               Logger.minor(this, "Algorithm: "+splitfileType+", blocks per 
segment: "+blocksPerSegment+", check blocks per segment: 
"+checkBlocksPerSegment+", segments: "+segmentCount);
                segments = new Segment[segmentCount]; // initially null on all 
entries
                if(segmentCount == 1) {
                        segments[0] = new Segment(splitfileType, 
splitfileDataBlocks, splitfileCheckBlocks, this, archiveContext, ctx, 
maxTempLength, splitUseLengths, recursionLevel+1);
@@ -102,6 +111,7 @@
                unstartedSegments = new Vector();
                for(int i=0;i<segments.length;i++)
                        unstartedSegments.add(segments[i]);
+               Logger.minor(this, "Segments: "+unstartedSegments.size());
        }

        /**
@@ -151,8 +161,8 @@
                synchronized(unstartedSegments) {
                        if(unstartedSegments.isEmpty()) return null;
                        int x = fctx.random.nextInt(unstartedSegments.size());
-                       Segment s = (Segment) unstartedSegments.get(x);
-                       unstartedSegments.remove(x);
+                       Logger.minor(this, "Starting segment "+x+" of 
"+unstartedSegments.size());
+                       Segment s = (Segment) unstartedSegments.remove(x);
                        return s;
                }
        }

Modified: trunk/freenet/src/freenet/client/SplitInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/SplitInserter.java 2005-11-11 18:57:07 UTC 
(rev 7528)
+++ trunk/freenet/src/freenet/client/SplitInserter.java 2005-11-11 21:55:47 UTC 
(rev 7529)
@@ -49,8 +49,8 @@
                this.splitfileAlgorithm = splitfileAlgorithm;
                this.ctx = ctx;
                this.dataLength = data.size();
-               segmentSize = 
FECCodec.getCodecMaxSegmentDataBlocks(splitfileAlgorithm);
-               checkSegmentSize = 
FECCodec.getCodecMaxSegmentCheckBlocks(splitfileAlgorithm);
+               segmentSize = ctx.splitfileSegmentDataBlocks;
+               checkSegmentSize = splitfileAlgorithm == 
Metadata.SPLITFILE_NONREDUNDANT ? 0 : ctx.splitfileSegmentCheckBlocks;
                tracker = new RetryTracker(ctx.maxInsertBlockRetries, 
Integer.MAX_VALUE, ctx.random, ctx.maxSplitInsertThreads, true, this);
                try {
                        splitIntoBlocks();
@@ -83,6 +83,7 @@
                } catch (Throwable t) {
                        Logger.error(this, "Caught "+t, t);
                        tracker.kill();
+                       if(t instanceof InserterException) throw 
(InserterException)t;
                        throw new 
InserterException(InserterException.INTERNAL_ERROR, t.toString());
                }
        }
@@ -113,7 +114,7 @@

                if(!missingURIs) {

-                       Metadata metadata = new Metadata(splitfileAlgorithm, 
dataURIs, checkURIs, clientMetadata, dataLength, compressionCodec);
+                       Metadata metadata = new Metadata(splitfileAlgorithm, 
dataURIs, checkURIs, segmentSize, checkSegmentSize, clientMetadata, dataLength, 
compressionCodec);

                        Bucket mbucket;
                        try {

Modified: trunk/freenet/src/freenet/client/StandardOnionFECCodec.java
===================================================================
--- trunk/freenet/src/freenet/client/StandardOnionFECCodec.java 2005-11-11 
18:57:07 UTC (rev 7528)
+++ trunk/freenet/src/freenet/client/StandardOnionFECCodec.java 2005-11-11 
21:55:47 UTC (rev 7529)
@@ -108,94 +108,103 @@
        }

        public void realDecode(SplitfileBlock[] dataBlockStatus, 
SplitfileBlock[] checkBlockStatus, int blockLength, BucketFactory bf) throws 
IOException {
-               Logger.minor(this, "Doing decode: "+dataBlockStatus.length+" 
data blocks, "+checkBlockStatus.length+" check blocks, block length 
"+blockLength+" with "+this);
+               Logger.minor(this, "Doing decode: "+dataBlockStatus.length+" 
data blocks, "+checkBlockStatus.length+" check blocks, block length 
"+blockLength+" with "+this, new Exception("debug"));
                if(dataBlockStatus.length + checkBlockStatus.length != n)
                        throw new IllegalArgumentException();
                if(dataBlockStatus.length != k)
                        throw new IllegalArgumentException();
                Buffer[] packets = new Buffer[k];
                Bucket[] buckets = new Bucket[n];
-               DataInputStream[] readers = new DataInputStream[k];
+               DataInputStream[] readers = new DataInputStream[n];
                OutputStream[] writers = new OutputStream[k];
-               int[] toDecode = new int[n-k];
                int numberToDecode = 0; // can be less than n-k

-               byte[] realBuffer = new byte[n * STRIPE_SIZE];
+               byte[] realBuffer = new byte[k * STRIPE_SIZE];

-               for(int i=0;i<n;i++)
+               int[] packetIndexes = new int[k];
+               for(int i=0;i<packetIndexes.length;i++)
+                       packetIndexes[i] = -1;
+
+               int idx = 0;
+               
+               for(int i=0;i<k;i++)
                        packets[i] = new Buffer(realBuffer, i*STRIPE_SIZE, 
STRIPE_SIZE);

                for(int i=0;i<dataBlockStatus.length;i++) {
                        buckets[i] = dataBlockStatus[i].getData();
-                       long sz = buckets[i].size();
-                       if(sz < blockLength) {
-                               if(i != dataBlockStatus.length-1)
-                                       throw new IllegalArgumentException("All 
buckets except the last must be the full size");
-                               if(sz < blockLength)
-                                       buckets[i] = pad(buckets[i], 
blockLength, bf, (int) sz);
-                               else throw new IllegalArgumentException("Too 
big: "+sz+" bigger than "+blockLength);
-                       }
                        if(buckets[i] == null) {
                                buckets[i] = bf.makeBucket(blockLength);
                                writers[i] = buckets[i].getOutputStream();
+                               Logger.minor(this, "writers["+i+"] != null");
                                readers[i] = null;
-                               toDecode[numberToDecode++] = i;
+                               numberToDecode++;
                        } else {
+                               long sz = buckets[i].size();
+                               if(sz < blockLength) {
+                                       if(i != dataBlockStatus.length-1)
+                                               throw new 
IllegalArgumentException("All buckets except the last must be the full size but 
data bucket "+i+" of "+dataBlockStatus.length+" ("+dataBlockStatus[i]+") is 
"+sz+" not "+blockLength);
+                                       if(sz < blockLength)
+                                               buckets[i] = pad(buckets[i], 
blockLength, bf, (int) sz);
+                                       else throw new 
IllegalArgumentException("Too big: "+sz+" bigger than "+blockLength);
+                               }
+                               Logger.minor(this, "writers["+i+"] = null 
(already filled)");
                                writers[i] = null;
                                readers[i] = new 
DataInputStream(buckets[i].getInputStream());
+                               packetIndexes[idx++] = i;
                        }
                }
                for(int i=0;i<checkBlockStatus.length;i++) {
                        buckets[i+k] = checkBlockStatus[i].getData();
                        if(buckets[i+k] == null) {
-                               buckets[i+k] = bf.makeBucket(blockLength);
-                               writers[i+k] = buckets[i+k].getOutputStream();
                                readers[i+k] = null;
-                               toDecode[numberToDecode++] = i+k;
                        } else {
-                               writers[i+k] = null;
                                readers[i+k] = new 
DataInputStream(buckets[i+k].getInputStream());
+                               if(idx < k)
+                                       packetIndexes[idx++] = i+k;
                        }
                }

-               if(numberToDecode != toDecode.length) {
-                       int[] newToDecode = new int[numberToDecode];
-                       System.arraycopy(toDecode, 0, newToDecode, 0, 
numberToDecode);
-                       toDecode = newToDecode;
-               }
-
+               if(idx < k)
+                       throw new IllegalArgumentException("Must have at least 
k packets");
+               
+               for(int i=0;i<packetIndexes.length;i++)
+                       Logger.minor(this, "["+i+"] = "+packetIndexes[i]);
+               
                if(numberToDecode > 0) {
                        // Do the (striped) decode
                        for(int 
offset=0;offset<blockLength;offset+=STRIPE_SIZE) {
                                // Read the data in first
-                               for(int i=0;i<n;i++) {
-                                       if(readers[i] != null) {
-                                               
readers[i].readFully(realBuffer, i*STRIPE_SIZE, STRIPE_SIZE);
-                                       }
+                               for(int i=0;i<k;i++) {
+                                       int x = packetIndexes[i];
+                                       readers[x].readFully(realBuffer, 
i*STRIPE_SIZE, STRIPE_SIZE);
                                }
                                // Do the decode
                                // Not shuffled
-                               code.decode(packets, toDecode);
+                               int[] disposableIndexes = new 
int[packetIndexes.length];
+                               System.arraycopy(packetIndexes, 0, 
disposableIndexes, 0, packetIndexes.length);
+                               code.decode(packets, disposableIndexes);
                                // packets now contains an array of decoded 
blocks, in order
                                // Write the data out
-                               for(int i=0;i<n;i++) {
+                               for(int i=0;i<k;i++) {
                                        if(writers[i] != null)
                                                writers[i].write(realBuffer, 
i*STRIPE_SIZE, STRIPE_SIZE);
                                }
                        }
                }
+               for(int i=0;i<k;i++) {
+                       if(writers[i] != null) writers[i].close();
+               }
                for(int i=0;i<n;i++) {
-                       if(writers[i] != null) writers[i].close();
                        if(readers[i] != null) readers[i].close();
                }
                // Set new buckets only after have a successful decode.
                // Note that the last data bucket will be overwritten padded.
                for(int i=0;i<dataBlockStatus.length;i++) {
-                       dataBlockStatus[i].setData(buckets[i]);
+                       Bucket data = buckets[i];
+                       if(data.size() != blockLength)
+                               throw new IllegalStateException("Block "+i+": 
"+data+" : "+dataBlockStatus[i]+" length "+data.size());
+                       dataBlockStatus[i].setData(data);
                }
-               for(int i=0;i<checkBlockStatus.length;i++) {
-                       checkBlockStatus[i].setData(buckets[i+k]);
-               }
        }

        public void encode(SplitfileBlock[] dataBlockStatus, SplitfileBlock[] 
checkBlockStatus, int blockLength, BucketFactory bf) throws IOException {
@@ -226,7 +235,7 @@
         * Do the actual encode.
         */
        private void realEncode(SplitfileBlock[] dataBlockStatus, 
SplitfileBlock[] checkBlockStatus, int blockLength, BucketFactory bf) throws 
IOException {
-               System.err.println("************* Encoding 
"+dataBlockStatus.length+" -> "+checkBlockStatus.length+"... *************");
+               System.err.println("************* Encoding 
"+dataBlockStatus.length+" -> "+checkBlockStatus.length+" *************");
                Logger.minor(this, "Doing encode: "+dataBlockStatus.length+" 
data blocks, "+checkBlockStatus.length+" check blocks, block length 
"+blockLength+" with "+this);
                if(dataBlockStatus.length + checkBlockStatus.length != n)
                        throw new IllegalArgumentException();
@@ -298,9 +307,11 @@
                        if(writers[i] != null) writers[i].close();
                // Set new buckets only after have a successful decode.
                for(int i=0;i<checkBlockStatus.length;i++) {
-                       checkBlockStatus[i].setData(buckets[i+k]);
+                       Bucket data = buckets[i+k];
+                       if(data == null) throw new NullPointerException();
+                       checkBlockStatus[i].setData(data);
                }
-               System.err.println("************* Encoded 
"+dataBlockStatus.length+" -> "+checkBlockStatus.length+"... *************");
+               System.err.println("************* Encoded 
"+dataBlockStatus.length+" -> "+checkBlockStatus.length+" *************");
        }

        private Bucket pad(Bucket oldData, int blockLength, BucketFactory bf, 
int l) throws IOException {

Modified: trunk/freenet/src/freenet/client/StdSplitfileBlock.java
===================================================================
--- trunk/freenet/src/freenet/client/StdSplitfileBlock.java     2005-11-11 
18:57:07 UTC (rev 7528)
+++ trunk/freenet/src/freenet/client/StdSplitfileBlock.java     2005-11-11 
21:55:47 UTC (rev 7529)
@@ -31,6 +31,7 @@

        public void setData(Bucket data) {
                fetchedData = data;
+               Logger.minor(this, "Set data: "+(data == null ? "(null)" : 
(""+data.size())+ " on "+this), new Exception("debug"));
        }

        public void start() {

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2005-11-11 18:57:07 UTC (rev 
7528)
+++ trunk/freenet/src/freenet/node/Version.java 2005-11-11 21:55:47 UTC (rev 
7529)
@@ -20,10 +20,10 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       public static final int buildNumber = 164;
+       public static final int buildNumber = 166;

        /** Oldest build of Fred we will talk to */
-       public static final int lastGoodBuild = 164;
+       public static final int lastGoodBuild = 166;

        /** The highest reported build of fred */
        public static int highestSeenBuild = buildNumber;

Modified: trunk/freenet/src/freenet/support/Fields.java
===================================================================
--- trunk/freenet/src/freenet/support/Fields.java       2005-11-11 18:57:07 UTC 
(rev 7528)
+++ trunk/freenet/src/freenet/support/Fields.java       2005-11-11 21:55:47 UTC 
(rev 7529)
@@ -510,4 +510,16 @@
         return buf;
     }

+       public static byte[] intsToBytes(int[] ints) {
+        byte[] buf = new byte[ints.length * 8];
+        for(int i=0;i<ints.length;i++) {
+            long x = ints[i];
+            for(int j=0;j<4;j++) {
+                buf[i*4+j] = (byte)x;
+                x >>= 8;
+            }
+        }
+        return buf;
+       }
+
 }


Reply via email to