blob: c4e1b6878f94d68b59125b529bb729981b7cea8c [file] [log] [blame]
Madan Jampani38a88212015-09-15 11:21:27 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Madan Jampani38a88212015-09-15 11:21:27 -07003 *
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 */
16package org.onosproject.store.host.impl;
17
alshabib8a4a6002015-11-25 14:31:16 -080018import com.google.common.collect.ImmutableSet;
19import com.google.common.collect.Sets;
Madan Jampani38a88212015-09-15 11:21:27 -070020import org.onlab.packet.IpAddress;
21import org.onlab.packet.MacAddress;
22import org.onlab.packet.VlanId;
23import org.onlab.util.KryoNamespace;
24import org.onosproject.net.Annotations;
25import org.onosproject.net.ConnectPoint;
26import org.onosproject.net.DefaultAnnotations;
27import org.onosproject.net.DefaultHost;
28import org.onosproject.net.DeviceId;
29import org.onosproject.net.Host;
30import org.onosproject.net.HostId;
Brian O'Connorf107bd72015-09-21 15:31:03 -070031import org.onosproject.net.HostLocation;
Madan Jampani38a88212015-09-15 11:21:27 -070032import org.onosproject.net.host.HostDescription;
33import org.onosproject.net.host.HostEvent;
34import org.onosproject.net.host.HostStore;
35import org.onosproject.net.host.HostStoreDelegate;
Madan Jampani38a88212015-09-15 11:21:27 -070036import org.onosproject.net.provider.ProviderId;
37import org.onosproject.store.AbstractStore;
38import org.onosproject.store.serializers.KryoNamespaces;
alshabib8a4a6002015-11-25 14:31:16 -080039import org.onosproject.store.service.ConsistentMap;
40import org.onosproject.store.service.MapEvent;
41import org.onosproject.store.service.MapEventListener;
42import org.onosproject.store.service.Serializer;
Madan Jampani38a88212015-09-15 11:21:27 -070043import org.onosproject.store.service.StorageService;
jobind19b7142019-05-17 09:46:52 -040044import org.onosproject.store.service.DistributedPrimitive.Status;
Ray Milkeyd0f017f2018-09-21 12:52:34 -070045import org.onosproject.store.service.Versioned;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070046import org.osgi.service.component.annotations.Activate;
47import org.osgi.service.component.annotations.Component;
48import org.osgi.service.component.annotations.Deactivate;
49import org.osgi.service.component.annotations.Reference;
50import org.osgi.service.component.annotations.ReferenceCardinality;
Madan Jampani38a88212015-09-15 11:21:27 -070051import org.slf4j.Logger;
52
alshabib8a4a6002015-11-25 14:31:16 -080053import java.util.Collection;
pier15743ea2019-04-11 11:35:55 +020054import java.util.Collections;
alshabib8a4a6002015-11-25 14:31:16 -080055import java.util.HashSet;
56import java.util.Map;
57import java.util.Objects;
58import java.util.Set;
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +053059import java.util.concurrent.ConcurrentHashMap;
60import java.util.concurrent.ScheduledExecutorService;
61import java.util.function.Consumer;
alshabib8a4a6002015-11-25 14:31:16 -080062import java.util.function.Predicate;
63import java.util.stream.Collectors;
64
alshabib8a4a6002015-11-25 14:31:16 -080065import static com.google.common.base.Preconditions.checkState;
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +053066import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
67import static org.onlab.util.Tools.groupedThreads;
alshabib8a4a6002015-11-25 14:31:16 -080068import static org.onosproject.net.DefaultAnnotations.merge;
jobind19b7142019-05-17 09:46:52 -040069import static org.onosproject.net.host.HostEvent.Type.*;
alshabib8a4a6002015-11-25 14:31:16 -080070import static org.slf4j.LoggerFactory.getLogger;
Madan Jampani38a88212015-09-15 11:21:27 -070071
72/**
73 * Manages the inventory of hosts using a {@code EventuallyConsistentMap}.
74 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070075@Component(immediate = true, service = HostStore.class)
alshabib8a4a6002015-11-25 14:31:16 -080076public class DistributedHostStore
Madan Jampani38a88212015-09-15 11:21:27 -070077 extends AbstractStore<HostEvent, HostStoreDelegate>
78 implements HostStore {
79
80 private final Logger log = getLogger(getClass());
81
Ray Milkeyd84f89b2018-08-17 14:54:17 -070082 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Madan Jampani38a88212015-09-15 11:21:27 -070083 protected StorageService storageService;
84
Madan Jampanic6371882016-06-03 21:30:17 -070085 private ConsistentMap<HostId, DefaultHost> hostsConsistentMap;
alshabib8a4a6002015-11-25 14:31:16 -080086 private Map<HostId, DefaultHost> hosts;
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +053087 private Map<IpAddress, Set<Host>> hostsByIp;
Harshada Chaundkarc9712222019-07-02 15:13:24 +000088 MapEventListener<HostId, DefaultHost> hostLocationTracker =
Madan Jampani38a88212015-09-15 11:21:27 -070089 new HostLocationTracker();
90
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +053091 private ScheduledExecutorService executor;
92
93 private Consumer<Status> statusChangeListener;
94
Madan Jampani38a88212015-09-15 11:21:27 -070095 @Activate
96 public void activate() {
97 KryoNamespace.Builder hostSerializer = KryoNamespace.newBuilder()
Jonathan Hart38feb6e2016-08-29 22:54:16 +000098 .register(KryoNamespaces.API);
Madan Jampanic6371882016-06-03 21:30:17 -070099 hostsConsistentMap = storageService.<HostId, DefaultHost>consistentMapBuilder()
Madan Jampani38a88212015-09-15 11:21:27 -0700100 .withName("onos-hosts")
alshabib8a4a6002015-11-25 14:31:16 -0800101 .withRelaxedReadConsistency()
102 .withSerializer(Serializer.using(hostSerializer.build()))
Madan Jampani38a88212015-09-15 11:21:27 -0700103 .build();
Charles Chan35a32322017-08-14 11:42:11 -0700104 hostsConsistentMap.addListener(hostLocationTracker);
Madan Jampanic6371882016-06-03 21:30:17 -0700105 hosts = hostsConsistentMap.asJavaMap();
alshabib8a4a6002015-11-25 14:31:16 -0800106
Charles Chan35c06ac2018-04-19 15:11:23 -0700107 executor = newSingleThreadScheduledExecutor(groupedThreads("onos/hosts", "status-listener", log));
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +0530108 statusChangeListener = status -> {
109 if (status == Status.ACTIVE) {
110 executor.execute(this::loadHostsByIp);
111 }
112 };
113 hostsConsistentMap.addStatusChangeListener(statusChangeListener);
114 loadHostsByIp();
Madan Jampani38a88212015-09-15 11:21:27 -0700115 log.info("Started");
116 }
117
118 @Deactivate
119 public void deactivate() {
Madan Jampanic6371882016-06-03 21:30:17 -0700120 hostsConsistentMap.removeListener(hostLocationTracker);
Charles Chan35c06ac2018-04-19 15:11:23 -0700121 executor.shutdown();
Charles Chan35a32322017-08-14 11:42:11 -0700122
Madan Jampani38a88212015-09-15 11:21:27 -0700123 log.info("Stopped");
124 }
125
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +0530126 private void loadHostsByIp() {
127 hostsByIp = new ConcurrentHashMap<IpAddress, Set<Host>>();
128 hostsConsistentMap.asJavaMap().values().forEach(host -> {
129 host.ipAddresses().forEach(ip -> {
130 Set<Host> existingHosts = hostsByIp.get(ip);
131 if (existingHosts == null) {
132 hostsByIp.put(ip, addHosts(host));
133 } else {
134 existingHosts.add(host);
135 }
136 });
137 });
138 }
139
Brian O'Connordab09742015-12-07 20:06:29 -0800140 private boolean shouldUpdate(DefaultHost existingHost,
141 ProviderId providerId,
Brian O'Connordab09742015-12-07 20:06:29 -0800142 HostDescription hostDescription,
143 boolean replaceIPs) {
144 if (existingHost == null) {
145 return true;
146 }
147
Charles Chan69ebcbb2017-04-27 14:33:21 -0700148 // Avoid overriding configured host with learnt host
149 if (existingHost.configured() && !hostDescription.configured()) {
Charles Chan29ecdee2017-02-22 18:46:56 -0800150 return false;
151 }
152
Brian O'Connordab09742015-12-07 20:06:29 -0800153 if (!Objects.equals(existingHost.providerId(), providerId) ||
154 !Objects.equals(existingHost.mac(), hostDescription.hwAddress()) ||
155 !Objects.equals(existingHost.vlan(), hostDescription.vlan()) ||
Jonghwan Hyun2c95acf2018-03-14 16:47:34 -0700156 !Objects.equals(existingHost.innerVlan(), hostDescription.innerVlan()) ||
157 !Objects.equals(existingHost.tpid(), hostDescription.tpid()) ||
Charles Chancd06c692017-04-27 20:46:06 -0700158 !Objects.equals(existingHost.locations(), hostDescription.locations())) {
Brian O'Connordab09742015-12-07 20:06:29 -0800159 return true;
160 }
161
162 if (replaceIPs) {
163 if (!Objects.equals(hostDescription.ipAddress(),
jobind19b7142019-05-17 09:46:52 -0400164 existingHost.ipAddresses())) {
Brian O'Connordab09742015-12-07 20:06:29 -0800165 return true;
166 }
167 } else {
168 if (!existingHost.ipAddresses().containsAll(hostDescription.ipAddress())) {
169 return true;
170 }
171 }
172
173 // check to see if any of the annotations provided by hostDescription
174 // differ from those in the existing host
175 return hostDescription.annotations().keys().stream()
jobind19b7142019-05-17 09:46:52 -0400176 .anyMatch(k -> !Objects.equals(hostDescription.annotations().value(k),
177 existingHost.annotations().value(k)));
Brian O'Connordab09742015-12-07 20:06:29 -0800178
179
180 }
181
Charles Chan009c3082015-11-10 14:18:04 -0800182 // TODO No longer need to return HostEvent
Madan Jampani38a88212015-09-15 11:21:27 -0700183 @Override
184 public HostEvent createOrUpdateHost(ProviderId providerId,
Brian O'Connorf107bd72015-09-21 15:31:03 -0700185 HostId hostId,
186 HostDescription hostDescription,
187 boolean replaceIPs) {
Madan Jampanic6371882016-06-03 21:30:17 -0700188 hostsConsistentMap.computeIf(hostId,
jobind19b7142019-05-17 09:46:52 -0400189 existingHost -> shouldUpdate(existingHost, providerId,
190 hostDescription, replaceIPs),
191 (id, existingHost) -> {
Brian O'Connorf107bd72015-09-21 15:31:03 -0700192
jobind19b7142019-05-17 09:46:52 -0400193 final Set<IpAddress> addresses;
194 if (existingHost == null || replaceIPs) {
195 addresses = ImmutableSet.copyOf(hostDescription.ipAddress());
196 } else {
197 addresses = Sets.newHashSet(existingHost.ipAddresses());
198 addresses.addAll(hostDescription.ipAddress());
199 }
Brian O'Connorf107bd72015-09-21 15:31:03 -0700200
jobind19b7142019-05-17 09:46:52 -0400201 final Annotations annotations;
202 if (existingHost != null) {
203 annotations = merge((DefaultAnnotations) existingHost.annotations(),
204 hostDescription.annotations());
205 } else {
206 annotations = hostDescription.annotations();
207 }
Jonathan Hart38feb6e2016-08-29 22:54:16 +0000208
jobind19b7142019-05-17 09:46:52 -0400209 return new DefaultHost(providerId,
210 hostId,
211 hostDescription.hwAddress(),
212 hostDescription.vlan(),
213 hostDescription.locations(),
214 addresses,
215 hostDescription.innerVlan(),
216 hostDescription.tpid(),
217 hostDescription.configured(),
218 annotations);
219 });
Charles Chan009c3082015-11-10 14:18:04 -0800220 return null;
Madan Jampani38a88212015-09-15 11:21:27 -0700221 }
222
Charles Chan009c3082015-11-10 14:18:04 -0800223 // TODO No longer need to return HostEvent
Madan Jampani38a88212015-09-15 11:21:27 -0700224 @Override
225 public HostEvent removeHost(HostId hostId) {
Charles Chan009c3082015-11-10 14:18:04 -0800226 hosts.remove(hostId);
227 return null;
Madan Jampani38a88212015-09-15 11:21:27 -0700228 }
229
Charles Chan009c3082015-11-10 14:18:04 -0800230 // TODO No longer need to return HostEvent
Madan Jampani38a88212015-09-15 11:21:27 -0700231 @Override
samanwita palc40e5ed2015-09-24 11:01:51 -0700232 public HostEvent removeIp(HostId hostId, IpAddress ipAddress) {
Charles Chan009c3082015-11-10 14:18:04 -0800233 hosts.compute(hostId, (id, existingHost) -> {
samanwita palc40e5ed2015-09-24 11:01:51 -0700234 if (existingHost != null) {
235 checkState(Objects.equals(hostId.mac(), existingHost.mac()),
236 "Existing and new MAC addresses differ.");
237 checkState(Objects.equals(hostId.vlanId(), existingHost.vlan()),
238 "Existing and new VLANs differ.");
239
samanwita pale7c08de2015-09-24 21:59:49 -0700240 Set<IpAddress> addresses = existingHost.ipAddresses();
samanwita palc40e5ed2015-09-24 11:01:51 -0700241 if (addresses != null && addresses.contains(ipAddress)) {
samanwita pale7c08de2015-09-24 21:59:49 -0700242 addresses = new HashSet<>(existingHost.ipAddresses());
samanwita palc40e5ed2015-09-24 11:01:51 -0700243 addresses.remove(ipAddress);
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +0530244 removeIpFromHostsByIp(existingHost, ipAddress);
samanwita palc40e5ed2015-09-24 11:01:51 -0700245 return new DefaultHost(existingHost.providerId(),
246 hostId,
247 existingHost.mac(),
248 existingHost.vlan(),
Charles Chancd06c692017-04-27 20:46:06 -0700249 existingHost.locations(),
samanwita palc40e5ed2015-09-24 11:01:51 -0700250 ImmutableSet.copyOf(addresses),
Charles Chan7993dfd2019-12-12 16:58:08 -0800251 existingHost.innerVlan(),
252 existingHost.tpid(),
Charles Chancd06c692017-04-27 20:46:06 -0700253 existingHost.configured(),
Charles Chan7993dfd2019-12-12 16:58:08 -0800254 existingHost.suspended(),
samanwita palc40e5ed2015-09-24 11:01:51 -0700255 existingHost.annotations());
256 } else {
257 return existingHost;
258 }
259 }
260 return null;
261 });
Charles Chan009c3082015-11-10 14:18:04 -0800262 return null;
samanwita palc40e5ed2015-09-24 11:01:51 -0700263 }
264
265 @Override
Charles Chan47933752017-11-30 15:37:50 -0800266 public void appendLocation(HostId hostId, HostLocation location) {
267 log.debug("Appending location {} to host {}", location, hostId);
268 hosts.compute(hostId, (id, existingHost) -> {
269 if (existingHost != null) {
270 checkState(Objects.equals(hostId.mac(), existingHost.mac()),
271 "Existing and new MAC addresses differ.");
272 checkState(Objects.equals(hostId.vlanId(), existingHost.vlan()),
273 "Existing and new VLANs differ.");
274
Charles Chan9bd0e5a2018-04-25 18:51:46 -0400275 // Move within the same switch
276 // Simply replace old location that is on the same device
277 Set<HostLocation> newLocations = Sets.newHashSet(location);
278 existingHost.locations().stream().filter(loc -> !loc.deviceId().equals(location.deviceId()))
279 .forEach(newLocations::add);
Charles Chan47933752017-11-30 15:37:50 -0800280
281 return new DefaultHost(existingHost.providerId(),
jobind19b7142019-05-17 09:46:52 -0400282 hostId, existingHost.mac(), existingHost.vlan(),
283 newLocations, existingHost.ipAddresses(),
Charles Chan7993dfd2019-12-12 16:58:08 -0800284 existingHost.innerVlan(), existingHost.tpid(),
285 existingHost.configured(), existingHost.suspended(), existingHost.annotations());
Charles Chan47933752017-11-30 15:37:50 -0800286 }
287 return null;
288 });
289 }
290
291 @Override
Charles Chan888e20a2017-05-01 15:44:23 -0700292 public void removeLocation(HostId hostId, HostLocation location) {
Charles Chan47933752017-11-30 15:37:50 -0800293 log.debug("Removing location {} from host {}", location, hostId);
Charles Chan888e20a2017-05-01 15:44:23 -0700294 hosts.compute(hostId, (id, existingHost) -> {
295 if (existingHost != null) {
296 checkState(Objects.equals(hostId.mac(), existingHost.mac()),
297 "Existing and new MAC addresses differ.");
298 checkState(Objects.equals(hostId.vlanId(), existingHost.vlan()),
299 "Existing and new VLANs differ.");
300
301 Set<HostLocation> locations = new HashSet<>(existingHost.locations());
302 locations.remove(location);
303
304 // Remove entire host if we are removing the last location
305 return locations.isEmpty() ? null :
306 new DefaultHost(existingHost.providerId(),
307 hostId, existingHost.mac(), existingHost.vlan(),
308 locations, existingHost.ipAddresses(),
Charles Chan7993dfd2019-12-12 16:58:08 -0800309 existingHost.innerVlan(), existingHost.tpid(),
310 existingHost.configured(), existingHost.suspended(), existingHost.annotations());
Charles Chan888e20a2017-05-01 15:44:23 -0700311 }
312 return null;
313 });
314 }
315
316 @Override
Madan Jampani38a88212015-09-15 11:21:27 -0700317 public int getHostCount() {
318 return hosts.size();
319 }
320
321 @Override
322 public Iterable<Host> getHosts() {
323 return ImmutableSet.copyOf(hosts.values());
324 }
325
326 @Override
327 public Host getHost(HostId hostId) {
328 return hosts.get(hostId);
329 }
330
331 @Override
332 public Set<Host> getHosts(VlanId vlanId) {
333 return filter(hosts.values(), host -> Objects.equals(host.vlan(), vlanId));
334 }
335
336 @Override
337 public Set<Host> getHosts(MacAddress mac) {
338 return filter(hosts.values(), host -> Objects.equals(host.mac(), mac));
339 }
340
341 @Override
342 public Set<Host> getHosts(IpAddress ip) {
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +0530343 Set<Host> hosts = hostsByIp.get(ip);
344 return hosts != null ? ImmutableSet.copyOf(hosts) : ImmutableSet.of();
Madan Jampani38a88212015-09-15 11:21:27 -0700345 }
346
347 @Override
348 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Charles Chan009c3082015-11-10 14:18:04 -0800349 Set<Host> filtered = hosts.entrySet().stream()
Charles Chancd06c692017-04-27 20:46:06 -0700350 .filter(entry -> entry.getValue().locations().contains(connectPoint))
Charles Chan009c3082015-11-10 14:18:04 -0800351 .map(Map.Entry::getValue)
352 .collect(Collectors.toSet());
353 return ImmutableSet.copyOf(filtered);
Madan Jampani38a88212015-09-15 11:21:27 -0700354 }
355
356 @Override
357 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Charles Chan009c3082015-11-10 14:18:04 -0800358 Set<Host> filtered = hosts.entrySet().stream()
Charles Chancd06c692017-04-27 20:46:06 -0700359 .filter(entry -> entry.getValue().locations().stream()
360 .map(HostLocation::deviceId).anyMatch(dpid -> dpid.equals(deviceId)))
Charles Chan009c3082015-11-10 14:18:04 -0800361 .map(Map.Entry::getValue)
362 .collect(Collectors.toSet());
HIGUCHI Yutafe2122c2015-09-30 13:46:22 -0700363 return ImmutableSet.copyOf(filtered);
Madan Jampani38a88212015-09-15 11:21:27 -0700364 }
365
jobind19b7142019-05-17 09:46:52 -0400366 @Override
367 public void suspend(HostId hostId) {
368 hosts.compute(hostId, (id, existingHost) -> {
369 if (existingHost != null) {
370 if (!existingHost.suspended()) {
371 return new DefaultHost(existingHost.providerId(),
372 hostId,
373 existingHost.mac(),
374 existingHost.vlan(),
375 existingHost.locations(),
376 existingHost.ipAddresses(),
377 existingHost.innerVlan(),
378 existingHost.tpid(),
379 existingHost.configured(),
380 true,
381 existingHost.annotations());
382 }
383
384 }
385 return null;
386 });
387 }
388
389 @Override
390 public void unsuspend(HostId hostId) {
391 hosts.compute(hostId, (id, existingHost) -> {
392 if (existingHost != null) {
393 if (existingHost.suspended()) {
394 return new DefaultHost(existingHost.providerId(),
395 hostId,
396 existingHost.mac(),
397 existingHost.vlan(),
398 existingHost.locations(),
399 existingHost.ipAddresses(),
400 existingHost.innerVlan(),
401 existingHost.tpid(),
402 existingHost.configured(),
403 false,
404 existingHost.annotations());
405
406 }
407 }
408 return null;
409 });
410 }
411
Madan Jampani38a88212015-09-15 11:21:27 -0700412 private Set<Host> filter(Collection<DefaultHost> collection, Predicate<DefaultHost> predicate) {
413 return collection.stream().filter(predicate).collect(Collectors.toSet());
414 }
415
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +0530416 private Set<Host> addHosts(Host host) {
417 Set<Host> hosts = Sets.newConcurrentHashSet();
418 hosts.add(host);
419 return hosts;
420 }
421
422 private Set<Host> updateHosts(Set<Host> existingHosts, Host host) {
pier15743ea2019-04-11 11:35:55 +0200423 existingHosts.removeIf(existingHost -> existingHost.id().equals(host.id()));
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +0530424 existingHosts.add(host);
425 return existingHosts;
426 }
427
428 private Set<Host> removeHosts(Set<Host> existingHosts, Host host) {
Harshada Chaundkarc9712222019-07-02 15:13:24 +0000429
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +0530430 if (existingHosts != null) {
pier15743ea2019-04-11 11:35:55 +0200431 existingHosts.removeIf(existingHost -> existingHost.id().equals(host.id()));
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +0530432 }
433
Ray Milkey74e59132018-01-17 15:24:52 -0800434 if (existingHosts == null || existingHosts.isEmpty()) {
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +0530435 return null;
436 }
437 return existingHosts;
438 }
439
pier15743ea2019-04-11 11:35:55 +0200440 private void updateHostsByIp(DefaultHost host, DefaultHost prevHost) {
Harshada Chaundkarc9712222019-07-02 15:13:24 +0000441 // Let's update first the current ips
442 host.ipAddresses().forEach(
pier15743ea2019-04-11 11:35:55 +0200443 ip -> hostsByIp.compute(ip, (k, v) -> v == null ? addHosts(host) : updateHosts(v, host)));
Harshada Chaundkarc9712222019-07-02 15:13:24 +0000444
pier15743ea2019-04-11 11:35:55 +0200445 // Let's remove then each old ip
Harshada Chaundkarc9712222019-07-02 15:13:24 +0000446 Set<IpAddress> oldIps = prevHost != null ? prevHost.ipAddresses() : Collections.emptySet();
pier15743ea2019-04-11 11:35:55 +0200447 Sets.difference(oldIps, host.ipAddresses()).forEach(
448 ip -> hostsByIp.computeIfPresent(ip, (k, v) -> removeHosts(v, host)));
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +0530449 }
450
451 private void removeHostsByIp(DefaultHost host) {
pier15743ea2019-04-11 11:35:55 +0200452 host.ipAddresses().forEach(ip -> hostsByIp.computeIfPresent(ip, (k, v) -> removeHosts(v, host)));
Deepa Vaddireddy0a71c8b2017-01-19 21:20:45 +0530453 }
454
455 private void removeIpFromHostsByIp(DefaultHost host, IpAddress ip) {
456 hostsByIp.computeIfPresent(ip, (k, v) -> removeHosts(v, host));
457 }
458
alshabib8a4a6002015-11-25 14:31:16 -0800459 private class HostLocationTracker implements MapEventListener<HostId, DefaultHost> {
Madan Jampani38a88212015-09-15 11:21:27 -0700460 @Override
alshabib8a4a6002015-11-25 14:31:16 -0800461 public void event(MapEvent<HostId, DefaultHost> event) {
pier15743ea2019-04-11 11:35:55 +0200462 DefaultHost host = Versioned.valueOrNull(event.newValue());
463 DefaultHost prevHost = Versioned.valueOrNull(event.oldValue());
alshabib1400ce92015-12-16 15:05:47 -0800464 switch (event.type()) {
465 case INSERT:
pier15743ea2019-04-11 11:35:55 +0200466 updateHostsByIp(host, prevHost);
Charles Chan009c3082015-11-10 14:18:04 -0800467 notifyDelegate(new HostEvent(HOST_ADDED, host));
alshabib1400ce92015-12-16 15:05:47 -0800468 break;
469 case UPDATE:
pier15743ea2019-04-11 11:35:55 +0200470 updateHostsByIp(host, prevHost);
jobind19b7142019-05-17 09:46:52 -0400471 if (host.suspended() && !prevHost.suspended()) {
472 notifyDelegate(new HostEvent(HOST_SUSPENDED, host, prevHost));
473 } else if (!host.suspended() && prevHost.suspended()) {
474 notifyDelegate(new HostEvent(HOST_UNSUSPENDED, host, prevHost));
475 } else if (!Objects.equals(prevHost.locations(), host.locations())) {
alshabib1400ce92015-12-16 15:05:47 -0800476 notifyDelegate(new HostEvent(HOST_MOVED, host, prevHost));
477 } else if (!Objects.equals(prevHost, host)) {
478 notifyDelegate(new HostEvent(HOST_UPDATED, host, prevHost));
479 }
480 break;
481 case REMOVE:
pier15743ea2019-04-11 11:35:55 +0200482 removeHostsByIp(prevHost);
483 notifyDelegate(new HostEvent(HOST_REMOVED, prevHost));
alshabib1400ce92015-12-16 15:05:47 -0800484 break;
485 default:
486 log.warn("Unknown map event type: {}", event.type());
Madan Jampani38a88212015-09-15 11:21:27 -0700487 }
488 }
489 }
490}