]> git.somenet.org - pub/jan/sbc.git/blob - src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java
[XVSM] Some simulation improvments, documentation
[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 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;
11
12 import java.io.Serializable;
13 import java.net.URI;
14 import java.util.Arrays;
15 import java.util.Collections;
16 import java.util.List;
17
18 public class CookXVSM extends AbstractXVSMConnector {
19     private static final Logger log = LoggerFactory.getLogger(CookXVSM.class);
20
21     private int cookId;
22
23     public CookXVSM(int id, int port) {
24         super(port);
25
26         this.cookId = id;
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);
36     }
37
38     public void listenForPizzas() {
39        getDefaultBuilder().setLookaround(true).enableCountAll().setCref(preparePizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
40
41             @Override
42             public void onEntriesWritten(List<? extends Serializable> entries)
43                     throws Exception {
44
45                 List<PizzaOrder> pizzas = castEntries(entries);
46
47                 if (inNotification.get()) Collections.shuffle(pizzas);
48
49                 for (PizzaOrder pizzaOrder : pizzas) {
50
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());
53
54                     try {
55                         if (!mayPrepareCustomerPizza(pizzaOrder, tx)) {
56                             capi.rollbackTransaction(tx);
57                             continue;
58                         }
59
60                         // Require the lock for preparing the pizza
61                         PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), preparePizzasContainer, tx, RequestTimeout.DEFAULT, pizzaAlreadyCooked);
62
63
64                         // tell the space that you prepare the pizza -> without a transaction!!
65                         Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
66                         pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
67
68                         notifyCustomerPizzaInProgress(order, pizzaInProgress);
69
70                         PizzaOrder pizza = createPizza(order);
71
72                         notifyCustomerPizzaDone(pizza, tx);
73                         capi.commitTransaction(tx);
74 //                        log.debug("I have completed preparing a pizza for order {}!", pizza.getOrderId());
75                     } catch (NullPointerException e) {
76                         // the strange nullpointer exception from the space
77                     } catch (EntityNotFoundByTemplate e) {
78 //                        log.info("entitynotfound: {}", e.getMessage());
79                     } catch (Exception e) {
80 //                        log.info("outer cook");
81 //                        log.info(e.getMessage());
82 //                        e.printStackTrace();
83                     }
84
85                 }
86             }
87         }).createSpaceListenerImpl();
88
89     }
90
91     public void listenForDeliveryPizzas() {
92         getDefaultBuilder().setLookaround(true).setCref(prepareDeliveryPizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
93
94             @Override
95             public void onEntriesWritten(List<? extends Serializable> entries)
96                     throws Exception {
97
98                 List<PizzaOrder> pizzas = castEntries(entries);
99
100                 if (inNotification.get()) Collections.shuffle(pizzas);
101
102                 for (PizzaOrder pizzaOrder : pizzas) {
103
104                     TransactionReference tx = capi.createTransaction(12000, URI.create(String.format(Util.SERVER_ADDR, port)));
105                     String pizzaAlreadyCooked = String.format("Delivery Pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
106
107                     try {
108                         if (!mayPrepareDeliveryPizza(pizzaOrder, tx)) {
109                             capi.rollbackTransaction(tx);
110                             continue;
111                         }
112
113                         // Require the lock for preparing the pizza
114                         PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), prepareDeliveryPizzasContainer, tx, RequestTimeout.DEFAULT, pizzaAlreadyCooked);
115
116                         // tell the space that you prepare the pizza -> without a transaction!!
117                         Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
118                         pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
119
120                         if (! Util.runSimulation) {
121                             notifyDeliveryPizzaInProgress(order, pizzaInProgress);
122                         }
123
124 //                        log.info("before creating!");
125
126                         PizzaOrder pizza = createPizza(order);
127
128 //                        log.info("after creating!");
129
130                         sendItemsToContainer(Arrays.asList(pizza), preparedDeliveryPizzasContainer, RequestTimeout.DEFAULT, tx);
131
132 //                        log.info("after prepareddeliverypizzascon");
133
134                         notifyDeliveryPizzaDone(pizza, tx);
135
136 //                        log.info("after notifydone");
137
138                         capi.commitTransaction(tx);
139                         log.info("I have completed preparing a delivery pizza for order {}!", pizza.getOrderId());
140                     } catch (NullPointerException e) {
141                         // the strange nullpointer exception from the space
142                     } catch (EntityNotFoundByTemplate e) {
143 //                        log.info("entitynotfound: {}", e.getMessage());
144
145                     } catch (Exception e) {
146 //                        log.info("outer cook");
147 //                        log.info(e.getMessage());
148 //                        e.printStackTrace();
149                     }
150
151                 }
152             }
153         }).createSpaceListenerImpl();
154
155     }
156
157     /**
158      * A cook may prepare a pizza if there is no current delivery order or if at least a pizza of the same order is
159      * in preparation or has been done!
160      */
161     private boolean mayPrepareCustomerPizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
162         List<PizzaOrder> deliveryPizzas = readMatchingEntities(new PizzaOrder(), prepareDeliveryPizzasContainer, tx, RequestTimeout.INFINITE, "MAYPREPAREPIZZA: Cannot access prepareDeliveryPizzasContainer");
163         if (!deliveryPizzas.isEmpty()) {
164             final PizzaOrder template = new PizzaOrder();
165             template.setOrderId(pizzaOrder.getOrderId());
166             final List<PizzaOrder> pizzasAlreadyDone = readMatchingEntities(template, preparedPizzasContainer, tx, RequestTimeout.INFINITE, "MAYPREPAREPIZZA: Cannot access preparedPizzasContainer");
167             if(! pizzasAlreadyDone.isEmpty()) return true;
168             final List<PizzaOrder> pizzasOfOrderInProgress = readMatchingEntities(template, pizzaInProgressContainer, tx, RequestTimeout.INFINITE, "MAYPREPAREPIZZA:: Cannot access pizzaInProgressContainer");
169             if (! pizzasOfOrderInProgress.isEmpty()) return true;
170
171             return false;
172         }
173         else return true;
174     }
175
176
177     private boolean mayPrepareDeliveryPizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
178         // TODO: return false if a cook has already started cooking pizzas of an open order
179         return true;
180     }
181
182     private void notifyCustomerPizzaDone(PizzaOrder pizza, TransactionReference tx) throws MzsCoreException {
183         sendItemsToContainer(Arrays.asList(pizza), preparedPizzasContainer, RequestTimeout.DEFAULT, tx);
184         final GroupData group = new GroupData();
185         final Order groupOrder = new Order();
186         groupOrder.setId(pizza.getOrderId());
187         group.setOrder(groupOrder);
188         group.setState(GroupState.ORDERED);
189         GroupData groupData = takeMatchingEntity(group, pizzeriaGroupContainer, tx, RequestTimeout.INFINITE, "Cannot take the group from pizzeriaGroupContainer");
190         final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
191         for (PizzaOrder orderedPizza : orderedPizzas) {
192             if (orderedPizza.getId() == pizza.getId()) {
193                 orderedPizza.setStatus(PizzaOrderStatus.DONE);
194                 orderedPizza.setCookId(pizza.getCookId());
195             }
196         }
197         sendItemsToContainer(Arrays.asList(groupData), pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
198     }
199
200     private void notifyDeliveryPizzaDone(PizzaOrder pizza, TransactionReference tx) throws MzsCoreException {
201         final DeliveryGroupData group = new DeliveryGroupData();
202         final Order groupOrder = new Order();
203         groupOrder.setId(pizza.getOrderId());
204         group.setOrder(groupOrder);
205         group.setDeliveryStatus(null);
206         DeliveryGroupData groupData = takeMatchingEntity(group, pizzeriaDeliveryContainer, tx, RequestTimeout.INFINITE, "Cannot take the delivery order from pizzeriaDeliveryContainer");
207         final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
208         for (PizzaOrder orderedPizza : orderedPizzas) {
209             if (orderedPizza.getId() == pizza.getId()) {
210                 orderedPizza.setStatus(PizzaOrderStatus.DONE);
211                 orderedPizza.setCookId(pizza.getCookId());
212             }
213         }
214         sendItemsToContainer(Arrays.asList(groupData), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, tx);
215     }
216
217     private void notifyDeliveryPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) throws MzsCoreException {
218         log.info("I say that I now prepare a delivery pizza for order {}", pizzaInProgress.getOrderId());
219         final DeliveryGroupData groupTemplate = new DeliveryGroupData();
220         final Order groupOrder = new Order();
221         groupOrder.setId(order.getOrderId());
222         groupTemplate.setOrder(groupOrder);
223         groupTemplate.setDeliveryStatus(null);
224         final TransactionReference inPreparationTx = getDefaultTransaction();
225         final DeliveryGroupData groupFromSpace = takeMatchingEntity(groupTemplate, pizzeriaDeliveryContainer, inPreparationTx, RequestTimeout.INFINITE, "Cannot take the delivery order from pizzeriaDeliveryContainer");
226         final List<PizzaOrder> orderedPizzas = groupFromSpace.getOrder().getOrderedPizzas();
227         for (PizzaOrder orderedPizza : orderedPizzas) {
228             if (orderedPizza.getId() == pizzaInProgress.getId()) {
229                 orderedPizza.setStatus(PizzaOrderStatus.IN_PREPARATION);
230                 orderedPizza.setCookId(pizzaInProgress.getCookId());
231             }
232         }
233         sendItemsToContainer(Arrays.asList(groupFromSpace), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, inPreparationTx);
234         sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, inPreparationTx);
235 //        log.info("before inprogress comit!");
236         capi.commitTransaction(inPreparationTx);
237     }
238
239     private void notifyCustomerPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) {
240         try {
241             log.info("I say that I now prepare a pizza for order {}", pizzaInProgress.getOrderId());
242             final GroupData groupTemplate = new GroupData();
243             final Order groupOrder = new Order();
244             groupOrder.setId(order.getOrderId());
245             groupTemplate.setOrder(groupOrder);
246             groupTemplate.setState(null);
247             final TransactionReference inPreparationTx = getDefaultTransaction();
248             final GroupData groupFromSpace = takeMatchingEntity(groupTemplate, pizzeriaGroupContainer, inPreparationTx, RequestTimeout.INFINITE, "Cannot take the order from pizzeriaGroupContainer");
249             final List<PizzaOrder> orderedPizzas = groupFromSpace.getOrder().getOrderedPizzas();
250             for (PizzaOrder orderedPizza : orderedPizzas) {
251                 if (orderedPizza.getId() == pizzaInProgress.getId()) {
252                     orderedPizza.setStatus(PizzaOrderStatus.IN_PREPARATION);
253                     orderedPizza.setCookId(pizzaInProgress.getCookId());
254                 }
255             }
256             sendItemsToContainer(Arrays.asList(groupFromSpace), pizzeriaGroupContainer, RequestTimeout.DEFAULT, inPreparationTx);
257             sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, inPreparationTx);
258             capi.commitTransaction(inPreparationTx);
259         } catch (Exception e) {
260 //            log.error("This error has occurred: {}", e.getMessage());
261 //            e.printStackTrace();
262         }
263     }
264
265     private PizzaOrder createPizza(PizzaOrder order) throws InterruptedException {
266         long duration = order.getPizzaType().duration;
267         if (! Util.runSimulation) {
268             Thread.sleep(duration * 1000);
269         }
270
271         PizzaOrder pizza = Pizza.createPizzaFromPizzaOrder(order, cookId, false);
272         pizza.setStatus(PizzaOrderStatus.DONE);
273         return pizza;
274     }
275
276 }