1 package at.ac.tuwien.sbc.valesriegler.xvsm;
3 import at.ac.tuwien.sbc.valesriegler.common.Util;
4 import at.ac.tuwien.sbc.valesriegler.types.*;
5 import at.ac.tuwien.sbc.valesriegler.xvsm.spacehelpers.SpaceAction;
6 import at.ac.tuwien.sbc.valesriegler.xvsm.spacehelpers.SpaceListener;
7 import org.mozartspaces.core.MzsConstants.RequestTimeout;
8 import org.mozartspaces.core.MzsCoreException;
9 import org.mozartspaces.core.TransactionReference;
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
13 import java.io.Serializable;
15 import java.util.Arrays;
16 import java.util.Collections;
17 import java.util.List;
19 public class CookXVSM extends AbstractXVSMConnector {
20 private static final Logger log = LoggerFactory.getLogger(CookXVSM.class);
24 public CookXVSM(int id, int port) {
28 orderTakenContainer = useContainer(Util.ORDER_TAKEN);
29 deliveryOrderTakenContainer = useContainer(Util.DELIVERY_ORDER_TAKEN);
30 preparedPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
31 preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
32 prepareDeliveryPizzasContainer = useContainer(Util.PREPARE_DELIVERY_PIZZAS);
33 pizzaInProgressContainer = useContainer(Util.PIZZAS_IN_PROGRESS);
34 preparedDeliveryPizzasContainer = useContainer(Util.DELIVER_DELIVERY_PIZZAS);
35 pizzeriaGroupContainer = useContainer(Util.PIZZERIA_GROUP);
36 pizzeriaDeliveryContainer = useContainer(Util.PIZZERIA_DELIVERY);
39 public void listenForPizzas() {
40 getDefaultBuilder().setLookaround(true).setCref(preparePizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
43 public void onEntriesWritten(List<? extends Serializable> entries)
46 List<PizzaOrder> pizzas = castEntries(entries);
48 if (inNotification.get()) Collections.shuffle(pizzas);
50 for (PizzaOrder pizzaOrder : pizzas) {
52 TransactionReference tx = capi.createTransaction(9000, URI.create(String.format(Util.SERVER_ADDR, port)));
53 String pizzaAlreadyCooked = String.format("Pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
56 if (!mayPreparePizza(pizzaOrder, tx)) {
57 capi.rollbackTransaction(tx);
61 // Require the lock for preparing the pizza
62 PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), preparePizzasContainer, tx, RequestTimeout.ZERO, pizzaAlreadyCooked);
65 // tell the space that you prepare the pizza -> without a transaction!!
66 Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
67 pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
70 log.debug("I say that I now prepare a pizza for order {}", pizzaInProgress.getOrderId());
71 sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, null);
73 PizzaOrder pizza = createPizza(order);
75 sendItemsToContainer(Arrays.asList(pizza), preparedPizzasContainer, RequestTimeout.DEFAULT, tx);
76 final GroupData group = new GroupData();
77 final Order groupOrder = new Order();
78 groupOrder.setId(pizza.getOrderId());
79 group.setOrder(groupOrder);
80 group.setState(GroupState.ORDERED);
81 GroupData groupData = takeMatchingEntity(group, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT, "Cannot take the group from pizzeriaGroupContainer");
82 final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
83 for (PizzaOrder orderedPizza : orderedPizzas) {
84 if (orderedPizza.getId() == pizza.getId()) {
85 orderedPizza.setStatus(PizzaOrderStatus.DONE);
86 orderedPizza.setCookId(pizza.getCookId());
89 sendItemsToContainer(Arrays.asList(groupData), pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
90 capi.commitTransaction(tx);
91 log.debug("I have completed preparing a pizza for order {}!", pizza.getOrderId());
92 } catch (NullPointerException e) {
93 // the strange nullpointer exception from the space
94 } catch (Exception e) {
95 log.info(e.getMessage());
100 }).createSpaceListenerImpl();
105 * A cook may prepare a pizza if there is no current delivery order or if at least a pizza of the same order is
106 * in preparation or has been done!
108 private boolean mayPreparePizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
109 List<PizzaOrder> deliveryPizzas = readMatchingEntities(new PizzaOrder(), prepareDeliveryPizzasContainer, tx, RequestTimeout.ZERO, "MAYPREPAREPIZZA: Cannot access prepareDeliveryPizzasContainer");
110 if (!deliveryPizzas.isEmpty()) {
111 final PizzaOrder template = new PizzaOrder();
112 template.setOrderId(pizzaOrder.getOrderId());
113 final List<PizzaOrder> pizzasOfOrderInProgress = readMatchingEntities(template, pizzaInProgressContainer, tx, RequestTimeout.ZERO, "MAYPREPAREPIZZA:: Cannot access pizzaInProgressContainer");
114 if (pizzasOfOrderInProgress.isEmpty()) return false;
115 final List<PizzaOrder> pizzasAlreadyDone = readMatchingEntities(template, preparedPizzasContainer, tx, RequestTimeout.ZERO, "MAYPREPAREPIZZA: Cannot access preparedPizzasContainer");
116 if(pizzasAlreadyDone.isEmpty()) return false;
122 public void listenForDeliveryPizzas() {
123 SpaceListener pizzasListener = getDefaultBuilder().setLookaround(true).setCref(prepareDeliveryPizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
126 public void onEntriesWritten(List<? extends Serializable> entries)
129 List<PizzaOrder> pizzas = castEntries(entries);
131 if (inNotification.get()) Collections.shuffle(pizzas);
133 for (PizzaOrder pizzaOrder : pizzas) {
135 TransactionReference tx = capi.createTransaction(9000, URI.create(String.format(Util.SERVER_ADDR, port)));
136 String pizzaAlreadyCooked = String.format("Pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
139 // Require the lock for preparing the pizza
140 PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), prepareDeliveryPizzasContainer, tx, RequestTimeout.ZERO, pizzaAlreadyCooked);
142 // tell the space that you prepare the pizza -> without a transaction!!
143 Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
144 pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
147 log.info("I say that I now prepare a pizza for order {}", pizzaInProgress.getOrderId());
148 sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, null);
150 PizzaOrder pizza = createPizza(order);
152 sendItemsToContainer(Arrays.asList(pizza), preparedDeliveryPizzasContainer, RequestTimeout.DEFAULT, tx);
154 final DeliveryGroupData group = new DeliveryGroupData();
155 final Order groupOrder = new Order();
156 groupOrder.setId(pizza.getOrderId());
157 group.setOrder(groupOrder);
158 group.setDeliveryStatus(null);
159 DeliveryGroupData groupData = takeMatchingEntity(group, pizzeriaDeliveryContainer, tx, RequestTimeout.DEFAULT, "Cannot take the delivery order from pizzeriaDeliveryContainer");
160 final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
161 for (PizzaOrder orderedPizza : orderedPizzas) {
162 if (orderedPizza.getId() == pizza.getId()) {
163 orderedPizza.setStatus(PizzaOrderStatus.DONE);
164 orderedPizza.setCookId(pizza.getCookId());
167 sendItemsToContainer(Arrays.asList(groupData), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, tx);
169 capi.commitTransaction(tx);
170 log.info("I have completed preparing a delivery pizza for order {}!", pizza.getOrderId());
171 } catch (NullPointerException e) {
172 // the strange nullpointer exception from the space
173 } catch (Exception e) {
174 log.info(e.getMessage());
179 }).createSpaceListenerImpl();
183 private PizzaOrder createPizza(PizzaOrder order) throws InterruptedException {
184 long duration = order.getPizzaType().duration;
185 Thread.sleep(duration * 1000);
187 PizzaOrder pizza = Pizza.createPizzaFromPizzaOrder(order, cookId, false);
188 pizza.setStatus(PizzaOrderStatus.DONE);