From fee5c5608e8ac442259cc270dc61ad83739440a2 Mon Sep 17 00:00:00 2001 From: Malay Virendra Bhavsar Date: Sun, 20 Oct 2024 12:15:53 -0500 Subject: [PATCH] Initial Commit --- .gitignore | 2 + ChandyLamport.java | 246 +++++++++++++++++++++++++++++++++++++++++++++ Client.java | 146 +++++++++++++++++++++++++++ Message.java | 33 ++++++ Node.java | 196 ++++++++++++++++++++++++++++++++++++ README.md | 140 ++++++++++++++++++++++++++ Server.java | 85 ++++++++++++++++ cleanup.sh | 54 ++++++++++ config.txt | 12 +++ launcher.sh | 64 ++++++++++++ script.bat | 10 ++ 11 files changed, 988 insertions(+) create mode 100644 .gitignore create mode 100644 ChandyLamport.java create mode 100644 Client.java create mode 100644 Message.java create mode 100644 Node.java create mode 100644 README.md create mode 100644 Server.java create mode 100644 cleanup.sh create mode 100644 config.txt create mode 100644 launcher.sh create mode 100644 script.bat diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7ea4f14 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/*.class +/abc/* \ No newline at end of file diff --git a/ChandyLamport.java b/ChandyLamport.java new file mode 100644 index 0000000..27552ba --- /dev/null +++ b/ChandyLamport.java @@ -0,0 +1,246 @@ +import java.util.*; +import java.io.*; +import java.net.*; + +enum Color { + BLUE, RED +}; + +public class ChandyLamport { + public Node node; + public int parentId; + + public int markersSent = 0; + public int markerReceived = 0; + + public int msgSent = 0; + public int msgReceived = 0; + + public Color color; + + public Map> localSs = new HashMap<>(); + public boolean state; + + public ChandyLamport(Node node) { + this.node = node; + this.color = Color.BLUE; + this.state = false; + } + + public void initSpanningTree() throws Exception { + System.out.println("[INIT] Snapshot Spanning process at NODE: " + this.node.id); + + this.color = Color.RED; + + this.printStatus(); + + for (Map.Entry entry : node.idToChannelMap.entrySet()) { + Socket channel = entry.getValue(); + Message msg = new Message(node.id); + System.out.println("[CL] Sending " + msg.messageType + " to Node" + entry.getKey()); + Client.sendMsg(msg, channel, node); + this.markersSent += 1; + } + } + + public void printStatus() { + System.out.println("========== Snapshot Status =========="); + System.out.println("Color: " + color); + System.out.println("MARKERS Sent: " + markersSent); + System.out.println("MARKERS Received:" + markerReceived); + System.out.println("====================================\n"); + } + + public void handleMarkerMessageFromParent(Message msg) throws Exception { + if (this.color == Color.RED) { + System.out.println("[REJECTED] MARKER message from Node " + msg.id); + Message rejectMarker = new Message(); + Socket channel = this.node.idToChannelMap.get(msg.id); + synchronized(node) { + Client.sendMsg(rejectMarker, channel, node); + } + return; + } + + this.color = Color.RED; + this.parentId = msg.id; + + for (Map.Entry entry : node.idToChannelMap.entrySet()) { + Socket channel = entry.getValue(); + + Message msg = new Message(node.id); + synchronized (node) { + Client.sendMsg(msg, channel, node); + this.markersSent++; + } + } + + System.out.println("[ACCEPTED] MARKER message from Node " + msg.id); + checkTreeCollapse(); + } + + public void handleMarkerRejectionMsg(Message msg) throws Exception { + this.markerReceived += 1; + checkTreeCollapse(); + } + + public void handleSnapshotResetMsg(Message msg) throws Exception { + if (this.color == Color.BLUE) return; + synchronized (node) { + System.out.println("[SNAPSHOT] Snapshot Reset"); + this.reset(); + } + + for (Map.Entry entry : node.idToChannelMap.entrySet()) { + if (entry.getKey() == 0 || msg.parents.contains(entry.getKey())) continue; + Socket channel = entry.getValue(); + + Set parents = new HashSet<>(msg.parents); + parents.add(this.node.id); + Message resetMsg = new Message(msg.message, parents); + synchronized (node) { + Client.sendMsg(resetMsg, channel, node); + } + } + } + + public void handleMarkerRepliesFromChild(Message msg) throws Exception { + this.localSs.putAll(msg.localSs); + + this.msgSent += msg.msgSent; + this.msgReceived += msg.msgReceived; + + if (msg.state == true) { + this.state = true; + } + + this.markerReceived++; + System.out.println("[ACCEPTED] MARKER message from Node " + msg.id); + printStatus(); + checkTreeCollapse(); + }; + + public void checkTreeCollapse() throws Exception { + System.out.println("[COLLAPSE] Tree collapse at Node-" + node.id); + if (markersSent == markerReceived) { + this.localSs.put(node.id, node.clock); + this.msgSent += node.msgSent; + this.msgReceived += node.msgReceived; + if (node.state == true) { + System.out.println("[ALERT] Node is still active"); + this.state = true; + } + + genOutput(node.id, node.clock); + + if (node.id == 0) { + handleConvergence(); + return; + } + Message markerReplyMsg = new Message( + node.id, + localSs, + state, + msgSent, + msgReceived); + Client.sendMsg(markerReplyMsg, node.idToChannelMap.get(parentId), node); + } + + } + + public void handleConvergence() throws Exception { + System.out.println("=============== Convergence ==============="); + System.out.println("Snapshots(Local): " + localSs); + System.out.println("Messages sent: " + msgSent); + System.out.println("Messages received: " + msgReceived); + System.out.println("States gathered: " + state); + System.out.println("=============================================\n"); + verifyConsistency(localSs, node.totalNodes); + this.initSnapshotReset(); + } + + public void initSnapshotReset() throws Exception { + System.out.println("[INIT] Snapshot Reset"); + + this.color = Color.BLUE; + Boolean flag = false; + + for (Map.Entry entry : node.idToChannelMap.entrySet()) { + Socket channel = entry.getValue(); + String msgText; + if (this.state == true || this.msgSent != this.msgReceived) { + msgText = "System not terminated"; + } else { + msgText = "System terminated"; + flag = true; + } + Set parents = new HashSet<>(); + parents.add(0); + Message msg = new Message(msgText, parents); + synchronized (node) { + Client.sendMsg(msg, channel, node); + } + } + this.reset(); + if (node.id == 0 && !flag) { + System.out.println("[SNAPSHOT] Not Terminated"); + try { + System.out.println("[SNAPSHOT] Process delayed for " + node.snapshotDelay); + Thread.sleep(this.node.snapshotDelay); + initSpanningTree(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } else { + System.out.println("[SNAPSHOT]: Terminated"); + } + } + + public void reset() { + this.state = false; + this.color = Color.BLUE; + this.markerReceived = 0; + this.markersSent = 0; + this.msgSent = 0; + this.msgReceived = 0; + this.localSs = new HashMap<>(); + } + + public static void verifyConsistency(Map> gatheredlocalSs, int n) { + boolean flag = true; + for (Map.Entry> entry : gatheredlocalSs.entrySet()) { + int curr = entry.getKey(); + for (int i = 0; i < n; i++) { + if (gatheredlocalSs.containsKey(i)) { + int ref = gatheredlocalSs.get(i).get(i); + for (int j = 0; j < n; j++) { + if (gatheredlocalSs.containsKey(j)) { + if (gatheredlocalSs.get(j).get(i) > ref) { + flag = false; + } + } + } + } + } + } + + System.out.println("================================"); + System.out.println("Conistency: " + (flag ? "VERIFIED" : "INVALID")); + System.out.println("================================\n"); + } + + public static void genOutput(int nodeId, Vector clock) throws Exception { + String filename = "config-" + nodeId + ".out"; + + FileOutputStream stream = new FileOutputStream(filename, true); + PrintWriter writer = new PrintWriter(stream); + + for (Integer i : clock) { + writer.print(i + " "); + } + writer.println(); + + writer.close(); + stream.close(); + } +} \ No newline at end of file diff --git a/Client.java b/Client.java new file mode 100644 index 0000000..fe81717 --- /dev/null +++ b/Client.java @@ -0,0 +1,146 @@ +import java.util.*; +import java.io.*; +import java.net.*; + +public class Client { + + List channelList; + Node node; + + public Client(Node node) { + this.node = node; + synchronized (node) { + this.channelList = connectChannels(node); + } + } + + public List connectChannels(Node node) { + System.out.println("[CLIENT] Making channel array..."); + List channelList = new ArrayList<>(); + for (Integer neighbour : node.neighbours.get(node.id)) { + String host = node.getHost(neighbour); + int port = node.getPort(neighbour); + try { + Socket client = new Socket(); + client.connect(new InetSocketAddress(host, port)); + client.setKeepAlive(true); + channelList.add(client); + node.idToChannelMap.put(node.hostToId_PortMap.get(host).get(0), client); + System.out.println("[CLIENT] Connected to " + host + ":" + port); + } catch (IOException error) { + System.out.println("[CLIENT] Unable to connect to " + host + ":" + port); + } + } + return channelList; + } + + public void mapProtocol() { + while (true) { + if (node.msgSent >= node.maxNumber) { + System.out.println("[CLIENT] Node state (ACTIVE -> PASSIVE) permanently..."); + node.state = false; + sendCustomEnd(); + node.pem_passive = true; + break; + } + + if (node.state == true) { + Random random = new Random(); + int count = random.nextInt(node.maxPerActive - node.minPerActive + 1) + node.minPerActive; + synchronized (node) { + sendBulkMsg(count); + } + } else { + try { + System.out.println("[CLIENT] Node state (ACTIVE -> PASSIVE) after sending " + node.msgSent + "/" + + node.maxNumber + " messages"); + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + public void sendBulkMsg(int count) { + + // System.out.println(String.format("Sending %d messages to neighbours...", + // count)); + Random random = new Random(); + + for (int i = 0; i < count; i++) { + if (node.msgSent >= node.maxNumber) { + node.state = false; + break; + } + int randomNumber = random.nextInt(this.channelList.size()); + int destination = node.neighbours.get(node.id).get(randomNumber); + // System.out.println("Sent a message to " + destination); + node.sndClk.set(destination, node.sndClk.get(destination) + 1); + Socket channel = channelList.get(randomNumber); + String messageString = "Hello " + node.name + " (" + node.msgSent + 1 + "/" + node.maxNumber + ")"; + Message msg = new Message(node.id, node.clock, messageString); + Client.sendMsg(msg, channel, node); + + try { + Thread.sleep(node.minSendDelay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + node.changeState(); + + } + + public void sendCustomEnd() { + for (Socket channel : this.channelList) { + Message msg = new Message(node.id, node.id); + Client.sendMsg(msg, channel, node); + } + + try { + node.pem_passive = true; + Thread.sleep(node.minSendDelay); + if (node.pem_passive && node.custom_end == node.neighbours.get(node.id).size()) + node.printNodeVectorClock(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public static void sendMsg(Message msg, Socket channel, Node node) { + try { + OutputStream outStream = channel.getOutputStream(); + DataOutputStream dataOut = new DataOutputStream(outStream); + + byte[] msgBytes = msg.toMessageBytes(); + dataOut.writeInt(msgBytes.length); + dataOut.write(msgBytes); // Send message + dataOut.flush(); + + if (msg.messageType == MessageType.APPLICATION) { + int prevEntry = node.clock.get(node.id); + node.clock.set(node.id, prevEntry + 1); + node.msgSent++; + } + } catch (IOException error) { + error.printStackTrace(); + } + } + + public void init() { + Thread client = new Thread(() -> { + System.out.println("[CLIENT] Starting..."); + try { + if (node.id == 0) { + node.changeState(); + } + System.out.println("[CLIENT] Init Map Protocol..."); + node.client.mapProtocol(); + } catch (Exception e) { + e.printStackTrace(); + } + }); + client.start(); + } +} \ No newline at end of file diff --git a/Message.java b/Message.java new file mode 100644 index 0000000..eb772c7 --- /dev/null +++ b/Message.java @@ -0,0 +1,33 @@ +import java.io.*; +import java.util.*; + +enum MessageType { + REQUEST, REPLY +}; + +public class Message implements Serializable { + public int id = -1; + public MessageType messageType; + public Vector clock; + + public Message(MessageType type, int id, Vector timestamp) { + this.messageType = type; + this.id = id; + this.clock = timestamp; + } + + public byte[] toMessageBytes() throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) { + objectOutputStream.writeObject(this); + } + return byteArrayOutputStream.toByteArray(); + } + + public static Message fromByteArray(byte[] data) throws IOException, ClassNotFoundException { + try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data); + ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)) { + return (Message) objectInputStream.readObject(); + } + } +} diff --git a/Node.java b/Node.java new file mode 100644 index 0000000..4b849aa --- /dev/null +++ b/Node.java @@ -0,0 +1,196 @@ +import java.io.*; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.*; +import java.util.regex.*; + +public class Node { + // Node + int id; + String name; + String port; + List> neighbours = new ArrayList<>(); + // Config + int totalNodes; + int requestDelay; + int executionTime; + int maxRequest; + // Variable + int requestSent = 0; + boolean under_cs = false; + Vector keys = new Vector<>(); + Vector clock = new Vector<>(); + + // Components + Server server; + Client client; + + // Helper + Map> hostToId_PortMap = new HashMap<>(); + Map> idToHost_PortMap = new HashMap<>(); + Map idToChannelMap = new HashMap<>(); + + public Node(int id) { + this.id = id; + } + + public static void main(String[] args) { + // Init Node + Node node; + // if (args.length > 0) + // node = new Node(Integer.parseInt(args[0])); + // else + node = new Node(-1); + // Parse the config file + node.readConfig(); + // Init Vector Clock; + node.initVectorClock(); + // Print details + node.printNodeConfig(); + node.printNodeNeighbours(); + + // Server + node.server = new Server(node.getPort(), node); + node.server.init(); + try { + System.out.println("[SERVER] Loading... Wait 10s"); + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // Client + node.client = new Client(node); + try { + System.out.println("[CLIENT] Loading... Wait 10s"); + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + node.client.init(); + + } + + public void readConfig() { + // Declring Variables + String CONFIG_FILE_NAME = "aos-project2/config.txt"; + String line; + int configLine = 0; + String localHost = ""; + // Get Host Name + try { + localHost = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + System.out.println(e); + } + + // REGEX Pattern + Pattern REGEX_PATTERN_CONFIG = Pattern.compile("^\\s*(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)"); + + try { + // Creating a reader for config file + BufferedReader reader = new BufferedReader(new FileReader(CONFIG_FILE_NAME)); + // Looping over the whole file, reading line by line + while ((line = reader.readLine()) != null) { + // Ignoring comments and empty line + line = line.split("#")[0].trim(); + if (line.isEmpty()) + continue; + + // Match for config file. + Matcher configMatcher = REGEX_PATTERN_CONFIG.matcher(line); + if (configMatcher.matches()) { + this.totalNodes = Integer.parseInt(configMatcher.group(1)); + this.requestDelay = Integer.parseInt(configMatcher.group(2)); + this.executionTime = Integer.parseInt(configMatcher.group(3)); + this.maxRequest = Integer.parseInt(configMatcher.group(4)); + } else if (configLine <= totalNodes) { + + // All this lines are in format [ XXXX XXXX XXXX ] + String[] nodeConf = line.split(" "); + // Extracting data for read node. + int node_Id = Integer.parseInt(nodeConf[0]); + // String node_Host = nodeConf[1]; + String node_Host = nodeConf[1] + ".utdallas.edu"; + int node_Port = Integer.parseInt(nodeConf[2]); + if (this.id == -1 && node_Host.equals(localHost)) { + this.id = node_Id; + } + List valueA = new ArrayList<>(); + valueA.add(node_Host); + valueA.add(String.valueOf(node_Port)); + List valueB = new ArrayList<>(); + valueB.add(node_Id); + valueB.add(node_Port); + + this.idToHost_PortMap.put(node_Id, valueA); + this.hostToId_PortMap.put(node_Host, valueB); + } + configLine += 1; + } + // Closing reader + reader.close(); + } catch ( + + IOException e) { + e.printStackTrace(); + } + } + + public String getHost() { + return idToHost_PortMap.get(id).get(0); + } + + public String getHost(int id) { + return idToHost_PortMap.get(id).get(0); + } + + public int getPort() { + return Integer.parseInt(idToHost_PortMap.get(id).get(1)); + } + + public int getPort(int id) { + return Integer.parseInt(idToHost_PortMap.get(id).get(1)); + } + + public void initVectorClock() { + for (int i = 0; i < totalNodes; i++) { + this.clock.add(0); + } + } + + /** + * This function is for Entering the critical section. + */ + public void enterCS(){} + + /** + * This function is for Leaving the critical section. + */ + public void leaveCS(){} + + /* ========== HELPER FUNCTIONS ========== */ + public void printNodeConfig() { + System.out.println("============ Node Config ============"); + System.out.println("Node Id: " + id); + System.out.println("Node Host: " + getHost()); + System.out.println("Node Port: " + getPort()); + System.out.println("Total Nodes: " + totalNodes); + System.out.println("Request Delay: " + requestDelay); + System.out.println("Execution Time: " + executionTime); + System.out.println("Max # of Request: " + maxRequest); + System.out.println("=====================================\n"); + } + + public void printNodeVectorClock() { + int totalSent = 0, totalReceive = 0; + System.out.println("========= Node Vector Clock ========="); + for (int i = 0; i < totalNodes; i++) { + System.out.println("NodeId: " + i + " | Msg: " + clock.get(i)); + } + System.out.println("Total Send: " + totalSent + " | Total Recieve: " + totalReceive + " | Diff: " + + (totalSent - totalReceive)); + System.out.println("=====================================\n"); + } + +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..40b5a4f --- /dev/null +++ b/README.md @@ -0,0 +1,140 @@ +# CS 6378: Advanced Operating Systems +**Project 1** +**Instructor:** Prof. Neeraj Mittal +**Author:** Malay Virendra Bhavsar (MXB230055) + +--- + +## Project Overview + +This individual project implements a distributed system using the Chandy-Lamport snapshot-taking protocol and the MAP (Message Active Passive) protocol. Developed in **Java (Version 22.0.2)**, the project emphasizes socket programming and distributed communication, running exclusively on the `dcXX.utdallas.edu` machines. + +--- + +## Project Components + +The project comprises several essential components: + +- **Node**: Sets up Client, Server, and ChandyLamport instances; manages the configuration file. + +- **Server**: Oversees incoming communications and directs them appropriately. + +- **Client**: Manages outgoing communications, including application and control messages. + +- **ChandyLamport**: Implements the snapshot protocol and ensures the consistency of snapshots. + +- **Message**: Establishes a structured format for inter-process message exchange. + +--- + +## Project Segments + +The project is divided into four main segments: + +1. **Part 1**: Implement a distributed system with `n` nodes, each able to send messages according to the MAP protocol. Nodes transition between active and passive states based on message counts and delays. + +2. **Part 2**: Integrate Chandy and Lamport’s protocol to record a consistent global snapshot, initiated by node 0, to detect the termination of the MAP protocol. + +3. **Part 3**: Implement Fidge/Mattern’s vector clock protocol to verify the consistency of snapshots through vector timestamps. + +4. **Part 4**: Create a protocol for halting all nodes after node 0 detects MAP protocol termination. + +--- + +## Configuration Format + +The project utilizes a plain-text configuration file formatted as follows: + +- The first line contains six tokens: + - `Number of nodes` + - `minPerActive` + - `maxPerActive` + - `minSendDelay` + - `snapshotDelay` + - `maxNumber`. +- The next `n` lines specify node details: + - `nodeId` + - `hostname` + - `port` +- The subsequent `n` lines list neighboring nodes. + + +--- + +## Output Format + +For a configuration file named `.txt` with `n` nodes, the program will generate `n` output files named `-.out`. Each file contains vector timestamps for each snapshot recorded by the respective process. + +**Example Output:** +``` +0 4 3 6 0 2 3 +3 7 6 7 2 4 4 +6 9 11 10 5 7 5 +8 12 14 23 8 10 7 +``` +--- + +## Getting Started + +### Prerequisites + +- Ensure you have **Java Development Kit (JDK) 22.0.2** installed. +- This project must be executed on the machines `dcXX.utdallas.edu` (where XX ∈ {01, 02, ..., 45}). + +### Setup Instructions + +1. **Create a project directory:** + ```bash + mkdir aos-project1 + cd aos-project1 + ``` + +2. Place all project files (including the configuration file) in this directory. + +3. Compile the project: + ```bash + javac *.java + ``` + +4. Clean up before and after running the program: + ```bash + chmod +x cleanup.sh + ./cleanup.sh + ``` + +5. Run the program: + ```bash + chmod +x launcher.sh + ./launcher.sh + ``` + +6. Perform cleanup after use: + ```bash + ./cleanup.sh + ``` + +### Connecting to the Server + +To connect to the server at `dcXX.utdallas.edu`, use the following command (omit the password): +```bash +ssh @dcXX.utdallas.edu +``` +Ensure that you replace with your actual username. After connecting, you can navigate to your project directory to compile and run your code. + +--- + +## Acknowledgments + +The `./launcher.sh` and `./cleanup.sh` scripts are provided by the professor. All credits go to the respective owners for these contributions. + +--- + +## Conclusion + +This project delves into the intricacies of distributed systems, showcasing effective communication and state consistency through the Chandy-Lamport protocol. We encourage you to explore these concepts deeply and enhance your understanding. + +If you have any questions or require further assistance, please don't hesitate to reach out! + +--- + + diff --git a/Server.java b/Server.java new file mode 100644 index 0000000..736dd0d --- /dev/null +++ b/Server.java @@ -0,0 +1,85 @@ +import java.io.*; +import java.net.*; + +public class Server { + int port; + Node node; + ServerSocket server; + + public Server(int port, Node node) { + this.port = port; + this.node = node; + } + + public void handleMessage(Message msg) { + if (msg.id != -1) + System.out.println("[SERVER] Message received from Node " + msg.id); + // Message Handler + + if (msg.messageType == MessageType.REQUEST) { + // Handle incoming Request for key. + } else if (msg.messageType == MessageType.REPLY) { + // Handle incoming Reply with key. + } + + } + + public void listen() { + try { + this.server = new ServerSocket(port); + System.out.println("[SERVER] Started @ port: " + port); + + while (true) { + Socket client = server.accept(); + // Start a new thread to handle the client connection + Thread listener = new Thread(() -> { + try { + InputStream clientInputStream = client.getInputStream(); + DataInputStream dataInputStream = new DataInputStream(clientInputStream); + + while (!client.isClosed()) { + + try { + // Reading Incoming Message. + int length = dataInputStream.readInt(); + byte[] buffer = new byte[length]; + dataInputStream.readFully(buffer); + Message msg = Message.fromByteArray(buffer); + synchronized (node) { + handleMessage(msg); + } + } catch (EOFException e) { + System.out.println("[SERVER] Connection closed by client"); + break; + } catch (IOException | ClassNotFoundException e) { + e.printStackTrace(); + break; + } + + } + + } catch (IOException e) { + e.printStackTrace(); + } + }); + listener.start(); + } + } catch ( + + IOException e) { + e.printStackTrace(); + } + } + + public void init() { + Thread server = new Thread(() -> { + System.out.println("[SERVER] Starting..."); + try { + node.server.listen(); + } catch (Exception e) { + e.printStackTrace(); + } + }); + server.start(); + } +} diff --git a/cleanup.sh b/cleanup.sh new file mode 100644 index 0000000..5eb36f3 --- /dev/null +++ b/cleanup.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# Code adapted from posted example by Jordan Frimpter +# Command to grant permission to file to run [RUN THIS]: chmod +x cleanup.sh + +# Change this to your netid [CHANGE THIS] +netid=mxb230055 + +# Root directory of project [CHANGE THIS] +PROJDIR=/home/013/m/mx/mxb230055/aos-project1 + +# Directory where the config file is located on your local system [CHANGE THIS] +CONFIGLOCAL=/home/013/m/mx/mxb230055/aos-project1/config.txt + +# extension for hosts [CHANGE THIS if using a different host system (setting to "" should suffice)] +hostExtension="utdallas.edu" + +# loop through hosts, remove comment lines starting with # and $ and any carriage returns +n=0 +# remove comments | remove other comments | remove carriage returns +cat $CONFIGLOCAL | sed -e "s/#.*//" | sed -e "/^\s*$/d" | sed -e "s/\r$//" | +( + # read the first valid line and collect only the number of hosts + read i + echo $i + ii=$( echo $i| awk '{ print $1 }' ) + echo Hosts: $ii + + # for each host, loop + while [[ $n -lt $ii ]] + do + # collect the name of the host from file; collect the second element on the line as a host + echo next host: + read line + host=$( echo $line | awk '{ print $2 }' ) + + # add host extension to string if missing from domain name + if [[ "$host" != *"$hostExtension"* ]]; + then + host="$host.$hostExtension" + fi + echo $host + + # issue command + echo issued command: -e "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $netid@$host killall -u $netid" & + gnome-terminal -e "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $netid@$host killall -u $netid" & + # sleep 1 + + # increment loop counter + n=$(( n + 1 )) + done +) + +echo "Cleanup complete" diff --git a/config.txt b/config.txt new file mode 100644 index 0000000..91d2bb3 --- /dev/null +++ b/config.txt @@ -0,0 +1,12 @@ +# six global parameters (see above) +5 6 10 100 2000 15 +0 dc02 1232 # nodeID hostName listen Port For local my pc node name = "LeoMalay" +1 dc03 1233 +2 dc04 1234 +3 dc05 1235 +4 dc06 1236 +1 4 # space delimited list of neighbors for node 0 +0 2 3 # space delimited list of neighbors for node 1 +1 3 # space delimited list of neighbors for node 2 +1 2 4 # space delimited list of neighbors for node 3 +0 3 # space delimited list of neighbors for node 4 \ No newline at end of file diff --git a/launcher.sh b/launcher.sh new file mode 100644 index 0000000..579fab8 --- /dev/null +++ b/launcher.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# Code adapted from posted example by Jordan Frimpter +# Command to grant permission to file to run [RUN THIS]: chmod +x launcher.sh + +# Change this to your netid [CHANGE THIS] +netid=mxb230055 + +# Root directory of project [CHANGE THIS] +PROJDIR=/home/013/m/mx/mxb230055/aos-project1 + +# Directory where the config file is located on your local system [CHANGE THIS] +CONFIGLOCAL=/home/013/m/mx/mxb230055/aos-project1/config.txt + +# Directory your compiled classes are in [CHANGE THIS if you move the classes] +BINDIR=$PROJDIR + +# Your main project class [CHANGE THIS if you rename the project] +PROG=Node + +# extension for hosts [CHANGE THIS if using a different host system (setting to "" should suffice)] +hostExtension="utdallas.edu" + +# run command [CHANGE THIS if you want a different pattern or use a different software] +runCommand="java -cp $BINDIR $PROG $CONFIGLOCAL" +# remove $CONFIGLOCAL if you don't want to give your program the configuration file path as an argument + +# loop through hosts, remove comment lines starting with # and $ and any carriage returns +n=0 +# remove comments | remove other comments | remove carriage returns +cat $CONFIGLOCAL | sed -e "s/#.*//" | sed -e "/^\s*$/d" | sed -e "s/\r$//" | +( + # read the first valid line and collect only the number of hosts + read i + echo $i + ii=$( echo $i| awk '{ print $1 }' ) + echo Hosts: $ii + + # for each host, loop + while [[ $n -lt $ii ]] + do + # read the port number and host address + read line + p=$( echo $line | awk '{ print $1 }' ) + host=$( echo $line | awk '{ print $2 }' ) + + # add host extension to string if missing from domain name + if [[ "$host" != *"$hostExtension"* ]]; + then + host="$host.$hostExtension" + fi + echo $host + + # issue command + echo issued command: gnome-terminal -e "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $netid@$host $runCommand; exec bash" & + gnome-terminal -e "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $netid@$host $runCommand; exec bash" & + sleep 1 + + # increment loop counter + n=$(( n + 1 )) + done +) + +echo "Launcher complete" \ No newline at end of file diff --git a/script.bat b/script.bat new file mode 100644 index 0000000..9e03805 --- /dev/null +++ b/script.bat @@ -0,0 +1,10 @@ +@echo off +setlocal enabledelayedexpansion + +set "n=4" + +for /L %%d in (0,1,%n%) do ( + start cmd /k "java Node %%d" +) + +endlocal \ No newline at end of file