Update of /cvsroot/freenet/freenet/src/freenet/node
In directory sc8-pr-cvs1:/tmp/cvs-serv14597/src/freenet/node

Modified Files:
        Node.java Main.java 
Added Files:
        RecentKeyList.java NewNodeContactor.java 
Log Message:
6347:
Contact the least experienced node every 30 seconds (customizable), and send it a 
request for a recently requested key. Remove it from the store first. Thus new nodes 
will gain experience even if their estimators are pessimistic. Stage 2 will be making 
initial estimators pessimistic. Will implement soon.

--- NEW FILE: RecentKeyList.java ---
package freenet.node;

import freenet.Key;
import freenet.crypt.RandomSource;

/**
 * @author amphibian
 * A class to store a list of recently requested keys
 */
public class RecentKeyList {
        Key[] keys;
        int length;
        final int maxLength;
        RandomSource rand;
        
        public RecentKeyList(int maxLength, RandomSource rand) {
                length = 0;
                this.maxLength = maxLength;
                keys = new Key[maxLength];
                this.rand = rand;
        }
        
        public synchronized Key random() {
                if(length == 0) return null;
                return keys[rand.nextInt(length)];
        }
        
        public synchronized void add(Key k) {
                if(length < maxLength) {
                        keys[length] = k;
                        length++;
                } else {
                        keys[rand.nextInt(maxLength)] = k;
                }
        }
}

--- NEW FILE: NewNodeContactor.java ---
package freenet.node;

import freenet.CommunicationException;
import freenet.Core;
import freenet.FieldSet;
import freenet.Key;
import freenet.MessageObject;
import freenet.MessageSendCallback;
import freenet.Storables;
import freenet.TrailerWriter;
import freenet.node.states.request.DataPending;
import freenet.node.states.request.FeedbackToken;
import freenet.node.states.request.Pending;
import freenet.node.states.request.RequestInitiator;
import freenet.support.Checkpointed;
import freenet.support.Logger;

/**
 * @author amphibian
 * Checkpoint to make random requests to unused nodes in
 * the routing table every N seconds.
 * Possible sources of bias:
 * 1. We are requesting keys we have processed recently.
 * 2. HTL is 25.
 */
public class NewNodeContactor implements Checkpointed {

        protected final Node n;
        
        public NewNodeContactor(Node n) {
                this.n = n;
        }
        
        public String getCheckpointName() {
                return "New node contactor";
        }

        public long nextCheckpoint() {
                return System.currentTimeMillis() + 
                        Node.newNodePollInterval;
        }

        public void checkpoint() {
                // First find a key to request
                Key k = Node.recentKeys.random();
                Core.logger.log(this, "Requesting "+k+" from least used node...",
                                Logger.DEBUG);
                ContactorToken ct = new ContactorToken();
                long id = Core.getRandSource().nextLong();
                // Remove key from store if it exists
                // FIXME: like in InternalClient, and FCP, maybe we want to 
                // keep it in the store and just pretend it's not for purposes of this 
request?
                if (n.ds.contains(k)) {
                        n.ds.remove(k, false);
                }
                RequestInitiator ri = 
                        new RequestInitiator(id, System.currentTimeMillis());
                Pending p = new DataPending(id, Node.maxHopsToLive /* FIXME: bias? */,
                                k, null, ct, ri, true);
                // Schedule a NodeContactorVector which returns the Pending
                // And then schedules the RequestInitiator
                NewNodeContactorRequest newReq = 
                        new NewNodeContactorRequest(p, ri, k, id);
                NodeContactorVector vector = new NodeContactorVector(newReq, k, id);
                n.schedule(vector);
        }

        class NewNodeContactorRequest extends State {

                Pending targetState;
                NodeMessageObject msg;
                
                protected NewNodeContactorRequest(long id) {
                        super(id);
                        throw new UnsupportedOperationException();
                }

                /**
                 * @param p the eventual Pending state we want to get to
                 * @param k the key we are using
                 * @param id the id of the chain
                 */
                public NewNodeContactorRequest(Pending p, NodeMessageObject mo,
                                                                           Key k, long 
id) {
                        super(id);
                        this.targetState = p;
                        this.msg = mo;
                }
                
                public State received(Node n, MessageObject mo) throws StateException {
                        if(!(mo instanceof NodeContactorVector)) {
                                throw new BadStateException("Not a 
NodeContactorVector: "+mo);
                        }
                        return targetState.received(n, msg);
                }
                
                public String getName() {
                        return "Node contactor request";
                }

                public void lost(Node n) {
                        Core.logger.log(this, "Lost "+this, Logger.NORMAL);
                }
        }
        
        /**
         * Class to get the Pending into the state machine, and then
         * schedule the RequestInitiator.
         * @author amphibian
         */
        class NodeContactorVector implements NodeMessageObject {
                
                State state;
                Key k;
                long id;
                
                public NodeContactorVector(State initialState,
                                                                  Key k, long id) {
                        this.state = initialState;
                        this.k = k;
                        this.id = id;
                }
                
