]> git.somenet.org - pub/jan/sbc.git/blob - src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java
[XVSM] Crucial container communication changes
[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.ContainerReference;
8 import org.mozartspaces.core.MzsConstants.RequestTimeout;
9 import org.mozartspaces.core.MzsCoreException;
10 import org.mozartspaces.core.TransactionReference;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13
14 import java.io.Serializable;
15 import java.net.URI;
16 import java.util.Arrays;
17 import java.util.Collections;
18 import java.util.List;
19
20 public class CookXVSM extends AbstractXVSMConnector {
21     private static final Logger log = LoggerFactory.getLogger(CookXVSM.class);
22
23     private int cookId;
24
25     public CookXVSM(int id, int port) {
26         super(port);
27
28         this.cookId = id;
29         orderTakenContainer = useContainer(Util.ORDER_TAKEN);
30         deliveryOrderTakenContainer = useContainer(Util.DELIVERY_ORDER_TAKEN);
31         preparedPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
32         preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
33         prepareDeliveryPizzasContainer = useContainer(Util.PREPARE_DELIVERY_PIZZAS);
34         pizzaInProgressContainer = useContainer(Util.PIZZAS_IN_PROGRESS);
35         preparedDeliveryPizzasContainer = useContainer(Util.DELIVER_DELIVERY_PIZZAS);
36         pizzeriaGroupContainer = useContainer(Util.PIZZERIA_GROUP);
37     }
38
39     public void listenForPizzas() {
40         SpaceListener pizzasListener = getDefaultBuilder().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("Pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
54
55                     try {
56                         if (!mayPreparePizza(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.ZERO, 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
70                         log.debug("I say that I now prepare a pizza for order {}", pizzaInProgress.getOrderId());
71                         sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, null);
72
73                         PizzaOrder pizza = createPizza(order);
74
75                         final ContainerReference container = preparedPizzasContainer;
76                         sendItemsToContainer(Arrays.asList(pizza), container, RequestTimeout.DEFAULT, tx);
77                         final GroupData group  = new GroupData();
78                         final Order groupOrder = new Order();
79                         groupOrder.setId(pizza.getOrderId());
80                         group.setOrder(groupOrder);
81                         group.setState(GroupState.ORDERED);
82                         GroupData groupData = takeMatchingEntity(group, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT, "Cannot take the group from pizzeriaGroupContainer");
83                         final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
84                         for (PizzaOrder orderedPizza : orderedPizzas) {
85                             if (orderedPizza.getId() == pizza.getId()) {
86                                 orderedPizza.setStatus(PizzaOrderStatus.DONE);
87                                 orderedPizza.setCookId(pizza.getCookId());
88                             }
89                         }
90                         sendItemsToContainer(Arrays.asList(groupData), pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
91                         capi.commitTransaction(tx);
92                         log.debug("I have completed preparing a pizza for order {}!", pizza.getOrderId());
93                     } catch (NullPointerException e) {
94                         // the strange nullpointer exception from the space
95                     } catch (Exception e) {
96                         log.info(e.getMessage());
97                     }
98
99                 }
100             }
101         }).createSpaceListenerImpl();
102
103     }
104
105     /**
106      * A cook may prepare a pizza if there is no current delivery order or if at least a pizza of the same order is
107      * in preparation!
108      */
109     private boolean mayPreparePizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
110         List<PizzaOrder> deliveryPizzas = readMatchingEntities(new PizzaOrder(), prepareDeliveryPizzasContainer, tx, RequestTimeout.ZERO, "BBBBBB");
111         if (!deliveryPizzas.isEmpty()) {
112             final PizzaOrder template = new PizzaOrder();
113             template.setOrderId(pizzaOrder.getOrderId());
114             final List<PizzaOrder> pizzasOfOrderInProgress = readMatchingEntities(template, pizzaInProgressContainer, tx, RequestTimeout.ZERO, "ASDF");
115             if (pizzasOfOrderInProgress.isEmpty()) return false;
116         }
117         return true;
118     }
119
120
121     public void listenForDeliveryPizzas() {
122         SpaceListener pizzasListener = getDefaultBuilder().setCref(prepareDeliveryPizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
123
124             @Override
125             public void onEntriesWritten(List<? extends Serializable> entries)
126                     throws Exception {
127
128                 List<PizzaOrder> pizzas = castEntries(entries);
129
130                 if (inNotification.get()) Collections.shuffle(pizzas);
131
132                 for (PizzaOrder pizzaOrder : pizzas) {
133
134                     TransactionReference tx = capi.createTransaction(9000, URI.create(String.format(Util.SERVER_ADDR, port)));
135                     String pizzaAlreadyCooked = String.format("Pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
136
137                     try {
138                         // Require the lock for preparing the pizza
139                         PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), prepareDeliveryPizzasContainer, tx, RequestTimeout.ZERO, pizzaAlreadyCooked);
140
141                         // tell the space that you prepare the pizza -> without a transaction!!
142                         Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
143                         pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
144
145
146                         log.info("I say that I now prepare a pizza for order {}", pizzaInProgress.getOrderId());
147                         sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, null);
148
149                         PizzaOrder pizza = createPizza(order);
150
151                         final ContainerReference container = preparedDeliveryPizzasContainer;
152                         sendItemsToContainer(Arrays.asList(pizza), container, RequestTimeout.DEFAULT, tx);
153
154                         capi.commitTransaction(tx);
155                         log.info("I have completed preparing a delivery pizza for order {}!", pizza.getOrderId());
156                     } catch (NullPointerException e) {
157                         // the strange nullpointer exception from the space
158                     } catch (Exception e) {
159                         log.info(e.getMessage());
160                     }
161
162                 }
163             }
164         }).createSpaceListenerImpl();
165
166     }
167
168     private PizzaOrder createPizza(PizzaOrder order) throws InterruptedException {
169         long duration = order.getPizzaType().duration;
170         Thread.sleep(duration * 1000);
171
172         PizzaOrder pizza = Pizza.createPizzaFromPizzaOrder(order, cookId, false);
173         pizza.setStatus(PizzaOrderStatus.DONE);
174         return pizza;
175     }
176
177 }