Move indices to TopologyImpl.
Change-Id: I3efd73129fafb786e959810e8239ce14d26af6d7
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java b/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java
index 2bba015..5ce3729 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java
@@ -1,5 +1,6 @@
package net.onrc.onos.core.topology;
+import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -15,12 +16,21 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+
public class TopologyImpl implements Topology {
@SuppressWarnings("unused")
private static final Logger log = LoggerFactory.getLogger(TopologyImpl.class);
// DPID -> Switch
private final ConcurrentMap<Dpid, Switch> switches;
+ // XXX may need to be careful when shallow copying.
+ private final ConcurrentMap<Dpid, ConcurrentMap<PortNumber, Port>> ports;
+
+ // Index from Port to Device
+ private final Multimap<SwitchPort, Device> devices;
private final ConcurrentMap<MACAddress, Device> mac2Device;
private final ConcurrentMap<SwitchPort, Link> outgoingLinks;
@@ -34,6 +44,9 @@
public TopologyImpl() {
// TODO: Does these object need to be stored in Concurrent Collection?
switches = new ConcurrentHashMap<>();
+ ports = new ConcurrentHashMap<>();
+ devices = Multimaps.synchronizedMultimap(
+ HashMultimap.<SwitchPort, Device>create());
mac2Device = new ConcurrentHashMap<>();
outgoingLinks = new ConcurrentHashMap<>();
incomingLinks = new ConcurrentHashMap<>();
@@ -45,16 +58,43 @@
return switches.get(dpid);
}
+ // Only add switch.
protected void putSwitch(Switch sw) {
switches.put(sw.getDpid(), sw);
+ ports.putIfAbsent(sw.getDpid(), new ConcurrentHashMap<PortNumber, Port>());
}
+ // TODO remove me when ready
protected void removeSwitch(Long dpid) {
- switches.remove(new Dpid(dpid));
+ removeSwitch(new Dpid(dpid));
}
+ // XXX Will remove ports in snapshot as side-effect.
protected void removeSwitch(Dpid dpid) {
switches.remove(dpid);
+ ports.remove(dpid);
+ }
+
+ // This method is expected to be serialized by writeLock.
+ protected void putPort(Port port) {
+ ConcurrentMap<PortNumber, Port> portMap = ports.get(port.getDpid());
+ if (portMap == null) {
+ portMap = new ConcurrentHashMap<>();
+ ConcurrentMap<PortNumber, Port> existing =
+ ports.putIfAbsent(port.getDpid(), portMap);
+ if (existing != null) {
+ // port map was added concurrently, using theirs
+ portMap = existing;
+ }
+ }
+ portMap.put(port.getNumber(), port);
+ }
+
+ protected void removePort(Port port) {
+ ConcurrentMap<PortNumber, Port> portMap = ports.get(port.getDpid());
+ if (portMap != null) {
+ portMap.remove(port.getNumber());
+ }
}
@Override
@@ -65,9 +105,9 @@
@Override
public Port getPort(Dpid dpid, PortNumber number) {
- Switch sw = getSwitch(dpid);
- if (sw != null) {
- return sw.getPort(number);
+ ConcurrentMap<PortNumber, Port> portMap = ports.get(dpid);
+ if (portMap != null) {
+ return portMap.get(number);
}
return null;
}
@@ -78,6 +118,15 @@
}
@Override
+ public Collection<Port> getPorts(Dpid dpid) {
+ ConcurrentMap<PortNumber, Port> portMap = ports.get(dpid);
+ if (portMap == null) {
+ return Collections.emptyList();
+ }
+ return Collections.unmodifiableCollection(portMap.values());
+ }
+
+ @Override
public Link getOutgoingLink(Dpid dpid, PortNumber number) {
return outgoingLinks.get(new SwitchPort(dpid, number));
}
@@ -139,11 +188,34 @@
return Collections.unmodifiableCollection(mac2Device.values());
}
+ @Override
+ public Collection<Device> getDevices(SwitchPort port) {
+ return Collections.unmodifiableCollection(devices.get(port));
+ }
+
+ // This method is expected to be serialized by writeLock.
+ // XXX new or updated device
protected void putDevice(Device device) {
+ // assuming Device is immutable
+ Device oldDevice = mac2Device.get(device.getMacAddress());
+ if (oldDevice != null) {
+ // remove old attachment point
+ removeDevice(oldDevice);
+ }
+ // add new attachment points
+ for (Port port : device.getAttachmentPoints()) {
+ // TODO Won't need remove() if we define Device equality to reflect
+ // all of it's fields.
+ devices.remove(port.asSwitchPort(), device);
+ devices.put(port.asSwitchPort(), device);
+ }
mac2Device.put(device.getMacAddress(), device);
}
protected void removeDevice(Device device) {
+ for (Port port : device.getAttachmentPoints()) {
+ devices.remove(port.asSwitchPort(), device);
+ }
mac2Device.remove(device.getMacAddress());
}