diff options
author | Håkon Hallingstad <hakon@verizonmedia.com> | 2020-03-01 14:56:11 +0100 |
---|---|---|
committer | Håkon Hallingstad <hakon@verizonmedia.com> | 2020-03-01 14:56:11 +0100 |
commit | 496054ead605206c528eab589eca6f4e6f9d4f29 (patch) | |
tree | 79c0895d3e02a47c7ed7dac544725cac293d9b95 /service-monitor | |
parent | aae80e66af1e581b3bd3bdf67a48fb57bf8ac8f4 (diff) |
More effective duper model update on activation
Diffstat (limited to 'service-monitor')
-rw-r--r-- | service-monitor/src/main/java/com/yahoo/vespa/service/duper/DuperModel.java | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/duper/DuperModel.java b/service-monitor/src/main/java/com/yahoo/vespa/service/duper/DuperModel.java index ca4a1e7f9c5..a99c7b4219f 100644 --- a/service-monitor/src/main/java/com/yahoo/vespa/service/duper/DuperModel.java +++ b/service-monitor/src/main/java/com/yahoo/vespa/service/duper/DuperModel.java @@ -10,12 +10,12 @@ import com.yahoo.vespa.service.monitor.DuperModelListener; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.logging.Logger; -import java.util.stream.Collectors; /** * A non-thread-safe mutable container of ApplicationInfo, also taking care of listeners on changes. @@ -26,7 +26,7 @@ public class DuperModel { private static Logger logger = Logger.getLogger(DuperModel.class.getName()); private final Map<ApplicationId, ApplicationInfo> applicationsById = new HashMap<>(); - private final Map<HostName, ApplicationInfo> applicationsByHostname = new HashMap<>(); + private final Map<HostName, ApplicationId> idsByHostname = new HashMap<>(); private final Map<ApplicationId, Set<HostName>> hostnamesById = new HashMap<>(); private final List<DuperModelListener> listeners = new ArrayList<>(); @@ -53,7 +53,7 @@ public class DuperModel { } public int numberOfHosts() { - return applicationsByHostname.size(); + return idsByHostname.size(); } public boolean contains(ApplicationId applicationId) { @@ -65,7 +65,7 @@ public class DuperModel { } public Optional<ApplicationInfo> getApplicationInfo(HostName hostName) { - return Optional.ofNullable(applicationsByHostname.get(hostName)); + return Optional.ofNullable(idsByHostname.get(hostName)).map(applicationsById::get); } public List<ApplicationInfo> getApplicationInfos() { @@ -73,7 +73,8 @@ public class DuperModel { } public void add(ApplicationInfo applicationInfo) { - ApplicationInfo oldApplicationInfo = applicationsById.put(applicationInfo.getApplicationId(), applicationInfo); + ApplicationId id = applicationInfo.getApplicationId(); + ApplicationInfo oldApplicationInfo = applicationsById.put(id, applicationInfo); final String logPrefix; if (oldApplicationInfo == null) { @@ -81,20 +82,35 @@ public class DuperModel { } else { logPrefix = isComplete ? "Reactivated application " : "Rebootstrapped application "; } - logger.log(LogLevel.INFO, logPrefix + applicationInfo.getApplicationId()); + logger.log(LogLevel.INFO, logPrefix + id); - Set<HostName> oldHostnames = hostnamesById.remove(applicationInfo.getApplicationId()); - if (oldHostnames != null) { - oldHostnames.forEach(applicationsByHostname::remove); - } + Set<HostName> hostnames = hostnamesById.computeIfAbsent(id, k -> new HashSet<>()); + Set<HostName> removedHosts = new HashSet<>(hostnames); - Set<HostName> hostnames = applicationInfo.getModel().getHosts().stream() + applicationInfo.getModel().getHosts().stream() .map(HostInfo::getHostname) .map(HostName::from) - .collect(Collectors.toSet()); - - hostnamesById.put(applicationInfo.getApplicationId(), hostnames); - hostnames.forEach(hostname -> applicationsByHostname.put(hostname, applicationInfo)); + .forEach(hostname -> { + if (!removedHosts.remove(hostname)) { + hostnames.add(hostname); + ApplicationId previousId = idsByHostname.put(hostname, id); + + if (previousId != null && !previousId.equals(id)) { + // If an activation contains a host that is currently assigned to a + // different application we will patch up our data structures to remain + // internally consistent. But listeners may be fooled. + logger.log(LogLevel.WARNING, hostname + " has been reassigned from " + + previousId + " to " + id); + + Set<HostName> previousHostnames = hostnamesById.get(id); + if (previousHostnames != null) { + previousHostnames.remove(hostname); + } + } + } + }); + + removedHosts.forEach(idsByHostname::remove); listeners.forEach(listener -> listener.applicationActivated(applicationInfo)); } @@ -102,7 +118,7 @@ public class DuperModel { public void remove(ApplicationId applicationId) { Set<HostName> hostnames = hostnamesById.remove(applicationId); if (hostnames != null) { - hostnames.forEach(applicationsByHostname::remove); + hostnames.forEach(idsByHostname::remove); } ApplicationInfo application = applicationsById.remove(applicationId); |