blob: 157d66c9317697a5042adfff3de56479ed8654b3 [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;
Jonathan Hart229794b2015-01-23 16:15:07 -080045import java.util.Collections;
Jonathan Hart5573d322015-01-21 10:13:25 -080046import java.util.List;
Jonathan Hart5573d322015-01-21 10:13:25 -080047
48import static com.google.common.base.Preconditions.checkArgument;
Jonathan Hart5573d322015-01-21 10:13:25 -080049import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
Jonathan Hart5573d322015-01-21 10:13:25 -080050import static org.slf4j.LoggerFactory.getLogger;
51
52/**
53 * Manages inventory of Intents in a distributed data store that uses optimistic
54 * replication and gossip based techniques.
55 */
56@Component(immediate = true, enabled = false)
57@Service
58public class GossipIntentStore
59 extends AbstractStore<IntentEvent, IntentStoreDelegate>
60 implements IntentStore {
61
62 private final Logger log = getLogger(getClass());
63
Jonathan Hart539a6462015-01-27 17:05:43 -080064 private EventuallyConsistentMap<IntentId, Intent> intents;
Jonathan Hart5573d322015-01-21 10:13:25 -080065
Jonathan Hart539a6462015-01-27 17:05:43 -080066 private EventuallyConsistentMap<IntentId, IntentState> intentStates;
Jonathan Hart5573d322015-01-21 10:13:25 -080067
Jonathan Hart539a6462015-01-27 17:05:43 -080068 private EventuallyConsistentMap<IntentId, List<Intent>> installables;
Jonathan Hart5573d322015-01-21 10:13:25 -080069
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected ClusterCommunicationService clusterCommunicator;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected ClusterService clusterService;
75
Jonathan Hart5573d322015-01-21 10:13:25 -080076 @Activate
77 public void activate() {
Jonathan Hart539a6462015-01-27 17:05:43 -080078 KryoNamespace.Builder intentSerializer = KryoNamespace.newBuilder()
79 .register(KryoNamespaces.API)
80 // TODO this should be in BASIC namespace
81 .register(Collections.emptyList().getClass());
82 intents = new EventuallyConsistentMapImpl<>("intents", clusterService,
83 clusterCommunicator,
84 intentSerializer,
85 new WallclockClockManager<>());
Jonathan Hart5573d322015-01-21 10:13:25 -080086
Jonathan Hart539a6462015-01-27 17:05:43 -080087 intentStates = new EventuallyConsistentMapImpl<>("intent-states",
88 clusterService,
89 clusterCommunicator,
90 intentSerializer,
91 new WallclockClockManager<>());
Jonathan Hart5573d322015-01-21 10:13:25 -080092
Jonathan Hart539a6462015-01-27 17:05:43 -080093 installables = new EventuallyConsistentMapImpl<>("intent-installables",
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 intentStates.addListener(new InternalIntentStatesListener());
Jonathan Hart5573d322015-01-21 10:13:25 -0800100
101 log.info("Started");
102 }
103
104 @Deactivate
105 public void deactivate() {
Jonathan Hart539a6462015-01-27 17:05:43 -0800106 intents.destroy();
107 intentStates.destroy();
108 installables.destroy();
Jonathan Hart5573d322015-01-21 10:13:25 -0800109
110 log.info("Stopped");
111 }
112
113 @Override
114 public long getIntentCount() {
115 return intents.size();
116 }
117
118 @Override
119 public Iterable<Intent> getIntents() {
120 // TODO don't actually need to copy intents, they are immutable
121 return ImmutableList.copyOf(intents.values());
122 }
123
124 @Override
125 public Intent getIntent(IntentId intentId) {
126 return intents.get(intentId);
127 }
128
129 @Override
130 public IntentState getIntentState(IntentId intentId) {
Jonathan Hart539a6462015-01-27 17:05:43 -0800131 return intentStates.get(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800132 }
133
134 @Override
135 public List<Intent> getInstallableIntents(IntentId intentId) {
Jonathan Hart539a6462015-01-27 17:05:43 -0800136 return installables.get(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800137 }
138
139 @Override
Jonathan Hart5573d322015-01-21 10:13:25 -0800140 public List<BatchWrite.Operation> batchWrite(BatchWrite batch) {
141
Jonathan Hart5573d322015-01-21 10:13:25 -0800142 List<BatchWrite.Operation> failed = new ArrayList<>();
143
144 for (BatchWrite.Operation op : batch.operations()) {
145 switch (op.type()) {
146 case CREATE_INTENT:
147 checkArgument(op.args().size() == 1,
148 "CREATE_INTENT takes 1 argument. %s", op);
149 Intent intent = op.arg(0);
150
Jonathan Hart539a6462015-01-27 17:05:43 -0800151 intents.put(intent.id(), intent);
152 intentStates.put(intent.id(), INSTALL_REQ);
Jonathan Hart5573d322015-01-21 10:13:25 -0800153
154 break;
155 case REMOVE_INTENT:
156 checkArgument(op.args().size() == 1,
157 "REMOVE_INTENT takes 1 argument. %s", op);
Jonathan Hart539a6462015-01-27 17:05:43 -0800158 IntentId intentId = op.arg(0);
159
160 intents.remove(intentId);
161 intentStates.remove(intentId);
162 installables.remove(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800163
164 break;
165 case SET_STATE:
166 checkArgument(op.args().size() == 2,
167 "SET_STATE takes 2 arguments. %s", op);
168 intent = op.arg(0);
169 IntentState newState = op.arg(1);
170
Jonathan Hart539a6462015-01-27 17:05:43 -0800171 intentStates.put(intent.id(), newState);
Jonathan Hart5573d322015-01-21 10:13:25 -0800172
173 break;
174 case SET_INSTALLABLE:
175 checkArgument(op.args().size() == 2,
176 "SET_INSTALLABLE takes 2 arguments. %s", op);
177 intentId = op.arg(0);
178 List<Intent> installableIntents = op.arg(1);
179
Jonathan Hart539a6462015-01-27 17:05:43 -0800180 installables.put(intentId, installableIntents);
Jonathan Hart5573d322015-01-21 10:13:25 -0800181
182 break;
183 case REMOVE_INSTALLED:
184 checkArgument(op.args().size() == 1,
185 "REMOVE_INSTALLED takes 1 argument. %s", op);
186 intentId = op.arg(0);
Jonathan Hart539a6462015-01-27 17:05:43 -0800187 installables.remove(intentId);
Jonathan Hart5573d322015-01-21 10:13:25 -0800188 break;
189 default:
190 log.warn("Unknown Operation encountered: {}", op);
191 failed.add(op);
192 break;
193 }
194 }
195
Jonathan Hart5573d322015-01-21 10:13:25 -0800196 return failed;
197 }
198
Jonathan Hart5573d322015-01-21 10:13:25 -0800199 private void notifyDelegateIfNotNull(IntentEvent event) {
200 if (event != null) {
201 notifyDelegate(event);
202 }
203 }
204
Jonathan Hart539a6462015-01-27 17:05:43 -0800205 private final class InternalIntentStatesListener implements
206 EventuallyConsistentMapListener<IntentId, IntentState> {
Jonathan Hart5573d322015-01-21 10:13:25 -0800207 @Override
Jonathan Hart539a6462015-01-27 17:05:43 -0800208 public void event(
209 EventuallyConsistentMapEvent<IntentId, IntentState> event) {
210 if (event.type() == EventuallyConsistentMapEvent.Type.PUT) {
211 IntentEvent externalEvent;
212 Intent intent = intents.get(event.key()); // TODO OK if this is null?
Jonathan Hart5573d322015-01-21 10:13:25 -0800213
Jonathan Hart5573d322015-01-21 10:13:25 -0800214 try {
Jonathan Hart539a6462015-01-27 17:05:43 -0800215 externalEvent = IntentEvent.getEvent(event.value(), intent);
216 } catch (IllegalArgumentException e) {
217 externalEvent = null;
Jonathan Hart5573d322015-01-21 10:13:25 -0800218 }
Jonathan Hart539a6462015-01-27 17:05:43 -0800219
220 notifyDelegateIfNotNull(externalEvent);
221 }
Jonathan Hart5573d322015-01-21 10:13:25 -0800222 }
223 }
224
Jonathan Hart5573d322015-01-21 10:13:25 -0800225}
226