3

Consider the following tree:

Tree

What i am trying to do is emulate a Tree Wave Algorithm, so that if a node has received a token from all but one of its directly connected neighbours, it sends a token to that silent neighbour (always true for a leaf node). And if a node receives a token from the silent neighbour a decision is made. The nodes are always 7, and tree structure the same so i always know each node's neighbours (directly connected nodes).

The tree algorithm pseudo-code:

The tree algorithm

I have the following object:

public final class Node implements Runnable {

    private final int name;

    // Indicating token receiving from neighbours
    private Map<Node, Boolean> neigh = new 
            HashMap<Node, Boolean>();

    public Node(int name) {
        this.name = name;
    }

    public int getName() {
        return name;
    }

    public void addNeigh(Node node) {
        neigh.put(node, false);
    }

    private int flag() {
        Collection<Boolean> c = neigh.values();
        int count = 0;
        for (Boolean bool : c) {
            if (!bool) {
                count++;
            }
        }
        return count;
    }

    private Node getSilentNeigh() {
        for (Entry<Node, Boolean> entry : neigh.entrySet()) {
            if (false == entry.getValue()) {
                return entry.getKey();
            }
        }
        return null;
    }

    public void sendToken(Node from, String token) {

        Node n;
        if ((n = getSilentNeigh()) != null && flag() == 1) {
            if (from.equals(n)) {
                System.out.println(name + " decides!");
            }
        }

        neigh.put(from, true);
    }

    @Override
    public boolean equals(Object obj) {

        if (this == obj) {
            return true;
        }

        if (!(obj instanceof Node)) {
            return false;
        }

        final Node n = (Node) obj;
        return name == n.name;
    }

    @Override
    public int hashCode() {
        int hc = 17;
        return 37 * hc + name;
    }

    @Override
    public void run() {
        while(flag() > 1);

        Node n = getSilentNeigh();

        System.out.println(name + " sends token to " + n.getName());

        n.sendToken(this, "token");
    }

    @Override
    public String toString() {
        return "Node " + name;
    }
}

Inside the run() method there is a while(condition) that actually means.. wait (receiving tokens from neighbours), and when there is only one neighbour that the node did not receive token send token to him.

This is how i create the nodes and how i associate each other:

        // Number of nodes
        int numberOfNodes = 7;

        // Array of nodes
        Node[] nodes = new Node[numberOfNodes]; 

        for (int i = 0; i < nodes.length; i++) {
            // Creating node
            nodes[i] = new Node(i);
        }

        nodes[0].addNeigh(nodes[1]);
        nodes[0].addNeigh(nodes[2]);
        nodes[1].addNeigh(nodes[0]);
        nodes[1].addNeigh(nodes[3]);
        nodes[1].addNeigh(nodes[4]);
        nodes[2].addNeigh(nodes[0]);
        nodes[2].addNeigh(nodes[5]);
        nodes[2].addNeigh(nodes[6]);    
        nodes[3].addNeigh(nodes[1]);
        nodes[4].addNeigh(nodes[1]);
        nodes[5].addNeigh(nodes[2]);
        nodes[6].addNeigh(nodes[2]);

What i do is randomly select the order of the nodes to execute:

        // List holding random node numbers
        List numbers = new ArrayList<Integer>();

        int chosen = 0;
        while (chosen < numberOfNodes) {
            int processNum = randInt(0, (numberOfNodes - 1));
            if (!numbers.contains(Integer.valueOf(processNum))) {
                 numbers.add(new Integer(processNum));
                 chosen++;
            }
        }

So for example the nodes may be in any order:

0, 5, 3, 4, 6, 2, 1
5, 3, 0, 2, 1, 6, 4
3, 1, 0, 2, 4, 6, 5

and then i start the threads:

for (Integer number : numbers) {
    Thread thread = new Thread(nodes[number]);
    thread.start();
}

Sometimes i get the expected result (2 must decide):

Nodes selected: 0, 4, 5, 2, 6, 3, 1
5 sends token to 2
4 sends token to 1
6 sends token to 2
3 sends token to 1
1 sends token to 0
0 sends token to 2
2 decides!
2 sends token to 0
0 decides!

