blob: 4fca6e0d8b5943fc5e3c4b38dc99453f2fc9caf7 [file] [log] [blame]
Jian Li75642312017-01-19 14:23:05 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Jian Li75642312017-01-19 14:23:05 -08003 *
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.mapping.impl;
17
Jian Li2c52e562017-03-02 00:15:45 +090018import com.google.common.collect.ImmutableList;
19import com.google.common.collect.Iterables;
20import com.google.common.collect.Maps;
Jian Li92919592017-02-27 17:10:47 +090021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
Jian Li2c52e562017-03-02 00:15:45 +090024import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
Jian Li92919592017-02-27 17:10:47 +090026import org.apache.felix.scr.annotations.Service;
Jian Li2c52e562017-03-02 00:15:45 +090027import org.onosproject.mapping.DefaultMapping;
28import org.onosproject.mapping.DefaultMappingEntry;
Jian Li92919592017-02-27 17:10:47 +090029import org.onosproject.mapping.Mapping;
Jian Li92919592017-02-27 17:10:47 +090030import org.onosproject.mapping.MappingEntry;
Jian Li2c52e562017-03-02 00:15:45 +090031import org.onosproject.mapping.MappingEvent;
32import org.onosproject.mapping.MappingId;
33import org.onosproject.mapping.MappingKey;
Jian Li75642312017-01-19 14:23:05 -080034import org.onosproject.mapping.MappingStore;
Jian Li95edb592017-01-29 08:42:07 +090035import org.onosproject.mapping.MappingStoreDelegate;
Jian Li2c52e562017-03-02 00:15:45 +090036import org.onosproject.mapping.MappingTreatment;
37import org.onosproject.mapping.MappingValue;
38import org.onosproject.mapping.actions.MappingAction;
39import org.onosproject.mapping.addresses.MappingAddress;
40import org.onosproject.mapping.instructions.MappingInstruction;
Jian Li92919592017-02-27 17:10:47 +090041import org.onosproject.net.DeviceId;
Jian Li2c52e562017-03-02 00:15:45 +090042import org.onosproject.net.device.DeviceService;
Jian Li92919592017-02-27 17:10:47 +090043import org.onosproject.store.AbstractStore;
Jian Li2c52e562017-03-02 00:15:45 +090044import org.onosproject.store.serializers.KryoNamespaces;
45import org.onosproject.store.service.ConsistentMap;
46import org.onosproject.store.service.MapEvent;
47import org.onosproject.store.service.MapEventListener;
48import org.onosproject.store.service.Serializer;
49import org.onosproject.store.service.StorageService;
Jian Li92919592017-02-27 17:10:47 +090050import org.slf4j.Logger;
51
Jian Li2c52e562017-03-02 00:15:45 +090052import java.util.Map;
53import java.util.concurrent.atomic.AtomicInteger;
54import java.util.stream.Collectors;
55
Jian Li92919592017-02-27 17:10:47 +090056import static org.slf4j.LoggerFactory.getLogger;
Jian Li75642312017-01-19 14:23:05 -080057
58/**
59 * Implementation of a distributed store for managing mapping information.
60 */
Jian Li92919592017-02-27 17:10:47 +090061@Component(immediate = true)
62@Service
63public class DistributedMappingStore
64 extends AbstractStore<MappingEvent, MappingStoreDelegate>
65 implements MappingStore {
66
67 private final Logger log = getLogger(getClass());
68
Jian Li2c52e562017-03-02 00:15:45 +090069 private ConsistentMap<MappingId, Mapping> database;
70 private ConsistentMap<MappingId, Mapping> cache;
71
72 private Map<MappingId, Mapping> databaseMap;
73 private Map<MappingId, Mapping> cacheMap;
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected StorageService storageService;
77
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 protected DeviceService deviceService;
80
81 private final MapEventListener<MappingId, Mapping> listener = new InternalListener();
82
Jian Li92919592017-02-27 17:10:47 +090083 @Activate
Jian Li2c52e562017-03-02 00:15:45 +090084 public void activate() {
85
86 Serializer serializer = Serializer.using(KryoNamespaces.API,
87 Mapping.class,
88 DefaultMapping.class,
89 MappingId.class,
90 MappingEvent.Type.class,
91 MappingKey.class,
92 MappingValue.class,
93 MappingAddress.class,
94 MappingAddress.Type.class,
95 MappingAction.class,
96 MappingAction.Type.class,
97 MappingTreatment.class,
98 MappingInstruction.class,
99 MappingInstruction.Type.class);
100
101 database = storageService.<MappingId, Mapping>consistentMapBuilder()
102 .withName("onos-mapping-database")
103 .withSerializer(serializer)
104 .build();
105
106 cache = storageService.<MappingId, Mapping>consistentMapBuilder()
107 .withName("onos-mapping-cache")
108 .withSerializer(serializer)
109 .build();
110
111 database.addListener(listener);
112 cache.addListener(listener);
113 databaseMap = database.asJavaMap();
114 cacheMap = cache.asJavaMap();
Jian Li92919592017-02-27 17:10:47 +0900115 log.info("Started");
116 }
117
118 @Deactivate
Jian Li2c52e562017-03-02 00:15:45 +0900119 public void deactivate() {
120 database.removeListener(listener);
121 cache.removeListener(listener);
Jian Li92919592017-02-27 17:10:47 +0900122 log.info("Stopped");
123 }
124
Jian Li2c52e562017-03-02 00:15:45 +0900125 /**
126 * Obtains map representation of mapping store.
127 *
128 * @param type mapping store type
129 * @return map representation of mapping store
130 */
131 private Map<MappingId, Mapping> getStoreMap(Type type) {
132 switch (type) {
133 case MAP_DATABASE:
134 return databaseMap;
135 case MAP_CACHE:
136 return cacheMap;
137 default:
138 log.warn("Unrecognized map store type {}", type);
139 return Maps.newConcurrentMap();
140 }
Jian Li95edb592017-01-29 08:42:07 +0900141 }
142
Jian Li2c52e562017-03-02 00:15:45 +0900143 /**
144 * Obtains mapping store.
145 *
146 * @param type mapping store type
147 * @return mapping store
148 */
149 private ConsistentMap<MappingId, Mapping> getStore(Type type) {
150 switch (type) {
151 case MAP_DATABASE:
152 return database;
153 case MAP_CACHE:
154 return cache;
155 default:
156 throw new IllegalArgumentException("Wrong mapping store " + type);
157 }
Jian Li95edb592017-01-29 08:42:07 +0900158 }
Jian Li92919592017-02-27 17:10:47 +0900159
160 @Override
161 public int getMappingCount(Type type) {
Jian Li2c52e562017-03-02 00:15:45 +0900162 AtomicInteger sum = new AtomicInteger(0);
163 deviceService.getDevices().forEach(device ->
164 sum.addAndGet(Iterables.size(getMappingEntries(type, device.id()))));
165 return sum.get();
Jian Li92919592017-02-27 17:10:47 +0900166 }
167
168 @Override
Jian Li791dd322017-04-20 00:15:56 +0900169 public Iterable<MappingEntry> getAllMappingEntries(Type type) {
170
171 Map<MappingId, Mapping> storeMap = getStoreMap(type);
172 return ImmutableList.copyOf(storeMap.values().stream()
173 .map(DefaultMappingEntry::new)
174 .collect(Collectors.toList()));
175 }
176
177 @Override
Jian Li92919592017-02-27 17:10:47 +0900178 public MappingEntry getMappingEntry(Type type, Mapping mapping) {
Jian Li2c52e562017-03-02 00:15:45 +0900179
180 return new DefaultMappingEntry(getStoreMap(type).get(mapping.id()));
Jian Li92919592017-02-27 17:10:47 +0900181 }
182
183 @Override
184 public Iterable<MappingEntry> getMappingEntries(Type type, DeviceId deviceId) {
Jian Li2c52e562017-03-02 00:15:45 +0900185
186 Map<MappingId, Mapping> storeMap = getStoreMap(type);
187 return ImmutableList.copyOf(storeMap.values().stream()
188 .filter(m -> m.deviceId() == deviceId)
189 .map(DefaultMappingEntry::new)
190 .collect(Collectors.toList()));
Jian Li92919592017-02-27 17:10:47 +0900191 }
192
193 @Override
Jian Lia1f960b2017-04-25 19:12:53 +0900194 public void storeMapping(Type type, MappingEntry mapping) {
Jian Li252750d2017-03-01 04:50:13 +0900195
Jian Li2c52e562017-03-02 00:15:45 +0900196 getStore(type).put(mapping.id(), mapping);
Jian Li252750d2017-03-01 04:50:13 +0900197 }
198
199 @Override
Jian Li2dc9f002017-03-03 04:26:31 +0900200 public MappingEvent removeMapping(Type type, Mapping mapping) {
Jian Li92919592017-02-27 17:10:47 +0900201
Jian Li2c52e562017-03-02 00:15:45 +0900202 getStore(type).remove(mapping.id());
Jian Li92919592017-02-27 17:10:47 +0900203 return null;
204 }
205
206 @Override
Jian Li2dc9f002017-03-03 04:26:31 +0900207 public void pendingDeleteMapping(Type type, Mapping mapping) {
208 // TODO: this will be implemented when management plane is ready
209 log.error("This method will be available when management plane is ready");
210 }
211
212 @Override
213 public MappingEvent addOrUpdateMappingEntry(Type type, MappingEntry entry) {
Jian Li2c52e562017-03-02 00:15:45 +0900214 // TODO: this will be implemented when management plane is ready
215 log.error("This method will be available when management plane is ready");
Jian Li92919592017-02-27 17:10:47 +0900216 return null;
217 }
218
219 @Override
220 public MappingEvent pendingMappingEntry(Type type, MappingEntry entry) {
Jian Li2c52e562017-03-02 00:15:45 +0900221 // TODO: this will be implemented when management plane is ready
222 log.error("This method will be available when management plane is ready");
Jian Li92919592017-02-27 17:10:47 +0900223 return null;
224 }
225
226 @Override
227 public void purgeMappingEntries(Type type) {
Jian Li2c52e562017-03-02 00:15:45 +0900228 getStore(type).clear();
229 }
Jian Li92919592017-02-27 17:10:47 +0900230
Jian Li2c52e562017-03-02 00:15:45 +0900231 /**
232 * Event listener to notify delegates about mapping events.
233 */
234 private class InternalListener implements MapEventListener<MappingId, Mapping> {
235
236 @Override
237 public void event(MapEvent<MappingId, Mapping> event) {
238 final MappingEvent.Type type;
239 final Mapping mapping;
240
241 switch (event.type()) {
242 case INSERT:
243 type = MappingEvent.Type.MAPPING_ADDED;
244 mapping = event.newValue().value();
245 break;
246 case UPDATE:
247 type = MappingEvent.Type.MAPPING_UPDATED;
248 mapping = event.newValue().value();
249 break;
250 case REMOVE:
251 type = MappingEvent.Type.MAPPING_REMOVED;
252 mapping = event.oldValue().value();
253 break;
254 default:
255 throw new IllegalArgumentException("Wrong event type " + event.type());
256 }
257 notifyDelegate(new MappingEvent(type, mapping));
258 }
Jian Li92919592017-02-27 17:10:47 +0900259 }
Jian Li75642312017-01-19 14:23:05 -0800260}