blob: ba348d47e8875e1e4aaf666a8fa4b2295fbcb6a1 [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 Hart5573d322015-01-21 10:13:25 -080029import org.onosproject.net.intent.IntentEvent;
30import org.onosproject.net.intent.IntentId;
31import org.onosproject.net.intent.IntentState;
32import org.onosproject.net.intent.IntentStore;
33import org.onosproject.net.intent.IntentStoreDelegate;
34import org.onosproject.store.AbstractStore;
Jonathan Hart5573d322015-01-21 10:13:25 -080035import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
Jonathan Hart539a6462015-01-27 17:05:43 -080036import org.onosproject.store.impl.EventuallyConsistentMap;
37import org.onosproject.store.impl.EventuallyConsistentMapEvent;
38import org.onosproject.store.impl.EventuallyConsistentMapImpl;
39import org.onosproject.store.impl.EventuallyConsistentMapListener;
40import org.onosproject.store.impl.WallclockClockManager;
41import org.onosproject.store.serializers.KryoNamespaces;
Jonathan Hart5573d322015-01-21 10:13:25 -080042import org.slf4j.Logger;
43
Jonathan Hart5573d322015-01-21 10:13:25 -080044import java.util.ArrayList;
45import java.util.List;
Jonathan Hart5573d322015-01-21 10:13:25 -080046
47import static com.google.common.base.Preconditions.checkArgument;
Jonathan Hart5573d322015-01-21 10:13:25 -080048import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
Jonathan Hart5573d322015-01-21 10:13:25 -080049import static org.slf4j.LoggerFactory.getLogger;
50
51/**
52 * Manages inventory of Intents in a distributed data store that uses optimistic
53 * replication and gossip based techniques.
54 */
Brian O'Connorb488b192015-02-06 17:58:58 -080055@Component(immediate = false, enabled = false)
Jonathan Hart5573d322015-01-21 10:13:25 -080056@Service
57public class GossipIntentStore
58 extends AbstractStore<IntentEvent, IntentStoreDelegate>
59 implements IntentStore {
60
61 private final Logger log = getLogger(getClass());
62
Jonathan Hart539a6462015-01-27 17:05:43 -080063 private EventuallyConsistentMap<IntentId, Intent> intents;
Jonathan Hart5573d322015-01-21 10:13:25 -080064
Jonathan Hart539a6462015-01-27 17:05:43 -080065 private EventuallyConsistentMap<IntentId, IntentState> intentStates;
Jonathan Hart5573d322015-01-21 10:13:25 -080066
Jonathan Hart539a6462015-01-27 17:05:43 -080067 private EventuallyConsistentMap<IntentId, List<Intent>> installables;
Jonathan Hart5573d322015-01-21 10:13:25 -080068
69 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 protected ClusterCommunicationService clusterCommunicator;
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected ClusterService clusterService;
74
Jonathan Hart5573d322015-01-21 10:13:25 -080075 @Activate
76 public void activate() {
Jonathan Hart539a6462015-01-27 17:05:43 -080077 KryoNamespace.Builder intentSerializer = KryoNamespace.newBuilder()
Jonathan Hart45727852015-01-28 13:35:54 -080078 .register(KryoNamespaces.API);
Jonathan Hart539a6462015-01-27 17:05:43 -080079 intents = new EventuallyConsistentMapImpl<>("intents", clusterService,
80 clusterCommunicator,
81 intentSerializer,
82 new WallclockClockManager<>());
Jonathan Hart5573d322015-01-21 10:13:25 -080083
Jonathan Hart539a6462015-01-27 17:05:43 -080084 intentStates = new EventuallyConsistentMapImpl<>("intent-states",
85 clusterService,
86 clusterCommunicator,
87 intentSerializer,
88 new WallclockClockManager<>());
Jonathan Hart5573d322015-01-21 10:13:25 -080089
Jonathan Hart539a6462015-01-27 17:05:43 -080090 installables = new EventuallyConsistentMapImpl<>("intent-installables",
91 clusterService,
92 clusterCommunicator,
93 intentSerializer,
94 new WallclockClockManager<>());
Jonathan Hart5573d322015-01-21 10:13:25 -080095
Jonathan Hart539a6462015-01-27 17:05:43 -080096 intentStates.addListener(new InternalIntentStatesListener());
Jonathan Hart5573d322015-01-21 10:13:25 -080097
98 log.info("Started");
99 }
100
101 @Deactivate
102 public void deactivate() {
Jonathan Hart539a6462015-01-27 17:05:43 -0800103 intents.destroy();
104 intentStates.destroy();
105 installables.destroy();
Jonathan Hart5573d322015-01-21 10:13:25 -0800106
107 log.info("Stopped");
108 }
109
110 @Override
111 public long getIntentCount() {
112 return intents.size();
113 }
114
115 @Override
116 public Iterable<Intent> getIntents() {
117 // TODO don't actually need to copy intents, they are immutable
118 return ImmutableList.copyOf(intents.values());
119 }
120
121 @Override
122 public Intent getIntent(IntentId intentId) {
123 return intents.get(intentId);
124 }
125
126 @Override
127 public IntentState getIntentState(IntentId intentId) {
Jonathan Hart539a6462015-01-27 17:05:43 -0800128 return intentStates.get(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800129 }
130
131 @Override
132 public List<Intent> getInstallableIntents(IntentId intentId) {
Jonathan Hart539a6462015-01-27 17:05:43 -0800133 return installables.get(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800134 }
135
136 @Override
Jonathan Hart5573d322015-01-21 10:13:25 -0800137 public List<BatchWrite.Operation> batchWrite(BatchWrite batch) {
138
Jonathan Hart5573d322015-01-21 10:13:25 -0800139 List<BatchWrite.Operation> failed = new ArrayList<>();
140
141 for (BatchWrite.Operation op : batch.operations()) {
142 switch (op.type()) {
143 case CREATE_INTENT:
144 checkArgument(op.args().size() == 1,
145 "CREATE_INTENT takes 1 argument. %s", op);
146 Intent intent = op.arg(0);
147
Jonathan Hart539a6462015-01-27 17:05:43 -0800148 intents.put(intent.id(), intent);
149 intentStates.put(intent.id(), INSTALL_REQ);
Jonathan Hart5573d322015-01-21 10:13:25 -0800150
151 break;
152 case REMOVE_INTENT:
153 checkArgument(op.args().size() == 1,
154 "REMOVE_INTENT takes 1 argument. %s", op);
Jonathan Hart539a6462015-01-27 17:05:43 -0800155 IntentId intentId = op.arg(0);
156
157 intents.remove(intentId);
158 intentStates.remove(intentId);
159 installables.remove(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800160
161 break;
162 case SET_STATE:
163 checkArgument(op.args().size() == 2,
164 "SET_STATE takes 2 arguments. %s", op);
165 intent = op.arg(0);
166 IntentState newState = op.arg(1);
167
Jonathan Hart539a6462015-01-27 17:05:43 -0800168 intentStates.put(intent.id(), newState);
Jonathan Hart5573d322015-01-21 10:13:25 -0800169
170 break;
171 case SET_INSTALLABLE:
172 checkArgument(op.args().size() == 2,
173 "SET_INSTALLABLE takes 2 arguments. %s", op);
174 intentId = op.arg(0);
175 List<Intent> installableIntents = op.arg(1);
176
Jonathan Hart539a6462015-01-27 17:05:43 -0800177 installables.put(intentId, installableIntents);
Jonathan Hart5573d322015-01-21 10:13:25 -0800178
179 break;
180 case REMOVE_INSTALLED:
181 checkArgument(op.args().size() == 1,
182 "REMOVE_INSTALLED takes 1 argument. %s", op);
183 intentId = op.arg(0);
Jonathan Hart539a6462015-01-27 17:05:43 -0800184 installables.remove(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800185 break;
186 default:
187 log.warn("Unknown Operation encountered: {}", op);
188 failed.add(op);
189 break;
190 }
191 }
192
Jonathan Hart5573d322015-01-21 10:13:25 -0800193 return failed;
194 }
195
Jonathan Hart5573d322015-01-21 10:13:25 -0800196 private void notifyDelegateIfNotNull(IntentEvent event) {
197 if (event != null) {
198 notifyDelegate(event);
199 }
200 }
201
Jonathan Hart539a6462015-01-27 17:05:43 -0800202 private final class InternalIntentStatesListener implements
203 EventuallyConsistentMapListener<IntentId, IntentState> {
Jonathan Hart5573d322015-01-21 10:13:25 -0800204 @Override
Jonathan Hart539a6462015-01-27 17:05:43 -0800205 public void event(
206 EventuallyConsistentMapEvent<IntentId, IntentState> event) {
207 if (event.type() == EventuallyConsistentMapEvent.Type.PUT) {
208 IntentEvent externalEvent;
209 Intent intent = intents.get(event.key()); // TODO OK if this is null?
Jonathan Hart5573d322015-01-21 10:13:25 -0800210
Jonathan Hart5573d322015-01-21 10:13:25 -0800211 try {
Jonathan Hart539a6462015-01-27 17:05:43 -0800212 externalEvent = IntentEvent.getEvent(event.value(), intent);
213 } catch (IllegalArgumentException e) {
214 externalEvent = null;
Jonathan Hart5573d322015-01-21 10:13:25 -0800215 }
Jonathan Hart539a6462015-01-27 17:05:43 -0800216
217 notifyDelegateIfNotNull(externalEvent);
218 }
Jonathan Hart5573d322015-01-21 10:13:25 -0800219 }
220 }
221
Jonathan Hart5573d322015-01-21 10:13:25 -0800222}
223