From 06b85e583dd9242855b2ca9173a580c766733a25 Mon Sep 17 00:00:00 2001 From: BMatajsz <90217645+BMatajsz@users.noreply.github.com> Date: Mon, 2 Dec 2024 17:25:26 -0500 Subject: Added Replica4 --- src/main/java/derms/Replica3.java | 100 ----- .../java/derms/Replica3pkg/CoordinatorClient.java | 155 ------- .../java/derms/Replica3pkg/DERMSInterface.java | 16 - src/main/java/derms/Replica3pkg/RemoteServer.java | 32 -- src/main/java/derms/Replica3pkg/Resource.java | 43 -- .../java/derms/Replica3pkg/ResponderClient.java | 154 ------- src/main/java/derms/Replica3pkg/Server.java | 479 --------------------- src/main/java/derms/Replica4.java | 108 +++++ .../java/derms/Replica4pkg/DERMSInterface.java | 16 + src/main/java/derms/Replica4pkg/RemoteServer.java | 43 ++ src/main/java/derms/Replica4pkg/Resource.java | 43 ++ src/main/java/derms/Replica4pkg/Server.java | 479 +++++++++++++++++++++ 12 files changed, 689 insertions(+), 979 deletions(-) delete mode 100644 src/main/java/derms/Replica3.java delete mode 100644 src/main/java/derms/Replica3pkg/CoordinatorClient.java delete mode 100644 src/main/java/derms/Replica3pkg/DERMSInterface.java delete mode 100644 src/main/java/derms/Replica3pkg/RemoteServer.java delete mode 100644 src/main/java/derms/Replica3pkg/Resource.java delete mode 100644 src/main/java/derms/Replica3pkg/ResponderClient.java delete mode 100644 src/main/java/derms/Replica3pkg/Server.java create mode 100644 src/main/java/derms/Replica4.java create mode 100644 src/main/java/derms/Replica4pkg/DERMSInterface.java create mode 100644 src/main/java/derms/Replica4pkg/RemoteServer.java create mode 100644 src/main/java/derms/Replica4pkg/Resource.java create mode 100644 src/main/java/derms/Replica4pkg/Server.java (limited to 'src/main/java/derms') diff --git a/src/main/java/derms/Replica3.java b/src/main/java/derms/Replica3.java deleted file mode 100644 index b1ee8ce..0000000 --- a/src/main/java/derms/Replica3.java +++ /dev/null @@ -1,100 +0,0 @@ -package derms; - -import derms.Replica3pkg.CoordinatorClient; -import derms.Replica3pkg.RemoteServer; -import derms.Replica3pkg.ResponderClient; -import derms.Replica3pkg.Server; -import derms.net.runicast.ReliableUnicastSender; -import derms.Replica; -import derms.ReplicaManager; -import derms.Request; -import derms.Response; -import javax.xml.ws.Endpoint; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Logger; - -public class Replica3 implements Replica { - - private ReplicaManager replicaManager; - private RemoteServer remoteServer; - private boolean alive = true; - - public Replica3(ReplicaManager replicaManager){ - this.replicaManager = replicaManager; - this.remoteServer = new RemoteServer(); - } - - @Override - public boolean isAlive() { - return alive; - } - - @Override - public void startProcess() { - - } - - @Override - public void processRequest(Request request) { - ResponderClient responderClient; - CoordinatorClient coordinatorClient; - String responseMessage; - switch (request.getFunction()) { - case "addResource": - responderClient = new ResponderClient(request.getClientID()); - responseMessage = responderClient.addResource(request.getResourceID(), request.getResourceType(), request.getDuration()); - break; - case "removeResource": - responderClient = new ResponderClient(request.getClientID()); - responseMessage = responderClient.removeResource(request.getResourceID(), request.getDuration()); - break; - case "listResourceAvailability": - responderClient = new ResponderClient(request.getClientID()); - responseMessage = responderClient.listResourceAvailability(request.getResourceType()); - break; - case "requestResource": - coordinatorClient = new CoordinatorClient(request.getClientID()); - responseMessage = coordinatorClient.requestResource(request.getResourceID(), request.getDuration()); - break; - case "findResource": - coordinatorClient = new CoordinatorClient(request.getClientID()); - responseMessage = coordinatorClient.findResource(request.getResourceType()); - break; - case "returnResource": - coordinatorClient = new CoordinatorClient(request.getClientID()); - responseMessage = coordinatorClient.returnResource(request.getResourceID()); - break; - case "swapResource": - coordinatorClient = new CoordinatorClient(request.getClientID()); - responseMessage = coordinatorClient.swapResource( - request.getClientID(), - request.getOldResourceID(), - request.getOldResourceType(), - request.getResourceID(), - request.getResourceType() - ); - break; - default: - responseMessage = "Unrecognized function: " + request.getFunction(); - log.severe("Unrecognized function in request: " + request.getFunction()); - break; - } - - Response response = new Response(request.getSequenceNumber(), responseMessage); - log.info("Replica " + 3 + " processed request: " + request + ", response: " + response); - replicaManager.sendResponseToFE(response); - } - - @Override - public void restart() { - - } - - @Override - public int getId() { - return 3; - } -} \ No newline at end of file diff --git a/src/main/java/derms/Replica3pkg/CoordinatorClient.java b/src/main/java/derms/Replica3pkg/CoordinatorClient.java deleted file mode 100644 index 9572099..0000000 --- a/src/main/java/derms/Replica3pkg/CoordinatorClient.java +++ /dev/null @@ -1,155 +0,0 @@ -//CoordinatorCLient.java -package derms.Replica3pkg; - -import javax.xml.namespace.QName; -import javax.xml.ws.Service; -import java.net.URL; -import java.io.*; -import java.util.*; - -public class CoordinatorClient { - private String coordinatorID; - private String serverName; - private DERMSInterface server; - - public CoordinatorClient(String coordinatorID) { - this.coordinatorID = coordinatorID; - this.serverName = coordinatorID.substring(0, 3).toUpperCase(); - } - - public void connectToServer() { - try { - String endpointURL = ""; - switch (serverName) { - case "MTL": - endpointURL = "http://localhost:8080/DERMS/MTL?wsdl"; - break; - case "QUE": - endpointURL = "http://localhost:8081/DERMS/QUE?wsdl"; - break; - case "SHE": - endpointURL = "http://localhost:8082/DERMS/SHE?wsdl"; - break; - default: - System.out.println("Invalid server code in coordinatorID."); - } - - URL url = new URL(endpointURL); - QName qname = new QName("http://DERMS.org/", "ServerService"); - Service service = Service.create(url, qname); - server = service.getPort(DERMSInterface.class); - - System.out.println("Connected to " + serverName + " server."); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public String requestResource(String resourceID, int duration) { - try { - String response = server.requestResource(coordinatorID, resourceID, duration); - log("requestResource", response); - System.out.println(response); - } catch (Exception e) { - e.printStackTrace(); - } - return "OK"; - } - - public String findResource(String resourceName) { - try { - String response = server.findResource(coordinatorID, resourceName); - log("findResource", response); - System.out.println("Resources you have occupied:\n" + response); - } catch (Exception e) { - e.printStackTrace(); - } - return "OK"; - } - - public String returnResource(String resourceID) { - try { - String response = server.returnResource(coordinatorID, resourceID); - log("returnResource", response); - System.out.println(response); - } catch (Exception e) { - e.printStackTrace(); - } - return "OK"; - } - - public String swapResource(String coordinatorID, String oldResourceID, String oldResourceType, String newResourceID, String newResourceType) { - try { - String response = server.swapResource(coordinatorID, oldResourceID, oldResourceType, newResourceID, newResourceType); - log("swapResource", response); - System.out.println(response); - } catch (Exception e) { - e.printStackTrace(); - } - return "OK"; - } - - private void log(String operation, String response) { - try (FileWriter fw = new FileWriter(coordinatorID + "_log.txt", true); - BufferedWriter bw = new BufferedWriter(fw); - PrintWriter out = new PrintWriter(bw)) { - String logEntry = String.format("%s - Operation: %s, Response: %s", new Date(), operation, response); - out.println(logEntry); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void run() { - Scanner scanner = new Scanner(System.in); - connectToServer(); - - while (true) { - System.out.println("Coordinator menu:"); - System.out.println("1. Request Resource"); - System.out.println("2. Find Resource"); - System.out.println("3. Return Resource"); - System.out.println("4. Swap Resource"); - System.out.println("5. Exit"); - System.out.print("Enter choice (number): "); - int choice = Integer.parseInt(scanner.nextLine()); - - switch (choice) { - case 1: - System.out.print("Enter resourceID: "); - String resourceID = scanner.nextLine(); - System.out.print("Enter duration: "); - int duration = Integer.parseInt(scanner.nextLine()); - requestResource(resourceID, duration); - break; - case 2: - System.out.print("Enter resourceName: "); - String resourceName = scanner.nextLine(); - findResource(resourceName); - break; - case 3: - System.out.print("Enter resourceID: "); - resourceID = scanner.nextLine(); - returnResource(resourceID); - break; - case 4: - swapResource(); - break; - case 5: - System.out.println("Exiting client"); - scanner.close(); - return; - default: - System.out.println("Invalid input"); - } - } - } - - public static void main(String[] args) { - Scanner scanner = new Scanner(System.in); - System.out.print("Enter coordinatorID: "); - String coordinatorID = scanner.nextLine(); - CoordinatorClient client = new CoordinatorClient(coordinatorID); - client.run(); - } -} \ No newline at end of file diff --git a/src/main/java/derms/Replica3pkg/DERMSInterface.java b/src/main/java/derms/Replica3pkg/DERMSInterface.java deleted file mode 100644 index 14099a5..0000000 --- a/src/main/java/derms/Replica3pkg/DERMSInterface.java +++ /dev/null @@ -1,16 +0,0 @@ -package derms.Replica3pkg; - -import javax.jws.WebService; -import javax.jws.soap.SOAPBinding; - -@WebService -@SOAPBinding(style = SOAPBinding.Style.RPC) -public interface DERMSInterface { - String addResource(String resourceID, String resourceName, int duration); - String removeResource(String resourceID, int duration); - String listResourceAvailability(String resourceName); - String requestResource(String coordinatorID, String resourceID, int duration); - String findResource(String coordinatorID, String resourceName); - String returnResource(String coordinatorID, String resourceID); - String swapResource(String coordinatorID, String oldResourceID, String oldResourceType, String newResourceID, String newResourceType); -} \ No newline at end of file diff --git a/src/main/java/derms/Replica3pkg/RemoteServer.java b/src/main/java/derms/Replica3pkg/RemoteServer.java deleted file mode 100644 index 16741dd..0000000 --- a/src/main/java/derms/Replica3pkg/RemoteServer.java +++ /dev/null @@ -1,32 +0,0 @@ -//RemoteServer.java -package derms.Replica3pkg; - -import javax.xml.ws.Endpoint; -import java.util.*; - -public class RemoteServer { - public RemoteServer() { - try { - Map UDPPorts = new HashMap<>(); - UDPPorts.put("MTL", 4000); - UDPPorts.put("QUE", 5000); - UDPPorts.put("SHE", 6000); - - String[] serverNames = {"MTL", "QUE", "SHE"}; - int i = 0; - for (String serverName : serverNames) { - int UDPPort = UDPPorts.get(serverName); - Server server = new Server(); - server.initServer(serverName, UDPPort, UDPPorts); - int port = 8080 + i; - String url = "http://localhost:" + port + "/DERMS/" + serverName; - Endpoint.publish(url, server); - i++; - System.out.println(serverName + " Server ready and waiting ..."); - } - - } catch (Exception e) { - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/src/main/java/derms/Replica3pkg/Resource.java b/src/main/java/derms/Replica3pkg/Resource.java deleted file mode 100644 index fceebca..0000000 --- a/src/main/java/derms/Replica3pkg/Resource.java +++ /dev/null @@ -1,43 +0,0 @@ -//Resource.java -package derms.Replica3pkg; - -import java.io.Serializable; - -public class Resource implements Serializable { - private static final long serialVersionUID = 1L; - - private String resourceName; - private int duration; - - public Resource(String resourceName, int duration) { - this.resourceName = resourceName.toUpperCase(); - this.duration = duration; - } - - // Getters - public String getResourceName() { - return resourceName; - } - - public synchronized int getDuration() { - return duration; - } - - // Setters - public synchronized void setDuration(int duration) { - this.duration = duration; - } - - // Methods to manipulate duration - public synchronized void addDuration(int additionalDuration) { - if (additionalDuration > 0) { - this.duration += additionalDuration; - } - } - - public synchronized void subDuration(int decrement) { - if (decrement > 0 && this.duration >= decrement) { - this.duration -= decrement; - } - } -} \ No newline at end of file diff --git a/src/main/java/derms/Replica3pkg/ResponderClient.java b/src/main/java/derms/Replica3pkg/ResponderClient.java deleted file mode 100644 index 85dfeaa..0000000 --- a/src/main/java/derms/Replica3pkg/ResponderClient.java +++ /dev/null @@ -1,154 +0,0 @@ -//ResponderClient.java -package derms.Replica3pkg; - - -import javax.xml.namespace.QName; -import javax.xml.ws.Service; -import java.io.*; -import java.net.URL; -import java.util.*; - -public class ResponderClient { - private String responderID; - private String serverName; - private Map servers; - - public ResponderClient(String responderID) { - this.responderID = responderID; - this.serverName = responderID.substring(0, 3).toUpperCase(); - this.servers = new HashMap<>(); - } - - public void connectToServer() { - try { - String[] serverNames = {"MTL", "QUE", "SHE"}; - String[] endpoints = { - "http://localhost:8080/DERMS/MTL?wsdl", - "http://localhost:8081/DERMS/QUE?wsdl", - "http://localhost:8082/DERMS/SHE?wsdl" - }; - - int i = 0; - for (String name : serverNames) { - URL url = new URL(endpoints[i]); - QName qname = new QName("http://DERMS.org/", "ServerService"); - Service service = Service.create(url, qname); - servers.put(name, service.getPort(DERMSInterface.class)); - System.out.println("Connected to " + name + " server."); - i++; - } - - } catch (Exception e) { - e.printStackTrace(); - } - } - - public String addResource(String resourceID, String resourceName, int duration) { - try { - String serverCode = resourceID.substring(0, 3).toUpperCase(); - DERMSInterface targetServer = servers.get(serverCode); - if (targetServer == null) { - System.out.println("Invalid server code in resourceID."); - return "Error"; - } - String response = targetServer.addResource(resourceID, resourceName, duration); - log("addResource", response); - System.out.println(response); - return "OK"; - } catch (Exception e) { - e.printStackTrace(); - return "Error"; - } - } - - public String removeResource(String resourceID, int duration) { - try { - String serverCode = resourceID.substring(0, 3).toUpperCase(); - DERMSInterface targetServer = servers.get(serverCode); - if (targetServer == null) { - System.out.println("Invalid server code in resourceID."); - } - String response = targetServer.removeResource(resourceID, duration); - log("removeResource", response); - System.out.println(response); - } catch (Exception e) { - e.printStackTrace(); - } - return "OK"; - } - - public String listResourceAvailability(String resourceName) { - try { - String response = servers.get(serverName).listResourceAvailability(resourceName); - log("listResourceAvailability", response); - System.out.println("Available Resources:\n" + response); - } catch (Exception e) { - e.printStackTrace(); - } - return "OK"; - } - - private void log(String operation, String response) { - try (FileWriter fw = new FileWriter(responderID + "_log.txt", true); - BufferedWriter bw = new BufferedWriter(fw); - PrintWriter out = new PrintWriter(bw)) { - String logEntry = String.format("%s - Operation: %s, Response: %s", new Date(), operation, response); - out.println(logEntry); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void start() { - Scanner scanner = new Scanner(System.in); - connectToServer(); - - while (true) { - System.out.println("Responder menu:"); - System.out.println("1. Add Resource"); - System.out.println("2. Remove Resource"); - System.out.println("3. List Resource Availability"); - System.out.println("4. Exit"); - System.out.print("Enter choice (number): "); - int choice = Integer.parseInt(scanner.nextLine()); - - switch (choice) { - case 1: - System.out.print("Enter resourceID: "); - String resourceID = scanner.nextLine(); - System.out.print("Enter resourceName: "); - String resourceName = scanner.nextLine(); - System.out.print("Enter duration: "); - int duration = Integer.parseInt(scanner.nextLine()); - addResource(resourceID, resourceName, duration); - break; - case 2: - System.out.print("Enter resourceID: "); - resourceID = scanner.nextLine(); - System.out.print("Enter duration (removal): "); - duration = Integer.parseInt(scanner.nextLine()); - removeResource(resourceID, duration); - break; - case 3: - System.out.print("Enter resourceName: "); - resourceName = scanner.nextLine(); - listResourceAvailability(resourceName); - break; - case 4: - System.out.println("Exiting client"); - scanner.close(); - return; - default: - System.out.println("Invalid input"); - } - } - } - - public static void main(String[] args) { - Scanner scanner = new Scanner(System.in); - System.out.print("Enter responderID: "); - String responderID = scanner.nextLine(); - ResponderClient client = new ResponderClient(responderID); - client.start(); - } -} \ No newline at end of file diff --git a/src/main/java/derms/Replica3pkg/Server.java b/src/main/java/derms/Replica3pkg/Server.java deleted file mode 100644 index 474e6f5..0000000 --- a/src/main/java/derms/Replica3pkg/Server.java +++ /dev/null @@ -1,479 +0,0 @@ -//Server.java -package derms.Replica3pkg; - -import javax.jws.WebService; -import javax.jws.WebMethod; -import java.io.*; -import java.net.*; -import java.util.*; - -@WebService(endpointInterface = "org.DERMS.DERMSInterface") -public class Server implements DERMSInterface { - private String serverName; - private int udpPort; - private Map> resourceMap; //resourceName -> (resourceID -> Resource) - private Map> coordinatorResources; //coordinatorID -> Set - private Map> coordinatorResourceDurations; //coordinatorID -> (resourceID -> allocatedDuration) - private Map serverUdpPorts; //serverName -> UDP port - - - public Server() { - this.resourceMap = new HashMap<>(); - this.coordinatorResources = new HashMap<>(); - this.coordinatorResourceDurations = new HashMap<>(); - startUDPListener(); - } - - @WebMethod(exclude = true) - public void initServer(String serverName, int udpPort, Map serverUdpPorts) { - this.serverName = serverName; - this.udpPort = udpPort; - this.serverUdpPorts = serverUdpPorts; - } - - //Start UDP Listener - private void startUDPListener() { - new Thread(() -> { - try (DatagramSocket socket = new DatagramSocket(udpPort)) { - byte[] buffer = new byte[4096]; - System.out.println(serverName + " UDP Server started on port " + udpPort); - - while (true) { - DatagramPacket request = new DatagramPacket(buffer, buffer.length); - socket.receive(request); - new Thread(() -> handleUDPRequest(request)).start(); - } - } catch (IOException e) { - e.printStackTrace(); - } - }).start(); - } - - //Handle UDP Request - private void handleUDPRequest(DatagramPacket requestPacket) { - try { - String requestData = new String(requestPacket.getData(), 0, requestPacket.getLength()); - String[] parts = requestData.split(":"); - String methodName = parts[0]; - String[] params = Arrays.copyOfRange(parts, 1, parts.length); - - String responseData = ""; - - switch (methodName) { - case "listResourceAvailability": - responseData = handleListResourceAvailability(params[0]); - break; - case "requestResource": - responseData = handleLocalResourceRequest(params[0], params[1], Integer.parseInt(params[2])); - break; - case "findResource": - responseData = handleFindResource(params[0], params[1]); - break; - case "returnResource": - responseData = handleReturnResource(params[0], params[1]); - break; - case "swapRequestResource": - responseData = handleSwapRequestResource(params[0], params[1], Integer.parseInt(params[2])); - break; - case "swapReturnResource": - responseData = handleSwapReturnResource(params[0], params[1]); - break; - case "checkCoordinatorResource": - responseData = checkCoordinatorHasResource(params[0], params[1]); - break; - case "getCoordinatorResourceDuration": - int duration = getCoordinatorResourceDuration(params[0], params[1]); - responseData = String.valueOf(duration); - break; - default: - responseData = "Invalid method"; - } - - //Send response - byte[] responseBytes = responseData.getBytes(); - DatagramPacket responsePacket = new DatagramPacket(responseBytes, responseBytes.length, requestPacket.getAddress(), requestPacket.getPort()); - DatagramSocket socket = new DatagramSocket(); - socket.send(responsePacket); - socket.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - //Operation Handlers - private synchronized String handleListResourceAvailability(String resourceName) { - StringBuilder result = new StringBuilder(); - resourceName = resourceName.toUpperCase(); - Map resources = resourceMap.get(resourceName); - - if (resources != null) { - for (Resource resource : resources.values()) { - if (resource.getDuration() > 0) { - result.append(resource.getResourceName()).append(" - ").append(serverName).append(" ").append(resource.getDuration()).append("\n"); - } - } - } - return result.toString(); - } - - private synchronized String handleLocalResourceRequest(String coordinatorID, String resourceID, int duration) { - for (Map resources : resourceMap.values()) { - Resource resource = resources.get(resourceID); - if (resource != null) { - if (resource.getDuration() >= duration) { - resource.subDuration(duration); - coordinatorResources.computeIfAbsent(coordinatorID, k -> new HashSet<>()).add(resourceID); - coordinatorResourceDurations.computeIfAbsent(coordinatorID, k -> new HashMap<>()).put(resourceID, duration); - - log("Resource " + resourceID + " allocated to " + coordinatorID + " for duration " + duration); - return "Resource " + resourceID + " allocated successfully."; - } else { - return "Insufficient duration for resource " + resourceID; - } - } - } - return "Resource " + resourceID + " not found."; - } - - private synchronized String handleFindResource(String coordinatorID, String resourceName) { - StringBuilder result = new StringBuilder(); - resourceName = resourceName.toUpperCase(); - Set resources = coordinatorResources.get(coordinatorID); - if (resources != null) { - Map resourceDurations = coordinatorResourceDurations.get(coordinatorID); - if (resourceDurations != null) { - for (String resourceID : resources) { - Resource resource = getResourceByID(resourceID); - if (resource != null && resource.getResourceName().equals(resourceName)) { - Integer allocatedDuration = resourceDurations.get(resourceID); - if (allocatedDuration != null) { - result.append(resource.getResourceName()).append(" - ").append(resourceID).append(" ").append(allocatedDuration).append("\n"); - } - } - } - } - } - return result.toString(); - } - - private synchronized String handleReturnResource(String coordinatorID, String resourceID) { - Set resources = coordinatorResources.get(coordinatorID); - if (resources != null && resources.contains(resourceID)) { - resources.remove(resourceID); - if (resources.isEmpty()) { - coordinatorResources.remove(coordinatorID); - } - Resource resource = getResourceByID(resourceID); - if (resource != null) { - Map resourceDurations = coordinatorResourceDurations.get(coordinatorID); - if (resourceDurations != null) { - Integer allocatedDuration = resourceDurations.remove(resourceID); - if (allocatedDuration != null) { - resource.addDuration(allocatedDuration); - } - if (resourceDurations.isEmpty()) { - coordinatorResourceDurations.remove(coordinatorID); - } - } - log("Coordinator " + coordinatorID + " returned resource " + resourceID); - return "Resource " + resourceID + " returned successfully."; - } else { - return "Resource " + resourceID + " not found."; - } - } else { - return "You do not occupy resource " + resourceID + "."; - } - } - - //Helper Methods - private Resource getResourceByID(String resourceID) { - for (Map resources : resourceMap.values()) { - if (resources.containsKey(resourceID)) { - return resources.get(resourceID); - } - } - return null; - } - - private synchronized String handleSwapRequestResource(String coordinatorID, String resourceID, int duration) { - //Attempt to allocate the resource to the coordinator - for (Map resources : resourceMap.values()) { - Resource resource = resources.get(resourceID); - if (resource != null) { - if (resource.getDuration() >= duration) { - resource.subDuration(duration); - coordinatorResources.computeIfAbsent(coordinatorID, k -> new HashSet<>()).add(resourceID); - coordinatorResourceDurations.computeIfAbsent(coordinatorID, k -> new HashMap<>()).put(resourceID, duration); - log("Resource " + resourceID + " temporarily allocated to " + coordinatorID + " for swapping, duration " + duration); - return "Success"; - } else { - return "Insufficient duration for resource " + resourceID; - } - } - } - return "Resource " + resourceID + " not found."; - } - - private synchronized String handleSwapReturnResource(String coordinatorID, String resourceID) { - Set resources = coordinatorResources.get(coordinatorID); - if (resources != null && resources.contains(resourceID)) { - resources.remove(resourceID); - if (resources.isEmpty()) { - coordinatorResources.remove(coordinatorID); - } - Resource resource = getResourceByID(resourceID); - if (resource != null) { - Map resourceDurations = coordinatorResourceDurations.get(coordinatorID); - if (resourceDurations != null) { - Integer allocatedDuration = resourceDurations.remove(resourceID); - if (allocatedDuration != null) { - resource.addDuration(allocatedDuration); - } - if (resourceDurations.isEmpty()) { - coordinatorResourceDurations.remove(coordinatorID); - } - } - log("Coordinator " + coordinatorID + " resource " + resourceID + " allocation undone during swap"); - return "Success"; - } else { - return "Resource " + resourceID + " not found."; - } - } else { - return "Coordinator did not acquire resource " + resourceID; - } - } - - private String sendUDPRequest(String serverName, String methodName, String... params) { - String response = ""; - try { - InetAddress host = InetAddress.getByName("localhost"); - int port = serverUdpPorts.get(serverName); - String requestData = methodName + ":" + String.join(":", params); - - byte[] requestBytes = requestData.getBytes(); - DatagramPacket requestPacket = new DatagramPacket(requestBytes, requestBytes.length, host, port); - - DatagramSocket socket = new DatagramSocket(); - socket.send(requestPacket); - - byte[] buffer = new byte[4096]; - DatagramPacket responsePacket = new DatagramPacket(buffer, buffer.length); - socket.receive(responsePacket); - - response = new String(responsePacket.getData(), 0, responsePacket.getLength()); - socket.close(); - } catch (Exception e) { - e.printStackTrace(); - } - return response; - } - - //Implement ResponderInterface Methods - @Override - public synchronized String addResource(String resourceID, String resourceName, int duration) { - resourceName = resourceName.toUpperCase(); - Map resources = resourceMap.computeIfAbsent(resourceName, k -> new HashMap<>()); - Resource resource = resources.get(resourceID); - - if (resource != null) { - if (duration > resource.getDuration()) { - resource.setDuration(duration); - log("Updated duration of resource " + resourceID); - return "Resource " + resourceID + " duration updated."; - } else { - log("Resource " + resourceID + " already exists with greater or equal duration."); - return "Resource " + resourceID + " already exists with greater or equal duration."; - } - } else { - resource = new Resource(resourceName, duration); - resources.put(resourceID, resource); - log("Added new resource " + resourceID); - return "Resource " + resourceID + " added successfully."; - } - } - - @Override - public synchronized String removeResource(String resourceID, int duration) { - for (Map resources : resourceMap.values()) { - Resource resource = resources.get(resourceID); - if (resource != null) { - if (duration >= resource.getDuration()) { - resources.remove(resourceID); - log("Resource " + resourceID + " completely removed."); - return "Resource " + resourceID + " completely removed."; - } else { - resource.subDuration(duration); - log("Decreased duration of resource " + resourceID); - return "Resource " + resourceID + " duration decreased by " + duration + "."; - } - } - } - log("Resource " + resourceID + " not found."); - return "Resource " + resourceID + " not found."; - } - - @Override - public String listResourceAvailability(String resourceName) { - resourceName = resourceName.toUpperCase(); - StringBuilder result = new StringBuilder(); - - synchronized (this) { - Map resources = resourceMap.get(resourceName); - if (resources != null) { - for (Resource resource : resources.values()) { - if (resource.getDuration() > 0) { - result.append(resource.getResourceName()).append(" - ").append(serverName).append(" ").append(resource.getDuration()).append("\n"); - } - } - } - } - - for (String otherServer : serverUdpPorts.keySet()) { - if (!otherServer.equals(serverName)) { - String response = sendUDPRequest(otherServer, "listResourceAvailability", resourceName); - result.append(response); - } - } - - return result.toString(); - } - - @Override - public String requestResource(String coordinatorID, String resourceID, int duration) { - String resourceServer = resourceID.substring(0, 3).toUpperCase(); - String response; - - if (resourceServer.equals(serverName)) { - response = handleLocalResourceRequest(coordinatorID, resourceID, duration); - } else { - response = sendUDPRequest(resourceServer, "requestResource", coordinatorID, resourceID, String.valueOf(duration)); - } - - log("Coordinator " + coordinatorID + " requested resource " + resourceID + ": " + response); - return response; - } - - @Override - public String findResource(String coordinatorID, String resourceName) { - resourceName = resourceName.toUpperCase(); - StringBuilder result = new StringBuilder(); - - for (String otherServer : serverUdpPorts.keySet()) { - String response; - if (otherServer.equals(serverName)) { - response = handleFindResource(coordinatorID, resourceName); - } else { - response = sendUDPRequest(otherServer, "findResource", coordinatorID, resourceName); - } - result.append(response); - } - - return result.toString(); - } - - @Override - public String returnResource(String coordinatorID, String resourceID) { - String resourceServer = resourceID.substring(0, 3).toUpperCase(); - String response; - - if (resourceServer.equals(serverName)) { - response = handleReturnResource(coordinatorID, resourceID); - } else { - response = sendUDPRequest(resourceServer, "returnResource", coordinatorID, resourceID); - } - - log("Coordinator " + coordinatorID + " returned resource " + resourceID + ": " + response); - return response; - } - - private synchronized int getCoordinatorResourceDuration(String coordinatorID, String resourceID) { - Map resourceDurations = coordinatorResourceDurations.get(coordinatorID); - if (resourceDurations != null && resourceDurations.containsKey(resourceID)) { - return resourceDurations.get(resourceID); - } - return 0; - } - - private synchronized String checkCoordinatorHasResource(String coordinatorID, String resourceID) { - Set resources = coordinatorResources.get(coordinatorID); - if (resources != null && resources.contains(resourceID)) { - return "true"; - } - return "false"; - } - - @Override - public String swapResource(String coordinatorID, String oldResourceID, String oldResourceType, String newResourceID, String newResourceType) { - String oldResourceServer = oldResourceID.substring(0, 3).toUpperCase(); - String newResourceServer = newResourceID.substring(0, 3).toUpperCase(); - - //Check if the coordinator has the old resource - String checkOldResourceResponse; - if (oldResourceServer.equals(serverName)) { - checkOldResourceResponse = checkCoordinatorHasResource(coordinatorID, oldResourceID); - } else { - checkOldResourceResponse = sendUDPRequest(oldResourceServer, "checkCoordinatorResource", coordinatorID, oldResourceID); - } - - if (!checkOldResourceResponse.equals("true")) { - return "Coordinator has not acquired the old resource."; - } - - //Get the duration allocated to the old resource - int duration; - if (oldResourceServer.equals(serverName)) { - duration = getCoordinatorResourceDuration(coordinatorID, oldResourceID); - } else { - String durationStr = sendUDPRequest(oldResourceServer, "getCoordinatorResourceDuration", coordinatorID, oldResourceID); - duration = Integer.parseInt(durationStr); - } - - //Attempt to acquire the new resource - String requestResponse; - if (newResourceServer.equals(serverName)) { - requestResponse = handleLocalResourceRequest(coordinatorID, newResourceID, duration); - } else { - requestResponse = sendUDPRequest(newResourceServer, "requestResource", coordinatorID, newResourceID, String.valueOf(duration)); - } - - if (!requestResponse.contains("allocated successfully")) { - return "Failed to acquire new resource: " + requestResponse; - } - - //Return the old resource - String returnResponse; - if (oldResourceServer.equals(serverName)) { - returnResponse = handleReturnResource(coordinatorID, oldResourceID); - } else { - returnResponse = sendUDPRequest(oldResourceServer, "returnResource", coordinatorID, oldResourceID); - } - - if (!returnResponse.contains("returned successfully")) { - //Undo the allocation of the new resource - if (newResourceServer.equals(serverName)) { - handleReturnResource(coordinatorID, newResourceID); - } else { - sendUDPRequest(newResourceServer, "returnResource", coordinatorID, newResourceID); - } - return "Failed to return old resource: " + returnResponse; - } - - log("Coordinator " + coordinatorID + " swapped resource " + oldResourceID + " with " + newResourceID); - - return "Resource swap successful."; - } - - //Logging method - private synchronized void log(String message) { - String logMessage = new Date() + " - " + message; - System.out.println(logMessage); - - try (FileWriter fw = new FileWriter(serverName + "_server_log.txt", true); - BufferedWriter bw = new BufferedWriter(fw); - PrintWriter out = new PrintWriter(bw)) { - out.println(logMessage); - } catch (IOException e) { - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/src/main/java/derms/Replica4.java b/src/main/java/derms/Replica4.java new file mode 100644 index 0000000..760f8bb --- /dev/null +++ b/src/main/java/derms/Replica4.java @@ -0,0 +1,108 @@ +package derms; + +//import derms.Replica3pkg.ResponderClient; +import java.io.*; +import java.util.*; + +import derms.Replica4pkg.RemoteServer; + +public class Replica4 implements Replica { + + private ReplicaManager replicaManager; + private RemoteServer remoteServer; + private boolean alive = true; + + public Replica4(ReplicaManager replicaManager){ + this.replicaManager = replicaManager; + } + + @Override + public boolean isAlive() { + return alive; + } + + @Override + public void startProcess() { + this.remoteServer = new RemoteServer(); + System.out.println("[Replica 4] Process started."); + } + + @Override + public void processRequest(Request request) { + ResponderClient responderClient; + CoordinatorClient coordinatorClient; + String responseMessage; + switch (request.getFunction()) { + case "addResource": + responderClient = new ResponderClient(request.getClientID()); + responseMessage = responderClient.addResource(request.getResourceID(), request.getResourceType(), request.getDuration()); + break; + case "removeResource": + responderClient = new ResponderClient(request.getClientID()); + responseMessage = responderClient.removeResource(request.getResourceID(), request.getDuration()); + break; + case "listResourceAvailability": + responderClient = new ResponderClient(request.getClientID()); + responseMessage = responderClient.listResourceAvailability(request.getResourceType()); + break; + case "requestResource": + coordinatorClient = new CoordinatorClient(request.getClientID()); + responseMessage = coordinatorClient.requestResource(request.getResourceID(), request.getDuration()); + break; + case "findResource": + coordinatorClient = new CoordinatorClient(request.getClientID()); + responseMessage = coordinatorClient.findResource(request.getResourceType()); + break; + case "returnResource": + coordinatorClient = new CoordinatorClient(request.getClientID()); + responseMessage = coordinatorClient.returnResource(request.getResourceID()); + break; + case "swapResource": + coordinatorClient = new CoordinatorClient(request.getClientID()); + responseMessage = coordinatorClient.swapResource( + request.getClientID(), + request.getOldResourceID(), + request.getOldResourceType(), + request.getResourceID(), + request.getResourceType() + ); + break; + default: + responseMessage = "Unrecognized function: " + request.getFunction(); + log("Unrecognized function in request: " + request.getFunction()); + break; + } + + Response response = new Response(request.getSequenceNumber(), responseMessage); + log("Replica " + 4 + " processed request: " + request + ", response: " + response); + replicaManager.sendResponseToFE(response); + } + + @Override + public void restart() { + shutDown(); + startProcess(); + } + + public void shutDown(){ + this.remoteServer.stopServers(); + } + + @Override + public int getId() { + return 4; + } + + public synchronized void log(String message) { + String logMessage = new Date() + " - " + message; + System.out.println(logMessage); + + try (FileWriter fw = new FileWriter("Replica4_log.txt", true); + BufferedWriter bw = new BufferedWriter(fw); + PrintWriter out = new PrintWriter(bw)) { + out.println(logMessage); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/derms/Replica4pkg/DERMSInterface.java b/src/main/java/derms/Replica4pkg/DERMSInterface.java new file mode 100644 index 0000000..933e619 --- /dev/null +++ b/src/main/java/derms/Replica4pkg/DERMSInterface.java @@ -0,0 +1,16 @@ +package derms.Replica4pkg; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +@WebService +@SOAPBinding(style = SOAPBinding.Style.RPC) +public interface DERMSInterface { + String addResource(String resourceID, String resourceName, int duration); + String removeResource(String resourceID, int duration); + String listResourceAvailability(String resourceName); + String requestResource(String coordinatorID, String resourceID, int duration); + String findResource(String coordinatorID, String resourceName); + String returnResource(String coordinatorID, String resourceID); + String swapResource(String coordinatorID, String oldResourceID, String oldResourceType, String newResourceID, String newResourceType); +} \ No newline at end of file diff --git a/src/main/java/derms/Replica4pkg/RemoteServer.java b/src/main/java/derms/Replica4pkg/RemoteServer.java new file mode 100644 index 0000000..a572dbe --- /dev/null +++ b/src/main/java/derms/Replica4pkg/RemoteServer.java @@ -0,0 +1,43 @@ +//RemoteServer.java +package derms.Replica4pkg; + +import javax.xml.ws.Endpoint; +import java.util.*; + +public class RemoteServer { + private List endpoints = new ArrayList<>(); + + public RemoteServer() { + try { + Map UDPPorts = new HashMap<>(); + UDPPorts.put("MTL", 4000); + UDPPorts.put("QUE", 5000); + UDPPorts.put("SHE", 6000); + + String[] serverNames = {"MTL", "QUE", "SHE"}; + int i = 0; + for (String serverName : serverNames) { + int UDPPort = UDPPorts.get(serverName); + Server server = new Server(); + server.initServer(serverName, UDPPort, UDPPorts); + int port = 8080 + i; + String url = "http://localhost:" + port + "/DERMS/" + serverName; + Endpoint endpoint = Endpoint.publish(url, server); + endpoints.add(endpoint); // Keep track of the Endpoint + i++; + System.out.println(serverName + " Server ready and waiting ..."); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Method to stop all servers + public void stopServers() { + for (Endpoint endpoint : endpoints) { + endpoint.stop(); + } + System.out.println("All servers have been stopped."); + } +} \ No newline at end of file diff --git a/src/main/java/derms/Replica4pkg/Resource.java b/src/main/java/derms/Replica4pkg/Resource.java new file mode 100644 index 0000000..365957e --- /dev/null +++ b/src/main/java/derms/Replica4pkg/Resource.java @@ -0,0 +1,43 @@ +//Resource.java +package derms.Replica4pkg; + +import java.io.Serializable; + +public class Resource implements Serializable { + private static final long serialVersionUID = 1L; + + private String resourceName; + private int duration; + + public Resource(String resourceName, int duration) { + this.resourceName = resourceName.toUpperCase(); + this.duration = duration; + } + + // Getters + public String getResourceName() { + return resourceName; + } + + public synchronized int getDuration() { + return duration; + } + + // Setters + public synchronized void setDuration(int duration) { + this.duration = duration; + } + + // Methods to manipulate duration + public synchronized void addDuration(int additionalDuration) { + if (additionalDuration > 0) { + this.duration += additionalDuration; + } + } + + public synchronized void subDuration(int decrement) { + if (decrement > 0 && this.duration >= decrement) { + this.duration -= decrement; + } + } +} \ No newline at end of file diff --git a/src/main/java/derms/Replica4pkg/Server.java b/src/main/java/derms/Replica4pkg/Server.java new file mode 100644 index 0000000..ee701d3 --- /dev/null +++ b/src/main/java/derms/Replica4pkg/Server.java @@ -0,0 +1,479 @@ +//Server.java +package derms.Replica4pkg; + +import javax.jws.WebService; +import javax.jws.WebMethod; +import java.io.*; +import java.net.*; +import java.util.*; + +@WebService(endpointInterface = "org.DERMS.DERMSInterface") +public class Server implements DERMSInterface { + private String serverName; + private int udpPort; + private Map> resourceMap; //resourceName -> (resourceID -> Resource) + private Map> coordinatorResources; //coordinatorID -> Set + private Map> coordinatorResourceDurations; //coordinatorID -> (resourceID -> allocatedDuration) + private Map serverUdpPorts; //serverName -> UDP port + + + public Server() { + this.resourceMap = new HashMap<>(); + this.coordinatorResources = new HashMap<>(); + this.coordinatorResourceDurations = new HashMap<>(); + startUDPListener(); + } + + @WebMethod(exclude = true) + public void initServer(String serverName, int udpPort, Map serverUdpPorts) { + this.serverName = serverName; + this.udpPort = udpPort; + this.serverUdpPorts = serverUdpPorts; + } + + //Start UDP Listener + private void startUDPListener() { + new Thread(() -> { + try (DatagramSocket socket = new DatagramSocket(udpPort)) { + byte[] buffer = new byte[4096]; + System.out.println(serverName + " UDP Server started on port " + udpPort); + + while (true) { + DatagramPacket request = new DatagramPacket(buffer, buffer.length); + socket.receive(request); + new Thread(() -> handleUDPRequest(request)).start(); + } + } catch (IOException e) { + e.printStackTrace(); + } + }).start(); + } + + //Handle UDP Request + private void handleUDPRequest(DatagramPacket requestPacket) { + try { + String requestData = new String(requestPacket.getData(), 0, requestPacket.getLength()); + String[] parts = requestData.split(":"); + String methodName = parts[0]; + String[] params = Arrays.copyOfRange(parts, 1, parts.length); + + String responseData = ""; + + switch (methodName) { + case "listResourceAvailability": + responseData = handleListResourceAvailability(params[0]); + break; + case "requestResource": + responseData = handleLocalResourceRequest(params[0], params[1], Integer.parseInt(params[2])); + break; + case "findResource": + responseData = handleFindResource(params[0], params[1]); + break; + case "returnResource": + responseData = handleReturnResource(params[0], params[1]); + break; + case "swapRequestResource": + responseData = handleSwapRequestResource(params[0], params[1], Integer.parseInt(params[2])); + break; + case "swapReturnResource": + responseData = handleSwapReturnResource(params[0], params[1]); + break; + case "checkCoordinatorResource": + responseData = checkCoordinatorHasResource(params[0], params[1]); + break; + case "getCoordinatorResourceDuration": + int duration = getCoordinatorResourceDuration(params[0], params[1]); + responseData = String.valueOf(duration); + break; + default: + responseData = "Invalid method"; + } + + //Send response + byte[] responseBytes = responseData.getBytes(); + DatagramPacket responsePacket = new DatagramPacket(responseBytes, responseBytes.length, requestPacket.getAddress(), requestPacket.getPort()); + DatagramSocket socket = new DatagramSocket(); + socket.send(responsePacket); + socket.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + //Operation Handlers + private synchronized String handleListResourceAvailability(String resourceName) { + StringBuilder result = new StringBuilder(); + resourceName = resourceName.toUpperCase(); + Map resources = resourceMap.get(resourceName); + + if (resources != null) { + for (Resource resource : resources.values()) { + if (resource.getDuration() > 0) { + result.append(resource.getResourceName()).append(" - ").append(serverName).append(" ").append(resource.getDuration()).append("\n"); + } + } + } + return result.toString(); + } + + private synchronized String handleLocalResourceRequest(String coordinatorID, String resourceID, int duration) { + for (Map resources : resourceMap.values()) { + Resource resource = resources.get(resourceID); + if (resource != null) { + if (resource.getDuration() >= duration) { + resource.subDuration(duration); + coordinatorResources.computeIfAbsent(coordinatorID, k -> new HashSet<>()).add(resourceID); + coordinatorResourceDurations.computeIfAbsent(coordinatorID, k -> new HashMap<>()).put(resourceID, duration); + + log("Resource " + resourceID + " allocated to " + coordinatorID + " for duration " + duration); + return "Resource " + resourceID + " allocated successfully."; + } else { + return "Insufficient duration for resource " + resourceID; + } + } + } + return "Resource " + resourceID + " not found."; + } + + private synchronized String handleFindResource(String coordinatorID, String resourceName) { + StringBuilder result = new StringBuilder(); + resourceName = resourceName.toUpperCase(); + Set resources = coordinatorResources.get(coordinatorID); + if (resources != null) { + Map resourceDurations = coordinatorResourceDurations.get(coordinatorID); + if (resourceDurations != null) { + for (String resourceID : resources) { + Resource resource = getResourceByID(resourceID); + if (resource != null && resource.getResourceName().equals(resourceName)) { + Integer allocatedDuration = resourceDurations.get(resourceID); + if (allocatedDuration != null) { + result.append(resource.getResourceName()).append(" - ").append(resourceID).append(" ").append(allocatedDuration).append("\n"); + } + } + } + } + } + return result.toString(); + } + + private synchronized String handleReturnResource(String coordinatorID, String resourceID) { + Set resources = coordinatorResources.get(coordinatorID); + if (resources != null && resources.contains(resourceID)) { + resources.remove(resourceID); + if (resources.isEmpty()) { + coordinatorResources.remove(coordinatorID); + } + Resource resource = getResourceByID(resourceID); + if (resource != null) { + Map resourceDurations = coordinatorResourceDurations.get(coordinatorID); + if (resourceDurations != null) { + Integer allocatedDuration = resourceDurations.remove(resourceID); + if (allocatedDuration != null) { + resource.addDuration(allocatedDuration); + } + if (resourceDurations.isEmpty()) { + coordinatorResourceDurations.remove(coordinatorID); + } + } + log("Coordinator " + coordinatorID + " returned resource " + resourceID); + return "Resource " + resourceID + " returned successfully."; + } else { + return "Resource " + resourceID + " not found."; + } + } else { + return "You do not occupy resource " + resourceID + "."; + } + } + + //Helper Methods + private Resource getResourceByID(String resourceID) { + for (Map resources : resourceMap.values()) { + if (resources.containsKey(resourceID)) { + return resources.get(resourceID); + } + } + return null; + } + + private synchronized String handleSwapRequestResource(String coordinatorID, String resourceID, int duration) { + //Attempt to allocate the resource to the coordinator + for (Map resources : resourceMap.values()) { + Resource resource = resources.get(resourceID); + if (resource != null) { + if (resource.getDuration() >= duration) { + resource.subDuration(duration); + coordinatorResources.computeIfAbsent(coordinatorID, k -> new HashSet<>()).add(resourceID); + coordinatorResourceDurations.computeIfAbsent(coordinatorID, k -> new HashMap<>()).put(resourceID, duration); + log("Resource " + resourceID + " temporarily allocated to " + coordinatorID + " for swapping, duration " + duration); + return "Success"; + } else { + return "Insufficient duration for resource " + resourceID; + } + } + } + return "Resource " + resourceID + " not found."; + } + + private synchronized String handleSwapReturnResource(String coordinatorID, String resourceID) { + Set resources = coordinatorResources.get(coordinatorID); + if (resources != null && resources.contains(resourceID)) { + resources.remove(resourceID); + if (resources.isEmpty()) { + coordinatorResources.remove(coordinatorID); + } + Resource resource = getResourceByID(resourceID); + if (resource != null) { + Map resourceDurations = coordinatorResourceDurations.get(coordinatorID); + if (resourceDurations != null) { + Integer allocatedDuration = resourceDurations.remove(resourceID); + if (allocatedDuration != null) { + resource.addDuration(allocatedDuration); + } + if (resourceDurations.isEmpty()) { + coordinatorResourceDurations.remove(coordinatorID); + } + } + log("Coordinator " + coordinatorID + " resource " + resourceID + " allocation undone during swap"); + return "Success"; + } else { + return "Resource " + resourceID + " not found."; + } + } else { + return "Coordinator did not acquire resource " + resourceID; + } + } + + private String sendUDPRequest(String serverName, String methodName, String... params) { + String response = ""; + try { + InetAddress host = InetAddress.getByName("localhost"); + int port = serverUdpPorts.get(serverName); + String requestData = methodName + ":" + String.join(":", params); + + byte[] requestBytes = requestData.getBytes(); + DatagramPacket requestPacket = new DatagramPacket(requestBytes, requestBytes.length, host, port); + + DatagramSocket socket = new DatagramSocket(); + socket.send(requestPacket); + + byte[] buffer = new byte[4096]; + DatagramPacket responsePacket = new DatagramPacket(buffer, buffer.length); + socket.receive(responsePacket); + + response = new String(responsePacket.getData(), 0, responsePacket.getLength()); + socket.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return response; + } + + //Implement ResponderInterface Methods + @Override + public synchronized String addResource(String resourceID, String resourceName, int duration) { + resourceName = resourceName.toUpperCase(); + Map resources = resourceMap.computeIfAbsent(resourceName, k -> new HashMap<>()); + Resource resource = resources.get(resourceID); + + if (resource != null) { + if (duration > resource.getDuration()) { + resource.setDuration(duration); + log("Updated duration of resource " + resourceID); + return "Resource " + resourceID + " duration updated."; + } else { + log("Resource " + resourceID + " already exists with greater or equal duration."); + return "Resource " + resourceID + " already exists with greater or equal duration."; + } + } else { + resource = new Resource(resourceName, duration); + resources.put(resourceID, resource); + log("Added new resource " + resourceID); + return "Resource " + resourceID + " added successfully."; + } + } + + @Override + public synchronized String removeResource(String resourceID, int duration) { + for (Map resources : resourceMap.values()) { + Resource resource = resources.get(resourceID); + if (resource != null) { + if (duration >= resource.getDuration()) { + resources.remove(resourceID); + log("Resource " + resourceID + " completely removed."); + return "Resource " + resourceID + " completely removed."; + } else { + resource.subDuration(duration); + log("Decreased duration of resource " + resourceID); + return "Resource " + resourceID + " duration decreased by " + duration + "."; + } + } + } + log("Resource " + resourceID + " not found."); + return "Resource " + resourceID + " not found."; + } + + @Override + public String listResourceAvailability(String resourceName) { + resourceName = resourceName.toUpperCase(); + StringBuilder result = new StringBuilder(); + + synchronized (this) { + Map resources = resourceMap.get(resourceName); + if (resources != null) { + for (Resource resource : resources.values()) { + if (resource.getDuration() > 0) { + result.append(resource.getResourceName()).append(" - ").append(serverName).append(" ").append(resource.getDuration()).append("\n"); + } + } + } + } + + for (String otherServer : serverUdpPorts.keySet()) { + if (!otherServer.equals(serverName)) { + String response = sendUDPRequest(otherServer, "listResourceAvailability", resourceName); + result.append(response); + } + } + + return result.toString(); + } + + @Override + public String requestResource(String coordinatorID, String resourceID, int duration) { + String resourceServer = resourceID.substring(0, 3).toUpperCase(); + String response; + + if (resourceServer.equals(serverName)) { + response = handleLocalResourceRequest(coordinatorID, resourceID, duration); + } else { + response = sendUDPRequest(resourceServer, "requestResource", coordinatorID, resourceID, String.valueOf(duration)); + } + + log("Coordinator " + coordinatorID + " requested resource " + resourceID + ": " + response); + return response; + } + + @Override + public String findResource(String coordinatorID, String resourceName) { + resourceName = resourceName.toUpperCase(); + StringBuilder result = new StringBuilder(); + + for (String otherServer : serverUdpPorts.keySet()) { + String response; + if (otherServer.equals(serverName)) { + response = handleFindResource(coordinatorID, resourceName); + } else { + response = sendUDPRequest(otherServer, "findResource", coordinatorID, resourceName); + } + result.append(response); + } + + return result.toString(); + } + + @Override + public String returnResource(String coordinatorID, String resourceID) { + String resourceServer = resourceID.substring(0, 3).toUpperCase(); + String response; + + if (resourceServer.equals(serverName)) { + response = handleReturnResource(coordinatorID, resourceID); + } else { + response = sendUDPRequest(resourceServer, "returnResource", coordinatorID, resourceID); + } + + log("Coordinator " + coordinatorID + " returned resource " + resourceID + ": " + response); + return response; + } + + private synchronized int getCoordinatorResourceDuration(String coordinatorID, String resourceID) { + Map resourceDurations = coordinatorResourceDurations.get(coordinatorID); + if (resourceDurations != null && resourceDurations.containsKey(resourceID)) { + return resourceDurations.get(resourceID); + } + return 0; + } + + private synchronized String checkCoordinatorHasResource(String coordinatorID, String resourceID) { + Set resources = coordinatorResources.get(coordinatorID); + if (resources != null && resources.contains(resourceID)) { + return "true"; + } + return "false"; + } + + @Override + public String swapResource(String coordinatorID, String oldResourceID, String oldResourceType, String newResourceID, String newResourceType) { + String oldResourceServer = oldResourceID.substring(0, 3).toUpperCase(); + String newResourceServer = newResourceID.substring(0, 3).toUpperCase(); + + //Check if the coordinator has the old resource + String checkOldResourceResponse; + if (oldResourceServer.equals(serverName)) { + checkOldResourceResponse = checkCoordinatorHasResource(coordinatorID, oldResourceID); + } else { + checkOldResourceResponse = sendUDPRequest(oldResourceServer, "checkCoordinatorResource", coordinatorID, oldResourceID); + } + + if (!checkOldResourceResponse.equals("true")) { + return "Coordinator has not acquired the old resource."; + } + + //Get the duration allocated to the old resource + int duration; + if (oldResourceServer.equals(serverName)) { + duration = getCoordinatorResourceDuration(coordinatorID, oldResourceID); + } else { + String durationStr = sendUDPRequest(oldResourceServer, "getCoordinatorResourceDuration", coordinatorID, oldResourceID); + duration = Integer.parseInt(durationStr); + } + + //Attempt to acquire the new resource + String requestResponse; + if (newResourceServer.equals(serverName)) { + requestResponse = handleLocalResourceRequest(coordinatorID, newResourceID, duration); + } else { + requestResponse = sendUDPRequest(newResourceServer, "requestResource", coordinatorID, newResourceID, String.valueOf(duration)); + } + + if (!requestResponse.contains("allocated successfully")) { + return "Failed to acquire new resource: " + requestResponse; + } + + //Return the old resource + String returnResponse; + if (oldResourceServer.equals(serverName)) { + returnResponse = handleReturnResource(coordinatorID, oldResourceID); + } else { + returnResponse = sendUDPRequest(oldResourceServer, "returnResource", coordinatorID, oldResourceID); + } + + if (!returnResponse.contains("returned successfully")) { + //Undo the allocation of the new resource + if (newResourceServer.equals(serverName)) { + handleReturnResource(coordinatorID, newResourceID); + } else { + sendUDPRequest(newResourceServer, "returnResource", coordinatorID, newResourceID); + } + return "Failed to return old resource: " + returnResponse; + } + + log("Coordinator " + coordinatorID + " swapped resource " + oldResourceID + " with " + newResourceID); + + return "Resource swap successful."; + } + + //Logging method + public synchronized void log(String message) { + String logMessage = new Date() + " - " + message; + System.out.println(logMessage); + + try (FileWriter fw = new FileWriter(serverName + "_server_log.txt", true); + BufferedWriter bw = new BufferedWriter(fw); + PrintWriter out = new PrintWriter(bw)) { + out.println(logMessage); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file -- cgit v1.2.3