]> git.somenet.org - pub/jan/sbc.git/blob - src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java
[XVSM] Some GroupAgent Container Refactoring. Full Driver<->DeliveryCustomer communic...
[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
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()) 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                         notifyDeliveryPizzaInProgress(order, pizzaInProgress);
122
123                         PizzaOrder pizza = createPizza(order);
124
125                         sendItemsToContainer(Arrays.asList(pizza), preparedDeliveryPizzasContainer, RequestTimeout.DEFAULT, tx);
126
127                         notifyDeliveryPizzaDone(pizza, tx);
128
129                         capi.commitTransaction(tx);
130                         log.info("I have completed preparing a delivery pizza for order {}!", pizza.getOrderId());
131                     } catch (NullPointerException e) {
132                         // the strange nullpointer exception from the space
133                     } catch (EntityNotFoundByTemplate e) {
134
135                     } catch (Exception e) {
136                         log.info("outer cook");
137                         log.info(e.getMessage());
138                         e.printStackTrace();
139                     }
140
141                 }
142             }
143         }).createSpaceListenerImpl();
144
145     }
146
147     /**
148      * A cook may prepare a pizza if there is no current delivery order or if at least a pizza of the same order is
149      * in preparation or has been done!
150      */
151     private boolean mayPrepareCustomerPizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
152         List<PizzaOrder> deliveryPizzas = readMatchingEntities(new PizzaOrder(), prepareDeliveryPizzasContainer, tx, RequestTimeout.INFINITE, "MAYPREPAREPIZZA: Cannot access prepareDeliveryPizzasContainer");
153         if (!deliveryPizzas.isEmpty()) {
154             final PizzaOrder template = new PizzaOrder();
155             template.setOrderId(pizzaOrder.getOrderId());
156             final List<PizzaOrder> pizzasAlreadyDone = readMatchingEntities(template, preparedPizzasContainer, tx, RequestTimeout.INFINITE, "MAYPREPAREPIZZA: Cannot access preparedPizzasContainer");
157             if(! pizzasAlreadyDone.isEmpty()) return true;
158             final List<PizzaOrder> pizzasOfOrderInProgress = readMatchingEntities(template, pizzaInProgressContainer, tx, RequestTimeout.INFINITE, "MAYPREPAREPIZZA:: Cannot access pizzaInProgressContainer");
159             if (! pizzasOfOrderInProgress.isEmpty()) return true;
160
161             return false;
162         }
163         else return true;
164     }
165
166
167     private boolean mayPrepareDeliveryPizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
168         // TODO: return false if a cook has already started cooking pizzas of an open order
169         return true;
170     }
171
172     private void notifyCustomerPizzaDone(PizzaOrder pizza, TransactionReference tx) throws MzsCoreException {
173         sendItemsToContainer(Arrays.asList(pizza), preparedPizzasContainer, RequestTimeout.DEFAULT, tx);
174         final GroupData group = new GroupData();
175         final Order groupOrder = new Order();
176         groupOrder.setId(pizza.getOrderId());
177         group.setOrder(groupOrder);
178         group.setState(GroupState.ORDERED);
179         GroupData groupData = takeMatchingEntity(group, pizzeriaGroupContainer, tx, RequestTimeout.INFINITE, "Cannot take the group from pizzeriaGroupContainer");
180         final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
181         for (PizzaOrder orderedPizza : orderedPizzas) {
182             if (orderedPizza.getId() == pizza.getId()) {
183                 orderedPizza.setStatus(PizzaOrderStatus.DONE);
184                 orderedPizza.setCookId(pizza.getCookId());
185             }
186         }
187         sendItemsToContainer(Arrays.asList(groupData), pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
188     }
189
190     private void notifyDeliveryPizzaDone(PizzaOrder pizza, TransactionReference tx) throws MzsCoreException {
191         final DeliveryGroupData group = new DeliveryGroupData();
192         final Order groupOrder = new Order();
193         groupOrder.setId(pizza.getOrderId());
194         group.setOrder(groupOrder);
195         group.setDeliveryStatus(null);
196         DeliveryGroupData groupData = takeMatchingEntity(group, pizzeriaDeliveryContainer, tx, RequestTimeout.INFINITE, "Cannot take the delivery order from pizzeriaDeliveryContainer");
197         final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
198         for (PizzaOrder orderedPizza : orderedPizzas) {
199             if (orderedPizza.getId() == pizza.getId()) {
200                 orderedPizza.setStatus(PizzaOrderStatus.DONE);
201                 orderedPizza.setCookId(pizza.getCookId());
202             }
203         }
204         sendItemsToContainer(Arrays.asList(groupData), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, tx);
205     }
206
207     private void notifyDeliveryPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) throws MzsCoreException {
208         log.info("I say that I now prepare a delivery pizza for order {}", pizzaInProgress.getOrderId());
209         final DeliveryGroupData groupTemplate = new DeliveryGroupData();
210         final Order groupOrder = new Order();
211         groupOrder.setId(order.getOrderId());
212         groupTemplate.setOrder(groupOrder);
213         groupTemplate.setDeliveryStatus(null);
214         final TransactionReference inPreparationTx = getDefaultTransaction();
215         final DeliveryGroupData groupFromSpace = takeMatchingEntity(groupTemplate, pizzeriaDeliveryContainer, inPreparationTx, RequestTimeout.INFINITE, "Cannot take the delivery order from pizzeriaDeliveryContainer");
216         final List<PizzaOrder> orderedPizzas = groupFromSpace.getOrder().getOrderedPizzas();
217         for (PizzaOrder orderedPizza : orderedPizzas) {
218             if (orderedPizza.getId() == pizzaInProgress.getId()) {
219                 orderedPizza.setStatus(PizzaOrderStatus.IN_PREPARATION);
220                 orderedPizza.setCookId(pizzaInProgress.getCookId());
221             }
222         }
223         sendItemsToContainer(Arrays.asList(groupFromSpace), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, inPreparationTx);
224         sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, inPreparationTx);
225         capi.commitTransaction(inPreparationTx);
226     }
227
228     private void notifyCustomerPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) {
229         try {
230             log.info("I say that I now prepare a pizza for order {}", pizzaInProgress.getOrderId());
231             final GroupData groupTemplate = new GroupData();
232             final Order groupOrder = new Order();
233             groupOrder.setId(order.getOrderId());
234             groupTemplate.setOrder(groupOrder);
235             groupTemplate.setState(null);
236             final TransactionReference inPreparationTx = getDefaultTransaction();
237             final GroupData groupFromSpace = takeMatchingEntity(groupTemplate, pizzeriaGroupContainer, inPreparationTx, RequestTimeout.INFINITE, "Cannot take the order from pizzeriaGroupContainer");
238             final List<PizzaOrder> orderedPizzas = groupFromSpace.getOrder().getOrderedPizzas();
239             for (PizzaOrder orderedPizza : orderedPizzas) {
240                 if (orderedPizza.getId() == pizzaInProgress.getId()) {
241                     orderedPizza.setStatus(PizzaOrderStatus.IN_PREPARATION);
242                     orderedPizza.setCookId(pizzaInProgress.getCookId());
243                 }
244             }
245             sendItemsToContainer(Arrays.asList(groupFromSpace), pizzeriaGroupContainer, RequestTimeout.DEFAULT, inPreparationTx);
246             sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, inPreparationTx);
247             capi.commitTransaction(inPreparationTx);
248         } catch (Exception e) {
249             log.error("This error has occurred: {}", e.getMessage());
250             e.printStackTrace();
251         }
252     }
253
254     private PizzaOrder createPizza(PizzaOrder order) throws InterruptedException {
255         long duration = order.getPizzaType().duration;
256         Thread.sleep(duration * 1000);
257
258         PizzaOrder pizza = Pizza.createPizzaFromPizzaOrder(order, cookId, false);
259         pizza.setStatus(PizzaOrderStatus.DONE);
260         return pizza;
261     }
262
263 }