blob: 17439ef3bba750d0aded37f1a592d2132d9af1bb [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
Jonathan Hart5573d322015-01-21 10:13:25 -080018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
24import org.onlab.util.KryoNamespace;
25import org.onosproject.cluster.ClusterService;
Jonathan Hart5573d322015-01-21 10:13:25 -080026import org.onosproject.net.intent.BatchWrite;
27import org.onosproject.net.intent.Intent;
Jonathan Hart74c83132015-02-02 18:37:57 -080028import org.onosproject.net.intent.IntentData;
Jonathan Hart5573d322015-01-21 10:13:25 -080029import org.onosproject.net.intent.IntentEvent;
Jonathan Hart5573d322015-01-21 10:13:25 -080030import org.onosproject.net.intent.IntentState;
31import org.onosproject.net.intent.IntentStore;
32import org.onosproject.net.intent.IntentStoreDelegate;
Jonathan Hart74c83132015-02-02 18:37:57 -080033import org.onosproject.net.intent.Key;
Jonathan Hart5573d322015-01-21 10:13:25 -080034import 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;
Jonathan Hart5ec32ba2015-02-05 13:33:58 -080040import org.onosproject.store.impl.MultiValuedTimestamp;
41import org.onosproject.store.impl.SystemClockTimestamp;
Jonathan Hart539a6462015-01-27 17:05:43 -080042import org.onosproject.store.serializers.KryoNamespaces;
Jonathan Hart5573d322015-01-21 10:13:25 -080043import org.slf4j.Logger;
44
Jonathan Hart5573d322015-01-21 10:13:25 -080045import java.util.List;
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -080046import java.util.stream.Collectors;
Jonathan Hart5573d322015-01-21 10:13:25 -080047
Jonathan Hart5573d322015-01-21 10:13:25 -080048import static org.slf4j.LoggerFactory.getLogger;
49
50/**
51 * Manages inventory of Intents in a distributed data store that uses optimistic
52 * replication and gossip based techniques.
53 */
Brian O'Connorb488b192015-02-06 17:58:58 -080054@Component(immediate = false, enabled = false)
Jonathan Hart5573d322015-01-21 10:13:25 -080055@Service
56public class GossipIntentStore
57 extends AbstractStore<IntentEvent, IntentStoreDelegate>
58 implements IntentStore {
59
60 private final Logger log = getLogger(getClass());
61
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -080062 // Map of intent key => current intent state
63 private EventuallyConsistentMap<Key, IntentData> currentState;
Jonathan Hart5573d322015-01-21 10:13:25 -080064
Jonathan Hart74c83132015-02-02 18:37:57 -080065 // Map of intent key => pending intent operation
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -080066 private EventuallyConsistentMap<Key, IntentData> pending;
Jonathan Hart74c83132015-02-02 18:37:57 -080067
Jonathan Hart5573d322015-01-21 10:13:25 -080068 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
69 protected ClusterCommunicationService clusterCommunicator;
70
71 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
72 protected ClusterService clusterService;
73
Jonathan Hart74c83132015-02-02 18:37:57 -080074 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 protected PartitionService partitionService;
76
Jonathan Hart5573d322015-01-21 10:13:25 -080077 @Activate
78 public void activate() {
Jonathan Hart539a6462015-01-27 17:05:43 -080079 KryoNamespace.Builder intentSerializer = KryoNamespace.newBuilder()
Jonathan Hart5ec32ba2015-02-05 13:33:58 -080080 .register(KryoNamespaces.API)
81 .register(IntentData.class)
82 .register(MultiValuedTimestamp.class)
83 .register(SystemClockTimestamp.class);
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -080084
85 currentState = new EventuallyConsistentMapImpl<>("intent-current",
86 clusterService,
87 clusterCommunicator,
88 intentSerializer,
Jonathan Hart5ec32ba2015-02-05 13:33:58 -080089 new IntentDataLogicalClockManager<>());
Jonathan Hart5573d322015-01-21 10:13:25 -080090
Jonathan Hart74c83132015-02-02 18:37:57 -080091 pending = new EventuallyConsistentMapImpl<>("intent-pending",
92 clusterService,
93 clusterCommunicator,
94 intentSerializer, // TODO
Jonathan Hart5ec32ba2015-02-05 13:33:58 -080095 new IntentDataClockManager<>());
Jonathan Hart74c83132015-02-02 18:37:57 -080096
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -080097 currentState.addListener(new InternalIntentStatesListener());
Jonathan Hart74c83132015-02-02 18:37:57 -080098 pending.addListener(new InternalPendingListener());
Jonathan Hart5573d322015-01-21 10:13:25 -080099
100 log.info("Started");
101 }
102
103 @Deactivate
104 public void deactivate() {
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800105 currentState.destroy();
Jonathan Hart74c83132015-02-02 18:37:57 -0800106 pending.destroy();
Jonathan Hart5573d322015-01-21 10:13:25 -0800107
108 log.info("Stopped");
109 }
110
111 @Override
112 public long getIntentCount() {
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800113 return currentState.size();
Jonathan Hart5573d322015-01-21 10:13:25 -0800114 }
115
116 @Override
117 public Iterable<Intent> getIntents() {
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800118 return currentState.values().stream()
119 .map(IntentData::intent)
120 .collect(Collectors.toList());
Jonathan Hart5573d322015-01-21 10:13:25 -0800121 }
122
123 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800124 public IntentState getIntentState(Key intentKey) {
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800125 IntentData data = currentState.get(intentKey);
126 if (data != null) {
127 return data.state();
128 }
129 return null;
Jonathan Hart5573d322015-01-21 10:13:25 -0800130 }
131
132 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800133 public List<Intent> getInstallableIntents(Key intentKey) {
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800134 IntentData data = currentState.get(intentKey);
135 if (data != null) {
136 return data.installables();
137 }
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800138 return null;
Jonathan Hart5573d322015-01-21 10:13:25 -0800139 }
140
141 @Override
Jonathan Hart5573d322015-01-21 10:13:25 -0800142 public List<BatchWrite.Operation> batchWrite(BatchWrite batch) {
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800143 // Deprecated
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800144 return null;
Jonathan Hart5573d322015-01-21 10:13:25 -0800145 }
146
Jonathan Hart74c83132015-02-02 18:37:57 -0800147 @Override
148 public void write(IntentData newData) {
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800149 log.debug("writing intent {}", newData);
150
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800151 // Only the master is modifying the current state. Therefore assume
152 // this always succeeds
153 currentState.put(newData.key(), newData);
154
155 // if current.put succeeded
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800156 pending.remove(newData.key(), newData);
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800157
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800158 /*try {
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800159 notifyDelegate(IntentEvent.getEvent(newData));
160 } catch (IllegalArgumentException e) {
161 //no-op
162 log.trace("ignore this exception: {}", e);
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800163 }*/
Jonathan Hart74c83132015-02-02 18:37:57 -0800164 }
165
166 @Override
167 public void batchWrite(Iterable<IntentData> updates) {
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800168 updates.forEach(this::write);
169 }
170
171 @Override
172 public Intent getIntent(Key key) {
173 IntentData data = currentState.get(key);
174 if (data != null) {
175 return data.intent();
176 }
177 return null;
Jonathan Hart74c83132015-02-02 18:37:57 -0800178 }
179
180 @Override
Jonathan Hart74c83132015-02-02 18:37:57 -0800181 public IntentData getIntentData(Key key) {
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800182 return currentState.get(key);
Jonathan Hart74c83132015-02-02 18:37:57 -0800183 }
184
185 @Override
186 public void addPending(IntentData data) {
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800187 log.debug("new call to pending {}", data);
188 if (data.version() == null) {
189 log.debug("updating timestamp");
190 data.setVersion(new SystemClockTimestamp());
191 }
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800192 pending.put(data.key(), data);
Jonathan Hart74c83132015-02-02 18:37:57 -0800193 }
194
195 @Override
196 public boolean isMaster(Intent intent) {
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800197 return partitionService.isMine(intent.key());
Jonathan Hart74c83132015-02-02 18:37:57 -0800198 }
199
Jonathan Hart5573d322015-01-21 10:13:25 -0800200 private void notifyDelegateIfNotNull(IntentEvent event) {
201 if (event != null) {
202 notifyDelegate(event);
203 }
204 }
205
Jonathan Hart539a6462015-01-27 17:05:43 -0800206 private final class InternalIntentStatesListener implements
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800207 EventuallyConsistentMapListener<Key, IntentData> {
Jonathan Hart5573d322015-01-21 10:13:25 -0800208 @Override
Jonathan Hart539a6462015-01-27 17:05:43 -0800209 public void event(
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800210 EventuallyConsistentMapEvent<Key, IntentData> event) {
Jonathan Hart539a6462015-01-27 17:05:43 -0800211 if (event.type() == EventuallyConsistentMapEvent.Type.PUT) {
212 IntentEvent externalEvent;
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800213 IntentData intentData = event.value();
Jonathan Hart5573d322015-01-21 10:13:25 -0800214
Jonathan Hart5573d322015-01-21 10:13:25 -0800215 try {
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800216 externalEvent = IntentEvent.getEvent(intentData.state(), intentData.intent());
Jonathan Hart539a6462015-01-27 17:05:43 -0800217 } catch (IllegalArgumentException e) {
218 externalEvent = null;
Jonathan Hart5573d322015-01-21 10:13:25 -0800219 }
Jonathan Hart539a6462015-01-27 17:05:43 -0800220
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800221 notifyDelegateIfNotNull(externalEvent);
Jonathan Hart539a6462015-01-27 17:05:43 -0800222 }
Jonathan Hart5573d322015-01-21 10:13:25 -0800223 }
224 }
225
Jonathan Hart74c83132015-02-02 18:37:57 -0800226 private final class InternalPendingListener implements
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800227 EventuallyConsistentMapListener<Key, IntentData> {
Jonathan Hart74c83132015-02-02 18:37:57 -0800228 @Override
229 public void event(
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800230 EventuallyConsistentMapEvent<Key, IntentData> event) {
Jonathan Hart74c83132015-02-02 18:37:57 -0800231 if (event.type() == EventuallyConsistentMapEvent.Type.PUT) {
232 // The pending intents map has been updated. If we are master for
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800233 // this intent's partition, notify the Manager that it should do
Jonathan Hart74c83132015-02-02 18:37:57 -0800234 // some work.
235 if (isMaster(event.value().intent())) {
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -0800236 if (delegate != null) {
237 delegate.process(event.value());
238 }
Jonathan Hart74c83132015-02-02 18:37:57 -0800239 }
Jonathan Hart5ec32ba2015-02-05 13:33:58 -0800240
241 try {
242 notifyDelegate(IntentEvent.getEvent(event.value()));
243 } catch (IllegalArgumentException e) {
244 //no-op
245 log.trace("ignore this exception: {}", e);
246 }
Jonathan Hart74c83132015-02-02 18:37:57 -0800247 }
248 }
249 }
250
Jonathan Hart5573d322015-01-21 10:13:25 -0800251}
252