1 package at.ac.tuwien.sbc.valesriegler.xvsm;
3 import java.io.Serializable;
5 import java.util.Arrays;
6 import java.util.Collections;
9 import at.ac.tuwien.sbc.valesriegler.types.*;
10 import org.mozartspaces.capi3.FifoCoordinator;
11 import org.mozartspaces.core.ContainerReference;
12 import org.mozartspaces.core.MzsConstants;
13 import org.mozartspaces.core.MzsConstants.RequestTimeout;
14 import org.mozartspaces.core.MzsCoreException;
15 import org.mozartspaces.core.TransactionReference;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
19 import at.ac.tuwien.sbc.valesriegler.common.Util;
21 public class CookXVSM extends AbstractXVSMConnector {
22 private static final Logger log = LoggerFactory.getLogger(CookXVSM.class);
26 public CookXVSM(int id, int port) {
30 orderTakenContainer = useContainer(Util.ORDER_TAKEN);
31 deliveryOrderTakenContainer = useContainer(Util.DELIVERY_ORDER_TAKEN);
32 preparedPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
33 preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
34 prepareDeliveryPizzasContainer = useContainer(Util.PREPARE_DELIVERY_PIZZAS);
35 pizzaInProgressContainer = useContainer(Util.PIZZAS_IN_PROGRESS) ;
36 preparedDeliveryPizzasContainer = useContainer(Util.DELIVER_DELIVERY_PIZZAS);
39 public void listenForPizzas() {
40 SpaceListener pizzasListener = new SpaceListenerImpl(capi, preparePizzasContainer, 15000) {
43 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.info("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 final ContainerReference container = preparedPizzasContainer;
76 sendItemsToContainer(Arrays.asList(pizza), container, RequestTimeout.DEFAULT, tx);
78 capi.commitTransaction(tx);
79 log.info("I have completed preparing a pizza for order {}!", pizza.getOrderId());
80 } catch (NullPointerException e) {
81 // the strange nullpointer exception from the space
82 } catch (Exception e) {
83 log.info(e.getMessage());
90 List<? extends Serializable> getEntries() throws Exception {
91 return capi.read(preparePizzasContainer, FifoCoordinator
92 .newSelector(MzsConstants.Selecting.COUNT_ALL),
93 RequestTimeout.DEFAULT, null);
96 createNotification(pizzasListener, preparePizzasContainer);
101 * A cook may prepare a pizza if there is no current delivery order or if at least a pizza of the same order is
104 private boolean mayPreparePizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
105 List<PizzaOrder> deliveryPizzas = readMatchingEntities(new PizzaOrder(), prepareDeliveryPizzasContainer, tx, RequestTimeout.ZERO, "BBBBBB");
106 if (! deliveryPizzas.isEmpty()) {
107 final PizzaOrder template = new PizzaOrder();
108 template.setOrderId(pizzaOrder.getOrderId());
109 final List<PizzaOrder> pizzasOfOrderInProgress = readMatchingEntities(template, pizzaInProgressContainer, tx, RequestTimeout.ZERO, "ASDF");
110 if(pizzasOfOrderInProgress.isEmpty()) return false;
116 public void listenForDeliveryPizzas() {
117 SpaceListener pizzasListener = new SpaceListenerImpl(capi, prepareDeliveryPizzasContainer, 15000) {
120 void onEntriesWritten(List<? extends Serializable> entries)
123 List<PizzaOrder> pizzas = castEntries(entries);
125 if(inNotification.get()) Collections.shuffle(pizzas);
127 for (PizzaOrder pizzaOrder : pizzas) {
129 TransactionReference tx = capi.createTransaction(9000, URI.create(String.format(Util.SERVER_ADDR, port)));
130 String pizzaAlreadyCooked = String.format("Pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
133 // Require the lock for preparing the pizza
134 PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), prepareDeliveryPizzasContainer, tx, RequestTimeout.ZERO, pizzaAlreadyCooked);
136 // tell the space that you prepare the pizza -> without a transaction!!
137 Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
138 pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
141 log.info("I say that I now prepare a pizza for order {}", pizzaInProgress.getOrderId());
142 sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, null);
144 PizzaOrder pizza = createPizza(order);
146 final ContainerReference container = preparedDeliveryPizzasContainer;
147 sendItemsToContainer(Arrays.asList(pizza), container, RequestTimeout.DEFAULT, tx);
149 capi.commitTransaction(tx);
150 log.info("I have completed preparing a delivery pizza for order {}!", pizza.getOrderId());
151 } catch (NullPointerException e) {
152 // the strange nullpointer exception from the space
153 } catch (Exception e) {
154 log.info(e.getMessage());
161 List<? extends Serializable> getEntries() throws Exception {
162 return capi.read(prepareDeliveryPizzasContainer, FifoCoordinator
163 .newSelector(MzsConstants.Selecting.COUNT_ALL),
164 RequestTimeout.DEFAULT, null);
167 createNotification(pizzasListener, prepareDeliveryPizzasContainer);
171 private PizzaOrder createPizza(PizzaOrder order) throws InterruptedException {
172 long duration = order.getPizzaType().duration;
173 Thread.sleep(duration * 1000);
175 PizzaOrder pizza = Pizza.createPizzaFromPizzaOrder(order, cookId, false);
176 pizza.setStatus(PizzaOrderStatus.DONE);