From 7d83929ecfd444c1b4b01546eac285d4b3640080 Mon Sep 17 00:00:00 2001 From: Gregor Riegler Date: Fri, 14 Jun 2013 19:26:42 +0200 Subject: [PATCH] [XVSM] LoadBalancer implemented --- erkenntnisse | 22 +- runXVSM-loadbalancer.sh | 1 + runXVSM-spaces.sh | 1 + runXVSM.sh | 17 +- .../tuwien/sbc/valesriegler/common/Util.java | 18 +- .../sbc/valesriegler/group/GroupAgent.java | 2 +- .../group/gui/DeliveryOverviewModel.java | 3 + .../valesriegler/pizzeria/PizzeriaAgent.java | 20 +- .../pizzeria/gui/PizzeriaFrame.java | 4 + .../gui/tablemodels/DeliveryOrdersModel.java | 9 +- .../valesriegler/types/DeliveryGroupData.java | 10 +- .../valesriegler/types/DeliveryStatus.java | 2 +- .../xvsm/AbstractXVSMConnector.java | 7 +- .../valesriegler/xvsm/LoadBalancerXVSM.java | 200 +++++++++++++++++- .../xvsm/loadbalancer/PizzeriaState.java | 42 ++++ .../xvsm/loadbalancer/PizzeriaStatus.java | 5 + src/main/resources/logback.xml | 2 +- 17 files changed, 312 insertions(+), 53 deletions(-) create mode 100755 runXVSM-loadbalancer.sh create mode 100644 src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/loadbalancer/PizzeriaState.java create mode 100644 src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/loadbalancer/PizzeriaStatus.java diff --git a/erkenntnisse b/erkenntnisse index a3fa1f5..692c1b4 100644 --- a/erkenntnisse +++ b/erkenntnisse @@ -1,4 +1,24 @@ XVSM: Ableitung scheisse: Pizza<->PizzaOrder wegen Template-matching DELETE-LOCK -> Congestion -keine primitiven datentypen für template-matching \ No newline at end of file +keine primitiven datentypen für template-matching +nullpointer-exception: java.lang.NullPointerException + at java.util.LinkedList$ListItr.next(LinkedList.java:891) + at org.mozartspaces.capi3.javanative.persistence.DeferredDB$PersistentTransaction.commitTransaction(DeferredDB.java:68) + at org.mozartspaces.capi3.javanative.isolation.DefaultTransaction.commit(DefaultTransaction.java:133) + at org.mozartspaces.runtime.DefaultTransactionManager.commitTx(DefaultTransactionManager.java:206) + at org.mozartspaces.runtime.DefaultTransactionManager.commitTransaction(DefaultTransactionManager.java:146) + at org.mozartspaces.runtime.tasks.CommitTransactionTask.runSpecific(CommitTransactionTask.java:94) + at org.mozartspaces.runtime.tasks.CommitTransactionTask.runSpecific(CommitTransactionTask.java:47) + at org.mozartspaces.runtime.tasks.AbstractTask.processRequest(AbstractTask.java:265) + at org.mozartspaces.runtime.tasks.AbstractTask.run(AbstractTask.java:122) + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) + at java.lang.Thread.run(Thread.java:722) + at [Request result retrieved with the following stack trace].(Unknown Source) + at org.mozartspaces.core.GenericRequestFuture.enhanceStackTrace(GenericRequestFuture.java:186) + at org.mozartspaces.core.GenericRequestFuture.getResultOrError(GenericRequestFuture.java:129) + at org.mozartspaces.core.GenericRequestFuture.getResult(GenericRequestFuture.java:81) + at org.mozartspaces.core.Capi.sendRequestAndWaitForResult(Capi.java:1307) + at org.mozartspaces.core.Capi.commitTransaction(Capi.java:997) + at org.mozartspaces.core.Capi.commitTransaction(Capi.java:980) diff --git a/runXVSM-loadbalancer.sh b/runXVSM-loadbalancer.sh new file mode 100755 index 0000000..e6625ab --- /dev/null +++ b/runXVSM-loadbalancer.sh @@ -0,0 +1 @@ +mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.loadbalancer.LoadBalancer" -Dexec.args="1 9873" \ No newline at end of file diff --git a/runXVSM-spaces.sh b/runXVSM-spaces.sh index b39fc99..1ac317e 100755 --- a/runXVSM-spaces.sh +++ b/runXVSM-spaces.sh @@ -3,3 +3,4 @@ mvn exec:java -Dexec.mainClass="org.mozartspaces.core.Server" -Dexec.args=9876 & mvn exec:java -Dexec.mainClass="org.mozartspaces.core.Server" -Dexec.args=9875 & mvn exec:java -Dexec.mainClass="org.mozartspaces.core.Server" -Dexec.args=9874 & mvn exec:java -Dexec.mainClass="org.mozartspaces.core.Server" -Dexec.args=9877 & +mvn exec:java -Dexec.mainClass="org.mozartspaces.core.Server" -Dexec.args=9873 & diff --git a/runXVSM.sh b/runXVSM.sh index 2916ed5..7e7c200 100755 --- a/runXVSM.sh +++ b/runXVSM.sh @@ -1,15 +1,16 @@ #!/bin/bash -mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.cook.Cook" -Dexec.args="1 9875" & -mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.cook.Cook" -Dexec.args="2 9875" & -mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.cook.Cook" -Dexec.args="1 9874" & -mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.cook.Cook" -Dexec.args="2 9874" & -mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.waiter.Waiter" -Dexec.args="1 9875" & +#mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.cook.Cook" -Dexec.args="1 9875" & +#mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.cook.Cook" -Dexec.args="2 9875" & +#mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.cook.Cook" -Dexec.args="1 9874" & +#mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.cook.Cook" -Dexec.args="2 9874" & mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.waiter.Waiter" -Dexec.args="2 9875" & +#mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.waiter.Waiter" -Dexec.args="2 9875" & mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.waiter.Waiter" -Dexec.args="1 9874" & -mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.waiter.Waiter" -Dexec.args="2 9874" & +#mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.waiter.Waiter" -Dexec.args="2 9874" & mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.driver.Driver" -Dexec.args="1 9875" & -mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.driver.Driver" -Dexec.args="2 9875" & +#mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.driver.Driver" -Dexec.args="2 9875" & mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.driver.Driver" -Dexec.args="1 9874" & -mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.driver.Driver" -Dexec.args="2 9874" & +#mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.xvsm.driver.Driver" -Dexec.args="2 9874" & mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.pizzeria.PizzeriaAgent" -Dexec.args="XVSM 9875" & mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.pizzeria.PizzeriaAgent" -Dexec.args="XVSM 9874" & +mvn exec:java -Dexec.mainClass="at.ac.tuwien.sbc.valesriegler.group.GroupAgent" -Dexec.args="XVSM" & diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/common/Util.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/common/Util.java index 1ba0576..2cafdec 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/common/Util.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/common/Util.java @@ -21,14 +21,14 @@ public abstract class Util { public int compare(HasOrder o1, HasOrder o2) { final int o1Id = o1.getOrder().getId(); final int o2Id = o2.getOrder().getId(); - if (o1Id == 0) { - if (o2Id > 0) - return 1; - } - if (o2Id == 0) { - if (o1Id > 0) - return 1; - } +// if (o1Id == 0) { +// if (o2Id > 0) +// return 1; +// } +// if (o2Id == 0) { +// if (o1Id > 0) +// return 1; +// } if (o1Id < o2Id) return -1; else if (o1Id > o2Id) @@ -64,7 +64,7 @@ public abstract class Util { public static final String DELIVERY_PROGRESS = "deliveryInProgress"; public static final String DELIVERY_DONE = "deliveryDone"; - public static final boolean runSimulation = true; + public static final boolean runSimulation = false; public static final String NUMBER_DISPLAY_FORMAT = String.format("%%0%dd", 3); diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/group/GroupAgent.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/group/GroupAgent.java index 67f1778..54ea502 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/group/GroupAgent.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/group/GroupAgent.java @@ -74,7 +74,7 @@ public class GroupAgent { } groupAgent = new GroupAgent(); - if (!Util.runSimulation) { + if (true || !Util.runSimulation) { groupGui = new GroupGUI(); SwingUtilities.invokeLater(groupGui); } else if (Util.useJMS) { diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/DeliveryOverviewModel.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/DeliveryOverviewModel.java index 6790c7d..905f982 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/DeliveryOverviewModel.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/DeliveryOverviewModel.java @@ -64,6 +64,9 @@ public class DeliveryOverviewModel extends TableModel { public void addDeliveries(List groups) { synchronized (items) { for (DeliveryGroupData group : groups) { + if(group.getDeliveryStatus() == DeliveryStatus.MOVED) { + continue; + } final DeliveryGroup deliveryGroup = items.get(group.getId()); if (deliveryGroup == null) { log.error("Delivery group not found: {}", group.getId()); diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/PizzeriaAgent.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/PizzeriaAgent.java index abf6917..7edb682 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/PizzeriaAgent.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/PizzeriaAgent.java @@ -53,8 +53,8 @@ public class PizzeriaAgent { case "XVSM" : pizzeriaAgent.createModels(); pizzeriaAgent.initXVSM(args[1]); - if (!Util.runSimulation) { - pizzeriaAgent.initGUI(); + if (true || !Util.runSimulation) { + pizzeriaAgent.initGUI(args[1]); } Util.useJMS = false; break; @@ -64,7 +64,7 @@ public class PizzeriaAgent { pizzeriaAgent.jmspc.init(); pizzeriaAgent.jmsnac = new JMSNAC(new PizzeriaJMSNACMsgListener()); if (!Util.runSimulation) { - pizzeriaAgent.initGUI(); + pizzeriaAgent.initGUI(args[1]); } Util.useJMS = true; break; @@ -90,15 +90,21 @@ public class PizzeriaAgent { xvsm.listenForGroupUpdates(); } - private void initGUI() { - PizzeriaGUI gui = new PizzeriaGUI(); + private void initGUI(String pizzeriaIdentifier) { + PizzeriaGUI gui = new PizzeriaGUI(pizzeriaIdentifier ); SwingUtilities.invokeLater(gui); } class PizzeriaGUI implements Runnable { - @Override + private final String id; + + public PizzeriaGUI(String pizzeriaIdentifier) { + this.id = pizzeriaIdentifier; + } + + @Override public void run() { - PizzeriaFrame frame = new PizzeriaFrame(); + PizzeriaFrame frame = new PizzeriaFrame(id); frame.setOnTablesCreatedHandler(new TablesCreatedHandler() { @Override diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/PizzeriaFrame.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/PizzeriaFrame.java index 49cb952..debb3be 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/PizzeriaFrame.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/PizzeriaFrame.java @@ -43,6 +43,10 @@ public class PizzeriaFrame extends JFrame { super("Pizzeria"); } + public PizzeriaFrame(String id) { + super("Pizzeria: " + id); + } + public void start() { diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/DeliveryOrdersModel.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/DeliveryOrdersModel.java index 6273902..459d9fd 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/DeliveryOrdersModel.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/DeliveryOrdersModel.java @@ -17,11 +17,12 @@ public class DeliveryOrdersModel extends AbstractOrdersModel private static final String ORDER_ID = "Order ID"; private static final String DELIVERY_ADDRESS = "Address"; private static final String STATUS = "Status"; - private static final String LOAD_BALANCER_ID = "Moved by"; - private static final String ORIGINAL_PIZZERIA = "Moved from"; + private static final String LOAD_BALANCER_ID = "Load Balancer"; + private static final String ORIGINAL_PIZZERIA = "From"; + private static final String TARGET_PIZZERIA = "To"; private static final String[] COLUMNS = new String[]{ORDER_ID, ID, DELIVERY_ADDRESS, STATUS, LOAD_BALANCER_ID, - ORIGINAL_PIZZERIA}; + ORIGINAL_PIZZERIA, TARGET_PIZZERIA}; @Override protected String[] getColumns() { @@ -48,6 +49,8 @@ public class DeliveryOrdersModel extends AbstractOrdersModel return group.getLoadBalancerId(); case ORIGINAL_PIZZERIA : return group.getOriginalPizzeriaId(); + case TARGET_PIZZERIA : + return (group.getOriginalPizzeriaId() != null) ? group.getPizzeriaId() : ""; default : throw new RuntimeException(UNHANDLEDCOLUMN); } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/DeliveryGroupData.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/DeliveryGroupData.java index fbf81df..9ff13cf 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/DeliveryGroupData.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/DeliveryGroupData.java @@ -1,12 +1,11 @@ package at.ac.tuwien.sbc.valesriegler.types; -import java.io.Serializable; - +import at.ac.tuwien.sbc.valesriegler.common.Util; import org.mozartspaces.capi3.Queryable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.ac.tuwien.sbc.valesriegler.common.Util; +import java.io.Serializable; @Queryable(autoindex = true) public class DeliveryGroupData implements Serializable, HasOrder { @@ -32,7 +31,6 @@ public class DeliveryGroupData implements Serializable, HasOrder { } public DeliveryGroupData() { - // To change body of created methods use File | Settings | File Templates. } public void setId(Integer id) { @@ -64,8 +62,8 @@ public class DeliveryGroupData implements Serializable, HasOrder { this.driverId = driverId; } - public Integer getWaiterIdOfOrder() { - return waiterIdOfOrder; + public int getWaiterIdOfOrder() { + return Util.getIntSafe(waiterIdOfOrder); } public void setWaiterIdOfOrder(Integer waiterIdOfOrder) { diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/DeliveryStatus.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/DeliveryStatus.java index b0d3495..b02cc86 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/DeliveryStatus.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/DeliveryStatus.java @@ -3,5 +3,5 @@ package at.ac.tuwien.sbc.valesriegler.types; import java.io.Serializable; public enum DeliveryStatus implements Serializable { - ORDERED, IN_PROGRESS, IS_DELIVERED, DELIVERED, PAID, DELIVERY_FAILED, START, ORDER_PENDING; + ORDERED, MOVED, IN_PROGRESS, IS_DELIVERED, DELIVERED, PAID, DELIVERY_FAILED, START, ORDER_PENDING; } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/AbstractXVSMConnector.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/AbstractXVSMConnector.java index 97ccc18..fb1d4b7 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/AbstractXVSMConnector.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/AbstractXVSMConnector.java @@ -4,10 +4,7 @@ import at.ac.tuwien.sbc.valesriegler.common.HasId; import at.ac.tuwien.sbc.valesriegler.common.Util; import at.ac.tuwien.sbc.valesriegler.types.GroupData; import at.ac.tuwien.sbc.valesriegler.xvsm.spacehelpers.SpaceListenerImplBuilder; -import org.mozartspaces.capi3.Coordinator; -import org.mozartspaces.capi3.CountNotMetException; -import org.mozartspaces.capi3.FifoCoordinator; -import org.mozartspaces.capi3.LindaCoordinator; +import org.mozartspaces.capi3.*; import org.mozartspaces.capi3.LindaCoordinator.LindaSelector; import org.mozartspaces.core.*; import org.mozartspaces.notifications.NotificationManager; @@ -82,7 +79,7 @@ public abstract class AbstractXVSMConnector { protected ContainerReference useContainerOfSpaceWithPort(String containerName, int spacePort) { try { final String address = String.format(Util.SERVER_ADDR, spacePort); - return CapiUtil.lookupOrCreateContainer(containerName, URI.create(address), createCoordinators(new FifoCoordinator(), new LindaCoordinator(false)), null, capi); + return CapiUtil.lookupOrCreateContainer(containerName, URI.create(address), createCoordinators(new FifoCoordinator(), new LindaCoordinator(false), new AnyCoordinator()), null, capi); } catch (MzsCoreException e) { Util.handleSpaceErrorAndTerminate(e); } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/LoadBalancerXVSM.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/LoadBalancerXVSM.java index ff66065..b09cb07 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/LoadBalancerXVSM.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/LoadBalancerXVSM.java @@ -2,28 +2,40 @@ package at.ac.tuwien.sbc.valesriegler.xvsm; import at.ac.tuwien.sbc.valesriegler.common.Util; +import at.ac.tuwien.sbc.valesriegler.types.DeliveryGroupData; +import at.ac.tuwien.sbc.valesriegler.types.DeliveryStatus; +import at.ac.tuwien.sbc.valesriegler.xvsm.loadbalancer.PizzeriaState; +import at.ac.tuwien.sbc.valesriegler.xvsm.loadbalancer.PizzeriaStatus; import at.ac.tuwien.sbc.valesriegler.xvsm.spacehelpers.SpaceAction; +import org.mozartspaces.capi3.AnyCoordinator; +import org.mozartspaces.core.ContainerReference; +import org.mozartspaces.core.MzsConstants; +import org.mozartspaces.core.TransactionReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.Serializable; -import java.util.List; -import java.util.Set; +import java.net.URI; +import java.util.*; public class LoadBalancerXVSM extends AbstractXVSMConnector { private static final Logger log = LoggerFactory.getLogger(LoadBalancerXVSM.class); + private static final int FREQUENCY = 1500; private int loadBalancerId; private Set pizzeriaIdentifiers; + private Map pizzeriaStates = Collections.synchronizedMap(new HashMap()); public LoadBalancerXVSM(int id, int port) { super(port); this.loadBalancerId = id; - this.groupAgentInfoContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_INFO, Util.GROUP_AGENT_PORT); } + /** + * The Load balancer listens for new pizzerias on the Group Agent Info container + */ public void listenForPizzerias() { getDefaultBuilder("listenForPizzerias").setLookaround(true).setCref(groupAgentInfoContainer).setSpaceAction(new SpaceAction() { @Override @@ -32,8 +44,9 @@ public class LoadBalancerXVSM extends AbstractXVSMConnector { final List pizzeriaRegistrations = castEntries(entries); for (PizzeriaRegistration registration : pizzeriaRegistrations) { final int pizzeriaId = registration.pizzeriaSpacePort; - if (! pizzeriaIdentifiers.contains(pizzeriaId)) { - pizzeriaIdentifiers.add(pizzeriaId); + if (pizzeriaStates.get(pizzeriaId) == null) { + final PizzeriaState pizzeriaState = new PizzeriaState(pizzeriaId); + pizzeriaStates.put(pizzeriaId, pizzeriaState); listenToPizzeria(pizzeriaId); } } @@ -42,13 +55,178 @@ public class LoadBalancerXVSM extends AbstractXVSMConnector { }).createSpaceListenerImpl(); } + /** + * Whenever a new pizzeria emerges a timer is started which periodically checks the delivery load + * of the pizzeria and contemplates moving deliveries. + */ private void listenToPizzeria(int pizzeriaId) { - getDefaultBuilder("listenForPizzeriaDeliveries").setLookaround(true).setCref(useContainerOfSpaceWithPort(Util.DELIVERY_ORDER_TAKEN, pizzeriaId)).setSpaceAction(new SpaceAction() { - @Override - public void onEntriesWritten(List entries) throws Exception { - // TODO: do something when pizzeria gets new deliveries - } - }).createSpaceListenerImpl(); + log.warn("Start listening to pizzeria {}", pizzeriaId); + + Timer timer = new Timer(); + + timer.schedule(new LoadCheck(useContainerOfSpaceWithPort(Util.DELIVERY_ORDER_TAKEN, pizzeriaId), pizzeriaId), 100, FREQUENCY); + } + private class LoadCheck extends TimerTask { + public static final int DELIVERIES_NUMBER_THRESHOLD = 20; + public static final double DELIVERY_FACTOR_THRESHOLD = 0.2; + public static final int INTERVAL_FACTOR = 2; + + private final ContainerReference container; + private final int pizzeriaId; + + public LoadCheck(ContainerReference containerReference, int pizzeriaId) { + this.container = containerReference; + this.pizzeriaId = pizzeriaId; + } + + @Override + public void run() { + log.info("Start running Check for pizzeriaId {}", pizzeriaId); + synchronized (pizzeriaStates) { + try { + List deliveries = null; + final PizzeriaState pizzeriaState = pizzeriaStates.get(pizzeriaId); + try { + deliveries = castEntries(capi.read(container, AnyCoordinator.newSelector(MzsConstants.Selecting.COUNT_MAX), MzsConstants.RequestTimeout.DEFAULT, null)); + } catch (Exception e) { + log.warn("Exception while reading deliveries from Pizzeria {}", pizzeriaId); + e.printStackTrace(); + pizzeriaState.setStatus(PizzeriaStatus.OFFLINE); + return; + } + pizzeriaState.setStatus(PizzeriaStatus.ONLINE); + + final long lastUpdatedTimestamp = pizzeriaState.getLastUpdateTime(); + final long now = new Date().getTime(); + final long interval = now - lastUpdatedTimestamp; + final int currentNumberDeliveries = deliveries.size(); + + // there has to be a stored value for the pizzeria and it should be current enough + if (lastUpdatedTimestamp != 0 && interval < FREQUENCY * INTERVAL_FACTOR && currentNumberDeliveries > DELIVERIES_NUMBER_THRESHOLD) { + log.info("Pizzeria is handled..."); + final int id = getPizzeriaWithLessWaitingDeliveries(currentNumberDeliveries); + if (id != 0) { + final PizzeriaState otherPizzeria = pizzeriaStates.get(id); + final int numberDeliveriesOtherPizzeria = otherPizzeria.getNumberDeliveries(); + + log.info("This pizzeria has {} deliveries", currentNumberDeliveries); + log.info("Other pizzeria {} has {} deliveries", id, numberDeliveriesOtherPizzeria); + + final int deliveryDifference = currentNumberDeliveries - (numberDeliveriesOtherPizzeria + currentNumberDeliveries) / INTERVAL_FACTOR; + + moveDeliveries(deliveryDifference, deliveries, pizzeriaId, id); + + log.info(String.format("Move %d deliveries from pizzeria %d to pizzeria %d", deliveryDifference, pizzeriaId, id)); + } else { + log.info("No pizzeria with less deliveries found!"); + } + } + + pizzeriaState.setNumberDeliveries(currentNumberDeliveries); + pizzeriaState.setLastUpdateTime(now); + + + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void moveDeliveries(int deliveryDifference, List deliveries, int pizzeriaId, int otherPizzeriaId) { + int movedDelivieries = 0; + final ContainerReference sourceOrderTakenContainer = useContainerOfSpaceWithPort(Util.DELIVERY_ORDER_TAKEN, pizzeriaId); + final ContainerReference sourceDeliveryGroupContainer = useContainerOfSpaceWithPort(Util.PIZZERIA_DELIVERY, pizzeriaId); + final ContainerReference targetPhoneCallsContainer = useContainerOfSpaceWithPort(Util.PHONE_CALLS, otherPizzeriaId); + final ContainerReference targetDeliveryGroupContainer = useContainerOfSpaceWithPort(Util.PIZZERIA_DELIVERY, otherPizzeriaId); + + /** + * Take deliveryDifference times a delivery group from the source containers and put them into + * the containers of the target pizzeria space + */ + for (DeliveryGroupData delivery : deliveries) { + if (movedDelivieries >= deliveryDifference) return; + + try { + + final TransactionReference tx = capi.createTransaction( + Util.SPACE_TRANSACTION_TIMEOUT, + URI.create(String.format(Util.SERVER_ADDR, pizzeriaId))); + final String errorMsg = "Cannot move the delivery as I can't take it!"; + DeliveryGroupData group = null; + try { + // Take any delivery from the source OrderTakenContainer + DeliveryGroupData template = new DeliveryGroupData(); + template.setDeliveryStatus(null); + group = takeMatchingEntity(template, sourceOrderTakenContainer, tx, MzsConstants.RequestTimeout.DEFAULT, errorMsg); + } catch (Exception e) { + log.warn(e.getMessage()); + continue; + } + try { + // Take the delivery with the right id from the source DeliveryGroupContainer + final DeliveryGroupData template = new DeliveryGroupData(); + template.setDeliveryStatus(null); + template.setId(group.getId()); + List groups = takeMatchingEntities(template, sourceDeliveryGroupContainer, tx, MzsConstants.RequestTimeout.DEFAULT, "Cannot take from sourceDeliveryGroupContainer"); + group = groups.get(0); + } catch (Exception e) { + log.warn(e.getMessage()); + continue; + } + group.setOriginalPizzeriaId(String.valueOf(pizzeriaId)); + group.setPizzeriaId(String.valueOf(otherPizzeriaId)); + group.setWaiterIdOfOrder(null); + group.setLoadBalancerId(loadBalancerId); + group.setDeliveryStatus(DeliveryStatus.MOVED); + + // Inform the source pizzeria that the delivery was moved + sendItemsToContainer(Arrays.asList(group), sourceDeliveryGroupContainer, MzsConstants.RequestTimeout.DEFAULT, tx); + capi.commitTransaction(tx); + + final TransactionReference otherTx = capi.createTransaction( + Util.SPACE_TRANSACTION_TIMEOUT, + URI.create(String.format(Util.SERVER_ADDR, otherPizzeriaId))); + + group.setDeliveryStatus(DeliveryStatus.START); + + // Send the deliveries to the other pizzeria + sendItemsToContainer(Arrays.asList(group), targetPhoneCallsContainer, MzsConstants.RequestTimeout.DEFAULT, otherTx); + sendItemsToContainer(Arrays.asList(group), targetDeliveryGroupContainer, MzsConstants.RequestTimeout.DEFAULT, otherTx); + + movedDelivieries++; + + capi.commitTransaction(otherTx); + + + } catch (NullPointerException e) { + // strange npe from space + } catch (Exception e) { + log.warn("Exception in moveDeliveries: {}", e.getMessage()); + e.printStackTrace(); + } + + } + } + + /** + * Returns the port of a pizzeria for which it is true: (numberOfDeliveries+currentNumberDeliveries* DELIVERY_FACTOR_THRESHOLD) states = pizzeriaStates.values(); + final long now = new Date().getTime(); + for (PizzeriaState state : states) { + final long lastUpdateTime = state.getLastUpdateTime(); + final long interval = now - lastUpdateTime; + final boolean differenceDeliveries = (state.getNumberDeliveries() + currentNumberDeliveries * DELIVERY_FACTOR_THRESHOLD) < currentNumberDeliveries; + if (differenceDeliveries && state.getStatus() != PizzeriaStatus.OFFLINE && lastUpdateTime != 0 && interval < FREQUENCY * INTERVAL_FACTOR) { + return state.getId(); + } + } + + return 0; + } + } } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/loadbalancer/PizzeriaState.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/loadbalancer/PizzeriaState.java new file mode 100644 index 0000000..46b41a2 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/loadbalancer/PizzeriaState.java @@ -0,0 +1,42 @@ +package at.ac.tuwien.sbc.valesriegler.xvsm.loadbalancer; + + +public class PizzeriaState { + + private final int id; + private long lastUpdateTime = 0; + private int numberDeliveries = 0; + private PizzeriaStatus status = PizzeriaStatus.ONLINE; + + public PizzeriaState(int id) { + this.id = id; + } + + public PizzeriaStatus getStatus() { + return status; + } + + public int getId() { + return id; + } + + public long getLastUpdateTime() { + return lastUpdateTime; + } + + public void setLastUpdateTime(long lastUpdateTime) { + this.lastUpdateTime = lastUpdateTime; + } + + public int getNumberDeliveries() { + return numberDeliveries; + } + + public void setNumberDeliveries(int numberDeliveries) { + this.numberDeliveries = numberDeliveries; + } + + public void setStatus(PizzeriaStatus status) { + this.status = status; + } +} diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/loadbalancer/PizzeriaStatus.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/loadbalancer/PizzeriaStatus.java new file mode 100644 index 0000000..2af4501 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/loadbalancer/PizzeriaStatus.java @@ -0,0 +1,5 @@ +package at.ac.tuwien.sbc.valesriegler.xvsm.loadbalancer; + +public enum PizzeriaStatus { + ONLINE, OFFLINE; +} diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 184b6a9..01e782f 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -12,7 +12,7 @@ - + -- 2.43.0