blob: 45944d97735da5fcb0db4060fc2baae1d1883e05 [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 Li2c52e562017-03-02 00:15:45 +090021import org.onosproject.mapping.DefaultMapping;
22import org.onosproject.mapping.DefaultMappingEntry;
Jian Li92919592017-02-27 17:10:47 +090023import org.onosproject.mapping.Mapping;
Jian Li92919592017-02-27 17:10:47 +090024import org.onosproject.mapping.MappingEntry;
Jian Li2c52e562017-03-02 00:15:45 +090025import org.onosproject.mapping.MappingEvent;
26import org.onosproject.mapping.MappingId;
27import org.onosproject.mapping.MappingKey;
Jian Li75642312017-01-19 14:23:05 -080028import org.onosproject.mapping.MappingStore;
Jian Li95edb592017-01-29 08:42:07 +090029import org.onosproject.mapping.MappingStoreDelegate;
Jian Li2c52e562017-03-02 00:15:45 +090030import org.onosproject.mapping.MappingTreatment;
31import org.onosproject.mapping.MappingValue;
32import org.onosproject.mapping.actions.MappingAction;
33import org.onosproject.mapping.addresses.MappingAddress;
34import org.onosproject.mapping.instructions.MappingInstruction;
Jian Li92919592017-02-27 17:10:47 +090035import org.onosproject.net.DeviceId;
Jian Li2c52e562017-03-02 00:15:45 +090036import org.onosproject.net.device.DeviceService;
Jian Li92919592017-02-27 17:10:47 +090037import org.onosproject.store.AbstractStore;
Jian Li2c52e562017-03-02 00:15:45 +090038import org.onosproject.store.serializers.KryoNamespaces;
39import org.onosproject.store.service.ConsistentMap;
40import org.onosproject.store.service.MapEvent;
41import org.onosproject.store.service.MapEventListener;
42import org.onosproject.store.service.Serializer;
43import org.onosproject.store.service.StorageService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070044import org.osgi.service.component.annotations.Activate;
45import org.osgi.service.component.annotations.Component;
46import org.osgi.service.component.annotations.Deactivate;
47import org.osgi.service.component.annotations.Reference;
48import org.osgi.service.component.annotations.ReferenceCardinality;
Jian Li92919592017-02-27 17:10:47 +090049import org.slf4j.Logger;
50
Jian Li2c52e562017-03-02 00:15:45 +090051import java.util.Map;
52import java.util.concurrent.atomic.AtomicInteger;
53import java.util.stream.Collectors;
54
Jian Li92919592017-02-27 17:10:47 +090055import static org.slf4j.LoggerFactory.getLogger;
Jian Li75642312017-01-19 14:23:05 -080056
57/**
58 * Implementation of a distributed store for managing mapping information.
59 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070060@Component(immediate = true, service = MappingStore.class)
Jian Li92919592017-02-27 17:10:47 +090061public class DistributedMappingStore
62 extends AbstractStore<MappingEvent, MappingStoreDelegate>
63 implements MappingStore {
64
65 private final Logger log = getLogger(getClass());
66
Jian Li2c52e562017-03-02 00:15:45 +090067 private ConsistentMap<MappingId, Mapping> database;
68 private ConsistentMap<MappingId, Mapping> cache;
69
70 private Map<MappingId, Mapping> databaseMap;
71 private Map<MappingId, Mapping> cacheMap;
72
Ray Milkeyd84f89b2018-08-17 14:54:17 -070073 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li2c52e562017-03-02 00:15:45 +090074 protected StorageService storageService;
75
Ray Milkeyd84f89b2018-08-17 14:54:17 -070076 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jian Li2c52e562017-03-02 00:15:45 +090077 protected DeviceService deviceService;
78
79 private final MapEventListener<MappingId, Mapping> listener = new InternalListener();
80
Jian Li92919592017-02-27 17:10:47 +090081 @Activate
Jian Li2c52e562017-03-02 00:15:45 +090082 public void activate() {
83
84 Serializer serializer = Serializer.using(KryoNamespaces.API,
85 Mapping.class,
86 DefaultMapping.class,
87 MappingId.class,
88 MappingEvent.Type.class,
89 MappingKey.class,
90 MappingValue.class,
91 MappingAddress.class,
92 MappingAddress.Type.class,
93 MappingAction.class,
94 MappingAction.Type.class,
95 MappingTreatment.class,
96 MappingInstruction.class,
97 MappingInstruction.Type.class);
98
99 database = storageService.<MappingId, Mapping>consistentMapBuilder()
100 .withName("onos-mapping-database")
101 .withSerializer(serializer)
102 .build();
103
104 cache = storageService.<MappingId, Mapping>consistentMapBuilder()
105 .withName("onos-mapping-cache")
106 .withSerializer(serializer)
107 .build();
108
109 database.addListener(listener);
110 cache.addListener(listener);
111 databaseMap = database.asJavaMap();
112 cacheMap = cache.asJavaMap();
Jian Li92919592017-02-27 17:10:47 +0900113 log.info("Started");
114 }
115
116 @Deactivate
Jian Li2c52e562017-03-02 00:15:45 +0900117 public void deactivate() {
118 database.removeListener(listener);
119 cache.removeListener(listener);
Jian Li92919592017-02-27 17:10:47 +0900120 log.info("Stopped");
121 }
122
Jian Li2c52e562017-03-02 00:15:45 +0900123 /**
124 * Obtains map representation of mapping store.
125 *
126 * @param type mapping store type
127 * @return map representation of mapping store
128 */
129 private Map<MappingId, Mapping> getStoreMap(Type type) {
130 switch (type) {
131 case MAP_DATABASE:
132 return databaseMap;
133 case MAP_CACHE:
134 return cacheMap;
135 default:
136 log.warn("Unrecognized map store type {}", type);
137 return Maps.newConcurrentMap();
138 }
Jian Li95edb592017-01-29 08:42:07 +0900139 }
140
Jian Li2c52e562017-03-02 00:15:45 +0900141 /**
142 * Obtains mapping store.
143 *
144 * @param type mapping store type
145 * @return mapping store
146 */
147 private ConsistentMap<MappingId, Mapping> getStore(Type type) {
148 switch (type) {
149 case MAP_DATABASE:
150 return database;
151 case MAP_CACHE:
152 return cache;
153 default:
154 throw new IllegalArgumentException("Wrong mapping store " + type);
155 }
Jian Li95edb592017-01-29 08:42:07 +0900156 }
Jian Li92919592017-02-27 17:10:47 +0900157
158 @Override
159 public int getMappingCount(Type type) {
Jian Li2c52e562017-03-02 00:15:45 +0900160 AtomicInteger sum = new AtomicInteger(0);
161 deviceService.getDevices().forEach(device ->
162 sum.addAndGet(Iterables.size(getMappingEntries(type, device.id()))));
163 return sum.get();
Jian Li92919592017-02-27 17:10:47 +0900164 }
165
166 @Override
Jian Li791dd322017-04-20 00:15:56 +0900167 public Iterable<MappingEntry> getAllMappingEntries(Type type) {
168
169 Map<MappingId, Mapping> storeMap = getStoreMap(type);
170 return ImmutableList.copyOf(storeMap.values().stream()
171 .map(DefaultMappingEntry::new)
172 .collect(Collectors.toList()));
173 }
174
175 @Override
Jian Li92919592017-02-27 17:10:47 +0900176 public MappingEntry getMappingEntry(Type type, Mapping mapping) {
Jian Li2c52e562017-03-02 00:15:45 +0900177
178 return new DefaultMappingEntry(getStoreMap(type).get(mapping.id()));
Jian Li92919592017-02-27 17:10:47 +0900179 }
180
181 @Override
182 public Iterable<MappingEntry> getMappingEntries(Type type, DeviceId deviceId) {
Jian Li2c52e562017-03-02 00:15:45 +0900183
184 Map<MappingId, Mapping> storeMap = getStoreMap(type);
185 return ImmutableList.copyOf(storeMap.values().stream()
186 .filter(m -> m.deviceId() == deviceId)
187 .map(DefaultMappingEntry::new)
188 .collect(Collectors.toList()));
Jian Li92919592017-02-27 17:10:47 +0900189 }
190
191 @Override
Jian Lia1f960b2017-04-25 19:12:53 +0900192 public void storeMapping(Type type, MappingEntry mapping) {
Jian Li252750d2017-03-01 04:50:13 +0900193
Jian Li2c52e562017-03-02 00:15:45 +0900194 getStore(type).put(mapping.id(), mapping);
Jian Li252750d2017-03-01 04:50:13 +0900195 }
196
197 @Override
Jian Li2dc9f002017-03-03 04:26:31 +0900198 public MappingEvent removeMapping(Type type, Mapping mapping) {
Jian Li92919592017-02-27 17:10:47 +0900199
Jian Li2c52e562017-03-02 00:15:45 +0900200 getStore(type).remove(mapping.id());
Jian Li92919592017-02-27 17:10:47 +0900201 return null;
202 }
203
204 @Override
Jian Li2dc9f002017-03-03 04:26:31 +0900205 public void pendingDeleteMapping(Type type, Mapping mapping) {
206 // TODO: this will be implemented when management plane is ready
207 log.error("This method will be available when management plane is ready");
208 }
209
210 @Override
211 public MappingEvent addOrUpdateMappingEntry(Type type, MappingEntry entry) {
Jian Li2c52e562017-03-02 00:15:45 +0900212 // TODO: this will be implemented when management plane is ready
213 log.error("This method will be available when management plane is ready");
Jian Li92919592017-02-27 17:10:47 +0900214 return null;
215 }
216
217 @Override
218 public MappingEvent pendingMappingEntry(Type type, MappingEntry entry) {
Jian Li2c52e562017-03-02 00:15:45 +0900219 // TODO: this will be implemented when management plane is ready
220 log.error("This method will be available when management plane is ready");
Jian Li92919592017-02-27 17:10:47 +0900221 return null;
222 }
223
224 @Override
225 public void purgeMappingEntries(Type type) {
Jian Li2c52e562017-03-02 00:15:45 +0900226 getStore(type).clear();
227 }
Jian Li92919592017-02-27 17:10:47 +0900228
Jian Li2c52e562017-03-02 00:15:45 +0900229 /**
230 * Event listener to notify delegates about mapping events.
231 */
232 private class InternalListener implements MapEventListener<MappingId, Mapping> {
233
234 @Override
235 public void event(MapEvent<MappingId, Mapping> event) {
236 final MappingEvent.Type type;
237 final Mapping mapping;
238
239 switch (event.type()) {
240 case INSERT:
241 type = MappingEvent.Type.MAPPING_ADDED;
242 mapping = event.newValue().value();
243 break;
244 case UPDATE:
245 type = MappingEvent.Type.MAPPING_UPDATED;
246 mapping = event.newValue().value();
247 break;
248 case REMOVE:
249 type = MappingEvent.Type.MAPPING_REMOVED;
250 mapping = event.oldValue().value();
251 break;
252 default:
253 throw new IllegalArgumentException("Wrong event type " + event.type());
254 }
255 notifyDelegate(new MappingEvent(type, mapping));
256 }
Jian Li92919592017-02-27 17:10:47 +0900257 }
Jian Li75642312017-01-19 14:23:05 -0800258}