Quantcast
Channel: Recent Questions - Stack Overflow
Viewing all articles
Browse latest Browse all 12111

Implementing a Leader-Election Algorithm for Rings of Rings

$
0
0

I'm working on implementing a leader-election algorithm for a ring of rings network as part of a project. The goal is to use an asynchronous-start and terminating variant of the LCR algorithm to eventually elect the processor with the maximum ID as the leader, ensure all processors in the main ring are aware of the elected leader, and terminate all processors in the main ring.

The network consists of subnetworks (rings) connected to form a larger ring (main ring). Each subnetwork executes the terminating LCR algorithm, while the main ring uses an asynchronous-start variant of the LCR algorithm. All rings are bidirectional, and processors have a sense of clockwise and counter-clockwise orientation, which could potentially be used to optimize message transmissions.

My task is to experimentally evaluate the correctness and performance of the implemented algorithm by executing it on networks of varying sizes and structures. This includes different numbers and positions of interface nodes, sizes of subnetworks, and starting with various ID assignments. I plan to test both specifically constructed ID assignments (e.g., IDs ascending clockwise or counter-clockwise) and random ID assignments.

The simulator should verify that the maximum ID is elected as the leader in each execution, which serves as an indication of the algorithm's correctness. Additionally, it should record the number of rounds and the total number of messages transmitted until termination to evaluate the algorithm's performance.

Here is my code so far:

LeaderElection.java

