From 76dc892491948adae5e5e62cf94448967e8d865b Mon Sep 17 00:00:00 2001 From: Ashlee Young Date: Sun, 6 Dec 2015 07:15:03 -0800 Subject: Fixes bad POM file with ONOS commit 8c68536972f63069c263635c9d9f4f31d7f3e9a2 Change-Id: I7adb5a2d3738d53dbc41db7577768b0e7ced5450 Signed-off-by: Ashlee Young --- .../store/host/impl/DistributedHostStore.java | 265 +++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java (limited to 'framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java') diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java new file mode 100644 index 00000000..836a3c22 --- /dev/null +++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java @@ -0,0 +1,265 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.store.host.impl; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; +import org.onlab.packet.VlanId; +import org.onlab.util.KryoNamespace; +import org.onosproject.net.Annotations; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DefaultAnnotations; +import org.onosproject.net.DefaultHost; +import org.onosproject.net.DeviceId; +import org.onosproject.net.Host; +import org.onosproject.net.HostId; +import org.onosproject.net.HostLocation; +import org.onosproject.net.host.HostDescription; +import org.onosproject.net.host.HostEvent; +import org.onosproject.net.host.HostStore; +import org.onosproject.net.host.HostStoreDelegate; +import org.onosproject.net.provider.ProviderId; +import org.onosproject.store.AbstractStore; +import org.onosproject.store.serializers.KryoNamespaces; +import org.onosproject.store.service.ConsistentMap; +import org.onosproject.store.service.MapEvent; +import org.onosproject.store.service.MapEventListener; +import org.onosproject.store.service.Serializer; +import org.onosproject.store.service.StorageService; +import org.slf4j.Logger; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static org.onosproject.net.DefaultAnnotations.merge; +import static org.onosproject.net.host.HostEvent.Type.*; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Manages the inventory of hosts using a {@code EventuallyConsistentMap}. + */ +@Component(immediate = true) +@Service +public class DistributedHostStore + extends AbstractStore + implements HostStore { + + private final Logger log = getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected StorageService storageService; + + private ConsistentMap host; + private Map hosts; + + private final ConcurrentHashMap prevHosts = + new ConcurrentHashMap<>(); + + private MapEventListener hostLocationTracker = + new HostLocationTracker(); + + @Activate + public void activate() { + KryoNamespace.Builder hostSerializer = KryoNamespace.newBuilder() + .register(KryoNamespaces.API); + + host = storageService.consistentMapBuilder() + .withName("onos-hosts") + .withRelaxedReadConsistency() + .withSerializer(Serializer.using(hostSerializer.build())) + .build(); + + hosts = host.asJavaMap(); + + host.addListener(hostLocationTracker); + + log.info("Started"); + } + + @Deactivate + public void deactivate() { + host.removeListener(hostLocationTracker); + prevHosts.clear(); + + log.info("Stopped"); + } + + // TODO No longer need to return HostEvent + @Override + public HostEvent createOrUpdateHost(ProviderId providerId, + HostId hostId, + HostDescription hostDescription, + boolean replaceIPs) { + // TODO: We need a way to detect conflicting changes and abort update. + // (BOC) Compute might do this for us. + + hosts.compute(hostId, (id, existingHost) -> { + HostLocation location = hostDescription.location(); + + final Set addresses; + if (existingHost == null || replaceIPs) { + addresses = ImmutableSet.copyOf(hostDescription.ipAddress()); + } else { + addresses = Sets.newHashSet(existingHost.ipAddresses()); + addresses.addAll(hostDescription.ipAddress()); + } + + final Annotations annotations; + if (existingHost != null) { + annotations = merge((DefaultAnnotations) existingHost.annotations(), + hostDescription.annotations()); + } else { + annotations = hostDescription.annotations(); + } + + return new DefaultHost(providerId, + hostId, + hostDescription.hwAddress(), + hostDescription.vlan(), + location, + addresses, + annotations); + }); + + return null; + } + + // TODO No longer need to return HostEvent + @Override + public HostEvent removeHost(HostId hostId) { + hosts.remove(hostId); + return null; + } + + // TODO No longer need to return HostEvent + @Override + public HostEvent removeIp(HostId hostId, IpAddress ipAddress) { + hosts.compute(hostId, (id, existingHost) -> { + if (existingHost != null) { + checkState(Objects.equals(hostId.mac(), existingHost.mac()), + "Existing and new MAC addresses differ."); + checkState(Objects.equals(hostId.vlanId(), existingHost.vlan()), + "Existing and new VLANs differ."); + + Set addresses = existingHost.ipAddresses(); + if (addresses != null && addresses.contains(ipAddress)) { + addresses = new HashSet<>(existingHost.ipAddresses()); + addresses.remove(ipAddress); + return new DefaultHost(existingHost.providerId(), + hostId, + existingHost.mac(), + existingHost.vlan(), + existingHost.location(), + ImmutableSet.copyOf(addresses), + existingHost.annotations()); + } else { + return existingHost; + } + } + return null; + }); + return null; + } + + @Override + public int getHostCount() { + return hosts.size(); + } + + @Override + public Iterable getHosts() { + return ImmutableSet.copyOf(hosts.values()); + } + + @Override + public Host getHost(HostId hostId) { + return hosts.get(hostId); + } + + @Override + public Set getHosts(VlanId vlanId) { + return filter(hosts.values(), host -> Objects.equals(host.vlan(), vlanId)); + } + + @Override + public Set getHosts(MacAddress mac) { + return filter(hosts.values(), host -> Objects.equals(host.mac(), mac)); + } + + @Override + public Set getHosts(IpAddress ip) { + return filter(hosts.values(), host -> host.ipAddresses().contains(ip)); + } + + @Override + public Set getConnectedHosts(ConnectPoint connectPoint) { + Set filtered = hosts.entrySet().stream() + .filter(entry -> entry.getValue().location().equals(connectPoint)) + .map(Map.Entry::getValue) + .collect(Collectors.toSet()); + return ImmutableSet.copyOf(filtered); + } + + @Override + public Set getConnectedHosts(DeviceId deviceId) { + Set filtered = hosts.entrySet().stream() + .filter(entry -> entry.getValue().location().deviceId().equals(deviceId)) + .map(Map.Entry::getValue) + .collect(Collectors.toSet()); + return ImmutableSet.copyOf(filtered); + } + + private Set filter(Collection collection, Predicate predicate) { + return collection.stream().filter(predicate).collect(Collectors.toSet()); + } + + private class HostLocationTracker implements MapEventListener { + @Override + public void event(MapEvent event) { + DefaultHost host = checkNotNull(event.value().value()); + if (event.type() == MapEvent.Type.INSERT) { + Host prevHost = prevHosts.put(host.id(), host); + if (prevHost == null) { + notifyDelegate(new HostEvent(HOST_ADDED, host)); + } else if (!Objects.equals(prevHost.location(), host.location())) { + notifyDelegate(new HostEvent(HOST_MOVED, host, prevHost)); + } else if (!Objects.equals(prevHost, host)) { + notifyDelegate(new HostEvent(HOST_UPDATED, host, prevHost)); + } + } else if (event.type() == MapEvent.Type.REMOVE) { + if (prevHosts.remove(host.id()) != null) { + notifyDelegate(new HostEvent(HOST_REMOVED, host)); + } + } + } + } +} -- cgit 1.2.3-korg