Yuta HIGUCHI

initial Distributed IntentStore using Hz

Change-Id: Iffb3f5fdfe8ba080fd039e67f8473ea18348f20d
...@@ -86,13 +86,13 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { ...@@ -86,13 +86,13 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> {
86 IntentEvent setState(Intent intent, IntentState newState); 86 IntentEvent setState(Intent intent, IntentState newState);
87 87
88 /** 88 /**
89 - * Adds the installable intents which resulted from compilation of the 89 + * Sets the installable intents which resulted from compilation of the
90 * specified original intent. 90 * specified original intent.
91 * 91 *
92 * @param intentId original intent identifier 92 * @param intentId original intent identifier
93 * @param installableIntents compiled installable intents 93 * @param installableIntents compiled installable intents
94 */ 94 */
95 - void addInstallableIntents(IntentId intentId, List<Intent> installableIntents); 95 + void setInstallableIntents(IntentId intentId, List<Intent> installableIntents);
96 96
97 /** 97 /**
98 * Returns the list of the installable events associated with the specified 98 * Returns the list of the installable events associated with the specified
......
...@@ -273,7 +273,7 @@ public class IntentManager ...@@ -273,7 +273,7 @@ public class IntentManager
273 273
274 // If all went well, associate the resulting list of installable 274 // If all went well, associate the resulting list of installable
275 // intents with the top-level intent and proceed to install. 275 // intents with the top-level intent and proceed to install.
276 - store.addInstallableIntents(intent.id(), installable); 276 + store.setInstallableIntents(intent.id(), installable);
277 executeInstallingPhase(intent); 277 executeInstallingPhase(intent);
278 278
279 } catch (Exception e) { 279 } catch (Exception e) {
...@@ -366,7 +366,7 @@ public class IntentManager ...@@ -366,7 +366,7 @@ public class IntentManager
366 } else { 366 } else {
367 // Otherwise, re-associate the newly compiled installable intents 367 // Otherwise, re-associate the newly compiled installable intents
368 // with the top-level intent and kick off installing phase. 368 // with the top-level intent and kick off installing phase.
369 - store.addInstallableIntents(intent.id(), installable); 369 + store.setInstallableIntents(intent.id(), installable);
370 executeInstallingPhase(intent); 370 executeInstallingPhase(intent);
371 } 371 }
372 } catch (Exception e) { 372 } catch (Exception e) {
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
16 package org.onlab.onos.store.intent.impl; 16 package org.onlab.onos.store.intent.impl;
17 17
18 import com.google.common.collect.ImmutableSet; 18 import com.google.common.collect.ImmutableSet;
19 +import com.hazelcast.core.IMap;
20 +
19 import org.apache.felix.scr.annotations.Activate; 21 import org.apache.felix.scr.annotations.Activate;
20 import org.apache.felix.scr.annotations.Component; 22 import org.apache.felix.scr.annotations.Component;
21 import org.apache.felix.scr.annotations.Deactivate; 23 import org.apache.felix.scr.annotations.Deactivate;
...@@ -26,30 +28,54 @@ import org.onlab.onos.net.intent.IntentId; ...@@ -26,30 +28,54 @@ import org.onlab.onos.net.intent.IntentId;
26 import org.onlab.onos.net.intent.IntentState; 28 import org.onlab.onos.net.intent.IntentState;
27 import org.onlab.onos.net.intent.IntentStore; 29 import org.onlab.onos.net.intent.IntentStore;
28 import org.onlab.onos.net.intent.IntentStoreDelegate; 30 import org.onlab.onos.net.intent.IntentStoreDelegate;
29 -import org.onlab.onos.store.AbstractStore; 31 +import org.onlab.onos.store.hz.AbstractHazelcastStore;
32 +import org.onlab.onos.store.hz.SMap;
30 import org.slf4j.Logger; 33 import org.slf4j.Logger;
31 34
32 import java.util.List; 35 import java.util.List;
33 import java.util.Map; 36 import java.util.Map;
34 import java.util.concurrent.ConcurrentHashMap; 37 import java.util.concurrent.ConcurrentHashMap;
35 38
39 +import static com.google.common.base.Verify.verify;
36 import static org.onlab.onos.net.intent.IntentState.*; 40 import static org.onlab.onos.net.intent.IntentState.*;
37 import static org.slf4j.LoggerFactory.getLogger; 41 import static org.slf4j.LoggerFactory.getLogger;
38 42
39 -//FIXME: I LIE I AM NOT DISTRIBUTED
40 @Component(immediate = true) 43 @Component(immediate = true)
41 @Service 44 @Service
42 public class DistributedIntentStore 45 public class DistributedIntentStore
43 - extends AbstractStore<IntentEvent, IntentStoreDelegate> 46 + extends AbstractHazelcastStore<IntentEvent, IntentStoreDelegate>
44 implements IntentStore { 47 implements IntentStore {
45 48
46 private final Logger log = getLogger(getClass()); 49 private final Logger log = getLogger(getClass());
47 - private final Map<IntentId, Intent> intents = new ConcurrentHashMap<>();
48 - private final Map<IntentId, IntentState> states = new ConcurrentHashMap<>();
49 - private final Map<IntentId, List<Intent>> installable = new ConcurrentHashMap<>();
50 50
51 + // Assumption: IntentId will not have synonyms
52 + private SMap<IntentId, Intent> intents;
53 + private SMap<IntentId, IntentState> states;
54 +
55 + // Map to store instance local intermediate state transition
56 + private transient Map<IntentId, IntentState> transientStates = new ConcurrentHashMap<>();
57 +
58 + private SMap<IntentId, List<Intent>> installable;
59 +
60 + @Override
51 @Activate 61 @Activate
52 public void activate() { 62 public void activate() {
63 + super.activate();
64 +
65 + // TODO: enable near cache, allow read from backup for this IMap
66 + IMap<byte[], byte[]> rawIntents = super.theInstance.getMap("intents");
67 + intents = new SMap<>(rawIntents , super.serializer);
68 +
69 + // TODO: disable near cache, disable read from backup for this IMap
70 + IMap<byte[], byte[]> rawStates = super.theInstance.getMap("intent-states");
71 + states = new SMap<>(rawStates , super.serializer);
72 +
73 + transientStates.clear();
74 +
75 + // TODO: disable near cache, disable read from backup for this IMap
76 + IMap<byte[], byte[]> rawInstallables = super.theInstance.getMap("installable-intents");
77 + installable = new SMap<>(rawInstallables , super.serializer);
78 +
53 log.info("Started"); 79 log.info("Started");
54 } 80 }
55 81
...@@ -60,16 +86,27 @@ public class DistributedIntentStore ...@@ -60,16 +86,27 @@ public class DistributedIntentStore
60 86
61 @Override 87 @Override
62 public IntentEvent createIntent(Intent intent) { 88 public IntentEvent createIntent(Intent intent) {
63 - intents.put(intent.id(), intent); 89 + Intent existing = intents.putIfAbsent(intent.id(), intent);
64 - return this.setState(intent, IntentState.SUBMITTED); 90 + if (existing != null) {
91 + // duplicate, ignore
92 + return null;
93 + } else {
94 + return this.setState(intent, IntentState.SUBMITTED);
95 + }
65 } 96 }
66 97
67 @Override 98 @Override
68 public IntentEvent removeIntent(IntentId intentId) { 99 public IntentEvent removeIntent(IntentId intentId) {
69 Intent intent = intents.remove(intentId); 100 Intent intent = intents.remove(intentId);
70 installable.remove(intentId); 101 installable.remove(intentId);
102 + if (intent == null) {
103 + // was already removed
104 + return null;
105 + }
71 IntentEvent event = this.setState(intent, WITHDRAWN); 106 IntentEvent event = this.setState(intent, WITHDRAWN);
72 states.remove(intentId); 107 states.remove(intentId);
108 + transientStates.remove(intentId);
109 + // TODO: Should we callremoveInstalledIntents if this Intent was
73 return event; 110 return event;
74 } 111 }
75 112
...@@ -90,31 +127,53 @@ public class DistributedIntentStore ...@@ -90,31 +127,53 @@ public class DistributedIntentStore
90 127
91 @Override 128 @Override
92 public IntentState getIntentState(IntentId id) { 129 public IntentState getIntentState(IntentId id) {
130 + final IntentState localState = transientStates.get(id);
131 + if (localState != null) {
132 + return localState;
133 + }
93 return states.get(id); 134 return states.get(id);
94 } 135 }
95 136
96 @Override 137 @Override
97 public IntentEvent setState(Intent intent, IntentState state) { 138 public IntentEvent setState(Intent intent, IntentState state) {
98 - IntentId id = intent.id(); 139 + final IntentId id = intent.id();
99 - states.put(id, state);
100 IntentEvent.Type type = null; 140 IntentEvent.Type type = null;
141 + IntentState prev = null;
142 + boolean transientStateChangeOnly = false;
101 143
144 + // TODO: enable sanity checking if Debug enabled, etc.
102 switch (state) { 145 switch (state) {
103 case SUBMITTED: 146 case SUBMITTED:
147 + prev = states.putIfAbsent(id, SUBMITTED);
148 + verify(prev == null, "Illegal state transition attempted from %s to SUBMITTED", prev);
104 type = IntentEvent.Type.SUBMITTED; 149 type = IntentEvent.Type.SUBMITTED;
105 break; 150 break;
106 case INSTALLED: 151 case INSTALLED:
152 + // parking state transition
153 + prev = states.replace(id, INSTALLED);
154 + verify(prev != null, "Illegal state transition attempted from non-SUBMITTED to INSTALLED");
107 type = IntentEvent.Type.INSTALLED; 155 type = IntentEvent.Type.INSTALLED;
108 break; 156 break;
109 case FAILED: 157 case FAILED:
158 + prev = states.replace(id, FAILED);
110 type = IntentEvent.Type.FAILED; 159 type = IntentEvent.Type.FAILED;
111 break; 160 break;
112 case WITHDRAWN: 161 case WITHDRAWN:
162 + prev = states.replace(id, WITHDRAWN);
163 + verify(prev != null, "Illegal state transition attempted from non-WITHDRAWING to WITHDRAWN");
113 type = IntentEvent.Type.WITHDRAWN; 164 type = IntentEvent.Type.WITHDRAWN;
114 break; 165 break;
115 default: 166 default:
167 + transientStateChangeOnly = true;
116 break; 168 break;
117 } 169 }
170 + if (!transientStateChangeOnly) {
171 + log.debug("Parking State change: {} {}=>{}", id, prev, state);
172 + }
173 + // Update instance local state, which includes non-parking state transition
174 + prev = transientStates.put(id, state);
175 + log.debug("Transient State change: {} {}=>{}", id, prev, state);
176 +
118 if (type == null) { 177 if (type == null) {
119 return null; 178 return null;
120 } 179 }
...@@ -122,7 +181,7 @@ public class DistributedIntentStore ...@@ -122,7 +181,7 @@ public class DistributedIntentStore
122 } 181 }
123 182
124 @Override 183 @Override
125 - public void addInstallableIntents(IntentId intentId, List<Intent> result) { 184 + public void setInstallableIntents(IntentId intentId, List<Intent> result) {
126 installable.put(intentId, result); 185 installable.put(intentId, result);
127 } 186 }
128 187
...@@ -136,4 +195,5 @@ public class DistributedIntentStore ...@@ -136,4 +195,5 @@ public class DistributedIntentStore
136 installable.remove(intentId); 195 installable.remove(intentId);
137 } 196 }
138 197
198 + // FIXME add handler to react to remote event
139 } 199 }
......
...@@ -68,6 +68,10 @@ public class SimpleIntentStore ...@@ -68,6 +68,10 @@ public class SimpleIntentStore
68 public IntentEvent removeIntent(IntentId intentId) { 68 public IntentEvent removeIntent(IntentId intentId) {
69 Intent intent = intents.remove(intentId); 69 Intent intent = intents.remove(intentId);
70 installable.remove(intentId); 70 installable.remove(intentId);
71 + if (intent == null) {
72 + // was already removed
73 + return null;
74 + }
71 IntentEvent event = this.setState(intent, WITHDRAWN); 75 IntentEvent event = this.setState(intent, WITHDRAWN);
72 states.remove(intentId); 76 states.remove(intentId);
73 return event; 77 return event;
...@@ -122,7 +126,7 @@ public class SimpleIntentStore ...@@ -122,7 +126,7 @@ public class SimpleIntentStore
122 } 126 }
123 127
124 @Override 128 @Override
125 - public void addInstallableIntents(IntentId intentId, List<Intent> result) { 129 + public void setInstallableIntents(IntentId intentId, List<Intent> result) {
126 installable.put(intentId, result); 130 installable.put(intentId, result);
127 } 131 }
128 132
......