Skip to content

Instantly share code, notes, and snippets.

@tinyzero4
Created October 5, 2023 14:58
Show Gist options
  • Save tinyzero4/f9b34b77231adbdf822d9c14aeab6456 to your computer and use it in GitHub Desktop.
Save tinyzero4/f9b34b77231adbdf822d9c14aeab6456 to your computer and use it in GitHub Desktop.
Tracker task
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicInteger;
import static java.lang.Integer.parseInt;
import static java.util.Objects.requireNonNull;
/**
* Host Tracker: Server names consist of an alphabetic host type (e.g. "apibox") concatenated with the server number, with server numbers allocated sequentially (so, "apibox:1", "apibox:2", etc. are valid hostnames). Write a tracking class with two operations, "allocate(hostType)" and "deallocate(hostName)". The former should reserve and return the next available hostname, while the latter should release that hostname back into the pool.
* For example:
*
* tracker = new Tracker();
*
* tracker.allocate("apibox");
* >> "apibox:1"
*
* tracker.allocate("apibox");
* >> "apibox:2"
*
* tracker.deallocate("apibox:1");
* tracker.allocate("apibox");
* >> "apibox:1"
*
* tracker.allocate("apibox");
* >> "apibox:3"
*
* tracker.deallocate("apibox:2");
* tracker.allocate("apibox");
* >> "apibox:2"
*
* tracker.allocate("sitebox");
*/
public class Tracker {
private final ConcurrentHashMap<String, AtomicInteger> byTypeCounters = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, ConcurrentSkipListSet<Integer>> byTypeDeAllocations = new ConcurrentHashMap<>();
public String allocate(String hostType) {
requireNonNull(hostType);
if (hostType.isBlank()) throw new IllegalArgumentException("hostType should not be blank");
Integer nextVersion = null;
var deallocations = byTypeDeAllocations.get(hostType);
if (deallocations != null) {
nextVersion = deallocations.pollFirst();
}
if (nextVersion == null) {
var byTypeCounter = byTypeCounters.getOrDefault(hostType, new AtomicInteger(0));
nextVersion = byTypeCounter.incrementAndGet();
byTypeCounters.put(hostType, byTypeCounter);
}
return hostType + ":" + nextVersion;
}
public void deallocate(String hostname) {
requireNonNull(hostname);
if (hostname.isBlank()) throw new IllegalArgumentException("hostname should not be blank");
var parts = hostname.split(":");
if (parts.length != 2) throw new IllegalArgumentException("invalid hostname definition");
var hostType = parts[0];
var version = parseInt(parts[1]);
var deallocations = byTypeDeAllocations.getOrDefault(hostType, new ConcurrentSkipListSet<>());
deallocations.add(version);
byTypeDeAllocations.put(hostType, deallocations);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment