blob: 17d8dcbaa64a7cccf9932ef313e6d296ec857c38 [file] [log] [blame]
Thomas Vachuska33979fd2015-07-31 11:41:14 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuska33979fd2015-07-31 11:41:14 -07003 *
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.incubator.store.virtual.impl;
17
Brian Stanke0e5c94e2016-03-08 11:20:04 -050018import com.google.common.collect.ImmutableSet;
19import com.google.common.collect.Sets;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050023import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070025import org.apache.felix.scr.annotations.Service;
Brian Stanke7a81b532016-06-14 15:43:51 -040026import org.onlab.packet.IpAddress;
27import org.onlab.packet.MacAddress;
28import org.onlab.packet.VlanId;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050029import org.onlab.util.KryoNamespace;
30import org.onosproject.core.CoreService;
31import org.onosproject.core.IdGenerator;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070032import org.onosproject.incubator.net.tunnel.TunnelId;
33import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
Brian Stanke7a81b532016-06-14 15:43:51 -040034import org.onosproject.incubator.net.virtual.DefaultVirtualHost;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050035import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070036import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050037import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070038import org.onosproject.incubator.net.virtual.NetworkId;
39import org.onosproject.incubator.net.virtual.TenantId;
40import org.onosproject.incubator.net.virtual.VirtualDevice;
Brian Stanke7a81b532016-06-14 15:43:51 -040041import org.onosproject.incubator.net.virtual.VirtualHost;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070042import org.onosproject.incubator.net.virtual.VirtualLink;
43import org.onosproject.incubator.net.virtual.VirtualNetwork;
44import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
Brian Stanke11f6d532016-07-05 16:17:59 -040045import org.onosproject.incubator.net.virtual.VirtualNetworkIntent;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050046import org.onosproject.incubator.net.virtual.VirtualNetworkService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070047import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
48import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
49import org.onosproject.incubator.net.virtual.VirtualPort;
50import org.onosproject.net.ConnectPoint;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050051import org.onosproject.net.Device;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070052import org.onosproject.net.DeviceId;
Brian Stanke7a81b532016-06-14 15:43:51 -040053import org.onosproject.net.HostId;
54import org.onosproject.net.HostLocation;
Brian Stanke612cebf2016-05-02 10:21:33 -040055import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070056import org.onosproject.net.PortNumber;
Brian Stanke11f6d532016-07-05 16:17:59 -040057import org.onosproject.net.intent.Intent;
58import org.onosproject.net.intent.IntentData;
59import org.onosproject.net.intent.IntentState;
60import org.onosproject.net.intent.Key;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070061import org.onosproject.store.AbstractStore;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050062import org.onosproject.store.serializers.KryoNamespaces;
63import org.onosproject.store.service.ConsistentMap;
64import org.onosproject.store.service.DistributedSet;
65import org.onosproject.store.service.MapEvent;
66import org.onosproject.store.service.MapEventListener;
67import org.onosproject.store.service.Serializer;
68import org.onosproject.store.service.SetEvent;
69import org.onosproject.store.service.SetEventListener;
70import org.onosproject.store.service.StorageService;
Brian Stanke11f6d532016-07-05 16:17:59 -040071import org.onosproject.store.service.WallClockTimestamp;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070072import org.slf4j.Logger;
73
Brian Stanke0e5c94e2016-03-08 11:20:04 -050074import java.util.HashSet;
75import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070076import java.util.Set;
Claudine Chiu7f872a72016-12-16 13:51:39 -050077import java.util.concurrent.atomic.AtomicBoolean;
Claudine Chiu945828d2016-11-21 12:47:07 -050078import java.util.function.BiFunction;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070079
Brian Stanke0e5c94e2016-03-08 11:20:04 -050080import static com.google.common.base.Preconditions.checkNotNull;
81import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070082import static org.slf4j.LoggerFactory.getLogger;
83
84/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050085 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070086 */
87@Component(immediate = true)
88@Service
89public class DistributedVirtualNetworkStore
90 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
91 implements VirtualNetworkStore {
92
93 private final Logger log = getLogger(getClass());
94
Brian Stanke0e5c94e2016-03-08 11:20:04 -050095 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070097
Brian Stanke0e5c94e2016-03-08 11:20:04 -050098 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700100
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500101 private IdGenerator idGenerator;
102
103 // Track tenants by ID
104 private DistributedSet<TenantId> tenantIdSet;
105
106 // Listener for tenant events
107 private final SetEventListener<TenantId> setListener = new InternalSetListener();
108
109 // Track virtual networks by network Id
110 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
111 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
112
113 // Listener for virtual network events
Claudine Chiu945828d2016-11-21 12:47:07 -0500114 private final MapEventListener<NetworkId, VirtualNetwork> virtualNetworkMapListener =
115 new InternalMapListener<>((mapEventType, virtualNetwork) -> {
116 VirtualNetworkEvent.Type eventType =
117 mapEventType.equals(MapEvent.Type.INSERT) ? VirtualNetworkEvent.Type.NETWORK_ADDED :
118 mapEventType.equals(MapEvent.Type.UPDATE) ? VirtualNetworkEvent.Type.NETWORK_UPDATED :
119 mapEventType.equals(MapEvent.Type.REMOVE) ? VirtualNetworkEvent.Type.NETWORK_REMOVED : null;
120 return eventType == null ? null : new VirtualNetworkEvent(eventType, virtualNetwork.id());
121 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500122
123 // Track virtual network IDs by tenant Id
124 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
125 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
126
127 // Track virtual devices by device Id
128 private ConsistentMap<DeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
129 private Map<DeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
130
Claudine Chiu945828d2016-11-21 12:47:07 -0500131 // Listener for virtual device events
132 private final MapEventListener<DeviceId, VirtualDevice> virtualDeviceMapListener =
133 new InternalMapListener<>((mapEventType, virtualDevice) -> {
134 VirtualNetworkEvent.Type eventType =
135 mapEventType.equals(MapEvent.Type.INSERT) ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_ADDED :
136 mapEventType.equals(MapEvent.Type.UPDATE) ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_UPDATED :
137 mapEventType.equals(MapEvent.Type.REMOVE) ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_REMOVED : null;
138 return eventType == null ? null :
139 new VirtualNetworkEvent(eventType, virtualDevice.networkId(), virtualDevice);
140 });
141
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500142 // Track device IDs by network Id
143 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
144 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
145
Brian Stanke7a81b532016-06-14 15:43:51 -0400146 // Track virtual hosts by host Id
147 private ConsistentMap<HostId, VirtualHost> hostIdVirtualHostConsistentMap;
148 private Map<HostId, VirtualHost> hostIdVirtualHostMap;
149
150 // Track host IDs by network Id
151 private ConsistentMap<NetworkId, Set<HostId>> networkIdHostIdSetConsistentMap;
152 private Map<NetworkId, Set<HostId>> networkIdHostIdSetMap;
153
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500154 // Track virtual links by network Id
155 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
156 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
157
158 // Track virtual ports by network Id
159 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
160 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
161
Brian Stanke11f6d532016-07-05 16:17:59 -0400162 // Track intent key to intent data
163 private ConsistentMap<Key, IntentData> intentKeyIntentDataConsistentMap;
164 private Map<Key, IntentData> intentKeyIntentDataMap;
165
166 // Track intent ID to TunnelIds
167 private ConsistentMap<Key, Set<TunnelId>> intentKeyTunnelIdSetConsistentMap;
168 private Map<Key, Set<TunnelId>> intentKeyTunnelIdSetMap;
169
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500170 private static final Serializer SERIALIZER = Serializer
171 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
172 .register(TenantId.class)
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700173 .register(NetworkId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500174 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500175 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500176 .register(VirtualDevice.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500177 .register(DefaultVirtualDevice.class)
Brian Stanke7a81b532016-06-14 15:43:51 -0400178 .register(VirtualHost.class)
179 .register(DefaultVirtualHost.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500180 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500181 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500182 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500183 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500184 .register(Device.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400185 .register(TunnelId.class)
Brian Stanke11f6d532016-07-05 16:17:59 -0400186 .register(IntentData.class)
187 .register(VirtualNetworkIntent.class)
188 .register(WallClockTimestamp.class)
HIGUCHI Yuta03666a32016-05-18 11:49:09 -0700189 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
Brian Stanke11f6d532016-07-05 16:17:59 -0400190 .build());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500191
192 /**
193 * Distributed network store service activate method.
194 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700195 @Activate
196 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500197 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
198
199 tenantIdSet = storageService.<TenantId>setBuilder()
200 .withSerializer(SERIALIZER)
201 .withName("onos-tenantId")
202 .withRelaxedReadConsistency()
203 .build()
204 .asDistributedSet();
205 tenantIdSet.addListener(setListener);
206
207 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
208 .withSerializer(SERIALIZER)
209 .withName("onos-networkId-virtualnetwork")
210 .withRelaxedReadConsistency()
211 .build();
Claudine Chiu945828d2016-11-21 12:47:07 -0500212 networkIdVirtualNetworkConsistentMap.addListener(virtualNetworkMapListener);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500213 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
214
215 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
216 .withSerializer(SERIALIZER)
217 .withName("onos-tenantId-networkIds")
218 .withRelaxedReadConsistency()
219 .build();
220 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
221
222 deviceIdVirtualDeviceConsistentMap = storageService.<DeviceId, VirtualDevice>consistentMapBuilder()
223 .withSerializer(SERIALIZER)
224 .withName("onos-deviceId-virtualdevice")
225 .withRelaxedReadConsistency()
226 .build();
Claudine Chiu945828d2016-11-21 12:47:07 -0500227 deviceIdVirtualDeviceConsistentMap.addListener(virtualDeviceMapListener);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500228 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
229
230 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
231 .withSerializer(SERIALIZER)
232 .withName("onos-networkId-deviceIds")
233 .withRelaxedReadConsistency()
234 .build();
235 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
236
Brian Stanke7a81b532016-06-14 15:43:51 -0400237 hostIdVirtualHostConsistentMap = storageService.<HostId, VirtualHost>consistentMapBuilder()
238 .withSerializer(SERIALIZER)
239 .withName("onos-hostId-virtualhost")
240 .withRelaxedReadConsistency()
241 .build();
242 hostIdVirtualHostMap = hostIdVirtualHostConsistentMap.asJavaMap();
243
244 networkIdHostIdSetConsistentMap = storageService.<NetworkId, Set<HostId>>consistentMapBuilder()
245 .withSerializer(SERIALIZER)
246 .withName("onos-networkId-hostIds")
247 .withRelaxedReadConsistency()
248 .build();
249 networkIdHostIdSetMap = networkIdHostIdSetConsistentMap.asJavaMap();
250
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500251 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
252 .withSerializer(SERIALIZER)
253 .withName("onos-networkId-virtuallinks")
254 .withRelaxedReadConsistency()
255 .build();
256 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
257
258 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
259 .withSerializer(SERIALIZER)
Brian Stanke11f6d532016-07-05 16:17:59 -0400260 .withName("onos-networkId-virtualports")
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500261 .withRelaxedReadConsistency()
262 .build();
263 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
264
Brian Stanke11f6d532016-07-05 16:17:59 -0400265 intentKeyTunnelIdSetConsistentMap = storageService.<Key, Set<TunnelId>>consistentMapBuilder()
266 .withSerializer(SERIALIZER)
267 .withName("onos-intentKey-tunnelIds")
268 .withRelaxedReadConsistency()
269 .build();
270 intentKeyTunnelIdSetMap = intentKeyTunnelIdSetConsistentMap.asJavaMap();
271
272 intentKeyIntentDataConsistentMap = storageService.<Key, IntentData>consistentMapBuilder()
273 .withSerializer(SERIALIZER)
274 .withName("onos-intentKey-intentData")
275 .withRelaxedReadConsistency()
276 .build();
277 intentKeyIntentDataMap = intentKeyIntentDataConsistentMap.asJavaMap();
278
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700279 log.info("Started");
280 }
281
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500282 /**
283 * Distributed network store service deactivate method.
284 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700285 @Deactivate
286 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500287 tenantIdSet.removeListener(setListener);
Claudine Chiu945828d2016-11-21 12:47:07 -0500288 networkIdVirtualNetworkConsistentMap.removeListener(virtualNetworkMapListener);
289 deviceIdVirtualDeviceConsistentMap.removeListener(virtualDeviceMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700290 log.info("Stopped");
291 }
292
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500293 /**
294 * This method is used for Junit tests to set the CoreService instance, which
295 * is required to set the IdGenerator instance.
296 *
297 * @param coreService core service instance
298 */
299 public void setCoreService(CoreService coreService) {
300 this.coreService = coreService;
301 }
302
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700303 @Override
304 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500305 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700306 }
307
308 @Override
309 public void removeTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500310 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700311 }
312
313 @Override
314 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500315 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700316 }
317
318 @Override
319 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500320
321 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
322 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
323 //TODO update both maps in one transaction.
324 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500325
326 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
327 if (networkIdSet == null) {
328 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500329 }
Brian Stanke5df14472016-03-11 19:34:38 -0500330 networkIdSet.add(virtualNetwork.id());
331 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
332
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500333 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700334 }
335
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500336 /**
337 * Returns a new network identifier from a virtual network block of identifiers.
338 *
339 * @return NetworkId network identifier
340 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700341 private NetworkId genNetworkId() {
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900342 NetworkId networkId;
343 do {
344 networkId = NetworkId.networkId(idGenerator.getNewId());
345 } while (!networkId.isVirtualNetworkId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700346
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900347 return networkId;
348 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700349
350 @Override
351 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500352 // Make sure that the virtual network exists before attempting to remove it.
353 if (networkExists(networkId)) {
Brian Stanke5df14472016-03-11 19:34:38 -0500354 //TODO update both maps in one transaction.
355
356 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500357 if (virtualNetwork == null) {
358 return;
359 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500360 TenantId tenantId = virtualNetwork.tenantId();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500361
Brian Stanke5df14472016-03-11 19:34:38 -0500362 Set<NetworkId> networkIdSet = new HashSet<>();
363 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
364 if (networkId1.id().equals(networkId.id())) {
365 networkIdSet.add(networkId1);
366 }
367 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500368
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500369 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
370 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700371 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500372 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700373 return new HashSet<>(Sets.difference(existingNetworkIds, networkIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500374 }
375 });
376 }
377 }
378
379 /**
380 * Returns if the network identifier exists.
381 *
382 * @param networkId network identifier
383 * @return true if the network identifier exists, false otherwise.
384 */
385 private boolean networkExists(NetworkId networkId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400386 checkNotNull(networkId, "The network identifier cannot be null.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500387 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700388 }
389
390 @Override
391 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500392 checkState(networkExists(networkId), "The network has not been added.");
393 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
394 if (deviceIdSet == null) {
395 deviceIdSet = new HashSet<>();
396 }
397 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
398 //TODO update both maps in one transaction.
399 deviceIdVirtualDeviceMap.put(deviceId, virtualDevice);
400 deviceIdSet.add(deviceId);
401 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
402 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700403 }
404
405 @Override
406 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500407 checkState(networkExists(networkId), "The network has not been added.");
408 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500409
410 Set<DeviceId> deviceIdSet = new HashSet<>();
411 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
412 if (deviceId1.equals(deviceId)) {
413 deviceIdSet.add(deviceId1);
414 }
415 });
416
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500417 if (deviceIdSet != null) {
418 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
419 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700420 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500421 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700422 return new HashSet<>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500423 }
424 });
425
Brian Stanke5df14472016-03-11 19:34:38 -0500426 deviceIdVirtualDeviceMap.remove(deviceId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500427 }
Brian Stanke7a81b532016-06-14 15:43:51 -0400428 //TODO remove virtual links and ports when removing the virtual device
429 }
430
431 @Override
432 public VirtualHost addHost(NetworkId networkId, HostId hostId, MacAddress mac,
433 VlanId vlan, HostLocation location, Set<IpAddress> ips) {
434 checkState(networkExists(networkId), "The network has not been added.");
435 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
436 if (hostIdSet == null) {
437 hostIdSet = new HashSet<>();
438 }
439 VirtualHost virtualhost = new DefaultVirtualHost(networkId, hostId, mac, vlan, location, ips);
440 //TODO update both maps in one transaction.
441 hostIdVirtualHostMap.put(hostId, virtualhost);
442 hostIdSet.add(hostId);
443 networkIdHostIdSetMap.put(networkId, hostIdSet);
444 return virtualhost;
445 }
446
447 @Override
448 public void removeHost(NetworkId networkId, HostId hostId) {
449 checkState(networkExists(networkId), "The network has not been added.");
450 //TODO update both maps in one transaction.
451
452 Set<HostId> hostIdSet = new HashSet<>();
453 networkIdHostIdSetMap.get(networkId).forEach(hostId1 -> {
454 if (hostId1.equals(hostId)) {
455 hostIdSet.add(hostId1);
456 }
457 });
458
459 if (hostIdSet != null) {
460 networkIdHostIdSetMap.compute(networkId, (id, existingHostIds) -> {
461 if (existingHostIds == null || existingHostIds.isEmpty()) {
462 return new HashSet<>();
463 } else {
464 return new HashSet<>(Sets.difference(existingHostIds, hostIdSet));
465 }
466 });
467
468 hostIdVirtualHostMap.remove(hostId);
469 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700470 }
471
472 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400473 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
474 Link.State state, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500475 checkState(networkExists(networkId), "The network has not been added.");
476 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
477 if (virtualLinkSet == null) {
478 virtualLinkSet = new HashSet<>();
479 }
Brian Stanke9a108972016-04-11 15:25:17 -0400480 // validate that the link does not already exist in this network
481 checkState(getLink(networkId, src, dst) == null, "The virtual link already exists");
482
483 VirtualLink virtualLink = DefaultVirtualLink.builder()
484 .networkId(networkId)
485 .src(src)
486 .dst(dst)
Brian Stanke612cebf2016-05-02 10:21:33 -0400487 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400488 .tunnelId(realizedBy)
489 .build();
490
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500491 virtualLinkSet.add(virtualLink);
492 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
493 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700494 }
495
496 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400497 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state) {
Brian Stanke9a108972016-04-11 15:25:17 -0400498 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
499 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
500 if (virtualLinkSet == null) {
501 virtualLinkSet = new HashSet<>();
502 }
503 virtualLinkSet.remove(virtualLink);
504
505 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
506 .networkId(virtualLink.networkId())
507 .src(virtualLink.src())
508 .dst(virtualLink.dst())
509 .tunnelId(tunnelId)
Brian Stanke612cebf2016-05-02 10:21:33 -0400510 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400511 .build();
512
513 virtualLinkSet.add(newVirtualLink);
514 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
515 }
516
517 @Override
518 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500519 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500520
Brian Stanke9a108972016-04-11 15:25:17 -0400521 final VirtualLink virtualLink = getLink(networkId, src, dst);
522 if (virtualLink == null) {
523 return null;
524 }
Brian Stanke5df14472016-03-11 19:34:38 -0500525 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400526 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500527
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500528 if (virtualLinkSet != null) {
529 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
530 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700531 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500532 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700533 return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500534 }
535 });
536 }
Brian Stanke9a108972016-04-11 15:25:17 -0400537 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700538 }
539
540 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700541 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId,
542 PortNumber portNumber, ConnectPoint realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500543 checkState(networkExists(networkId), "The network has not been added.");
544 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700545
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500546 if (virtualPortSet == null) {
547 virtualPortSet = new HashSet<>();
548 }
Yoonseon Han6c603892016-09-01 11:52:21 -0700549
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500550 Device device = deviceIdVirtualDeviceMap.get(deviceId);
551 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700552
553 boolean exist = virtualPortSet.stream().anyMatch(
554 p -> p.element().id().equals(deviceId) &&
555 p.number().equals(portNumber));
556 checkState(!exist, "The requested Port Number is already in use");
557
558 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device,
559 portNumber, realizedBy);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500560 virtualPortSet.add(virtualPort);
561 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
Claudine Chiu7f872a72016-12-16 13:51:39 -0500562 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_ADDED,
563 networkId, virtualPort));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500564 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700565 }
566
567 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700568 public void bindPort(NetworkId networkId, DeviceId deviceId,
569 PortNumber portNumber, ConnectPoint realizedBy) {
570
571 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap
572 .get(networkId);
573
574 VirtualPort vPort = virtualPortSet.stream().filter(
575 p -> p.element().id().equals(deviceId) &&
576 p.number().equals(portNumber)).findFirst().get();
577 checkNotNull(vPort, "The virtual port has not been added.");
578
579 Device device = deviceIdVirtualDeviceMap.get(deviceId);
580 checkNotNull(device, "The device has not been created for deviceId: "
581 + deviceId);
582
583 virtualPortSet.remove(vPort);
584 vPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
585 virtualPortSet.add(vPort);
586 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
Claudine Chiu7f872a72016-12-16 13:51:39 -0500587 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_UPDATED,
588 networkId, vPort));
Yoonseon Han6c603892016-09-01 11:52:21 -0700589 }
590
591 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700592 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500593 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500594
595 Set<VirtualPort> virtualPortSet = new HashSet<>();
596 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
597 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
598 virtualPortSet.add(port);
599 }
600 });
601
Claudine Chiu7f872a72016-12-16 13:51:39 -0500602 if (!virtualPortSet.isEmpty()) {
603 AtomicBoolean portRemoved = new AtomicBoolean(false);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500604 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
605 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700606 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500607 } else {
Claudine Chiu7f872a72016-12-16 13:51:39 -0500608 portRemoved.set(true);
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700609 return new HashSet<>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500610 }
611 });
Claudine Chiu7f872a72016-12-16 13:51:39 -0500612 if (portRemoved.get()) {
613 virtualPortSet.forEach(virtualPort -> notifyDelegate(
614 new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_REMOVED,
615 networkId, virtualPort)
616 ));
617 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500618 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700619 }
620
621 @Override
622 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500623 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
624 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
625 if (networkIdSet != null) {
626 networkIdSet.forEach(networkId -> virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId)));
627 }
628 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700629 }
630
631 @Override
Brian Stanke86914282016-05-25 15:36:50 -0400632 public VirtualNetwork getNetwork(NetworkId networkId) {
633 return networkIdVirtualNetworkMap.get(networkId);
634 }
635
636 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700637 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500638 checkState(networkExists(networkId), "The network has not been added.");
639 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
640 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
641 if (deviceIdSet != null) {
642 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(deviceIdVirtualDeviceMap.get(deviceId)));
643 }
644 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700645 }
646
647 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400648 public Set<VirtualHost> getHosts(NetworkId networkId) {
649 checkState(networkExists(networkId), "The network has not been added.");
650 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
651 Set<VirtualHost> virtualHostSet = new HashSet<>();
652 if (hostIdSet != null) {
653 hostIdSet.forEach(hostId -> virtualHostSet.add(hostIdVirtualHostMap.get(hostId)));
654 }
655 return ImmutableSet.copyOf(virtualHostSet);
656 }
657
658 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700659 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500660 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500661 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
662 if (virtualLinkSet == null) {
663 virtualLinkSet = new HashSet<>();
664 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500665 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700666 }
667
Brian Stanke612cebf2016-05-02 10:21:33 -0400668 @Override
669 public VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke9a108972016-04-11 15:25:17 -0400670 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
671 if (virtualLinkSet == null) {
672 return null;
673 }
674
675 VirtualLink virtualLink = null;
676 for (VirtualLink link : virtualLinkSet) {
677 if (link.src().equals(src) && link.dst().equals(dst)) {
678 virtualLink = link;
679 break;
680 }
681 }
682 return virtualLink;
683 }
684
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700685 @Override
686 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500687 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500688 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
689 if (virtualPortSet == null) {
690 virtualPortSet = new HashSet<>();
691 }
692
Brian Stanke612cebf2016-05-02 10:21:33 -0400693 if (deviceId == null) {
694 return ImmutableSet.copyOf(virtualPortSet);
695 }
696
Brian Stanke5df14472016-03-11 19:34:38 -0500697 Set<VirtualPort> portSet = new HashSet<>();
698 virtualPortSet.forEach(virtualPort -> {
699 if (virtualPort.element().id().equals(deviceId)) {
700 portSet.add(virtualPort);
701 }
702 });
703 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500704 }
705
Brian Stanke11f6d532016-07-05 16:17:59 -0400706 @Override
707 public synchronized void addOrUpdateIntent(Intent intent, IntentState state) {
708 checkNotNull(intent, "Intent cannot be null");
709 IntentData intentData = removeIntent(intent.key());
710 if (intentData == null) {
711 intentData = new IntentData(intent, state, new WallClockTimestamp(System.currentTimeMillis()));
712 } else {
713 intentData = new IntentData(intent, state, intentData.version());
714 }
715 intentKeyIntentDataMap.put(intent.key(), intentData);
716 }
717
718 @Override
719 public IntentData removeIntent(Key intentKey) {
720 checkNotNull(intentKey, "Intent key cannot be null");
721 return intentKeyIntentDataMap.remove(intentKey);
722 }
723
724 @Override
725 public void addTunnelId(Intent intent, TunnelId tunnelId) {
726 // Add the tunnelId to the intent key set map
727 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.remove(intent.key());
728 if (tunnelIdSet == null) {
729 tunnelIdSet = new HashSet<>();
730 }
731 tunnelIdSet.add(tunnelId);
732 intentKeyTunnelIdSetMap.put(intent.key(), tunnelIdSet);
733 }
734
735 @Override
736 public Set<TunnelId> getTunnelIds(Intent intent) {
737 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.get(intent.key());
738 return tunnelIdSet == null ? new HashSet<TunnelId>() : ImmutableSet.copyOf(tunnelIdSet);
739 }
740
741 @Override
742 public void removeTunnelId(Intent intent, TunnelId tunnelId) {
743 Set<TunnelId> tunnelIdSet = new HashSet<>();
744 intentKeyTunnelIdSetMap.get(intent.key()).forEach(tunnelId1 -> {
745 if (tunnelId1.equals(tunnelId)) {
746 tunnelIdSet.add(tunnelId);
747 }
748 });
749
750 if (!tunnelIdSet.isEmpty()) {
751 intentKeyTunnelIdSetMap.compute(intent.key(), (key, existingTunnelIds) -> {
752 if (existingTunnelIds == null || existingTunnelIds.isEmpty()) {
753 return new HashSet<>();
754 } else {
755 return new HashSet<>(Sets.difference(existingTunnelIds, tunnelIdSet));
756 }
757 });
758 }
759 }
760
761 @Override
762 public Set<Intent> getIntents() {
763 Set<Intent> intents = new HashSet<>();
764 intentKeyIntentDataMap.values().forEach(intentData -> intents.add(intentData.intent()));
765 return ImmutableSet.copyOf(intents);
766 }
767
768 @Override
769 public Intent getIntent(Key key) {
770 IntentData intentData = intentKeyIntentDataMap.get(key);
771 return intentData == null ? null : intentData.intent();
772 }
773
774 @Override
775 public Set<IntentData> getIntentData() {
776 return ImmutableSet.copyOf(intentKeyIntentDataMap.values());
777 }
778
779 @Override
780 public IntentData getIntentData(Key key) {
781 IntentData intentData = intentKeyIntentDataMap.get(key);
782 return intentData == null ? null : new IntentData(intentData);
783 }
784
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500785 /**
786 * Listener class to map listener set events to the virtual network events.
787 */
788 private class InternalSetListener implements SetEventListener<TenantId> {
789 @Override
790 public void event(SetEvent<TenantId> event) {
791 VirtualNetworkEvent.Type type = null;
792 switch (event.type()) {
793 case ADD:
794 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
795 break;
796 case REMOVE:
797 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
798 break;
799 default:
800 log.error("Unsupported event type: " + event.type());
801 }
802 notifyDelegate(new VirtualNetworkEvent(type, null));
803 }
804 }
805
806 /**
807 * Listener class to map listener map events to the virtual network events.
808 */
Claudine Chiu945828d2016-11-21 12:47:07 -0500809 private class InternalMapListener<K, V> implements MapEventListener<K, V> {
810
811 private final BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent;
812
813 InternalMapListener(BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent) {
814 this.createEvent = createEvent;
815 }
816
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500817 @Override
Claudine Chiu945828d2016-11-21 12:47:07 -0500818 public void event(MapEvent<K, V> event) {
819 checkNotNull(event.key());
820 VirtualNetworkEvent vnetEvent = null;
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500821 switch (event.type()) {
822 case INSERT:
Claudine Chiu945828d2016-11-21 12:47:07 -0500823 vnetEvent = createEvent.apply(event.type(), event.newValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500824 break;
825 case UPDATE:
826 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
Claudine Chiu945828d2016-11-21 12:47:07 -0500827 vnetEvent = createEvent.apply(MapEvent.Type.REMOVE, event.oldValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500828 } else {
Claudine Chiu945828d2016-11-21 12:47:07 -0500829 vnetEvent = createEvent.apply(event.type(), event.newValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500830 }
831 break;
832 case REMOVE:
Claudine Chiu945828d2016-11-21 12:47:07 -0500833 if (event.oldValue() != null) {
834 vnetEvent = createEvent.apply(event.type(), event.oldValue().value());
835 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500836 break;
837 default:
838 log.error("Unsupported event type: " + event.type());
839 }
Claudine Chiu945828d2016-11-21 12:47:07 -0500840 if (vnetEvent != null) {
841 notifyDelegate(vnetEvent);
842 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500843 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700844 }
845}