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.capi3.EntryLockedException;
7 import org.mozartspaces.core.MzsConstants;
8 import org.mozartspaces.core.MzsConstants.RequestTimeout;
9 import org.mozartspaces.core.MzsCoreException;
10 import org.mozartspaces.core.RequestContext;
11 import org.mozartspaces.core.TransactionReference;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
15 import java.io.Serializable;
17 import java.util.Arrays;
18 import java.util.Collections;
19 import java.util.List;
21 public class CookXVSM extends AbstractXVSMConnector {
22 private static final Logger log = LoggerFactory.getLogger(CookXVSM.class);
25 public CookXVSM(int id, int port) {
29 orderTakenContainer = useContainer(Util.ORDER_TAKEN);
30 deliveryOrderTakenContainer = useContainer(Util.DELIVERY_ORDER_TAKEN);
31 preparedPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
32 preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
33 prepareDeliveryPizzasContainer = useContainer(Util.PREPARE_DELIVERY_PIZZAS);
34 pizzaInProgressContainer = useContainer(Util.PIZZAS_IN_PROGRESS);
35 preparedDeliveryPizzasContainer = useContainer(Util.DELIVER_DELIVERY_PIZZAS);
36 pizzeriaGroupContainer = useContainer(Util.PIZZERIA_GROUP);
37 pizzeriaDeliveryContainer = useContainer(Util.PIZZERIA_DELIVERY);
40 public void listenForPizzas() {
41 getDefaultBuilder("listenForNormalPizzas").setLookaround(true).setCref(preparePizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
44 public void onEntriesWritten(List<? extends Serializable> entries)
47 List<PizzaOrder> pizzas = castEntries(entries);
49 sortOrShufflePizzas(pizzas, inNotification.get());
51 for (PizzaOrder pizzaOrder : pizzas) {
53 TransactionReference tx = capi.createTransaction(9000, URI.create(String.format(Util.SERVER_ADDR, port)));
54 String pizzaAlreadyCooked = String.format("Normal pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
57 if (!mayPrepareCustomerPizza(pizzaOrder, tx)) {
58 capi.rollbackTransaction(tx);
62 // Require the lock for preparing the pizza
63 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);
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 (EntryLockedException e) {
81 capi.rollbackTransaction(tx);
82 } catch (Exception e) {
83 log.error("outer cook");
84 log.error(e.getMessage());
89 }).createSpaceListenerImpl();
93 private void sortOrShufflePizzas(List<PizzaOrder> pizzas, boolean notification) {
94 if (notification) Collections.shuffle(pizzas);
96 Collections.sort(pizzas);
100 public void listenForDeliveryPizzas() {
101 getDefaultBuilder("listenForDeliveryPizzas").setLookaround(true).setCref(prepareDeliveryPizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
104 public void onEntriesWritten(List<? extends Serializable> entries)
107 List<PizzaOrder> pizzas = castEntries(entries);
109 sortOrShufflePizzas(pizzas, inNotification.get());
111 for (PizzaOrder pizzaOrder : pizzas) {
113 final RequestContext requestContext = new RequestContext();
114 TransactionReference tx = capi.createTransaction(12000, URI.create(String.format(Util.SERVER_ADDR, port)));
115 String pizzaAlreadyCooked = String.format("Delivery Pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
118 if (!mayPrepareDeliveryPizza(tx, pizzaOrder)) {
119 capi.rollbackTransaction(tx);
123 // Require the lock for preparing the pizza
124 PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), prepareDeliveryPizzasContainer, tx, RequestTimeout.ZERO, pizzaAlreadyCooked);
126 // tell the space that you prepare the pizza -> without a transaction!!
127 Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
128 pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
130 notifyDeliveryPizzaInProgress(order, pizzaInProgress);
132 log.debug("before creating!");
134 PizzaOrder pizza = createPizza(order);
136 log.debug("after creating!");
139 log.debug("after prepareddeliverypizzascon");
141 notifyDeliveryPizzaDone(pizza, tx);
143 log.debug("after notifydone");
145 capi.commitTransaction(tx);
146 log.debug("I have completed preparing a delivery pizza for order {}!", pizza.getOrderId());
147 } catch (NullPointerException e) {
148 // the strange nullpointer exception from the space
149 } catch (EntityNotFoundByTemplate e) {
150 log.info("entitynotfound: {}", e.getMessage());
151 } catch (EntryLockedException e) {
152 capi.rollbackTransaction(tx);
153 } catch (Exception e) {
154 log.error("outer cook");
155 log.error(e.getMessage());
160 }).createSpaceListenerImpl();
165 * A cook may prepare a pizza if there is no current delivery order or if at least a pizza of the same order is
166 * in preparation or has been done!
168 private boolean mayPrepareCustomerPizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
169 boolean mayPrepare = false;
171 List<PizzaOrder> deliveryPizzas = readMatchingEntities(new PizzaOrder(), prepareDeliveryPizzasContainer, tx, RequestTimeout.DEFAULT, "mayPrepareCustomerPizza: Cannot access prepareDeliveryPizzasContainer", MzsConstants.Selecting.COUNT_MAX);
172 if (!deliveryPizzas.isEmpty()) {
173 Pizza pizza = new Pizza();
174 pizza.setIdOfOrder(pizzaOrder.getOrderId());
175 final List<Pizza> pizzasAlreadyDone = readMatchingEntities(pizza, preparedPizzasContainer, tx, RequestTimeout.DEFAULT, "mayPrepareCustomerPizza: Cannot access preparedPizzasContainer", MzsConstants.Selecting.COUNT_MAX);
176 if(! pizzasAlreadyDone.isEmpty()) mayPrepare = true;
178 final List<Pizza> pizzasOfOrderInProgress = readMatchingEntities(pizza, pizzaInProgressContainer, tx, RequestTimeout.DEFAULT, "mayPrepareCustomerPizza: Cannot access pizzaInProgressContainer", MzsConstants.Selecting.COUNT_MAX);
179 if (! pizzasOfOrderInProgress.isEmpty()) mayPrepare = true;
180 else mayPrepare = false;
183 else mayPrepare = true;
184 log.warn("Cook may prepare Customer pizza: {} for order {}", mayPrepare, pizzaOrder.getOrderId());
190 * A cook may prepare a delivery pizza if no customer group order is open
192 private boolean mayPrepareDeliveryPizza(TransactionReference tx, PizzaOrder pizzaOrder) throws MzsCoreException {
193 boolean mayPrepare = false;
195 Pizza pizza = new Pizza();
196 pizza.setDeliveryPizza(false);
197 final List<Pizza> preparedNonDeliveryPizzas = readMatchingEntities(pizza, preparedPizzasContainer, tx, RequestTimeout.DEFAULT, "mayPrepareDeliveryPizza: cannot access preparedPizzasContainer", MzsConstants.Selecting.COUNT_MAX);
198 if(! preparedNonDeliveryPizzas.isEmpty()) {
199 log.warn("PreparedNonDeliveryPizzas NOT empty!");
203 final List<Pizza> nonDeliveryPizzasInProgress = readMatchingEntities(pizza, pizzaInProgressContainer, tx, RequestTimeout.DEFAULT, "mayPrepareDeliveryPizza: cannot access pizzaInProgressContainer", MzsConstants.Selecting.COUNT_MAX);
204 if (! nonDeliveryPizzasInProgress.isEmpty()) mayPrepare = false;
205 else mayPrepare = true;
207 log.warn("Cook may prepare Delivery pizza: {} for order {}", mayPrepare, pizzaOrder.getOrderId());
211 private void notifyCustomerPizzaDone(PizzaOrder pizza, TransactionReference tx) throws MzsCoreException {
212 sendItemsToContainer(Arrays.asList(pizza), preparedPizzasContainer, RequestTimeout.DEFAULT, tx);
213 final GroupData group = new GroupData();
214 final Order groupOrder = new Order();
215 groupOrder.setId(pizza.getOrderId());
216 group.setOrder(groupOrder);
217 group.setState(GroupState.ORDERED);
218 GroupData groupData = takeMatchingEntity(group, pizzeriaGroupContainer, tx, RequestTimeout.INFINITE, "Cannot take the group from pizzeriaGroupContainer");
219 final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
220 for (PizzaOrder orderedPizza : orderedPizzas) {
221 if (orderedPizza.getId() == pizza.getId()) {
222 orderedPizza.setStatus(PizzaOrderStatus.DONE);
223 orderedPizza.setCookId(pizza.getCookId());
226 sendItemsToContainer(Arrays.asList(groupData), pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
229 private void notifyDeliveryPizzaDone(PizzaOrder pizza, TransactionReference tx) throws MzsCoreException {
230 sendItemsToContainer(Arrays.asList(pizza), preparedDeliveryPizzasContainer, RequestTimeout.DEFAULT, tx);
231 final DeliveryGroupData group = new DeliveryGroupData();
232 final Order groupOrder = new Order();
233 groupOrder.setId(pizza.getOrderId());
234 group.setOrder(groupOrder);
235 group.setDeliveryStatus(null);
236 DeliveryGroupData groupData = takeMatchingEntity(group, pizzeriaDeliveryContainer, tx, RequestTimeout.INFINITE, "Cannot take the delivery order from pizzeriaDeliveryContainer");
237 final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
238 for (PizzaOrder orderedPizza : orderedPizzas) {
239 if (orderedPizza.getId() == pizza.getId()) {
240 orderedPizza.setStatus(PizzaOrderStatus.DONE);
241 orderedPizza.setCookId(pizza.getCookId());
244 sendItemsToContainer(Arrays.asList(groupData), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, tx);
247 private void notifyDeliveryPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) throws MzsCoreException {
249 log.info("I say that I now prepare a delivery pizza for order {}", pizzaInProgress.getOrderId());
250 final DeliveryGroupData groupTemplate = new DeliveryGroupData();
251 final Order groupOrder = new Order();
252 groupOrder.setId(order.getOrderId());
253 groupTemplate.setOrder(groupOrder);
254 groupTemplate.setDeliveryStatus(null);
255 final TransactionReference inPreparationTx = getDefaultTransaction();
256 final DeliveryGroupData groupFromSpace = takeMatchingEntity(groupTemplate, pizzeriaDeliveryContainer, inPreparationTx, RequestTimeout.DEFAULT, "Cannot take the delivery order from pizzeriaDeliveryContainer");
257 final List<PizzaOrder> orderedPizzas = groupFromSpace.getOrder().getOrderedPizzas();
258 for (PizzaOrder orderedPizza : orderedPizzas) {
259 if (orderedPizza.getId() == pizzaInProgress.getId()) {
260 orderedPizza.setStatus(PizzaOrderStatus.IN_PREPARATION);
261 orderedPizza.setCookId(pizzaInProgress.getCookId());
264 sendItemsToContainer(Arrays.asList(groupFromSpace), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, inPreparationTx);
265 sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, inPreparationTx);
266 log.debug("before inprogress comit!");
267 capi.commitTransaction(inPreparationTx);
268 } catch(NullPointerException e) {
269 } catch (Exception e) {
270 log.error("notifyDeliveryPizzaInProgress: {}", e.getMessage());
275 private void notifyCustomerPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) {
277 log.info("I say that I now prepare a pizza for order {}", pizzaInProgress.getOrderId());
278 final GroupData groupTemplate = new GroupData();
279 final Order groupOrder = new Order();
280 groupOrder.setId(order.getOrderId());
281 groupTemplate.setOrder(groupOrder);
282 groupTemplate.setState(null);
283 final TransactionReference inPreparationTx = getDefaultTransaction();
284 final GroupData groupFromSpace = takeMatchingEntity(groupTemplate, pizzeriaGroupContainer, inPreparationTx, 100, "Cannot take the order from pizzeriaGroupContainer");
285 final List<PizzaOrder> orderedPizzas = groupFromSpace.getOrder().getOrderedPizzas();
286 for (PizzaOrder orderedPizza : orderedPizzas) {
287 if (orderedPizza.getId() == pizzaInProgress.getId()) {
288 orderedPizza.setStatus(PizzaOrderStatus.IN_PREPARATION);
289 orderedPizza.setCookId(pizzaInProgress.getCookId());
292 sendItemsToContainer(Arrays.asList(groupFromSpace), pizzeriaGroupContainer, RequestTimeout.ZERO, inPreparationTx);
293 sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.ZERO, inPreparationTx);
294 capi.commitTransaction(inPreparationTx);
295 } catch(NullPointerException e) {
296 } catch (Exception e) {
297 log.error("notifyCustomerPizzaInProgress: {}", e.getMessage());
302 private PizzaOrder createPizza(PizzaOrder order) throws InterruptedException {
303 long duration = order.getPizzaType().duration;
304 if (! Util.runSimulation) {
305 Thread.sleep(duration * 1000);
308 PizzaOrder pizza = Pizza.createPizzaFromPizzaOrder(order, cookId, false);
309 pizza.setStatus(PizzaOrderStatus.DONE);