Author: toad
Date: 2006-09-29 16:42:10 +0000 (Fri, 29 Sep 2006)
New Revision: 10570

Added:
   trunk/freenet/src/freenet/client/async/BackgroundBlockEncoder.java
Modified:
   trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
   trunk/freenet/src/freenet/client/InserterContext.java
   trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
   trunk/freenet/src/freenet/client/async/SingleFileInserter.java
   trunk/freenet/src/freenet/client/async/SplitFileInserter.java
   trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java
   trunk/freenet/src/freenet/node/NodeClientCore.java
Log:
Once we pass the two thirds of an insert needed to fetch it, encode all its 
remaining blocks in the background, so that we can make the metadata ASAP (and 
then the URI for the metadata, and insert it)

Modified: trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
===================================================================
--- trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2006-09-29 16:15:28 UTC (rev 10569)
+++ trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2006-09-29 16:42:10 UTC (rev 10570)
@@ -6,6 +6,7 @@
 import java.io.IOException;
 import java.util.HashMap;

+import freenet.client.async.BackgroundBlockEncoder;
 import freenet.client.async.ClientGetter;
 import freenet.client.async.ClientPutter;
 import freenet.client.async.HealingQueue;
@@ -32,6 +33,7 @@
        private final BucketFactory persistentBucketFactory;
        private final PersistentFileTracker persistentFileTracker;
        private final NodeClientCore core;
+       private final BackgroundBlockEncoder blockEncoder;
        /** One CEP for all requests and inserts */
        private final ClientEventProducer globalEventProducer;
        private long curMaxLength;
@@ -89,6 +91,7 @@
                this.cacheLocalRequests = cacheLocalRequests;
                this.persistentBucketFactory = 
node.persistentEncryptedTempBucketFactory;
                this.healingQueue = node.getHealingQueue();
+               this.blockEncoder = node.backgroundBlockEncoder;
        }

        public void setMaxLength(long maxLength) {
@@ -188,6 +191,6 @@
                                forceNonPersistent ? new 
NullPersistentFileTracker() : persistentFileTracker,
                                random, INSERT_RETRIES, 
CONSECUTIVE_RNFS_ASSUME_SUCCESS,
                                SPLITFILE_INSERT_THREADS, 
SPLITFILE_BLOCKS_PER_SEGMENT, SPLITFILE_CHECK_BLOCKS_PER_SEGMENT, 
-                               globalEventProducer, cacheLocalRequests, 
core.uskManager);
+                               globalEventProducer, cacheLocalRequests, 
core.uskManager, blockEncoder);
        }
 }

Modified: trunk/freenet/src/freenet/client/InserterContext.java
===================================================================
--- trunk/freenet/src/freenet/client/InserterContext.java       2006-09-29 
16:15:28 UTC (rev 10569)
+++ trunk/freenet/src/freenet/client/InserterContext.java       2006-09-29 
16:42:10 UTC (rev 10570)
@@ -1,5 +1,6 @@
 package freenet.client;

+import freenet.client.async.BackgroundBlockEncoder;
 import freenet.client.async.USKManager;
 import freenet.client.events.ClientEventProducer;
 import freenet.client.events.SimpleEventProducer;
@@ -27,10 +28,11 @@
        /** Interesting tradeoff, see comments at top of Node.java. */
        public final boolean cacheLocalRequests;
        public final USKManager uskManager;
+       public final BackgroundBlockEncoder backgroundBlockEncoder;

        public InserterContext(BucketFactory bf, BucketFactory persistentBF, 
PersistentFileTracker tracker, RandomSource random,
                        int maxRetries, int rnfsToSuccess, int maxThreads, int 
splitfileSegmentDataBlocks, int splitfileSegmentCheckBlocks,
-                       ClientEventProducer eventProducer, boolean 
cacheLocalRequests, USKManager uskManager) {
+                       ClientEventProducer eventProducer, boolean 
cacheLocalRequests, USKManager uskManager, BackgroundBlockEncoder blockEncoder) 
{
                this.bf = bf;
                this.persistentFileTracker = tracker;
                this.persistentBucketFactory = persistentBF;
@@ -45,6 +47,7 @@
                this.splitfileSegmentDataBlocks = splitfileSegmentDataBlocks;
                this.splitfileSegmentCheckBlocks = splitfileSegmentCheckBlocks;
                this.cacheLocalRequests = cacheLocalRequests;
+               this.backgroundBlockEncoder = blockEncoder;
        }

        public InserterContext(InserterContext ctx, SimpleEventProducer 
producer, boolean forceNonPersistent) {
@@ -62,6 +65,7 @@
                this.splitfileSegmentDataBlocks = 
ctx.splitfileSegmentDataBlocks;
                this.splitfileSegmentCheckBlocks = 
ctx.splitfileSegmentCheckBlocks;
                this.cacheLocalRequests = ctx.cacheLocalRequests;
+               this.backgroundBlockEncoder = ctx.backgroundBlockEncoder;
        }

        public InserterContext(InserterContext ctx, SimpleEventProducer 
producer) {
@@ -79,6 +83,7 @@
                this.splitfileSegmentDataBlocks = 
ctx.splitfileSegmentDataBlocks;
                this.splitfileSegmentCheckBlocks = 
ctx.splitfileSegmentCheckBlocks;
                this.cacheLocalRequests = ctx.cacheLocalRequests;
+               this.backgroundBlockEncoder = ctx.backgroundBlockEncoder;
        }

 }

