blob: c1d6273e7eee645e50d4050995d869b7cccf59c4 [file] [log] [blame]
tom4c6606f2014-09-07 11:11:21 -07001package org.onlab.onos.net.trivial.impl;
2
tomeadbb462014-09-07 16:10:19 -07003import com.google.common.collect.HashMultimap;
4import com.google.common.collect.ImmutableSet;
5import com.google.common.collect.Multimap;
6import org.onlab.onos.net.ConnectPoint;
7import org.onlab.onos.net.DefaultLink;
8import org.onlab.onos.net.DeviceId;
9import org.onlab.onos.net.Link;
10import org.onlab.onos.net.link.LinkDescription;
11import org.onlab.onos.net.link.LinkEvent;
12import org.onlab.onos.net.provider.ProviderId;
13
14import java.util.Collections;
15import java.util.HashSet;
16import java.util.Map;
17import java.util.Objects;
18import java.util.Set;
19import java.util.concurrent.ConcurrentHashMap;
20
tom4c6606f2014-09-07 11:11:21 -070021/**
22 * Manages inventory of infrastructure links using trivial in-memory link
23 * implementation.
24 */
tomeadbb462014-09-07 16:10:19 -070025class SimpleLinkStore {
26
27 // Link inventory
28 private final Map<LinkKey, DefaultLink> links = new ConcurrentHashMap<>();
29
30 // Egress and ingress link sets
31 private final Multimap<DeviceId, Link> srcLinks = HashMultimap.create();
32 private final Multimap<DeviceId, Link> dstLinks = HashMultimap.create();
33
34 private static final Set<Link> EMPTY = ImmutableSet.copyOf(new Link[]{});
35
36 /**
37 * Returns the number of links in the store.
38 *
39 * @return number of links
40 */
41 int getLinkCount() {
42 return links.size();
43 }
44
45 /**
46 * Returns an iterable collection of all links in the inventory.
47 *
48 * @return collection of all links
49 */
50 Iterable<Link> getLinks() {
51 return Collections.unmodifiableSet(new HashSet<Link>(links.values()));
52 }
53
54 /**
55 * Returns all links egressing from the specified device.
56 *
57 * @param deviceId device identifier
58 * @return set of device links
59 */
60 Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
61 return ImmutableSet.copyOf(srcLinks.get(deviceId));
62 }
63
64 /**
65 * Returns all links ingressing from the specified device.
66 *
67 * @param deviceId device identifier
68 * @return set of device links
69 */
70 Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
71 return ImmutableSet.copyOf(dstLinks.get(deviceId));
72 }
73
74 /**
75 * Returns all links egressing from the specified connection point.
76 *
77 * @param src source connection point
78 * @return set of connection point links
79 */
80 Set<Link> getEgressLinks(ConnectPoint src) {
81 Set<Link> egress = new HashSet<>();
82 for (Link link : srcLinks.get(src.deviceId())) {
83 if (link.src().equals(src)) {
84 egress.add(link);
85 }
86 }
87 return egress;
88 }
89
90 /**
91 * Returns all links ingressing to the specified connection point.
92 *
93 * @param dst destination connection point
94 * @return set of connection point links
95 */
96 Set<Link> getIngressLinks(ConnectPoint dst) {
97 Set<Link> ingress = new HashSet<>();
98 for (Link link : dstLinks.get(dst.deviceId())) {
99 if (link.src().equals(dst)) {
100 ingress.add(link);
101 }
102 }
103 return ingress;
104 }
105
106
107 /**
108 * Creates a new link, or updates an existing one, based on the given
109 * information.
110 *
111 * @param providerId provider identity
112 * @param linkDescription link description
113 * @return create or update link event, or null if no change resulted
114 */
115 public LinkEvent createOrUpdateLink(ProviderId providerId,
116 LinkDescription linkDescription) {
117 LinkKey key = new LinkKey(linkDescription.src(), linkDescription.dst());
118 DefaultLink link = links.get(key);
119 if (link == null) {
120 return createLink(providerId, key, linkDescription);
121 }
122 return updateLink(link, linkDescription);
123 }
124
125 // Creates and stores the link and returns the appropriate event.
126 private LinkEvent createLink(ProviderId providerId, LinkKey key,
127 LinkDescription linkDescription) {
128 DefaultLink link = new DefaultLink(providerId, key.src, key.dst,
129 linkDescription.type());
130 synchronized (this) {
131 links.put(key, link);
132 srcLinks.put(link.src().deviceId(), link);
133 dstLinks.put(link.dst().deviceId(), link);
134 }
135 return new LinkEvent(LinkEvent.Type.LINK_ADDED, link);
136 }
137
138 // Updates, if necessary the specified link and returns the appropriate event.
139 private LinkEvent updateLink(DefaultLink link, LinkDescription linkDescription) {
140 return null;
141 }
142
143 /**
144 * Removes the link based on the specified information.
145 *
146 * @param src link source
147 * @param dst link destination
148 * @return remove link event, or null if no change resulted
149 */
150 LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) {
151 synchronized (this) {
152 Link link = links.remove(new LinkKey(src, dst));
153 srcLinks.remove(link.src().deviceId(), link);
154 dstLinks.remove(link.dst().deviceId(), link);
155 return link == null ? null : new LinkEvent(LinkEvent.Type.LINK_REMOVED, link);
156 }
157 }
158
159 // Auxiliary key to track links.
160 private class LinkKey {
161 final ConnectPoint src;
162 final ConnectPoint dst;
163
164 LinkKey(ConnectPoint src, ConnectPoint dst) {
165 this.src = src;
166 this.dst = dst;
167 }
168
169 @Override
170 public int hashCode() {
171 return Objects.hash(src, dst);
172 }
173
174 @Override
175 public boolean equals(Object obj) {
176 if (obj instanceof LinkKey) {
177 final LinkKey other = (LinkKey) obj;
178 return Objects.equals(this.src, other.src) &&
179 Objects.equals(this.dst, other.dst);
180 }
181 return false;
182 }
183 }
tom4c6606f2014-09-07 11:11:21 -0700184}