                public State getInitialState() {
                        return state;
                }
                
                public boolean isExternal() {
                        return true; // id is external
                }

                public void drop(Node n) {
                        Core.logger.log(this, "Dropped "+k+" ("+id+"!", Logger.NORMAL);
                }

                public long id() {
                        return id;
                }
        }
        
        /**
         * FeedbackToken implementation for NewNodeContactor.
         * Doesn't do much since RT is informed in Pending etc.
         * @author amphibian
         */
        class ContactorToken implements FeedbackToken {

                public void queryRejected(Node n, int htl, String reason, FieldSet fs, 
int unreachable, int restarted, int rejected, MessageSendCallback cb) throws 
CommunicationException {
                        // Oh well...
                }

                public void restarted(Node n, long millis, MessageSendCallback cb) 
throws CommunicationException {
                        // Doesn't matter
                }

                public void dataNotFound(Node n, long timeOfQuery, MessageSendCallback 
cb) throws CommunicationException {
                        // Doesn't matter
                }

                public TrailerWriter dataFound(Node n, Storables sto, long ctLength) 
throws CommunicationException {
                        // Doesn't matter
                        return null;
                }

                public void insertReply(Node n, long millis) throws 
CommunicationException {
                        // Doesn't matter
                }

                public void storeData(Node n, NodeReference nr, FieldSet estimator, 
long rate, int hopsSinceReset, MessageSendCallback cb) throws CommunicationException {
                        // Doesn't matter
                }
        }
}

Index: Node.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/node/Node.java,v
retrieving revision 1.253
retrieving revision 1.254
diff -u -w -r1.253 -r1.254
--- Node.java   21 Nov 2003 00:26:19 -0000      1.253
+++ Node.java   21 Nov 2003 21:12:43 -0000      1.254
@@ -112,6 +112,7 @@
         config.addOption("failureTableSize",    1, 20000,  1360); // 20000 failed 
keys - uses ~ 2.7MB
         config.addOption("failureTableItems",   1, 100000, 1361);
         config.addOption("failureTableTime",    1, 1800000l, 1362); // 30 min
+        config.addOption("newNodePollInterval",1, 30000, 1363); // 30 seconds
     
         // ARK stuff
         config.addOption("minCP",               1, 0.01F,    1370);
@@ -653,6 +654,14 @@
                           "The amount of time to keep keys cache keys that could not 
be found and",
                           "automatically fail requests for them.");
 
+        // newNodePollInterval
+        config.setExpert("newNodePollInterval", true);
+        config.argDesc("newNodePollInterval", "<milliseconds>");
+        config.shortDesc("newNodePollInterval", "interval between polling new nodes");
+        config.longDesc("newNodePollInterval", "The node will send a request for a 
random "+
+                       "recently requested key to the node in the routing table with 
the fewest accesses, "+
+                       "every N milliseconds. Please enter N.");
+        
         // bandwidthLimit
         config.setExpert ("bandwidthLimit", true); // because deprecated
         config.argDesc   ("bandwidthLimit", "<bytes/sec>");
@@ -1903,6 +1912,8 @@
     static public float minRTFullPRef;
     static public String routingTableImpl;
     static public RunningAverage myPQueryRejected;
+       static public int newNodePollInterval = 30000; // 30 seconds
+
     
     // announcement options
     static public int announcementAttempts;
@@ -2013,6 +2024,7 @@
     static public boolean defaultToSimpleUIMode;
     static public boolean defaultToOCMHTMLPeerHandlerMode;
     
+    static public RecentKeyList recentKeys;
     
     public static boolean isAuthorized(Identity id, String p) {
         if ( adminPassword != null && !adminPassword.equals("") 
@@ -2072,6 +2084,8 @@
         }
         myPQueryRejected = new DecayingRunningAverage(0.0, 0.2);
         // set network parameters
+               newNodePollInterval = params.getInt("newNodePollInterval");
+               recentKeys = new RecentKeyList(512, Core.getRandSource());
         routeConnectTimeout = params.getInt("routeConnectTimeout");
         maxHopsToLive = params.getInt("maxHopsToLive");
                maxLog2DataSize = params.getInt("maxLog2DataSize");

Index: Main.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/node/Main.java,v
retrieving revision 1.311
retrieving revision 1.312
diff -u -w -r1.311 -r1.312
--- Main.java   20 Nov 2003 23:54:52 -0000      1.311
+++ Main.java   21 Nov 2003 21:12:43 -0000      1.312
@@ -1048,6 +1048,7 @@
                     new Checkpoint(routingStore).schedule(node);
                     new Checkpoint(diagnosticsCheckpoint).schedule(node);
                     new Checkpoint(ft).schedule(node);
+                    new Checkpoint(new NewNodeContactor(node)).schedule(node);
                     new Checkpoint(loadStats).schedule(node);
                     if(ipDetector != null)
                         new Checkpoint(ipDetector).schedule(node);

_______________________________________________
cvs mailing list
[EMAIL PROTECTED]
http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/cvs

Reply via email to