Added: trunk/freenet/src/freenet/client/async/BackgroundBlockEncoder.java
===================================================================
--- trunk/freenet/src/freenet/client/async/BackgroundBlockEncoder.java  
2006-09-29 16:15:28 UTC (rev 10569)
+++ trunk/freenet/src/freenet/client/async/BackgroundBlockEncoder.java  
2006-09-29 16:42:10 UTC (rev 10570)
@@ -0,0 +1,63 @@
+package freenet.client.async;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+/**
+ * Keeps a queue of SingleBlockInserter's to encode.
+ * Encodes them.
+ */
+public class BackgroundBlockEncoder implements Runnable {
+
+       // Minimize memory usage at the cost of having to encode from the end
+       private final ArrayList queue;
+       
+       public BackgroundBlockEncoder() {
+               queue = new ArrayList();
+       }
+       
+       public void queue(SingleBlockInserter sbi) {
+               if(sbi.isFinished()) return;
+               if(sbi.resultingURI != null) return;
+               WeakReference ref = new WeakReference(sbi);
+               synchronized(this) {
+                       queue.add(ref);
+                       notifyAll();
+               }
+       }
+       
+       public void queue(SingleBlockInserter[] sbis) {
+               synchronized(this) {
+                       for(int i=0;i<sbis.length;i++) {
+                               if(sbis[i].isFinished()) continue;
+                               if(sbis[i].resultingURI != null) continue;
+                               WeakReference ref = new WeakReference(sbis[i]);
+                               queue.add(ref);
+                       }
+                       notifyAll();
+               }
+       }
+       
+       public void run() {
+               while(true) {
+                       SingleBlockInserter sbi = null;
+                       synchronized(this) {
+                               try {
+                                       wait(100*1000);
+                               } catch (InterruptedException e) {
+                                       // Ignore
+                               }
+                               while(true) {
+                                       if(queue.isEmpty()) break;
+                                       WeakReference ref = (WeakReference) 
queue.remove(queue.size()-1);
+                                       sbi = (SingleBlockInserter) ref.get();
+                                       if(sbi == null) continue;
+                               }
+                       }
+                       if(sbi.isFinished()) continue;
+                       if(sbi.resultingURI != null) continue;
+                       sbi.tryEncode();
+               }
+       }
+
+}

Modified: trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleBlockInserter.java     
2006-09-29 16:15:28 UTC (rev 10569)
+++ trunk/freenet/src/freenet/client/async/SingleBlockInserter.java     
2006-09-29 16:42:10 UTC (rev 10570)
@@ -306,4 +306,17 @@
                return null;
        }

+       /** Attempt to encode the block, if necessary */
+       public void tryEncode() {
+               try {
+                       encode();
+               } catch (InserterException e) {
+                       fail(e);
+               } catch (Throwable t) {
+                       Logger.error(this, "Caught "+t, t);
+                       // Don't requeue on BackgroundBlockEncoder.
+                       // Not necessary to do so (we'll ask again when we need 
it), and it'll probably just break again.
+               }
+       }
+
 }

