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.OrderStatus;
26 import at.ac.tuwien.sbc.valesriegler.types.Table;
28 public class WaiterXVSMConnector extends AbstractXVSMConnector {
29 private static final Logger log = LoggerFactory.getLogger(WaiterXVSMConnector.class);
30 private final int waiterId;
32 public WaiterXVSMConnector(int waiterId) {
35 this.waiterId = waiterId;
37 useFreeTablesContainer();
38 useAssignTableContainer();
40 useTakeOrderContainer();
45 public void listenForFreeTable() {
47 NotificationListener freeTableListener = new NotificationListener() {
49 public void entryOperationFinished(final Notification notification, final Operation operation, final List<? extends Serializable> entries) {
51 log.info("{} tables have become free", entries.size());
53 List<Table> tables = castEntries(entries);
54 Collections.shuffle(tables);
56 for (Table table : tables) {
58 TransactionReference tx = capi.createTransaction(3000, URI.create(Util.SERVER_ADDR));
61 // Acquire a lock for the free table in the FreeTableContainer
62 int id = table.getId();
63 log.info("Try to find the table with id {}", id);
65 Table tableTemplate = new Table(id);
66 Table lockedFreeTable = takeEntityByTemplateFromContainer(tableTemplate, freeTablesContainer, tx, 1000, String.format("There was no free table found with id %d", id));
68 log.info("Table with id {} was found", id);
70 GroupData groupTemplate = new GroupData();
71 GroupData lockedGroup = takeEntityByTemplateFromContainer(groupTemplate, assignTableContainer, tx, RequestTimeout.DEFAULT, "There is no group waiting for a table at the moment");
73 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
75 } catch (IllegalArgumentException e) {
76 log.info("IllegalArgumentException");
78 } catch (EntityNotFoundByTemplate e) {
79 log.info(e.getMessage());
80 } catch (Exception e) {
81 log.error("AN INNER EXCEPTION");
84 } catch (TransactionException e) {
85 log.info("An unimportant TransactionException has occurred");
86 } catch (Exception e) {
87 log.error("OUTER EXCEPTION");
94 notificationMgr.createNotification(freeTablesContainer, freeTableListener, Operation.WRITE);
95 log.info("Created freeTablesContainer notification for a waiter");
96 } catch (MzsCoreException e) {
98 } catch (InterruptedException e) {
104 public void listenForNewGuests() {
105 NotificationListener newGroupsListener = new NotificationListener() {
107 public void entryOperationFinished(final Notification notification, final Operation operation, final List<? extends Serializable> entries) {
109 log.info("New guest groups have arrived");
111 List<GroupData> groups = castEntries(entries);
112 Collections.shuffle(groups);
114 for (GroupData group : groups) {
116 TransactionReference tx = capi.createTransaction(1500, URI.create(Util.SERVER_ADDR));
119 // Acquire a lock for the group in the AssignTableContainer
120 String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId());
122 GroupData lockedGroup = takeEntityByTemplateFromContainer(new GroupData(group.getId()), assignTableContainer, tx, 1000, groupNotFound);
123 // Acquire a lock for one free table in the TablesContainer
124 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()));
126 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
128 } catch (IllegalArgumentException e) {
129 log.info("IllegalArgumentException");
131 } catch (EntityNotFoundByTemplate e) {
132 log.info(e.getMessage());
133 } catch (Exception e) {
134 log.error("AN INNER EXCEPTION");
137 } catch (TransactionException e) {
138 log.info("An unimportant TransactionException has occurred");
139 } catch (Exception e) {
140 log.error("OUTER EXCEPTION");
147 notificationMgr.createNotification(assignTableContainer, newGroupsListener, Operation.WRITE);
148 log.info("Created assingTableContainer notification for a waiter");
149 } catch (MzsCoreException e) {
151 } catch (InterruptedException e) {
156 public void listenForOrders() {
157 NotificationListener ordersListener = new NotificationListener() {
159 public void entryOperationFinished(final Notification notification, final Operation operation, final List<? extends Serializable> entries) {
160 log.info("A new order has arrived!");
162 List<GroupData> groups = castEntries(entries);
163 if(groups.size() != 1) throw new RuntimeException("Multiple orders in one notification?! That should not happen!");
165 GroupData groupData = groups.get(0);
168 TransactionReference tx = capi.createTransaction(1500, URI.create(Util.SERVER_ADDR));
169 GroupData entity = new GroupData(groupData.getId());
170 entity.setState(GroupState.ORDER_PENDING);
171 takeEntityByTemplateFromContainer(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, String.format("The order for group %d was already taken by an other waiter!", groupData.getId()));
174 log.info("Will now write taken order from group {} to space", groupData.getId());
175 groupData.setOrderWaiter(waiterId);
176 groupData.setState(GroupState.ORDERED);
177 groupData.getOrder().setStatus(OrderStatus.ORDERED);
178 sendItemsToContainer(Arrays.asList(groupData), ordersContainer, RequestTimeout.ZERO, tx);
179 sendItemsToContainer(Arrays.asList(groupData), groupsContainer, RequestTimeout.ZERO, tx);
180 capi.commitTransaction(tx);
183 log.info("Waiter has taken order from group {}", groupData.getId());
185 } catch (MzsCoreException e) {
186 log.info("ERROR in listenForOrders");
193 notificationMgr.createNotification(takeOrderContainer, ordersListener, Operation.WRITE);
194 log.info("Created takeOrderContainer notification for a waiter");
195 } catch (MzsCoreException e) {
197 } catch (InterruptedException e) {
202 private void assignGroupToTable(GroupData lockedGroup,
203 Table lockedFreeTable, TransactionReference tx)
204 throws MzsCoreException {
205 // The new group sits down at the table
206 lockedFreeTable.setGroupId(lockedGroup.getId());
209 // The new group now wants to order
210 lockedGroup.setState(GroupState.ORDER_PENDING);
211 lockedGroup.setTable(lockedFreeTable);
212 lockedGroup.setTableWaiter(waiterId);
214 sendItemsToContainer(Arrays.asList(lockedFreeTable), tablesContainer, RequestTimeout.ZERO, tx);
215 sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer, RequestTimeout.ZERO, tx);
218 sendItemsToContainer(Arrays.asList(lockedGroup), groupsContainer, RequestTimeout.ZERO, tx);
221 capi.commitTransaction(tx);
222 log.info("Assigned table to group with groupId {}", lockedGroup.getId());
223 } catch (Exception e) {
224 log.info("Assigning a table to group with groupId {} failed", lockedGroup.getId());