Jonathan Hart | 472062d | 2014-04-03 10:56:48 -0700 | [diff] [blame] | 1 | package net.onrc.onos.core.topology; |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 2 | |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 3 | import java.util.ArrayList; |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 4 | import java.util.Collection; |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 5 | import java.util.Collections; |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 6 | import java.util.Iterator; |
| 7 | import java.util.List; |
| 8 | import java.util.Map; |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 9 | import java.util.concurrent.ConcurrentHashMap; |
| 10 | import java.util.concurrent.ConcurrentMap; |
Jonathan Hart | 26f291b | 2014-02-18 16:57:24 -0800 | [diff] [blame] | 11 | import java.util.concurrent.locks.Lock; |
| 12 | import java.util.concurrent.locks.ReadWriteLock; |
| 13 | import java.util.concurrent.locks.ReentrantReadWriteLock; |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 14 | |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 15 | import javax.annotation.concurrent.GuardedBy; |
| 16 | |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 17 | import net.floodlightcontroller.util.MACAddress; |
Yuta HIGUCHI | 8f3dfa3 | 2014-06-25 00:14:25 -0700 | [diff] [blame] | 18 | import net.onrc.onos.core.util.Dpid; |
| 19 | import net.onrc.onos.core.util.PortNumber; |
Jonathan Hart | 25bd53e | 2014-04-30 23:44:09 -0700 | [diff] [blame] | 20 | import net.onrc.onos.core.util.SwitchPort; |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 21 | |
| 22 | import org.slf4j.Logger; |
| 23 | import org.slf4j.LoggerFactory; |
| 24 | |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 25 | import com.google.common.collect.HashMultimap; |
| 26 | import com.google.common.collect.Multimap; |
| 27 | import com.google.common.collect.Multimaps; |
| 28 | |
Jonathan Hart | e37e4e2 | 2014-05-13 19:12:02 -0700 | [diff] [blame] | 29 | public class TopologyImpl implements Topology { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 30 | @SuppressWarnings("unused") |
Jonathan Hart | e37e4e2 | 2014-05-13 19:12:02 -0700 | [diff] [blame] | 31 | private static final Logger log = LoggerFactory.getLogger(TopologyImpl.class); |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 32 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 33 | // DPID -> Switch |
Yuta HIGUCHI | 8f3dfa3 | 2014-06-25 00:14:25 -0700 | [diff] [blame] | 34 | private final ConcurrentMap<Dpid, Switch> switches; |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 35 | // XXX may need to be careful when shallow copying. |
| 36 | private final ConcurrentMap<Dpid, ConcurrentMap<PortNumber, Port>> ports; |
| 37 | |
Yuta HIGUCHI | bfc77f0 | 2014-07-14 22:50:25 -0700 | [diff] [blame] | 38 | // Index from Port to Host |
| 39 | private final Multimap<SwitchPort, Host> hosts; |
| 40 | private final ConcurrentMap<MACAddress, Host> mac2Host; |
Jonathan Hart | 25bd53e | 2014-04-30 23:44:09 -0700 | [diff] [blame] | 41 | |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 42 | // SwitchPort -> (type -> Link) |
| 43 | private final ConcurrentMap<SwitchPort, ConcurrentMap<String, Link>> outgoingLinks; |
| 44 | private final ConcurrentMap<SwitchPort, ConcurrentMap<String, Link>> incomingLinks; |
Yuta HIGUCHI | 5d2d8d4 | 2014-02-20 22:22:53 -0800 | [diff] [blame] | 45 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 46 | private ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); |
| 47 | private Lock readLock = readWriteLock.readLock(); |
| 48 | // TODO use the write lock after refactor |
| 49 | private Lock writeLock = readWriteLock.writeLock(); |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 50 | |
Jonathan Hart | e37e4e2 | 2014-05-13 19:12:02 -0700 | [diff] [blame] | 51 | public TopologyImpl() { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 52 | // TODO: Does these object need to be stored in Concurrent Collection? |
| 53 | switches = new ConcurrentHashMap<>(); |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 54 | ports = new ConcurrentHashMap<>(); |
Yuta HIGUCHI | bfc77f0 | 2014-07-14 22:50:25 -0700 | [diff] [blame] | 55 | hosts = Multimaps.synchronizedMultimap( |
| 56 | HashMultimap.<SwitchPort, Host>create()); |
| 57 | mac2Host = new ConcurrentHashMap<>(); |
Jonathan Hart | 25bd53e | 2014-04-30 23:44:09 -0700 | [diff] [blame] | 58 | outgoingLinks = new ConcurrentHashMap<>(); |
| 59 | incomingLinks = new ConcurrentHashMap<>(); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 60 | } |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 61 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 62 | @Override |
Yuta HIGUCHI | 8f3dfa3 | 2014-06-25 00:14:25 -0700 | [diff] [blame] | 63 | public Switch getSwitch(Dpid dpid) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 64 | // TODO Check if it is safe to directly return this Object. |
| 65 | return switches.get(dpid); |
| 66 | } |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 67 | |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 68 | // Only add switch. |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 69 | protected void putSwitch(Switch sw) { |
| 70 | switches.put(sw.getDpid(), sw); |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 71 | ports.putIfAbsent(sw.getDpid(), new ConcurrentHashMap<PortNumber, Port>()); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 72 | } |
Pavlin Radoslavov | 6d224ee | 2014-02-18 16:43:15 -0800 | [diff] [blame] | 73 | |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 74 | // XXX Will remove ports in snapshot as side-effect. |
Yuta HIGUCHI | 8f3dfa3 | 2014-06-25 00:14:25 -0700 | [diff] [blame] | 75 | protected void removeSwitch(Dpid dpid) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 76 | switches.remove(dpid); |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 77 | ports.remove(dpid); |
| 78 | } |
| 79 | |
| 80 | // This method is expected to be serialized by writeLock. |
| 81 | protected void putPort(Port port) { |
| 82 | ConcurrentMap<PortNumber, Port> portMap = ports.get(port.getDpid()); |
| 83 | if (portMap == null) { |
| 84 | portMap = new ConcurrentHashMap<>(); |
| 85 | ConcurrentMap<PortNumber, Port> existing = |
| 86 | ports.putIfAbsent(port.getDpid(), portMap); |
| 87 | if (existing != null) { |
| 88 | // port map was added concurrently, using theirs |
| 89 | portMap = existing; |
| 90 | } |
| 91 | } |
| 92 | portMap.put(port.getNumber(), port); |
| 93 | } |
| 94 | |
| 95 | protected void removePort(Port port) { |
| 96 | ConcurrentMap<PortNumber, Port> portMap = ports.get(port.getDpid()); |
| 97 | if (portMap != null) { |
| 98 | portMap.remove(port.getNumber()); |
| 99 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 100 | } |
Pavlin Radoslavov | 6d224ee | 2014-02-18 16:43:15 -0800 | [diff] [blame] | 101 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 102 | @Override |
| 103 | public Iterable<Switch> getSwitches() { |
| 104 | // TODO Check if it is safe to directly return this Object. |
| 105 | return Collections.unmodifiableCollection(switches.values()); |
| 106 | } |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 107 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 108 | @Override |
Yuta HIGUCHI | 8f3dfa3 | 2014-06-25 00:14:25 -0700 | [diff] [blame] | 109 | public Port getPort(Dpid dpid, PortNumber number) { |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 110 | ConcurrentMap<PortNumber, Port> portMap = ports.get(dpid); |
| 111 | if (portMap != null) { |
| 112 | return portMap.get(number); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 113 | } |
| 114 | return null; |
| 115 | } |
Pavlin Radoslavov | 06df22a | 2014-02-18 19:16:27 -0800 | [diff] [blame] | 116 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 117 | @Override |
Yuta HIGUCHI | 8f3dfa3 | 2014-06-25 00:14:25 -0700 | [diff] [blame] | 118 | public Port getPort(SwitchPort port) { |
| 119 | return getPort(port.dpid(), port.port()); |
Jonathan Hart | 25bd53e | 2014-04-30 23:44:09 -0700 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | @Override |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 123 | public Collection<Port> getPorts(Dpid dpid) { |
| 124 | ConcurrentMap<PortNumber, Port> portMap = ports.get(dpid); |
| 125 | if (portMap == null) { |
| 126 | return Collections.emptyList(); |
| 127 | } |
| 128 | return Collections.unmodifiableCollection(portMap.values()); |
| 129 | } |
| 130 | |
| 131 | @Override |
Yuta HIGUCHI | 8f3dfa3 | 2014-06-25 00:14:25 -0700 | [diff] [blame] | 132 | public Link getOutgoingLink(Dpid dpid, PortNumber number) { |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 133 | return getOutgoingLink(new SwitchPort(dpid, number)); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 134 | } |
Pavlin Radoslavov | 7c8f69a | 2014-02-19 19:01:45 -0800 | [diff] [blame] | 135 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 136 | @Override |
Yuta HIGUCHI | 8f3dfa3 | 2014-06-25 00:14:25 -0700 | [diff] [blame] | 137 | public Link getOutgoingLink(SwitchPort port) { |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 138 | Map<String, Link> links = outgoingLinks.get(port); |
| 139 | return getPacketLinkIfExists(links); |
| 140 | } |
| 141 | |
| 142 | // TODO remove when we no longer need packet fall back behavior |
| 143 | /** |
| 144 | * Gets the "packet" link if such exists, if not return whatever found. |
| 145 | * |
| 146 | * @param links Collection of links to search from |
| 147 | * @return Link instance found or null if no link exists |
| 148 | */ |
| 149 | private Link getPacketLinkIfExists(Map<String, Link> links) { |
| 150 | |
| 151 | if (links == null) { |
| 152 | return null; |
| 153 | } |
| 154 | |
Yuta HIGUCHI | dbc3312 | 2014-07-10 13:32:32 -0700 | [diff] [blame] | 155 | Link link = links.get(TopologyElement.TYPE_PACKET_LAYER); |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 156 | if (link != null) { |
| 157 | // return packet link |
| 158 | return link; |
| 159 | } else { |
| 160 | // return whatever found |
| 161 | Iterator<Link> it = links.values().iterator(); |
| 162 | if (it.hasNext()) { |
| 163 | return it.next(); |
| 164 | } |
| 165 | } |
| 166 | return null; |
| 167 | } |
| 168 | |
| 169 | @Override |
| 170 | public Link getOutgoingLink(Dpid dpid, PortNumber number, String type) { |
| 171 | return getOutgoingLink(new SwitchPort(dpid, number), type); |
| 172 | } |
| 173 | |
| 174 | @Override |
| 175 | public Link getOutgoingLink(SwitchPort port, String type) { |
| 176 | Map<String, Link> links = outgoingLinks.get(port); |
| 177 | return links.get(type); |
| 178 | } |
| 179 | |
| 180 | @Override |
| 181 | public Collection<Link> getOutgoingLinks(SwitchPort port) { |
| 182 | return Collections.unmodifiableCollection(outgoingLinks.get(port).values()); |
Yuta HIGUCHI | 8f3dfa3 | 2014-06-25 00:14:25 -0700 | [diff] [blame] | 183 | } |
| 184 | |
| 185 | @Override |
| 186 | public Link getIncomingLink(Dpid dpid, PortNumber number) { |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 187 | return getIncomingLink(new SwitchPort(dpid, number)); |
Yuta HIGUCHI | 8f3dfa3 | 2014-06-25 00:14:25 -0700 | [diff] [blame] | 188 | } |
| 189 | |
| 190 | @Override |
| 191 | public Link getIncomingLink(SwitchPort port) { |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 192 | Map<String, Link> links = incomingLinks.get(port); |
| 193 | return getPacketLinkIfExists(links); |
| 194 | } |
| 195 | |
| 196 | @Override |
| 197 | public Link getIncomingLink(Dpid dpid, PortNumber number, String type) { |
| 198 | return getIncomingLink(new SwitchPort(dpid, number), type); |
| 199 | } |
| 200 | |
| 201 | @Override |
| 202 | public Link getIncomingLink(SwitchPort port, String type) { |
| 203 | Map<String, Link> links = incomingLinks.get(port); |
| 204 | return links.get(type); |
| 205 | } |
| 206 | |
| 207 | @Override |
| 208 | public Collection<Link> getIncomingLinks(SwitchPort port) { |
| 209 | return Collections.unmodifiableCollection(incomingLinks.get(port).values()); |
Yuta HIGUCHI | 8f3dfa3 | 2014-06-25 00:14:25 -0700 | [diff] [blame] | 210 | } |
| 211 | |
| 212 | @Override |
| 213 | public Link getLink(Dpid srcDpid, PortNumber srcNumber, |
| 214 | Dpid dstDpid, PortNumber dstNumber) { |
| 215 | |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 216 | final SwitchPort dstSwitchPort = new SwitchPort(dstDpid, dstNumber); |
| 217 | Collection<Link> links = getOutgoingLinks(new SwitchPort(srcDpid, srcNumber)); |
| 218 | for (Link link : links) { |
| 219 | if (link == null) { |
| 220 | continue; |
| 221 | } |
| 222 | if (link.getDstPort().asSwitchPort().equals(dstSwitchPort)) { |
| 223 | return link; |
| 224 | } |
| 225 | } |
| 226 | return null; |
| 227 | } |
| 228 | |
| 229 | @Override |
| 230 | public Link getLink(Dpid srcDpid, PortNumber srcNumber, |
| 231 | Dpid dstDpid, PortNumber dstNumber, |
| 232 | String type) { |
| 233 | |
| 234 | Link link = getOutgoingLink(srcDpid, srcNumber, type); |
Ray Milkey | b29e626 | 2014-04-09 16:02:14 -0700 | [diff] [blame] | 235 | if (link == null) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 236 | return null; |
Ray Milkey | b29e626 | 2014-04-09 16:02:14 -0700 | [diff] [blame] | 237 | } |
| 238 | if (!link.getDstSwitch().getDpid().equals(dstDpid)) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 239 | return null; |
Ray Milkey | b29e626 | 2014-04-09 16:02:14 -0700 | [diff] [blame] | 240 | } |
| 241 | if (!link.getDstPort().getNumber().equals(dstNumber)) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 242 | return null; |
Ray Milkey | b29e626 | 2014-04-09 16:02:14 -0700 | [diff] [blame] | 243 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 244 | return link; |
| 245 | } |
Pavlin Radoslavov | 7c8f69a | 2014-02-19 19:01:45 -0800 | [diff] [blame] | 246 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 247 | @Override |
| 248 | public Iterable<Link> getLinks() { |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 249 | List<Link> links = new ArrayList<>(); |
| 250 | |
| 251 | for (Map<String, Link> portLinks : outgoingLinks.values()) { |
| 252 | links.addAll(portLinks.values()); |
| 253 | } |
| 254 | return links; |
Jonathan Hart | 25bd53e | 2014-04-30 23:44:09 -0700 | [diff] [blame] | 255 | } |
Toshio Koide | 2f570c1 | 2014-02-06 16:55:32 -0800 | [diff] [blame] | 256 | |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 257 | @GuardedBy("topology.writeLock") |
Jonathan Hart | 25bd53e | 2014-04-30 23:44:09 -0700 | [diff] [blame] | 258 | protected void putLink(Link link) { |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 259 | putLinkMap(outgoingLinks, link.getSrcPort().asSwitchPort(), link); |
| 260 | putLinkMap(incomingLinks, link.getDstPort().asSwitchPort(), link); |
Jonathan Hart | 25bd53e | 2014-04-30 23:44:09 -0700 | [diff] [blame] | 261 | } |
| 262 | |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 263 | /** |
| 264 | * Helper method to update outgoingLinks, incomingLinks. |
| 265 | * |
| 266 | * @param linkMap outgoingLinks or incomingLinks |
| 267 | * @param port Map key |
| 268 | * @param link Link to add |
| 269 | */ |
| 270 | @GuardedBy("topology.writeLock") |
| 271 | private void putLinkMap(ConcurrentMap<SwitchPort, ConcurrentMap<String, Link>> linkMap, |
| 272 | SwitchPort port, Link link) { |
| 273 | ConcurrentMap<String, Link> portLinks = new ConcurrentHashMap<String, Link>(3); |
| 274 | portLinks.put(link.getType(), link); |
| 275 | Map<String, Link> existing = linkMap.putIfAbsent( |
| 276 | port, |
| 277 | portLinks); |
| 278 | if (existing != null) { |
| 279 | // no conditional update here |
| 280 | existing.put(link.getType(), link); |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | @GuardedBy("topology.writeLock") |
Jonathan Hart | 25bd53e | 2014-04-30 23:44:09 -0700 | [diff] [blame] | 285 | protected void removeLink(Link link) { |
Yuta HIGUCHI | 8313f0b | 2014-07-09 16:36:03 -0700 | [diff] [blame] | 286 | ConcurrentMap<String, Link> portLinks = outgoingLinks.get(link.getSrcPort().asSwitchPort()); |
| 287 | if (portLinks != null) { |
| 288 | // no conditional update here |
| 289 | portLinks.remove(link.getType()); |
| 290 | } |
| 291 | portLinks = incomingLinks.get(link.getDstPort().asSwitchPort()); |
| 292 | if (portLinks != null) { |
| 293 | // no conditional update here |
| 294 | portLinks.remove(link.getType()); |
| 295 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 296 | } |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 297 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 298 | @Override |
Yuta HIGUCHI | bfc77f0 | 2014-07-14 22:50:25 -0700 | [diff] [blame] | 299 | public Host getHostByMac(MACAddress address) { |
| 300 | return mac2Host.get(address); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 301 | } |
Pavlin Radoslavov | 6d224ee | 2014-02-18 16:43:15 -0800 | [diff] [blame] | 302 | |
TeruU | 65bc5ff | 2014-04-23 22:22:32 -0700 | [diff] [blame] | 303 | @Override |
Yuta HIGUCHI | bfc77f0 | 2014-07-14 22:50:25 -0700 | [diff] [blame] | 304 | public Iterable<Host> getHosts() { |
| 305 | return Collections.unmodifiableCollection(mac2Host.values()); |
TeruU | 65bc5ff | 2014-04-23 22:22:32 -0700 | [diff] [blame] | 306 | } |
| 307 | |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 308 | @Override |
Yuta HIGUCHI | bfc77f0 | 2014-07-14 22:50:25 -0700 | [diff] [blame] | 309 | public Collection<Host> getHosts(SwitchPort port) { |
| 310 | return Collections.unmodifiableCollection(hosts.get(port)); |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 311 | } |
| 312 | |
| 313 | // This method is expected to be serialized by writeLock. |
| 314 | // XXX new or updated device |
Yuta HIGUCHI | bfc77f0 | 2014-07-14 22:50:25 -0700 | [diff] [blame] | 315 | protected void putHost(Host host) { |
| 316 | // assuming Host is immutable |
| 317 | Host oldHost = mac2Host.get(host.getMacAddress()); |
| 318 | if (oldHost != null) { |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 319 | // remove old attachment point |
Yuta HIGUCHI | bfc77f0 | 2014-07-14 22:50:25 -0700 | [diff] [blame] | 320 | removeHost(oldHost); |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 321 | } |
| 322 | // add new attachment points |
Yuta HIGUCHI | bfc77f0 | 2014-07-14 22:50:25 -0700 | [diff] [blame] | 323 | for (Port port : host.getAttachmentPoints()) { |
| 324 | // TODO Won't need remove() if we define Host equality to reflect |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 325 | // all of it's fields. |
Yuta HIGUCHI | bfc77f0 | 2014-07-14 22:50:25 -0700 | [diff] [blame] | 326 | hosts.remove(port.asSwitchPort(), host); |
| 327 | hosts.put(port.asSwitchPort(), host); |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 328 | } |
Yuta HIGUCHI | bfc77f0 | 2014-07-14 22:50:25 -0700 | [diff] [blame] | 329 | mac2Host.put(host.getMacAddress(), host); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 330 | } |
Pavlin Radoslavov | 6d224ee | 2014-02-18 16:43:15 -0800 | [diff] [blame] | 331 | |
Yuta HIGUCHI | bfc77f0 | 2014-07-14 22:50:25 -0700 | [diff] [blame] | 332 | protected void removeHost(Host host) { |
| 333 | for (Port port : host.getAttachmentPoints()) { |
| 334 | hosts.remove(port.asSwitchPort(), host); |
Yuta HIGUCHI | fa74284 | 2014-07-03 22:35:13 -0700 | [diff] [blame] | 335 | } |
Yuta HIGUCHI | bfc77f0 | 2014-07-14 22:50:25 -0700 | [diff] [blame] | 336 | mac2Host.remove(host.getMacAddress()); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 337 | } |
Jonathan Hart | 26f291b | 2014-02-18 16:57:24 -0800 | [diff] [blame] | 338 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 339 | @Override |
| 340 | public void acquireReadLock() { |
| 341 | readLock.lock(); |
| 342 | } |
Jonathan Hart | 26f291b | 2014-02-18 16:57:24 -0800 | [diff] [blame] | 343 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 344 | @Override |
| 345 | public void releaseReadLock() { |
| 346 | readLock.unlock(); |
| 347 | } |
Pavlin Radoslavov | 8ffb8bf | 2014-02-20 15:34:26 -0800 | [diff] [blame] | 348 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 349 | protected void acquireWriteLock() { |
| 350 | writeLock.lock(); |
| 351 | } |
Pavlin Radoslavov | 8ffb8bf | 2014-02-20 15:34:26 -0800 | [diff] [blame] | 352 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 353 | protected void releaseWriteLock() { |
| 354 | writeLock.unlock(); |
| 355 | } |
Yuta HIGUCHI | 80829d1 | 2014-02-05 20:16:56 -0800 | [diff] [blame] | 356 | } |