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