From 036b77cf2df4fa12e43ac36a8d692308736002c8 Mon Sep 17 00:00:00 2001 From: senft-desktop Date: Thu, 20 Dec 2012 08:48:25 +0100 Subject: [PATCH] Removed BucketEntry in favor of NodeIdentifier, buckets still not correct --- ws2012/P2P/uebungen/8/src/CLI.java | 42 +++ .../P2P/uebungen/8/src/node/Identifier.java | 93 ++++--- ws2012/P2P/uebungen/8/src/node/Node.java | 262 +++++++++--------- .../uebungen/8/src/node/NodeIdentifier.java | 35 +++ .../P2P/uebungen/8/src/node/UDPHandler.java | 217 ++++++++------- .../uebungen/8/src/routingtable/Bucket.java | 122 ++++---- .../8/src/routingtable/BucketEntry.java | 35 --- .../8/src/routingtable/RoutingTable.java | 74 +++-- 8 files changed, 477 insertions(+), 403 deletions(-) create mode 100644 ws2012/P2P/uebungen/8/src/CLI.java create mode 100644 ws2012/P2P/uebungen/8/src/node/NodeIdentifier.java delete mode 100644 ws2012/P2P/uebungen/8/src/routingtable/BucketEntry.java diff --git a/ws2012/P2P/uebungen/8/src/CLI.java b/ws2012/P2P/uebungen/8/src/CLI.java new file mode 100644 index 00000000..d7c61fe2 --- /dev/null +++ b/ws2012/P2P/uebungen/8/src/CLI.java @@ -0,0 +1,42 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.logging.LogManager; + +import node.Node; +import node.NodeIdentifier; + +public class CLI { + + public static void main(String[] args) throws IOException { + System.setProperty("java.util.logging.config.file", + "logging.properties"); + + try { + LogManager.getLogManager().readConfiguration(); + } catch (Exception e) { + e.printStackTrace(); + } + + Node node = new Node(); + + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + String s; + while ((s = in.readLine()) != null && s.length() != 0) { + String[] splitted = s.split(" "); + + String cmd = splitted[0]; + + switch (cmd) { + case "status": + for (NodeIdentifier id : node.getNeighbors()) { + System.out.println(id); + } + break; + default: + System.out.println("Unknown command."); + break; + } + } + } +} \ No newline at end of file diff --git a/ws2012/P2P/uebungen/8/src/node/Identifier.java b/ws2012/P2P/uebungen/8/src/node/Identifier.java index f81144d7..b7c74584 100644 --- a/ws2012/P2P/uebungen/8/src/node/Identifier.java +++ b/ws2012/P2P/uebungen/8/src/node/Identifier.java @@ -5,65 +5,70 @@ import java.util.BitSet; import java.util.Random; public class Identifier { - private static Random random = new Random(System.currentTimeMillis()); + private static Random random = new Random(System.currentTimeMillis()); - private BitSet bits; + protected BitSet bits; - public Identifier(byte[] bytes) { - this.bits = BitSet.valueOf(bytes); - } + public Identifier(byte[] bytes) { + this.bits = BitSet.valueOf(bytes); + } private Identifier(BitSet bits) { - this.bits = bits; - } + this.bits = bits; + } public static Identifier getStaticIdentifier() { - BitSet middle = new BitSet(Node.ID_BITS); + BitSet middle = new BitSet(Node.ID_BITS); middle.set(Node.ID_BITS - 1); return new Identifier(middle); - } + } - public static Identifier getRandomIdentifier() { - BitSet bits = new BitSet(Node.ID_BITS); + public static Identifier getRandomIdentifier() { + BitSet bits = new BitSet(Node.ID_BITS); - for (int i = 0; i < Node.ID_BITS; i++) { - double threshold = random.nextGaussian(); - if (threshold > 0) { - bits.set(i); - } - } + for (int i = 0; i < Node.ID_BITS; i++) { + double threshold = random.nextGaussian(); + if (threshold > 0) { + bits.set(i); + } + } - return new Identifier(bits); - } + return new Identifier(bits); + } - public BitSet distanceTo(Identifier otherID) { - BitSet distance = (BitSet) bits.clone(); - distance.xor(otherID.getBitSet()); - return distance; - } + public BigInteger distanceTo(Identifier otherID) { + BitSet distance = (BitSet) bits.clone(); + distance.xor(otherID.getBitSet()); + return new BigInteger(1, distance.toByteArray()); + } - public boolean isBitSetAt(int index) { - return bits.get(index); - } + public boolean isBitSetAt(int index) { + return bits.get(index); + } - public byte[] getBytes() { - return bits.toByteArray(); - } + public byte[] getBytes() { + return bits.toByteArray(); + } - @Override - public boolean equals(Object o) { - if (!(o instanceof Identifier)) { - return false; - } else { - return bits.equals(((Identifier) o).getBitSet()); - } - } + @Override + public boolean equals(Object o) { + if (!(o instanceof Identifier)) { + return false; + } else { + return bits.equals(((Identifier) o).getBitSet()); + } + } - public BitSet getBitSet() { - return bits; - } + @Override + public int hashCode() { + return toString().hashCode(); + } - public String toString() { - return new BigInteger(bits.toByteArray()).toString(); - } + private BitSet getBitSet() { + return bits; + } + + public String toString() { + return new BigInteger(1, bits.toByteArray()).toString(); + } } diff --git a/ws2012/P2P/uebungen/8/src/node/Node.java b/ws2012/P2P/uebungen/8/src/node/Node.java index 0a1695a8..cad00fd1 100644 --- a/ws2012/P2P/uebungen/8/src/node/Node.java +++ b/ws2012/P2P/uebungen/8/src/node/Node.java @@ -14,178 +14,182 @@ import java.util.logging.Logger; import message.Ack; import message.MessageType; -import routingtable.BucketEntry; import routingtable.RoutingTable; public class Node { - /** - * Size of ID space - */ - public static final int ID_BITS = 8; + /** + * Size of ID space (has to be a multiple of 8) + */ + public static final int ID_BITS = 8; - /** - * The bucket size - */ - private static final int BUCKET_SIZE = 2; + /** + * The bucket size + */ + public static final int BUCKET_SIZE = 2; - /** - * The first node is always spawned on port 50000 - */ - private static final int INITIAL_PORT = 50000; + /** + * The first node is always spawned on port 50000 + */ + private static final int INITIAL_PORT = 50000; private static final Identifier INITIAL_ID = Identifier .getStaticIdentifier(); - private final static Logger LOGGER = Logger.getLogger(Node.class.getName()); + private static final int _BUFFER_SIZE = 512; - private InetSocketAddress address; - private DatagramChannel channel; + private final static Logger LOGGER = Logger.getLogger(Node.class.getName()); - private Map acks = new HashMap(); + private InetSocketAddress address; + private DatagramChannel channel; - private Thread thread; - private UDPHandler udpListen; + private Map acks = new HashMap(); - private Identifier nodeID = Identifier.getRandomIdentifier(); + private Thread thread; + private UDPHandler udpListen; - private RoutingTable rt = new RoutingTable(BUCKET_SIZE); + private Identifier nodeID = Identifier.getRandomIdentifier(); - public Node() { - System.setProperty("java.net.preferIPv4Stack", "true"); + private RoutingTable rt = new RoutingTable(BUCKET_SIZE); - try { - channel = DatagramChannel.open(); + public Node() { + System.setProperty("java.net.preferIPv4Stack", "true"); - try { - address = new InetSocketAddress("localhost", INITIAL_PORT); - channel.socket().bind(address); + try { + channel = DatagramChannel.open(); - this.nodeID = INITIAL_ID; - } catch (SocketException e) { - // Port 9999 is already bound -> pick a random port - channel.socket().bind(new InetSocketAddress("localhost", 0)); - address = (InetSocketAddress) channel.getLocalAddress(); - } + try { + address = new InetSocketAddress("localhost", INITIAL_PORT); + channel.socket().bind(address); - channel.configureBlocking(false); + this.nodeID = INITIAL_ID; + } catch (SocketException e) { + // Port 9999 is already bound -> pick a random port + channel.socket().bind(new InetSocketAddress("localhost", 0)); + address = (InetSocketAddress) channel.getLocalAddress(); + } - udpListen = new UDPHandler(this); - thread = new Thread(udpListen); - thread.start(); + channel.configureBlocking(false); - LOGGER.log(Level.INFO, "Initialized node {0} on {1}", new Object[] { - getName(), address.toString() }); + udpListen = new UDPHandler(this); + thread = new Thread(udpListen); + thread.start(); - if (address.getPort() != INITIAL_PORT) { - joinNetworkVia( - new InetSocketAddress("localhost", INITIAL_PORT), - INITIAL_ID); - } + LOGGER.log(Level.INFO, "Initialized node {0} on {1}", new Object[] { + getName(), address.toString() }); - } catch (IOException e) { - e.printStackTrace(); - } - } + if (address.getPort() != INITIAL_PORT) { + joinNetworkVia(new NodeIdentifier(INITIAL_ID.getBytes(), + new InetSocketAddress("127.0.0.1", INITIAL_PORT))); + } - private void joinNetworkVia(InetSocketAddress receiver, Identifier id) { - LOGGER.log(Level.INFO, "Trying to join network via node {0} ({1})", - new Object[] { id, receiver }); + } catch (IOException e) { + e.printStackTrace(); + } + } - rt.update(id, receiver); - // Send a FIND_NODE. The node to find is my own id (bootstrapping...) - sendFindNode(receiver, nodeID); - } + private void joinNetworkVia(NodeIdentifier receiver) { + LOGGER.log(Level.INFO, "Trying to join network via node {0}", + new Object[] { receiver }); - void sendFindNode(InetSocketAddress receiver, Identifier idToFind) { - ByteBuffer buffer = ByteBuffer.allocate(5 + 4 + 4); + rt.update(receiver); + // Send a FIND_NODE. The node to find is my own id (bootstrapping...) + sendFindNode(receiver, nodeID); + } - Identifier rpc_id = Identifier.getRandomIdentifier(); + void sendFindNode(NodeIdentifier receiver, Identifier idToFind) { + ByteBuffer buffer = ByteBuffer.allocate(_BUFFER_SIZE); - buffer.put(MessageType.FIND_NODE); - buffer.put(nodeID.getBytes()); - buffer.put(rpc_id.getBytes()); - buffer.put(idToFind.getBytes()); + Identifier rpc_id = Identifier.getRandomIdentifier(); - if (send(buffer, receiver)) { - LOGGER.log(Level.INFO, "Sending [FIND_NODE {0}] to node {1}", - new Object[] { idToFind, receiver }); - } - } + buffer.put(MessageType.FIND_NODE); + buffer.put(nodeID.getBytes()); + buffer.put(rpc_id.getBytes()); + buffer.put(idToFind.getBytes()); - void sendClosestNodesTo(InetSocketAddress receiver, Identifier receiverId, - Identifier idToFind, Identifier rpc_id) { + if (send(buffer, receiver.getAddress())) { + LOGGER.log(Level.INFO, "Sending [FIND_NODE {0}] to node {1}", + new Object[] { idToFind, receiver }); + } + } - // TODO: how big?! - ByteBuffer buffer = ByteBuffer.allocate(512); + void sendClosestNodesTo(NodeIdentifier receiver, Identifier idToFind, + Identifier rpc_id) { + ByteBuffer buffer = ByteBuffer.allocate(_BUFFER_SIZE); - buffer.put(MessageType.NODES); - buffer.put(nodeID.getBytes()); - buffer.put(rpc_id.getBytes()); + buffer.put(MessageType.NODES); + buffer.put(nodeID.getBytes()); + buffer.put(rpc_id.getBytes()); - Set entries = rt.getClosestNodesTo(idToFind); - for (BucketEntry e : entries) { - if (!receiverId.equals(e.id)) - buffer.put(e.getBytes()); - } + Set entries = rt.getClosestNodesTo(idToFind); + for (NodeIdentifier id : entries) { + if (!receiver.equals(id)) { + buffer.put(id.getTripleAsBytes()); + } + } - if (send(buffer, receiver)) { - LOGGER.log(Level.INFO, "Sending [NODES {0}] to node {1}.", - new Object[] { idToFind, receiverId }); - } - } + if (send(buffer, receiver.getAddress())) { + LOGGER.log(Level.INFO, + "Sending {0} nodes to to node {1} [FIND_NODE {2}].", + new Object[] { entries.size(), receiver, idToFind }); + } + } - private boolean send(ByteBuffer buffer, InetSocketAddress to) { - buffer.flip(); - try { - channel.send(buffer, to); - return true; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } + private boolean send(ByteBuffer buffer, InetSocketAddress to) { + buffer.flip(); + try { + channel.send(buffer, to); + return true; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } - public String getName() { - return nodeID.toString(); - } + public String getName() { + return nodeID.toString(); + } - public boolean hasAcks() { - return !acks.isEmpty(); - } + public boolean hasAcks() { + return !acks.isEmpty(); + } - protected boolean hasAck(int ack_id) { - return acks.containsKey(ack_id); - } + protected boolean hasAck(int ack_id) { + return acks.containsKey(ack_id); + } - protected Ack getAck(int ack_id) { - return acks.get(ack_id); - } + protected Ack getAck(int ack_id) { + return acks.get(ack_id); + } - protected void removeAck(int ack_id) { - acks.remove(ack_id).setReceived(); - } + protected void removeAck(int ack_id) { + acks.remove(ack_id).setReceived(); + } - public DatagramChannel getChannel() { - return channel; - } + public DatagramChannel getChannel() { + return channel; + } - public void updateBuckets(Identifier id, InetSocketAddress from) { - rt.update(id, from); - } + public void updateBuckets(NodeIdentifier id) { + rt.update(id); + } - public Identifier getID() { - return nodeID; - } + public Identifier getID() { + return nodeID; + } - public static void main(String[] args) { - System.setProperty("java.util.logging.config.file", - "logging.properties"); + public Set getNeighbors() { + return rt.getEntries(); + } - try { - LogManager.getLogManager().readConfiguration(); - } catch (Exception e) { - e.printStackTrace(); - } + public static void main(String[] args) { + System.setProperty("java.util.logging.config.file", + "logging.properties"); - new Node(); - } + try { + LogManager.getLogManager().readConfiguration(); + } catch (Exception e) { + e.printStackTrace(); + } + + new Node(); + } } diff --git a/ws2012/P2P/uebungen/8/src/node/NodeIdentifier.java b/ws2012/P2P/uebungen/8/src/node/NodeIdentifier.java new file mode 100644 index 00000000..60adecb5 --- /dev/null +++ b/ws2012/P2P/uebungen/8/src/node/NodeIdentifier.java @@ -0,0 +1,35 @@ +package node; + +import java.math.BigInteger; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; + +import util.BufferUtil; + +public class NodeIdentifier extends Identifier { + + private InetSocketAddress address; + + public NodeIdentifier(byte[] bytes, InetSocketAddress address) { + super(bytes); + this.address = address; + } + + public byte[] getTripleAsBytes() { + ByteBuffer result = ByteBuffer.allocate(8 + (Node.ID_BITS / 8)); + + result.put(BufferUtil.addrToBytes(address)); + result.put(bits.toByteArray()); + return result.array(); + } + + public InetSocketAddress getAddress() { + return address; + } + + public String toString() { + return new BigInteger(1, bits.toByteArray()).toString() + " (" + + address.toString() + ")"; + } + +} diff --git a/ws2012/P2P/uebungen/8/src/node/UDPHandler.java b/ws2012/P2P/uebungen/8/src/node/UDPHandler.java index 228ff11a..63df20a9 100644 --- a/ws2012/P2P/uebungen/8/src/node/UDPHandler.java +++ b/ws2012/P2P/uebungen/8/src/node/UDPHandler.java @@ -3,143 +3,146 @@ package node; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; -import java.util.HashSet; -import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import message.MessageType; -import routingtable.BucketEntry; public class UDPHandler implements Runnable { - private final static Logger LOGGER = Logger.getLogger(UDPHandler.class - .getName()); + private final static Logger LOGGER = Logger.getLogger(UDPHandler.class + .getName()); - public static final int BUF_SIZE = 512; + public static final int BUF_SIZE = 512; - private volatile boolean running = true; - private ByteBuffer buffer = ByteBuffer.allocate(BUF_SIZE); + private volatile boolean running = true; + private ByteBuffer buffer = ByteBuffer.allocate(BUF_SIZE); - private Node node; + private Node node; - public UDPHandler(Node node) { - this.node = node; - } + public UDPHandler(Node node) { + this.node = node; + } - /** - * Takes the buffer of this UDPHandler as is and tries to read an IP address - * (4 bytes and 1 int) from it. If there is no/incomplete or wrong data, - * this will fail. - * - * @return the address that has been read - */ - private InetSocketAddress getIPFromBuffer() { - StringBuilder theAddr = new StringBuilder(); - // Read 4 Bytes and 1 Integer = 1 IP address - for (int i = 0; i < 4; i++) { - theAddr.append(buffer.get()); - if (i < 3) { - theAddr.append("."); - } - } - int port = buffer.getInt(); - return new InetSocketAddress(theAddr.toString(), port); - } + /** + * Takes the buffer of this UDPHandler as is and tries to read an IP address + * (4 bytes and 1 int) from it. If there is no/incomplete or wrong data, + * this will fail. + * + * @return the address that has been read + */ + private InetSocketAddress getIPFromBuffer() { + StringBuilder theAddr = new StringBuilder(); + // Read 4 Bytes and 1 Integer = 1 IP address + for (int i = 0; i < 4; i++) { + theAddr.append(buffer.get()); + if (i < 3) { + theAddr.append("."); + } + } + int port = buffer.getInt(); + return new InetSocketAddress(theAddr.toString(), port); + } - private Identifier getIDFromBuffer() { - int numBytes = Node.ID_BITS / 8; - byte[] result = new byte[numBytes]; + private Identifier getIDFromBuffer() { + int numBytes = Node.ID_BITS / 8; + byte[] result = new byte[numBytes]; + for (int i = 0; i < numBytes; i++) { + result[i] = buffer.get(); + } + return new Identifier(result); + } - for (int i = 0; i < numBytes; i++) { - result[i] = buffer.get(); - } + private NodeIdentifier getNodeTripleFromBuffer() { + InetSocketAddress address = getIPFromBuffer(); - return new Identifier(result); - } + int numBytes = Node.ID_BITS / 8; + byte[] result = new byte[numBytes]; + for (int i = 0; i < numBytes; i++) { + result[i] = buffer.get(); + } + return new NodeIdentifier(result, address); + } - public void run() { - InetSocketAddress from = null; + public void run() { + InetSocketAddress from = null; - // Run until I get killed, and all my acks have been answered - while (running || node.hasAcks()) { - try { - from = (InetSocketAddress) node.getChannel().receive(buffer); + // Run until I get killed, and all my acks have been answered + while (running || node.hasAcks()) { + try { + from = (InetSocketAddress) node.getChannel().receive(buffer); - // channel.receive() is non-blocking. So we need to check if - // something actually has been written to the buffer - if (buffer.remaining() != BUF_SIZE) { - buffer.flip(); + // channel.receive() is non-blocking. So we need to check if + // something actually has been written to the buffer + if (buffer.remaining() != BUF_SIZE) { + buffer.flip(); - byte messageType = buffer.get(); + byte messageType = buffer.get(); - Identifier fromID = getIDFromBuffer(); - Identifier rpc_id = getIDFromBuffer(); + NodeIdentifier fromID = new NodeIdentifier( + getIDFromBuffer().getBytes(), from); + Identifier rpc_id = getIDFromBuffer(); - switch (messageType) { - case MessageType.FIND_NODE: - receiveFindNode(from, fromID, rpc_id); - break; - case MessageType.NODES: - receiveNodes(from, fromID, rpc_id); - break; - case MessageType.PING: - LOGGER.log(Level.INFO, "Received [ping] from {0}", - new Object[] { from.toString() }); - break; - default: - LOGGER.log(Level.INFO, - "Received unknown command from {0}: [{1}]{2}", - new Object[] { from.toString(), messageType, - new String(buffer.array()) }); - } + switch (messageType) { + case MessageType.FIND_NODE: + receiveFindNode(fromID, rpc_id); + break; + case MessageType.NODES: + receiveNodes(fromID, rpc_id); + break; + case MessageType.PING: + LOGGER.log(Level.INFO, "Received [ping] from {0}", + new Object[] { from.toString() }); + break; + default: + LOGGER.log(Level.INFO, + "Received unknown command from {0}: [{1}]{2}", + new Object[] { from.toString(), messageType, + new String(buffer.array()) }); + } - node.updateBuckets(fromID, from); - } else { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + node.updateBuckets(new NodeIdentifier(fromID.getBytes(), + from)); - buffer.clear(); + } else { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } - } catch (IOException e) { - e.printStackTrace(); - } - } - } + buffer.clear(); - private void receiveNodes(InetSocketAddress from, Identifier fromID, - Identifier rpc_id) { + } catch (IOException e) { + e.printStackTrace(); + } + } + } - Set readEntries = new HashSet(); + private void receiveNodes(NodeIdentifier fromID, Identifier rpc_id) { - while (buffer.hasRemaining()) { - InetSocketAddress address = getIPFromBuffer(); - Identifier id = getIDFromBuffer(); - BucketEntry entry = new BucketEntry(id, address); - readEntries.add(entry); + int numReceived = 0; - // TODO: Just add all nodes?! - node.updateBuckets(id, address); - } + while (buffer.hasRemaining()) { + NodeIdentifier newID = getNodeTripleFromBuffer(); + node.updateBuckets(newID); + numReceived++; + } - LOGGER.log(Level.INFO, "Received {0} [NODES] from Node {1} ({2})", - new Object[] { readEntries.size(), fromID, from.toString() }); - } + LOGGER.log(Level.INFO, "Received {0} [NODES] from Node {1})", + new Object[] { numReceived, fromID }); + } - private void receiveFindNode(InetSocketAddress from, Identifier fromID, - Identifier rpc_id) { - Identifier idToFind = getIDFromBuffer(); + private void receiveFindNode(NodeIdentifier fromID, Identifier rpc_id) { + Identifier idToFind = getIDFromBuffer(); - LOGGER.log(Level.INFO, "Received [FIND_NODE {0}] from Node {1} ({2})", - new Object[] { idToFind, fromID, from.toString() }); + LOGGER.log(Level.INFO, "Received [FIND_NODE {0}] from Node {1}", + new Object[] { idToFind, fromID }); - node.sendClosestNodesTo(from, fromID, idToFind, rpc_id); - } + node.sendClosestNodesTo(fromID, idToFind, rpc_id); + } - public void terminate() { - running = false; - } + public void terminate() { + running = false; + } } diff --git a/ws2012/P2P/uebungen/8/src/routingtable/Bucket.java b/ws2012/P2P/uebungen/8/src/routingtable/Bucket.java index f7f5282b..e9ee7e9a 100644 --- a/ws2012/P2P/uebungen/8/src/routingtable/Bucket.java +++ b/ws2012/P2P/uebungen/8/src/routingtable/Bucket.java @@ -5,94 +5,98 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import node.Identifier; +import node.NodeIdentifier; public class Bucket { private final static Logger LOGGER = Logger.getLogger(Bucket.class .getName()); - private int size; + private int bucketSize; - public List entries = new ArrayList(); - public Bucket left = null; - public Bucket right = null; + private List entries = new ArrayList(); + private Bucket left = null; + private Bucket right = null; private int level = 0; public Bucket(int size, int level) { this.level = level; - this.size = size; + this.bucketSize = size; } - public void update(BucketEntry entry) { - update(this, entry); + public void update(NodeIdentifier newID) { + update(this, newID); } - private void update(Bucket bucket, BucketEntry newEntry) { + private void update(Bucket bucket, NodeIdentifier newID) { if (!bucket.isLeaf()) { - if (newEntry.id.isBitSetAt(level)) { + if (newID.isBitSetAt(level)) { - update(bucket.right, newEntry); + update(bucket.right, newID); } else { - update(bucket.left, newEntry); + update(bucket.left, newID); } - } else if (bucket.isLeaf() && bucket.hasSpace()) { - - if (entries.contains(newEntry)) { + } else if (bucket.hasSpace()) { + System.out.println(entries == null); + if (entries.contains(newID)) { // Move to beginning LOGGER.log( Level.FINE, - "Node {0} ({1}) already in routing table. Move to end of bucket.", - new Object[] { newEntry.id, newEntry.address }); - if (entries.size() > 1) { - entries.remove(newEntry); - entries.add(newEntry); - } - } else { - LOGGER.log(Level.INFO, - "Added new node {0} ({1}) to routing table.", - new Object[] { newEntry.id, newEntry.address }); - entries.add(newEntry); - } - - } else { - // TODO: only split if necessary - // Leaf, but full -> split - - Bucket newLeft = new Bucket(size, level + 1); - Bucket newRight = new Bucket(size, level + 1); - - // Add the new entry and in the following loop distribute all - // existing entries to left/right - entries.add(newEntry); - - for (BucketEntry entry : entries) { - if (entry.id.isBitSetAt(level)) { - newLeft.entries - .add(new BucketEntry(entry.id, entry.address)); - } else { - newRight.entries - .add(new BucketEntry(entry.id, entry.address)); + "Node {0} already in routing table. Move to end of bucket.", + new Object[] { newID }); + if (entries.size() > 1) { + entries.remove(newID); + entries.add(newID); } + } else { + LOGGER.log(Level.INFO, "Added new node {0} to routing table.", + new Object[] { newID }); + entries.add(newID); } - bucket.entries = null; - bucket.left = newLeft; - bucket.right = newRight; + } else { // Bucket is full + System.out.println(entries == null); + if (!entries.contains(newID)) { + // TODO: only split if necessary + + Bucket newLeft = new Bucket(bucketSize, level + 1); + Bucket newRight = new Bucket(bucketSize, level + 1); + + // Add the new entry and in the following loop distribute all + // existing entries to left/right + entries.add(newID); + + for (NodeIdentifier entry : entries) { + if (entry.isBitSetAt(level)) { + newLeft.entries.add(entry); + } else { + newRight.entries.add(entry); + } + } + bucket.entries = null; + bucket.left = newLeft; + bucket.right = newRight; + } else { + // Node is already present -> check if it's still alive + LOGGER.log( + Level.FINE, + "Node {0} already in routing table. Check if still alive...", + new Object[] { newID }); + } } } - public boolean hasNode(Identifier id) { + public boolean hasNode(NodeIdentifier id) { return hasNode(this, id); } - private boolean hasNode(Bucket bucket, Identifier idToFind) { + private boolean hasNode(Bucket bucket, NodeIdentifier idToFind) { if (bucket.isLeaf()) { - for (BucketEntry entry : bucket.entries) { - if (entry.id.equals(idToFind)) { + for (NodeIdentifier id : bucket.entries) { + if (id.equals(idToFind)) { return true; } } @@ -107,18 +111,10 @@ public class Bucket { } private boolean isLeaf() { - return left == null && right == null; + return left == null && right == null && entries != null; } private boolean hasSpace() { - return entries.size() < size; - } - - public List getClosestNodesTo(Identifier id) { - List result = new ArrayList(); - - // TODO - - return result; + return entries.size() < bucketSize; } } \ No newline at end of file diff --git a/ws2012/P2P/uebungen/8/src/routingtable/BucketEntry.java b/ws2012/P2P/uebungen/8/src/routingtable/BucketEntry.java deleted file mode 100644 index de137f28..00000000 --- a/ws2012/P2P/uebungen/8/src/routingtable/BucketEntry.java +++ /dev/null @@ -1,35 +0,0 @@ -package routingtable; - -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; - -import util.BufferUtil; - -import node.Identifier; -import node.Node; - -public class BucketEntry { - public Identifier id; - public InetSocketAddress address; - - public BucketEntry(Identifier id, InetSocketAddress address) { - this.id = id; - this.address = address; - } - - public boolean equals(Object o) { - if (!(o instanceof BucketEntry)) { - return false; - } else { - BucketEntry entry = (BucketEntry) o; - return id.equals(entry.id) && address.equals(entry.address); - } - } - - public byte[] getBytes() { - ByteBuffer result = ByteBuffer.allocate(8 + (Node.ID_BITS / 8)); - result.put(BufferUtil.addrToBytes(address)); - result.put(id.getBytes()); - return result.array(); - } -} diff --git a/ws2012/P2P/uebungen/8/src/routingtable/RoutingTable.java b/ws2012/P2P/uebungen/8/src/routingtable/RoutingTable.java index 48b7de33..decb7e6f 100644 --- a/ws2012/P2P/uebungen/8/src/routingtable/RoutingTable.java +++ b/ws2012/P2P/uebungen/8/src/routingtable/RoutingTable.java @@ -1,43 +1,67 @@ package routingtable; -import java.net.InetSocketAddress; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; +import java.util.List; import java.util.Set; import node.Identifier; +import node.Node; +import node.NodeIdentifier; public class RoutingTable { - private Bucket tree; + private Bucket tree; - private Set entries = new HashSet(); + private Set entries = new HashSet(); - private int bucketSize; + private int bucketSize; - public RoutingTable(int bucketSize) { - this.tree = new Bucket(bucketSize, 0); - this.bucketSize = bucketSize; - } + public RoutingTable(int bucketSize) { + this.tree = new Bucket(bucketSize, 0); + this.bucketSize = bucketSize; + } - public void update(Identifier id, InetSocketAddress address) { - BucketEntry newEntry = new BucketEntry(id, address); - entries.add(newEntry); - tree.update(newEntry); - } + public void update(NodeIdentifier id) { + entries.add(id); + tree.update(id); + } - public Set getClosestNodesTo(Identifier id) { - Set result = new HashSet(); + public Set getClosestNodesTo(final Identifier id) { + Set result = new HashSet(); - if (entries.size() <= bucketSize) { - result.addAll(entries); - return result; - } else { - // TODO get all nodes that are closest.. - return null; - } - } + if (entries.size() <= bucketSize) { + result.addAll(entries); - public void remove(Identifier node) { + } else { + List temp = new ArrayList(entries); - } + Collections.sort(temp, new Comparator() { + @Override + public int compare(NodeIdentifier o1, NodeIdentifier o2) { + BigInteger dist1 = id.distanceTo(o1); + BigInteger dist2 = id.distanceTo(o2); + return dist1.compareTo(dist2); + } + }); + + for (int i = 0; i < Node.BUCKET_SIZE; i++) { + result.add(temp.get(i)); + } + + } + + return result; + } + + public void remove(Identifier node) { + // TODO + } + + public Set getEntries() { + return entries; + } } \ No newline at end of file