blob: 781650dfcfc943e20b43e597ab01ccce47964b93 [file] [log] [blame]
Simon Huntcda9c032016-04-11 10:32:54 -07001/*
2 * Copyright 2016 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.ui.impl.topo.model;
18
Simon Hunt23fb1352016-04-11 12:15:19 -070019import org.onosproject.cluster.ControllerNode;
Simon Hunt642bc452016-05-04 19:34:45 -070020import org.onosproject.cluster.NodeId;
Simon Hunt23fb1352016-04-11 12:15:19 -070021import org.onosproject.cluster.RoleInfo;
Simon Huntcda9c032016-04-11 10:32:54 -070022import org.onosproject.event.EventDispatcher;
23import org.onosproject.net.Device;
Simon Hunt23fb1352016-04-11 12:15:19 -070024import org.onosproject.net.DeviceId;
Simon Huntc0f20c12016-05-09 09:30:20 -070025import org.onosproject.net.EdgeLink;
Simon Hunt23fb1352016-04-11 12:15:19 -070026import org.onosproject.net.Host;
Simon Huntc0f20c12016-05-09 09:30:20 -070027import org.onosproject.net.HostId;
28import org.onosproject.net.HostLocation;
Simon Hunt23fb1352016-04-11 12:15:19 -070029import org.onosproject.net.Link;
30import org.onosproject.net.region.Region;
Simon Huntc0f20c12016-05-09 09:30:20 -070031import org.onosproject.net.region.RegionId;
Simon Hunt4f4ffc32016-08-03 18:30:47 -070032import org.onosproject.ui.UiTopoLayoutService;
Simon Hunt642bc452016-05-04 19:34:45 -070033import org.onosproject.ui.model.ServiceBundle;
Simon Hunt338a3b42016-04-14 09:43:52 -070034import org.onosproject.ui.model.topo.UiClusterMember;
Simon Huntcda9c032016-04-11 10:32:54 -070035import org.onosproject.ui.model.topo.UiDevice;
Simon Huntc0f20c12016-05-09 09:30:20 -070036import org.onosproject.ui.model.topo.UiElement;
37import org.onosproject.ui.model.topo.UiHost;
38import org.onosproject.ui.model.topo.UiLink;
39import org.onosproject.ui.model.topo.UiLinkId;
40import org.onosproject.ui.model.topo.UiRegion;
Simon Hunt4f4ffc32016-08-03 18:30:47 -070041import org.onosproject.ui.model.topo.UiTopoLayout;
42import org.onosproject.ui.model.topo.UiTopoLayoutId;
Simon Hunt23fb1352016-04-11 12:15:19 -070043import org.onosproject.ui.model.topo.UiTopology;
Simon Hunt642bc452016-05-04 19:34:45 -070044import org.slf4j.Logger;
45import org.slf4j.LoggerFactory;
Simon Hunt23fb1352016-04-11 12:15:19 -070046
Simon Huntb1ce2602016-07-23 14:04:31 -070047import java.util.HashSet;
Simon Huntd5b96732016-07-08 13:22:27 -070048import java.util.List;
Simon Huntc0f20c12016-05-09 09:30:20 -070049import java.util.Set;
50
51import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
Simon Hunt642bc452016-05-04 19:34:45 -070052import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.CLUSTER_MEMBER_ADDED_OR_UPDATED;
53import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.CLUSTER_MEMBER_REMOVED;
54import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.DEVICE_ADDED_OR_UPDATED;
Simon Hunt23fb1352016-04-11 12:15:19 -070055import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.DEVICE_REMOVED;
Simon Huntc0f20c12016-05-09 09:30:20 -070056import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.HOST_ADDED_OR_UPDATED;
57import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.HOST_MOVED;
58import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.HOST_REMOVED;
59import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.LINK_ADDED_OR_UPDATED;
60import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.LINK_REMOVED;
61import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.REGION_ADDED_OR_UPDATED;
62import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.REGION_REMOVED;
63import static org.onosproject.ui.model.topo.UiLinkId.uiLinkId;
Simon Huntcda9c032016-04-11 10:32:54 -070064
65/**
66 * UI Topology Model cache.
67 */
68class ModelCache {
69
Simon Huntc0f20c12016-05-09 09:30:20 -070070 private static final String E_NO_ELEMENT = "Tried to remove non-member {}: {}";
71
Simon Hunt642bc452016-05-04 19:34:45 -070072 private static final Logger log = LoggerFactory.getLogger(ModelCache.class);
73
74 private final ServiceBundle services;
Simon Huntcda9c032016-04-11 10:32:54 -070075 private final EventDispatcher dispatcher;
Simon Hunt23fb1352016-04-11 12:15:19 -070076 private final UiTopology uiTopology = new UiTopology();
Simon Huntcda9c032016-04-11 10:32:54 -070077
Simon Hunt642bc452016-05-04 19:34:45 -070078 ModelCache(ServiceBundle services, EventDispatcher eventDispatcher) {
79 this.services = services;
Simon Huntcda9c032016-04-11 10:32:54 -070080 this.dispatcher = eventDispatcher;
81 }
82
Simon Hunt338a3b42016-04-14 09:43:52 -070083 @Override
84 public String toString() {
85 return "ModelCache{" + uiTopology + "}";
86 }
87
Simon Huntc0f20c12016-05-09 09:30:20 -070088 private void postEvent(UiModelEvent.Type type, UiElement subject) {
89 dispatcher.post(new UiModelEvent(type, subject));
90 }
91
Simon Huntcda9c032016-04-11 10:32:54 -070092 void clear() {
Simon Hunt23fb1352016-04-11 12:15:19 -070093 uiTopology.clear();
Simon Huntcda9c032016-04-11 10:32:54 -070094 }
95
96 /**
Simon Huntc0f20c12016-05-09 09:30:20 -070097 * Create our internal model of the global topology. An assumption we are
98 * making is that the topology is empty to start.
Simon Huntcda9c032016-04-11 10:32:54 -070099 */
100 void load() {
Simon Huntc0f20c12016-05-09 09:30:20 -0700101 loadClusterMembers();
102 loadRegions();
103 loadDevices();
104 loadLinks();
105 loadHosts();
Simon Huntcda9c032016-04-11 10:32:54 -0700106 }
107
108
Simon Huntc0f20c12016-05-09 09:30:20 -0700109 // === CLUSTER MEMBERS
110
111 private UiClusterMember addNewClusterMember(ControllerNode n) {
112 UiClusterMember member = new UiClusterMember(uiTopology, n);
113 uiTopology.add(member);
114 return member;
115 }
116
117 private void updateClusterMember(UiClusterMember member) {
118 ControllerNode.State state = services.cluster().getState(member.id());
119 member.setState(state);
120 member.setMastership(services.mastership().getDevicesOf(member.id()));
121 // NOTE: 'UI-attached' is session-based data, not global, so will
122 // be set elsewhere
123 }
124
125 private void loadClusterMembers() {
126 for (ControllerNode n : services.cluster().getNodes()) {
127 UiClusterMember member = addNewClusterMember(n);
128 updateClusterMember(member);
129 }
130 }
131
132 // invoked from UiSharedTopologyModel cluster event listener
Simon Hunt338a3b42016-04-14 09:43:52 -0700133 void addOrUpdateClusterMember(ControllerNode cnode) {
Simon Hunt642bc452016-05-04 19:34:45 -0700134 NodeId id = cnode.id();
135 UiClusterMember member = uiTopology.findClusterMember(id);
136 if (member == null) {
Simon Huntc0f20c12016-05-09 09:30:20 -0700137 member = addNewClusterMember(cnode);
Simon Hunt338a3b42016-04-14 09:43:52 -0700138 }
Simon Huntc0f20c12016-05-09 09:30:20 -0700139 updateClusterMember(member);
Simon Hunt338a3b42016-04-14 09:43:52 -0700140
Simon Huntc0f20c12016-05-09 09:30:20 -0700141 postEvent(CLUSTER_MEMBER_ADDED_OR_UPDATED, member);
Simon Hunt338a3b42016-04-14 09:43:52 -0700142 }
143
Simon Huntc0f20c12016-05-09 09:30:20 -0700144 // package private for unit test access
145 UiClusterMember accessClusterMember(NodeId id) {
146 return uiTopology.findClusterMember(id);
147 }
148
149 // invoked from UiSharedTopologyModel cluster event listener
Simon Hunt338a3b42016-04-14 09:43:52 -0700150 void removeClusterMember(ControllerNode cnode) {
Simon Hunt642bc452016-05-04 19:34:45 -0700151 NodeId id = cnode.id();
152 UiClusterMember member = uiTopology.findClusterMember(id);
153 if (member != null) {
154 uiTopology.remove(member);
Simon Huntc0f20c12016-05-09 09:30:20 -0700155 postEvent(CLUSTER_MEMBER_REMOVED, member);
Simon Hunt642bc452016-05-04 19:34:45 -0700156 } else {
Simon Huntc0f20c12016-05-09 09:30:20 -0700157 log.warn(E_NO_ELEMENT, "cluster node", id);
Simon Hunt642bc452016-05-04 19:34:45 -0700158 }
Simon Hunt338a3b42016-04-14 09:43:52 -0700159 }
160
Simon Huntd5b96732016-07-08 13:22:27 -0700161 List<UiClusterMember> getAllClusterMembers() {
162 return uiTopology.allClusterMembers();
163 }
164
Simon Huntc0f20c12016-05-09 09:30:20 -0700165
166 // === MASTERSHIP CHANGES
167
168 // invoked from UiSharedTopologyModel mastership listener
Simon Hunt338a3b42016-04-14 09:43:52 -0700169 void updateMasterships(DeviceId deviceId, RoleInfo roleInfo) {
Simon Huntc0f20c12016-05-09 09:30:20 -0700170 // To think about:: do we need to store mastership info?
171 // or can we rely on looking it up live?
Simon Hunt338a3b42016-04-14 09:43:52 -0700172 // TODO: store the updated mastership information
173 // TODO: post event
174 }
175
Simon Huntb1ce2602016-07-23 14:04:31 -0700176 // === THE NULL REGION
177
178 UiRegion nullRegion() {
179 return uiTopology.nullRegion();
180 }
Simon Huntc0f20c12016-05-09 09:30:20 -0700181
182 // === REGIONS
183
184 private UiRegion addNewRegion(Region r) {
185 UiRegion region = new UiRegion(uiTopology, r);
186 uiTopology.add(region);
Simon Huntb1ce2602016-07-23 14:04:31 -0700187 log.debug("Region {} added to topology", region);
Simon Huntc0f20c12016-05-09 09:30:20 -0700188 return region;
189 }
190
191 private void updateRegion(UiRegion region) {
Simon Huntb1ce2602016-07-23 14:04:31 -0700192 RegionId rid = region.id();
193 Set<DeviceId> deviceIds = services.region().getRegionDevices(rid);
194
195 // Make sure device objects refer to their region
196 deviceIds.forEach(d -> {
197 UiDevice dev = uiTopology.findDevice(d);
198 if (dev != null) {
199 dev.setRegionId(rid);
200 } else {
201 // if we don't have the UiDevice in the topology, what can we do?
202 log.warn("Region device {}, but we don't have UiDevice in topology", d);
203 }
204 });
205
206 // Make sure the region object refers to the devices
207 region.reconcileDevices(deviceIds);
Simon Hunt4f4ffc32016-08-03 18:30:47 -0700208
209 fixupContainmentHierarchy(region);
210 }
211
212 private void fixupContainmentHierarchy(UiRegion region) {
213 UiTopoLayoutService ls = services.layout();
214 RegionId regionId = region.id();
215
216 UiTopoLayout layout = ls.getLayout(regionId);
217 if (layout == null) {
218 // no layout backed by this region
219 log.warn("No layout backed by region {}", regionId);
220 return;
221 }
222
223 UiTopoLayoutId layoutId = layout.id();
224
225 if (!layout.isRoot()) {
226 UiTopoLayoutId parentId = layout.parent();
227 UiTopoLayout parentLayout = ls.getLayout(parentId);
228 RegionId parentRegionId = parentLayout.regionId();
229 region.setParent(parentRegionId);
230 }
231
232 Set<UiTopoLayout> kids = ls.getChildren(layoutId);
233 Set<RegionId> kidRegionIds = new HashSet<>(kids.size());
234 kids.forEach(k -> kidRegionIds.add(k.regionId()));
235 region.setChildren(kidRegionIds);
Simon Huntc0f20c12016-05-09 09:30:20 -0700236 }
237
238 private void loadRegions() {
239 for (Region r : services.region().getRegions()) {
240 UiRegion region = addNewRegion(r);
241 updateRegion(region);
242 }
243 }
244
245 // invoked from UiSharedTopologyModel region listener
Simon Hunt338a3b42016-04-14 09:43:52 -0700246 void addOrUpdateRegion(Region region) {
Simon Huntc0f20c12016-05-09 09:30:20 -0700247 RegionId id = region.id();
248 UiRegion uiRegion = uiTopology.findRegion(id);
249 if (uiRegion == null) {
250 uiRegion = addNewRegion(region);
251 }
252 updateRegion(uiRegion);
253
254 postEvent(REGION_ADDED_OR_UPDATED, uiRegion);
Simon Hunt338a3b42016-04-14 09:43:52 -0700255 }
256
Simon Hunt58a0dd02016-05-17 11:54:23 -0700257 // package private for unit test access
258 UiRegion accessRegion(RegionId id) {
Simon Huntd5b96732016-07-08 13:22:27 -0700259 return id == null ? null : uiTopology.findRegion(id);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700260 }
261
Simon Huntc0f20c12016-05-09 09:30:20 -0700262 // invoked from UiSharedTopologyModel region listener
Simon Hunt338a3b42016-04-14 09:43:52 -0700263 void removeRegion(Region region) {
Simon Huntc0f20c12016-05-09 09:30:20 -0700264 RegionId id = region.id();
265 UiRegion uiRegion = uiTopology.findRegion(id);
266 if (uiRegion != null) {
267 uiTopology.remove(uiRegion);
268 postEvent(REGION_REMOVED, uiRegion);
269 } else {
270 log.warn(E_NO_ELEMENT, "region", id);
271 }
Simon Hunt338a3b42016-04-14 09:43:52 -0700272 }
273
Simon Hunt10973dd2016-08-01 15:50:35 -0700274 Set<UiRegion> getAllRegions() {
275 return uiTopology.allRegions();
276 }
277
Simon Huntc0f20c12016-05-09 09:30:20 -0700278
279 // === DEVICES
280
281 private UiDevice addNewDevice(Device d) {
282 UiDevice device = new UiDevice(uiTopology, d);
Simon Huntb1ce2602016-07-23 14:04:31 -0700283 updateDevice(device);
Simon Huntc0f20c12016-05-09 09:30:20 -0700284 uiTopology.add(device);
Simon Huntb1ce2602016-07-23 14:04:31 -0700285 log.debug("Device {} added to topology", device);
Simon Huntc0f20c12016-05-09 09:30:20 -0700286 return device;
287 }
288
Simon Huntb1ce2602016-07-23 14:04:31 -0700289 // make sure the UiDevice is tagged with the region it belongs to
Simon Huntc0f20c12016-05-09 09:30:20 -0700290 private void updateDevice(UiDevice device) {
Simon Huntb1ce2602016-07-23 14:04:31 -0700291 Region r = services.region().getRegionForDevice(device.id());
292 RegionId rid = r == null ? UiRegion.NULL_ID : r.id();
293 device.setRegionId(rid);
Simon Huntc0f20c12016-05-09 09:30:20 -0700294 }
295
296 private void loadDevices() {
297 for (Device d : services.device().getDevices()) {
Simon Huntb1ce2602016-07-23 14:04:31 -0700298 addNewDevice(d);
Simon Huntc0f20c12016-05-09 09:30:20 -0700299 }
300 }
301
302 // invoked from UiSharedTopologyModel device listener
Simon Huntcda9c032016-04-11 10:32:54 -0700303 void addOrUpdateDevice(Device device) {
Simon Huntc0f20c12016-05-09 09:30:20 -0700304 DeviceId id = device.id();
305 UiDevice uiDevice = uiTopology.findDevice(id);
306 if (uiDevice == null) {
307 uiDevice = addNewDevice(device);
Simon Huntb1ce2602016-07-23 14:04:31 -0700308 } else {
309 updateDevice(uiDevice);
Simon Huntc0f20c12016-05-09 09:30:20 -0700310 }
Simon Huntcda9c032016-04-11 10:32:54 -0700311
Simon Huntc0f20c12016-05-09 09:30:20 -0700312 postEvent(DEVICE_ADDED_OR_UPDATED, uiDevice);
Simon Huntcda9c032016-04-11 10:32:54 -0700313 }
314
Simon Hunt58a0dd02016-05-17 11:54:23 -0700315 // package private for unit test access
316 UiDevice accessDevice(DeviceId id) {
317 return uiTopology.findDevice(id);
318 }
319
Simon Huntc0f20c12016-05-09 09:30:20 -0700320 // invoked from UiSharedTopologyModel device listener
Simon Huntcda9c032016-04-11 10:32:54 -0700321 void removeDevice(Device device) {
Simon Huntc0f20c12016-05-09 09:30:20 -0700322 DeviceId id = device.id();
323 UiDevice uiDevice = uiTopology.findDevice(id);
324 if (uiDevice != null) {
325 uiTopology.remove(uiDevice);
326 postEvent(DEVICE_REMOVED, uiDevice);
327 } else {
328 log.warn(E_NO_ELEMENT, "device", id);
329 }
Simon Huntcda9c032016-04-11 10:32:54 -0700330 }
331
Simon Hunt4854f3d2016-08-02 18:13:15 -0700332 Set<UiDevice> getAllDevices() {
333 return uiTopology.allDevices();
334 }
335
Simon Huntc0f20c12016-05-09 09:30:20 -0700336
337 // === LINKS
338
339 private UiLink addNewLink(UiLinkId id) {
340 UiLink uiLink = new UiLink(uiTopology, id);
341 uiTopology.add(uiLink);
342 return uiLink;
343 }
344
345 private void updateLink(UiLink uiLink, Link link) {
346 uiLink.attachBackingLink(link);
347 }
348
349 private void loadLinks() {
350 for (Link link : services.link().getLinks()) {
351 UiLinkId id = uiLinkId(link);
352
353 UiLink uiLink = uiTopology.findLink(id);
354 if (uiLink == null) {
355 uiLink = addNewLink(id);
356 }
357 updateLink(uiLink, link);
358 }
359 }
360
361 // invoked from UiSharedTopologyModel link listener
Simon Hunt23fb1352016-04-11 12:15:19 -0700362 void addOrUpdateLink(Link link) {
Simon Huntc0f20c12016-05-09 09:30:20 -0700363 UiLinkId id = uiLinkId(link);
364 UiLink uiLink = uiTopology.findLink(id);
365 if (uiLink == null) {
366 uiLink = addNewLink(id);
367 }
368 updateLink(uiLink, link);
369
370 postEvent(LINK_ADDED_OR_UPDATED, uiLink);
Simon Hunt23fb1352016-04-11 12:15:19 -0700371 }
372
Simon Hunt58a0dd02016-05-17 11:54:23 -0700373 // package private for unit test access
374 UiLink accessLink(UiLinkId id) {
375 return uiTopology.findLink(id);
376 }
377
Simon Huntc0f20c12016-05-09 09:30:20 -0700378 // invoked from UiSharedTopologyModel link listener
Simon Hunt23fb1352016-04-11 12:15:19 -0700379 void removeLink(Link link) {
Simon Huntc0f20c12016-05-09 09:30:20 -0700380 UiLinkId id = uiLinkId(link);
381 UiLink uiLink = uiTopology.findLink(id);
382 if (uiLink != null) {
383 boolean remaining = uiLink.detachBackingLink(link);
384 if (remaining) {
385 postEvent(LINK_ADDED_OR_UPDATED, uiLink);
386 } else {
387 uiTopology.remove(uiLink);
388 postEvent(LINK_REMOVED, uiLink);
389 }
390 } else {
391 log.warn(E_NO_ELEMENT, "link", id);
392 }
Simon Hunt23fb1352016-04-11 12:15:19 -0700393 }
394
Simon Hunt4854f3d2016-08-02 18:13:15 -0700395 Set<UiLink> getAllLinks() {
396 return uiTopology.allLinks();
397 }
Simon Huntc0f20c12016-05-09 09:30:20 -0700398
399 // === HOSTS
400
Simon Hunt58a0dd02016-05-17 11:54:23 -0700401 private EdgeLink synthesizeLink(Host h) {
402 return createEdgeLink(h, true);
403 }
404
Simon Huntc0f20c12016-05-09 09:30:20 -0700405 private UiHost addNewHost(Host h) {
406 UiHost host = new UiHost(uiTopology, h);
407 uiTopology.add(host);
408
Simon Hunt58a0dd02016-05-17 11:54:23 -0700409 EdgeLink elink = synthesizeLink(h);
410 UiLinkId elinkId = uiLinkId(elink);
411 host.setEdgeLinkId(elinkId);
412
413 // add synthesized edge link to the topology
414 UiLink edgeLink = addNewLink(elinkId);
415 edgeLink.attachEdgeLink(elink);
Simon Huntc0f20c12016-05-09 09:30:20 -0700416
417 return host;
418 }
419
Simon Hunt58a0dd02016-05-17 11:54:23 -0700420 private void insertNewUiLink(UiLinkId id, EdgeLink e) {
421 UiLink newEdgeLink = addNewLink(id);
422 newEdgeLink.attachEdgeLink(e);
Simon Huntc0f20c12016-05-09 09:30:20 -0700423
Simon Huntc0f20c12016-05-09 09:30:20 -0700424 }
425
426 private void updateHost(UiHost uiHost, Host h) {
Simon Hunt58a0dd02016-05-17 11:54:23 -0700427 UiLink existing = uiTopology.findLink(uiHost.edgeLinkId());
428
429 EdgeLink currentElink = synthesizeLink(h);
430 UiLinkId currentElinkId = uiLinkId(currentElink);
431
432 if (existing != null) {
433 if (!currentElinkId.equals(existing.id())) {
434 // edge link has changed
435 insertNewUiLink(currentElinkId, currentElink);
436 uiHost.setEdgeLinkId(currentElinkId);
437
438 uiTopology.remove(existing);
439 }
440
441 } else {
442 // no previously existing edge link
443 insertNewUiLink(currentElinkId, currentElink);
444 uiHost.setEdgeLinkId(currentElinkId);
445
446 }
447
Simon Huntc0f20c12016-05-09 09:30:20 -0700448 HostLocation hloc = h.location();
449 uiHost.setLocation(hloc.deviceId(), hloc.port());
Simon Huntc0f20c12016-05-09 09:30:20 -0700450 }
451
452 private void loadHosts() {
453 for (Host h : services.host().getHosts()) {
454 UiHost host = addNewHost(h);
455 updateHost(host, h);
456 }
457 }
458
459 // invoked from UiSharedTopologyModel host listener
Simon Hunt23fb1352016-04-11 12:15:19 -0700460 void addOrUpdateHost(Host host) {
Simon Huntc0f20c12016-05-09 09:30:20 -0700461 HostId id = host.id();
462 UiHost uiHost = uiTopology.findHost(id);
463 if (uiHost == null) {
464 uiHost = addNewHost(host);
465 }
466 updateHost(uiHost, host);
467
468 postEvent(HOST_ADDED_OR_UPDATED, uiHost);
Simon Hunt23fb1352016-04-11 12:15:19 -0700469 }
470
Simon Huntc0f20c12016-05-09 09:30:20 -0700471 // invoked from UiSharedTopologyModel host listener
Simon Hunt23fb1352016-04-11 12:15:19 -0700472 void moveHost(Host host, Host prevHost) {
Simon Huntc0f20c12016-05-09 09:30:20 -0700473 UiHost uiHost = uiTopology.findHost(prevHost.id());
Simon Hunt58a0dd02016-05-17 11:54:23 -0700474 if (uiHost != null) {
475 updateHost(uiHost, host);
476 postEvent(HOST_MOVED, uiHost);
477 } else {
478 log.warn(E_NO_ELEMENT, "host", prevHost.id());
479 }
480 }
Simon Huntc0f20c12016-05-09 09:30:20 -0700481
Simon Hunt58a0dd02016-05-17 11:54:23 -0700482 // package private for unit test access
483 UiHost accessHost(HostId id) {
484 return uiTopology.findHost(id);
Simon Hunt23fb1352016-04-11 12:15:19 -0700485 }
486
Simon Huntc0f20c12016-05-09 09:30:20 -0700487 // invoked from UiSharedTopologyModel host listener
Simon Hunt23fb1352016-04-11 12:15:19 -0700488 void removeHost(Host host) {
Simon Huntc0f20c12016-05-09 09:30:20 -0700489 HostId id = host.id();
490 UiHost uiHost = uiTopology.findHost(id);
491 if (uiHost != null) {
Simon Hunt58a0dd02016-05-17 11:54:23 -0700492 UiLink edgeLink = uiTopology.findLink(uiHost.edgeLinkId());
493 uiTopology.remove(edgeLink);
Simon Huntc0f20c12016-05-09 09:30:20 -0700494 uiTopology.remove(uiHost);
Simon Huntc0f20c12016-05-09 09:30:20 -0700495 postEvent(HOST_REMOVED, uiHost);
496 } else {
497 log.warn(E_NO_ELEMENT, "host", id);
498 }
Simon Hunt23fb1352016-04-11 12:15:19 -0700499 }
Simon Hunt338a3b42016-04-14 09:43:52 -0700500
Simon Hunt4854f3d2016-08-02 18:13:15 -0700501 Set<UiHost> getAllHosts() {
502 return uiTopology.allHosts();
503 }
504
Simon Huntc0f20c12016-05-09 09:30:20 -0700505
Simon Huntb1ce2602016-07-23 14:04:31 -0700506 /**
507 * Refreshes the internal state.
508 */
509 public void refresh() {
510 // fix up internal linkages if they aren't correct
511
Simon Hunt4f4ffc32016-08-03 18:30:47 -0700512 // make sure regions reflect layout containment hierarchy
513 fixupContainmentHierarchy(uiTopology.nullRegion());
514 uiTopology.allRegions().forEach(this::fixupContainmentHierarchy);
515
516 // make sure devices are in the correct region
Simon Huntb1ce2602016-07-23 14:04:31 -0700517 Set<UiDevice> allDevices = uiTopology.allDevices();
518
519 services.region().getRegions().forEach(r -> {
520 RegionId rid = r.id();
521 UiRegion region = uiTopology.findRegion(rid);
522 if (region != null) {
523 Set<DeviceId> deviceIds = services.region().getRegionDevices(rid);
524 region.reconcileDevices(deviceIds);
525
526 deviceIds.forEach(devId -> {
527 UiDevice dev = uiTopology.findDevice(devId);
528 if (dev != null) {
529 dev.setRegionId(r.id());
530 allDevices.remove(dev);
531 } else {
532 log.warn("Region device ID {} but no UiDevice in topology",
533 devId);
534 }
535 });
536 } else {
537 log.warn("No UiRegion in topology for ID {}", rid);
538 }
539 });
540
541 // what is left over, must belong to the null-region
542 Set<DeviceId> leftOver = new HashSet<>(allDevices.size());
543 allDevices.forEach(d -> leftOver.add(d.id()));
544 uiTopology.nullRegion().reconcileDevices(leftOver);
545 }
546
Simon Huntc0f20c12016-05-09 09:30:20 -0700547 // === CACHE STATISTICS
548
Simon Hunt338a3b42016-04-14 09:43:52 -0700549 /**
Simon Hunt58a0dd02016-05-17 11:54:23 -0700550 * Returns a detailed (multi-line) string showing the contents of the cache.
551 *
552 * @return detailed string
553 */
554 public String dumpString() {
555 return uiTopology.dumpString();
556 }
557
558 /**
Simon Hunt338a3b42016-04-14 09:43:52 -0700559 * Returns the number of members in the cluster.
560 *
561 * @return number of cluster members
562 */
563 public int clusterMemberCount() {
564 return uiTopology.clusterMemberCount();
565 }
566
567 /**
Simon Huntc0f20c12016-05-09 09:30:20 -0700568 * Returns the number of regions in the topology.
Simon Hunt338a3b42016-04-14 09:43:52 -0700569 *
570 * @return number of regions
571 */
572 public int regionCount() {
573 return uiTopology.regionCount();
574 }
Simon Hunt58a0dd02016-05-17 11:54:23 -0700575
576 /**
577 * Returns the number of devices in the topology.
578 *
579 * @return number of devices
580 */
581 public int deviceCount() {
582 return uiTopology.deviceCount();
583 }
584
585 /**
586 * Returns the number of links in the topology.
587 *
588 * @return number of links
589 */
590 public int linkCount() {
591 return uiTopology.linkCount();
592 }
593
594 /**
595 * Returns the number of hosts in the topology.
596 *
597 * @return number of hosts
598 */
599 public int hostCount() {
600 return uiTopology.hostCount();
601 }
Simon Huntd5b96732016-07-08 13:22:27 -0700602
Simon Huntcda9c032016-04-11 10:32:54 -0700603}