1 package at.ac.tuwien.sbc.valesriegler.xvsm;
3 import java.io.Serializable;
5 import java.util.Arrays;
6 import java.util.Collections;
7 import java.util.Iterator;
10 import at.ac.tuwien.sbc.valesriegler.common.OrderId;
11 import at.ac.tuwien.sbc.valesriegler.types.*;
12 import org.mozartspaces.capi3.AnyCoordinator;
13 import org.mozartspaces.capi3.FifoCoordinator;
14 import org.mozartspaces.capi3.LindaCoordinator;
15 import org.mozartspaces.core.ContainerReference;
16 import org.mozartspaces.core.MzsConstants;
17 import org.mozartspaces.core.MzsConstants.RequestTimeout;
18 import org.mozartspaces.core.MzsCoreException;
19 import org.mozartspaces.core.TransactionException;
20 import org.mozartspaces.core.TransactionReference;
21 import org.mozartspaces.notifications.Notification;
22 import org.mozartspaces.notifications.NotificationListener;
23 import org.mozartspaces.notifications.Operation;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
27 import at.ac.tuwien.sbc.valesriegler.common.Util;
29 public class WaiterXVSM extends AbstractXVSMConnector {
30 private static final Logger log = LoggerFactory.getLogger(WaiterXVSM.class);
31 private final int waiterId;
33 public WaiterXVSM(int waiterId) {
36 this.waiterId = waiterId;
38 freeTablesContainer = useContainer(Util.FREE_TABLES);
39 assignTableContainer = useContainer(Util.ASSIGN_TABLE);
40 takeOrderContainer = useContainer(Util.TAKE_ORDER);
41 orderTakenContainer = useContainer(Util.ORDER_TAKEN);
42 preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
43 orderCompleteContainer = useContainer(Util.ORDER_COMPLETE);
44 deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
45 paymentRequestContainer = useContainer(Util.PAYMENT_REQUEST);
46 paymentDoneContainer = useContainer(Util.PAYMENT_DONE);
47 tableAssignedContainer = useContainer(Util.TABLE_ASSIGNED);
48 infoContainer = useContainer(Util.INFO);
51 public void listenForFreeTable() {
52 SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer, false) {
55 void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
57 List<Table> tables = castEntries(entries);
59 for (Table table : tables) {
61 TransactionReference tx = capi.createTransaction(
62 Util.SPACE_TRANSACTION_TIMEOUT,
63 URI.create(Util.SERVER_ADDR));
65 // Acquire a lock for the free table in the
67 int id = table.getId();
69 Table tableTemplate = new Table(id);
71 Table lockedFreeTable = takeMatchingEntity(tableTemplate,
72 freeTablesContainer, tx, RequestTimeout.DEFAULT,
73 String.format("There was no free table found with id %d", id));
76 GroupData groupTemplate = new GroupData();
77 GroupData lockedGroup = takeMatchingEntity(groupTemplate,
78 assignTableContainer, tx, RequestTimeout.DEFAULT,
79 "There is no group waiting for a table at the moment");
81 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
82 } catch (Exception e) {
83 // log.info(e.getMessage());
89 createNotification(listener, freeTablesContainer);
94 public void listenForNewGuests() {
95 SpaceListener listener = new SpaceListenerImpl(capi, assignTableContainer) {
98 void onEntriesWritten(List<? extends Serializable> entries)
100 log.info("New guest groups have arrived");
102 List<GroupData> groups = castEntries(entries);
104 for (GroupData group : groups) {
106 TransactionReference tx = capi.createTransaction(
107 Util.SPACE_TRANSACTION_TIMEOUT,
108 URI.create(Util.SERVER_ADDR));
110 // Acquire a lock for the group in the
111 // AssignTableContainer
112 String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId());
115 GroupData lockedGroup = takeMatchingEntity(
116 new GroupData(group.getId()),
117 assignTableContainer, tx,
118 RequestTimeout.DEFAULT, groupNotFound);
119 // Acquire a lock for one free table in the
121 String noFreeTable = String.format("No free table for group with id %d could be found", group.getId());
122 Table lockedFreeTable = takeMatchingEntity(new Table(null), freeTablesContainer, tx, RequestTimeout.DEFAULT,
125 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
126 } catch (Exception e) {
127 // log.info(e.getMessage());
133 createNotification(listener, assignTableContainer);
136 public void listenForPaymentRequest() {
137 SpaceListener paymentListener = new SpaceListenerImpl(capi, paymentRequestContainer) {
140 void onEntriesWritten(List<? extends Serializable> entries)
143 List<GroupData> groups = castEntries(entries);
145 for (GroupData groupData : groups) {
146 TransactionReference tx = capi.createTransaction(
147 Util.SPACE_TRANSACTION_TIMEOUT,
148 URI.create(Util.SERVER_ADDR));
149 GroupData entity = new GroupData(groupData.getId());
151 // Acquire the lock so that another waiter can't do the same
153 String paymentRequestTakenByOtherWaiter = String.format(
154 "The payment request for group %d was already taken by an other waiter!",
157 takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
159 groupData.setPayingWaiter(waiterId);
161 sendItemsToContainer(Arrays.asList(groupData), paymentDoneContainer, RequestTimeout.ZERO, tx);
163 capi.commitTransaction(tx);
164 } catch (Exception e) {
165 // log.info(e.getMessage());
171 createNotification(paymentListener, paymentRequestContainer);
174 public void listenForOrderRequests() {
175 SpaceListener ordersListener = new SpaceListenerImpl(capi, takeOrderContainer) {
178 void onEntriesWritten(List<? extends Serializable> entries)
181 List<GroupData> groups = castEntries(entries);
183 for (GroupData groupData : groups) {
185 TransactionReference tx = capi.createTransaction(
186 Util.SPACE_TRANSACTION_TIMEOUT,
187 URI.create(Util.SERVER_ADDR));
188 GroupData entity = new GroupData(groupData.getId());
189 entity.setState(GroupState.SITTING);
192 // Acquire the lock so that another waiter can't do the same thing!
193 String orderTakenByOtherWaiter = String.format(
194 "The order for group %d was already taken by an other waiter!",
196 takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
198 groupData.setOrderWaiter(waiterId);
199 groupData.setState(GroupState.ORDERED);
200 Order order = groupData.getOrder();
201 order.setStatus(OrderStatus.ORDERED);
203 /* get the id of the last order of the pizzeria and set the order accordingly and
205 final OrderId orderId = takeMatchingEntity(new OrderId(null), infoContainer, tx, RequestTimeout.INFINITE, "The Order id object could not be taken from the space!");
206 final int id = orderId.getId();
208 final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
209 for (PizzaOrder orderedPizza : orderedPizzas) {
210 orderedPizza.setId(id);
212 sendItemsToContainer(Arrays.asList(new OrderId(id+1)), infoContainer, RequestTimeout.DEFAULT, tx);
214 // send the order as a whole to the space
215 sendItemsToContainer(Arrays.asList(groupData),
216 orderTakenContainer, RequestTimeout.ZERO, tx);
217 sendItemsToContainer(order.getOrderedPizzas(),
218 preparePizzasContainer, RequestTimeout.ZERO, tx);
219 capi.commitTransaction(tx);
221 log.info("Waiter has taken order from group {}",
223 } catch (Exception e) {
224 // log.info(e.getMessage());
230 createNotification(ordersListener, takeOrderContainer);
233 public void listenForPreparedPizzas() {
235 * A waiter gets informed when a new pizza is complete. He takes the
236 * orderId of the pizza and looks up the corresponding order from which
237 * he gets the number of necessary pizzas of the order. He then tries to
238 * fetch all pizzas with the corresponding orderId and compares the
239 * number of those pizzas with the number of necessary pizzas. If all
240 * pizzas of an order are complete he then delivers them!
242 SpaceListener preparedPizzasListener = new SpaceListenerImpl(capi, deliverPizzasContainer) {
245 void onEntriesWritten(List<? extends Serializable> entries)
248 List<Pizza> pizzas = castEntries(entries);
250 for (Pizza pizza : pizzas) {
251 int orderId = pizza.getOrderId();
253 TransactionReference tx = capi.createTransaction(
254 Util.SPACE_TRANSACTION_TIMEOUT,
255 URI.create(Util.SERVER_ADDR));
258 GroupData entity = new GroupData();
259 entity.setState(null);
260 Order order = new Order();
261 order.setId(orderId);
262 entity.setOrder(order);
264 GroupData groupData = takeMatchingEntity(entity,
265 orderTakenContainer, tx, RequestTimeout.DEFAULT,
266 "Another waiter just checks if the order is complete");
267 int groupId = groupData.getId();
268 int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
270 Pizza pizzaTemplate = new Pizza();
271 pizzaTemplate.setOrderId(orderId);
273 List<Pizza> pizzasOfOrder = takeMatchingEntities(
274 pizzaTemplate, deliverPizzasContainer, tx,
275 RequestTimeout.DEFAULT,
276 "Cannot take the pizzas from the deliverPizzasContainer");
278 if (pizzasOfOrder.size() == numberOfPizzas) {
279 GroupData group = new GroupData();
280 group.setServingWaiter(waiterId);
281 Order completeOrder = new Order();
282 completeOrder.setId(orderId);
283 completeOrder.setGroupId(groupId);
284 group.setOrder(completeOrder);
285 sendItemsToContainer(Arrays.asList(group),
286 orderCompleteContainer, RequestTimeout.DEFAULT,
288 capi.commitTransaction(tx);
290 log.info("Not yet all pizzas prepared! Order with id "
291 + orderId + " has " + numberOfPizzas
292 + " pizzas, but only " + pizzasOfOrder.size()
293 + " pizzas are ready by now!");
294 capi.rollbackTransaction(tx);
296 } catch (NullPointerException e) {
298 } catch (Exception e) {
299 capi.rollbackTransaction(tx);
305 createNotification(preparedPizzasListener, deliverPizzasContainer);
308 private void assignGroupToTable(GroupData lockedGroup,
309 Table lockedFreeTable, TransactionReference tx)
310 throws MzsCoreException {
311 // The new group sits down at the table
312 lockedFreeTable.setGroupId(lockedGroup.getId());
314 // The new group now wants to order
315 lockedGroup.setState(GroupState.SITTING);
316 lockedGroup.setTable(lockedFreeTable);
317 lockedGroup.setTableWaiter(waiterId);
319 sendItemsToContainer(Arrays.asList(lockedFreeTable),
320 tableAssignedContainer, RequestTimeout.ZERO, tx);
321 sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer,
322 RequestTimeout.ZERO, tx);
325 capi.commitTransaction(tx);
326 log.info("Assigned table to group with groupId {}",
327 lockedGroup.getId());
328 } catch (Exception e) {
329 log.info("Assigning a table to group with groupId {} failed",
330 lockedGroup.getId());
331 log.info(e.getMessage());