From 6330dc9906f3dec6909eed53e3be75a931c59987 Mon Sep 17 00:00:00 2001 From: Gregor Riegler Date: Fri, 10 May 2013 22:25:43 +0200 Subject: [PATCH] Make cook and waiter look around for work to do if they are idle --- .../tuwien/sbc/valesriegler/common/Util.java | 6 +- .../sbc/valesriegler/group/GroupAgent.java | 2 +- .../valesriegler/pizzeria/PizzeriaAgent.java | 3 +- .../xvsm/AbstractXVSMConnector.java | 61 ++- .../sbc/valesriegler/xvsm/CookXVSM.java | 82 ++-- .../sbc/valesriegler/xvsm/GroupAgentXVSM.java | 101 ++--- .../valesriegler/xvsm/PizzeriaAgentXVSM.java | 4 + .../sbc/valesriegler/xvsm/SpaceListener.java | 86 ++++ .../valesriegler/xvsm/SpaceListenerImpl.java | 40 ++ .../sbc/valesriegler/xvsm/WaiterXVSM.java | 417 +++++++----------- 10 files changed, 397 insertions(+), 405 deletions(-) create mode 100644 src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/SpaceListener.java create mode 100644 src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/SpaceListenerImpl.java 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 e16ddc4..9c03192 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 @@ -1,5 +1,6 @@ package at.ac.tuwien.sbc.valesriegler.common; +import java.io.Serializable; import java.net.URI; import java.util.Collections; import java.util.HashMap; @@ -15,8 +16,6 @@ import org.mozartspaces.core.MzsCoreException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.ac.tuwien.sbc.valesriegler.xvsm.AbstractXVSMConnector; - public abstract class Util { private static final Logger log = LoggerFactory.getLogger(Util.class); @@ -37,6 +36,8 @@ public abstract class Util { public static final String IS_EATING = "isEating"; public static final String PAYMENT_DONE = "hasPaid"; + public static final long SPACE_TRANSACTION_TIMEOUT = 1500; + public static final String SERVER_ADDR = "xvsm://localhost:9876"; public static ContainerReference getOrCreateNamedContainer(final String spaceUri, final String containerName, final Capi capi, final List coordinators) @@ -71,4 +72,5 @@ public abstract class Util { return myMap; } + } 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 beed127..48896ee 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 @@ -5,6 +5,7 @@ import java.util.List; import javax.swing.SwingUtilities; +import org.mozartspaces.core.MzsConstants.RequestTimeout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,7 +51,6 @@ public class GroupAgent { xvsm.listenForTableAssigned(); xvsm.listenForOrdersTaken(); -// xvsm.listenForGroupDataChanges(); xvsm.listenForDeliveredOrders(); xvsm.listenForPaymentRequest(); xvsm.listenForPaymentDone(); 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 496e31f..6b1f146 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 @@ -7,6 +7,7 @@ import java.util.List; import javax.swing.SwingUtilities; import org.mozartspaces.core.Entry; +import org.mozartspaces.core.MzsConstants.RequestTimeout; import org.mozartspaces.notifications.Notification; import org.mozartspaces.notifications.NotificationListener; import org.mozartspaces.notifications.Operation; @@ -104,7 +105,7 @@ public class PizzeriaAgent { @Override public void freeTablesCreated(List tables) { if(!Util.useJMS) { - xvsm.sendFreeTablesToSpace(tables); + xvsm.sendFreeTablesToContainer(tables); } } }); 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 c385445..a3a6f01 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,6 +4,7 @@ import java.io.Serializable; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.List; import org.mozartspaces.capi3.AnyCoordinator; @@ -17,20 +18,23 @@ import org.mozartspaces.core.ContainerReference; import org.mozartspaces.core.DefaultMzsCore; import org.mozartspaces.core.Entry; import org.mozartspaces.core.MzsConstants; -import org.mozartspaces.core.MzsTimeoutException; -import org.mozartspaces.core.MzsConstants.RequestTimeout; import org.mozartspaces.core.MzsCore; import org.mozartspaces.core.MzsCoreException; +import org.mozartspaces.core.MzsTimeoutException; import org.mozartspaces.core.TransactionReference; import org.mozartspaces.notifications.NotificationManager; +import org.mozartspaces.notifications.Operation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +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.types.Table; public abstract class AbstractXVSMConnector { + public static Object lockObject = new Object(); + public static long timeOflastOperation = new Date().getTime(); + private static final Logger log = LoggerFactory.getLogger(AbstractXVSMConnector.class); protected ContainerReference tableAssignedContainer; @@ -82,6 +86,16 @@ public abstract class AbstractXVSMConnector { e.printStackTrace(); System.exit(1); } + + protected void createNotification(SpaceListener listener, + ContainerReference cref) { + listener.startHandlingAbsenceOfNotifications(); + try { + notificationMgr.createNotification(cref, listener, Operation.WRITE); + } catch (Exception e) { + handleSpaceErrorAndTerminate(e); + } + } protected void sendItemsToContainer( List items, ContainerReference cref, long timeout, TransactionReference tx) { @@ -141,23 +155,34 @@ public abstract class AbstractXVSMConnector { protected List castEntries(List entries) { List newList = new ArrayList(); - List newEntries = (List) entries; - for (Entry entry : newEntries) { - newList.add((T) entry.getValue()); + if(entries.size() == 0) return newList; + + Serializable firstEntry = entries.get(0); + if (firstEntry instanceof Entry) { + + List newEntries = (List) entries; + for (Entry entry : newEntries) { + newList.add((T) entry.getValue()); + } + return newList; + } else { + return (List) entries; } - return newList; } - -// public void sendTablesToSpace(List
tables) { -// sendItemsToContainer(tables, tableOccupiedContainer, RequestTimeout.DEFAULT, null); -// } - - public void sendFreeTablesToSpace(List
tables) { - sendItemsToContainer(tables, freeTablesContainer, RequestTimeout.DEFAULT, null); + + + protected T getSingleEntity(final List entities) { + if(entities.size() != 1) { + throw new RuntimeException("Only one entity was expected!"); + } + return entities.get(0); } - - public void sendNewGroupsToSpace(List newGroups) { -// sendItemsToContainer(newGroups, groupsContainer, RequestTimeout.DEFAULT, null); - sendItemsToContainer(newGroups, assignTableContainer, RequestTimeout.DEFAULT, null); + + protected GroupData getSingleGroup(final List entities) { + List groups = castEntries(entities); + if(groups.size() != 1) { + throw new RuntimeException("Only one group was expected!"); + } + return groups.get(0); } } \ No newline at end of file diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java index 76d665f..871cde4 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java @@ -38,63 +38,43 @@ public class CookXVSM extends AbstractXVSMConnector { } public void listenForPizzas() { - NotificationListener pizzasListener = new NotificationListener() { - @Override - public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { - - log.info("New Pizzas to prepare!"); - + SpaceListener pizzasListener = new SpaceListenerImpl(capi, preparePizzasContainer) { + + @Override + void onEntriesWritten(List entries) + throws Exception { + List pizzas = castEntries(entries); Collections.rotate(pizzas, cookId); + for (PizzaOrder pizzaOrder : pizzas) { - try { - try { - TransactionReference tx = capi.createTransaction(9000, URI.create(Util.SERVER_ADDR)); - String pizzaAlreadyCooked = String.format("Pizza with id %d has already been cooked by another cook", pizzaOrder.getId()); - - // Require the lock for preparing the pizza - PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), preparePizzasContainer, tx, 1000, pizzaAlreadyCooked); - - // tell the space that you prepare the pizza -> without a transaction!! - Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId); - pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION); - - log.info("I say that I now prepare this pizza:"); - log.info(pizzaInProgress.toString()); - sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, null); - - PizzaOrder pizza = createPizza(order); - - sendItemsToContainer(Arrays.asList(pizza), deliverPizzasContainer, RequestTimeout.DEFAULT, tx); - - capi.commitTransaction(tx); - log.info("I have completed preparing a pizza for order {}!", pizza.getOrderId()); - } catch (IllegalArgumentException e) { - log.info("IllegalArgumentException"); - e.printStackTrace(); - } catch (EntityNotFoundByTemplate e) { - log.info(e.getMessage()); - } catch (NullPointerException e) { - // for some reason mozartspaces throws a npe but it doesn't seem to mean anything - } catch (Exception e) { - log.error("AN INNER EXCEPTION"); - e.printStackTrace(); - } - } catch (TransactionException e) { - log.info("An unimportant TransactionException has occurred"); - } catch (Exception e) { - log.error("OUTER EXCEPTION"); - } + + TransactionReference tx = capi.createTransaction(9000, URI.create(Util.SERVER_ADDR)); + String pizzaAlreadyCooked = String.format("Pizza with id %d has already been cooked by another cook", pizzaOrder.getId()); + + // Require the lock for preparing the pizza + PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), preparePizzasContainer, tx, 1000, pizzaAlreadyCooked); + + // tell the space that you prepare the pizza -> without a transaction!! + Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId); + pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION); + + log.info("I say that I now prepare this pizza:"); + log.info(pizzaInProgress.toString()); + sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, null); + + PizzaOrder pizza = createPizza(order); + + sendItemsToContainer(Arrays.asList(pizza), deliverPizzasContainer, RequestTimeout.DEFAULT, tx); + + capi.commitTransaction(tx); + log.info("I have completed preparing a pizza for order {}!", pizza.getOrderId()); + } - } }; - try { - notificationMgr.createNotification(preparePizzasContainer, pizzasListener, Operation.WRITE); - log.info("Created pizzasContainer notification for a cook"); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } + createNotification(pizzasListener, preparePizzasContainer); + } private PizzaOrder createPizza(PizzaOrder order) throws InterruptedException { diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupAgentXVSM.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupAgentXVSM.java index aa0a435..7bc06c6 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupAgentXVSM.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupAgentXVSM.java @@ -5,12 +5,14 @@ import java.util.List; import javax.swing.SwingUtilities; +import org.mozartspaces.core.MzsConstants.RequestTimeout; import org.mozartspaces.notifications.Notification; import org.mozartspaces.notifications.NotificationListener; import org.mozartspaces.notifications.Operation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.ac.tuwien.sbc.valesriegler.common.HasId; import at.ac.tuwien.sbc.valesriegler.common.Util; import at.ac.tuwien.sbc.valesriegler.group.GroupAgent; import at.ac.tuwien.sbc.valesriegler.types.GroupData; @@ -30,16 +32,12 @@ public class GroupAgentXVSM extends AbstractXVSMConnector { } public void listenForDeliveredOrders() { - NotificationListener deliveredOrders = new NotificationListener() { - @Override - public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { - final List groups = castEntries(entries); - - log.info("{} order was delivered!", groups.size()); - if(groups.size() != 1) { - throw new RuntimeException("A waiter should only deliver one order at once!"); - } - final int groupId = groups.get(0).getOrder().getId(); + SpaceListener deliveredOrders = new SpaceListenerImpl(capi, orderCompleteContainer, false) { + + @Override + void onEntriesWritten(List entries) throws Exception { + GroupData groupData = getSingleGroup(entries); + final int groupId = groupData.getOrder().getId(); SwingUtilities.invokeLater(new Runnable() { @Override @@ -49,25 +47,15 @@ public class GroupAgentXVSM extends AbstractXVSMConnector { }); } }; - try { - notificationMgr.createNotification(orderCompleteContainer, deliveredOrders, Operation.WRITE); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } + createNotification(deliveredOrders, orderCompleteContainer); + } public void listenForPaymentRequest() { - NotificationListener paymentRequest = new NotificationListener() { + SpaceListener paymentRequest = new SpaceListenerImpl(capi, paymentRequestContainer, false) { @Override - public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { - log.info("PAY REQUEST by"); - final List groups = castEntries(entries); - - if(groups.size() != 1) { - throw new RuntimeException("A group only says as a whole that it wants to pay"); - } - final GroupData group = groups.get(0); - log.info("PAY REQUEST by {}", group.getId()); + void onEntriesWritten(List entries) throws Exception { + final GroupData group = getSingleGroup(entries); SwingUtilities.invokeLater(new Runnable() { @Override @@ -77,26 +65,18 @@ public class GroupAgentXVSM extends AbstractXVSMConnector { }); } + + }; - try { - notificationMgr.createNotification(paymentRequestContainer, paymentRequest, Operation.WRITE); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } + createNotification(paymentRequest, paymentRequestContainer); } public void listenForPaymentDone() { - NotificationListener payment = new NotificationListener() { + SpaceListener payment = new SpaceListenerImpl(capi, paymentDoneContainer, false) { @Override - public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { + void onEntriesWritten(List entries) throws Exception { - final List groups = castEntries(entries); - - if(groups.size() != 1) { - throw new RuntimeException("A group can only have paid as a whole!"); - } - final GroupData group = groups.get(0); - + final GroupData group = getSingleGroup(entries); SwingUtilities.invokeLater(new Runnable() { @Override @@ -107,19 +87,14 @@ public class GroupAgentXVSM extends AbstractXVSMConnector { } }; - try { - notificationMgr.createNotification(paymentDoneContainer, payment, Operation.WRITE); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } + createNotification(payment, paymentDoneContainer); } public void listenForTableAssigned() { - NotificationListener tableAssignmentListener = new NotificationListener() { + SpaceListener tableAssignmentListener = new SpaceListenerImpl(capi, tableAssignedContainer, false) { @Override - public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { - log.info("A table was assigned to a group, heureka!"); + void onEntriesWritten(List entries) throws Exception { final List
tables = castEntries(entries); @@ -131,26 +106,15 @@ public class GroupAgentXVSM extends AbstractXVSMConnector { }); } }; - try { - notificationMgr.createNotification(tableAssignedContainer, tableAssignmentListener, Operation.WRITE); - log.info("Created tableOccupiedContainer notification for the group agent"); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } + createNotification(tableAssignmentListener, tableAssignedContainer); + } public void listenForOrdersTaken() { - NotificationListener orderTakenListener = new NotificationListener() { + SpaceListener tableAssignmentListener = new SpaceListenerImpl(capi, orderTakenContainer, false) { @Override - public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { - - - final List groups = castEntries(entries); - - if(groups.size() != 1) { - throw new RuntimeException("A group always orders as a whole!"); - } - final GroupData group = groups.get(0); + void onEntriesWritten(List entries) throws Exception { + final GroupData group = getSingleGroup(entries); SwingUtilities.invokeLater(new Runnable() { @@ -161,12 +125,11 @@ public class GroupAgentXVSM extends AbstractXVSMConnector { }); } }; - try { - notificationMgr.createNotification(orderTakenContainer, orderTakenListener, Operation.WRITE); - log.info("Created orderTakenContainer notification for the group agent"); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } + createNotification(tableAssignmentListener, orderTakenContainer); + } + + public void sendNewGroupsToSpace(List groupData) { + sendItemsToContainer(groupData, assignTableContainer, RequestTimeout.DEFAULT, null); } } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/PizzeriaAgentXVSM.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/PizzeriaAgentXVSM.java index 8945536..b4a6885 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/PizzeriaAgentXVSM.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/PizzeriaAgentXVSM.java @@ -261,6 +261,10 @@ public void listenForTakenOrders() { } } + public void sendFreeTablesToContainer(List
tables) { + sendItemsToContainer(tables, freeTablesContainer, RequestTimeout.DEFAULT, null); + } + diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/SpaceListener.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/SpaceListener.java new file mode 100644 index 0000000..e8f344d --- /dev/null +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/SpaceListener.java @@ -0,0 +1,86 @@ +package at.ac.tuwien.sbc.valesriegler.xvsm; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +import org.mozartspaces.notifications.Notification; +import org.mozartspaces.notifications.NotificationListener; +import org.mozartspaces.notifications.Operation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * The SpaceListener provides the {@link NotificationListener} interface. + *

+ * In {@link SpaceListener#getEntries()} a method for reading the entities, that are normally expected from the notification, + * must be supplied. Thus, it's possible in {@link SpaceListener#startHandlingAbsenceOfNotifications()} to start a timer and to + * execute the actions, which are normally triggered by the notification, with space objects read from {@link SpaceListener#getEntries()}. + * If {@link SpaceListener#lookAround} is true the timer periodically checks if the corresponding {@link AbstractXVSMConnector#timeOflastOperation} is old enough (= the agent is idle for some time) + * and possibly executes the action as a result. + * + * @author Gregor Riegler + * + */ +public abstract class SpaceListener implements NotificationListener { + private static final Logger log = LoggerFactory + .getLogger(SpaceListener.class); + + protected boolean lookAround = true; + + @Override + public void entryOperationFinished(Notification arg0, Operation arg1, + List entries) { + synchronized (AbstractXVSMConnector.lockObject) { + try { + onEntriesWritten(entries); + } catch (Exception e) { +// e.printStackTrace(); + } + AbstractXVSMConnector.timeOflastOperation = new Date().getTime(); + } + } + + abstract List getEntries() throws Exception; + + abstract void onEntriesWritten(List entries) + throws Exception; + + public void startHandlingAbsenceOfNotifications() { + if(!lookAround) return; + + Timer timer = new Timer(); + + timer.schedule(new SpaceTask(), 500, 3000); + } + + class SpaceTask extends TimerTask { + + @Override + public void run() { + long time = new Date().getTime(); + if(time-3000 <= AbstractXVSMConnector.timeOflastOperation) return; + synchronized(AbstractXVSMConnector.lockObject) { + try { + + List entries = getEntries(); + if(entries.size() != 0) { + onEntriesWritten(entries); + } + } catch (Exception e) { + log.info(e.getMessage()); +// e.printStackTrace(); + } + AbstractXVSMConnector.timeOflastOperation = new Date().getTime(); + } + + } + } + +} + + + diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/SpaceListenerImpl.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/SpaceListenerImpl.java new file mode 100644 index 0000000..8b3bd61 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/SpaceListenerImpl.java @@ -0,0 +1,40 @@ +package at.ac.tuwien.sbc.valesriegler.xvsm; + +import java.io.Serializable; +import java.util.List; + +import org.mozartspaces.capi3.AnyCoordinator; +import org.mozartspaces.core.Capi; +import org.mozartspaces.core.ContainerReference; +import org.mozartspaces.core.MzsConstants; +import org.mozartspaces.core.MzsConstants.RequestTimeout; + +/** + * + * @author Gregor Riegler + * + * @see SpaceListener + */ +public abstract class SpaceListenerImpl extends SpaceListener { + + private final Capi capi; + private final ContainerReference cref; + + + public SpaceListenerImpl(Capi core, ContainerReference cref) { + this.capi = core; + this.cref= cref; + } + + public SpaceListenerImpl(Capi core, ContainerReference cref, boolean lookAround) { + this(core, cref); + this.lookAround = lookAround; + } + + @Override + List getEntries() throws Exception { + return capi.read(cref, AnyCoordinator + .newSelector(MzsConstants.Selecting.COUNT_MAX), + RequestTimeout.DEFAULT, null); + } +} diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java index c387ab8..8a91408 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java @@ -2,16 +2,13 @@ package at.ac.tuwien.sbc.valesriegler.xvsm; import java.io.Serializable; import java.net.URI; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; -import javax.swing.text.html.parser.Entity; - import org.mozartspaces.capi3.AnyCoordinator; -import org.mozartspaces.capi3.LindaCoordinator; +import org.mozartspaces.core.ContainerReference; import org.mozartspaces.core.MzsConstants; import org.mozartspaces.core.MzsConstants.RequestTimeout; import org.mozartspaces.core.MzsCoreException; @@ -41,245 +38,155 @@ public class WaiterXVSM extends AbstractXVSMConnector { this.waiterId = waiterId; freeTablesContainer = useContainer(Util.FREE_TABLES); - assignTableContainer = useContainer(Util.ASSIGN_TABLE) ; - takeOrderContainer = useContainer(Util.TAKE_ORDER) ; - orderTakenContainer = useContainer(Util.ORDER_TAKEN) ; - preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS) ; - orderCompleteContainer = useContainer(Util.ORDER_COMPLETE) ; + assignTableContainer = useContainer(Util.ASSIGN_TABLE); + takeOrderContainer = useContainer(Util.TAKE_ORDER); + orderTakenContainer = useContainer(Util.ORDER_TAKEN); + preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS); + orderCompleteContainer = useContainer(Util.ORDER_COMPLETE); deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS); - paymentRequestContainer = useContainer(Util.PAYMENT_REQUEST) ; + paymentRequestContainer = useContainer(Util.PAYMENT_REQUEST); paymentDoneContainer = useContainer(Util.PAYMENT_DONE); tableAssignedContainer = useContainer(Util.TABLE_ASSIGNED); } public void listenForFreeTable() { + SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer) { - NotificationListener freeTableListener = new NotificationListener() { @Override - public void entryOperationFinished(final Notification notification, - final Operation operation, - final List entries) { + void onEntriesWritten(List entries) throws Exception { - log.info("{} tables have become free", entries.size()); +// log.info("{} tables have become free", entries.size()); List

tables = castEntries(entries); Collections.rotate(tables, waiterId); for (Table table : tables) { - try { - TransactionReference tx = capi.createTransaction(3000, - URI.create(Util.SERVER_ADDR)); - - try { - // Acquire a lock for the free table in the - // FreeTableContainer - int id = table.getId(); - log.info("Try to find the table with id {}", id); - - Table tableTemplate = new Table(id); - Table lockedFreeTable = takeMatchingEntity( - tableTemplate, - freeTablesContainer, - tx, - 1000, - String.format( - "There was no free table found with id %d", - id)); - - log.info("Table with id {} was found", id); - - GroupData groupTemplate = new GroupData(); - GroupData lockedGroup = takeMatchingEntity( - groupTemplate, assignTableContainer, tx, - RequestTimeout.DEFAULT, - "There is no group waiting for a table at the moment"); - - assignGroupToTable(lockedGroup, lockedFreeTable, tx); - - } catch (IllegalArgumentException e) { - log.info("IllegalArgumentException"); - e.printStackTrace(); - } catch (EntityNotFoundByTemplate e) { - log.info(e.getMessage()); - } catch (Exception e) { - log.error("AN INNER EXCEPTION"); - e.printStackTrace(); - } - } catch (TransactionException e) { - log.info("An unimportant TransactionException has occurred"); - } catch (Exception e) { - log.error("OUTER EXCEPTION"); - } + TransactionReference tx = capi.createTransaction( + Util.SPACE_TRANSACTION_TIMEOUT, + URI.create(Util.SERVER_ADDR)); + + // Acquire a lock for the free table in the + // FreeTableContainer + int id = table.getId(); + + Table tableTemplate = new Table(id); + Table lockedFreeTable = takeMatchingEntity(tableTemplate, + freeTablesContainer, tx, RequestTimeout.DEFAULT, + String.format("There was no free table found with id %d", id)); + + + GroupData groupTemplate = new GroupData(); + GroupData lockedGroup = takeMatchingEntity(groupTemplate, + assignTableContainer, tx, RequestTimeout.DEFAULT, + "There is no group waiting for a table at the moment"); + + assignGroupToTable(lockedGroup, lockedFreeTable, tx); } } }; - try { - notificationMgr.createNotification(freeTablesContainer, - freeTableListener, Operation.WRITE); - log.info("Created freeTablesContainer notification for a waiter"); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } + createNotification(listener, freeTablesContainer); } + + public void listenForNewGuests() { - NotificationListener newGroupsListener = new NotificationListener() { + SpaceListener listener = new SpaceListenerImpl(capi, assignTableContainer) { + @Override - public void entryOperationFinished(final Notification notification, - final Operation operation, - final List entries) { - + void onEntriesWritten(List entries) + throws Exception { log.info("New guest groups have arrived"); List groups = castEntries(entries); Collections.rotate(groups, waiterId); for (GroupData group : groups) { - try { - TransactionReference tx = capi.createTransaction(1500, - URI.create(Util.SERVER_ADDR)); - - try { - // Acquire a lock for the group in the - // AssignTableContainer - String groupNotFound = String - .format("Group with id %d was already assigned a table by another waiter!", - group.getId()); - - GroupData lockedGroup = takeMatchingEntity( - new GroupData(group.getId()), - assignTableContainer, tx, 1000, - groupNotFound); - // Acquire a lock for one free table in the - // TablesContainer - Table lockedFreeTable = takeMatchingEntity( - new Table(null), - freeTablesContainer, - tx, - RequestTimeout.DEFAULT, - String.format( - "No free table for group with id %d could be found", - group.getId())); - - assignGroupToTable(lockedGroup, lockedFreeTable, tx); - - } catch (IllegalArgumentException e) { - log.info("IllegalArgumentException"); - e.printStackTrace(); - } catch (EntityNotFoundByTemplate e) { - log.info(e.getMessage()); - } catch (Exception e) { - log.error("AN INNER EXCEPTION"); - e.printStackTrace(); - } - } catch (TransactionException e) { - log.info("An unimportant TransactionException has occurred"); - } catch (Exception e) { - log.error("OUTER EXCEPTION"); - } - + + TransactionReference tx = capi.createTransaction( + Util.SPACE_TRANSACTION_TIMEOUT, + URI.create(Util.SERVER_ADDR)); + + // Acquire a lock for the group in the + // AssignTableContainer + String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId()); + + GroupData lockedGroup = takeMatchingEntity( + new GroupData(group.getId()), + assignTableContainer, tx, + RequestTimeout.DEFAULT, groupNotFound); + // Acquire a lock for one free table in the + // TablesContainer + String noFreeTable = String.format("No free table for group with id %d could be found", group.getId()); + Table lockedFreeTable = takeMatchingEntity(new Table(null), freeTablesContainer, tx, RequestTimeout.DEFAULT, + noFreeTable); + + assignGroupToTable(lockedGroup, lockedFreeTable, tx); } } }; - try { - notificationMgr.createNotification(assignTableContainer, - newGroupsListener, Operation.WRITE); - log.info("Created assingTableContainer notification for a waiter"); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } + + createNotification(listener, assignTableContainer); } public void listenForPaymentRequest() { - log.info("INITIALIZE PAYMENT NOTIFICATION"); - NotificationListener paymentListener = new NotificationListener() { + SpaceListener paymentListener = new SpaceListenerImpl(capi, paymentRequestContainer) { + @Override - public void entryOperationFinished(final Notification notification, - final Operation operation, - final List entries) { - log.info("A PAYMENT REQUEST HAS ARRIVED!"); + void onEntriesWritten(List entries) + throws Exception { List groups = castEntries(entries); - - GroupData groupData = groups.get(0); - - try { - TransactionReference tx = capi.createTransaction(1500, + + for (GroupData groupData : groups) { + TransactionReference tx = capi.createTransaction( + Util.SPACE_TRANSACTION_TIMEOUT, URI.create(Util.SERVER_ADDR)); GroupData entity = new GroupData(groupData.getId()); // Acquire the lock so that another waiter can't do the same // thing! - takeMatchingEntity( - entity, - paymentRequestContainer, - tx, - RequestTimeout.DEFAULT, - String.format( - "The payment request for group %d was already taken by an other waiter!", - groupData.getId())); + String paymentRequestTakenByOtherWaiter = String.format( + "The payment request for group %d was already taken by an other waiter!", + groupData.getId()); + takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter); - groupData.setPayingWaiter(waiterId); - - sendItemsToContainer(Arrays.asList(groupData), - paymentDoneContainer, RequestTimeout.ZERO, tx); - capi.commitTransaction(tx); + sendItemsToContainer(Arrays.asList(groupData), paymentDoneContainer, RequestTimeout.ZERO, tx); - } catch (MzsCoreException e) { - log.info("ERROR in listenForPaymentRequest"); - e.printStackTrace(); + capi.commitTransaction(tx); } } }; - try { - notificationMgr.createNotification(paymentRequestContainer, - paymentListener, Operation.WRITE); - log.info("Created payment notification for a waiter"); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } + createNotification(paymentListener, paymentRequestContainer); } public void listenForOrderRequests() { - NotificationListener ordersListener = new NotificationListener() { + SpaceListener ordersListener = new SpaceListenerImpl(capi, takeOrderContainer) { + @Override - public void entryOperationFinished(final Notification notification, - final Operation operation, - final List entries) { - log.info("A new order has arrived!"); + void onEntriesWritten(List entries) + throws Exception { List groups = castEntries(entries); - if (groups.size() != 1) - throw new RuntimeException( - "Multiple orders in one notification?! That should not happen!"); + + for (GroupData groupData : groups) { - GroupData groupData = groups.get(0); - - try { - TransactionReference tx = capi.createTransaction(1500, + TransactionReference tx = capi.createTransaction( + Util.SPACE_TRANSACTION_TIMEOUT, URI.create(Util.SERVER_ADDR)); GroupData entity = new GroupData(groupData.getId()); entity.setState(GroupState.SITTING); - // Acquire the lock so that another waiter can't do the same - // thing! - takeMatchingEntity( - entity, - takeOrderContainer, - tx, - RequestTimeout.DEFAULT, - String.format( - "The order for group %d was already taken by an other waiter!", - groupData.getId())); - - log.info( - "Will now write taken order from group {} to space", + // Acquire the lock so that another waiter can't do the same thing! + String orderTakenByOtherWaiter = String.format( + "The order for group %d was already taken by an other waiter!", groupData.getId()); + takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter); + groupData.setOrderWaiter(waiterId); groupData.setState(GroupState.ORDERED); Order order = groupData.getOrder(); @@ -293,20 +200,11 @@ public class WaiterXVSM extends AbstractXVSMConnector { log.info("Waiter has taken order from group {}", groupData.getId()); - } catch (MzsCoreException e) { - log.info("ERROR in listenForOrders"); - e.printStackTrace(); - } + } } }; - - try { - notificationMgr.createNotification(takeOrderContainer, - ordersListener, Operation.WRITE); - log.info("Created takeOrderContainer notification for a waiter"); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } + + createNotification(ordersListener, takeOrderContainer); } public void listenForPreparedPizzas() { @@ -318,89 +216,82 @@ public class WaiterXVSM extends AbstractXVSMConnector { * number of those pizzas with the number of necessary pizzas. If all * pizzas of an order are complete he then delivers them! */ - NotificationListener preparedPizzasListener = new NotificationListener() { + SpaceListener preparedPizzasListener = new SpaceListenerImpl(capi, deliverPizzasContainer) { + @Override - public void entryOperationFinished(final Notification notification, - final Operation operation, - final List entries) { + void onEntriesWritten(List entries) + throws Exception { List pizzas = castEntries(entries); - if (pizzas.size() != 1) - throw new RuntimeException( - "Multiple pizzas in one notification?! That should not happen! A cook can only prepare one at the same time!"); - - Pizza pizza = pizzas.get(0); - int orderId = pizza.getOrderId(); + + for (Pizza pizza : pizzas) { + int orderId = pizza.getOrderId(); - try { - TransactionReference tx = capi.createTransaction(1500, + TransactionReference tx = capi.createTransaction( + Util.SPACE_TRANSACTION_TIMEOUT, URI.create(Util.SERVER_ADDR)); - GroupData entity = new GroupData(); - entity.setState(null); - Order order = new Order(); - order.setId(orderId); - entity.setOrder(order); - - GroupData groupData = takeMatchingEntity(entity, - orderTakenContainer, tx, RequestTimeout.DEFAULT, - "Another waiter just checks if the order is complete"); - int groupId = groupData.getId(); - int numberOfPizzas = groupData.getOrder() - .getNumberOfPizzas(); - - Pizza pizzaTemplate = new Pizza(); - pizzaTemplate.setOrderId(orderId); - - List pizzasOfOrder = takeMatchingEntities( - pizzaTemplate, deliverPizzasContainer, tx, - RequestTimeout.DEFAULT, - "Cannot take the pizzas from the deliverPizzasContainer"); - - // for an unkown reason even pizzas not matching the orderid - // are returned. that's why we have to check again if the - // pizza really belongs to the order in question - Iterator it = pizzasOfOrder.iterator(); - while (it.hasNext()) { - Pizza nextPizza = it.next(); - if (nextPizza.getOrderId() != orderId) { - it.remove(); + try { + GroupData entity = new GroupData(); + entity.setState(null); + Order order = new Order(); + order.setId(orderId); + entity.setOrder(order); + + GroupData groupData = takeMatchingEntity(entity, + orderTakenContainer, tx, RequestTimeout.DEFAULT, + "Another waiter just checks if the order is complete"); + int groupId = groupData.getId(); + int numberOfPizzas = groupData.getOrder().getNumberOfPizzas(); + + Pizza pizzaTemplate = new Pizza(); + pizzaTemplate.setOrderId(orderId); + + List pizzasOfOrder = takeMatchingEntities( + pizzaTemplate, deliverPizzasContainer, tx, + RequestTimeout.DEFAULT, + "Cannot take the pizzas from the deliverPizzasContainer"); + + // for an unkown reason even pizzas not matching the orderid + // are returned. that's why we have to check again if the + // pizza really belongs to the order in question + Iterator it = pizzasOfOrder.iterator(); + while (it.hasNext()) { + Pizza nextPizza = it.next(); + if (nextPizza.getOrderId() != orderId) { + log.info("WRONG!"); + it.remove(); + } } - } - if (pizzasOfOrder.size() == numberOfPizzas) { - GroupData group = new GroupData(); - group.setServingWaiter(waiterId); - Order completeOrder = new Order(); - completeOrder.setId(orderId); - completeOrder.setGroupId(groupId); - group.setOrder(completeOrder); - sendItemsToContainer(Arrays.asList(group), - orderCompleteContainer, RequestTimeout.DEFAULT, - tx); - capi.commitTransaction(tx); - } else { - log.info("Not yet all pizzas prepared! Order with id " - + orderId + " has " + numberOfPizzas - + " pizzas, but only " + pizzasOfOrder.size() - + " pizzas are ready by now!"); + if (pizzasOfOrder.size() == numberOfPizzas) { + GroupData group = new GroupData(); + group.setServingWaiter(waiterId); + Order completeOrder = new Order(); + completeOrder.setId(orderId); + completeOrder.setGroupId(groupId); + group.setOrder(completeOrder); + sendItemsToContainer(Arrays.asList(group), + orderCompleteContainer, RequestTimeout.DEFAULT, + tx); + capi.commitTransaction(tx); + } else { + log.info("Not yet all pizzas prepared! Order with id " + + orderId + " has " + numberOfPizzas + + " pizzas, but only " + pizzasOfOrder.size() + + " pizzas are ready by now!"); + capi.rollbackTransaction(tx); + } + } catch (NullPointerException e) { + + } catch (Exception e) { capi.rollbackTransaction(tx); } - - } catch (MzsCoreException e) { - log.error("ERROR in listenForPreparedPizzas!"); - e.printStackTrace(); } } }; - try { - notificationMgr.createNotification(deliverPizzasContainer, - preparedPizzasListener, Operation.WRITE); - log.info("Created deliverPizzasContainer notification for a waiter"); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } + createNotification(preparedPizzasListener, deliverPizzasContainer); } private void assignGroupToTable(GroupData lockedGroup, @@ -414,8 +305,8 @@ public class WaiterXVSM extends AbstractXVSMConnector { lockedGroup.setTable(lockedFreeTable); lockedGroup.setTableWaiter(waiterId); - sendItemsToContainer(Arrays.asList(lockedFreeTable), tableAssignedContainer, - RequestTimeout.ZERO, tx); + sendItemsToContainer(Arrays.asList(lockedFreeTable), + tableAssignedContainer, RequestTimeout.ZERO, tx); sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer, RequestTimeout.ZERO, tx); -- 2.43.0