package com.workshare.msnos.core; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.UUID; import javax.annotation.concurrent.GuardedBy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.workshare.msnos.core.geo.Location; import com.workshare.msnos.core.protocols.ip.Endpoint; import com.workshare.msnos.core.protocols.ip.Endpoint.Type; import com.workshare.msnos.soup.json.Json; import com.workshare.msnos.usvc.IMicroservice; public class Ring { private static Logger log = LoggerFactory.getLogger(Ring.class); private final UUID uuid; @GuardedBy("this") private Location location = Location.UNKNOWN; private Ring(UUID uuid) { this.uuid = uuid; } public UUID uuid() { return uuid; } public synchronized Location location() { return location; } public synchronized void onMicroserviceJoin(IMicroservice uservice) { Location loc = uservice.getLocation(); if (loc.getPrecision() > location.getPrecision()) { location = loc; log.debug("Location of the ring udated: {}", location); } } @Override public String toString() { return Json.toJsonString(this); } @Override public int hashCode() { return uuid.hashCode(); } @Override public boolean equals(Object obj) { try { Ring other = (Ring) obj; return other.uuid.equals(this.uuid); } catch (Exception any) { return false; } } private static Map<UUID, Ring> rings = new HashMap<UUID, Ring>(); public static Ring make(Set<Endpoint> endpoints) { Endpoint point = null; if (endpoints != null) for (Endpoint endpoint : endpoints) { point = endpoint; if (endpoint.getType() == Type.UDP) break; } UUID uid = null; if (point != null) { final byte[] address = point.getNetwork().getAddress(); if (address != null) { final long most = toLong(address); final long least = point.getNetwork().getPrefix(); uid = new UUID(most, least); } } if (uid == null) { uid = UUID.randomUUID(); log.warn("Random ring is being generated as no endpoints are available: {}", endpoints); } synchronized(rings) { Ring ring = rings.get(uid); if (ring == null) { ring = new Ring(uid); rings.put(uid, ring); log.debug("Created new ring based on UUID {}", uid); } return ring; } } public static Ring random() { return new Ring(UUID.randomUUID()); } private static long toLong(byte[] values) { long shift = 0; long total = 0; for (byte value : values) { final long lval = (int)(value&0xff); total = total + lval << shift; shift += 8; } return total; } }