blob: 051a01cfdc5ac10a76a37a523138c93713db4b33 [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
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800140 public Intent getIntent(Key intentKey) {
141 // TODO: Implement this
142 return null;
143 }
144
145
Jonathan Hart5573d322015-01-21 10:13:25 -0800146 public Intent getIntent(IntentId intentId) {
147 return intents.get(intentId);
148 }
149
150 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800151 public IntentState getIntentState(Key intentKey) {
152 // TODO: implement this
153 return IntentState.FAILED;
Jonathan Hart5573d322015-01-21 10:13:25 -0800154 }
155
156 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800157 public List<Intent> getInstallableIntents(Key intentKey) {
158 // TODO: implement this or delete class
159 return null;
160 /*
Jonathan Hart539a6462015-01-27 17:05:43 -0800161 return installables.get(intentId);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800162 */
Jonathan Hart5573d322015-01-21 10:13:25 -0800163 }
164
165 @Override
Jonathan Hart5573d322015-01-21 10:13:25 -0800166 public List<BatchWrite.Operation> batchWrite(BatchWrite batch) {
167
Jonathan Hart5573d322015-01-21 10:13:25 -0800168 List<BatchWrite.Operation> failed = new ArrayList<>();
169
170 for (BatchWrite.Operation op : batch.operations()) {
171 switch (op.type()) {
172 case CREATE_INTENT:
173 checkArgument(op.args().size() == 1,
174 "CREATE_INTENT takes 1 argument. %s", op);
175 Intent intent = op.arg(0);
176
Jonathan Hart539a6462015-01-27 17:05:43 -0800177 intents.put(intent.id(), intent);
178 intentStates.put(intent.id(), INSTALL_REQ);
Jonathan Hart5573d322015-01-21 10:13:25 -0800179
Jonathan Hart74c83132015-02-02 18:37:57 -0800180 // TODO remove from pending?
181
182
Jonathan Hart5573d322015-01-21 10:13:25 -0800183 break;
184 case REMOVE_INTENT:
185 checkArgument(op.args().size() == 1,
186 "REMOVE_INTENT takes 1 argument. %s", op);
Jonathan Hart539a6462015-01-27 17:05:43 -0800187 IntentId intentId = op.arg(0);
188
189 intents.remove(intentId);
190 intentStates.remove(intentId);
191 installables.remove(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800192
193 break;
194 case SET_STATE:
195 checkArgument(op.args().size() == 2,
196 "SET_STATE takes 2 arguments. %s", op);
197 intent = op.arg(0);
198 IntentState newState = op.arg(1);
199
Jonathan Hart539a6462015-01-27 17:05:43 -0800200 intentStates.put(intent.id(), newState);
Jonathan Hart5573d322015-01-21 10:13:25 -0800201
202 break;
203 case SET_INSTALLABLE:
204 checkArgument(op.args().size() == 2,
205 "SET_INSTALLABLE takes 2 arguments. %s", op);
206 intentId = op.arg(0);
207 List<Intent> installableIntents = op.arg(1);
208
Jonathan Hart539a6462015-01-27 17:05:43 -0800209 installables.put(intentId, installableIntents);
Jonathan Hart5573d322015-01-21 10:13:25 -0800210
211 break;
212 case REMOVE_INSTALLED:
213 checkArgument(op.args().size() == 1,
214 "REMOVE_INSTALLED takes 1 argument. %s", op);
215 intentId = op.arg(0);
Jonathan Hart539a6462015-01-27 17:05:43 -0800216 installables.remove(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800217 break;
218 default:
219 log.warn("Unknown Operation encountered: {}", op);
220 failed.add(op);
221 break;
222 }
223 }
224
Jonathan Hart5573d322015-01-21 10:13:25 -0800225 return failed;
226 }
227
Jonathan Hart74c83132015-02-02 18:37:57 -0800228 @Override
229 public void write(IntentData newData) {
230 // TODO
231 }
232
233 @Override
234 public void batchWrite(Iterable<IntentData> updates) {
235 // TODO
236 }
237
238 @Override
Jonathan Hart74c83132015-02-02 18:37:57 -0800239 public IntentData getIntentData(Key key) {
240 return null; // TODO
241 }
242
243 @Override
244 public void addPending(IntentData data) {
245 // TODO implement
246
247 // Check the intent versions
248 //pending.put(op.key(), op);
249 }
250
251 @Override
252 public boolean isMaster(Intent intent) {
253 // TODO
254 //return partitionService.isMine(intent.key());
255 return false;
256 }
257
Jonathan Hart5573d322015-01-21 10:13:25 -0800258 private void notifyDelegateIfNotNull(IntentEvent event) {
259 if (event != null) {
260 notifyDelegate(event);
261 }
262 }
263
Jonathan Hart539a6462015-01-27 17:05:43 -0800264 private final class InternalIntentStatesListener implements
265 EventuallyConsistentMapListener<IntentId, IntentState> {
Jonathan Hart5573d322015-01-21 10:13:25 -0800266 @Override
Jonathan Hart539a6462015-01-27 17:05:43 -0800267 public void event(
268 EventuallyConsistentMapEvent<IntentId, IntentState> event) {
269 if (event.type() == EventuallyConsistentMapEvent.Type.PUT) {
270 IntentEvent externalEvent;
271 Intent intent = intents.get(event.key()); // TODO OK if this is null?
Jonathan Hart5573d322015-01-21 10:13:25 -0800272
Jonathan Hart5573d322015-01-21 10:13:25 -0800273 try {
Jonathan Hart539a6462015-01-27 17:05:43 -0800274 externalEvent = IntentEvent.getEvent(event.value(), intent);
275 } catch (IllegalArgumentException e) {
276 externalEvent = null;
Jonathan Hart5573d322015-01-21 10:13:25 -0800277 }
Jonathan Hart539a6462015-01-27 17:05:43 -0800278
279 notifyDelegateIfNotNull(externalEvent);
280 }
Jonathan Hart5573d322015-01-21 10:13:25 -0800281 }
282 }
283
Jonathan Hart74c83132015-02-02 18:37:57 -0800284 private final class InternalPendingListener implements
285 EventuallyConsistentMapListener<String, IntentOperation> {
286 @Override
287 public void event(
288 EventuallyConsistentMapEvent<String, IntentOperation> event) {
289 if (event.type() == EventuallyConsistentMapEvent.Type.PUT) {
290 // The pending intents map has been updated. If we are master for
291 // this intent's partition, notify the Manager that they should do
292 // some work.
293 if (isMaster(event.value().intent())) {
294 // TODO delegate.process(event.value());
295 log.debug("implement this");
296 }
297 }
298 }
299 }
300
Jonathan Hart5573d322015-01-21 10:13:25 -0800301}
302