]> git.somenet.org - pub/jan/sbc.git/blob - src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java
[XVSM] Some simulation support.
[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.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;
12
13 import java.io.Serializable;
14 import java.net.URI;
15 import java.util.Arrays;
16 import java.util.Collections;
17 import java.util.List;
18
19 public class CookXVSM extends AbstractXVSMConnector {
20     private static final Logger log = LoggerFactory.getLogger(CookXVSM.class);
21
22     private int cookId;
23
24     public CookXVSM(int id, int port) {
25         super(port);
26
27         this.cookId = id;
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);
37     }
38
39     public void listenForPizzas() {
40        getDefaultBuilder().setLookaround(true).enableCountAll().setCref(preparePizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
41
42             @Override
43             public void onEntriesWritten(List<? extends Serializable> entries)
44                     throws Exception {
45
46                 List<PizzaOrder> pizzas = castEntries(entries);
47
48                 if (inNotification.get()) Collections.shuffle(pizzas);
49
50                 for (PizzaOrder pizzaOrder : pizzas) {
51
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());
54
55                     try {
56                         if (!mayPrepareCustomerPizza(pizzaOrder, tx)) {
57                             capi.rollbackTransaction(tx);
58                             continue;
59                         }
60
61                         // Require the lock for preparing the pizza
62                         PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), preparePizzasContainer, tx, RequestTimeout.DEFAULT, pizzaAlreadyCooked);
63
64
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);
68
69                         notifyCustomerPizzaInProgress(order, pizzaInProgress);
70
71                         PizzaOrder pizza = createPizza(order);
72
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());
83                         e.printStackTrace();
84                     }
85
86                 }
87             }
88         }).createSpaceListenerImpl();
89
90     }
91
92     public void listenForDeliveryPizzas() {
93         SpaceListener pizzasListener = getDefaultBuilder().setLookaround(true).setCref(prepareDeliveryPizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
94
95             @Override
96             public void onEntriesWritten(List<? extends Serializable> entries)
97                     throws Exception {
98
99                 List<PizzaOrder> pizzas = castEntries(entries);
100
101                 if (inNotification.get() || Util.runSimulation) Collections.shuffle(pizzas);
102
103                 for (PizzaOrder pizzaOrder : pizzas) {
104
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());
107
108                     try {
109                         if (!mayPrepareDeliveryPizza(pizzaOrder, tx)) {
110                             capi.rollbackTransaction(tx);
111                             continue;
112                         }
113
114                         // Require the lock for preparing the pizza
115                         PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), prepareDeliveryPizzasContainer, tx, RequestTimeout.DEFAULT, pizzaAlreadyCooked);
116
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);
120
121                         if (! Util.runSimulation) {
122                             notifyDeliveryPizzaInProgress(order, pizzaInProgress);
123                         }
124
125 //                        log.info("before creating!");
126
127                         PizzaOrder pizza = createPizza(order);
128
129 //                        log.info("after creating!");
130
131                         sendItemsToContainer(Arrays.asList(pizza), preparedDeliveryPizzasContainer, RequestTimeout.DEFAULT, tx);
132
133 //                        log.info("after prepareddeliverypizzascon");
134
135                         notifyDeliveryPizzaDone(pizza, tx);
136
137 //                        log.info("after notifydone");
138
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());
145
146                     } catch (Exception e) {
147                         log.info("outer cook");
148                         log.info(e.getMessage());
149                         e.printStackTrace();
150                     }
151
152                 }
153             }
154         }).createSpaceListenerImpl();
155
156     }
157
158     /**
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!
161      */
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;
171
172             return false;
173         }
174         else return true;
175     }
176
177
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
180         return true;
181     }
182
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());
196             }
197         }
198         sendItemsToContainer(Arrays.asList(groupData), pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
199     }
200
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());
213             }
214         }
215         sendItemsToContainer(Arrays.asList(groupData), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, tx);
216     }
217
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());
232             }
233         }
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);
238     }
239
240     private void notifyCustomerPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) {
241         try {
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());
255                 }
256             }
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());
262             e.printStackTrace();
263         }
264     }
265
266     private PizzaOrder createPizza(PizzaOrder order) throws InterruptedException {
267         long duration = order.getPizzaType().duration;
268         if (! Util.runSimulation) {
269             Thread.sleep(duration * 1000);
270         }
271
272         PizzaOrder pizza = Pizza.createPizzaFromPizzaOrder(order, cookId, false);
273         pizza.setStatus(PizzaOrderStatus.DONE);
274         return pizza;
275     }
276
277 }