0% found this document useful (0 votes)
20 views

DC Assignment

The document discusses implementing distributed computing concepts like RMI, leader election using the Bully algorithm, logical clocks and weighted round robin load balancing. It provides code snippets to implement these concepts along with analyzing their time and space complexity.

Uploaded by

beg4mercy3000
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)
20 views

DC Assignment

The document discusses implementing distributed computing concepts like RMI, leader election using the Bully algorithm, logical clocks and weighted round robin load balancing. It provides code snippets to implement these concepts along with analyzing their time and space complexity.

Uploaded by

beg4mercy3000
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/ 23

Academic Year: 2023-24 Semester: VI

Class/Branch: TE/DS Subject:Distributed Computing


Assignment No. 1
Course Outcome(CO)
CO1 To summarize the knowledge of the basic elements and concepts related to distributed
system technologies.

CO2 To apply middleware technologies such as RPC, RMI and Object based middleware to
support distributed applications.

CO3 To analyze various techniques used for clock synchronization and mutual exclusion.

CO4 To apply the concepts of Resource and Process management for load balancing & load
sharing.

CO5 To explain the concepts of Consistency and Replication Management.

CO6 To apply distributed file systems like NFS, AFS to build distributed applications.

Q. 1 Develop Client Server interaction using RMI to facilitate remote communication between a
client and a server by allowing objects to be invoked remotely. (CO2, L3)
Solution:
Step 1: Create RMIPracIF.java file
import java.io.*;
import java.rmi.*;
import java.rmi.server.*;

public interface RMIPracIF extends Remote


{
public String welcome(String str)throws RemoteException;

}
Step 2: Create RMIIFImpl.java file
import java.rmi.*;
import java.rmi.server.*;

public class RMIIFImpl extends UnicastRemoteObject implements RMIPracIF


{
public RMIIFImpl()throws RemoteException{}
public String welcome(String str)
{
String res="Hi," + str + " have a great time in the Corporate World";
return res;
}
}
Step 3: create RMIServer.java file
import java.rmi.*;
import java.rmi.server.*;

public class RMIServer extends RMIIFImpl


{
RMIServer()throws Exception{}
public static void main(String a[])throws Exception
{
RMIIFImpl ri=new RMIIFImpl();
Naming.rebind("StudName",ri);
System.out.println("Server initiated....");
}
}

Step 4: create RMIClient.java file


