From d267dd1dda606f0c56d8afaa7187485e60ebfd86 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Thu, 28 Nov 2024 17:32:28 -0500 Subject: move replica2 to top level --- src/main/java/derms/replica2/ResponderServer.java | 94 +++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/main/java/derms/replica2/ResponderServer.java (limited to 'src/main/java/derms/replica2/ResponderServer.java') diff --git a/src/main/java/derms/replica2/ResponderServer.java b/src/main/java/derms/replica2/ResponderServer.java new file mode 100644 index 0000000..02ff6b6 --- /dev/null +++ b/src/main/java/derms/replica2/ResponderServer.java @@ -0,0 +1,94 @@ +package derms.replica2; + +import java.io.IOException; +import java.net.InetAddress; +import java.time.Duration; +import java.util.Collection; +import java.util.NoSuchElementException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +class ResponderServer { + static final Duration timeout = Duration.ofSeconds(5); + + private City city; + private Resources resources; + private Servers servers; + private Logger log; + + ResponderServer(City city, Resources resources, Servers servers) throws IOException { + this.city = city; + this.resources = resources; + this.servers = servers; + this.log = DermsLogger.getLogger(this.getClass()); + } + + ResponderServer() throws IOException { + this(new City(), new Resources(), new Servers()); + } + + void addResource(Resource r) { + resources.add(r); + log.info("Added resource "+r+" - success"); + } + + void removeResource(ResourceID rid, int duration) throws NoSuchResourceException { + log.info("Remove duration "+duration+" from "+rid); + try { + Resource resource = resources.getByID(rid); + synchronized (resource) { + if (duration < 0 || duration >= resource.duration) { + resources.removeByID(rid); + log.info("Removed resource "+rid+" - success"); + } else { + resource.duration -= duration; + log.info("Removed duration from resource "+rid+". New duration: "+resource.duration+" - success"); + } + } + } catch (NoSuchElementException e) { + // Wanted to remove duration from resource. + if (duration >= 0) { + String msg = "Cannot remove duration from "+rid+": resource does not exist."; + log.warning(msg); + throw new NoSuchResourceException(msg); + } + + // Duration is negative---wanted to remove resource completely. + // Success because it is already removed. + log.info("Not removing "+rid+": resource does not exist."); + } + } + + Resource[] listResourceAvailability(ResourceType rname) throws ServerCommunicationError { + log.info("Request for available "+rname); + Collection availableResources = ConcurrentHashMap.newKeySet(); + ExecutorService pool = Executors.newFixedThreadPool(servers.size()); + try { + for (InetAddress serverAddr : servers.all()) { + pool.execute(new ResourceAvailability.Client(serverAddr, rname, availableResources)); + } + } catch (IOException e) { + String msg = "Failed to start ResourceAvailability Client: "+e.getMessage(); + log.severe(msg); + throw new ServerCommunicationError("ResourceAvailability: "+msg); + } + + log.fine("Started worker threads"); + pool.shutdown(); + boolean terminated; + try { + terminated = pool.awaitTermination(timeout.toMillis(), TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new ServerCommunicationError("listResourceAvailability(): listResourceAvailability() interrupted: "+e.getMessage()); + } + if (!terminated) { + throw new ServerCommunicationError("ResourceAvailability: request timed out: no response after "+timeout.toString()); + } + log.info("Response length "+availableResources.size()); + Resource[] arr = new Resource[0]; + return availableResources.toArray(arr); + } +} -- cgit v1.2.3