Author: toad
Date: 2007-02-16 20:59:34 +0000 (Fri, 16 Feb 2007)
New Revision: 11823

Modified:
   trunk/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
   trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
   trunk/freenet/src/freenet/client/async/SimpleSingleFileFetcher.java
   trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
   trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
   trunk/freenet/src/freenet/client/async/USKChecker.java
   trunk/freenet/src/freenet/node/SendableGet.java
   trunk/freenet/src/freenet/node/SendableRequest.java
   trunk/freenet/src/freenet/node/SimpleSendableInsert.java
Log:
Infrastructure for multiple requests per registered SendableGet.

Modified: trunk/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/BaseSingleFileFetcher.java   
2007-02-16 20:26:10 UTC (rev 11822)
+++ trunk/freenet/src/freenet/client/async/BaseSingleFileFetcher.java   
2007-02-16 20:59:34 UTC (rev 11823)
@@ -5,6 +5,7 @@

 import freenet.client.FetchContext;
 import freenet.keys.ClientKey;
+import freenet.keys.ClientSSK;
 import freenet.node.SendableGet;
 import freenet.support.Logger;

@@ -15,6 +16,7 @@
        final int maxRetries;
        private int retryCount;
        final FetchContext ctx;
+       static final int[] keys = new int[] { 0 };

        BaseSingleFileFetcher(ClientKey key, int maxRetries, FetchContext ctx, 
ClientRequester parent) {
                super(parent);
@@ -23,8 +25,16 @@
                this.key = key;
                this.ctx = ctx;
        }
+
+       public int[] allKeys() {
+               return keys;
+       }

-       public ClientKey getKey() {
+       public int chooseKey() {
+               return 0;
+       }
+       
+       public ClientKey getKey(int token) {
                return key;
        }

@@ -32,6 +42,10 @@
                return ctx;
        }

