Author: toad
Date: 2008-02-02 23:00:04 +0000 (Sat, 02 Feb 2008)
New Revision: 17483

Added:
   trunk/freenet/src/freenet/client/async/OfferedKeysList.java
Modified:
   trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
Log:
Beginnings of client layer support

Modified: trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2008-02-02 21:54:52 UTC (rev 17482)
+++ trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2008-02-02 23:00:04 UTC (rev 17483)
@@ -86,6 +86,7 @@
         * To speed up fetching, a RGA or SVBN must only exist if it is 
non-empty.
         */
        private final SortedVectorByNumber[] priorities;
+       private final OfferedKeysList[] offeredKeys;
        // we have one for inserts and one for requests
        final boolean isInsertScheduler;
        final boolean isSSKScheduler;
@@ -178,6 +179,13 @@
                                new PrioritySchedulerCallback(this));

                this.choosenPriorityScheduler = 
sc.getString(name+"_priority_policy");
+               if(!forInserts) {
+                       offeredKeys = new 
OfferedKeysList[RequestStarter.NUMBER_OF_PRIORITY_CLASSES];
+                       for(short 
i=0;i<RequestStarter.NUMBER_OF_PRIORITY_CLASSES;i++)
+                               offeredKeys[i] = new 
OfferedKeysList(node.clientCore, random, i);
+               } else {
+                       offeredKeys = null;
+               }
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
        }

@@ -376,6 +384,11 @@
                                Logger.minor(this, "Nothing to do");
                        return null;
                }
+               boolean tryOfferedKeys = (offeredKeys != null) && 
node.random.nextBoolean();
+               if(tryOfferedKeys) {
+                       if(!offeredKeys[choosenPriorityClass].isEmpty())
+                               return offeredKeys[choosenPriorityClass];
+               }
                SortedVectorByNumber s = priorities[choosenPriorityClass];
                if(s != null){
                        while(true) {

Added: trunk/freenet/src/freenet/client/async/OfferedKeysList.java
===================================================================
--- trunk/freenet/src/freenet/client/async/OfferedKeysList.java                 
        (rev 0)
+++ trunk/freenet/src/freenet/client/async/OfferedKeysList.java 2008-02-02 
23:00:04 UTC (rev 17483)
@@ -0,0 +1,123 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.client.async;
+
+import java.util.HashSet;
+import java.util.Vector;
+
+import freenet.crypt.RandomSource;
+import freenet.keys.ClientKey;
+import freenet.node.LowLevelGetException;
+import freenet.node.NodeClientCore;
+import freenet.node.RequestScheduler;
+import freenet.node.SendableRequest;
+import freenet.support.Logger;
+
+/**
+ * All the keys at a given priority which we have received key offers from 
other nodes for.
+ * 
+ * This list needs to be kept up to date when:
+ * - A request is removed.
+ * - A request's priority changes.
+ * - A key is found.
+ * - A node disconnects or restarts (through the BlockOffer objects on the 
FailureTable).
+ * 
+ * And of course, when an offer is received, we need to add an element.
+ * 
+ * @author toad
+ *
+ */
+public class OfferedKeysList extends SendableRequest {
+
+       private final HashSet keys;
+       // FIXME is there any way to avoid the O(n) shuffling penalty here?
+       private final Vector keysList;
+       private static boolean logMINOR;
+       private final RandomSource random;
+       private final short priorityClass;
+       private final NodeClientCore core;
+       
+       OfferedKeysList(NodeClientCore core, RandomSource random, short 
priorityClass) {
+               this.keys = new HashSet();
+               this.keysList = new Vector();
+               this.random = random;
+               this.priorityClass = priorityClass;
+               this.core = core;
+               logMINOR = Logger.shouldLog(Logger.MINOR, this);
+       }
+       
+       /** Called when a key is found. */
+       public synchronized void onFoundKey(ClientKey key) {
+               logMINOR = Logger.shouldLog(Logger.MINOR, this);
+               if(logMINOR) Logger.minor(this, "Found "+key+" , removing it");
+               keys.remove(key);
+               keysList.remove(key);
+       }
+       
+       /** Called when there are no more valid offers for a key */
+       public synchronized void onNoOffers(ClientKey key) {
+               logMINOR = Logger.shouldLog(Logger.MINOR, this);
+               if(logMINOR) Logger.minor(this, "No offers for "+key+" , 
removing it");
+               keys.remove(key);
+               keysList.remove(key);
+       }
+
+       public synchronized boolean isEmpty() {
+               return keys.isEmpty();
+       }
+
+       public Object[] allKeys() {
+               // Not supported.
+               throw new UnsupportedOperationException();
+       }
+
+       public Object chooseKey() {
+               // Pick a random key
+               if(keysList.isEmpty()) return null;
+               Object o = keysList.remove(random.nextInt(keysList.size()));
+               keys.remove(o);
+               return o;
+       }
+
+       public Object getClient() {
+               return this;
+       }
+
+       public ClientRequester getClientRequest() {
+               // FIXME is this safe?
+               return null;
+       }
+
+       public short getPriorityClass() {
+               return priorityClass;
+       }
+
+       public int getRetryCount() {
+               return 0; // All keys have equal chance even if they've been 
tried before.
+       }
+
+       public void internalError(Object keyNum, Throwable t) {
+               Logger.error(this, "Internal error: "+t, t);
+       }
+       
+       public boolean send(NodeClientCore node, RequestScheduler sched, Object 
keyNum) {
+               ClientKey key = (ClientKey) keyNum;
+               try {
+                       core.realGetKey(key, false, true, // if it's not cached 
it won't propagate FIXME support =false??
+                                       false);
+               } catch (LowLevelGetException e) {
+                       Logger.minor(this, "Caught low level get exception "+e, 
e);
+               }
+               return true;
+       }
+
+       public boolean canRemove() {
+               return false;
+       }
+
+       public boolean isCancelled() {
+               return false;
+       }
+
+}


Reply via email to