0% found this document useful (0 votes)
15 views15 pages

DC Exp 8 Election Algorithms

Distributed Computing Experiment on Election Algorithm

Uploaded by

vivekagangwani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views15 pages

DC Exp 8 Election Algorithms

Distributed Computing Experiment on Election Algorithm

Uploaded by

vivekagangwani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 15

SUBJECT: Distributed Computing

Experiment No.: 8
Branch: COMPS A – Batch B
Date: 10/11/2024
Name: Hrishikesh Dalal, Dhureen Shettigar, Dhruv Doshi, Vivek
Gangwani
UID: 2022300019, 2022300023, 2022300024,2022300027

Batch: COMPS A (Batch B)


Instructor: Dr. Sudhir Dhage
Topic: Movie ticket booking system

Aim: To understand and implement the Election Algorithms in Distributed


System

Objective:

1. To explore the role of election algorithms in distributed systems for efficient


coordination.
2. To gain an understanding of the Bully and Ring election algorithms and
their mechanisms.
3. To implement and observe the operation of the Ring algorithm in a
distributed setup.

Theory:

In distributed systems, maintaining a single coordinator process is essential to


manage tasks, allocate resources, and handle requests. This is achieved through
election algorithms, which ensure that one process is designated as the
coordinator, while others operate as non-coordinator processes. Election
algorithms allow the system to establish this coordinator dynamically, especially
when nodes may enter or exit the network at any time.

The primary objective of an election algorithm is to reach a consensus among all


processes in a system regarding the coordinator, typically by designating the
process with the highest priority or ID. This consensus ensures a reliable and
stable central authority, enabling streamlined operation of the entire distributed
system.

Election Algorithms Overview:

The election problem in distributed computing involves selecting a coordinator


process from multiple processes on different machines, so that only one process
assumes the role of coordinator at a given time.

Election algorithms work within the following constraints:

● Peer-to-Peer Communication: Each process can communicate directly


with other processes.
● Unique Process IDs: Processes are assigned unique IDs, allowing the
system to prioritize higher IDs for the coordinator role.
● Distributed Nature: Since the election process is distributed, no single
machine oversees the process.
Bully Algorithm:

In the Bully Algorithm, any process that detects the absence of a coordinator can
initiate an election. This algorithm operates under the following assumptions:

1. A process that suspects the coordinator has failed will send an "Election"
message to all processes with higher priority.
2. If no higher-priority process responds, the initiating process assumes the
role of coordinator and informs all lower-priority processes by sending an
"Elected" message.
3. If a higher-priority process responds, the initiating process waits for a set
duration to allow the higher-priority process to complete the election.

Detailed Steps for Bully Algorithm:

● Initiator Process: When a process, Pi, detects the absence of a


coordinator, it initiates the election by messaging all processes with higher
IDs.
● Coordinator Election: If no higher-priority process replies, Pi becomes
the coordinator and notifies other lower-priority processes.
● Election Continuation: If Pi receives a reply from a higher-priority
process, it halts its election attempt and waits for a new coordinator
announcement. If the process with the highest priority fails to assume the
coordinator role, Pi resumes the election.
Bully Algo Ring Algo

Ring Algorithm:

In the Ring Algorithm, processes are arranged in a logical ring, and each process
communicates only with its immediate neighbor. The algorithm assumes the
message continues circulating around the ring, even if a process crashes.

Detailed Steps for Ring Algorithm:

1. Initiating Election: Any process, Pi, that notices the coordinator’s


absence begins the election by initializing an active list and sending an
"Elect(i)" message to its right neighbor.
2. Active List Update: Each process adds its ID to the active list as it
receives the "Elect(j)" message.
○ If the active list reaches the origin process (completing the ring), the
initiator selects the highest ID in the list as the coordinator.
3. Electing a Coordinator: The process with the highest ID from the active
list is chosen as the new coordinator, and an "Elected" message is passed
around the ring to inform each process of the coordinator change.

In both algorithms, the selected coordinator is responsible for synchronizing


