diff options
author | Harald Musum <musum@verizonmedia.com> | 2020-12-07 14:23:28 +0100 |
---|---|---|
committer | Harald Musum <musum@verizonmedia.com> | 2020-12-07 14:23:28 +0100 |
commit | 7e7b7c72b7ca4131f6f29efa0f9d63f857d9f369 (patch) | |
tree | a037b007b9c4cb81b247d8d14227d74374f4bbb3 | |
parent | f98e158a6f61cd39029f439da903f10e75e4c3fa (diff) | |
parent | 72a1848f3d752aa16495fe39a3ebd58463b9b277 (diff) |
Merge branch 'master' into hmusum/refactor-reconfigurer
17 files changed, 187 insertions, 28 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java index ddb3e21fb57..f085b4a9fde 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java @@ -115,7 +115,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { private static final String ENVIRONMENT_VARIABLES_ELEMENT = "environment-variables"; // The node count to enforce in a cluster running ZooKeeper - private static final int MIN_ZOOKEEPER_NODE_COUNT = 3; + private static final int MIN_ZOOKEEPER_NODE_COUNT = 1; private static final int MAX_ZOOKEEPER_NODE_COUNT = 7; public enum Networking { disable, enable } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java index 0728925fde1..06d2a461342 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java @@ -900,7 +900,7 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase { } { try { - tester.createModel(servicesXml.apply(1), true); + tester.createModel(servicesXml.apply(2), true); fail("Expected exception"); } catch (IllegalArgumentException ignored) {} } diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterResources.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterResources.java index 8f4c9f81d7f..20e5e887c72 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterResources.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterResources.java @@ -63,6 +63,10 @@ public class ClusterResources { .withBandwidthGbps(nodeResources.bandwidthGbps() * nodes); } + public ClusterResources justNumbers() { + return new ClusterResources(nodes, groups, nodeResources.justNumbers()); + } + @Override public boolean equals(Object o) { if (o == this) return true; diff --git a/container-accesslogging/src/main/java/com/yahoo/container/logging/LogFileHandler.java b/container-accesslogging/src/main/java/com/yahoo/container/logging/LogFileHandler.java index 75e9febc192..ab246a21a43 100644 --- a/container-accesslogging/src/main/java/com/yahoo/container/logging/LogFileHandler.java +++ b/container-accesslogging/src/main/java/com/yahoo/container/logging/LogFileHandler.java @@ -298,7 +298,14 @@ public class LogFileHandler extends StreamHandler { if (symlinkName == null) return; File f = new File(fileName); File f2 = new File(f.getParent(), symlinkName); - String [] cmd = new String[]{"/bin/ln", "-sf", f.getName(), f2.getPath()}; + String canonicalPath; + try { + canonicalPath = f.getCanonicalPath(); + } catch (IOException e) { + logger.warning("Got '" + e + "' while doing f.getCanonicalPath() on file '" + f.getPath() + "'."); + return; + } + String [] cmd = new String[]{"/bin/ln", "-sf", canonicalPath, f2.getPath()}; try { int retval = new ProcessExecuter().exec(cmd).getFirst(); // Detonator pattern: Think of all the fun we can have if ln isn't what we diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackageValidator.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackageValidator.java index 3e72936575d..bb2d8b3c553 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackageValidator.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackageValidator.java @@ -18,8 +18,10 @@ import com.yahoo.vespa.hosted.controller.deployment.DeploymentSteps; import java.time.Instant; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -46,6 +48,7 @@ public class ApplicationPackageValidator { validateSteps(applicationPackage.deploymentSpec()); validateEndpointRegions(applicationPackage.deploymentSpec()); validateEndpointChange(application, applicationPackage, instant); + validateCompactedEndpoint(applicationPackage); validateSecurityClientsPem(applicationPackage); } @@ -98,6 +101,25 @@ public class ApplicationPackageValidator { instant)); } + /** Verify that compactable endpoint parts (instance aname nd endpoint ID) do not clash */ + private void validateCompactedEndpoint(ApplicationPackage applicationPackage) { + Map<List<String>, InstanceEndpoint> instanceEndpoints = new HashMap<>(); + for (var instanceSpec : applicationPackage.deploymentSpec().instances()) { + for (var endpoint : instanceSpec.endpoints()) { + List<String> nonCompactableIds = nonCompactableIds(instanceSpec.name(), endpoint); + InstanceEndpoint instanceEndpoint = new InstanceEndpoint(instanceSpec.name(), endpoint.endpointId()); + InstanceEndpoint existingEndpoint = instanceEndpoints.get(nonCompactableIds); + if (existingEndpoint != null) { + throw new IllegalArgumentException("Endpoint with ID '" + endpoint.endpointId() + "' in instance '" + + instanceSpec.name().value() + + "' clashes with endpoint '" + existingEndpoint.endpointId + + "' in instance '" + existingEndpoint.instance + "'"); + } + instanceEndpoints.put(nonCompactableIds, instanceEndpoint); + } + } + } + /** Verify changes to endpoint configuration by comparing given application package to the existing one, if any */ private void validateEndpointChange(Application application, InstanceName instanceName, ApplicationPackage applicationPackage, Instant instant) { var validationId = ValidationId.globalEndpointChange; @@ -161,4 +183,28 @@ public class ApplicationPackageValidator { }); } + /** Returns a list of the non-compactable IDs of given instance and endpoint */ + private static List<String> nonCompactableIds(InstanceName instance, Endpoint endpoint) { + List<String> ids = new ArrayList<>(2); + if (!instance.isDefault()) { + ids.add(instance.value()); + } + if (!"default".equals(endpoint.endpointId())) { + ids.add(endpoint.endpointId()); + } + return ids; + } + + private static class InstanceEndpoint { + + private final InstanceName instance; + private final String endpointId; + + public InstanceEndpoint(InstanceName instance, String endpointId) { + this.instance = instance; + this.endpointId = endpointId; + } + + } + } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java index cbf6307f5e6..be51f39374b 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java @@ -699,7 +699,8 @@ public class ApplicationApiHandler extends LoggingRequestHandler { toSlime(cluster.min(), clusterObject.setObject("min")); toSlime(cluster.max(), clusterObject.setObject("max")); toSlime(cluster.current(), clusterObject.setObject("current")); - if (cluster.target().isPresent() && ! cluster.target().get().equals(cluster.current())) + if (cluster.target().isPresent() + && ! cluster.target().get().justNumbers().equals(cluster.current().justNumbers())) toSlime(cluster.target().get(), clusterObject.setObject("target")); cluster.suggested().ifPresent(suggested -> toSlime(suggested, clusterObject.setObject("suggested"))); scalingEventsToSlime(cluster.scalingEvents(), clusterObject.setArray("scalingEvents")); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java index a3b22ccd649..569c22d8bf6 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java @@ -977,4 +977,34 @@ public class ControllerTest { app1.submit().deploy(); } + @Test + public void testClashingEndpointIdAndInstanceName() { + String deploymentXml = "<deployment version='1.0' athenz-domain='domain' athenz-service='service'>\n" + + " <instance id=\"default\">\n" + + " <prod>\n" + + " <region active=\"true\">us-west-1</region>\n" + + " </prod>\n" + + " <endpoints>\n" + + " <endpoint id=\"dev\" container-id=\"qrs\"/>\n" + + " </endpoints>\n" + + " </instance>\n" + + " <instance id=\"dev\">\n" + + " <prod>\n" + + " <region active=\"true\">us-west-1</region>\n" + + " </prod>\n" + + " <endpoints>\n" + + " <endpoint id=\"default\" container-id=\"qrs\"/>\n" + + " </endpoints>\n" + + " </instance>\n" + + "</deployment>\n"; + ApplicationPackage applicationPackage = ApplicationPackageBuilder.fromDeploymentXml(deploymentXml); + try { + tester.newDeploymentContext().submit(applicationPackage); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertEquals("Endpoint with ID 'default' in instance 'dev' clashes with endpoint 'dev' in instance 'default'", + e.getMessage()); + } + } + } diff --git a/fnet/src/vespa/fnet/transport_thread.cpp b/fnet/src/vespa/fnet/transport_thread.cpp index 8c3783c74a4..5e1a9759a60 100644 --- a/fnet/src/vespa/fnet/transport_thread.cpp +++ b/fnet/src/vespa/fnet/transport_thread.cpp @@ -393,7 +393,7 @@ FNET_TransportThread::InitEventLoop() } void -FNET_TransportThread::handle_wakeup_events() +FNET_TransportThread::handle_wakeup() { { std::lock_guard<std::mutex> guard(_lock); @@ -473,10 +473,11 @@ FNET_TransportThread::EventLoopIteration() { _now = steady_clock::now(); // handle io-events - _selector.dispatch(*this); + auto dispatchResult = _selector.dispatch(*this); - // Must be called after selector.dispatch - handle_wakeup_events(); + if ((dispatchResult == vespalib::SelectorDispatchResult::NO_WAKEUP) && (getConfig()._events_before_wakeup > 1)) { + handle_wakeup(); + } // handle IOC time-outs if (getConfig()._iocTimeOut > vespalib::duration::zero()) { diff --git a/fnet/src/vespa/fnet/transport_thread.h b/fnet/src/vespa/fnet/transport_thread.h index 36490c88656..371544f9c8a 100644 --- a/fnet/src/vespa/fnet/transport_thread.h +++ b/fnet/src/vespa/fnet/transport_thread.h @@ -172,8 +172,6 @@ private: return _shutdown.load(std::memory_order_relaxed); } - void handle_wakeup_events(); - public: FNET_TransportThread(const FNET_TransportThread &) = delete; FNET_TransportThread &operator=(const FNET_TransportThread &) = delete; @@ -404,8 +402,8 @@ public: void WaitFinished(); - // Empty selector call-back for selector wakeup - void handle_wakeup() { } + // selector call-back for wakeup events + void handle_wakeup(); // selector call-back for io-events void handle_event(FNET_IOComponent &ctx, bool read, bool write); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java index 58cbe3a96d7..92de7232786 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java @@ -55,7 +55,7 @@ public class Autoscaler { * @return scaling advice for this cluster */ public Advice autoscale(Cluster cluster, NodeList clusterNodes) { - if (cluster.minResources().equals(cluster.maxResources())) return Advice.none("Autoscaling is disabled"); // Shortcut + if (cluster.minResources().equals(cluster.maxResources())) return Advice.none("Autoscaling is not enabled"); return autoscale(cluster, clusterNodes, Limits.of(cluster), cluster.exclusive()); } @@ -71,7 +71,7 @@ public class Autoscaler { int measurementsPerNode = clusterTimeseries.measurementsPerNode(); if (measurementsPerNode < minimumMeasurementsPerNode(clusterNodes.clusterSpec())) return Advice.none("Collecting more data before making new scaling decisions" + - " (as " + measurementsPerNode + " data points per node but need " + + " (has " + measurementsPerNode + " measurements per node but need " + minimumMeasurementsPerNode(clusterNodes.clusterSpec()) + ")"); int nodesMeasured = clusterTimeseries.nodesMeasured(); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java index 206aa077027..0b5a04ca42c 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java @@ -2,10 +2,12 @@ package com.yahoo.vespa.hosted.provision.provisioning; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.ApplicationTransaction; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.NodeType; +import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.exception.LoadBalancerServiceException; import com.yahoo.transaction.NestedTransaction; import com.yahoo.vespa.flags.BooleanFlag; @@ -82,7 +84,8 @@ public class LoadBalancerProvisioner { try (var lock = db.lock(application)) { ClusterSpec.Id clusterId = effectiveId(cluster); List<Node> nodes = nodesOf(clusterId, application); - provision(application, clusterId, nodes, false); + LoadBalancerId loadBalancerId = requireNonClashing(new LoadBalancerId(application, clusterId)); + provision(loadBalancerId, nodes, false); } } @@ -149,9 +152,30 @@ public class LoadBalancerProvisioner { return canForwardTo; } + /** Find all load balancer IDs owned by given tenant and application */ + private List<LoadBalancerId> findLoadBalancers(TenantName tenant, ApplicationName application) { + return db.readLoadBalancerIds().stream() + .filter(id -> id.application().tenant().equals(tenant) && + id.application().application().equals(application)) + .collect(Collectors.toUnmodifiableList()); + } + + /** Require that load balancer IDs do not clash. This prevents name clashing when compacting endpoint DNS names */ + private LoadBalancerId requireNonClashing(LoadBalancerId loadBalancerId) { + List<LoadBalancerId> loadBalancerIds = findLoadBalancers(loadBalancerId.application().tenant(), + loadBalancerId.application().application()); + List<String> nonCompactableIds = withoutCompactableIds(loadBalancerId); + for (var id : loadBalancerIds) { + if (id.equals(loadBalancerId)) continue; + if (nonCompactableIds.equals(withoutCompactableIds(id))) { + throw new IllegalArgumentException(loadBalancerId + " clashes with " + id); + } + } + return loadBalancerId; + } + /** Idempotently provision a load balancer for given application and cluster */ - private void provision(ApplicationId application, ClusterSpec.Id clusterId, List<Node> nodes, boolean activate) { - var id = new LoadBalancerId(application, clusterId); + private void provision(LoadBalancerId id, List<Node> nodes, boolean activate) { var now = nodeRepository.clock().instant(); var loadBalancer = db.readLoadBalancer(id); if (loadBalancer.isEmpty() && activate) return; // Nothing to activate as this load balancer was never prepared @@ -171,6 +195,10 @@ public class LoadBalancerProvisioner { db.writeLoadBalancer(newLoadBalancer); } + private void provision(ApplicationId application, ClusterSpec.Id clusterId, List<Node> nodes, boolean activate) { + provision(new LoadBalancerId(application, clusterId), nodes, activate); + } + private LoadBalancerInstance provisionInstance(LoadBalancerId id, List<Node> nodes, boolean force) { var reals = new LinkedHashSet<Real>(); for (var node : nodes) { @@ -206,6 +234,18 @@ public class LoadBalancerProvisioner { return nodes.stream().collect(Collectors.groupingBy(node -> effectiveId(node.allocation().get().membership().cluster()))); } + /** Returns a list of the non-compactable IDs of given load balancer */ + private static List<String> withoutCompactableIds(LoadBalancerId id) { + List<String> ids = new ArrayList<>(2); + if (!"default".equals(id.cluster().value())) { + ids.add(id.cluster().value()); + } + if (!id.application().instance().isDefault()) { + ids.add(id.application().instance().value()); + } + return ids; + } + /** Find IP addresses reachable by the load balancer service */ private Set<String> reachableIpAddresses(Node node) { Set<String> reachable = new LinkedHashSet<>(node.ipConfig().primary()); @@ -225,4 +265,5 @@ public class LoadBalancerProvisioner { return cluster.combinedId().orElse(cluster.id()); } + } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java index c51ef7250e2..7a636a030ec 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java @@ -33,6 +33,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * @author mpolden @@ -236,6 +237,31 @@ public class LoadBalancerProvisionerTest { assertEquals(cluster, lbs.get().get(0).id().cluster()); } + @Test + public void reject_load_balancers_with_clashing_names() { + ApplicationId instance1 = ApplicationId.from("t1", "a1", "default"); + ApplicationId instance2 = ApplicationId.from("t1", "a1", "dev"); + ApplicationId instance3 = ApplicationId.from("t1", "a1", "qrs"); + ClusterSpec.Id devCluster = ClusterSpec.Id.from("dev"); + ClusterSpec.Id defaultCluster = ClusterSpec.Id.from("default"); + + // instance1 is deployed + tester.activate(instance1, prepare(instance1, clusterRequest(ClusterSpec.Type.container, devCluster))); + + // instance2 clashes because cluster name matches instance1 + try { + prepare(instance2, clusterRequest(ClusterSpec.Type.container, defaultCluster)); + fail("Expected exception"); + } catch (IllegalArgumentException ignored) { + } + + // instance2 changes cluster name and does not clash + tester.activate(instance2, prepare(instance2, clusterRequest(ClusterSpec.Type.container, ClusterSpec.Id.from("qrs")))); + + // instance3 clashes because instance name matches instance2 cluster + tester.activate(instance3, prepare(instance3, clusterRequest(ClusterSpec.Type.container, defaultCluster))); + } + private void dirtyNodesOf(ApplicationId application) { tester.nodeRepository().setDirty(tester.nodeRepository().getNodes(application), Agent.system, this.getClass().getSimpleName()); } diff --git a/vespalib/src/tests/net/selector/selector_test.cpp b/vespalib/src/tests/net/selector/selector_test.cpp index 7d7a147bcb2..5c91dfdc122 100644 --- a/vespalib/src/tests/net/selector/selector_test.cpp +++ b/vespalib/src/tests/net/selector/selector_test.cpp @@ -77,7 +77,12 @@ struct Fixture { } Fixture &poll(int timeout_ms = 60000) { selector.poll(timeout_ms); - selector.dispatch(*this); + auto dispatchResult = selector.dispatch(*this); + if (wakeup) { + EXPECT_TRUE(dispatchResult == SelectorDispatchResult::WAKEUP_CALLED); + } else { + EXPECT_TRUE(dispatchResult == SelectorDispatchResult::NO_WAKEUP); + } return *this; } void verify(bool expect_wakeup, std::vector<std::pair<bool,bool> > expect_events) { diff --git a/vespalib/src/vespa/vespalib/net/selector.h b/vespalib/src/vespa/vespalib/net/selector.h index 6b1967ddcd9..24b3abc806e 100644 --- a/vespalib/src/vespa/vespalib/net/selector.h +++ b/vespalib/src/vespa/vespalib/net/selector.h @@ -31,6 +31,7 @@ public: }; //----------------------------------------------------------------------------- +enum class SelectorDispatchResult {WAKEUP_CALLED, NO_WAKEUP}; template <typename Context> class Selector @@ -55,11 +56,13 @@ public: void poll(int timeout_ms) { _events.extract(_epoll, timeout_ms); } size_t num_events() const { return _events.size(); } template <typename Handler> - void dispatch(Handler &handler) { + SelectorDispatchResult dispatch(Handler &handler) { + SelectorDispatchResult result = SelectorDispatchResult::NO_WAKEUP; for (const auto &evt: _events) { if (evt.data.ptr == nullptr) { _wakeup_pipe.read_tokens(); handler.handle_wakeup(); + result = SelectorDispatchResult::WAKEUP_CALLED; } else { Context &ctx = *((Context *)(evt.data.ptr)); bool read = ((evt.events & (EPOLLIN | EPOLLERR | EPOLLHUP)) != 0); @@ -67,6 +70,7 @@ public: handler.handle_event(ctx, read, write); } } + return result; } }; diff --git a/vespalib/src/vespa/vespalib/stllike/hashtable.hpp b/vespalib/src/vespa/vespalib/stllike/hashtable.hpp index b954169912a..57f05ca6542 100644 --- a/vespalib/src/vespa/vespalib/stllike/hashtable.hpp +++ b/vespalib/src/vespa/vespalib/stllike/hashtable.hpp @@ -160,7 +160,7 @@ hashtable<Key, Value, Hash, Equal, KeyExtract, Modulator>::insertInternal(V && n _nodes[h] = std::forward<V>(node); _count++; return insert_result(iterator(this, h), true); - } else if (_nodes.size() <= _nodes.capacity()) { + } else { for (next_t c(h); c != Node::npos; c = _nodes[c].getNext()) { if (_equal(_keyExtractor(_nodes[c].getValue()), _keyExtractor(node))) { return insert_result(iterator(this, c), false); @@ -177,9 +177,6 @@ hashtable<Key, Value, Hash, Equal, KeyExtract, Modulator>::insertInternal(V && n resize(_nodes.capacity()*2); return insertInternal(std::forward<V>(node)); } - } else { - resize(_nodes.capacity()*2); - return insertInternal(std::forward<V>(node)); } } diff --git a/zkfacade/src/main/java/com/yahoo/vespa/curator/stats/LatencyMetrics.java b/zkfacade/src/main/java/com/yahoo/vespa/curator/stats/LatencyMetrics.java index 3bfb1fca4d9..22af158faa9 100644 --- a/zkfacade/src/main/java/com/yahoo/vespa/curator/stats/LatencyMetrics.java +++ b/zkfacade/src/main/java/com/yahoo/vespa/curator/stats/LatencyMetrics.java @@ -77,6 +77,6 @@ public class LatencyMetrics { '}'; } - private double secondsWithMillis(Duration duration) { return duration.toMillis() / 1000.0; } + private double secondsWithMillis(Duration duration) { return round(duration.toMillis()) / 1000.0; } private double roundTo3DecimalPlaces(double value) { return round(value * 1000) / 1000.0; } } diff --git a/zookeeper-server/zookeeper-server-3.5.6/src/main/java/com/yahoo/vespa/zookeeper/Reconfigurer.java b/zookeeper-server/zookeeper-server-3.5.6/src/main/java/com/yahoo/vespa/zookeeper/Reconfigurer.java index 89c29a642d4..90de4a9472e 100644 --- a/zookeeper-server/zookeeper-server-3.5.6/src/main/java/com/yahoo/vespa/zookeeper/Reconfigurer.java +++ b/zookeeper-server/zookeeper-server-3.5.6/src/main/java/com/yahoo/vespa/zookeeper/Reconfigurer.java @@ -89,10 +89,9 @@ public class Reconfigurer extends AbstractComponent { ". Joining servers: " + joiningServers + ", leaving servers: " + leavingServers); sleeper.accept(reconfigWaitPeriod()); String connectionSpec = connectionSpec(activeConfig); - boolean reconfigured = false; Instant end = Instant.now().plus(reconfigTimeout); // Loop reconfiguring since we might need to wait until another reconfiguration is finished before we can succeed - for (int attempts = 1; ! reconfigured && Instant.now().isBefore(end); attempts++) { + for (int attempts = 1; Instant.now().isBefore(end); attempts++) { try { Instant reconfigStarted = Instant.now(); zkAdmin.reconfigure(connectionSpec, joiningServers, leavingServers); @@ -101,14 +100,14 @@ public class Reconfigurer extends AbstractComponent { Duration.between(reconfigTriggered, reconfigEnded) + ", after " + attempts + " attempt(s). ZooKeeper reconfig call took " + Duration.between(reconfigStarted, reconfigEnded)); - reconfigured = true; + activeConfig = newConfig; + return; } catch (ReconfigException e) { log.log(Level.INFO, "Reconfiguration failed. Retrying in " + retryWait + ": " + Exceptions.toMessageString(e)); sleeper.accept(retryWait); } } - activeConfig = newConfig; } /** Returns how long this node should wait before reconfiguring the cluster */ |