summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Musum <musum@verizonmedia.com>2020-12-07 14:23:28 +0100
committerHarald Musum <musum@verizonmedia.com>2020-12-07 14:23:28 +0100
commit7e7b7c72b7ca4131f6f29efa0f9d63f857d9f369 (patch)
treea037b007b9c4cb81b247d8d14227d74374f4bbb3
parentf98e158a6f61cd39029f439da903f10e75e4c3fa (diff)
parent72a1848f3d752aa16495fe39a3ebd58463b9b277 (diff)
Merge branch 'master' into hmusum/refactor-reconfigurer
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java2
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java2
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/ClusterResources.java4
-rw-r--r--container-accesslogging/src/main/java/com/yahoo/container/logging/LogFileHandler.java9
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackageValidator.java46
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java30
-rw-r--r--fnet/src/vespa/fnet/transport_thread.cpp9
-rw-r--r--fnet/src/vespa/fnet/transport_thread.h6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisioner.java47
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/LoadBalancerProvisionerTest.java26
-rw-r--r--vespalib/src/tests/net/selector/selector_test.cpp7
-rw-r--r--vespalib/src/vespa/vespalib/net/selector.h6
-rw-r--r--vespalib/src/vespa/vespalib/stllike/hashtable.hpp5
-rw-r--r--zkfacade/src/main/java/com/yahoo/vespa/curator/stats/LatencyMetrics.java2
-rw-r--r--zookeeper-server/zookeeper-server-3.5.6/src/main/java/com/yahoo/vespa/zookeeper/Reconfigurer.java7
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 */