tasks and handling requests, ensuring the distributed system operates with a
central management process despite being spread across multiple machines.
These mechanisms are crucial for fault tolerance, allowing the system to
dynamically adjust the coordinator role in response to changes in process
availability.
Ring Algorithm
Code:
class Process:

def __init__(self, id, active_status=True):

self.id = id

self.active_status = active_status

class Ring:

def __init__(self):

self.n = int(input("Enter number of processes: "))

if self.n <= 0:

raise ValueError("Number of processes must be positive")

self.processes = [Process(i) for i in range(self.n)]

def get_max_id_process(self):

"""Find the process with the highest ID that is still active."""

max_id = -1

max_process = None

for process in self.processes:

if process.active_status and process.id > max_id:

max_id = process.id

max_process = process

return max_process

def get_process_index(self, process_id):


"""Get the index of a process by its ID."""

for i, process in enumerate(self.processes):

if process.id == process_id:

return i

return -1

def get_next_active_process(self, current_idx):

"""Find the next active process in the ring."""

next_idx = (current_idx + 1) % self.n

while next_idx != current_idx:

if self.processes[next_idx].active_status:

return next_idx

next_idx = (next_idx + 1) % self.n

return current_idx

def perform_election(self):

# Simulate failure of the process with highest ID

failed_process = self.get_max_id_process()

if not failed_process:

print("No active processes in the ring.")

return

failed_process.active_status = False

print(f"\nProcess {failed_process.id} has failed.\n")

# Get initiator process

while True:
try:

initiator_id = int(input("Enter the process ID to initiate


election: "))

initiator_idx = self.get_process_index(initiator_id)

if initiator_idx == -1 or not
self.processes[initiator_idx].active_status:

print("Invalid or failed process ID. Please choose an active


process.")

continue

break

except ValueError:

print("Please enter a valid process ID.")

# Election Phase

current_idx = initiator_idx

election_message = [initiator_id] # Start with initiator's ID

print("\nElection Phase:")

while True:

next_idx = self.get_next_active_process(current_idx)

# Add current process ID to election message if not already present

if self.processes[current_idx].id not in election_message:

election_message.append(self.processes[current_idx].id)

print(f"Process {self.processes[current_idx].id} passes Election


message to Process {self.processes[next_idx].id}")
print(f"Election message: {election_message}")

# If we've completed the ring and returned to initiator

if next_idx == initiator_idx and len(election_message) > 1:

break

current_idx = next_idx

# Select coordinator (highest ID in election_message)

coordinator_id = max(election_message)

coordinator_idx = self.get_process_index(coordinator_id)

print(f"\nProcess {coordinator_id} becomes the new coordinator\n")

# Coordinator Announcement Phase

print("\nCoordinator Announcement Phase:")

current_idx = coordinator_idx

visited_processes = set([coordinator_id])

while True:

next_idx = self.get_next_active_process(current_idx)

if self.processes[next_idx].id not in visited_processes:

print(f"Process {self.processes[current_idx].id} passes


Coordinator({coordinator_id}) message to Process {self.processes[next_idx].id}")

visited_processes.add(self.processes[next_idx].id)

current_idx = next_idx

else:
break

print("\nEnd of election")

def main():

try:

ring = Ring()

ring.perform_election()

except ValueError as e:

print(f"Error: {e}")

except KeyboardInterrupt:

print("\nProgram terminated by user")

if __name__ == "__main__":

main()

Output:
Bully Algorithm

Code:
class Process:

def __init__(self, id, active_status=True):

self.id = id

self.active_status = active_status

self.coordinator = None

self.timeout = False # Simulates timeout in response waiting

class BullyElection:

def __init__(self):

self.n = int(input("Enter number of processes: "))

if self.n <= 0:

raise ValueError("Number of processes must be positive")

self.processes = [Process(i) for i in range(self.n)]

self.current_coordinator = self.get_max_id_process()

# Set initial coordinator for all processes

for process in self.processes:

process.coordinator = self.current_coordinator.id

def get_max_id_process(self):

"""Find the process with the highest ID that is still active."""

max_id = -1

max_process = None
for process in self.processes:

if process.active_status and process.id > max_id:

max_id = process.id

max_process = process

return max_process

def get_higher_processes(self, process_id):

"""Get list of active processes with higher IDs."""

return [p for p in self.processes

if p.active_status and p.id > process_id]

def simulate_process_failure(self):

"""Simulate failure of the current coordinator."""

if self.current_coordinator:

self.current_coordinator.active_status = False

print(f"\nCoordinator (Process {self.current_coordinator.id}) has


failed.")

self.current_coordinator = None

return True

return False

def send_election_message(self, sender_id, receiver_id):

"""Simulate sending an election message."""

print(f"Process {sender_id} sends Election message to Process


{receiver_id}")
def send_ok_message(self, sender_id, receiver_id):

"""Simulate sending an OK message."""

print(f"Process {sender_id} sends OK message to Process {receiver_id}")

def send_coordinator_message(self, coordinator_id, receiver_id):

"""Simulate sending a coordinator message."""

print(f"Process {coordinator_id} sends Coordinator message to Process


{receiver_id}")

def start_election(self, initiator_id):

"""Start an election process initiated by the given process."""

print(f"\nElection initiated by Process {initiator_id}")

# Get higher-priority active processes

higher_processes = self.get_higher_processes(initiator_id)

if not higher_processes:

# If no higher priority processes exist, this process becomes


coordinator

self.become_coordinator(initiator_id)

return

# Send election messages to higher-priority processes

received_ok = False

for process in higher_processes:

self.send_election_message(initiator_id, process.id)
if process.active_status and not process.timeout:

self.send_ok_message(process.id, initiator_id)

received_ok = True

# Higher priority process starts a new election

self.start_election(process.id)

if not received_ok:

# If no OK messages received, this process becomes coordinator

self.become_coordinator(initiator_id)

def become_coordinator(self, process_id):

"""Make a process the coordinator and announce it."""

print(f"\nProcess {process_id} becomes the coordinator")

self.current_coordinator = self.processes[process_id]

# Send coordinator messages to all other active processes

for process in self.processes:

if process.active_status and process.id != process_id:

self.send_coordinator_message(process_id, process.id)

process.coordinator = process_id

def perform_election(self):

"""Main election procedure."""

# First, simulate failure of current coordinator


if not self.simulate_process_failure():

print("No active coordinator to fail.")

return

# Get initiator process ID

while True:

try:

initiator_id = int(input("Enter the process ID to initiate


election: "))

if not (0 <= initiator_id < self.n):

print(f"Invalid process ID. Please enter a number between 0


and {self.n-1}")

continue

if not self.processes[initiator_id].active_status:

print("This process has failed. Please choose an active


process.")

continue

break

except ValueError:

print("Please enter a valid process ID.")

# Start the election process

self.start_election(initiator_id)

# Print final state

print("\nFinal state:")

for process in self.processes:


if process.active_status:

print(f"Process {process.id} is active and its coordinator is


Process {process.coordinator}")

else:

print(f"Process {process.id} has failed")

def main():

try:

bully = BullyElection()

bully.perform_election()

except ValueError as e:

print(f"Error: {e}")

except KeyboardInterrupt:

print("\nProgram terminated by user")

if __name__ == "__main__":

main()

Output:
Conclusion:
In this practical study, we successfully implemented and analyzed two fundamental distributed
election algorithms - the Ring Algorithm and the Bully Algorithm - using Python.
Our implementation demonstrated distinct characteristics of each algorithm. The Ring Algorithm
showed consistent message complexity, requiring exactly 2(n-1) messages for any election
process: (n-1) messages for the election phase and (n-1) messages for coordinator
announcement, regardless of which process initiates the election. In contrast, the Bully
Algorithm's performance varied significantly based on the initiating process. When initiated by
the lowest ID process, it required Θ(n²) messages, but performed more efficiently when higher
ID processes initiated the election.
Through this implementation, we gained practical insights into distributed systems and
successfully demonstrated how both algorithms handle coordinator failures with different
approaches and trade-offs.

You might also like