Modified: trunk/freenet/src/freenet/client/async/SingleFileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileInserter.java      
2006-09-29 16:15:28 UTC (rev 10569)
+++ trunk/freenet/src/freenet/client/async/SingleFileInserter.java      
2006-09-29 16:42:10 UTC (rev 10570)
@@ -584,16 +584,22 @@
                private void startMetadata() {
                        try {
                                ClientPutState putter;
+                               ClientPutState splitInserter;
                                synchronized(this) {
                                        if(metadataPutter == null) {
                                                if(logMINOR) Logger.minor(this, 
"Cannot start metadata yet: no metadataPutter");
-                                               return;
                                        }
                                        putter = metadataPutter;
+                                       splitInserter = sfi;
                                }
-                               if(logMINOR) Logger.minor(this, "Starting 
metadata inserter: "+putter+" for "+this);
-                               putter.schedule();
-                               if(logMINOR) Logger.minor(this, "Started 
metadata inserter: "+putter+" for "+this);
+                               if(putter != null) {
+                                       if(logMINOR) Logger.minor(this, 
"Starting metadata inserter: "+putter+" for "+this);
+                                       putter.schedule();
+                                       if(logMINOR) Logger.minor(this, 
"Started metadata inserter: "+putter+" for "+this);
+                               } else {
+                                       // Get all the URIs ASAP so we can 
start to insert the metadata.
+                                       
((SplitFileInserter)splitInserter).forceEncode();
+                               }
                        } catch (InserterException e1) {
                                Logger.error(this, "Failing "+this+" : "+e1, 
e1);
                                fail(e1);

Modified: trunk/freenet/src/freenet/client/async/SplitFileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileInserter.java       
2006-09-29 16:15:28 UTC (rev 10569)
+++ trunk/freenet/src/freenet/client/async/SplitFileInserter.java       
2006-09-29 16:42:10 UTC (rev 10570)
@@ -436,4 +436,11 @@
                return dataLength;
        }

+       /** Force the remaining blocks which haven't been encoded so far to be 
encoded ASAP. */
+       public void forceEncode() {
+               for(int i=0;i<segments.length;i++) {
+                       segments[i].forceEncode();
+               }
+       }
+
 }

Modified: trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java        
2006-09-29 16:15:28 UTC (rev 10569)
+++ trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java        
2006-09-29 16:42:10 UTC (rev 10570)
@@ -616,4 +616,10 @@
        public void onFetchable(ClientPutState state) {
                // Ignore
        }
+
+       /** Force the remaining blocks which haven't been encoded so far to be 
encoded ASAP. */
+       public void forceEncode() {
+               // TODO Auto-generated method stub
+               
+       }
 }

Modified: trunk/freenet/src/freenet/node/NodeClientCore.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeClientCore.java  2006-09-29 16:15:28 UTC 
(rev 10569)
+++ trunk/freenet/src/freenet/node/NodeClientCore.java  2006-09-29 16:42:10 UTC 
(rev 10570)
@@ -7,6 +7,7 @@
 import freenet.client.HighLevelSimpleClient;
 import freenet.client.HighLevelSimpleClientImpl;
 import freenet.client.InserterContext;
+import freenet.client.async.BackgroundBlockEncoder;
 import freenet.client.async.HealingQueue;
 import freenet.client.async.SimpleHealingQueue;
 import freenet.client.async.USKManager;
@@ -79,6 +80,7 @@
        SimpleToadletServer toadletContainer;
        // FIXME why isn't this just in fproxy?
        public BookmarkManager bookmarkManager;
+       public final BackgroundBlockEncoder backgroundBlockEncoder;

        // Client stuff that needs to be configged - FIXME
        static final int MAX_ARCHIVE_HANDLERS = 200; // don't take up much 
RAM... FIXME
@@ -90,6 +92,10 @@
        NodeClientCore(Node node, Config config, SubConfig nodeConfig, File 
nodeDir, int portNumber, int sortOrder, SimpleFieldSet throttleFS) throws 
NodeInitException {
                this.node = node;
                this.random = node.random;
+               this.backgroundBlockEncoder = new BackgroundBlockEncoder();
+               Thread t = new Thread(backgroundBlockEncoder, "Background block 
encoder");
+               t.setDaemon(true);
+               t.start();
                byte[] pwdBuf = new byte[16];
                random.nextBytes(pwdBuf);
                this.formPassword = Base64.encode(pwdBuf);
@@ -183,7 +189,7 @@
                healingQueue = new 
SimpleHealingQueue(requestStarters.chkPutScheduler,
                                new InserterContext(tempBucketFactory, 
tempBucketFactory, persistentTempBucketFactory, 
                                                random, 0, 2, 1, 0, 0, new 
SimpleEventProducer(), 
-                                               
!Node.DONT_CACHE_LOCAL_REQUESTS, uskManager), 
RequestStarter.PREFETCH_PRIORITY_CLASS, 512 /* FIXME make configurable */);
+                                               
!Node.DONT_CACHE_LOCAL_REQUESTS, uskManager, backgroundBlockEncoder), 
RequestStarter.PREFETCH_PRIORITY_CLASS, 512 /* FIXME make configurable */);

        }



Reply via email to