Author: vive
Date: 2007-06-15 23:27:17 +0000 (Fri, 15 Jun 2007)
New Revision: 13619

Added:
   trunk/apps/load-balancing-sims/phase7/sim/SimpleNode.java
   trunk/apps/load-balancing-sims/phase7/sim/SimpleQuery.java
Log:
Simulations for high-level load/routing modelling


Added: trunk/apps/load-balancing-sims/phase7/sim/SimpleNode.java
===================================================================
--- trunk/apps/load-balancing-sims/phase7/sim/SimpleNode.java                   
        (rev 0)
+++ trunk/apps/load-balancing-sims/phase7/sim/SimpleNode.java   2007-06-15 
23:27:17 UTC (rev 13619)
@@ -0,0 +1,205 @@
+//
+// A simple node (without protocol details) for high-level and topology 
simulations
+//
+package sim;
+
+import java.util.Vector;
+import java.util.LinkedList;
+import java.util.HashSet;
+import java.util.Random;
+
+class SimpleNode {
+    
+    double location;
+    public Vector<SimpleNode> neighbors; // Symmetric for undirected, outgoing 
when directed
+    public Vector<SimpleNode> incoming;  // Incoming when directed
+    Random rand;
+    boolean print_steps = false;
+
+    /*** stats ***/
+    int load = 0;
+    int loadmem = 0;
+    int busy = 0;
+    int initiated = 0;
+        
+    public SimpleNode(double x) {
+       this.location = x;
+       neighbors = new Vector<SimpleNode>();
+       incoming = new Vector<SimpleNode>();
+       rand = new Random ((int) (System.currentTimeMillis() % 10000));
+    }
+
+    public LinkedList<SimpleQuery> route(SimpleQuery q) {
+       load++;              // Received query from peer
+       loadmem++;
+       int htl = q.htl;     // Internal htl value
+       if(print_steps)
+           printQueryState(htl);
+
+       LinkedList<SimpleQuery> result = new LinkedList<SimpleQuery>();
+
+       if(this.location == q.target.getLocation()) {
+           result.addLast(new 
SimpleQuery(this,q.target,SimpleQuery.SUCCESS,0));
+           return result;
+       }
+
+       if(htl == 0) {      
+            result.addLast(new 
SimpleQuery(this,q.target,SimpleQuery.HTLSTOP,0));
+           return result;
+       }
+
+       if(busy != 0) {
+           result.addLast(new 
SimpleQuery(this,q.target,SimpleQuery.REJECTLOOP,htl-1));
+           return result;
+       }
+
+       busy = 1;
+
+       HashSet<SimpleNode> peers = new HashSet<SimpleNode>(neighbors); 
+       peers.remove(q.peer);
+       
+       int time = 0;
+       while(htl>0) {
+
+           if(print_steps && (time>0))
+               printQueryState(htl);
+           time++;
+           
+           double bestdist = Double.MAX_VALUE;
+           SimpleNode bestpeer = null;
+           
+           for (SimpleNode peer: peers) {
+               double dist = peer.distanceTo(q.target);
+               if(dist < bestdist) {
+                   bestdist = dist;
+                   bestpeer = peer;
+               } else if (dist == bestdist) {
+                   if(rand.nextDouble()<0.5) {
+                       bestdist = dist;
+                       bestpeer = peer;
+                   }
+               }
+           }
+           
+           if(bestpeer == null) {          // Dead end
+               result.addLast(new 
SimpleQuery(this,q.target,SimpleQuery.DEADEND,htl-1));
+               return result;
+           }
+
+           result.addLast(new 
SimpleQuery(this,q.target,SimpleQuery.FORWARD,htl-1));   
+           peers.remove(bestpeer);
+
+           if(print_steps)
+               System.err.println("sending to " + bestpeer.getLocation() + 
"(attempt #"+time+")");
+
+                         // fixme: Freenet HTL heuristic
+           LinkedList<SimpleQuery> attempt = bestpeer.route(new 
SimpleQuery(this,q.target,SimpleQuery.FORWARD,htl-1));
+           load++;       // Received answer
+           loadmem++;
+           result.addAll(attempt);
+
+           switch(attempt.getLast().type) {
+
+           case SimpleQuery.SUCCESS:           
+               result.addLast(new 
SimpleQuery(this,q.peer,SimpleQuery.SUCCESS,0));
+               return result;
+               
+           case SimpleQuery.HTLSTOP:
+               result.addLast(new 
SimpleQuery(this,q.peer,SimpleQuery.HTLSTOP,0));
+               return result;
+
+           default:
+               htl = attempt.getLast().htl;
+               break;
+           }
+       }
+
+       result.addLast(new SimpleQuery(this,q.target,SimpleQuery.HTLSTOP,0));
+       return result;
+    }
+
+
+    public double getLocation() {
+       return location;
+    }
+
+    public double distanceTo(SimpleNode target) {
+       return distanceTo(target.location);
+    }
+
+    public double distanceTo(double pos) {
+       if ((pos<0) || (pos>1)) {
+           System.err.println("SimpleNode.distanceTo(): malformed distance"); 
System.exit(-1);
+       }
+       return Math.min(Math.max(location,pos)-Math.min(location,pos), 
Math.min(location,pos)+1.0-Math.max(location,pos));
+    }
+
+    public void connect(SimpleNode target) {
+       if (target == this) {
+           System.err.println("SimpleNode.connect(): connecting itself"); 
System.exit(-1);
+       }
+
+       if (neighbors.contains(target)) {
+           System.err.println("SimpleNode.connect(): neighbors exists"); 
System.exit(-1);
+       }
+       neighbors.add(target);
+       target.connectIncoming(this);
+    }
+
+    // This is for easy book-keeping when we are evaluating a directed model
+    public void connectIncoming(SimpleNode source) {
+       if(source == this) {
+           System.err.println("SimpleNode.connectIncoming(): connecting 
itself"); System.exit(-1);
+       }
+       if(incoming.contains(source)) {
+           System.err.println("SimpleNode.connectIncoming(): source exists"); 
System.exit(-1);
+       }
+       incoming.add(source);
+
+    }
+
+    public void disconnect(SimpleNode target) {
+       if (target == this) {
+           System.err.println("SimpleNode.disconnect(): disconnecting 
itself"); System.exit(-1);
+       }
+
+       if (!neighbors.remove(target)) {
+           System.err.println("SimpleNode.disconnect(): neighbor not exists"); 
System.exit(-1);
+       }
+    }
+
+    public boolean hasNeighbor(SimpleNode peer) {
+       return neighbors.contains(peer);
+    }
+
+    public int getDegree() {
+       return neighbors.size();
+    }
+
+    public void printNeighbors() {
+       System.out.print("[ ");
+       for(SimpleNode n: neighbors) {
+           System.out.print(n.getLocation() + " ");
+       }
+       System.out.print("]");
+    }
+
+    public void printIncoming() {
+       System.out.print("I[ ");
+       for(SimpleNode n: incoming) {
+           System.out.print(n.getLocation() + " ");
+       }
+       System.out.print("]");
+    }
+
+    public void printQueryState(int htl) {
+       System.err.print("[htl="+htl+"]");
+       System.err.print("location " + location +":\t");
+       System.err.print("[ ");
+       for(SimpleNode n: neighbors) {
+           System.err.print(n.getLocation() + " ");
+       }
+       System.err.print("]\t");
+    }
+
+}

Added: trunk/apps/load-balancing-sims/phase7/sim/SimpleQuery.java
===================================================================
--- trunk/apps/load-balancing-sims/phase7/sim/SimpleQuery.java                  
        (rev 0)
+++ trunk/apps/load-balancing-sims/phase7/sim/SimpleQuery.java  2007-06-15 
23:27:17 UTC (rev 13619)
@@ -0,0 +1,22 @@
+package sim;
+
+class SimpleQuery {
+
+    public static final int SUCCESS=0;
+    public static final int DEADEND=1;
+    public static final int HTLSTOP=2;
+    public static final int REJECTLOOP=3;
+    public static final int FORWARD=4;
+
+    final SimpleNode peer;
+    final SimpleNode target;
+    final int type;
+    int htl;
+
+    public SimpleQuery (SimpleNode peer, SimpleNode target, int type, int htl) 
{
+       this.peer = peer;
+       this.target = target;
+       this.type = type;
+       this.htl = htl;
+    }
+}


Reply via email to