summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBMatajsz <90217645+BMatajsz@users.noreply.github.com>2024-12-03 00:20:44 +0100
committerGitHub <noreply@github.com>2024-12-03 00:20:44 +0100
commit71fca772c5ed9eb68547def5a70e442f66442487 (patch)
tree02d0bc27ac33885c6bf8c466eb5fb819c2bab37c
parent0214c5d6960c3a1c80dd1657b7800d118f97f9b7 (diff)
parent4c6e9d35dbf18f4b132300e4c560e36f43e412ca (diff)
downloadsoen423-71fca772c5ed9eb68547def5a70e442f66442487.zip
Merge pull request #3 from sam-rba/ReplicaBence
Replica bence
-rw-r--r--.gitignore1
-rw-r--r--src/main/java/derms/Replica4.java108
-rw-r--r--src/main/java/derms/Replica4pkg/DERMSInterface.java16
-rw-r--r--src/main/java/derms/Replica4pkg/RemoteServer.java43
-rw-r--r--src/main/java/derms/Replica4pkg/Resource.java43
-rw-r--r--src/main/java/derms/Replica4pkg/Server.java479
6 files changed, 690 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 7c49878..46a5ad6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@
*.toc
javadoc
target
+.DS_Store
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<Endpoint> endpoints = new ArrayList<>();
+
+ public RemoteServer() {
+ try {
+ Map<String, Integer> 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..080a7db
--- /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 = "derms.Replica4pkg.DERMSInterface")
+public class Server implements DERMSInterface {
+ private String serverName;
+ private int udpPort;
+ private Map<String, Map<String, Resource>> resourceMap; //resourceName -> (resourceID -> Resource)
+ private Map<String, Set<String>> coordinatorResources; //coordinatorID -> Set<resourceID>
+ private Map<String, Map<String, Integer>> coordinatorResourceDurations; //coordinatorID -> (resourceID -> allocatedDuration)
+ private Map<String, Integer> 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<String, Integer> 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<String, Resource> 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<String, Resource> 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<String> resources = coordinatorResources.get(coordinatorID);
+ if (resources != null) {
+ Map<String, Integer> 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<String> 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<String, Integer> 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<String, Resource> 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<String, Resource> 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<String> 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<String, Integer> 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<String, Resource> 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<String, Resource> 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<String, Resource> 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<String, Integer> 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<String> 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