blob: f3917c97a958009f4cdc62946fd34f8f4c22c6bd [file] [log] [blame]
Jonathan Hart5573d322015-01-21 10:13:25 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.store.intent.impl;
17
18import com.google.common.collect.ImmutableList;
Jonathan Hart5573d322015-01-21 10:13:25 -080019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
25import org.onlab.util.KryoNamespace;
26import org.onosproject.cluster.ClusterService;
Jonathan Hart5573d322015-01-21 10:13:25 -080027import org.onosproject.net.intent.BatchWrite;
28import org.onosproject.net.intent.Intent;
Jonathan Hart74c83132015-02-02 18:37:57 -080029import org.onosproject.net.intent.IntentData;
Jonathan Hart5573d322015-01-21 10:13:25 -080030import org.onosproject.net.intent.IntentEvent;
31import org.onosproject.net.intent.IntentId;
Jonathan Hart74c83132015-02-02 18:37:57 -080032import org.onosproject.net.intent.IntentOperation;
Jonathan Hart5573d322015-01-21 10:13:25 -080033import org.onosproject.net.intent.IntentState;
34import org.onosproject.net.intent.IntentStore;
35import org.onosproject.net.intent.IntentStoreDelegate;
Jonathan Hart74c83132015-02-02 18:37:57 -080036import org.onosproject.net.intent.Key;
Jonathan Hart5573d322015-01-21 10:13:25 -080037import org.onosproject.store.AbstractStore;
Jonathan Hart5573d322015-01-21 10:13:25 -080038import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
Jonathan Hart539a6462015-01-27 17:05:43 -080039import org.onosproject.store.impl.EventuallyConsistentMap;
40import org.onosproject.store.impl.EventuallyConsistentMapEvent;
41import org.onosproject.store.impl.EventuallyConsistentMapImpl;
42import org.onosproject.store.impl.EventuallyConsistentMapListener;
43import org.onosproject.store.impl.WallclockClockManager;
44import org.onosproject.store.serializers.KryoNamespaces;
Jonathan Hart5573d322015-01-21 10:13:25 -080045import org.slf4j.Logger;
46
Jonathan Hart5573d322015-01-21 10:13:25 -080047import java.util.ArrayList;
48import java.util.List;
Jonathan Hart5573d322015-01-21 10:13:25 -080049
50import static com.google.common.base.Preconditions.checkArgument;
Jonathan Hart5573d322015-01-21 10:13:25 -080051import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
Jonathan Hart5573d322015-01-21 10:13:25 -080052import static org.slf4j.LoggerFactory.getLogger;
53
54/**
55 * Manages inventory of Intents in a distributed data store that uses optimistic
56 * replication and gossip based techniques.
57 */
Brian O'Connorb488b192015-02-06 17:58:58 -080058@Component(immediate = false, enabled = false)
Jonathan Hart5573d322015-01-21 10:13:25 -080059@Service
60public class GossipIntentStore
61 extends AbstractStore<IntentEvent, IntentStoreDelegate>
62 implements IntentStore {
63
64 private final Logger log = getLogger(getClass());
65
Jonathan Hart539a6462015-01-27 17:05:43 -080066 private EventuallyConsistentMap<IntentId, Intent> intents;
Jonathan Hart5573d322015-01-21 10:13:25 -080067
Jonathan Hart539a6462015-01-27 17:05:43 -080068 private EventuallyConsistentMap<IntentId, IntentState> intentStates;
Jonathan Hart5573d322015-01-21 10:13:25 -080069
Jonathan Hart539a6462015-01-27 17:05:43 -080070 private EventuallyConsistentMap<IntentId, List<Intent>> installables;
Jonathan Hart5573d322015-01-21 10:13:25 -080071
Jonathan Hart74c83132015-02-02 18:37:57 -080072 // Map of intent key => pending intent operation
73 private EventuallyConsistentMap<String, IntentOperation> pending;
74
Jonathan Hart5573d322015-01-21 10:13:25 -080075 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected ClusterCommunicationService clusterCommunicator;
77
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 protected ClusterService clusterService;
80
Jonathan Hart74c83132015-02-02 18:37:57 -080081 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected PartitionService partitionService;
83
Jonathan Hart5573d322015-01-21 10:13:25 -080084 @Activate
85 public void activate() {
Jonathan Hart539a6462015-01-27 17:05:43 -080086 KryoNamespace.Builder intentSerializer = KryoNamespace.newBuilder()
Jonathan Hart45727852015-01-28 13:35:54 -080087 .register(KryoNamespaces.API);
Jonathan Hart539a6462015-01-27 17:05:43 -080088 intents = new EventuallyConsistentMapImpl<>("intents", clusterService,
89 clusterCommunicator,
90 intentSerializer,
91 new WallclockClockManager<>());
Jonathan Hart5573d322015-01-21 10:13:25 -080092
Jonathan Hart539a6462015-01-27 17:05:43 -080093 intentStates = new EventuallyConsistentMapImpl<>("intent-states",
94 clusterService,
95 clusterCommunicator,
96 intentSerializer,
97 new WallclockClockManager<>());
Jonathan Hart5573d322015-01-21 10:13:25 -080098
Jonathan Hart539a6462015-01-27 17:05:43 -080099 installables = new EventuallyConsistentMapImpl<>("intent-installables",
100 clusterService,
101 clusterCommunicator,
102 intentSerializer,
103 new WallclockClockManager<>());
Jonathan Hart5573d322015-01-21 10:13:25 -0800104
Jonathan Hart74c83132015-02-02 18:37:57 -0800105 pending = new EventuallyConsistentMapImpl<>("intent-pending",
106 clusterService,
107 clusterCommunicator,
108 intentSerializer, // TODO
109 new WallclockClockManager<>());
110
Jonathan Hart539a6462015-01-27 17:05:43 -0800111 intentStates.addListener(new InternalIntentStatesListener());
Jonathan Hart74c83132015-02-02 18:37:57 -0800112 pending.addListener(new InternalPendingListener());
Jonathan Hart5573d322015-01-21 10:13:25 -0800113
114 log.info("Started");
115 }
116
117 @Deactivate
118 public void deactivate() {
Jonathan Hart74c83132015-02-02 18:37:57 -0800119
Jonathan Hart539a6462015-01-27 17:05:43 -0800120 intents.destroy();
121 intentStates.destroy();
122 installables.destroy();
Jonathan Hart74c83132015-02-02 18:37:57 -0800123 pending.destroy();
Jonathan Hart5573d322015-01-21 10:13:25 -0800124
125 log.info("Stopped");
126 }
127
128 @Override
129 public long getIntentCount() {
130 return intents.size();
131 }
132
133 @Override
134 public Iterable<Intent> getIntents() {
135 // TODO don't actually need to copy intents, they are immutable
136 return ImmutableList.copyOf(intents.values());
137 }
138
139 @Override
140 public Intent getIntent(IntentId intentId) {
141 return intents.get(intentId);
142 }
143
144 @Override
145 public IntentState getIntentState(IntentId intentId) {
Jonathan Hart539a6462015-01-27 17:05:43 -0800146 return intentStates.get(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800147 }
148
149 @Override
150 public List<Intent> getInstallableIntents(IntentId intentId) {
Jonathan Hart539a6462015-01-27 17:05:43 -0800151 return installables.get(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800152 }
153
154 @Override
Jonathan Hart5573d322015-01-21 10:13:25 -0800155 public List<BatchWrite.Operation> batchWrite(BatchWrite batch) {
156
Jonathan Hart5573d322015-01-21 10:13:25 -0800157 List<BatchWrite.Operation> failed = new ArrayList<>();
158
159 for (BatchWrite.Operation op : batch.operations()) {
160 switch (op.type()) {
161 case CREATE_INTENT:
162 checkArgument(op.args().size() == 1,
163 "CREATE_INTENT takes 1 argument. %s", op);
164 Intent intent = op.arg(0);
165
Jonathan Hart539a6462015-01-27 17:05:43 -0800166 intents.put(intent.id(), intent);
167 intentStates.put(intent.id(), INSTALL_REQ);
Jonathan Hart5573d322015-01-21 10:13:25 -0800168
Jonathan Hart74c83132015-02-02 18:37:57 -0800169 // TODO remove from pending?
170
171
Jonathan Hart5573d322015-01-21 10:13:25 -0800172 break;
173 case REMOVE_INTENT:
174 checkArgument(op.args().size() == 1,
175 "REMOVE_INTENT takes 1 argument. %s", op);
Jonathan Hart539a6462015-01-27 17:05:43 -0800176 IntentId intentId = op.arg(0);
177
178 intents.remove(intentId);
179 intentStates.remove(intentId);
180 installables.remove(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800181
182 break;
183 case SET_STATE:
184 checkArgument(op.args().size() == 2,
185 "SET_STATE takes 2 arguments. %s", op);
186 intent = op.arg(0);
187 IntentState newState = op.arg(1);
188
Jonathan Hart539a6462015-01-27 17:05:43 -0800189 intentStates.put(intent.id(), newState);
Jonathan Hart5573d322015-01-21 10:13:25 -0800190
191 break;
192 case SET_INSTALLABLE:
193 checkArgument(op.args().size() == 2,
194 "SET_INSTALLABLE takes 2 arguments. %s", op);
195 intentId = op.arg(0);
196 List<Intent> installableIntents = op.arg(1);
197
Jonathan Hart539a6462015-01-27 17:05:43 -0800198 installables.put(intentId, installableIntents);
Jonathan Hart5573d322015-01-21 10:13:25 -0800199
200 break;
201 case REMOVE_INSTALLED:
202 checkArgument(op.args().size() == 1,
203 "REMOVE_INSTALLED takes 1 argument. %s", op);
204 intentId = op.arg(0);
Jonathan Hart539a6462015-01-27 17:05:43 -0800205 installables.remove(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800206 break;
207 default:
208 log.warn("Unknown Operation encountered: {}", op);
209 failed.add(op);
210 break;
211 }
212 }
213
Jonathan Hart5573d322015-01-21 10:13:25 -0800214 return failed;
215 }
216
Jonathan Hart74c83132015-02-02 18:37:57 -0800217 @Override
218 public void write(IntentData newData) {
219 // TODO
220 }
221
222 @Override
223 public void batchWrite(Iterable<IntentData> updates) {
224 // TODO
225 }
226
227 @Override
228 public Intent getIntent(Key key) {
229 return null; // TODO
230 }
231
232 @Override
233 public IntentData getIntentData(Key key) {
234 return null; // TODO
235 }
236
237 @Override
238 public void addPending(IntentData data) {
239 // TODO implement
240
241 // Check the intent versions
242 //pending.put(op.key(), op);
243 }
244
245 @Override
246 public boolean isMaster(Intent intent) {
247 // TODO
248 //return partitionService.isMine(intent.key());
249 return false;
250 }
251
Jonathan Hart5573d322015-01-21 10:13:25 -0800252 private void notifyDelegateIfNotNull(IntentEvent event) {
253 if (event != null) {
254 notifyDelegate(event);
255 }
256 }
257
Jonathan Hart539a6462015-01-27 17:05:43 -0800258 private final class InternalIntentStatesListener implements
259 EventuallyConsistentMapListener<IntentId, IntentState> {
Jonathan Hart5573d322015-01-21 10:13:25 -0800260 @Override
Jonathan Hart539a6462015-01-27 17:05:43 -0800261 public void event(
262 EventuallyConsistentMapEvent<IntentId, IntentState> event) {
263 if (event.type() == EventuallyConsistentMapEvent.Type.PUT) {
264 IntentEvent externalEvent;
265 Intent intent = intents.get(event.key()); // TODO OK if this is null?
Jonathan Hart5573d322015-01-21 10:13:25 -0800266
Jonathan Hart5573d322015-01-21 10:13:25 -0800267 try {
Jonathan Hart539a6462015-01-27 17:05:43 -0800268 externalEvent = IntentEvent.getEvent(event.value(), intent);
269 } catch (IllegalArgumentException e) {
270 externalEvent = null;
Jonathan Hart5573d322015-01-21 10:13:25 -0800271 }
Jonathan Hart539a6462015-01-27 17:05:43 -0800272
273 notifyDelegateIfNotNull(externalEvent);
274 }
Jonathan Hart5573d322015-01-21 10:13:25 -0800275 }
276 }
277
Jonathan Hart74c83132015-02-02 18:37:57 -0800278 private final class InternalPendingListener implements
279 EventuallyConsistentMapListener<String, IntentOperation> {
280 @Override
281 public void event(
282 EventuallyConsistentMapEvent<String, IntentOperation> event) {
283 if (event.type() == EventuallyConsistentMapEvent.Type.PUT) {
284 // The pending intents map has been updated. If we are master for
285 // this intent's partition, notify the Manager that they should do
286 // some work.
287 if (isMaster(event.value().intent())) {
288 // TODO delegate.process(event.value());
289 log.debug("implement this");
290 }
291 }
292 }
293 }
294
Jonathan Hart5573d322015-01-21 10:13:25 -0800295}
296