package pl.edu.mimuw.cloudatlas.agent; import pl.edu.mimuw.cloudatlas.agent.messages.*; import pl.edu.mimuw.cloudatlas.agent.modules.GossipGirlStrategies; import pl.edu.mimuw.cloudatlas.agent.modules.TimerScheduledTask; import pl.edu.mimuw.cloudatlas.model.*; import java.lang.reflect.UndeclaredThrowableException; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; public class HierarchyConfig { private GossipGirlStrategies gossipGirlStrategies; private GossipGirlStrategies.ZoneSelectionStrategy zoneSelectionStrategy; private Random random = new Random(); private EventBus eventBus; HierarchyConfig(EventBus eventBus, String zonePath, String zoneStrategy) { zoneSelectionStrategy = parseStrategy(zoneStrategy); gossipGirlStrategies = new GossipGirlStrategies(new PathName(zonePath)); this.eventBus = eventBus; } private GossipGirlStrategies.ZoneSelectionStrategy parseStrategy(String selectionStrategy) { switch (selectionStrategy) { case "RoundRobinExp": return GossipGirlStrategies.ZoneSelectionStrategy.ROUND_ROBIN_EXP_FREQ; case "RoundRobinUniform": return GossipGirlStrategies.ZoneSelectionStrategy.ROUND_ROBIN_SAME_FREQ; case "RandomExp": return GossipGirlStrategies.ZoneSelectionStrategy.RANDOM_DECR_EXP; case "RandomUniform": return GossipGirlStrategies.ZoneSelectionStrategy.RANDOM_UNFIORM; default: throw new UnsupportedOperationException("Selection strategy doesnt exist"); } } public void startGossip(long gossipPeriod) { Supplier taskSupplier = () -> new TimerScheduledTask() { public void run() { try { System.out.println("INFO: initiating gossip"); PathName gossipLevel = gossipGirlStrategies.selectStrategy(zoneSelectionStrategy); ValueContact contact = selectContactFromLevel(gossipLevel); if (contact != null) { System.out.println("INFO: found a contact " + contact.toString()); InitiateGossipMessage message = new InitiateGossipMessage("", 0, new PathName("/uw/violet07"), contact); sendMessage(message); } else { System.out.println("DEBUG: couldn't find contact for gossip"); } } catch (InterruptedException e) { System.out.println("Interrupted while initiating gossip"); } catch (Exception e) { System.out.println("ERROR: something happened " + e.toString()); } } }; AgentUtils.startRecursiveTask(taskSupplier, gossipPeriod, eventBus); } private ValueContact selectContactFromLevel(PathName path) throws Exception { CompletableFuture responseFuture = new CompletableFuture(); this.eventBus.addMessage(new RequestStateMessage("", 0, responseFuture)); StateMessage response = (StateMessage) responseFuture.get(); ZMI root = response.getZMI(); List siblings = getSiblings(root, path); filterEmptyContacts(siblings); if (siblings.isEmpty()) { return selectFallbackContact(); } ZMI zmi = selectZMI(siblings); ValueSet contactsValue = (ValueSet) zmi.getAttributes().getOrNull("contacts"); Set valueSet = contactsValue.getValue(); return selectContactFromSet(valueSet); } // TODO private ValueContact selectFallbackContact() throws Exception { return null; } private ZMI selectZMI(List zmis) throws Exception { int i = random.nextInt(zmis.size()); for (ZMI zmi : zmis) { if (i == 0) { return zmi; } i--; } System.out.println("ERROR: empty list passed to selectZMI"); throw new Exception("empty list passed to selectZMI"); } private ValueContact selectContactFromSet(Set contacts) throws Exception { int i = random.nextInt(contacts.size()); for (Value contact : contacts) { if (i == 0) { return (ValueContact) contact; } i--; } System.out.println("ERROR: empty list passed to selectContactFromSet"); throw new Exception("empty list passed to selectContactFromSet"); } private List getSiblings(ZMI root, PathName path) { try { List siblingsAndI = root.findDescendant(path).getFather().getSons(); List siblings = new ArrayList(); for (ZMI siblingOrI : siblingsAndI) { if (!siblingOrI.getPathName().equals(path)) { siblings.add(siblingOrI); } } return siblings; } catch (ZMI.NoSuchZoneException e) { System.out.println("ERROR: didn't find path when looking for siblings"); return new ArrayList(); } } private void filterEmptyContacts(List zmis) { Iterator iterator = zmis.iterator(); while (iterator.hasNext()) { ZMI zmi = iterator.next(); ValueSet contacts = (ValueSet) zmi.getAttributes().getOrNull("contacts"); if (contacts == null || contacts.isNull() || contacts.isEmpty()) { iterator.remove(); } } } public void startQueries(long queriesPeriod) { Supplier taskSupplier = () -> new TimerScheduledTask() { public void run() { try { sendMessage(new RunQueriesMessage("", 0)); } catch (InterruptedException e) { System.out.println("Interrupted while triggering queries"); } } }; AgentUtils.startRecursiveTask(taskSupplier, queriesPeriod, eventBus); } }