1 package at.ac.tuwien.sbc.valesriegler.xvsm;
3 import java.io.Serializable;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.Collections;
10 import org.mozartspaces.capi3.CountNotMetException;
11 import org.mozartspaces.core.MzsConstants.RequestTimeout;
12 import org.mozartspaces.core.MzsCoreException;
13 import org.mozartspaces.core.MzsTimeoutException;
14 import org.mozartspaces.core.TransactionException;
15 import org.mozartspaces.core.TransactionReference;
16 import org.mozartspaces.notifications.Notification;
17 import org.mozartspaces.notifications.NotificationListener;
18 import org.mozartspaces.notifications.Operation;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
22 import at.ac.tuwien.sbc.valesriegler.common.Util;
23 import at.ac.tuwien.sbc.valesriegler.types.GroupData;
24 import at.ac.tuwien.sbc.valesriegler.types.GroupState;
25 import at.ac.tuwien.sbc.valesriegler.types.Order;
26 import at.ac.tuwien.sbc.valesriegler.types.OrderStatus;
27 import at.ac.tuwien.sbc.valesriegler.types.PizzaOrder;
28 import at.ac.tuwien.sbc.valesriegler.types.Table;
30 public class WaiterXVSM extends AbstractXVSMConnector {
31 private static final Logger log = LoggerFactory.getLogger(WaiterXVSM.class);
32 private final int waiterId;
34 public WaiterXVSM(int waiterId) {
37 this.waiterId = waiterId;
39 useFreeTablesContainer();
40 useAssignTableContainer();
42 useTakeOrderContainer();
44 usePreparePizzasContainer();
48 public void listenForFreeTable() {
50 NotificationListener freeTableListener = new NotificationListener() {
52 public void entryOperationFinished(final Notification notification, final Operation operation, final List<? extends Serializable> entries) {
54 log.info("{} tables have become free", entries.size());
56 List<Table> tables = castEntries(entries);
57 Collections.shuffle(tables);
59 for (Table table : tables) {
61 TransactionReference tx = capi.createTransaction(3000, URI.create(Util.SERVER_ADDR));
64 // Acquire a lock for the free table in the FreeTableContainer
65 int id = table.getId();
66 log.info("Try to find the table with id {}", id);
68 Table tableTemplate = new Table(id);
69 Table lockedFreeTable = takeEntityByTemplateFromContainer(tableTemplate, freeTablesContainer, tx, 1000, String.format("There was no free table found with id %d", id));
71 log.info("Table with id {} was found", id);
73 GroupData groupTemplate = new GroupData();
74 GroupData lockedGroup = takeEntityByTemplateFromContainer(groupTemplate, assignTableContainer, tx, RequestTimeout.DEFAULT, "There is no group waiting for a table at the moment");
76 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
78 } catch (IllegalArgumentException e) {
79 log.info("IllegalArgumentException");
81 } catch (EntityNotFoundByTemplate e) {
82 log.info(e.getMessage());
83 } catch (Exception e) {
84 log.error("AN INNER EXCEPTION");
87 } catch (TransactionException e) {
88 log.info("An unimportant TransactionException has occurred");
89 } catch (Exception e) {
90 log.error("OUTER EXCEPTION");
97 notificationMgr.createNotification(freeTablesContainer, freeTableListener, Operation.WRITE);
98 log.info("Created freeTablesContainer notification for a waiter");
99 } catch (Exception e) {
100 handleSpaceErrorAndTerminate(e);
105 public void listenForNewGuests() {
106 NotificationListener newGroupsListener = new NotificationListener() {
108 public void entryOperationFinished(final Notification notification, final Operation operation, final List<? extends Serializable> entries) {
110 log.info("New guest groups have arrived");
112 List<GroupData> groups = castEntries(entries);
113 Collections.shuffle(groups);
115 for (GroupData group : groups) {
117 TransactionReference tx = capi.createTransaction(1500, URI.create(Util.SERVER_ADDR));
120 // Acquire a lock for the group in the AssignTableContainer
121 String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId());
123 GroupData lockedGroup = takeEntityByTemplateFromContainer(new GroupData(group.getId()), assignTableContainer, tx, 1000, groupNotFound);
124 // Acquire a lock for one free table in the TablesContainer
125 Table lockedFreeTable = takeEntityByTemplateFromContainer(new Table(null), freeTablesContainer, tx, RequestTimeout.DEFAULT, String.format("No free table for group with id %d could be found", group.getId()));
127 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
129 } catch (IllegalArgumentException e) {
130 log.info("IllegalArgumentException");
132 } catch (EntityNotFoundByTemplate e) {
133 log.info(e.getMessage());
134 } catch (Exception e) {
135 log.error("AN INNER EXCEPTION");
138 } catch (TransactionException e) {
139 log.info("An unimportant TransactionException has occurred");
140 } catch (Exception e) {
141 log.error("OUTER EXCEPTION");
148 notificationMgr.createNotification(assignTableContainer, newGroupsListener, Operation.WRITE);
149 log.info("Created assingTableContainer notification for a waiter");
150 } catch (Exception e) {
151 handleSpaceErrorAndTerminate(e);
155 public void listenForOrders() {
156 NotificationListener ordersListener = new NotificationListener() {
158 public void entryOperationFinished(final Notification notification, final Operation operation, final List<? extends Serializable> entries) {
159 log.info("A new order has arrived!");
161 List<GroupData> groups = castEntries(entries);
162 if(groups.size() != 1) throw new RuntimeException("Multiple orders in one notification?! That should not happen!");
164 GroupData groupData = groups.get(0);
167 TransactionReference tx = capi.createTransaction(1500, URI.create(Util.SERVER_ADDR));
168 GroupData entity = new GroupData(groupData.getId());
169 entity.setState(GroupState.ORDER_PENDING);
170 takeEntityByTemplateFromContainer(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, String.format("The order for group %d was already taken by an other waiter!", groupData.getId()));
173 log.info("Will now write taken order from group {} to space", groupData.getId());
174 groupData.setOrderWaiter(waiterId);
175 groupData.setState(GroupState.ORDERED);
176 Order order = groupData.getOrder();
177 order.setStatus(OrderStatus.ORDERED);
179 sendItemsToContainer(Arrays.asList(groupData), ordersContainer, RequestTimeout.ZERO, tx);
180 sendItemsToContainer(Arrays.asList(groupData), groupsContainer, RequestTimeout.ZERO, tx);
181 sendItemsToContainer(order.getOrderedPizzas(), preparePizzasContainer, RequestTimeout.ZERO, tx);
182 capi.commitTransaction(tx);
185 log.info("Waiter has taken order from group {}", groupData.getId());
186 } catch (MzsCoreException e) {
187 log.info("ERROR in listenForOrders");
194 notificationMgr.createNotification(takeOrderContainer, ordersListener, Operation.WRITE);
195 log.info("Created takeOrderContainer notification for a waiter");
196 } catch (Exception e) {
197 handleSpaceErrorAndTerminate(e);
201 public void listenForPreparedPizzas() {
205 private void assignGroupToTable(GroupData lockedGroup,
206 Table lockedFreeTable, TransactionReference tx)
207 throws MzsCoreException {
208 // The new group sits down at the table
209 lockedFreeTable.setGroupId(lockedGroup.getId());
212 // The new group now wants to order
213 lockedGroup.setState(GroupState.ORDER_PENDING);
214 lockedGroup.setTable(lockedFreeTable);
215 lockedGroup.setTableWaiter(waiterId);
217 sendItemsToContainer(Arrays.asList(lockedFreeTable), tablesContainer, RequestTimeout.ZERO, tx);
218 sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer, RequestTimeout.ZERO, tx);
219 sendItemsToContainer(Arrays.asList(lockedGroup), groupsContainer, RequestTimeout.ZERO, tx);
222 capi.commitTransaction(tx);
223 log.info("Assigned table to group with groupId {}", lockedGroup.getId());
224 } catch (Exception e) {
225 log.info("Assigning a table to group with groupId {} failed", lockedGroup.getId());