From a6530fb14df6acab2df1dce7689f978cd3afbccf Mon Sep 17 00:00:00 2001 From: Gregor Riegler Date: Sat, 11 May 2013 01:47:30 +0200 Subject: [PATCH] Solve some space concurrency bugs --- .../tuwien/sbc/valesriegler/common/Util.java | 7 ++ .../tuwien/sbc/valesriegler/types/Pizza.java | 28 ++++- .../xvsm/AbstractXVSMConnector.java | 17 ++- .../sbc/valesriegler/xvsm/CookXVSM.java | 57 +++++---- .../sbc/valesriegler/xvsm/GroupAgentXVSM.java | 4 +- .../sbc/valesriegler/xvsm/GroupXVSM.java | 6 +- .../valesriegler/xvsm/PizzeriaAgentXVSM.java | 1 + .../sbc/valesriegler/xvsm/SpaceListener.java | 34 +++-- .../valesriegler/xvsm/SpaceListenerImpl.java | 9 +- .../sbc/valesriegler/xvsm/WaiterXVSM.java | 119 +++++++++--------- 10 files changed, 180 insertions(+), 102 deletions(-) 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 9c03192..7a0a02f 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 @@ -6,6 +6,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Random; import org.mozartspaces.capi3.Coordinator; import org.mozartspaces.core.Capi; @@ -36,6 +37,8 @@ public abstract class Util { public static final String IS_EATING = "isEating"; public static final String PAYMENT_DONE = "hasPaid"; + private static Random random = new Random(); + public static final long SPACE_TRANSACTION_TIMEOUT = 1500; public static final String SERVER_ADDR = "xvsm://localhost:9876"; @@ -71,6 +74,10 @@ public abstract class Util { } return myMap; } + + public static int getRandom(int min, int max){ + return random.nextInt(max - min + 1) + min; + } } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/Pizza.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/Pizza.java index 021176c..a318dc2 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/Pizza.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/Pizza.java @@ -14,6 +14,14 @@ import at.ac.tuwien.sbc.valesriegler.waiter.Waiter; */ public class Pizza extends PizzaOrder implements Serializable { public Waiter deliveryAgent; + + /** + * Yes that's funny! the pizza has a field idOfOrder although PizzaOrder already has a field orderId! + * The reason: The space linda selection is a little bit limited. when I look for a template pizza with orderId set the + * space gives me ALL pizzas. The reason obviously is that it can't really include the field of the superclass in the search. + * So we must have an idOfOrder field in the pizza and not only in the PizzaOrder for the time being.. ^^ + */ + private Integer idOfOrder; // private Person consumer; @@ -22,7 +30,7 @@ public class Pizza extends PizzaOrder implements Serializable { this.id = id; this.pizzaType = type; this.cookId = cookId; - this.orderId = orderId; + this.idOfOrder = orderId; } public Pizza() { @@ -39,6 +47,24 @@ public class Pizza extends PizzaOrder implements Serializable { + ", orderId=" + orderId + ", pizzaType=" + pizzaType + ", status=" + status + ", cookId=" + cookId + "]"; } + + @Override + public int getOrderId() { + return getIdOfOrder(); + }; + + @Override + public void setOrderId(Integer orderId) { + this.idOfOrder = orderId; + }; + + public int getIdOfOrder() { + return Util.getIntSafe(idOfOrder); + } + + public void setIdOfOrder(Integer idOfOrder) { + this.idOfOrder = idOfOrder; + } 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 a3a6f01..fc2d0c7 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 @@ -6,10 +6,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; +import java.util.concurrent.atomic.AtomicLong; -import org.mozartspaces.capi3.AnyCoordinator; import org.mozartspaces.capi3.Coordinator; import org.mozartspaces.capi3.CountNotMetException; +import org.mozartspaces.capi3.FifoCoordinator; import org.mozartspaces.capi3.LindaCoordinator; import org.mozartspaces.capi3.LindaCoordinator.LindaSelector; import org.mozartspaces.core.Capi; @@ -33,7 +34,7 @@ import at.ac.tuwien.sbc.valesriegler.types.GroupData; public abstract class AbstractXVSMConnector { public static Object lockObject = new Object(); - public static long timeOflastOperation = new Date().getTime(); + public static AtomicLong timeOflastOperation = new AtomicLong(new Date().getTime()); private static final Logger log = LoggerFactory.getLogger(AbstractXVSMConnector.class); @@ -69,7 +70,17 @@ public abstract class AbstractXVSMConnector { protected ContainerReference useContainer(String containerName) { try { - return CapiUtil.lookupOrCreateContainer(containerName, URI.create(Util.SERVER_ADDR), createCoordinators(new AnyCoordinator(), new LindaCoordinator(false)), null, capi); + return CapiUtil.lookupOrCreateContainer(containerName, URI.create(Util.SERVER_ADDR), createCoordinators(new FifoCoordinator(), new LindaCoordinator(false)), null, capi); + } catch (MzsCoreException e) { + handleSpaceErrorAndTerminate(e); + } + + throw new RuntimeException("Could not Create container " + containerName); + } + + protected ContainerReference useContainer(String containerName, List coordinators) { + try { + return CapiUtil.lookupOrCreateContainer(containerName, URI.create(Util.SERVER_ADDR), coordinators, null, capi); } catch (MzsCoreException e) { handleSpaceErrorAndTerminate(e); } 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 871cde4..93011af 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 @@ -6,14 +6,11 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.mozartspaces.capi3.AnyCoordinator; +import org.mozartspaces.capi3.FifoCoordinator; import org.mozartspaces.capi3.LindaCoordinator; +import org.mozartspaces.core.MzsConstants; import org.mozartspaces.core.MzsConstants.RequestTimeout; -import org.mozartspaces.core.TransactionException; import org.mozartspaces.core.TransactionReference; -import org.mozartspaces.notifications.Notification; -import org.mozartspaces.notifications.NotificationListener; -import org.mozartspaces.notifications.Operation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,45 +30,59 @@ public class CookXVSM extends AbstractXVSMConnector { this.cookId = id; orderTakenContainer = useContainer(Util.ORDER_TAKEN) ; deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS); - preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS) ; + preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS, createCoordinators(new FifoCoordinator(), new LindaCoordinator(false))); pizzaInProgressContainer = useContainer(Util.PIZZAS_IN_PROGRESS) ; } public void listenForPizzas() { - SpaceListener pizzasListener = new SpaceListenerImpl(capi, preparePizzasContainer) { + SpaceListener pizzasListener = new SpaceListenerImpl(capi, preparePizzasContainer, 15000) { @Override void onEntriesWritten(List entries) throws Exception { List pizzas = castEntries(entries); - Collections.rotate(pizzas, cookId); + + if(inNotification.get()) Collections.shuffle(pizzas); for (PizzaOrder pizzaOrder : pizzas) { 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); + try { + // Require the lock for preparing the pizza + PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), preparePizzasContainer, tx, RequestTimeout.ZERO, pizzaAlreadyCooked); + + // tell the space that you prepare the pizza -> without a transaction!! + Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId); + pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION); - 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()); + log.info("I say that I now prepare a pizza for order {}", pizzaInProgress.getOrderId()); + 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 (NullPointerException e) { + // the strange nullpointer exception from the space + } catch (Exception e) { + log.info(e.getMessage()); + } } } + + @Override + List getEntries() throws Exception { + return capi.read(preparePizzasContainer, FifoCoordinator + .newSelector(MzsConstants.Selecting.COUNT_ALL), + RequestTimeout.DEFAULT, null); + } }; createNotification(pizzasListener, preparePizzasContainer); 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 7bc06c6..a348677 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,6 +5,8 @@ import java.util.List; import javax.swing.SwingUtilities; +import org.mozartspaces.capi3.FifoCoordinator; +import org.mozartspaces.capi3.LindaCoordinator; import org.mozartspaces.core.MzsConstants.RequestTimeout; import org.mozartspaces.notifications.Notification; import org.mozartspaces.notifications.NotificationListener; @@ -23,7 +25,7 @@ public class GroupAgentXVSM extends AbstractXVSMConnector { public GroupAgentXVSM() { super(); - assignTableContainer = useContainer(Util.ASSIGN_TABLE) ; + assignTableContainer = useContainer(Util.ASSIGN_TABLE); orderCompleteContainer = useContainer(Util.ORDER_COMPLETE) ; paymentRequestContainer = useContainer(Util.PAYMENT_REQUEST) ; paymentDoneContainer = useContainer(Util.PAYMENT_DONE); diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupXVSM.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupXVSM.java index 3d32ef7..bca5363 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupXVSM.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupXVSM.java @@ -60,7 +60,7 @@ public class GroupXVSM extends AbstractXVSMConnector { } private void eatAndThenPay() { - int timeToEat = getRandom(3, 5); + int timeToEat = Util.getRandom(3, 5); log.info("I eat {} seconds now...", timeToEat); GroupData groupData = new GroupData(); @@ -75,9 +75,5 @@ public class GroupXVSM extends AbstractXVSMConnector { sendItemsToContainer(Arrays.asList(groupData), paymentRequestContainer, RequestTimeout.DEFAULT, null); log.info("I sent my payment request to the space! GroupId: {}", groupId); } - - private int getRandom(int min, int max){ - return random.nextInt(max - min + 1) + min; - } } 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 b4a6885..7042b66 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 @@ -9,6 +9,7 @@ import java.util.List; import javax.swing.SwingUtilities; import org.mozartspaces.capi3.AnyCoordinator; +import org.mozartspaces.capi3.FifoCoordinator; import org.mozartspaces.capi3.LindaCoordinator; import org.mozartspaces.core.MzsCoreException; import org.mozartspaces.core.TransactionReference; 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 index e8f344d..5716045 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/SpaceListener.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/SpaceListener.java @@ -5,6 +5,7 @@ import java.util.Date; import java.util.List; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicBoolean; import org.mozartspaces.notifications.Notification; import org.mozartspaces.notifications.NotificationListener; @@ -30,17 +31,22 @@ public abstract class SpaceListener implements NotificationListener { .getLogger(SpaceListener.class); protected boolean lookAround = true; + protected long timeout = 3000; + protected AtomicBoolean inNotification = new AtomicBoolean(true); @Override public void entryOperationFinished(Notification arg0, Operation arg1, List entries) { synchronized (AbstractXVSMConnector.lockObject) { + AbstractXVSMConnector.timeOflastOperation.set(new Date().getTime()); try { + log.info("I am running a notification now!"); + inNotification.set(true); onEntriesWritten(entries); } catch (Exception e) { // e.printStackTrace(); } - AbstractXVSMConnector.timeOflastOperation = new Date().getTime(); + } } @@ -51,30 +57,38 @@ public abstract class SpaceListener implements NotificationListener { public void startHandlingAbsenceOfNotifications() { if(!lookAround) return; + AbstractXVSMConnector.timeOflastOperation.set(new Date().getTime() + 3500); Timer timer = new Timer(); - timer.schedule(new SpaceTask(), 500, 3000); + timer.schedule(new SpaceTask(), 3000, 3000); } class SpaceTask extends TimerTask { @Override public void run() { - long time = new Date().getTime(); - if(time-3000 <= AbstractXVSMConnector.timeOflastOperation) return; + if(new Date().getTime()-timeout <= AbstractXVSMConnector.timeOflastOperation.get()) { + return; + } synchronized(AbstractXVSMConnector.lockObject) { try { - - List entries = getEntries(); - if(entries.size() != 0) { - onEntriesWritten(entries); - } + AbstractXVSMConnector.timeOflastOperation.set(new Date().getTime()); + log.info("Timer task running"); + + List entries = getEntries(); + if(entries.size() != 0) { + log.info("{} entries in timer", entries.size()); + inNotification.set(false); + onEntriesWritten(entries); + } else { + log.info("No entries in timer!"); + } } 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 index 8b3bd61..b612fb9 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/SpaceListenerImpl.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/SpaceListenerImpl.java @@ -4,6 +4,7 @@ import java.io.Serializable; import java.util.List; import org.mozartspaces.capi3.AnyCoordinator; +import org.mozartspaces.capi3.FifoCoordinator; import org.mozartspaces.core.Capi; import org.mozartspaces.core.ContainerReference; import org.mozartspaces.core.MzsConstants; @@ -20,7 +21,6 @@ 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; @@ -30,10 +30,15 @@ public abstract class SpaceListenerImpl extends SpaceListener { this(core, cref); this.lookAround = lookAround; } + + public SpaceListenerImpl(Capi core, ContainerReference cref, long milliseconds) { + this(core, cref); + this.timeout = milliseconds; + } @Override List getEntries() throws Exception { - return capi.read(cref, AnyCoordinator + return capi.read(cref, FifoCoordinator .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 8a91408..73be4ab 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 @@ -8,6 +8,8 @@ import java.util.Iterator; import java.util.List; import org.mozartspaces.capi3.AnyCoordinator; +import org.mozartspaces.capi3.FifoCoordinator; +import org.mozartspaces.capi3.LindaCoordinator; import org.mozartspaces.core.ContainerReference; import org.mozartspaces.core.MzsConstants; import org.mozartspaces.core.MzsConstants.RequestTimeout; @@ -50,15 +52,12 @@ public class WaiterXVSM extends AbstractXVSMConnector { } public void listenForFreeTable() { - SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer) { + SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer, false) { @Override void onEntriesWritten(List entries) throws Exception { -// log.info("{} tables have become free", entries.size()); - List tables = castEntries(entries); - Collections.rotate(tables, waiterId); for (Table table : tables) { @@ -71,17 +70,21 @@ public class WaiterXVSM extends AbstractXVSMConnector { 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)); + try { + 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"); + 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); + assignGroupToTable(lockedGroup, lockedFreeTable, tx); + } catch (Exception e) { +// log.info(e.getMessage()); + } } } }; @@ -100,7 +103,6 @@ public class WaiterXVSM extends AbstractXVSMConnector { log.info("New guest groups have arrived"); List groups = castEntries(entries); - Collections.rotate(groups, waiterId); for (GroupData group : groups) { @@ -112,17 +114,21 @@ public class WaiterXVSM extends AbstractXVSMConnector { // 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 { + 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); + } catch (Exception e) { +// log.info(e.getMessage()); + } } } }; @@ -150,13 +156,17 @@ public class WaiterXVSM extends AbstractXVSMConnector { 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); + try { + takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter); - groupData.setPayingWaiter(waiterId); + groupData.setPayingWaiter(waiterId); - sendItemsToContainer(Arrays.asList(groupData), paymentDoneContainer, RequestTimeout.ZERO, tx); + sendItemsToContainer(Arrays.asList(groupData), paymentDoneContainer, RequestTimeout.ZERO, tx); - capi.commitTransaction(tx); + capi.commitTransaction(tx); + } catch (Exception e) { +// log.info(e.getMessage()); + } } } }; @@ -181,25 +191,31 @@ public class WaiterXVSM extends AbstractXVSMConnector { GroupData entity = new GroupData(groupData.getId()); entity.setState(GroupState.SITTING); - // 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(); - order.setStatus(OrderStatus.ORDERED); + try { + // 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); - sendItemsToContainer(Arrays.asList(groupData), - orderTakenContainer, RequestTimeout.ZERO, tx); - sendItemsToContainer(order.getOrderedPizzas(), - preparePizzasContainer, RequestTimeout.ZERO, tx); - capi.commitTransaction(tx); + groupData.setOrderWaiter(waiterId); + groupData.setState(GroupState.ORDERED); + Order order = groupData.getOrder(); + order.setStatus(OrderStatus.ORDERED); - log.info("Waiter has taken order from group {}", - groupData.getId()); + + // send the order as a whole to the space + sendItemsToContainer(Arrays.asList(groupData), + orderTakenContainer, RequestTimeout.ZERO, tx); + sendItemsToContainer(order.getOrderedPizzas(), + preparePizzasContainer, RequestTimeout.ZERO, tx); + capi.commitTransaction(tx); + + log.info("Waiter has taken order from group {}", + groupData.getId()); + } catch (Exception e) { +// log.info(e.getMessage()); + } } } }; @@ -252,18 +268,6 @@ public class WaiterXVSM extends AbstractXVSMConnector { 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); @@ -317,6 +321,7 @@ public class WaiterXVSM extends AbstractXVSMConnector { } catch (Exception e) { log.info("Assigning a table to group with groupId {} failed", lockedGroup.getId()); + log.info(e.getMessage()); } } -- 2.43.0