[XVSM] LoadBalancer implemented
authorGregor Riegler <gregor.riegler@gmail.com>
Fri, 14 Jun 2013 17:26:42 +0000 (19:26 +0200)
committerGregor Riegler <gregor.riegler@gmail.com>
Fri, 14 Jun 2013 17:26:42 +0000 (19:26 +0200)
17 files changed:
erkenntnisse
runXVSM-loadbalancer.sh [new file with mode: 0755]
runXVSM-spaces.sh
runXVSM.sh
src/main/java/at/ac/tuwien/sbc/valesriegler/common/Util.java
src/main/java/at/ac/tuwien/sbc/valesriegler/group/GroupAgent.java
src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/DeliveryOverviewModel.java
src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/PizzeriaAgent.java
src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/PizzeriaFrame.java
src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/DeliveryOrdersModel.java
src/main/java/at/ac/tuwien/sbc/valesriegler/types/DeliveryGroupData.java
src/main/java/at/ac/tuwien/sbc/valesriegler/types/DeliveryStatus.java
src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/AbstractXVSMConnector.java
src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/LoadBalancerXVSM.java
src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/loadbalancer/PizzeriaState.java [new file with mode: 0644]
src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/loadbalancer/PizzeriaStatus.java [new file with mode: 0644]
src/main/resources/logback.xml

index a3fa1f5c000468b0ca123ef52c35e638dd588525..692c1b4fda451ed877cbd5a2b89f2f8a68c43279 100644 (file)
@@ -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 (executable)
index 0000000..e6625ab
--- /dev/null
@@ -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
index b39fc99d517c81e5852b443621f901949e599de8..1ac317ed1282af072d48a3b322e8f07505105b79 100755 (executable)
@@ -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 &
index 2916ed5ddcb85f7c8b3a7a226c5b70e0764c9966..7e7c200580d200cb574463aa2b0ebf301451b45f 100755 (executable)
@@ -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" &
index 1ba05766612cd6f664f47b9f9598c51b9f703661..2cafdec4339c1566eb35135a40a1294b618a3bcf 100644 (file)
@@ -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);
 
index 67f17781a9cee44934c63d87dbdfadeff0ee6d2d..54ea502a7d683ceec75e5e3010bc6eb7326b17fd 100644 (file)
@@ -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) {
index 6790c7db33e853c0a325e40789870d6b61ecc2f6..905f982eb9ebec5b96e08a772f68d6438286ab96 100644 (file)
@@ -64,6 +64,9 @@ public class DeliveryOverviewModel extends TableModel<DeliveryGroup> {
        public void addDeliveries(List<DeliveryGroupData> 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());
index abf69170cb6dcd2ac50a7141403af468b6a953af..7edb682c3dda9b115f8ab8122d6a95d07f89c61f 100644 (file)
@@ -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
index 49cb9522b6deac0093b457eaaa7fa5dea8f4c73e..debb3be0b81d9d13b879dc0dd58421ddfd376124 100644 (file)
@@ -43,6 +43,10 @@ public class PizzeriaFrame extends JFrame {
         super("Pizzeria");
     }
 
+    public PizzeriaFrame(String id) {
+        super("Pizzeria: " + id);
+    }
+
     public void start() {
 
 
index 62739021bee4e1fcb246a6b7870a6a6e3f3816df..459d9fd5864b262a8ebb547c8c945d0834641bfc 100644 (file)
@@ -17,11 +17,12 @@ public class DeliveryOrdersModel extends AbstractOrdersModel<DeliveryGroupData>
        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<DeliveryGroupData>
                                return group.getLoadBalancerId();
                        case ORIGINAL_PIZZERIA :
                                return group.getOriginalPizzeriaId();
+            case TARGET_PIZZERIA :
+                return (group.getOriginalPizzeriaId() != null) ? group.getPizzeriaId() : "";
                        default :
                                throw new RuntimeException(UNHANDLEDCOLUMN);
                }
index fbf81df42e5f6277713c8cb1a1c7d24a842a9754..9ff13cf97b536ce49f555b5c5ebcf33f6ccd3875 100644 (file)
@@ -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) {
index b0d34958e28c1585bf2c9853f3b5a223a44940f0..b02cc865a8fdb098ed4666510da16d6e972e3e4a 100644 (file)
@@ -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;
 }
index 97ccc18e8bde2784068959998f07dce10f2245f4..fb1d4b7c2b1cde7a232d16bc1f1ced09a536679f 100644 (file)
@@ -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);
         }
index ff6606563e5ba24967046ad3dfad14ad5eb114f0..b09cb07c2bf9572e74a9d8a96a1c38f1af62f91c 100644 (file)
@@ -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<Integer> pizzeriaIdentifiers;
+    private Map<Integer, PizzeriaState> pizzeriaStates = Collections.synchronizedMap(new HashMap<Integer, PizzeriaState>());
 
     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<PizzeriaRegistration> 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<? extends Serializable> 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<DeliveryGroupData> 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<DeliveryGroupData> 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<DeliveryGroupData> 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)<currentNumberDeliveries.
+         * If there is no such pizzeria available the method return 0.
+         */
+        private int getPizzeriaWithLessWaitingDeliveries(int currentNumberDeliveries) {
+            final Collection<PizzeriaState> 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 (file)
index 0000000..46b41a2
--- /dev/null
@@ -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 (file)
index 0000000..2af4501
--- /dev/null
@@ -0,0 +1,5 @@
+package at.ac.tuwien.sbc.valesriegler.xvsm.loadbalancer;
+
+public enum PizzeriaStatus {
+    ONLINE, OFFLINE;
+}
index 184b6a9769c8af867539d49cc57728db4098a0ef..01e782ffa3f64003cd5f17f253c39888625792e3 100644 (file)
@@ -12,7 +12,7 @@
        </appender>\r
 \r
        <logger name="at.ac.tuwien">\r
-               <level value="warn" />\r
+               <level value="info" />\r
        </logger>\r
 \r
        <root>\r