]> git.somenet.org - pub/jan/sbc.git/blob - src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java
[XVSM] Add presentation
[pub/jan/sbc.git] / src / main / java / at / ac / tuwien / sbc / valesriegler / xvsm / CookXVSM.java
1 package at.ac.tuwien.sbc.valesriegler.xvsm;
2
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;
14
15 import java.io.Serializable;
16 import java.net.URI;
17 import java.util.Arrays;
18 import java.util.Collections;
19 import java.util.List;
20
21 public class CookXVSM extends AbstractXVSMConnector {
22     private static final Logger log = LoggerFactory.getLogger(CookXVSM.class);
23
24     private int cookId;
25     private SpaceListenerImpl listenForDeliveryPizzas;
26     private SpaceListenerImpl listenForNormalPizzas;
27
28     public CookXVSM(int id, int port) {
29         super(port);
30
31         this.cookId = id;
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);
41     }
42
43     public void listenForPizzas() {
44         listenForNormalPizzas = getDefaultBuilder("listenForNormalPizzas").noNotification().setCref(preparePizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
45
46             @Override
47             public void onEntriesWritten(List<? extends Serializable> entries)
48                     throws Exception {
49
50                 log.info("Normal pizzas onEntrieswritten of cook {} with size {}", cookId, entries.size());
51                 List<PizzaOrder> pizzas = castEntries(entries);
52
53                 Collections.sort(pizzas);
54
55                 for (PizzaOrder pizzaOrder : pizzas) {
56
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());
59
60                     try {
61                         if (!mayPrepareCustomerPizza(pizzaOrder, tx)) {
62                             capi.rollbackTransaction(tx);
63                             continue;
64                         }
65
66                         // Require the lock for preparing the pizza
67                         PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), preparePizzasContainer, tx, RequestTimeout.ZERO, pizzaAlreadyCooked);
68
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);
72
73                         notifyCustomerPizzaInProgress(order, pizzaInProgress);
74
75                         PizzaOrder pizza = createPizza(order);
76
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());
89                     }
90
91                 }
92             }
93         }).createSpaceListenerImpl();
94
95     }
96
97     public void listenForDeliveryPizzas() {
98         listenForDeliveryPizzas = getDefaultBuilder("listenForDeliveryPizzas").noNotification().setCref(prepareDeliveryPizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
99
100             @Override
101             public void onEntriesWritten(List<? extends Serializable> entries)
102                     throws Exception {
103                 log.info("Delivery pizzas onEntrieswritten of cook {} with size {}", cookId, entries.size());
104
105                 List<PizzaOrder> pizzas = castEntries(entries);
106
107                 Collections.sort(pizzas);
108
109                 for (PizzaOrder pizzaOrder : pizzas) {
110
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());
113
114                     try {
115                         if (!mayPrepareDeliveryPizza(tx, pizzaOrder)) {
116                             capi.rollbackTransaction(tx);
117                             continue;
118                         }
119
120                         // Require the lock for preparing the pizza
121                         PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), prepareDeliveryPizzasContainer, tx, RequestTimeout.ZERO, pizzaAlreadyCooked);
122
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);
126
127                         notifyDeliveryPizzaInProgress(order, pizzaInProgress);
128
129                         log.debug("before creating!");
130
131                         PizzaOrder pizza = createPizza(order);
132
133                         log.debug("after creating!");
134
135
136                         log.debug("after prepareddeliverypizzascon");
137
138                         notifyDeliveryPizzaDone(pizza, tx);
139
140                         log.debug("after notifydone");
141
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());
153                     }
154
155                 }
156             }
157         }).createSpaceListenerImpl();
158
159     }
160
161     public void start() {
162         try {
163             final SpaceAction spaceActionDelivery = listenForDeliveryPizzas.getSpaceAction();
164             final SpaceAction spaceActionNormalGroup = listenForNormalPizzas.getSpaceAction();
165             while(true) {
166                 spaceActionDelivery.onEntriesWritten(listenForDeliveryPizzas.getEntries());
167                 Thread.sleep(1000);
168                 spaceActionNormalGroup.onEntriesWritten(listenForNormalPizzas.getEntries());
169                 Thread.sleep(1000);
170             }
171         } catch (Exception e) {
172             log.info(e.getMessage());
173         }
174     }
175
176     /**
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!
179      */
180     private boolean mayPrepareCustomerPizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
181         boolean mayPrepare = false;
182
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;
189             else {
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;
193             }
194         }
195         else mayPrepare = true;
196         log.info("Cook may prepare Customer pizza: {} for order {}", mayPrepare, pizzaOrder.getOrderId());
197         return mayPrepare;
198     }
199
200
201     /**
202      * A cook may prepare a delivery pizza if no customer group order is open
203      */
204     private boolean mayPrepareDeliveryPizza(TransactionReference tx, PizzaOrder pizzaOrder) throws MzsCoreException {
205         boolean mayPrepare = false;
206
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!");
212            mayPrepare = false;
213         }
214         else {
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;
218         }
219         log.info("Cook may prepare Delivery pizza: {} for order {}", mayPrepare, pizzaOrder.getOrderId());
220         return mayPrepare;
221     }
222
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());
236             }
237         }
238         sendItemsToContainer(Arrays.asList(groupData), pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
239     }
240
241     private void sortOrShufflePizzas(List<PizzaOrder> pizzas, boolean notification) {
242         if (notification) Collections.shuffle(pizzas);
243         else {
244             Collections.sort(pizzas);
245         }
246     }
247
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());
261             }
262         }
263         sendItemsToContainer(Arrays.asList(groupData), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, tx);
264     }
265
266     private void notifyDeliveryPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) throws MzsCoreException {
267         try {
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());
281                 }
282             }
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());
290             e.printStackTrace();
291         }
292     }
293
294     private void notifyCustomerPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) {
295         try {
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());
309                 }
310             }
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());
317             e.printStackTrace();
318         }
319     }
320
321     private PizzaOrder createPizza(PizzaOrder order) throws InterruptedException {
322         long duration = order.getPizzaType().duration;
323         if (! Util.runSimulation) {
324             Thread.sleep(duration * 1000);
325         }
326
327         PizzaOrder pizza = Pizza.createPizzaFromPizzaOrder(order, cookId, false);
328         pizza.setStatus(PizzaOrderStatus.DONE);
329         return pizza;
330     }
331 }