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).enableCountAll().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("Normal pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
56 if (!mayPrepareCustomerPizza(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.DEFAULT, 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);
69 notifyCustomerPizzaInProgress(order, pizzaInProgress);
71 PizzaOrder pizza = createPizza(order);
73 notifyCustomerPizzaDone(pizza, tx);
74 capi.commitTransaction(tx);
75 log.debug("I have completed preparing a pizza for order {}!", pizza.getOrderId());
76 } catch (NullPointerException e) {
77 // the strange nullpointer exception from the space
78 } catch (EntityNotFoundByTemplate e) {
79 log.info("entitynotfound: {}", e.getMessage());
80 } catch (Exception e) {
81 log.info("outer cook");
82 log.info(e.getMessage());
88 }).createSpaceListenerImpl();
92 public void listenForDeliveryPizzas() {
93 SpaceListener pizzasListener = getDefaultBuilder().setLookaround(true).setCref(prepareDeliveryPizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
96 public void onEntriesWritten(List<? extends Serializable> entries)
99 List<PizzaOrder> pizzas = castEntries(entries);
101 if (inNotification.get() || Util.runSimulation) Collections.shuffle(pizzas);
103 for (PizzaOrder pizzaOrder : pizzas) {
105 TransactionReference tx = capi.createTransaction(12000, URI.create(String.format(Util.SERVER_ADDR, port)));
106 String pizzaAlreadyCooked = String.format("Delivery Pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
109 if (!mayPrepareDeliveryPizza(pizzaOrder, tx)) {
110 capi.rollbackTransaction(tx);
114 // Require the lock for preparing the pizza
115 PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), prepareDeliveryPizzasContainer, tx, RequestTimeout.DEFAULT, pizzaAlreadyCooked);
117 // tell the space that you prepare the pizza -> without a transaction!!
118 Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
119 pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
121 if (! Util.runSimulation) {
122 notifyDeliveryPizzaInProgress(order, pizzaInProgress);
125 // log.info("before creating!");
127 PizzaOrder pizza = createPizza(order);
129 // log.info("after creating!");
131 sendItemsToContainer(Arrays.asList(pizza), preparedDeliveryPizzasContainer, RequestTimeout.DEFAULT, tx);
133 // log.info("after prepareddeliverypizzascon");
135 notifyDeliveryPizzaDone(pizza, tx);
137 // log.info("after notifydone");
139 capi.commitTransaction(tx);
140 log.info("I have completed preparing a delivery pizza for order {}!", pizza.getOrderId());
141 } catch (NullPointerException e) {
142 // the strange nullpointer exception from the space
143 } catch (EntityNotFoundByTemplate e) {
144 log.info("entitynotfound: {}", e.getMessage());
146 } catch (Exception e) {
147 log.info("outer cook");
148 log.info(e.getMessage());
154 }).createSpaceListenerImpl();
159 * A cook may prepare a pizza if there is no current delivery order or if at least a pizza of the same order is
160 * in preparation or has been done!
162 private boolean mayPrepareCustomerPizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
163 List<PizzaOrder> deliveryPizzas = readMatchingEntities(new PizzaOrder(), prepareDeliveryPizzasContainer, tx, RequestTimeout.INFINITE, "MAYPREPAREPIZZA: Cannot access prepareDeliveryPizzasContainer");
164 if (!deliveryPizzas.isEmpty()) {
165 final PizzaOrder template = new PizzaOrder();
166 template.setOrderId(pizzaOrder.getOrderId());
167 final List<PizzaOrder> pizzasAlreadyDone = readMatchingEntities(template, preparedPizzasContainer, tx, RequestTimeout.INFINITE, "MAYPREPAREPIZZA: Cannot access preparedPizzasContainer");
168 if(! pizzasAlreadyDone.isEmpty()) return true;
169 final List<PizzaOrder> pizzasOfOrderInProgress = readMatchingEntities(template, pizzaInProgressContainer, tx, RequestTimeout.INFINITE, "MAYPREPAREPIZZA:: Cannot access pizzaInProgressContainer");
170 if (! pizzasOfOrderInProgress.isEmpty()) return true;
178 private boolean mayPrepareDeliveryPizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
179 // TODO: return false if a cook has already started cooking pizzas of an open order
183 private void notifyCustomerPizzaDone(PizzaOrder pizza, TransactionReference tx) throws MzsCoreException {
184 sendItemsToContainer(Arrays.asList(pizza), preparedPizzasContainer, RequestTimeout.DEFAULT, tx);
185 final GroupData group = new GroupData();
186 final Order groupOrder = new Order();
187 groupOrder.setId(pizza.getOrderId());
188 group.setOrder(groupOrder);
189 group.setState(GroupState.ORDERED);
190 GroupData groupData = takeMatchingEntity(group, pizzeriaGroupContainer, tx, RequestTimeout.INFINITE, "Cannot take the group from pizzeriaGroupContainer");
191 final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
192 for (PizzaOrder orderedPizza : orderedPizzas) {
193 if (orderedPizza.getId() == pizza.getId()) {
194 orderedPizza.setStatus(PizzaOrderStatus.DONE);
195 orderedPizza.setCookId(pizza.getCookId());
198 sendItemsToContainer(Arrays.asList(groupData), pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
201 private void notifyDeliveryPizzaDone(PizzaOrder pizza, TransactionReference tx) throws MzsCoreException {
202 final DeliveryGroupData group = new DeliveryGroupData();
203 final Order groupOrder = new Order();
204 groupOrder.setId(pizza.getOrderId());
205 group.setOrder(groupOrder);
206 group.setDeliveryStatus(null);
207 DeliveryGroupData groupData = takeMatchingEntity(group, pizzeriaDeliveryContainer, tx, RequestTimeout.INFINITE, "Cannot take the delivery order from pizzeriaDeliveryContainer");
208 final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
209 for (PizzaOrder orderedPizza : orderedPizzas) {
210 if (orderedPizza.getId() == pizza.getId()) {
211 orderedPizza.setStatus(PizzaOrderStatus.DONE);
212 orderedPizza.setCookId(pizza.getCookId());
215 sendItemsToContainer(Arrays.asList(groupData), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, tx);
218 private void notifyDeliveryPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) throws MzsCoreException {
219 log.info("I say that I now prepare a delivery pizza for order {}", pizzaInProgress.getOrderId());
220 final DeliveryGroupData groupTemplate = new DeliveryGroupData();
221 final Order groupOrder = new Order();
222 groupOrder.setId(order.getOrderId());
223 groupTemplate.setOrder(groupOrder);
224 groupTemplate.setDeliveryStatus(null);
225 final TransactionReference inPreparationTx = getDefaultTransaction();
226 final DeliveryGroupData groupFromSpace = takeMatchingEntity(groupTemplate, pizzeriaDeliveryContainer, inPreparationTx, RequestTimeout.INFINITE, "Cannot take the delivery order from pizzeriaDeliveryContainer");
227 final List<PizzaOrder> orderedPizzas = groupFromSpace.getOrder().getOrderedPizzas();
228 for (PizzaOrder orderedPizza : orderedPizzas) {
229 if (orderedPizza.getId() == pizzaInProgress.getId()) {
230 orderedPizza.setStatus(PizzaOrderStatus.IN_PREPARATION);
231 orderedPizza.setCookId(pizzaInProgress.getCookId());
234 sendItemsToContainer(Arrays.asList(groupFromSpace), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, inPreparationTx);
235 sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, inPreparationTx);
236 log.info("before inprogress comit!");
237 capi.commitTransaction(inPreparationTx);
240 private void notifyCustomerPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) {
242 log.info("I say that I now prepare a pizza for order {}", pizzaInProgress.getOrderId());
243 final GroupData groupTemplate = new GroupData();
244 final Order groupOrder = new Order();
245 groupOrder.setId(order.getOrderId());
246 groupTemplate.setOrder(groupOrder);
247 groupTemplate.setState(null);
248 final TransactionReference inPreparationTx = getDefaultTransaction();
249 final GroupData groupFromSpace = takeMatchingEntity(groupTemplate, pizzeriaGroupContainer, inPreparationTx, RequestTimeout.INFINITE, "Cannot take the order from pizzeriaGroupContainer");
250 final List<PizzaOrder> orderedPizzas = groupFromSpace.getOrder().getOrderedPizzas();
251 for (PizzaOrder orderedPizza : orderedPizzas) {
252 if (orderedPizza.getId() == pizzaInProgress.getId()) {
253 orderedPizza.setStatus(PizzaOrderStatus.IN_PREPARATION);
254 orderedPizza.setCookId(pizzaInProgress.getCookId());
257 sendItemsToContainer(Arrays.asList(groupFromSpace), pizzeriaGroupContainer, RequestTimeout.DEFAULT, inPreparationTx);
258 sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, inPreparationTx);
259 capi.commitTransaction(inPreparationTx);
260 } catch (Exception e) {
261 log.error("This error has occurred: {}", e.getMessage());
266 private PizzaOrder createPizza(PizzaOrder order) throws InterruptedException {
267 long duration = order.getPizzaType().duration;
268 if (! Util.runSimulation) {
269 Thread.sleep(duration * 1000);
272 PizzaOrder pizza = Pizza.createPizzaFromPizzaOrder(order, cookId, false);
273 pizza.setStatus(PizzaOrderStatus.DONE);