import java.io.FileWriter;import java.io.IOException;public class LeaderElection {    public static void main(String[] args) {        int[] networkSizes = {10, 20, 30}; // Example network sizes        try (FileWriter csvWriter = new FileWriter("leader_election_results.csv")) {            // Write CSV header            csvWriter.append("Ring ID,Ring Size,Sub-Ring Size,Leader ID,Total Message Count,Rounds,Termination Status\n");            // For each network size...            for (int size : networkSizes) {                RingOfRingsNetwork network = new RingOfRingsNetwork(size, 10);                // Ensure unique IDs across all sub-rings                network.ensureUniqueIds();                // Run algorithms...                network.runAsynchronousStartLCR();                network.runTerminatingLCR();                // Write to CSV after termination                writeStatsToCSV(network, csvWriter, size);            }        } catch (IOException e) {            e.printStackTrace();        }    }    private static void writeStatsToCSV(RingOfRingsNetwork network, FileWriter csvWriter, int size) throws IOException {        // Collect and write statistics for each ring to CSV        for (int i = 0; i < network.rings.size(); i++) {            RingNetwork ring = network.rings.get(i);            csvWriter.append(String.join(",",                 String.valueOf(i+1), // Ring ID                String.valueOf(size),                String.valueOf(10), // Assuming sub-ring size is 10 for simplicity                String.valueOf(ring.getLeaderId()),                String.valueOf(ring.processors.stream().mapToInt(Processor::getMessageCount).sum()),                String.valueOf(ring.processors.get(0).getMessageCount()), // Assuming all processors have the same round count                String.valueOf(ring.processors.stream().allMatch(p -> p.receivedTerminationMessage)) // Termination status            ));            csvWriter.append("\n");        }    }}

Processor.java

import java.util.*;class Processor {    int id;    Processor next;    boolean leader;    boolean active;    int messageCount;    boolean receivedTerminationMessage;    int ultimateLeaderId;    public Processor(int id) {        this.id = id;        this.leader = false;        this.active = true;        this.messageCount = 0;        this.receivedTerminationMessage = false;        this.ultimateLeaderId = -1; // Default value indicating no ultimate leader set    }    public void incrementMessageCount() {        this.messageCount++;        System.out.println("Processor " + id +" incremented message count to " + messageCount);    }    public int getMessageCount() {        return this.messageCount;    }    public void setLeader(boolean leader) {        this.leader = leader;    }    public boolean isActive() {        return this.active;    }    public void receiveId(int newId) {        if (newId > this.id) {            System.out.println("Processor " + id +" updated ID from " + this.id +" to " + newId);            this.id = newId;            incrementMessageCount(); // Increment message count when a new ID is received and set        }    }    public void passId() {        if (this.active) {            next.receiveId(this.id); // Forward the current ID to the next processor        }    }    public void terminate() {        this.active = false;        if (this.leader) {            this.leader = true;        }        System.out.println("Processor " + id +" is now terminated.");        if (!receivedTerminationMessage) {            next.receiveTerminationSignal(); // Propagate the termination signal to the next processor        }    }    public void setUltimateLeaderId(int id) {        this.ultimateLeaderId = id; // Set the ultimate leader ID        if (this.id == id) {            setLeader(true); // If the current ID matches the ultimate leader ID, set this processor as the leader        }        System.out.println("Processor " + this.id +" acknowledges ultimate leader ID: " + this.ultimateLeaderId);        // Propagate the ultimate leader ID to the next processor only if the next processor's ID is not the same as the current processor's ID        if (next.id != this.id) {            next.setUltimateLeaderId(id);        }    }    public void receiveTerminationSignal() {        this.receivedTerminationMessage = true;        incrementMessageCount(); // Increment message count when a termination signal is received        terminate(); // Terminate the processor when a termination signal is received    }    public void setTerminationStatus(boolean status) {        this.active = !status;    }    public int getUltimateLeaderId() {        return this.ultimateLeaderId;    }}

RingNetwork.java

import java.util.List;import java.util.ArrayList;import java.util.Random;class RingNetwork {    List<Processor> processors;    int size;    int leaderId; // ID of the elected leader    int totalMessageCount; // Total messages sent during the election    int roundCount; // Total rounds taken to elect a leader    public RingNetwork(int size) {        this.size = size;        this.processors = new ArrayList<>();        this.leaderId = 0;        this.totalMessageCount = 0;        this.roundCount = 0;        // Initialize processors and their next pointers        for (int i = 0; i < size; i++) {            processors.add(new Processor(i));        }        for (int i = 0; i < size; i++) {            Processor current = processors.get(i);            current.next = processors.get((i + 1) % size);        }        // Print the initial state of the ring        System.out.println("Initial state:");        for (Processor p : processors) {            System.out.println("Processor " + p.id +" -> Next Processor " + p.next.id);        }    }    public int getLeaderId() {        return this.leaderId;    }    public int getTotalMessageCount() {        return this.totalMessageCount;    }    public int getRoundCount() {        return this.roundCount;    }    public void setUltimateLeaderId(int id) {        this.leaderId = id;        // Optionally, update all processors in this ring with the ultimate leader ID        for (Processor p : processors) {            p.setUltimateLeaderId(id);        }    }    public void terminate() {        for (Processor processor : processors) {            processor.terminate();            processor.setTerminationStatus(true); // Set the termination status        }    }    public void runAsynchronousStartLCR() {        Random rand = new Random();        int maxRounds = 1000; // Maximum number of rounds to prevent infinite loop        // Assign random IDs and reset counts        for (Processor processor : processors) {            processor.id = rand.nextInt(Integer.MAX_VALUE);        }        this.totalMessageCount = 0;        this.roundCount = 0;        boolean electedLeader = false;        while (!electedLeader && this.roundCount < maxRounds) {            this.roundCount++;            for (Processor p : processors) {                if (p.isActive()) {                    Processor nextActiveProcessor = p.next;                    while (!nextActiveProcessor.isActive()) {                        nextActiveProcessor = nextActiveProcessor.next;                    }                    nextActiveProcessor.receiveId(p.id);                    this.totalMessageCount++;                }                if (p.isActive() && p.id == p.next.id) {                    electedLeader = true;                    p.setLeader(true);                    this.leaderId = p.id;                    System.out.println("Leader elected: Processor " + p.id);                    break; // Exit the loop as soon as a leader is elected                }            }            // Print the state of the ring at the end of each round            System.out.println("End of round " + this.roundCount +":");            for (Processor p : processors) {                System.out.println("Processor " + p.id +" -> Next Processor " + p.next.id);            }        }    }    public void runTerminatingLCR() {        // Ensure leader is elected and all processors are aware of the leader ID before terminating        if (this.leaderId == 0 || processors.stream().anyMatch(p -> p.getUltimateLeaderId() != this.leaderId)) {            System.out.println("Cannot terminate: Leader has not been elected or not all processors are aware of the leader ID");            return;        }        // Terminate all processors in this ring        terminate();        // Print the state of the ring after termination        System.out.println("State after termination:");        for (Processor p : processors) {            if (p.isActive()) {                System.out.println("Processor " + p.id +" is still active");            } else {                System.out.println("Processor " + p.id +" is terminated");            }        }    }}

RingOfRingsNetwork.java

import java.util.ArrayList;import java.util.List;public class RingOfRingsNetwork {    List<RingNetwork> rings;    int totalMessageCount = 0;    int totalRounds = 0;    public RingOfRingsNetwork(int numberOfRings, int sizeOfEachRing) {        rings = new ArrayList<>();        for (int i = 0; i < numberOfRings; i++) {            rings.add(new RingNetwork(sizeOfEachRing));        }        ensureUniqueIds();    }    public void ensureUniqueIds() {        int id = 0;        for (RingNetwork ring : rings) {            for (Processor processor : ring.processors) {                processor.id = id++;            }        }    }    public void runAsynchronousStartLCR() {        for (RingNetwork ring : rings) {            ring.runAsynchronousStartLCR();            totalMessageCount += ring.getTotalMessageCount();            totalRounds += ring.getRoundCount();        }        electUltimateLeader();    }    public void electUltimateLeader() {        RingNetwork mainRing = new RingNetwork(rings.size());        for (int i = 0; i < rings.size(); i++) {            mainRing.processors.get(i).id = rings.get(i).getLeaderId();        }        mainRing.runAsynchronousStartLCR();        int ultimateLeaderId = mainRing.getLeaderId();        for (RingNetwork ring : rings) {            ring.setUltimateLeaderId(ultimateLeaderId);        }        totalMessageCount += mainRing.getTotalMessageCount();        totalRounds += mainRing.getRoundCount();    }    public void runTerminatingLCR() {        for (RingNetwork ring : rings) {            ring.runTerminatingLCR();        }    }}

Output

Repetition: The terminal output shows that multiple processors are acknowledging the ultimate leader ID multiple times. This could indicate that processors are either receiving the leader election message multiple times or the algorithm is not properly terminating after acknowledging the leader.

Leader ID Consistency: In the terminal output, all processors acknowledge the same ultimate leader ID, which seems consistent. However, the correctness of this leader ID (i.e., whether it's truly the maximum ID across all processors) needs to be verified against the algorithm's requirements.

Termination Status: In the CSV output, all rings are marked with a termination status of "FALSE," and the rounds are recorded as "0," which suggests that the algorithm is not progressing through rounds as expected, or the rounds and termination status are not being tracked or updated correctly.

Message Count: The total message count in the CSV output is uniformly "6" across different ring sizes, which seems unlikely, especially if the algorithm is supposed to scale with the network size. This could indicate an issue with how messages are counted or a lack of variability in the test cases.

Algorithm Performance: The uniformity in message count and zero rounds across all test cases in the CSV output might point to an issue with the algorithm's implementation, particularly in how it progresses through rounds and concludes the election process.

Overall, the outputs suggest potential issues with message handling, round progression, termination detection, and possibly the correctness of the leader election process itself. Further investigation and debugging of the algorithm's implementation are needed to address these inconsistencies and ensure it meets the specified requirements.


Viewing all articles
Browse latest Browse all 12111

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>