+       public boolean isSSK() {
+               return key instanceof ClientSSK;
+       }
+
        /** Try again - returns true if we can retry */
        protected boolean retry() {
                retryCount++;

Modified: trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2007-02-16 20:26:10 UTC (rev 11822)
+++ trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2007-02-16 20:59:34 UTC (rev 11823)
@@ -168,22 +168,26 @@
                if(req instanceof SendableGet) {
                        SendableGet getter = (SendableGet)req;
                        if(!getter.ignoreStore()) {
-                               ClientKeyBlock block;
-                               try {
-                                       block = node.fetchKey(getter.getKey(), 
getter.dontCache());
-                               } catch (KeyVerifyException e) {
-                                       // Verify exception, probably bogus at 
source;
-                                       // verifies at low-level, but not at 
decode.
-                                       if(logMINOR)
-                                               Logger.minor(this, "Decode 
failed: "+e, e);
-                                       getter.onFailure(new 
LowLevelGetException(LowLevelGetException.DECODE_FAILED));
-                                       return;
+                               int[] keyTokens = getter.allKeys();
+                               for(int i=0;i<keyTokens.length;i++) {
+                                       int tok = keyTokens[i];
+                                       ClientKeyBlock block;
+                                       try {
+                                               block = 
node.fetchKey(getter.getKey(tok), getter.dontCache());
+                                       } catch (KeyVerifyException e) {
+                                               // Verify exception, probably 
bogus at source;
+                                               // verifies at low-level, but 
not at decode.
+                                               if(logMINOR)
+                                                       Logger.minor(this, 
"Decode failed: "+e, e);
+                                               getter.onFailure(new 
LowLevelGetException(LowLevelGetException.DECODE_FAILED), tok);
+                                               return;
+                                       }
+                                       if(block != null) {
+                                               if(logMINOR) Logger.minor(this, 
"Can fulfill "+req+" immediately from store");
+                                               getter.onSuccess(block, true, 
tok);
+                                               return;
+                                       }
                                }
-                               if(block != null) {
-                                       if(logMINOR) Logger.minor(this, "Can 
fulfill "+req+" immediately from store");
-                                       getter.onSuccess(block, true);
-                                       return;
-                               }
                        }
                }
                innerRegister(req);

Modified: trunk/freenet/src/freenet/client/async/SimpleSingleFileFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SimpleSingleFileFetcher.java 
2007-02-16 20:26:10 UTC (rev 11822)
+++ trunk/freenet/src/freenet/client/async/SimpleSingleFileFetcher.java 
2007-02-16 20:59:34 UTC (rev 11823)
@@ -6,9 +6,9 @@
 import java.io.IOException;

 import freenet.client.ClientMetadata;
+import freenet.client.FetchContext;
 import freenet.client.FetchException;
 import freenet.client.FetchResult;
-import freenet.client.FetchContext;
 import freenet.keys.ClientKey;
 import freenet.keys.ClientKeyBlock;
 import freenet.keys.KeyDecodeException;
@@ -36,7 +36,7 @@
        final long token;

        // Translate it, then call the real onFailure
-       public void onFailure(LowLevelGetException e) {
+       public void onFailure(LowLevelGetException e, int reqTokenIgnored) {
                switch(e.code) {
                case LowLevelGetException.DATA_NOT_FOUND:
                        onFailure(new 
FetchException(FetchException.DATA_NOT_FOUND));
@@ -105,7 +105,7 @@
                rcb.onSuccess(data, this);
        }

-       public void onSuccess(ClientKeyBlock block, boolean fromStore) {
+       public void onSuccess(ClientKeyBlock block, boolean fromStore, int 
reqTokenIgnored) {
                Bucket data = extract(block);
                if(data == null) return; // failed
                if(!block.isMetadata()) {

Modified: trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleBlockInserter.java     
2007-02-16 20:26:10 UTC (rev 11822)
+++ trunk/freenet/src/freenet/client/async/SingleBlockInserter.java     
2007-02-16 20:59:34 UTC (rev 11823)
@@ -283,21 +283,24 @@
                return finished;
        }

-       public void send(NodeClientCore core) {
+       public boolean send(NodeClientCore core) {
                try {
                        if(logMINOR) Logger.minor(this, "Starting request: 
"+this);
                        ClientKeyBlock b = getBlock();
                        if(b != null)
                                core.realPut(b, ctx.cacheLocalRequests);
-                       else
+                       else {
                                fail(new 
InserterException(InserterException.CANCELLED));
+                               return false;
+                       }
                } catch (LowLevelPutException e) {
                        onFailure(e);
                        if(logMINOR) Logger.minor(this, "Request failed: 
"+this+" for "+e);
-                       return;
+                       return true;
                }
                if(logMINOR) Logger.minor(this, "Request succeeded: "+this);
                onSuccess();
+               return true;
        }

        public Object getClient() {

Modified: trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileFetcher.java       
2007-02-16 20:26:10 UTC (rev 11822)
+++ trunk/freenet/src/freenet/client/async/SingleFileFetcher.java       
2007-02-16 20:59:34 UTC (rev 11823)
@@ -113,7 +113,7 @@

        // Process the completed data. May result in us going to a
        // splitfile, or another SingleFileFetcher, etc.
-       public void onSuccess(ClientKeyBlock block, boolean fromStore) {
+       public void onSuccess(ClientKeyBlock block, boolean fromStore, int 
token) {
                parent.completedBlock(fromStore);
                // Extract data
                Bucket data = extract(block);

Modified: trunk/freenet/src/freenet/client/async/USKChecker.java
===================================================================
--- trunk/freenet/src/freenet/client/async/USKChecker.java      2007-02-16 
20:26:10 UTC (rev 11822)
+++ trunk/freenet/src/freenet/client/async/USKChecker.java      2007-02-16 
20:59:34 UTC (rev 11823)
@@ -25,11 +25,11 @@
                this.cb = cb;
        }

-       public void onSuccess(ClientKeyBlock block, boolean fromStore) {
+       public void onSuccess(ClientKeyBlock block, boolean fromStore, int 
token) {
                cb.onSuccess((ClientSSKBlock)block);
        }

-       public void onFailure(LowLevelGetException e) {
+       public void onFailure(LowLevelGetException e, int token) {
         if(Logger.shouldLog(Logger.MINOR, this))
                Logger.minor(this, "onFailure: "+e+" for "+this);
                // Firstly, can we retry?

Modified: trunk/freenet/src/freenet/node/SendableGet.java
===================================================================
--- trunk/freenet/src/freenet/node/SendableGet.java     2007-02-16 20:26:10 UTC 
(rev 11822)
+++ trunk/freenet/src/freenet/node/SendableGet.java     2007-02-16 20:59:34 UTC 
(rev 11823)
@@ -5,10 +5,8 @@

 import freenet.client.FetchContext;
 import freenet.client.async.ClientRequester;
-import freenet.keys.ClientCHK;
 import freenet.keys.ClientKey;
 import freenet.keys.ClientKeyBlock;
-import freenet.keys.ClientSSK;
 import freenet.support.Logger;

 /**
@@ -16,20 +14,30 @@
  */
 public abstract class SendableGet implements SendableRequest {

+       /** Is this an SSK? */
+       public abstract boolean isSSK();
+       
        /** Parent BaseClientGetter. Required for schedulers. */
        public final ClientRequester parent;

-       /** Get the key to fetch (this time!). */
-       public abstract ClientKey getKey();
+       /** Choose a key to fetch.
+        * @return An integer identifying a specific key. -1 indicates no keys 
available. */
+       public abstract int chooseKey();

+       /** All key identifiers */
+       public abstract int[] allKeys();
+       
+       /** Get a numbered key to fetch. */
+       public abstract ClientKey getKey(int token);
+       
        /** Get the fetch context (settings) object. */
        public abstract FetchContext getContext();

        /** Called when/if the low-level request succeeds. */
-       public abstract void onSuccess(ClientKeyBlock block, boolean fromStore);
+       public abstract void onSuccess(ClientKeyBlock block, boolean fromStore, 
int token);

        /** Called when/if the low-level request fails. */
-       public abstract void onFailure(LowLevelGetException e);
+       public abstract void onFailure(LowLevelGetException e, int token);

        /** Should the request ignore the datastore? */
        public abstract boolean ignoreStore();
@@ -43,40 +51,46 @@
                this.parent = parent;
        }

-       /** Do the request, blocking. Called by RequestStarter. */
-       public void send(NodeClientCore core) {
-               synchronized (this) {
-                       if(isCancelled()) {
-                               onFailure(new 
LowLevelGetException(LowLevelGetException.CANCELLED));
-                               return;
-                       }       
+       /** Do the request, blocking. Called by RequestStarter. 
+        * @return True if a request was executed. False if caller should try 
to find another request, and remove
+        * this one from the queue. */
+       public boolean send(NodeClientCore core) {
+               FetchContext ctx = getContext();
+               while(true) {
+                       synchronized (this) {
+                               if(isCancelled()) {
+                                       onFailure(new 
LowLevelGetException(LowLevelGetException.CANCELLED), -1);
+                                       return false;
+                               }       
+                       }
+                       ClientKeyBlock block;
+                       int keyNum = -1;
+                       try {
+                               keyNum = chooseKey();
+                               if(keyNum == -1) return false;
+                               ClientKey key = getKey(keyNum);
+                               if(key == null) continue;
+                               block = core.realGetKey(key, 
ctx.localRequestOnly, ctx.cacheLocalRequests, ctx.ignoreStore);
+                       } catch (LowLevelGetException e) {
+                               onFailure(e, keyNum);
+                               return true;
+                       } catch (Throwable t) {
+                               Logger.error(this, "Caught "+t, t);
+                               onFailure(new 
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR), keyNum);
+                               return true;
+                       }
+                       onSuccess(block, false, keyNum);
+                       return true;
                }
-               // Do we need to support the last 3?
-               ClientKeyBlock block;
-               try {
-                       FetchContext ctx = getContext();
-                       block = core.realGetKey(getKey(), ctx.localRequestOnly, 
ctx.cacheLocalRequests, ctx.ignoreStore);
-               } catch (LowLevelGetException e) {
-                       onFailure(e);
-                       return;
-               } catch (Throwable t) {
-                       Logger.error(this, "Caught "+t, t);
-                       onFailure(new 
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR));
-                       return;
-               }
-               onSuccess(block, false);
        }

        public void schedule() {
-               ClientKey key = getKey();
                if(Logger.shouldLog(Logger.MINOR, this))
-                       Logger.minor(this, "Scheduling "+this+" for "+key);
-               if(key instanceof ClientCHK)
-                       parent.chkScheduler.register(this);
-               else if(key instanceof ClientSSK)
+                       Logger.minor(this, "Scheduling "+this);
+               if(isSSK())
                        parent.sskScheduler.register(this);
                else
-                       throw new IllegalStateException(String.valueOf(key));
+                       parent.chkScheduler.register(this);
        }

 }

Modified: trunk/freenet/src/freenet/node/SendableRequest.java
===================================================================
--- trunk/freenet/src/freenet/node/SendableRequest.java 2007-02-16 20:26:10 UTC 
(rev 11822)
+++ trunk/freenet/src/freenet/node/SendableRequest.java 2007-02-16 20:59:34 UTC 
(rev 11823)
@@ -15,8 +15,10 @@
        public int getRetryCount();

        /** ONLY called by RequestStarter. Start the actual request using the 
NodeClientCore
-        * provided. The request has been removed from the structure already. */
-       public void send(NodeClientCore node);
+        * provided. The request has been removed from the structure already, 
if canRemove().
+        * @return True if a request was sent, false otherwise (in which case 
the request will
+        * be removed if it hasn't already been). */
+       public boolean send(NodeClientCore node);

        /** Get client context object */
        public Object getClient();

Modified: trunk/freenet/src/freenet/node/SimpleSendableInsert.java
===================================================================
--- trunk/freenet/src/freenet/node/SimpleSendableInsert.java    2007-02-16 
20:26:10 UTC (rev 11822)
+++ trunk/freenet/src/freenet/node/SimpleSendableInsert.java    2007-02-16 
20:59:34 UTC (rev 11823)
@@ -45,7 +45,7 @@
                return 0;
        }

-       public void send(NodeClientCore core) {
+       public boolean send(NodeClientCore core) {
                boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
                try {
                        if(logMINOR) Logger.minor(this, "Starting request: 
"+this);
@@ -53,12 +53,13 @@
                } catch (LowLevelPutException e) {
                        onFailure(e);
                        if(logMINOR) Logger.minor(this, "Request failed: 
"+this+" for "+e);
-                       return;
+                       return true;
                } finally {
                        finished = true;
                }
                if(logMINOR) Logger.minor(this, "Request succeeded: "+this);
                onSuccess();
+               return true;
        }

        public Object getClient() {


Reply via email to