import java.rmi.*;
import java.rmi.server.*;
public class RMIClient
{
private static final String HOST_NAME="localhost";
public static void main(String arg[]) throws Exception
{
try
{
RMIPracIF r = (RMIPracIF)Naming.lookup("//"+HOST_NAME+"/StudName");
String s1 = r.welcome("GIT-BE Comps");
System.out.println(s1);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Output:

Q.2 Implement the Bully Algorithm for conducting elections in distributed systems, ensuring the
selection of a leader node with the highest priority and conclude time as well as space
complexity.(CO3, L4)
Solution:
class Node:
def __init__(self, node_id):
self.node_id = node_id
self.leader = None

def __str__(self):
return f"Node {self.node_id}"

def start_election(self, nodes):


"""Initiate an election process."""
print(f"{self} initiates an election.")
higher_nodes = [node for node in nodes if node.node_id > self.node_id]

# Send election messages to higher nodes


for higher_node in higher_nodes:
higher_node.receive_election(self)

def receive_election(self, initiating_node):


"""Receive an election message and respond accordingly."""
print(
f"{self} receives an election message from {initiating_node}.")
if self.leader is None or self.node_id > self.leader.node_id:
print(
f"{self} sends an OK message to {initiating_node}.")
initiating_node.receive_ok(self)
else:
print(
f"{self} ignores the election message from {initiating_node}.")

def receive_ok(self, responding_node):


"""Receive an OK message and acknowledge the leader."""
print(
f"{self} receives an OK message from {responding_node}.")
self.leader = responding_node
print(
f"{self} acknowledges {responding_node} as the leader.")

if __name__ == "__main__":
# Create nodes with unique IDs
nodes = [Node(1), Node(2), Node(3), Node(4), Node(5), Node(6), Node(7)]

# Simulate leader election


for node in nodes:
node.start_election(nodes)

# Find the elected leader


elected_leader = max(nodes, key=lambda node: node.node_id)

print(f"\n{elected_leader} is elected as the leader.")

Output:
Time Complexity : O(n^2) in the worst case scenario, where n is the number of processes.
Space complexity : O(n)

Q.3 Develop a C program to implement Lamport's Logical Clock for timestamping events in a
distributed system, ensuring causal ordering of events across multiple processes. Analyze time
and space complexity for the same. (CO3,L4)
Solution:
// Java program to illustrate the Lamport's Logical Clock
import java.util.*;
public class GFG {
// Function to find the maximum timestamp between 2 events
static int max1(int a, int b)
{
// Return the greatest of the two
if (a > b)
return a;
else
return b;
}
// Function to display the logical timestamp
static void display(int e1, int e2, int p1[], int p2[])
{
int i;
System.out.print(
"\nThe time stamps of events in P1:\n");
for (i = 0; i < e1; i++) {
System.out.print(p1[i] + " ");
}
System.out.println(
"\nThe time stamps of events in P2:");
// Print the array p2[]
for (i = 0; i < e2; i++)
System.out.print(p2[i] + " ");
}
// Function to find the timestamp of events
static void lamportLogicalClock(int e1, int e2,int m[][])
{
int i, j, k;
int p1[] = new int[e1];
int p2[] = new int[e2];
// Initialize p1[] and p2[]
for (i = 0; i < e1; i++)
p1[i] = i + 1;
for (i = 0; i < e2; i++)
p2[i] = i + 1;
for (i = 0; i < e2; i++)
System.out.print("\te2" + (i + 1));
for (i = 0; i < e1; i++) {
System.out.print("\n e1" + (i + 1) + "\t");
for (j = 0; j < e2; j++)
System.out.print(m[i][j] + "\t");
}
for (i = 0; i < e1; i++) {
for (j = 0; j < e2; j++) {
// Change the timestamp if the message is sent
if (m[i][j] == 1) {
p2[j] = max1(p2[j], p1[i] + 1);
for (k = j + 1; k < e2; k++)
p2[k] = p2[k - 1] + 1;
}
// Change the timestamp if the message is received
if (m[i][j] == -1) {
p1[i] = max1(p1[i], p2[j] + 1);
for (k = i + 1; k < e1; k++)
p1[k] = p1[k - 1] + 1;
}
}
}
// Function Call
display(e1, e2, p1, p2);
}
public static void main(String args[])
{
int e1 = 5, e2 = 3;
int m[][] = new int[5][3];
// message is sent and received between two process
m[0][0] = 0;
m[0][1] = 0;
m[0][2] = 0;
m[1][0] = 0;
m[1][1] = 0;
m[1][2] = 1;
m[2][0] = 0;
m[2][1] = 0;
m[2][2] = 0;
m[3][0] = 0;
m[3][1] = 0;
m[3][2] = 0;
m[4][0] = 0;
m[4][1] = -1;
m[4][2] = 0;
// Function Call
lamportLogicalClock(e1, e2, m);
}
}
Output:

Time Complexity: O(e1 * e2 * (e1 + e2))


Space Complexity: O(e1 + e2)

Q.4 Implement a Weighted Round Robin Load Balancing Algorithm to distribute incoming
requests among servers based on assigned weights, optimizing resource utilization and
performance. (CO4, L3)
Solution:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
class WeightedRoundRobinBalancer {
private List<Server> servers;
private int[] cumulativeWeights;
private int totalWeight;
private int currentIndex;
private Random random;
public WeightedRoundRobinBalancer(List<Server> servers) {
this.servers = new ArrayList<>(servers);
this.totalWeight = calculateTotalWeight(servers);
this.cumulativeWeights = calculateCumulativeWeights(servers);
this.currentIndex = 0;
this.random = new Random();
}
private int calculateTotalWeight(List<Server> servers) {
int totalWeight = 0;
for (Server server : servers) {
totalWeight += server.getWeight();
}
return totalWeight;
}
private int[] calculateCumulativeWeights(List<Server> servers) {
int[] cumulativeWeights = new int[servers.size()];
cumulativeWeights[0] = servers.get(0).getWeight();
for (int i = 1; i < servers.size(); i++) {
cumulativeWeights[i] = cumulativeWeights[i - 1] +
servers.get(i).getWeight();
}
return cumulativeWeights;
}

public Server getNextServer() {


int randomValue = random.nextInt(totalWeight);
for (int i = 0; i < cumulativeWeights.length; i++) {
if (randomValue < cumulativeWeights[i]) {
currentIndex = i;
break;
}
}
return servers.get(currentIndex);
}
// Inner class representing a server with a weight
static class Server {
private String name;
private int weight;

public Server(String name, int weight) {


this.name = name;
this.weight = weight;
}

public String getName() {


return name;
}

public int getWeight() {


return weight;
}
}
}
public class WeightedRoundRobinExample {
public static void main(String[] args) {
// Sample list of servers with weights
List<WeightedRoundRobinBalancer.Server> serverList = new ArrayList<>();
serverList.add(new WeightedRoundRobinBalancer.Server("Server1", 3));
serverList.add(new WeightedRoundRobinBalancer.Server("Server2", 2));
serverList.add(new WeightedRoundRobinBalancer.Server("Server3", 1));

// Create a weighted round-robin load balancer with the server list


WeightedRoundRobinBalancer balancer = new
WeightedRoundRobinBalancer(serverList);
// Simulate requests to the load balancer
for (int i = 0; i < 10; i++) {
WeightedRoundRobinBalancer.Server nextServer =
balancer.getNextServer();
System.out.println("Request " + (i + 1) + ": Routed to " +
nextServer.getName());
}
}
}
Output:

Q.5 Configure a distributed file system in distributed computing, applying procedural knowledge
to establish networked storage for shared data access and management. (CO6,L3)
Answer:
To set up a distributed file system, you will need:
● a computer running Windows Server 2012 or later that is not itself used a cluster node or
for file storage
● the DFS Namespaces and DFS Replication roles set up on the computer described above
● the DFS Namespaces and DFS Replication roles set up on all of the nodes
● a shared folder with full control permissions for the node1admin and node2admin users,
which will function as a backup folder when the main shared folder becomes
inaccessible.
To set up a distributed file system, complete the following steps:
● Add the DFS roles.
● Create shared folders.
● Create a namespace.
● Add the shared folders to the namespace.
● Set up replication.
● Set up priorities for the folder targets.
Adding the DFS roles
To add the DFS roles:
● Open Server Manager and click Add Roles and Features.
● At the Select server roles stage, expand the File and Storage Services and select the DFS
Namespaces and DFS Replication items.

Creating shared folders


Note:
● This folder must only be used to replicate data from the cluster.
● This folder must not be located on a cluster node or in the file storage.
● This folder must be accessible to all nodes.
To create a shared folder, open Server Manager, click File and Storage Services → Shares and
then click Tasks → New Share
Creating a namespace
Namespaces can be created and configured using the DFS Management console. You will need
to select a server, grant access permissions to users, and specify the type of the namespace.
To create a namespace:
● Open Server Manager and click Tools → DFS Management. In the DFS Management
snap-in that opens, click New Namespace
● Specify the name of the server that will host the namespace and click Next.
● Specify a name for the namespace and click Edit Settings

● In the Edit Settings dialog box, select the Use custom permissions and click Customize....
Next, grant full control permissions for the shared folder to the node1admin and
node2admin users.
● At the Namespace Type stage, select Domain-based namespace, then select the Enable
Windows Server 2008 mode option and click Next.

● Check to make sure that the specified settings are correct and click Create.
● Click Close to close the wizard.

Adding the shared folders to the namespace


In this step, you need to add the main and backup shared folders to the namespace.

To do this:
● In the DFS Management snap-in, click New Folder
● In the dialog box that opens, specify a name for the folder. This name will be
displayed in the namespace of the distributed file system.

● Specify the path to the shared folder and click OK.

● Repeat steps 1 through 3 to add the backup folder to the namespace. The added
folders will appear in the Folder targets list. When you are done, click OK.
● A message will appear saying that you can create a replication group. Click Yes to
create a replication group and start setting up replication.

Setting up replication
To set up replication, you need to create a replication group, specify a server, select a topology of
connections among group members, select a replication schedule, and specify replication
bandwidth. All of the above can be specified via the Replicate Folder Wizard:
● The wizard will suggest the names of the replication group and replicated folder. Edit
these names if necessary or keep the default names and click Next.
● The wizard will inform you if the folder targets can participate in replication. Review the
information in the Eligibility column and click Next.

● Select the server that contains the data to be replicated to folder targets and click Next.
● For the topology to be used, select Full mesh and click Next.

● For the replication schedule, select Replicate continuously using the specified bandwidth.
From the Bandwidth drop-down list, select Full and click Next.
● Check to make sure that the specified settings are correct and click Create.

● Once the replication group is created, click Close, to close the wizard.
● If a Replication Delay warning appears, click OK.

You might also like