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.SpaceListenerImpl;
7 import org.mozartspaces.capi3.EntryLockedException;
8 import org.mozartspaces.core.MzsConstants;
9 import org.mozartspaces.core.MzsConstants.RequestTimeout;
10 import org.mozartspaces.core.MzsCoreException;
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 private SpaceListenerImpl listenForDeliveryPizzas;
26 private SpaceListenerImpl listenForNormalPizzas;
28 public CookXVSM(int id, int port) {
32 orderTakenContainer = useContainer(Util.ORDER_TAKEN);
33 deliveryOrderTakenContainer = useContainer(Util.DELIVERY_ORDER_TAKEN);
34 preparedPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
35 preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
36 prepareDeliveryPizzasContainer = useContainer(Util.PREPARE_DELIVERY_PIZZAS);
37 pizzaInProgressContainer = useContainer(Util.PIZZAS_IN_PROGRESS);
38 preparedDeliveryPizzasContainer = useContainer(Util.DELIVER_DELIVERY_PIZZAS);
39 pizzeriaGroupContainer = useContainer(Util.PIZZERIA_GROUP);
40 pizzeriaDeliveryContainer = useContainer(Util.PIZZERIA_DELIVERY);
43 public void listenForPizzas() {
44 listenForNormalPizzas = getDefaultBuilder("listenForNormalPizzas").noNotification().setCref(preparePizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
47 public void onEntriesWritten(List<? extends Serializable> entries)
50 log.info("Normal pizzas onEntrieswritten of cook {} with size {}", cookId, entries.size());
51 List<PizzaOrder> pizzas = castEntries(entries);
53 Collections.sort(pizzas);
55 for (PizzaOrder pizzaOrder : pizzas) {
57 TransactionReference tx = capi.createTransaction(9000, URI.create(String.format(Util.SERVER_ADDR, port)));
58 String pizzaAlreadyCooked = String.format("Normal pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
61 if (!mayPrepareCustomerPizza(pizzaOrder, tx)) {
62 capi.rollbackTransaction(tx);
66 // Require the lock for preparing the pizza
67 PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), preparePizzasContainer, tx, RequestTimeout.ZERO, pizzaAlreadyCooked);
69 // tell the space that you prepare the pizza -> without a transaction!!
70 Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
71 pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
73 notifyCustomerPizzaInProgress(order, pizzaInProgress);
75 PizzaOrder pizza = createPizza(order);
77 notifyCustomerPizzaDone(pizza, 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 (EntityNotFoundByTemplate e) {
83 log.info("entitynotfound: {}", e.getMessage());
84 } catch (EntryLockedException e) {
85 capi.rollbackTransaction(tx);
86 } catch (Exception e) {
87 log.error("outer cook");
88 log.error(e.getMessage());
93 }).createSpaceListenerImpl();
97 public void listenForDeliveryPizzas() {
98 listenForDeliveryPizzas = getDefaultBuilder("listenForDeliveryPizzas").noNotification().setCref(prepareDeliveryPizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
101 public void onEntriesWritten(List<? extends Serializable> entries)
103 log.info("Delivery pizzas onEntrieswritten of cook {} with size {}", cookId, entries.size());
105 List<PizzaOrder> pizzas = castEntries(entries);
107 Collections.sort(pizzas);
109 for (PizzaOrder pizzaOrder : pizzas) {
111 TransactionReference tx = capi.createTransaction(12000, URI.create(String.format(Util.SERVER_ADDR, port)));
112 String pizzaAlreadyCooked = String.format("Delivery Pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
115 if (!mayPrepareDeliveryPizza(tx, pizzaOrder)) {
116 capi.rollbackTransaction(tx);
120 // Require the lock for preparing the pizza
121 PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), prepareDeliveryPizzasContainer, tx, RequestTimeout.ZERO, pizzaAlreadyCooked);
123 // tell the space that you prepare the pizza -> without a transaction!!
124 Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
125 pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
127 notifyDeliveryPizzaInProgress(order, pizzaInProgress);
129 log.debug("before creating!");
131 PizzaOrder pizza = createPizza(order);
133 log.debug("after creating!");
136 log.debug("after prepareddeliverypizzascon");
138 notifyDeliveryPizzaDone(pizza, tx);
140 log.debug("after notifydone");
142 capi.commitTransaction(tx);
143 log.debug("I have completed preparing a delivery pizza for order {}!", pizza.getOrderId());
144 } catch (NullPointerException e) {
145 // the strange nullpointer exception from the space
146 } catch (EntityNotFoundByTemplate e) {
147 log.info("entitynotfound: {}", e.getMessage());
148 } catch (EntryLockedException e) {
149 capi.rollbackTransaction(tx);
150 } catch (Exception e) {
151 log.error("outer cook");
152 log.error(e.getMessage());
157 }).createSpaceListenerImpl();
161 public void start() {
163 final SpaceAction spaceActionDelivery = listenForDeliveryPizzas.getSpaceAction();
164 final SpaceAction spaceActionNormalGroup = listenForNormalPizzas.getSpaceAction();
166 spaceActionDelivery.onEntriesWritten(listenForDeliveryPizzas.getEntries());
168 spaceActionNormalGroup.onEntriesWritten(listenForNormalPizzas.getEntries());
171 } catch (Exception e) {
172 log.info(e.getMessage());
177 * A cook may prepare a pizza if there is no current delivery order or if at least a pizza of the same order is
178 * in preparation or has been done!
180 private boolean mayPrepareCustomerPizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
181 boolean mayPrepare = false;
183 List<PizzaOrder> deliveryPizzas = readMatchingEntities(new PizzaOrder(), prepareDeliveryPizzasContainer, tx, RequestTimeout.DEFAULT, "mayPrepareCustomerPizza: Cannot access prepareDeliveryPizzasContainer", MzsConstants.Selecting.COUNT_MAX);
184 if (!deliveryPizzas.isEmpty()) {
185 Pizza pizza = new Pizza();
186 pizza.setIdOfOrder(pizzaOrder.getOrderId());
187 final List<Pizza> pizzasAlreadyDone = readMatchingEntities(pizza, preparedPizzasContainer, tx, RequestTimeout.DEFAULT, "mayPrepareCustomerPizza: Cannot access preparedPizzasContainer", MzsConstants.Selecting.COUNT_MAX);
188 if(! pizzasAlreadyDone.isEmpty()) mayPrepare = true;
190 final List<Pizza> pizzasOfOrderInProgress = readMatchingEntities(pizza, pizzaInProgressContainer, tx, RequestTimeout.DEFAULT, "mayPrepareCustomerPizza: Cannot access pizzaInProgressContainer", MzsConstants.Selecting.COUNT_MAX);
191 if (! pizzasOfOrderInProgress.isEmpty()) mayPrepare = true;
192 else mayPrepare = false;
195 else mayPrepare = true;
196 log.info("Cook may prepare Customer pizza: {} for order {}", mayPrepare, pizzaOrder.getOrderId());
202 * A cook may prepare a delivery pizza if no customer group order is open
204 private boolean mayPrepareDeliveryPizza(TransactionReference tx, PizzaOrder pizzaOrder) throws MzsCoreException {
205 boolean mayPrepare = false;
207 Pizza pizza = new Pizza();
208 pizza.setDeliveryPizza(false);
209 final List<Pizza> preparedNonDeliveryPizzas = readMatchingEntities(pizza, preparedPizzasContainer, tx, RequestTimeout.DEFAULT, "mayPrepareDeliveryPizza: cannot access preparedPizzasContainer", MzsConstants.Selecting.COUNT_MAX);
210 if(! preparedNonDeliveryPizzas.isEmpty()) {
211 log.info("PreparedNonDeliveryPizzas NOT empty!");
215 final List<Pizza> nonDeliveryPizzasInProgress = readMatchingEntities(pizza, pizzaInProgressContainer, tx, RequestTimeout.DEFAULT, "mayPrepareDeliveryPizza: cannot access pizzaInProgressContainer", MzsConstants.Selecting.COUNT_MAX);
216 if (! nonDeliveryPizzasInProgress.isEmpty()) mayPrepare = false;
217 else mayPrepare = true;
219 log.info("Cook may prepare Delivery pizza: {} for order {}", mayPrepare, pizzaOrder.getOrderId());
223 private void notifyCustomerPizzaDone(PizzaOrder pizza, TransactionReference tx) throws MzsCoreException {
224 sendItemsToContainer(Arrays.asList(pizza), preparedPizzasContainer, RequestTimeout.DEFAULT, tx);
225 final GroupData group = new GroupData();
226 final Order groupOrder = new Order();
227 groupOrder.setId(pizza.getOrderId());
228 group.setOrder(groupOrder);
229 group.setState(GroupState.ORDERED);
230 GroupData groupData = takeMatchingEntity(group, pizzeriaGroupContainer, tx, RequestTimeout.INFINITE, "Cannot take the group from pizzeriaGroupContainer");
231 final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
232 for (PizzaOrder orderedPizza : orderedPizzas) {
233 if (orderedPizza.getId() == pizza.getId()) {
234 orderedPizza.setStatus(PizzaOrderStatus.DONE);
235 orderedPizza.setCookId(pizza.getCookId());
238 sendItemsToContainer(Arrays.asList(groupData), pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
241 private void sortOrShufflePizzas(List<PizzaOrder> pizzas, boolean notification) {
242 if (notification) Collections.shuffle(pizzas);
244 Collections.sort(pizzas);
248 private void notifyDeliveryPizzaDone(PizzaOrder pizza, TransactionReference tx) throws MzsCoreException {
249 sendItemsToContainer(Arrays.asList(pizza), preparedDeliveryPizzasContainer, RequestTimeout.DEFAULT, tx);
250 final DeliveryGroupData group = new DeliveryGroupData();
251 final Order groupOrder = new Order();
252 groupOrder.setId(pizza.getOrderId());
253 group.setOrder(groupOrder);
254 group.setDeliveryStatus(null);
255 DeliveryGroupData groupData = takeMatchingEntity(group, pizzeriaDeliveryContainer, tx, RequestTimeout.INFINITE, "Cannot take the delivery order from pizzeriaDeliveryContainer");
256 final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
257 for (PizzaOrder orderedPizza : orderedPizzas) {
258 if (orderedPizza.getId() == pizza.getId()) {
259 orderedPizza.setStatus(PizzaOrderStatus.DONE);
260 orderedPizza.setCookId(pizza.getCookId());
263 sendItemsToContainer(Arrays.asList(groupData), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, tx);
266 private void notifyDeliveryPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) throws MzsCoreException {
268 log.info("I say that I now prepare a delivery pizza for order {}", pizzaInProgress.getOrderId());
269 final DeliveryGroupData groupTemplate = new DeliveryGroupData();
270 final Order groupOrder = new Order();
271 groupOrder.setId(order.getOrderId());
272 groupTemplate.setOrder(groupOrder);
273 groupTemplate.setDeliveryStatus(null);
274 final TransactionReference inPreparationTx = getDefaultTransaction();
275 final DeliveryGroupData groupFromSpace = takeMatchingEntity(groupTemplate, pizzeriaDeliveryContainer, inPreparationTx, RequestTimeout.DEFAULT, "Cannot take the delivery order from pizzeriaDeliveryContainer");
276 final List<PizzaOrder> orderedPizzas = groupFromSpace.getOrder().getOrderedPizzas();
277 for (PizzaOrder orderedPizza : orderedPizzas) {
278 if (orderedPizza.getId() == pizzaInProgress.getId()) {
279 orderedPizza.setStatus(PizzaOrderStatus.IN_PREPARATION);
280 orderedPizza.setCookId(pizzaInProgress.getCookId());
283 sendItemsToContainer(Arrays.asList(groupFromSpace), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, inPreparationTx);
284 sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, inPreparationTx);
285 log.debug("before inprogress comit!");
286 capi.commitTransaction(inPreparationTx);
287 } catch(NullPointerException e) {
288 } catch (Exception e) {
289 log.error("notifyDeliveryPizzaInProgress: {}", e.getMessage());
294 private void notifyCustomerPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) {
296 log.info("I say that I now prepare a pizza for order {}", pizzaInProgress.getOrderId());
297 final GroupData groupTemplate = new GroupData();
298 final Order groupOrder = new Order();
299 groupOrder.setId(order.getOrderId());
300 groupTemplate.setOrder(groupOrder);
301 groupTemplate.setState(null);
302 final TransactionReference inPreparationTx = getDefaultTransaction();
303 final GroupData groupFromSpace = takeMatchingEntity(groupTemplate, pizzeriaGroupContainer, inPreparationTx, RequestTimeout.DEFAULT, "Cannot take the order from pizzeriaGroupContainer");
304 final List<PizzaOrder> orderedPizzas = groupFromSpace.getOrder().getOrderedPizzas();
305 for (PizzaOrder orderedPizza : orderedPizzas) {
306 if (orderedPizza.getId() == pizzaInProgress.getId()) {
307 orderedPizza.setStatus(PizzaOrderStatus.IN_PREPARATION);
308 orderedPizza.setCookId(pizzaInProgress.getCookId());
311 sendItemsToContainer(Arrays.asList(groupFromSpace), pizzeriaGroupContainer, RequestTimeout.ZERO, inPreparationTx);
312 sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.ZERO, inPreparationTx);
313 capi.commitTransaction(inPreparationTx);
314 } catch(NullPointerException e) {
315 } catch (Exception e) {
316 log.error("notifyCustomerPizzaInProgress: {}", e.getMessage());
321 private PizzaOrder createPizza(PizzaOrder order) throws InterruptedException {
322 long duration = order.getPizzaType().duration;
323 if (! Util.runSimulation) {
324 Thread.sleep(duration * 1000);
327 PizzaOrder pizza = Pizza.createPizzaFromPizzaOrder(order, cookId, false);
328 pizza.setStatus(PizzaOrderStatus.DONE);