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 org.mozartspaces.core.MzsConstants.RequestTimeout;
7 import org.mozartspaces.core.MzsCoreException;
8 import org.mozartspaces.core.TransactionReference;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
12 import java.io.Serializable;
14 import java.util.Arrays;
15 import java.util.Collections;
16 import java.util.List;
18 public class CookXVSM extends AbstractXVSMConnector {
19 private static final Logger log = LoggerFactory.getLogger(CookXVSM.class);
23 public CookXVSM(int id, int port) {
27 orderTakenContainer = useContainer(Util.ORDER_TAKEN);
28 deliveryOrderTakenContainer = useContainer(Util.DELIVERY_ORDER_TAKEN);
29 preparedPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
30 preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
31 prepareDeliveryPizzasContainer = useContainer(Util.PREPARE_DELIVERY_PIZZAS);
32 pizzaInProgressContainer = useContainer(Util.PIZZAS_IN_PROGRESS);
33 preparedDeliveryPizzasContainer = useContainer(Util.DELIVER_DELIVERY_PIZZAS);
34 pizzeriaGroupContainer = useContainer(Util.PIZZERIA_GROUP);
35 pizzeriaDeliveryContainer = useContainer(Util.PIZZERIA_DELIVERY);
38 public void listenForPizzas() {
39 getDefaultBuilder("").setLookaround(true).setCref(preparePizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
42 public void onEntriesWritten(List<? extends Serializable> entries)
45 List<PizzaOrder> pizzas = castEntries(entries);
47 if (inNotification.get()) Collections.shuffle(pizzas);
49 for (PizzaOrder pizzaOrder : pizzas) {
51 TransactionReference tx = capi.createTransaction(9000, URI.create(String.format(Util.SERVER_ADDR, port)));
52 String pizzaAlreadyCooked = String.format("Normal pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
55 if (!mayPrepareCustomerPizza(pizzaOrder, tx)) {
56 capi.rollbackTransaction(tx);
60 // Require the lock for preparing the pizza
61 PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), preparePizzasContainer, tx, RequestTimeout.ZERO, pizzaAlreadyCooked);
63 // tell the space that you prepare the pizza -> without a transaction!!
64 Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
65 pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
67 notifyCustomerPizzaInProgress(order, pizzaInProgress);
69 PizzaOrder pizza = createPizza(order);
71 notifyCustomerPizzaDone(pizza, tx);
72 capi.commitTransaction(tx);
73 log.debug("I have completed preparing a pizza for order {}!", pizza.getOrderId());
74 } catch (NullPointerException e) {
75 // the strange nullpointer exception from the space
76 } catch (EntityNotFoundByTemplate e) {
77 log.info("entitynotfound: {}", e.getMessage());
78 } catch (Exception e) {
79 log.error("outer cook");
80 log.error(e.getMessage());
85 }).createSpaceListenerImpl();
89 public void listenForDeliveryPizzas() {
90 getDefaultBuilder("").setLookaround(true).setCref(prepareDeliveryPizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
93 public void onEntriesWritten(List<? extends Serializable> entries)
96 List<PizzaOrder> pizzas = castEntries(entries);
98 if (inNotification.get()) Collections.shuffle(pizzas);
100 for (PizzaOrder pizzaOrder : pizzas) {
102 TransactionReference tx = capi.createTransaction(12000, URI.create(String.format(Util.SERVER_ADDR, port)));
103 String pizzaAlreadyCooked = String.format("Delivery Pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
106 if (!mayPrepareDeliveryPizza(tx)) {
107 capi.rollbackTransaction(tx);
111 // Require the lock for preparing the pizza
112 PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), prepareDeliveryPizzasContainer, tx, RequestTimeout.ZERO, pizzaAlreadyCooked);
114 // tell the space that you prepare the pizza -> without a transaction!!
115 Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
116 pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
118 notifyDeliveryPizzaInProgress(order, pizzaInProgress);
120 log.debug("before creating!");
122 PizzaOrder pizza = createPizza(order);
124 log.debug("after creating!");
126 sendItemsToContainer(Arrays.asList(pizza), preparedDeliveryPizzasContainer, RequestTimeout.DEFAULT, tx);
128 log.debug("after prepareddeliverypizzascon");
130 notifyDeliveryPizzaDone(pizza, tx);
132 log.debug("after notifydone");
134 capi.commitTransaction(tx);
135 log.debug("I have completed preparing a delivery pizza for order {}!", pizza.getOrderId());
136 } catch (NullPointerException e) {
137 // the strange nullpointer exception from the space
138 } catch (EntityNotFoundByTemplate e) {
139 log.info("entitynotfound: {}", e.getMessage());
141 } catch (Exception e) {
142 log.error("outer cook");
143 log.error(e.getMessage());
148 }).createSpaceListenerImpl();
153 * A cook may prepare a pizza if there is no current delivery order or if at least a pizza of the same order is
154 * in preparation or has been done!
156 private boolean mayPrepareCustomerPizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
157 List<PizzaOrder> deliveryPizzas = readMatchingEntities(new PizzaOrder(), prepareDeliveryPizzasContainer, tx, RequestTimeout.DEFAULT, "MAYPREPAREPIZZA: Cannot access prepareDeliveryPizzasContainer");
158 if (!deliveryPizzas.isEmpty()) {
159 final PizzaOrder template = new PizzaOrder();
160 template.setOrderId(pizzaOrder.getOrderId());
161 final List<PizzaOrder> pizzasAlreadyDone = readMatchingEntities(template, preparedPizzasContainer, tx, RequestTimeout.DEFAULT, "MAYPREPAREPIZZA: Cannot access preparedPizzasContainer");
162 if(! pizzasAlreadyDone.isEmpty()) return true;
163 final List<PizzaOrder> pizzasOfOrderInProgress = readMatchingEntities(template, pizzaInProgressContainer, tx, RequestTimeout.DEFAULT, "MAYPREPAREPIZZA:: Cannot access pizzaInProgressContainer");
164 if (! pizzasOfOrderInProgress.isEmpty()) return true;
172 private boolean mayPrepareDeliveryPizza(TransactionReference tx) throws MzsCoreException {
173 final PizzaOrder template = new PizzaOrder();
174 template.setDeliveryPizza(false);
175 final List<PizzaOrder> preparedNonDeliveryPizzas = readMatchingEntities(template, preparedPizzasContainer, tx, RequestTimeout.DEFAULT, "mayPrepareDeliveryPizza: cannot access preparedPizzasContainer");
176 if(! preparedNonDeliveryPizzas.isEmpty()) return false;
177 final List<PizzaOrder> nonDeliveryPizzasInProgress = readMatchingEntities(template, pizzaInProgressContainer, tx, RequestTimeout.DEFAULT, "mayPrepareDeliveryPizza: cannot access pizzaInProgressContainer");
178 if (! nonDeliveryPizzasInProgress.isEmpty()) return false;
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.DEFAULT, "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.debug("before inprogress comit!");
237 capi.commitTransaction(inPreparationTx);
240 private void notifyCustomerPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) {
242 log.debug("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, 100, "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.ZERO, inPreparationTx);
258 sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.ZERO, 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);