But usually i get an error and only one decides:

Nodes selected: 5, 3, 4, 6, 0, 2, 1
3 sends token to 1
5 sends token to 2
4 sends token to 1
6 sends token to 2
2 sends token to 0
0 sends token to 1
1 decides!
Exception in thread "Thread-6" java.lang.NullPointerException
    at uk.ac.ncl.csc8103.wave.Node.run(Node.java:86)
    at java.lang.Thread.run(Thread.java:745)

And yes this is for an Assignment, and i am really close to this guys.. but i am facing this prob.

  • Provide the code which is selecting the nodes. how are you sending token for nodes ? show how you build node and neighbours – Mani Oct 24 '14 at 20:34

2 Answers2

1

Well, your run method calls Node n = getSilentNeigh(); This call may return null, and you use the n variable without checking that it's not null.

@Override
public void run() {
    while(flag() > 1);
    Node n = getSilentNeigh(); // this call can return null
    System.out.println(name + " sends token to " + n.getName()); // you are probably getting 
                                                                 // NullPointerException here
    n.sendToken(this, "token");
}
Eran
  • 387,369
  • 54
  • 702
  • 768
1
Inside the run() method there is a while(condition) that actually means.. wait (receiving tokens from neighbours)

This is not true as per your code

  while(flag() > 1);

if the Node has only one Node ( 4 /5 / 6 ) - for these the flag() would return 1 and which will terminate while loop and then would move forward and send requst even before the initiators starts send message

UPDATE

As you know there are 4 initiators for this code (3,4,5,6) And excepts to get out of while loop ..

Take this

Nodes selected: 5, 3, 4, 6, 0, 2, 1 3 sends token to 1 5 sends token to 2 4 sends token to 1 6 sends token to 2 2 sends token to 0 0 sends token to 1 1 decides!

It is purely an race condition , what if previously started initiator (5) already reached /sends message to other initator's (3) neighbor ( 1) . while Initator(3) try to start and get SlientNeigh it would got Null ( no slient neigh) . thus you are getting Null pointer exception at n.sendToken.

Reference for Algorithm : You dont need to sycn ( we dont have rule that each node should receive only one message from neighbour) .

From the reference three simple properties

  – In each computation there is one initiator, which starts the algorithm by sending out exactly one message

–– A process, upon receipt of a message, either sends out one message or decides


–– The algorithm terminates in the initiator and when this happens, each process has sent a message at least once
Mani
  • 3,274
  • 2
  • 17
  • 27
  • Yes, but the initiators are actually the 4, 5, 6 (leaf nodes). So, they are supposed to start the algorithm. –  Oct 24 '14 at 20:58
  • But my understanding is . Only one Initiator for an computation . inst ? Other initiator's Message may collide with other computation since you are sharing the same instance. - correct me - i may be wrong. – Mani Oct 24 '14 at 21:04
  • There is no requirement that exactly one node must initiate an execution. Yes, it may collide, but i cannot find a proper way of doing this... –  Oct 24 '14 at 21:13
  • Ohhh! true. How can i synchronise it? –  Oct 24 '14 at 21:19
  • Before sych .Would like to understand the expectation. what would be your excepted results ? 3 Initiators out 7 Nodes it can be 1 decides / more than 1 decides as long as it already receives message and no slient neighbors to send message . is it correct ? – Mani Oct 24 '14 at 21:23
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/63611/discussion-between-michalis-daniilakis-and-mani). –  Oct 24 '14 at 21:31
  • Each algorithm has rules. and my understanding is you should have one initiator . upon receipt of request he should send to his neighbor or decides ( as long as he already sent he can decides) . But each node should sent atleast one message . Each node can receive multiple message – Mani Oct 24 '14 at 21:35
  • Ok then, maybe i am the one that don't understand the algorithm. –  Oct 24 '14 at 21:37
  • 1
    So , if you can make sure these rules you are fine. Assume you are using this algorithm to ping and availability of servers in the data center (network). each server should sent message to make sure the server is alive . As you said you may have multiple initiators as long as each server sent at least one ping you should be fine . Think algorithm with real time usage . some time easy to understand – Mani Oct 24 '14 at 21:37