From ab118d47c1c371e5d30f576216a8f347bd746974 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Tue, 26 Nov 2024 15:52:51 -0500 Subject: frontend --- src/main/java/derms/frontend/DERMSServerImpl.java | 347 ++++++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100644 src/main/java/derms/frontend/DERMSServerImpl.java (limited to 'src/main/java/derms/frontend/DERMSServerImpl.java') diff --git a/src/main/java/derms/frontend/DERMSServerImpl.java b/src/main/java/derms/frontend/DERMSServerImpl.java new file mode 100644 index 0000000..c65fea9 --- /dev/null +++ b/src/main/java/derms/frontend/DERMSServerImpl.java @@ -0,0 +1,347 @@ +// DERMSImpl.java +package derms.frontend; + +//import logger.Logger; +//import model.Resource; +import java.util.*; +import java.util.stream.Collectors; +import java.util.Optional; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.jws.WebMethod; +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; +import javax.jws.soap.SOAPBinding.Style; + +//import constants.Constants; +//import constants.PortConstants; +//import validation.ValidationService; +//import interfaces.DERMSInterface; + +@WebService(endpointInterface = "frontend.DERMSInterface") +@SOAPBinding(style = Style.RPC) +public class DERMSServerImpl implements DERMSInterface { + + private static long DYNAMIC_TIMEOUT = 10000; + private static int Rm1BugCount = 0; + private static int Rm2BugCount = 0; + private static int Rm3BugCount = 0; + private static int Rm4BugCount = 0; + private static int Rm1NoResponseCount = 0; + private static int Rm2NoResponseCount = 0; + private static int Rm3NoResponseCount = 0; + private static int Rm4NoResponseCount = 0; + private long responseTime = DYNAMIC_TIMEOUT; + private long startTime; + private CountDownLatch latch; + private final FEInterface inter; + private final List responses = new ArrayList<>(); + + public DERMSServerImpl(FEInterface inter) { + super(); + this.inter = inter; + } + + @WebMethod + public synchronized String addResource(String resourceID, String resourceName, int duration) { + MyRequest myRequest = new MyRequest("addResource", ""); + myRequest.setResourceID(resourceID); + myRequest.setResourceType(resourceName); + myRequest.setDuration(duration); + myRequest.setSequenceNumber(sendUdpUnicastToSequencer(myRequest)); + System.out.println("FE Implementation:addEvent>>>" + myRequest.toString()); + return validateResponses(myRequest); + } + + @WebMethod + public synchronized String removeResource(String resourceID, int duration) { + MyRequest myRequest = new MyRequest("removeResource", ""); + myRequest.setResourceID(resourceID); + myRequest.setDuration(duration); + myRequest.setSequenceNumber(sendUdpUnicastToSequencer(myRequest)); + System.out.println("FE Implementation:removeEvent>>>" + myRequest.toString()); + return validateResponses(myRequest); + } + + @WebMethod + public synchronized String listResourceAvailability(String resourceName) { + MyRequest myRequest = new MyRequest("listEventAvailability", ""); + myRequest.setResourceType(resourceName); + myRequest.setSequenceNumber(sendUdpUnicastToSequencer(myRequest)); + System.out.println("FE Implementation:listEventAvailability>>>" + myRequest.toString()); + return validateResponses(myRequest); + } + + @WebMethod + public synchronized String requestResource(String coordinatorID, String resourceID, int duration) { + MyRequest myRequest = new MyRequest("requestResource", coordinatorID); + myRequest.setResourceID(resourceID); + myRequest.setDuration(duration); + myRequest.setSequenceNumber(sendUdpUnicastToSequencer(myRequest)); + System.out.println("FE Implementation:bookEvent>>>" + myRequest.toString()); + return validateResponses(myRequest); + } + + @WebMethod + public synchronized String findResource(String coordinatorID, String resourceName) { + MyRequest myRequest = new MyRequest("findResource", coordinatorID); + myRequest.setResourceType(resourceName); + myRequest.setSequenceNumber(sendUdpUnicastToSequencer(myRequest)); + System.out.println("FE Implementation:bookEvent>>>" + myRequest.toString()); + return validateResponses(myRequest); + } + + @WebMethod + public synchronized String returnResource(String coordinatorID, String resourceID) { + MyRequest myRequest = new MyRequest("findResource", coordinatorID); + myRequest.setResourceID(resourceID); + myRequest.setSequenceNumber(sendUdpUnicastToSequencer(myRequest)); + System.out.println("FE Implementation:bookEvent>>>" + myRequest.toString()); + return validateResponses(myRequest); + } + + @WebMethod + public synchronized String swapResource(String coordinatorID, String oldResourceID, String oldResourceType, String newResourceID, String newResourceType) { + MyRequest myRequest = new MyRequest("swapResource", coordinatorID); + myRequest.setResourceID(newResourceID); + myRequest.setResourceType(newResourceType); + myRequest.setOldResourceID(oldResourceID); + myRequest.setOldResourceType(oldResourceType); + myRequest.setSequenceNumber(sendUdpUnicastToSequencer(myRequest)); + System.out.println("FE Implementation:swapEvent>>>" + myRequest.toString()); + return validateResponses(myRequest); + } + + public void waitForResponse() { + try { + System.out.println("FE Implementation:waitForResponse>>>ResponsesRemain" + latch.getCount()); + boolean timeoutReached = latch.await(DYNAMIC_TIMEOUT, TimeUnit.MILLISECONDS); + if (timeoutReached) { + setDynamicTimout(); + } + } catch (InterruptedException e) { + e.printStackTrace(); +// inter.sendRequestToSequencer(myRequest); + } +// check result and react correspondingly + } + + private String validateResponses(MyRequest myRequest) { + String resp; + switch ((int) latch.getCount()) { + case 0: + case 1: + case 2: + case 3: + resp = findMajorityResponse(myRequest); + break; + case 4: + resp = "Fail: No response from any server"; + System.out.println(resp); + if (myRequest.haveRetries()) { + myRequest.countRetry(); + resp = retryRequest(myRequest); + } + rmDown(1); + rmDown(2); + rmDown(3); + rmDown(4); + break; + default: + resp = "Fail: " + myRequest.noRequestSendError(); + break; + } + System.out.println("FE Implementation:validateResponses>>>Responses remain:" + latch.getCount() + " >>>Response to be sent to client " + resp); + return resp; + } + + private String findMajorityResponse(MyRequest myRequest) { + RmResponse res1 = null; + RmResponse res2 = null; + RmResponse res3 = null; + RmResponse res4 = null; + for (RmResponse response :responses) { + if (response.getSequenceID() == myRequest.getSequenceNumber()) { + switch (response.getRmNumber()) { + case 1: + res1 = response; + break; + case 2: + res2 = response; + break; + case 3: + res3 = response; + break; + case 4: + res4 = response; + break; + } + } + } + System.out.println("FE Implementation:findMajorityResponse>>>RM1" + ((res1 != null) ? res1.getResponse() : "null")); + System.out.println("FE Implementation:findMajorityResponse>>>RM2" + ((res2 != null) ? res2.getResponse() : "null")); + System.out.println("FE Implementation:findMajorityResponse>>>RM3" + ((res3 != null) ? res3.getResponse() : "null")); + System.out.println("FE Implementation:findMajorityResponse>>>RM4" + ((res4 != null) ? res4.getResponse() : "null")); + + // Handling null responses and marking RMs down + if (res1 == null) rmDown(1); + if (res2 == null) rmDown(2); + if (res3 == null) rmDown(3); + if (res4 == null) rmDown(4); + + // Majority voting logic + List validResponses = Arrays.asList(res1, res2, res3, res4).stream() + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + Map responseCounts = validResponses.stream() + .collect(Collectors.groupingBy(RmResponse::getResponse, Collectors.counting())); + + // Find the response with the highest count + Optional> majorityEntry = responseCounts.entrySet().stream() + .filter(entry -> entry.getValue() >= 3) // At least 3 matching responses for majority + .findFirst(); + + if (majorityEntry.isPresent()) { + String majorityResponse = majorityEntry.get().getKey(); + System.out.println("Majority response found: " + majorityResponse); + return majorityResponse; + } + + // Handle bugs or discrepancies + responseCounts.forEach((response, count) -> { + if (count == 1) { + validResponses.stream() + .filter(r -> r.getResponse().equals(response)) + .forEach(r -> rmBugFound(r.getRmNumber())); + } + }); + + return "Fail: majority response not found"; + } + + private void rmBugFound(int rmNumber) { + switch (rmNumber) { + case 1: + Rm1BugCount++; + if (Rm1BugCount == 3) { + Rm1BugCount = 0; + inter.informRmHasBug(rmNumber); + } + break; + case 2: + Rm2BugCount++; + if (Rm2BugCount == 3) { + Rm2BugCount = 0; + inter.informRmHasBug(rmNumber); + } + break; + + case 3: + Rm3BugCount++; + if (Rm3BugCount == 3) { + Rm3BugCount = 0; + inter.informRmHasBug(rmNumber); + } + break; + case 4: + Rm4BugCount++; + if (Rm4BugCount == 3) { + Rm4BugCount = 0; + inter.informRmHasBug(rmNumber); + } + break; + } + System.out.println("FE Implementation:rmBugFound>>>RM1 - bugs:" + Rm1BugCount); + System.out.println("FE Implementation:rmBugFound>>>RM2 - bugs:" + Rm2BugCount); + System.out.println("FE Implementation:rmBugFound>>>RM3 - bugs:" + Rm3BugCount); + System.out.println("FE Implementation:rmBugFound>>>RM4 - bugs:" + Rm4BugCount); + } + + private void rmDown(int rmNumber) { + DYNAMIC_TIMEOUT = 10000; + switch (rmNumber) { + case 1: + Rm1NoResponseCount++; + if (Rm1NoResponseCount == 3) { + Rm1NoResponseCount = 0; + inter.informRmIsDown(rmNumber); + } + break; + case 2: + Rm2NoResponseCount++; + if (Rm2NoResponseCount == 3) { + Rm2NoResponseCount = 0; + inter.informRmIsDown(rmNumber); + } + break; + + case 3: + Rm3NoResponseCount++; + if (Rm3NoResponseCount == 3) { + Rm3NoResponseCount = 0; + inter.informRmIsDown(rmNumber); + } + break; + case 4: + Rm4NoResponseCount++; + if (Rm4NoResponseCount == 3) { + Rm4NoResponseCount = 0; + inter.informRmIsDown(rmNumber); + } + break; + } + System.out.println("FE Implementation:rmDown>>>RM1 - noResponse:" + Rm1NoResponseCount); + System.out.println("FE Implementation:rmDown>>>RM2 - noResponse:" + Rm2NoResponseCount); + System.out.println("FE Implementation:rmDown>>>RM3 - noResponse:" + Rm3NoResponseCount); + System.out.println("FE Implementation:rmDown>>>RM4 - noResponse:" + Rm3NoResponseCount); + } + + private void setDynamicTimout() { + if (responseTime < 4000) { + DYNAMIC_TIMEOUT = (DYNAMIC_TIMEOUT + (responseTime * 3)) / 2; +// System.out.println("FE Implementation:setDynamicTimout>>>" + responseTime * 2); + } else { + DYNAMIC_TIMEOUT = 10000; + } + System.out.println("FE Implementation:setDynamicTimout>>>" + DYNAMIC_TIMEOUT); + } + + private void notifyOKCommandReceived() { + latch.countDown(); + System.out.println("FE Implementation:notifyOKCommandReceived>>>Response Received: Remaining responses" + latch.getCount()); + } + + public void addReceivedResponse(RmResponse res) { + long endTime = System.nanoTime(); + responseTime = (endTime - startTime) / 1000000; + System.out.println("Current Response time is: " + responseTime); + responses.add(res); + notifyOKCommandReceived(); + } + + private int sendUdpUnicastToSequencer(MyRequest myRequest) { + startTime = System.nanoTime(); + int sequenceNumber = inter.sendRequestToSequencer(myRequest); + myRequest.setSequenceNumber(sequenceNumber); + latch = new CountDownLatch(4); + waitForResponse(); + return sequenceNumber; + } + + private String retryRequest(MyRequest myRequest) { + System.out.println("FE Implementation:retryRequest>>>" + myRequest.toString()); + startTime = System.nanoTime(); + inter.retryRequest(myRequest); + latch = new CountDownLatch(4); + waitForResponse(); + return validateResponses(myRequest); + } + + +} + -- cgit v1.2.3