tom

Started an initial clone for DistributedDeviceStore

1 -package org.onlab.onos.store.device.impl;
2 -
3 -/**
4 - * Created by tom on 9/19/14.
5 - */
6 -public class DeleteMe {
7 -}
1 +package org.onlab.onos.store.device.impl;
2 +
3 +import com.google.common.collect.ImmutableList;
4 +import org.apache.felix.scr.annotations.Activate;
5 +import org.apache.felix.scr.annotations.Component;
6 +import org.apache.felix.scr.annotations.Deactivate;
7 +import org.apache.felix.scr.annotations.Service;
8 +import org.onlab.onos.net.DefaultDevice;
9 +import org.onlab.onos.net.DefaultPort;
10 +import org.onlab.onos.net.Device;
11 +import org.onlab.onos.net.DeviceId;
12 +import org.onlab.onos.net.MastershipRole;
13 +import org.onlab.onos.net.Port;
14 +import org.onlab.onos.net.PortNumber;
15 +import org.onlab.onos.net.device.DeviceDescription;
16 +import org.onlab.onos.net.device.DeviceEvent;
17 +import org.onlab.onos.net.device.DeviceStore;
18 +import org.onlab.onos.net.device.PortDescription;
19 +import org.onlab.onos.net.provider.ProviderId;
20 +import org.slf4j.Logger;
21 +
22 +import java.util.ArrayList;
23 +import java.util.Collections;
24 +import java.util.HashMap;
25 +import java.util.HashSet;
26 +import java.util.Iterator;
27 +import java.util.List;
28 +import java.util.Map;
29 +import java.util.Objects;
30 +import java.util.Set;
31 +import java.util.concurrent.ConcurrentHashMap;
32 +
33 +import static com.google.common.base.Preconditions.checkArgument;
34 +import static org.onlab.onos.net.device.DeviceEvent.Type.*;
35 +import static org.slf4j.LoggerFactory.getLogger;
36 +
37 +/**
38 + * Manages inventory of infrastructure devices using Hazelcast-backed map.
39 + */
40 +@Component(immediate = true)
41 +@Service
42 +public class DistributedDeviceStore implements DeviceStore {
43 +
44 + private final Logger log = getLogger(getClass());
45 +
46 + public static final String DEVICE_NOT_FOUND = "Device with ID %s not found";
47 +
48 + private final Map<DeviceId, DefaultDevice> devices = new ConcurrentHashMap<>();
49 + private final Map<DeviceId, MastershipRole> roles = new ConcurrentHashMap<>();
50 + private final Set<DeviceId> availableDevices = new HashSet<>();
51 + private final Map<DeviceId, Map<PortNumber, Port>> devicePorts = new HashMap<>();
52 +
53 + @Activate
54 + public void activate() {
55 + log.info("Started");
56 + }
57 +
58 + @Deactivate
59 + public void deactivate() {
60 + log.info("Stopped");
61 + }
62 +
63 + @Override
64 + public int getDeviceCount() {
65 + return devices.size();
66 + }
67 +
68 + @Override
69 + public Iterable<Device> getDevices() {
70 + return Collections.unmodifiableSet(new HashSet<Device>(devices.values()));
71 + }
72 +
73 + @Override
74 + public Device getDevice(DeviceId deviceId) {
75 + return devices.get(deviceId);
76 + }
77 +
78 + @Override
79 + public DeviceEvent createOrUpdateDevice(ProviderId providerId, DeviceId deviceId,
80 + DeviceDescription deviceDescription) {
81 + DefaultDevice device = devices.get(deviceId);
82 + if (device == null) {
83 + return createDevice(providerId, deviceId, deviceDescription);
84 + }
85 + return updateDevice(providerId, device, deviceDescription);
86 + }
87 +
88 + // Creates the device and returns the appropriate event if necessary.
89 + private DeviceEvent createDevice(ProviderId providerId, DeviceId deviceId,
90 + DeviceDescription desc) {
91 + DefaultDevice device = new DefaultDevice(providerId, deviceId, desc.type(),
92 + desc.manufacturer(),
93 + desc.hwVersion(), desc.swVersion(),
94 + desc.serialNumber());
95 + synchronized (this) {
96 + devices.put(deviceId, device);
97 + availableDevices.add(deviceId);
98 +
99 + // For now claim the device as a master automatically.
100 + roles.put(deviceId, MastershipRole.MASTER);
101 + }
102 + return new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device, null);
103 + }
104 +
105 + // Updates the device and returns the appropriate event if necessary.
106 + private DeviceEvent updateDevice(ProviderId providerId, DefaultDevice device,
107 + DeviceDescription desc) {
108 + // We allow only certain attributes to trigger update
109 + if (!Objects.equals(device.hwVersion(), desc.hwVersion()) ||
110 + !Objects.equals(device.swVersion(), desc.swVersion())) {
111 + DefaultDevice updated = new DefaultDevice(providerId, device.id(),
112 + desc.type(),
113 + desc.manufacturer(),
114 + desc.hwVersion(),
115 + desc.swVersion(),
116 + desc.serialNumber());
117 + synchronized (this) {
118 + devices.put(device.id(), updated);
119 + availableDevices.add(device.id());
120 + }
121 + return new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, device, null);
122 + }
123 +
124 + // Otherwise merely attempt to change availability
125 + synchronized (this) {
126 + boolean added = availableDevices.add(device.id());
127 + return !added ? null :
128 + new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device, null);
129 + }
130 + }
131 +
132 + @Override
133 + public DeviceEvent markOffline(DeviceId deviceId) {
134 + synchronized (this) {
135 + Device device = devices.get(deviceId);
136 + boolean removed = device != null && availableDevices.remove(deviceId);
137 + return !removed ? null :
138 + new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device, null);
139 + }
140 + }
141 +
142 + @Override
143 + public List<DeviceEvent> updatePorts(DeviceId deviceId,
144 + List<PortDescription> portDescriptions) {
145 + List<DeviceEvent> events = new ArrayList<>();
146 + synchronized (this) {
147 + Device device = devices.get(deviceId);
148 + checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
149 + Map<PortNumber, Port> ports = getPortMap(deviceId);
150 +
151 + // Add new ports
152 + Set<PortNumber> processed = new HashSet<>();
153 + for (PortDescription portDescription : portDescriptions) {
154 + Port port = ports.get(portDescription.portNumber());
155 + events.add(port == null ?
156 + createPort(device, portDescription, ports) :
157 + updatePort(device, port, portDescription, ports));
158 + processed.add(portDescription.portNumber());
159 + }
160 +
161 + events.addAll(pruneOldPorts(device, ports, processed));
162 + }
163 + return events;
164 + }
165 +
166 + // Creates a new port based on the port description adds it to the map and
167 + // Returns corresponding event.
168 + private DeviceEvent createPort(Device device, PortDescription portDescription,
169 + Map<PortNumber, Port> ports) {
170 + DefaultPort port = new DefaultPort(device, portDescription.portNumber(),
171 + portDescription.isEnabled());
172 + ports.put(port.number(), port);
173 + return new DeviceEvent(PORT_ADDED, device, port);
174 + }
175 +
176 + // CHecks if the specified port requires update and if so, it replaces the
177 + // existing entry in the map and returns corresponding event.
178 + private DeviceEvent updatePort(Device device, Port port,
179 + PortDescription portDescription,
180 + Map<PortNumber, Port> ports) {
181 + if (port.isEnabled() != portDescription.isEnabled()) {
182 + DefaultPort updatedPort =
183 + new DefaultPort(device, portDescription.portNumber(),
184 + portDescription.isEnabled());
185 + ports.put(port.number(), updatedPort);
186 + return new DeviceEvent(PORT_UPDATED, device, port);
187 + }
188 + return null;
189 + }
190 +
191 + // Prunes the specified list of ports based on which ports are in the
192 + // processed list and returns list of corresponding events.
193 + private List<DeviceEvent> pruneOldPorts(Device device,
194 + Map<PortNumber, Port> ports,
195 + Set<PortNumber> processed) {
196 + List<DeviceEvent> events = new ArrayList<>();
197 + Iterator<PortNumber> iterator = ports.keySet().iterator();
198 + while (iterator.hasNext()) {
199 + PortNumber portNumber = iterator.next();
200 + if (!processed.contains(portNumber)) {
201 + events.add(new DeviceEvent(PORT_REMOVED, device,
202 + ports.get(portNumber)));
203 + iterator.remove();
204 + }
205 + }
206 + return events;
207 + }
208 +
209 + // Gets the map of ports for the specified device; if one does not already
210 + // exist, it creates and registers a new one.
211 + private Map<PortNumber, Port> getPortMap(DeviceId deviceId) {
212 + Map<PortNumber, Port> ports = devicePorts.get(deviceId);
213 + if (ports == null) {
214 + ports = new HashMap<>();
215 + devicePorts.put(deviceId, ports);
216 + }
217 + return ports;
218 + }
219 +
220 + @Override
221 + public DeviceEvent updatePortStatus(DeviceId deviceId,
222 + PortDescription portDescription) {
223 + synchronized (this) {
224 + Device device = devices.get(deviceId);
225 + checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
226 + Map<PortNumber, Port> ports = getPortMap(deviceId);
227 + Port port = ports.get(portDescription.portNumber());
228 + return updatePort(device, port, portDescription, ports);
229 + }
230 + }
231 +
232 + @Override
233 + public List<Port> getPorts(DeviceId deviceId) {
234 + Map<PortNumber, Port> ports = devicePorts.get(deviceId);
235 + return ports == null ? new ArrayList<Port>() : ImmutableList.copyOf(ports.values());
236 + }
237 +
238 + @Override
239 + public Port getPort(DeviceId deviceId, PortNumber portNumber) {
240 + Map<PortNumber, Port> ports = devicePorts.get(deviceId);
241 + return ports == null ? null : ports.get(portNumber);
242 + }
243 +
244 + @Override
245 + public boolean isAvailable(DeviceId deviceId) {
246 + return availableDevices.contains(deviceId);
247 + }
248 +
249 + @Override
250 + public MastershipRole getRole(DeviceId deviceId) {
251 + MastershipRole role = roles.get(deviceId);
252 + return role != null ? role : MastershipRole.NONE;
253 + }
254 +
255 + @Override
256 + public DeviceEvent setRole(DeviceId deviceId, MastershipRole role) {
257 + synchronized (this) {
258 + Device device = getDevice(deviceId);
259 + checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
260 + MastershipRole oldRole = roles.put(deviceId, role);
261 + return oldRole == role ? null :
262 + new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device, null);
263 + }
264 + }
265 +
266 + @Override
267 + public DeviceEvent removeDevice(DeviceId deviceId) {
268 + synchronized (this) {
269 + roles.remove(deviceId);
270 + Device device = devices.remove(deviceId);
271 + return device == null ? null :
272 + new DeviceEvent(DEVICE_REMOVED, device, null);
273 + }
274 + }
275 +}