diff --git a/.travis.yml b/.travis.yml index 9031c5f4..ada3b53d 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,15 @@ language: java jdk: -- oraclejdk8 + - oraclejdk8 sudo: false install: ./installViaTravis.sh script: ./buildViaTravis.sh cache: directories: - - $HOME/.gradle/caches/ + - $HOME/.gradle/caches/ env: global: - - secure: GLRunlapijH/uL489R5wpobpQdLOKQS0oJ9Bk69K3Bee6quaaeK4bnO7aEQcSd2MSF0obFT1Hz9WWhiz18c50n9gfkwBsPxWI7AnGn3aQd+qNbJ8yacdAZ7MWq9oThMUblxnLR4figaJC6vtL48GReOVxAtqp/jGIBod5ugUW1Q= - - secure: UWbxxiBxHFc7zvg9bwda9hHozuHnURJWjkyTiJWMmJbXBB1fj45mX4aSkan1v0G2zSaLYnxEOeQuFNcTyN4xZdUcyfBIM0g8XbJg2sadVUMquevzpB9u/lO3KhT5hxl2V2i58pO6cUyAW3FAOgjBAd8gTbgex0AghSh2/HYR8Hs= - - secure: gTZNqDSkoLvEl89xxi79RIKyvFRpPYM3G5LwjBmRZYKJxJHQYk6ZC8blw4i5PklY9aeCIScqA1t5H4SGLy/HZSnY7yvUzxmZAJkxZDAp0p7HEjuzA6lz790yoeXdGo7vfSKmdnygTJPeR+fJC6aRru3xPrF8kaF1nvZ6UHV46U8= - - secure: F6Fipjti9Po5UgyPMvvBcJW7KTTMoHx2jsUSbLebTSwQBkyHOc7DL7pmM3xSG2FAQk5qS0arn7IKnJk2TOKToU/oEK9kvfnce/Bv340KaRpcToxaEw/4f4gUNHm98BvJJcRmYTCCQ2jYoa9Nk4RMtQB6fUYdPJ6NCgNmwjJJaHk= + - secure: GLRunlapijH/uL489R5wpobpQdLOKQS0oJ9Bk69K3Bee6quaaeK4bnO7aEQcSd2MSF0obFT1Hz9WWhiz18c50n9gfkwBsPxWI7AnGn3aQd+qNbJ8yacdAZ7MWq9oThMUblxnLR4figaJC6vtL48GReOVxAtqp/jGIBod5ugUW1Q= + - secure: UWbxxiBxHFc7zvg9bwda9hHozuHnURJWjkyTiJWMmJbXBB1fj45mX4aSkan1v0G2zSaLYnxEOeQuFNcTyN4xZdUcyfBIM0g8XbJg2sadVUMquevzpB9u/lO3KhT5hxl2V2i58pO6cUyAW3FAOgjBAd8gTbgex0AghSh2/HYR8Hs= + - secure: gTZNqDSkoLvEl89xxi79RIKyvFRpPYM3G5LwjBmRZYKJxJHQYk6ZC8blw4i5PklY9aeCIScqA1t5H4SGLy/HZSnY7yvUzxmZAJkxZDAp0p7HEjuzA6lz790yoeXdGo7vfSKmdnygTJPeR+fJC6aRru3xPrF8kaF1nvZ6UHV46U8= + - secure: F6Fipjti9Po5UgyPMvvBcJW7KTTMoHx2jsUSbLebTSwQBkyHOc7DL7pmM3xSG2FAQk5qS0arn7IKnJk2TOKToU/oEK9kvfnce/Bv340KaRpcToxaEw/4f4gUNHm98BvJJcRmYTCCQ2jYoa9Nk4RMtQB6fUYdPJ6NCgNmwjJJaHk= diff --git a/build.gradle b/build.gradle index a7a9c30e..4ea0798d 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,7 @@ subprojects { project(':dyno-core') { apply plugin: 'osgi' apply plugin: 'project-report' - + dependencies { compile 'org.apache.commons:commons-math:2.2' compile 'org.apache.commons:commons-lang3:3.6' @@ -54,7 +54,7 @@ project(':dyno-core') { project(':dyno-contrib') { apply plugin: 'osgi' apply plugin: 'project-report' - + dependencies { compile project(':dyno-core') compile 'com.google.inject:guice:4.1.0' @@ -62,9 +62,9 @@ project(':dyno-contrib') { compile 'com.netflix.servo:servo-core:0.12.17' compile 'com.netflix.eureka:eureka-client:1.8.6' compile 'org.apache.commons:commons-lang3:3.5' - compile ('com.ecwid.consul:consul-api:1.2.1') { + compile('com.ecwid.consul:consul-api:1.2.1') { exclude group: 'org.apache.httpcomponents' - } + } testCompile 'com.pszymczyk.consul:embedded-consul:0.3.3' } } diff --git a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/ArchaiusConnectionPoolConfiguration.java b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/ArchaiusConnectionPoolConfiguration.java index ce76a684..8f2bf74f 100644 --- a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/ArchaiusConnectionPoolConfiguration.java +++ b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/ArchaiusConnectionPoolConfiguration.java @@ -32,104 +32,104 @@ public class ArchaiusConnectionPoolConfiguration extends ConnectionPoolConfigurationImpl { - private static final Logger Logger = LoggerFactory.getLogger(ArchaiusConnectionPoolConfiguration.class); - - private static final String DynoPrefix = "dyno."; - - //private final DynamicIntProperty port; - private final DynamicIntProperty maxConnsPerHost; - private final DynamicIntProperty maxTimeoutWhenExhausted; - private final DynamicIntProperty maxFailoverCount; - private final DynamicIntProperty connectTimeout; - private final DynamicIntProperty socketTimeout; - private final DynamicBooleanProperty localZoneAffinity; - private final DynamicIntProperty resetTimingsFrequency; + private static final Logger Logger = LoggerFactory.getLogger(ArchaiusConnectionPoolConfiguration.class); + + private static final String DynoPrefix = "dyno."; + + //private final DynamicIntProperty port; + private final DynamicIntProperty maxConnsPerHost; + private final DynamicIntProperty maxTimeoutWhenExhausted; + private final DynamicIntProperty maxFailoverCount; + private final DynamicIntProperty connectTimeout; + private final DynamicIntProperty socketTimeout; + private final DynamicBooleanProperty localZoneAffinity; + private final DynamicIntProperty resetTimingsFrequency; private final DynamicStringProperty configPublisherConfig; private final DynamicIntProperty compressionThreshold; - - private final LoadBalancingStrategy loadBalanceStrategy; - private final CompressionStrategy compressionStrategy; - private final ErrorRateMonitorConfig errorRateConfig; - private final RetryPolicyFactory retryPolicyFactory; + + private final LoadBalancingStrategy loadBalanceStrategy; + private final CompressionStrategy compressionStrategy; + private final ErrorRateMonitorConfig errorRateConfig; + private final RetryPolicyFactory retryPolicyFactory; private final DynamicBooleanProperty failOnStartupIfNoHosts; - private DynamicBooleanProperty isDualWriteEnabled; + private DynamicBooleanProperty isDualWriteEnabled; private DynamicStringProperty dualWriteClusterName; private DynamicIntProperty dualWritePercentage; - public ArchaiusConnectionPoolConfiguration(String name) { - super(name); + public ArchaiusConnectionPoolConfiguration(String name) { + super(name); - String propertyPrefix = DynoPrefix + name; + String propertyPrefix = DynoPrefix + name; - maxConnsPerHost = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".connection.maxConnsPerHost", super.getMaxConnsPerHost()); - maxTimeoutWhenExhausted = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".connection.maxTimeoutWhenExhausted", super.getMaxTimeoutWhenExhausted()); - maxFailoverCount = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".connection.maxFailoverCount", super.getMaxFailoverCount()); - connectTimeout = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".connection.connectTimeout", super.getConnectTimeout()); - socketTimeout = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".connection.socketTimeout", super.getSocketTimeout()); - localZoneAffinity = DynamicPropertyFactory.getInstance().getBooleanProperty(propertyPrefix + ".connection.localZoneAffinity", super.localZoneAffinity()); - resetTimingsFrequency = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".connection.metrics.resetFrequencySeconds", super.getTimingCountersResetFrequencySeconds()); + maxConnsPerHost = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".connection.maxConnsPerHost", super.getMaxConnsPerHost()); + maxTimeoutWhenExhausted = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".connection.maxTimeoutWhenExhausted", super.getMaxTimeoutWhenExhausted()); + maxFailoverCount = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".connection.maxFailoverCount", super.getMaxFailoverCount()); + connectTimeout = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".connection.connectTimeout", super.getConnectTimeout()); + socketTimeout = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".connection.socketTimeout", super.getSocketTimeout()); + localZoneAffinity = DynamicPropertyFactory.getInstance().getBooleanProperty(propertyPrefix + ".connection.localZoneAffinity", super.localZoneAffinity()); + resetTimingsFrequency = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".connection.metrics.resetFrequencySeconds", super.getTimingCountersResetFrequencySeconds()); configPublisherConfig = DynamicPropertyFactory.getInstance().getStringProperty(propertyPrefix + ".config.publisher.address", super.getConfigurationPublisherConfig()); - failOnStartupIfNoHosts = DynamicPropertyFactory.getInstance().getBooleanProperty(propertyPrefix + ".config.startup.failIfNoHosts", super.getFailOnStartupIfNoHosts()); + failOnStartupIfNoHosts = DynamicPropertyFactory.getInstance().getBooleanProperty(propertyPrefix + ".config.startup.failIfNoHosts", super.getFailOnStartupIfNoHosts()); compressionThreshold = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".config.compressionThreshold", super.getValueCompressionThreshold()); - loadBalanceStrategy = parseLBStrategy(propertyPrefix); - errorRateConfig = parseErrorRateMonitorConfig(propertyPrefix); - retryPolicyFactory = parseRetryPolicyFactory(propertyPrefix); - compressionStrategy = parseCompressionStrategy(propertyPrefix); + loadBalanceStrategy = parseLBStrategy(propertyPrefix); + errorRateConfig = parseErrorRateMonitorConfig(propertyPrefix); + retryPolicyFactory = parseRetryPolicyFactory(propertyPrefix); + compressionStrategy = parseCompressionStrategy(propertyPrefix); isDualWriteEnabled = DynamicPropertyFactory.getInstance().getBooleanProperty(propertyPrefix + ".dualwrite.enabled", super.isDualWriteEnabled()); dualWriteClusterName = DynamicPropertyFactory.getInstance().getStringProperty(propertyPrefix + ".dualwrite.cluster", super.getDualWriteClusterName()); dualWritePercentage = DynamicPropertyFactory.getInstance().getIntProperty(propertyPrefix + ".dualwrite.percentage", super.getDualWritePercentage()); - } + } - @Override - public String getName() { - return super.getName(); - } + @Override + public String getName() { + return super.getName(); + } - @Override - public int getMaxConnsPerHost() { - return maxConnsPerHost.get(); - } + @Override + public int getMaxConnsPerHost() { + return maxConnsPerHost.get(); + } - @Override - public int getMaxTimeoutWhenExhausted() { - return maxTimeoutWhenExhausted.get(); - } + @Override + public int getMaxTimeoutWhenExhausted() { + return maxTimeoutWhenExhausted.get(); + } - @Override - public int getMaxFailoverCount() { - return maxFailoverCount.get(); - } + @Override + public int getMaxFailoverCount() { + return maxFailoverCount.get(); + } - @Override - public int getConnectTimeout() { - return connectTimeout.get(); - } + @Override + public int getConnectTimeout() { + return connectTimeout.get(); + } - @Override - public int getSocketTimeout() { - return socketTimeout.get(); - } + @Override + public int getSocketTimeout() { + return socketTimeout.get(); + } - @Override - public RetryPolicyFactory getRetryPolicyFactory() { - return retryPolicyFactory; - } + @Override + public RetryPolicyFactory getRetryPolicyFactory() { + return retryPolicyFactory; + } - @Override - public boolean localZoneAffinity() { - return localZoneAffinity.get(); - } + @Override + public boolean localZoneAffinity() { + return localZoneAffinity.get(); + } - @Override - public LoadBalancingStrategy getLoadBalancingStrategy() { - return loadBalanceStrategy; - } + @Override + public LoadBalancingStrategy getLoadBalancingStrategy() { + return loadBalanceStrategy; + } @Override public CompressionStrategy getCompressionStrategy() { @@ -142,9 +142,9 @@ public int getValueCompressionThreshold() { } @Override - public int getTimingCountersResetFrequencySeconds() { - return resetTimingsFrequency.get(); - } + public int getTimingCountersResetFrequencySeconds() { + return resetTimingsFrequency.get(); + } @Override public String getConfigurationPublisherConfig() { @@ -171,17 +171,17 @@ public int getDualWritePercentage() { return dualWritePercentage.get(); } - public void setIsDualWriteEnabled(DynamicBooleanProperty booleanProperty) { - this.isDualWriteEnabled = booleanProperty; - } + public void setIsDualWriteEnabled(DynamicBooleanProperty booleanProperty) { + this.isDualWriteEnabled = booleanProperty; + } - public void setDualWriteClusterName(DynamicStringProperty stringProperty) { - this.dualWriteClusterName = stringProperty; - } + public void setDualWriteClusterName(DynamicStringProperty stringProperty) { + this.dualWriteClusterName = stringProperty; + } - public void setDualWritePercentage(DynamicIntProperty intProperty) { - this.dualWritePercentage = intProperty; - } + public void setDualWritePercentage(DynamicIntProperty intProperty) { + this.dualWritePercentage = intProperty; + } @Override public String toString() { @@ -208,22 +208,22 @@ public String toString() { } private LoadBalancingStrategy parseLBStrategy(String propertyPrefix) { - - LoadBalancingStrategy defaultConfig = super.getLoadBalancingStrategy(); - - String cfg = - DynamicPropertyFactory.getInstance().getStringProperty(propertyPrefix + ".lbStrategy", defaultConfig.name()).get(); - - LoadBalancingStrategy lb = null; - try { - lb = LoadBalancingStrategy.valueOf(cfg); - } catch (Exception e) { - Logger.warn("Unable to parse LoadBalancingStrategy: " + cfg + ", switching to default: " + defaultConfig.name()); - lb = defaultConfig; - } - - return lb; - } + + LoadBalancingStrategy defaultConfig = super.getLoadBalancingStrategy(); + + String cfg = + DynamicPropertyFactory.getInstance().getStringProperty(propertyPrefix + ".lbStrategy", defaultConfig.name()).get(); + + LoadBalancingStrategy lb = null; + try { + lb = LoadBalancingStrategy.valueOf(cfg); + } catch (Exception e) { + Logger.warn("Unable to parse LoadBalancingStrategy: " + cfg + ", switching to default: " + defaultConfig.name()); + lb = defaultConfig; + } + + return lb; + } private CompressionStrategy parseCompressionStrategy(String propertyPrefix) { @@ -236,7 +236,7 @@ private CompressionStrategy parseCompressionStrategy(String propertyPrefix) { CompressionStrategy cs = null; try { cs = CompressionStrategy.valueOf(cfg); - Logger.info("Dyno configuration: CompressionStrategy = " + cs.name()); + Logger.info("Dyno configuration: CompressionStrategy = " + cs.name()); } catch (IllegalArgumentException ex) { Logger.warn("Unable to parse CompressionStrategy: " + cfg + ", switching to default: " + defaultCompStrategy.name()); cs = defaultCompStrategy; @@ -245,77 +245,77 @@ private CompressionStrategy parseCompressionStrategy(String propertyPrefix) { return cs; } - - private ErrorRateMonitorConfig parseErrorRateMonitorConfig(String propertyPrefix) { - String errorRateConfig = DynamicPropertyFactory.getInstance().getStringProperty(propertyPrefix + ".errorRateConfig", null).get(); - try { - if (errorRateConfig == null) { - return null; - } - - // Classic format that is supported is json. - - JSONObject json = new JSONObject(errorRateConfig); - - int window = json.getInt("window"); - int frequency = json.getInt("frequency"); - int suppress = json.getInt("suppress"); - - ErrorRateMonitorConfigImpl configImpl = new ErrorRateMonitorConfigImpl(window, frequency, suppress); - - JSONArray thresholds = json.getJSONArray("thresholds"); - for (int i=0; i * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/DynoCPMonitor.java b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/DynoCPMonitor.java index 0e8b9f85..59f598d3 100644 --- a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/DynoCPMonitor.java +++ b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/DynoCPMonitor.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,53 +25,53 @@ import com.netflix.servo.monitor.Monitors; public class DynoCPMonitor extends CountingConnectionPoolMonitor { - - private static final Logger Logger = LoggerFactory.getLogger(DynoCPMonitor.class); - - public DynoCPMonitor(String namePrefix) { - - try { - DefaultMonitorRegistry.getInstance().register(Monitors.newObjectMonitor(namePrefix, this)); - } catch (Exception e) { - Logger.warn("Failed to register metrics with monitor registry", e); - } - } - - @Monitor(name = "OperationSuccess", type = DataSourceType.COUNTER) - @Override - public long getOperationSuccessCount() { - return super.getOperationSuccessCount(); - } - - @Monitor(name = "OperationFailure", type = DataSourceType.COUNTER) - @Override - public long getOperationFailureCount() { - return super.getOperationFailureCount(); - } - - @Monitor(name = "ConnectionCreated", type = DataSourceType.COUNTER) - @Override - public long getConnectionCreatedCount() { - return super.getConnectionCreatedCount(); - } - - @Monitor(name = "ConnectionClosed", type = DataSourceType.COUNTER) - @Override - public long getConnectionClosedCount() { - return super.getConnectionClosedCount(); - } - - @Monitor(name = "ConnectionCreateFailed", type = DataSourceType.COUNTER) - @Override - public long getConnectionCreateFailedCount() { - return super.getConnectionCreateFailedCount(); - } - - @Monitor(name = "ConnectionBorrowed", type = DataSourceType.COUNTER) - @Override - public long getConnectionBorrowedCount() { - return super.getConnectionBorrowedCount(); - } + + private static final Logger Logger = LoggerFactory.getLogger(DynoCPMonitor.class); + + public DynoCPMonitor(String namePrefix) { + + try { + DefaultMonitorRegistry.getInstance().register(Monitors.newObjectMonitor(namePrefix, this)); + } catch (Exception e) { + Logger.warn("Failed to register metrics with monitor registry", e); + } + } + + @Monitor(name = "OperationSuccess", type = DataSourceType.COUNTER) + @Override + public long getOperationSuccessCount() { + return super.getOperationSuccessCount(); + } + + @Monitor(name = "OperationFailure", type = DataSourceType.COUNTER) + @Override + public long getOperationFailureCount() { + return super.getOperationFailureCount(); + } + + @Monitor(name = "ConnectionCreated", type = DataSourceType.COUNTER) + @Override + public long getConnectionCreatedCount() { + return super.getConnectionCreatedCount(); + } + + @Monitor(name = "ConnectionClosed", type = DataSourceType.COUNTER) + @Override + public long getConnectionClosedCount() { + return super.getConnectionClosedCount(); + } + + @Monitor(name = "ConnectionCreateFailed", type = DataSourceType.COUNTER) + @Override + public long getConnectionCreateFailedCount() { + return super.getConnectionCreateFailedCount(); + } + + @Monitor(name = "ConnectionBorrowed", type = DataSourceType.COUNTER) + @Override + public long getConnectionBorrowedCount() { + return super.getConnectionBorrowedCount(); + } @Monitor(name = "ConnectionBorrowedAvgLat", type = DataSourceType.GAUGE) @Override @@ -92,81 +92,82 @@ public long getConnectionBorrowedLatP99() { } @Monitor(name = "ConnectionReturned", type = DataSourceType.COUNTER) - @Override - public long getConnectionReturnedCount() { - return super.getConnectionReturnedCount(); - } - - @Monitor(name = "PoolExhausted", type = DataSourceType.COUNTER) - @Override - public long getPoolExhaustedTimeoutCount() { - return super.getPoolExhaustedTimeoutCount(); - } - - @Monitor(name = "SocketTimeout", type = DataSourceType.COUNTER) - @Override - public long getSocketTimeoutCount() { - return super.getSocketTimeoutCount(); - } - - @Monitor(name = "OperationTimeout", type = DataSourceType.COUNTER) - @Override - public long getOperationTimeoutCount() { - return super.getOperationTimeoutCount(); - } - - @Monitor(name = "NumFailover", type = DataSourceType.COUNTER) - @Override - public long getFailoverCount() { - return super.getFailoverCount(); - } - - - @Monitor(name = "ConnectionBusy", type = DataSourceType.COUNTER) - @Override - public long getNumBusyConnections() { - return super.getNumBusyConnections(); - } - - @Monitor(name = "ConnectionOpen", type = DataSourceType.COUNTER) - @Override - public long getNumOpenConnections() { - return super.getNumOpenConnections(); - } - @Monitor(name = "NoHostCount", type = DataSourceType.COUNTER) - @Override - public long getNoHostCount() { - return super.getNoHostCount(); - } - - @Monitor(name = "UnknownError", type = DataSourceType.COUNTER) - @Override - public long getUnknownErrorCount() { - return super.getUnknownErrorCount(); - } - - @Monitor(name = "BadRequest", type = DataSourceType.COUNTER) - @Override - public long getBadRequestCount() { - return super.getBadRequestCount(); - } - - - @Monitor(name = "HostCount", type = DataSourceType.GAUGE) - @Override - public long getHostCount() { - return super.getHostCount(); - } - - @Monitor(name = "HostUpCount", type = DataSourceType.GAUGE) - @Override - public long getHostUpCount() { - return super.getHostUpCount(); - } - - @Monitor(name = "HostDownCount", type = DataSourceType.GAUGE) - @Override - public long getHostDownCount() { - return super.getHostDownCount(); - } + @Override + public long getConnectionReturnedCount() { + return super.getConnectionReturnedCount(); + } + + @Monitor(name = "PoolExhausted", type = DataSourceType.COUNTER) + @Override + public long getPoolExhaustedTimeoutCount() { + return super.getPoolExhaustedTimeoutCount(); + } + + @Monitor(name = "SocketTimeout", type = DataSourceType.COUNTER) + @Override + public long getSocketTimeoutCount() { + return super.getSocketTimeoutCount(); + } + + @Monitor(name = "OperationTimeout", type = DataSourceType.COUNTER) + @Override + public long getOperationTimeoutCount() { + return super.getOperationTimeoutCount(); + } + + @Monitor(name = "NumFailover", type = DataSourceType.COUNTER) + @Override + public long getFailoverCount() { + return super.getFailoverCount(); + } + + + @Monitor(name = "ConnectionBusy", type = DataSourceType.COUNTER) + @Override + public long getNumBusyConnections() { + return super.getNumBusyConnections(); + } + + @Monitor(name = "ConnectionOpen", type = DataSourceType.COUNTER) + @Override + public long getNumOpenConnections() { + return super.getNumOpenConnections(); + } + + @Monitor(name = "NoHostCount", type = DataSourceType.COUNTER) + @Override + public long getNoHostCount() { + return super.getNoHostCount(); + } + + @Monitor(name = "UnknownError", type = DataSourceType.COUNTER) + @Override + public long getUnknownErrorCount() { + return super.getUnknownErrorCount(); + } + + @Monitor(name = "BadRequest", type = DataSourceType.COUNTER) + @Override + public long getBadRequestCount() { + return super.getBadRequestCount(); + } + + + @Monitor(name = "HostCount", type = DataSourceType.GAUGE) + @Override + public long getHostCount() { + return super.getHostCount(); + } + + @Monitor(name = "HostUpCount", type = DataSourceType.GAUGE) + @Override + public long getHostUpCount() { + return super.getHostUpCount(); + } + + @Monitor(name = "HostDownCount", type = DataSourceType.GAUGE) + @Override + public long getHostDownCount() { + return super.getHostDownCount(); + } } diff --git a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/DynoOPMonitor.java b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/DynoOPMonitor.java index 40b6e244..29231fe5 100644 --- a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/DynoOPMonitor.java +++ b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/DynoOPMonitor.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -31,29 +31,29 @@ public class DynoOPMonitor implements OperationMonitor { - private final ConcurrentHashMap counterMap = new ConcurrentHashMap(); - private final ConcurrentHashMap timerMap = new ConcurrentHashMap(); + private final ConcurrentHashMap counterMap = new ConcurrentHashMap(); + private final ConcurrentHashMap timerMap = new ConcurrentHashMap(); - private final String appName; + private final String appName; - public DynoOPMonitor(String applicationName) { - appName = applicationName; - } - - @Override - public void recordLatency(String opName, long duration, TimeUnit unit) { - getOrCreateTimers(opName).recordLatency(duration, unit); - } + public DynoOPMonitor(String applicationName) { + appName = applicationName; + } + + @Override + public void recordLatency(String opName, long duration, TimeUnit unit) { + getOrCreateTimers(opName).recordLatency(duration, unit); + } - @Override - public void recordSuccess(String opName) { - getOrCreateCounter(opName, false).incrementSuccess(); - } + @Override + public void recordSuccess(String opName) { + getOrCreateCounter(opName, false).incrementSuccess(); + } - @Override - public void recordFailure(String opName, String reason) { - getOrCreateCounter(opName, false).incrementFailure(); - } + @Override + public void recordFailure(String opName, String reason) { + getOrCreateCounter(opName, false).incrementFailure(); + } @Override public void recordSuccess(String opName, boolean compressionEnabled) { @@ -66,100 +66,100 @@ public void recordFailure(String opName, boolean compressionEnabled, String reas } private class DynoOpCounter { - - private final Counter success; + + private final Counter success; private final Counter successCompressionEnabled; - private final Counter failure; + private final Counter failure; private final Counter failureCompressionEnabled; - - private DynoOpCounter(String appName, String opName) { - success = getNewCounter("Dyno__" + appName + "__" + opName + "__SUCCESS", opName, "false"); + + private DynoOpCounter(String appName, String opName) { + success = getNewCounter("Dyno__" + appName + "__" + opName + "__SUCCESS", opName, "false"); successCompressionEnabled = getNewCounter("Dyno__" + appName + "__" + opName + "__SUCCESS", opName, "true"); failure = getNewCounter("Dyno__" + appName + "__" + opName + "__ERROR", opName, "false"); failureCompressionEnabled = getNewCounter("Dyno__" + appName + "__" + opName + "__ERROR", opName, "true"); - } - - private void incrementSuccess() { - success.increment(); - } - - private void incrementFailure() { - failure.increment(); - } - - private BasicCounter getNewCounter(String metricName, String opName, String compressionEnabled) { - MonitorConfig config = MonitorConfig.builder(metricName) - .withTag(new BasicTag("dyno_op", opName)) + } + + private void incrementSuccess() { + success.increment(); + } + + private void incrementFailure() { + failure.increment(); + } + + private BasicCounter getNewCounter(String metricName, String opName, String compressionEnabled) { + MonitorConfig config = MonitorConfig.builder(metricName) + .withTag(new BasicTag("dyno_op", opName)) .withTag(new BasicTag("compression_enabled", compressionEnabled)) .build(); - return new BasicCounter(config); - } - } - - private DynoOpCounter getOrCreateCounter(String opName, boolean compressionEnabled) { - - String counterName = opName + "_" + compressionEnabled; - DynoOpCounter counter = counterMap.get(counterName); - - if (counter != null) { - return counter; - } - - counter = new DynoOpCounter(appName, counterName); - - DynoOpCounter prevCounter = counterMap.putIfAbsent(counterName, counter); - if (prevCounter != null) { - return prevCounter; - } - - DefaultMonitorRegistry.getInstance().register(counter.success); - DefaultMonitorRegistry.getInstance().register(counter.failure); - DefaultMonitorRegistry.getInstance().register(counter.successCompressionEnabled); - DefaultMonitorRegistry.getInstance().register(counter.failureCompressionEnabled); - - return counter; - } - - private class DynoTimingCounters { - - private final EstimatedHistogramMean latMean; - private final EstimatedHistogramPercentile lat99; - private final EstimatedHistogramPercentile lat995; - private final EstimatedHistogramPercentile lat999; - - private final EstimatedHistogram estHistogram; - - private DynoTimingCounters(String appName, String opName) { - - estHistogram = new EstimatedHistogram(); - latMean = new EstimatedHistogramMean("Dyno__" + appName + "__" + opName + "__latMean", opName, estHistogram); - lat99 = new EstimatedHistogramPercentile("Dyno__" + appName + "__" + opName + "__lat990", opName, estHistogram, 0.99); - lat995 = new EstimatedHistogramPercentile("Dyno__" + appName + "__" + opName + "__lat995", opName, estHistogram, 0.995); - lat999 = new EstimatedHistogramPercentile("Dyno__" + appName + "__" + opName + "__lat999", opName, estHistogram, 0.999); - } - - public void recordLatency(long duration, TimeUnit unit) { - long durationMicros = TimeUnit.MICROSECONDS.convert(duration, unit); - estHistogram.add(durationMicros); - } - } - - private DynoTimingCounters getOrCreateTimers(String opName) { - - DynoTimingCounters timer = timerMap.get(opName); - if (timer != null) { - return timer; - } - timer = new DynoTimingCounters(appName, opName); - DynoTimingCounters prevTimer = timerMap.putIfAbsent(opName, timer); - if (prevTimer != null) { - return prevTimer; - } - DefaultMonitorRegistry.getInstance().register(timer.latMean); - DefaultMonitorRegistry.getInstance().register(timer.lat99); - DefaultMonitorRegistry.getInstance().register(timer.lat995); - DefaultMonitorRegistry.getInstance().register(timer.lat999); - return timer; - } + return new BasicCounter(config); + } + } + + private DynoOpCounter getOrCreateCounter(String opName, boolean compressionEnabled) { + + String counterName = opName + "_" + compressionEnabled; + DynoOpCounter counter = counterMap.get(counterName); + + if (counter != null) { + return counter; + } + + counter = new DynoOpCounter(appName, counterName); + + DynoOpCounter prevCounter = counterMap.putIfAbsent(counterName, counter); + if (prevCounter != null) { + return prevCounter; + } + + DefaultMonitorRegistry.getInstance().register(counter.success); + DefaultMonitorRegistry.getInstance().register(counter.failure); + DefaultMonitorRegistry.getInstance().register(counter.successCompressionEnabled); + DefaultMonitorRegistry.getInstance().register(counter.failureCompressionEnabled); + + return counter; + } + + private class DynoTimingCounters { + + private final EstimatedHistogramMean latMean; + private final EstimatedHistogramPercentile lat99; + private final EstimatedHistogramPercentile lat995; + private final EstimatedHistogramPercentile lat999; + + private final EstimatedHistogram estHistogram; + + private DynoTimingCounters(String appName, String opName) { + + estHistogram = new EstimatedHistogram(); + latMean = new EstimatedHistogramMean("Dyno__" + appName + "__" + opName + "__latMean", opName, estHistogram); + lat99 = new EstimatedHistogramPercentile("Dyno__" + appName + "__" + opName + "__lat990", opName, estHistogram, 0.99); + lat995 = new EstimatedHistogramPercentile("Dyno__" + appName + "__" + opName + "__lat995", opName, estHistogram, 0.995); + lat999 = new EstimatedHistogramPercentile("Dyno__" + appName + "__" + opName + "__lat999", opName, estHistogram, 0.999); + } + + public void recordLatency(long duration, TimeUnit unit) { + long durationMicros = TimeUnit.MICROSECONDS.convert(duration, unit); + estHistogram.add(durationMicros); + } + } + + private DynoTimingCounters getOrCreateTimers(String opName) { + + DynoTimingCounters timer = timerMap.get(opName); + if (timer != null) { + return timer; + } + timer = new DynoTimingCounters(appName, opName); + DynoTimingCounters prevTimer = timerMap.putIfAbsent(opName, timer); + if (prevTimer != null) { + return prevTimer; + } + DefaultMonitorRegistry.getInstance().register(timer.latMean); + DefaultMonitorRegistry.getInstance().register(timer.lat99); + DefaultMonitorRegistry.getInstance().register(timer.lat995); + DefaultMonitorRegistry.getInstance().register(timer.lat999); + return timer; + } } diff --git a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/ElasticConnectionPoolConfigurationPublisher.java b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/ElasticConnectionPoolConfigurationPublisher.java index 57cd6ef1..4369b9ed 100644 --- a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/ElasticConnectionPoolConfigurationPublisher.java +++ b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/ElasticConnectionPoolConfigurationPublisher.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -82,7 +82,7 @@ JSONObject createJsonFromConfig(ConnectionPoolConfiguration config) throws JSONE json.put("DynomiteClusterName", clusterName); Method[] methods = config.getClass().getMethods(); - for (Method method: methods) { + for (Method method : methods) { if (method.getName().startsWith("get")) { Class ret = method.getReturnType(); if (ret.isPrimitive() || ret == java.lang.String.class) { diff --git a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/EstimatedHistogramBasedCounter.java b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/EstimatedHistogramBasedCounter.java index ed60b57d..17a230b2 100644 --- a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/EstimatedHistogramBasedCounter.java +++ b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/EstimatedHistogramBasedCounter.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,71 +25,71 @@ public abstract class EstimatedHistogramBasedCounter extends AbstractMonitor { - protected final EstimatedHistogram estHistogram; - - /** - * Creates a new instance of the counter. - */ - public EstimatedHistogramBasedCounter(final String name, final String opName, final EstimatedHistogram histogram) { - super(MonitorConfig.builder(name).build() - .withAdditionalTag(DataSourceType.GAUGE) - .withAdditionalTag(new BasicTag("dyno_op", opName))); - this.estHistogram = histogram; - } - - public EstimatedHistogramBasedCounter(final String name, final String opName, final String tagName, final EstimatedHistogram histogram) { - super(MonitorConfig.builder(name).build() - .withAdditionalTag(DataSourceType.GAUGE) - .withAdditionalTag(new BasicTag(tagName, opName))); - this.estHistogram = histogram; - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof EstimatedHistogramBasedCounter)) { - return false; - } - EstimatedHistogramBasedCounter m = (EstimatedHistogramBasedCounter) obj; - return config.equals(m.getConfig()) && estHistogram.equals(m.estHistogram); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return Objects.hashCode(config, estHistogram.hashCode()); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("config", config) - .add("count", getValue()) - .toString(); - } - - public static class EstimatedHistogramMean extends EstimatedHistogramBasedCounter { - - public EstimatedHistogramMean(final String name, final String opName, final EstimatedHistogram histogram) { - super(name, opName, histogram); - } - - public EstimatedHistogramMean(final String name, final String opName, final String tagName, final EstimatedHistogram histogram) { - super(name, opName, tagName, histogram); - } - - @Override - public Number getValue() { - return estHistogram.mean(); - } + protected final EstimatedHistogram estHistogram; + + /** + * Creates a new instance of the counter. + */ + public EstimatedHistogramBasedCounter(final String name, final String opName, final EstimatedHistogram histogram) { + super(MonitorConfig.builder(name).build() + .withAdditionalTag(DataSourceType.GAUGE) + .withAdditionalTag(new BasicTag("dyno_op", opName))); + this.estHistogram = histogram; + } + + public EstimatedHistogramBasedCounter(final String name, final String opName, final String tagName, final EstimatedHistogram histogram) { + super(MonitorConfig.builder(name).build() + .withAdditionalTag(DataSourceType.GAUGE) + .withAdditionalTag(new BasicTag(tagName, opName))); + this.estHistogram = histogram; + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof EstimatedHistogramBasedCounter)) { + return false; + } + EstimatedHistogramBasedCounter m = (EstimatedHistogramBasedCounter) obj; + return config.equals(m.getConfig()) && estHistogram.equals(m.estHistogram); + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + return Objects.hashCode(config, estHistogram.hashCode()); + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("config", config) + .add("count", getValue()) + .toString(); + } + + public static class EstimatedHistogramMean extends EstimatedHistogramBasedCounter { + + public EstimatedHistogramMean(final String name, final String opName, final EstimatedHistogram histogram) { + super(name, opName, histogram); + } + + public EstimatedHistogramMean(final String name, final String opName, final String tagName, final EstimatedHistogram histogram) { + super(name, opName, tagName, histogram); + } + + @Override + public Number getValue() { + return estHistogram.mean(); + } @Override public Number getValue(int pollerIndex) { return estHistogram.mean(); } - public void add(long n) { + public void add(long n) { this.estHistogram.add(n); } @@ -97,30 +97,30 @@ public void reset() { this.estHistogram.getBuckets(true); } - } + } + + public static class EstimatedHistogramPercentile extends EstimatedHistogramBasedCounter { - public static class EstimatedHistogramPercentile extends EstimatedHistogramBasedCounter { + private final double percentile; - private final double percentile; - - public EstimatedHistogramPercentile(final String name, final String opName, final EstimatedHistogram histogram, double pVal) { - super(name, opName, histogram); - percentile = pVal; - } + public EstimatedHistogramPercentile(final String name, final String opName, final EstimatedHistogram histogram, double pVal) { + super(name, opName, histogram); + percentile = pVal; + } - public EstimatedHistogramPercentile(final String name, final String opName, final String tagName, final EstimatedHistogram histogram, double pVal) { - super(name, opName, tagName, histogram); - percentile = pVal; - } + public EstimatedHistogramPercentile(final String name, final String opName, final String tagName, final EstimatedHistogram histogram, double pVal) { + super(name, opName, tagName, histogram); + percentile = pVal; + } - @Override - public Number getValue() { - return estHistogram.percentile(percentile); - } + @Override + public Number getValue() { + return estHistogram.percentile(percentile); + } @Override public Number getValue(int pollerIndex) { return estHistogram.percentile(percentile); } - } + } } diff --git a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/EurekaHostsSupplier.java b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/EurekaHostsSupplier.java index bba6ee6c..95c1796d 100644 --- a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/EurekaHostsSupplier.java +++ b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/EurekaHostsSupplier.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -39,96 +39,95 @@ /** * Simple class that implements {@link Supplier}<{@link List}<{@link Host}>>. It provides a List<{@link Host}> * using the {@link DiscoveryManager} which is the eureka client. - * + * * Note that the class needs the eureka application name to discover all instances for that application. - * + * * @author poberai */ public class EurekaHostsSupplier implements HostSupplier { - private static final Logger Logger = LoggerFactory.getLogger(EurekaHostsSupplier.class); + private static final Logger Logger = LoggerFactory.getLogger(EurekaHostsSupplier.class); + + // The Dynomite cluster name for discovering nodes + private final String applicationName; + private final EurekaClient discoveryClient; - // The Dynomite cluster name for discovering nodes - private final String applicationName; - private final EurekaClient discoveryClient; - - @Deprecated + @Deprecated public EurekaHostsSupplier(String applicationName, DiscoveryClient dClient) { this.applicationName = applicationName.toUpperCase(); this.discoveryClient = dClient; } - + public EurekaHostsSupplier(String applicationName, EurekaClient dClient) { this.applicationName = applicationName.toUpperCase(); this.discoveryClient = dClient; } - public static EurekaHostsSupplier newInstance(String applicationName, EurekaHostsSupplier hostsSupplier) { + public static EurekaHostsSupplier newInstance(String applicationName, EurekaHostsSupplier hostsSupplier) { return new EurekaHostsSupplier(applicationName, hostsSupplier.getDiscoveryClient()); } - @Override - public List getHosts() { - return getUpdateFromEureka(); - } - - private List getUpdateFromEureka() { - - if (discoveryClient == null) { - Logger.error("Discovery client cannot be null"); - throw new RuntimeException("EurekaHostsSupplier needs a non-null DiscoveryClient"); - } - - Logger.info("Dyno fetching instance list for app: " + applicationName); - - Application app = discoveryClient.getApplication(applicationName); - List hosts = new ArrayList(); - - if (app == null) { - return hosts; - } - - List ins = app.getInstances(); - - if (ins == null || ins.isEmpty()) { - return hosts; - } - - hosts = Lists.newArrayList(Collections2.transform(ins, - - new Function() { - @Override - public Host apply(InstanceInfo info) { - - Host.Status status = info.getStatus() == InstanceStatus.UP ? Host.Status.Up : Host.Status.Down; - - String rack = null; - try { - if (info.getDataCenterInfo() instanceof AmazonInfo) { - AmazonInfo amazonInfo = (AmazonInfo)info.getDataCenterInfo(); - rack = amazonInfo.get(MetaDataKey.availabilityZone); - } - } - catch (Throwable t) { - Logger.error("Error getting rack for host " + info.getHostName(), t); - } - if(rack == null) { - Logger.error("Rack wasn't found for host:" + info.getHostName() + " there may be issues matching it up to the token map"); - } - Host host = new Host(info.getHostName(), info.getIPAddr(), rack, status); - return host; - } - })); - - Logger.info("Dyno found hosts from eureka - num hosts: " + hosts.size()); - - return hosts; - } - - @Override - public String toString() { - return EurekaHostsSupplier.class.getName(); - } + @Override + public List getHosts() { + return getUpdateFromEureka(); + } + + private List getUpdateFromEureka() { + + if (discoveryClient == null) { + Logger.error("Discovery client cannot be null"); + throw new RuntimeException("EurekaHostsSupplier needs a non-null DiscoveryClient"); + } + + Logger.info("Dyno fetching instance list for app: " + applicationName); + + Application app = discoveryClient.getApplication(applicationName); + List hosts = new ArrayList(); + + if (app == null) { + return hosts; + } + + List ins = app.getInstances(); + + if (ins == null || ins.isEmpty()) { + return hosts; + } + + hosts = Lists.newArrayList(Collections2.transform(ins, + + new Function() { + @Override + public Host apply(InstanceInfo info) { + + Host.Status status = info.getStatus() == InstanceStatus.UP ? Host.Status.Up : Host.Status.Down; + + String rack = null; + try { + if (info.getDataCenterInfo() instanceof AmazonInfo) { + AmazonInfo amazonInfo = (AmazonInfo) info.getDataCenterInfo(); + rack = amazonInfo.get(MetaDataKey.availabilityZone); + } + } catch (Throwable t) { + Logger.error("Error getting rack for host " + info.getHostName(), t); + } + if (rack == null) { + Logger.error("Rack wasn't found for host:" + info.getHostName() + " there may be issues matching it up to the token map"); + } + Host host = new Host(info.getHostName(), info.getIPAddr(), rack, status); + return host; + } + })); + + Logger.info("Dyno found hosts from eureka - num hosts: " + hosts.size()); + + return hosts; + } + + @Override + public String toString() { + return EurekaHostsSupplier.class.getName(); + } public String getApplicationName() { return applicationName; diff --git a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/consul/ConsulHelper.java b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/consul/ConsulHelper.java index 0d7169ff..a17067c0 100644 --- a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/consul/ConsulHelper.java +++ b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/consul/ConsulHelper.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,7 +25,7 @@ import com.ecwid.consul.v1.health.model.HealthService; /** - * + * * Class with support for consul simple/commons operations */ public class ConsulHelper { @@ -52,18 +52,18 @@ public static Map getMetadata(List tags) { for (String tag : tags) { String[] parts = StringUtils.split(tag, "="); switch (parts.length) { - case 0: - break; - case 1: - metadata.put(parts[0], parts[0]); - break; - case 2: - metadata.put(parts[0], parts[1]); - break; - default: - String[] end = Arrays.copyOfRange(parts, 1, parts.length); - metadata.put(parts[0], StringUtils.join(end, "=")); - break; + case 0: + break; + case 1: + metadata.put(parts[0], parts[0]); + break; + case 2: + metadata.put(parts[0], parts[1]); + break; + default: + String[] end = Arrays.copyOfRange(parts, 1, parts.length); + metadata.put(parts[0], StringUtils.join(end, "=")); + break; } } diff --git a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/consul/ConsulHostsSupplier.java b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/consul/ConsulHostsSupplier.java index a5f15dc6..b643c439 100644 --- a/dyno-contrib/src/main/java/com/netflix/dyno/contrib/consul/ConsulHostsSupplier.java +++ b/dyno-contrib/src/main/java/com/netflix/dyno/contrib/consul/ConsulHostsSupplier.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,6 +14,7 @@ * limitations under the License. */ package com.netflix.dyno.contrib.consul; + import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -38,22 +39,22 @@ /** * Simple class that implements {@link Supplier}<{@link List}<{@link Host}>>. It provides a List<{@link Host}> * using the {@link DiscoveryManager} which is the consul client. - * + * * Note that the class needs the consul application name to discover all instances for that application. - * + * * Example of register at consul - * - curl -X PUT http://localhost:8500/v1/agent/service/register -d "{ - \"ID\": \"dynomite-8102\", - \"Name\": \"dynomite\", - \"Tags\": [\"datacenter=dc\",\"cloud=openstack\",\"rack=dc-rack\"], - \"Address\": \"127.0.0.2\", - \"Port\": 8102, - \"Check\": { - \"Interval\": \"10s\", - \"HTTP\": \"http://127.0.0.1:22222/ping\" - }}" - * + * + curl -X PUT http://localhost:8500/v1/agent/service/register -d "{ + \"ID\": \"dynomite-8102\", + \"Name\": \"dynomite\", + \"Tags\": [\"datacenter=dc\",\"cloud=openstack\",\"rack=dc-rack\"], + \"Address\": \"127.0.0.2\", + \"Port\": 8102, + \"Check\": { + \"Interval\": \"10s\", + \"HTTP\": \"http://127.0.0.1:22222/ping\" + }}" + * * @author tiodollar */ public class ConsulHostsSupplier implements HostSupplier { diff --git a/dyno-contrib/src/test/java/com/netflix/dyno/contrib/ConsulHostsSupplierTest.java b/dyno-contrib/src/test/java/com/netflix/dyno/contrib/ConsulHostsSupplierTest.java index f4a1c865..4b459541 100644 --- a/dyno-contrib/src/test/java/com/netflix/dyno/contrib/ConsulHostsSupplierTest.java +++ b/dyno-contrib/src/test/java/com/netflix/dyno/contrib/ConsulHostsSupplierTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -43,10 +43,10 @@ public class ConsulHostsSupplierTest { @Before public void beforeEach() { String config = "{" + - "\"datacenter\": \"test-dc\"," + - "\"log_level\": \"INFO\"," + - "\"node_name\": \"foobar\"" + - "}"; + "\"datacenter\": \"test-dc\"," + + "\"log_level\": \"INFO\"," + + "\"node_name\": \"foobar\"" + + "}"; consulServer = ConsulStarterBuilder.consulStarter().withCustomConfig(config).build().start(); consulClient = new ConsulClient("127.0.0.1", consulServer.getHttpPort()); } diff --git a/dyno-contrib/src/test/java/com/netflix/dyno/contrib/ElasticConnectionPoolConfigurationPublisherTest.java b/dyno-contrib/src/test/java/com/netflix/dyno/contrib/ElasticConnectionPoolConfigurationPublisherTest.java index 9eeece5c..f5546f43 100644 --- a/dyno-contrib/src/test/java/com/netflix/dyno/contrib/ElasticConnectionPoolConfigurationPublisherTest.java +++ b/dyno-contrib/src/test/java/com/netflix/dyno/contrib/ElasticConnectionPoolConfigurationPublisherTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -42,7 +42,7 @@ public void testLibraryVersion() { ElasticConnectionPoolConfigurationPublisher publisher = new ElasticConnectionPoolConfigurationPublisher("ClientApp", "dyno_cluster_1", "unit-test-vip", config); - Map versions = publisher.getLibraryVersion(this.getClass(), "dyno-core"); + Map versions = publisher.getLibraryVersion(this.getClass(), "dyno-core"); assertTrue(versions.size() == 1 || versions.size() == 0); // dyno-contrib depends on dyno-core } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/AsyncOperation.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/AsyncOperation.java index 8e351ee7..d465a9b4 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/AsyncOperation.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/AsyncOperation.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,21 +18,19 @@ import com.netflix.dyno.connectionpool.exception.DynoException; /** - * Interface for representing an async operation. The execution of the operation should return + * Interface for representing an async operation. The execution of the operation should return * a future to the result of the execution. - * - * @author poberai * * @param * @param + * @author poberai */ public interface AsyncOperation extends BaseOperation { - - /** - * - * @param client - * @return - * @throws DynoException - */ + + /** + * @param client + * @return + * @throws DynoException + */ public ListenableFuture executeAsync(CL client) throws DynoException; } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/BaseOperation.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/BaseOperation.java index 5fc67640..acd3f6e2 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/BaseOperation.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/BaseOperation.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,35 +18,32 @@ /** * Base for any operation that can be performed using a connection from the * connection pool - * + * + * @param client + * @param result * @author poberai * @author ipapapa - * - * @param - * client - * @param - * result */ public interface BaseOperation { /** * Op name. Used for tracking metrics etc. - * + * * @return String */ public String getName(); /** * The key for the operation. Useful for implementing token aware routing. - * + * * @return String */ public String getStringKey(); - + /** * The binary key for the operation - * - * @return + * + * @return */ public byte[] getBinaryKey(); diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/Connection.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/Connection.java index 83952d14..4389083d 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/Connection.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/Connection.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,22 +20,21 @@ /** * Interface to an instance of a connection on a host. - * - * @author poberai - * + * * @param + * @author poberai */ public interface Connection { /** * Execute an operation on the connection and return a result - * + * * @param * @param op * @throws DynoException */ public OperationResult execute(Operation op) throws DynoException; - + public ListenableFuture> executeAsync(AsyncOperation op) throws DynoException; /** @@ -50,39 +49,41 @@ public interface Connection { /** * Open a new connection - * + * * @throws DynoException */ public void open() throws DynoException; /** - * Can be used by clients to indicate connection exception. + * Can be used by clients to indicate connection exception. * This can be analyzed by connection pools later - * e.g remove host from connection pool etc. - * + * e.g remove host from connection pool etc. + * * @return */ public DynoConnectException getLastException(); - + /** * Return the parent HostConnectionPool that manages this connection. * This is generally useful for meta operations on HostConnectionPool(s) when dealing with their Connection(s) - * e.g - * 1. Return connections safely to the parent pool after executing operations on them - * 2. Reporting error stats to parent pools when performing ops on connections. The parent pools can then - * decide whether the connections should be recycled etc. + * e.g + * 1. Return connections safely to the parent pool after executing operations on them + * 2. Reporting error stats to parent pools when performing ops on connections. The parent pools can then + * decide whether the connections should be recycled etc. + * * @return */ public HostConnectionPool getParentConnectionPool(); - + /** * Operation to send ping heartbeats on Connection(s) * This is primarily used for active monitoring so that stale/bad connections to Hosts can be recycled. */ public void execPing(); - + /** * Can be used by different layers within dyno to add valuable information to the Connection. + * * @return ConnectionContext */ public ConnectionContext getContext(); diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionContext.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionContext.java index 84b2111f..d749e727 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionContext.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionContext.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,38 +22,39 @@ /** * Context specific to a connection. This interface makes it possible to store * connection specific state such as prepared CQL statement ids etc. - * - * @author poberai * + * @author poberai */ public interface ConnectionContext { /** * Set metadata identified by 'key' + * * @param key * @param obj */ public void setMetadata(String key, Object obj); - + /** - * @return Get metadata stored by calling setMetadata * @param key + * @return Get metadata stored by calling setMetadata */ public Object getMetadata(String key); - + /** - * @return Return true if the metadata with the specified key exists. * @param key + * @return Return true if the metadata with the specified key exists. */ public boolean hasMetadata(String key); - + /** * Reset all metadata */ public void reset(); - + /** * Return all context - * @return Map + * + * @return Map */ public Map getAll(); } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionFactory.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionFactory.java index a655540d..b674715c 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionFactory.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionFactory.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,20 +21,20 @@ /** * Factory used to create and open new connections on a host. - * - * @author poberai - * + * * @param + * @author poberai */ public interface ConnectionFactory { - - /** - * Create a connection for this {@link HostConnectionPool} - * @param pool - * @param observor - * @return - * @throws DynoConnectException - * @throws ThrottledException - */ - public Connection createConnection(HostConnectionPool pool, ConnectionObservor observor) throws DynoConnectException, ThrottledException; + + /** + * Create a connection for this {@link HostConnectionPool} + * + * @param pool + * @param observor + * @return + * @throws DynoConnectException + * @throws ThrottledException + */ + public Connection createConnection(HostConnectionPool pool, ConnectionObservor observor) throws DynoConnectException, ThrottledException; } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionObservor.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionObservor.java index 20f13501..bc1a0657 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionObservor.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionObservor.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,24 +16,25 @@ package com.netflix.dyno.connectionpool; /** - * Interface for observers to connections becoming active and inactive. + * Interface for observers to connections becoming active and inactive. * Observers can then track stats about this and even implement connection recycling * in order to keep the connection pool primed with active connections - * - * @author poberai * + * @author poberai */ public interface ConnectionObservor { - /** - * Connection has been established for this host - * @param host - */ - public void connectionEstablished(Host host); + /** + * Connection has been established for this host + * + * @param host + */ + public void connectionEstablished(Host host); - /** - * Connection to this host was lost - * @param host - */ - public void connectionLost(Host host); + /** + * Connection to this host was lost + * + * @param host + */ + public void connectionLost(Host host); } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPool.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPool.java index de1f56fc..58c74584 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPool.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPool.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,39 +24,39 @@ /** * Base interface for a pool of connections. A concrete connection pool will * track hosts in a cluster. - * - * @author poberai + * * @param + * @author poberai */ public interface ConnectionPool { - - /** + + /** * Add a host to the connection pool. - * + * * @param host - * @returns True if host was added or false if host already exists * @throws DynoException + * @returns True if host was added or false if host already exists */ boolean addHost(Host host); - /** + /** * Remove a host from the connection pool. - * + * * @param host - * @returns True if host was added or false if host already exists * @throws DynoException + * @returns True if host was added or false if host already exists */ boolean removeHost(Host host); /** - * @return Return true if the host is up * @param host + * @return Return true if the host is up */ boolean isHostUp(Host host); /** - * @return Return true if host is contained within the connection pool * @param host + * @return Return true if host is contained within the connection pool */ boolean hasHost(Host host); @@ -69,7 +69,7 @@ public interface ConnectionPool { * @return Get all pools */ List> getPools(); - + /** * Set the complete set of hosts in the ring * @@ -79,8 +79,8 @@ public interface ConnectionPool { Future updateHosts(Collection activeHosts, Collection inactiveHosts); /** - * @return Return an immutable connection pool for this host * @param host + * @return Return an immutable connection pool for this host */ HostConnectionPool getHostPool(Host host); @@ -88,25 +88,27 @@ public interface ConnectionPool { * Execute an operation with failover within the context of the connection * pool. The operation will only fail over for connection pool errors and * not application errors. - * + * * @param * @param op * @throws DynoException */ OperationResult executeWithFailover(Operation op) throws DynoException; - + /** * Scatter gather style operation + * * @param op - * @return Collection> + * @return Collection> * @throws DynoException */ Collection> executeWithRing(TokenRackMapper tokenRackMapper, Operation op) throws DynoException; /** * Execute an operation asynchronously. + * * @param op - * @return ListenableFuture> + * @return ListenableFuture> * @throws DynoException */ ListenableFuture> executeAsync(AsyncOperation op) throws DynoException; diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPoolConfiguration.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPoolConfiguration.java index 2de9f56f..860b493b 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPoolConfiguration.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPoolConfiguration.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,16 +22,20 @@ * Specifies configuration settings for an instance of a dyno connection pool. */ public interface ConnectionPoolConfiguration { - - enum LoadBalancingStrategy { - RoundRobin, TokenAware; - } + + enum LoadBalancingStrategy { + RoundRobin, TokenAware; + } enum CompressionStrategy { - /** Disables compression */ + /** + * Disables compression + */ NONE, - /** Compresses values that exceed {@link #getValueCompressionThreshold()} */ + /** + * Compresses values that exceed {@link #getValueCompressionThreshold()} + */ THRESHOLD } @@ -68,7 +72,7 @@ enum CompressionStrategy { * Returns the {@link LoadBalancingStrategy} for this connection pool. */ LoadBalancingStrategy getLoadBalancingStrategy(); - + /** * Specifies the socket connection timeout */ @@ -83,33 +87,34 @@ enum CompressionStrategy { *

*/ boolean localZoneAffinity(); - + /** * Returns the {@link ErrorMonitorFactory} to use for this connection pool. */ ErrorMonitorFactory getErrorMonitorFactory(); - + /** * Returns the {@link RetryPolicyFactory} to use for this connection pool. */ RetryPolicyFactory getRetryPolicyFactory(); - + /** * Returns the {@link HostSupplier} to use for this connection pool. */ HostSupplier getHostSupplier(); - + /** * Returns the {@link TokenMapSupplier} to use for this connection pool. */ TokenMapSupplier getTokenSupplier(); - + /** * Returns the {@link HashPartitioner} for this connection pool. - * @return + * + * @return */ HashPartitioner getHashPartitioner(); - + /** * Returns the interval for which pings are issued on connections. * @@ -118,7 +123,7 @@ enum CompressionStrategy { *

*/ int getPingFrequencySeconds(); - + /** * Returns the local rack name for this connection pool. In AWS terminology this is a zone, e.g. us-east-1c. */ @@ -150,7 +155,7 @@ enum CompressionStrategy { * log configuration settings to a central system such as elastic search or cassandra. *

*/ - String getConfigurationPublisherConfig(); + String getConfigurationPublisherConfig(); /** * If there are no hosts marked as 'Up' in the {@link HostSupplier} when starting the connection pool @@ -209,8 +214,10 @@ enum CompressionStrategy { * Returns the schedule time delay in milliseconds for the connection pool health tracker */ int getHealthTrackerDelayMillis(); + /** * Returns the amount of time pool reconnect has to wait before establishing new connections. + * * @return */ int getPoolReconnectWaitMillis(); diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPoolConfigurationPublisher.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPoolConfigurationPublisher.java index f3b33e33..c687ba28 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPoolConfigurationPublisher.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPoolConfigurationPublisher.java @@ -28,5 +28,4 @@ enum PublisherType { void publish(); - } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPoolMonitor.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPoolMonitor.java index 2e861ded..9f94fa81 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPoolMonitor.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ConnectionPoolMonitor.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,41 +21,41 @@ * Monitoring interface to receive notification of pool events. A concrete * monitor will make event stats available to a monitoring application and may * also log events to a log file. - * + * * @author poberai */ public interface ConnectionPoolMonitor { - + /** * Succeeded in executing an operation - * + * * @param host * @param latency */ - public void incOperationSuccess(Host host, long latency); + public void incOperationSuccess(Host host, long latency); + + public long getOperationSuccessCount(); - public long getOperationSuccessCount(); - /** * Errors trying to execute an operation. - * + * * @param reason * @param host */ - public void incOperationFailure(Host host, Exception reason); + public void incOperationFailure(Host host, Exception reason); + + public long getOperationFailureCount(); - public long getOperationFailureCount(); - /** * An operation failed but the connection pool will attempt to fail over to - * another host/connection. + * another host/connection. */ public void incFailover(Host host, Exception reason); public long getFailoverCount(); - + /** * Created a connection successfully */ @@ -65,9 +65,8 @@ public interface ConnectionPoolMonitor { /** * Closed a connection - * + * * @param reason - * */ public void incConnectionClosed(Host host, Exception reason); @@ -75,7 +74,7 @@ public interface ConnectionPoolMonitor { /** * Attempt to create a connection failed - * + * * @param host * @param reason */ @@ -85,11 +84,9 @@ public interface ConnectionPoolMonitor { /** * Incremented for each connection borrowed - * - * @param host - * Host from which the connection was borrowed - * @param delay - * Time spent in the connection pool borrowing the connection + * + * @param host Host from which the connection was borrowed + * @param delay Time spent in the connection pool borrowing the connection */ public void incConnectionBorrowed(Host host, long delay); @@ -124,9 +121,8 @@ public interface ConnectionPoolMonitor { /** * Incremented for each connection returned. - * - * @param host - * Host to which connection is returned + * + * @param host Host to which connection is returned */ public void incConnectionReturned(Host host); @@ -135,8 +131,7 @@ public interface ConnectionPoolMonitor { /** * Incremented for each connection recycle. * - * @param host - * Host to which connection is returned for recycle + * @param host Host to which connection is returned for recycle */ public void incConnectionRecycled(Host host); @@ -156,27 +151,27 @@ public interface ConnectionPoolMonitor { * @return Count of socket timeouts trying to execute an operation */ public long getSocketTimeoutCount(); - + /** * @return Get number of unknown errors */ public long getUnknownErrorCount(); - + /** * @return Get number of invalid requests (i.e. bad argument values) */ public long getBadRequestCount(); - + /** * @return Count of times no hosts at all were available to execute an operation. */ public long getNoHostCount(); - + /** * @return Return the number of hosts in the pool */ public long getHostCount(); - + /** * @return Return the number of times any host was marked as down. */ @@ -190,7 +185,7 @@ public interface ConnectionPoolMonitor { /** * A host was added and given the associated pool. The pool is immutable and * can be used to get info about the number of open connections - * + * * @param host * @param pool */ @@ -199,23 +194,22 @@ public interface ConnectionPoolMonitor { /** * A host was removed from the pool. This is usually called when a downed * host is removed from the ring. - * + * * @param host */ public void hostRemoved(Host host); /** * A host was identified as downed. - * + * * @param host - * @param reason - * Exception that caused the host to be identified as down + * @param reason Exception that caused the host to be identified as down */ public void hostDown(Host host, Exception reason); /** * A host was reactivated after being marked down - * + * * @param host * @param pool */ diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/DecoratingFuture.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/DecoratingFuture.java index d719c08a..6be15698 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/DecoratingFuture.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/DecoratingFuture.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,36 +22,36 @@ public class DecoratingFuture implements Future { - private final ListenableFuture> innerFuture; - - public DecoratingFuture(final ListenableFuture> listenableFuture) { - innerFuture = listenableFuture; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return innerFuture.cancel(mayInterruptIfRunning); - } - - @Override - public boolean isCancelled() { - return innerFuture.isCancelled(); - } - - @Override - public boolean isDone() { - return innerFuture.isDone(); - } - - @Override - public V get() throws InterruptedException, ExecutionException { - OperationResult opResult = innerFuture.get(); - return opResult.getResult(); - } - - @Override - public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - OperationResult opResult = innerFuture.get(timeout, unit); - return opResult.getResult(); - } + private final ListenableFuture> innerFuture; + + public DecoratingFuture(final ListenableFuture> listenableFuture) { + innerFuture = listenableFuture; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return innerFuture.cancel(mayInterruptIfRunning); + } + + @Override + public boolean isCancelled() { + return innerFuture.isCancelled(); + } + + @Override + public boolean isDone() { + return innerFuture.isDone(); + } + + @Override + public V get() throws InterruptedException, ExecutionException { + OperationResult opResult = innerFuture.get(); + return opResult.getResult(); + } + + @Override + public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + OperationResult opResult = innerFuture.get(timeout, unit); + return opResult.getResult(); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/DecoratingListenableFuture.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/DecoratingListenableFuture.java index ffe229ab..ff4ec9d6 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/DecoratingListenableFuture.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/DecoratingListenableFuture.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,39 +23,39 @@ public class DecoratingListenableFuture implements ListenableFuture { - private final Future innerFuture; - - public DecoratingListenableFuture(Future future) { - innerFuture = future; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return innerFuture.cancel(mayInterruptIfRunning); - } - - @Override - public boolean isCancelled() { - return innerFuture.isCancelled(); - } - - @Override - public boolean isDone() { - return innerFuture.isDone(); - } - - @Override - public V get() throws InterruptedException, ExecutionException { - return innerFuture.get(); - } - - @Override - public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - return innerFuture.get(timeout, unit); - } - - @Override - public void addListener(Runnable listener, Executor executor) { - throw new RuntimeException("Not Implemented"); - } + private final Future innerFuture; + + public DecoratingListenableFuture(Future future) { + innerFuture = future; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return innerFuture.cancel(mayInterruptIfRunning); + } + + @Override + public boolean isCancelled() { + return innerFuture.isCancelled(); + } + + @Override + public boolean isDone() { + return innerFuture.isDone(); + } + + @Override + public V get() throws InterruptedException, ExecutionException { + return innerFuture.get(); + } + + @Override + public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return innerFuture.get(timeout, unit); + } + + @Override + public void addListener(Runnable listener, Executor executor) { + throw new RuntimeException("Not Implemented"); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ErrorRateMonitorConfig.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ErrorRateMonitorConfig.java index d3a003db..945ae974 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ErrorRateMonitorConfig.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ErrorRateMonitorConfig.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,61 +21,68 @@ /** * Interface for config required by {@link ErrorRateMonitor} - * @author poberai * + * @author poberai */ public interface ErrorRateMonitorConfig { - /** - * Size of the window (in seconds) that should be monitored - * @return int - */ - public int getWindowSizeSeconds(); - - /** - * Frequency at which the error rate check should run - * @return int - */ - public int getCheckFrequencySeconds(); - - /** - * Window for suppressing alerts once the alert has been triggered. - * This is useful for suppressing a deluge of alerts once a critical alert has been fired. - * @return int - */ - public int getCheckSuppressWindowSeconds(); - - /** - * Multiple ErrorThresholds to honor - * @return List - */ - public List getThresholds(); - - /** - * Interface the describes an isolated error threshold to monitor - * @author poberai - * - */ - public interface ErrorThreshold { - - /** - * Error threshold - * @return int - */ - public int getThresholdPerSecond(); - - /** - * Size of window to consider when sampling the error rate - * @return int - */ - public int getWindowSeconds(); - - /** - * How much of the window should be above error threshold in order to generate the alert. - * This is used when the error rates are sparse but still frequent enough to trigger an alert - * @return int - */ - public int getWindowCoveragePercentage(); - } - + /** + * Size of the window (in seconds) that should be monitored + * + * @return int + */ + public int getWindowSizeSeconds(); + + /** + * Frequency at which the error rate check should run + * + * @return int + */ + public int getCheckFrequencySeconds(); + + /** + * Window for suppressing alerts once the alert has been triggered. + * This is useful for suppressing a deluge of alerts once a critical alert has been fired. + * + * @return int + */ + public int getCheckSuppressWindowSeconds(); + + /** + * Multiple ErrorThresholds to honor + * + * @return List + */ + public List getThresholds(); + + /** + * Interface the describes an isolated error threshold to monitor + * + * @author poberai + */ + public interface ErrorThreshold { + + /** + * Error threshold + * + * @return int + */ + public int getThresholdPerSecond(); + + /** + * Size of window to consider when sampling the error rate + * + * @return int + */ + public int getWindowSeconds(); + + /** + * How much of the window should be above error threshold in order to generate the alert. + * This is used when the error rates are sparse but still frequent enough to trigger an alert + * + * @return int + */ + public int getWindowCoveragePercentage(); + } + } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HashPartitioner.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HashPartitioner.java index 11f2b534..455cc0c7 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HashPartitioner.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HashPartitioner.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,44 +18,42 @@ import com.netflix.dyno.connectionpool.impl.lb.HostToken; /** - * Interface for generating hash for a given key. + * Interface for generating hash for a given key. * The implementing class is also responsible for determining how to map the hash to the underlying dynomite server topology * expressed via the Collection - * - * @author poberai * + * @author poberai */ public interface HashPartitioner { - /** - * @param key - * @return Long - */ - public Long hash(int key); - - /** - * @param key - * @return Long - */ - public Long hash(long key); - - /** - * @param key - * @return Long - */ - public Long hash(String key); - - /** - * @param key - * @return Long - */ - public Long hash(byte[] key); - - /** - * - * @param keyHash - * @return - */ - public HostToken getToken(Long keyHash); + /** + * @param key + * @return Long + */ + public Long hash(int key); + + /** + * @param key + * @return Long + */ + public Long hash(long key); + + /** + * @param key + * @return Long + */ + public Long hash(String key); + + /** + * @param key + * @return Long + */ + public Long hash(byte[] key); + + /** + * @param keyHash + * @return + */ + public HostToken getToken(Long keyHash); } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HealthTracker.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HealthTracker.java index b1def901..854ed7d4 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HealthTracker.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HealthTracker.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/Host.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/Host.java index 11348feb..22d43178 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/Host.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/Host.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,7 +23,7 @@ /** * Class encapsulating information about a host. - * + *

* This is immutable except for the host status. Note that the HostSupplier may * not know the Dynomite port, whereas the Host object created by the load * balancer may receive the port the cluster_describe REST call. Hence, we must @@ -31,7 +31,6 @@ * * @author poberai * @author ipapapa - * */ public class Host implements Comparable { @@ -90,7 +89,7 @@ public Host(String hostname, String ipAddress, int port, String rack, String dat } public Host(String name, String ipAddress, int port, String rack, String datacenter, Status status, - String hashtag) { + String hashtag) { this(name, ipAddress, port, port, rack, datacenter, status, hashtag); } @@ -199,7 +198,7 @@ public boolean equals(Object obj) { return false; Host other = (Host) obj; - + boolean equals = true; equals &= (hostname != null) ? hostname.equals(other.hostname) : other.hostname == null; @@ -222,6 +221,6 @@ public String toString() { return "Host [hostname=" + hostname + ", ipAddress=" + ipAddress + ", port=" + port + ", rack: " + rack + ", datacenter: " + datacenter + ", status: " + status.name() + ", hashtag=" - + hashtag + ", password=" + (Objects.nonNull(password) ? "masked" : "null") + "]"; + + hashtag + ", password=" + (Objects.nonNull(password) ? "masked" : "null") + "]"; } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostConnectionPool.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostConnectionPool.java index 0949bd31..e3f8fa5c 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostConnectionPool.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostConnectionPool.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,43 +22,41 @@ /** * Interface for a pool of {@link Connection}(s) for a single {@link Host} - * - * The interface prescribes certain key features required by clients of this class, such as - *

    - *
  1. Basic connection pool life cycle management such as prime connections (init) and shutdown

  2. - * - *
  3. Basic {@link Connection} life cycle management such as borrow / return / close / markAsDown

  4. - * - *
  5. Tracking the {@link Host} associated with the connection pool.

  6. - * - *
  7. Visibility into the status of the connection pool and it's connections. - *
      - *
    1. Tracking status of pool - isConnecting / isActive / isShutdown
    2. - *
    3. Tracking basic counters for connections - active / pending / blocked / idle / busy / closed etc
    4. - *
    5. Tracking latency scores for connections to this host.
    6. - *
    7. Tracking failures for connections to this host.
    8. - *
    - *
- * + *

+ * The interface prescribes certain key features required by clients of this class, such as + *

    + *
  1. Basic connection pool life cycle management such as prime connections (init) and shutdown

  2. + * + *
  3. Basic {@link Connection} life cycle management such as borrow / return / close / markAsDown

  4. + * + *
  5. Tracking the {@link Host} associated with the connection pool.

  6. + * + *
  7. Visibility into the status of the connection pool and it's connections. + *
      + *
    1. Tracking status of pool - isConnecting / isActive / isShutdown
    2. + *
    3. Tracking basic counters for connections - active / pending / blocked / idle / busy / closed etc
    4. + *
    5. Tracking latency scores for connections to this host.
    6. + *
    7. Tracking failures for connections to this host.
    8. + *
    + *
+ *

* This class is intended to be used within a collection of {@link HostConnectionPool} tracked by a * {@link ConnectionPool} for all the {@link Host}(s) within a Dynomite cluster. - * - * @see {@link ConnectionPool} for references to this class. - * - * @author poberai - * + * * @param + * @author poberai + * @see {@link ConnectionPool} for references to this class. */ public interface HostConnectionPool { - + /** * Borrow a connection from the host. May create a new connection if one is * not available. - * + * * @param duration The amount of time to wait for a connection to become available - * @param unit Specifies the unit of time corresponding to the duration (i.e. seconds vs milliseconds) - * @return A borrowed connection. Connection must be returned either by calling returnConnection - * or closeConnection. + * @param unit Specifies the unit of time corresponding to the duration (i.e. seconds vs milliseconds) + * @return A borrowed connection. Connection must be returned either by calling returnConnection + * or closeConnection. * @throws DynoException */ Connection borrowConnection(int duration, TimeUnit unit) throws DynoException; @@ -67,7 +65,7 @@ public interface HostConnectionPool { * Return a connection to the host's pool. May close the connection if the * pool is down or the last exception on the connection is determined to be * fatal. - * + * * @param connection * @return True if connection was closed */ @@ -75,7 +73,7 @@ public interface HostConnectionPool { /** * Close this connection and update internal state - * + * * @param connection */ boolean closeConnection(Connection connection); @@ -95,8 +93,8 @@ public interface HostConnectionPool { void markAsDown(DynoException reason); /** - * Recycle all connections in the connection pool. - * Note that the impl should either be able to handle active requests when re-cycling connections + * Recycle all connections in the connection pool. + * Note that the impl should either be able to handle active requests when re-cycling connections * or should be NOT active when re-cycling connections, so that calling clients can failover to other pools/hosts. */ void reconnect(); @@ -108,7 +106,7 @@ public interface HostConnectionPool { /** * Create new connections and add them to the pool. Consult ConnectionPoolConfiguration.getMaxConnsPerHost() - * + * * @throws DynoException * @returns Actual number of connections created */ @@ -123,17 +121,18 @@ public interface HostConnectionPool { * @return Return true if the pool is active. */ boolean isActive(); - + /** * @return Return true if the has been shut down and is no longer accepting traffic. */ boolean isShutdown(); - + /** - * Get all connections for the managed pool underneath. + * Get all connections for the managed pool underneath. * USE with EXTREME CAUTION since all vended connections must be returned to the pool * in order to avoid pool exhaustion. - * @return Collection> + * + * @return Collection> */ Collection> getAllConnections(); diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostConnectionStats.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostConnectionStats.java index 10160f0f..d5ba72e7 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostConnectionStats.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostConnectionStats.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,49 +18,49 @@ /** * Stats for connection operations for each {@code Host} * These are tracked by the {@link ConnectionPoolMonitor} for the {@link ConnectionPool} - * @author poberai * + * @author poberai */ public interface HostConnectionStats { - /** - * @return boolean - */ - public boolean isHostUp(); + /** + * @return boolean + */ + public boolean isHostUp(); + + /** + * @return long + */ + public long getConnectionsBorrowed(); + + /** + * @return long + */ + public long getConnectionsReturned(); + + /** + * @return long + */ + public long getConnectionsCreated(); - /** - * @return long - */ - public long getConnectionsBorrowed(); - - /** - * @return long - */ - public long getConnectionsReturned(); - - /** - * @return long - */ - public long getConnectionsCreated(); - - /** - * @return long - */ - public long getConnectionsClosed(); + /** + * @return long + */ + public long getConnectionsClosed(); - /** - * @return long - */ - public long getConnectionsCreateFailed(); + /** + * @return long + */ + public long getConnectionsCreateFailed(); - /** - * @return long - */ - public long getOperationSuccessCount(); + /** + * @return long + */ + public long getOperationSuccessCount(); - /** - * @return long - */ - public long getOperationErrorCount(); + /** + * @return long + */ + public long getOperationErrorCount(); } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostGroup.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostGroup.java index fd2c74c6..dedbd3a8 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostGroup.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostGroup.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,31 +23,30 @@ /** * Class representing a group of hosts. This is useful for underlying connection pool implementations - * where a single multiplexed connection can be used to talk to a group of hosts. - * e.g spy memcached uses this approach where there is a single selector for a group of hosts. - * - * @author poberai + * where a single multiplexed connection can be used to talk to a group of hosts. + * e.g spy memcached uses this approach where there is a single selector for a group of hosts. * + * @author poberai */ public class HostGroup extends Host { - private final List hostList = new ArrayList(); - - public HostGroup(String hostname, String ipAddress, int port, String rack) { - super(hostname, ipAddress, port, rack); - } - - public void add(Collection hosts) { - for (Host host : hosts) { - if (!host.isUp()) { - throw new DynoConnectException("Cannot add host that is DOWN"); - } - hostList.add(host); - } - } - - public List getHostList() { - return hostList; - } - + private final List hostList = new ArrayList(); + + public HostGroup(String hostname, String ipAddress, int port, String rack) { + super(hostname, ipAddress, port, rack); + } + + public void add(Collection hosts) { + for (Host host : hosts) { + if (!host.isUp()) { + throw new DynoConnectException("Cannot add host that is DOWN"); + } + hostList.add(host); + } + } + + public List getHostList() { + return hostList; + } + } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostSupplier.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostSupplier.java index 91a5b109..c6e4e567 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostSupplier.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/HostSupplier.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,17 +18,17 @@ import java.util.List; /** - * Interface for a supplier of host objects that map to the dynomite cluster. The {@link ConnectionPool} object can use this to + * Interface for a supplier of host objects that map to the dynomite cluster. The {@link ConnectionPool} object can use this to * instantiate {@link Connection}s to the hosts supplied by the host supplier - * - * @author poberai * + * @author poberai */ public interface HostSupplier { - - /** - * Return a list of dynomite hosts for the connection pool - * @return List - */ - public List getHosts(); + + /** + * Return a list of dynomite hosts for the connection pool + * + * @return List + */ + public List getHosts(); } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ListenableFuture.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ListenableFuture.java index bc0ad310..30a8c110 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ListenableFuture.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/ListenableFuture.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,5 +20,5 @@ public interface ListenableFuture extends Future { - public void addListener(Runnable listener, Executor executor); + public void addListener(Runnable listener, Executor executor); } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/MultiKeyCompressionOperation.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/MultiKeyCompressionOperation.java index 80e5c72c..d19973db 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/MultiKeyCompressionOperation.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/MultiKeyCompressionOperation.java @@ -1,18 +1,16 @@ package com.netflix.dyno.connectionpool; + /** - * - * Interface to be used for multi key operations, i.e. + * Interface to be used for multi key operations, i.e. * taking as input an vararg like String... * - * - * @author ipapapa - * * @param * @param + * @author ipapapa */ public interface MultiKeyCompressionOperation extends Operation { - String[] compressMultiKeyValue(ConnectionContext ctx, String... value); + String[] compressMultiKeyValue(ConnectionContext ctx, String... value); String decompressValue(ConnectionContext ctx, String value); } \ No newline at end of file diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/Operation.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/Operation.java index 163e26f6..330097df 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/Operation.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/Operation.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,15 +19,15 @@ /** * Interface that represents a synchronous operation on the connection - * @author poberai * * @param * @param + * @author poberai */ public interface Operation extends BaseOperation { /** * Execute the operation on the client object and return the results. - * + * * @param client - The client object * @param state - State and metadata specific to the connection * @return diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/OperationMonitor.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/OperationMonitor.java index 979cf44c..9dde7766 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/OperationMonitor.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/OperationMonitor.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,45 +18,47 @@ import java.util.concurrent.TimeUnit; /** - * Interface for recording high level stats for operation executions. - * Includes latency, success and failures. - * - * @author poberai + * Interface for recording high level stats for operation executions. + * Includes latency, success and failures. * + * @author poberai */ public interface OperationMonitor { - /** - * Record latency for the operation - * @param opName - * @param duration - * @param unit - */ - void recordLatency(String opName, long duration, TimeUnit unit); - - /** - * Record success for the operation - * @param opName - */ - void recordSuccess(String opName); + /** + * Record latency for the operation + * + * @param opName + * @param duration + * @param unit + */ + void recordLatency(String opName, long duration, TimeUnit unit); + + /** + * Record success for the operation + * + * @param opName + */ + void recordSuccess(String opName); - /** - * Record success while specifying if compression has been enabled for - * the operation. Note that this means that either the value was - * compressed or decompressed during the operation. If compression has been - * enabled but the value does not reach the threshold then this will be false. - * - * @param opName - * @param compressionEnabled + /** + * Record success while specifying if compression has been enabled for + * the operation. Note that this means that either the value was + * compressed or decompressed during the operation. If compression has been + * enabled but the value does not reach the threshold then this will be false. + * + * @param opName + * @param compressionEnabled */ - void recordSuccess(String opName, boolean compressionEnabled); + void recordSuccess(String opName, boolean compressionEnabled); - /** - * Record failure for the operation - * @param opName - * @param reason - */ - void recordFailure(String opName, String reason); + /** + * Record failure for the operation + * + * @param opName + * @param reason + */ + void recordFailure(String opName, String reason); - void recordFailure(String opName, boolean compressionEnabled, String reason); + void recordFailure(String opName, boolean compressionEnabled, String reason); } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/OperationResult.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/OperationResult.java index d14e17a1..4d6459b9 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/OperationResult.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/OperationResult.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,16 +20,16 @@ /** * Interface representing the result of executing an {@link Operation} - * @author poberai * * @param + * @author poberai */ public interface OperationResult { /** * @return Get the host on which the operation was performed */ public Host getNode(); - + /** * @param node */ @@ -47,10 +47,9 @@ public interface OperationResult { public long getLatency(); /** + * @param units * @return Return the length of time to perform the operation to the remote service. Does not include * connection pool overhead. - * - * @param units */ public long getLatency(TimeUnit units); @@ -62,37 +61,40 @@ public interface OperationResult { /** * Set the number of attempts executing this connection + * * @param count */ public OperationResult setAttemptsCount(int count); - + /** * Set latency after executing the operation. This method is useful to apps that do async operations * and can proxy back latency stats to Dyno once they receive their result via the future. - * + * * @param duration * @param unit */ public OperationResult setLatency(long duration, TimeUnit unit); - + /** * Method that returns any other metadata that is associated with this OperationResult. - * - * @return Map + * + * @return Map */ public Map getMetadata(); - + /** - * Add metadata to the OperationResult. Can be used within different layers of Dyno to add metadata about each layer. + * Add metadata to the OperationResult. Can be used within different layers of Dyno to add metadata about each layer. * Very useful for providing insight into the operation when debugging. + * * @param key * @param value */ public OperationResult addMetadata(String key, String value); /** - * Add metadata to the OperationResult. Can be used within different layers of Dyno to add metadata about each layer. + * Add metadata to the OperationResult. Can be used within different layers of Dyno to add metadata about each layer. * Very useful for providing insight into the operation when debugging. + * * @param map */ public OperationResult addMetadata(Map map); diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/RetryPolicy.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/RetryPolicy.java index d6ca9b21..f5e19321 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/RetryPolicy.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/RetryPolicy.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,7 +19,6 @@ * Interface for retry policies when executing an {@link Operation}. * * @author poberai, jcacciatore - * */ public interface RetryPolicy { /** @@ -39,7 +38,7 @@ public interface RetryPolicy { /** * Ask the policy if a retry is allowed. Note that this will return false if {@link #success()} has been called. - * + * * @return boolean */ boolean allowRetry(); @@ -50,15 +49,15 @@ public interface RetryPolicy { * @return boolean */ boolean allowCrossZoneFallback(); - + /** * Return the number of attempts since {@link #begin()} was called - * + * * @return int */ int getAttemptCount(); - + public static interface RetryPolicyFactory { - public RetryPolicy getRetryPolicy(); + public RetryPolicy getRetryPolicy(); } } \ No newline at end of file diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/TokenMapSupplier.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/TokenMapSupplier.java index fa9f9e92..2318da81 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/TokenMapSupplier.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/TokenMapSupplier.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,9 +23,8 @@ /** * Interface for supplying the list of {@link HostToken} that represent the * dynomite server topology - * - * @author poberai * + * @author poberai */ public interface TokenMapSupplier { @@ -35,7 +34,6 @@ public interface TokenMapSupplier { public List getTokens(Set activeHosts); /** - * * @param host * @return */ diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/TokenPoolTopology.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/TokenPoolTopology.java index 7cad37db..745d320d 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/TokenPoolTopology.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/TokenPoolTopology.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,123 +24,123 @@ import java.util.logging.Logger; public class TokenPoolTopology { - private static final org.slf4j.Logger Logger = LoggerFactory.getLogger(TokenPoolTopology.class); - - private final ConcurrentHashMap> map = new ConcurrentHashMap>(); - private final ConcurrentHashMap> rackTokenHostMap = new ConcurrentHashMap>(); - private final int replicationFactor; - - public TokenPoolTopology (int replicationFactor) { - this.replicationFactor = replicationFactor; - } - - public void addToken(String rack, Long token, HostConnectionPool hostPool) { - - List list = map.get(rack); - if (list == null) { - list = new ArrayList(); - map.put(rack, list); - } - - list.add(new TokenStatus(token, hostPool)); - } - - public void addHostToken(String rack, Long token, Host host) { - Logger.info("Adding Host to Topology" + host); - Map tokenHostMap = rackTokenHostMap.get(rack); - if (tokenHostMap == null) { - tokenHostMap = new HashMap<>(); - rackTokenHostMap.put(rack, tokenHostMap); - } - tokenHostMap.put(token, host); - } - - public void removeHost(String rack, Long token, Host host) { - Logger.info("Removing Host from Topology" + host); - - Map tokenHostMap = rackTokenHostMap.get(rack); - if (tokenHostMap == null) { - return; - } - tokenHostMap.put(token, null); - } - - public ConcurrentHashMap> getAllTokens() { - return map; - } - - public int getReplicationFactor() { - return replicationFactor; - } - - public String getRandomRack() { - List racks = new ArrayList(rackTokenHostMap.keySet()); - Collections.shuffle(racks); - return racks.get(0); - } - - public List getTokensForRack(String rack) { - if (rack != null && map.containsKey(rack)) { - return map.get(rack); - } - - return null; - } - - public Map getTokenHostsForRack(String rack) { - if (rack != null && rackTokenHostMap.containsKey(rack)) { - return rackTokenHostMap.get(rack); - } - - return null; - } - - public String toString() { - - ArrayList keyList = new ArrayList(map.keySet()); - Collections.sort(keyList); - - StringBuilder sb = new StringBuilder(); - sb.append("TokenPoolTopology\n"); - - for (String key : keyList) { - sb.append("\nRack: " + key + "\n"); - List list = map.get(key); - Collections.sort(list); - for (TokenStatus token : list) { - sb.append(token.toString()).append("\n"); - } - } - - return sb.toString(); - } - - public static class TokenStatus implements Comparable { - - private Long token; - private HostConnectionPool hostPool; - - private TokenStatus(Long t, HostConnectionPool pool) { - token = t; - hostPool = pool; - } - - public Long getToken() { - return token; - } - - public HostConnectionPool getHostPool() { - return hostPool; - } - - @Override - public int compareTo(TokenStatus o) { - return this.token.compareTo(o.token); - } - - public String toString() { - return token + " ==> " + hostPool.toString(); - } - } - + private static final org.slf4j.Logger Logger = LoggerFactory.getLogger(TokenPoolTopology.class); + + private final ConcurrentHashMap> map = new ConcurrentHashMap>(); + private final ConcurrentHashMap> rackTokenHostMap = new ConcurrentHashMap>(); + private final int replicationFactor; + + public TokenPoolTopology(int replicationFactor) { + this.replicationFactor = replicationFactor; + } + + public void addToken(String rack, Long token, HostConnectionPool hostPool) { + + List list = map.get(rack); + if (list == null) { + list = new ArrayList(); + map.put(rack, list); + } + + list.add(new TokenStatus(token, hostPool)); + } + + public void addHostToken(String rack, Long token, Host host) { + Logger.info("Adding Host to Topology" + host); + Map tokenHostMap = rackTokenHostMap.get(rack); + if (tokenHostMap == null) { + tokenHostMap = new HashMap<>(); + rackTokenHostMap.put(rack, tokenHostMap); + } + tokenHostMap.put(token, host); + } + + public void removeHost(String rack, Long token, Host host) { + Logger.info("Removing Host from Topology" + host); + + Map tokenHostMap = rackTokenHostMap.get(rack); + if (tokenHostMap == null) { + return; + } + tokenHostMap.put(token, null); + } + + public ConcurrentHashMap> getAllTokens() { + return map; + } + + public int getReplicationFactor() { + return replicationFactor; + } + + public String getRandomRack() { + List racks = new ArrayList(rackTokenHostMap.keySet()); + Collections.shuffle(racks); + return racks.get(0); + } + + public List getTokensForRack(String rack) { + if (rack != null && map.containsKey(rack)) { + return map.get(rack); + } + + return null; + } + + public Map getTokenHostsForRack(String rack) { + if (rack != null && rackTokenHostMap.containsKey(rack)) { + return rackTokenHostMap.get(rack); + } + + return null; + } + + public String toString() { + + ArrayList keyList = new ArrayList(map.keySet()); + Collections.sort(keyList); + + StringBuilder sb = new StringBuilder(); + sb.append("TokenPoolTopology\n"); + + for (String key : keyList) { + sb.append("\nRack: " + key + "\n"); + List list = map.get(key); + Collections.sort(list); + for (TokenStatus token : list) { + sb.append(token.toString()).append("\n"); + } + } + + return sb.toString(); + } + + public static class TokenStatus implements Comparable { + + private Long token; + private HostConnectionPool hostPool; + + private TokenStatus(Long t, HostConnectionPool pool) { + token = t; + hostPool = pool; + } + + public Long getToken() { + return token; + } + + public HostConnectionPool getHostPool() { + return hostPool; + } + + @Override + public int compareTo(TokenStatus o) { + return this.token.compareTo(o.token); + } + + public String toString() { + return token + " ==> " + hostPool.toString(); + } + } + } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/BadRequestException.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/BadRequestException.java index c2b36919..f8704421 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/BadRequestException.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/BadRequestException.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,9 +17,9 @@ public class BadRequestException extends DynoException { - /** - * - */ - private static final long serialVersionUID = 6244389154130041929L; + /** + * + */ + private static final long serialVersionUID = 6244389154130041929L; } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/DynoConnectException.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/DynoConnectException.java index 020d6b18..45827b7e 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/DynoConnectException.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/DynoConnectException.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,10 +21,10 @@ public class DynoConnectException extends DynoException { - private static final long serialVersionUID = 5111292446354085002L; + private static final long serialVersionUID = 5111292446354085002L; + + private Host host = Host.NO_HOST; - private Host host = Host.NO_HOST; - private long latency = 0; private long latencyWithPool = 0; private int attemptCount = 0; @@ -75,14 +75,14 @@ public long getLatencyWithPool() { @Override public String getMessage() { return new StringBuilder() - .append(getClass().getSimpleName()) - .append(": [") - .append( "host=" ).append(host.toString()) - .append(", latency=" ).append(latency).append("(").append(latencyWithPool).append(")") - .append(", attempts=").append(attemptCount) - .append("]") - .append(super.getMessage()) - .toString(); + .append(getClass().getSimpleName()) + .append(": [") + .append("host=").append(host.toString()) + .append(", latency=").append(latency).append("(").append(latencyWithPool).append(")") + .append(", attempts=").append(attemptCount) + .append("]") + .append(super.getMessage()) + .toString(); } public String getOriginalMessage() { diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/DynoException.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/DynoException.java index a238ba7e..b766e970 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/DynoException.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/DynoException.java @@ -16,13 +16,13 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -32,34 +32,32 @@ package com.netflix.dyno.connectionpool.exception; - /** * Connection exception caused by an error in the connection pool or a transport * error related to the connection itself. Application errors are derived from * OperationException. - * + * * @author poberai - * */ public class DynoException extends RuntimeException { - private static final long serialVersionUID = 3757459937536486618L; + private static final long serialVersionUID = 3757459937536486618L; - public DynoException() { - super(); - } + public DynoException() { + super(); + } - public DynoException(String message, Throwable cause) { - super(message, cause); - } + public DynoException(String message, Throwable cause) { + super(message, cause); + } - public DynoException(String message) { - super(message); - } + public DynoException(String message) { + super(message); + } - public DynoException(Throwable cause) { - super(cause); - } + public DynoException(Throwable cause) { + super(cause); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/FatalConnectionException.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/FatalConnectionException.java index 60890396..92716b97 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/FatalConnectionException.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/FatalConnectionException.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,20 +17,20 @@ public class FatalConnectionException extends DynoConnectException { - /** - * - */ - private static final long serialVersionUID = 953422826144906928L; + /** + * + */ + private static final long serialVersionUID = 953422826144906928L; - public FatalConnectionException(String message) { - super(message); - } + public FatalConnectionException(String message) { + super(message); + } - public FatalConnectionException(Throwable t) { - super(t); - } + public FatalConnectionException(Throwable t) { + super(t); + } - public FatalConnectionException(String message, Throwable cause) { - super(message, cause); - } + public FatalConnectionException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/IsDeadConnectionException.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/IsDeadConnectionException.java index a4fa1ea2..7d5ff270 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/IsDeadConnectionException.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/IsDeadConnectionException.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/IsRetryableException.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/IsRetryableException.java index d02ee2ef..04bac92c 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/IsRetryableException.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/IsRetryableException.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/NoAvailableHostsException.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/NoAvailableHostsException.java index a5e4b2ad..b9894ef5 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/NoAvailableHostsException.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/NoAvailableHostsException.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,10 +18,10 @@ public class NoAvailableHostsException extends DynoConnectException { - private static final long serialVersionUID = -6345231310492496030L; + private static final long serialVersionUID = -6345231310492496030L; - public NoAvailableHostsException(String message) { - super(message); - } + public NoAvailableHostsException(String message) { + super(message); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/PoolExhaustedException.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/PoolExhaustedException.java index c1af2fae..063fdbd7 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/PoolExhaustedException.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/PoolExhaustedException.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,13 +24,13 @@ public class PoolExhaustedException extends DynoConnectException { private final HostConnectionPool hcp; - private static final long serialVersionUID = 9081993527008721028L; + private static final long serialVersionUID = 9081993527008721028L; - public PoolExhaustedException(HostConnectionPool hostConnectionPool, String message) { - super(message); + public PoolExhaustedException(HostConnectionPool hostConnectionPool, String message) { + super(message); this.hcp = hostConnectionPool; - } + } public PoolExhaustedException(HostConnectionPool hostConnectionPool, String message, Throwable cause) { super(message, cause); diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/PoolOfflineException.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/PoolOfflineException.java index 8f33d2dc..001eb47b 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/PoolOfflineException.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/PoolOfflineException.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,9 +22,9 @@ */ public class PoolOfflineException extends DynoConnectException { - private static final long serialVersionUID = -345340994112630363L; + private static final long serialVersionUID = -345340994112630363L; - public PoolOfflineException(Host host, String message) { - super(message); - } + public PoolOfflineException(Host host, String message) { + super(message); + } } \ No newline at end of file diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/PoolTimeoutException.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/PoolTimeoutException.java index e062755a..6976e7d1 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/PoolTimeoutException.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/PoolTimeoutException.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,7 +22,7 @@ */ public class PoolTimeoutException extends DynoConnectException implements IsRetryableException { - private static final long serialVersionUID = -8579946319118318717L; + private static final long serialVersionUID = -8579946319118318717L; public PoolTimeoutException(String message) { super(message); diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/ThrottledException.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/ThrottledException.java index e89e5026..6677798b 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/ThrottledException.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/ThrottledException.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,9 +18,9 @@ public class ThrottledException extends DynoConnectException implements IsRetryableException { - private static final long serialVersionUID = -9132799199614005261L; + private static final long serialVersionUID = -9132799199614005261L; - public ThrottledException(String message) { + public ThrottledException(String message) { super(message); } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/TimeoutException.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/TimeoutException.java index 4c50d981..6812d96a 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/TimeoutException.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/exception/TimeoutException.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,17 +18,17 @@ public class TimeoutException extends DynoConnectException implements IsRetryableException, IsDeadConnectionException { - private static final long serialVersionUID = 5025308550262085866L; + private static final long serialVersionUID = 5025308550262085866L; - public TimeoutException(String message) { - super(message); - } + public TimeoutException(String message) { + super(message); + } - public TimeoutException(Throwable t) { - super(t); - } + public TimeoutException(Throwable t) { + super(t); + } - public TimeoutException(String message, Throwable cause) { - super(message, cause); - } + public TimeoutException(String message, Throwable cause) { + super(message, cause); + } } \ No newline at end of file diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/ConnectionContextImpl.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/ConnectionContextImpl.java index 025e68b6..6ad8154f 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/ConnectionContextImpl.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/ConnectionContextImpl.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,30 +22,30 @@ public class ConnectionContextImpl implements ConnectionContext { - private final ConcurrentHashMap context = new ConcurrentHashMap(); - - @Override - public void setMetadata(String key, Object obj) { - context.put(key, obj); - } - - @Override - public Object getMetadata(String key) { - return context.get(key); - } - - @Override - public boolean hasMetadata(String key) { - return context.containsKey(key); - } - - @Override - public void reset() { - context.clear(); - } - - @Override - public Map getAll() { - return context; - } + private final ConcurrentHashMap context = new ConcurrentHashMap(); + + @Override + public void setMetadata(String key, Object obj) { + context.put(key, obj); + } + + @Override + public Object getMetadata(String key) { + return context.get(key); + } + + @Override + public boolean hasMetadata(String key) { + return context.containsKey(key); + } + + @Override + public void reset() { + context.clear(); + } + + @Override + public Map getAll() { + return context; + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/ConnectionPoolConfigurationImpl.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/ConnectionPoolConfigurationImpl.java index 57ade08b..7f81962e 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/ConnectionPoolConfigurationImpl.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/ConnectionPoolConfigurationImpl.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,53 +30,53 @@ import com.netflix.dyno.connectionpool.impl.utils.ConfigUtils; public class ConnectionPoolConfigurationImpl implements ConnectionPoolConfiguration { - - // DEFAULTS - private static final int DEFAULT_MAX_CONNS_PER_HOST = 3; - private static final int DEFAULT_MAX_TIMEOUT_WHEN_EXHAUSTED = 800; - private static final int DEFAULT_MAX_FAILOVER_COUNT = 3; - private static final int DEFAULT_CONNECT_TIMEOUT = 3000; - private static final int DEFAULT_SOCKET_TIMEOUT = 12000; - private static final int DEFAULT_POOL_SHUTDOWN_DELAY = 60000; - private static final int DEFAULT_PING_FREQ_SECONDS = 30; - private static final int DEFAULT_FLUSH_TIMINGS_FREQ_SECONDS = 300; - private static final boolean DEFAULT_LOCAL_RACK_AFFINITY = true; - private static final LoadBalancingStrategy DEFAULT_LB_STRATEGY = LoadBalancingStrategy.TokenAware; - private static final CompressionStrategy DEFAULT_COMPRESSION_STRATEGY = CompressionStrategy.NONE; + + // DEFAULTS + private static final int DEFAULT_MAX_CONNS_PER_HOST = 3; + private static final int DEFAULT_MAX_TIMEOUT_WHEN_EXHAUSTED = 800; + private static final int DEFAULT_MAX_FAILOVER_COUNT = 3; + private static final int DEFAULT_CONNECT_TIMEOUT = 3000; + private static final int DEFAULT_SOCKET_TIMEOUT = 12000; + private static final int DEFAULT_POOL_SHUTDOWN_DELAY = 60000; + private static final int DEFAULT_PING_FREQ_SECONDS = 30; + private static final int DEFAULT_FLUSH_TIMINGS_FREQ_SECONDS = 300; + private static final boolean DEFAULT_LOCAL_RACK_AFFINITY = true; + private static final LoadBalancingStrategy DEFAULT_LB_STRATEGY = LoadBalancingStrategy.TokenAware; + private static final CompressionStrategy DEFAULT_COMPRESSION_STRATEGY = CompressionStrategy.NONE; private static final String DEFAULT_CONFIG_PUBLISHER_ADDRESS = null; private static final boolean DEFAULT_FAIL_ON_STARTUP_IFNOHOSTS = true; private static final int DEFAULT_FAIL_ON_STARTUP_IFNOHOSTS_SECONDS = 60; private static final int DEFAULT_VALUE_COMPRESSION_THRESHOLD_BYTES = 5 * 1024; // By default, compression is OFF - private static final boolean DEFAULT_IS_DUAL_WRITE_ENABLED = false; + private static final boolean DEFAULT_IS_DUAL_WRITE_ENABLED = false; private static final int DEFAULT_DUAL_WRITE_PERCENTAGE = 0; private static final int DEFAULT_HEALTH_TRACKER_DELAY_MILLIS = 10 * 1000; private static final int DEFAULT_POOL_RECONNECT_WAIT_MILLIS = 5 * 1000; private HostSupplier hostSupplier; - private TokenMapSupplier tokenSupplier; - private HostConnectionPoolFactory hostConnectionPoolFactory; - private HashPartitioner hashPartitioner; - private String hashtag; - private final String name; - private int maxConnsPerHost = DEFAULT_MAX_CONNS_PER_HOST; - private int maxTimeoutWhenExhausted = DEFAULT_MAX_TIMEOUT_WHEN_EXHAUSTED; - private int maxFailoverCount = DEFAULT_MAX_FAILOVER_COUNT; - private int connectTimeout = DEFAULT_CONNECT_TIMEOUT; - private int socketTimeout = DEFAULT_SOCKET_TIMEOUT; - private int poolShutdownDelay = DEFAULT_POOL_SHUTDOWN_DELAY; - private int pingFrequencySeconds = DEFAULT_PING_FREQ_SECONDS; - private int flushTimingsFrequencySeconds = DEFAULT_FLUSH_TIMINGS_FREQ_SECONDS; - private boolean localZoneAffinity = DEFAULT_LOCAL_RACK_AFFINITY; - private LoadBalancingStrategy lbStrategy = DEFAULT_LB_STRATEGY; - private String localRack; - private String localDataCenter; + private TokenMapSupplier tokenSupplier; + private HostConnectionPoolFactory hostConnectionPoolFactory; + private HashPartitioner hashPartitioner; + private String hashtag; + private final String name; + private int maxConnsPerHost = DEFAULT_MAX_CONNS_PER_HOST; + private int maxTimeoutWhenExhausted = DEFAULT_MAX_TIMEOUT_WHEN_EXHAUSTED; + private int maxFailoverCount = DEFAULT_MAX_FAILOVER_COUNT; + private int connectTimeout = DEFAULT_CONNECT_TIMEOUT; + private int socketTimeout = DEFAULT_SOCKET_TIMEOUT; + private int poolShutdownDelay = DEFAULT_POOL_SHUTDOWN_DELAY; + private int pingFrequencySeconds = DEFAULT_PING_FREQ_SECONDS; + private int flushTimingsFrequencySeconds = DEFAULT_FLUSH_TIMINGS_FREQ_SECONDS; + private boolean localZoneAffinity = DEFAULT_LOCAL_RACK_AFFINITY; + private LoadBalancingStrategy lbStrategy = DEFAULT_LB_STRATEGY; + private String localRack; + private String localDataCenter; private boolean failOnStartupIfNoHosts = DEFAULT_FAIL_ON_STARTUP_IFNOHOSTS; private int failOnStarupIfNoHostsSeconds = DEFAULT_FAIL_ON_STARTUP_IFNOHOSTS_SECONDS; private CompressionStrategy compressionStrategy = DEFAULT_COMPRESSION_STRATEGY; - private int valueCompressionThreshold = DEFAULT_VALUE_COMPRESSION_THRESHOLD_BYTES; + private int valueCompressionThreshold = DEFAULT_VALUE_COMPRESSION_THRESHOLD_BYTES; - // Dual Write Settings - private boolean isDualWriteEnabled = DEFAULT_IS_DUAL_WRITE_ENABLED; + // Dual Write Settings + private boolean isDualWriteEnabled = DEFAULT_IS_DUAL_WRITE_ENABLED; private String dualWriteClusterName = null; private int dualWritePercentage = DEFAULT_DUAL_WRITE_PERCENTAGE; private int healthTrackerDelayMillis = DEFAULT_HEALTH_TRACKER_DELAY_MILLIS; @@ -85,29 +85,29 @@ public class ConnectionPoolConfigurationImpl implements ConnectionPoolConfigurat private RetryPolicyFactory retryFactory = new RetryPolicyFactory() { - @Override - public RetryPolicy getRetryPolicy() { - return new RunOnce(); - } - }; - - private ErrorMonitorFactory errorMonitorFactory = new SimpleErrorMonitorFactory(); + @Override + public RetryPolicy getRetryPolicy() { + return new RunOnce(); + } + }; + + private ErrorMonitorFactory errorMonitorFactory = new SimpleErrorMonitorFactory(); public ConnectionPoolConfigurationImpl(String name) { - this.name = name; - this.localRack = ConfigUtils.getLocalZone(); - this.localDataCenter = ConfigUtils.getDataCenter(); - } + this.name = name; + this.localRack = ConfigUtils.getLocalZone(); + this.localDataCenter = ConfigUtils.getDataCenter(); + } - /** - * Copy constructor used to construct a new instance of this config with mostly the same values as the given + /** + * Copy constructor used to construct a new instance of this config with mostly the same values as the given * config. * - * @param config + * @param config */ - public ConnectionPoolConfigurationImpl(ConnectionPoolConfigurationImpl config) { - this.name = config.getName() + "_shadow"; + public ConnectionPoolConfigurationImpl(ConnectionPoolConfigurationImpl config) { + this.name = config.getName() + "_shadow"; this.compressionStrategy = config.getCompressionStrategy(); this.valueCompressionThreshold = config.getValueCompressionThreshold(); @@ -125,7 +125,7 @@ public ConnectionPoolConfigurationImpl(ConnectionPoolConfigurationImpl config) { this.socketTimeout = config.getSocketTimeout(); this.errorMonitorFactory = config.getErrorMonitorFactory(); this.tokenSupplier = config.getTokenSupplier(); - this.hashPartitioner = config.getHashPartitioner(); + this.hashPartitioner = config.getHashPartitioner(); this.isDualWriteEnabled = config.isDualWriteEnabled(); this.dualWriteClusterName = config.getDualWriteClusterName(); this.dualWritePercentage = config.getDualWritePercentage(); @@ -133,63 +133,63 @@ public ConnectionPoolConfigurationImpl(ConnectionPoolConfigurationImpl config) { this.healthTrackerDelayMillis = config.getHealthTrackerDelayMillis(); this.poolReconnectWaitMillis = config.getPoolReconnectWaitMillis(); } - - @Override - public String getName() { - return name; - } - - - @Override - public int getMaxConnsPerHost() { - return maxConnsPerHost; - } - - @Override - public int getMaxTimeoutWhenExhausted() { - return maxTimeoutWhenExhausted; - } - - @Override - public int getMaxFailoverCount() { - return maxFailoverCount; - } - - - @Override - public int getConnectTimeout() { - return connectTimeout; - } - - @Override - public int getSocketTimeout() { - return socketTimeout; - } - - @Override - public RetryPolicyFactory getRetryPolicyFactory() { - return retryFactory; - } - - @Override - public boolean localZoneAffinity() { - return localZoneAffinity; - } - - @Override - public ErrorMonitorFactory getErrorMonitorFactory() { - return errorMonitorFactory; - } - - @Override - public LoadBalancingStrategy getLoadBalancingStrategy() { - return lbStrategy; - } - - @Override - public int getPingFrequencySeconds() { - return pingFrequencySeconds; - } + + @Override + public String getName() { + return name; + } + + + @Override + public int getMaxConnsPerHost() { + return maxConnsPerHost; + } + + @Override + public int getMaxTimeoutWhenExhausted() { + return maxTimeoutWhenExhausted; + } + + @Override + public int getMaxFailoverCount() { + return maxFailoverCount; + } + + + @Override + public int getConnectTimeout() { + return connectTimeout; + } + + @Override + public int getSocketTimeout() { + return socketTimeout; + } + + @Override + public RetryPolicyFactory getRetryPolicyFactory() { + return retryFactory; + } + + @Override + public boolean localZoneAffinity() { + return localZoneAffinity; + } + + @Override + public ErrorMonitorFactory getErrorMonitorFactory() { + return errorMonitorFactory; + } + + @Override + public LoadBalancingStrategy getLoadBalancingStrategy() { + return lbStrategy; + } + + @Override + public int getPingFrequencySeconds() { + return pingFrequencySeconds; + } @Override public String getLocalRack() { @@ -245,102 +245,102 @@ public int getDualWritePercentage() { return dualWritePercentage; } - @Override - public int getHealthTrackerDelayMillis() { - return healthTrackerDelayMillis; - } - - @Override - public int getPoolReconnectWaitMillis() { - return poolReconnectWaitMillis; - } - - @Override - public String toString() { - return "ConnectionPoolConfigurationImpl{" + - "name=" + name + - ", hostSupplier=" + hostSupplier + - ", tokenSupplier=" + tokenSupplier + - ", hostConnectionPoolFactory=" + hostConnectionPoolFactory + - ", name='" + name + '\'' + - ", maxConnsPerHost=" + maxConnsPerHost + - ", maxTimeoutWhenExhausted=" + maxTimeoutWhenExhausted + - ", maxFailoverCount=" + maxFailoverCount + - ", connectTimeout=" + connectTimeout + - ", socketTimeout=" + socketTimeout + - ", poolShutdownDelay=" + poolShutdownDelay + - ", pingFrequencySeconds=" + pingFrequencySeconds + - ", flushTimingsFrequencySeconds=" + flushTimingsFrequencySeconds + - ", localZoneAffinity=" + localZoneAffinity + - ", lbStrategy=" + lbStrategy + - ", hashPartitioner=" + hashPartitioner + - ", localRack='" + localRack + '\'' + - ", localDataCenter='" + localDataCenter + '\'' + - ", failOnStartupIfNoHosts=" + failOnStartupIfNoHosts + - ", failOnStarupIfNoHostsSeconds=" + failOnStarupIfNoHostsSeconds + - ", compressionStrategy=" + compressionStrategy + - ", valueCompressionThreshold=" + valueCompressionThreshold + - ", isDualWriteEnabled=" + isDualWriteEnabled + - ", dualWriteClusterName='" + dualWriteClusterName + '\'' + - ", dualWritePercentage=" + dualWritePercentage + - ", retryFactory=" + retryFactory + - ", errorMonitorFactory=" + errorMonitorFactory + - ", hashtag=" + hashtag + - ", healthTrackerDelayMillis=" + healthTrackerDelayMillis + - ", poolReconnectWaitMillis=" + poolReconnectWaitMillis + - '}'; - } - - // ALL SETTERS - public ConnectionPoolConfigurationImpl setMaxConnsPerHost(int maxConnsPerHost) { - this.maxConnsPerHost = maxConnsPerHost; - return this; - } - - public ConnectionPoolConfigurationImpl setMaxTimeoutWhenExhausted(int maxTimeoutWhenExhausted) { - this.maxTimeoutWhenExhausted = maxTimeoutWhenExhausted; - return this; - } - - public ConnectionPoolConfigurationImpl setMaxFailoverCount(int maxFailoverCount) { - this.maxFailoverCount = maxFailoverCount; - return this; - } - - public ConnectionPoolConfigurationImpl setConnectTimeout(int connectTimeout) { - this.connectTimeout = connectTimeout; - return this; - } - - public ConnectionPoolConfigurationImpl setSocketTimeout(int socketTimeout) { - this.socketTimeout = socketTimeout; - return this; - } - - public ConnectionPoolConfigurationImpl setLoadBalancingStrategy(LoadBalancingStrategy strategy) { - this.lbStrategy = strategy; - return this; - } - - public ConnectionPoolConfigurationImpl setRetryPolicyFactory(RetryPolicyFactory factory) { - this.retryFactory = factory; - return this; - } - - public ConnectionPoolConfigurationImpl setPoolShutdownDelay(int shutdownDelaySeconds) { - poolShutdownDelay = shutdownDelaySeconds; - return this; - } - - public ConnectionPoolConfigurationImpl setPingFrequencySeconds(int seconds) { - pingFrequencySeconds = seconds; - return this; - } - - public ConnectionPoolConfigurationImpl setLocalZoneAffinity(boolean condition) { - localZoneAffinity = condition; - return this; - } + @Override + public int getHealthTrackerDelayMillis() { + return healthTrackerDelayMillis; + } + + @Override + public int getPoolReconnectWaitMillis() { + return poolReconnectWaitMillis; + } + + @Override + public String toString() { + return "ConnectionPoolConfigurationImpl{" + + "name=" + name + + ", hostSupplier=" + hostSupplier + + ", tokenSupplier=" + tokenSupplier + + ", hostConnectionPoolFactory=" + hostConnectionPoolFactory + + ", name='" + name + '\'' + + ", maxConnsPerHost=" + maxConnsPerHost + + ", maxTimeoutWhenExhausted=" + maxTimeoutWhenExhausted + + ", maxFailoverCount=" + maxFailoverCount + + ", connectTimeout=" + connectTimeout + + ", socketTimeout=" + socketTimeout + + ", poolShutdownDelay=" + poolShutdownDelay + + ", pingFrequencySeconds=" + pingFrequencySeconds + + ", flushTimingsFrequencySeconds=" + flushTimingsFrequencySeconds + + ", localZoneAffinity=" + localZoneAffinity + + ", lbStrategy=" + lbStrategy + + ", hashPartitioner=" + hashPartitioner + + ", localRack='" + localRack + '\'' + + ", localDataCenter='" + localDataCenter + '\'' + + ", failOnStartupIfNoHosts=" + failOnStartupIfNoHosts + + ", failOnStarupIfNoHostsSeconds=" + failOnStarupIfNoHostsSeconds + + ", compressionStrategy=" + compressionStrategy + + ", valueCompressionThreshold=" + valueCompressionThreshold + + ", isDualWriteEnabled=" + isDualWriteEnabled + + ", dualWriteClusterName='" + dualWriteClusterName + '\'' + + ", dualWritePercentage=" + dualWritePercentage + + ", retryFactory=" + retryFactory + + ", errorMonitorFactory=" + errorMonitorFactory + + ", hashtag=" + hashtag + + ", healthTrackerDelayMillis=" + healthTrackerDelayMillis + + ", poolReconnectWaitMillis=" + poolReconnectWaitMillis + + '}'; + } + + // ALL SETTERS + public ConnectionPoolConfigurationImpl setMaxConnsPerHost(int maxConnsPerHost) { + this.maxConnsPerHost = maxConnsPerHost; + return this; + } + + public ConnectionPoolConfigurationImpl setMaxTimeoutWhenExhausted(int maxTimeoutWhenExhausted) { + this.maxTimeoutWhenExhausted = maxTimeoutWhenExhausted; + return this; + } + + public ConnectionPoolConfigurationImpl setMaxFailoverCount(int maxFailoverCount) { + this.maxFailoverCount = maxFailoverCount; + return this; + } + + public ConnectionPoolConfigurationImpl setConnectTimeout(int connectTimeout) { + this.connectTimeout = connectTimeout; + return this; + } + + public ConnectionPoolConfigurationImpl setSocketTimeout(int socketTimeout) { + this.socketTimeout = socketTimeout; + return this; + } + + public ConnectionPoolConfigurationImpl setLoadBalancingStrategy(LoadBalancingStrategy strategy) { + this.lbStrategy = strategy; + return this; + } + + public ConnectionPoolConfigurationImpl setRetryPolicyFactory(RetryPolicyFactory factory) { + this.retryFactory = factory; + return this; + } + + public ConnectionPoolConfigurationImpl setPoolShutdownDelay(int shutdownDelaySeconds) { + poolShutdownDelay = shutdownDelaySeconds; + return this; + } + + public ConnectionPoolConfigurationImpl setPingFrequencySeconds(int seconds) { + pingFrequencySeconds = seconds; + return this; + } + + public ConnectionPoolConfigurationImpl setLocalZoneAffinity(boolean condition) { + localZoneAffinity = condition; + return this; + } public ConnectionPoolConfigurationImpl setFailOnStartupIfNoHosts(boolean condition) { this.failOnStartupIfNoHosts = condition; @@ -357,52 +357,52 @@ public ConnectionPoolConfigurationImpl setCompressionStrategy(CompressionStrateg return this; } - public ConnectionPoolConfigurationImpl setCompressionThreshold(int thresholdInBytes) { - this.valueCompressionThreshold = thresholdInBytes; - return this; - } - - - public HostSupplier getHostSupplier() { - return hostSupplier; - } - - public ConnectionPoolConfigurationImpl withHostSupplier(HostSupplier hSupplier) { - hostSupplier = hSupplier; - return this; - } - - public TokenMapSupplier getTokenSupplier() { - return tokenSupplier; - } - - public String getHashtag() { - return hashtag; - } - - public ConnectionPoolConfigurationImpl withTokenSupplier(TokenMapSupplier tSupplier) { - tokenSupplier = tSupplier; - return this; - } - - public HashPartitioner getHashPartitioner() { - return hashPartitioner; - } - - public ConnectionPoolConfigurationImpl withHashPartitioner(HashPartitioner hPartitioner) { - hashPartitioner = hPartitioner; - return this; - } - - public ConnectionPoolConfigurationImpl withHashtag(String htag) { - hashtag = htag; - return this; - } + public ConnectionPoolConfigurationImpl setCompressionThreshold(int thresholdInBytes) { + this.valueCompressionThreshold = thresholdInBytes; + return this; + } + + + public HostSupplier getHostSupplier() { + return hostSupplier; + } + + public ConnectionPoolConfigurationImpl withHostSupplier(HostSupplier hSupplier) { + hostSupplier = hSupplier; + return this; + } - public ConnectionPoolConfigurationImpl withErrorMonitorFactory(ErrorMonitorFactory factory) { - errorMonitorFactory = factory; - return this; - } + public TokenMapSupplier getTokenSupplier() { + return tokenSupplier; + } + + public String getHashtag() { + return hashtag; + } + + public ConnectionPoolConfigurationImpl withTokenSupplier(TokenMapSupplier tSupplier) { + tokenSupplier = tSupplier; + return this; + } + + public HashPartitioner getHashPartitioner() { + return hashPartitioner; + } + + public ConnectionPoolConfigurationImpl withHashPartitioner(HashPartitioner hPartitioner) { + hashPartitioner = hPartitioner; + return this; + } + + public ConnectionPoolConfigurationImpl withHashtag(String htag) { + hashtag = htag; + return this; + } + + public ConnectionPoolConfigurationImpl withErrorMonitorFactory(ErrorMonitorFactory factory) { + errorMonitorFactory = factory; + return this; + } public ConnectionPoolConfigurationImpl withHostConnectionPoolFactory(HostConnectionPoolFactory factory) { hostConnectionPoolFactory = factory; @@ -421,68 +421,68 @@ public ConnectionPoolConfigurationImpl withPoolReconnectWaitMillis(int millis) { public static class ErrorRateMonitorConfigImpl implements ErrorRateMonitorConfig { - int window = 20; - int checkFrequency = 1; - int suppressWindow = 90; - - private List thresholds = new ArrayList(); - - public ErrorRateMonitorConfigImpl() { - this.addThreshold(10, 10, 80); - } - - public ErrorRateMonitorConfigImpl(int w, int f, int s) { - this.window = w; - this.checkFrequency = f; - this.suppressWindow = s; - } - - @Override - public int getWindowSizeSeconds() { - return window; - } - - @Override - public int getCheckFrequencySeconds() { - return checkFrequency; - } - - @Override - public int getCheckSuppressWindowSeconds() { - return suppressWindow; - } - - @Override - public List getThresholds() { - return thresholds; - } - - public void addThreshold(final int bucketThreshold, final int bucketWindow, final int bucketCoverage) { - thresholds.add(new ErrorThreshold() { - - @Override - public int getThresholdPerSecond() { - return bucketThreshold; - } - - @Override - public int getWindowSeconds() { - return bucketWindow; - } - - @Override - public int getWindowCoveragePercentage() { - return bucketCoverage; - } - - }); - } - } + int window = 20; + int checkFrequency = 1; + int suppressWindow = 90; + + private List thresholds = new ArrayList(); + + public ErrorRateMonitorConfigImpl() { + this.addThreshold(10, 10, 80); + } + + public ErrorRateMonitorConfigImpl(int w, int f, int s) { + this.window = w; + this.checkFrequency = f; + this.suppressWindow = s; + } + + @Override + public int getWindowSizeSeconds() { + return window; + } + + @Override + public int getCheckFrequencySeconds() { + return checkFrequency; + } + + @Override + public int getCheckSuppressWindowSeconds() { + return suppressWindow; + } + + @Override + public List getThresholds() { + return thresholds; + } + + public void addThreshold(final int bucketThreshold, final int bucketWindow, final int bucketCoverage) { + thresholds.add(new ErrorThreshold() { + + @Override + public int getThresholdPerSecond() { + return bucketThreshold; + } + + @Override + public int getWindowSeconds() { + return bucketWindow; + } + + @Override + public int getWindowCoveragePercentage() { + return bucketCoverage; + } + + }); + } + } public ConnectionPoolConfigurationImpl setLocalRack(String rack) { - this.localRack = rack; - return this; - } + this.localRack = rack; + return this; + } public ConnectionPoolConfigurationImpl setLocalDataCenter(String dc) { this.localDataCenter = dc; diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/ConnectionPoolImpl.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/ConnectionPoolImpl.java index 0457da5f..b804bc87 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/ConnectionPoolImpl.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/ConnectionPoolImpl.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -44,36 +44,34 @@ * Main implementation class for {@link ConnectionPool} The pool deals with a * bunch of other components and brings together all the functionality for Dyno. * Hence this is where all the action happens. - * + *

* Here are the top salient features of this class. - * + *

* 1. Manages a collection of {@link HostConnectionPool}s for all the * {@link Host}s that it receives from the {@link HostSupplier} - * + *

* 2. Manages adding and removing hosts as dictated by the HostSupplier. - * + *

* 3. Enables execution of {@link Operation} using a {@link Connection} borrowed * from the {@link HostConnectionPool}s - * + *

* 4. Employs a {@link HostSelectionStrategy} (basically Round Robin or Token * Aware) when executing operations - * + *

* 5. Uses a health check monitor for tracking error rates from the execution of * operations. The health check monitor can then decide to recycle a given * HostConnectionPool, and execute requests using fallback HostConnectionPools * for remote DCs. - * + *

* 6. Uses {@link RetryPolicy} when executing operations for better resilience * against transient failures. - * + * + * @param + * @author poberai * @see {@link HostSupplier} {@link Host} {@link HostSelectionStrategy} * @see {@link Connection} {@link ConnectionFactory} - * {@link ConnectionPoolConfiguration} {@link ConnectionPoolMonitor} + * {@link ConnectionPoolConfiguration} {@link ConnectionPoolMonitor} * @see {@link ConnectionPoolHealthTracker} - * - * @author poberai - * - * @param */ public class ConnectionPoolImpl implements ConnectionPool, TopologyView { @@ -100,12 +98,12 @@ public class ConnectionPoolImpl implements ConnectionPool, TopologyView private Type poolType; public ConnectionPoolImpl(ConnectionFactory cFactory, ConnectionPoolConfiguration cpConfig, - ConnectionPoolMonitor cpMon) { + ConnectionPoolMonitor cpMon) { this(cFactory, cpConfig, cpMon, Type.Sync); } public ConnectionPoolImpl(ConnectionFactory cFactory, ConnectionPoolConfiguration cpConfig, - ConnectionPoolMonitor cpMon, Type type) { + ConnectionPoolMonitor cpMon, Type type) { this.connFactory = cFactory; this.cpConfiguration = cpConfig; this.cpMonitor = cpMon; @@ -114,14 +112,14 @@ public ConnectionPoolImpl(ConnectionFactory cFactory, ConnectionPoolConfigur this.cpHealthTracker = new ConnectionPoolHealthTracker(cpConfiguration, connPoolThreadPool); switch (type) { - case Sync: - hostConnPoolFactory = new SyncHostConnectionPoolFactory(); - break; - case Async: - hostConnPoolFactory = new AsyncHostConnectionPoolFactory(); - break; - default: - throw new RuntimeException("unknown type"); + case Sync: + hostConnPoolFactory = new SyncHostConnectionPoolFactory(); + break; + case Async: + hostConnPoolFactory = new AsyncHostConnectionPoolFactory(); + break; + default: + throw new RuntimeException("unknown type"); } this.hostsUpdater = new HostsUpdater(cpConfiguration.getHostSupplier(), cpConfiguration.getTokenSupplier()); @@ -152,566 +150,566 @@ public boolean addHost(Host host) { public boolean addHost(Host host, boolean refreshLoadBalancer) { - //host.setPort(cpConfiguration.getPort()); + //host.setPort(cpConfiguration.getPort()); - HostConnectionPool connPool = cpMap.get(host); + HostConnectionPool connPool = cpMap.get(host); - if (connPool != null) { - if (Logger.isDebugEnabled()) { - Logger.debug("HostConnectionPool already exists for host: " + host + ", ignoring addHost"); - } - return false; - } + if (connPool != null) { + if (Logger.isDebugEnabled()) { + Logger.debug("HostConnectionPool already exists for host: " + host + ", ignoring addHost"); + } + return false; + } - final HostConnectionPool hostPool = hostConnPoolFactory.createHostConnectionPool(host, this); + final HostConnectionPool hostPool = hostConnPoolFactory.createHostConnectionPool(host, this); - HostConnectionPool prevPool = cpMap.putIfAbsent(host, hostPool); - if (prevPool == null) { - // This is the first time we are adding this pool. - Logger.info("Adding host connection pool for host: " + host); + HostConnectionPool prevPool = cpMap.putIfAbsent(host, hostPool); + if (prevPool == null) { + // This is the first time we are adding this pool. + Logger.info("Adding host connection pool for host: " + host); - try { - int primed = hostPool.primeConnections(); - Logger.info("Successfully primed " + primed + " of " + cpConfiguration.getMaxConnsPerHost() + " to " - + host); + try { + int primed = hostPool.primeConnections(); + Logger.info("Successfully primed " + primed + " of " + cpConfiguration.getMaxConnsPerHost() + " to " + + host); - if (hostPool.isActive()) { - if (refreshLoadBalancer) { - selectionStrategy.addHost(host, hostPool); - } + if (hostPool.isActive()) { + if (refreshLoadBalancer) { + selectionStrategy.addHost(host, hostPool); + } - cpHealthTracker.initializePingHealthchecksForPool(hostPool); + cpHealthTracker.initializePingHealthchecksForPool(hostPool); - cpMonitor.hostAdded(host, hostPool); + cpMonitor.hostAdded(host, hostPool); - } else { - Logger.info( - "Failed to prime enough connections to host " + host + " for it take traffic; will retry"); - cpMap.remove(host); - } + } else { + Logger.info( + "Failed to prime enough connections to host " + host + " for it take traffic; will retry"); + cpMap.remove(host); + } - return primed > 0; - } catch (DynoException e) { - Logger.error("Failed to init host pool for host: " + host, e); - cpMap.remove(host); - return false; - } - } else { - return false; - } + return primed > 0; + } catch (DynoException e) { + Logger.error("Failed to init host pool for host: " + host, e); + cpMap.remove(host); + return false; + } + } else { + return false; + } } @Override public boolean removeHost(Host host) { - Logger.info(String.format("Removing host %s from selectionStrategy, cpHealthTracker, cpMonitor", - host.getHostAddress())); - // Since there are multiple data structures of host, token, connection pool etc, call removehost even - // if it is not found in the cpMap - selectionStrategy.removeHost(host); - cpHealthTracker.removeHost(host); - cpMonitor.hostRemoved(host); - HostConnectionPool hostPool = cpMap.remove(host); - if (hostPool != null) { - hostPool.shutdown(); - Logger.info(String.format("Remove host: Successfully removed hostPool for host %s from connection pool", - host.getHostAddress())); - return true; - } else { - Logger.info(String.format("Remove host: Host pool for host %s NOT FOUND in the connection pool", host.getHostAddress())); - return false; - } + Logger.info(String.format("Removing host %s from selectionStrategy, cpHealthTracker, cpMonitor", + host.getHostAddress())); + // Since there are multiple data structures of host, token, connection pool etc, call removehost even + // if it is not found in the cpMap + selectionStrategy.removeHost(host); + cpHealthTracker.removeHost(host); + cpMonitor.hostRemoved(host); + HostConnectionPool hostPool = cpMap.remove(host); + if (hostPool != null) { + hostPool.shutdown(); + Logger.info(String.format("Remove host: Successfully removed hostPool for host %s from connection pool", + host.getHostAddress())); + return true; + } else { + Logger.info(String.format("Remove host: Host pool for host %s NOT FOUND in the connection pool", host.getHostAddress())); + return false; + } } @Override public boolean isHostUp(Host host) { - HostConnectionPool hostPool = cpMap.get(host); - return (hostPool != null) ? hostPool.isActive() : false; + HostConnectionPool hostPool = cpMap.get(host); + return (hostPool != null) ? hostPool.isActive() : false; } @Override public boolean hasHost(Host host) { - return cpMap.get(host) != null; + return cpMap.get(host) != null; } @Override public List> getActivePools() { - return new ArrayList>( - CollectionUtils.filter(getPools(), new Predicate>() { - - @Override - public boolean apply(HostConnectionPool hostPool) { - if (hostPool == null) { - return false; - } - return hostPool.isActive(); - } - })); + return new ArrayList>( + CollectionUtils.filter(getPools(), new Predicate>() { + + @Override + public boolean apply(HostConnectionPool hostPool) { + if (hostPool == null) { + return false; + } + return hostPool.isActive(); + } + })); } @Override public List> getPools() { - return new ArrayList>(cpMap.values()); + return new ArrayList>(cpMap.values()); } @Override public Future updateHosts(Collection hostsUp, Collection hostsDown) { - Logger.debug(String.format("Updating hosts: UP=%s, DOWN=%s", hostsUp, hostsDown)); - boolean condition = false; - if (hostsUp != null && !hostsUp.isEmpty()) { - for (Host hostUp : hostsUp) { - condition |= addHost(hostUp); - } - } - if (hostsDown != null && !hostsDown.isEmpty()) { - for (Host hostDown : hostsDown) { - condition |= removeHost(hostDown); - } - } - return getEmptyFutureTask(condition); + Logger.debug(String.format("Updating hosts: UP=%s, DOWN=%s", hostsUp, hostsDown)); + boolean condition = false; + if (hostsUp != null && !hostsUp.isEmpty()) { + for (Host hostUp : hostsUp) { + condition |= addHost(hostUp); + } + } + if (hostsDown != null && !hostsDown.isEmpty()) { + for (Host hostDown : hostsDown) { + condition |= removeHost(hostDown); + } + } + return getEmptyFutureTask(condition); } @Override public HostConnectionPool getHostPool(Host host) { - return cpMap.get(host); + return cpMap.get(host); } @Override public OperationResult executeWithFailover(Operation op) throws DynoException { - // Start recording the operation - long startTime = System.currentTimeMillis(); - - RetryPolicy retry = cpConfiguration.getRetryPolicyFactory().getRetryPolicy(); - retry.begin(); - - DynoException lastException = null; - - do { - Connection connection = null; - - try { - connection = selectionStrategy.getConnectionUsingRetryPolicy(op, - cpConfiguration.getMaxTimeoutWhenExhausted(), TimeUnit.MILLISECONDS, retry); - - connection.getContext().setMetadata("host", connection.getHost().getHostAddress()); - connection.getContext().setMetadata("port", connection.getHost().getPort()); - - OperationResult result = connection.execute(op); - - // Add context to the result from the successful execution - result.setNode(connection.getHost()).addMetadata(connection.getContext().getAll()); - - retry.success(); - cpMonitor.incOperationSuccess(connection.getHost(), System.currentTimeMillis() - startTime); - - return result; - - } catch (NoAvailableHostsException e) { - cpMonitor.incOperationFailure(null, e); - - throw e; - } catch (PoolExhaustedException e) { - Logger.warn("Pool exhausted: " + e.getMessage()); - cpMonitor.incOperationFailure(null, e); - cpHealthTracker.trackConnectionError(e.getHostConnectionPool(), e); - } catch (DynoException e) { - - retry.failure(e); - lastException = e; - - if (connection != null) { - cpMonitor.incOperationFailure(connection.getHost(), e); - - if (retry.allowRetry()) { - cpMonitor.incFailover(connection.getHost(), e); - } - - // Track the connection health so that the pool can be - // purged at a later point - cpHealthTracker.trackConnectionError(connection.getParentConnectionPool(), lastException); - } else { - cpMonitor.incOperationFailure(null, e); - } - } catch (Throwable t) { - throw new RuntimeException(t); - } finally { - if (connection != null) { - if (connection.getLastException() != null - && connection.getLastException() instanceof FatalConnectionException) { - Logger.warn("Received FatalConnectionException; closing connection " - + connection.getContext().getAll() + " to host " - + connection.getParentConnectionPool().getHost()); - connection.getParentConnectionPool().recycleConnection(connection); - // note - don't increment connection closed metric here; - // it's done in closeConnection - } else { - connection.getContext().reset(); - connection.getParentConnectionPool().returnConnection(connection); - } - } - } - - } while (retry.allowRetry()); - - throw lastException; + // Start recording the operation + long startTime = System.currentTimeMillis(); + + RetryPolicy retry = cpConfiguration.getRetryPolicyFactory().getRetryPolicy(); + retry.begin(); + + DynoException lastException = null; + + do { + Connection connection = null; + + try { + connection = selectionStrategy.getConnectionUsingRetryPolicy(op, + cpConfiguration.getMaxTimeoutWhenExhausted(), TimeUnit.MILLISECONDS, retry); + + connection.getContext().setMetadata("host", connection.getHost().getHostAddress()); + connection.getContext().setMetadata("port", connection.getHost().getPort()); + + OperationResult result = connection.execute(op); + + // Add context to the result from the successful execution + result.setNode(connection.getHost()).addMetadata(connection.getContext().getAll()); + + retry.success(); + cpMonitor.incOperationSuccess(connection.getHost(), System.currentTimeMillis() - startTime); + + return result; + + } catch (NoAvailableHostsException e) { + cpMonitor.incOperationFailure(null, e); + + throw e; + } catch (PoolExhaustedException e) { + Logger.warn("Pool exhausted: " + e.getMessage()); + cpMonitor.incOperationFailure(null, e); + cpHealthTracker.trackConnectionError(e.getHostConnectionPool(), e); + } catch (DynoException e) { + + retry.failure(e); + lastException = e; + + if (connection != null) { + cpMonitor.incOperationFailure(connection.getHost(), e); + + if (retry.allowRetry()) { + cpMonitor.incFailover(connection.getHost(), e); + } + + // Track the connection health so that the pool can be + // purged at a later point + cpHealthTracker.trackConnectionError(connection.getParentConnectionPool(), lastException); + } else { + cpMonitor.incOperationFailure(null, e); + } + } catch (Throwable t) { + throw new RuntimeException(t); + } finally { + if (connection != null) { + if (connection.getLastException() != null + && connection.getLastException() instanceof FatalConnectionException) { + Logger.warn("Received FatalConnectionException; closing connection " + + connection.getContext().getAll() + " to host " + + connection.getParentConnectionPool().getHost()); + connection.getParentConnectionPool().recycleConnection(connection); + // note - don't increment connection closed metric here; + // it's done in closeConnection + } else { + connection.getContext().reset(); + connection.getParentConnectionPool().returnConnection(connection); + } + } + } + + } while (retry.allowRetry()); + + throw lastException; } @Override - public Collection> executeWithRing(TokenRackMapper tokenRackMapper, Operation op) throws DynoException { + public Collection> executeWithRing(TokenRackMapper tokenRackMapper, Operation op) throws DynoException { - // Start recording the operation - long startTime = System.currentTimeMillis(); + // Start recording the operation + long startTime = System.currentTimeMillis(); - Collection> connections = selectionStrategy - .getConnectionsToRing(tokenRackMapper, cpConfiguration.getMaxTimeoutWhenExhausted(), TimeUnit.MILLISECONDS); + Collection> connections = selectionStrategy + .getConnectionsToRing(tokenRackMapper, cpConfiguration.getMaxTimeoutWhenExhausted(), TimeUnit.MILLISECONDS); - LinkedBlockingQueue> connQueue = new LinkedBlockingQueue>(); - connQueue.addAll(connections); + LinkedBlockingQueue> connQueue = new LinkedBlockingQueue>(); + connQueue.addAll(connections); - List> results = new ArrayList>(); + List> results = new ArrayList>(); - DynoException lastException = null; + DynoException lastException = null; - try { - while (!connQueue.isEmpty()) { + try { + while (!connQueue.isEmpty()) { - Connection connection = connQueue.poll(); + Connection connection = connQueue.poll(); - RetryPolicy retry = cpConfiguration.getRetryPolicyFactory().getRetryPolicy(); - retry.begin(); + RetryPolicy retry = cpConfiguration.getRetryPolicyFactory().getRetryPolicy(); + retry.begin(); - do { - try { - connection.getContext().setMetadata("host", connection.getHost().getHostAddress()); - OperationResult result = connection.execute(op); + do { + try { + connection.getContext().setMetadata("host", connection.getHost().getHostAddress()); + OperationResult result = connection.execute(op); - // Add context to the result from the successful - // execution - result.setNode(connection.getHost()).addMetadata(connection.getContext().getAll()); + // Add context to the result from the successful + // execution + result.setNode(connection.getHost()).addMetadata(connection.getContext().getAll()); - retry.success(); - cpMonitor.incOperationSuccess(connection.getHost(), System.currentTimeMillis() - startTime); + retry.success(); + cpMonitor.incOperationSuccess(connection.getHost(), System.currentTimeMillis() - startTime); - results.add(result); + results.add(result); - } catch (NoAvailableHostsException e) { - cpMonitor.incOperationFailure(null, e); + } catch (NoAvailableHostsException e) { + cpMonitor.incOperationFailure(null, e); - throw e; - } catch (DynoException e) { + throw e; + } catch (DynoException e) { - retry.failure(e); - lastException = e; + retry.failure(e); + lastException = e; - cpMonitor.incOperationFailure(connection != null ? connection.getHost() : null, e); + cpMonitor.incOperationFailure(connection != null ? connection.getHost() : null, e); - // Track the connection health so that the pool can be - // purged at a later point - if (connection != null) { - cpHealthTracker.trackConnectionError(connection.getParentConnectionPool(), lastException); - } + // Track the connection health so that the pool can be + // purged at a later point + if (connection != null) { + cpHealthTracker.trackConnectionError(connection.getParentConnectionPool(), lastException); + } - } catch (Throwable t) { - throw new RuntimeException(t); - } finally { - connection.getContext().reset(); - connection.getParentConnectionPool().returnConnection(connection); - } + } catch (Throwable t) { + throw new RuntimeException(t); + } finally { + connection.getContext().reset(); + connection.getParentConnectionPool().returnConnection(connection); + } - } while (retry.allowRetry()); - } + } while (retry.allowRetry()); + } - // we fail the entire operation on a partial failure. hence need to - // clean up the rest of the pending connections - } finally { - List> remainingConns = new ArrayList>(); - connQueue.drainTo(remainingConns); - for (Connection connectionToClose : remainingConns) { - try { - connectionToClose.getContext().reset(); - connectionToClose.getParentConnectionPool().returnConnection(connectionToClose); - } catch (Throwable t) { + // we fail the entire operation on a partial failure. hence need to + // clean up the rest of the pending connections + } finally { + List> remainingConns = new ArrayList>(); + connQueue.drainTo(remainingConns); + for (Connection connectionToClose : remainingConns) { + try { + connectionToClose.getContext().reset(); + connectionToClose.getParentConnectionPool().returnConnection(connectionToClose); + } catch (Throwable t) { - } - } - } + } + } + } - if (lastException != null) { - throw lastException; - } else { - return results; - } - } + if (lastException != null) { + throw lastException; + } else { + return results; + } + } /** * Use with EXTREME CAUTION. Connection that is borrowed must be returned, * else we will have connection pool exhaustion - * + * * @param baseOperation * @return */ public Connection getConnectionForOperation(BaseOperation baseOperation) { - return selectionStrategy.getConnection(baseOperation, cpConfiguration.getMaxTimeoutWhenExhausted(), - TimeUnit.MILLISECONDS); + return selectionStrategy.getConnection(baseOperation, cpConfiguration.getMaxTimeoutWhenExhausted(), + TimeUnit.MILLISECONDS); } @Override public void shutdown() { - if (started.get()) { - for (Host host : cpMap.keySet()) { - removeHost(host); - } - cpHealthTracker.stop(); - hostsUpdater.stop(); - connPoolThreadPool.shutdownNow(); - deregisterMonitorConsoleMBean(); - } + if (started.get()) { + for (Host host : cpMap.keySet()) { + removeHost(host); + } + cpHealthTracker.stop(); + hostsUpdater.stop(); + connPoolThreadPool.shutdownNow(); + deregisterMonitorConsoleMBean(); + } } @Override public Future start() throws DynoException { - if (started.get()) { - return getEmptyFutureTask(false); - } - - HostSupplier hostSupplier = cpConfiguration.getHostSupplier(); - if (hostSupplier == null) { - throw new DynoException("Host supplier not configured!"); - } - - HostStatusTracker hostStatus = hostsUpdater.refreshHosts(); - cpMonitor.setHostCount(hostStatus.getHostCount()); - - Collection hostsUp = hostStatus.getActiveHosts(); - if (hostsUp == null || hostsUp.isEmpty()) { - throw new NoAvailableHostsException("No available hosts when starting connection pool"); - } - - final ExecutorService threadPool = Executors.newFixedThreadPool(Math.max(10, hostsUp.size())); - final List> futures = new ArrayList>(); - - for (final Host host : hostsUp) { - - // Add host connection pool, but don't init the load balancer yet - futures.add(threadPool.submit(new Callable() { - - @Override - public Void call() throws Exception { - addHost(host, false); - return null; - } - })); - } - - try { - for (Future future : futures) { - try { - future.get(); - } catch (InterruptedException e) { - // do nothing - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } - } finally { - threadPool.shutdownNow(); - } - - boolean success = started.compareAndSet(false, true); - if (success) { - idling.set(false); - idleThreadPool.shutdownNow(); - selectionStrategy = initSelectionStrategy(); - cpHealthTracker.start(); - - connPoolThreadPool.scheduleWithFixedDelay(new Runnable() { - - @Override - public void run() { - try { - HostStatusTracker hostStatus = hostsUpdater.refreshHosts(); - cpMonitor.setHostCount(hostStatus.getHostCount()); - Logger.debug(hostStatus.toString()); - updateHosts(hostStatus.getActiveHosts(), hostStatus.getInactiveHosts()); - } catch (Throwable throwable) { - Logger.error("Failed to update hosts cache", throwable); - } - } - - }, 15 * 1000, 30 * 1000, TimeUnit.MILLISECONDS); - - MonitorConsole.getInstance().registerConnectionPool(this); - registerMonitorConsoleMBean(MonitorConsole.getInstance()); - } - return getEmptyFutureTask(true); + if (started.get()) { + return getEmptyFutureTask(false); + } + + HostSupplier hostSupplier = cpConfiguration.getHostSupplier(); + if (hostSupplier == null) { + throw new DynoException("Host supplier not configured!"); + } + + HostStatusTracker hostStatus = hostsUpdater.refreshHosts(); + cpMonitor.setHostCount(hostStatus.getHostCount()); + + Collection hostsUp = hostStatus.getActiveHosts(); + if (hostsUp == null || hostsUp.isEmpty()) { + throw new NoAvailableHostsException("No available hosts when starting connection pool"); + } + + final ExecutorService threadPool = Executors.newFixedThreadPool(Math.max(10, hostsUp.size())); + final List> futures = new ArrayList>(); + + for (final Host host : hostsUp) { + + // Add host connection pool, but don't init the load balancer yet + futures.add(threadPool.submit(new Callable() { + + @Override + public Void call() throws Exception { + addHost(host, false); + return null; + } + })); + } + + try { + for (Future future : futures) { + try { + future.get(); + } catch (InterruptedException e) { + // do nothing + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + } finally { + threadPool.shutdownNow(); + } + + boolean success = started.compareAndSet(false, true); + if (success) { + idling.set(false); + idleThreadPool.shutdownNow(); + selectionStrategy = initSelectionStrategy(); + cpHealthTracker.start(); + + connPoolThreadPool.scheduleWithFixedDelay(new Runnable() { + + @Override + public void run() { + try { + HostStatusTracker hostStatus = hostsUpdater.refreshHosts(); + cpMonitor.setHostCount(hostStatus.getHostCount()); + Logger.debug(hostStatus.toString()); + updateHosts(hostStatus.getActiveHosts(), hostStatus.getInactiveHosts()); + } catch (Throwable throwable) { + Logger.error("Failed to update hosts cache", throwable); + } + } + + }, 15 * 1000, 30 * 1000, TimeUnit.MILLISECONDS); + + MonitorConsole.getInstance().registerConnectionPool(this); + registerMonitorConsoleMBean(MonitorConsole.getInstance()); + } + return getEmptyFutureTask(true); } @Override public void idle() { - if (this.started.get()) { - throw new IllegalStateException("Cannot move from started to idle once the pool has been started"); - } - - if (idling.compareAndSet(false, true)) { - idleThreadPool.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - if (!started.get()) { - try { - HostStatusTracker hostStatus = hostsUpdater.refreshHosts(); - cpMonitor.setHostCount(hostStatus.getHostCount()); - Collection hostsUp = hostStatus.getActiveHosts(); - if (hostsUp.size() > 0) { - Logger.debug("Found hosts while IDLING; starting the connection pool"); - start().get(); - } - } catch (NoAvailableHostsException nah) { - Logger.debug("No hosts found, will continue IDLING"); - } catch (DynoException de) { - Logger.warn("Attempt to start connection pool FAILED", de); - } catch (Exception e) { - Logger.warn("Attempt to start connection pool FAILED", e); - } - } - } - }, 30, 60, TimeUnit.SECONDS); - } + if (this.started.get()) { + throw new IllegalStateException("Cannot move from started to idle once the pool has been started"); + } + + if (idling.compareAndSet(false, true)) { + idleThreadPool.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + if (!started.get()) { + try { + HostStatusTracker hostStatus = hostsUpdater.refreshHosts(); + cpMonitor.setHostCount(hostStatus.getHostCount()); + Collection hostsUp = hostStatus.getActiveHosts(); + if (hostsUp.size() > 0) { + Logger.debug("Found hosts while IDLING; starting the connection pool"); + start().get(); + } + } catch (NoAvailableHostsException nah) { + Logger.debug("No hosts found, will continue IDLING"); + } catch (DynoException de) { + Logger.warn("Attempt to start connection pool FAILED", de); + } catch (Exception e) { + Logger.warn("Attempt to start connection pool FAILED", e); + } + } + } + }, 30, 60, TimeUnit.SECONDS); + } } @Override public ConnectionPoolConfiguration getConfiguration() { - return cpConfiguration; + return cpConfiguration; } private void registerMonitorConsoleMBean(MonitorConsoleMBean bean) { - final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); - try { - ObjectName objectName = new ObjectName(MonitorConsole.OBJECT_NAME); - if (!server.isRegistered(objectName)) { - server.registerMBean(bean, objectName); - Logger.info("registered mbean " + objectName); - } else { - Logger.info("mbean " + objectName + " has already been registered !"); - } - } catch (MalformedObjectNameException | InstanceAlreadyExistsException | MBeanRegistrationException - | NotCompliantMBeanException ex) { - Logger.error("Unable to register MonitorConsole mbean ", ex); - } + final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + try { + ObjectName objectName = new ObjectName(MonitorConsole.OBJECT_NAME); + if (!server.isRegistered(objectName)) { + server.registerMBean(bean, objectName); + Logger.info("registered mbean " + objectName); + } else { + Logger.info("mbean " + objectName + " has already been registered !"); + } + } catch (MalformedObjectNameException | InstanceAlreadyExistsException | MBeanRegistrationException + | NotCompliantMBeanException ex) { + Logger.error("Unable to register MonitorConsole mbean ", ex); + } } private void deregisterMonitorConsoleMBean() { - final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); - try { - ObjectName objectName = new ObjectName(MonitorConsole.OBJECT_NAME); - if (server.isRegistered(objectName)) { - server.unregisterMBean(objectName); - Logger.info("deregistered mbean " + objectName); - } - } catch (MalformedObjectNameException | MBeanRegistrationException | InstanceNotFoundException ex) { - Logger.error("Unable to deregister MonitorConsole mbean ", ex); - } + final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + try { + ObjectName objectName = new ObjectName(MonitorConsole.OBJECT_NAME); + if (server.isRegistered(objectName)) { + server.unregisterMBean(objectName); + Logger.info("deregistered mbean " + objectName); + } + } catch (MalformedObjectNameException | MBeanRegistrationException | InstanceNotFoundException ex) { + Logger.error("Unable to deregister MonitorConsole mbean ", ex); + } } private HostSelectionWithFallback initSelectionStrategy() { - if (cpConfiguration.getTokenSupplier() == null) { - throw new RuntimeException("TokenMapSupplier not configured"); - } - HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfiguration, cpMonitor); - selection.initWithHosts(cpMap); - return selection; + if (cpConfiguration.getTokenSupplier() == null) { + throw new RuntimeException("TokenMapSupplier not configured"); + } + HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfiguration, cpMonitor); + selection.initWithHosts(cpMap); + return selection; } private Future getEmptyFutureTask(final Boolean condition) { - FutureTask future = new FutureTask(new Callable() { - @Override - public Boolean call() throws Exception { - return condition; - } - }); + FutureTask future = new FutureTask(new Callable() { + @Override + public Boolean call() throws Exception { + return condition; + } + }); - future.run(); - return future; + future.run(); + return future; } private class SyncHostConnectionPoolFactory implements HostConnectionPoolFactory { - @Override - public HostConnectionPool createHostConnectionPool(Host host, ConnectionPoolImpl parentPoolImpl) { - return new HostConnectionPoolImpl(host, connFactory, cpConfiguration, cpMonitor); - } + @Override + public HostConnectionPool createHostConnectionPool(Host host, ConnectionPoolImpl parentPoolImpl) { + return new HostConnectionPoolImpl(host, connFactory, cpConfiguration, cpMonitor); + } } private class AsyncHostConnectionPoolFactory implements HostConnectionPoolFactory { - @Override - public HostConnectionPool createHostConnectionPool(Host host, ConnectionPoolImpl parentPoolImpl) { - return new SimpleAsyncConnectionPoolImpl(host, connFactory, cpConfiguration, cpMonitor); - } + @Override + public HostConnectionPool createHostConnectionPool(Host host, ConnectionPoolImpl parentPoolImpl) { + return new SimpleAsyncConnectionPoolImpl(host, connFactory, cpConfiguration, cpMonitor); + } } @Override public ListenableFuture> executeAsync(AsyncOperation op) throws DynoException { - DynoException lastException = null; - Connection connection = null; - long startTime = System.currentTimeMillis(); + DynoException lastException = null; + Connection connection = null; + long startTime = System.currentTimeMillis(); - try { - connection = selectionStrategy.getConnection(op, cpConfiguration.getMaxTimeoutWhenExhausted(), - TimeUnit.MILLISECONDS); + try { + connection = selectionStrategy.getConnection(op, cpConfiguration.getMaxTimeoutWhenExhausted(), + TimeUnit.MILLISECONDS); - ListenableFuture> futureResult = connection.executeAsync(op); + ListenableFuture> futureResult = connection.executeAsync(op); - cpMonitor.incOperationSuccess(connection.getHost(), System.currentTimeMillis() - startTime); + cpMonitor.incOperationSuccess(connection.getHost(), System.currentTimeMillis() - startTime); - return futureResult; + return futureResult; - } catch (NoAvailableHostsException e) { - cpMonitor.incOperationFailure(null, e); - throw e; - } catch (DynoException e) { + } catch (NoAvailableHostsException e) { + cpMonitor.incOperationFailure(null, e); + throw e; + } catch (DynoException e) { - lastException = e; - cpMonitor.incOperationFailure(connection != null ? connection.getHost() : null, e); + lastException = e; + cpMonitor.incOperationFailure(connection != null ? connection.getHost() : null, e); - // Track the connection health so that the pool can be purged at a - // later point - if (connection != null) { - cpHealthTracker.trackConnectionError(connection.getParentConnectionPool(), lastException); - } + // Track the connection health so that the pool can be purged at a + // later point + if (connection != null) { + cpHealthTracker.trackConnectionError(connection.getParentConnectionPool(), lastException); + } - } catch (Throwable t) { - t.printStackTrace(); - } finally { - if (connection != null) { - connection.getParentConnectionPool().returnConnection(connection); - } - } - return null; + } catch (Throwable t) { + t.printStackTrace(); + } finally { + if (connection != null) { + connection.getParentConnectionPool().returnConnection(connection); + } + } + return null; } public TokenPoolTopology getTopology() { - return selectionStrategy.getTokenPoolTopology(); + return selectionStrategy.getTokenPoolTopology(); } @Override public Map> getTopologySnapshot() { - return Collections.unmodifiableMap(selectionStrategy.getTokenPoolTopology().getAllTokens()); + return Collections.unmodifiableMap(selectionStrategy.getTokenPoolTopology().getAllTokens()); } @Override public Long getTokenForKey(String key) { - if (cpConfiguration - .getLoadBalancingStrategy() == ConnectionPoolConfiguration.LoadBalancingStrategy.TokenAware) { - return selectionStrategy.getTokenForKey(key); - } + if (cpConfiguration + .getLoadBalancingStrategy() == ConnectionPoolConfiguration.LoadBalancingStrategy.TokenAware) { + return selectionStrategy.getTokenForKey(key); + } - return null; + return null; } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/CountingConnectionPoolMonitor.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/CountingConnectionPoolMonitor.java index 95856498..94db8f39 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/CountingConnectionPoolMonitor.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/CountingConnectionPoolMonitor.java @@ -30,31 +30,31 @@ /** * Impl of {@link ConnectionPoolMonitor} using thread safe AtomicLongs - * @author poberai * + * @author poberai */ public class CountingConnectionPoolMonitor implements ConnectionPoolMonitor { // Tracking operation level metrics - private final AtomicLong operationFailureCount = new AtomicLong(); - private final AtomicLong operationSuccessCount = new AtomicLong(); + private final AtomicLong operationFailureCount = new AtomicLong(); + private final AtomicLong operationSuccessCount = new AtomicLong(); // Tracking connection counts - private final AtomicLong connectionCreateCount = new AtomicLong(); - private final AtomicLong connectionClosedCount = new AtomicLong(); + private final AtomicLong connectionCreateCount = new AtomicLong(); + private final AtomicLong connectionClosedCount = new AtomicLong(); private final AtomicLong connectionCreateFailureCount = new AtomicLong(); - private final AtomicLong connectionBorrowCount = new AtomicLong(); - private final AtomicLong connectionReturnCount = new AtomicLong(); + private final AtomicLong connectionBorrowCount = new AtomicLong(); + private final AtomicLong connectionReturnCount = new AtomicLong(); private final AtomicLong connectionRecycledCount = new AtomicLong(); private final AtomicLong operationFailoverCount = new AtomicLong(); - private final AtomicLong poolTimeoutCount = new AtomicLong(); - private final AtomicLong poolExhastedCount = new AtomicLong(); - private final AtomicLong operationTimeoutCount = new AtomicLong(); - private final AtomicLong socketTimeoutCount = new AtomicLong(); - private final AtomicLong noHostsCount = new AtomicLong(); - private final AtomicLong unknownErrorCount = new AtomicLong(); - private final AtomicLong badRequestCount = new AtomicLong(); + private final AtomicLong poolTimeoutCount = new AtomicLong(); + private final AtomicLong poolExhastedCount = new AtomicLong(); + private final AtomicLong operationTimeoutCount = new AtomicLong(); + private final AtomicLong socketTimeoutCount = new AtomicLong(); + private final AtomicLong noHostsCount = new AtomicLong(); + private final AtomicLong unknownErrorCount = new AtomicLong(); + private final AtomicLong badRequestCount = new AtomicLong(); private final EstimatedHistogram borrowedConnHistogram = new EstimatedHistogram(); @@ -63,7 +63,7 @@ public class CountingConnectionPoolMonitor implements ConnectionPoolMonitor { // where we can get out of sync is node replacement. In that case // the host will be removed from the HostSupplier but will still be // in our hostStats as 'down'. - private final AtomicLong hostSupplierCount = new AtomicLong(); + private final AtomicLong hostSupplierCount = new AtomicLong(); private final ConcurrentHashMap hostStats = new ConcurrentHashMap(); @@ -71,28 +71,28 @@ public CountingConnectionPoolMonitor() { } private void trackError(Host host, Exception reason) { - if (reason != null) { - if (reason instanceof PoolTimeoutException) { - this.poolTimeoutCount.incrementAndGet(); - } else if (reason instanceof PoolExhaustedException) { - this.poolExhastedCount.incrementAndGet(); - } else if (reason instanceof TimeoutException) { + if (reason != null) { + if (reason instanceof PoolTimeoutException) { + this.poolTimeoutCount.incrementAndGet(); + } else if (reason instanceof PoolExhaustedException) { + this.poolExhastedCount.incrementAndGet(); + } else if (reason instanceof TimeoutException) { this.socketTimeoutCount.incrementAndGet(); } else if (reason instanceof FatalConnectionException) { this.socketTimeoutCount.incrementAndGet(); - } else if (reason instanceof BadRequestException) { - this.badRequestCount.incrementAndGet(); - } else if (reason instanceof NoAvailableHostsException ) { - this.noHostsCount.incrementAndGet(); - } else { - this.unknownErrorCount.incrementAndGet(); - } - } else { - this.unknownErrorCount.incrementAndGet(); - } + } else if (reason instanceof BadRequestException) { + this.badRequestCount.incrementAndGet(); + } else if (reason instanceof NoAvailableHostsException) { + this.noHostsCount.incrementAndGet(); + } else { + this.unknownErrorCount.incrementAndGet(); + } + } else { + this.unknownErrorCount.incrementAndGet(); + } if (host != null) { - getOrCreateHostStats(host).opFailure.incrementAndGet(); + getOrCreateHostStats(host).opFailure.incrementAndGet(); } } @@ -156,7 +156,7 @@ public void incConnectionBorrowed(Host host, long delay) { this.connectionBorrowCount.incrementAndGet(); this.borrowedConnHistogram.add(delay); if (host == null || (host instanceof HostGroup)) { - return; + return; } getOrCreateHostStats(host).borrowed.incrementAndGet(); @@ -191,7 +191,7 @@ public void resetConnectionBorrowedLatStats() { public void incConnectionReturned(Host host) { this.connectionReturnCount.incrementAndGet(); if (host == null || (host instanceof HostGroup)) { - return; + return; } getOrCreateHostStats(host).returned.incrementAndGet(); } @@ -206,7 +206,9 @@ public void incConnectionRecycled(Host host) { } @Override - public long getConnectionRecycledCount() { return this.connectionRecycledCount.get(); } + public long getConnectionRecycledCount() { + return this.connectionRecycledCount.get(); + } public long getPoolExhaustedTimeoutCount() { return this.poolExhastedCount.get(); @@ -258,27 +260,27 @@ public String toString() { // Build the complete status string return new StringBuilder() .append("CountingConnectionPoolMonitor(") - .append("Connections[" ) - .append( "open=" ).append(getNumOpenConnections()) - .append(",busy=" ).append(getNumBusyConnections()) - .append(",create=" ).append(connectionCreateCount.get()) - .append(",close=" ).append(connectionClosedCount.get()) - .append(",createFailed=" ).append(connectionCreateFailureCount.get()) - .append(",borrow=" ).append(connectionBorrowCount.get()) - .append(",return=" ).append(connectionReturnCount.get()) - .append(",recycle=" ).append(connectionRecycledCount.get()) + .append("Connections[") + .append("open=").append(getNumOpenConnections()) + .append(",busy=").append(getNumBusyConnections()) + .append(",create=").append(connectionCreateCount.get()) + .append(",close=").append(connectionClosedCount.get()) + .append(",createFailed=").append(connectionCreateFailureCount.get()) + .append(",borrow=").append(connectionBorrowCount.get()) + .append(",return=").append(connectionReturnCount.get()) + .append(",recycle=").append(connectionRecycledCount.get()) .append("], Operations[") - .append( "success=" ).append(operationSuccessCount.get()) - .append(",failure=" ).append(operationFailureCount.get()) - .append(",optimeout=" ).append(operationTimeoutCount.get()) - .append(",timeout=" ).append(socketTimeoutCount.get()) - .append(",failover=" ).append(operationFailoverCount.get()) - .append(",nohosts=" ).append(noHostsCount.get()) - .append(",unknown=" ).append(unknownErrorCount.get()) - .append(",exhausted=" ).append(poolExhastedCount.get()) + .append("success=").append(operationSuccessCount.get()) + .append(",failure=").append(operationFailureCount.get()) + .append(",optimeout=").append(operationTimeoutCount.get()) + .append(",timeout=").append(socketTimeoutCount.get()) + .append(",failover=").append(operationFailoverCount.get()) + .append(",nohosts=").append(noHostsCount.get()) + .append(",unknown=").append(unknownErrorCount.get()) + .append(",exhausted=").append(poolExhastedCount.get()) .append("], Hosts[") - .append( "up=" ).append(getHostUpCount()) - .append(",down=" ).append(getHostDownCount()) + .append("up=").append(getHostUpCount()) + .append(",down=").append(getHostDownCount()) .append("])").toString(); } @@ -287,121 +289,121 @@ public long getHostCount() { return this.hostSupplierCount.get(); } - @Override - public long getHostUpCount() { - int count = 0; - for (HostConnectionStats stats : hostStats.values()) { - count = stats.isHostUp() ? count + 1 : count; - } - return count; - } + @Override + public long getHostUpCount() { + int count = 0; + for (HostConnectionStats stats : hostStats.values()) { + count = stats.isHostUp() ? count + 1 : count; + } + return count; + } @Override public long getHostDownCount() { return getHostCount() - getHostUpCount(); } - @Override - public void hostAdded(Host host, HostConnectionPool pool) { + @Override + public void hostAdded(Host host, HostConnectionPool pool) { getOrCreateHostStats(host).hostUp.set(true); - } - - @Override - public void hostRemoved(Host host) { - getOrCreateHostStats(host).hostUp.set(false); - } - - @Override - public void hostDown(Host host, Exception reason) { - getOrCreateHostStats(host).hostUp.set(false); - } - - @Override - public void hostUp(Host host, HostConnectionPool pool) { - getOrCreateHostStats(host).hostUp.set(true); - } - - @Override - public Map getHostStats() { - return hostStats; - } - - public HostConnectionStatsImpl getOrCreateHostStats(Host host) { - - HostConnectionStatsImpl hStats = (HostConnectionStatsImpl) hostStats.get(host); - if (hStats != null) { - return hStats; - } - hostStats.putIfAbsent(host, new HostConnectionStatsImpl(host)); - return (HostConnectionStatsImpl) hostStats.get(host); - } - - private class HostConnectionStatsImpl implements HostConnectionStats { - - private AtomicBoolean hostUp = new AtomicBoolean(true); - private final String name; - - private final AtomicLong opFailure = new AtomicLong(); - private final AtomicLong opSuccess = new AtomicLong(); - private final AtomicLong created = new AtomicLong(); - private final AtomicLong closed = new AtomicLong(); - private final AtomicLong createFailed = new AtomicLong(); - private final AtomicLong borrowed = new AtomicLong(); - private final AtomicLong returned = new AtomicLong(); - - private HostConnectionStatsImpl(Host host) { - this.name = host.getHostAddress(); - } - - @Override - public boolean isHostUp() { - return hostUp.get(); - } - - @Override - public long getConnectionsBorrowed() { - return borrowed.get(); - } - - @Override - public long getConnectionsReturned() { - return returned.get(); - } - - @Override - public long getConnectionsCreated() { - return created.get(); - } - - @Override - public long getConnectionsClosed() { - return closed.get(); - } - - @Override - public long getConnectionsCreateFailed() { - return createFailed.get(); - } - - @Override - public long getOperationSuccessCount() { - return opSuccess.get(); - } - - @Override - public long getOperationErrorCount() { - return opFailure.get(); - } - - public String toString() { - return name + " isUp: " + hostUp.get() + - ", borrowed: " + borrowed.get() + - ", returned: " + returned.get() + - ", created: " + created.get() + - ", closed: " + closed.get() + - ", createFailed: " + createFailed.get() + - ", success: " + opSuccess.get() + - ", error: " + opFailure.get(); - } - } + } + + @Override + public void hostRemoved(Host host) { + getOrCreateHostStats(host).hostUp.set(false); + } + + @Override + public void hostDown(Host host, Exception reason) { + getOrCreateHostStats(host).hostUp.set(false); + } + + @Override + public void hostUp(Host host, HostConnectionPool pool) { + getOrCreateHostStats(host).hostUp.set(true); + } + + @Override + public Map getHostStats() { + return hostStats; + } + + public HostConnectionStatsImpl getOrCreateHostStats(Host host) { + + HostConnectionStatsImpl hStats = (HostConnectionStatsImpl) hostStats.get(host); + if (hStats != null) { + return hStats; + } + hostStats.putIfAbsent(host, new HostConnectionStatsImpl(host)); + return (HostConnectionStatsImpl) hostStats.get(host); + } + + private class HostConnectionStatsImpl implements HostConnectionStats { + + private AtomicBoolean hostUp = new AtomicBoolean(true); + private final String name; + + private final AtomicLong opFailure = new AtomicLong(); + private final AtomicLong opSuccess = new AtomicLong(); + private final AtomicLong created = new AtomicLong(); + private final AtomicLong closed = new AtomicLong(); + private final AtomicLong createFailed = new AtomicLong(); + private final AtomicLong borrowed = new AtomicLong(); + private final AtomicLong returned = new AtomicLong(); + + private HostConnectionStatsImpl(Host host) { + this.name = host.getHostAddress(); + } + + @Override + public boolean isHostUp() { + return hostUp.get(); + } + + @Override + public long getConnectionsBorrowed() { + return borrowed.get(); + } + + @Override + public long getConnectionsReturned() { + return returned.get(); + } + + @Override + public long getConnectionsCreated() { + return created.get(); + } + + @Override + public long getConnectionsClosed() { + return closed.get(); + } + + @Override + public long getConnectionsCreateFailed() { + return createFailed.get(); + } + + @Override + public long getOperationSuccessCount() { + return opSuccess.get(); + } + + @Override + public long getOperationErrorCount() { + return opFailure.get(); + } + + public String toString() { + return name + " isUp: " + hostUp.get() + + ", borrowed: " + borrowed.get() + + ", returned: " + returned.get() + + ", created: " + created.get() + + ", closed: " + closed.get() + + ", createFailed: " + createFailed.get() + + ", success: " + opSuccess.get() + + ", error: " + opFailure.get(); + } + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/FutureOperationalResultImpl.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/FutureOperationalResultImpl.java index d4789d50..f7a61af1 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/FutureOperationalResultImpl.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/FutureOperationalResultImpl.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,86 +28,85 @@ import com.netflix.dyno.connectionpool.OperationResult; /** - * Impl for Future> that encapsulates an inner future. - * The class provides a functionality to record the time when the caller calls get() on the future. - * This helps record end-end timing for async operations. + * Impl for Future> that encapsulates an inner future. + * The class provides a functionality to record the time when the caller calls get() on the future. + * This helps record end-end timing for async operations. * Not that there is a caveat here that if the future is called at a later point in time, then yes the timing stats - * will appear to be bloated unnecessarily. What we really need here is a listenable future, where we should log the - * timing stats on the callback. - * - * @author poberai + * will appear to be bloated unnecessarily. What we really need here is a listenable future, where we should log the + * timing stats on the callback. * * @param + * @author poberai */ public class FutureOperationalResultImpl implements ListenableFuture> { - - private final Future future; - private final OperationResultImpl opResult; - private final long startTime; - private final AtomicBoolean timeRecorded = new AtomicBoolean(false); - - public FutureOperationalResultImpl(String opName, Future rFuture, long start, OperationMonitor opMonitor) { - this.future = rFuture; - this.opResult = new OperationResultImpl(opName, rFuture, opMonitor).attempts(1); - this.startTime = start; - } - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return future.cancel(mayInterruptIfRunning); - } + private final Future future; + private final OperationResultImpl opResult; + private final long startTime; + private final AtomicBoolean timeRecorded = new AtomicBoolean(false); + + public FutureOperationalResultImpl(String opName, Future rFuture, long start, OperationMonitor opMonitor) { + this.future = rFuture; + this.opResult = new OperationResultImpl(opName, rFuture, opMonitor).attempts(1); + this.startTime = start; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return future.cancel(mayInterruptIfRunning); + } + + @Override + public boolean isCancelled() { + return future.isCancelled(); + } + + @Override + public boolean isDone() { + return future.isDone(); + } + + @Override + public OperationResult get() throws InterruptedException, ExecutionException { + try { + future.get(); + return opResult; + } finally { + recordTimeIfNeeded(); + } + } - @Override - public boolean isCancelled() { - return future.isCancelled(); - } + private void recordTimeIfNeeded() { + if (timeRecorded.get()) { + return; + } + if (timeRecorded.compareAndSet(false, true)) { + opResult.setLatency(System.currentTimeMillis() - startTime, TimeUnit.MILLISECONDS); + } + } - @Override - public boolean isDone() { - return future.isDone(); - } + @Override + public OperationResult get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + try { + future.get(timeout, unit); + return opResult; + } finally { + recordTimeIfNeeded(); + } + } - @Override - public OperationResult get() throws InterruptedException, ExecutionException { - try { - future.get(); - return opResult; - } finally { - recordTimeIfNeeded(); - } - } + public FutureOperationalResultImpl node(Host node) { + opResult.setNode(node); + return this; + } - private void recordTimeIfNeeded() { - if (timeRecorded.get()) { - return; - } - if (timeRecorded.compareAndSet(false, true)) { - opResult.setLatency(System.currentTimeMillis()-startTime, TimeUnit.MILLISECONDS); - } - } + public OperationResultImpl getOpResult() { + return opResult; + } - @Override - public OperationResult get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - try { - future.get(timeout, unit); - return opResult; - } finally { - recordTimeIfNeeded(); - } - } - - public FutureOperationalResultImpl node(Host node) { - opResult.setNode(node); - return this; - } - - public OperationResultImpl getOpResult() { - return opResult; - } - - @Override - public void addListener(Runnable listener, Executor executor) { - throw new RuntimeException("Not Implemented"); - } + @Override + public void addListener(Runnable listener, Executor executor) { + throw new RuntimeException("Not Implemented"); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostConnectionPoolFactory.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostConnectionPoolFactory.java index b8882acf..df295b2f 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostConnectionPoolFactory.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostConnectionPoolFactory.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,9 +20,9 @@ public interface HostConnectionPoolFactory { - HostConnectionPool createHostConnectionPool(Host host, ConnectionPoolImpl parentPoolImpl); + HostConnectionPool createHostConnectionPool(Host host, ConnectionPoolImpl parentPoolImpl); - enum Type { + enum Type { /** Asynchronous, non-blocking instance */ Async, diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostConnectionPoolImpl.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostConnectionPoolImpl.java index 71c5f229..29ab5209 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostConnectionPoolImpl.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostConnectionPoolImpl.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -41,135 +41,134 @@ /** * Main impl for {@link HostConnectionPool} - * - * This class does not allow shared access to the connections being managed for this pool. - * Hence it uses a {@link LinkedBlockingQueue} to manage the available connections. - * When a connection needs to be borrowed, we wait or poll the queue. As connections are returned, they are added back into the queue. - * This is the normal behavior during the "Active" state of this pool. - * - * The class also manages another state called "Inactive" where it can be put "Down" where it stops accepting requests for borrowing more connections, - * and simply terminates every connection that is returned to it. This is generally useful when the host is going away, or where the error rate - * from the connections of this pool are greater than a configured error threshold and then an external component decides to recycle the connection pool. - * - * @author poberai + *

+ * This class does not allow shared access to the connections being managed for this pool. + * Hence it uses a {@link LinkedBlockingQueue} to manage the available connections. + * When a connection needs to be borrowed, we wait or poll the queue. As connections are returned, they are added back into the queue. + * This is the normal behavior during the "Active" state of this pool. + *

+ * The class also manages another state called "Inactive" where it can be put "Down" where it stops accepting requests for borrowing more connections, + * and simply terminates every connection that is returned to it. This is generally useful when the host is going away, or where the error rate + * from the connections of this pool are greater than a configured error threshold and then an external component decides to recycle the connection pool. * * @param + * @author poberai */ public class HostConnectionPoolImpl implements HostConnectionPool { - private static final Logger Logger = LoggerFactory.getLogger(HostConnectionPoolImpl.class); - private static final int CONNECTION_CREATE_RETRY_CNT = 3; - - // The connections available for this connection pool - private final LinkedBlockingQueue> availableConnections = new LinkedBlockingQueue>(); - // Track the no of connections open (both available and in use) - private final AtomicInteger numActiveConnections = new AtomicInteger(0); - - // Private members required by this class - private final Host host; - private final ConnectionFactory connFactory; - private final ConnectionPoolConfiguration cpConfig; - private final ConnectionPoolMonitor monitor; - - // states that dictate the behavior of the pool - - // cp not inited is the starting state of the pool. The pool will not allow connections to be borrowed in this state - private final ConnectionPoolState cpNotInited = new ConnectionPoolNotInited(); - // cp active is where connections of the pool can be borrowed and returned - private final ConnectionPoolState cpActive = new ConnectionPoolActive(this); - // cp reconnecting is where connections cannot be borrowed and all returning connections will be shutdown - private final ConnectionPoolState cpReconnecting = new ConnectionPoolReconnectingOrDown(); - // similar to reconnecting - private final ConnectionPoolState cpDown = new ConnectionPoolReconnectingOrDown(); - - // The thread safe reference to the pool state - private final AtomicReference> cpState = new AtomicReference>(cpNotInited); - - public HostConnectionPoolImpl(Host host, ConnectionFactory conFactory, - ConnectionPoolConfiguration cpConfig, ConnectionPoolMonitor poolMonitor) { - this.host = host; - this.connFactory = conFactory; - this.cpConfig = cpConfig; - this.monitor = poolMonitor; - } - - @Override - public Connection borrowConnection(int duration, TimeUnit unit) throws DynoException { - return cpState.get().borrowConnection(duration, unit); - } - - @Override - public boolean returnConnection(Connection connection) { - return cpState.get().returnConnection(connection); - } - - @Override - public boolean closeConnection(Connection connection) { - return cpState.get().closeConnection(connection); - } - - @Override - public void recycleConnection(Connection connection) { - cpState.get().recycleConnection(connection); - } - - @Override - public void markAsDown(DynoException reason) { + private static final Logger Logger = LoggerFactory.getLogger(HostConnectionPoolImpl.class); + private static final int CONNECTION_CREATE_RETRY_CNT = 3; + + // The connections available for this connection pool + private final LinkedBlockingQueue> availableConnections = new LinkedBlockingQueue>(); + // Track the no of connections open (both available and in use) + private final AtomicInteger numActiveConnections = new AtomicInteger(0); + + // Private members required by this class + private final Host host; + private final ConnectionFactory connFactory; + private final ConnectionPoolConfiguration cpConfig; + private final ConnectionPoolMonitor monitor; + + // states that dictate the behavior of the pool + + // cp not inited is the starting state of the pool. The pool will not allow connections to be borrowed in this state + private final ConnectionPoolState cpNotInited = new ConnectionPoolNotInited(); + // cp active is where connections of the pool can be borrowed and returned + private final ConnectionPoolState cpActive = new ConnectionPoolActive(this); + // cp reconnecting is where connections cannot be borrowed and all returning connections will be shutdown + private final ConnectionPoolState cpReconnecting = new ConnectionPoolReconnectingOrDown(); + // similar to reconnecting + private final ConnectionPoolState cpDown = new ConnectionPoolReconnectingOrDown(); + + // The thread safe reference to the pool state + private final AtomicReference> cpState = new AtomicReference>(cpNotInited); + + public HostConnectionPoolImpl(Host host, ConnectionFactory conFactory, + ConnectionPoolConfiguration cpConfig, ConnectionPoolMonitor poolMonitor) { + this.host = host; + this.connFactory = conFactory; + this.cpConfig = cpConfig; + this.monitor = poolMonitor; + } + + @Override + public Connection borrowConnection(int duration, TimeUnit unit) throws DynoException { + return cpState.get().borrowConnection(duration, unit); + } + + @Override + public boolean returnConnection(Connection connection) { + return cpState.get().returnConnection(connection); + } + + @Override + public boolean closeConnection(Connection connection) { + return cpState.get().closeConnection(connection); + } + + @Override + public void recycleConnection(Connection connection) { + cpState.get().recycleConnection(connection); + } + + @Override + public void markAsDown(DynoException reason) { if (Logger.isDebugEnabled()) { Logger.debug(String.format("Marking Host Connection Pool %s DOWN", getHost())); } - - ConnectionPoolState currentState = cpState.get(); - - if (currentState == cpDown) { - if (Logger.isDebugEnabled()) { - Logger.debug("CP is already down, hence ignoring mark as down request"); - } - return; - } - - if (!(cpState.compareAndSet(currentState, cpDown))) { - // someone already beat us to it - return; - } - - monitor.hostDown(host, reason); + + ConnectionPoolState currentState = cpState.get(); + + if (currentState == cpDown) { + if (Logger.isDebugEnabled()) { + Logger.debug("CP is already down, hence ignoring mark as down request"); + } + return; + } + + if (!(cpState.compareAndSet(currentState, cpDown))) { + // someone already beat us to it + return; + } + + monitor.hostDown(host, reason); monitor.resetConnectionBorrowedLatStats(); // NOTE - SIDE EFFECT - } + } - @Override + @Override public void reconnect() { markAsDown(null); - reconnect(cpDown); - - if (cpState.get() == cpActive) { - monitor.hostUp(host, this); - } - } - - @Override - public void shutdown() { - - Logger.info("Shutting down connection pool for host:" + host); - cpState.set(cpDown); - - List> connections = new ArrayList>(); - availableConnections.drainTo(connections); - - for (Connection connection : connections) { - cpState.get().closeConnection(connection); - } - } - - @Override - public int primeConnections() throws DynoException { - - Logger.info("Priming connection pool for host:" + host + ", with conns:" + cpConfig.getMaxConnsPerHost()); - - if(cpState.get() != cpNotInited) { - throw new DynoException("Connection pool has already been inited, cannot prime connections for host:" + host); - } + reconnect(cpDown); + + if (cpState.get() == cpActive) { + monitor.hostUp(host, this); + } + } + + @Override + public void shutdown() { + + Logger.info("Shutting down connection pool for host:" + host); + cpState.set(cpDown); + + List> connections = new ArrayList>(); + availableConnections.drainTo(connections); + + for (Connection connection : connections) { + cpState.get().closeConnection(connection); + } + } + + @Override + public int primeConnections() throws DynoException { + + Logger.info("Priming connection pool for host:" + host + ", with conns:" + cpConfig.getMaxConnsPerHost()); + + if (cpState.get() != cpNotInited) { + throw new DynoException("Connection pool has already been inited, cannot prime connections for host:" + host); + } int primedConnectionCount = reconnect(cpNotInited); @@ -180,208 +179,207 @@ public int primeConnections() throws DynoException { } return primedConnectionCount; - } - - private int reconnect(ConnectionPoolState prevState) throws DynoException { - - if (!(cpState.compareAndSet(prevState, cpReconnecting))) { - Logger.info("Reconnect connections already called by someone else, ignoring reconnect connections request"); - return 0; - } - - int successfullyCreated = 0; - - for (int i = 0; i < cpConfig.getMaxConnsPerHost(); i++) { - boolean success = createConnectionWithRetries(); - if (success) { - successfullyCreated++; - } - } - - if (successfullyCreated == cpConfig.getMaxConnsPerHost()) { - if (!(cpState.compareAndSet(cpReconnecting, cpActive))) { - throw new IllegalStateException("something went wrong with prime connections"); - } - } else { - if (!(cpState.compareAndSet(cpReconnecting, cpDown))) { - throw new IllegalStateException("something went wrong with prime connections"); - } - } - return successfullyCreated; - } - - private boolean createConnectionWithRetries() { - - boolean success = false; - RetryPolicy retry = new RetryNTimes.RetryFactory(CONNECTION_CREATE_RETRY_CNT).getRetryPolicy(); - - retry.begin(); - - while (retry.allowRetry()) { - - try { - cpActive.createConnection(); - retry.success(); - success = true; - break; - } catch (DynoException e) { - retry.failure(e); - } - } - - return success; - } - - @Override - public Host getHost() { - return host; - } - - @Override - public boolean isActive() { - return cpState.get() == cpActive; - } - - @Override - public boolean isShutdown() { - return cpState.get() == cpDown; - } - - /** - * DO NOT call this method on this pool. This pool needs to manage shared thread safe access to connections - * and hence at any given time all connections are being used by some operation. - * In any case getAllConnections() is meant for ping based active monitoring of connections which is not needed for this - * pool since it is "sync" in nature. For sync pools we collect feedback from the operations directly and relay that to - * ConnectionPoolHealthChecker. - * - */ - @Override - public Collection> getAllConnections() { - throw new RuntimeException("Not Implemented"); - } - - @Override - public int getConnectionTimeout() { - return cpConfig.getConnectTimeout(); - } - - @Override - public int getSocketTimeout() { - return cpConfig.getSocketTimeout(); - } - - @Override - public int size() { - return cpState.get().connectionsCount(); - } - - private interface ConnectionPoolState { - - - Connection createConnection(); - - Connection borrowConnection(int duration, TimeUnit unit); - - boolean returnConnection(Connection connection); - - boolean closeConnection(Connection connection); - - void recycleConnection(Connection connection); - - int connectionsCount(); - } - - - private class ConnectionPoolActive implements ConnectionPoolState { - - private final HostConnectionPoolImpl pool; - - private ConnectionPoolActive(HostConnectionPoolImpl cp) { - pool = cp; - } - - @Override - public Connection createConnection() { - - try { - Connection connection = connFactory.createConnection((HostConnectionPool) pool, null); - connection.open(); - availableConnections.add(connection); - - monitor.incConnectionCreated(host); - numActiveConnections.incrementAndGet(); - - return connection; - } catch (DynoConnectException e) { + } + + private int reconnect(ConnectionPoolState prevState) throws DynoException { + + if (!(cpState.compareAndSet(prevState, cpReconnecting))) { + Logger.info("Reconnect connections already called by someone else, ignoring reconnect connections request"); + return 0; + } + + int successfullyCreated = 0; + + for (int i = 0; i < cpConfig.getMaxConnsPerHost(); i++) { + boolean success = createConnectionWithRetries(); + if (success) { + successfullyCreated++; + } + } + + if (successfullyCreated == cpConfig.getMaxConnsPerHost()) { + if (!(cpState.compareAndSet(cpReconnecting, cpActive))) { + throw new IllegalStateException("something went wrong with prime connections"); + } + } else { + if (!(cpState.compareAndSet(cpReconnecting, cpDown))) { + throw new IllegalStateException("something went wrong with prime connections"); + } + } + return successfullyCreated; + } + + private boolean createConnectionWithRetries() { + + boolean success = false; + RetryPolicy retry = new RetryNTimes.RetryFactory(CONNECTION_CREATE_RETRY_CNT).getRetryPolicy(); + + retry.begin(); + + while (retry.allowRetry()) { + + try { + cpActive.createConnection(); + retry.success(); + success = true; + break; + } catch (DynoException e) { + retry.failure(e); + } + } + + return success; + } + + @Override + public Host getHost() { + return host; + } + + @Override + public boolean isActive() { + return cpState.get() == cpActive; + } + + @Override + public boolean isShutdown() { + return cpState.get() == cpDown; + } + + /** + * DO NOT call this method on this pool. This pool needs to manage shared thread safe access to connections + * and hence at any given time all connections are being used by some operation. + * In any case getAllConnections() is meant for ping based active monitoring of connections which is not needed for this + * pool since it is "sync" in nature. For sync pools we collect feedback from the operations directly and relay that to + * ConnectionPoolHealthChecker. + */ + @Override + public Collection> getAllConnections() { + throw new RuntimeException("Not Implemented"); + } + + @Override + public int getConnectionTimeout() { + return cpConfig.getConnectTimeout(); + } + + @Override + public int getSocketTimeout() { + return cpConfig.getSocketTimeout(); + } + + @Override + public int size() { + return cpState.get().connectionsCount(); + } + + private interface ConnectionPoolState { + + + Connection createConnection(); + + Connection borrowConnection(int duration, TimeUnit unit); + + boolean returnConnection(Connection connection); + + boolean closeConnection(Connection connection); + + void recycleConnection(Connection connection); + + int connectionsCount(); + } + + + private class ConnectionPoolActive implements ConnectionPoolState { + + private final HostConnectionPoolImpl pool; + + private ConnectionPoolActive(HostConnectionPoolImpl cp) { + pool = cp; + } + + @Override + public Connection createConnection() { + + try { + Connection connection = connFactory.createConnection((HostConnectionPool) pool, null); + connection.open(); + availableConnections.add(connection); + + monitor.incConnectionCreated(host); + numActiveConnections.incrementAndGet(); + + return connection; + } catch (DynoConnectException e) { /* adding error log under debug flag to avoid flooding log lines while debugging specific error scenarios. */ - if (Logger.isDebugEnabled()) { - if (monitor.getConnectionCreateFailedCount() % 10000 == 0) { - Logger.error("Failed to create connection", e); - } - } - monitor.incConnectionCreateFailed(host, e); - throw e; - } catch (RuntimeException e) { - if (monitor.getConnectionCreateFailedCount() % 10000 == 0) { - Logger.error("Failed to create connection", e); - } - monitor.incConnectionCreateFailed(host, e); - throw new DynoConnectException(e); - } - } - - - @Override - public boolean returnConnection(Connection connection) { - try { - if (numActiveConnections.get() > cpConfig.getMaxConnsPerHost()) { + if (Logger.isDebugEnabled()) { + if (monitor.getConnectionCreateFailedCount() % 10000 == 0) { + Logger.error("Failed to create connection", e); + } + } + monitor.incConnectionCreateFailed(host, e); + throw e; + } catch (RuntimeException e) { + if (monitor.getConnectionCreateFailedCount() % 10000 == 0) { + Logger.error("Failed to create connection", e); + } + monitor.incConnectionCreateFailed(host, e); + throw new DynoConnectException(e); + } + } + + + @Override + public boolean returnConnection(Connection connection) { + try { + if (numActiveConnections.get() > cpConfig.getMaxConnsPerHost()) { // Just close the connection return closeConnection(connection); } else { - // Add the given connection back to the pool - availableConnections.add(connection); - return false; - } - } finally { - monitor.incConnectionReturned(host); - } - } - - @Override - public boolean closeConnection(Connection connection) { - try { - connection.close(); - return true; - } catch (Exception e) { - Logger.error("Failed to close connection for host: " + host + " " + e.getMessage()); - return false; - } finally { - numActiveConnections.decrementAndGet(); - monitor.incConnectionClosed(host, connection.getLastException()); - } - } - - @Override - public void recycleConnection(Connection connection) { - this.closeConnection(connection); - monitor.incConnectionReturned(host); - // Create a new connection and add it to pool - if (createConnectionWithRetries()) { - monitor.incConnectionRecycled(host); - } else { - Logger.error("Connection recycle failed to create a new connection"); - } - } - - @Override - public int connectionsCount() { - return numActiveConnections.get(); - } - - @Override - public Connection borrowConnection(int duration, TimeUnit unit) { + // Add the given connection back to the pool + availableConnections.add(connection); + return false; + } + } finally { + monitor.incConnectionReturned(host); + } + } + + @Override + public boolean closeConnection(Connection connection) { + try { + connection.close(); + return true; + } catch (Exception e) { + Logger.error("Failed to close connection for host: " + host + " " + e.getMessage()); + return false; + } finally { + numActiveConnections.decrementAndGet(); + monitor.incConnectionClosed(host, connection.getLastException()); + } + } + + @Override + public void recycleConnection(Connection connection) { + this.closeConnection(connection); + monitor.incConnectionReturned(host); + // Create a new connection and add it to pool + if (createConnectionWithRetries()) { + monitor.incConnectionRecycled(host); + } else { + Logger.error("Connection recycle failed to create a new connection"); + } + } + + @Override + public int connectionsCount() { + return numActiveConnections.get(); + } + + @Override + public Connection borrowConnection(int duration, TimeUnit unit) { if (numActiveConnections.get() < 1) { // Need to throw something other than DynoConnectException in order to bubble past HostSelectionWithFallback @@ -391,116 +389,115 @@ public Connection borrowConnection(int duration, TimeUnit unit) { } // Start recording how long it takes to get the connection - for insight/metrics - long startTime = System.nanoTime()/1000; - - Connection conn = null; - try { - // wait on the connection pool with a timeout - conn = availableConnections.poll(duration, unit); - } catch (InterruptedException e) { - Logger.info("Thread interrupted when waiting on connections"); - throw new DynoConnectException(e); - } + long startTime = System.nanoTime() / 1000; + + Connection conn = null; + try { + // wait on the connection pool with a timeout + conn = availableConnections.poll(duration, unit); + } catch (InterruptedException e) { + Logger.info("Thread interrupted when waiting on connections"); + throw new DynoConnectException(e); + } - long delay = System.nanoTime()/1000 - startTime; + long delay = System.nanoTime() / 1000 - startTime; - if (conn == null) { + if (conn == null) { throw new PoolTimeoutException("Fast fail waiting for connection from pool") .setHost(getHost()) .setLatency(delay); - } + } monitor.incConnectionBorrowed(host, delay); - return conn; - } - } - - - - private class ConnectionPoolReconnectingOrDown implements ConnectionPoolState { - - private ConnectionPoolReconnectingOrDown() { - } - - @Override - public Connection createConnection() { - throw new PoolOfflineException(getHost(), "Cannot create new connection when pool is down"); - } - - @Override - public Connection borrowConnection(int duration, TimeUnit unit) { - throw new PoolOfflineException(getHost(), "Cannot borrow connection when pool is down"); - } - - @Override - public boolean returnConnection(Connection connection) { - - monitor.incConnectionReturned(host); - return closeConnection(connection); - } - - @Override - public boolean closeConnection(Connection connection) { - try { - connection.close(); - return true; - } catch (Exception e) { - Logger.warn("Failed to close connection for host: " + host + " " + e.getMessage()); - return false; - } finally { - numActiveConnections.decrementAndGet(); - monitor.incConnectionClosed(host, connection.getLastException()); - } - } - - @Override - public void recycleConnection(Connection connection) { - this.closeConnection(connection); - } - - @Override - public int connectionsCount() { - return 0; - } - } - - private class ConnectionPoolNotInited implements ConnectionPoolState { - - private ConnectionPoolNotInited() { - } - - @Override - public Connection createConnection() { - throw new DynoConnectException("Pool must be initialized first"); - } - - @Override - public Connection borrowConnection(int duration, TimeUnit unit) { - throw new DynoConnectException("Pool must be initialized first"); - } - - @Override - public boolean returnConnection(Connection connection) { - throw new DynoConnectException("Pool must be initialized first"); - } - - @Override - public boolean closeConnection(Connection connection) { - throw new DynoConnectException("Pool must be initialized first"); - } - - @Override - public void recycleConnection(Connection connection) { - throw new DynoConnectException("Pool must be initialized first"); - } - - @Override - public int connectionsCount() { - return 0; - } - } - - public String toString() { - return "HostConnectionPool: [Host: " + host + ", Pool active: " + isActive() + "]"; - } + return conn; + } + } + + + private class ConnectionPoolReconnectingOrDown implements ConnectionPoolState { + + private ConnectionPoolReconnectingOrDown() { + } + + @Override + public Connection createConnection() { + throw new PoolOfflineException(getHost(), "Cannot create new connection when pool is down"); + } + + @Override + public Connection borrowConnection(int duration, TimeUnit unit) { + throw new PoolOfflineException(getHost(), "Cannot borrow connection when pool is down"); + } + + @Override + public boolean returnConnection(Connection connection) { + + monitor.incConnectionReturned(host); + return closeConnection(connection); + } + + @Override + public boolean closeConnection(Connection connection) { + try { + connection.close(); + return true; + } catch (Exception e) { + Logger.warn("Failed to close connection for host: " + host + " " + e.getMessage()); + return false; + } finally { + numActiveConnections.decrementAndGet(); + monitor.incConnectionClosed(host, connection.getLastException()); + } + } + + @Override + public void recycleConnection(Connection connection) { + this.closeConnection(connection); + } + + @Override + public int connectionsCount() { + return 0; + } + } + + private class ConnectionPoolNotInited implements ConnectionPoolState { + + private ConnectionPoolNotInited() { + } + + @Override + public Connection createConnection() { + throw new DynoConnectException("Pool must be initialized first"); + } + + @Override + public Connection borrowConnection(int duration, TimeUnit unit) { + throw new DynoConnectException("Pool must be initialized first"); + } + + @Override + public boolean returnConnection(Connection connection) { + throw new DynoConnectException("Pool must be initialized first"); + } + + @Override + public boolean closeConnection(Connection connection) { + throw new DynoConnectException("Pool must be initialized first"); + } + + @Override + public void recycleConnection(Connection connection) { + throw new DynoConnectException("Pool must be initialized first"); + } + + @Override + public int connectionsCount() { + return 0; + } + } + + public String toString() { + return "HostConnectionPool: [Host: " + host + ", Pool active: " + isActive() + "]"; + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostSelectionStrategy.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostSelectionStrategy.java index 35c441ca..fd6b02bf 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostSelectionStrategy.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostSelectionStrategy.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,49 +28,45 @@ /** * Interface that encapsulates a strategy for selecting a {@link Connection} to a {@link Host} for the given {@link BaseOperation} - * @author poberai * * @param + * @author poberai */ public interface HostSelectionStrategy { - /** - * - * @param op - * @param hashtag - * @return - * @throws NoAvailableHostsException - */ - HostConnectionPool getPoolForOperation(BaseOperation op, String hashtag) + /** + * @param op + * @param hashtag + * @return + * @throws NoAvailableHostsException + */ + HostConnectionPool getPoolForOperation(BaseOperation op, String hashtag) throws NoAvailableHostsException; - /** - * - * @param ops - * @return - * @throws NoAvailableHostsException - */ - Map,BaseOperation> getPoolsForOperationBatch(Collection> ops) throws NoAvailableHostsException; - - /** - * - * @return - */ - List> getOrderedHostPools(); - - /** - * - * @param token - * @return - */ - HostConnectionPool getPoolForToken(Long token); - - /** - * - * @param start - * @param end - * @return - */ - List> getPoolsForTokens(Long start, Long end); + + /** + * @param ops + * @return + * @throws NoAvailableHostsException + */ + Map, BaseOperation> getPoolsForOperationBatch(Collection> ops) throws NoAvailableHostsException; + + /** + * @return + */ + List> getOrderedHostPools(); + + /** + * @param token + * @return + */ + HostConnectionPool getPoolForToken(Long token); + + /** + * @param start + * @param end + * @return + */ + List> getPoolsForTokens(Long start, Long end); /** * Finds the server Host that owns the specified key. @@ -81,7 +77,7 @@ HostConnectionPool getPoolForOperation(BaseOperation op, String hasht */ HostToken getTokenForKey(String key) throws UnsupportedOperationException; - + /** * Finds the server Host that owns the specified binary key. * @@ -89,44 +85,46 @@ HostConnectionPool getPoolForOperation(BaseOperation op, String hasht * @return {@link HostToken} * @throws UnsupportedOperationException for non-token aware load balancing strategies */ - HostToken getTokenForKey(byte[] key) throws UnsupportedOperationException; - - - /** - * Init the connection pool with the set of hosts provided - * @param hostPools - */ - void initWithHosts(Map> hostPools); - - /** - * Add a host to the selection strategy. This is useful when the underlying dynomite topology changes. - * @param {@link com.netflix.dyno.connectionpool.impl.lb.HostToken} - * @param hostPool - * @return true/false indicating whether the pool was indeed added - */ - boolean addHostPool(HostToken host, HostConnectionPool hostPool); - - /** - * Remove a host from the selection strategy. This is useful when the underlying dynomite topology changes. - * @param {@link com.netflix.dyno.connectionpool.impl.lb.HostToken} - * @return true/false indicating whether the pool was indeed removed - */ - boolean removeHostPool(HostToken host); - - boolean isTokenAware(); - - boolean isEmpty(); - - interface HostSelectionStrategyFactory { - - /** - * Create/Return a HostSelectionStrategy - * @return HostSelectionStrategy - */ - public HostSelectionStrategy vendPoolSelectionStrategy(); - } + HostToken getTokenForKey(byte[] key) throws UnsupportedOperationException; + + + /** + * Init the connection pool with the set of hosts provided + * + * @param hostPools + */ + void initWithHosts(Map> hostPools); + + /** + * Add a host to the selection strategy. This is useful when the underlying dynomite topology changes. + * + * @param {@link com.netflix.dyno.connectionpool.impl.lb.HostToken} + * @param hostPool + * @return true/false indicating whether the pool was indeed added + */ + boolean addHostPool(HostToken host, HostConnectionPool hostPool); + + /** + * Remove a host from the selection strategy. This is useful when the underlying dynomite topology changes. + * + * @param {@link com.netflix.dyno.connectionpool.impl.lb.HostToken} + * @return true/false indicating whether the pool was indeed removed + */ + boolean removeHostPool(HostToken host); + + boolean isTokenAware(); + + boolean isEmpty(); + interface HostSelectionStrategyFactory { + /** + * Create/Return a HostSelectionStrategy + * + * @return HostSelectionStrategy + */ + public HostSelectionStrategy vendPoolSelectionStrategy(); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostStatusTracker.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostStatusTracker.java index e15f189e..6212dcb7 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostStatusTracker.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostStatusTracker.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,196 +28,197 @@ import org.slf4j.LoggerFactory; /** - * Helper class that can be used in conjunction with a {@link HostSupplier} repeatedly to understand whether the change within the + * Helper class that can be used in conjunction with a {@link HostSupplier} repeatedly to understand whether the change within the * active and inactive host set. *

- * Implementations of {@link ConnectionPool} can then use this utility to adapt to topology changes and hence manage the corresponding - * {@link HostConnectionPool} objects for the set of active hosts. + * Implementations of {@link ConnectionPool} can then use this utility to adapt to topology changes and hence manage the corresponding + * {@link HostConnectionPool} objects for the set of active hosts. *

* Note the behavior of this class is such that if a host disappears and it was last known as active * then it will be moved to inactive. If however it disappears and its last known state was inactive * then it is removed from tracking altogether. This is to support terminations/node replacements. * * @author poberai - * */ public class HostStatusTracker { private static final Logger logger = LoggerFactory.getLogger(HostStatusTracker.class); - - // the set of active and inactive hosts - private final Set activeHosts = new HashSet(); - private final Set inactiveHosts = new HashSet(); - - public HostStatusTracker() { - } - - public HostStatusTracker(Collection up, Collection down) { - - verifyMutuallyExclusive(up, down); - - activeHosts.addAll(up); - inactiveHosts.addAll(down); - } - - /** - * Helper method to check that there is no overlap b/w hosts up and down. - * @param A - * @param B - */ - private void verifyMutuallyExclusive(Collection A, Collection B) { - - Set left = new HashSet(A); - Set right = new HashSet(B); - - boolean modified = left.removeAll(right); - if (modified) { - throw new RuntimeException("Host up and down sets are not mutually exclusive!"); - } - } - - /** - * All we need to check here is that whether the new active set is not exactly the same as the - * prev active set. If there are any new hosts that have been added or any hosts that are missing - * then return 'true' indicating that the active set has changed. - * - * @param hostsUp - * @return true/false indicating whether the active set has changed from the previous set. - */ - public boolean activeSetChanged(Collection hostsUp) { - - return !hostsUp.equals(activeHosts); - } - - /** - * This check is more involved than the active set check. Here we 2 conditions to check for - * - * 1. We could have new hosts that were in the active set and have shown up in the inactive set. - * 2. We can also have the case where hosts from the active set have disappeared and also not in the provided inactive set. - * This is where we have simply forgotten about some active host and that it needs to be shutdown - * - * @param hostsUp - * @param hostsDown - * @return true/false indicating whether we have a host that has been shutdown - */ - public boolean inactiveSetChanged(Collection hostsUp, Collection hostsDown) { - - boolean newInactiveHostsFound = false; - - // Check for condition 1. - for (Host hostDown : hostsDown) { - if (activeHosts.contains(hostDown)) { - newInactiveHostsFound = true; - break; - } - } - - // Check for condition 2. - Set prevActiveHosts = new HashSet(activeHosts); - prevActiveHosts.removeAll(hostsUp); - - newInactiveHostsFound = !prevActiveHosts.isEmpty(); - - return newInactiveHostsFound; - } - - /** - * Helper method that checks if anything has changed b/w the current state and the new set of hosts up and down - * @param hostsUp - * @param hostsDown - * @return true/false indicating whether the set of hosts has changed or not. - */ - public boolean checkIfChanged(Collection hostsUp, Collection hostsDown) { - boolean changed = activeSetChanged(hostsUp) || inactiveSetChanged(hostsUp, hostsDown); - - if (changed && logger.isDebugEnabled()) { - Set changedHostsUp = new HashSet<>(hostsUp); - changedHostsUp.removeAll(activeHosts); - changedHostsUp.forEach(x -> logger.debug("New host up: {}", x.getHostAddress())); - - Set changedHostsDown = new HashSet<>(hostsDown); - changedHostsDown.removeAll(inactiveHosts); - changedHostsDown.forEach(x -> logger.debug("New host down: {}", x.getHostAddress())); - } - return changed; - } - - /** - * Helper method that actually changes the state of the class to reflect the new set of hosts up and down - * Note that the new HostStatusTracker is returned that holds onto the new state. Calling classes must update their - * references to use the new HostStatusTracker - * - * @param hostsUp - * @param hostsDown - * @return - */ - public HostStatusTracker computeNewHostStatus(Collection hostsUp, Collection hostsDown) { - - verifyMutuallyExclusive(hostsUp, hostsDown); - - Set nextActiveHosts = new HashSet(hostsUp); - - // Get the hosts that are currently down - Set nextInactiveHosts = new HashSet(hostsDown); + + // the set of active and inactive hosts + private final Set activeHosts = new HashSet(); + private final Set inactiveHosts = new HashSet(); + + public HostStatusTracker() { + } + + public HostStatusTracker(Collection up, Collection down) { + + verifyMutuallyExclusive(up, down); + + activeHosts.addAll(up); + inactiveHosts.addAll(down); + } + + /** + * Helper method to check that there is no overlap b/w hosts up and down. + * + * @param A + * @param B + */ + private void verifyMutuallyExclusive(Collection A, Collection B) { + + Set left = new HashSet(A); + Set right = new HashSet(B); + + boolean modified = left.removeAll(right); + if (modified) { + throw new RuntimeException("Host up and down sets are not mutually exclusive!"); + } + } + + /** + * All we need to check here is that whether the new active set is not exactly the same as the + * prev active set. If there are any new hosts that have been added or any hosts that are missing + * then return 'true' indicating that the active set has changed. + * + * @param hostsUp + * @return true/false indicating whether the active set has changed from the previous set. + */ + public boolean activeSetChanged(Collection hostsUp) { + + return !hostsUp.equals(activeHosts); + } + + /** + * This check is more involved than the active set check. Here we 2 conditions to check for + *

+ * 1. We could have new hosts that were in the active set and have shown up in the inactive set. + * 2. We can also have the case where hosts from the active set have disappeared and also not in the provided inactive set. + * This is where we have simply forgotten about some active host and that it needs to be shutdown + * + * @param hostsUp + * @param hostsDown + * @return true/false indicating whether we have a host that has been shutdown + */ + public boolean inactiveSetChanged(Collection hostsUp, Collection hostsDown) { + + boolean newInactiveHostsFound = false; + + // Check for condition 1. + for (Host hostDown : hostsDown) { + if (activeHosts.contains(hostDown)) { + newInactiveHostsFound = true; + break; + } + } + + // Check for condition 2. + Set prevActiveHosts = new HashSet(activeHosts); + prevActiveHosts.removeAll(hostsUp); + + newInactiveHostsFound = !prevActiveHosts.isEmpty(); + + return newInactiveHostsFound; + } + + /** + * Helper method that checks if anything has changed b/w the current state and the new set of hosts up and down + * + * @param hostsUp + * @param hostsDown + * @return true/false indicating whether the set of hosts has changed or not. + */ + public boolean checkIfChanged(Collection hostsUp, Collection hostsDown) { + boolean changed = activeSetChanged(hostsUp) || inactiveSetChanged(hostsUp, hostsDown); + + if (changed && logger.isDebugEnabled()) { + Set changedHostsUp = new HashSet<>(hostsUp); + changedHostsUp.removeAll(activeHosts); + changedHostsUp.forEach(x -> logger.debug("New host up: {}", x.getHostAddress())); + + Set changedHostsDown = new HashSet<>(hostsDown); + changedHostsDown.removeAll(inactiveHosts); + changedHostsDown.forEach(x -> logger.debug("New host down: {}", x.getHostAddress())); + } + return changed; + } + + /** + * Helper method that actually changes the state of the class to reflect the new set of hosts up and down + * Note that the new HostStatusTracker is returned that holds onto the new state. Calling classes must update their + * references to use the new HostStatusTracker + * + * @param hostsUp + * @param hostsDown + * @return + */ + public HostStatusTracker computeNewHostStatus(Collection hostsUp, Collection hostsDown) { + + verifyMutuallyExclusive(hostsUp, hostsDown); + + Set nextActiveHosts = new HashSet(hostsUp); + + // Get the hosts that are currently down + Set nextInactiveHosts = new HashSet(hostsDown); // add any previous hosts that were currently down iff they are still reported by the HostSupplier - Set union = new HashSet<>(hostsUp); + Set union = new HashSet<>(hostsUp); union.addAll(hostsDown); if (!union.containsAll(inactiveHosts)) { logger.info("REMOVING at least one inactive host from {} b/c it is no longer reported by HostSupplier", inactiveHosts); inactiveHosts.retainAll(union); } - nextInactiveHosts.addAll(inactiveHosts); - - // Now remove from the total set of inactive hosts any host that is currently up. - // This typically happens when a host moves from the inactive state to the active state. - // And hence it will be there in the prev inactive set, and will also be there in the new active set - // for this round. - for (Host host : nextActiveHosts) { - nextInactiveHosts.remove(host); - } - - // Now add any host that is not in the new active hosts set and that was in the previous active set - Set prevActiveHosts = new HashSet(activeHosts); - prevActiveHosts.removeAll(hostsUp); - - // If anyone is remaining in the prev set then add it to the inactive set, since it has gone away - nextInactiveHosts.addAll(prevActiveHosts); - - for (Host host : nextActiveHosts) { - host.setStatus(Status.Up); - } - for (Host host : nextInactiveHosts) { - host.setStatus(Status.Down); - } - return new HostStatusTracker(nextActiveHosts, nextInactiveHosts); - } - - public boolean isHostUp(Host host) { - return activeHosts.contains(host); - } - - public Collection getActiveHosts() { - return activeHosts; - } - - public Collection getInactiveHosts() { - return inactiveHosts; - } - - /** - * Returns the total number of hosts being tracked by this instance. Note that this is calculated - * on every invocation. - * - * @return Integer - */ - public int getHostCount() { - // The host collections are never null since they are initialized during construction of this instance. - return activeHosts.size() + inactiveHosts.size(); - } - - public String toString() { - return "HostStatusTracker \nactiveSet: " + activeHosts.toString() + "\ninactiveSet: " + inactiveHosts.toString(); - } + nextInactiveHosts.addAll(inactiveHosts); + + // Now remove from the total set of inactive hosts any host that is currently up. + // This typically happens when a host moves from the inactive state to the active state. + // And hence it will be there in the prev inactive set, and will also be there in the new active set + // for this round. + for (Host host : nextActiveHosts) { + nextInactiveHosts.remove(host); + } + + // Now add any host that is not in the new active hosts set and that was in the previous active set + Set prevActiveHosts = new HashSet(activeHosts); + prevActiveHosts.removeAll(hostsUp); + + // If anyone is remaining in the prev set then add it to the inactive set, since it has gone away + nextInactiveHosts.addAll(prevActiveHosts); + + for (Host host : nextActiveHosts) { + host.setStatus(Status.Up); + } + for (Host host : nextInactiveHosts) { + host.setStatus(Status.Down); + } + return new HostStatusTracker(nextActiveHosts, nextInactiveHosts); + } + + public boolean isHostUp(Host host) { + return activeHosts.contains(host); + } + + public Collection getActiveHosts() { + return activeHosts; + } + + public Collection getInactiveHosts() { + return inactiveHosts; + } + + /** + * Returns the total number of hosts being tracked by this instance. Note that this is calculated + * on every invocation. + * + * @return Integer + */ + public int getHostCount() { + // The host collections are never null since they are initialized during construction of this instance. + return activeHosts.size() + inactiveHosts.size(); + } + + public String toString() { + return "HostStatusTracker \nactiveSet: " + activeHosts.toString() + "\ninactiveSet: " + inactiveHosts.toString(); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostsUpdater.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostsUpdater.java index dce7606b..93ae570a 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostsUpdater.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/HostsUpdater.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,115 +30,115 @@ public class HostsUpdater { - private static final Logger Logger = LoggerFactory.getLogger(ConnectionPoolImpl.class); - - private final HostSupplier hostSupplier; - private final TokenMapSupplier tokenMapSupplier; - - private final AtomicBoolean stop = new AtomicBoolean(false); - private final AtomicReference hostTracker = new AtomicReference(null); - - public HostsUpdater(HostSupplier hSupplier, TokenMapSupplier tokenMapSupplier) { - this.hostSupplier = hSupplier; - this.tokenMapSupplier = tokenMapSupplier; - this.hostTracker.set(new HostStatusTracker()); - } - - - public HostStatusTracker refreshHosts() { - - if (stop.get() || Thread.currentThread().isInterrupted()) { - return null; - } - - List allHostsFromHostSupplier = hostSupplier.getHosts(); - if (allHostsFromHostSupplier == null || allHostsFromHostSupplier.isEmpty()) { - throw new NoAvailableHostsException("No available hosts when starting HostsUpdater"); - } - - List hostsUpFromHostSupplier = new ArrayList<>(); - List hostsDownFromHostSupplier = new ArrayList<>(); - - for (Host host : allHostsFromHostSupplier) { - if (host.isUp()) { - hostsUpFromHostSupplier.add(host); - } else { - hostsDownFromHostSupplier.add(host); - } - } - - // if nothing has changed, just return the earlier hosttracker. - if (!hostTracker.get().checkIfChanged(new HashSet<>(hostsUpFromHostSupplier), new HashSet<>(hostsDownFromHostSupplier))) { - return hostTracker.get(); - } - - /** - * HostTracker should return the hosts that we get from TokenMapSupplier. - * Hence get the hosts from HostSupplier and map them to TokenMapSupplier - * and return them. - */ - Collections.sort(allHostsFromHostSupplier); - Set hostSet = new HashSet<>(allHostsFromHostSupplier); - // Create a list of host/Tokens - List hostTokens; - if (tokenMapSupplier != null) { - Logger.info("Getting Hosts from TokenMapSupplier"); - hostTokens = tokenMapSupplier.getTokens(hostSet); - - if (hostTokens.isEmpty()) { - throw new DynoException("No hosts in the TokenMapSupplier"); - } - } else { - throw new DynoException("TokenMapSupplier not provided"); - } - - // The key here really needs to be a object that is overlapping between - // the host from HostSupplier and TokenMapSupplier. Since that is a - // subset of the Host object itself, Host is the key as well as value here. - Map allHostSetFromTokenMapSupplier = new HashMap<>(); - for (HostToken ht : hostTokens) { - allHostSetFromTokenMapSupplier.put(ht.getHost(), ht.getHost()); - } - - hostsUpFromHostSupplier.clear(); - hostsDownFromHostSupplier.clear(); - - for (Host hostFromHostSupplier : allHostsFromHostSupplier) { - if (hostFromHostSupplier.isUp()) { - Host hostFromTokenMapSupplier = allHostSetFromTokenMapSupplier.get(hostFromHostSupplier); - - hostsUpFromHostSupplier.add(new Host(hostFromHostSupplier.getHostName(), hostFromHostSupplier.getIpAddress(), - hostFromTokenMapSupplier.getPort(), hostFromTokenMapSupplier.getSecurePort(), hostFromTokenMapSupplier.getRack(), - hostFromTokenMapSupplier.getDatacenter(), Host.Status.Up, hostFromTokenMapSupplier.getHashtag(), - hostFromTokenMapSupplier.getPassword())); - allHostSetFromTokenMapSupplier.remove(hostFromTokenMapSupplier); - } else { - Host hostFromTokenMapSupplier = allHostSetFromTokenMapSupplier.get(hostFromHostSupplier); - - hostsDownFromHostSupplier.add(new Host(hostFromHostSupplier.getHostName(), hostFromHostSupplier.getIpAddress(), - hostFromTokenMapSupplier.getPort(), hostFromTokenMapSupplier.getSecurePort(), hostFromTokenMapSupplier.getRack(), - hostFromTokenMapSupplier.getDatacenter(), Host.Status.Down, hostFromTokenMapSupplier.getHashtag(), - hostFromTokenMapSupplier.getPassword())); - allHostSetFromTokenMapSupplier.remove(hostFromTokenMapSupplier); - } - } - - // if a node is down, it might be absent in hostSupplier but has its presence in TokenMapSupplier. - // Add that host to the down list here. - for (Host h : allHostSetFromTokenMapSupplier.keySet()) { - hostsDownFromHostSupplier.add(new Host(h.getHostName(), h.getIpAddress(), - h.getPort(), h.getSecurePort(), h.getRack(), - h.getDatacenter(), Host.Status.Down, h.getHashtag())); - - } - - HostStatusTracker newTracker = hostTracker.get().computeNewHostStatus(hostsUpFromHostSupplier, hostsDownFromHostSupplier); - hostTracker.set(newTracker); - - return hostTracker.get(); - } - - public void stop() { - stop.set(true); - } + private static final Logger Logger = LoggerFactory.getLogger(ConnectionPoolImpl.class); + + private final HostSupplier hostSupplier; + private final TokenMapSupplier tokenMapSupplier; + + private final AtomicBoolean stop = new AtomicBoolean(false); + private final AtomicReference hostTracker = new AtomicReference(null); + + public HostsUpdater(HostSupplier hSupplier, TokenMapSupplier tokenMapSupplier) { + this.hostSupplier = hSupplier; + this.tokenMapSupplier = tokenMapSupplier; + this.hostTracker.set(new HostStatusTracker()); + } + + + public HostStatusTracker refreshHosts() { + + if (stop.get() || Thread.currentThread().isInterrupted()) { + return null; + } + + List allHostsFromHostSupplier = hostSupplier.getHosts(); + if (allHostsFromHostSupplier == null || allHostsFromHostSupplier.isEmpty()) { + throw new NoAvailableHostsException("No available hosts when starting HostsUpdater"); + } + + List hostsUpFromHostSupplier = new ArrayList<>(); + List hostsDownFromHostSupplier = new ArrayList<>(); + + for (Host host : allHostsFromHostSupplier) { + if (host.isUp()) { + hostsUpFromHostSupplier.add(host); + } else { + hostsDownFromHostSupplier.add(host); + } + } + + // if nothing has changed, just return the earlier hosttracker. + if (!hostTracker.get().checkIfChanged(new HashSet<>(hostsUpFromHostSupplier), new HashSet<>(hostsDownFromHostSupplier))) { + return hostTracker.get(); + } + + /** + * HostTracker should return the hosts that we get from TokenMapSupplier. + * Hence get the hosts from HostSupplier and map them to TokenMapSupplier + * and return them. + */ + Collections.sort(allHostsFromHostSupplier); + Set hostSet = new HashSet<>(allHostsFromHostSupplier); + // Create a list of host/Tokens + List hostTokens; + if (tokenMapSupplier != null) { + Logger.info("Getting Hosts from TokenMapSupplier"); + hostTokens = tokenMapSupplier.getTokens(hostSet); + + if (hostTokens.isEmpty()) { + throw new DynoException("No hosts in the TokenMapSupplier"); + } + } else { + throw new DynoException("TokenMapSupplier not provided"); + } + + // The key here really needs to be a object that is overlapping between + // the host from HostSupplier and TokenMapSupplier. Since that is a + // subset of the Host object itself, Host is the key as well as value here. + Map allHostSetFromTokenMapSupplier = new HashMap<>(); + for (HostToken ht : hostTokens) { + allHostSetFromTokenMapSupplier.put(ht.getHost(), ht.getHost()); + } + + hostsUpFromHostSupplier.clear(); + hostsDownFromHostSupplier.clear(); + + for (Host hostFromHostSupplier : allHostsFromHostSupplier) { + if (hostFromHostSupplier.isUp()) { + Host hostFromTokenMapSupplier = allHostSetFromTokenMapSupplier.get(hostFromHostSupplier); + + hostsUpFromHostSupplier.add(new Host(hostFromHostSupplier.getHostName(), hostFromHostSupplier.getIpAddress(), + hostFromTokenMapSupplier.getPort(), hostFromTokenMapSupplier.getSecurePort(), hostFromTokenMapSupplier.getRack(), + hostFromTokenMapSupplier.getDatacenter(), Host.Status.Up, hostFromTokenMapSupplier.getHashtag(), + hostFromTokenMapSupplier.getPassword())); + allHostSetFromTokenMapSupplier.remove(hostFromTokenMapSupplier); + } else { + Host hostFromTokenMapSupplier = allHostSetFromTokenMapSupplier.get(hostFromHostSupplier); + + hostsDownFromHostSupplier.add(new Host(hostFromHostSupplier.getHostName(), hostFromHostSupplier.getIpAddress(), + hostFromTokenMapSupplier.getPort(), hostFromTokenMapSupplier.getSecurePort(), hostFromTokenMapSupplier.getRack(), + hostFromTokenMapSupplier.getDatacenter(), Host.Status.Down, hostFromTokenMapSupplier.getHashtag(), + hostFromTokenMapSupplier.getPassword())); + allHostSetFromTokenMapSupplier.remove(hostFromTokenMapSupplier); + } + } + + // if a node is down, it might be absent in hostSupplier but has its presence in TokenMapSupplier. + // Add that host to the down list here. + for (Host h : allHostSetFromTokenMapSupplier.keySet()) { + hostsDownFromHostSupplier.add(new Host(h.getHostName(), h.getIpAddress(), + h.getPort(), h.getSecurePort(), h.getRack(), + h.getDatacenter(), Host.Status.Down, h.getHashtag())); + + } + + HostStatusTracker newTracker = hostTracker.get().computeNewHostStatus(hostsUpFromHostSupplier, hostsDownFromHostSupplier); + hostTracker.set(newTracker); + + return hostTracker.get(); + } + + public void stop() { + stop.set(true); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/LastOperationMonitor.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/LastOperationMonitor.java index 2614426a..5a7d80e5 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/LastOperationMonitor.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/LastOperationMonitor.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,63 +23,62 @@ /** * Simple in memory map based impl of {@link OperationMonitor} - * Mainly used for testing. - * - * @author poberai + * Mainly used for testing. * + * @author poberai */ public class LastOperationMonitor implements OperationMonitor { - private final ConcurrentHashMap latestTimings = new ConcurrentHashMap(); - private final ConcurrentHashMap opCounters = new ConcurrentHashMap(); - private final ConcurrentHashMap opFailureCounters = new ConcurrentHashMap(); - - @Override - public void recordLatency(String opName, long duration, TimeUnit unit) { - latestTimings.put(opName, TimeUnit.MILLISECONDS.convert(duration, unit)); - } + private final ConcurrentHashMap latestTimings = new ConcurrentHashMap(); + private final ConcurrentHashMap opCounters = new ConcurrentHashMap(); + private final ConcurrentHashMap opFailureCounters = new ConcurrentHashMap(); - @Override - public void recordSuccess(String opName) { - AtomicInteger count = opCounters.get(opName); - if (count == null) { - opCounters.put(opName, new AtomicInteger(1)); - } else { - count.incrementAndGet(); - } - } + @Override + public void recordLatency(String opName, long duration, TimeUnit unit) { + latestTimings.put(opName, TimeUnit.MILLISECONDS.convert(duration, unit)); + } - @Override - public void recordSuccess(String opName, boolean compressionEnabled) { - String name = opName + "_" + compressionEnabled; - AtomicInteger count = opCounters.get(name); - if (count == null) { - opCounters.put(name, new AtomicInteger(1)); - } else { - count.incrementAndGet(); - } - } + @Override + public void recordSuccess(String opName) { + AtomicInteger count = opCounters.get(opName); + if (count == null) { + opCounters.put(opName, new AtomicInteger(1)); + } else { + count.incrementAndGet(); + } + } - @Override - public void recordFailure(String opName, String reason) { - AtomicInteger count = opFailureCounters.get(opName); - if (count == null) { - opFailureCounters.put(opName, new AtomicInteger(1)); - } else { - count.incrementAndGet(); - } - } + @Override + public void recordSuccess(String opName, boolean compressionEnabled) { + String name = opName + "_" + compressionEnabled; + AtomicInteger count = opCounters.get(name); + if (count == null) { + opCounters.put(name, new AtomicInteger(1)); + } else { + count.incrementAndGet(); + } + } + + @Override + public void recordFailure(String opName, String reason) { + AtomicInteger count = opFailureCounters.get(opName); + if (count == null) { + opFailureCounters.put(opName, new AtomicInteger(1)); + } else { + count.incrementAndGet(); + } + } - @Override - public void recordFailure(String opName, boolean compressionEnabled, String reason) { - String name = opName + "_" + compressionEnabled; + @Override + public void recordFailure(String opName, boolean compressionEnabled, String reason) { + String name = opName + "_" + compressionEnabled; AtomicInteger count = opCounters.get(name); if (count == null) { opCounters.put(name, new AtomicInteger(1)); } else { count.incrementAndGet(); } - } + } public Integer getSuccessCount(String opName) { return opCounters.get(opName).get(); diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/MonitorConsole.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/MonitorConsole.java index 388d2cf9..fb8e737a 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/MonitorConsole.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/MonitorConsole.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,37 +23,36 @@ /** * Console that gives the admin insight into the current status of the Dyno {@link ConnectionPool} - * - * @author poberai * + * @author poberai */ public class MonitorConsole implements MonitorConsoleMBean { - private static final MonitorConsole Instance = new MonitorConsole(); + private static final MonitorConsole Instance = new MonitorConsole(); /*package*/ static final String OBJECT_NAME = "com.netflix.dyno.connectionpool.impl:type=MonitorConsole"; public static MonitorConsole getInstance() { - return Instance; - } + return Instance; + } - private final ConcurrentHashMap cpMonitors = new ConcurrentHashMap(); - private final ConcurrentHashMap> connectionPools = new ConcurrentHashMap>(); - - private MonitorConsole() { - - } + private final ConcurrentHashMap cpMonitors = new ConcurrentHashMap(); + private final ConcurrentHashMap> connectionPools = new ConcurrentHashMap>(); + + private MonitorConsole() { + + } @Override - public String getMonitorNames() { - return cpMonitors.keySet().toString(); - } - - public void addMonitorConsole(String name, ConnectionPoolMonitor monitor) { - cpMonitors.put(name, monitor); - } - - public void registerConnectionPool(ConnectionPoolImpl cp) { + public String getMonitorNames() { + return cpMonitors.keySet().toString(); + } + + public void addMonitorConsole(String name, ConnectionPoolMonitor monitor) { + cpMonitors.put(name, monitor); + } + + public void registerConnectionPool(ConnectionPoolImpl cp) { ConnectionPoolImpl cpImpl = connectionPools.putIfAbsent(cp.getName(), cp); if (cpImpl != null) { @@ -65,65 +64,65 @@ public void registerConnectionPool(ConnectionPoolImpl cp) { addMonitorConsole(cp.getName(), cp.getMonitor()); } - } + } @Override - public String getMonitorStats(String name) { - - ConnectionPoolMonitor cpMonitor = cpMonitors.get(name); - if (cpMonitor == null) { - return name + " NOT FOUND"; - } - - StringBuilder sb = new StringBuilder(); - - sb - .append("ConnectionPoolMonitor(") - .append("\nConnections[" ) - .append(" created: " ).append(cpMonitor.getConnectionCreatedCount()) - .append(", closed: " ).append(cpMonitor.getConnectionClosedCount()) - .append(", recycled: ").append(cpMonitor.getConnectionRecycledCount()) - .append(", createFailed: " ).append(cpMonitor.getConnectionCreateFailedCount()) - .append(", borrowed: ").append(cpMonitor.getConnectionBorrowedCount()) - .append(", returned: ").append(cpMonitor.getConnectionReturnedCount()) - .append(", borrowedLatMean: ").append(cpMonitor.getConnectionBorrowedLatMean()) - .append(", borrowedLatP99: ").append(cpMonitor.getConnectionBorrowedLatP99()) - - .append("]\nOperations[") - .append(" success=" ).append(cpMonitor.getOperationSuccessCount()) - .append(", failure=" ).append(cpMonitor.getOperationFailureCount()) - .append(", failover=").append(cpMonitor.getFailoverCount()) - .append("]\nHosts[") - .append(" add=" ).append(cpMonitor.getHostUpCount()) - .append(", down=" ).append(cpMonitor.getHostDownCount()) - .append("])"); - - Map hostStats = cpMonitor.getHostStats(); - for (Host host : hostStats.keySet()) { - - if (host.getHostAddress().contains("AllHosts")) { - continue; - } - - HostConnectionStats hStats = hostStats.get(host); - sb.append("\nHost: " + host.getHostAddress() + ":" + host.getPort() + ":" + host.getRack() + "\t"); - sb.append(" borrowed: " + hStats.getConnectionsBorrowed()); - sb.append(" returned: " + hStats.getConnectionsReturned()); - sb.append(" created: " + hStats.getConnectionsCreated()); - sb.append(" closed: " + hStats.getConnectionsClosed()); - sb.append(" createFailed: " + hStats.getConnectionsCreateFailed()); - sb.append(" errors: " + hStats.getOperationErrorCount()); - sb.append(" success: " + hStats.getOperationSuccessCount()); - } - sb.append("\n"); - - return sb.toString(); - } - - public TokenPoolTopology getTopology(String cpName) { - ConnectionPoolImpl pool = connectionPools.get(cpName); - return (pool != null) ? pool.getTopology() : null; - } + public String getMonitorStats(String name) { + + ConnectionPoolMonitor cpMonitor = cpMonitors.get(name); + if (cpMonitor == null) { + return name + " NOT FOUND"; + } + + StringBuilder sb = new StringBuilder(); + + sb + .append("ConnectionPoolMonitor(") + .append("\nConnections[") + .append(" created: ").append(cpMonitor.getConnectionCreatedCount()) + .append(", closed: ").append(cpMonitor.getConnectionClosedCount()) + .append(", recycled: ").append(cpMonitor.getConnectionRecycledCount()) + .append(", createFailed: ").append(cpMonitor.getConnectionCreateFailedCount()) + .append(", borrowed: ").append(cpMonitor.getConnectionBorrowedCount()) + .append(", returned: ").append(cpMonitor.getConnectionReturnedCount()) + .append(", borrowedLatMean: ").append(cpMonitor.getConnectionBorrowedLatMean()) + .append(", borrowedLatP99: ").append(cpMonitor.getConnectionBorrowedLatP99()) + + .append("]\nOperations[") + .append(" success=").append(cpMonitor.getOperationSuccessCount()) + .append(", failure=").append(cpMonitor.getOperationFailureCount()) + .append(", failover=").append(cpMonitor.getFailoverCount()) + .append("]\nHosts[") + .append(" add=").append(cpMonitor.getHostUpCount()) + .append(", down=").append(cpMonitor.getHostDownCount()) + .append("])"); + + Map hostStats = cpMonitor.getHostStats(); + for (Host host : hostStats.keySet()) { + + if (host.getHostAddress().contains("AllHosts")) { + continue; + } + + HostConnectionStats hStats = hostStats.get(host); + sb.append("\nHost: " + host.getHostAddress() + ":" + host.getPort() + ":" + host.getRack() + "\t"); + sb.append(" borrowed: " + hStats.getConnectionsBorrowed()); + sb.append(" returned: " + hStats.getConnectionsReturned()); + sb.append(" created: " + hStats.getConnectionsCreated()); + sb.append(" closed: " + hStats.getConnectionsClosed()); + sb.append(" createFailed: " + hStats.getConnectionsCreateFailed()); + sb.append(" errors: " + hStats.getOperationErrorCount()); + sb.append(" success: " + hStats.getOperationSuccessCount()); + } + sb.append("\n"); + + return sb.toString(); + } + + public TokenPoolTopology getTopology(String cpName) { + ConnectionPoolImpl pool = connectionPools.get(cpName); + return (pool != null) ? pool.getTopology() : null; + } @Override public Map>> getTopologySnapshot(String cpName) { diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/MonitorConsoleMBean.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/MonitorConsoleMBean.java index d7941880..456e8e55 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/MonitorConsoleMBean.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/MonitorConsoleMBean.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/MonitorConsoleResource.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/MonitorConsoleResource.java index 1fed989a..7786a905 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/MonitorConsoleResource.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/MonitorConsoleResource.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -38,87 +38,87 @@ @Path("/dyno/console") public class MonitorConsoleResource { - private static final Logger Logger = LoggerFactory.getLogger(MonitorConsoleResource.class); + private static final Logger Logger = LoggerFactory.getLogger(MonitorConsoleResource.class); - public MonitorConsoleResource() { - Logger.info("LOADED MonitorConsoleResource"); - } + public MonitorConsoleResource() { + Logger.info("LOADED MonitorConsoleResource"); + } - @Path("/monitors") - @GET - @Consumes(MediaType.TEXT_PLAIN) - @Produces(MediaType.TEXT_PLAIN) - public String getMonitorNames() { - return MonitorConsole.getInstance().getMonitorNames(); - } + @Path("/monitors") + @GET + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public String getMonitorNames() { + return MonitorConsole.getInstance().getMonitorNames(); + } - @Path("/monitor/{monitorName}") - @GET - @Consumes(MediaType.TEXT_PLAIN) - @Produces(MediaType.TEXT_PLAIN) - public String getMonitorStats(@PathParam("monitorName") String monitorName) { + @Path("/monitor/{monitorName}") + @GET + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public String getMonitorStats(@PathParam("monitorName") String monitorName) { - return MonitorConsole.getInstance().getMonitorStats(monitorName); - } + return MonitorConsole.getInstance().getMonitorStats(monitorName); + } @SuppressWarnings("unchecked") - @Path("/monitor/{cpName}/configuration") - @GET - @Consumes(MediaType.TEXT_PLAIN) - @Produces(MediaType.APPLICATION_JSON) - public String getConnectionPoolConfiguration(@PathParam("cpName") String cpName) { - JSONObject json = new JSONObject(); - - Map config = MonitorConsole.getInstance().getRuntimeConfiguration(cpName); - if (config != null) { - for (Map.Entry entry: config.entrySet()) { - json.put(entry.getKey(), entry.getValue()); - } - } - return json.toJSONString(); - } - - @Path("/topologies") - @GET - @Consumes(MediaType.TEXT_PLAIN) - @Produces(MediaType.TEXT_PLAIN) - public String getConnectionPoolNames() { - return MonitorConsole.getInstance().getMonitorNames(); - } - - @SuppressWarnings("unchecked") - @Path("/topology/{cpName}") - @GET - @Consumes(MediaType.TEXT_PLAIN) - @Produces(MediaType.APPLICATION_JSON) - public String getConnectionPoolToplogy(@PathParam("cpName") String cpName) { - - TokenPoolTopology topology = MonitorConsole.getInstance().getTopology(cpName); - if (topology == null) { - return "Not Found: " + cpName; - } - - ConcurrentHashMap> map = topology.getAllTokens(); - - JSONObject json = new JSONObject(); - - for (String rack : map.keySet()) { - List tokens = map.get(rack); - json.put(rack, getTokenStatusMap(tokens)); - } - return json.toJSONString(); - } - - private Map getTokenStatusMap(List tokens) { - - Map map = new HashMap(); - for (TokenStatus tokenStatus : tokens) { - String token = tokenStatus.getToken().toString(); - HostConnectionPool hostPool = tokenStatus.getHostPool(); - String poolStatus = hostPool.getHost().getHostAddress() + "__" + (hostPool.isActive() ? "UP" : "DOWN"); - map.put(token, poolStatus); - } - return map; - } + @Path("/monitor/{cpName}/configuration") + @GET + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.APPLICATION_JSON) + public String getConnectionPoolConfiguration(@PathParam("cpName") String cpName) { + JSONObject json = new JSONObject(); + + Map config = MonitorConsole.getInstance().getRuntimeConfiguration(cpName); + if (config != null) { + for (Map.Entry entry : config.entrySet()) { + json.put(entry.getKey(), entry.getValue()); + } + } + return json.toJSONString(); + } + + @Path("/topologies") + @GET + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public String getConnectionPoolNames() { + return MonitorConsole.getInstance().getMonitorNames(); + } + + @SuppressWarnings("unchecked") + @Path("/topology/{cpName}") + @GET + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.APPLICATION_JSON) + public String getConnectionPoolToplogy(@PathParam("cpName") String cpName) { + + TokenPoolTopology topology = MonitorConsole.getInstance().getTopology(cpName); + if (topology == null) { + return "Not Found: " + cpName; + } + + ConcurrentHashMap> map = topology.getAllTokens(); + + JSONObject json = new JSONObject(); + + for (String rack : map.keySet()) { + List tokens = map.get(rack); + json.put(rack, getTokenStatusMap(tokens)); + } + return json.toJSONString(); + } + + private Map getTokenStatusMap(List tokens) { + + Map map = new HashMap(); + for (TokenStatus tokenStatus : tokens) { + String token = tokenStatus.getToken().toString(); + HostConnectionPool hostPool = tokenStatus.getHostPool(); + String poolStatus = hostPool.getHost().getHostAddress() + "__" + (hostPool.isActive() ? "UP" : "DOWN"); + map.put(token, poolStatus); + } + return map; + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/OperationResultImpl.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/OperationResultImpl.java index c909b846..56cdbf48 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/OperationResultImpl.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/OperationResultImpl.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,114 +28,113 @@ /** * Impl for {@link OperationResult} * It tracks operation result, op attempts, latency, execution host etc - * - * @author poberai * * @param + * @author poberai */ public class OperationResultImpl implements OperationResult { - private final String opName; - private final R result; - private final Future futureResult; - private Host host = null; - private long duration = 0; - private int attempts = 0; - private final OperationMonitor opMonitor; - private final ConcurrentHashMap metadata = new ConcurrentHashMap(); - - public OperationResultImpl(String name, R r, OperationMonitor monitor) { - opName = name; - result = r; - futureResult = null; - opMonitor = monitor; - } - - public OperationResultImpl(String name, Future future, OperationMonitor monitor) { - opName = name; - result = null; - futureResult = future; - opMonitor = monitor; - } - - @Override - public Host getNode() { - return host; - } - - @Override - public R getResult() { - try { - return futureResult != null ? futureResult.get() : result; - } catch (Exception e) { - throw new DynoException(e); - } - } - - @Override - public long getLatency() { - return duration; - } - - @Override - public long getLatency(TimeUnit units) { - return units.convert(duration, TimeUnit.MILLISECONDS); - } - - @Override - public int getAttemptsCount() { - return attempts; - } - - @Override - public OperationResultImpl setAttemptsCount(int count) { - attempts = count; - return this; - } - - public OperationResultImpl setNode(Host h) { - host = h; - return this; - } - - public OperationResultImpl attempts(int count) { - attempts = count; - return this; - } - - public OperationResultImpl latency(long time) { - this.duration = time; - if (opMonitor != null) { - opMonitor.recordLatency(opName, time, TimeUnit.MILLISECONDS); - } - return this; - } - - @Override - public OperationResultImpl setLatency(long time, TimeUnit unit) { - this.duration = TimeUnit.MILLISECONDS.convert(time, unit); - if (opMonitor != null) { - opMonitor.recordLatency(opName, time, unit); - } - return this; - } - - @Override - public Map getMetadata() { - return metadata; - } - - @Override - public OperationResultImpl addMetadata(String key, String value) { - metadata.put(key, value); - return this; - } - - @Override - public OperationResultImpl addMetadata(Map map) { - for (String key : map.keySet()) { - metadata.put(key, map.get(key).toString()); - } - return this; - } + private final String opName; + private final R result; + private final Future futureResult; + private Host host = null; + private long duration = 0; + private int attempts = 0; + private final OperationMonitor opMonitor; + private final ConcurrentHashMap metadata = new ConcurrentHashMap(); + + public OperationResultImpl(String name, R r, OperationMonitor monitor) { + opName = name; + result = r; + futureResult = null; + opMonitor = monitor; + } + + public OperationResultImpl(String name, Future future, OperationMonitor monitor) { + opName = name; + result = null; + futureResult = future; + opMonitor = monitor; + } + + @Override + public Host getNode() { + return host; + } + + @Override + public R getResult() { + try { + return futureResult != null ? futureResult.get() : result; + } catch (Exception e) { + throw new DynoException(e); + } + } + + @Override + public long getLatency() { + return duration; + } + + @Override + public long getLatency(TimeUnit units) { + return units.convert(duration, TimeUnit.MILLISECONDS); + } + + @Override + public int getAttemptsCount() { + return attempts; + } + + @Override + public OperationResultImpl setAttemptsCount(int count) { + attempts = count; + return this; + } + + public OperationResultImpl setNode(Host h) { + host = h; + return this; + } + + public OperationResultImpl attempts(int count) { + attempts = count; + return this; + } + + public OperationResultImpl latency(long time) { + this.duration = time; + if (opMonitor != null) { + opMonitor.recordLatency(opName, time, TimeUnit.MILLISECONDS); + } + return this; + } + + @Override + public OperationResultImpl setLatency(long time, TimeUnit unit) { + this.duration = TimeUnit.MILLISECONDS.convert(time, unit); + if (opMonitor != null) { + opMonitor.recordLatency(opName, time, unit); + } + return this; + } + + @Override + public Map getMetadata() { + return metadata; + } + + @Override + public OperationResultImpl addMetadata(String key, String value) { + metadata.put(key, value); + return this; + } + + @Override + public OperationResultImpl addMetadata(Map map) { + for (String key : map.keySet()) { + metadata.put(key, map.get(key).toString()); + } + return this; + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/RetryNTimes.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/RetryNTimes.java index 23f1989d..438cfb29 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/RetryNTimes.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/RetryNTimes.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,115 +22,114 @@ /** * Simple implementation of {@link RetryPolicy} that ensures an operation can be re tried at most N times. - * + *

* Note that RetryNTimes (2) means that a total of 2 + 1 = 3 attempts will be allowed before giving up. - * - * @author poberai * + * @author poberai */ public class RetryNTimes implements RetryPolicy { - private int n; - private final AtomicReference state = new AtomicReference<>(new RetryState(0, false)); - private final boolean allowCrossZoneFallback; - - public RetryNTimes(int n, boolean allowFallback) { - this.n = n; - this.allowCrossZoneFallback = allowFallback; - } - - @Override - public void begin() { - } - - @Override - public void success() { - boolean success = false; - RetryState rs; - while (!success) { - rs = state.get(); - success = state.compareAndSet(rs, new RetryState(rs.count + 1, true)); - } - } - - @Override - public void failure(Exception e) { - boolean success = false; - RetryState rs; - while (!success) { - rs = state.get(); - success = state.compareAndSet(rs, new RetryState(rs.count + 1, false)); - } - } - - @Override - public boolean allowRetry() { - final RetryState rs = state.get(); - return !rs.success && rs.count <= n; - } - - @Override - public int getAttemptCount() { - return state.get().count; - } - - @Override - public boolean allowCrossZoneFallback() { - return allowCrossZoneFallback; - } - - @Override - public String toString() { - return "RetryNTimes{" + - "n=" + n + - ", state=" + state.get() + - ", allowCrossZoneFallback=" + allowCrossZoneFallback + - '}'; - } - - public static class RetryFactory implements RetryPolicyFactory { - - int n; - boolean allowCrossZoneFallback; - - public RetryFactory(int n) { - this(n, true); - } - - public RetryFactory(int n, boolean allowFallback) { - this.n = n; - this.allowCrossZoneFallback = allowFallback; - } - - @Override - public RetryPolicy getRetryPolicy() { - return new RetryNTimes(n, allowCrossZoneFallback); - } - - @Override - public String toString() { - return "RetryFactory{" + - "n=" + n + - ", allowCrossZoneFallback=" + allowCrossZoneFallback + - '}'; - } - } - - private class RetryState { - private final int count; - private final boolean success; - - public RetryState(final int count, final boolean success) { - this.count = count; - this.success = success; - } - - @Override - public String toString() { - return "RetryState{" + - "count=" + count + - ", success=" + success + - '}'; - } - } + private int n; + private final AtomicReference state = new AtomicReference<>(new RetryState(0, false)); + private final boolean allowCrossZoneFallback; + + public RetryNTimes(int n, boolean allowFallback) { + this.n = n; + this.allowCrossZoneFallback = allowFallback; + } + + @Override + public void begin() { + } + + @Override + public void success() { + boolean success = false; + RetryState rs; + while (!success) { + rs = state.get(); + success = state.compareAndSet(rs, new RetryState(rs.count + 1, true)); + } + } + + @Override + public void failure(Exception e) { + boolean success = false; + RetryState rs; + while (!success) { + rs = state.get(); + success = state.compareAndSet(rs, new RetryState(rs.count + 1, false)); + } + } + + @Override + public boolean allowRetry() { + final RetryState rs = state.get(); + return !rs.success && rs.count <= n; + } + + @Override + public int getAttemptCount() { + return state.get().count; + } + + @Override + public boolean allowCrossZoneFallback() { + return allowCrossZoneFallback; + } + + @Override + public String toString() { + return "RetryNTimes{" + + "n=" + n + + ", state=" + state.get() + + ", allowCrossZoneFallback=" + allowCrossZoneFallback + + '}'; + } + + public static class RetryFactory implements RetryPolicyFactory { + + int n; + boolean allowCrossZoneFallback; + + public RetryFactory(int n) { + this(n, true); + } + + public RetryFactory(int n, boolean allowFallback) { + this.n = n; + this.allowCrossZoneFallback = allowFallback; + } + + @Override + public RetryPolicy getRetryPolicy() { + return new RetryNTimes(n, allowCrossZoneFallback); + } + + @Override + public String toString() { + return "RetryFactory{" + + "n=" + n + + ", allowCrossZoneFallback=" + allowCrossZoneFallback + + '}'; + } + } + + private class RetryState { + private final int count; + private final boolean success; + + public RetryState(final int count, final boolean success) { + this.count = count; + this.success = success; + } + + @Override + public String toString() { + return "RetryState{" + + "count=" + count + + ", success=" + success + + '}'; + } + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/RunOnce.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/RunOnce.java index 729e47b6..0965aa8f 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/RunOnce.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/RunOnce.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,54 +20,53 @@ import com.netflix.dyno.connectionpool.RetryPolicy; /** - * Simple impl that allows at most one attempt which essentially mean no retries. - * - * @author poberai + * Simple impl that allows at most one attempt which essentially mean no retries. * + * @author poberai */ public class RunOnce implements RetryPolicy { - private AtomicInteger attempts = new AtomicInteger(0); - - @Override - public void begin() { - } + private AtomicInteger attempts = new AtomicInteger(0); + + @Override + public void begin() { + } + + @Override + public void success() { + attempts.incrementAndGet(); + } - @Override - public void success() { - attempts.incrementAndGet(); - } + @Override + public void failure(Exception e) { + attempts.incrementAndGet(); + } - @Override - public void failure(Exception e) { - attempts.incrementAndGet(); - } + @Override + public boolean allowRetry() { + return attempts.get() == 0; + } - @Override - public boolean allowRetry() { - return attempts.get() == 0; - } + @Override + public int getAttemptCount() { + return attempts.get() > 0 ? 1 : 0; + } - @Override - public int getAttemptCount() { - return attempts.get() > 0 ? 1 : 0; - } - - public static class RetryFactory implements RetryPolicyFactory { + public static class RetryFactory implements RetryPolicyFactory { - @Override - public RetryPolicy getRetryPolicy() { - return new RunOnce(); - } - } + @Override + public RetryPolicy getRetryPolicy() { + return new RunOnce(); + } + } - @Override - public boolean allowCrossZoneFallback() { - return false; - } + @Override + public boolean allowCrossZoneFallback() { + return false; + } - @Override - public String toString() { - return "RunOnce"; - } + @Override + public String toString() { + return "RunOnce"; + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/SimpleAsyncConnectionPoolImpl.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/SimpleAsyncConnectionPoolImpl.java index 171bad99..4679ce65 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/SimpleAsyncConnectionPoolImpl.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/SimpleAsyncConnectionPoolImpl.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -36,203 +36,205 @@ public class SimpleAsyncConnectionPoolImpl implements HostConnectionPool { - private static final Logger Logger = LoggerFactory.getLogger(SimpleAsyncConnectionPoolImpl.class); - - private final Host host; - private final ConnectionFactory connFactory; - private final ConnectionPoolConfiguration cpConfig; - private final ConnectionPoolMonitor cpMonitor; - - // state to track the connections being used - private final CircularList> rrSelector = new CircularList>(new ArrayList>()); - private final ConcurrentHashMap, Connection> connMap = new ConcurrentHashMap, Connection>(); - - // Tracking state of host connection pool. - private final AtomicBoolean active = new AtomicBoolean(false); - private final AtomicBoolean reconnecting = new AtomicBoolean(false); - - public SimpleAsyncConnectionPoolImpl(Host host, ConnectionFactory cFactory, - ConnectionPoolConfiguration config, ConnectionPoolMonitor monitor) { - - this.host = host; - this.connFactory = cFactory; - this.cpConfig = config; - this.cpMonitor = monitor; - } - - @Override - public Connection borrowConnection(int duration, TimeUnit unit) throws DynoException { - - if (!active.get()) { - throw new DynoConnectException("Cannot connect to pool when pool is shutdown for host: " + host); - } - - long start = System.currentTimeMillis(); - Connection connection = rrSelector.getNextElement(); - if (connection == null) { - throw new DynoConnectException("Cannot find connection for host: " + host); - } - cpMonitor.incConnectionBorrowed(host, System.currentTimeMillis() - start); - return connection; - } - - @Override - public boolean returnConnection(Connection connection) { - try { - if (!active.get()) { - // Just close the connection - return closeConnection(connection); - - } else { - // do nothing here - return false; - } - } finally { - cpMonitor.incConnectionReturned(host); - } - } - - @Override - public boolean closeConnection(Connection connection) { - try { - Connection prevConnection = connMap.remove(connection); - if (prevConnection != null) { - connection.close(); - rrSelector.removeElement(connection); - cpMonitor.incConnectionClosed(host, connection.getLastException()); - } - return true; - } catch (Exception e) { - Logger.error("Failed to close connection for host: " + host, e); - return false; - } finally { - } - } - - @Override - public void recycleConnection(Connection connection) { - this.closeConnection(connection); - cpMonitor.incConnectionReturned(host); - createConnection(); - cpMonitor.incConnectionRecycled(host); - } - - - @Override - public void markAsDown(DynoException reason) { - - if (!active.get()) { - return; // already marked as down - } - - active.compareAndSet(true, false); - } - - @Override - public void reconnect() { - - if (active.get()) { - Logger.info("Pool already active, ignoring reconnect connections request"); - return; - } - - if (reconnecting.get()) { - Logger.info("Pool already reconnecting, ignoring reconnect connections request"); - return; - } - - if (!(reconnecting.compareAndSet(false, true))) { - Logger.info("Pool already reconnecting, ignoring reconnect connections request"); - return; - } - - try { - shutdown(); - primeConnections(); - } finally { - reconnecting.set(false); - } - } - - @Override - public void shutdown() { - - Logger.info("Shutting down connection pool for host:" + host); - active.set(false); - - for (Connection connection : connMap.keySet()) { - closeConnection(connection); - } - - connMap.clear(); - } - - @Override - public int primeConnections() throws DynoException { - - Logger.info("Priming connection pool for host:" + host); - - if(active.get()) { - throw new DynoException("Connection pool has already been inited, cannot prime connections for host:" + host); - } - - int created = 0; - for (int i=0; i> getAllConnections() { - return connMap.keySet(); - } - - @Override - public int getConnectionTimeout() { - return cpConfig.getConnectTimeout(); - } - - @Override - public int getSocketTimeout() { - return cpConfig.getSocketTimeout(); - } - - private Connection createConnection() throws DynoException { - - Connection connection = connFactory.createConnection((HostConnectionPool) this, null); - connMap.put(connection, connection); - connection.open(); - rrSelector.addElement(connection); - - cpMonitor.incConnectionCreated(host); - return connection; - } - - @Override - public Host getHost() { - return host; - } - - @Override - public boolean isActive() { - return active.get(); - } - - @Override - public boolean isShutdown() { - return !active.get(); - } - - @Override - public int size() { return rrSelector.getSize(); } + private static final Logger Logger = LoggerFactory.getLogger(SimpleAsyncConnectionPoolImpl.class); + + private final Host host; + private final ConnectionFactory connFactory; + private final ConnectionPoolConfiguration cpConfig; + private final ConnectionPoolMonitor cpMonitor; + + // state to track the connections being used + private final CircularList> rrSelector = new CircularList>(new ArrayList>()); + private final ConcurrentHashMap, Connection> connMap = new ConcurrentHashMap, Connection>(); + + // Tracking state of host connection pool. + private final AtomicBoolean active = new AtomicBoolean(false); + private final AtomicBoolean reconnecting = new AtomicBoolean(false); + + public SimpleAsyncConnectionPoolImpl(Host host, ConnectionFactory cFactory, + ConnectionPoolConfiguration config, ConnectionPoolMonitor monitor) { + + this.host = host; + this.connFactory = cFactory; + this.cpConfig = config; + this.cpMonitor = monitor; + } + + @Override + public Connection borrowConnection(int duration, TimeUnit unit) throws DynoException { + + if (!active.get()) { + throw new DynoConnectException("Cannot connect to pool when pool is shutdown for host: " + host); + } + + long start = System.currentTimeMillis(); + Connection connection = rrSelector.getNextElement(); + if (connection == null) { + throw new DynoConnectException("Cannot find connection for host: " + host); + } + cpMonitor.incConnectionBorrowed(host, System.currentTimeMillis() - start); + return connection; + } + + @Override + public boolean returnConnection(Connection connection) { + try { + if (!active.get()) { + // Just close the connection + return closeConnection(connection); + + } else { + // do nothing here + return false; + } + } finally { + cpMonitor.incConnectionReturned(host); + } + } + + @Override + public boolean closeConnection(Connection connection) { + try { + Connection prevConnection = connMap.remove(connection); + if (prevConnection != null) { + connection.close(); + rrSelector.removeElement(connection); + cpMonitor.incConnectionClosed(host, connection.getLastException()); + } + return true; + } catch (Exception e) { + Logger.error("Failed to close connection for host: " + host, e); + return false; + } finally { + } + } + + @Override + public void recycleConnection(Connection connection) { + this.closeConnection(connection); + cpMonitor.incConnectionReturned(host); + createConnection(); + cpMonitor.incConnectionRecycled(host); + } + + + @Override + public void markAsDown(DynoException reason) { + + if (!active.get()) { + return; // already marked as down + } + + active.compareAndSet(true, false); + } + + @Override + public void reconnect() { + + if (active.get()) { + Logger.info("Pool already active, ignoring reconnect connections request"); + return; + } + + if (reconnecting.get()) { + Logger.info("Pool already reconnecting, ignoring reconnect connections request"); + return; + } + + if (!(reconnecting.compareAndSet(false, true))) { + Logger.info("Pool already reconnecting, ignoring reconnect connections request"); + return; + } + + try { + shutdown(); + primeConnections(); + } finally { + reconnecting.set(false); + } + } + + @Override + public void shutdown() { + + Logger.info("Shutting down connection pool for host:" + host); + active.set(false); + + for (Connection connection : connMap.keySet()) { + closeConnection(connection); + } + + connMap.clear(); + } + + @Override + public int primeConnections() throws DynoException { + + Logger.info("Priming connection pool for host:" + host); + + if (active.get()) { + throw new DynoException("Connection pool has already been inited, cannot prime connections for host:" + host); + } + + int created = 0; + for (int i = 0; i < cpConfig.getMaxConnsPerHost(); i++) { + try { + createConnection(); + created++; + } catch (DynoConnectException e) { + Logger.error("Failed to create connection", e); + cpMonitor.incConnectionCreateFailed(host, e); + throw e; + } + } + active.compareAndSet(false, true); + + return created; + } + + @Override + public Collection> getAllConnections() { + return connMap.keySet(); + } + + @Override + public int getConnectionTimeout() { + return cpConfig.getConnectTimeout(); + } + + @Override + public int getSocketTimeout() { + return cpConfig.getSocketTimeout(); + } + + private Connection createConnection() throws DynoException { + + Connection connection = connFactory.createConnection((HostConnectionPool) this, null); + connMap.put(connection, connection); + connection.open(); + rrSelector.addElement(connection); + + cpMonitor.incConnectionCreated(host); + return connection; + } + + @Override + public Host getHost() { + return host; + } + + @Override + public boolean isActive() { + return active.get(); + } + + @Override + public boolean isShutdown() { + return !active.get(); + } + + @Override + public int size() { + return rrSelector.getSize(); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/BinarySearchTokenMapper.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/BinarySearchTokenMapper.java index e4d09116..e56877d1 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/BinarySearchTokenMapper.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/BinarySearchTokenMapper.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,105 +28,104 @@ import com.netflix.dyno.connectionpool.impl.lb.HostToken; /** - * Impl of {@link HashPartitioner} that can be used to keys to the dynomite topology ring using the binary search mechanism. - * Note that the class only performs the function of binary search to locate a hash token on the dynomite topology ring. - * The hash token to be generated from the key is generated using the HashPartitioner provided to this class. - * + * Impl of {@link HashPartitioner} that can be used to keys to the dynomite topology ring using the binary search mechanism. + * Note that the class only performs the function of binary search to locate a hash token on the dynomite topology ring. + * The hash token to be generated from the key is generated using the HashPartitioner provided to this class. + * * @author poberai * @author ipapapa - * */ public class BinarySearchTokenMapper implements HashPartitioner { - private final HashPartitioner partitioner; - - private final AtomicReference> binarySearch = new AtomicReference>(null); - private final ConcurrentHashMap tokenMap = new ConcurrentHashMap(); - - public BinarySearchTokenMapper(HashPartitioner p) { - this.partitioner = p; - } - - @Override - public Long hash(int key) { - return partitioner.hash(key); - } - - @Override - public Long hash(long key) { - return partitioner.hash(key); - } - - @Override - public Long hash(String key) { - return partitioner.hash(key); - } - - @Override - public Long hash(byte[] key) { - return partitioner.hash(key); - } - - @Override - public HostToken getToken(Long keyHash) { - Long token = binarySearch.get().getTokenOwner(keyHash); - if (token == null) { - throw new NoAvailableHostsException("Token not found for key hash: " + keyHash); - } - return tokenMap.get(token); - } - - public void initSearchMechanism(Collection hostTokens) { - - for (HostToken hostToken : hostTokens) { - tokenMap.put(hostToken.getToken(), hostToken); - } - initBinarySearch(); - } - - public void addHostToken(HostToken hostToken) { - - HostToken prevToken = tokenMap.putIfAbsent(hostToken.getToken(), hostToken); - if (prevToken == null) { - initBinarySearch(); - } - } - - public void remoteHostToken(HostToken hostToken) { - - HostToken prevToken = tokenMap.remove(hostToken.getToken()); - if (prevToken != null) { - initBinarySearch(); - } - } - - public void removeHost(Host host) { - - HostToken theToken = null; - - for (HostToken token : tokenMap.values()) { - if (token.getHost().equals(host)) { - theToken = token; - break; - } - } - - if (theToken != null) { - remoteHostToken(theToken); - } - } - - private void initBinarySearch() { - List tokens = new ArrayList(tokenMap.keySet()); - Collections.sort(tokens); - binarySearch.set(new DynoBinarySearch(tokens)); - } - - public boolean isEmpty() { - return this.tokenMap.size() == 0; - } - - public String toString() { - return binarySearch.toString(); - } + private final HashPartitioner partitioner; + + private final AtomicReference> binarySearch = new AtomicReference>(null); + private final ConcurrentHashMap tokenMap = new ConcurrentHashMap(); + + public BinarySearchTokenMapper(HashPartitioner p) { + this.partitioner = p; + } + + @Override + public Long hash(int key) { + return partitioner.hash(key); + } + + @Override + public Long hash(long key) { + return partitioner.hash(key); + } + + @Override + public Long hash(String key) { + return partitioner.hash(key); + } + + @Override + public Long hash(byte[] key) { + return partitioner.hash(key); + } + + @Override + public HostToken getToken(Long keyHash) { + Long token = binarySearch.get().getTokenOwner(keyHash); + if (token == null) { + throw new NoAvailableHostsException("Token not found for key hash: " + keyHash); + } + return tokenMap.get(token); + } + + public void initSearchMechanism(Collection hostTokens) { + + for (HostToken hostToken : hostTokens) { + tokenMap.put(hostToken.getToken(), hostToken); + } + initBinarySearch(); + } + + public void addHostToken(HostToken hostToken) { + + HostToken prevToken = tokenMap.putIfAbsent(hostToken.getToken(), hostToken); + if (prevToken == null) { + initBinarySearch(); + } + } + + public void remoteHostToken(HostToken hostToken) { + + HostToken prevToken = tokenMap.remove(hostToken.getToken()); + if (prevToken != null) { + initBinarySearch(); + } + } + + public void removeHost(Host host) { + + HostToken theToken = null; + + for (HostToken token : tokenMap.values()) { + if (token.getHost().equals(host)) { + theToken = token; + break; + } + } + + if (theToken != null) { + remoteHostToken(theToken); + } + } + + private void initBinarySearch() { + List tokens = new ArrayList(tokenMap.keySet()); + Collections.sort(tokens); + binarySearch.set(new DynoBinarySearch(tokens)); + } + + public boolean isEmpty() { + return this.tokenMap.size() == 0; + } + + public String toString() { + return binarySearch.toString(); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/DynoBinarySearch.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/DynoBinarySearch.java index fbc7aa12..7c1998a0 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/DynoBinarySearch.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/DynoBinarySearch.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,181 +25,180 @@ /** * Utility class that maps a given token hashed from a key using a {@link HashPartitioner} * to a dynomite server on the dynomite topology ring. - * - * Note that as long as the Token T implements the comparable interface this class can be used - * to perform the bin search on other homogeneous lists as well. - * + *

+ * Note that as long as the Token T implements the comparable interface this class can be used + * to perform the bin search on other homogeneous lists as well. + *

* Here are the imp details of the mapping algorithm - * 1. If a hashed token directly maps to a point on that ring, then that point is chosen. - * 2. If a hashed token maps between 2 points A and B where A > B then B is chosen as the owner of the token - * 3. All hashed tokens that go past the last point on the ring are mapped to the first point on the ring. - * - * e.g - * - * Consider the following points on the ring. - * - * 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 - * - * Elements 0 .. 9 --> 10 - * 10 --> 10 - * 15 --> 20 - * 30 --> 30 - * 58 --> 60 - * 100 --> 100 - * 100 + --> 10 - * - * @author poberai + * 1. If a hashed token directly maps to a point on that ring, then that point is chosen. + * 2. If a hashed token maps between 2 points A and B where A > B then B is chosen as the owner of the token + * 3. All hashed tokens that go past the last point on the ring are mapped to the first point on the ring. + *

+ * e.g + *

+ * Consider the following points on the ring. + *

+ * 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 + *

+ * Elements 0 .. 9 --> 10 + * 10 --> 10 + * 15 --> 20 + * 30 --> 30 + * 58 --> 60 + * 100 --> 100 + * 100 + --> 10 * * @param + * @author poberai */ public class DynoBinarySearch> { - - private final List> rangeList = new ArrayList>(); - - private final AtomicBoolean listEmpty = new AtomicBoolean(false); - - public DynoBinarySearch(List list) { - - if (list.isEmpty()) { - listEmpty.set(true); - return; - } - - if (list.size() == 1) { - rangeList.add(new DynoTokenRange(null, list.get(0))); - - } else { - // add the first range - rangeList.add(new DynoTokenRange(null, list.get(0))); - // add rest of the tokens - for (int i=1; i<(list.size()); i++) { - rangeList.add(new DynoTokenRange(list.get(i-1), list.get(i))); - } - - rangeList.get(rangeList.size()-1).isLastRange = true; - } - } - - - public T getTokenOwner(T token) { - - // Some quick boundary checks - if (listEmpty.get()) { - return null; - } - - if (rangeList.size() == 1) { - return rangeList.get(0).getTokenOwner(); - } - - DynoTokenRange firstRange = rangeList.get(0); - DynoTokenRange lastRange = rangeList.get(rangeList.size()-1); - - if (firstRange.compareTo(token) == 0) { - // Token is smaller than FIRST range, map to first range. - return firstRange.getTokenOwner(); - } - - if (lastRange.compareTo(token) < 0) { - // Token is greater than LAST range, map to first range. - return firstRange.getTokenOwner(); - } - - int index = Collections.binarySearch(rangeList, token); - - if (index < 0) { - throw new RuntimeException("Token not found!: " + token); - } - - return rangeList.get(index).getTokenOwner(); - } - - public String toString() { - - StringBuilder sb = new StringBuilder("[DynoBinarySearch:\n"); - for (DynoTokenRange r : rangeList) { - sb.append(r.toString()).append("\n"); - } - sb.append("]"); - return sb.toString(); - } - - static class DynoTokenRange> implements Comparable { - - final T start; - final T end; - boolean isFirstRange = false; - boolean isLastRange = false; - - DynoTokenRange(T s, T e) { - this.start = s; - this.end = e; - - if (s == null) { - isFirstRange = true; - } - - if (isFirstRange) { - if (end == null) { - throw new RuntimeException("Bad Range: end must not be null"); - } - } else if (!(lessThan(start, end))) { - throw new RuntimeException("Bad Range: start must be less than end: " + this.toString()); - } - } - - public T getTokenOwner() { - return end; - } - - public String toString() { - if (isFirstRange) { - return "(null," + end + "]"; - } else { - return "(" + start + "," + end + "]"; - } - } - - @Override - public int compareTo(T key) { - - // Boundary checks, to be safe! - - if (isFirstRange) { - - if (lessThanEquals(key, end)) { - return 0; // This key is within this range - } else { - // else This range is smaller than this key - return -1; - } - } - - // Functionality for any other range i.e in another position in the list except for the first - if (lessThanEquals(key, start)) { - // This range is greater than the key - return 1; - } - - if (lessThan(start, key) && lessThanEquals(key, end)) { - // This key is within this range - return 0; - } - - if (lessThan(end, key)) { - // This range is smaller than this key - return -1; - } else { - throw new RuntimeException("Invalid key for bin search: " + key + ", this range: " + this.toString()); - } - } - - private boolean lessThan(T left, T right) { - return left.compareTo(right) < 0; - } - - private boolean lessThanEquals(T left, T right) { - return left.compareTo(right) <= 0; - } - } + + private final List> rangeList = new ArrayList>(); + + private final AtomicBoolean listEmpty = new AtomicBoolean(false); + + public DynoBinarySearch(List list) { + + if (list.isEmpty()) { + listEmpty.set(true); + return; + } + + if (list.size() == 1) { + rangeList.add(new DynoTokenRange(null, list.get(0))); + + } else { + // add the first range + rangeList.add(new DynoTokenRange(null, list.get(0))); + // add rest of the tokens + for (int i = 1; i < (list.size()); i++) { + rangeList.add(new DynoTokenRange(list.get(i - 1), list.get(i))); + } + + rangeList.get(rangeList.size() - 1).isLastRange = true; + } + } + + + public T getTokenOwner(T token) { + + // Some quick boundary checks + if (listEmpty.get()) { + return null; + } + + if (rangeList.size() == 1) { + return rangeList.get(0).getTokenOwner(); + } + + DynoTokenRange firstRange = rangeList.get(0); + DynoTokenRange lastRange = rangeList.get(rangeList.size() - 1); + + if (firstRange.compareTo(token) == 0) { + // Token is smaller than FIRST range, map to first range. + return firstRange.getTokenOwner(); + } + + if (lastRange.compareTo(token) < 0) { + // Token is greater than LAST range, map to first range. + return firstRange.getTokenOwner(); + } + + int index = Collections.binarySearch(rangeList, token); + + if (index < 0) { + throw new RuntimeException("Token not found!: " + token); + } + + return rangeList.get(index).getTokenOwner(); + } + + public String toString() { + + StringBuilder sb = new StringBuilder("[DynoBinarySearch:\n"); + for (DynoTokenRange r : rangeList) { + sb.append(r.toString()).append("\n"); + } + sb.append("]"); + return sb.toString(); + } + + static class DynoTokenRange> implements Comparable { + + final T start; + final T end; + boolean isFirstRange = false; + boolean isLastRange = false; + + DynoTokenRange(T s, T e) { + this.start = s; + this.end = e; + + if (s == null) { + isFirstRange = true; + } + + if (isFirstRange) { + if (end == null) { + throw new RuntimeException("Bad Range: end must not be null"); + } + } else if (!(lessThan(start, end))) { + throw new RuntimeException("Bad Range: start must be less than end: " + this.toString()); + } + } + + public T getTokenOwner() { + return end; + } + + public String toString() { + if (isFirstRange) { + return "(null," + end + "]"; + } else { + return "(" + start + "," + end + "]"; + } + } + + @Override + public int compareTo(T key) { + + // Boundary checks, to be safe! + + if (isFirstRange) { + + if (lessThanEquals(key, end)) { + return 0; // This key is within this range + } else { + // else This range is smaller than this key + return -1; + } + } + + // Functionality for any other range i.e in another position in the list except for the first + if (lessThanEquals(key, start)) { + // This range is greater than the key + return 1; + } + + if (lessThan(start, key) && lessThanEquals(key, end)) { + // This key is within this range + return 0; + } + + if (lessThan(end, key)) { + // This range is smaller than this key + return -1; + } else { + throw new RuntimeException("Invalid key for bin search: " + key + ", this range: " + this.toString()); + } + } + + private boolean lessThan(T left, T right) { + return left.compareTo(right) < 0; + } + + private boolean lessThanEquals(T left, T right) { + return left.compareTo(right) <= 0; + } + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur1Hash.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur1Hash.java index 1a68f8ad..62351f73 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur1Hash.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur1Hash.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,115 +19,115 @@ import java.nio.ByteOrder; public class Murmur1Hash { - - /** - * Hashes bytes in part of an array. - * @param data The data to hash. - * @param offset Where to start munging. - * @param length How many bytes to process. - * @param seed The seed to start with. - * @return The 32-bit hash of the data in question. - */ - public static int hash(byte[] data, int offset, int length, int seed) { - return hash(ByteBuffer.wrap(data, offset, length), seed); - } - - public static int hash(byte[] data, int length) { - - int seed = (0xdeadbeef * length); - - return hash(ByteBuffer.wrap(data, 0, length), seed); - } - - /** - * Hashes the bytes in a buffer from the current position to the limit. - * @param buf The bytes to hash. - * @param seed The seed for the hash. - * @return The 32 bit murmur hash of the bytes in the buffer. - */ - public static int hash(ByteBuffer buf, int seed) { - - // save byte order for later restoration - ByteOrder byteOrder = buf.order(); - buf.order(ByteOrder.LITTLE_ENDIAN); - - int m = 0x5bd1e995; - int r = 24; - - int h = seed ^ buf.remaining(); - - while (buf.remaining() >= 4) { - - int k = buf.getInt(); - - k *= m; - k ^= k >>> r; - k *= m; - h *= m; - h ^= k; - } - - if (buf.remaining() > 0) { - ByteBuffer finish = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN); - // for big-endian version, use this first: - // finish.position(4-buf.remaining()); - finish.put(buf).rewind(); - h ^= finish.getInt(); - h *= m; - } - - h ^= h >>> 13; - h *= m; - h ^= h >>> 15; - - buf.order(byteOrder); - return h; - } - - - public static long hash64A(byte[] data, int seed) { - return hash64A(ByteBuffer.wrap(data), seed); - } - - public static long hash64A(byte[] data, int offset, int length, int seed) { - return hash64A(ByteBuffer.wrap(data, offset, length), seed); - } - - public static long hash64A(ByteBuffer buf, int seed) { - ByteOrder byteOrder = buf.order(); - buf.order(ByteOrder.LITTLE_ENDIAN); - - long m = 0xc6a4a7935bd1e995L; - int r = 47; - - long h = seed ^ (buf.remaining() * m); - - while (buf.remaining() >= 8) { - long k = buf.getLong(); - - k *= m; - k ^= k >>> r; - k *= m; - - h ^= k; - h *= m; - } - - if (buf.remaining() > 0) { - ByteBuffer finish = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN); - // for big-endian version, do this first: - // finish.position(8-buf.remaining()); - finish.put(buf).rewind(); - h ^= finish.getLong(); - h *= m; - } - - h ^= h >>> r; - h *= m; - h ^= h >>> r; - - buf.order(byteOrder); - return h; - } + + /** + * Hashes bytes in part of an array. + * @param data The data to hash. + * @param offset Where to start munging. + * @param length How many bytes to process. + * @param seed The seed to start with. + * @return The 32-bit hash of the data in question. + */ + public static int hash(byte[] data, int offset, int length, int seed) { + return hash(ByteBuffer.wrap(data, offset, length), seed); + } + + public static int hash(byte[] data, int length) { + + int seed = (0xdeadbeef * length); + + return hash(ByteBuffer.wrap(data, 0, length), seed); + } + + /** + * Hashes the bytes in a buffer from the current position to the limit. + * @param buf The bytes to hash. + * @param seed The seed for the hash. + * @return The 32 bit murmur hash of the bytes in the buffer. + */ + public static int hash(ByteBuffer buf, int seed) { + + // save byte order for later restoration + ByteOrder byteOrder = buf.order(); + buf.order(ByteOrder.LITTLE_ENDIAN); + + int m = 0x5bd1e995; + int r = 24; + + int h = seed ^ buf.remaining(); + + while (buf.remaining() >= 4) { + + int k = buf.getInt(); + + k *= m; + k ^= k >>> r; + k *= m; + h *= m; + h ^= k; + } + + if (buf.remaining() > 0) { + ByteBuffer finish = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN); + // for big-endian version, use this first: + // finish.position(4-buf.remaining()); + finish.put(buf).rewind(); + h ^= finish.getInt(); + h *= m; + } + + h ^= h >>> 13; + h *= m; + h ^= h >>> 15; + + buf.order(byteOrder); + return h; + } + + + public static long hash64A(byte[] data, int seed) { + return hash64A(ByteBuffer.wrap(data), seed); + } + + public static long hash64A(byte[] data, int offset, int length, int seed) { + return hash64A(ByteBuffer.wrap(data, offset, length), seed); + } + + public static long hash64A(ByteBuffer buf, int seed) { + ByteOrder byteOrder = buf.order(); + buf.order(ByteOrder.LITTLE_ENDIAN); + + long m = 0xc6a4a7935bd1e995L; + int r = 47; + + long h = seed ^ (buf.remaining() * m); + + while (buf.remaining() >= 8) { + long k = buf.getLong(); + + k *= m; + k ^= k >>> r; + k *= m; + + h ^= k; + h *= m; + } + + if (buf.remaining() > 0) { + ByteBuffer finish = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN); + // for big-endian version, do this first: + // finish.position(8-buf.remaining()); + finish.put(buf).rewind(); + h ^= finish.getLong(); + h *= m; + } + + h ^= h >>> r; + h *= m; + h ^= h >>> r; + + buf.order(byteOrder); + return h; + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur1HashPartitioner.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur1HashPartitioner.java index b54b09d6..8c5b78bf 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur1HashPartitioner.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur1HashPartitioner.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -32,45 +32,45 @@ public class Murmur1HashPartitioner implements HashPartitioner { private static final Charset charset = Charset.forName(UTF_8); @Override - public Long hash(String key) { + public Long hash(String key) { if (key == null) { return 0L; } ByteBuffer bb = ByteBuffer.wrap(key.getBytes(charset)); byte[] b = bb.array(); return UnsignedIntsUtils.toLong(Murmur1Hash.hash(b, b.length)); - } - - @Override - public Long hash(byte[] key) { - if (key == null) { - return 0L; - } + } + + @Override + public Long hash(byte[] key) { + if (key == null) { + return 0L; + } return UnsignedIntsUtils.toLong(Murmur1Hash.hash(key, key.length)); - } - + } + @Override - public Long hash(long key) { - - ByteBuffer bb = ByteBuffer.allocate(8).putLong(0, key); - bb.rewind(); + public Long hash(long key) { + + ByteBuffer bb = ByteBuffer.allocate(8).putLong(0, key); + bb.rewind(); byte[] b = bb.array(); return UnsignedIntsUtils.toLong(Murmur1Hash.hash(b, b.length)); - } + } @Override - public Long hash(int key) { - ByteBuffer bb = ByteBuffer.allocate(4); + public Long hash(int key) { + ByteBuffer bb = ByteBuffer.allocate(4); bb.putInt(key); bb.rewind(); byte[] b = bb.array(); return UnsignedIntsUtils.toLong(Murmur1Hash.hash(b, b.length)); - } + } - @Override - public HostToken getToken(Long keyHash) { - throw new RuntimeException("NotImplemented"); - } + @Override + public HostToken getToken(Long keyHash) { + throw new RuntimeException("NotImplemented"); + } } \ No newline at end of file diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur2Hash.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur2Hash.java index 4f704d92..57590be9 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur2Hash.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur2Hash.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,31 +15,32 @@ */ package com.netflix.dyno.connectionpool.impl.hash; -/** +/** * murmur hash 2.0. - * + * * The murmur hash is a relatively fast hash function from * http://murmurhash.googlepages.com/ for platforms with efficient * multiplication. - * + * * This is a re-implementation of the original C code plus some * additional features. - * + * * Public domain. - * + * * @author Viliam Holub * @version 1.0.2 * */ public final class Murmur2Hash { - + // all methods static; private constructor. - private Murmur2Hash() {} + private Murmur2Hash() { + } - /** + /** * Generates 32 bit hash from byte array of the given length and * seed. - * + * * @param data byte array to hash * @param length length of the array to hash * @param seed initial seed value @@ -52,25 +53,28 @@ public static int hash32(final byte[] data, int length, int seed) { final int r = 24; // Initialize the hash to a random value - int h = seed^length; - int length4 = length/4; + int h = seed ^ length; + int length4 = length / 4; - for (int i=0; i>> r; k *= m; h *= m; h ^= k; } - + // Handle the last few bytes of the input array - switch (length%4) { - case 3: h ^= (data[(length&~3) +2]&0xff) << 16; - case 2: h ^= (data[(length&~3) +1]&0xff) << 8; - case 1: h ^= (data[length&~3]&0xff); + switch (length % 4) { + case 3: + h ^= (data[(length & ~3) + 2] & 0xff) << 16; + case 2: + h ^= (data[(length & ~3) + 1] & 0xff) << 8; + case 1: + h ^= (data[length & ~3] & 0xff); h *= m; } @@ -80,44 +84,44 @@ public static int hash32(final byte[] data, int length, int seed) { return h; } - - /** + + /** * Generates 32 bit hash from byte array with default seed value. - * + * * @param data byte array to hash * @param length length of the array to hash * @return 32 bit hash of the given array */ public static int hash32(final byte[] data, int length) { - return hash32(data, length, 0x9747b28c); + return hash32(data, length, 0x9747b28c); } - /** + /** * Generates 32 bit hash from a string. - * + * * @param text string to hash * @return 32 bit hash of the given string */ public static int hash32(final String text) { - final byte[] bytes = text.getBytes(); + final byte[] bytes = text.getBytes(); return hash32(bytes, bytes.length); } - /** + /** * Generates 32 bit hash from a substring. - * + * * @param text string to hash * @param from starting index * @param length length of the substring to hash * @return 32 bit hash of the given string */ public static int hash32(final String text, int from, int length) { - return hash32(text.substring( from, from+length)); + return hash32(text.substring(from, from + length)); } - - /** + + /** * Generates 64 bit hash from byte array of the given length and seed. - * + * * @param data byte array to hash * @param length length of the array to hash * @param seed initial seed value @@ -127,46 +131,54 @@ public static long hash64(final byte[] data, int length, int seed) { final long m = 0xc6a4a7935bd1e995L; final int r = 47; - long h = (seed&0xffffffffl)^(length*m); + long h = (seed & 0xffffffffl) ^ (length * m); - int length8 = length/8; + int length8 = length / 8; + + for (int i = 0; i < length8; i++) { + final int i8 = i * 8; + long k = ((long) data[i8 + 0] & 0xff) + (((long) data[i8 + 1] & 0xff) << 8) + + (((long) data[i8 + 2] & 0xff) << 16) + (((long) data[i8 + 3] & 0xff) << 24) + + (((long) data[i8 + 4] & 0xff) << 32) + (((long) data[i8 + 5] & 0xff) << 40) + + (((long) data[i8 + 6] & 0xff) << 48) + (((long) data[i8 + 7] & 0xff) << 56); - for (int i=0; i>> r; k *= m; - + h ^= k; - h *= m; + h *= m; } - - switch (length%8) { - case 7: h ^= (long)(data[(length&~7)+6]&0xff) << 48; - case 6: h ^= (long)(data[(length&~7)+5]&0xff) << 40; - case 5: h ^= (long)(data[(length&~7)+4]&0xff) << 32; - case 4: h ^= (long)(data[(length&~7)+3]&0xff) << 24; - case 3: h ^= (long)(data[(length&~7)+2]&0xff) << 16; - case 2: h ^= (long)(data[(length&~7)+1]&0xff) << 8; - case 1: h ^= (long)(data[length&~7]&0xff); + + switch (length % 8) { + case 7: + h ^= (long) (data[(length & ~7) + 6] & 0xff) << 48; + case 6: + h ^= (long) (data[(length & ~7) + 5] & 0xff) << 40; + case 5: + h ^= (long) (data[(length & ~7) + 4] & 0xff) << 32; + case 4: + h ^= (long) (data[(length & ~7) + 3] & 0xff) << 24; + case 3: + h ^= (long) (data[(length & ~7) + 2] & 0xff) << 16; + case 2: + h ^= (long) (data[(length & ~7) + 1] & 0xff) << 8; + case 1: + h ^= (long) (data[length & ~7] & 0xff); h *= m; - }; - + } + ; + h ^= h >>> r; h *= m; h ^= h >>> r; return h; } - - /** + + /** * Generates 64 bit hash from byte array with default seed value. - * + * * @param data byte array to hash * @param length length of the array to hash * @return 64 bit hash of the given string @@ -175,26 +187,26 @@ public static long hash64(final byte[] data, int length) { return hash64(data, length, 0xe17a1465); } - /** + /** * Generates 64 bit hash from a string. - * + * * @param text string to hash * @return 64 bit hash of the given string */ public static long hash64(final String text) { - final byte[] bytes = text.getBytes(); + final byte[] bytes = text.getBytes(); return hash64(bytes, bytes.length); } - /** + /** * Generates 64 bit hash from a substring. - * + * * @param text string to hash * @param from starting index * @param length length of the substring to hash * @return 64 bit hash of the given array */ public static long hash64(final String text, int from, int length) { - return hash64(text.substring( from, from+length)); + return hash64(text.substring(from, from + length)); } } \ No newline at end of file diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur2HashPartitioner.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur2HashPartitioner.java index 616f6777..333b822e 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur2HashPartitioner.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur2HashPartitioner.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,52 +27,52 @@ * */ public class Murmur2HashPartitioner implements HashPartitioner { - - private static final String UTF_8 = "UTF-8"; - private static final Charset charset = Charset.forName(UTF_8); - public Murmur2HashPartitioner() { - } + private static final String UTF_8 = "UTF-8"; + private static final Charset charset = Charset.forName(UTF_8); + + public Murmur2HashPartitioner() { + } + + @Override + public Long hash(long key) { + + ByteBuffer bb = ByteBuffer.allocate(8).putLong(0, key); + byte[] b = bb.array(); + return UnsignedIntsUtils.toLong(Murmur2Hash.hash32(b, b.length)); + } + + @Override + public Long hash(int key) { + + ByteBuffer bb = ByteBuffer.allocate(4); + bb.putInt(key); + bb.rewind(); - @Override - public Long hash(long key) { - - ByteBuffer bb = ByteBuffer.allocate(8).putLong(0, key); - byte[] b = bb.array(); - return UnsignedIntsUtils.toLong(Murmur2Hash.hash32(b, b.length)); - } + byte[] b = bb.array(); + return UnsignedIntsUtils.toLong(Murmur2Hash.hash32(b, b.length)); + } - @Override - public Long hash(int key) { - - ByteBuffer bb = ByteBuffer.allocate(4); - bb.putInt(key); - bb.rewind(); - - byte[] b = bb.array(); - return UnsignedIntsUtils.toLong(Murmur2Hash.hash32(b, b.length)); - } + @Override + public Long hash(String key) { + if (key == null) { + return 0L; + } + ByteBuffer bb = ByteBuffer.wrap(key.getBytes(charset)); + byte[] b = bb.array(); + return UnsignedIntsUtils.toLong(Murmur2Hash.hash32(b, b.length)); + } - @Override - public Long hash(String key) { - if (key == null) { - return 0L; - } - ByteBuffer bb = ByteBuffer.wrap(key.getBytes(charset)); - byte[] b = bb.array(); - return UnsignedIntsUtils.toLong(Murmur2Hash.hash32(b, b.length)); - } - - @Override - public Long hash(byte[] key) { - if (key == null) { - return 0L; - } - return UnsignedIntsUtils.toLong(Murmur2Hash.hash32(key, key.length)); - } + @Override + public Long hash(byte[] key) { + if (key == null) { + return 0L; + } + return UnsignedIntsUtils.toLong(Murmur2Hash.hash32(key, key.length)); + } - @Override - public HostToken getToken(Long keyHash) { - throw new RuntimeException("NotImplemented"); - } + @Override + public HostToken getToken(Long keyHash) { + throw new RuntimeException("NotImplemented"); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur3Hash.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur3Hash.java index fa703a4b..036c1365 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur3Hash.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur3Hash.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,63 +17,63 @@ public class Murmur3Hash { - /** Returns the MurmurHash3_x86_32 hash. */ - - public static int hash32(byte[] data, int length) { - return murmurhash3x8632(data, 0, length, 0); - } - - public static int murmurhash3x8632(byte[] data, int offset, int len, int seed) { + /** Returns the MurmurHash3_x86_32 hash. */ - int c1 = 0xcc9e2d51; - int c2 = 0x1b873593; + public static int hash32(byte[] data, int length) { + return murmurhash3x8632(data, 0, length, 0); + } - int h1 = seed; - int roundedEnd = offset + (len & 0xfffffffc); // round down to 4 byte block + public static int murmurhash3x8632(byte[] data, int offset, int len, int seed) { - for (int i = offset; i < roundedEnd; i += 4) { - // little endian load order - int k1 = (data[i] & 0xff) | ((data[i + 1] & 0xff) << 8) | ((data[i + 2] & 0xff) << 16) | (data[i + 3] << 24); - k1 *= c1; - k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15); - k1 *= c2; + int c1 = 0xcc9e2d51; + int c2 = 0x1b873593; - h1 ^= k1; - h1 = (h1 << 13) | (h1 >>> 19); // ROTL32(h1,13); - h1 = h1 * 5 + 0xe6546b64; - } + int h1 = seed; + int roundedEnd = offset + (len & 0xfffffffc); // round down to 4 byte block - // tail - int k1 = 0; + for (int i = offset; i < roundedEnd; i += 4) { + // little endian load order + int k1 = (data[i] & 0xff) | ((data[i + 1] & 0xff) << 8) | ((data[i + 2] & 0xff) << 16) | (data[i + 3] << 24); + k1 *= c1; + k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15); + k1 *= c2; - switch(len & 0x03) { - case 3: - k1 = (data[roundedEnd + 2] & 0xff) << 16; - // fallthrough - case 2: - k1 |= (data[roundedEnd + 1] & 0xff) << 8; - // fallthrough - case 1: - k1 |= data[roundedEnd] & 0xff; - k1 *= c1; - k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15); - k1 *= c2; - h1 ^= k1; - default: - } + h1 ^= k1; + h1 = (h1 << 13) | (h1 >>> 19); // ROTL32(h1,13); + h1 = h1 * 5 + 0xe6546b64; + } - // finalization - h1 ^= len; + // tail + int k1 = 0; - // fmix(h1); - h1 ^= h1 >>> 16; - h1 *= 0x85ebca6b; - h1 ^= h1 >>> 13; - h1 *= 0xc2b2ae35; - h1 ^= h1 >>> 16; + switch (len & 0x03) { + case 3: + k1 = (data[roundedEnd + 2] & 0xff) << 16; + // fallthrough + case 2: + k1 |= (data[roundedEnd + 1] & 0xff) << 8; + // fallthrough + case 1: + k1 |= data[roundedEnd] & 0xff; + k1 *= c1; + k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15); + k1 *= c2; + h1 ^= k1; + default: + } - return h1; - } + // finalization + h1 ^= len; + + // fmix(h1); + h1 ^= h1 >>> 16; + h1 *= 0x85ebca6b; + h1 ^= h1 >>> 13; + h1 *= 0xc2b2ae35; + h1 ^= h1 >>> 16; + + return h1; + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur3HashPartitioner.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur3HashPartitioner.java index 93da0ba6..234f55ca 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur3HashPartitioner.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/Murmur3HashPartitioner.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,51 +28,51 @@ */ public class Murmur3HashPartitioner implements HashPartitioner { - private static final String UTF_8 = "UTF-8"; - private static final Charset charset = Charset.forName(UTF_8); + private static final String UTF_8 = "UTF-8"; + private static final Charset charset = Charset.forName(UTF_8); + + public Murmur3HashPartitioner() { + } - public Murmur3HashPartitioner() { - } + @Override + public Long hash(long key) { - @Override - public Long hash(long key) { + ByteBuffer bb = ByteBuffer.allocate(8).putLong(0, key); + byte[] b = bb.array(); + return UnsignedIntsUtils.toLong(Murmur3Hash.hash32(b, b.length)); + } - ByteBuffer bb = ByteBuffer.allocate(8).putLong(0, key); - byte[] b = bb.array(); - return UnsignedIntsUtils.toLong(Murmur3Hash.hash32(b, b.length)); - } + @Override + public Long hash(int key) { - @Override - public Long hash(int key) { + ByteBuffer bb = ByteBuffer.allocate(4); + bb.putInt(key); + bb.rewind(); - ByteBuffer bb = ByteBuffer.allocate(4); - bb.putInt(key); - bb.rewind(); + byte[] b = bb.array(); + return UnsignedIntsUtils.toLong(Murmur3Hash.hash32(b, b.length)); + } - byte[] b = bb.array(); - return UnsignedIntsUtils.toLong(Murmur3Hash.hash32(b, b.length)); - } + @Override + public Long hash(String key) { + if (key == null) { + return 0L; + } + ByteBuffer bb = ByteBuffer.wrap(key.getBytes(charset)); + byte[] b = bb.array(); + return UnsignedIntsUtils.toLong(Murmur3Hash.hash32(b, b.length)); + } - @Override - public Long hash(String key) { - if (key == null) { - return 0L; - } - ByteBuffer bb = ByteBuffer.wrap(key.getBytes(charset)); - byte[] b = bb.array(); - return UnsignedIntsUtils.toLong(Murmur3Hash.hash32(b, b.length)); - } - - @Override - public Long hash(byte[] key) { - if (key == null) { - return 0L; - } - return UnsignedIntsUtils.toLong(Murmur3Hash.hash32(key, key.length)); - } + @Override + public Long hash(byte[] key) { + if (key == null) { + return 0L; + } + return UnsignedIntsUtils.toLong(Murmur3Hash.hash32(key, key.length)); + } - @Override - public HostToken getToken(Long keyHash) { - throw new RuntimeException("NotImplemented"); - } + @Override + public HostToken getToken(Long keyHash) { + throw new RuntimeException("NotImplemented"); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/UnsignedIntsUtils.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/UnsignedIntsUtils.java index 2d35e26a..cf9b9110 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/UnsignedIntsUtils.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/hash/UnsignedIntsUtils.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,15 +16,16 @@ package com.netflix.dyno.connectionpool.impl.hash; public class UnsignedIntsUtils { - - static final long INT_MASK = 0xffffffffL; - private UnsignedIntsUtils() {} + static final long INT_MASK = 0xffffffffL; - /** - * Returns the value of the given {@code int} as a {@code long}, when treated as unsigned. - */ - public static long toLong(int value) { - return value & INT_MASK; - } + private UnsignedIntsUtils() { + } + + /** + * Returns the value of the given {@code int} as a {@code long}, when treated as unsigned. + */ + public static long toLong(int value) { + return value & INT_MASK; + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/ConnectionPoolHealthTracker.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/ConnectionPoolHealthTracker.java index 5dba3a6a..24e82b55 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/ConnectionPoolHealthTracker.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/ConnectionPoolHealthTracker.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -32,118 +32,117 @@ /** * This class tracks the error rates for any {@link HostConnectionPool} via the {@link ErrorRateMonitor} - * The error rates are recorded directly by the class but the error rates are checked asynchronously in another thread. + * The error rates are recorded directly by the class but the error rates are checked asynchronously in another thread. * Once the thread decides that the error rates have crossed a configured threshold, then the {@link HostConnectionPool} is recycled. * i.e it is first marked as DOWN to prevent any new connections from being borrowed from it. Then the pool is reconnect()'d - * - * Hence callers to {@link HostConnectionPool} should take it's isActive() state into account when using this class. - * i.e before borrowing a connection check for isActive(). If not active, then use a fallback pool else throw an ex to the caller. - * Resume executing operations against the pool only once the pool becomes active. - * - * @author poberai + *

+ * Hence callers to {@link HostConnectionPool} should take it's isActive() state into account when using this class. + * i.e before borrowing a connection check for isActive(). If not active, then use a fallback pool else throw an ex to the caller. + * Resume executing operations against the pool only once the pool becomes active. * * @param + * @author poberai */ public class ConnectionPoolHealthTracker implements HealthTracker { - - private static final Logger Logger = LoggerFactory.getLogger(ConnectionPoolHealthTracker.class); - - private final ConnectionPoolConfiguration cpConfiguration; - private final ScheduledExecutorService threadPool; - private final AtomicBoolean stop = new AtomicBoolean(false); - private final ConcurrentHashMap errorRates = new ConcurrentHashMap(); - private final ConcurrentHashMap> reconnectingPools = new ConcurrentHashMap>(); - private final ConcurrentHashMap> pingingPools = new ConcurrentHashMap>(); - - private final AtomicBoolean startedPing = new AtomicBoolean(false); - - private final Integer SleepMillis; - private final Integer PoolReconnectWaitMillis; - - public ConnectionPoolHealthTracker(ConnectionPoolConfiguration config, ScheduledExecutorService thPool) { - this(config, thPool, config.getHealthTrackerDelayMillis(), config.getPoolReconnectWaitMillis()); - } - - public ConnectionPoolHealthTracker(ConnectionPoolConfiguration config, ScheduledExecutorService thPool, int sleepMillis, int poolReconnectWaitMillis) { - cpConfiguration = config; - threadPool = thPool; - SleepMillis = sleepMillis; - PoolReconnectWaitMillis = poolReconnectWaitMillis; - } - - - public void removeHost(Host host) { - HostConnectionPool destPool = reconnectingPools.get(host); - if (destPool != null) { - Logger.info("Health tracker marking host as down " + host); - destPool.getHost().setStatus(Status.Down); - } - } - - public void start() { - - threadPool.scheduleWithFixedDelay(new Runnable() { - - @Override - public void run() { - - if(stop.get() || Thread.currentThread().isInterrupted()) { - return; - } - - Logger.debug("Running, pending pools size: " + reconnectingPools.size()); - - for (Host host : reconnectingPools.keySet()) { - - if (!host.isUp()) { - Logger.info("Host: " + host + " is marked as down, evicting host from reconnection pool"); - reconnectingPools.remove(host); - continue; - } - - HostConnectionPool pool = reconnectingPools.get(host); - Logger.info("Checking for reconnecting pool for host: " + host + ", pool active? " + pool.isActive()); - if (pool.isActive()) { - // Pool is already active. Move on - reconnectingPools.remove(host); - } else { - try { - Logger.info("Reconnecting pool : " + pool); - pool.markAsDown(null); - if (PoolReconnectWaitMillis > 0) { - Logger.debug("Sleeping to allow enough time to drain connections"); - Thread.sleep(PoolReconnectWaitMillis); - } - pool.reconnect(); - if (pool.isActive()) { - Logger.info("Host pool reactivated: " + host); - reconnectingPools.remove(host); - } else { - Logger.info("Could not re-activate pool, will try again later"); - } - } catch (Exception e) { - // do nothing, will retry again once thread wakes up - Logger.warn("Failed to reconnect pool for host: " + host + " " + e.getMessage()); - } - } - } - } - - }, 1000, SleepMillis, TimeUnit.MILLISECONDS); - } - - public void stop() { - stop.set(true); - } - - @Override - public void trackConnectionError(HostConnectionPool hostPool, DynoException e) { - - if (e != null && e instanceof TimeoutException) { - // don't track timeouts, since that may not be indicative of an actual n/w problem - // that may just be a slowdown due to pool saturation of larger payloads - return; - } + + private static final Logger Logger = LoggerFactory.getLogger(ConnectionPoolHealthTracker.class); + + private final ConnectionPoolConfiguration cpConfiguration; + private final ScheduledExecutorService threadPool; + private final AtomicBoolean stop = new AtomicBoolean(false); + private final ConcurrentHashMap errorRates = new ConcurrentHashMap(); + private final ConcurrentHashMap> reconnectingPools = new ConcurrentHashMap>(); + private final ConcurrentHashMap> pingingPools = new ConcurrentHashMap>(); + + private final AtomicBoolean startedPing = new AtomicBoolean(false); + + private final Integer SleepMillis; + private final Integer PoolReconnectWaitMillis; + + public ConnectionPoolHealthTracker(ConnectionPoolConfiguration config, ScheduledExecutorService thPool) { + this(config, thPool, config.getHealthTrackerDelayMillis(), config.getPoolReconnectWaitMillis()); + } + + public ConnectionPoolHealthTracker(ConnectionPoolConfiguration config, ScheduledExecutorService thPool, int sleepMillis, int poolReconnectWaitMillis) { + cpConfiguration = config; + threadPool = thPool; + SleepMillis = sleepMillis; + PoolReconnectWaitMillis = poolReconnectWaitMillis; + } + + + public void removeHost(Host host) { + HostConnectionPool destPool = reconnectingPools.get(host); + if (destPool != null) { + Logger.info("Health tracker marking host as down " + host); + destPool.getHost().setStatus(Status.Down); + } + } + + public void start() { + + threadPool.scheduleWithFixedDelay(new Runnable() { + + @Override + public void run() { + + if (stop.get() || Thread.currentThread().isInterrupted()) { + return; + } + + Logger.debug("Running, pending pools size: " + reconnectingPools.size()); + + for (Host host : reconnectingPools.keySet()) { + + if (!host.isUp()) { + Logger.info("Host: " + host + " is marked as down, evicting host from reconnection pool"); + reconnectingPools.remove(host); + continue; + } + + HostConnectionPool pool = reconnectingPools.get(host); + Logger.info("Checking for reconnecting pool for host: " + host + ", pool active? " + pool.isActive()); + if (pool.isActive()) { + // Pool is already active. Move on + reconnectingPools.remove(host); + } else { + try { + Logger.info("Reconnecting pool : " + pool); + pool.markAsDown(null); + if (PoolReconnectWaitMillis > 0) { + Logger.debug("Sleeping to allow enough time to drain connections"); + Thread.sleep(PoolReconnectWaitMillis); + } + pool.reconnect(); + if (pool.isActive()) { + Logger.info("Host pool reactivated: " + host); + reconnectingPools.remove(host); + } else { + Logger.info("Could not re-activate pool, will try again later"); + } + } catch (Exception e) { + // do nothing, will retry again once thread wakes up + Logger.warn("Failed to reconnect pool for host: " + host + " " + e.getMessage()); + } + } + } + } + + }, 1000, SleepMillis, TimeUnit.MILLISECONDS); + } + + public void stop() { + stop.set(true); + } + + @Override + public void trackConnectionError(HostConnectionPool hostPool, DynoException e) { + + if (e != null && e instanceof TimeoutException) { + // don't track timeouts, since that may not be indicative of an actual n/w problem + // that may just be a slowdown due to pool saturation of larger payloads + return; + } if (e != null && e instanceof PoolExhaustedException) { String hostName = "Unknown"; @@ -156,75 +155,75 @@ public void trackConnectionError(HostConnectionPool hostPool, DynoException return; } - if (e != null && e instanceof FatalConnectionException) { - - Host host = hostPool.getHost(); - - ErrorMonitor errorMonitor = errorRates.get(host); - - if (errorMonitor == null) { - - errorMonitor = cpConfiguration.getErrorMonitorFactory().createErrorMonitor(hostPool.size()); - errorRates.putIfAbsent(host, errorMonitor); - errorMonitor = errorRates.get(host); - } - - boolean errorRateOk = errorMonitor.trackError(1); - - if (!errorRateOk) { - Logger.error("FAIL: Attempting to reconnect pool due to exceptions =>" + e.getMessage()); - reconnectPool(hostPool); - } - } - } - - public void reconnectPool(HostConnectionPool hostPool) { - Host host = hostPool.getHost(); - Logger.error("Enqueueing host cp for recycling due to too many errors: " + hostPool); - hostPool.markAsDown(null); - reconnectingPools.put(host, hostPool); - } - - public void initializePingHealthchecksForPool(HostConnectionPool hostPool) { - - pingingPools.putIfAbsent(hostPool.getHost(), hostPool); - if (startedPing.get()) { - return; - } - - if (pingingPools.size() > 0) { - if (startedPing.compareAndSet(false, true)) { - - threadPool.scheduleWithFixedDelay(new Runnable() { - - @Override - public void run() { - for (HostConnectionPool hostPool : pingingPools.values()) { - pingHostPool(hostPool); - } - } - }, 1, cpConfiguration.getPingFrequencySeconds(), TimeUnit.SECONDS); - - } else { - return; - } - } else { - return; // no pools to ping - } - } - - private void pingHostPool(HostConnectionPool hostPool) { - for (Connection connection : hostPool.getAllConnections()) { - try { - connection.execPing(); - } catch (DynoException e) { - trackConnectionError(hostPool, e); - } - } - } - - // used for unit tests - ConcurrentHashMap> getReconnectingPools() { - return reconnectingPools; - } + if (e != null && e instanceof FatalConnectionException) { + + Host host = hostPool.getHost(); + + ErrorMonitor errorMonitor = errorRates.get(host); + + if (errorMonitor == null) { + + errorMonitor = cpConfiguration.getErrorMonitorFactory().createErrorMonitor(hostPool.size()); + errorRates.putIfAbsent(host, errorMonitor); + errorMonitor = errorRates.get(host); + } + + boolean errorRateOk = errorMonitor.trackError(1); + + if (!errorRateOk) { + Logger.error("FAIL: Attempting to reconnect pool due to exceptions =>" + e.getMessage()); + reconnectPool(hostPool); + } + } + } + + public void reconnectPool(HostConnectionPool hostPool) { + Host host = hostPool.getHost(); + Logger.error("Enqueueing host cp for recycling due to too many errors: " + hostPool); + hostPool.markAsDown(null); + reconnectingPools.put(host, hostPool); + } + + public void initializePingHealthchecksForPool(HostConnectionPool hostPool) { + + pingingPools.putIfAbsent(hostPool.getHost(), hostPool); + if (startedPing.get()) { + return; + } + + if (pingingPools.size() > 0) { + if (startedPing.compareAndSet(false, true)) { + + threadPool.scheduleWithFixedDelay(new Runnable() { + + @Override + public void run() { + for (HostConnectionPool hostPool : pingingPools.values()) { + pingHostPool(hostPool); + } + } + }, 1, cpConfiguration.getPingFrequencySeconds(), TimeUnit.SECONDS); + + } else { + return; + } + } else { + return; // no pools to ping + } + } + + private void pingHostPool(HostConnectionPool hostPool) { + for (Connection connection : hostPool.getAllConnections()) { + try { + connection.execPing(); + } catch (DynoException e) { + trackConnectionError(hostPool, e); + } + } + } + + // used for unit tests + ConcurrentHashMap> getReconnectingPools() { + return reconnectingPools; + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/ErrorMonitor.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/ErrorMonitor.java index 5fd7b87c..4790bd87 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/ErrorMonitor.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/ErrorMonitor.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,20 +17,21 @@ public interface ErrorMonitor { - - /** - * Monitor errors - * @param numErrors - * @return true/false indicating whether the error are within the threshold. - * True: Errors still ok. False: errors have crossed the threshold - */ - boolean trackError(int numErrors); - - interface ErrorMonitorFactory { + /** + * Monitor errors + * @param numErrors + * @return true/false indicating whether the error are within the threshold. + * True: Errors still ok. False: errors have crossed the threshold + */ + boolean trackError(int numErrors); - @Deprecated - ErrorMonitor createErrorMonitor(); - ErrorMonitor createErrorMonitor(int maxValue); - } + + interface ErrorMonitorFactory { + + @Deprecated + ErrorMonitor createErrorMonitor(); + + ErrorMonitor createErrorMonitor(int maxValue); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/ErrorRateMonitor.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/ErrorRateMonitor.java index 2b85c848..0bded57d 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/ErrorRateMonitor.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/ErrorRateMonitor.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,124 +27,123 @@ /** * Class that can be used to track the error rates for {@link ConnectionPoolHealthTracker} - * It makes use of {@link RateTracker} to track the error rates and then periodically applies the + * It makes use of {@link RateTracker} to track the error rates and then periodically applies the * {@link ErrorRateMonitorConfig} to apply error rate check policies to determine error threshold violations. - * - * @author poberai * + * @author poberai */ public class ErrorRateMonitor { - private final List policies = new ArrayList(); - private final AtomicLong lastCheckTimestamp = new AtomicLong(0L); - private final AtomicLong suppressCheckTimestamp = new AtomicLong(0L); - - private final AtomicReference errorCheckLock = new AtomicReference(null); - - private final long errorCheckFrequencySeconds; - private final RateTracker rateTracker; - private final int suppressErrorWindow; - - public ErrorRateMonitor(int windowSize, int checkFrequency, int suppressWindow) { - - this.rateTracker = new RateTracker(windowSize); - this.errorCheckFrequencySeconds = checkFrequency; - this.lastCheckTimestamp.set(System.currentTimeMillis()/1000); - this.suppressErrorWindow = suppressWindow; - } - - public ErrorRateMonitor(ErrorRateMonitorConfig config) { - - this(config.getWindowSizeSeconds(), config.getCheckFrequencySeconds(), config.getCheckSuppressWindowSeconds()); - for (ErrorThreshold threshold : config.getThresholds()) { - addPolicy(new SimpleErrorCheckPolicy(threshold)); - } - } - - public void addPolicy(ErrorCheckPolicy policy) { - policies.add(policy); - } - - public boolean trackErrorRate(int count) { - - long timestamp = System.currentTimeMillis()/1000; - - this.rateTracker.trackRate(count); - - if ((timestamp - lastCheckTimestamp.get()) >= errorCheckFrequencySeconds) { - - if ((timestamp - suppressCheckTimestamp.get()) <= suppressErrorWindow) { - // don't check error. This is to prevent repeatedly firing alerts - return true; - } - - String expected = errorCheckLock.get(); - boolean casWon = errorCheckLock.compareAndSet(expected, UUID.randomUUID().toString()); - - if (casWon) { - // record that we checked - lastCheckTimestamp.set(timestamp); - - boolean failure = false; - List buckets = rateTracker.getAllBuckets(); - - for (ErrorCheckPolicy policy : policies) { - failure = policy.checkErrorRate(buckets); - if (failure) { - break; - } - } - - if (failure) { - // Set the timestamp to suppress subsequent alerts for the configured time period - suppressCheckTimestamp.set(timestamp); - } - return !failure; - } - } - - return true; - } - - public interface ErrorCheckPolicy { - - public boolean checkErrorRate(List buckets); - } - - public static class SimpleErrorCheckPolicy implements ErrorCheckPolicy { - - private final int perBucketThreshold; - private final int windowSize; - private final int bucketCoveragePercentage; - - public SimpleErrorCheckPolicy(int bucketThreshold, int numBuckets, int bucketCoverage) { - this.perBucketThreshold = bucketThreshold; - this.windowSize = numBuckets; - this.bucketCoveragePercentage = bucketCoverage; - } - - public SimpleErrorCheckPolicy(ErrorThreshold threshold) { - this(threshold.getThresholdPerSecond(), threshold.getWindowSeconds(), threshold.getWindowCoveragePercentage()); - } - - @Override - public boolean checkErrorRate(List buckets) { - - int minViolationBucketThreshold = (windowSize * bucketCoveragePercentage)/100; - - int numBucketsOverThreshold = 0; - for (Bucket b : buckets) { - if (b.count() >= perBucketThreshold) { - numBucketsOverThreshold++; - } - } - - return numBucketsOverThreshold >= minViolationBucketThreshold; - } - } - - // used for unit tests - RateTracker getRateTracker() { - return rateTracker; - } + private final List policies = new ArrayList(); + private final AtomicLong lastCheckTimestamp = new AtomicLong(0L); + private final AtomicLong suppressCheckTimestamp = new AtomicLong(0L); + + private final AtomicReference errorCheckLock = new AtomicReference(null); + + private final long errorCheckFrequencySeconds; + private final RateTracker rateTracker; + private final int suppressErrorWindow; + + public ErrorRateMonitor(int windowSize, int checkFrequency, int suppressWindow) { + + this.rateTracker = new RateTracker(windowSize); + this.errorCheckFrequencySeconds = checkFrequency; + this.lastCheckTimestamp.set(System.currentTimeMillis() / 1000); + this.suppressErrorWindow = suppressWindow; + } + + public ErrorRateMonitor(ErrorRateMonitorConfig config) { + + this(config.getWindowSizeSeconds(), config.getCheckFrequencySeconds(), config.getCheckSuppressWindowSeconds()); + for (ErrorThreshold threshold : config.getThresholds()) { + addPolicy(new SimpleErrorCheckPolicy(threshold)); + } + } + + public void addPolicy(ErrorCheckPolicy policy) { + policies.add(policy); + } + + public boolean trackErrorRate(int count) { + + long timestamp = System.currentTimeMillis() / 1000; + + this.rateTracker.trackRate(count); + + if ((timestamp - lastCheckTimestamp.get()) >= errorCheckFrequencySeconds) { + + if ((timestamp - suppressCheckTimestamp.get()) <= suppressErrorWindow) { + // don't check error. This is to prevent repeatedly firing alerts + return true; + } + + String expected = errorCheckLock.get(); + boolean casWon = errorCheckLock.compareAndSet(expected, UUID.randomUUID().toString()); + + if (casWon) { + // record that we checked + lastCheckTimestamp.set(timestamp); + + boolean failure = false; + List buckets = rateTracker.getAllBuckets(); + + for (ErrorCheckPolicy policy : policies) { + failure = policy.checkErrorRate(buckets); + if (failure) { + break; + } + } + + if (failure) { + // Set the timestamp to suppress subsequent alerts for the configured time period + suppressCheckTimestamp.set(timestamp); + } + return !failure; + } + } + + return true; + } + + public interface ErrorCheckPolicy { + + public boolean checkErrorRate(List buckets); + } + + public static class SimpleErrorCheckPolicy implements ErrorCheckPolicy { + + private final int perBucketThreshold; + private final int windowSize; + private final int bucketCoveragePercentage; + + public SimpleErrorCheckPolicy(int bucketThreshold, int numBuckets, int bucketCoverage) { + this.perBucketThreshold = bucketThreshold; + this.windowSize = numBuckets; + this.bucketCoveragePercentage = bucketCoverage; + } + + public SimpleErrorCheckPolicy(ErrorThreshold threshold) { + this(threshold.getThresholdPerSecond(), threshold.getWindowSeconds(), threshold.getWindowCoveragePercentage()); + } + + @Override + public boolean checkErrorRate(List buckets) { + + int minViolationBucketThreshold = (windowSize * bucketCoveragePercentage) / 100; + + int numBucketsOverThreshold = 0; + for (Bucket b : buckets) { + if (b.count() >= perBucketThreshold) { + numBucketsOverThreshold++; + } + } + + return numBucketsOverThreshold >= minViolationBucketThreshold; + } + } + + // used for unit tests + RateTracker getRateTracker() { + return rateTracker; + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/RateTracker.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/RateTracker.java index 05767e7f..d3a94e92 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/RateTracker.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/RateTracker.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -33,266 +33,265 @@ /** * Class that tracks the rate at which events occur over a specified rolling time window (in seconds) * This is useful for tracking error rates from {@link ErrorRateMonitor} - * - * @author poberai * + * @author poberai */ public class RateTracker { - - private final AtomicReference bucketCreateLock = new AtomicReference(null); - private final AtomicInteger wonLock = new AtomicInteger(0); - - final RollingWindow rWindow; - - public RateTracker(int numSeconds) { - - int windowSize = numSeconds; - rWindow = new RollingWindow(windowSize); - } - - public void trackRate() { - trackRate(1); - } - - public void trackRate(int count) { - - long currentTime = System.currentTimeMillis() / 1000; // the current second - - // compare the current window - int compare = rWindow.compareWindow(currentTime); - - if (compare == 0) { - // it is the same window, increment the quota and check the rate for this second - rWindow.trackRate(count); - - } else if (compare < 0) { - - // the current window that is tracked is in the past, so create the window for this second - // it does not matter if some other thread beat us to setting the last bucket. - - BucketCreator expected = bucketCreateLock.get(); - BucketCreator newCreator = new BucketCreator(currentTime); - boolean success = bucketCreateLock.compareAndSet(expected, newCreator) ; - - if (success) { - - wonLock.incrementAndGet(); - newCreator.futureBucket.run(); - - } else { - - try { - bucketCreateLock.get().futureBucket.get(20, TimeUnit.MILLISECONDS); - } catch (TimeoutException e) { - //return true; - e.printStackTrace(); - } catch (Exception e) { - throw new DynoException(e); - } - } - - rWindow.trackRate(count); - - - } else { - // it is the prev window, let the request through - return ; - } - } - - - public List getBuckets(int lookback) { - return rWindow.getBuckets(lookback); - } - - - public List getAllBuckets() { - return rWindow.getAllBuckets(); - } - - // used for unit tests - int getWonLockCount() { - return wonLock.get(); - } - - class RollingWindow { - - private final int windowSize; - - private final LinkedBlockingDeque queue = new LinkedBlockingDeque(); - private final AtomicInteger bucketCreateCount = new AtomicInteger(0); - - private RollingWindow(int wSize) { - - windowSize = wSize; - - long currentTime = System.currentTimeMillis()/1000; - long startTime = currentTime - windowSize + 1; - - for (long i = startTime; i<=currentTime; i++) { - queue.addFirst(new Bucket(i)); - } - } - - private void trackRate(int count) { - queue.peekFirst().track(count); - } - - // used primarily for unit tests - int getQueueSize() { - return queue.size(); - } - - int getBucketCreateCount() { - return bucketCreateCount.get(); - } - - private List getBuckets(int lookback) { - - List list = new ArrayList(); - int count = 0; - Iterator iter = queue.iterator(); - - while (iter.hasNext() && count < lookback) { - list.add(iter.next()); - count++; - } - return list; - } - - private List getAllBuckets() { - - List list = new ArrayList(); - Iterator iter = queue.iterator(); - - while (iter.hasNext()) { - list.add(iter.next()); - } - return list; - } - - private int compareWindow(long currentTimestamp) { - - Long lastBucketTimestamp = queue.peekFirst().lastTimestamp.get(); - return lastBucketTimestamp.compareTo(currentTimestamp); - } - - private void addNewBucket(long timestamp) { - - bucketCreateCount.incrementAndGet(); - - Bucket newBucket = new Bucket(timestamp); - queue.removeLast(); - queue.addFirst(newBucket); - } - - private void syncToNewWindow(long timestamp) { - - long currentTimestamp = queue.peekFirst().lastTimestamp.get(); - - if (currentTimestamp == timestamp) { - return; - } - - while (currentTimestamp < timestamp) { - currentTimestamp++; - addNewBucket(currentTimestamp); - } - } - - public Bucket firstBucket() { - return queue.peekFirst(); - } - } - - public static class Bucket { - - private final AtomicLong lastTimestamp = new AtomicLong(0L); - private final AtomicInteger count = new AtomicInteger(0); - - public Bucket() { - this(System.currentTimeMillis()/1000); // the current second - } - - private Bucket(long timestamp) { - lastTimestamp.set(timestamp); // the current second - } - - public int track(int delta) { - return count.addAndGet(delta); - } - - public int count() { - return count.get(); - } - - public long timestamp() { - return lastTimestamp.get(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + new Long(lastTimestamp.get()).intValue(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - Bucket other = (Bucket) obj; - return this.lastTimestamp.get() == other.lastTimestamp.get(); - } - - public String toString() { - return "" + this.count(); - } - } - - private class BucketCreator { - - private final String id = UUID.randomUUID().toString(); - private final long timestamp; - private final FutureTask futureBucket; - - private BucketCreator(long time) { - this.timestamp = time; - - this.futureBucket = new FutureTask(new Callable() { - - @Override - public Bucket call() throws Exception { - rWindow.syncToNewWindow(timestamp); - return rWindow.firstBucket(); - } - - }); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - result = prime * result + (int) (timestamp ^ (timestamp >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - BucketCreator other = (BucketCreator) obj; - boolean equals = true; - equals &= (id != null) ? id.equals(other.id) : other.id == null; - equals &= (timestamp == other.timestamp); - return equals; - } - - } + + private final AtomicReference bucketCreateLock = new AtomicReference(null); + private final AtomicInteger wonLock = new AtomicInteger(0); + + final RollingWindow rWindow; + + public RateTracker(int numSeconds) { + + int windowSize = numSeconds; + rWindow = new RollingWindow(windowSize); + } + + public void trackRate() { + trackRate(1); + } + + public void trackRate(int count) { + + long currentTime = System.currentTimeMillis() / 1000; // the current second + + // compare the current window + int compare = rWindow.compareWindow(currentTime); + + if (compare == 0) { + // it is the same window, increment the quota and check the rate for this second + rWindow.trackRate(count); + + } else if (compare < 0) { + + // the current window that is tracked is in the past, so create the window for this second + // it does not matter if some other thread beat us to setting the last bucket. + + BucketCreator expected = bucketCreateLock.get(); + BucketCreator newCreator = new BucketCreator(currentTime); + boolean success = bucketCreateLock.compareAndSet(expected, newCreator); + + if (success) { + + wonLock.incrementAndGet(); + newCreator.futureBucket.run(); + + } else { + + try { + bucketCreateLock.get().futureBucket.get(20, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + //return true; + e.printStackTrace(); + } catch (Exception e) { + throw new DynoException(e); + } + } + + rWindow.trackRate(count); + + + } else { + // it is the prev window, let the request through + return; + } + } + + + public List getBuckets(int lookback) { + return rWindow.getBuckets(lookback); + } + + + public List getAllBuckets() { + return rWindow.getAllBuckets(); + } + + // used for unit tests + int getWonLockCount() { + return wonLock.get(); + } + + class RollingWindow { + + private final int windowSize; + + private final LinkedBlockingDeque queue = new LinkedBlockingDeque(); + private final AtomicInteger bucketCreateCount = new AtomicInteger(0); + + private RollingWindow(int wSize) { + + windowSize = wSize; + + long currentTime = System.currentTimeMillis() / 1000; + long startTime = currentTime - windowSize + 1; + + for (long i = startTime; i <= currentTime; i++) { + queue.addFirst(new Bucket(i)); + } + } + + private void trackRate(int count) { + queue.peekFirst().track(count); + } + + // used primarily for unit tests + int getQueueSize() { + return queue.size(); + } + + int getBucketCreateCount() { + return bucketCreateCount.get(); + } + + private List getBuckets(int lookback) { + + List list = new ArrayList(); + int count = 0; + Iterator iter = queue.iterator(); + + while (iter.hasNext() && count < lookback) { + list.add(iter.next()); + count++; + } + return list; + } + + private List getAllBuckets() { + + List list = new ArrayList(); + Iterator iter = queue.iterator(); + + while (iter.hasNext()) { + list.add(iter.next()); + } + return list; + } + + private int compareWindow(long currentTimestamp) { + + Long lastBucketTimestamp = queue.peekFirst().lastTimestamp.get(); + return lastBucketTimestamp.compareTo(currentTimestamp); + } + + private void addNewBucket(long timestamp) { + + bucketCreateCount.incrementAndGet(); + + Bucket newBucket = new Bucket(timestamp); + queue.removeLast(); + queue.addFirst(newBucket); + } + + private void syncToNewWindow(long timestamp) { + + long currentTimestamp = queue.peekFirst().lastTimestamp.get(); + + if (currentTimestamp == timestamp) { + return; + } + + while (currentTimestamp < timestamp) { + currentTimestamp++; + addNewBucket(currentTimestamp); + } + } + + public Bucket firstBucket() { + return queue.peekFirst(); + } + } + + public static class Bucket { + + private final AtomicLong lastTimestamp = new AtomicLong(0L); + private final AtomicInteger count = new AtomicInteger(0); + + public Bucket() { + this(System.currentTimeMillis() / 1000); // the current second + } + + private Bucket(long timestamp) { + lastTimestamp.set(timestamp); // the current second + } + + public int track(int delta) { + return count.addAndGet(delta); + } + + public int count() { + return count.get(); + } + + public long timestamp() { + return lastTimestamp.get(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + new Long(lastTimestamp.get()).intValue(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + + Bucket other = (Bucket) obj; + return this.lastTimestamp.get() == other.lastTimestamp.get(); + } + + public String toString() { + return "" + this.count(); + } + } + + private class BucketCreator { + + private final String id = UUID.randomUUID().toString(); + private final long timestamp; + private final FutureTask futureBucket; + + private BucketCreator(long time) { + this.timestamp = time; + + this.futureBucket = new FutureTask(new Callable() { + + @Override + public Bucket call() throws Exception { + rWindow.syncToNewWindow(timestamp); + return rWindow.firstBucket(); + } + + }); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + (int) (timestamp ^ (timestamp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + BucketCreator other = (BucketCreator) obj; + boolean equals = true; + equals &= (id != null) ? id.equals(other.id) : other.id == null; + equals &= (timestamp == other.timestamp); + return equals; + } + + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/SimpleErrorMonitorImpl.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/SimpleErrorMonitorImpl.java index b2ceea6e..ebf6c5a0 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/SimpleErrorMonitorImpl.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/health/SimpleErrorMonitorImpl.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,53 +17,53 @@ import java.util.concurrent.atomic.AtomicInteger; - public class SimpleErrorMonitorImpl implements ErrorMonitor { +public class SimpleErrorMonitorImpl implements ErrorMonitor { - private final AtomicInteger errorCount = new AtomicInteger(0); - private final int threshold; + private final AtomicInteger errorCount = new AtomicInteger(0); + private final int threshold; - public SimpleErrorMonitorImpl(int numErrorThreshold) { - threshold = numErrorThreshold; - } + public SimpleErrorMonitorImpl(int numErrorThreshold) { + threshold = numErrorThreshold; + } - @Override - public boolean trackError(int numErrors) { + @Override + public boolean trackError(int numErrors) { - int currentCount = errorCount.addAndGet(numErrors); - if (currentCount >= threshold) { - // Reset the count - boolean success = errorCount.compareAndSet(currentCount, 0); - if (success) { - return false; // ERROR above threshold! - } else { - return true; // all OK. Someone else beat us to reporting the errors as above threshold - } - } - return true; // Errors NOT above threshold - } + int currentCount = errorCount.addAndGet(numErrors); + if (currentCount >= threshold) { + // Reset the count + boolean success = errorCount.compareAndSet(currentCount, 0); + if (success) { + return false; // ERROR above threshold! + } else { + return true; // all OK. Someone else beat us to reporting the errors as above threshold + } + } + return true; // Errors NOT above threshold + } - - public static class SimpleErrorMonitorFactory implements ErrorMonitorFactory { - private int threshold; - - public SimpleErrorMonitorFactory() { - this(10); // default - } - public SimpleErrorMonitorFactory(int simpleErrorThreshold) { - this.threshold = simpleErrorThreshold; - } + public static class SimpleErrorMonitorFactory implements ErrorMonitorFactory { + private int threshold; - @Override - public ErrorMonitor createErrorMonitor() { - return new SimpleErrorMonitorImpl(this.threshold); - } + public SimpleErrorMonitorFactory() { + this(10); // default + } - @Override - public ErrorMonitor createErrorMonitor(int maxValue) { - return new SimpleErrorMonitorImpl(maxValue); - } + public SimpleErrorMonitorFactory(int simpleErrorThreshold) { + this.threshold = simpleErrorThreshold; + } - // TODO add setter and keep error threshold in sync with maxConnsPerHost OR switch to error rate monitor - } + @Override + public ErrorMonitor createErrorMonitor() { + return new SimpleErrorMonitorImpl(this.threshold); + } + + @Override + public ErrorMonitor createErrorMonitor(int maxValue) { + return new SimpleErrorMonitorImpl(maxValue); + } + + // TODO add setter and keep error threshold in sync with maxConnsPerHost OR switch to error rate monitor + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/AbstractTokenMapSupplier.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/AbstractTokenMapSupplier.java index 171a8f4e..ac1c2bd1 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/AbstractTokenMapSupplier.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/AbstractTokenMapSupplier.java @@ -62,7 +62,7 @@ * "rack": "dyno_sandbox--useast1e", * "token": "1383429731", * "zone": "us-east-1e", - * "hashtag" : "{}" + * "hashtag" : "{}" * }, * { * "dc": "eu-west-1", @@ -81,7 +81,7 @@ * "token": "1383429731", * "zone": "eu-west-1b", * "hashtag" : "{}" - + * * }, * { * "dc": "us-east-1", @@ -91,14 +91,13 @@ * "token": "1383429731", * "zone": "us-east-1d", * "hashtag" : "{}" - + * * } - *] + * ] * * * @author poberai * @author ipapapa - * */ public abstract class AbstractTokenMapSupplier implements TokenMapSupplier { diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/CircularList.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/CircularList.java index 9e14745f..9d287a30 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/CircularList.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/CircularList.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,134 +22,140 @@ import java.util.concurrent.atomic.AtomicReference; /** - * Utility class that encapsulates a thread safe circular list. It also provides functionality to be able to dynamically add and remove - * elements from the list in a thread safe manner while callers to the class are still using the list. - * - * This utility is mainly useful for ROUND ROBIN style load balancers. It is also useful for Connection pool monitors that need to track + * Utility class that encapsulates a thread safe circular list. It also provides functionality to be able to dynamically add and remove + * elements from the list in a thread safe manner while callers to the class are still using the list. + *

+ * This utility is mainly useful for ROUND ROBIN style load balancers. It is also useful for Connection pool monitors that need to track * state of operations against a connection pool in a bounded circular buffer - * - * @author poberai * * @param + * @author poberai */ public class CircularList { - // The thread safe reference to the inner list. Maintaining an atomic ref at this level helps enabling swapping out of the entire list - // underneath when there is a change to the list such as element addition or removal - private final AtomicReference ref = new AtomicReference(null); - - /** - * Constructor - * @param origList - */ - public CircularList(Collection origList) { - ref.set(new InnerList(origList)); - } - - /** - * Get the next element in the list - * @return T - */ - public T getNextElement() { - return ref.get().getNextElement(); - } - - /** - * Swap the entire inner list with a new list - * @param newList - */ - public void swapWithList(Collection newList) { - InnerList newInnerList = new InnerList(newList); - ref.set(newInnerList); - } - - /** - * Add an element to the list. This causes the inner list to be swapped out - * @param element - */ - public synchronized void addElement(T element) { - List origList = ref.get().list; - boolean isPresent = origList.contains(element); - if (isPresent) { - return; - } - - List newList = new ArrayList(origList); - newList.add(element); - - swapWithList(newList); - } - - /** - * Remove an element from this list. This causes the inner list to be swapped out - * @param element - */ - public synchronized void removeElement(T element) { - List origList = ref.get().list; - boolean isPresent = origList.contains(element); - if (!isPresent) { - return; - } - - List newList = new ArrayList(origList); - newList.remove(element); - - swapWithList(newList); - } - - /** - * Helpful utility to access the inner list. Must be used with care since the inner list can change. - * @return List - */ - public List getEntireList() { - InnerList iList = ref.get(); - return iList != null ? iList.getList() : null; - } - - /** - * Gets the size of the bounded list underneath. Note that this num can change if the inner list is swapped out. - * @return - */ - public int getSize() { - InnerList iList = ref.get(); - return iList != null ? iList.getList().size() : 0; - } - - /** - * The inner list which manages the circular access to the actual list. - * @author poberai - * - */ - private class InnerList { - private final List list; - private final Integer size; - - // The rotating index over the list. currentIndex always indicates the index of the element that was last accessed - // Using AtomicLong instead of AtomicInteger to avoid resetting value on overflow. Range of long is good enough - // to not wrap currentIndex. - private final AtomicLong currentIndex = new AtomicLong(0L); - - private InnerList(Collection newList) { - if (newList != null) { - list = new ArrayList<>(newList); - size = list.size(); - } else { - list = null; - size = 0; - } - } - - private int getNextIndex() { - return (int) (currentIndex.incrementAndGet() % size); - } - - private T getNextElement() { - return (list == null || list.size() == 0) ? null : list.get(getNextIndex()); - } - - private List getList() { - return list; - } - } + // The thread safe reference to the inner list. Maintaining an atomic ref at this level helps enabling swapping out of the entire list + // underneath when there is a change to the list such as element addition or removal + private final AtomicReference ref = new AtomicReference(null); + + /** + * Constructor + * + * @param origList + */ + public CircularList(Collection origList) { + ref.set(new InnerList(origList)); + } + + /** + * Get the next element in the list + * + * @return T + */ + public T getNextElement() { + return ref.get().getNextElement(); + } + + /** + * Swap the entire inner list with a new list + * + * @param newList + */ + public void swapWithList(Collection newList) { + InnerList newInnerList = new InnerList(newList); + ref.set(newInnerList); + } + + /** + * Add an element to the list. This causes the inner list to be swapped out + * + * @param element + */ + public synchronized void addElement(T element) { + List origList = ref.get().list; + boolean isPresent = origList.contains(element); + if (isPresent) { + return; + } + + List newList = new ArrayList(origList); + newList.add(element); + + swapWithList(newList); + } + + /** + * Remove an element from this list. This causes the inner list to be swapped out + * + * @param element + */ + public synchronized void removeElement(T element) { + List origList = ref.get().list; + boolean isPresent = origList.contains(element); + if (!isPresent) { + return; + } + + List newList = new ArrayList(origList); + newList.remove(element); + + swapWithList(newList); + } + + /** + * Helpful utility to access the inner list. Must be used with care since the inner list can change. + * + * @return List + */ + public List getEntireList() { + InnerList iList = ref.get(); + return iList != null ? iList.getList() : null; + } + + /** + * Gets the size of the bounded list underneath. Note that this num can change if the inner list is swapped out. + * + * @return + */ + public int getSize() { + InnerList iList = ref.get(); + return iList != null ? iList.getList().size() : 0; + } + + /** + * The inner list which manages the circular access to the actual list. + * + * @author poberai + */ + private class InnerList { + private final List list; + private final Integer size; + + // The rotating index over the list. currentIndex always indicates the index of the element that was last accessed + // Using AtomicLong instead of AtomicInteger to avoid resetting value on overflow. Range of long is good enough + // to not wrap currentIndex. + private final AtomicLong currentIndex = new AtomicLong(0L); + + private InnerList(Collection newList) { + if (newList != null) { + list = new ArrayList<>(newList); + size = list.size(); + } else { + list = null; + size = 0; + } + } + + private int getNextIndex() { + return (int) (currentIndex.incrementAndGet() % size); + } + + private T getNextElement() { + return (list == null || list.size() == 0) ? null : list.get(getNextIndex()); + } + + private List getList() { + return list; + } + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/HostSelectionWithFallback.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/HostSelectionWithFallback.java index 5af19194..1961a401 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/HostSelectionWithFallback.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/HostSelectionWithFallback.java @@ -55,30 +55,29 @@ *

* Note that this class does not prefer any one remote HostSelectionStrategy over another. * + * @param * @author poberai * @author jcacciatore - * - * @param */ public class HostSelectionWithFallback { - private static final Logger logger = LoggerFactory.getLogger(HostSelectionWithFallback.class); + private static final Logger logger = LoggerFactory.getLogger(HostSelectionWithFallback.class); // Only used in calculating replication factor private final String localDataCenter; - // tracks the local zone - private final String localRack; - // The selector for the local zone - private final HostSelectionStrategy localSelector; - // Track selectors for each remote zone - private final ConcurrentHashMap> remoteRackSelectors = new ConcurrentHashMap>(); + // tracks the local zone + private final String localRack; + // The selector for the local zone + private final HostSelectionStrategy localSelector; + // Track selectors for each remote zone + private final ConcurrentHashMap> remoteRackSelectors = new ConcurrentHashMap>(); - private final ConcurrentHashMap hostTokens = new ConcurrentHashMap(); + private final ConcurrentHashMap hostTokens = new ConcurrentHashMap(); - private final TokenMapSupplier tokenSupplier; - private final ConnectionPoolConfiguration cpConfig; - private final ConnectionPoolMonitor cpMonitor; + private final TokenMapSupplier tokenSupplier; + private final ConnectionPoolConfiguration cpConfig; + private final ConnectionPoolMonitor cpMonitor; private final AtomicInteger replicationFactor = new AtomicInteger(-1); @@ -86,85 +85,85 @@ public class HostSelectionWithFallback { // pool for traffic. It only affects metrics such as failover/fallback private final AtomicReference topology = new AtomicReference<>(null); - // list of names of remote zones. Used for RoundRobin over remote zones when local zone host is down - private final CircularList remoteDCNames = new CircularList(new ArrayList()); + // list of names of remote zones. Used for RoundRobin over remote zones when local zone host is down + private final CircularList remoteDCNames = new CircularList(new ArrayList()); - private final HostSelectionStrategyFactory selectorFactory; + private final HostSelectionStrategyFactory selectorFactory; - public HostSelectionWithFallback(ConnectionPoolConfiguration config, ConnectionPoolMonitor monitor) { + public HostSelectionWithFallback(ConnectionPoolConfiguration config, ConnectionPoolMonitor monitor) { - cpMonitor = monitor; - cpConfig = config; - localRack = cpConfig.getLocalRack(); + cpMonitor = monitor; + cpConfig = config; + localRack = cpConfig.getLocalRack(); localDataCenter = cpConfig.getLocalDataCenter(); - tokenSupplier = cpConfig.getTokenSupplier(); - - selectorFactory = new DefaultSelectionFactory(cpConfig); - localSelector = selectorFactory.vendPoolSelectionStrategy(); - - } - - public Connection getConnection(BaseOperation op, int duration, TimeUnit unit) throws NoAvailableHostsException, PoolExhaustedException { - return getConnection(op, null, duration, unit, cpConfig.getRetryPolicyFactory().getRetryPolicy()); - } - - public Connection getConnectionUsingRetryPolicy(BaseOperation op, int duration, TimeUnit unit, RetryPolicy retry) throws NoAvailableHostsException, PoolExhaustedException { - return getConnection(op, null, duration, unit, retry); - } - - private Connection getConnection(BaseOperation op, Long token, int duration, TimeUnit unit, RetryPolicy retry) - throws NoAvailableHostsException, PoolExhaustedException, PoolTimeoutException, PoolOfflineException { - DynoConnectException lastEx = null; - HostConnectionPool hostPool = null; - - if (retry.getAttemptCount() == 0 || (retry.getAttemptCount() > 0 && !retry.allowCrossZoneFallback())) { - // By default zone affinity is enabled; if the local rack is not known at startup it is disabled - if (cpConfig.localZoneAffinity()) { - hostPool = getHostPoolForOperationOrTokenInLocalZone(op, token); - } else { - hostPool = getFallbackHostPool(op, token); - } - } - - if (hostPool != null) { - try { - // Note that if a PoolExhaustedException is thrown it is caught by the calling - // ConnectionPoolImpl#executeXXX() method - return hostPool.borrowConnection(duration, unit); - } catch (PoolTimeoutException pte) { - lastEx = pte; - cpMonitor.incOperationFailure(null, pte); - } - } - - if (attemptFallback()) { - if (topology.get().getTokensForRack(localRack) != null) { - cpMonitor.incFailover(null, lastEx); - } - - hostPool = getFallbackHostPool(op, token); - - if (hostPool != null) { - return hostPool.borrowConnection(duration, unit); - } - } - - if (lastEx == null) { - throw new PoolOfflineException(hostPool == null ? null : hostPool.getHost(), "host pool is offline and no Racks available for fallback"); - } else { - throw lastEx; - } - } - - // Should be called when a connection is required on that particular zone with no fall backs what so ever - private Connection getConnectionForTokenOnRackNoFallback(BaseOperation op, Long token, String rack, int duration, TimeUnit unit, RetryPolicy retry) + tokenSupplier = cpConfig.getTokenSupplier(); + + selectorFactory = new DefaultSelectionFactory(cpConfig); + localSelector = selectorFactory.vendPoolSelectionStrategy(); + + } + + public Connection getConnection(BaseOperation op, int duration, TimeUnit unit) throws NoAvailableHostsException, PoolExhaustedException { + return getConnection(op, null, duration, unit, cpConfig.getRetryPolicyFactory().getRetryPolicy()); + } + + public Connection getConnectionUsingRetryPolicy(BaseOperation op, int duration, TimeUnit unit, RetryPolicy retry) throws NoAvailableHostsException, PoolExhaustedException { + return getConnection(op, null, duration, unit, retry); + } + + private Connection getConnection(BaseOperation op, Long token, int duration, TimeUnit unit, RetryPolicy retry) + throws NoAvailableHostsException, PoolExhaustedException, PoolTimeoutException, PoolOfflineException { + DynoConnectException lastEx = null; + HostConnectionPool hostPool = null; + + if (retry.getAttemptCount() == 0 || (retry.getAttemptCount() > 0 && !retry.allowCrossZoneFallback())) { + // By default zone affinity is enabled; if the local rack is not known at startup it is disabled + if (cpConfig.localZoneAffinity()) { + hostPool = getHostPoolForOperationOrTokenInLocalZone(op, token); + } else { + hostPool = getFallbackHostPool(op, token); + } + } + + if (hostPool != null) { + try { + // Note that if a PoolExhaustedException is thrown it is caught by the calling + // ConnectionPoolImpl#executeXXX() method + return hostPool.borrowConnection(duration, unit); + } catch (PoolTimeoutException pte) { + lastEx = pte; + cpMonitor.incOperationFailure(null, pte); + } + } + + if (attemptFallback()) { + if (topology.get().getTokensForRack(localRack) != null) { + cpMonitor.incFailover(null, lastEx); + } + + hostPool = getFallbackHostPool(op, token); + + if (hostPool != null) { + return hostPool.borrowConnection(duration, unit); + } + } + + if (lastEx == null) { + throw new PoolOfflineException(hostPool == null ? null : hostPool.getHost(), "host pool is offline and no Racks available for fallback"); + } else { + throw lastEx; + } + } + + // Should be called when a connection is required on that particular zone with no fall backs what so ever + private Connection getConnectionForTokenOnRackNoFallback(BaseOperation op, Long token, String rack, int duration, TimeUnit unit, RetryPolicy retry) throws NoAvailableHostsException, PoolExhaustedException, PoolTimeoutException, PoolOfflineException { DynoConnectException lastEx = null; // find the selector for that rack, - HostSelectionStrategy selector = findSelectorForRack(rack); - // get the host using that selector - HostConnectionPool hostPool = selector.getPoolForToken(token); + HostSelectionStrategy selector = findSelectorForRack(rack); + // get the host using that selector + HostConnectionPool hostPool = selector.getPoolForToken(token); if (hostPool != null) { try { @@ -192,7 +191,7 @@ private HostConnectionPool getHostPoolForOperationOrTokenInLocalZone(BaseOpe if (isConnectionPoolActive(hostPool)) { return hostPool; } - } + } } catch (NoAvailableHostsException e) { cpMonitor.incOperationFailure(null, e); @@ -209,348 +208,352 @@ private boolean attemptFallback() { private HostConnectionPool getFallbackHostPool(BaseOperation op, Long token) { int numRemotes = remoteDCNames.getEntireList().size(); - if (numRemotes == 0) { - throw new NoAvailableHostsException("Could not find any remote Racks for fallback"); - } - - int numTries = Math.min(numRemotes, cpConfig.getMaxFailoverCount()); - - DynoException lastEx = null; - - while ((numTries > 0)) { - - numTries--; - String remoteDC = remoteDCNames.getNextElement(); - HostSelectionStrategy remoteDCSelector = remoteRackSelectors.get(remoteDC); - - try { - - HostConnectionPool fallbackHostPool = - (op != null) ? remoteDCSelector.getPoolForOperation(op,cpConfig.getHashtag()) : remoteDCSelector.getPoolForToken(token); - - if (isConnectionPoolActive(fallbackHostPool)) { - return fallbackHostPool; - } - - } catch (NoAvailableHostsException e) { - cpMonitor.incOperationFailure(null, e); - lastEx = e; - } - } - - if (lastEx != null) { - throw lastEx; - } else { - throw new NoAvailableHostsException("Local rack host offline and could not find any remote hosts for fallback connection"); - } - } - - public Collection> getConnectionsToRing(TokenRackMapper tokenRackMapper, int duration, TimeUnit unit) throws NoAvailableHostsException, PoolExhaustedException { - String targetRack = localRack; - if (targetRack == null) { - // get tokens for random rack - targetRack = topology.get().getRandomRack(); - } - final Set tokens = topology.get().getTokenHostsForRack(targetRack).keySet(); - DynoConnectException lastEx = null; - - final List> connections = new ArrayList<>(); - - for (Long token : tokens) { - try { - // Cursor has a map of token to rack which indicates an affinity to a zone for that token. - // This is valid in case of an iterator based query like scan. - // Try to use that same rack if it is specified. - String rack = null; - if (tokenRackMapper != null) - rack = tokenRackMapper.getRackForToken(token); - if (rack != null) { - connections.add(getConnectionForTokenOnRackNoFallback(null, token, rack, duration, unit, new RunOnce())); - } else { - Connection c = getConnection(null, token, duration, unit, new RunOnce()); - if (tokenRackMapper != null) { - tokenRackMapper.setRackForToken(token, c.getHost().getRack()); - } - connections.add(c); - } - } catch (DynoConnectException e) { - logger.warn("Failed to get connection when getting all connections from ring", e.getMessage()); - lastEx = e; - break; - } - } - - if (lastEx != null) { - // Return all previously borrowed connection to avoid any connection leaks - for (Connection connection : connections) { - try { - connection.getParentConnectionPool().returnConnection(connection); - } catch (DynoConnectException e) { - // do nothing - } - } - throw lastEx; - - } else { - return connections; - } - } - - - private HostSelectionStrategy findSelectorForRack(String rack) { - if (localRack == null) { - return localSelector; - } - - if (localRack.equals(rack)) { - return localSelector; - } - - HostSelectionStrategy remoteSelector = remoteRackSelectors.get(rack); - return remoteSelector; - } - - private boolean isConnectionPoolActive(HostConnectionPool hPool) { - if (hPool == null) { - return false; - } - Host host = hPool.getHost(); - return host.isUp() && hPool.isActive(); - } - - private Map> getHostPoolsForRack(final Map> map, final String rack) { - - Map> dcPools = - CollectionUtils.filterKeys(map, new Predicate() { - - @Override - public boolean apply(HostToken x) { - if (localRack == null) { - return true; - } - return rack.equals(x.getHost().getRack()); - } - }); - return dcPools; - } - - /** - * Initialize the topology with the host pools obtained from discovery. - * hPools comes from discovery. - * @param hPools - */ - public void initWithHosts(Map> hPools) { - - // Get the list of tokens for these hosts - //tokenSupplier.initWithHosts(hPools.keySet()); - List allHostTokens = tokenSupplier.getTokens(hPools.keySet()); - Map> tokenPoolMap = new HashMap>(); - - // Update inner state with the host tokens. - for (HostToken hToken : allHostTokens) { - hostTokens.put(hToken.getHost(), hToken); - tokenPoolMap.put(hToken, hPools.get(hToken.getHost())); - } - - // Initialize Local selector - Map> localPools = getHostPoolsForRack(tokenPoolMap, localRack); - localSelector.initWithHosts(localPools); - if (localSelector.isTokenAware()) { - replicationFactor.set(calculateReplicationFactorForDC(allHostTokens, cpConfig.getLocalDataCenter())); - } - - // Initialize Remote selectors - Set remoteRacks = hPools.keySet().stream().map(h -> h.getRack()).filter(rack -> rack != null && !rack.equals(localRack)).collect(Collectors.toSet()); - - for (String rack : remoteRacks) { - Map> dcPools = getHostPoolsForRack(tokenPoolMap, rack); - HostSelectionStrategy remoteSelector = selectorFactory.vendPoolSelectionStrategy(); - remoteSelector.initWithHosts(dcPools); - remoteRackSelectors.put(rack, remoteSelector); - } - - remoteDCNames.swapWithList(remoteRackSelectors.keySet()); + if (numRemotes == 0) { + throw new NoAvailableHostsException("Could not find any remote Racks for fallback"); + } + + int numTries = Math.min(numRemotes, cpConfig.getMaxFailoverCount()); + + DynoException lastEx = null; + + while ((numTries > 0)) { + + numTries--; + String remoteDC = remoteDCNames.getNextElement(); + HostSelectionStrategy remoteDCSelector = remoteRackSelectors.get(remoteDC); + + try { + + HostConnectionPool fallbackHostPool = + (op != null) ? remoteDCSelector.getPoolForOperation(op, cpConfig.getHashtag()) : remoteDCSelector.getPoolForToken(token); + + if (isConnectionPoolActive(fallbackHostPool)) { + return fallbackHostPool; + } + + } catch (NoAvailableHostsException e) { + cpMonitor.incOperationFailure(null, e); + lastEx = e; + } + } + + if (lastEx != null) { + throw lastEx; + } else { + throw new NoAvailableHostsException("Local rack host offline and could not find any remote hosts for fallback connection"); + } + } + + public Collection> getConnectionsToRing(TokenRackMapper tokenRackMapper, int duration, TimeUnit unit) throws NoAvailableHostsException, PoolExhaustedException { + String targetRack = localRack; + if (targetRack == null) { + // get tokens for random rack + targetRack = topology.get().getRandomRack(); + } + final Set tokens = topology.get().getTokenHostsForRack(targetRack).keySet(); + DynoConnectException lastEx = null; + + final List> connections = new ArrayList<>(); + + for (Long token : tokens) { + try { + // Cursor has a map of token to rack which indicates an affinity to a zone for that token. + // This is valid in case of an iterator based query like scan. + // Try to use that same rack if it is specified. + String rack = null; + if (tokenRackMapper != null) + rack = tokenRackMapper.getRackForToken(token); + if (rack != null) { + connections.add(getConnectionForTokenOnRackNoFallback(null, token, rack, duration, unit, new RunOnce())); + } else { + Connection c = getConnection(null, token, duration, unit, new RunOnce()); + if (tokenRackMapper != null) { + tokenRackMapper.setRackForToken(token, c.getHost().getRack()); + } + connections.add(c); + } + } catch (DynoConnectException e) { + logger.warn("Failed to get connection when getting all connections from ring", e.getMessage()); + lastEx = e; + break; + } + } + + if (lastEx != null) { + // Return all previously borrowed connection to avoid any connection leaks + for (Connection connection : connections) { + try { + connection.getParentConnectionPool().returnConnection(connection); + } catch (DynoConnectException e) { + // do nothing + } + } + throw lastEx; + + } else { + return connections; + } + } + + + private HostSelectionStrategy findSelectorForRack(String rack) { + if (localRack == null) { + return localSelector; + } + + if (localRack.equals(rack)) { + return localSelector; + } + + HostSelectionStrategy remoteSelector = remoteRackSelectors.get(rack); + return remoteSelector; + } + + private boolean isConnectionPoolActive(HostConnectionPool hPool) { + if (hPool == null) { + return false; + } + Host host = hPool.getHost(); + return host.isUp() && hPool.isActive(); + } + + private Map> getHostPoolsForRack(final Map> map, final String rack) { + + Map> dcPools = + CollectionUtils.filterKeys(map, new Predicate() { + + @Override + public boolean apply(HostToken x) { + if (localRack == null) { + return true; + } + return rack.equals(x.getHost().getRack()); + } + }); + return dcPools; + } + + /** + * Initialize the topology with the host pools obtained from discovery. + * hPools comes from discovery. + * + * @param hPools + */ + public void initWithHosts(Map> hPools) { + + // Get the list of tokens for these hosts + //tokenSupplier.initWithHosts(hPools.keySet()); + List allHostTokens = tokenSupplier.getTokens(hPools.keySet()); + Map> tokenPoolMap = new HashMap>(); + + // Update inner state with the host tokens. + for (HostToken hToken : allHostTokens) { + hostTokens.put(hToken.getHost(), hToken); + tokenPoolMap.put(hToken, hPools.get(hToken.getHost())); + } + + // Initialize Local selector + Map> localPools = getHostPoolsForRack(tokenPoolMap, localRack); + localSelector.initWithHosts(localPools); + if (localSelector.isTokenAware()) { + replicationFactor.set(calculateReplicationFactorForDC(allHostTokens, cpConfig.getLocalDataCenter())); + } + + // Initialize Remote selectors + Set remoteRacks = hPools.keySet().stream().map(h -> h.getRack()).filter(rack -> rack != null && !rack.equals(localRack)).collect(Collectors.toSet()); + + for (String rack : remoteRacks) { + Map> dcPools = getHostPoolsForRack(tokenPoolMap, rack); + HostSelectionStrategy remoteSelector = selectorFactory.vendPoolSelectionStrategy(); + remoteSelector.initWithHosts(dcPools); + remoteRackSelectors.put(rack, remoteSelector); + } + + remoteDCNames.swapWithList(remoteRackSelectors.keySet()); topology.set(createTokenPoolTopology(allHostTokens)); - } - - /** - * Calculate replication factor from the given list of hosts - * @param allHostTokens - * @return replicationFactor - */ - int calculateReplicationFactor(List allHostTokens) { - return calculateReplicationFactorForDC(allHostTokens, null); - } - - /** - * Calculate replication factor for a datacenter. - * If datacenter is null we use one of the hosts from the list and use its DC. - * @param allHostTokens - * @param dataCenter - * @return replicationFactor for the dataCenter - */ - int calculateReplicationFactorForDC(List allHostTokens, String dataCenter) { - Map groups = new HashMap<>(); - - Set uniqueHostTokens = new HashSet<>(allHostTokens); - if (dataCenter == null) { - if(localRack != null) { - dataCenter = localRack.substring(0, localRack.length() - 1); - } else { - // No DC specified. Get the DC from the first host and use its replication factor - dataCenter = allHostTokens.get(0).getHost().getRack().substring(0, localRack.length() - 1); - } - } - - for (HostToken hostToken: uniqueHostTokens) { - if(hostToken.getHost().getRack().contains(dataCenter)) { - Long token = hostToken.getToken(); - if (groups.containsKey(token)) { - int current = groups.get(token); - groups.put(token, current + 1); - } else { - groups.put(token, 1); - } - } - } - - Set uniqueCounts = new HashSet<>(groups.values()); - - if (uniqueCounts.size() > 1) { - throw new RuntimeException("Invalid configuration - replication factor cannot be asymmetric"); - } - - int rf = uniqueCounts.toArray(new Integer[uniqueCounts.size()])[0]; - - if (rf > 3) { - logger.warn("Replication Factor is high: " + uniqueHostTokens); - } - - return rf; - - } + } + + /** + * Calculate replication factor from the given list of hosts + * + * @param allHostTokens + * @return replicationFactor + */ + int calculateReplicationFactor(List allHostTokens) { + return calculateReplicationFactorForDC(allHostTokens, null); + } + + /** + * Calculate replication factor for a datacenter. + * If datacenter is null we use one of the hosts from the list and use its DC. + * + * @param allHostTokens + * @param dataCenter + * @return replicationFactor for the dataCenter + */ + int calculateReplicationFactorForDC(List allHostTokens, String dataCenter) { + Map groups = new HashMap<>(); + + Set uniqueHostTokens = new HashSet<>(allHostTokens); + if (dataCenter == null) { + if (localRack != null) { + dataCenter = localRack.substring(0, localRack.length() - 1); + } else { + // No DC specified. Get the DC from the first host and use its replication factor + dataCenter = allHostTokens.get(0).getHost().getRack().substring(0, localRack.length() - 1); + } + } + + for (HostToken hostToken : uniqueHostTokens) { + if (hostToken.getHost().getRack().contains(dataCenter)) { + Long token = hostToken.getToken(); + if (groups.containsKey(token)) { + int current = groups.get(token); + groups.put(token, current + 1); + } else { + groups.put(token, 1); + } + } + } + + Set uniqueCounts = new HashSet<>(groups.values()); + + if (uniqueCounts.size() > 1) { + throw new RuntimeException("Invalid configuration - replication factor cannot be asymmetric"); + } + + int rf = uniqueCounts.toArray(new Integer[uniqueCounts.size()])[0]; + + if (rf > 3) { + logger.warn("Replication Factor is high: " + uniqueHostTokens); + } + + return rf; + + } public void addHost(Host host, HostConnectionPool hostPool) { - HostToken hostToken = tokenSupplier.getTokenForHost(host, hostTokens.keySet()); - if (hostToken == null) { - throw new DynoConnectException("Could not find host token for host: " + host); - } - - hostTokens.put(hostToken.getHost(), hostToken); - - HostSelectionStrategy selector = findSelectorForRack(host.getRack()); - if (selector != null) { - selector.addHostPool(hostToken, hostPool); - } - topology.get().addHostToken(hostToken.getHost().getRack(), hostToken.getToken(), hostToken.getHost()); - } - - public void removeHost(Host host) { - - HostToken hostToken = hostTokens.remove(host); - if (hostToken != null) { - HostSelectionStrategy selector = findSelectorForRack(host.getRack()); - if (selector != null) { - selector.removeHostPool(hostToken); - } - topology.get().removeHost(hostToken.getHost().getRack(), hostToken.getToken(), hostToken.getHost()); - } - } - - private class DefaultSelectionFactory implements HostSelectionStrategyFactory { - - private final LoadBalancingStrategy lbStrategy; - private final HashPartitioner hashPartitioner; - - private DefaultSelectionFactory(ConnectionPoolConfiguration config) { - lbStrategy = config.getLoadBalancingStrategy(); - hashPartitioner = config.getHashPartitioner(); - } - - @Override - public HostSelectionStrategy vendPoolSelectionStrategy() { - - switch (lbStrategy) { - case RoundRobin: - return new RoundRobinSelection(); - case TokenAware: - return hashPartitioner != null - ? new TokenAwareSelection(hashPartitioner) - : new TokenAwareSelection(); - default : - throw new RuntimeException("LoadBalancing strategy not supported! " + cpConfig.getLoadBalancingStrategy().name()); - } - } - } - - private void updateTokenPoolTopology(TokenPoolTopology topology) { - if (localRack != null) { - addTokens(topology, localRack, localSelector); - } - for (String remoteRack : remoteRackSelectors.keySet()) { - addTokens(topology, remoteRack, remoteRackSelectors.get(remoteRack)); - } - } - - /** - * Create token pool topology from the host tokens - * @param allHostTokens - * @return tokenPoolTopology with the host information - */ - public TokenPoolTopology createTokenPoolTopology(List allHostTokens) { - TokenPoolTopology topology = new TokenPoolTopology(replicationFactor.get()); - for (HostToken hostToken : allHostTokens) { - String rack = hostToken.getHost().getRack(); - topology.addHostToken(rack, hostToken.getToken(), hostToken.getHost()); - } - updateTokenPoolTopology(topology); + HostToken hostToken = tokenSupplier.getTokenForHost(host, hostTokens.keySet()); + if (hostToken == null) { + throw new DynoConnectException("Could not find host token for host: " + host); + } + + hostTokens.put(hostToken.getHost(), hostToken); + + HostSelectionStrategy selector = findSelectorForRack(host.getRack()); + if (selector != null) { + selector.addHostPool(hostToken, hostPool); + } + topology.get().addHostToken(hostToken.getHost().getRack(), hostToken.getToken(), hostToken.getHost()); + } + + public void removeHost(Host host) { + + HostToken hostToken = hostTokens.remove(host); + if (hostToken != null) { + HostSelectionStrategy selector = findSelectorForRack(host.getRack()); + if (selector != null) { + selector.removeHostPool(hostToken); + } + topology.get().removeHost(hostToken.getHost().getRack(), hostToken.getToken(), hostToken.getHost()); + } + } + + private class DefaultSelectionFactory implements HostSelectionStrategyFactory { + + private final LoadBalancingStrategy lbStrategy; + private final HashPartitioner hashPartitioner; + + private DefaultSelectionFactory(ConnectionPoolConfiguration config) { + lbStrategy = config.getLoadBalancingStrategy(); + hashPartitioner = config.getHashPartitioner(); + } + + @Override + public HostSelectionStrategy vendPoolSelectionStrategy() { + + switch (lbStrategy) { + case RoundRobin: + return new RoundRobinSelection(); + case TokenAware: + return hashPartitioner != null + ? new TokenAwareSelection(hashPartitioner) + : new TokenAwareSelection(); + default: + throw new RuntimeException("LoadBalancing strategy not supported! " + cpConfig.getLoadBalancingStrategy().name()); + } + } + } + + private void updateTokenPoolTopology(TokenPoolTopology topology) { + if (localRack != null) { + addTokens(topology, localRack, localSelector); + } + for (String remoteRack : remoteRackSelectors.keySet()) { + addTokens(topology, remoteRack, remoteRackSelectors.get(remoteRack)); + } + } + + /** + * Create token pool topology from the host tokens + * + * @param allHostTokens + * @return tokenPoolTopology with the host information + */ + public TokenPoolTopology createTokenPoolTopology(List allHostTokens) { + TokenPoolTopology topology = new TokenPoolTopology(replicationFactor.get()); + for (HostToken hostToken : allHostTokens) { + String rack = hostToken.getHost().getRack(); + topology.addHostToken(rack, hostToken.getToken(), hostToken.getHost()); + } + updateTokenPoolTopology(topology); return topology; } - public TokenPoolTopology getTokenPoolTopology() { - TokenPoolTopology topology = new TokenPoolTopology(replicationFactor.get()); - updateTokenPoolTopology(topology); - return topology; + public TokenPoolTopology getTokenPoolTopology() { + TokenPoolTopology topology = new TokenPoolTopology(replicationFactor.get()); + updateTokenPoolTopology(topology); + return topology; - } + } - private void addTokens(TokenPoolTopology topology, String rack, HostSelectionStrategy selectionStrategy) { + private void addTokens(TokenPoolTopology topology, String rack, HostSelectionStrategy selectionStrategy) { - Collection> pools = selectionStrategy.getOrderedHostPools(); - for (HostConnectionPool pool : pools) { - if (pool == null) { - continue; - } - HostToken hToken = hostTokens.get(pool.getHost()); - if (hToken == null) { - continue; - } - topology.addToken(rack, hToken.getToken(), pool); - } - } + Collection> pools = selectionStrategy.getOrderedHostPools(); + for (HostConnectionPool pool : pools) { + if (pool == null) { + continue; + } + HostToken hToken = hostTokens.get(pool.getHost()); + if (hToken == null) { + continue; + } + topology.addToken(rack, hToken.getToken(), pool); + } + } public Long getTokenForKey(String key) { return localSelector.getTokenForKey(key).getToken(); } - @Override - public String toString() { - return "HostSelectionWithFallback{" + - "localDataCenter='" + localDataCenter + '\'' + - ", localRack='" + localRack + '\'' + - ", localSelector=" + localSelector + - ", remoteDCSelectors=" + remoteRackSelectors + - ", hostTokens=" + hostTokens + - ", tokenSupplier=" + tokenSupplier + - ", cpConfig=" + cpConfig + - ", cpMonitor=" + cpMonitor + - ", replicationFactor=" + replicationFactor + - ", topology=" + topology + - ", remoteDCNames=" + remoteDCNames + - ", selectorFactory=" + selectorFactory + - '}'; - } + @Override + public String toString() { + return "HostSelectionWithFallback{" + + "localDataCenter='" + localDataCenter + '\'' + + ", localRack='" + localRack + '\'' + + ", localSelector=" + localSelector + + ", remoteDCSelectors=" + remoteRackSelectors + + ", hostTokens=" + hostTokens + + ", tokenSupplier=" + tokenSupplier + + ", cpConfig=" + cpConfig + + ", cpMonitor=" + cpMonitor + + ", replicationFactor=" + replicationFactor + + ", topology=" + topology + + ", remoteDCNames=" + remoteDCNames + + ", selectorFactory=" + selectorFactory + + '}'; + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/HostToken.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/HostToken.java index 630ba047..45c8e8f2 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/HostToken.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/HostToken.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,65 +18,64 @@ import com.netflix.dyno.connectionpool.Host; /** - * Simple class that encapsulates a host and it's token on the dynomite topology ring. - * The class must implements Comparable so that it can be stored in a sorted collection that can then be - * used in search algos like binary search for efficiently finding the owning token for a hash operation key. - * - * @author poberai + * Simple class that encapsulates a host and it's token on the dynomite topology ring. + * The class must implements Comparable so that it can be stored in a sorted collection that can then be + * used in search algos like binary search for efficiently finding the owning token for a hash operation key. * + * @author poberai */ public class HostToken implements Comparable { - private final Long token; - private final Host host; + private final Long token; + private final Host host; + + public HostToken(Long token, Host host) { + this.token = token; + this.host = host; + } + + public Long getToken() { + return token; + } + + public Host getHost() { + return host; + } - public HostToken(Long token, Host host) { - this.token = token; - this.host = host; - } + @Override + public String toString() { + return "HostToken [token=" + token + ", host=" + host + "]"; + } - public Long getToken() { - return token; - } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((host == null) ? 0 : host.hashCode()); + result = prime * result + ((token == null) ? 0 : token.hashCode()); + return result; + } - public Host getHost() { - return host; - } + @Override + public boolean equals(Object obj) { - @Override - public String toString() { - return "HostToken [token=" + token + ", host=" + host + "]"; - } + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((host == null) ? 0 : host.hashCode()); - result = prime * result + ((token == null) ? 0 : token.hashCode()); - return result; - } + HostToken other = (HostToken) obj; + boolean equals = true; + equals &= (token != null) ? (token.equals(other.token)) : (other.token == null); + equals &= (host != null) ? (host.equals(other.host)) : (other.host == null); + return equals; + } - @Override - public boolean equals(Object obj) { - - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - HostToken other = (HostToken) obj; - boolean equals = true; - equals &= (token != null) ? (token.equals(other.token)) : (other.token == null); - equals &= (host != null) ? (host.equals(other.host)) : (other.host == null); - return equals; - } + @Override + public int compareTo(Long o) { + return this.token.compareTo(o); + } - @Override - public int compareTo(Long o) { - return this.token.compareTo(o); - } - - public int compareTo(HostToken o) { - return this.token.compareTo(o.getToken()); - } + public int compareTo(HostToken o) { + return this.token.compareTo(o.getToken()); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/HttpEndpointBasedTokenMapSupplier.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/HttpEndpointBasedTokenMapSupplier.java index 7484d62f..7460e079 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/HttpEndpointBasedTokenMapSupplier.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/HttpEndpointBasedTokenMapSupplier.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -51,29 +51,29 @@ public class HttpEndpointBasedTokenMapSupplier extends AbstractTokenMapSupplier public HttpEndpointBasedTokenMapSupplier() { this(DefaultServerUrl, defaultPort); } - + public HttpEndpointBasedTokenMapSupplier(int port) { - this(DefaultServerUrl, port); + this(DefaultServerUrl, port); } public HttpEndpointBasedTokenMapSupplier(String url, int port) { - super(port); - - /** - * If no port is passed means -1 then we will substitute to defaultPort - * else the passed one. - */ - url = url.replace("{port}", (port > -1) ? Integer.toString(port) : Integer.toString(defaultPort)); - serverUrl = url; + super(port); + + /** + * If no port is passed means -1 then we will substitute to defaultPort + * else the passed one. + */ + url = url.replace("{port}", (port > -1) ? Integer.toString(port) : Integer.toString(defaultPort)); + serverUrl = url; } @Override public String getTopologyJsonPayload(String hostname) { - try { - return getResponseViaHttp(hostname); - } catch (Exception e) { - throw new RuntimeException(e); - } + try { + return getResponseViaHttp(hostname); + } catch (Exception e) { + throw new RuntimeException(e); + } } /** @@ -81,130 +81,130 @@ public String getTopologyJsonPayload(String hostname) { */ @Override public String getTopologyJsonPayload(Set activeHosts) { - int count = NUM_RETRIER_ACROSS_NODES; - String response; - Exception lastEx = null; - - do { - try { - response = getTopologyFromRandomNodeWithRetry(activeHosts); - if (response != null) { - return response; - } - } catch (Exception e) { - lastEx = e; - } finally { - count--; - } - } while ((count > 0)); - - if (lastEx != null) { - if (lastEx instanceof ConnectTimeoutException) { - throw new TimeoutException("Unable to obtain topology", lastEx); - } - throw new DynoException(lastEx); - } else { - throw new DynoException("Could not contact dynomite for token map"); - } + int count = NUM_RETRIER_ACROSS_NODES; + String response; + Exception lastEx = null; + + do { + try { + response = getTopologyFromRandomNodeWithRetry(activeHosts); + if (response != null) { + return response; + } + } catch (Exception e) { + lastEx = e; + } finally { + count--; + } + } while ((count > 0)); + + if (lastEx != null) { + if (lastEx instanceof ConnectTimeoutException) { + throw new TimeoutException("Unable to obtain topology", lastEx); + } + throw new DynoException(lastEx); + } else { + throw new DynoException("Could not contact dynomite for token map"); + } } private String getResponseViaHttp(String hostname) throws Exception { - String url = serverUrl; - url = url.replace("{hostname}", hostname); - - if (Logger.isDebugEnabled()) { - Logger.debug("Making http call to url: " + url); - } - - DefaultHttpClient client = new DefaultHttpClient(); - client.getParams().setParameter(HttpConnectionParams.CONNECTION_TIMEOUT, 2000); - client.getParams().setParameter(HttpConnectionParams.SO_TIMEOUT, 5000); - - DefaultHttpRequestRetryHandler retryhandler = new DefaultHttpRequestRetryHandler(NUM_RETRIER_ACROSS_NODES, - true); - client.setHttpRequestRetryHandler(retryhandler); - - HttpGet get = new HttpGet(url); - - HttpResponse response = client.execute(get); - int statusCode = response.getStatusLine().getStatusCode(); - if (!(statusCode == 200)) { - Logger.error("Got non 200 status code from " + url); - return null; - } - - InputStream in = null; - try { - in = response.getEntity().getContent(); - return IOUtilities.toString(in); - } finally { - if (in != null) { - in.close(); - } - } + String url = serverUrl; + url = url.replace("{hostname}", hostname); + + if (Logger.isDebugEnabled()) { + Logger.debug("Making http call to url: " + url); + } + + DefaultHttpClient client = new DefaultHttpClient(); + client.getParams().setParameter(HttpConnectionParams.CONNECTION_TIMEOUT, 2000); + client.getParams().setParameter(HttpConnectionParams.SO_TIMEOUT, 5000); + + DefaultHttpRequestRetryHandler retryhandler = new DefaultHttpRequestRetryHandler(NUM_RETRIER_ACROSS_NODES, + true); + client.setHttpRequestRetryHandler(retryhandler); + + HttpGet get = new HttpGet(url); + + HttpResponse response = client.execute(get); + int statusCode = response.getStatusLine().getStatusCode(); + if (!(statusCode == 200)) { + Logger.error("Got non 200 status code from " + url); + return null; + } + + InputStream in = null; + try { + in = response.getEntity().getContent(); + return IOUtilities.toString(in); + } finally { + if (in != null) { + in.close(); + } + } } /** * Finds a random host from the set of active hosts to perform * cluster_describe - * + * * @param activeHosts * @return a random host */ public Host getRandomHost(Set activeHosts) { - Random random = new Random(); + Random random = new Random(); - List hostsUp = new ArrayList(CollectionUtils.filter(activeHosts, new Predicate() { + List hostsUp = new ArrayList(CollectionUtils.filter(activeHosts, new Predicate() { - @Override - public boolean apply(Host x) { - return x.isUp(); - } - })); + @Override + public boolean apply(Host x) { + return x.isUp(); + } + })); - return hostsUp.get(random.nextInt(hostsUp.size())); + return hostsUp.get(random.nextInt(hostsUp.size())); } /** * Tries multiple nodes, and it only bubbles up the last node's exception. * We want to bubble up the exception in order for the last node to be * removed from the connection pool. - * + * * @param activeHosts * @return the topology from cluster_describe */ private String getTopologyFromRandomNodeWithRetry(Set activeHosts) { - int count = NUM_RETRIES_PER_NODE; - String nodeResponse; - Exception lastEx; - final Host randomHost = getRandomHost(activeHosts); - do { - try { - lastEx = null; - nodeResponse = getResponseViaHttp(randomHost.getHostName()); - if (nodeResponse != null) { - Logger.info("Received topology from " + randomHost); - return nodeResponse; - } - } catch (Exception e) { - Logger.info("cannot get topology from : " + randomHost); - lastEx = e; - } finally { - count--; - } - - } while ((count > 0)); - - if (lastEx != null) { - if (lastEx instanceof ConnectTimeoutException) { - throw new TimeoutException("Unable to obtain topology", lastEx).setHost(randomHost); - } - throw new DynoException(String.format("Unable to obtain topology from %s", randomHost), lastEx); - } else { - throw new DynoException(String.format("Could not contact dynomite manager for token map on %s", randomHost)); - } + int count = NUM_RETRIES_PER_NODE; + String nodeResponse; + Exception lastEx; + final Host randomHost = getRandomHost(activeHosts); + do { + try { + lastEx = null; + nodeResponse = getResponseViaHttp(randomHost.getHostName()); + if (nodeResponse != null) { + Logger.info("Received topology from " + randomHost); + return nodeResponse; + } + } catch (Exception e) { + Logger.info("cannot get topology from : " + randomHost); + lastEx = e; + } finally { + count--; + } + + } while ((count > 0)); + + if (lastEx != null) { + if (lastEx instanceof ConnectTimeoutException) { + throw new TimeoutException("Unable to obtain topology", lastEx).setHost(randomHost); + } + throw new DynoException(String.format("Unable to obtain topology from %s", randomHost), lastEx); + } else { + throw new DynoException(String.format("Could not contact dynomite manager for token map on %s", randomHost)); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/RoundRobinSelection.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/RoundRobinSelection.java index d6bea508..5cd93735 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/RoundRobinSelection.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/RoundRobinSelection.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,136 +30,136 @@ /** * Simple impl of {@link HostSelectionStrategy} that uses ROUND ROBIN. It employs the {@link CircularList} data structure - * to provide RR balancing in a thread safe manner. + * to provide RR balancing in a thread safe manner. * Note that the class can also support dynamically adding and removing {@link Host} - * @author poberai * * @param + * @author poberai */ public class RoundRobinSelection implements HostSelectionStrategy { - - // The total set of host pools. Once the host is selected, we ask it's corresponding pool to vend a connection - private final ConcurrentHashMap> tokenPools = new ConcurrentHashMap>(); - - // the circular list of Host over which we load balance in a round robin fashion - private final CircularList circularList = new CircularList(null); - - public RoundRobinSelection() { - } - - @Override - public HostConnectionPool getPoolForOperation(BaseOperation op, String hashtag) throws NoAvailableHostsException { - - int numTries = circularList.getSize(); - HostConnectionPool lastPool = null; - - while (numTries > 0) { - lastPool = getNextConnectionPool(); - numTries--; - if (lastPool.isActive() && lastPool.getHost().isUp()) { - return lastPool; - } - } - - // If we reach here then we haven't found an active pool. Return the last inactive pool anyways, - // and HostSelectionWithFallback can choose a fallback pool from another dc - return lastPool; - } - - @Override - public Map, BaseOperation> getPoolsForOperationBatch(Collection> ops) throws NoAvailableHostsException { - Map, BaseOperation> map = new HashMap, BaseOperation>(); - for (BaseOperation op : ops) { - map.put(getNextConnectionPool(), op); - } - return map; - } - - - @Override - public List> getOrderedHostPools() { - return new ArrayList>(tokenPools.values()); - } - - - @Override - public HostConnectionPool getPoolForToken(Long token) { - return tokenPools.get(token); - } - - - @Override - public List> getPoolsForTokens(Long start, Long end) { - throw new UnsupportedOperationException(); - } + + // The total set of host pools. Once the host is selected, we ask it's corresponding pool to vend a connection + private final ConcurrentHashMap> tokenPools = new ConcurrentHashMap>(); + + // the circular list of Host over which we load balance in a round robin fashion + private final CircularList circularList = new CircularList(null); + + public RoundRobinSelection() { + } + + @Override + public HostConnectionPool getPoolForOperation(BaseOperation op, String hashtag) throws NoAvailableHostsException { + + int numTries = circularList.getSize(); + HostConnectionPool lastPool = null; + + while (numTries > 0) { + lastPool = getNextConnectionPool(); + numTries--; + if (lastPool.isActive() && lastPool.getHost().isUp()) { + return lastPool; + } + } + + // If we reach here then we haven't found an active pool. Return the last inactive pool anyways, + // and HostSelectionWithFallback can choose a fallback pool from another dc + return lastPool; + } + + @Override + public Map, BaseOperation> getPoolsForOperationBatch(Collection> ops) throws NoAvailableHostsException { + Map, BaseOperation> map = new HashMap, BaseOperation>(); + for (BaseOperation op : ops) { + map.put(getNextConnectionPool(), op); + } + return map; + } + + + @Override + public List> getOrderedHostPools() { + return new ArrayList>(tokenPools.values()); + } + + + @Override + public HostConnectionPool getPoolForToken(Long token) { + return tokenPools.get(token); + } + + + @Override + public List> getPoolsForTokens(Long start, Long end) { + throw new UnsupportedOperationException(); + } @Override public HostToken getTokenForKey(String key) throws UnsupportedOperationException { throw new UnsupportedOperationException("Not implemented for Round Robin load balancing strategy"); } - - @Override - public HostToken getTokenForKey(byte[] key) throws UnsupportedOperationException { + + @Override + public HostToken getTokenForKey(byte[] key) throws UnsupportedOperationException { throw new UnsupportedOperationException("Not implemented for Round Robin load balancing strategy"); - } + } private HostConnectionPool getNextConnectionPool() throws NoAvailableHostsException { - HostToken hostToken = circularList.getNextElement(); - - HostConnectionPool hostPool = tokenPools.get(hostToken.getToken()); - if (hostPool == null) { - throw new NoAvailableHostsException("Could not find host connection pool for host token: " + hostToken); - } - return hostPool; - } - - @Override - public void initWithHosts(Map> hPools) { - - for (HostToken token : hPools.keySet()) { - tokenPools.put(token.getToken(), hPools.get(token)); - } - circularList.swapWithList(hPools.keySet()); - } - - @Override - public boolean addHostPool(HostToken host, HostConnectionPool hostPool) { - - HostConnectionPool prevPool = tokenPools.put(host.getToken(), hostPool); - if (prevPool == null) { - List newHostList = new ArrayList(circularList.getEntireList()); - newHostList.add(host); - circularList.swapWithList(newHostList); - } - return prevPool == null; - } - - @Override - public boolean removeHostPool(HostToken host) { - - HostConnectionPool prevPool = tokenPools.get(host.getToken()); - if (prevPool != null) { - List newHostList = new ArrayList(circularList.getEntireList()); - newHostList.remove(host); - circularList.swapWithList(newHostList); - tokenPools.remove(host.getToken()); - } - return prevPool != null; - } - - @Override - public boolean isTokenAware() { - return false; - } - - @Override - public boolean isEmpty() { - return tokenPools.isEmpty(); - } - - public String toString() { - return "RoundRobinSelector: list: " + circularList.toString(); - } + HostToken hostToken = circularList.getNextElement(); + + HostConnectionPool hostPool = tokenPools.get(hostToken.getToken()); + if (hostPool == null) { + throw new NoAvailableHostsException("Could not find host connection pool for host token: " + hostToken); + } + return hostPool; + } + + @Override + public void initWithHosts(Map> hPools) { + + for (HostToken token : hPools.keySet()) { + tokenPools.put(token.getToken(), hPools.get(token)); + } + circularList.swapWithList(hPools.keySet()); + } + + @Override + public boolean addHostPool(HostToken host, HostConnectionPool hostPool) { + + HostConnectionPool prevPool = tokenPools.put(host.getToken(), hostPool); + if (prevPool == null) { + List newHostList = new ArrayList(circularList.getEntireList()); + newHostList.add(host); + circularList.swapWithList(newHostList); + } + return prevPool == null; + } + + @Override + public boolean removeHostPool(HostToken host) { + + HostConnectionPool prevPool = tokenPools.get(host.getToken()); + if (prevPool != null) { + List newHostList = new ArrayList(circularList.getEntireList()); + newHostList.remove(host); + circularList.swapWithList(newHostList); + tokenPools.remove(host.getToken()); + } + return prevPool != null; + } + + @Override + public boolean isTokenAware() { + return false; + } + + @Override + public boolean isEmpty() { + return tokenPools.isEmpty(); + } + + public String toString() { + return "RoundRobinSelector: list: " + circularList.toString(); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelection.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelection.java index f11320b2..ae0a6857 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelection.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelection.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -38,23 +38,22 @@ * the TOKEN AWARE algorithm. Note that this component needs to be aware of the * dynomite ring topology to be able to successfully map to the correct token * owner for any key of an {@link Operation} - * - * @author poberai - * @author ipapapa * * @param + * @author poberai + * @author ipapapa */ public class TokenAwareSelection implements HostSelectionStrategy { - + private final BinarySearchTokenMapper tokenMapper; private final ConcurrentHashMap> tokenPools = new ConcurrentHashMap>(); - - public TokenAwareSelection() { - - this(new Murmur1HashPartitioner()); - } - + + public TokenAwareSelection() { + + this(new Murmur1HashPartitioner()); + } + public TokenAwareSelection(HashPartitioner hashPartitioner) { this.tokenMapper = new BinarySearchTokenMapper(hashPartitioner); @@ -78,7 +77,7 @@ public Long get(HostToken x) { /** * Identifying the proper pool for the operation. A couple of things that may affect the decision * (a) hashtags: In this case we will construct the key by decomposing from the hashtag - * (b) type of key: string keys vs binary keys. + * (b) type of key: string keys vs binary keys. * In binary keys hashtags do not really matter. */ @Override @@ -89,11 +88,11 @@ public HostConnectionPool getPoolForOperation(BaseOperation op, Strin HostToken hToken; if (key != null) { - // If a hashtag is provided by Dynomite then we use that to create the key to hash. - if (hashtag == null || hashtag.isEmpty()) { + // If a hashtag is provided by Dynomite then we use that to create the key to hash. + if (hashtag == null || hashtag.isEmpty()) { hToken = this.getTokenForKey(key); - } else { - String hashValue = StringUtils.substringBetween(key,Character.toString(hashtag.charAt(0)), Character.toString(hashtag.charAt(1))); + } else { + String hashValue = StringUtils.substringBetween(key, Character.toString(hashtag.charAt(0)), Character.toString(hashtag.charAt(1))); hToken = this.getTokenForKey(hashValue); } @@ -107,7 +106,7 @@ public HostConnectionPool getPoolForOperation(BaseOperation op, Strin "Could not find host connection pool for key: " + key + ", hash: " + tokenMapper.hash(key) + " Token:" + hToken.getToken()); } } else { - // the key is binary + // the key is binary byte[] binaryKey = op.getBinaryKey(); hToken = this.getTokenForKey(binaryKey); if (hToken == null) { @@ -150,7 +149,7 @@ public HostToken getTokenForKey(String key) throws UnsupportedOperationException Long keyHash = tokenMapper.hash(key); return tokenMapper.getToken(keyHash); } - + @Override public HostToken getTokenForKey(byte[] key) throws UnsupportedOperationException { Long keyHash = tokenMapper.hash(key); @@ -160,45 +159,45 @@ public HostToken getTokenForKey(byte[] key) throws UnsupportedOperationException @Override public boolean addHostPool(HostToken hostToken, HostConnectionPool hostPool) { - HostConnectionPool prevPool = tokenPools.put(hostToken.getToken(), hostPool); - if (prevPool == null) { - tokenMapper.addHostToken(hostToken); - return true; - } else { - return false; - } + HostConnectionPool prevPool = tokenPools.put(hostToken.getToken(), hostPool); + if (prevPool == null) { + tokenMapper.addHostToken(hostToken); + return true; + } else { + return false; + } } @Override public boolean removeHostPool(HostToken hostToken) { - HostConnectionPool prev = tokenPools.get(hostToken.getToken()); - if (prev != null) { - tokenPools.remove(hostToken.getToken()); - return true; - } else { - return false; - } + HostConnectionPool prev = tokenPools.get(hostToken.getToken()); + if (prev != null) { + tokenPools.remove(hostToken.getToken()); + return true; + } else { + return false; + } } @Override public boolean isTokenAware() { - return true; + return true; } @Override public boolean isEmpty() { - return tokenPools.isEmpty(); + return tokenPools.isEmpty(); } public Long getKeyHash(String key) { - Long keyHash = tokenMapper.hash(key); - return keyHash; + Long keyHash = tokenMapper.hash(key); + return keyHash; } @Override public String toString() { - return "TokenAwareSelection: " + tokenMapper.toString(); + return "TokenAwareSelection: " + tokenMapper.toString(); } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/CollectionUtils.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/CollectionUtils.java index 2c5e839b..41a15185 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/CollectionUtils.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/CollectionUtils.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,130 +24,130 @@ /** * Simple utils that operation on collections. Use of this class helps avoid many uses of collection utilities in guava - * and we want to avoid using guava as much as possible to minimize dep jar version conflicts. - * - * @author poberai + * and we want to avoid using guava as much as possible to minimize dep jar version conflicts. * + * @author poberai */ public class CollectionUtils { - public interface Transform { - public Y get(X x); - } - - public interface MapEntryTransform { - public Z get(X x, Y y); - } - - public static interface Predicate { - public boolean apply(X x); - } - - public static Collection transform(Collection from, Transform transform) { - - List list = new ArrayList(); - for (X x : from) { - Y y = transform.get(x); - list.add(y); - } - return list; - } - - public static Collection filter(Collection from, Predicate predicate) { - - List list = new ArrayList(); - for (X x : from) { - if (predicate.apply(x)) { - list.add(x); - } - } - return list; - } - - - public static X find(Collection from, Predicate predicate) { - - for (X x : from) { - if (predicate.apply(x)) { - return x; - } - } - return null; - } - - public static Map filterKeys(Map from, Predicate predicate) { - - Map toMap = new HashMap(); - for (X x : from.keySet()) { - if (predicate.apply(x)) { - toMap.put(x, from.get(x)); - } - } - return toMap; - } - - public static void transform(Map from, Map to, MapEntryTransform transform) { - - for (X x : from.keySet()) { - Y fromValue = from.get(x); - Z toValue = transform.get(x, fromValue); - to.put(x, toValue); - } - } - - public static Map transform(Map from, MapEntryTransform transform) { - - Map toMap = new HashMap(); - transform(from, toMap, transform); - return toMap; - } - - public static Map transformMapKeys(Map from, Transform transform) { - - Map toMap = new HashMap(); - for (X x : from.keySet()) { - Z z = from.get(x); - if (z != null) { - Y y = transform.get(x); - toMap.put(y, z); - } - } - return toMap; - } - - public static MapDifference difference(Map left, Map right) { - - MapDifference diff = new MapDifference(); - - for (X keyInLeft: left.keySet()) { - - if (!right.containsKey(keyInLeft)) { - diff.leftOnly.put(keyInLeft, left.get(keyInLeft)); - } - } - for (X keyInRight: right.keySet()) { - - if (!left.containsKey(keyInRight)) { - diff.rightOnly.put(keyInRight, right.get(keyInRight)); - } - } - return diff; - } - - public static class MapDifference { - - private Map leftOnly = new HashMap(); - private Map rightOnly = new HashMap(); - - public Map entriesOnlyOnLeft() { - return leftOnly; - } - public Map entriesOnlyOnRight() { - return rightOnly; - } - } - - public static List newArrayList(X ... args) { - return Arrays.asList(args); - } + public interface Transform { + public Y get(X x); + } + + public interface MapEntryTransform { + public Z get(X x, Y y); + } + + public static interface Predicate { + public boolean apply(X x); + } + + public static Collection transform(Collection from, Transform transform) { + + List list = new ArrayList(); + for (X x : from) { + Y y = transform.get(x); + list.add(y); + } + return list; + } + + public static Collection filter(Collection from, Predicate predicate) { + + List list = new ArrayList(); + for (X x : from) { + if (predicate.apply(x)) { + list.add(x); + } + } + return list; + } + + + public static X find(Collection from, Predicate predicate) { + + for (X x : from) { + if (predicate.apply(x)) { + return x; + } + } + return null; + } + + public static Map filterKeys(Map from, Predicate predicate) { + + Map toMap = new HashMap(); + for (X x : from.keySet()) { + if (predicate.apply(x)) { + toMap.put(x, from.get(x)); + } + } + return toMap; + } + + public static void transform(Map from, Map to, MapEntryTransform transform) { + + for (X x : from.keySet()) { + Y fromValue = from.get(x); + Z toValue = transform.get(x, fromValue); + to.put(x, toValue); + } + } + + public static Map transform(Map from, MapEntryTransform transform) { + + Map toMap = new HashMap(); + transform(from, toMap, transform); + return toMap; + } + + public static Map transformMapKeys(Map from, Transform transform) { + + Map toMap = new HashMap(); + for (X x : from.keySet()) { + Z z = from.get(x); + if (z != null) { + Y y = transform.get(x); + toMap.put(y, z); + } + } + return toMap; + } + + public static MapDifference difference(Map left, Map right) { + + MapDifference diff = new MapDifference(); + + for (X keyInLeft : left.keySet()) { + + if (!right.containsKey(keyInLeft)) { + diff.leftOnly.put(keyInLeft, left.get(keyInLeft)); + } + } + for (X keyInRight : right.keySet()) { + + if (!left.containsKey(keyInRight)) { + diff.rightOnly.put(keyInRight, right.get(keyInRight)); + } + } + return diff; + } + + public static class MapDifference { + + private Map leftOnly = new HashMap(); + private Map rightOnly = new HashMap(); + + public Map entriesOnlyOnLeft() { + return leftOnly; + } + + public Map entriesOnlyOnRight() { + return rightOnly; + } + } + + public static List newArrayList(X... args) { + return Arrays.asList(args); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/ConfigUtils.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/ConfigUtils.java index 906df36a..7a730f46 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/ConfigUtils.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/ConfigUtils.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,46 +25,46 @@ public class ConfigUtils { public static String getLocalZone() { - String localRack = System.getenv("LOCAL_RACK") == null ? System.getProperty("LOCAL_RACK") : System.getenv("LOCAL_RACK"); + String localRack = System.getenv("LOCAL_RACK") == null ? System.getProperty("LOCAL_RACK") : System.getenv("LOCAL_RACK"); - //backward compatible - if (localRack == null) { - localRack = System.getenv("EC2_AVAILABILITY_ZONE") == null ? System.getProperty("EC2_AVAILABILITY_ZONE") : System.getenv("EC2_AVAILABILITY_ZONE"); - } + //backward compatible + if (localRack == null) { + localRack = System.getenv("EC2_AVAILABILITY_ZONE") == null ? System.getProperty("EC2_AVAILABILITY_ZONE") : System.getenv("EC2_AVAILABILITY_ZONE"); + } - return localRack; + return localRack; } /** - * + * * @return the datacenter that the client is in */ public static String getDataCenter() { - String localDatacenter = System.getenv("LOCAL_DATACENTER") == null ? System.getProperty("LOCAL_DATACENTER") : System.getenv("LOCAL_DATACENTER"); + String localDatacenter = System.getenv("LOCAL_DATACENTER") == null ? System.getProperty("LOCAL_DATACENTER") : System.getenv("LOCAL_DATACENTER"); - //backward compatible - if (localDatacenter == null) { - localDatacenter = System.getenv("EC2_REGION") == null ? System.getProperty("EC2_REGION") : System.getenv("EC2_REGION"); - } + //backward compatible + if (localDatacenter == null) { + localDatacenter = System.getenv("EC2_REGION") == null ? System.getProperty("EC2_REGION") : System.getenv("EC2_REGION"); + } - if (localDatacenter == null) { - return getDataCenterFromRack(getLocalZone()); - } - return localDatacenter; + if (localDatacenter == null) { + return getDataCenterFromRack(getLocalZone()); + } + return localDatacenter; } /** - * + * * Datacenter format us-east-x, us-west-x etc. * @param rack * @return the datacenter based on the provided rack */ public static String getDataCenterFromRack(String rack) { - if (rack != null) { - return rack.substring(0, rack.length() - 1); - } - return null; + if (rack != null) { + return rack.substring(0, rack.length() - 1); + } + return null; } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/EstimatedHistogram.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/EstimatedHistogram.java index 55ab3515..4925678d 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/EstimatedHistogram.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/EstimatedHistogram.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,7 +22,7 @@ import org.slf4j.Logger; public class EstimatedHistogram { - + /** * The series of values to which the counts in `buckets` correspond: * 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 17, 20, etc. @@ -39,31 +39,26 @@ public class EstimatedHistogram { // buckets is one element longer than bucketOffsets -- the last element is values greater than the last offset final AtomicLongArray buckets; - public EstimatedHistogram() - { + public EstimatedHistogram() { this(90); } - public EstimatedHistogram(int bucketCount) - { + public EstimatedHistogram(int bucketCount) { bucketOffsets = newOffsets(bucketCount); buckets = new AtomicLongArray(bucketOffsets.length + 1); } - public EstimatedHistogram(long[] offsets, long[] bucketData) - { - assert bucketData.length == offsets.length +1; + public EstimatedHistogram(long[] offsets, long[] bucketData) { + assert bucketData.length == offsets.length + 1; bucketOffsets = offsets; buckets = new AtomicLongArray(bucketData); } - private static long[] newOffsets(int size) - { + private static long[] newOffsets(int size) { long[] result = new long[size]; long last = 1; result[0] = last; - for (int i = 1; i < size; i++) - { + for (int i = 1; i < size; i++) { long next = Math.round(last * 1.2); if (next == last) next++; @@ -77,8 +72,7 @@ private static long[] newOffsets(int size) /** * @return the histogram values corresponding to each bucket index */ - public long[] getBucketOffsets() - { + public long[] getBucketOffsets() { return bucketOffsets; } @@ -86,11 +80,9 @@ public long[] getBucketOffsets() * Increments the count of the bucket closest to n, rounding UP. * @param n */ - public void add(long n) - { + public void add(long n) { int index = Arrays.binarySearch(bucketOffsets, n); - if (index < 0) - { + if (index < 0) { // inexact match, take the first bucket higher than n index = -index - 1; } @@ -101,8 +93,7 @@ public void add(long n) /** * @return the count in the given bucket */ - long get(int bucket) - { + long get(int bucket) { return buckets.get(bucket); } @@ -110,8 +101,7 @@ long get(int bucket) * @param reset zero out buckets afterwards if true * @return a long[] containing the current histogram buckets */ - public long[] getBuckets(boolean reset) - { + public long[] getBuckets(boolean reset) { final int len = buckets.length(); long[] rv = new long[len]; @@ -128,10 +118,8 @@ public long[] getBuckets(boolean reset) /** * @return the smallest value that could have been added to this histogram */ - public long min() - { - for (int i = 0; i < buckets.length(); i++) - { + public long min() { + for (int i = 0; i < buckets.length(); i++) { if (buckets.get(i) > 0) return i == 0 ? 0 : 1 + bucketOffsets[i - 1]; } @@ -142,14 +130,12 @@ public long min() * @return the largest value that could have been added to this histogram. If the histogram * overflowed, returns Long.MAX_VALUE. */ - public long max() - { + public long max() { int lastBucket = buckets.length() - 1; if (buckets.get(lastBucket) > 0) return Long.MAX_VALUE; - for (int i = lastBucket - 1; i >= 0; i--) - { + for (int i = lastBucket - 1; i >= 0; i--) { if (buckets.get(i) > 0) return bucketOffsets[i]; } @@ -160,8 +146,7 @@ public long max() * @param percentile * @return estimated value at given percentile */ - public long percentile(double percentile) - { + public long percentile(double percentile) { assert percentile >= 0 && percentile <= 1.0; int lastBucket = buckets.length() - 1; if (buckets.get(lastBucket) > 0) @@ -172,8 +157,7 @@ public long percentile(double percentile) return 0; long elements = 0; - for (int i = 0; i < lastBucket; i++) - { + for (int i = 0; i < lastBucket; i++) { elements += buckets.get(i); if (elements >= pcount) return bucketOffsets[i]; @@ -185,16 +169,14 @@ public long percentile(double percentile) * @return the mean histogram value (average of bucket offsets, weighted by count) * @throws IllegalStateException if any values were greater than the largest bucket threshold */ - public long mean() - { + public long mean() { int lastBucket = buckets.length() - 1; if (buckets.get(lastBucket) > 0) throw new IllegalStateException("Unable to compute ceiling for max when histogram overflowed"); long elements = 0; long sum = 0; - for (int i = 0; i < lastBucket; i++) - { + for (int i = 0; i < lastBucket; i++) { long bCount = buckets.get(i); elements += bCount; sum += bCount * bucketOffsets[i]; @@ -206,19 +188,17 @@ public long mean() /** * @return the total number of non-zero values */ - public long count() - { - long sum = 0L; - for (int i = 0; i < buckets.length(); i++) - sum += buckets.get(i); - return sum; + public long count() { + long sum = 0L; + for (int i = 0; i < buckets.length(); i++) + sum += buckets.get(i); + return sum; } /** * @return true if this histogram has overflowed -- that is, a value larger than our largest bucket could bound was added */ - public boolean isOverflowed() - { + public boolean isOverflowed() { return buckets.get(buckets.length() - 1) > 0; } @@ -227,8 +207,7 @@ public boolean isOverflowed() * * @param log */ - public void log(Logger log) - { + public void log(Logger log) { // only print overflow if there is any int nameCount; if (buckets.get(buckets.length() - 1) == 0) @@ -238,16 +217,14 @@ public void log(Logger log) String[] names = new String[nameCount]; int maxNameLength = 0; - for (int i = 0; i < nameCount; i++) - { + for (int i = 0; i < nameCount; i++) { names[i] = nameOfRange(bucketOffsets, i); maxNameLength = Math.max(maxNameLength, names[i].length()); } // emit log records String formatstr = "%" + maxNameLength + "s: %d"; - for (int i = 0; i < nameCount; i++) - { + for (int i = 0; i < nameCount; i++) { long count = buckets.get(i); // sort-of-hack to not print empty ranges at the start that are only used to demarcate the // first populated range. for code clarity we don't omit this record from the maxNameLength @@ -258,15 +235,13 @@ public void log(Logger log) } } - private static String nameOfRange(long[] bucketOffsets, int index) - { + private static String nameOfRange(long[] bucketOffsets, int index) { StringBuilder sb = new StringBuilder(); appendRange(sb, bucketOffsets, index); return sb.toString(); } - private static void appendRange(StringBuilder sb, long[] bucketOffsets, int index) - { + private static void appendRange(StringBuilder sb, long[] bucketOffsets, int index) { sb.append("["); if (index == 0) if (bucketOffsets[0] > 0) @@ -286,8 +261,7 @@ private static void appendRange(StringBuilder sb, long[] bucketOffsets, int inde } @Override - public boolean equals(Object o) - { + public boolean equals(Object o) { if (this == o) return true; @@ -296,12 +270,11 @@ public boolean equals(Object o) EstimatedHistogram that = (EstimatedHistogram) o; return Arrays.equals(getBucketOffsets(), that.getBucketOffsets()) && - Arrays.equals(getBuckets(false), that.getBuckets(false)); + Arrays.equals(getBuckets(false), that.getBuckets(false)); } @Override - public int hashCode() - { + public int hashCode() { return Objects.hash(getBucketOffsets(), getBuckets(false)); } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/IOUtilities.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/IOUtilities.java index 165f45ee..907badbe 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/IOUtilities.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/IOUtilities.java @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2011 Netflix - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,44 +25,44 @@ public class IOUtilities { - public static List readLines(File file) { + public static List readLines(File file) { - BufferedReader reader = null; - try { - reader = new BufferedReader(new FileReader(file)); - String line = null; - - List lines = new ArrayList(); - while ((line = reader.readLine()) != null) { - lines.add(line); - } - return lines; - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - } - } - } - } + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(file)); + String line = null; - public static String toString(InputStream in) { + List lines = new ArrayList(); + while ((line = reader.readLine()) != null) { + lines.add(line); + } + return lines; + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + } + } + } + } - byte[] buffer = new byte[1024]; - int numRead = -1; - StringBuilder sb = new StringBuilder(); + public static String toString(InputStream in) { - try { - while ((numRead = in.read(buffer)) != -1) { - sb.append(new String(buffer, 0, numRead)); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - return sb.toString(); - } + byte[] buffer = new byte[1024]; + int numRead = -1; + StringBuilder sb = new StringBuilder(); + + try { + while ((numRead = in.read(buffer)) != -1) { + sb.append(new String(buffer, 0, numRead)); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return sb.toString(); + } } diff --git a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/RateLimitUtil.java b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/RateLimitUtil.java index dd541087..b16bb15c 100644 --- a/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/RateLimitUtil.java +++ b/dyno-core/src/main/java/com/netflix/dyno/connectionpool/impl/utils/RateLimitUtil.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,79 +21,79 @@ public class RateLimitUtil { - private final AtomicReference ref = new AtomicReference(null); - - private RateLimitUtil(int rps) { - this.ref.set(new InnerState(rps)); - } - - public static RateLimitUtil create(int n) { - return new RateLimitUtil(n); - } - - public int getRps() { - return ref.get().getRps(); - } - - public boolean acquire() { - - if (ref.get().checkSameSecond()) { - long timeToSleepMs = ref.get().increment(); - if (timeToSleepMs != -1) { - try { - Thread.sleep(timeToSleepMs); - return false; - } catch (InterruptedException e) { - // do nothing here - return false; - } - } else { - return true; - } - - } else { - - InnerState oldState = ref.get(); - InnerState newState = new InnerState(oldState.limit); - - ref.compareAndSet(oldState, newState); - return false; - } - } - - - private class InnerState { - - private final AtomicInteger counter = new AtomicInteger(); - private final AtomicLong second = new AtomicLong(0L); - private final AtomicLong origTime = new AtomicLong(0L); - - private final int limit; - - private InnerState(int limit) { - this.limit = limit; - counter.set(0); - origTime.set(System.currentTimeMillis()); - second.set(origTime.get()/1000); - } - - private boolean checkSameSecond() { - long time = System.currentTimeMillis(); - return second.get() == time/1000; - } - - private long increment() { - - if (counter.get() < limit) { - counter.incrementAndGet(); - return -1; - } else { - return System.currentTimeMillis() - origTime.get(); - } - } - - private int getRps() { - return limit; - } - } + private final AtomicReference ref = new AtomicReference(null); + + private RateLimitUtil(int rps) { + this.ref.set(new InnerState(rps)); + } + + public static RateLimitUtil create(int n) { + return new RateLimitUtil(n); + } + + public int getRps() { + return ref.get().getRps(); + } + + public boolean acquire() { + + if (ref.get().checkSameSecond()) { + long timeToSleepMs = ref.get().increment(); + if (timeToSleepMs != -1) { + try { + Thread.sleep(timeToSleepMs); + return false; + } catch (InterruptedException e) { + // do nothing here + return false; + } + } else { + return true; + } + + } else { + + InnerState oldState = ref.get(); + InnerState newState = new InnerState(oldState.limit); + + ref.compareAndSet(oldState, newState); + return false; + } + } + + + private class InnerState { + + private final AtomicInteger counter = new AtomicInteger(); + private final AtomicLong second = new AtomicLong(0L); + private final AtomicLong origTime = new AtomicLong(0L); + + private final int limit; + + private InnerState(int limit) { + this.limit = limit; + counter.set(0); + origTime.set(System.currentTimeMillis()); + second.set(origTime.get() / 1000); + } + + private boolean checkSameSecond() { + long time = System.currentTimeMillis(); + return second.get() == time / 1000; + } + + private long increment() { + + if (counter.get() < limit) { + counter.incrementAndGet(); + return -1; + } else { + return System.currentTimeMillis() - origTime.get(); + } + } + + private int getRps() { + return limit; + } + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/ConnectionContextImplTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/ConnectionContextImplTest.java index c1215f48..eaa02d9d 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/ConnectionContextImplTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/ConnectionContextImplTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,17 +20,17 @@ public class ConnectionContextImplTest { - @Test - public void testMetadata() throws Exception { + @Test + public void testMetadata() throws Exception { - ConnectionContextImpl context = new ConnectionContextImpl(); + ConnectionContextImpl context = new ConnectionContextImpl(); - Assert.assertFalse(context.hasMetadata("m1")); - context.setMetadata("m1", "foobar"); - Assert.assertTrue(context.hasMetadata("m1")); - Assert.assertEquals("foobar", context.getMetadata("m1")); + Assert.assertFalse(context.hasMetadata("m1")); + context.setMetadata("m1", "foobar"); + Assert.assertTrue(context.hasMetadata("m1")); + Assert.assertEquals("foobar", context.getMetadata("m1")); - context.reset(); - Assert.assertFalse(context.hasMetadata("m1")); - } + context.reset(); + Assert.assertFalse(context.hasMetadata("m1")); + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/ConnectionPoolImplTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/ConnectionPoolImplTest.java index 25c25344..7940b699 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/ConnectionPoolImplTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/ConnectionPoolImplTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -57,94 +57,94 @@ import com.netflix.dyno.connectionpool.impl.lb.HostToken; public class ConnectionPoolImplTest { - - private static class TestClient { - - private final AtomicInteger ops = new AtomicInteger(0); - } - - private static TestClient client = new TestClient(); - - private static ConnectionPoolConfigurationImpl cpConfig = new ConnectionPoolConfigurationImpl("TestClient"); - private static CountingConnectionPoolMonitor cpMonitor = new CountingConnectionPoolMonitor(); - - private static class TestConnection implements Connection { - - private AtomicInteger ops = new AtomicInteger(0); - private DynoConnectException ex; - - private HostConnectionPool hostPool; - - private TestConnection(HostConnectionPool pool) { - this.hostPool = pool; - } - - @Override - public OperationResult execute(Operation op) throws DynoException { - - try { - if (op != null) { - R r = op.execute(client, null); - return new OperationResultImpl("Test", r, null); - } - } catch (DynoConnectException e) { - ex = e; - throw e; - } finally { - ops.incrementAndGet(); - } - return null; - } - - @Override - public void close() { - } - - @Override - public Host getHost() { - return hostPool.getHost(); - } - - @Override - public void open() throws DynoException { - } - - @Override - public DynoConnectException getLastException() { - return ex; - } - - @Override - public HostConnectionPool getParentConnectionPool() { - return hostPool; - } - - @Override - public ListenableFuture> executeAsync(AsyncOperation op) throws DynoException { - throw new RuntimeException("Not Implemented"); - } - - @Override - public void execPing() { - } - - @Override - public ConnectionContext getContext() { - return new ConnectionContextImpl(); - } - } - - private static ConnectionFactory connFactory = new ConnectionFactory() { - - @Override - public Connection createConnection(HostConnectionPool pool, ConnectionObservor observor) throws DynoConnectException, ThrottledException { - return new TestConnection(pool); - } - }; - - private Host host1 = new Host("host1", 8080, "localRack", Status.Up); - private Host host2 = new Host("host2", 8080, "localRack", Status.Up); - private Host host3 = new Host("host3", 8080, "localRack", Status.Up); + + private static class TestClient { + + private final AtomicInteger ops = new AtomicInteger(0); + } + + private static TestClient client = new TestClient(); + + private static ConnectionPoolConfigurationImpl cpConfig = new ConnectionPoolConfigurationImpl("TestClient"); + private static CountingConnectionPoolMonitor cpMonitor = new CountingConnectionPoolMonitor(); + + private static class TestConnection implements Connection { + + private AtomicInteger ops = new AtomicInteger(0); + private DynoConnectException ex; + + private HostConnectionPool hostPool; + + private TestConnection(HostConnectionPool pool) { + this.hostPool = pool; + } + + @Override + public OperationResult execute(Operation op) throws DynoException { + + try { + if (op != null) { + R r = op.execute(client, null); + return new OperationResultImpl("Test", r, null); + } + } catch (DynoConnectException e) { + ex = e; + throw e; + } finally { + ops.incrementAndGet(); + } + return null; + } + + @Override + public void close() { + } + + @Override + public Host getHost() { + return hostPool.getHost(); + } + + @Override + public void open() throws DynoException { + } + + @Override + public DynoConnectException getLastException() { + return ex; + } + + @Override + public HostConnectionPool getParentConnectionPool() { + return hostPool; + } + + @Override + public ListenableFuture> executeAsync(AsyncOperation op) throws DynoException { + throw new RuntimeException("Not Implemented"); + } + + @Override + public void execPing() { + } + + @Override + public ConnectionContext getContext() { + return new ConnectionContextImpl(); + } + } + + private static ConnectionFactory connFactory = new ConnectionFactory() { + + @Override + public Connection createConnection(HostConnectionPool pool, ConnectionObservor observor) throws DynoConnectException, ThrottledException { + return new TestConnection(pool); + } + }; + + private Host host1 = new Host("host1", 8080, "localRack", Status.Up); + private Host host2 = new Host("host2", 8080, "localRack", Status.Up); + private Host host3 = new Host("host3", 8080, "localRack", Status.Up); // Used for Cross Rack fallback testing private Host host4 = new Host("host4", 8080, "remoteRack", Status.Up); @@ -152,63 +152,63 @@ public Connection createConnection(HostConnectionPool po private Host host6 = new Host("host6", 8080, "remoteRack", Status.Up); private final List hostSupplierHosts = new ArrayList(); - - @Before - public void beforeTest() { - - hostSupplierHosts.clear(); - - client = new TestClient(); - cpConfig = new ConnectionPoolConfigurationImpl("TestClient").setLoadBalancingStrategy(LoadBalancingStrategy.RoundRobin); - cpConfig.withHostSupplier(new HostSupplier() { - - @Override - public List getHosts() { - return hostSupplierHosts; - } - }); - - cpConfig.setLocalRack("localRack"); - cpConfig.setLoadBalancingStrategy(LoadBalancingStrategy.RoundRobin); - - cpConfig.withTokenSupplier(getTokenMapSupplier()); - - cpMonitor = new CountingConnectionPoolMonitor(); - } - - @Test - public void testConnectionPoolNormal() throws Exception { - - final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); - hostSupplierHosts.add(host1); - hostSupplierHosts.add(host2); - - pool.start(); - - final Callable testLogic = new Callable() { - - @Override - public Void call() throws Exception { - Thread.sleep(1000); - return null; - } - }; - - try { - runTest(pool, testLogic); - checkConnectionPoolMonitorStats(2); - } finally { - pool.shutdown(); - } - } - - private void checkConnectionPoolMonitorStats(int numHosts) { + + @Before + public void beforeTest() { + + hostSupplierHosts.clear(); + + client = new TestClient(); + cpConfig = new ConnectionPoolConfigurationImpl("TestClient").setLoadBalancingStrategy(LoadBalancingStrategy.RoundRobin); + cpConfig.withHostSupplier(new HostSupplier() { + + @Override + public List getHosts() { + return hostSupplierHosts; + } + }); + + cpConfig.setLocalRack("localRack"); + cpConfig.setLoadBalancingStrategy(LoadBalancingStrategy.RoundRobin); + + cpConfig.withTokenSupplier(getTokenMapSupplier()); + + cpMonitor = new CountingConnectionPoolMonitor(); + } + + @Test + public void testConnectionPoolNormal() throws Exception { + + final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); + hostSupplierHosts.add(host1); + hostSupplierHosts.add(host2); + + pool.start(); + + final Callable testLogic = new Callable() { + + @Override + public Void call() throws Exception { + Thread.sleep(1000); + return null; + } + }; + + try { + runTest(pool, testLogic); + checkConnectionPoolMonitorStats(2); + } finally { + pool.shutdown(); + } + } + + private void checkConnectionPoolMonitorStats(int numHosts) { checkConnectionPoolMonitorStats(numHosts, false); } - - private void checkConnectionPoolMonitorStats(int numHosts, boolean fallback) { - System.out.println("Total ops: " + client.ops.get()); - Assert.assertTrue("Total ops: " + client.ops.get(), client.ops.get() > 0); + + private void checkConnectionPoolMonitorStats(int numHosts, boolean fallback) { + System.out.println("Total ops: " + client.ops.get()); + Assert.assertTrue("Total ops: " + client.ops.get(), client.ops.get() > 0); Assert.assertEquals(client.ops.get(), cpMonitor.getOperationSuccessCount()); @@ -216,35 +216,35 @@ private void checkConnectionPoolMonitorStats(int numHosts, boolean fallback) { Assert.assertEquals(0, cpMonitor.getOperationFailureCount()); } - Assert.assertEquals(0, cpMonitor.getOperationTimeoutCount()); - - Assert.assertEquals(numHosts*cpConfig.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); - Assert.assertEquals(0, cpMonitor.getConnectionCreateFailedCount()); - Assert.assertEquals(numHosts * cpConfig.getMaxConnsPerHost(), cpMonitor.getConnectionClosedCount()); - - Assert.assertEquals(client.ops.get(), cpMonitor.getConnectionBorrowedCount()); - Assert.assertEquals(client.ops.get(), cpMonitor.getConnectionReturnedCount()); - } - - private TokenMapSupplier getTokenMapSupplier() { - - /** - cqlsh:dyno_bootstrap> select "availabilityZone","hostname","token" from tokens where "appId" = 'dynomite_redis_puneet'; - - availabilityZone | hostname | token - ------------------+--------------------------------------------+------------ - us-east-1c | ec2-54-83-179-213.compute-1.amazonaws.com | 1383429731 - us-east-1c | ec2-54-224-184-99.compute-1.amazonaws.com | 309687905 - us-east-1c | ec2-54-91-190-159.compute-1.amazonaws.com | 3530913377 - us-east-1c | ec2-54-81-31-218.compute-1.amazonaws.com | 2457171554 - us-east-1e | ec2-54-198-222-153.compute-1.amazonaws.com | 309687905 - us-east-1e | ec2-54-198-239-231.compute-1.amazonaws.com | 2457171554 - us-east-1e | ec2-54-226-212-40.compute-1.amazonaws.com | 1383429731 - us-east-1e | ec2-54-197-178-229.compute-1.amazonaws.com | 3530913377 - - cqlsh:dyno_bootstrap> - */ - final Map tokenMap = new HashMap(); + Assert.assertEquals(0, cpMonitor.getOperationTimeoutCount()); + + Assert.assertEquals(numHosts * cpConfig.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); + Assert.assertEquals(0, cpMonitor.getConnectionCreateFailedCount()); + Assert.assertEquals(numHosts * cpConfig.getMaxConnsPerHost(), cpMonitor.getConnectionClosedCount()); + + Assert.assertEquals(client.ops.get(), cpMonitor.getConnectionBorrowedCount()); + Assert.assertEquals(client.ops.get(), cpMonitor.getConnectionReturnedCount()); + } + + private TokenMapSupplier getTokenMapSupplier() { + + /** + cqlsh:dyno_bootstrap> select "availabilityZone","hostname","token" from tokens where "appId" = 'dynomite_redis_puneet'; + + availabilityZone | hostname | token + ------------------+--------------------------------------------+------------ + us-east-1c | ec2-54-83-179-213.compute-1.amazonaws.com | 1383429731 + us-east-1c | ec2-54-224-184-99.compute-1.amazonaws.com | 309687905 + us-east-1c | ec2-54-91-190-159.compute-1.amazonaws.com | 3530913377 + us-east-1c | ec2-54-81-31-218.compute-1.amazonaws.com | 2457171554 + us-east-1e | ec2-54-198-222-153.compute-1.amazonaws.com | 309687905 + us-east-1e | ec2-54-198-239-231.compute-1.amazonaws.com | 2457171554 + us-east-1e | ec2-54-226-212-40.compute-1.amazonaws.com | 1383429731 + us-east-1e | ec2-54-197-178-229.compute-1.amazonaws.com | 3530913377 + + cqlsh:dyno_bootstrap> + */ + final Map tokenMap = new HashMap(); tokenMap.put(host1, new HostToken(309687905L, host1)); tokenMap.put(host2, new HostToken(1383429731L, host2)); @@ -253,7 +253,7 @@ private TokenMapSupplier getTokenMapSupplier() { tokenMap.put(host5, new HostToken(1383429731L, host5)); tokenMap.put(host6, new HostToken(2457171554L, host6)); - return new TokenMapSupplier() { + return new TokenMapSupplier() { @Override public List getTokens(Set activeHosts) { @@ -270,111 +270,111 @@ public List getTokens(Set activeHosts) { } } - @Override - public HostToken getTokenForHost(Host host, Set activeHosts) { - return tokenMap.get(host); - } - - }; - } - - @Test - public void testAddingNewHosts() throws Exception { - - final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); - hostSupplierHosts.add(host1); - hostSupplierHosts.add(host2); - - pool.start(); - - final Callable testLogic = new Callable() { - - @Override - public Void call() throws Exception { - Thread.sleep(1000); - pool.addHost(host3); - Thread.sleep(1000); - return null; - } - }; - - runTest(pool, testLogic); - - checkConnectionPoolMonitorStats(3); - - checkHostStats(host1); - checkHostStats(host2); - checkHostStats(host3); - - HostConnectionStats h1Stats = cpMonitor.getHostStats().get(host1); - HostConnectionStats h2Stats = cpMonitor.getHostStats().get(host2); - HostConnectionStats h3Stats = cpMonitor.getHostStats().get(host3); - - Assert.assertTrue("h3Stats: " + h3Stats + " h1Stats: " + h1Stats, h1Stats.getOperationSuccessCount() > h3Stats.getOperationSuccessCount()); - Assert.assertTrue("h3Stats: " + h3Stats + " h2Stats: " + h2Stats, h2Stats.getOperationSuccessCount() > h3Stats.getOperationSuccessCount()); - } - - private void checkHostStats(Host host) { - - HostConnectionStats hStats = cpMonitor.getHostStats().get(host); - Assert.assertTrue("host ops: " + hStats.getOperationSuccessCount(), hStats.getOperationSuccessCount() > 0); - Assert.assertEquals(0, hStats.getOperationErrorCount()); - Assert.assertEquals(cpConfig.getMaxConnsPerHost(), hStats.getConnectionsCreated()); - Assert.assertEquals(0, hStats.getConnectionsCreateFailed()); - Assert.assertEquals(cpConfig.getMaxConnsPerHost(), hStats.getConnectionsClosed()); - Assert.assertEquals(hStats.getOperationSuccessCount(), hStats.getConnectionsBorrowed()); - Assert.assertEquals(hStats.getOperationSuccessCount(), hStats.getConnectionsReturned()); - } - - @Test - public void testRemovingHosts() throws Exception { - - final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); - hostSupplierHosts.add(host1); - hostSupplierHosts.add(host2); - hostSupplierHosts.add(host3); - - pool.start(); - - final Callable testLogic = new Callable() { - - @Override - public Void call() throws Exception { - Thread.sleep(1000); - pool.removeHost(host2); - Thread.sleep(1000); - return null; - } - }; - - runTest(pool, testLogic); - - checkConnectionPoolMonitorStats(3); - - checkHostStats(host1); - checkHostStats(host2); - checkHostStats(host3); - - HostConnectionStats h1Stats = cpMonitor.getHostStats().get(host1); - HostConnectionStats h2Stats = cpMonitor.getHostStats().get(host2); - HostConnectionStats h3Stats = cpMonitor.getHostStats().get(host3); - - Assert.assertTrue("h1Stats: " + h1Stats + " h2Stats: " + h2Stats, h1Stats.getOperationSuccessCount() > h2Stats.getOperationSuccessCount()); - Assert.assertTrue("h2Stats: " + h2Stats + " h3Stats: " + h3Stats, h3Stats.getOperationSuccessCount() > h2Stats.getOperationSuccessCount()); - } - - @Test (expected=NoAvailableHostsException.class) - public void testNoAvailableHosts() throws Exception { - - final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); - pool.start(); - - try { - executeTestClientOperation(pool); - } finally { - pool.shutdown(); - } - } + @Override + public HostToken getTokenForHost(Host host, Set activeHosts) { + return tokenMap.get(host); + } + + }; + } + + @Test + public void testAddingNewHosts() throws Exception { + + final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); + hostSupplierHosts.add(host1); + hostSupplierHosts.add(host2); + + pool.start(); + + final Callable testLogic = new Callable() { + + @Override + public Void call() throws Exception { + Thread.sleep(1000); + pool.addHost(host3); + Thread.sleep(1000); + return null; + } + }; + + runTest(pool, testLogic); + + checkConnectionPoolMonitorStats(3); + + checkHostStats(host1); + checkHostStats(host2); + checkHostStats(host3); + + HostConnectionStats h1Stats = cpMonitor.getHostStats().get(host1); + HostConnectionStats h2Stats = cpMonitor.getHostStats().get(host2); + HostConnectionStats h3Stats = cpMonitor.getHostStats().get(host3); + + Assert.assertTrue("h3Stats: " + h3Stats + " h1Stats: " + h1Stats, h1Stats.getOperationSuccessCount() > h3Stats.getOperationSuccessCount()); + Assert.assertTrue("h3Stats: " + h3Stats + " h2Stats: " + h2Stats, h2Stats.getOperationSuccessCount() > h3Stats.getOperationSuccessCount()); + } + + private void checkHostStats(Host host) { + + HostConnectionStats hStats = cpMonitor.getHostStats().get(host); + Assert.assertTrue("host ops: " + hStats.getOperationSuccessCount(), hStats.getOperationSuccessCount() > 0); + Assert.assertEquals(0, hStats.getOperationErrorCount()); + Assert.assertEquals(cpConfig.getMaxConnsPerHost(), hStats.getConnectionsCreated()); + Assert.assertEquals(0, hStats.getConnectionsCreateFailed()); + Assert.assertEquals(cpConfig.getMaxConnsPerHost(), hStats.getConnectionsClosed()); + Assert.assertEquals(hStats.getOperationSuccessCount(), hStats.getConnectionsBorrowed()); + Assert.assertEquals(hStats.getOperationSuccessCount(), hStats.getConnectionsReturned()); + } + + @Test + public void testRemovingHosts() throws Exception { + + final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); + hostSupplierHosts.add(host1); + hostSupplierHosts.add(host2); + hostSupplierHosts.add(host3); + + pool.start(); + + final Callable testLogic = new Callable() { + + @Override + public Void call() throws Exception { + Thread.sleep(1000); + pool.removeHost(host2); + Thread.sleep(1000); + return null; + } + }; + + runTest(pool, testLogic); + + checkConnectionPoolMonitorStats(3); + + checkHostStats(host1); + checkHostStats(host2); + checkHostStats(host3); + + HostConnectionStats h1Stats = cpMonitor.getHostStats().get(host1); + HostConnectionStats h2Stats = cpMonitor.getHostStats().get(host2); + HostConnectionStats h3Stats = cpMonitor.getHostStats().get(host3); + + Assert.assertTrue("h1Stats: " + h1Stats + " h2Stats: " + h2Stats, h1Stats.getOperationSuccessCount() > h2Stats.getOperationSuccessCount()); + Assert.assertTrue("h2Stats: " + h2Stats + " h3Stats: " + h3Stats, h3Stats.getOperationSuccessCount() > h2Stats.getOperationSuccessCount()); + } + + @Test(expected = NoAvailableHostsException.class) + public void testNoAvailableHosts() throws Exception { + + final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); + pool.start(); + + try { + executeTestClientOperation(pool); + } finally { + pool.shutdown(); + } + } @Test public void testIdleWhenNoAvailableHosts() throws Exception { @@ -393,60 +393,60 @@ public void testIdleWhenNoAvailableHosts() throws Exception { pool.shutdown(); } } - - @Test - public void testPoolTimeout() throws Exception { - final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); - hostSupplierHosts.add(host1); - hostSupplierHosts.add(host2); - hostSupplierHosts.add(host3); + @Test + public void testPoolTimeout() throws Exception { + + final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); + hostSupplierHosts.add(host1); + hostSupplierHosts.add(host2); + hostSupplierHosts.add(host3); pool.start(); - - // Now exhaust all 9 connections, so that the 10th one can fail with PoolExhaustedException - final ExecutorService threadPool = Executors.newFixedThreadPool(9); - - final Callable blockConnectionForSomeTime = new Callable() { - - @Override - public Void call() throws Exception { - try { - Thread.sleep(10000); // sleep for a VERY long time to ensure pool exhaustion - } catch (InterruptedException e) { - // just return - } - return null; - } - }; - - final CountDownLatch latch = new CountDownLatch(9); - for (int i=0; i<9; i++) { - threadPool.submit(new Callable() { - - @Override - public Void call() throws Exception { - latch.countDown(); - executeTestClientOperation(pool, blockConnectionForSomeTime); - return null; - } - }); - } + + // Now exhaust all 9 connections, so that the 10th one can fail with PoolExhaustedException + final ExecutorService threadPool = Executors.newFixedThreadPool(9); + + final Callable blockConnectionForSomeTime = new Callable() { + + @Override + public Void call() throws Exception { + try { + Thread.sleep(10000); // sleep for a VERY long time to ensure pool exhaustion + } catch (InterruptedException e) { + // just return + } + return null; + } + }; + + final CountDownLatch latch = new CountDownLatch(9); + for (int i = 0; i < 9; i++) { + threadPool.submit(new Callable() { + + @Override + public Void call() throws Exception { + latch.countDown(); + executeTestClientOperation(pool, blockConnectionForSomeTime); + return null; + } + }); + } latch.await(); Thread.sleep(100); // wait patiently for all threads to have blocked the connections - - try { - executeTestClientOperation(pool); - Assert.fail("TEST FAILED"); - } catch (PoolTimeoutException e) { - threadPool.shutdownNow(); - pool.shutdown(); - } - } - - @Test(expected = PoolOfflineException.class) - public void testPoolOffline() { + + try { + executeTestClientOperation(pool); + Assert.fail("TEST FAILED"); + } catch (PoolTimeoutException e) { + threadPool.shutdownNow(); + pool.shutdown(); + } + } + + @Test(expected = PoolOfflineException.class) + public void testPoolOffline() { final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); hostSupplierHosts.add(host1); @@ -468,78 +468,78 @@ public Void call() throws Exception { pool.shutdown(); } } - - - @Test - public void testHostEvictionDueToErrorRates() throws Exception { - - // First configure the error rate monitor - ErrorRateMonitorConfigImpl errConfig = new ErrorRateMonitorConfigImpl(); - errConfig.checkFrequency = 1; - errConfig.window = 1; - errConfig.suppressWindow = 60; - - errConfig.addThreshold(10, 1, 100); - - final AtomicReference badHost = new AtomicReference(); - - final ConnectionFactory badConnectionFactory = new ConnectionFactory() { - - @Override - public Connection createConnection(final HostConnectionPool pool, ConnectionObservor cObservor) throws DynoConnectException, ThrottledException { - - return new TestConnection(pool) { - - @Override - public OperationResult execute(Operation op) throws DynoException { - if (pool.getHost().getHostAddress().equals(badHost.get())) { - throw new FatalConnectionException("Fail for bad host"); - } - return super.execute(op); - } - }; - } - }; - - final ConnectionPoolImpl pool = new ConnectionPoolImpl(badConnectionFactory, cpConfig, cpMonitor); - hostSupplierHosts.add(host1); - hostSupplierHosts.add(host2); - hostSupplierHosts.add(host3); + + + @Test + public void testHostEvictionDueToErrorRates() throws Exception { + + // First configure the error rate monitor + ErrorRateMonitorConfigImpl errConfig = new ErrorRateMonitorConfigImpl(); + errConfig.checkFrequency = 1; + errConfig.window = 1; + errConfig.suppressWindow = 60; + + errConfig.addThreshold(10, 1, 100); + + final AtomicReference badHost = new AtomicReference(); + + final ConnectionFactory badConnectionFactory = new ConnectionFactory() { + + @Override + public Connection createConnection(final HostConnectionPool pool, ConnectionObservor cObservor) throws DynoConnectException, ThrottledException { + + return new TestConnection(pool) { + + @Override + public OperationResult execute(Operation op) throws DynoException { + if (pool.getHost().getHostAddress().equals(badHost.get())) { + throw new FatalConnectionException("Fail for bad host"); + } + return super.execute(op); + } + }; + } + }; + + final ConnectionPoolImpl pool = new ConnectionPoolImpl(badConnectionFactory, cpConfig, cpMonitor); + hostSupplierHosts.add(host1); + hostSupplierHosts.add(host2); + hostSupplierHosts.add(host3); pool.start(); - final Callable testLogic = new Callable() { + final Callable testLogic = new Callable() { - @Override - public Void call() throws Exception { - Thread.sleep(2000); - badHost.set("host2"); - Thread.sleep(2000); - return null; - } - }; + @Override + public Void call() throws Exception { + Thread.sleep(2000); + badHost.set("host2"); + Thread.sleep(2000); + return null; + } + }; runTest(pool, testLogic); - - Assert.assertTrue("Total ops: " + client.ops.get(), client.ops.get() > 0); - Assert.assertTrue("Total errors: " + cpMonitor.getOperationFailureCount(), cpMonitor.getOperationFailureCount() > 0); - - Assert.assertEquals(3 * cpConfig.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); - Assert.assertEquals(0, cpMonitor.getConnectionCreateFailedCount()); - Assert.assertEquals(3 * cpConfig.getMaxConnsPerHost(), cpMonitor.getConnectionClosedCount()); - - Assert.assertEquals(client.ops.get() + cpMonitor.getOperationFailureCount(), cpMonitor.getConnectionBorrowedCount()); - Assert.assertEquals(client.ops.get() + cpMonitor.getOperationFailureCount(), cpMonitor.getConnectionReturnedCount()); - - checkHostStats(host1); - checkHostStats(host3); - - HostConnectionStats h2Stats = cpMonitor.getHostStats().get(host2); - Assert.assertEquals(cpMonitor.getOperationFailureCount(), h2Stats.getOperationErrorCount()); - - } - - @Test + + Assert.assertTrue("Total ops: " + client.ops.get(), client.ops.get() > 0); + Assert.assertTrue("Total errors: " + cpMonitor.getOperationFailureCount(), cpMonitor.getOperationFailureCount() > 0); + + Assert.assertEquals(3 * cpConfig.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); + Assert.assertEquals(0, cpMonitor.getConnectionCreateFailedCount()); + Assert.assertEquals(3 * cpConfig.getMaxConnsPerHost(), cpMonitor.getConnectionClosedCount()); + + Assert.assertEquals(client.ops.get() + cpMonitor.getOperationFailureCount(), cpMonitor.getConnectionBorrowedCount()); + Assert.assertEquals(client.ops.get() + cpMonitor.getOperationFailureCount(), cpMonitor.getConnectionReturnedCount()); + + checkHostStats(host1); + checkHostStats(host3); + + HostConnectionStats h2Stats = cpMonitor.getHostStats().get(host2); + Assert.assertEquals(cpMonitor.getOperationFailureCount(), h2Stats.getOperationErrorCount()); + + } + + @Test public void testCrossRackFailover() throws Exception { final RetryNTimes retry = new RetryNTimes(3, true); @@ -589,53 +589,53 @@ public Void call() throws Exception { Assert.assertEquals(0, cpMonitor.getOperationTimeoutCount()); - Assert.assertEquals(numHosts*cpConfig.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); + Assert.assertEquals(numHosts * cpConfig.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); Assert.assertEquals(0, cpMonitor.getConnectionCreateFailedCount()); } finally { pool.shutdown(); } } - - @Test - public void testWithRetries() throws Exception { - - final ConnectionFactory badConnectionFactory = new ConnectionFactory() { - @Override - public Connection createConnection(final HostConnectionPool pool, ConnectionObservor cObservor) throws DynoConnectException, ThrottledException { - return new TestConnection(pool) { - @Override - public OperationResult execute(Operation op) throws DynoException { - throw new DynoException("Fail for bad host"); - } - }; - } - }; - - final RetryNTimes retry = new RetryNTimes(3, false); - final RetryPolicyFactory rFactory = new RetryNTimes.RetryPolicyFactory() { - @Override - public RetryPolicy getRetryPolicy() { - return retry; - } - }; - - final ConnectionPoolImpl pool = - new ConnectionPoolImpl(badConnectionFactory, cpConfig.setRetryPolicyFactory(rFactory), cpMonitor); - hostSupplierHosts.add(host1); - - pool.start(); - - - try { - executeTestClientOperation(pool, null); + + @Test + public void testWithRetries() throws Exception { + + final ConnectionFactory badConnectionFactory = new ConnectionFactory() { + @Override + public Connection createConnection(final HostConnectionPool pool, ConnectionObservor cObservor) throws DynoConnectException, ThrottledException { + return new TestConnection(pool) { + @Override + public OperationResult execute(Operation op) throws DynoException { + throw new DynoException("Fail for bad host"); + } + }; + } + }; + + final RetryNTimes retry = new RetryNTimes(3, false); + final RetryPolicyFactory rFactory = new RetryNTimes.RetryPolicyFactory() { + @Override + public RetryPolicy getRetryPolicy() { + return retry; + } + }; + + final ConnectionPoolImpl pool = + new ConnectionPoolImpl(badConnectionFactory, cpConfig.setRetryPolicyFactory(rFactory), cpMonitor); + hostSupplierHosts.add(host1); + + pool.start(); + + + try { + executeTestClientOperation(pool, null); Assert.fail("Test failed: expected PoolExhaustedException"); - } catch (DynoException e) { - Assert.assertEquals("Retry: " + retry.getAttemptCount(), 4, retry.getAttemptCount()); - } finally { - pool.shutdown(); - } - } + } catch (DynoException e) { + Assert.assertEquals("Retry: " + retry.getAttemptCount(), 4, retry.getAttemptCount()); + } finally { + pool.shutdown(); + } + } @Test(expected = NoAvailableHostsException.class) public void testHostsDownDuringStartup() { @@ -643,112 +643,112 @@ public void testHostsDownDuringStartup() { final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); hostSupplierHosts.add(new Host("host1_down", 8080, "localRack", Status.Down)); - hostSupplierHosts.add(new Host("host2_down", 8080, "localRack",Status.Down)); + hostSupplierHosts.add(new Host("host2_down", 8080, "localRack", Status.Down)); hostSupplierHosts.add(new Host("host3_down", 8080, "localRack", Status.Down)); pool.start(); } - private void executeTestClientOperation(final ConnectionPoolImpl pool) { - executeTestClientOperation(pool, null); - } - - private void executeTestClientOperation(final ConnectionPoolImpl pool, final Callable customLogic) { - pool.executeWithFailover(new Operation() { - - @Override - public Integer execute(TestClient client, ConnectionContext state) throws DynoException { - if (customLogic != null) { - try { + private void executeTestClientOperation(final ConnectionPoolImpl pool) { + executeTestClientOperation(pool, null); + } + + private void executeTestClientOperation(final ConnectionPoolImpl pool, final Callable customLogic) { + pool.executeWithFailover(new Operation() { + + @Override + public Integer execute(TestClient client, ConnectionContext state) throws DynoException { + if (customLogic != null) { + try { customLogic.call(); } catch (DynoException de) { throw de; - } catch (Exception e) { + } catch (Exception e) { throw new RuntimeException(e); - } - } - client.ops.incrementAndGet(); - return 1; - } - - @Override - public String getName() { - return "TestOperation"; - } - - - @Override - public String getStringKey() { - return "TestOperation"; - } - - @Override - public byte[] getBinaryKey() { - return null; - } - }); - } + } + } + client.ops.incrementAndGet(); + return 1; + } + + @Override + public String getName() { + return "TestOperation"; + } + + + @Override + public String getStringKey() { + return "TestOperation"; + } + + @Override + public byte[] getBinaryKey() { + return null; + } + }); + } private void runTest(final ConnectionPoolImpl pool, final Callable customTestLogic) throws Exception { - - int nThreads = 1; - final ExecutorService threadPool = Executors.newFixedThreadPool(nThreads); - final AtomicBoolean stop = new AtomicBoolean(false); - - final CountDownLatch latch = new CountDownLatch(nThreads); - - for (int i=0; i() { - - @Override - public Void call() throws Exception { - try { - while (!stop.get() && !Thread.currentThread().isInterrupted()) { - try { - pool.executeWithFailover(new Operation() { - - @Override - public Integer execute(TestClient client, ConnectionContext state) throws DynoException { - client.ops.incrementAndGet(); - return 1; - } - - @Override - public String getName() { - return "TestOperation"; - } - - @Override - public String getStringKey() { - return "TestOperation"; - } - - @Override - public byte[] getBinaryKey() { - return null; - } - - }); - } catch (DynoException e) { + + int nThreads = 1; + final ExecutorService threadPool = Executors.newFixedThreadPool(nThreads); + final AtomicBoolean stop = new AtomicBoolean(false); + + final CountDownLatch latch = new CountDownLatch(nThreads); + + for (int i = 0; i < nThreads; i++) { + threadPool.submit(new Callable() { + + @Override + public Void call() throws Exception { + try { + while (!stop.get() && !Thread.currentThread().isInterrupted()) { + try { + pool.executeWithFailover(new Operation() { + + @Override + public Integer execute(TestClient client, ConnectionContext state) throws DynoException { + client.ops.incrementAndGet(); + return 1; + } + + @Override + public String getName() { + return "TestOperation"; + } + + @Override + public String getStringKey() { + return "TestOperation"; + } + + @Override + public byte[] getBinaryKey() { + return null; + } + + }); + } catch (DynoException e) { // System.out.println("FAILED Test Worker operation: " + e.getMessage()); // e.printStackTrace(); - } - } - - } finally { - latch.countDown(); - } - return null; - } - }); - } - - customTestLogic.call(); - - stop.set(true); - latch.await(); - threadPool.shutdownNow(); - pool.shutdown(); - } + } + } + + } finally { + latch.countDown(); + } + return null; + } + }); + } + + customTestLogic.call(); + + stop.set(true); + latch.await(); + threadPool.shutdownNow(); + pool.shutdown(); + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/CountingConnectionPoolMonitorTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/CountingConnectionPoolMonitorTest.java index 95c23200..ae9418d8 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/CountingConnectionPoolMonitorTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/CountingConnectionPoolMonitorTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,57 +25,57 @@ public class CountingConnectionPoolMonitorTest { - @Test - public void testProcess() throws Exception { + @Test + public void testProcess() throws Exception { - CountingConnectionPoolMonitor counter = new CountingConnectionPoolMonitor(); + CountingConnectionPoolMonitor counter = new CountingConnectionPoolMonitor(); - Host host1 = new Host("host1","address1", 1111, "rack1"); - Host host2 = new Host("host2","address2", 2222, "rack1"); + Host host1 = new Host("host1", "address1", 1111, "rack1"); + Host host2 = new Host("host2", "address2", 2222, "rack1"); - // Host 1 - counter.incConnectionCreated(host1); - counter.incConnectionClosed(host1, null); - counter.incConnectionCreateFailed(host1, null); - counter.incConnectionBorrowed(host1, 0); - counter.incConnectionReturned(host1); + // Host 1 + counter.incConnectionCreated(host1); + counter.incConnectionClosed(host1, null); + counter.incConnectionCreateFailed(host1, null); + counter.incConnectionBorrowed(host1, 0); + counter.incConnectionReturned(host1); - counter.incOperationSuccess(host1, 0); - counter.incOperationFailure(host1, null); + counter.incOperationSuccess(host1, 0); + counter.incOperationFailure(host1, null); - // Host 2 - counter.incConnectionBorrowed(host2, 0); - counter.incConnectionReturned(host2); + // Host 2 + counter.incConnectionBorrowed(host2, 0); + counter.incConnectionReturned(host2); - counter.incOperationSuccess(host2, 0); - counter.incOperationFailure(host2, null); + counter.incOperationSuccess(host2, 0); + counter.incOperationFailure(host2, null); - counter.incOperationFailure(host2, new PoolTimeoutException("")); - counter.incOperationFailure(host2, new PoolExhaustedException(null, "")); - counter.incOperationFailure(host2, new NoAvailableHostsException("")); + counter.incOperationFailure(host2, new PoolTimeoutException("")); + counter.incOperationFailure(host2, new PoolExhaustedException(null, "")); + counter.incOperationFailure(host2, new NoAvailableHostsException("")); - // VERIFY COUNTS - Assert.assertEquals(1, counter.getConnectionCreatedCount()); - Assert.assertEquals(1, counter.getConnectionClosedCount()); - Assert.assertEquals(1, counter.getConnectionCreateFailedCount()); - Assert.assertEquals(2, counter.getConnectionBorrowedCount()); - Assert.assertEquals(2, counter.getConnectionReturnedCount()); + // VERIFY COUNTS + Assert.assertEquals(1, counter.getConnectionCreatedCount()); + Assert.assertEquals(1, counter.getConnectionClosedCount()); + Assert.assertEquals(1, counter.getConnectionCreateFailedCount()); + Assert.assertEquals(2, counter.getConnectionBorrowedCount()); + Assert.assertEquals(2, counter.getConnectionReturnedCount()); - Assert.assertEquals(2, counter.getOperationSuccessCount()); - Assert.assertEquals(5, counter.getOperationFailureCount()); + Assert.assertEquals(2, counter.getOperationSuccessCount()); + Assert.assertEquals(5, counter.getOperationFailureCount()); - Assert.assertEquals(1, counter.getHostStats().get(host1).getConnectionsBorrowed()); - Assert.assertEquals(1, counter.getHostStats().get(host1).getConnectionsReturned()); - Assert.assertEquals(1, counter.getHostStats().get(host1).getConnectionsCreated()); - Assert.assertEquals(1, counter.getHostStats().get(host1).getConnectionsCreateFailed()); - Assert.assertEquals(1, counter.getHostStats().get(host1).getOperationSuccessCount()); - Assert.assertEquals(1, counter.getHostStats().get(host1).getOperationErrorCount()); + Assert.assertEquals(1, counter.getHostStats().get(host1).getConnectionsBorrowed()); + Assert.assertEquals(1, counter.getHostStats().get(host1).getConnectionsReturned()); + Assert.assertEquals(1, counter.getHostStats().get(host1).getConnectionsCreated()); + Assert.assertEquals(1, counter.getHostStats().get(host1).getConnectionsCreateFailed()); + Assert.assertEquals(1, counter.getHostStats().get(host1).getOperationSuccessCount()); + Assert.assertEquals(1, counter.getHostStats().get(host1).getOperationErrorCount()); - Assert.assertEquals(1, counter.getHostStats().get(host2).getConnectionsBorrowed()); - Assert.assertEquals(1, counter.getHostStats().get(host2).getConnectionsReturned()); - Assert.assertEquals(0, counter.getHostStats().get(host2).getConnectionsCreated()); - Assert.assertEquals(0, counter.getHostStats().get(host2).getConnectionsCreateFailed()); - Assert.assertEquals(1, counter.getHostStats().get(host2).getOperationSuccessCount()); - Assert.assertEquals(4, counter.getHostStats().get(host2).getOperationErrorCount()); - } + Assert.assertEquals(1, counter.getHostStats().get(host2).getConnectionsBorrowed()); + Assert.assertEquals(1, counter.getHostStats().get(host2).getConnectionsReturned()); + Assert.assertEquals(0, counter.getHostStats().get(host2).getConnectionsCreated()); + Assert.assertEquals(0, counter.getHostStats().get(host2).getConnectionsCreateFailed()); + Assert.assertEquals(1, counter.getHostStats().get(host2).getOperationSuccessCount()); + Assert.assertEquals(4, counter.getHostStats().get(host2).getOperationErrorCount()); + } } \ No newline at end of file diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/FutureOperationalResultImplTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/FutureOperationalResultImplTest.java index 4f80149c..f7c9286f 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/FutureOperationalResultImplTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/FutureOperationalResultImplTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,39 +27,39 @@ public class FutureOperationalResultImplTest { - @Test - public void testFutureResult() throws Exception { + @Test + public void testFutureResult() throws Exception { - final FutureTask futureTask = new FutureTask(new Callable() { - @Override - public Integer call() throws Exception { - return 11; - } - }); + final FutureTask futureTask = new FutureTask(new Callable() { + @Override + public Integer call() throws Exception { + return 11; + } + }); - LastOperationMonitor opMonitor = new LastOperationMonitor(); - FutureOperationalResultImpl futureResult = - new FutureOperationalResultImpl("test", futureTask, System.currentTimeMillis(), opMonitor); + LastOperationMonitor opMonitor = new LastOperationMonitor(); + FutureOperationalResultImpl futureResult = + new FutureOperationalResultImpl("test", futureTask, System.currentTimeMillis(), opMonitor); - ExecutorService threadPool = Executors.newSingleThreadExecutor(); + ExecutorService threadPool = Executors.newSingleThreadExecutor(); - threadPool.submit(new Callable() { + threadPool.submit(new Callable() { - @Override - public Void call() throws Exception { - Thread.sleep(400); - futureTask.run(); - return null; - } - }); + @Override + public Void call() throws Exception { + Thread.sleep(400); + futureTask.run(); + return null; + } + }); - OperationResult opResult = futureResult.get(); - int integerResult = opResult.getResult(); - long latency = opResult.getLatency(); + OperationResult opResult = futureResult.get(); + int integerResult = opResult.getResult(); + long latency = opResult.getLatency(); - Assert.assertEquals(11, integerResult); - Assert.assertTrue(latency >= 400); + Assert.assertEquals(11, integerResult); + Assert.assertTrue(latency >= 400); - threadPool.shutdownNow(); - } + threadPool.shutdownNow(); + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/HostConnectionPoolImplTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/HostConnectionPoolImplTest.java index 59405749..38ad8130 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/HostConnectionPoolImplTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/HostConnectionPoolImplTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -47,306 +47,307 @@ public class HostConnectionPoolImplTest { - private static final Host TestHost = new Host("TestHost", "TestAddress", 1234, "TestRack"); - - // TEST UTILS SETUP - private class TestClient { - - } - - //private static AtomicBoolean stop = new AtomicBoolean(false); - private static HostConnectionPoolImpl pool; - private static ExecutorService threadPool; - private static int numWorkers = 10; - - private static class TestConnection implements Connection { - - private DynoConnectException ex; - private HostConnectionPool myPool; + private static final Host TestHost = new Host("TestHost", "TestAddress", 1234, "TestRack"); + + // TEST UTILS SETUP + private class TestClient { + + } + + //private static AtomicBoolean stop = new AtomicBoolean(false); + private static HostConnectionPoolImpl pool; + private static ExecutorService threadPool; + private static int numWorkers = 10; - private TestConnection(HostConnectionPool pool) { - myPool = pool; - } - @Override - public OperationResult execute(Operation op) throws DynoException { - return null; - } + private static class TestConnection implements Connection { - @Override - public void close() { - } + private DynoConnectException ex; + private HostConnectionPool myPool; - @Override - public Host getHost() { - return TestHost; - } + private TestConnection(HostConnectionPool pool) { + myPool = pool; + } - @Override - public void open() throws DynoException { - } + @Override + public OperationResult execute(Operation op) throws DynoException { + return null; + } - @Override - public DynoConnectException getLastException() { - return ex; - } + @Override + public void close() { + } - @Override - public HostConnectionPool getParentConnectionPool() { - return myPool; - } + @Override + public Host getHost() { + return TestHost; + } - public void setException(DynoConnectException e) { - ex = e; - } + @Override + public void open() throws DynoException { + } - @Override - public ListenableFuture> executeAsync(AsyncOperation op) throws DynoException { - throw new RuntimeException("Not Implemented"); - } + @Override + public DynoConnectException getLastException() { + return ex; + } - @Override - public void execPing() { - // do nothing - } + @Override + public HostConnectionPool getParentConnectionPool() { + return myPool; + } - @Override - public ConnectionContext getContext() { - return null; - } - } + public void setException(DynoConnectException e) { + ex = e; + } - private static ConnectionFactory connFactory = new ConnectionFactory() { + @Override + public ListenableFuture> executeAsync(AsyncOperation op) throws DynoException { + throw new RuntimeException("Not Implemented"); + } - @Override - public Connection createConnection(HostConnectionPool pool, ConnectionObservor cObservor) throws DynoConnectException, ThrottledException { - return new TestConnection(pool); - } - }; + @Override + public void execPing() { + // do nothing + } - private static ConnectionPoolConfigurationImpl config = new ConnectionPoolConfigurationImpl("TestClient"); - private static CountingConnectionPoolMonitor cpMonitor = new CountingConnectionPoolMonitor(); + @Override + public ConnectionContext getContext() { + return null; + } + } - @BeforeClass - public static void beforeClass() { - threadPool = Executors.newFixedThreadPool(numWorkers); - } + private static ConnectionFactory connFactory = new ConnectionFactory() { - @Before - public void beforeTest() { - //stop.set(false); - cpMonitor = new CountingConnectionPoolMonitor(); // reset all monitor stats - } + @Override + public Connection createConnection(HostConnectionPool pool, ConnectionObservor cObservor) throws DynoConnectException, ThrottledException { + return new TestConnection(pool); + } + }; - @After - public void afterTest() { - if (pool != null) { - pool.shutdown(); - } - } + private static ConnectionPoolConfigurationImpl config = new ConnectionPoolConfigurationImpl("TestClient"); + private static CountingConnectionPoolMonitor cpMonitor = new CountingConnectionPoolMonitor(); - @AfterClass - public static void afterClass() { - threadPool.shutdownNow(); - } + @BeforeClass + public static void beforeClass() { + threadPool = Executors.newFixedThreadPool(numWorkers); + } - @Test - public void testRegularProcess() throws Exception { + @Before + public void beforeTest() { + //stop.set(false); + cpMonitor = new CountingConnectionPoolMonitor(); // reset all monitor stats + } - final BasicResult result = new BasicResult(); - final TestControl control = new TestControl(4); - - pool = new HostConnectionPoolImpl(TestHost, connFactory, config, cpMonitor); - int numConns = pool.primeConnections(); - - for (int i=0; i<4; i++) { - threadPool.submit(new BasicWorker(result, control)); - } - - Thread.sleep(300); - - control.stop(); - control.waitOnFinish(); - - pool.shutdown(); + @After + public void afterTest() { + if (pool != null) { + pool.shutdown(); + } + } - Thread.sleep(300); - - Assert.assertEquals(config.getMaxConnsPerHost(), numConns); - - int expected = result.successCount.get(); - Assert.assertTrue(expected - cpMonitor.getConnectionBorrowedCount() <= 5); - Assert.assertTrue(expected - cpMonitor.getConnectionReturnedCount() <= 5); - - Assert.assertEquals(config.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); - Assert.assertEquals(config.getMaxConnsPerHost(), cpMonitor.getConnectionClosedCount()); - - Assert.assertEquals(0, result.failureCount.get()); - } - - @Test - public void testPoolTimeouts() throws Exception { - - pool = new HostConnectionPoolImpl(TestHost, connFactory, config, cpMonitor); - int numConns = pool.primeConnections(); - - final BasicResult result = new BasicResult(); - final TestControl control = new TestControl(4); - - for (int i=0; i<5; i++) { // Note 5 threads .. which is more than the no of available conns .. hence we should see timeouts - threadPool.submit(new BasicWorker(result, control, 55)); - } - - Thread.sleep(300); - - control.stop(); - control.waitOnFinish(); - - pool.shutdown(); + @AfterClass + public static void afterClass() { + threadPool.shutdownNow(); + } + + @Test + public void testRegularProcess() throws Exception { + + final BasicResult result = new BasicResult(); + final TestControl control = new TestControl(4); + + pool = new HostConnectionPoolImpl(TestHost, connFactory, config, cpMonitor); + int numConns = pool.primeConnections(); + + for (int i = 0; i < 4; i++) { + threadPool.submit(new BasicWorker(result, control)); + } Thread.sleep(300); - Assert.assertEquals(config.getMaxConnsPerHost(), numConns); + control.stop(); + control.waitOnFinish(); - int expected = result.successCount.get(); - Assert.assertTrue(expected - cpMonitor.getConnectionBorrowedCount() <= 5); - Assert.assertTrue(expected - cpMonitor.getConnectionReturnedCount() <= 5); + pool.shutdown(); - Assert.assertEquals(config.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); - Assert.assertEquals(config.getMaxConnsPerHost(), cpMonitor.getConnectionClosedCount()); - - Assert.assertEquals(0, cpMonitor.getConnectionCreateFailedCount()); - - Assert.assertTrue(result.failureCount.get() > 0); - } - - @Test - public void testMarkHostAsDown() throws Exception { - - pool = new HostConnectionPoolImpl(TestHost, connFactory, config, cpMonitor); - int numConns = pool.primeConnections(); + Thread.sleep(300); - final BasicResult result = new BasicResult(); - final TestControl control = new TestControl(4); + Assert.assertEquals(config.getMaxConnsPerHost(), numConns); - for (int i=0; i<4; i++) { // Note 4 threads .. which is more than the no of available conns .. hence we should see timeouts - threadPool.submit(new BasicWorker(result, control)); - } + int expected = result.successCount.get(); + Assert.assertTrue(expected - cpMonitor.getConnectionBorrowedCount() <= 5); + Assert.assertTrue(expected - cpMonitor.getConnectionReturnedCount() <= 5); - Thread.sleep(500); + Assert.assertEquals(config.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); + Assert.assertEquals(config.getMaxConnsPerHost(), cpMonitor.getConnectionClosedCount()); - Assert.assertTrue(result.opCount.get() > 0); - Assert.assertEquals(0, result.failureCount.get()); + Assert.assertEquals(0, result.failureCount.get()); + } - pool.markAsDown(new FatalConnectionException("mark pool as down")); + @Test + public void testPoolTimeouts() throws Exception { - Thread.sleep(200); + pool = new HostConnectionPoolImpl(TestHost, connFactory, config, cpMonitor); + int numConns = pool.primeConnections(); - control.stop(); - control.waitOnFinish(); + final BasicResult result = new BasicResult(); + final TestControl control = new TestControl(4); - pool.shutdown(); + for (int i = 0; i < 5; i++) { // Note 5 threads .. which is more than the no of available conns .. hence we should see timeouts + threadPool.submit(new BasicWorker(result, control, 55)); + } - Assert.assertEquals(config.getMaxConnsPerHost(), numConns); + Thread.sleep(300); - Assert.assertEquals(result.successCount.get(), cpMonitor.getConnectionBorrowedCount()); - Assert.assertEquals(result.successCount.get(), cpMonitor.getConnectionReturnedCount()); - Assert.assertEquals(config.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); - Assert.assertEquals(config.getMaxConnsPerHost(), cpMonitor.getConnectionClosedCount()); - Assert.assertEquals(0, cpMonitor.getConnectionCreateFailedCount()); + control.stop(); + control.waitOnFinish(); - Assert.assertTrue(result.failureCount.get() > 0); - } + pool.shutdown(); - private class BasicWorker implements Callable { + Thread.sleep(300); - private final BasicResult result; - private final TestControl control; + Assert.assertEquals(config.getMaxConnsPerHost(), numConns); - private int sleepMs = -1; + int expected = result.successCount.get(); + Assert.assertTrue(expected - cpMonitor.getConnectionBorrowedCount() <= 5); + Assert.assertTrue(expected - cpMonitor.getConnectionReturnedCount() <= 5); - private BasicWorker(BasicResult result, TestControl testControl) { - this.result = result; - this.control = testControl; - } + Assert.assertEquals(config.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); + Assert.assertEquals(config.getMaxConnsPerHost(), cpMonitor.getConnectionClosedCount()); - private BasicWorker(BasicResult result, TestControl testControl, int sleep) { - this.result = result; - this.control = testControl; - this.sleepMs = sleep; - } + Assert.assertEquals(0, cpMonitor.getConnectionCreateFailedCount()); - @Override - public Void call() throws Exception { + Assert.assertTrue(result.failureCount.get() > 0); + } - while (!control.isStopped() && !Thread.currentThread().isInterrupted()) { + @Test + public void testMarkHostAsDown() throws Exception { - Connection connection = null; - try { - connection = pool.borrowConnection(100, TimeUnit.MILLISECONDS); - if (sleepMs > 0) { - Thread.sleep(sleepMs); - } - pool.returnConnection(connection); - result.successCount.incrementAndGet(); - result.lastSuccess.set(true); - } catch (InterruptedException e) { - } catch (DynoConnectException e) { - result.failureCount.incrementAndGet(); - result.lastSuccess.set(false); - if (connection != null) { - ((TestConnection)connection).setException(e); - } - } finally { - result.opCount.incrementAndGet(); - } - } + pool = new HostConnectionPoolImpl(TestHost, connFactory, config, cpMonitor); + int numConns = pool.primeConnections(); - control.reportFinish(); - return null; - } - } + final BasicResult result = new BasicResult(); + final TestControl control = new TestControl(4); - private class TestControl { + for (int i = 0; i < 4; i++) { // Note 4 threads .. which is more than the no of available conns .. hence we should see timeouts + threadPool.submit(new BasicWorker(result, control)); + } - private final AtomicBoolean stop = new AtomicBoolean(false); - private final CountDownLatch latch; + Thread.sleep(500); - private TestControl(int n) { - latch = new CountDownLatch(n); - } + Assert.assertTrue(result.opCount.get() > 0); + Assert.assertEquals(0, result.failureCount.get()); - private void reportFinish() { - latch.countDown(); - } + pool.markAsDown(new FatalConnectionException("mark pool as down")); - private void waitOnFinish() throws InterruptedException { - latch.await(); - } + Thread.sleep(200); - private boolean isStopped() { - return stop.get(); - } + control.stop(); + control.waitOnFinish(); - private void stop() { - stop.set(true); - } - } + pool.shutdown(); - private class BasicResult { + Assert.assertEquals(config.getMaxConnsPerHost(), numConns); - private final AtomicInteger opCount = new AtomicInteger(0); - private final AtomicInteger successCount = new AtomicInteger(0); - private final AtomicInteger failureCount = new AtomicInteger(0); - - private AtomicBoolean lastSuccess = new AtomicBoolean(false); - - private BasicResult() { - } - - @Override - public String toString() { - return "BasicResult [opCount=" + opCount + ", successCount=" + successCount + - ", failureCount=" + failureCount + ", lastSuccess=" + lastSuccess.get() + "]"; - } - } + Assert.assertEquals(result.successCount.get(), cpMonitor.getConnectionBorrowedCount()); + Assert.assertEquals(result.successCount.get(), cpMonitor.getConnectionReturnedCount()); + Assert.assertEquals(config.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); + Assert.assertEquals(config.getMaxConnsPerHost(), cpMonitor.getConnectionClosedCount()); + Assert.assertEquals(0, cpMonitor.getConnectionCreateFailedCount()); + + Assert.assertTrue(result.failureCount.get() > 0); + } + + private class BasicWorker implements Callable { + + private final BasicResult result; + private final TestControl control; + + private int sleepMs = -1; + + private BasicWorker(BasicResult result, TestControl testControl) { + this.result = result; + this.control = testControl; + } + + private BasicWorker(BasicResult result, TestControl testControl, int sleep) { + this.result = result; + this.control = testControl; + this.sleepMs = sleep; + } + + @Override + public Void call() throws Exception { + + while (!control.isStopped() && !Thread.currentThread().isInterrupted()) { + + Connection connection = null; + try { + connection = pool.borrowConnection(100, TimeUnit.MILLISECONDS); + if (sleepMs > 0) { + Thread.sleep(sleepMs); + } + pool.returnConnection(connection); + result.successCount.incrementAndGet(); + result.lastSuccess.set(true); + } catch (InterruptedException e) { + } catch (DynoConnectException e) { + result.failureCount.incrementAndGet(); + result.lastSuccess.set(false); + if (connection != null) { + ((TestConnection) connection).setException(e); + } + } finally { + result.opCount.incrementAndGet(); + } + } + + control.reportFinish(); + return null; + } + } + + private class TestControl { + + private final AtomicBoolean stop = new AtomicBoolean(false); + private final CountDownLatch latch; + + private TestControl(int n) { + latch = new CountDownLatch(n); + } + + private void reportFinish() { + latch.countDown(); + } + + private void waitOnFinish() throws InterruptedException { + latch.await(); + } + + private boolean isStopped() { + return stop.get(); + } + + private void stop() { + stop.set(true); + } + } + + private class BasicResult { + + private final AtomicInteger opCount = new AtomicInteger(0); + private final AtomicInteger successCount = new AtomicInteger(0); + private final AtomicInteger failureCount = new AtomicInteger(0); + + private AtomicBoolean lastSuccess = new AtomicBoolean(false); + + private BasicResult() { + } + + @Override + public String toString() { + return "BasicResult [opCount=" + opCount + ", successCount=" + successCount + + ", failureCount=" + failureCount + ", lastSuccess=" + lastSuccess.get() + "]"; + } + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/HostStatusTrackerTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/HostStatusTrackerTest.java index 0ebfaace..69329337 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/HostStatusTrackerTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/HostStatusTrackerTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,140 +28,140 @@ public class HostStatusTrackerTest { - @Test - public void testMutuallyExclusive() throws Exception { + @Test + public void testMutuallyExclusive() throws Exception { - Set up = getHostSet("A", "B", "D", "E"); - Set down = getHostSet("C", "F", "H"); + Set up = getHostSet("A", "B", "D", "E"); + Set down = getHostSet("C", "F", "H"); - new HostStatusTracker(up, down); + new HostStatusTracker(up, down); - up = getHostSet(); - down = getHostSet("C", "F", "H"); + up = getHostSet(); + down = getHostSet("C", "F", "H"); - new HostStatusTracker(up, down); + new HostStatusTracker(up, down); - up = getHostSet("A", "C", "D"); - down = getHostSet(); + up = getHostSet("A", "C", "D"); + down = getHostSet(); - new HostStatusTracker(up, down); - } + new HostStatusTracker(up, down); + } - @Test (expected=RuntimeException.class) - public void testNotMutuallyExclusive() throws Exception { + @Test(expected = RuntimeException.class) + public void testNotMutuallyExclusive() throws Exception { - Set up = getHostSet("A", "B", "D", "E"); - Set down = getHostSet("C", "F", "H", "E"); + Set up = getHostSet("A", "B", "D", "E"); + Set down = getHostSet("C", "F", "H", "E"); - new HostStatusTracker(up, down); - } + new HostStatusTracker(up, down); + } - @Test - public void testEurekaUpdates() throws Exception { + @Test + public void testEurekaUpdates() throws Exception { - Set up = getHostSet("A", "B", "D", "E"); - Set down = getHostSet("C", "F", "H"); + Set up = getHostSet("A", "B", "D", "E"); + Set down = getHostSet("C", "F", "H"); - // First time update - HostStatusTracker tracker = new HostStatusTracker(up, down); + // First time update + HostStatusTracker tracker = new HostStatusTracker(up, down); - verifySet(tracker.getActiveHosts(), "A", "E", "D" ,"B"); - verifySet(tracker.getInactiveHosts(), "C", "H" ,"F"); + verifySet(tracker.getActiveHosts(), "A", "E", "D", "B"); + verifySet(tracker.getInactiveHosts(), "C", "H", "F"); - // Round 2. New server 'J' shows up - tracker = tracker.computeNewHostStatus(getHostSet("A", "B", "E", "D", "J"), getHostSet("C", "H" ,"F")); + // Round 2. New server 'J' shows up + tracker = tracker.computeNewHostStatus(getHostSet("A", "B", "E", "D", "J"), getHostSet("C", "H", "F")); - verifySet(tracker.getActiveHosts(), "A", "E", "D", "J", "B"); - verifySet(tracker.getInactiveHosts(), "C", "H" ,"F"); + verifySet(tracker.getActiveHosts(), "A", "E", "D", "J", "B"); + verifySet(tracker.getInactiveHosts(), "C", "H", "F"); - // Round 3. server 'A' goes from active to inactive - tracker = tracker.computeNewHostStatus(getHostSet("B", "E", "D", "J"), getHostSet("A", "C", "H", "F")); + // Round 3. server 'A' goes from active to inactive + tracker = tracker.computeNewHostStatus(getHostSet("B", "E", "D", "J"), getHostSet("A", "C", "H", "F")); - verifySet(tracker.getActiveHosts(), "E", "D", "J", "B"); - verifySet(tracker.getInactiveHosts(), "C", "A", "H" ,"F"); + verifySet(tracker.getActiveHosts(), "E", "D", "J", "B"); + verifySet(tracker.getInactiveHosts(), "C", "A", "H", "F"); - // Round 4. New servers 'X' and 'Y' show up and "D" goes from active to inactive - tracker = tracker.computeNewHostStatus(getHostSet("X", "Y", "B", "E", "J"), getHostSet("A", "C", "D", "H", "F")); + // Round 4. New servers 'X' and 'Y' show up and "D" goes from active to inactive + tracker = tracker.computeNewHostStatus(getHostSet("X", "Y", "B", "E", "J"), getHostSet("A", "C", "D", "H", "F")); - verifySet(tracker.getActiveHosts(), "X", "Y", "B", "E", "J"); - verifySet(tracker.getInactiveHosts(), "C", "A", "H", "D", "F"); + verifySet(tracker.getActiveHosts(), "X", "Y", "B", "E", "J"); + verifySet(tracker.getInactiveHosts(), "C", "A", "H", "D", "F"); - // Round 5. server "B" goes MISSING - tracker = tracker.computeNewHostStatus(getHostSet("X", "Y", "E", "J"), getHostSet("A", "C", "D", "H", "F")); + // Round 5. server "B" goes MISSING + tracker = tracker.computeNewHostStatus(getHostSet("X", "Y", "E", "J"), getHostSet("A", "C", "D", "H", "F")); - verifySet(tracker.getActiveHosts(), "X", "Y", "E", "J"); - verifySet(tracker.getInactiveHosts(), "C", "A", "H", "D", "F", "B"); + verifySet(tracker.getActiveHosts(), "X", "Y", "E", "J"); + verifySet(tracker.getInactiveHosts(), "C", "A", "H", "D", "F", "B"); - // Round 6. server "E" and "J" go MISSING and new server "K" shows up and "A" and "C" go from inactive to active - tracker = tracker.computeNewHostStatus(getHostSet("X", "Y", "A", "K", "C"), getHostSet("D", "H", "F")); + // Round 6. server "E" and "J" go MISSING and new server "K" shows up and "A" and "C" go from inactive to active + tracker = tracker.computeNewHostStatus(getHostSet("X", "Y", "A", "K", "C"), getHostSet("D", "H", "F")); - verifySet(tracker.getActiveHosts(), "X", "Y", "A", "C", "K"); - verifySet(tracker.getInactiveHosts(), "H", "D", "F", "E", "J"); + verifySet(tracker.getActiveHosts(), "X", "Y", "A", "C", "K"); + verifySet(tracker.getInactiveHosts(), "H", "D", "F", "E", "J"); - // Round 7. all active hosts go from active to inactive - tracker = tracker.computeNewHostStatus(getHostSet(), getHostSet("D", "H", "F", "X", "Y", "A", "K", "C")); + // Round 7. all active hosts go from active to inactive + tracker = tracker.computeNewHostStatus(getHostSet(), getHostSet("D", "H", "F", "X", "Y", "A", "K", "C")); - verifySet(tracker.getActiveHosts(), ""); - verifySet(tracker.getInactiveHosts(), "H", "D", "F", "X", "Y", "A", "K", "C"); + verifySet(tracker.getActiveHosts(), ""); + verifySet(tracker.getInactiveHosts(), "H", "D", "F", "X", "Y", "A", "K", "C"); - // Round 8. 'X' 'Y' 'A' and 'C' go from inactive to active and 'K' disappears from down list - tracker = tracker.computeNewHostStatus(getHostSet("X", "Y", "A", "C"), getHostSet("D", "H", "F")); + // Round 8. 'X' 'Y' 'A' and 'C' go from inactive to active and 'K' disappears from down list + tracker = tracker.computeNewHostStatus(getHostSet("X", "Y", "A", "C"), getHostSet("D", "H", "F")); - verifySet(tracker.getActiveHosts(), "X", "Y", "A", "C"); - verifySet(tracker.getInactiveHosts(), "H", "D", "F"); + verifySet(tracker.getActiveHosts(), "X", "Y", "A", "C"); + verifySet(tracker.getInactiveHosts(), "H", "D", "F"); - // Round 9. All inactive hosts disappear - tracker = tracker.computeNewHostStatus(getHostSet("X", "Y", "A", "C"), getHostSet()); + // Round 9. All inactive hosts disappear + tracker = tracker.computeNewHostStatus(getHostSet("X", "Y", "A", "C"), getHostSet()); - verifySet(tracker.getActiveHosts(), "X", "Y", "A", "C"); - verifySet(tracker.getInactiveHosts(), ""); + verifySet(tracker.getActiveHosts(), "X", "Y", "A", "C"); + verifySet(tracker.getInactiveHosts(), ""); - // Round 9. All active hosts disappear - tracker = tracker.computeNewHostStatus(getHostSet(), getHostSet("K", "J")); + // Round 9. All active hosts disappear + tracker = tracker.computeNewHostStatus(getHostSet(), getHostSet("K", "J")); - verifySet(tracker.getActiveHosts(), ""); - verifySet(tracker.getInactiveHosts(), "J", "K", "X", "Y", "A", "C"); + verifySet(tracker.getActiveHosts(), ""); + verifySet(tracker.getInactiveHosts(), "J", "K", "X", "Y", "A", "C"); - // Round 10. All hosts disappear - tracker = tracker.computeNewHostStatus(getHostSet(), getHostSet()); + // Round 10. All hosts disappear + tracker = tracker.computeNewHostStatus(getHostSet(), getHostSet()); - verifySet(tracker.getActiveHosts(), ""); - verifySet(tracker.getInactiveHosts(), ""); - } + verifySet(tracker.getActiveHosts(), ""); + verifySet(tracker.getInactiveHosts(), ""); + } - private Set getHostSet(String ...names) { + private Set getHostSet(String... names) { - Set set = new HashSet(); - if (names != null && names.length > 0) { - for (String name : names) { - if (!name.isEmpty()) { - set.add(new Host(name, 1234, "r1")); - } - } - } - return set; - } + Set set = new HashSet(); + if (names != null && names.length > 0) { + for (String name : names) { + if (!name.isEmpty()) { + set.add(new Host(name, 1234, "r1")); + } + } + } + return set; + } - private void verifySet(Collection hosts, String ... names) { + private void verifySet(Collection hosts, String... names) { - Set expected = new HashSet(); - if (names != null && names.length > 0) { - for (String n : names) { - if (n != null && !n.isEmpty()) { - expected.add(n); - } - } - } + Set expected = new HashSet(); + if (names != null && names.length > 0) { + for (String n : names) { + if (n != null && !n.isEmpty()) { + expected.add(n); + } + } + } - Set result = new HashSet( CollectionUtils.transform(hosts, new Transform() { + Set result = new HashSet(CollectionUtils.transform(hosts, new Transform() { - @Override - public String get(Host x) { - return x.getHostAddress(); - } - })); + @Override + public String get(Host x) { + return x.getHostAddress(); + } + })); - Assert.assertEquals(expected, result); - } + Assert.assertEquals(expected, result); + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/OperationResultImplTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/OperationResultImplTest.java index 7a606b79..209b8a13 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/OperationResultImplTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/OperationResultImplTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,23 +25,23 @@ public class OperationResultImplTest { - @Test - public void testProcess() throws Exception { - - OperationMonitor monitor = new LastOperationMonitor(); - OperationResultImpl opResult = new OperationResultImpl("test", 11, monitor); - Host host = new Host("testHost", "rand_ip", 1234, "rand_rack"); - - opResult.attempts(2) - .addMetadata("foo", "f1").addMetadata("bar", "b1") - .setLatency(10, TimeUnit.MILLISECONDS) - .setNode(host); - - Assert.assertEquals(2, opResult.getAttemptsCount()); - Assert.assertEquals(10, opResult.getLatency()); - Assert.assertEquals(10, opResult.getLatency(TimeUnit.MILLISECONDS)); - Assert.assertEquals(host, opResult.getNode()); - Assert.assertEquals("f1", opResult.getMetadata().get("foo")); - Assert.assertEquals("b1", opResult.getMetadata().get("bar")); - } + @Test + public void testProcess() throws Exception { + + OperationMonitor monitor = new LastOperationMonitor(); + OperationResultImpl opResult = new OperationResultImpl("test", 11, monitor); + Host host = new Host("testHost", "rand_ip", 1234, "rand_rack"); + + opResult.attempts(2) + .addMetadata("foo", "f1").addMetadata("bar", "b1") + .setLatency(10, TimeUnit.MILLISECONDS) + .setNode(host); + + Assert.assertEquals(2, opResult.getAttemptsCount()); + Assert.assertEquals(10, opResult.getLatency()); + Assert.assertEquals(10, opResult.getLatency(TimeUnit.MILLISECONDS)); + Assert.assertEquals(host, opResult.getNode()); + Assert.assertEquals("f1", opResult.getMetadata().get("foo")); + Assert.assertEquals("b1", opResult.getMetadata().get("bar")); + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/RetryNTimesTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/RetryNTimesTest.java index 12a5cbd1..81707eaa 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/RetryNTimesTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/RetryNTimesTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,26 +20,26 @@ public class RetryNTimesTest { - @Test - public void testNRetries() throws Exception { + @Test + public void testNRetries() throws Exception { - RetryNTimes retry = new RetryNTimes(3, true); + RetryNTimes retry = new RetryNTimes(3, true); - RuntimeException e = new RuntimeException("failure"); - retry.begin(); + RuntimeException e = new RuntimeException("failure"); + retry.begin(); - Assert.assertTrue(retry.allowRetry()); + Assert.assertTrue(retry.allowRetry()); - retry.failure(e); - Assert.assertTrue(retry.allowRetry()); - retry.failure(e); - Assert.assertTrue(retry.allowRetry()); - retry.failure(e); - Assert.assertTrue(retry.allowRetry()); + retry.failure(e); + Assert.assertTrue(retry.allowRetry()); + retry.failure(e); + Assert.assertTrue(retry.allowRetry()); + retry.failure(e); + Assert.assertTrue(retry.allowRetry()); - retry.failure(e); - Assert.assertFalse(retry.allowRetry()); + retry.failure(e); + Assert.assertFalse(retry.allowRetry()); - Assert.assertEquals(4, retry.getAttemptCount()); - } + Assert.assertEquals(4, retry.getAttemptCount()); + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/RunOnceTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/RunOnceTest.java index ea72b919..8a2a8e0e 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/RunOnceTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/RunOnceTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,21 +20,21 @@ public class RunOnceTest { - @Test - public void testRetry() throws Exception { + @Test + public void testRetry() throws Exception { - RunOnce retry = new RunOnce(); + RunOnce retry = new RunOnce(); - RuntimeException e = new RuntimeException("failure"); - retry.begin(); + RuntimeException e = new RuntimeException("failure"); + retry.begin(); - Assert.assertTrue(retry.allowRetry()); + Assert.assertTrue(retry.allowRetry()); - retry.failure(e); - Assert.assertFalse(retry.allowRetry()); - retry.failure(e); - Assert.assertFalse(retry.allowRetry()); + retry.failure(e); + Assert.assertFalse(retry.allowRetry()); + retry.failure(e); + Assert.assertFalse(retry.allowRetry()); - Assert.assertEquals(1, retry.getAttemptCount()); - } + Assert.assertEquals(1, retry.getAttemptCount()); + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/SimpleAsyncConnectionPoolImplTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/SimpleAsyncConnectionPoolImplTest.java index 7ba68ea2..9947fc91 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/SimpleAsyncConnectionPoolImplTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/SimpleAsyncConnectionPoolImplTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -43,259 +43,260 @@ public class SimpleAsyncConnectionPoolImplTest { - // TEST UTILS SETUP - private static final Host TestHost = new Host("TestHost", "TestIp", 1234, "TestRack"); + // TEST UTILS SETUP + private static final Host TestHost = new Host("TestHost", "TestIp", 1234, "TestRack"); - private class TestClient {} + private class TestClient { + } - private static SimpleAsyncConnectionPoolImpl pool; - private static ExecutorService threadPool; + private static SimpleAsyncConnectionPoolImpl pool; + private static ExecutorService threadPool; - private static ConnectionFactory connFactory = new ConnectionFactory() { + private static ConnectionFactory connFactory = new ConnectionFactory() { @SuppressWarnings("unchecked") @Override - public Connection createConnection(HostConnectionPool pool, ConnectionObservor cObservor) throws DynoConnectException, ThrottledException { - return mock(Connection.class); - } - }; + public Connection createConnection(HostConnectionPool pool, ConnectionObservor cObservor) throws DynoConnectException, ThrottledException { + return mock(Connection.class); + } + }; - private static ConnectionPoolConfigurationImpl config = new ConnectionPoolConfigurationImpl("TestClient"); - private static CountingConnectionPoolMonitor cpMonitor = new CountingConnectionPoolMonitor(); + private static ConnectionPoolConfigurationImpl config = new ConnectionPoolConfigurationImpl("TestClient"); + private static CountingConnectionPoolMonitor cpMonitor = new CountingConnectionPoolMonitor(); - @BeforeClass - public static void beforeClass() { - threadPool = Executors.newFixedThreadPool(10); - } + @BeforeClass + public static void beforeClass() { + threadPool = Executors.newFixedThreadPool(10); + } - @Before - public void beforeTest() { - cpMonitor = new CountingConnectionPoolMonitor(); // reset all monitor stats - } + @Before + public void beforeTest() { + cpMonitor = new CountingConnectionPoolMonitor(); // reset all monitor stats + } - @After - public void afterTest() { - if (pool != null) { - pool.shutdown(); - } - } + @After + public void afterTest() { + if (pool != null) { + pool.shutdown(); + } + } - @AfterClass - public static void afterClass() { - threadPool.shutdownNow(); - } + @AfterClass + public static void afterClass() { + threadPool.shutdownNow(); + } - @Test - public void testRegularProcess() throws Exception { + @Test + public void testRegularProcess() throws Exception { - pool = new SimpleAsyncConnectionPoolImpl(TestHost, connFactory, config, cpMonitor); - pool.primeConnections(); + pool = new SimpleAsyncConnectionPoolImpl(TestHost, connFactory, config, cpMonitor); + pool.primeConnections(); - int nThreads = 3; - final TestControl control = new TestControl(3); - final BasicResult total = new BasicResult(); + int nThreads = 3; + final TestControl control = new TestControl(3); + final BasicResult total = new BasicResult(); - for (int i=0; i(TestHost, connFactory, config, cpMonitor); - pool.primeConnections(); + pool = new SimpleAsyncConnectionPoolImpl(TestHost, connFactory, config, cpMonitor); + pool.primeConnections(); - int nThreads = 3; - final TestControl control = new TestControl(3); - final BasicResult total = new BasicResult(); + int nThreads = 3; + final TestControl control = new TestControl(3); + final BasicResult total = new BasicResult(); - for (int i=0; i 0); - Assert.assertFalse("Total: " + total, total.lastSuccess.get()); - Assert.assertEquals("Total: " + total, total.opCount.get(), (total.successCount.get() + total.failureCount.get())); + Assert.assertTrue("Total: " + total, total.failureCount.get() > 0); + Assert.assertFalse("Total: " + total, total.lastSuccess.get()); + Assert.assertEquals("Total: " + total, total.opCount.get(), (total.successCount.get() + total.failureCount.get())); - pool.shutdown(); + pool.shutdown(); - Assert.assertEquals("Conns borrowed: " + cpMonitor.getConnectionBorrowedCount(), total.successCount.get(), cpMonitor.getConnectionBorrowedCount()); - Assert.assertEquals("Conns returned: " + cpMonitor.getConnectionReturnedCount(), cpMonitor.getConnectionBorrowedCount(), cpMonitor.getConnectionReturnedCount()); - Assert.assertEquals("Conns created: " + cpMonitor.getConnectionCreatedCount(), config.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); - Assert.assertEquals("Conns closed: " + cpMonitor.getConnectionClosedCount(), cpMonitor.getConnectionCreatedCount(), cpMonitor.getConnectionClosedCount()); - Assert.assertEquals("Conns create failed: " + cpMonitor.getConnectionCreateFailedCount(), 0, cpMonitor.getConnectionCreateFailedCount()); - } + Assert.assertEquals("Conns borrowed: " + cpMonitor.getConnectionBorrowedCount(), total.successCount.get(), cpMonitor.getConnectionBorrowedCount()); + Assert.assertEquals("Conns returned: " + cpMonitor.getConnectionReturnedCount(), cpMonitor.getConnectionBorrowedCount(), cpMonitor.getConnectionReturnedCount()); + Assert.assertEquals("Conns created: " + cpMonitor.getConnectionCreatedCount(), config.getMaxConnsPerHost(), cpMonitor.getConnectionCreatedCount()); + Assert.assertEquals("Conns closed: " + cpMonitor.getConnectionClosedCount(), cpMonitor.getConnectionCreatedCount(), cpMonitor.getConnectionClosedCount()); + Assert.assertEquals("Conns create failed: " + cpMonitor.getConnectionCreateFailedCount(), 0, cpMonitor.getConnectionCreateFailedCount()); + } - @Test - public void testReconnect() throws Exception { + @Test + public void testReconnect() throws Exception { - pool = new SimpleAsyncConnectionPoolImpl(TestHost, connFactory, config, cpMonitor); - pool.primeConnections(); + pool = new SimpleAsyncConnectionPoolImpl(TestHost, connFactory, config, cpMonitor); + pool.primeConnections(); - int nThreads = 3; - TestControl control = new TestControl(3); - BasicResult total = new BasicResult(); + int nThreads = 3; + TestControl control = new TestControl(3); + BasicResult total = new BasicResult(); - for (int i=0; i 0); - Assert.assertTrue("Total: " + total, total.lastSuccess.get()); + Assert.assertFalse("Total: " + total, total.failureCount.get() > 0); + Assert.assertTrue("Total: " + total, total.lastSuccess.get()); - pool.markAsDown(new FatalConnectionException("mark pool as down")); + pool.markAsDown(new FatalConnectionException("mark pool as down")); - Thread.sleep(200); + Thread.sleep(200); - control.stop(); - control.waitOnFinish(); + control.stop(); + control.waitOnFinish(); - Assert.assertTrue("Total: " + total, total.failureCount.get() > 0); - Assert.assertFalse("Total: " + total, total.lastSuccess.get()); - Assert.assertEquals("Total: " + total, total.opCount.get(), (total.successCount.get() + total.failureCount.get())); + Assert.assertTrue("Total: " + total, total.failureCount.get() > 0); + Assert.assertFalse("Total: " + total, total.lastSuccess.get()); + Assert.assertEquals("Total: " + total, total.opCount.get(), (total.successCount.get() + total.failureCount.get())); - pool.reconnect(); - Thread.sleep(100); + pool.reconnect(); + Thread.sleep(100); - control = new TestControl(3); - total = new BasicResult(); + control = new TestControl(3); + total = new BasicResult(); - for (int i=0; i { + private class BasicWorker implements Callable { - private final BasicResult result; - private final TestControl control; + private final BasicResult result; + private final TestControl control; - private int sleepMs = -1; + private int sleepMs = -1; - private BasicWorker(BasicResult result, TestControl testControl) { - this.result = result; - this.control = testControl; - } + private BasicWorker(BasicResult result, TestControl testControl) { + this.result = result; + this.control = testControl; + } - private BasicWorker(BasicResult result, TestControl testControl, int sleep) { - this.result = result; - this.control = testControl; - this.sleepMs = sleep; - } + private BasicWorker(BasicResult result, TestControl testControl, int sleep) { + this.result = result; + this.control = testControl; + this.sleepMs = sleep; + } - @Override - public Void call() throws Exception { - - while (!control.isStopped() && !Thread.currentThread().isInterrupted()) { - - Connection connection = null; - try { - connection = pool.borrowConnection(20, TimeUnit.MILLISECONDS); - if (sleepMs > 0) { - Thread.sleep(sleepMs); - } - pool.returnConnection(connection); - result.successCount.incrementAndGet(); - result.lastSuccess.set(true); - } catch (InterruptedException e) { - } catch (DynoConnectException e) { - result.failureCount.incrementAndGet(); - result.lastSuccess.set(false); - } finally { - result.opCount.incrementAndGet(); - } - } - - control.reportFinish(); - return null; - } - } - - private class TestControl { - - private final AtomicBoolean stop = new AtomicBoolean(false); - private final CountDownLatch latch; - - private TestControl(int n) { - latch = new CountDownLatch(n); - } - - private void reportFinish() { - latch.countDown(); - } - - private void waitOnFinish() throws InterruptedException { - latch.await(); - } - - private boolean isStopped() { - return stop.get(); - } - - private void stop() { - stop.set(true); - } - } - - private class BasicResult { - - private final AtomicInteger opCount = new AtomicInteger(0); - private final AtomicInteger successCount = new AtomicInteger(0); - private final AtomicInteger failureCount = new AtomicInteger(0); - - private AtomicBoolean lastSuccess = new AtomicBoolean(false); - - private BasicResult() { - } + @Override + public Void call() throws Exception { + + while (!control.isStopped() && !Thread.currentThread().isInterrupted()) { + + Connection connection = null; + try { + connection = pool.borrowConnection(20, TimeUnit.MILLISECONDS); + if (sleepMs > 0) { + Thread.sleep(sleepMs); + } + pool.returnConnection(connection); + result.successCount.incrementAndGet(); + result.lastSuccess.set(true); + } catch (InterruptedException e) { + } catch (DynoConnectException e) { + result.failureCount.incrementAndGet(); + result.lastSuccess.set(false); + } finally { + result.opCount.incrementAndGet(); + } + } + + control.reportFinish(); + return null; + } + } + + private class TestControl { + + private final AtomicBoolean stop = new AtomicBoolean(false); + private final CountDownLatch latch; + + private TestControl(int n) { + latch = new CountDownLatch(n); + } + + private void reportFinish() { + latch.countDown(); + } + + private void waitOnFinish() throws InterruptedException { + latch.await(); + } + + private boolean isStopped() { + return stop.get(); + } + + private void stop() { + stop.set(true); + } + } + + private class BasicResult { + + private final AtomicInteger opCount = new AtomicInteger(0); + private final AtomicInteger successCount = new AtomicInteger(0); + private final AtomicInteger failureCount = new AtomicInteger(0); + + private AtomicBoolean lastSuccess = new AtomicBoolean(false); + + private BasicResult() { + } - @Override - public String toString() { - return "BasicResult [opCount=" + opCount + ", successCount=" + successCount + - ", failureCount=" + failureCount + ", lastSuccess=" + lastSuccess.get() + "]"; - } - } + @Override + public String toString() { + return "BasicResult [opCount=" + opCount + ", successCount=" + successCount + + ", failureCount=" + failureCount + ", lastSuccess=" + lastSuccess.get() + "]"; + } + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/hash/BinarySearchTokenMapperTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/hash/BinarySearchTokenMapperTest.java index 27d60e9a..80dde8e6 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/hash/BinarySearchTokenMapperTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/hash/BinarySearchTokenMapperTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -29,119 +29,119 @@ public class BinarySearchTokenMapperTest { - @Test - public void testSearchToken() throws Exception { + @Test + public void testSearchToken() throws Exception { - final BinarySearchTokenMapper tokenMapper = new BinarySearchTokenMapper(new Murmur1HashPartitioner()); - tokenMapper.initSearchMechanism(getTestTokens()); + final BinarySearchTokenMapper tokenMapper = new BinarySearchTokenMapper(new Murmur1HashPartitioner()); + tokenMapper.initSearchMechanism(getTestTokens()); - Long failures = 0L; + Long failures = 0L; - failures += runTest(309687905L - 1000000L, 309687905L, "h1", tokenMapper); - Assert.assertTrue("Failures: " + failures, failures == 0); + failures += runTest(309687905L - 1000000L, 309687905L, "h1", tokenMapper); + Assert.assertTrue("Failures: " + failures, failures == 0); - failures += runTest(309687905L + 1L, 309687905L + 1000000L, "h2", tokenMapper); - Assert.assertTrue("Failures: " + failures, failures == 0); + failures += runTest(309687905L + 1L, 309687905L + 1000000L, "h2", tokenMapper); + Assert.assertTrue("Failures: " + failures, failures == 0); - failures += runTest(1383429731L + 1L, 1383429731L + 1000000L, "h3", tokenMapper); - Assert.assertTrue("Failures: " + failures, failures == 0); + failures += runTest(1383429731L + 1L, 1383429731L + 1000000L, "h3", tokenMapper); + Assert.assertTrue("Failures: " + failures, failures == 0); - failures += runTest(2457171554L + 1L, 2457171554L + 1000000L, "h4", tokenMapper); - Assert.assertTrue("Failures: " + failures, failures == 0); + failures += runTest(2457171554L + 1L, 2457171554L + 1000000L, "h4", tokenMapper); + Assert.assertTrue("Failures: " + failures, failures == 0); - failures += runTest(3530913377L + 1L, 3530913377L + 1000000L, "h1", tokenMapper); - Assert.assertTrue("Failures: " + failures, failures == 0); - } + failures += runTest(3530913377L + 1L, 3530913377L + 1000000L, "h1", tokenMapper); + Assert.assertTrue("Failures: " + failures, failures == 0); + } - @Test - public void testAddToken() throws Exception { + @Test + public void testAddToken() throws Exception { - final BinarySearchTokenMapper tokenMapper = new BinarySearchTokenMapper(new Murmur1HashPartitioner()); - tokenMapper.initSearchMechanism(getTestTokens()); + final BinarySearchTokenMapper tokenMapper = new BinarySearchTokenMapper(new Murmur1HashPartitioner()); + tokenMapper.initSearchMechanism(getTestTokens()); - Long failures = 0L; + Long failures = 0L; - failures += runTest(309687905L + 1L, 309687905L + 1000000L, "h2", tokenMapper); - Assert.assertTrue("Failures: " + failures, failures == 0); + failures += runTest(309687905L + 1L, 309687905L + 1000000L, "h2", tokenMapper); + Assert.assertTrue("Failures: " + failures, failures == 0); - failures += runTest(1383429731L + 1L, 1383429731L + 1000000L, "h3", tokenMapper); - Assert.assertTrue("Failures: " + failures, failures == 0); + failures += runTest(1383429731L + 1L, 1383429731L + 1000000L, "h3", tokenMapper); + Assert.assertTrue("Failures: " + failures, failures == 0); - // Now construct the midpoint token between 'h2' and 'h3' - Long midpoint = 309687905L + (1383429731L - 309687905L)/2; - tokenMapper.addHostToken(new HostToken(midpoint, new Host("h23", -1, "r1", Status.Up))); + // Now construct the midpoint token between 'h2' and 'h3' + Long midpoint = 309687905L + (1383429731L - 309687905L) / 2; + tokenMapper.addHostToken(new HostToken(midpoint, new Host("h23", -1, "r1", Status.Up))); - failures += runTest(309687905L + 1L, 309687905L + 10L, "h23", tokenMapper); - Assert.assertTrue("Failures: " + failures, failures == 0); + failures += runTest(309687905L + 1L, 309687905L + 10L, "h23", tokenMapper); + Assert.assertTrue("Failures: " + failures, failures == 0); - failures += runTest(1383429731L + 1L, 1383429731L + 1000000L, "h3", tokenMapper); - Assert.assertTrue("Failures: " + failures, failures == 0); - } + failures += runTest(1383429731L + 1L, 1383429731L + 1000000L, "h3", tokenMapper); + Assert.assertTrue("Failures: " + failures, failures == 0); + } - @Test - public void testRemoveToken() throws Exception { + @Test + public void testRemoveToken() throws Exception { - final BinarySearchTokenMapper tokenMapper = new BinarySearchTokenMapper(new Murmur1HashPartitioner()); - tokenMapper.initSearchMechanism(getTestTokens()); + final BinarySearchTokenMapper tokenMapper = new BinarySearchTokenMapper(new Murmur1HashPartitioner()); + tokenMapper.initSearchMechanism(getTestTokens()); - Long failures = 0L; + Long failures = 0L; - failures += runTest(309687905L + 1L, 309687905L + 1000000L, "h2", tokenMapper); - Assert.assertTrue("Failures: " + failures, failures == 0); + failures += runTest(309687905L + 1L, 309687905L + 1000000L, "h2", tokenMapper); + Assert.assertTrue("Failures: " + failures, failures == 0); - failures += runTest(1383429731L + 1L, 1383429731L + 1000000L, "h3", tokenMapper); - Assert.assertTrue("Failures: " + failures, failures == 0); + failures += runTest(1383429731L + 1L, 1383429731L + 1000000L, "h3", tokenMapper); + Assert.assertTrue("Failures: " + failures, failures == 0); - // Now remove token 'h3' - tokenMapper.remoteHostToken(new HostToken(1383429731L, new Host("h2", -1, "r1", Status.Up))); + // Now remove token 'h3' + tokenMapper.remoteHostToken(new HostToken(1383429731L, new Host("h2", -1, "r1", Status.Up))); - failures += runTest(309687905L + 1L, 309687905L + 10L, "h3", tokenMapper); - Assert.assertTrue("Failures: " + failures, failures == 0); - } + failures += runTest(309687905L + 1L, 309687905L + 10L, "h3", tokenMapper); + Assert.assertTrue("Failures: " + failures, failures == 0); + } - private long runTest(Long start, Long end, final String expectedToken, final BinarySearchTokenMapper tokenMapper) { + private long runTest(Long start, Long end, final String expectedToken, final BinarySearchTokenMapper tokenMapper) { - final AtomicLong failures = new AtomicLong(0L); - final AtomicLong counter = new AtomicLong(start); + final AtomicLong failures = new AtomicLong(0L); + final AtomicLong counter = new AtomicLong(start); - while (counter.incrementAndGet() <= end) { + while (counter.incrementAndGet() <= end) { - final long hash = counter.get(); + final long hash = counter.get(); - HostToken hToken = tokenMapper.getToken(hash); - if (!(hToken.getHost().getHostAddress().equals(expectedToken))) { - failures.incrementAndGet(); - } - } - return failures.get(); - } + HostToken hToken = tokenMapper.getToken(hash); + if (!(hToken.getHost().getHostAddress().equals(expectedToken))) { + failures.incrementAndGet(); + } + } + return failures.get(); + } - private Collection getTestTokens() { + private Collection getTestTokens() { - /** - cqlsh:dyno_bootstrap> select "availabilityZone","hostname","token" from tokens where "appId" = 'dynomite_redis_puneet'; + /** + cqlsh:dyno_bootstrap> select "availabilityZone","hostname","token" from tokens where "appId" = 'dynomite_redis_puneet'; -availabilityZone | hostname | token -------------------+--------------------------------------------+------------ - us-east-1c | ec2-54-83-179-213.compute-1.amazonaws.com | 1383429731 - us-east-1c | ec2-54-224-184-99.compute-1.amazonaws.com | 309687905 - us-east-1c | ec2-54-91-190-159.compute-1.amazonaws.com | 3530913377 - us-east-1c | ec2-54-81-31-218.compute-1.amazonaws.com | 2457171554 - us-east-1e | ec2-54-198-222-153.compute-1.amazonaws.com | 309687905 - us-east-1e | ec2-54-198-239-231.compute-1.amazonaws.com | 2457171554 - us-east-1e | ec2-54-226-212-40.compute-1.amazonaws.com | 1383429731 - us-east-1e | ec2-54-197-178-229.compute-1.amazonaws.com | 3530913377 + availabilityZone | hostname | token + ------------------+--------------------------------------------+------------ + us-east-1c | ec2-54-83-179-213.compute-1.amazonaws.com | 1383429731 + us-east-1c | ec2-54-224-184-99.compute-1.amazonaws.com | 309687905 + us-east-1c | ec2-54-91-190-159.compute-1.amazonaws.com | 3530913377 + us-east-1c | ec2-54-81-31-218.compute-1.amazonaws.com | 2457171554 + us-east-1e | ec2-54-198-222-153.compute-1.amazonaws.com | 309687905 + us-east-1e | ec2-54-198-239-231.compute-1.amazonaws.com | 2457171554 + us-east-1e | ec2-54-226-212-40.compute-1.amazonaws.com | 1383429731 + us-east-1e | ec2-54-197-178-229.compute-1.amazonaws.com | 3530913377 -cqlsh:dyno_bootstrap> - */ + cqlsh:dyno_bootstrap> + */ - List tokens = new ArrayList(); + List tokens = new ArrayList(); - tokens.add(new HostToken(309687905L, new Host("h1", -1, "r1", Status.Up))); - tokens.add(new HostToken(1383429731L, new Host("h2", -1, "r1", Status.Up))); - tokens.add(new HostToken(2457171554L, new Host("h3", -1, "r1", Status.Up))); - tokens.add(new HostToken(3530913377L, new Host("h4", -1, "r1", Status.Up))); + tokens.add(new HostToken(309687905L, new Host("h1", -1, "r1", Status.Up))); + tokens.add(new HostToken(1383429731L, new Host("h2", -1, "r1", Status.Up))); + tokens.add(new HostToken(2457171554L, new Host("h3", -1, "r1", Status.Up))); + tokens.add(new HostToken(3530913377L, new Host("h4", -1, "r1", Status.Up))); - return tokens; - } + return tokens; + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/hash/DynoBinarySearchTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/hash/DynoBinarySearchTest.java index e4855538..3e53d893 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/hash/DynoBinarySearchTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/hash/DynoBinarySearchTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,106 +27,106 @@ public class DynoBinarySearchTest { - @Test - public void testTokenRange() throws Exception { + @Test + public void testTokenRange() throws Exception { - DynoTokenRange r1 = new DynoTokenRange(20, 40); + DynoTokenRange r1 = new DynoTokenRange(20, 40); - Assert.assertEquals(1, r1.compareTo(10)); - Assert.assertEquals(1, r1.compareTo(15)); - Assert.assertEquals(1, r1.compareTo(20)); - Assert.assertEquals(0, r1.compareTo(22)); - Assert.assertEquals(0, r1.compareTo(30)); - Assert.assertEquals(0, r1.compareTo(40)); - Assert.assertEquals(-1, r1.compareTo(42)); + Assert.assertEquals(1, r1.compareTo(10)); + Assert.assertEquals(1, r1.compareTo(15)); + Assert.assertEquals(1, r1.compareTo(20)); + Assert.assertEquals(0, r1.compareTo(22)); + Assert.assertEquals(0, r1.compareTo(30)); + Assert.assertEquals(0, r1.compareTo(40)); + Assert.assertEquals(-1, r1.compareTo(42)); - // First Range - r1 = new DynoTokenRange(null, 40); + // First Range + r1 = new DynoTokenRange(null, 40); - Assert.assertEquals(0, r1.compareTo(10)); - Assert.assertEquals(0, r1.compareTo(15)); - Assert.assertEquals(0, r1.compareTo(20)); - Assert.assertEquals(0, r1.compareTo(22)); - Assert.assertEquals(0, r1.compareTo(30)); - Assert.assertEquals(0, r1.compareTo(40)); - Assert.assertEquals(-1, r1.compareTo(42)); - } + Assert.assertEquals(0, r1.compareTo(10)); + Assert.assertEquals(0, r1.compareTo(15)); + Assert.assertEquals(0, r1.compareTo(20)); + Assert.assertEquals(0, r1.compareTo(22)); + Assert.assertEquals(0, r1.compareTo(30)); + Assert.assertEquals(0, r1.compareTo(40)); + Assert.assertEquals(-1, r1.compareTo(42)); + } - @Test - public void testTokenSearch() throws Exception { + @Test + public void testTokenSearch() throws Exception { - List list = Arrays.asList(10, 20, 30, 40, 50, 60, 70, 80, 90, 100); + List list = Arrays.asList(10, 20, 30, 40, 50, 60, 70, 80, 90, 100); - DynoBinarySearch search = new DynoBinarySearch(list); + DynoBinarySearch search = new DynoBinarySearch(list); - for (int i=0; i<=133; i++) { + for (int i = 0; i <= 133; i++) { - Integer token = search.getTokenOwner(i); - Integer expected = getExpectedToken(i); + Integer token = search.getTokenOwner(i); + Integer expected = getExpectedToken(i); - Assert.assertEquals(expected, token); - } - } + Assert.assertEquals(expected, token); + } + } - @Test - public void testTokenDistribution() throws Exception { + @Test + public void testTokenDistribution() throws Exception { - List tokens = Arrays.asList(611697721L, 2043353485L, 3475009249L); + List tokens = Arrays.asList(611697721L, 2043353485L, 3475009249L); - DynoBinarySearch search = new DynoBinarySearch(tokens); + DynoBinarySearch search = new DynoBinarySearch(tokens); - Map tokenCount = new HashMap(); + Map tokenCount = new HashMap(); - tokenCount.put(611697721L, 0L); - tokenCount.put(2043353485L, 0L); - tokenCount.put(3475009249L, 0L); + tokenCount.put(611697721L, 0L); + tokenCount.put(2043353485L, 0L); + tokenCount.put(3475009249L, 0L); - Murmur1HashPartitioner hash = new Murmur1HashPartitioner(); + Murmur1HashPartitioner hash = new Murmur1HashPartitioner(); - for (int i=0; i<1000000; i++) { + for (int i = 0; i < 1000000; i++) { - // Compute the hash - long lHash = hash.hash("" + i); + // Compute the hash + long lHash = hash.hash("" + i); - // Now lookup the node - Long token = search.getTokenOwner(lHash); + // Now lookup the node + Long token = search.getTokenOwner(lHash); - Long count = tokenCount.get(token); - count++; - tokenCount.put(token, count); - } + Long count = tokenCount.get(token); + count++; + tokenCount.put(token, count); + } - long total = 0; - for (Long value : tokenCount.values()) { - total += value; - } + long total = 0; + for (Long value : tokenCount.values()) { + total += value; + } - for (Long token : tokenCount.keySet()) { + for (Long token : tokenCount.keySet()) { - Long value = tokenCount.get(token); - Long percent = value*100/total; + Long value = tokenCount.get(token); + Long percent = value * 100 / total; - Assert.assertTrue("Percentage is off for tokenCount: " + tokenCount, percent >= 30 && percent <= 35); - } - } + Assert.assertTrue("Percentage is off for tokenCount: " + tokenCount, percent >= 30 && percent <= 35); + } + } - private int getExpectedToken(int key) throws Exception { + private int getExpectedToken(int key) throws Exception { - if (key < 10) { - return 10; - } + if (key < 10) { + return 10; + } - if (key > 100) { - return 10; - } + if (key > 100) { + return 10; + } - if (key % 10 == 0) { - return key; - } + if (key % 10 == 0) { + return key; + } - return key + (10 - key%10); - } + return key + (10 - key % 10); + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/hash/Murmur1HashPartitionerTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/hash/Murmur1HashPartitionerTest.java index 5ab5d9a5..9ea49cc3 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/hash/Murmur1HashPartitionerTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/hash/Murmur1HashPartitionerTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,24 +26,24 @@ public class Murmur1HashPartitionerTest { - @Test - public void test1MKeys() throws Exception { + @Test + public void test1MKeys() throws Exception { - Murmur1HashPartitioner hash = new Murmur1HashPartitioner(); + Murmur1HashPartitioner hash = new Murmur1HashPartitioner(); - List testTokens = readInTestTokens(); + List testTokens = readInTestTokens(); - for (int i=0; i<1000000; i++) { - long lHash = hash.hash("" + i); - long expected = Long.parseLong(testTokens.get(i)); + for (int i = 0; i < 1000000; i++) { + long lHash = hash.hash("" + i); + long expected = Long.parseLong(testTokens.get(i)); - Assert.assertEquals("Failed for i: " + i, expected, lHash); - } - } + Assert.assertEquals("Failed for i: " + i, expected, lHash); + } + } - private List readInTestTokens() throws IOException { - return IOUtilities.readLines(new File("./src/main/java/TestTokens.txt")); - } + private List readInTestTokens() throws IOException { + return IOUtilities.readLines(new File("./src/main/java/TestTokens.txt")); + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/health/ConnectionPoolHealthTrackerTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/health/ConnectionPoolHealthTrackerTest.java index c6077cca..e7d6cfda 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/health/ConnectionPoolHealthTrackerTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/health/ConnectionPoolHealthTrackerTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -45,117 +45,117 @@ public class ConnectionPoolHealthTrackerTest { - private static ScheduledExecutorService threadPool; + private static ScheduledExecutorService threadPool; - @BeforeClass - public static void beforeClass() { - BasicConfigurator.configure(); - threadPool = Executors.newScheduledThreadPool(1); - } + @BeforeClass + public static void beforeClass() { + BasicConfigurator.configure(); + threadPool = Executors.newScheduledThreadPool(1); + } - @AfterClass - public static void afterClass() { - BasicConfigurator.resetConfiguration(); - threadPool.shutdownNow(); - } + @AfterClass + public static void afterClass() { + BasicConfigurator.resetConfiguration(); + threadPool.shutdownNow(); + } - @Test - public void testConnectionPoolRecycle() throws Exception { + @Test + public void testConnectionPoolRecycle() throws Exception { - ConnectionPoolConfiguration config = new ConnectionPoolConfigurationImpl("test"); - ConnectionPoolHealthTracker tracker = new ConnectionPoolHealthTracker(config, threadPool, 1000, -1); - tracker.start(); + ConnectionPoolConfiguration config = new ConnectionPoolConfigurationImpl("test"); + ConnectionPoolHealthTracker tracker = new ConnectionPoolHealthTracker(config, threadPool, 1000, -1); + tracker.start(); - Host h1 = new Host("h1", "r1", Status.Up); - AtomicBoolean poolStatus = new AtomicBoolean(false); - HostConnectionPool hostPool = getMockConnectionPool(h1, poolStatus); + Host h1 = new Host("h1", "r1", Status.Up); + AtomicBoolean poolStatus = new AtomicBoolean(false); + HostConnectionPool hostPool = getMockConnectionPool(h1, poolStatus); - FatalConnectionException e = new FatalConnectionException("fatal"); + FatalConnectionException e = new FatalConnectionException("fatal"); - for (int i=0; i<10; i++) { - tracker.trackConnectionError(hostPool, e); - } - Thread.sleep(2000); + for (int i = 0; i < 10; i++) { + tracker.trackConnectionError(hostPool, e); + } + Thread.sleep(2000); - tracker.stop(); + tracker.stop(); - verify(hostPool, atLeastOnce()).markAsDown(any(DynoException.class)); - verify(hostPool, times(1)).reconnect(); + verify(hostPool, atLeastOnce()).markAsDown(any(DynoException.class)); + verify(hostPool, times(1)).reconnect(); - Assert.assertTrue("Pool active? : " + hostPool.isActive(), hostPool.isActive()); - // Check that the reconnecting pool is no longer being tracked by the tracker - Assert.assertNull(tracker.getReconnectingPools().get(h1)); - } + Assert.assertTrue("Pool active? : " + hostPool.isActive(), hostPool.isActive()); + // Check that the reconnecting pool is no longer being tracked by the tracker + Assert.assertNull(tracker.getReconnectingPools().get(h1)); + } - @Test - public void testBadConnectionPoolKeepsReconnecting() throws Exception { + @Test + public void testBadConnectionPoolKeepsReconnecting() throws Exception { - ConnectionPoolConfiguration config = new ConnectionPoolConfigurationImpl("test"); - ConnectionPoolHealthTracker tracker = new ConnectionPoolHealthTracker(config, threadPool, 1000, -1); - tracker.start(); + ConnectionPoolConfiguration config = new ConnectionPoolConfigurationImpl("test"); + ConnectionPoolHealthTracker tracker = new ConnectionPoolHealthTracker(config, threadPool, 1000, -1); + tracker.start(); - Host h1 = new Host("h1", "r1", Status.Up); - AtomicBoolean poolStatus = new AtomicBoolean(false); - HostConnectionPool hostPool = getMockConnectionPool(h1, poolStatus, true); + Host h1 = new Host("h1", "r1", Status.Up); + AtomicBoolean poolStatus = new AtomicBoolean(false); + HostConnectionPool hostPool = getMockConnectionPool(h1, poolStatus, true); - FatalConnectionException e = new FatalConnectionException("fatal"); + FatalConnectionException e = new FatalConnectionException("fatal"); - for (int i=0; i<10; i++) { - tracker.trackConnectionError(hostPool, e); - } - Thread.sleep(2000); + for (int i = 0; i < 10; i++) { + tracker.trackConnectionError(hostPool, e); + } + Thread.sleep(2000); - tracker.stop(); + tracker.stop(); - verify(hostPool, atLeastOnce()).markAsDown(any(DynoException.class)); - verify(hostPool, atLeastOnce()).reconnect(); + verify(hostPool, atLeastOnce()).markAsDown(any(DynoException.class)); + verify(hostPool, atLeastOnce()).reconnect(); - Assert.assertFalse("Pool active? : " + hostPool.isActive(), hostPool.isActive()); - // Check that the reconnecting pool is not still being tracked by the tracker - Assert.assertNotNull(tracker.getReconnectingPools().get(h1)); - } + Assert.assertFalse("Pool active? : " + hostPool.isActive(), hostPool.isActive()); + // Check that the reconnecting pool is not still being tracked by the tracker + Assert.assertNotNull(tracker.getReconnectingPools().get(h1)); + } - private HostConnectionPool getMockConnectionPool(final Host host, final AtomicBoolean active) { - return getMockConnectionPool(host, active, false); - } + private HostConnectionPool getMockConnectionPool(final Host host, final AtomicBoolean active) { + return getMockConnectionPool(host, active, false); + } - private HostConnectionPool getMockConnectionPool(final Host host, final AtomicBoolean active, final Boolean badConnectionPool) { + private HostConnectionPool getMockConnectionPool(final Host host, final AtomicBoolean active, final Boolean badConnectionPool) { - @SuppressWarnings("unchecked") - HostConnectionPool hostPool = mock(HostConnectionPool.class); - when(hostPool.getHost()).thenReturn(host); + @SuppressWarnings("unchecked") + HostConnectionPool hostPool = mock(HostConnectionPool.class); + when(hostPool.getHost()).thenReturn(host); - doAnswer(new Answer() { + doAnswer(new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return active.get(); - } - }).when(hostPool).isActive(); + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + return active.get(); + } + }).when(hostPool).isActive(); - doAnswer(new Answer() { + doAnswer(new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - active.set(false); - return null; - } - }).when(hostPool).markAsDown(any(DynoException.class)); + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + active.set(false); + return null; + } + }).when(hostPool).markAsDown(any(DynoException.class)); - doAnswer(new Answer() { + doAnswer(new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - if (badConnectionPool) { - throw new RuntimeException(); - } else { - active.set(true); - return null; - } - } - }).when(hostPool).reconnect(); + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + if (badConnectionPool) { + throw new RuntimeException(); + } else { + active.set(true); + return null; + } + } + }).when(hostPool).reconnect(); - return hostPool; - } + return hostPool; + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/health/ErrorRateMonitorTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/health/ErrorRateMonitorTest.java index e2c37140..b3932ace 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/health/ErrorRateMonitorTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/health/ErrorRateMonitorTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -36,133 +36,135 @@ public class ErrorRateMonitorTest { - @Test - public void testSimpleErrorCheckPolicy() throws Exception { + @Test + public void testSimpleErrorCheckPolicy() throws Exception { - List buckets = getBuckets(116, 120, 121, 120, 130, 125, 130, 120, 120, 120); + List buckets = getBuckets(116, 120, 121, 120, 130, 125, 130, 120, 120, 120); - SimpleErrorCheckPolicy policy = new SimpleErrorCheckPolicy(120, 10, 80); - Assert.assertTrue(policy.checkErrorRate(buckets)); + SimpleErrorCheckPolicy policy = new SimpleErrorCheckPolicy(120, 10, 80); + Assert.assertTrue(policy.checkErrorRate(buckets)); - policy = new SimpleErrorCheckPolicy(121, 10, 80); - Assert.assertFalse(policy.checkErrorRate(buckets)); + policy = new SimpleErrorCheckPolicy(121, 10, 80); + Assert.assertFalse(policy.checkErrorRate(buckets)); - policy = new SimpleErrorCheckPolicy(130, 10, 20); - Assert.assertTrue(policy.checkErrorRate(buckets)); + policy = new SimpleErrorCheckPolicy(130, 10, 20); + Assert.assertTrue(policy.checkErrorRate(buckets)); - } + } - private List getBuckets(Integer ... values) { - List buckets = new ArrayList(); + private List getBuckets(Integer... values) { + List buckets = new ArrayList(); - for (Integer i : values) { - Bucket b = new Bucket(); - b.track(i); - buckets.add(b); - } + for (Integer i : values) { + Bucket b = new Bucket(); + b.track(i); + buckets.add(b); + } - return buckets; - } + return buckets; + } - @Test - public void testNoErrorCheckTriggers() throws Exception { + @Test + public void testNoErrorCheckTriggers() throws Exception { - final ErrorRateMonitor errorMonitor = new ErrorRateMonitor(20, 1, 10); - errorMonitor.addPolicy(new SimpleErrorCheckPolicy(130, 8, 80)); // 80% of 10 seconds, if error rate > 120 then alert - errorMonitor.addPolicy(new SimpleErrorCheckPolicy(200, 4, 80)); // 80% of 5 seconds, if error rate > 200 then alert + final ErrorRateMonitor errorMonitor = new ErrorRateMonitor(20, 1, 10); + errorMonitor.addPolicy(new SimpleErrorCheckPolicy(130, 8, 80)); // 80% of 10 seconds, if error rate > 120 then alert + errorMonitor.addPolicy(new SimpleErrorCheckPolicy(200, 4, 80)); // 80% of 5 seconds, if error rate > 200 then alert - List rates = CollectionUtils.newArrayList(90, 120, 180); - int errorCount = runTest(9, errorMonitor, rates); + List rates = CollectionUtils.newArrayList(90, 120, 180); + int errorCount = runTest(9, errorMonitor, rates); - Assert.assertEquals(0, errorCount); - } + Assert.assertEquals(0, errorCount); + } - @Test - public void testSustainedErrorTriggers() throws Exception { + @Test + public void testSustainedErrorTriggers() throws Exception { - final ErrorRateMonitor errorMonitor = new ErrorRateMonitor(20, 1, 10); - errorMonitor.addPolicy(new SimpleErrorCheckPolicy(130, 8, 80)); // 80% of 10 seconds, if error rate > 120 then alert - errorMonitor.addPolicy(new SimpleErrorCheckPolicy(200, 4, 80)); // 80% of 5 seconds, if error rate > 200 then alert + final ErrorRateMonitor errorMonitor = new ErrorRateMonitor(20, 1, 10); + errorMonitor.addPolicy(new SimpleErrorCheckPolicy(130, 8, 80)); // 80% of 10 seconds, if error rate > 120 then alert + errorMonitor.addPolicy(new SimpleErrorCheckPolicy(200, 4, 80)); // 80% of 5 seconds, if error rate > 200 then alert - List rates = CollectionUtils.newArrayList(130, 140, 180); - int errorCount = runTest(9, errorMonitor, rates); + List rates = CollectionUtils.newArrayList(130, 140, 180); + int errorCount = runTest(9, errorMonitor, rates); - Assert.assertEquals(1, errorCount); - } + Assert.assertEquals(1, errorCount); + } - @Test - public void testOnlyLargeSpikeTriggers() throws Exception { + @Test + public void testOnlyLargeSpikeTriggers() throws Exception { - final ErrorRateMonitor errorMonitor = new ErrorRateMonitor(20, 1, 10); - errorMonitor.addPolicy(new SimpleErrorCheckPolicy(130, 10, 80)); // 80% of 10 seconds, if error rate > 120 then alert - errorMonitor.addPolicy(new SimpleErrorCheckPolicy(200, 4, 80)); // 80% of 5 seconds, if error rate > 200 then alert + final ErrorRateMonitor errorMonitor = new ErrorRateMonitor(20, 1, 10); + errorMonitor.addPolicy(new SimpleErrorCheckPolicy(130, 10, 80)); // 80% of 10 seconds, if error rate > 120 then alert + errorMonitor.addPolicy(new SimpleErrorCheckPolicy(200, 4, 80)); // 80% of 5 seconds, if error rate > 200 then alert - List rates = new ArrayList(); rates.add(110); rates.add(250); - int errorCount = runTest(10, errorMonitor, rates); + List rates = new ArrayList(); + rates.add(110); + rates.add(250); + int errorCount = runTest(10, errorMonitor, rates); - Assert.assertEquals(1, errorCount); - } + Assert.assertEquals(1, errorCount); + } - private int runTest(int totalTestRunTimeSeconds, final ErrorRateMonitor errorMonitor, final List rates) throws Exception { + private int runTest(int totalTestRunTimeSeconds, final ErrorRateMonitor errorMonitor, final List rates) throws Exception { - int numThreads = 5; - ExecutorService threadPool = Executors.newFixedThreadPool(numThreads); + int numThreads = 5; + ExecutorService threadPool = Executors.newFixedThreadPool(numThreads); - final AtomicReference limiter = new AtomicReference(RateLimitUtil.create(rates.get(0))); - final AtomicBoolean stop = new AtomicBoolean(false); + final AtomicReference limiter = new AtomicReference(RateLimitUtil.create(rates.get(0))); + final AtomicBoolean stop = new AtomicBoolean(false); - final CyclicBarrier barrier = new CyclicBarrier(numThreads+1); - final CountDownLatch latch = new CountDownLatch(numThreads); + final CyclicBarrier barrier = new CyclicBarrier(numThreads + 1); + final CountDownLatch latch = new CountDownLatch(numThreads); - final AtomicInteger errorCount = new AtomicInteger(0); + final AtomicInteger errorCount = new AtomicInteger(0); - for (int i=0; i() { + threadPool.submit(new Callable() { - @Override - public Void call() throws Exception { + @Override + public Void call() throws Exception { - barrier.await(); - while (!stop.get() && !Thread.currentThread().isInterrupted()) { - if (limiter.get().acquire()) { - boolean success = errorMonitor.trackErrorRate(1); - if (!success) { - errorCount.incrementAndGet(); - } - } - } - latch.countDown(); - return null; - } - }); - } + barrier.await(); + while (!stop.get() && !Thread.currentThread().isInterrupted()) { + if (limiter.get().acquire()) { + boolean success = errorMonitor.trackErrorRate(1); + if (!success) { + errorCount.incrementAndGet(); + } + } + } + latch.countDown(); + return null; + } + }); + } - barrier.await(); + barrier.await(); - int numIterations = rates.size(); - int sleepPerIteration = totalTestRunTimeSeconds/numIterations; + int numIterations = rates.size(); + int sleepPerIteration = totalTestRunTimeSeconds / numIterations; - int round = 1; - do { - Thread.sleep(sleepPerIteration*1000); - if (round < rates.size()) { - System.out.println("Changing rate to " + rates.get(round)); - limiter.set(RateLimitUtil.create(rates.get(round))); - } - round++; - } while (round <= numIterations); + int round = 1; + do { + Thread.sleep(sleepPerIteration * 1000); + if (round < rates.size()) { + System.out.println("Changing rate to " + rates.get(round)); + limiter.set(RateLimitUtil.create(rates.get(round))); + } + round++; + } while (round <= numIterations); - stop.set(true); - latch.await(); - threadPool.shutdownNow(); + stop.set(true); + latch.await(); + threadPool.shutdownNow(); - List buckets = errorMonitor.getRateTracker().getAllBuckets(); - for (Bucket b : buckets) { - System.out.print(" " + b.count()); - } - System.out.println("\n=========TEST DONE=============="); + List buckets = errorMonitor.getRateTracker().getAllBuckets(); + for (Bucket b : buckets) { + System.out.print(" " + b.count()); + } + System.out.println("\n=========TEST DONE=============="); - return errorCount.get(); - } + return errorCount.get(); + } } \ No newline at end of file diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/health/RateTrackerTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/health/RateTrackerTest.java index 4af2111f..2b4c6224 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/health/RateTrackerTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/health/RateTrackerTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -32,105 +32,105 @@ import com.netflix.dyno.connectionpool.impl.utils.RateLimitUtil; public class RateTrackerTest { - - @Test - public void testProcess() throws Exception { - final RateTracker tracker = new RateTracker(20); + @Test + public void testProcess() throws Exception { - int numThreads = 5; - ExecutorService threadPool = Executors.newFixedThreadPool(numThreads); + final RateTracker tracker = new RateTracker(20); - final AtomicReference limiter = new AtomicReference(RateLimitUtil.create(100)); + int numThreads = 5; + ExecutorService threadPool = Executors.newFixedThreadPool(numThreads); - final AtomicBoolean stop = new AtomicBoolean(false); + final AtomicReference limiter = new AtomicReference(RateLimitUtil.create(100)); - // stats - final AtomicInteger totalOps = new AtomicInteger(0); + final AtomicBoolean stop = new AtomicBoolean(false); - final CyclicBarrier barrier = new CyclicBarrier(numThreads+1); - final CountDownLatch latch = new CountDownLatch(numThreads); + // stats + final AtomicInteger totalOps = new AtomicInteger(0); - for (int i=0; i() { + for (int i = 0; i < numThreads; i++) { - @Override - public Void call() throws Exception { + threadPool.submit(new Callable() { - barrier.await(); - while (!stop.get() && !Thread.currentThread().isInterrupted()) { - if (limiter.get().acquire()){ - tracker.trackRate(1); - totalOps.incrementAndGet(); - } - } - latch.countDown(); - return null; - } - }); - } + @Override + public Void call() throws Exception { - barrier.await(); + barrier.await(); + while (!stop.get() && !Thread.currentThread().isInterrupted()) { + if (limiter.get().acquire()) { + tracker.trackRate(1); + totalOps.incrementAndGet(); + } + } + latch.countDown(); + return null; + } + }); + } - Thread.sleep(4000); - System.out.println("Changing rate to 120"); - limiter.set(RateLimitUtil.create(120)); + barrier.await(); - Thread.sleep(4000); - System.out.println("Changing rate to 80"); - limiter.set(RateLimitUtil.create(80)); + Thread.sleep(4000); + System.out.println("Changing rate to 120"); + limiter.set(RateLimitUtil.create(120)); - Thread.sleep(4000); - System.out.println("Changing rate to 200"); - limiter.set(RateLimitUtil.create(200)); + Thread.sleep(4000); + System.out.println("Changing rate to 80"); + limiter.set(RateLimitUtil.create(80)); - Thread.sleep(4000); - System.out.println("Changing rate to 100"); - limiter.set(RateLimitUtil.create(100)); + Thread.sleep(4000); + System.out.println("Changing rate to 200"); + limiter.set(RateLimitUtil.create(200)); - stop.set(true); - threadPool.shutdownNow(); + Thread.sleep(4000); + System.out.println("Changing rate to 100"); + limiter.set(RateLimitUtil.create(100)); - //Thread.sleep(100); - latch.await(); - - System.out.println("======================="); - System.out.println("Won lock: " + tracker.getWonLockCount()); - System.out.println("Total ops: " + totalOps.get()); + stop.set(true); + threadPool.shutdownNow(); - Assert.assertEquals(20, tracker.rWindow.getQueueSize()); - Assert.assertTrue(16 >= tracker.rWindow.getBucketCreateCount()); + //Thread.sleep(100); + latch.await(); - List allBuckets = tracker.getAllBuckets(); + System.out.println("======================="); + System.out.println("Won lock: " + tracker.getWonLockCount()); + System.out.println("Total ops: " + totalOps.get()); - // Remove the first bucket since it's essentially unreliable since that is when the test had stopped. - allBuckets.remove(0); + Assert.assertEquals(20, tracker.rWindow.getQueueSize()); + Assert.assertTrue(16 >= tracker.rWindow.getBucketCreateCount()); - for (Bucket b : allBuckets) { - System.out.print(" " + b.count()); - } - System.out.println(""); - Assert.assertTrue("P diff failed", 10 >= percentageDiff(200, allBuckets.get(0).count())); - Assert.assertTrue("P diff failed", 10 >= percentageDiff(200, allBuckets.get(1).count())); - Assert.assertTrue("P diff failed", 10 >= percentageDiff(200, allBuckets.get(2).count())); + List allBuckets = tracker.getAllBuckets(); - Assert.assertTrue("P diff failed", 10 >= percentageDiff(80, allBuckets.get(4).count())); - Assert.assertTrue("P diff failed", 10 >= percentageDiff(80, allBuckets.get(5).count())); - Assert.assertTrue("P diff failed", 10 >= percentageDiff(80, allBuckets.get(6).count())); + // Remove the first bucket since it's essentially unreliable since that is when the test had stopped. + allBuckets.remove(0); - Assert.assertTrue("P diff failed", 10 >= percentageDiff(120, allBuckets.get(8).count())); - Assert.assertTrue("P diff failed", 10 >= percentageDiff(120, allBuckets.get(9).count())); - Assert.assertTrue("P diff failed", 10 >= percentageDiff(120, allBuckets.get(10).count())); + for (Bucket b : allBuckets) { + System.out.print(" " + b.count()); + } + System.out.println(""); + Assert.assertTrue("P diff failed", 10 >= percentageDiff(200, allBuckets.get(0).count())); + Assert.assertTrue("P diff failed", 10 >= percentageDiff(200, allBuckets.get(1).count())); + Assert.assertTrue("P diff failed", 10 >= percentageDiff(200, allBuckets.get(2).count())); - Assert.assertTrue("P diff failed", 10 >= percentageDiff(100, allBuckets.get(12).count())); - Assert.assertTrue("P diff failed", 10 >= percentageDiff(100, allBuckets.get(13).count())); - Assert.assertTrue("P diff failed", 10 >= percentageDiff(100, allBuckets.get(14).count())); - } + Assert.assertTrue("P diff failed", 10 >= percentageDiff(80, allBuckets.get(4).count())); + Assert.assertTrue("P diff failed", 10 >= percentageDiff(80, allBuckets.get(5).count())); + Assert.assertTrue("P diff failed", 10 >= percentageDiff(80, allBuckets.get(6).count())); - private int percentageDiff(int expected, int result) { - int pDiff = expected == 0 ? 0 : Math.abs(expected-result)*100/expected; - System.out.println("Expected: " + expected + " pDiff: " + pDiff); - return pDiff; - } + Assert.assertTrue("P diff failed", 10 >= percentageDiff(120, allBuckets.get(8).count())); + Assert.assertTrue("P diff failed", 10 >= percentageDiff(120, allBuckets.get(9).count())); + Assert.assertTrue("P diff failed", 10 >= percentageDiff(120, allBuckets.get(10).count())); + + Assert.assertTrue("P diff failed", 10 >= percentageDiff(100, allBuckets.get(12).count())); + Assert.assertTrue("P diff failed", 10 >= percentageDiff(100, allBuckets.get(13).count())); + Assert.assertTrue("P diff failed", 10 >= percentageDiff(100, allBuckets.get(14).count())); + } + + private int percentageDiff(int expected, int result) { + int pDiff = expected == 0 ? 0 : Math.abs(expected - result) * 100 / expected; + System.out.println("Expected: " + expected + " pDiff: " + pDiff); + return pDiff; + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/AbstractTokenMapSupplierTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/AbstractTokenMapSupplierTest.java index d540f385..f274e067 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/AbstractTokenMapSupplierTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/AbstractTokenMapSupplierTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,16 +26,16 @@ public class AbstractTokenMapSupplierTest { - final String json = "[{\"token\":\"3051939411\",\"hostname\":\"ec2-54-237-143-4.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.237.143.4\",\"zone\":\"us-east-1d\"}\"," + - "\"{\"token\":\"188627880\",\"hostname\":\"ec2-50-17-65-2.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"50.17.65.2\",\"zone\":\"us-east-1d\"},\"" + - "\"{\"token\":\"2019187467\",\"hostname\":\"ec2-54-83-87-174.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.83.87.174\",\"zone\":\"us-east-1c\" },\"" + - "\"{\"token\":\"3450843231\",\"hostname\":\"ec2-54-81-138-73.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.81.138.73\",\"zone\":\"us-east-1c\"},\""+ - "\"{\"token\":\"587531700\",\"hostname\":\"ec2-54-82-176-215.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.82.176.215\",\"zone\":\"us-east-1c\"},\"" + - "\"{\"token\":\"3101134286\",\"hostname\":\"ec2-54-82-83-115.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.82.83.115\",\"zone\":\"us-east-1e\"},\"" + - "\"{\"token\":\"237822755\",\"hostname\":\"ec2-54-211-220-55.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.211.220.55\",\"zone\":\"us-east-1e\"},\"" + - "\"{\"token\":\"1669478519\",\"hostname\":\"ec2-54-80-65-203.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.80.65.203\",\"zone\":\"us-east-1e\"}]\""; + final String json = "[{\"token\":\"3051939411\",\"hostname\":\"ec2-54-237-143-4.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.237.143.4\",\"zone\":\"us-east-1d\"}\"," + + "\"{\"token\":\"188627880\",\"hostname\":\"ec2-50-17-65-2.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"50.17.65.2\",\"zone\":\"us-east-1d\"},\"" + + "\"{\"token\":\"2019187467\",\"hostname\":\"ec2-54-83-87-174.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.83.87.174\",\"zone\":\"us-east-1c\" },\"" + + "\"{\"token\":\"3450843231\",\"hostname\":\"ec2-54-81-138-73.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.81.138.73\",\"zone\":\"us-east-1c\"},\"" + + "\"{\"token\":\"587531700\",\"hostname\":\"ec2-54-82-176-215.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.82.176.215\",\"zone\":\"us-east-1c\"},\"" + + "\"{\"token\":\"3101134286\",\"hostname\":\"ec2-54-82-83-115.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.82.83.115\",\"zone\":\"us-east-1e\"},\"" + + "\"{\"token\":\"237822755\",\"hostname\":\"ec2-54-211-220-55.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.211.220.55\",\"zone\":\"us-east-1e\"},\"" + + "\"{\"token\":\"1669478519\",\"hostname\":\"ec2-54-80-65-203.compute-1.amazonaws.com\",\"port\":\"11211\",\"dc\":\"us-east-1\",\"ip\":\"54.80.65.203\",\"zone\":\"us-east-1e\"}]\""; - private TokenMapSupplier testTokenMapSupplier = new AbstractTokenMapSupplier() { + private TokenMapSupplier testTokenMapSupplier = new AbstractTokenMapSupplier() { @Override public String getTopologyJsonPayload(Set activeHosts) { @@ -43,32 +43,32 @@ public String getTopologyJsonPayload(Set activeHosts) { } @Override - public String getTopologyJsonPayload(String hostname) { - return json; - } - }; + public String getTopologyJsonPayload(String hostname) { + return json; + } + }; - @Test - public void testParseJson() throws Exception { + @Test + public void testParseJson() throws Exception { - List hostList = new ArrayList<>(); + List hostList = new ArrayList<>(); - hostList.add(new Host("ec2-54-237-143-4.compute-1.amazonaws.com", "rack", Status.Up)); - hostList.add(new Host("ec2-50-17-65-2.compute-1.amazonaws.com", "rack" , Status.Up)); - hostList.add(new Host("ec2-54-83-87-174.compute-1.amazonaws.com", "rack", Status.Up)); - hostList.add(new Host("ec2-54-81-138-73.compute-1.amazonaws.com", "rack", Status.Up)); - hostList.add(new Host("ec2-54-82-176-215.compute-1.amazonaws.com", "rack", Status.Up)); - hostList.add(new Host("ec2-54-82-83-115.compute-1.amazonaws.com", "rack", Status.Up)); - hostList.add(new Host("ec2-54-211-220-55.compute-1.amazonaws.com", "rack", Status.Up)); - hostList.add(new Host("ec2-54-80-65-203.compute-1.amazonaws.com", "rack", Status.Up)); + hostList.add(new Host("ec2-54-237-143-4.compute-1.amazonaws.com", "rack", Status.Up)); + hostList.add(new Host("ec2-50-17-65-2.compute-1.amazonaws.com", "rack", Status.Up)); + hostList.add(new Host("ec2-54-83-87-174.compute-1.amazonaws.com", "rack", Status.Up)); + hostList.add(new Host("ec2-54-81-138-73.compute-1.amazonaws.com", "rack", Status.Up)); + hostList.add(new Host("ec2-54-82-176-215.compute-1.amazonaws.com", "rack", Status.Up)); + hostList.add(new Host("ec2-54-82-83-115.compute-1.amazonaws.com", "rack", Status.Up)); + hostList.add(new Host("ec2-54-211-220-55.compute-1.amazonaws.com", "rack", Status.Up)); + hostList.add(new Host("ec2-54-80-65-203.compute-1.amazonaws.com", "rack", Status.Up)); - List hTokens = testTokenMapSupplier.getTokens(new HashSet<>(hostList)); - Collections.sort(hTokens, new Comparator() { - @Override - public int compare(HostToken o1, HostToken o2) { - return o1.getToken().compareTo(o2.getToken()); - } - }); + List hTokens = testTokenMapSupplier.getTokens(new HashSet<>(hostList)); + Collections.sort(hTokens, new Comparator() { + @Override + public int compare(HostToken o1, HostToken o2) { + return o1.getToken().compareTo(o2.getToken()); + } + }); Assert.assertTrue(validateHostToken(hTokens.get(0), 188627880L, "ec2-50-17-65-2.compute-1.amazonaws.com", "50.17.65.2", 11211, "us-east-1d", "us-east-1")); Assert.assertTrue(validateHostToken(hTokens.get(1), 237822755L, "ec2-54-211-220-55.compute-1.amazonaws.com", "54.211.220.55", 11211, "us-east-1e", "us-east-1")); diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/CircularListTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/CircularListTest.java index d52c9c9c..b8932f6d 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/CircularListTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/CircularListTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -41,348 +41,348 @@ public class CircularListTest { - private static final List iList = new ArrayList(); - private static final CircularList cList = new CircularList(iList); - private static final Integer size = 10; + private static final List iList = new ArrayList(); + private static final CircularList cList = new CircularList(iList); + private static final Integer size = 10; - private static ExecutorService threadPool; + private static ExecutorService threadPool; - @BeforeClass - public static void beforeClass() { - threadPool = Executors.newFixedThreadPool(5); - } + @BeforeClass + public static void beforeClass() { + threadPool = Executors.newFixedThreadPool(5); + } - @Before - public void beforeTest() { + @Before + public void beforeTest() { - iList.clear(); - for (int i=0; i> future = threadPool.submit(new Callable>() { + Future> future = threadPool.submit(new Callable>() { - @Override - public Map call() throws Exception { + @Override + public Map call() throws Exception { - TestWorker worker = new TestWorker(); + TestWorker worker = new TestWorker(); - while(!stop.get()) { - worker.process(); - } + while (!stop.get()) { + worker.process(); + } - return worker.map; - } - }); + return worker.map; + } + }); - Thread.sleep(500); + Thread.sleep(500); - List newList = new ArrayList(); - newList.addAll(iList); - for (int i=10; i<15; i++) { - newList.add(i); - } + List newList = new ArrayList(); + newList.addAll(iList); + for (int i = 10; i < 15; i++) { + newList.add(i); + } - cList.swapWithList(newList); + cList.swapWithList(newList); - Thread.sleep(100); + Thread.sleep(100); - stop.set(true); + stop.set(true); - Map result = future.get(); + Map result = future.get(); - Map subMap = CollectionUtils.filterKeys(result, new Predicate() { - @Override - public boolean apply(Integer input) { - return input != null && input < 10 ; - } - }); + Map subMap = CollectionUtils.filterKeys(result, new Predicate() { + @Override + public boolean apply(Integer input) { + return input != null && input < 10; + } + }); - List list = new ArrayList(subMap.values()); - checkValues(list); + List list = new ArrayList(subMap.values()); + checkValues(list); - subMap = CollectionUtils.difference(result, subMap).entriesOnlyOnLeft(); - list = new ArrayList(subMap.values()); - checkValues(list); - } + subMap = CollectionUtils.difference(result, subMap).entriesOnlyOnLeft(); + list = new ArrayList(subMap.values()); + checkValues(list); + } - @Test - public void testSingleThreadWithElementRemove() throws Exception { + @Test + public void testSingleThreadWithElementRemove() throws Exception { - final AtomicBoolean stop = new AtomicBoolean(false); + final AtomicBoolean stop = new AtomicBoolean(false); - Future> future = threadPool.submit(new Callable>() { + Future> future = threadPool.submit(new Callable>() { - @Override - public Map call() throws Exception { + @Override + public Map call() throws Exception { - TestWorker worker = new TestWorker(); + TestWorker worker = new TestWorker(); - while(!stop.get()) { - worker.process(); - } + while (!stop.get()) { + worker.process(); + } - return worker.map; - } - }); + return worker.map; + } + }); - Thread.sleep(200); + Thread.sleep(200); - List newList = new ArrayList(); - newList.addAll(iList); + List newList = new ArrayList(); + newList.addAll(iList); - final List removedElements = new ArrayList(); - removedElements.add(newList.remove(2)); - removedElements.add(newList.remove(5)); - removedElements.add(newList.remove(6)); + final List removedElements = new ArrayList(); + removedElements.add(newList.remove(2)); + removedElements.add(newList.remove(5)); + removedElements.add(newList.remove(6)); - cList.swapWithList(newList); + cList.swapWithList(newList); - Thread.sleep(200); - stop.set(true); + Thread.sleep(200); + stop.set(true); - Map result = future.get(); + Map result = future.get(); - Map subMap = CollectionUtils.filterKeys(result, new Predicate() { - @Override - public boolean apply(Integer input) { - return !removedElements.contains(input); - } - }); + Map subMap = CollectionUtils.filterKeys(result, new Predicate() { + @Override + public boolean apply(Integer input) { + return !removedElements.contains(input); + } + }); - checkValues(new ArrayList(subMap.values())); - } + checkValues(new ArrayList(subMap.values())); + } - @Test - public void testMultipleThreads() throws Exception { + @Test + public void testMultipleThreads() throws Exception { - final AtomicBoolean stop = new AtomicBoolean(false); - final CyclicBarrier barrier = new CyclicBarrier(5); - final List>> futures = new ArrayList>>(); + final AtomicBoolean stop = new AtomicBoolean(false); + final CyclicBarrier barrier = new CyclicBarrier(5); + final List>> futures = new ArrayList>>(); - for (int i=0; i<5; i++) { - futures.add(threadPool.submit(new Callable>() { + for (int i = 0; i < 5; i++) { + futures.add(threadPool.submit(new Callable>() { - @Override - public Map call() throws Exception { + @Override + public Map call() throws Exception { - barrier.await(); + barrier.await(); - TestWorker worker = new TestWorker(); + TestWorker worker = new TestWorker(); - while (!stop.get()) { - worker.process(); - } + while (!stop.get()) { + worker.process(); + } - return worker.map; - } - })); - } + return worker.map; + } + })); + } - Thread.sleep(200); - stop.set(true); + Thread.sleep(200); + stop.set(true); - Map totalMap = getTotalMap(futures); - checkValues(new ArrayList(totalMap.values())); - } + Map totalMap = getTotalMap(futures); + checkValues(new ArrayList(totalMap.values())); + } - @Test - public void testMultipleThreadsWithElementAdd() throws Exception { + @Test + public void testMultipleThreadsWithElementAdd() throws Exception { - final AtomicBoolean stop = new AtomicBoolean(false); - final CyclicBarrier barrier = new CyclicBarrier(5); - final List>> futures = new ArrayList>>(); + final AtomicBoolean stop = new AtomicBoolean(false); + final CyclicBarrier barrier = new CyclicBarrier(5); + final List>> futures = new ArrayList>>(); - for (int i=0; i<5; i++) { - futures.add(threadPool.submit(new Callable>() { + for (int i = 0; i < 5; i++) { + futures.add(threadPool.submit(new Callable>() { - @Override - public Map call() throws Exception { + @Override + public Map call() throws Exception { - barrier.await(); + barrier.await(); - TestWorker worker = new TestWorker(); + TestWorker worker = new TestWorker(); - while (!stop.get()) { - worker.process(); - } + while (!stop.get()) { + worker.process(); + } - return worker.map; - } - })); - } + return worker.map; + } + })); + } - Thread.sleep(200); + Thread.sleep(200); - List newList = new ArrayList(iList); - for (int i=10; i<15; i++) { - newList.add(i); - } + List newList = new ArrayList(iList); + for (int i = 10; i < 15; i++) { + newList.add(i); + } - cList.swapWithList(newList); + cList.swapWithList(newList); - Thread.sleep(200); - stop.set(true); + Thread.sleep(200); + stop.set(true); - Map result = getTotalMap(futures); + Map result = getTotalMap(futures); - Map subMap = CollectionUtils.filterKeys(result, new Predicate() { - @Override - public boolean apply(Integer input) { - return input < 10; - } - }); + Map subMap = CollectionUtils.filterKeys(result, new Predicate() { + @Override + public boolean apply(Integer input) { + return input < 10; + } + }); - checkValues(new ArrayList(subMap.values())); + checkValues(new ArrayList(subMap.values())); - subMap = CollectionUtils.difference(result, subMap).entriesOnlyOnLeft(); - checkValues(new ArrayList(subMap.values())); - } + subMap = CollectionUtils.difference(result, subMap).entriesOnlyOnLeft(); + checkValues(new ArrayList(subMap.values())); + } - @Test - public void testMultipleThreadsWithElementsRemoved() throws Exception { + @Test + public void testMultipleThreadsWithElementsRemoved() throws Exception { - final AtomicBoolean stop = new AtomicBoolean(false); - final CyclicBarrier barrier = new CyclicBarrier(5); - final List>> futures = new ArrayList>>(); + final AtomicBoolean stop = new AtomicBoolean(false); + final CyclicBarrier barrier = new CyclicBarrier(5); + final List>> futures = new ArrayList>>(); - for (int i=0; i<5; i++) { - futures.add(threadPool.submit(new Callable>() { + for (int i = 0; i < 5; i++) { + futures.add(threadPool.submit(new Callable>() { - @Override - public Map call() throws Exception { + @Override + public Map call() throws Exception { - barrier.await(); + barrier.await(); - TestWorker worker = new TestWorker(); + TestWorker worker = new TestWorker(); - while (!stop.get()) { - worker.process(); - } + while (!stop.get()) { + worker.process(); + } - return worker.map; - } - })); - } + return worker.map; + } + })); + } - Thread.sleep(200); + Thread.sleep(200); - List newList = new ArrayList(iList); + List newList = new ArrayList(iList); - final List removedElements = new ArrayList(); - removedElements.add(newList.remove(2)); - removedElements.add(newList.remove(5)); - removedElements.add(newList.remove(6)); + final List removedElements = new ArrayList(); + removedElements.add(newList.remove(2)); + removedElements.add(newList.remove(5)); + removedElements.add(newList.remove(6)); - cList.swapWithList(newList); + cList.swapWithList(newList); - Thread.sleep(200); - stop.set(true); + Thread.sleep(200); + stop.set(true); - Map result = getTotalMap(futures); + Map result = getTotalMap(futures); - Map subMap = CollectionUtils.filterKeys(result, new Predicate() { + Map subMap = CollectionUtils.filterKeys(result, new Predicate() { - @Override - public boolean apply(Integer x) { - return !removedElements.contains(x); - } - }); + @Override + public boolean apply(Integer x) { + return !removedElements.contains(x); + } + }); - checkValues(new ArrayList(subMap.values())); - } + checkValues(new ArrayList(subMap.values())); + } - @Test - public void testCircularListGet() { - // integer overflow on read index should not result in exception - for (long i = 0; i < (long) Integer.MAX_VALUE + 10; i++) { - cList.getNextElement(); - } - } + @Test + public void testCircularListGet() { + // integer overflow on read index should not result in exception + for (long i = 0; i < (long) Integer.MAX_VALUE + 10; i++) { + cList.getNextElement(); + } + } - private class TestWorker { + private class TestWorker { - private final ConcurrentHashMap map = new ConcurrentHashMap(); + private final ConcurrentHashMap map = new ConcurrentHashMap(); - private void process() { + private void process() { - Integer element = cList.getNextElement(); - Integer count = map.get(element); - if (count == null) { - map.put(element, 1); - } else { - map.put(element, count+1); - } - } - } + Integer element = cList.getNextElement(); + Integer count = map.get(element); + if (count == null) { + map.put(element, 1); + } else { + map.put(element, count + 1); + } + } + } - private static Map getTotalMap(List>> futures) throws InterruptedException, ExecutionException { + private static Map getTotalMap(List>> futures) throws InterruptedException, ExecutionException { - Map totalMap = new HashMap(); + Map totalMap = new HashMap(); - for (Future> f : futures) { + for (Future> f : futures) { - Map map = f.get(); + Map map = f.get(); - for (Integer element : map.keySet()) { - Integer count = totalMap.get(element); - if (count == null) { - totalMap.put(element, map.get(element)); - } else { - totalMap.put(element, map.get(element) + count); - } - } - } - return totalMap; - } + for (Integer element : map.keySet()) { + Integer count = totalMap.get(element); + if (count == null) { + totalMap.put(element, map.get(element)); + } else { + totalMap.put(element, map.get(element) + count); + } + } + } + return totalMap; + } - private static double checkValues(List values) { + private static double checkValues(List values) { - System.out.println("Values: " + values); - SummaryStatistics ss = new SummaryStatistics(); - for (int i=0; i * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -54,194 +54,194 @@ public class HostSelectionWithFallbackTest { - private Map poolStatus = new HashMap(); + private Map poolStatus = new HashMap(); - private BaseOperation testOperation = new BaseOperation() { + private BaseOperation testOperation = new BaseOperation() { - @Override - public String getName() { - return "test"; - } + @Override + public String getName() { + return "test"; + } - @Override - public String getStringKey() { - return "11"; - } + @Override + public String getStringKey() { + return "11"; + } - @Override - public byte[] getBinaryKey() { - return null; - } - }; - - private final ConnectionPoolConfigurationImpl cpConfig = new ConnectionPoolConfigurationImpl("test"); - private final ConnectionPoolMonitor cpMonitor = new CountingConnectionPoolMonitor(); + @Override + public byte[] getBinaryKey() { + return null; + } + }; - String dc = "us-east-1"; - String rack1 = "us-east-1c"; - String rack2 = "us-east-1d"; - String rack3 = "us-east-1e"; + private final ConnectionPoolConfigurationImpl cpConfig = new ConnectionPoolConfigurationImpl("test"); + private final ConnectionPoolMonitor cpMonitor = new CountingConnectionPoolMonitor(); - Host h1 = new Host("h1", rack1, Status.Up); - Host h2 = new Host("h2", rack1, Status.Up); - Host h3 = new Host("h3", "remoteRack1", Status.Up); - Host h4 = new Host("h4", "remoteRack1", Status.Up); - Host h5 = new Host("h5", "remoteRack2", Status.Up); - Host h6 = new Host("h6", "remoteRack2", Status.Up); + String dc = "us-east-1"; + String rack1 = "us-east-1c"; + String rack2 = "us-east-1d"; + String rack3 = "us-east-1e"; - Host[] arr = {h1, h2, h3, h4, h5, h6}; - List hosts = Arrays.asList(arr); + Host h1 = new Host("h1", rack1, Status.Up); + Host h2 = new Host("h2", rack1, Status.Up); + Host h3 = new Host("h3", "remoteRack1", Status.Up); + Host h4 = new Host("h4", "remoteRack1", Status.Up); + Host h5 = new Host("h5", "remoteRack2", Status.Up); + Host h6 = new Host("h6", "remoteRack2", Status.Up); - @Before - public void beforeTest() { - cpConfig.setLocalRack(rack1); - cpConfig.setLocalDataCenter(dc); - cpConfig.setLoadBalancingStrategy(LoadBalancingStrategy.RoundRobin); - cpConfig.withTokenSupplier(getTokenMapSupplier()); - } + Host[] arr = {h1, h2, h3, h4, h5, h6}; + List hosts = Arrays.asList(arr); - @Test - public void testFallbackToRemotePoolWhenPoolInactive() throws Exception { + @Before + public void beforeTest() { + cpConfig.setLocalRack(rack1); + cpConfig.setLocalDataCenter(dc); + cpConfig.setLoadBalancingStrategy(LoadBalancingStrategy.RoundRobin); + cpConfig.withTokenSupplier(getTokenMapSupplier()); + } - HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); + @Test + public void testFallbackToRemotePoolWhenPoolInactive() throws Exception { - Map> pools = new HashMap>(); + HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); - for (Host host : hosts) { - poolStatus.put(host, new AtomicBoolean(true)); - pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); - } + Map> pools = new HashMap>(); - selection.initWithHosts(pools); + for (Host host : hosts) { + poolStatus.put(host, new AtomicBoolean(true)); + pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); + } - Set hostnames = new HashSet(); + selection.initWithHosts(pools); - for (int i=0; i<10; i++) { - Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); - hostnames.add(conn.getHost().getHostAddress()); - } + Set hostnames = new HashSet(); - verifyExactly(hostnames, "h1", "h2"); + for (int i = 0; i < 10; i++) { + Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); + hostnames.add(conn.getHost().getHostAddress()); + } - // Now mark h1 and h2 both as "DOWN" - poolStatus.get(h1).set(false); - poolStatus.get(h2).set(false); - hostnames.clear(); + verifyExactly(hostnames, "h1", "h2"); - for (int i=0; i<10; i++) { - Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); - hostnames.add(conn.getHost().getHostAddress()); - } + // Now mark h1 and h2 both as "DOWN" + poolStatus.get(h1).set(false); + poolStatus.get(h2).set(false); + hostnames.clear(); - verifyExactly(hostnames, "h3", "h4", "h5", "h6"); + for (int i = 0; i < 10; i++) { + Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); + hostnames.add(conn.getHost().getHostAddress()); + } - // Now bring h1 back up - poolStatus.get(h1).set(true); - hostnames.clear(); + verifyExactly(hostnames, "h3", "h4", "h5", "h6"); - for (int i=0; i<10; i++) { - Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); - hostnames.add(conn.getHost().getHostAddress()); - } + // Now bring h1 back up + poolStatus.get(h1).set(true); + hostnames.clear(); - verifyExactly(hostnames, "h1"); + for (int i = 0; i < 10; i++) { + Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); + hostnames.add(conn.getHost().getHostAddress()); + } - // Now bring h2 back up - poolStatus.get(h2).set(true); - hostnames.clear(); - for (int i=0; i<10; i++) { - Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); - hostnames.add(conn.getHost().getHostAddress()); - } + verifyExactly(hostnames, "h1"); - verifyExactly(hostnames, "h1", "h2"); - } + // Now bring h2 back up + poolStatus.get(h2).set(true); + hostnames.clear(); + for (int i = 0; i < 10; i++) { + Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); + hostnames.add(conn.getHost().getHostAddress()); + } - @Test - public void testFallbackToRemotePoolWhenHostDown() throws Exception { + verifyExactly(hostnames, "h1", "h2"); + } - HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); + @Test + public void testFallbackToRemotePoolWhenHostDown() throws Exception { - Map> pools = new HashMap>(); + HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); - for (Host host : hosts) { - poolStatus.put(host, new AtomicBoolean(true)); - pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); - } + Map> pools = new HashMap>(); - selection.initWithHosts(pools); + for (Host host : hosts) { + poolStatus.put(host, new AtomicBoolean(true)); + pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); + } + + selection.initWithHosts(pools); - Set hostnames = new HashSet(); + Set hostnames = new HashSet(); - for (int i=0; i<10; i++) { - Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); - hostnames.add(conn.getHost().getHostAddress()); - } + for (int i = 0; i < 10; i++) { + Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); + hostnames.add(conn.getHost().getHostAddress()); + } - verifyExactly(hostnames, "h1", "h2"); + verifyExactly(hostnames, "h1", "h2"); - // Now mark h1 and h2 both as "DOWN" - h1.setStatus(Status.Down); - h2.setStatus(Status.Down); - hostnames.clear(); + // Now mark h1 and h2 both as "DOWN" + h1.setStatus(Status.Down); + h2.setStatus(Status.Down); + hostnames.clear(); - for (int i=0; i<10; i++) { - Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); - hostnames.add(conn.getHost().getHostAddress()); - } + for (int i = 0; i < 10; i++) { + Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); + hostnames.add(conn.getHost().getHostAddress()); + } - verifyExactly(hostnames, "h3", "h4", "h5", "h6"); + verifyExactly(hostnames, "h3", "h4", "h5", "h6"); - // Now bring h1 back up - h1.setStatus(Status.Up); - hostnames.clear(); + // Now bring h1 back up + h1.setStatus(Status.Up); + hostnames.clear(); - for (int i=0; i<10; i++) { - Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); - hostnames.add(conn.getHost().getHostAddress()); - } + for (int i = 0; i < 10; i++) { + Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); + hostnames.add(conn.getHost().getHostAddress()); + } - System.out.println(" " + hostnames); - verifyExactly(hostnames, "h1"); + System.out.println(" " + hostnames); + verifyExactly(hostnames, "h1"); - // Now bring h2 back up - h2.setStatus(Status.Up); - hostnames.clear(); - for (int i=0; i<10; i++) { - Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); - hostnames.add(conn.getHost().getHostAddress()); - } + // Now bring h2 back up + h2.setStatus(Status.Up); + hostnames.clear(); + for (int i = 0; i < 10; i++) { + Connection conn = selection.getConnection(testOperation, 1, TimeUnit.MILLISECONDS); + hostnames.add(conn.getHost().getHostAddress()); + } - verifyExactly(hostnames, "h1", "h2"); + verifyExactly(hostnames, "h1", "h2"); // Verify that failover metric has increased Assert.assertTrue(cpMonitor.getFailoverCount() > 0); - } + } - @Test - public void testCrossRackFallback() throws Exception { + @Test + public void testCrossRackFallback() throws Exception { - HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); + HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); RetryPolicy retry = new RetryNTimes(3, true); - Map> pools = new HashMap>(); + Map> pools = new HashMap>(); - for (Host host : hosts) { - poolStatus.put(host, new AtomicBoolean(true)); - pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); - } + for (Host host : hosts) { + poolStatus.put(host, new AtomicBoolean(true)); + pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); + } - selection.initWithHosts(pools); + selection.initWithHosts(pools); - Set hostnames = new HashSet(); + Set hostnames = new HashSet(); - for (int i = 0; i < 10; i++) { - Connection conn = selection.getConnectionUsingRetryPolicy(testOperation, 1, TimeUnit.MILLISECONDS, + for (int i = 0; i < 10; i++) { + Connection conn = selection.getConnectionUsingRetryPolicy(testOperation, 1, TimeUnit.MILLISECONDS, retry); - hostnames.add(conn.getHost().getHostAddress()); - } + hostnames.add(conn.getHost().getHostAddress()); + } - verifyExactly(hostnames, "h1", "h2"); + verifyExactly(hostnames, "h1", "h2"); // Record a failure so that retry attempt is not 0 and get another connection retry.failure(new Exception("Unit Test Retry Exception")); @@ -250,147 +250,147 @@ public void testCrossRackFallback() throws Exception { String fallbackHost = conn.getHost().getHostAddress(); Assert.assertTrue(!fallbackHost.equals("h1") && !fallbackHost.equals("h2")); - } + } - @Test - public void testGetConnectionsFromRingNormal() throws Exception { + @Test + public void testGetConnectionsFromRingNormal() throws Exception { - HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); + HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); - Map> pools = new HashMap>(); + Map> pools = new HashMap>(); - for (Host host : hosts) { - poolStatus.put(host, new AtomicBoolean(true)); - pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); - } + for (Host host : hosts) { + poolStatus.put(host, new AtomicBoolean(true)); + pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); + } - selection.initWithHosts(pools); + selection.initWithHosts(pools); - Collection hostnames = runConnectionsToRingTest(selection); - verifyExactly(hostnames, "h1", "h2"); - } + Collection hostnames = runConnectionsToRingTest(selection); + verifyExactly(hostnames, "h1", "h2"); + } - @Test - public void testGetConnectionsFromRingWhenPrimaryHostPoolInactive() throws Exception { + @Test + public void testGetConnectionsFromRingWhenPrimaryHostPoolInactive() throws Exception { - HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); + HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); - Map> pools = new HashMap>(); + Map> pools = new HashMap>(); - for (Host host : hosts) { - poolStatus.put(host, new AtomicBoolean(true)); - pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); - } + for (Host host : hosts) { + poolStatus.put(host, new AtomicBoolean(true)); + pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); + } - selection.initWithHosts(pools); + selection.initWithHosts(pools); - // Put Host H1 as DOWN - poolStatus.get(h1).set(false); + // Put Host H1 as DOWN + poolStatus.get(h1).set(false); - Collection hostnames = runConnectionsToRingTest(selection); - verifyPresent(hostnames, "h2"); - verifyAtLeastOnePresent(hostnames, "h3", "h5"); + Collection hostnames = runConnectionsToRingTest(selection); + verifyPresent(hostnames, "h2"); + verifyAtLeastOnePresent(hostnames, "h3", "h5"); - // Put Host H2 as DOWN - selection.initWithHosts(pools); - poolStatus.get(h1).set(true); - poolStatus.get(h2).set(false); + // Put Host H2 as DOWN + selection.initWithHosts(pools); + poolStatus.get(h1).set(true); + poolStatus.get(h2).set(false); - hostnames = runConnectionsToRingTest(selection); + hostnames = runConnectionsToRingTest(selection); - verifyPresent(hostnames, "h1"); - verifyAtLeastOnePresent(hostnames, "h4", "h6"); + verifyPresent(hostnames, "h1"); + verifyAtLeastOnePresent(hostnames, "h4", "h6"); - // Put Hosts H1 and H2 as DOWN - selection.initWithHosts(pools); - poolStatus.get(h1).set(false); - poolStatus.get(h2).set(false); + // Put Hosts H1 and H2 as DOWN + selection.initWithHosts(pools); + poolStatus.get(h1).set(false); + poolStatus.get(h2).set(false); - hostnames = runConnectionsToRingTest(selection); - verifyAtLeastOnePresent(hostnames, "h3", "h5"); - verifyAtLeastOnePresent(hostnames, "h4", "h6"); + hostnames = runConnectionsToRingTest(selection); + verifyAtLeastOnePresent(hostnames, "h3", "h5"); + verifyAtLeastOnePresent(hostnames, "h4", "h6"); - // Put Hosts H1,H2,H3 as DOWN - selection.initWithHosts(pools); - poolStatus.get(h1).set(false); - poolStatus.get(h2).set(false); - poolStatus.get(h3).set(false); + // Put Hosts H1,H2,H3 as DOWN + selection.initWithHosts(pools); + poolStatus.get(h1).set(false); + poolStatus.get(h2).set(false); + poolStatus.get(h3).set(false); - hostnames = runConnectionsToRingTest(selection); + hostnames = runConnectionsToRingTest(selection); verifyAtLeastOnePresent(hostnames, "h4", "h6"); - verifyPresent(hostnames, "h5"); + verifyPresent(hostnames, "h5"); - // Put Hosts H1,H2,H3,H4 as DOWN - selection.initWithHosts(pools); - poolStatus.get(h1).set(false); - poolStatus.get(h2).set(false); - poolStatus.get(h3).set(false); - poolStatus.get(h4).set(false); + // Put Hosts H1,H2,H3,H4 as DOWN + selection.initWithHosts(pools); + poolStatus.get(h1).set(false); + poolStatus.get(h2).set(false); + poolStatus.get(h3).set(false); + poolStatus.get(h4).set(false); - hostnames = runConnectionsToRingTest(selection); - verifyExactly(hostnames, "h5", "h6"); - } + hostnames = runConnectionsToRingTest(selection); + verifyExactly(hostnames, "h5", "h6"); + } - @Test - public void testGetConnectionsFromRingWhenHostDown() throws Exception { + @Test + public void testGetConnectionsFromRingWhenHostDown() throws Exception { - HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); + HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); - Map> pools = new HashMap>(); + Map> pools = new HashMap>(); - for (Host host : hosts) { - poolStatus.put(host, new AtomicBoolean(true)); - pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); - } + for (Host host : hosts) { + poolStatus.put(host, new AtomicBoolean(true)); + pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); + } - selection.initWithHosts(pools); + selection.initWithHosts(pools); - // Put Host H1 as DOWN - h1.setStatus(Status.Down); + // Put Host H1 as DOWN + h1.setStatus(Status.Down); - Collection hostnames = runConnectionsToRingTest(selection); - verifyPresent(hostnames, "h2"); - verifyAtLeastOnePresent(hostnames, "h3", "h5"); + Collection hostnames = runConnectionsToRingTest(selection); + verifyPresent(hostnames, "h2"); + verifyAtLeastOnePresent(hostnames, "h3", "h5"); - // Put Host H2 as DOWN - selection.initWithHosts(pools); - h1.setStatus(Status.Up); - h2.setStatus(Status.Down); + // Put Host H2 as DOWN + selection.initWithHosts(pools); + h1.setStatus(Status.Up); + h2.setStatus(Status.Down); - hostnames = runConnectionsToRingTest(selection); + hostnames = runConnectionsToRingTest(selection); - verifyPresent(hostnames, "h1"); - verifyAtLeastOnePresent(hostnames, "h4", "h6"); + verifyPresent(hostnames, "h1"); + verifyAtLeastOnePresent(hostnames, "h4", "h6"); - // Put Hosts H1 and H2 as DOWN - selection.initWithHosts(pools); - h1.setStatus(Status.Down); - h2.setStatus(Status.Down); + // Put Hosts H1 and H2 as DOWN + selection.initWithHosts(pools); + h1.setStatus(Status.Down); + h2.setStatus(Status.Down); - hostnames = runConnectionsToRingTest(selection); - verifyAtLeastOnePresent(hostnames, "h3", "h5"); - verifyAtLeastOnePresent(hostnames, "h4", "h6"); + hostnames = runConnectionsToRingTest(selection); + verifyAtLeastOnePresent(hostnames, "h3", "h5"); + verifyAtLeastOnePresent(hostnames, "h4", "h6"); - // Put Hosts H1,H2,H3 as DOWN - selection.initWithHosts(pools); - h1.setStatus(Status.Down); - h2.setStatus(Status.Down); - h3.setStatus(Status.Down); + // Put Hosts H1,H2,H3 as DOWN + selection.initWithHosts(pools); + h1.setStatus(Status.Down); + h2.setStatus(Status.Down); + h3.setStatus(Status.Down); - hostnames = runConnectionsToRingTest(selection); + hostnames = runConnectionsToRingTest(selection); verifyAtLeastOnePresent(hostnames, "h4", "h6"); verifyPresent(hostnames, "h5"); - // Put Hosts H1,H2,H3,H4 as DOWN - selection.initWithHosts(pools); - h1.setStatus(Status.Down); - h2.setStatus(Status.Down); - h3.setStatus(Status.Down); - h4.setStatus(Status.Down); + // Put Hosts H1,H2,H3,H4 as DOWN + selection.initWithHosts(pools); + h1.setStatus(Status.Down); + h2.setStatus(Status.Down); + h3.setStatus(Status.Down); + h4.setStatus(Status.Down); - hostnames = runConnectionsToRingTest(selection); - verifyExactly(hostnames, "h5", "h6"); - } + hostnames = runConnectionsToRingTest(selection); + verifyExactly(hostnames, "h5", "h6"); + } @Test public void testReplicationFactorOf3WithDupes() { @@ -402,7 +402,7 @@ public void testReplicationFactorOf3WithDupes() { List hostTokens = Arrays.asList( new HostToken(1383429731L, new Host("host-1", -1, rack1)), // Use -1 otherwise the port is opened which works new HostToken(2815085496L, new Host("host-2", -1, rack1)), - new HostToken(4246741261L, new Host("host-3", -1, rack1 )), + new HostToken(4246741261L, new Host("host-3", -1, rack1)), new HostToken(1383429731L, new Host("host-4", -1, rack1)), new HostToken(2815085496L, new Host("host-5", -1, rack1)), new HostToken(4246741261L, new Host("host-6", -1, rack1)), @@ -423,13 +423,13 @@ public void testReplicationFactorOf3WithDupes() { Assert.assertEquals(3, rf); } - @Test + @Test public void testReplicationFactorOf3() { cpConfig.setLocalRack("us-east-1c"); - cpConfig.setLoadBalancingStrategy(LoadBalancingStrategy.TokenAware); - cpConfig.withTokenSupplier(getTokenMapSupplier()); + cpConfig.setLoadBalancingStrategy(LoadBalancingStrategy.TokenAware); + cpConfig.withTokenSupplier(getTokenMapSupplier()); - HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); + HostSelectionWithFallback selection = new HostSelectionWithFallback(cpConfig, cpMonitor); List hostTokens = Arrays.asList( new HostToken(1111L, new Host("host-1", -1, rack1)), @@ -440,10 +440,10 @@ public void testReplicationFactorOf3() { new HostToken(2222L, new Host("host-6", -1, rack1)) ); - int rf = selection.calculateReplicationFactor(hostTokens); + int rf = selection.calculateReplicationFactor(hostTokens); Assert.assertEquals(3, rf); - } + } @Test public void testReplicationFactorOf2() { @@ -503,7 +503,7 @@ public void testIllegalReplicationFactor() { } @Test - public void testReplicationFactorForMultiRegionCluster() { + public void testReplicationFactorForMultiRegionCluster() { cpConfig.setLocalRack("us-east-1d"); cpConfig.setLoadBalancingStrategy(LoadBalancingStrategy.TokenAware); cpConfig.withTokenSupplier(getTokenMapSupplier()); @@ -536,8 +536,8 @@ public void testReplicationFactorForMultiRegionCluster() { int rf = selection.calculateReplicationFactor(hostTokens); Assert.assertEquals(3, rf); - } - + } + @Test public void testChangingHashPartitioner() { cpConfig.setLoadBalancingStrategy(LoadBalancingStrategy.TokenAware); @@ -552,111 +552,115 @@ public void testChangingHashPartitioner() { pools.put(host, getMockHostConnectionPool(host, poolStatus.get(host))); } - selection.initWithHosts(pools); + selection.initWithHosts(pools); Connection connection = selection.getConnection(testOperation, 10, TimeUnit.MILLISECONDS); // Verify that h1 has been selected instead of h2 assertEquals("h1", connection.getHost().getHostAddress()); - } + } - private Collection runConnectionsToRingTest(HostSelectionWithFallback selection) { + private Collection runConnectionsToRingTest(HostSelectionWithFallback selection) { - Collection> connections = selection.getConnectionsToRing( null, 10, TimeUnit.MILLISECONDS); + Collection> connections = selection.getConnectionsToRing(null, 10, TimeUnit.MILLISECONDS); - return CollectionUtils.transform(connections, new Transform, String>() { - @Override - public String get(Connection x) { - return x.getHost().getHostAddress(); - } - }); + return CollectionUtils.transform(connections, new Transform, String>() { + @Override + public String get(Connection x) { + return x.getHost().getHostAddress(); + } + }); - } + } - private void verifyExactly(Collection resultCollection, String ... hostnames) { + private void verifyExactly(Collection resultCollection, String... hostnames) { - Set result = new HashSet(resultCollection); - Set all = new HashSet(); - all.add("h1"); all.add("h2"); all.add("h3"); - all.add("h4"); all.add("h5"); all.add("h6"); + Set result = new HashSet(resultCollection); + Set all = new HashSet(); + all.add("h1"); + all.add("h2"); + all.add("h3"); + all.add("h4"); + all.add("h5"); + all.add("h6"); - Set expected = new HashSet(Arrays.asList(hostnames)); - Set notExpected = new HashSet(all); - notExpected.removeAll(expected); + Set expected = new HashSet(Arrays.asList(hostnames)); + Set notExpected = new HashSet(all); + notExpected.removeAll(expected); - for (String e : expected) { - Assert.assertTrue("Result: " + result + ", expected: " + e, result.contains(e)); - } - for (String ne : notExpected) { - Assert.assertFalse("Result: " + result, result.contains(ne)); - } - } + for (String e : expected) { + Assert.assertTrue("Result: " + result + ", expected: " + e, result.contains(e)); + } + for (String ne : notExpected) { + Assert.assertFalse("Result: " + result, result.contains(ne)); + } + } - private void verifyPresent(Collection resultCollection, String ... hostnames) { + private void verifyPresent(Collection resultCollection, String... hostnames) { - Set result = new HashSet(resultCollection); - for (String h : hostnames) { - Assert.assertTrue("Result: " + result + ", expected: " + h, result.contains(h)); - } - } + Set result = new HashSet(resultCollection); + for (String h : hostnames) { + Assert.assertTrue("Result: " + result + ", expected: " + h, result.contains(h)); + } + } - private void verifyAtLeastOnePresent(Collection resultCollection, String ... hostnames) { + private void verifyAtLeastOnePresent(Collection resultCollection, String... hostnames) { - Set result = new HashSet(resultCollection); - boolean present = false; - for (String h : hostnames) { - if (result.contains(h)) { - present = true; - break; - } - } - Assert.assertTrue("Result: " + result + ", expected at least one of: " + hostnames, present); - } + Set result = new HashSet(resultCollection); + boolean present = false; + for (String h : hostnames) { + if (result.contains(h)) { + present = true; + break; + } + } + Assert.assertTrue("Result: " + result + ", expected at least one of: " + hostnames, present); + } - @SuppressWarnings("unchecked") - private HostConnectionPool getMockHostConnectionPool(final Host host, final AtomicBoolean status) { + @SuppressWarnings("unchecked") + private HostConnectionPool getMockHostConnectionPool(final Host host, final AtomicBoolean status) { - Connection mockConnection = mock(Connection.class); - when(mockConnection.getHost()).thenReturn(host); + Connection mockConnection = mock(Connection.class); + when(mockConnection.getHost()).thenReturn(host); - HostConnectionPool mockPool = mock(HostConnectionPool.class); - when(mockPool.isActive()).thenAnswer(new Answer() { + HostConnectionPool mockPool = mock(HostConnectionPool.class); + when(mockPool.isActive()).thenAnswer(new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return status.get(); - } + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + return status.get(); + } - }); - when(mockPool.borrowConnection(any(Integer.class), any(TimeUnit.class))).thenReturn(mockConnection); - when(mockPool.getHost()).thenReturn(host); + }); + when(mockPool.borrowConnection(any(Integer.class), any(TimeUnit.class))).thenReturn(mockConnection); + when(mockPool.getHost()).thenReturn(host); - when(mockConnection.getParentConnectionPool()).thenReturn(mockPool); + when(mockConnection.getParentConnectionPool()).thenReturn(mockPool); - return mockPool; - } + return mockPool; + } - /** - cqlsh:dyno_bootstrap> select "availabilityZone","hostname","token" from tokens where "appId" = 'dynomite_redis_puneet'; + /** + cqlsh:dyno_bootstrap> select "availabilityZone","hostname","token" from tokens where "appId" = 'dynomite_redis_puneet'; - availabilityZone | hostname | token - ------------------+--------------------------------------------+------------ - us-east-1c | ec2-54-83-179-213.compute-1.amazonaws.com | 1383429731 - us-east-1c | ec2-54-224-184-99.compute-1.amazonaws.com | 309687905 - us-east-1c | ec2-54-91-190-159.compute-1.amazonaws.com | 3530913377 - us-east-1c | ec2-54-81-31-218.compute-1.amazonaws.com | 2457171554 - us-east-1e | ec2-54-198-222-153.compute-1.amazonaws.com | 309687905 - us-east-1e | ec2-54-198-239-231.compute-1.amazonaws.com | 2457171554 - us-east-1e | ec2-54-226-212-40.compute-1.amazonaws.com | 1383429731 - us-east-1e | ec2-54-197-178-229.compute-1.amazonaws.com | 3530913377 + availabilityZone | hostname | token + ------------------+--------------------------------------------+------------ + us-east-1c | ec2-54-83-179-213.compute-1.amazonaws.com | 1383429731 + us-east-1c | ec2-54-224-184-99.compute-1.amazonaws.com | 309687905 + us-east-1c | ec2-54-91-190-159.compute-1.amazonaws.com | 3530913377 + us-east-1c | ec2-54-81-31-218.compute-1.amazonaws.com | 2457171554 + us-east-1e | ec2-54-198-222-153.compute-1.amazonaws.com | 309687905 + us-east-1e | ec2-54-198-239-231.compute-1.amazonaws.com | 2457171554 + us-east-1e | ec2-54-226-212-40.compute-1.amazonaws.com | 1383429731 + us-east-1e | ec2-54-197-178-229.compute-1.amazonaws.com | 3530913377 - cqlsh:dyno_bootstrap> - */ + cqlsh:dyno_bootstrap> + */ - private TokenMapSupplier getTokenMapSupplier() { + private TokenMapSupplier getTokenMapSupplier() { - final Map tokenMap = new HashMap(); + final Map tokenMap = new HashMap(); tokenMap.put(h1, new HostToken(1383429731L, h1)); tokenMap.put(h2, new HostToken(3530913377L, h2)); @@ -665,49 +669,49 @@ private TokenMapSupplier getTokenMapSupplier() { tokenMap.put(h5, new HostToken(1383429731L, h5)); tokenMap.put(h6, new HostToken(3530913377L, h6)); - return new TokenMapSupplier () { + return new TokenMapSupplier() { @Override - public List getTokens(Set activeHosts) { - return new ArrayList(tokenMap.values()); - } - - @Override - public HostToken getTokenForHost(Host host, Set activeHosts) { - return tokenMap.get(host); - } - - }; - } - - private HashPartitioner getMockHashPartitioner(final Long hash) { - return new HashPartitioner() { - @Override - public Long hash(int key) { - return hash; - } - - @Override - public Long hash(long key) { - return hash; - } - - @Override - public Long hash(String key) { - return hash; - } - - @Override - public Long hash(byte[] key) { - return hash; - } - - @Override - public HostToken getToken(Long keyHash) { - throw new RuntimeException("NotImplemented"); - } - - - }; - } + public List getTokens(Set activeHosts) { + return new ArrayList(tokenMap.values()); + } + + @Override + public HostToken getTokenForHost(Host host, Set activeHosts) { + return tokenMap.get(host); + } + + }; + } + + private HashPartitioner getMockHashPartitioner(final Long hash) { + return new HashPartitioner() { + @Override + public Long hash(int key) { + return hash; + } + + @Override + public Long hash(long key) { + return hash; + } + + @Override + public Long hash(String key) { + return hash; + } + + @Override + public Long hash(byte[] key) { + return hash; + } + + @Override + public HostToken getToken(Long keyHash) { + throw new RuntimeException("NotImplemented"); + } + + + }; + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/HostTokenTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/HostTokenTest.java index 48579941..1db4ffc2 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/HostTokenTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/HostTokenTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,52 +27,52 @@ public class HostTokenTest { - @Test - public void testEquals() throws Exception { + @Test + public void testEquals() throws Exception { - HostToken t1 = new HostToken(1L, new Host("foo", 1234, "foo_rack")); - HostToken t2 = new HostToken(1L, new Host("foo", 1234, "foo_rack")); + HostToken t1 = new HostToken(1L, new Host("foo", 1234, "foo_rack")); + HostToken t2 = new HostToken(1L, new Host("foo", 1234, "foo_rack")); - Assert.assertEquals(t1, t2); + Assert.assertEquals(t1, t2); - // change token - HostToken t3 = new HostToken(2L, new Host("foo", 1234, "foo_rack")); - Assert.assertFalse(t1.equals(t3)); + // change token + HostToken t3 = new HostToken(2L, new Host("foo", 1234, "foo_rack")); + Assert.assertFalse(t1.equals(t3)); - // change host name - HostToken t4 = new HostToken(1L, new Host("foo1", 1234, "foo_rack")); - Assert.assertFalse(t1.equals(t4)); - } + // change host name + HostToken t4 = new HostToken(1L, new Host("foo1", 1234, "foo_rack")); + Assert.assertFalse(t1.equals(t4)); + } - @Test - public void testSort() throws Exception { + @Test + public void testSort() throws Exception { - HostToken t1 = new HostToken(1L, new Host("foo1", 1234, "foo_rack")); - HostToken t2 = new HostToken(2L, new Host("foo2", 1234, "foo_rack")); - HostToken t3 = new HostToken(3L, new Host("foo3", 1234, "foo_rack")); - HostToken t4 = new HostToken(4L, new Host("foo4", 1234, "foo_rack")); - HostToken t5 = new HostToken(5L, new Host("foo5", 1234, "foo_rack")); + HostToken t1 = new HostToken(1L, new Host("foo1", 1234, "foo_rack")); + HostToken t2 = new HostToken(2L, new Host("foo2", 1234, "foo_rack")); + HostToken t3 = new HostToken(3L, new Host("foo3", 1234, "foo_rack")); + HostToken t4 = new HostToken(4L, new Host("foo4", 1234, "foo_rack")); + HostToken t5 = new HostToken(5L, new Host("foo5", 1234, "foo_rack")); - HostToken[] arr = {t5, t2, t4, t3, t1}; - List list = Arrays.asList(arr); + HostToken[] arr = {t5, t2, t4, t3, t1}; + List list = Arrays.asList(arr); - Assert.assertEquals(t5, list.get(0)); - Assert.assertEquals(t2, list.get(1)); - Assert.assertEquals(t4, list.get(2)); - Assert.assertEquals(t3, list.get(3)); - Assert.assertEquals(t1, list.get(4)); + Assert.assertEquals(t5, list.get(0)); + Assert.assertEquals(t2, list.get(1)); + Assert.assertEquals(t4, list.get(2)); + Assert.assertEquals(t3, list.get(3)); + Assert.assertEquals(t1, list.get(4)); - Collections.sort(list, new Comparator() { - @Override - public int compare(HostToken o1, HostToken o2) { - return o1.compareTo(o2); - } - }); + Collections.sort(list, new Comparator() { + @Override + public int compare(HostToken o1, HostToken o2) { + return o1.compareTo(o2); + } + }); - Assert.assertEquals(t1, list.get(0)); - Assert.assertEquals(t2, list.get(1)); - Assert.assertEquals(t3, list.get(2)); - Assert.assertEquals(t4, list.get(3)); - Assert.assertEquals(t5, list.get(4)); - } + Assert.assertEquals(t1, list.get(0)); + Assert.assertEquals(t2, list.get(1)); + Assert.assertEquals(t3, list.get(2)); + Assert.assertEquals(t4, list.get(3)); + Assert.assertEquals(t5, list.get(4)); + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/RoundRobinSelectionTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/RoundRobinSelectionTest.java index 8db51af9..cc150e97 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/RoundRobinSelectionTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/RoundRobinSelectionTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -36,7 +36,7 @@ public class RoundRobinSelectionTest { /** * cqlsh:dyno_bootstrap> select "availabilityZone","hostname","token" from * tokens where "appId" = 'dynomite_redis_puneet'; - * + * * availabilityZone | hostname | token * ------------------+--------------------------------------------+------------ * us-east-1c | ec2-54-83-179-213.compute-1.amazonaws.com | 1383429731 @@ -47,7 +47,7 @@ public class RoundRobinSelectionTest { * us-east-1e | ec2-54-198-239-231.compute-1.amazonaws.com | 2457171554 * us-east-1e | ec2-54-226-212-40.compute-1.amazonaws.com | 1383429731 * us-east-1e | ec2-54-197-178-229.compute-1.amazonaws.com | 3530913377 - * + * * cqlsh:dyno_bootstrap> */ @@ -68,10 +68,10 @@ public String getStringKey() { return null; } - @Override - public byte[] getBinaryKey() { - return null; - } + @Override + public byte[] getBinaryKey() { + return null; + } }; @Test diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelectionBinaryTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelectionBinaryTest.java index 18e9b6c9..43c3926b 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelectionBinaryTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelectionBinaryTest.java @@ -1,12 +1,12 @@ /** * Copyright 2017 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -39,230 +39,230 @@ public class TokenAwareSelectionBinaryTest { - /** - * cqlsh:dyno_bootstrap> select "availabilityZone","hostname","token" from - * tokens where "appId" = 'dynomite_redis_puneet'; - * - * availabilityZone | hostname | token - * ------------------+--------------------------------------------+------------ - * us-east-1c | ec2-54-83-179-213.compute-1.amazonaws.com | 1383429731 - * us-east-1c | ec2-54-224-184-99.compute-1.amazonaws.com | 309687905 us-east-1c - * | ec2-54-91-190-159.compute-1.amazonaws.com | 3530913377 us-east-1c | - * ec2-54-81-31-218.compute-1.amazonaws.com | 2457171554 us-east-1e | - * ec2-54-198-222-153.compute-1.amazonaws.com | 309687905 us-east-1e | - * ec2-54-198-239-231.compute-1.amazonaws.com | 2457171554 us-east-1e | - * ec2-54-226-212-40.compute-1.amazonaws.com | 1383429731 us-east-1e | - * ec2-54-197-178-229.compute-1.amazonaws.com | 3530913377 - * - * cqlsh:dyno_bootstrap> - */ + /** + * cqlsh:dyno_bootstrap> select "availabilityZone","hostname","token" from + * tokens where "appId" = 'dynomite_redis_puneet'; + * + * availabilityZone | hostname | token + * ------------------+--------------------------------------------+------------ + * us-east-1c | ec2-54-83-179-213.compute-1.amazonaws.com | 1383429731 + * us-east-1c | ec2-54-224-184-99.compute-1.amazonaws.com | 309687905 us-east-1c + * | ec2-54-91-190-159.compute-1.amazonaws.com | 3530913377 us-east-1c | + * ec2-54-81-31-218.compute-1.amazonaws.com | 2457171554 us-east-1e | + * ec2-54-198-222-153.compute-1.amazonaws.com | 309687905 us-east-1e | + * ec2-54-198-239-231.compute-1.amazonaws.com | 2457171554 us-east-1e | + * ec2-54-226-212-40.compute-1.amazonaws.com | 1383429731 us-east-1e | + * ec2-54-197-178-229.compute-1.amazonaws.com | 3530913377 + * + * cqlsh:dyno_bootstrap> + */ private static final String UTF_8 = "UTF-8"; private static final Charset charset = Charset.forName(UTF_8); - private final HostToken h1 = new HostToken(309687905L, new Host("h1", -1, "r1", Status.Up)); - private final HostToken h2 = new HostToken(1383429731L, new Host("h2", -1, "r1", Status.Up)); - private final HostToken h3 = new HostToken(2457171554L, new Host("h3", -1, "r1", Status.Up)); - private final HostToken h4 = new HostToken(3530913377L, new Host("h4", -1, "r1", Status.Up)); + private final HostToken h1 = new HostToken(309687905L, new Host("h1", -1, "r1", Status.Up)); + private final HostToken h2 = new HostToken(1383429731L, new Host("h2", -1, "r1", Status.Up)); + private final HostToken h3 = new HostToken(2457171554L, new Host("h3", -1, "r1", Status.Up)); + private final HostToken h4 = new HostToken(3530913377L, new Host("h4", -1, "r1", Status.Up)); - private final HostToken h1p8100 = new HostToken(309687905L, new Host("h1", 8100, "r1", Status.Up)); - private final HostToken h1p8101 = new HostToken(1383429731L, new Host("h1", 8101, "r1", Status.Up)); - private final HostToken h1p8102 = new HostToken(2457171554L, new Host("h1", 8102, "r1", Status.Up)); - private final HostToken h1p8103 = new HostToken(3530913377L, new Host("h1", 8103, "r1", Status.Up)); + private final HostToken h1p8100 = new HostToken(309687905L, new Host("h1", 8100, "r1", Status.Up)); + private final HostToken h1p8101 = new HostToken(1383429731L, new Host("h1", 8101, "r1", Status.Up)); + private final HostToken h1p8102 = new HostToken(2457171554L, new Host("h1", 8102, "r1", Status.Up)); + private final HostToken h1p8103 = new HostToken(3530913377L, new Host("h1", 8103, "r1", Status.Up)); - private final Murmur1HashPartitioner m1Hash = new Murmur1HashPartitioner(); + private final Murmur1HashPartitioner m1Hash = new Murmur1HashPartitioner(); - @Test - public void testTokenAware() throws Exception { + @Test + public void testTokenAware() throws Exception { - TreeMap> pools = new TreeMap>( - new Comparator() { + TreeMap> pools = new TreeMap>( + new Comparator() { - @Override - public int compare(HostToken o1, HostToken o2) { - return o1.getHost().getHostAddress().compareTo(o2.getHost().getHostAddress()); - } - }); + @Override + public int compare(HostToken o1, HostToken o2) { + return o1.getHost().getHostAddress().compareTo(o2.getHost().getHostAddress()); + } + }); - pools.put(h1, getMockHostConnectionPool(h1)); - pools.put(h2, getMockHostConnectionPool(h2)); - pools.put(h3, getMockHostConnectionPool(h3)); - pools.put(h4, getMockHostConnectionPool(h4)); + pools.put(h1, getMockHostConnectionPool(h1)); + pools.put(h2, getMockHostConnectionPool(h2)); + pools.put(h3, getMockHostConnectionPool(h3)); + pools.put(h4, getMockHostConnectionPool(h4)); - TokenAwareSelection tokenAwareSelector = new TokenAwareSelection(); - tokenAwareSelector.initWithHosts(pools); + TokenAwareSelection tokenAwareSelector = new TokenAwareSelection(); + tokenAwareSelector.initWithHosts(pools); - Map result = new HashMap(); - runTest(0L, 100000L, result, tokenAwareSelector); + Map result = new HashMap(); + runTest(0L, 100000L, result, tokenAwareSelector); - System.out.println("Token distribution: " + result); + System.out.println("Token distribution: " + result); - verifyTokenDistribution(result.values()); - } + verifyTokenDistribution(result.values()); + } - @Test - public void testTokenAwareMultiplePorts() throws Exception { + @Test + public void testTokenAwareMultiplePorts() throws Exception { - TreeMap> pools = new TreeMap>( - new Comparator() { + TreeMap> pools = new TreeMap>( + new Comparator() { - @Override - public int compare(HostToken o1, HostToken o2) { - return o1.compareTo(o2); - } - }); + @Override + public int compare(HostToken o1, HostToken o2) { + return o1.compareTo(o2); + } + }); - pools.put(h1p8100, getMockHostConnectionPool(h1p8100)); - pools.put(h1p8101, getMockHostConnectionPool(h1p8101)); - pools.put(h1p8102, getMockHostConnectionPool(h1p8102)); - pools.put(h1p8103, getMockHostConnectionPool(h1p8103)); + pools.put(h1p8100, getMockHostConnectionPool(h1p8100)); + pools.put(h1p8101, getMockHostConnectionPool(h1p8101)); + pools.put(h1p8102, getMockHostConnectionPool(h1p8102)); + pools.put(h1p8103, getMockHostConnectionPool(h1p8103)); - TokenAwareSelection tokenAwareSelector = new TokenAwareSelection(); - tokenAwareSelector.initWithHosts(pools); + TokenAwareSelection tokenAwareSelector = new TokenAwareSelection(); + tokenAwareSelector.initWithHosts(pools); - Map result = new HashMap(); - runTestWithPorts(0L, 100000L, result, tokenAwareSelector); + Map result = new HashMap(); + runTestWithPorts(0L, 100000L, result, tokenAwareSelector); - System.out.println("Token distribution: " + result); + System.out.println("Token distribution: " + result); - verifyTokenDistribution(result.values()); - } + verifyTokenDistribution(result.values()); + } - private BaseOperation getTestOperation(final Long n) { + private BaseOperation getTestOperation(final Long n) { - return new BaseOperation() { + return new BaseOperation() { - @Override - public String getName() { - return "TestOperation" + n; - } + @Override + public String getName() { + return "TestOperation" + n; + } - @Override - public String getStringKey() { - return "" + n; - } + @Override + public String getStringKey() { + return "" + n; + } - @Override - public byte[] getBinaryKey() { - String key = "" + n; - ByteBuffer bb = ByteBuffer.wrap(key.getBytes(charset)); - return bb.array(); - } - }; - } + @Override + public byte[] getBinaryKey() { + String key = "" + n; + ByteBuffer bb = ByteBuffer.wrap(key.getBytes(charset)); + return bb.array(); + } + }; + } - private void runTest(long start, long end, Map result, - TokenAwareSelection tokenAwareSelector) { + private void runTest(long start, long end, Map result, + TokenAwareSelection tokenAwareSelector) { - for (long i = start; i <= end; i++) { + for (long i = start; i <= end; i++) { - BaseOperation op = getTestOperation(i); - HostConnectionPool pool = tokenAwareSelector.getPoolForOperation(op, null); + BaseOperation op = getTestOperation(i); + HostConnectionPool pool = tokenAwareSelector.getPoolForOperation(op, null); - String hostName = pool.getHost().getHostAddress(); + String hostName = pool.getHost().getHostAddress(); - verifyKeyHash(op.getBinaryKey(), hostName); + verifyKeyHash(op.getBinaryKey(), hostName); - Integer count = result.get(hostName); - if (count == null) { - count = 0; - } - result.put(hostName, ++count); - } - } + Integer count = result.get(hostName); + if (count == null) { + count = 0; + } + result.put(hostName, ++count); + } + } - private void runTestWithPorts(long start, long end, Map result, - TokenAwareSelection tokenAwareSelector) { + private void runTestWithPorts(long start, long end, Map result, + TokenAwareSelection tokenAwareSelector) { - for (long i = start; i <= end; i++) { + for (long i = start; i <= end; i++) { - BaseOperation op = getTestOperation(i); - HostConnectionPool pool = tokenAwareSelector.getPoolForOperation(op, null); + BaseOperation op = getTestOperation(i); + HostConnectionPool pool = tokenAwareSelector.getPoolForOperation(op, null); - int port = pool.getHost().getPort(); + int port = pool.getHost().getPort(); - verifyKeyHashWithPort(op.getBinaryKey(), port); + verifyKeyHashWithPort(op.getBinaryKey(), port); - Integer count = result.get(port); - if (count == null) { - count = 0; - } - result.put(port, ++count); - } - } + Integer count = result.get(port); + if (count == null) { + count = 0; + } + result.put(port, ++count); + } + } - private void verifyKeyHash(byte[] key, String hostname) { + private void verifyKeyHash(byte[] key, String hostname) { - Long keyHash = m1Hash.hash(key); + Long keyHash = m1Hash.hash(key); - String expectedHostname = null; + String expectedHostname = null; - if (keyHash <= 309687905L) { - expectedHostname = "h1"; - } else if (keyHash <= 1383429731L) { - expectedHostname = "h2"; - } else if (keyHash <= 2457171554L) { - expectedHostname = "h3"; - } else if (keyHash <= 3530913377L) { - expectedHostname = "h4"; - } else { - expectedHostname = "h1"; - } + if (keyHash <= 309687905L) { + expectedHostname = "h1"; + } else if (keyHash <= 1383429731L) { + expectedHostname = "h2"; + } else if (keyHash <= 2457171554L) { + expectedHostname = "h3"; + } else if (keyHash <= 3530913377L) { + expectedHostname = "h4"; + } else { + expectedHostname = "h1"; + } - if (!expectedHostname.equals(hostname)) { - Assert.fail("FAILED! for key: " + key.toString() + ", got hostname: " + hostname + ", expected: " - + expectedHostname + " for hash: " + keyHash); - } - } + if (!expectedHostname.equals(hostname)) { + Assert.fail("FAILED! for key: " + key.toString() + ", got hostname: " + hostname + ", expected: " + + expectedHostname + " for hash: " + keyHash); + } + } - private void verifyKeyHashWithPort(byte[] key, int port) { + private void verifyKeyHashWithPort(byte[] key, int port) { - Long keyHash = m1Hash.hash(key); + Long keyHash = m1Hash.hash(key); - String expectedHostname = null; - int expectedPort = 0; + String expectedHostname = null; + int expectedPort = 0; - if (keyHash <= 309687905L) { - expectedPort = 8100; - } else if (keyHash <= 1383429731L) { // 1129055870 - expectedPort = 8101; - } else if (keyHash <= 2457171554L) { - expectedPort = 8102; - } else if (keyHash <= 3530913377L) { - expectedPort = 8103; - } else { - expectedPort = 8100; - } - - if (expectedPort != port) { - Assert.fail("FAILED! for key: " + key.toString() + ", got port: " + port + ", expected: " + expectedPort - + " for hash: " + keyHash); - } - } - - private void verifyTokenDistribution(Collection values) { - - int sum = 0; - int count = 0; - for (int n : values) { - sum += n; - count++; - } + if (keyHash <= 309687905L) { + expectedPort = 8100; + } else if (keyHash <= 1383429731L) { // 1129055870 + expectedPort = 8101; + } else if (keyHash <= 2457171554L) { + expectedPort = 8102; + } else if (keyHash <= 3530913377L) { + expectedPort = 8103; + } else { + expectedPort = 8100; + } + + if (expectedPort != port) { + Assert.fail("FAILED! for key: " + key.toString() + ", got port: " + port + ", expected: " + expectedPort + + " for hash: " + keyHash); + } + } + + private void verifyTokenDistribution(Collection values) { + + int sum = 0; + int count = 0; + for (int n : values) { + sum += n; + count++; + } - double mean = (sum / count); + double mean = (sum / count); - for (int n : values) { - double percentageDiff = 100 * ((mean - n) / mean); - Assert.assertTrue(percentageDiff < 1.0); - } - } - - @SuppressWarnings("unchecked") - public HostConnectionPool getMockHostConnectionPool(final HostToken hostToken) { - - HostConnectionPool mockHostPool = mock(HostConnectionPool.class); - when(mockHostPool.isActive()).thenReturn(true); - when(mockHostPool.getHost()).thenReturn(hostToken.getHost()); - - return mockHostPool; - } + for (int n : values) { + double percentageDiff = 100 * ((mean - n) / mean); + Assert.assertTrue(percentageDiff < 1.0); + } + } + + @SuppressWarnings("unchecked") + public HostConnectionPool getMockHostConnectionPool(final HostToken hostToken) { + + HostConnectionPool mockHostPool = mock(HostConnectionPool.class); + when(mockHostPool.isActive()).thenReturn(true); + when(mockHostPool.getHost()).thenReturn(hostToken.getHost()); + + return mockHostPool; + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelectionHastagTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelectionHastagTest.java index f887a6bc..3182c04d 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelectionHastagTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelectionHastagTest.java @@ -1,12 +1,12 @@ /** * Copyright 2017 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -35,7 +35,7 @@ /** * Test cases to cover the hashtag APIs. - * + * * @author ipapapa * */ @@ -162,16 +162,16 @@ public String getStringKey() { return n + "-{" + hashValue + "}"; } - @Override - public byte[] getBinaryKey() { - return null; - } + @Override + public byte[] getBinaryKey() { + return null; + } }; } private void runTest(long start, long end, Map result, - TokenAwareSelection tokenAwareSelector, String hashtag, int testSelector) { + TokenAwareSelection tokenAwareSelector, String hashtag, int testSelector) { for (long i = start; i <= end; i++) { diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelectionTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelectionTest.java index 5fa4c044..bacaa8ad 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelectionTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenAwareSelectionTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -35,222 +35,225 @@ public class TokenAwareSelectionTest { - /** - cqlsh:dyno_bootstrap> select "availabilityZone","hostname","token" from tokens where "appId" = 'dynomite_redis_puneet'; + /** + cqlsh:dyno_bootstrap> select "availabilityZone","hostname","token" from tokens where "appId" = 'dynomite_redis_puneet'; - availabilityZone | hostname | token - ------------------+--------------------------------------------+------------ - us-east-1c | ec2-54-83-179-213.compute-1.amazonaws.com | 1383429731 - us-east-1c | ec2-54-224-184-99.compute-1.amazonaws.com | 309687905 - us-east-1c | ec2-54-91-190-159.compute-1.amazonaws.com | 3530913377 - us-east-1c | ec2-54-81-31-218.compute-1.amazonaws.com | 2457171554 - us-east-1e | ec2-54-198-222-153.compute-1.amazonaws.com | 309687905 - us-east-1e | ec2-54-198-239-231.compute-1.amazonaws.com | 2457171554 - us-east-1e | ec2-54-226-212-40.compute-1.amazonaws.com | 1383429731 - us-east-1e | ec2-54-197-178-229.compute-1.amazonaws.com | 3530913377 + availabilityZone | hostname | token + ------------------+--------------------------------------------+------------ + us-east-1c | ec2-54-83-179-213.compute-1.amazonaws.com | 1383429731 + us-east-1c | ec2-54-224-184-99.compute-1.amazonaws.com | 309687905 + us-east-1c | ec2-54-91-190-159.compute-1.amazonaws.com | 3530913377 + us-east-1c | ec2-54-81-31-218.compute-1.amazonaws.com | 2457171554 + us-east-1e | ec2-54-198-222-153.compute-1.amazonaws.com | 309687905 + us-east-1e | ec2-54-198-239-231.compute-1.amazonaws.com | 2457171554 + us-east-1e | ec2-54-226-212-40.compute-1.amazonaws.com | 1383429731 + us-east-1e | ec2-54-197-178-229.compute-1.amazonaws.com | 3530913377 - cqlsh:dyno_bootstrap> - */ + cqlsh:dyno_bootstrap> + */ - private final HostToken h1 = new HostToken(309687905L, new Host("h1", -1, "r1", Status.Up)); - private final HostToken h2 = new HostToken(1383429731L, new Host("h2", -1, "r1", Status.Up)); - private final HostToken h3 = new HostToken(2457171554L, new Host("h3", -1, "r1", Status.Up)); - private final HostToken h4 = new HostToken(3530913377L, new Host("h4", -1, "r1", Status.Up)); - - - private final HostToken h1p8100 = new HostToken(309687905L, new Host("h1", 8100, "r1", Status.Up)); - private final HostToken h1p8101 = new HostToken(1383429731L, new Host("h1", 8101, "r1", Status.Up)); - private final HostToken h1p8102 = new HostToken(2457171554L, new Host("h1", 8102, "r1", Status.Up)); - private final HostToken h1p8103 = new HostToken(3530913377L, new Host("h1", 8103, "r1", Status.Up)); + private final HostToken h1 = new HostToken(309687905L, new Host("h1", -1, "r1", Status.Up)); + private final HostToken h2 = new HostToken(1383429731L, new Host("h2", -1, "r1", Status.Up)); + private final HostToken h3 = new HostToken(2457171554L, new Host("h3", -1, "r1", Status.Up)); + private final HostToken h4 = new HostToken(3530913377L, new Host("h4", -1, "r1", Status.Up)); - private final Murmur1HashPartitioner m1Hash = new Murmur1HashPartitioner(); - @Test - public void testTokenAware() throws Exception { + private final HostToken h1p8100 = new HostToken(309687905L, new Host("h1", 8100, "r1", Status.Up)); + private final HostToken h1p8101 = new HostToken(1383429731L, new Host("h1", 8101, "r1", Status.Up)); + private final HostToken h1p8102 = new HostToken(2457171554L, new Host("h1", 8102, "r1", Status.Up)); + private final HostToken h1p8103 = new HostToken(3530913377L, new Host("h1", 8103, "r1", Status.Up)); - TreeMap> pools = new TreeMap>(new Comparator() { + private final Murmur1HashPartitioner m1Hash = new Murmur1HashPartitioner(); - @Override - public int compare(HostToken o1, HostToken o2) { - return o1.getHost().getHostAddress().compareTo(o2.getHost().getHostAddress()); - } - }); + @Test + public void testTokenAware() throws Exception { - pools.put(h1, getMockHostConnectionPool(h1)); - pools.put(h2, getMockHostConnectionPool(h2)); - pools.put(h3, getMockHostConnectionPool(h3)); - pools.put(h4, getMockHostConnectionPool(h4)); + TreeMap> pools = new TreeMap>(new Comparator() { - TokenAwareSelection tokenAwareSelector = new TokenAwareSelection(); - tokenAwareSelector.initWithHosts(pools); + @Override + public int compare(HostToken o1, HostToken o2) { + return o1.getHost().getHostAddress().compareTo(o2.getHost().getHostAddress()); + } + }); - Map result = new HashMap(); - runTest(0L, 100000L, result, tokenAwareSelector); + pools.put(h1, getMockHostConnectionPool(h1)); + pools.put(h2, getMockHostConnectionPool(h2)); + pools.put(h3, getMockHostConnectionPool(h3)); + pools.put(h4, getMockHostConnectionPool(h4)); - System.out.println("Token distribution: " + result); + TokenAwareSelection tokenAwareSelector = new TokenAwareSelection(); + tokenAwareSelector.initWithHosts(pools); - verifyTokenDistribution(result.values()); - } + Map result = new HashMap(); + runTest(0L, 100000L, result, tokenAwareSelector); - @Test - public void testTokenAwareMultiplePorts() throws Exception { + System.out.println("Token distribution: " + result); - TreeMap> pools = new TreeMap>(new Comparator() { + verifyTokenDistribution(result.values()); + } - @Override - public int compare(HostToken o1, HostToken o2) { - return o1.compareTo(o2); - } - }); + @Test + public void testTokenAwareMultiplePorts() throws Exception { - pools.put(h1p8100, getMockHostConnectionPool(h1p8100)); - pools.put(h1p8101, getMockHostConnectionPool(h1p8101)); - pools.put(h1p8102, getMockHostConnectionPool(h1p8102)); - pools.put(h1p8103, getMockHostConnectionPool(h1p8103)); + TreeMap> pools = new TreeMap>(new Comparator() { + @Override + public int compare(HostToken o1, HostToken o2) { + return o1.compareTo(o2); + } + }); - TokenAwareSelection tokenAwareSelector = new TokenAwareSelection(); - tokenAwareSelector.initWithHosts(pools); + pools.put(h1p8100, getMockHostConnectionPool(h1p8100)); + pools.put(h1p8101, getMockHostConnectionPool(h1p8101)); + pools.put(h1p8102, getMockHostConnectionPool(h1p8102)); + pools.put(h1p8103, getMockHostConnectionPool(h1p8103)); - Map result = new HashMap(); - runTestWithPorts(0L, 100000L, result, tokenAwareSelector); - System.out.println("Token distribution: " + result); + TokenAwareSelection tokenAwareSelector = new TokenAwareSelection(); + tokenAwareSelector.initWithHosts(pools); - verifyTokenDistribution(result.values()); - } + Map result = new HashMap(); + runTestWithPorts(0L, 100000L, result, tokenAwareSelector); - private BaseOperation getTestOperation(final Long n) { + System.out.println("Token distribution: " + result); - return new BaseOperation() { + verifyTokenDistribution(result.values()); + } - @Override - public String getName() { - return "TestOperation" + n; - } + private BaseOperation getTestOperation(final Long n) { - @Override - public String getStringKey() { - return "" + n; - } + return new BaseOperation() { - @Override - public byte[] getBinaryKey() { - return null; - } - }; - } + @Override + public String getName() { + return "TestOperation" + n; + } + @Override + public String getStringKey() { + return "" + n; + } - private void runTest(long start, long end, Map result, TokenAwareSelection tokenAwareSelector) { + @Override + public byte[] getBinaryKey() { + return null; + } + }; + } - for (long i=start; i<=end; i++) { - BaseOperation op = getTestOperation(i); - HostConnectionPool pool = tokenAwareSelector.getPoolForOperation(op, null); + private void runTest(long start, long end, Map result, TokenAwareSelection tokenAwareSelector) { - String hostName = pool.getHost().getHostAddress(); + for (long i = start; i <= end; i++) { - verifyKeyHash(op.getStringKey(), hostName); + BaseOperation op = getTestOperation(i); + HostConnectionPool pool = tokenAwareSelector.getPoolForOperation(op, null); - Integer count = result.get(hostName); - if (count == null) { - count = 0; - } - result.put(hostName, ++count); - } - } + String hostName = pool.getHost().getHostAddress(); - - private void runTestWithPorts(long start, long end, Map result, TokenAwareSelection tokenAwareSelector) { + verifyKeyHash(op.getStringKey(), hostName); - for (long i=start; i<=end; i++) { + Integer count = result.get(hostName); + if (count == null) { + count = 0; + } + result.put(hostName, ++count); + } + } - BaseOperation op = getTestOperation(i); - HostConnectionPool pool = tokenAwareSelector.getPoolForOperation(op, null); - int port = pool.getHost().getPort(); + private void runTestWithPorts(long start, long end, Map result, TokenAwareSelection tokenAwareSelector) { - verifyKeyHashWithPort(op.getStringKey(), port); + for (long i = start; i <= end; i++) { - Integer count = result.get(port); - if (count == null) { - count = 0; - } - result.put(port, ++count); - } - } - private void verifyKeyHash(String key, String hostname) { + BaseOperation op = getTestOperation(i); + HostConnectionPool pool = tokenAwareSelector.getPoolForOperation(op, null); - Long keyHash = m1Hash.hash(key); + int port = pool.getHost().getPort(); - String expectedHostname = null; + verifyKeyHashWithPort(op.getStringKey(), port); - if (keyHash <= 309687905L) { - expectedHostname = "h1"; - } else if (keyHash <= 1383429731L) { - expectedHostname = "h2"; - } else if (keyHash <= 2457171554L) { - expectedHostname = "h3"; - } else if (keyHash <= 3530913377L) { - expectedHostname = "h4"; - } else { - expectedHostname = "h1"; - } - - if (!expectedHostname.equals(hostname)) { - Assert.fail("FAILED! for key: " + key + ", got hostname: " + hostname + ", expected: " + expectedHostname + " for hash: " + keyHash); - } - } + Integer count = result.get(port); + if (count == null) { + count = 0; + } + result.put(port, ++count); + } + } - - private void verifyKeyHashWithPort(String key, int port) { + private void verifyKeyHash(String key, String hostname) { - Long keyHash = m1Hash.hash(key); + Long keyHash = m1Hash.hash(key); - String expectedHostname = null; - int expectedPort = 0; + String expectedHostname = null; - if (keyHash <= 309687905L) { - expectedPort = 8100; - } else if (keyHash <= 1383429731L) { //1129055870 - expectedPort = 8101; - } else if (keyHash <= 2457171554L) { - expectedPort = 8102; - } else if (keyHash <= 3530913377L) { - expectedPort = 8103; - } else { - expectedPort = 8100; - } - - if (expectedPort != port) { - Assert.fail("FAILED! for key: " + key + ", got port: " + port + ", expected: " + expectedPort + " for hash: " + keyHash); - } - } - private void verifyTokenDistribution(Collection values) { - - int sum = 0; int count = 0; - for (int n : values) { - sum += n; - count++; - } - - double mean = (sum/count); - - for (int n : values) { - double percentageDiff = 100*((mean-n)/mean); - Assert.assertTrue(percentageDiff < 1.0); - } - } - - - @SuppressWarnings("unchecked") - public HostConnectionPool getMockHostConnectionPool(final HostToken hostToken) { - - HostConnectionPool mockHostPool = mock(HostConnectionPool.class); - when(mockHostPool.isActive()).thenReturn(true); - when(mockHostPool.getHost()).thenReturn(hostToken.getHost()); - - return mockHostPool; - } + if (keyHash <= 309687905L) { + expectedHostname = "h1"; + } else if (keyHash <= 1383429731L) { + expectedHostname = "h2"; + } else if (keyHash <= 2457171554L) { + expectedHostname = "h3"; + } else if (keyHash <= 3530913377L) { + expectedHostname = "h4"; + } else { + expectedHostname = "h1"; + } + + if (!expectedHostname.equals(hostname)) { + Assert.fail("FAILED! for key: " + key + ", got hostname: " + hostname + ", expected: " + expectedHostname + " for hash: " + keyHash); + } + } + + + private void verifyKeyHashWithPort(String key, int port) { + + Long keyHash = m1Hash.hash(key); + + String expectedHostname = null; + int expectedPort = 0; + + if (keyHash <= 309687905L) { + expectedPort = 8100; + } else if (keyHash <= 1383429731L) { //1129055870 + expectedPort = 8101; + } else if (keyHash <= 2457171554L) { + expectedPort = 8102; + } else if (keyHash <= 3530913377L) { + expectedPort = 8103; + } else { + expectedPort = 8100; + } + + if (expectedPort != port) { + Assert.fail("FAILED! for key: " + key + ", got port: " + port + ", expected: " + expectedPort + " for hash: " + keyHash); + } + } + + private void verifyTokenDistribution(Collection values) { + + int sum = 0; + int count = 0; + for (int n : values) { + sum += n; + count++; + } + + double mean = (sum / count); + + for (int n : values) { + double percentageDiff = 100 * ((mean - n) / mean); + Assert.assertTrue(percentageDiff < 1.0); + } + } + + + @SuppressWarnings("unchecked") + public HostConnectionPool getMockHostConnectionPool(final HostToken hostToken) { + + HostConnectionPool mockHostPool = mock(HostConnectionPool.class); + when(mockHostPool.isActive()).thenReturn(true); + when(mockHostPool.getHost()).thenReturn(hostToken.getHost()); + + return mockHostPool; + } } diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenMapSupplierTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenMapSupplierTest.java index 0bc9cf99..f72c9782 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenMapSupplierTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/lb/TokenMapSupplierTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -130,7 +130,7 @@ public void testParseJsonWithPorts() throws Exception { Assert.assertTrue(hTokens.get(7).getHost().getHostName().equals("ec2-54-80-65-203.compute-1.amazonaws.com")); Assert.assertEquals(hTokens.get(7).getHost().getPort(), 11218); } - + @Test public void testParseJsonWithHastags() throws Exception { diff --git a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/utils/RateLimitUtilTest.java b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/utils/RateLimitUtilTest.java index 6b070b80..53ade6a4 100644 --- a/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/utils/RateLimitUtilTest.java +++ b/dyno-core/src/test/java/com/netflix/dyno/connectionpool/impl/utils/RateLimitUtilTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,57 +28,57 @@ public class RateLimitUtilTest { - @Test - public void testRate() throws Exception { + @Test + public void testRate() throws Exception { - int nThreads = 5; - int expectedRps = 100; + int nThreads = 5; + int expectedRps = 100; - final RateLimitUtil rateLimiter = RateLimitUtil.create(expectedRps); - final AtomicBoolean stop = new AtomicBoolean(false); - final AtomicLong counter = new AtomicLong(0L); - final CountDownLatch latch = new CountDownLatch(nThreads); + final RateLimitUtil rateLimiter = RateLimitUtil.create(expectedRps); + final AtomicBoolean stop = new AtomicBoolean(false); + final AtomicLong counter = new AtomicLong(0L); + final CountDownLatch latch = new CountDownLatch(nThreads); - ExecutorService thPool = Executors.newFixedThreadPool(nThreads); + ExecutorService thPool = Executors.newFixedThreadPool(nThreads); - final CyclicBarrier barrier = new CyclicBarrier(nThreads+1); + final CyclicBarrier barrier = new CyclicBarrier(nThreads + 1); - final AtomicLong end = new AtomicLong(0L); + final AtomicLong end = new AtomicLong(0L); - for (int i=0; i() { + thPool.submit(new Callable() { - @Override - public Void call() throws Exception { - barrier.await(); - while (!stop.get()) { - if(rateLimiter.acquire()) { - counter.incrementAndGet(); - } - } - latch.countDown(); - return null; - } - }); - } + @Override + public Void call() throws Exception { + barrier.await(); + while (!stop.get()) { + if (rateLimiter.acquire()) { + counter.incrementAndGet(); + } + } + latch.countDown(); + return null; + } + }); + } - long start = System.currentTimeMillis(); - barrier.await(); - Thread.sleep(10000); - stop.set(true); - latch.await(); - end.set(System.currentTimeMillis()); - thPool.shutdownNow(); + long start = System.currentTimeMillis(); + barrier.await(); + Thread.sleep(10000); + stop.set(true); + latch.await(); + end.set(System.currentTimeMillis()); + thPool.shutdownNow(); - long duration = end.get() - start; - long totalCount = counter.get(); - double resultRps = ((double)(totalCount)/((double)duration/1000.0)); - System.out.println("Total Count : " + totalCount + ", duration: " + duration + ", result rps: " + resultRps); + long duration = end.get() - start; + long totalCount = counter.get(); + double resultRps = ((double) (totalCount) / ((double) duration / 1000.0)); + System.out.println("Total Count : " + totalCount + ", duration: " + duration + ", result rps: " + resultRps); - double percentageDiff = Math.abs(expectedRps-resultRps)*100/resultRps; - System.out.println("Percentage diff: " + percentageDiff); + double percentageDiff = Math.abs(expectedRps - resultRps) * 100 / resultRps; + System.out.println("Percentage diff: " + percentageDiff); - Assert.assertTrue(percentageDiff < 12.0); - } + Assert.assertTrue(percentageDiff < 12.0); + } } diff --git a/dyno-core/src/test/resources/log4j.xml b/dyno-core/src/test/resources/log4j.xml index 8484f4e7..735e8b2f 100644 --- a/dyno-core/src/test/resources/log4j.xml +++ b/dyno-core/src/test/resources/log4j.xml @@ -10,8 +10,8 @@ - - + + \ No newline at end of file diff --git a/dyno-demo/src/main/java/com/netflix/dyno/demo/memcached/DynoMCacheDriver.java b/dyno-demo/src/main/java/com/netflix/dyno/demo/memcached/DynoMCacheDriver.java index 19174f64..d335ba2a 100644 --- a/dyno-demo/src/main/java/com/netflix/dyno/demo/memcached/DynoMCacheDriver.java +++ b/dyno-demo/src/main/java/com/netflix/dyno/demo/memcached/DynoMCacheDriver.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/dyno-demo/src/main/java/com/netflix/dyno/demo/redis/CustomTokenSupplierExample.java b/dyno-demo/src/main/java/com/netflix/dyno/demo/redis/CustomTokenSupplierExample.java index 1530bf10..c4cc1f93 100644 --- a/dyno-demo/src/main/java/com/netflix/dyno/demo/redis/CustomTokenSupplierExample.java +++ b/dyno-demo/src/main/java/com/netflix/dyno/demo/redis/CustomTokenSupplierExample.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -33,9 +33,9 @@ * Simple example that illustrates using a custom token map supplier. This example works with a local redis * installation on the default port. To setup and run: *

    - *
  1. brew install redis
  2. - *
  3. redis-server /usr/local/etc/redis.conf
  4. - *
  5. java -classpath <...classpath...> com.netflix.dyno.demo.redis.CustomTokenSupplierExample
  6. + *
  7. brew install redis
  8. + *
  9. redis-server /usr/local/etc/redis.conf
  10. + *
  11. java -classpath <...classpath...> com.netflix.dyno.demo.redis.CustomTokenSupplierExample
  12. *
*/ public class CustomTokenSupplierExample { @@ -88,12 +88,12 @@ public HostToken getTokenForHost(Host host, Set activeHosts) { public void runSimpleTest() throws Exception { // write - for (int i=0; i<10; i++) { + for (int i = 0; i < 10; i++) { client.set("" + i, "" + i); } // read - for (int i=0; i<10; i++) { - OperationResult result = client.d_get(""+i); + for (int i = 0; i < 10; i++) { + OperationResult result = client.d_get("" + i); System.out.println("Key: " + i + ", Value: " + result.getResult() + " " + result.getNode()); } } diff --git a/dyno-demo/src/main/java/com/netflix/dyno/demo/redis/DynoDistributedCounterDemo.java b/dyno-demo/src/main/java/com/netflix/dyno/demo/redis/DynoDistributedCounterDemo.java index 7339e3dc..12802de3 100644 --- a/dyno-demo/src/main/java/com/netflix/dyno/demo/redis/DynoDistributedCounterDemo.java +++ b/dyno-demo/src/main/java/com/netflix/dyno/demo/redis/DynoDistributedCounterDemo.java @@ -111,7 +111,7 @@ protected void startWrites(final int ops, final AtomicInteger failure) { final Random random = new Random(System.currentTimeMillis()); - final int numCounters = counters.size() > 1 ? counters.size() -1 : 1; + final int numCounters = counters.size() > 1 ? counters.size() - 1 : 1; for (int i = 0; i < numWriters; i++) { @@ -222,7 +222,7 @@ public void cleanup(int nKeys) { } public void cleanup(DynoCounter counter) throws Exception { - for (String key: counter.getGeneratedKeys()) { + for (String key : counter.getGeneratedKeys()) { System.out.println("deleting key: " + key); client.del(key); counter.close(); @@ -265,5 +265,4 @@ public static void main(String[] args) throws IOException { } - } diff --git a/dyno-demo/src/main/java/com/netflix/dyno/demo/redis/DynoJedisDemo.java b/dyno-demo/src/main/java/com/netflix/dyno/demo/redis/DynoJedisDemo.java index 51e8e200..f60f4f41 100644 --- a/dyno-demo/src/main/java/com/netflix/dyno/demo/redis/DynoJedisDemo.java +++ b/dyno-demo/src/main/java/com/netflix/dyno/demo/redis/DynoJedisDemo.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -78,1263 +78,1261 @@ public class DynoJedisDemo { - private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DynoJedisDemo.class); + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DynoJedisDemo.class); - public static final String randomValue = "dcfa7d0973834e5c9f480b65de19d684dcfa7d097383dcfa7d0973834e5c9f480b65de19d684dcfa7d097383dcfa7d0973834e5c9f480b65de19d684dcfa7d097383dcfa7d0973834e5c9f480b65de19d684dcfa7d097383"; + public static final String randomValue = "dcfa7d0973834e5c9f480b65de19d684dcfa7d097383dcfa7d0973834e5c9f480b65de19d684dcfa7d097383dcfa7d0973834e5c9f480b65de19d684dcfa7d097383dcfa7d0973834e5c9f480b65de19d684dcfa7d097383"; - protected DynoJedisClient client; - protected DynoJedisClient shadowClusterClient; - - protected int numKeys; - - protected final String localRack; - protected final String clusterName; - protected final String shadowClusterName; - - public DynoJedisDemo(String clusterName, String localRack) { - this(clusterName, null, localRack); - } - - public DynoJedisDemo(String primaryCluster, String shadowCluster, String localRack) { - this.clusterName = primaryCluster; - this.shadowClusterName = shadowCluster; - this.localRack = localRack; - } - - public void initWithLocalHost() throws Exception { - - final int port = 6379; - - - final HostSupplier localHostSupplier = new HostSupplier() { - final Host hostSupplierHost = new Host("localhost", localRack, Status.Up); - - @Override - public List getHosts() { - return Collections.singletonList(hostSupplierHost); - } - }; - - final TokenMapSupplier tokenSupplier = new TokenMapSupplier() { - - final Host tokenHost = new Host("localhost", port, localRack, Status.Up); - final HostToken localHostToken = new HostToken(100000L, tokenHost); - - @Override - public List getTokens(Set activeHosts) { - return Collections.singletonList(localHostToken); - } - - @Override - public HostToken getTokenForHost(Host host, Set activeHosts) { - return localHostToken; - } - }; - - init(localHostSupplier, port, tokenSupplier); - } - - private void initWithRemoteCluster(final List hosts, final int port) throws Exception { - final HostSupplier clusterHostSupplier = () -> hosts; - - init(clusterHostSupplier, port, null); - } - - public void initWithRemoteClusterFromFile(final String filename, final int port) throws Exception { - initWithRemoteCluster(readHostsFromFile(filename, port), port); - } - - public void initWithRemoteClusterFromEurekaUrl(final String clusterName, final int port) throws Exception { - initWithRemoteCluster(getHostsFromDiscovery(clusterName), port); - } - - public void initDualClientWithRemoteClustersFromFile(final String primaryHostsFile, final String shadowHostsFile, - final int port) throws Exception { - final HostSupplier primaryClusterHostSupplier = () -> { - try { - return readHostsFromFile(primaryHostsFile, port); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - }; - - final HostSupplier shadowClusterHostSupplier = () -> { - try { - return readHostsFromFile(shadowHostsFile, port); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - }; - initDualWriterDemo(primaryClusterHostSupplier, shadowClusterHostSupplier, - null, null); - } - - public void initDualClientWithRemoteClustersFromEurekaUrl(final String primaryClusterName, - final String shadowClusterName) { - final HostSupplier primaryClusterHostSupplier = () -> getHostsFromDiscovery(primaryClusterName); - final HostSupplier shadowClusterHostSupplier = () -> getHostsFromDiscovery(shadowClusterName); - - initDualWriterDemo(primaryClusterHostSupplier, shadowClusterHostSupplier, null, null); - } - - public void initDualWriterDemo(HostSupplier primaryClusterHostSupplier, HostSupplier shadowClusterHostSupplier, - TokenMapSupplier primaryTokenSupplier, TokenMapSupplier shadowTokenSupplier) { - this.client = new DynoJedisClient.Builder() - .withApplicationName("demo") - .withDynomiteClusterName("dyno-dev") - .withHostSupplier(primaryClusterHostSupplier) - .withDualWriteHostSupplier(shadowClusterHostSupplier) - .withTokenMapSupplier(primaryTokenSupplier) - .withDualWriteTokenMapSupplier(shadowTokenSupplier) - .build(); - - ConnectionPoolConfigurationImpl shadowCPConfig = - new ArchaiusConnectionPoolConfiguration(shadowClusterName); - - this.shadowClusterClient = new DynoJedisClient.Builder() - .withApplicationName("demo") - .withDynomiteClusterName("dyno-dev") - .withHostSupplier(primaryClusterHostSupplier) - .withTokenMapSupplier(primaryTokenSupplier) - .withCPConfig(shadowCPConfig) - .build(); - - } - - public void init(HostSupplier hostSupplier, int port, TokenMapSupplier tokenSupplier) throws Exception { - client = new DynoJedisClient.Builder().withApplicationName("demo").withDynomiteClusterName("dyno_dev") - .withHostSupplier(hostSupplier) - .withTokenMapSupplier(tokenSupplier) - // .withCPConfig( - // new ConnectionPoolConfigurationImpl("demo") - // .setCompressionStrategy(ConnectionPoolConfiguration.CompressionStrategy.THRESHOLD) - // .setCompressionThreshold(2048) - // .setLocalRack(this.localRack) - // ) - .build(); - } - - public void runSimpleTest() throws Exception { - - this.numKeys = 10; - System.out.println("Simple test selected"); - - // write - for (int i = 0; i < numKeys; i++) { - System.out.println("Writing key/value => DynoClientTest-" + i + " / " + i); - client.set("DynoClientTest-" + i, "" + i); - } - // read - for (int i = 0; i < numKeys; i++) { - OperationResult result = client.d_get("DynoClientTest-" + i); - System.out.println("Reading Key: " + i + ", Value: " + result.getResult() + " " + result.getNode()); - } - - // read from shadow cluster - if (shadowClusterClient != null) { - // read - for (int i = 0; i < numKeys; i++) { - OperationResult result = shadowClusterClient.d_get("DynoClientTest-" + i); - System.out.println("Reading Key: " + i + ", Value: " + result.getResult() + " " + result.getNode()); - } - } - } - - public void runSimpleDualWriterPipelineTest() { - this.numKeys = 10; - System.out.println("Simple Dual Writer Pipeline test selected"); - - // write - DynoJedisPipeline pipeline = client.pipelined(); - for (int i = 0; i < numKeys; i++) { - System.out.println("Writing key/value => DynoClientTest/" + i); - pipeline.hset("DynoClientTest", "DynoClientTest-" + i, "" + i); - } - pipeline.sync(); - - // new pipeline - pipeline = client.pipelined(); - for (int i = 0; i < numKeys; i++) { - System.out.println("Writing key/value => DynoClientTest-1/" + i); - pipeline.hset("DynoClientTest-1", "DynoClientTest-" + i, "" + i); - } - pipeline.sync(); - - // read - System.out.println("Reading keys from dual writer pipeline client"); - for (int i = 0; i < numKeys; i++) { - OperationResult result = client.d_hget("DynoClientTest", "DynoClientTest-" + i); - System.out.println("Reading Key: DynoClientTest/" + i + ", Value: " + result.getResult() + " " + result.getNode()); - result = client.d_hget("DynoClientTest-1", "DynoClientTest-" + i); - System.out.println("Reading Key: DynoClientTest-1/" + i + ", Value: " + result.getResult() + " " + result.getNode()); - } - - // read from shadow cluster - System.out.println("Reading keys from shadow Jedis client"); - if (shadowClusterClient != null) { - // read - for (int i = 0; i < numKeys; i++) { - OperationResult result = shadowClusterClient.d_hget("DynoClientTest", "DynoClientTest-" + i); - System.out.println("Reading Key: DynoClientTest/" + i + ", Value: " + result.getResult() + " " + result.getNode()); - result = shadowClusterClient.d_hget("DynoClientTest-1", "DynoClientTest-" + i); - System.out.println("Reading Key: DynoClientTest-1/" + i + ", Value: " + result.getResult() + " " + result.getNode()); - } - } - - try { - pipeline.close(); - } catch (Throwable t) { - t.printStackTrace(); - } - } - - /** - * This tests covers the use of binary keys - * - * @throws Exception - */ - public void runBinaryKeyTest() throws Exception { - - System.out.println("Binary Key test selected"); - byte[] videoInt =ByteBuffer.allocate(4).putInt(new Integer(100)).array(); - byte[] locInt =ByteBuffer.allocate(4).putInt(new Integer(200)).array(); + protected DynoJedisClient client; + protected DynoJedisClient shadowClusterClient; + + protected int numKeys; + + protected final String localRack; + protected final String clusterName; + protected final String shadowClusterName; + + public DynoJedisDemo(String clusterName, String localRack) { + this(clusterName, null, localRack); + } + + public DynoJedisDemo(String primaryCluster, String shadowCluster, String localRack) { + this.clusterName = primaryCluster; + this.shadowClusterName = shadowCluster; + this.localRack = localRack; + } + + public void initWithLocalHost() throws Exception { + + final int port = 6379; + + + final HostSupplier localHostSupplier = new HostSupplier() { + final Host hostSupplierHost = new Host("localhost", localRack, Status.Up); + + @Override + public List getHosts() { + return Collections.singletonList(hostSupplierHost); + } + }; + + final TokenMapSupplier tokenSupplier = new TokenMapSupplier() { + + final Host tokenHost = new Host("localhost", port, localRack, Status.Up); + final HostToken localHostToken = new HostToken(100000L, tokenHost); + + @Override + public List getTokens(Set activeHosts) { + return Collections.singletonList(localHostToken); + } + + @Override + public HostToken getTokenForHost(Host host, Set activeHosts) { + return localHostToken; + } + }; + + init(localHostSupplier, port, tokenSupplier); + } + + private void initWithRemoteCluster(final List hosts, final int port) throws Exception { + final HostSupplier clusterHostSupplier = () -> hosts; + + init(clusterHostSupplier, port, null); + } + + public void initWithRemoteClusterFromFile(final String filename, final int port) throws Exception { + initWithRemoteCluster(readHostsFromFile(filename, port), port); + } + + public void initWithRemoteClusterFromEurekaUrl(final String clusterName, final int port) throws Exception { + initWithRemoteCluster(getHostsFromDiscovery(clusterName), port); + } + + public void initDualClientWithRemoteClustersFromFile(final String primaryHostsFile, final String shadowHostsFile, + final int port) throws Exception { + final HostSupplier primaryClusterHostSupplier = () -> { + try { + return readHostsFromFile(primaryHostsFile, port); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + }; + + final HostSupplier shadowClusterHostSupplier = () -> { + try { + return readHostsFromFile(shadowHostsFile, port); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + }; + initDualWriterDemo(primaryClusterHostSupplier, shadowClusterHostSupplier, + null, null); + } + + public void initDualClientWithRemoteClustersFromEurekaUrl(final String primaryClusterName, + final String shadowClusterName) { + final HostSupplier primaryClusterHostSupplier = () -> getHostsFromDiscovery(primaryClusterName); + final HostSupplier shadowClusterHostSupplier = () -> getHostsFromDiscovery(shadowClusterName); + + initDualWriterDemo(primaryClusterHostSupplier, shadowClusterHostSupplier, null, null); + } + + public void initDualWriterDemo(HostSupplier primaryClusterHostSupplier, HostSupplier shadowClusterHostSupplier, + TokenMapSupplier primaryTokenSupplier, TokenMapSupplier shadowTokenSupplier) { + this.client = new DynoJedisClient.Builder() + .withApplicationName("demo") + .withDynomiteClusterName("dyno-dev") + .withHostSupplier(primaryClusterHostSupplier) + .withDualWriteHostSupplier(shadowClusterHostSupplier) + .withTokenMapSupplier(primaryTokenSupplier) + .withDualWriteTokenMapSupplier(shadowTokenSupplier) + .build(); + + ConnectionPoolConfigurationImpl shadowCPConfig = + new ArchaiusConnectionPoolConfiguration(shadowClusterName); + + this.shadowClusterClient = new DynoJedisClient.Builder() + .withApplicationName("demo") + .withDynomiteClusterName("dyno-dev") + .withHostSupplier(primaryClusterHostSupplier) + .withTokenMapSupplier(primaryTokenSupplier) + .withCPConfig(shadowCPConfig) + .build(); + + } + + public void init(HostSupplier hostSupplier, int port, TokenMapSupplier tokenSupplier) throws Exception { + client = new DynoJedisClient.Builder().withApplicationName("demo").withDynomiteClusterName("dyno_dev") + .withHostSupplier(hostSupplier) + .withTokenMapSupplier(tokenSupplier) + // .withCPConfig( + // new ConnectionPoolConfigurationImpl("demo") + // .setCompressionStrategy(ConnectionPoolConfiguration.CompressionStrategy.THRESHOLD) + // .setCompressionThreshold(2048) + // .setLocalRack(this.localRack) + // ) + .build(); + } + + public void runSimpleTest() throws Exception { + + this.numKeys = 10; + System.out.println("Simple test selected"); + + // write + for (int i = 0; i < numKeys; i++) { + System.out.println("Writing key/value => DynoClientTest-" + i + " / " + i); + client.set("DynoClientTest-" + i, "" + i); + } + // read + for (int i = 0; i < numKeys; i++) { + OperationResult result = client.d_get("DynoClientTest-" + i); + System.out.println("Reading Key: " + i + ", Value: " + result.getResult() + " " + result.getNode()); + } + + // read from shadow cluster + if (shadowClusterClient != null) { + // read + for (int i = 0; i < numKeys; i++) { + OperationResult result = shadowClusterClient.d_get("DynoClientTest-" + i); + System.out.println("Reading Key: " + i + ", Value: " + result.getResult() + " " + result.getNode()); + } + } + } + + public void runSimpleDualWriterPipelineTest() { + this.numKeys = 10; + System.out.println("Simple Dual Writer Pipeline test selected"); + + // write + DynoJedisPipeline pipeline = client.pipelined(); + for (int i = 0; i < numKeys; i++) { + System.out.println("Writing key/value => DynoClientTest/" + i); + pipeline.hset("DynoClientTest", "DynoClientTest-" + i, "" + i); + } + pipeline.sync(); + + // new pipeline + pipeline = client.pipelined(); + for (int i = 0; i < numKeys; i++) { + System.out.println("Writing key/value => DynoClientTest-1/" + i); + pipeline.hset("DynoClientTest-1", "DynoClientTest-" + i, "" + i); + } + pipeline.sync(); + + // read + System.out.println("Reading keys from dual writer pipeline client"); + for (int i = 0; i < numKeys; i++) { + OperationResult result = client.d_hget("DynoClientTest", "DynoClientTest-" + i); + System.out.println("Reading Key: DynoClientTest/" + i + ", Value: " + result.getResult() + " " + result.getNode()); + result = client.d_hget("DynoClientTest-1", "DynoClientTest-" + i); + System.out.println("Reading Key: DynoClientTest-1/" + i + ", Value: " + result.getResult() + " " + result.getNode()); + } + + // read from shadow cluster + System.out.println("Reading keys from shadow Jedis client"); + if (shadowClusterClient != null) { + // read + for (int i = 0; i < numKeys; i++) { + OperationResult result = shadowClusterClient.d_hget("DynoClientTest", "DynoClientTest-" + i); + System.out.println("Reading Key: DynoClientTest/" + i + ", Value: " + result.getResult() + " " + result.getNode()); + result = shadowClusterClient.d_hget("DynoClientTest-1", "DynoClientTest-" + i); + System.out.println("Reading Key: DynoClientTest-1/" + i + ", Value: " + result.getResult() + " " + result.getNode()); + } + } + + try { + pipeline.close(); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + /** + * This tests covers the use of binary keys + * + * @throws Exception + */ + public void runBinaryKeyTest() throws Exception { + + System.out.println("Binary Key test selected"); + byte[] videoInt = ByteBuffer.allocate(4).putInt(new Integer(100)).array(); + byte[] locInt = ByteBuffer.allocate(4).putInt(new Integer(200)).array(); byte[] overallKey = new byte[videoInt.length + locInt.length]; - byte[] firstWindow = ByteBuffer.allocate(4).putFloat(new Float(1.25)).array(); - byte[] secondWindow = ByteBuffer.allocate(4).putFloat(new Float(1.5)).array(); - byte[] thirdWindow = ByteBuffer.allocate(4).putFloat(new Float(1.75)).array(); - byte[] fourthWindow = ByteBuffer.allocate(4).putFloat(new Float(2.0)).array(); - - byte[] overallVal = new byte[firstWindow.length + secondWindow.length + thirdWindow.length - + fourthWindow.length]; - - byte[] newKey = new byte[videoInt.length+locInt.length]; - - // write - client.set(overallKey, overallVal); - System.out.println("Writing Key: " + new String(overallKey, Charset.forName("UTF-8"))); - - // read - OperationResult result = client.d_get(newKey); - System.out.println("Reading Key: " + new String(newKey, Charset.forName("UTF-8")) + ", Value: " + result.getResult().toString() + " " + result.getNode()); - - } - - /** - * To run this test, the hashtag FP must be set on the Dynomite cluster. The - * assumed hashtag for this test is {} hence each key is foo-{}. To - * validate that this test succeeds observe the cluster manually. - * - * @throws Exception - */ - public void runSimpleTestWithHashtag() throws Exception { - - this.numKeys = 100; - System.out.println("Simple test with hashtag selected"); - - // write - for (int i = 0; i < numKeys; i++) { - System.out.println("Writing key/value => DynoClientTest-" + i + " / " + i); - client.set(i + "-{bar}", " " + i); - } - // read - for (int i = 0; i < numKeys; i++) { - OperationResult result = client.d_get(i + "-{bar}"); - System.out.println( - "Reading Key: " + i + "-{bar}" + " , Value: " + result.getResult() + " " + result.getNode()); - } - } - - public void runPipelineEmptyResult() throws Exception { - DynoJedisPipeline pipeline = client.pipelined(); - DynoJedisPipeline pipeline2 = client.pipelined(); - - try { - byte[] field1 = "field1".getBytes(); - byte[] field2 = "field2".getBytes(); - - pipeline.hset("myHash".getBytes(), field1, "hello".getBytes()); - pipeline.hset("myHash".getBytes(), field2, "world".getBytes()); - - Thread.sleep(1000); - - Response> result = pipeline.hmget("myHash".getBytes(), field1, field2, "miss".getBytes()); - - pipeline.sync(); - - System.out.println("TEST-1: hmget for 2 valid results and 1 non-existent field"); - for (int i = 0; i < result.get().size(); i++) { - byte[] val = result.get().get(i); - if (val != null) { - System.out.println("TEST-1:Result => " + i + ") " + new String(val)); - } else { - System.out.println("TEST-1:Result => " + i + ") " + val); - } - } - - } catch (Exception e) { - pipeline.discardPipelineAndReleaseConnection(); - throw e; - } - - try { - Response> result2 = pipeline2.hmget("foo".getBytes(), "miss1".getBytes(), "miss2".getBytes()); - - pipeline2.sync(); - - System.out.println("TEST-2: hmget when all fields (3) are not present in the hash"); - if (result2.get() == null) { - System.out.println("TEST-2: result is null"); - } else { - for (int i = 0; i < result2.get().size(); i++) { - System.out.println("TEST-2:" + Arrays.toString(result2.get().get(i))); - } - } - } catch (Exception e) { - pipeline.discardPipelineAndReleaseConnection(); - throw e; - } - } - - public void runKeysTest() throws Exception { - System.out.println("Writing 10,000 keys to dynomite..."); - - for (int i = 0; i < 500; i++) { - client.set("DynoClientTest_KEYS-TEST-key" + i, "value-" + i); - } - - System.out.println("finished writing 10000 keys, querying for keys(\"DynoClientTest_KYES-TEST*\")"); - - Set result = client.keys("DynoClientTest_KEYS-TEST*"); - - System.out.println("Got " + result.size() + " results, below"); - System.out.println(result); - } - - public void runScanTest(boolean populateKeys) throws Exception { - logger.info("SCAN TEST -- begin"); - - final String keyPattern = System.getProperty("dyno.demo.scan.key.pattern", "DynoClientTest_key-*"); - final String keyPrefix = System.getProperty("dyno.demo.scan.key.prefix", "DynoClientTest_key-"); - - if (populateKeys) { - logger.info("Writing 500 keys to {} with prefix {}", this.clusterName, keyPrefix); - for (int i = 0; i < 500; i++) { - client.set(keyPrefix + i, "value-" + i); - } - } - - logger.info("Reading keys from {} with pattern {}", this.clusterName, keyPattern); - CursorBasedResult cbi = null; - long start = System.currentTimeMillis(); - int count = 0; - do { - try { - - cbi = client.dyno_scan(cbi, 5, keyPattern); - } catch (PoolOfflineException ex) { - logger.info("Caught exception.... retrying scan"); - cbi = null; - continue; - } - - - List results = cbi.getStringResult(); - count += results.size(); - int i = 0; - for (String res : results) { - logger.info("{}) {}", i, res); - i++; - } - } while ((cbi == null) || !cbi.isComplete()); - long end = System.currentTimeMillis(); - - - logger.info("SCAN TEST -- done {} results in {}ms", count, end - start); - } - - public void runSScanTest(boolean populateKeys) throws Exception { - logger.info("SET SCAN TEST -- begin"); - - final String key = "DynoClientTest_Set"; - - if (populateKeys) { - logger.info("Populating set in cluster {} with key {}", this.clusterName, key); - for (int i = 0; i < 50; i++) { - client.sadd(key, "value-" + i); - } - } - - logger.info("Reading members of set from cluster {} with key {}", this.clusterName, key); - ScanResult scanResult; - final Set matches = new HashSet<>(); - String cursor = "0"; - do { - - final ScanParams scanParams = new ScanParams().count(10); - scanParams.match("*"); - scanResult = client.sscan(key, cursor, scanParams); - matches.addAll(scanResult.getResult()); - cursor = scanResult.getCursor(); - if ("0".equals(cursor)) { - break; - } - } while (true); - logger.info("SET SCAN TEST -- done"); - } - - public void cleanup(int nKeys) throws Exception { - - // writes for initial seeding - for (int i = 0; i < nKeys; i++) { - System.out.println("Deleting : " + i); - client.del("DynoDemoTest" + i); - } - } - - public void runMultiThreaded() throws Exception { - this.runMultiThreaded(1000, true, 2, 2); - } + byte[] firstWindow = ByteBuffer.allocate(4).putFloat(new Float(1.25)).array(); + byte[] secondWindow = ByteBuffer.allocate(4).putFloat(new Float(1.5)).array(); + byte[] thirdWindow = ByteBuffer.allocate(4).putFloat(new Float(1.75)).array(); + byte[] fourthWindow = ByteBuffer.allocate(4).putFloat(new Float(2.0)).array(); + + byte[] overallVal = new byte[firstWindow.length + secondWindow.length + thirdWindow.length + + fourthWindow.length]; + + byte[] newKey = new byte[videoInt.length + locInt.length]; + + // write + client.set(overallKey, overallVal); + System.out.println("Writing Key: " + new String(overallKey, Charset.forName("UTF-8"))); + + // read + OperationResult result = client.d_get(newKey); + System.out.println("Reading Key: " + new String(newKey, Charset.forName("UTF-8")) + ", Value: " + result.getResult().toString() + " " + result.getNode()); + + } + + /** + * To run this test, the hashtag FP must be set on the Dynomite cluster. The + * assumed hashtag for this test is {} hence each key is foo-{}. To + * validate that this test succeeds observe the cluster manually. + * + * @throws Exception + */ + public void runSimpleTestWithHashtag() throws Exception { + + this.numKeys = 100; + System.out.println("Simple test with hashtag selected"); + + // write + for (int i = 0; i < numKeys; i++) { + System.out.println("Writing key/value => DynoClientTest-" + i + " / " + i); + client.set(i + "-{bar}", " " + i); + } + // read + for (int i = 0; i < numKeys; i++) { + OperationResult result = client.d_get(i + "-{bar}"); + System.out.println( + "Reading Key: " + i + "-{bar}" + " , Value: " + result.getResult() + " " + result.getNode()); + } + } + + public void runPipelineEmptyResult() throws Exception { + DynoJedisPipeline pipeline = client.pipelined(); + DynoJedisPipeline pipeline2 = client.pipelined(); + + try { + byte[] field1 = "field1".getBytes(); + byte[] field2 = "field2".getBytes(); + + pipeline.hset("myHash".getBytes(), field1, "hello".getBytes()); + pipeline.hset("myHash".getBytes(), field2, "world".getBytes()); + + Thread.sleep(1000); + + Response> result = pipeline.hmget("myHash".getBytes(), field1, field2, "miss".getBytes()); + + pipeline.sync(); + + System.out.println("TEST-1: hmget for 2 valid results and 1 non-existent field"); + for (int i = 0; i < result.get().size(); i++) { + byte[] val = result.get().get(i); + if (val != null) { + System.out.println("TEST-1:Result => " + i + ") " + new String(val)); + } else { + System.out.println("TEST-1:Result => " + i + ") " + val); + } + } + + } catch (Exception e) { + pipeline.discardPipelineAndReleaseConnection(); + throw e; + } + + try { + Response> result2 = pipeline2.hmget("foo".getBytes(), "miss1".getBytes(), "miss2".getBytes()); + + pipeline2.sync(); + + System.out.println("TEST-2: hmget when all fields (3) are not present in the hash"); + if (result2.get() == null) { + System.out.println("TEST-2: result is null"); + } else { + for (int i = 0; i < result2.get().size(); i++) { + System.out.println("TEST-2:" + Arrays.toString(result2.get().get(i))); + } + } + } catch (Exception e) { + pipeline.discardPipelineAndReleaseConnection(); + throw e; + } + } + + public void runKeysTest() throws Exception { + System.out.println("Writing 10,000 keys to dynomite..."); + + for (int i = 0; i < 500; i++) { + client.set("DynoClientTest_KEYS-TEST-key" + i, "value-" + i); + } + + System.out.println("finished writing 10000 keys, querying for keys(\"DynoClientTest_KYES-TEST*\")"); + + Set result = client.keys("DynoClientTest_KEYS-TEST*"); + + System.out.println("Got " + result.size() + " results, below"); + System.out.println(result); + } + + public void runScanTest(boolean populateKeys) throws Exception { + logger.info("SCAN TEST -- begin"); + + final String keyPattern = System.getProperty("dyno.demo.scan.key.pattern", "DynoClientTest_key-*"); + final String keyPrefix = System.getProperty("dyno.demo.scan.key.prefix", "DynoClientTest_key-"); + + if (populateKeys) { + logger.info("Writing 500 keys to {} with prefix {}", this.clusterName, keyPrefix); + for (int i = 0; i < 500; i++) { + client.set(keyPrefix + i, "value-" + i); + } + } + + logger.info("Reading keys from {} with pattern {}", this.clusterName, keyPattern); + CursorBasedResult cbi = null; + long start = System.currentTimeMillis(); + int count = 0; + do { + try { + + cbi = client.dyno_scan(cbi, 5, keyPattern); + } catch (PoolOfflineException ex) { + logger.info("Caught exception.... retrying scan"); + cbi = null; + continue; + } + + + List results = cbi.getStringResult(); + count += results.size(); + int i = 0; + for (String res : results) { + logger.info("{}) {}", i, res); + i++; + } + } while ((cbi == null) || !cbi.isComplete()); + long end = System.currentTimeMillis(); + + + logger.info("SCAN TEST -- done {} results in {}ms", count, end - start); + } + + public void runSScanTest(boolean populateKeys) throws Exception { + logger.info("SET SCAN TEST -- begin"); + + final String key = "DynoClientTest_Set"; + + if (populateKeys) { + logger.info("Populating set in cluster {} with key {}", this.clusterName, key); + for (int i = 0; i < 50; i++) { + client.sadd(key, "value-" + i); + } + } + + logger.info("Reading members of set from cluster {} with key {}", this.clusterName, key); + ScanResult scanResult; + final Set matches = new HashSet<>(); + String cursor = "0"; + do { + + final ScanParams scanParams = new ScanParams().count(10); + scanParams.match("*"); + scanResult = client.sscan(key, cursor, scanParams); + matches.addAll(scanResult.getResult()); + cursor = scanResult.getCursor(); + if ("0".equals(cursor)) { + break; + } + } while (true); + logger.info("SET SCAN TEST -- done"); + } + + public void cleanup(int nKeys) throws Exception { + + // writes for initial seeding + for (int i = 0; i < nKeys; i++) { + System.out.println("Deleting : " + i); + client.del("DynoDemoTest" + i); + } + } + + public void runMultiThreaded() throws Exception { + this.runMultiThreaded(1000, true, 2, 2); + } - public void runMultiThreaded(final int items, boolean doSeed, final int numReaders, final int numWriters) - throws Exception { + public void runMultiThreaded(final int items, boolean doSeed, final int numReaders, final int numWriters) + throws Exception { - final int nKeys = items; - if (doSeed) { - // writes for initial seeding - for (int i = 0; i < nKeys; i++) { - System.out.println("Writing : " + i); - client.set("DynoDemoTest" + i, "" + i); - } - } + final int nKeys = items; + if (doSeed) { + // writes for initial seeding + for (int i = 0; i < nKeys; i++) { + System.out.println("Writing : " + i); + client.set("DynoDemoTest" + i, "" + i); + } + } - final int nThreads = numReaders + numWriters + 1; + final int nThreads = numReaders + numWriters + 1; - final ExecutorService threadPool = Executors.newFixedThreadPool(nThreads); - - final AtomicBoolean stop = new AtomicBoolean(false); - final CountDownLatch latch = new CountDownLatch(nThreads); - - final AtomicInteger success = new AtomicInteger(0); - final AtomicInteger failure = new AtomicInteger(0); - final AtomicInteger emptyReads = new AtomicInteger(0); - - startWrites(nKeys, numWriters, threadPool, stop, latch, success, failure); - startReads(nKeys, numReaders, threadPool, stop, latch, success, failure, emptyReads); - - threadPool.submit(new Callable() { - - @Override - public Void call() throws Exception { - while (!stop.get()) { - System.out.println("Success: " + success.get() + ", failure: " + failure.get() + ", emptyReads: " - + emptyReads.get()); - Thread.sleep(1000); - } - latch.countDown(); - return null; - } - - }); - - Thread.sleep(15 * 1000); - - stop.set(true); - latch.await(); - threadPool.shutdownNow(); - - executePostRunActions(); - - System.out.println("Cleaning up keys"); - cleanup(nKeys); - - System.out.println("FINAL RESULT \nSuccess: " + success.get() + ", failure: " + failure.get() + ", emptyReads: " - + emptyReads.get()); - - } - - protected void executePostRunActions() { - // nothing to do here - } - - protected void startWrites(final int nKeys, final int numWriters, final ExecutorService threadPool, - final AtomicBoolean stop, final CountDownLatch latch, final AtomicInteger success, - final AtomicInteger failure) { - - for (int i = 0; i < numWriters; i++) { - - threadPool.submit(new Callable() { - - final Random random = new Random(); - - @Override - public Void call() throws Exception { - - while (!stop.get()) { - int key = random.nextInt(nKeys); - int value = random.nextInt(nKeys); - - try { - client.set("DynoDemoTest" + key, "" + value); - success.incrementAndGet(); - } catch (Exception e) { - System.out.println("WRITE FAILURE: " + e.getMessage()); - failure.incrementAndGet(); - } - } + final ExecutorService threadPool = Executors.newFixedThreadPool(nThreads); + + final AtomicBoolean stop = new AtomicBoolean(false); + final CountDownLatch latch = new CountDownLatch(nThreads); + + final AtomicInteger success = new AtomicInteger(0); + final AtomicInteger failure = new AtomicInteger(0); + final AtomicInteger emptyReads = new AtomicInteger(0); + + startWrites(nKeys, numWriters, threadPool, stop, latch, success, failure); + startReads(nKeys, numReaders, threadPool, stop, latch, success, failure, emptyReads); + + threadPool.submit(new Callable() { + + @Override + public Void call() throws Exception { + while (!stop.get()) { + System.out.println("Success: " + success.get() + ", failure: " + failure.get() + ", emptyReads: " + + emptyReads.get()); + Thread.sleep(1000); + } + latch.countDown(); + return null; + } + + }); + + Thread.sleep(15 * 1000); + + stop.set(true); + latch.await(); + threadPool.shutdownNow(); + + executePostRunActions(); + + System.out.println("Cleaning up keys"); + cleanup(nKeys); + + System.out.println("FINAL RESULT \nSuccess: " + success.get() + ", failure: " + failure.get() + ", emptyReads: " + + emptyReads.get()); + + } + + protected void executePostRunActions() { + // nothing to do here + } + + protected void startWrites(final int nKeys, final int numWriters, final ExecutorService threadPool, + final AtomicBoolean stop, final CountDownLatch latch, final AtomicInteger success, + final AtomicInteger failure) { + + for (int i = 0; i < numWriters; i++) { + + threadPool.submit(new Callable() { + + final Random random = new Random(); + + @Override + public Void call() throws Exception { + + while (!stop.get()) { + int key = random.nextInt(nKeys); + int value = random.nextInt(nKeys); + + try { + client.set("DynoDemoTest" + key, "" + value); + success.incrementAndGet(); + } catch (Exception e) { + System.out.println("WRITE FAILURE: " + e.getMessage()); + failure.incrementAndGet(); + } + } - latch.countDown(); - return null; - } - - }); - } - } - - protected void startReads(final int nKeys, final int numReaders, final ExecutorService threadPool, - final AtomicBoolean stop, final CountDownLatch latch, final AtomicInteger success, - final AtomicInteger failure, final AtomicInteger emptyReads) { - - for (int i = 0; i < numReaders; i++) { - - threadPool.submit(new Callable() { - - final Random random = new Random(); - - @Override - public Void call() throws Exception { + latch.countDown(); + return null; + } + + }); + } + } + + protected void startReads(final int nKeys, final int numReaders, final ExecutorService threadPool, + final AtomicBoolean stop, final CountDownLatch latch, final AtomicInteger success, + final AtomicInteger failure, final AtomicInteger emptyReads) { + + for (int i = 0; i < numReaders; i++) { + + threadPool.submit(new Callable() { + + final Random random = new Random(); + + @Override + public Void call() throws Exception { - while (!stop.get()) { - int key = random.nextInt(nKeys); + while (!stop.get()) { + int key = random.nextInt(nKeys); - try { - String value = client.get("DynoDemoTest" + key); - success.incrementAndGet(); - if (value == null || value.isEmpty()) { - emptyReads.incrementAndGet(); - } - } catch (Exception e) { - System.out.println("READ FAILURE: " + e.getMessage()); - failure.incrementAndGet(); - } - } - - latch.countDown(); - return null; - } - }); - } - } - - public void stop() { - if (client != null) { - client.stopClient(); - } - } - - private List readHostsFromFile(String filename, int port) throws Exception { - - List hosts = new ArrayList(); - File file = new File(filename); - BufferedReader reader = new BufferedReader(new FileReader(file)); - - try { - String line = null; - while ((line = reader.readLine()) != null) { - if (line.trim().isEmpty()) { - continue; - } - String[] parts = line.trim().split(" "); - if (parts.length != 2) { - throw new RuntimeException("Bad data format in file:" + line); - } - Host host = new Host(parts[0].trim(), port, parts[1].trim(), Status.Up); - hosts.add(host); - } - } finally { - reader.close(); - } - return hosts; - } - - public void runBinarySinglePipeline() throws Exception { - - for (int i = 0; i < 10; i++) { - DynoJedisPipeline pipeline = client.pipelined(); - - Map bar = new HashMap(); - bar.put("key__1".getBytes(), "value__1".getBytes()); - bar.put("key__2".getBytes(), "value__2".getBytes()); - - Response hmsetResult = pipeline.hmset(("hash__" + i).getBytes(), bar); - - pipeline.sync(); - - System.out.println(hmsetResult.get()); - } - - System.out.println("Reading all keys"); - - DynoJedisPipeline readPipeline = client.pipelined(); - Response> resp = readPipeline.hgetAll("hash__1".getBytes()); - readPipeline.sync(); - - StringBuilder sb = new StringBuilder(); - for (byte[] bytes : resp.get().keySet()) { - if (sb.length() > 0) { - sb.append(","); - } - sb.append(new String(bytes)); - } - System.out.println("Got hash :" + sb.toString()); - } - - public void runCompressionInPipelineTest() throws Exception { - final int maxNumKeys = 100; - final int maxPipelineSize = 10; - final int maxOperations = 500; - final Random rand = new Random(); - - for (int operationIter = 0; operationIter < maxOperations; operationIter++) { - - DynoJedisPipeline pipeline = client.pipelined(); - int pipelineSize = 1 + rand.nextInt(maxPipelineSize); - - // key to be used in pipeline - String key = "hash__" + rand.nextInt(maxNumKeys); - - // Map of field -> value - Map map = new HashMap<>(); - - // List of fields to be later used in HMGet - List fields = new ArrayList<>(pipelineSize); - - // Create a map of field -> value, also accumulate all fields - for (int pipelineIter = 0; pipelineIter < pipelineSize; pipelineIter++) { - String field = "field_" + pipelineIter; - fields.add(field); - String prefixSuffix = key + "_" + field; - String value = prefixSuffix + "_" + generateValue(pipelineIter) + "_" + prefixSuffix; - map.put(field, value); - } - - Response HMSetResult = pipeline.hmset(key, map); - Response> HMGetResult = pipeline.hmget(key, fields.toArray(new String[fields.size()])); - try { - pipeline.sync(); - } catch (Exception e) { - pipeline.discardPipelineAndReleaseConnection(); - System.out.println("Exception while writing key " + key + " fields: " + fields); - throw e; - } - - if (!HMSetResult.get().equals("OK")) { - System.out.println("Result mismatch for HMSet key: '" + key + "' fields: '" + fields + "' result: '" - + HMSetResult.get() + "'"); - } - if ((operationIter % 100) == 0) { - System.out.println("\n>>>>>>>> " + operationIter + " operations performed...."); - } - List HMGetResultStrings = HMGetResult.get(); - for (int i = 0; i < HMGetResultStrings.size(); i++) { - String prefixSuffix = key + "_" + fields.get(i); - String value = HMGetResultStrings.get(i); - if (value.startsWith(prefixSuffix) && value.endsWith(prefixSuffix)) { - continue; - } else { - System.out.println("Result mismatch key: '" + key + "' field: '" + fields.get(i) + "' value: '" - + HMGetResultStrings.get(i) + "'"); - } - - } - } - System.out.println("Compression test Done: " + maxOperations + " pipeline operations performed."); - - } - - public void runSandboxTest() throws Exception { - Set keys = client.keys("zuulRules:*"); - System.out.println("GOT KEYS"); - System.out.println(keys.size()); - } - - private static String generateValue(int kilobytes) { - StringBuilder sb = new StringBuilder(kilobytes * 512); // estimating 2 - // bytes per char - for (int i = 0; i < kilobytes; i++) { - for (int j = 0; j < 10; j++) { - sb.append("abcdefghijklmnopqrstuvwxzy0123456789a1b2c3d4f5g6h7"); // 50 - // characters - // (~100 - // bytes) - sb.append(":"); - sb.append("abcdefghijklmnopqrstuvwxzy0123456789a1b2c3d4f5g6h7"); - sb.append(":"); - } - } - - return sb.toString(); - - } - - /** - * This demo runs a pipeline across ten different keys. The pipeline leverages - * the hash value {bar} to determine the node where to send the data. - * - * @throws Exception - */ - public void runPipelineWithHashtag() throws Exception { - - DynoJedisPipeline pipeline = client.pipelined(); - try { - - pipeline.set("pipeline-hashtag1-{bar}", "value-1"); - pipeline.set("pipeline-hashtag2-{bar}", "value-2"); - pipeline.set("pipeline-hashtag3-{bar}", "value-3"); - pipeline.set("pipeline-hashtag4-{bar}", "value-4"); - pipeline.set("pipeline-hashtag5-{bar}", "value-5"); - pipeline.set("pipeline-hashtag6-{bar}", "value-6"); - pipeline.set("pipeline-hashtag7-{bar}", "value-7"); - pipeline.set("pipeline-hashtag8-{bar}", "value-8"); - pipeline.set("pipeline-hashtag9-{bar}", "value-9"); - pipeline.set("pipeline-hashtag10-{bar}", "value-10"); - - Response value1 = pipeline.get("pipeline-hashtag1-{bar}"); - Response value2 = pipeline.get("pipeline-hashtag2-{bar}"); - Response value3 = pipeline.get("pipeline-hashtag3-{bar}"); - Response value4 = pipeline.get("pipeline-hashtag4-{bar}"); - Response value5 = pipeline.get("pipeline-hashtag5-{bar}"); - Response value6 = pipeline.get("pipeline-hashtag6-{bar}"); - pipeline.sync(); - - System.out.println(value1.get()); - System.out.println(value2.get()); - System.out.println(value3.get()); - System.out.println(value4.get()); - System.out.println(value5.get()); - System.out.println(value6.get()); - } catch (Exception e) { - pipeline.discardPipelineAndReleaseConnection(); - throw e; - } - } - - public void runPipeline() throws Exception { - - int numThreads = 5; - - final ExecutorService threadPool = Executors.newFixedThreadPool(numThreads); - final AtomicBoolean stop = new AtomicBoolean(false); - final CountDownLatch latch = new CountDownLatch(numThreads); - - for (int i = 0; i < numThreads; i++) { - threadPool.submit(new Callable() { - - final Random rand = new Random(); - - @Override - public Void call() throws Exception { - - final AtomicInteger iter = new AtomicInteger(0); - - while (!stop.get()) { - int index = rand.nextInt(5); - int i = iter.incrementAndGet(); - DynoJedisPipeline pipeline = client.pipelined(); - - try { - Response resultA1 = pipeline.hset("DynoJedisDemo_pipeline-" + index, "a1", - constructRandomValue(index)); - Response resultA2 = pipeline.hset("DynoJedisDemo_pipeline-" + index, "a2", - "value-" + i); - - pipeline.sync(); + try { + String value = client.get("DynoDemoTest" + key); + success.incrementAndGet(); + if (value == null || value.isEmpty()) { + emptyReads.incrementAndGet(); + } + } catch (Exception e) { + System.out.println("READ FAILURE: " + e.getMessage()); + failure.incrementAndGet(); + } + } + + latch.countDown(); + return null; + } + }); + } + } + + public void stop() { + if (client != null) { + client.stopClient(); + } + } + + private List readHostsFromFile(String filename, int port) throws Exception { + + List hosts = new ArrayList(); + File file = new File(filename); + BufferedReader reader = new BufferedReader(new FileReader(file)); + + try { + String line = null; + while ((line = reader.readLine()) != null) { + if (line.trim().isEmpty()) { + continue; + } + String[] parts = line.trim().split(" "); + if (parts.length != 2) { + throw new RuntimeException("Bad data format in file:" + line); + } + Host host = new Host(parts[0].trim(), port, parts[1].trim(), Status.Up); + hosts.add(host); + } + } finally { + reader.close(); + } + return hosts; + } + + public void runBinarySinglePipeline() throws Exception { + + for (int i = 0; i < 10; i++) { + DynoJedisPipeline pipeline = client.pipelined(); + + Map bar = new HashMap(); + bar.put("key__1".getBytes(), "value__1".getBytes()); + bar.put("key__2".getBytes(), "value__2".getBytes()); + + Response hmsetResult = pipeline.hmset(("hash__" + i).getBytes(), bar); + + pipeline.sync(); + + System.out.println(hmsetResult.get()); + } + + System.out.println("Reading all keys"); + + DynoJedisPipeline readPipeline = client.pipelined(); + Response> resp = readPipeline.hgetAll("hash__1".getBytes()); + readPipeline.sync(); + + StringBuilder sb = new StringBuilder(); + for (byte[] bytes : resp.get().keySet()) { + if (sb.length() > 0) { + sb.append(","); + } + sb.append(new String(bytes)); + } + System.out.println("Got hash :" + sb.toString()); + } + + public void runCompressionInPipelineTest() throws Exception { + final int maxNumKeys = 100; + final int maxPipelineSize = 10; + final int maxOperations = 500; + final Random rand = new Random(); + + for (int operationIter = 0; operationIter < maxOperations; operationIter++) { + + DynoJedisPipeline pipeline = client.pipelined(); + int pipelineSize = 1 + rand.nextInt(maxPipelineSize); + + // key to be used in pipeline + String key = "hash__" + rand.nextInt(maxNumKeys); + + // Map of field -> value + Map map = new HashMap<>(); + + // List of fields to be later used in HMGet + List fields = new ArrayList<>(pipelineSize); + + // Create a map of field -> value, also accumulate all fields + for (int pipelineIter = 0; pipelineIter < pipelineSize; pipelineIter++) { + String field = "field_" + pipelineIter; + fields.add(field); + String prefixSuffix = key + "_" + field; + String value = prefixSuffix + "_" + generateValue(pipelineIter) + "_" + prefixSuffix; + map.put(field, value); + } + + Response HMSetResult = pipeline.hmset(key, map); + Response> HMGetResult = pipeline.hmget(key, fields.toArray(new String[fields.size()])); + try { + pipeline.sync(); + } catch (Exception e) { + pipeline.discardPipelineAndReleaseConnection(); + System.out.println("Exception while writing key " + key + " fields: " + fields); + throw e; + } + + if (!HMSetResult.get().equals("OK")) { + System.out.println("Result mismatch for HMSet key: '" + key + "' fields: '" + fields + "' result: '" + + HMSetResult.get() + "'"); + } + if ((operationIter % 100) == 0) { + System.out.println("\n>>>>>>>> " + operationIter + " operations performed...."); + } + List HMGetResultStrings = HMGetResult.get(); + for (int i = 0; i < HMGetResultStrings.size(); i++) { + String prefixSuffix = key + "_" + fields.get(i); + String value = HMGetResultStrings.get(i); + if (value.startsWith(prefixSuffix) && value.endsWith(prefixSuffix)) { + continue; + } else { + System.out.println("Result mismatch key: '" + key + "' field: '" + fields.get(i) + "' value: '" + + HMGetResultStrings.get(i) + "'"); + } + + } + } + System.out.println("Compression test Done: " + maxOperations + " pipeline operations performed."); + + } + + public void runSandboxTest() throws Exception { + Set keys = client.keys("zuulRules:*"); + System.out.println("GOT KEYS"); + System.out.println(keys.size()); + } + + private static String generateValue(int kilobytes) { + StringBuilder sb = new StringBuilder(kilobytes * 512); // estimating 2 + // bytes per char + for (int i = 0; i < kilobytes; i++) { + for (int j = 0; j < 10; j++) { + sb.append("abcdefghijklmnopqrstuvwxzy0123456789a1b2c3d4f5g6h7"); // 50 + // characters + // (~100 + // bytes) + sb.append(":"); + sb.append("abcdefghijklmnopqrstuvwxzy0123456789a1b2c3d4f5g6h7"); + sb.append(":"); + } + } + + return sb.toString(); + + } + + /** + * This demo runs a pipeline across ten different keys. The pipeline leverages + * the hash value {bar} to determine the node where to send the data. + * + * @throws Exception + */ + public void runPipelineWithHashtag() throws Exception { + + DynoJedisPipeline pipeline = client.pipelined(); + try { + + pipeline.set("pipeline-hashtag1-{bar}", "value-1"); + pipeline.set("pipeline-hashtag2-{bar}", "value-2"); + pipeline.set("pipeline-hashtag3-{bar}", "value-3"); + pipeline.set("pipeline-hashtag4-{bar}", "value-4"); + pipeline.set("pipeline-hashtag5-{bar}", "value-5"); + pipeline.set("pipeline-hashtag6-{bar}", "value-6"); + pipeline.set("pipeline-hashtag7-{bar}", "value-7"); + pipeline.set("pipeline-hashtag8-{bar}", "value-8"); + pipeline.set("pipeline-hashtag9-{bar}", "value-9"); + pipeline.set("pipeline-hashtag10-{bar}", "value-10"); + + Response value1 = pipeline.get("pipeline-hashtag1-{bar}"); + Response value2 = pipeline.get("pipeline-hashtag2-{bar}"); + Response value3 = pipeline.get("pipeline-hashtag3-{bar}"); + Response value4 = pipeline.get("pipeline-hashtag4-{bar}"); + Response value5 = pipeline.get("pipeline-hashtag5-{bar}"); + Response value6 = pipeline.get("pipeline-hashtag6-{bar}"); + pipeline.sync(); + + System.out.println(value1.get()); + System.out.println(value2.get()); + System.out.println(value3.get()); + System.out.println(value4.get()); + System.out.println(value5.get()); + System.out.println(value6.get()); + } catch (Exception e) { + pipeline.discardPipelineAndReleaseConnection(); + throw e; + } + } + + public void runPipeline() throws Exception { + + int numThreads = 5; + + final ExecutorService threadPool = Executors.newFixedThreadPool(numThreads); + final AtomicBoolean stop = new AtomicBoolean(false); + final CountDownLatch latch = new CountDownLatch(numThreads); + + for (int i = 0; i < numThreads; i++) { + threadPool.submit(new Callable() { + + final Random rand = new Random(); + + @Override + public Void call() throws Exception { + + final AtomicInteger iter = new AtomicInteger(0); + + while (!stop.get()) { + int index = rand.nextInt(5); + int i = iter.incrementAndGet(); + DynoJedisPipeline pipeline = client.pipelined(); + + try { + Response resultA1 = pipeline.hset("DynoJedisDemo_pipeline-" + index, "a1", + constructRandomValue(index)); + Response resultA2 = pipeline.hset("DynoJedisDemo_pipeline-" + index, "a2", + "value-" + i); + + pipeline.sync(); - System.out.println(resultA1.get() + " " + resultA2.get()); - - } catch (Exception e) { - pipeline.discardPipelineAndReleaseConnection(); - throw e; - } - - } - latch.countDown(); - return null; - } - }); - } - - Thread.sleep(5000); - stop.set(true); - latch.await(); + System.out.println(resultA1.get() + " " + resultA2.get()); + + } catch (Exception e) { + pipeline.discardPipelineAndReleaseConnection(); + throw e; + } + + } + latch.countDown(); + return null; + } + }); + } + + Thread.sleep(5000); + stop.set(true); + latch.await(); - threadPool.shutdownNow(); - } + threadPool.shutdownNow(); + } - private String constructRandomValue(int sizeInKB) { + private String constructRandomValue(int sizeInKB) { - int requriredLength = sizeInKB * 1024; - - String s = randomValue; - int sLength = s.length(); - - StringBuilder sb = new StringBuilder(); - int lengthSoFar = 0; + int requriredLength = sizeInKB * 1024; + + String s = randomValue; + int sLength = s.length(); + + StringBuilder sb = new StringBuilder(); + int lengthSoFar = 0; - do { - sb.append(s); - lengthSoFar += sLength; - } while (lengthSoFar < requriredLength); + do { + sb.append(s); + lengthSoFar += sLength; + } while (lengthSoFar < requriredLength); - String ss = sb.toString(); + String ss = sb.toString(); - if (ss.length() > requriredLength) { - ss = sb.substring(0, requriredLength); - } + if (ss.length() > requriredLength) { + ss = sb.substring(0, requriredLength); + } - return ss; - } + return ss; + } - private List getHostsFromDiscovery(final String clusterName) { + private List getHostsFromDiscovery(final String clusterName) { - String env = System.getProperty("netflix.environment", "test"); - String discoveryKey = String.format("dyno.demo.discovery.%s", env); + String env = System.getProperty("netflix.environment", "test"); + String discoveryKey = String.format("dyno.demo.discovery.%s", env); - if (!System.getProperties().containsKey(discoveryKey)) { - throw new IllegalArgumentException("Discovery URL not found"); - } + if (!System.getProperties().containsKey(discoveryKey)) { + throw new IllegalArgumentException("Discovery URL not found"); + } - String localDatacenter = System.getProperty("LOCAL_DATACENTER"); - final String discoveryUrl = String.format(System.getProperty(discoveryKey), localDatacenter); + String localDatacenter = System.getProperty("LOCAL_DATACENTER"); + final String discoveryUrl = String.format(System.getProperty(discoveryKey), localDatacenter); - final String url = String.format("http://%s/%s", discoveryUrl, clusterName); + final String url = String.format("http://%s/%s", discoveryUrl, clusterName); - HttpClient client = new DefaultHttpClient(); - try { - HttpResponse response = client.execute(new HttpGet(url)); - InputStream in = response.getEntity().getContent(); + HttpClient client = new DefaultHttpClient(); + try { + HttpResponse response = client.execute(new HttpGet(url)); + InputStream in = response.getEntity().getContent(); - SAXParserFactory parserFactor = SAXParserFactory.newInstance(); + SAXParserFactory parserFactor = SAXParserFactory.newInstance(); - SAXParser parser = parserFactor.newSAXParser(); - SAXHandler handler = new SAXHandler("instance", "public-hostname", "availability-zone", "status", - "local-ipv4"); - parser.parse(in, handler); + SAXParser parser = parserFactor.newSAXParser(); + SAXHandler handler = new SAXHandler("instance", "public-hostname", "availability-zone", "status", + "local-ipv4"); + parser.parse(in, handler); - List hosts = new ArrayList(); + List hosts = new ArrayList(); - for (Map map : handler.getList()) { - String rack = map.get("availability-zone"); - Status status = map.get("status").equalsIgnoreCase("UP") ? Status.Up : Status.Down; - Host host = new Host(map.get("public-hostname"), map.get("local-ipv4"), rack, status); - hosts.add(host); - System.out.println("Host: " + host); - } + for (Map map : handler.getList()) { + String rack = map.get("availability-zone"); + Status status = map.get("status").equalsIgnoreCase("UP") ? Status.Up : Status.Down; + Host host = new Host(map.get("public-hostname"), map.get("local-ipv4"), rack, status); + hosts.add(host); + System.out.println("Host: " + host); + } - return hosts; - } catch (Throwable e) { - throw new RuntimeException(e); - } - } + return hosts; + } catch (Throwable e) { + throw new RuntimeException(e); + } + } - public void runLongTest() throws InterruptedException { + public void runLongTest() throws InterruptedException { - final ExecutorService threadPool = Executors.newFixedThreadPool(2); + final ExecutorService threadPool = Executors.newFixedThreadPool(2); - final AtomicBoolean stop = new AtomicBoolean(false); - final CountDownLatch latch = new CountDownLatch(2); + final AtomicBoolean stop = new AtomicBoolean(false); + final CountDownLatch latch = new CountDownLatch(2); - final AtomicInteger success = new AtomicInteger(0); - final AtomicInteger failure = new AtomicInteger(0); - final AtomicInteger emptyReads = new AtomicInteger(0); + final AtomicInteger success = new AtomicInteger(0); + final AtomicInteger failure = new AtomicInteger(0); + final AtomicInteger emptyReads = new AtomicInteger(0); - threadPool.submit(new Callable() { + threadPool.submit(new Callable() { - @Override - public Void call() throws Exception { - while (!stop.get()) { - System.out.println("Getting Value for key '0'"); - String value = client.get("0"); - System.out.println("Got Value for key '0' : " + value); - Thread.sleep(5000); - } - latch.countDown(); - return null; - } + @Override + public Void call() throws Exception { + while (!stop.get()) { + System.out.println("Getting Value for key '0'"); + String value = client.get("0"); + System.out.println("Got Value for key '0' : " + value); + Thread.sleep(5000); + } + latch.countDown(); + return null; + } - }); + }); - threadPool.submit(new Callable() { + threadPool.submit(new Callable() { - @Override - public Void call() throws Exception { - while (!stop.get()) { - System.out.println("Success: " + success.get() + ", failure: " + failure.get() + ", emptyReads: " - + emptyReads.get()); - Thread.sleep(1000); - } - latch.countDown(); - return null; - } - - }); - - Thread.sleep(60 * 1000); - - stop.set(true); - latch.await(); - threadPool.shutdownNow(); - } - - private class SAXHandler extends DefaultHandler { - - private final List> list = new ArrayList>(); - private final String rootElement; - private final Set interestElements = new HashSet(); - - private Map currentPayload = null; - private String currentInterestElement = null; - - private SAXHandler(String root, String... interests) { - - rootElement = root; - for (String s : interests) { - interestElements.add(s); - } - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) - throws SAXException { - - if (qName.equalsIgnoreCase(rootElement)) { - // prep for next instance - currentPayload = new HashMap(); - return; - } - - if (interestElements.contains(qName)) { - // note the element to be parsed. this will be used in chars - // callback - currentInterestElement = qName; - } - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - - // add host to list - if (qName.equalsIgnoreCase(rootElement)) { - list.add(currentPayload); - currentPayload = null; - } - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - - String value = new String(ch, start, length); - - if (currentInterestElement != null && currentPayload != null) { - currentPayload.put(currentInterestElement, value); - currentInterestElement = null; - } - } - - public List> getList() { - return list; - } - } - - public void runEvalTest() throws Exception { - - client.set("EvalTest", "true"); - - List keys = Lists.newArrayList("EvalTest"); - List args = Lists.newArrayList("true"); - Object obj = client.eval( - "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end", - keys, args); - if (obj.toString().equals("1")) - System.out.println("EVAL Test Succeeded"); - else - System.out.println("EVAL Test Failed"); - - } - - private void runJsonTest() throws Exception { - DynoJedisJsonClient jsonClient = new DynoJedisJsonClient(this.client); - Gson gson = new Gson(); - List list = new ArrayList<>(); - list.add("apple"); - list.add("orange"); - Map> map = new HashMap<>(); - map.put("fruits", list); - final JsonPath jsonPath = new JsonPath().appendSubKey("fruits"); - - System.out.println("Get path: " + jsonPath.toString()); - System.out.println("inserting json: " + list); - OperationResult set1Result = jsonClient.set("test1", map); - OperationResult set2Result = jsonClient.set("test2", map); - OperationResult arrappendResult = jsonClient.arrappend("test1", - new JsonPath().appendSubKey("fruits"), "mango"); - OperationResult arrinsertResult = jsonClient.arrinsert("test1", - new JsonPath().appendSubKey("fruits"), 0,"banana"); - OperationResult set3Result = jsonClient.set("test1", new JsonPath().appendSubKey("flowers"), - Arrays.asList("rose", "lily")); - OperationResult> typeResult = jsonClient.type("test1"); - OperationResult get1Result = jsonClient.get("test1", jsonPath); - OperationResult get2Result = jsonClient.get("test2", jsonPath); - OperationResult> mgetResult = jsonClient.mget(Arrays.asList("test1", "test2"), jsonPath.atIndex(-1)); - OperationResult> objkeysResult = jsonClient.objkeys("test1"); - OperationResult objlenResult = jsonClient.objlen("test1"); - OperationResult del1Result = jsonClient.del("test1"); - OperationResult del2Result = jsonClient.del("test2"); - - System.out.println("Json set1 result: " + set1Result.getResult()); - System.out.println("Json set2 result: " + set2Result.getResult()); - System.out.println("Json arrappend result: " + arrappendResult.getResult()); - System.out.println("Json addinsert result: " + arrinsertResult.getResult()); - System.out.println("Json set3 result: " + set3Result.getResult()); - System.out.println("Json type result: " + typeResult.getResult().getTypeName()); - System.out.println("Json get1 result: " + get1Result.getResult()); - System.out.println("Json get2 result: " + get2Result.getResult()); - System.out.println("Json mget result: " + mgetResult.getResult()); - System.out.println("Json del1 result: " + del1Result.getResult()); - System.out.println("Json del2 result: " + del2Result.getResult()); - System.out.println("Json objkeys result: " + objkeysResult.getResult()); - System.out.println("Json objlen result: " + objlenResult.getResult()); - } - - public void runEvalShaTest() throws Exception { - client.set("EvalShaTestKey", "EVALSHA_WORKS"); - - List keys = Lists.newArrayList("EvalShaTestKey"); - List args = Lists.newArrayList(); - - String script_hash = client.scriptLoad("return redis.call('get', KEYS[1])"); - - // Make sure that the script is saved in Redis' script cache. - if (client.scriptExists(script_hash) == Boolean.FALSE) { - throw new Exception("Test failed. Script did not exist when it should have."); - } - - Object obj = client.evalsha(script_hash, keys, args); - if (obj.toString().equals("EVALSHA_WORKS")) - System.out.println("EVALSHA Test Succeeded"); - else - throw new Exception("EVALSHA Test Failed. Expected: 'EVALSHA_WORKS'; Got: '" + obj.toString()); - - // Flush the script cache. - client.scriptFlush(); - - // Make sure that the script is no longer in the cache. - if (client.scriptExists(script_hash) == Boolean.TRUE) { - throw new Exception("Test failed. Script existed when it shouldn't have."); - } - - // Clean up the created key. - client.del(keys.get(0)); - - System.out.println("SCRIPT EXISTS and SCRIPT FLUSH Test succeeded."); - } - - private void runExpireHashTest() throws Exception { - this.numKeys = 10; - System.out.println("Expire hash test selected"); - - // write - long ttl = 5; // seconds - for (int i = 0; i < numKeys; i++) { - System.out.println("Writing key/value => DynoClientTest-" + i + " / " + i); - client.ehset("DynoClientTest","DynoClientTest-" + i, "" + i, ttl); - } - - // read - System.out.println("Reading expire hash values (before ttl expiry)"); - for (int i = 0; i < numKeys; i++) { - String val = client.ehget("DynoClientTest", "DynoClientTest-" + i); - System.out.println("Reading Key: " + i + ", Value: " + val); - } - - // sleep for seconds - Thread.sleep(ttl * 1000); - - // read after expiry - System.out.println("Reading expire hash values (after ttl expiry)"); - for (int i = 0; i < numKeys; i++) { - String val = client.ehget("DynoClientTest", "DynoClientTest-" + i); - System.out.println("Reading Key: " + i + ", Value: " + val); - } - } - - /** - * - * @param args - *
    - * -l | -p [-s ] -t - *
- *
    - * -l,--localhost localhost - * -p,--primaryCluster Primary cluster - * -s,--shadowCluster Shadow cluster - * -t,--test Test to run - *
- */ - public static void main(String args[]) throws IOException { - Option primaryCluster = new Option("p", "primaryCluster", true, "Primary cluster"); - primaryCluster.setArgName("clusterName"); - - Option secondaryCluster = new Option("s","shadowCluster", true, "Shadow cluster"); - secondaryCluster.setArgName("clusterName"); - - Option localhost = new Option("l", "localhost", false, "localhost"); - Option test = new Option("t", "test", true, "Test to run"); - test.setArgName("testNumber"); - test.setRequired(true); - - OptionGroup cluster = new OptionGroup() - .addOption(localhost) - .addOption(primaryCluster); - cluster.setRequired(true); - - Options options = new Options(); - options.addOptionGroup(cluster) - .addOption(secondaryCluster) - .addOption(test); - - Properties props = new Properties(); - props.load(DynoJedisDemo.class.getResourceAsStream("/demo.properties")); - for (String name : props.stringPropertyNames()) { - System.setProperty(name, props.getProperty(name)); - } - - if (!props.containsKey("EC2_AVAILABILITY_ZONE") && !props.containsKey("dyno.demo.lbStrategy")) { - throw new IllegalArgumentException( - "MUST set local for load balancing OR set the load balancing strategy to round robin"); - } - - String rack = props.getProperty("EC2_AVAILABILITY_ZONE", null); - String hostsFile = props.getProperty("dyno.demo.hostsFile"); - String shadowHostsFile = props.getProperty("dyno.demo.shadowHostsFile"); - int port = Integer.valueOf(props.getProperty("dyno.demo.port", "8102")); - - DynoJedisDemo demo = null; - try { - CommandLineParser parser = new DefaultParser(); - CommandLine cli = parser.parse(options, args); - - int testNumber = Integer.parseInt(cli.getOptionValue("t")); - if (cli.hasOption("l")) { - demo = new DynoJedisDemo("dyno-localhost", rack); - demo.initWithLocalHost(); - } else { - demo = new DynoJedisDemo(cli.getOptionValue("p"), rack); - if (!cli.hasOption("s")) { - if (hostsFile != null) { - demo.initWithRemoteClusterFromFile(hostsFile, port); - } else { - demo.initWithRemoteClusterFromEurekaUrl(cli.getOptionValue("p"), port); - } - } else { - if (hostsFile != null) { - demo.initDualClientWithRemoteClustersFromFile(hostsFile, shadowHostsFile, port); - } else { - demo.initDualClientWithRemoteClustersFromEurekaUrl(cli.getOptionValue("p"), - cli.getOptionValue("s")); - } - } - } - System.out.println("Connected"); - - switch (testNumber) { - case 1: { - demo.runSimpleTest(); - break; - } - case 2: { - demo.runKeysTest(); - break; - } - case 3: { - demo.runSimpleTestWithHashtag(); - break; - } - case 4: { - demo.runMultiThreaded(); - break; - } - case 5: { - final boolean writeKeys = Boolean.valueOf(props.getProperty("dyno.demo.scan.populateKeys")); - demo.runScanTest(writeKeys); - break; - } - case 6: { - demo.runPipeline(); - break; - } - case 7: { - demo.runPipelineWithHashtag(); - break; - } - case 8: { - demo.runSScanTest(true); - break; - } - case 9: { - demo.runCompressionInPipelineTest(); - break; - } - case 10: { - demo.runEvalTest(); - demo.runEvalShaTest(); - break; - } - - case 11: { - demo.runBinaryKeyTest(); - break; - } - - case 12: { - demo.runExpireHashTest(); - break; - } - - case 13: { - demo.runJsonTest(); - break; - } - } - - // demo.runSinglePipeline(); - // demo.runPipeline(); - // demo.runBinarySinglePipeline(); - // demo.runPipelineEmptyResult(); - // demo.runSinglePipelineWithCompression(false); - // demo.runLongTest(); - // demo.runSandboxTest(); - - Thread.sleep(1000); - - // demo.cleanup(demo.numKeys); - - } catch (ParseException pe) { - HelpFormatter helpFormatter = new HelpFormatter(); - helpFormatter.printHelp(120, DynoJedisDemo.class.getSimpleName(), "", options, "", true); - } catch (Throwable e) { - e.printStackTrace(); - } finally { - if (demo != null) { - demo.stop(); - } - System.out.println("Done"); - - System.out.flush(); - System.err.flush(); - System.exit(0); - } - } + @Override + public Void call() throws Exception { + while (!stop.get()) { + System.out.println("Success: " + success.get() + ", failure: " + failure.get() + ", emptyReads: " + + emptyReads.get()); + Thread.sleep(1000); + } + latch.countDown(); + return null; + } + + }); + + Thread.sleep(60 * 1000); + + stop.set(true); + latch.await(); + threadPool.shutdownNow(); + } + + private class SAXHandler extends DefaultHandler { + + private final List> list = new ArrayList>(); + private final String rootElement; + private final Set interestElements = new HashSet(); + + private Map currentPayload = null; + private String currentInterestElement = null; + + private SAXHandler(String root, String... interests) { + + rootElement = root; + for (String s : interests) { + interestElements.add(s); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + + if (qName.equalsIgnoreCase(rootElement)) { + // prep for next instance + currentPayload = new HashMap(); + return; + } + + if (interestElements.contains(qName)) { + // note the element to be parsed. this will be used in chars + // callback + currentInterestElement = qName; + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + + // add host to list + if (qName.equalsIgnoreCase(rootElement)) { + list.add(currentPayload); + currentPayload = null; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + + String value = new String(ch, start, length); + + if (currentInterestElement != null && currentPayload != null) { + currentPayload.put(currentInterestElement, value); + currentInterestElement = null; + } + } + + public List> getList() { + return list; + } + } + + public void runEvalTest() throws Exception { + + client.set("EvalTest", "true"); + + List keys = Lists.newArrayList("EvalTest"); + List args = Lists.newArrayList("true"); + Object obj = client.eval( + "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end", + keys, args); + if (obj.toString().equals("1")) + System.out.println("EVAL Test Succeeded"); + else + System.out.println("EVAL Test Failed"); + + } + + private void runJsonTest() throws Exception { + DynoJedisJsonClient jsonClient = new DynoJedisJsonClient(this.client); + Gson gson = new Gson(); + List list = new ArrayList<>(); + list.add("apple"); + list.add("orange"); + Map> map = new HashMap<>(); + map.put("fruits", list); + final JsonPath jsonPath = new JsonPath().appendSubKey("fruits"); + + System.out.println("Get path: " + jsonPath.toString()); + System.out.println("inserting json: " + list); + OperationResult set1Result = jsonClient.set("test1", map); + OperationResult set2Result = jsonClient.set("test2", map); + OperationResult arrappendResult = jsonClient.arrappend("test1", + new JsonPath().appendSubKey("fruits"), "mango"); + OperationResult arrinsertResult = jsonClient.arrinsert("test1", + new JsonPath().appendSubKey("fruits"), 0, "banana"); + OperationResult set3Result = jsonClient.set("test1", new JsonPath().appendSubKey("flowers"), + Arrays.asList("rose", "lily")); + OperationResult> typeResult = jsonClient.type("test1"); + OperationResult get1Result = jsonClient.get("test1", jsonPath); + OperationResult get2Result = jsonClient.get("test2", jsonPath); + OperationResult> mgetResult = jsonClient.mget(Arrays.asList("test1", "test2"), jsonPath.atIndex(-1)); + OperationResult> objkeysResult = jsonClient.objkeys("test1"); + OperationResult objlenResult = jsonClient.objlen("test1"); + OperationResult del1Result = jsonClient.del("test1"); + OperationResult del2Result = jsonClient.del("test2"); + + System.out.println("Json set1 result: " + set1Result.getResult()); + System.out.println("Json set2 result: " + set2Result.getResult()); + System.out.println("Json arrappend result: " + arrappendResult.getResult()); + System.out.println("Json addinsert result: " + arrinsertResult.getResult()); + System.out.println("Json set3 result: " + set3Result.getResult()); + System.out.println("Json type result: " + typeResult.getResult().getTypeName()); + System.out.println("Json get1 result: " + get1Result.getResult()); + System.out.println("Json get2 result: " + get2Result.getResult()); + System.out.println("Json mget result: " + mgetResult.getResult()); + System.out.println("Json del1 result: " + del1Result.getResult()); + System.out.println("Json del2 result: " + del2Result.getResult()); + System.out.println("Json objkeys result: " + objkeysResult.getResult()); + System.out.println("Json objlen result: " + objlenResult.getResult()); + } + + public void runEvalShaTest() throws Exception { + client.set("EvalShaTestKey", "EVALSHA_WORKS"); + + List keys = Lists.newArrayList("EvalShaTestKey"); + List args = Lists.newArrayList(); + + String script_hash = client.scriptLoad("return redis.call('get', KEYS[1])"); + + // Make sure that the script is saved in Redis' script cache. + if (client.scriptExists(script_hash) == Boolean.FALSE) { + throw new Exception("Test failed. Script did not exist when it should have."); + } + + Object obj = client.evalsha(script_hash, keys, args); + if (obj.toString().equals("EVALSHA_WORKS")) + System.out.println("EVALSHA Test Succeeded"); + else + throw new Exception("EVALSHA Test Failed. Expected: 'EVALSHA_WORKS'; Got: '" + obj.toString()); + + // Flush the script cache. + client.scriptFlush(); + + // Make sure that the script is no longer in the cache. + if (client.scriptExists(script_hash) == Boolean.TRUE) { + throw new Exception("Test failed. Script existed when it shouldn't have."); + } + + // Clean up the created key. + client.del(keys.get(0)); + + System.out.println("SCRIPT EXISTS and SCRIPT FLUSH Test succeeded."); + } + + private void runExpireHashTest() throws Exception { + this.numKeys = 10; + System.out.println("Expire hash test selected"); + + // write + long ttl = 5; // seconds + for (int i = 0; i < numKeys; i++) { + System.out.println("Writing key/value => DynoClientTest-" + i + " / " + i); + client.ehset("DynoClientTest", "DynoClientTest-" + i, "" + i, ttl); + } + + // read + System.out.println("Reading expire hash values (before ttl expiry)"); + for (int i = 0; i < numKeys; i++) { + String val = client.ehget("DynoClientTest", "DynoClientTest-" + i); + System.out.println("Reading Key: " + i + ", Value: " + val); + } + + // sleep for seconds + Thread.sleep(ttl * 1000); + + // read after expiry + System.out.println("Reading expire hash values (after ttl expiry)"); + for (int i = 0; i < numKeys; i++) { + String val = client.ehget("DynoClientTest", "DynoClientTest-" + i); + System.out.println("Reading Key: " + i + ", Value: " + val); + } + } + + /** + * @param args
    + * -l | -p [-s ] -t + *
+ *
    + * -l,--localhost localhost + * -p,--primaryCluster Primary cluster + * -s,--shadowCluster Shadow cluster + * -t,--test Test to run + *
+ */ + public static void main(String args[]) throws IOException { + Option primaryCluster = new Option("p", "primaryCluster", true, "Primary cluster"); + primaryCluster.setArgName("clusterName"); + + Option secondaryCluster = new Option("s", "shadowCluster", true, "Shadow cluster"); + secondaryCluster.setArgName("clusterName"); + + Option localhost = new Option("l", "localhost", false, "localhost"); + Option test = new Option("t", "test", true, "Test to run"); + test.setArgName("testNumber"); + test.setRequired(true); + + OptionGroup cluster = new OptionGroup() + .addOption(localhost) + .addOption(primaryCluster); + cluster.setRequired(true); + + Options options = new Options(); + options.addOptionGroup(cluster) + .addOption(secondaryCluster) + .addOption(test); + + Properties props = new Properties(); + props.load(DynoJedisDemo.class.getResourceAsStream("/demo.properties")); + for (String name : props.stringPropertyNames()) { + System.setProperty(name, props.getProperty(name)); + } + + if (!props.containsKey("EC2_AVAILABILITY_ZONE") && !props.containsKey("dyno.demo.lbStrategy")) { + throw new IllegalArgumentException( + "MUST set local for load balancing OR set the load balancing strategy to round robin"); + } + + String rack = props.getProperty("EC2_AVAILABILITY_ZONE", "us-east-1c"); + String hostsFile = props.getProperty("dyno.demo.hostsFile"); + String shadowHostsFile = props.getProperty("dyno.demo.shadowHostsFile"); + int port = Integer.valueOf(props.getProperty("dyno.demo.port", "8102")); + + DynoJedisDemo demo = null; + try { + CommandLineParser parser = new DefaultParser(); + CommandLine cli = parser.parse(options, args); + + int testNumber = Integer.parseInt(cli.getOptionValue("t")); + if (cli.hasOption("l")) { + demo = new DynoJedisDemo("dyno-localhost", rack); + demo.initWithLocalHost(); + } else { + demo = new DynoJedisDemo(cli.getOptionValue("p"), rack); + if (!cli.hasOption("s")) { + if (hostsFile != null) { + demo.initWithRemoteClusterFromFile(hostsFile, port); + } else { + demo.initWithRemoteClusterFromEurekaUrl(cli.getOptionValue("p"), port); + } + } else { + if (hostsFile != null) { + demo.initDualClientWithRemoteClustersFromFile(hostsFile, shadowHostsFile, port); + } else { + demo.initDualClientWithRemoteClustersFromEurekaUrl(cli.getOptionValue("p"), + cli.getOptionValue("s")); + } + } + } + System.out.println("Connected"); + + switch (testNumber) { + case 1: { + demo.runSimpleTest(); + break; + } + case 2: { + demo.runKeysTest(); + break; + } + case 3: { + demo.runSimpleTestWithHashtag(); + break; + } + case 4: { + demo.runMultiThreaded(); + break; + } + case 5: { + final boolean writeKeys = Boolean.valueOf(props.getProperty("dyno.demo.scan.populateKeys")); + demo.runScanTest(writeKeys); + break; + } + case 6: { + demo.runPipeline(); + break; + } + case 7: { + demo.runPipelineWithHashtag(); + break; + } + case 8: { + demo.runSScanTest(true); + break; + } + case 9: { + demo.runCompressionInPipelineTest(); + break; + } + case 10: { + demo.runEvalTest(); + demo.runEvalShaTest(); + break; + } + + case 11: { + demo.runBinaryKeyTest(); + break; + } + + case 12: { + demo.runExpireHashTest(); + break; + } + + case 13: { + demo.runJsonTest(); + break; + } + } + + // demo.runSinglePipeline(); + // demo.runPipeline(); + // demo.runBinarySinglePipeline(); + // demo.runPipelineEmptyResult(); + // demo.runSinglePipelineWithCompression(false); + // demo.runLongTest(); + // demo.runSandboxTest(); + + Thread.sleep(1000); + + // demo.cleanup(demo.numKeys); + + } catch (ParseException pe) { + HelpFormatter helpFormatter = new HelpFormatter(); + helpFormatter.printHelp(120, DynoJedisDemo.class.getSimpleName(), "", options, "", true); + } catch (Throwable e) { + e.printStackTrace(); + } finally { + if (demo != null) { + demo.stop(); + } + System.out.println("Done"); + + System.out.flush(); + System.err.flush(); + System.exit(0); + } + } } \ No newline at end of file diff --git a/dyno-demo/src/main/resources/demo.properties b/dyno-demo/src/main/resources/demo.properties index 7e8e3532..39dbca24 100644 --- a/dyno-demo/src/main/resources/demo.properties +++ b/dyno-demo/src/main/resources/demo.properties @@ -2,30 +2,24 @@ ## Properties to initialize the demo app # LOCAL_DATACENTER=us-east-1 -#LOCAL_RACK=us-east-1e +LOCAL_RACK=us-east-1e NETFLIX_STACK=dyno_demo -#EC2_AVAILABILITY_ZONE=us-east-1 - -dyno.demo.lbStrategy=TokenAware - +EC2_AVAILABILITY_ZONE=us-east-1c netflix.appinfo.name=dyno_demo netflix.environment=test netflix.appinfo.metadata.enableRoute53=false netflix.discovery.registration.enabled=false netflix.appinfo.validateInstanceId=false - dyno.demo.retryPolicy=RetryNTimes:2 dyno.demo.port=8102 dyno.demo.discovery.prod=discoveryreadonly.%s.dynprod.netflix.net:7001/v2/apps dyno.demo.discovery.test=discoveryreadonly.%s.dyntest.netflix.net:7001/v2/apps - ## # These properties apply to runScanTest(). Note that .prefix will apply only if .populateKeys is true. To query for a # pattern w/out writing anything to the cluster, ensure .populateKeys is false and set the pattern. dyno.demo.scan.populateKeys=false dyno.demo.scan.key.prefix=DynoClientTest_key- dyno.demo.scan.key.pattern=DynoClientTest_key-* - ## Uncomment for hosts file usage #dyno.demo.hostsFile=file:/// diff --git a/dyno-demo/src/main/resources/log4j.xml b/dyno-demo/src/main/resources/log4j.xml index 427e3f83..911cbacc 100644 --- a/dyno-demo/src/main/resources/log4j.xml +++ b/dyno-demo/src/main/resources/log4j.xml @@ -10,12 +10,11 @@ - - - + + \ No newline at end of file diff --git a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/CursorBasedResultImpl.java b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/CursorBasedResultImpl.java index f65cec79..069c65ab 100644 --- a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/CursorBasedResultImpl.java +++ b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/CursorBasedResultImpl.java @@ -56,7 +56,7 @@ public class CursorBasedResultImpl implements CursorBasedResult, TokenRack @Override public List getResult() { final List aggregated = new ArrayList<>(); - for (ScanResult sr: result.values()) { + for (ScanResult sr : result.values()) { aggregated.addAll(sr.getResult()); } return aggregated; @@ -65,7 +65,7 @@ public List getResult() { @Override public List getStringResult() { final List aggregated = new ArrayList<>(); - for (Map.Entry> entry: result.entrySet()) { + for (Map.Entry> entry : result.entrySet()) { aggregated.add(String.format("%s -> %s", entry.getKey(), entry.getValue().getCursor())); } return aggregated; @@ -83,7 +83,7 @@ public String getCursorForHost(String host) { @Override public boolean isComplete() { - for (ScanResult r: result.values()) { + for (ScanResult r : result.values()) { if (!r.getCursor().equals("0")) { return false; } diff --git a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoDualWriterClient.java b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoDualWriterClient.java index 4bc5d41c..d6aa1726 100644 --- a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoDualWriterClient.java +++ b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoDualWriterClient.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -120,7 +120,7 @@ private Future> writeAsync(final String key, Callable Future> writeAsync(final byte[] key, Callable Future> writeAsync(final byte[] key, Callable 0 && dial.isInRange(key); } - + private boolean sendShadowRequest(byte[] key) { - return this.getConnPool().getConfiguration().isDualWriteEnabled() && + return this.getConnPool().getConfiguration().isDualWriteEnabled() && !this.getConnPool().isIdle() && this.getConnPool().getActivePools().size() > 0 && dial.isInRange(key); @@ -188,20 +188,20 @@ public TimestampDial(int range) { @Override public boolean isInRange(String key) { - return range.get() > (System.currentTimeMillis() % 100); + return range.get() > (System.currentTimeMillis() % 100); } - + @Override public boolean isInRange(byte[] key) { - return range.get() > (System.currentTimeMillis() % 100); + return range.get() > (System.currentTimeMillis() % 100); } @Override public void setRange(int range) { this.range.set(range); } - } - + } + //----------------------------- JEDIS COMMANDS -------------------------------------- @@ -225,7 +225,7 @@ public OperationResult call() throws Exception { @Override public OperationResult d_hmset(final String key, final Map hash) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_hmset(key, hash); @@ -294,7 +294,7 @@ public String setex(final String key, int seconds, String value) { @Override public OperationResult d_setex(final String key, final Integer seconds, final String value) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_setex(key, seconds, value); @@ -307,7 +307,7 @@ public OperationResult call() throws Exception { @Override public Long del(final String key) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_del(key); @@ -316,10 +316,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.del(key); } - + @Override public Long expire(final String key, final int seconds) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_expire(key, seconds); @@ -328,10 +328,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.expire(key, seconds); } - + @Override public Long expireAt(final String key, final long unixTime) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_expireAt(key, unixTime); @@ -340,10 +340,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.expireAt(key, unixTime); } - + @Override public String getSet(final String key, final String value) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_getSet(key, value); @@ -352,10 +352,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.getSet(key, value); } - + @Override public Long hdel(final String key, final String... fields) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_hdel(key, fields); @@ -364,10 +364,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.hdel(key); } - + @Override - public Long hincrBy(final String key, final String field, final long value) { - writeAsync(key, new Callable>(){ + public Long hincrBy(final String key, final String field, final long value) { + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_hincrBy(key, field, value); @@ -376,10 +376,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.hincrBy(key, field, value); } - + @Override - public Double hincrByFloat(final String key, final String field, final double value) { - writeAsync(key, new Callable>(){ + public Double hincrByFloat(final String key, final String field, final double value) { + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_hincrByFloat(key, field, value); @@ -388,10 +388,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.hincrByFloat(key, field, value); } - + @Override - public Long hsetnx(final String key, final String field, final String value) { - writeAsync(key, new Callable>(){ + public Long hsetnx(final String key, final String field, final String value) { + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_hsetnx(key, field, value); @@ -400,10 +400,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.hsetnx(key, field, value); } - + @Override public Long incr(final String key) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_incr(key); @@ -412,10 +412,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.incr(key); } - + @Override public Long incrBy(final String key, final long delta) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_incrBy(key, delta); @@ -424,10 +424,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.incrBy(key, delta); } - + @Override public Double incrByFloat(final String key, final double increment) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_incrByFloat(key, increment); @@ -436,10 +436,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.incrByFloat(key, increment); } - + @Override public String lpop(final String key) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_lpop(key); @@ -448,10 +448,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.lpop(key); } - + @Override public Long lpush(final String key, final String... values) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_lpush(key, values); @@ -460,10 +460,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.lpush(key, values); } - + @Override public Long lrem(final String key, final long count, final String value) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_lrem(key, count, value); @@ -472,10 +472,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.lrem(key, count, value); } - + @Override public String lset(final String key, final long count, final String value) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_lset(key, count, value); @@ -484,10 +484,10 @@ public OperationResult call() throws Exception { return DynoDualWriterClient.super.lset(key, count, value); } - + @Override public String ltrim(final String key, final long start, final long end) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_ltrim(key, start, end); @@ -499,7 +499,7 @@ public OperationResult call() throws Exception { @Override public Long persist(final String key) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_persist(key); @@ -511,7 +511,7 @@ public OperationResult call() throws Exception { @Override public Long pexpireAt(final String key, final long millisecondsTimestamp) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_pexpireAt(key, millisecondsTimestamp); @@ -523,7 +523,7 @@ public OperationResult call() throws Exception { @Override public Long pttl(final String key) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_pttl(key); @@ -535,7 +535,7 @@ public OperationResult call() throws Exception { @Override public String rename(final String oldkey, final String newkey) { - writeAsync(oldkey, new Callable>(){ + writeAsync(oldkey, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_rename(oldkey, oldkey); @@ -547,7 +547,7 @@ public OperationResult call() throws Exception { @Override public String rpop(final String key) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_rpop(key); @@ -559,7 +559,7 @@ public OperationResult call() throws Exception { @Override public Long scard(final String key) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_scard(key); @@ -571,7 +571,7 @@ public OperationResult call() throws Exception { @Override public Boolean setbit(final String key, final long offset, final boolean value) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_setbit(key, offset, value); @@ -583,7 +583,7 @@ public OperationResult call() throws Exception { @Override public Boolean setbit(final String key, final long offset, final String value) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_setbit(key, offset, value); @@ -595,7 +595,7 @@ public OperationResult call() throws Exception { @Override public Long setnx(final String key, final String value) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_setnx(key, value); @@ -607,7 +607,7 @@ public OperationResult call() throws Exception { @Override public Long setrange(final String key, final long offset, final String value) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_setrange(key, offset, value); @@ -619,7 +619,7 @@ public OperationResult call() throws Exception { @Override public Set smembers(final String key) { - writeAsync(key, new Callable>>(){ + writeAsync(key, new Callable>>() { @Override public OperationResult> call() throws Exception { return shadowClient.d_smembers(key); @@ -631,19 +631,19 @@ public OperationResult> call() throws Exception { @Override public Long smove(final String srckey, final String dstkey, final String member) { - writeAsync(srckey, new Callable>(){ + writeAsync(srckey, new Callable>() { @Override public OperationResult call() throws Exception { - return shadowClient.d_smove(srckey,dstkey,member); + return shadowClient.d_smove(srckey, dstkey, member); } }); - return DynoDualWriterClient.super.smove(srckey,dstkey,member); + return DynoDualWriterClient.super.smove(srckey, dstkey, member); } @Override public List sort(final String key) { - writeAsync(key, new Callable>>(){ + writeAsync(key, new Callable>>() { @Override public OperationResult> call() throws Exception { return shadowClient.d_sort(key); @@ -655,7 +655,7 @@ public OperationResult> call() throws Exception { @Override public String spop(final String key) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_spop(key); @@ -667,43 +667,43 @@ public OperationResult call() throws Exception { @Override public Long srem(final String key, final String... members) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { - return shadowClient.d_srem(key,members); + return shadowClient.d_srem(key, members); } }); - return DynoDualWriterClient.super.srem(key,members); + return DynoDualWriterClient.super.srem(key, members); } @Override public ScanResult sscan(final String key, final String cursor) { - writeAsync(key, new Callable>>(){ + writeAsync(key, new Callable>>() { @Override public OperationResult> call() throws Exception { - return shadowClient.d_sscan(key,cursor); + return shadowClient.d_sscan(key, cursor); } }); - return DynoDualWriterClient.super.sscan(key,cursor); + return DynoDualWriterClient.super.sscan(key, cursor); } @Override public ScanResult sscan(final String key, final String cursor, final ScanParams params) { - writeAsync(key, new Callable>>(){ + writeAsync(key, new Callable>>() { @Override public OperationResult> call() throws Exception { - return shadowClient.d_sscan(key,cursor,params); + return shadowClient.d_sscan(key, cursor, params); } }); - return DynoDualWriterClient.super.sscan(key,cursor,params); + return DynoDualWriterClient.super.sscan(key, cursor, params); } @Override public Long ttl(final String key) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_ttl(key); @@ -715,7 +715,7 @@ public OperationResult call() throws Exception { @Override public Long zadd(final String key, final double score, final String member) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_zadd(key, score, member); @@ -727,7 +727,7 @@ public OperationResult call() throws Exception { @Override public Long zadd(final String key, final Map scoreMembers) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_zadd(key, scoreMembers); @@ -739,7 +739,7 @@ public OperationResult call() throws Exception { @Override public Double zincrby(final String key, final double score, final String member) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_zincrby(key, score, member); @@ -751,7 +751,7 @@ public OperationResult call() throws Exception { @Override public Long zrem(final String key, final String... member) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_zrem(key, member); @@ -763,7 +763,7 @@ public OperationResult call() throws Exception { @Override public List blpop(final int timeout, final String key) { - writeAsync(key, new Callable>>(){ + writeAsync(key, new Callable>>() { @Override public OperationResult> call() throws Exception { return shadowClient.d_blpop(timeout, key); @@ -775,7 +775,7 @@ public OperationResult> call() throws Exception { @Override public List brpop(final int timeout, final String key) { - writeAsync(key, new Callable>>(){ + writeAsync(key, new Callable>>() { @Override public OperationResult> call() throws Exception { return shadowClient.d_brpop(timeout, key); @@ -790,7 +790,7 @@ public OperationResult> call() throws Exception { @Override public String set(final byte[] key, final byte[] value) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_set(key, value); @@ -802,7 +802,7 @@ public OperationResult call() throws Exception { @Override public String setex(final byte[] key, final int seconds, final byte[] value) { - writeAsync(key, new Callable>(){ + writeAsync(key, new Callable>() { @Override public OperationResult call() throws Exception { return shadowClient.d_setex(key, seconds, value); diff --git a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoDualWriterPipeline.java b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoDualWriterPipeline.java index cac49f6a..f5ab8162 100644 --- a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoDualWriterPipeline.java +++ b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoDualWriterPipeline.java @@ -123,19 +123,28 @@ private boolean canSendShadowRequest(byte[] key) { */ @Override public void sync() { - scheduleAsync(() -> { shadowPipeline.sync(); return null; }); + scheduleAsync(() -> { + shadowPipeline.sync(); + return null; + }); super.sync(); } @Override public List syncAndReturnAll() { - scheduleAsync(() -> { this.shadowPipeline.sync(); return null; }); + scheduleAsync(() -> { + this.shadowPipeline.sync(); + return null; + }); return super.syncAndReturnAll(); } @Override public void discardPipelineAndReleaseConnection() { - scheduleAsync(() -> { this.shadowPipeline.discardPipelineAndReleaseConnection(); return null; }); + scheduleAsync(() -> { + this.shadowPipeline.discardPipelineAndReleaseConnection(); + return null; + }); super.discardPipelineAndReleaseConnection(); } @@ -152,7 +161,7 @@ public void close() throws Exception { public Response append(final String key, final String value) { writeAsync(key, () -> shadowPipeline.append(key, value)); - return DynoDualWriterPipeline.super.append(key,value); + return DynoDualWriterPipeline.super.append(key, value); } @Override @@ -180,7 +189,7 @@ public Response decr(final String key) { public Response decrBy(final String key, final long integer) { writeAsync(key, () -> shadowPipeline.decrBy(key, integer)); - return DynoDualWriterPipeline.super.decrBy(key,integer); + return DynoDualWriterPipeline.super.decrBy(key, integer); } @Override @@ -194,7 +203,7 @@ public Response del(final String key) { public Response expire(final String key, final int seconds) { writeAsync(key, () -> shadowPipeline.expire(key, seconds)); - return DynoDualWriterPipeline.super.expire(key,seconds); + return DynoDualWriterPipeline.super.expire(key, seconds); } @Override @@ -206,7 +215,7 @@ public Response pexpire(String key, long milliseconds) { public Response expireAt(final String key, final long unixTime) { writeAsync(key, () -> shadowPipeline.expireAt(key, unixTime)); - return DynoDualWriterPipeline.super.expireAt(key,unixTime); + return DynoDualWriterPipeline.super.expireAt(key, unixTime); } @Override @@ -219,21 +228,21 @@ public Response pexpireAt(String key, long millisecondsTimestamp) { public Response hdel(final String key, final String... field) { writeAsync(key, () -> shadowPipeline.hdel(key, field)); - return DynoDualWriterPipeline.super.hdel(key,field); + return DynoDualWriterPipeline.super.hdel(key, field); } @Override public Response hincrBy(final String key, final String field, final long value) { writeAsync(key, () -> shadowPipeline.hincrBy(key, field, value)); - return DynoDualWriterPipeline.super.hincrBy(key,field, value); + return DynoDualWriterPipeline.super.hincrBy(key, field, value); } /* not supported by RedisPipeline 2.7.3 */ public Response hincrByFloat(final String key, final String field, final double value) { writeAsync(key, () -> shadowPipeline.hincrByFloat(key, field, value)); - return DynoDualWriterPipeline.super.hincrByFloat(key,field, value); + return DynoDualWriterPipeline.super.hincrByFloat(key, field, value); } /** @@ -244,14 +253,14 @@ public Response hincrByFloat(final String key, final String field, final public Response hmset(final byte[] key, final Map hash) { writeAsync(key, () -> shadowPipeline.hmset(key, hash)); - return DynoDualWriterPipeline.super.hmset(key,hash); + return DynoDualWriterPipeline.super.hmset(key, hash); } @Override public Response hmset(final String key, final Map hash) { writeAsync(key, () -> shadowPipeline.hmset(key, hash)); - return DynoDualWriterPipeline.super.hmset(key,hash); + return DynoDualWriterPipeline.super.hmset(key, hash); } @Override @@ -268,14 +277,14 @@ public Response hset(final String key, final String field, final String va public Response hset(final byte[] key, final byte[] field, final byte[] value) { writeAsync(key, () -> shadowPipeline.hset(key, field, value)); - return DynoDualWriterPipeline.super.hset(key,field, value); + return DynoDualWriterPipeline.super.hset(key, field, value); } @Override public Response hsetnx(final String key, final String field, final String value) { writeAsync(key, () -> shadowPipeline.hsetnx(key, field, value)); - return DynoDualWriterPipeline.super.hsetnx(key,field, value); + return DynoDualWriterPipeline.super.hsetnx(key, field, value); } @Override @@ -289,21 +298,21 @@ public Response incr(final String key) { public Response incrBy(final String key, final long integer) { writeAsync(key, () -> shadowPipeline.incrBy(key, integer)); - return DynoDualWriterPipeline.super.incrBy(key,integer); + return DynoDualWriterPipeline.super.incrBy(key, integer); } /* not supported by RedisPipeline 2.7.3 */ public Response incrByFloat(final String key, final double increment) { writeAsync(key, () -> shadowPipeline.incrByFloat(key, increment)); - return DynoDualWriterPipeline.super.incrByFloat(key,increment); + return DynoDualWriterPipeline.super.incrByFloat(key, increment); } @Override public Response linsert(final String key, final ListPosition where, final String pivot, final String value) { writeAsync(key, () -> shadowPipeline.linsert(key, where, pivot, value)); - return DynoDualWriterPipeline.super.linsert(key,where, pivot, value); + return DynoDualWriterPipeline.super.linsert(key, where, pivot, value); } @Override @@ -317,42 +326,42 @@ public Response lpop(final String key) { public Response lpush(final String key, final String... string) { writeAsync(key, () -> shadowPipeline.lpush(key, string)); - return DynoDualWriterPipeline.super.lpush(key,string); + return DynoDualWriterPipeline.super.lpush(key, string); } @Override public Response lpushx(final String key, final String... string) { writeAsync(key, () -> shadowPipeline.lpushx(key, string)); - return DynoDualWriterPipeline.super.lpushx(key,string); + return DynoDualWriterPipeline.super.lpushx(key, string); } @Override public Response lrem(final String key, final long count, final String value) { writeAsync(key, () -> shadowPipeline.lrem(key, count, value)); - return DynoDualWriterPipeline.super.lrem(key,count, value); + return DynoDualWriterPipeline.super.lrem(key, count, value); } @Override public Response lset(final String key, final long index, final String value) { writeAsync(key, () -> shadowPipeline.lset(key, index, value)); - return DynoDualWriterPipeline.super.lset(key,index, value); + return DynoDualWriterPipeline.super.lset(key, index, value); } @Override public Response ltrim(final String key, final long start, final long end) { writeAsync(key, () -> shadowPipeline.ltrim(key, start, end)); - return DynoDualWriterPipeline.super.ltrim(key,start, end); + return DynoDualWriterPipeline.super.ltrim(key, start, end); } @Override public Response move(final String key, final int dbIndex) { writeAsync(key, () -> shadowPipeline.move(key, dbIndex)); - return DynoDualWriterPipeline.super.move(key,dbIndex); + return DynoDualWriterPipeline.super.move(key, dbIndex); } @Override @@ -366,14 +375,14 @@ public Response persist(final String key) { public Response rename(final String oldkey, final String newkey) { writeAsync(newkey, () -> shadowPipeline.rename(oldkey, newkey)); - return DynoDualWriterPipeline.super.rename(oldkey,newkey); + return DynoDualWriterPipeline.super.rename(oldkey, newkey); } /* not supported by RedisPipeline 2.7.3 */ public Response renamenx(final String oldkey, final String newkey) { writeAsync(newkey, () -> shadowPipeline.renamenx(oldkey, newkey)); - return DynoDualWriterPipeline.super.renamenx(oldkey,newkey); + return DynoDualWriterPipeline.super.renamenx(oldkey, newkey); } @Override @@ -387,56 +396,56 @@ public Response rpop(final String key) { public Response rpush(final String key, final String... string) { writeAsync(key, () -> shadowPipeline.rpush(key, string)); - return DynoDualWriterPipeline.super.rpush(key,string); + return DynoDualWriterPipeline.super.rpush(key, string); } @Override public Response rpushx(final String key, final String... string) { writeAsync(key, () -> shadowPipeline.rpushx(key, string)); - return DynoDualWriterPipeline.super.rpushx(key,string); + return DynoDualWriterPipeline.super.rpushx(key, string); } @Override public Response sadd(final String key, final String... member) { writeAsync(key, () -> shadowPipeline.sadd(key, member)); - return DynoDualWriterPipeline.super.sadd(key,member); + return DynoDualWriterPipeline.super.sadd(key, member); } @Override public Response set(final String key, final String value) { writeAsync(key, () -> shadowPipeline.set(key, value)); - return DynoDualWriterPipeline.super.set(key,value); + return DynoDualWriterPipeline.super.set(key, value); } @Override public Response setbit(final String key, final long offset, final boolean value) { writeAsync(key, () -> shadowPipeline.setbit(key, offset, value)); - return DynoDualWriterPipeline.super.setbit(key,offset, value); + return DynoDualWriterPipeline.super.setbit(key, offset, value); } @Override public Response setex(final String key, final int seconds, final String value) { writeAsync(key, () -> shadowPipeline.setex(key, seconds, value)); - return DynoDualWriterPipeline.super.setex(key,seconds, value); + return DynoDualWriterPipeline.super.setex(key, seconds, value); } @Override public Response setnx(final String key, final String value) { writeAsync(key, () -> shadowPipeline.setnx(key, value)); - return DynoDualWriterPipeline.super.setnx(key,value); + return DynoDualWriterPipeline.super.setnx(key, value); } @Override public Response setrange(final String key, final long offset, final String value) { writeAsync(key, () -> shadowPipeline.setrange(key, offset, value)); - return DynoDualWriterPipeline.super.setrange(key,offset, value); + return DynoDualWriterPipeline.super.setrange(key, offset, value); } @Override @@ -450,7 +459,7 @@ public Response> sort(final String key) { public Response> sort(final String key, final SortingParams sortingParameters) { writeAsync(key, () -> shadowPipeline.sort(key, sortingParameters)); - return DynoDualWriterPipeline.super.sort(key,sortingParameters); + return DynoDualWriterPipeline.super.sort(key, sortingParameters); } @Override @@ -464,14 +473,14 @@ public Response spop(final String key) { public Response> spop(final String key, final long count) { writeAsync(key, () -> shadowPipeline.spop(key, count)); - return DynoDualWriterPipeline.super.spop(key,count); + return DynoDualWriterPipeline.super.spop(key, count); } @Override public Response srem(final String key, final String... member) { writeAsync(key, () -> shadowPipeline.srem(key, member)); - return DynoDualWriterPipeline.super.srem(key,member); + return DynoDualWriterPipeline.super.srem(key, member); } /** @@ -492,42 +501,42 @@ public Response> sscan(final String key, final String cursor) public Response zadd(final String key, final double score, final String member) { writeAsync(key, () -> shadowPipeline.zadd(key, score, member)); - return DynoDualWriterPipeline.super.zadd(key,score, member); + return DynoDualWriterPipeline.super.zadd(key, score, member); } @Override public Response zadd(final String key, final Map scoreMembers) { writeAsync(key, () -> shadowPipeline.zadd(key, scoreMembers)); - return DynoDualWriterPipeline.super.zadd(key,scoreMembers); + return DynoDualWriterPipeline.super.zadd(key, scoreMembers); } @Override public Response zincrby(final String key, final double score, final String member) { writeAsync(key, () -> shadowPipeline.zincrby(key, score, member)); - return DynoDualWriterPipeline.super.zincrby(key,score, member); + return DynoDualWriterPipeline.super.zincrby(key, score, member); } @Override public Response zrem(final String key, final String... member) { writeAsync(key, () -> shadowPipeline.zrem(key, member)); - return DynoDualWriterPipeline.super.zrem(key,member); + return DynoDualWriterPipeline.super.zrem(key, member); } @Override public Response zremrangeByRank(final String key, final long start, final long end) { writeAsync(key, () -> shadowPipeline.zremrangeByRank(key, start, end)); - return DynoDualWriterPipeline.super.zremrangeByRank(key,start, end); + return DynoDualWriterPipeline.super.zremrangeByRank(key, start, end); } @Override public Response zremrangeByScore(final String key, final double start, final double end) { writeAsync(key, () -> shadowPipeline.zremrangeByScore(key, start, end)); - return DynoDualWriterPipeline.super.zremrangeByScore(key,start, end); + return DynoDualWriterPipeline.super.zremrangeByScore(key, start, end); } /** @@ -562,7 +571,7 @@ public Response zremrangeByLex(String key, String start, String end) { public Response set(final byte[] key, final byte[] value) { writeAsync(key, () -> shadowPipeline.set(key, value)); - return DynoDualWriterPipeline.super.set(key,value); + return DynoDualWriterPipeline.super.set(key, value); } @Override @@ -652,7 +661,7 @@ public Response zadd(String arg0, Map arg1, ZAddParams arg public Response zadd(final String key, final double score, final String member, final ZAddParams params) { writeAsync(key, () -> shadowPipeline.zadd(key, score, member, params)); - return DynoDualWriterPipeline.super.zadd(key,score, member, params); + return DynoDualWriterPipeline.super.zadd(key, score, member, params); } @@ -685,7 +694,7 @@ public Response decr(byte[] key) { public Response decrBy(final byte[] key, final long integer) { writeAsync(key, () -> shadowPipeline.decrBy(key, integer)); - return DynoDualWriterPipeline.super.decrBy(key,integer); + return DynoDualWriterPipeline.super.decrBy(key, integer); } @Override @@ -729,7 +738,7 @@ public Response getbit(byte[] key, long offset) { public Response getSet(final byte[] key, final byte[] value) { writeAsync(key, () -> shadowPipeline.getSet(key, value)); - return DynoDualWriterPipeline.super.getSet(key,value); + return DynoDualWriterPipeline.super.getSet(key, value); } @Override @@ -881,7 +890,7 @@ public Response setrange(byte[] key, long offset, byte[] value) { public Response setex(final byte[] key, final int seconds, final byte[] value) { writeAsync(key, () -> shadowPipeline.setex(key, seconds, value)); - return DynoDualWriterPipeline.super.setex(key,seconds, value); + return DynoDualWriterPipeline.super.setex(key, seconds, value); } @Override diff --git a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisClient.java b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisClient.java index 64cc5163..f4e846ab 100644 --- a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisClient.java +++ b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisClient.java @@ -69,7 +69,7 @@ public class DynoJedisClient implements JedisCommands, BinaryJedisCommands, Mult protected final ConnectionPoolMonitor cpMonitor; public DynoJedisClient(String name, String clusterName, ConnectionPool pool, DynoOPMonitor operationMonitor, - ConnectionPoolMonitor cpMonitor) { + ConnectionPoolMonitor cpMonitor) { this.appName = name; this.clusterName = clusterName; this.connPool = pool; @@ -138,7 +138,7 @@ private abstract class MultiKeyOperation implements Operation { private MultiKeyOperation(final List keys, final OpName o) { Object firstKey = (keys != null && keys.size() > 0) ? keys.get(0) : null; - if(firstKey != null) { + if (firstKey != null) { if (firstKey instanceof String) {//string key this.keys = keys; this.binaryKeys = null; @@ -195,15 +195,14 @@ public byte[] getBinaryKey() { *
  • {@link #hsetnx(String, String, String) HSETNX}
  • *
  • {@link #hvals(String) HVALS}
  • * - * + * *
      *
    • {@link #get(byte[]) GET}
    • *
    • {@link #set(byte[], byte[]) SET}
    • *
    • {@link #setex(byte[], int, byte[]) SETEX}
    • *
    * - * @param - * the parameterized type + * @param the parameterized type */ private abstract class CompressionValueOperation extends BaseKeyOperation implements CompressionOperation { @@ -266,8 +265,7 @@ public String decompressValue(String value, ConnectionContext ctx) { *
  • {@link #msetnx(String...) MSETNX}
  • * * - * @param - * the parameterized type + * @param the parameterized type */ private abstract class CompressionValueMultiKeyOperation extends MultiKeyOperation implements MultiKeyCompressionOperation { @@ -285,33 +283,32 @@ private CompressionValueMultiKeyOperation(List keys, OpName o) { */ @Override public String[] compressMultiKeyValue(ConnectionContext ctx, String... keyValues) { - List items = Arrays.asList(keyValues); - List newItems = new ArrayList(); - - for (int i = 0 ; i < items.size() ; i++) { - /* - * String... keyValues is a List of keys and values. - * The value always comes second and this is the one - * we want to compress. - */ - if(i % 2 == 0 ) { - String value = items.get(i); - - try { - if ((2 * value.length()) > connPool.getConfiguration().getValueCompressionThreshold()) { - newItems.add(i, ZipUtils.compressStringToBase64String(value)); - ctx.setMetadata("compression", true); - } - - } catch (IOException e) { - Logger.warn( - "UNABLE to compress [" + value + "] for key [" + getStringKey() + "]; sending value uncompressed"); - } - } - else { - newItems.add(items.get(i)); - } - } + List items = Arrays.asList(keyValues); + List newItems = new ArrayList(); + + for (int i = 0; i < items.size(); i++) { + /* + * String... keyValues is a List of keys and values. + * The value always comes second and this is the one + * we want to compress. + */ + if (i % 2 == 0) { + String value = items.get(i); + + try { + if ((2 * value.length()) > connPool.getConfiguration().getValueCompressionThreshold()) { + newItems.add(i, ZipUtils.compressStringToBase64String(value)); + ctx.setMetadata("compression", true); + } + + } catch (IOException e) { + Logger.warn( + "UNABLE to compress [" + value + "] for key [" + getStringKey() + "]; sending value uncompressed"); + } + } else { + newItems.add(items.get(i)); + } + } return (String[]) newItems.toArray(); } @@ -496,7 +493,9 @@ public Long execute(Jedis client, ConnectionContext state) { } @Override - public Object eval(String script, int keyCount, String... params) { return d_eval(script, keyCount, params).getResult(); } + public Object eval(String script, int keyCount, String... params) { + return d_eval(script, keyCount, params).getResult(); + } public OperationResult d_eval(final String script, final int keyCount, final String... params) { if (keyCount == 0) { @@ -522,17 +521,19 @@ public Object eval(String script) { } @Override - public Object evalsha(String sha1, int keyCount, String... params) { return d_evalsha(sha1, keyCount, params).getResult(); } + public Object evalsha(String sha1, int keyCount, String... params) { + return d_evalsha(sha1, keyCount, params).getResult(); + } public OperationResult d_evalsha(String sha1, int keyCount, String... params) { if (keyCount == 0) { throw new DynoException("Need at least one key in script"); } return connPool.executeWithFailover(new BaseKeyOperation(params[0], OpName.EVALSHA) { - @Override - public Object execute(Jedis client, ConnectionContext state) { - return client.evalsha(sha1, keyCount, params); - } + @Override + public Object execute(Jedis client, ConnectionContext state) { + return client.evalsha(sha1, keyCount, params); + } }); } @@ -543,10 +544,14 @@ public Object evalsha(String sha1, List keys, List args) { } @Override - public Object evalsha(String sha1) { return evalsha(sha1, 0); } + public Object evalsha(String sha1) { + return evalsha(sha1, 0); + } @Override - public Boolean scriptExists(String sha1) { return d_scriptExists(sha1).getResult(); } + public Boolean scriptExists(String sha1) { + return d_scriptExists(sha1).getResult(); + } public OperationResult d_scriptExists(String sha1) { return connPool.executeWithFailover(new BaseKeyOperation(sha1, OpName.SCRIPT_EXISTS) { @@ -563,7 +568,9 @@ public List scriptExists(String... sha1) { } @Override - public String scriptLoad(String script) { return d_scriptLoad(script).getResult(); } + public String scriptLoad(String script) { + return d_scriptLoad(script).getResult(); + } public OperationResult d_scriptLoad(final String script) { return connPool.executeWithFailover(new BaseKeyOperation(script, OpName.SCRIPT_LOAD) { @@ -574,7 +581,9 @@ public String execute(Jedis client, ConnectionContext state) throws DynoExceptio }); } - public String scriptFlush() { return d_scriptFlush().getResult(); } + public String scriptFlush() { + return d_scriptFlush().getResult(); + } public OperationResult d_scriptFlush() { return connPool.executeWithFailover(new BaseKeyOperation("", OpName.SCRIPT_FLUSH) { @@ -585,7 +594,9 @@ public String execute(Jedis client, ConnectionContext state) throws DynoExceptio }); } - public String scriptKill() { return d_scriptKill().getResult(); } + public String scriptKill() { + return d_scriptKill().getResult(); + } public OperationResult d_scriptKill() { return connPool.executeWithFailover(new BaseKeyOperation("", OpName.SCRIPT_KILL) { @@ -858,7 +869,7 @@ public ScanResult> execute(Jedis client, ConnectionCon new CompressionValueOperation>>(key, OpName.HSCAN) { @Override public ScanResult> execute(final Jedis client, - final ConnectionContext state) { + final ConnectionContext state) { return new ScanResult<>(cursor, new ArrayList(CollectionUtils.transform( client.hscan(key, cursor).getResult(), new CollectionUtils.Transform, Map.Entry>() { @@ -882,12 +893,12 @@ private String getCursorValue(final ConnectionContext state, final CursorBasedRe } private List>> scatterGatherScan(final CursorBasedResult cursor, - final int count, final String... pattern) { + final int count, final String... pattern) { if (!(cursor instanceof TokenRackMapper)) { throw new DynoException("cursor does not implement the TokenRackMapper interface"); } - return new ArrayList<>(connPool.executeWithRing((TokenRackMapper)cursor, new BaseKeyOperation>("SCAN", OpName.SCAN) { + return new ArrayList<>(connPool.executeWithRing((TokenRackMapper) cursor, new BaseKeyOperation>("SCAN", OpName.SCAN) { @Override public ScanResult execute(final Jedis client, final ConnectionContext state) throws DynoException { if (pattern != null && pattern.length > 0) { @@ -1110,7 +1121,7 @@ public Long linsert(final String key, final ListPosition where, final String piv } public OperationResult d_linsert(final String key, final ListPosition where, final String pivot, - final String value) { + final String value) { return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.LINSERT) { @@ -1525,7 +1536,7 @@ public String set(final String key, final String value, final String nxxx, final } public OperationResult d_set(final String key, final String value, final String nxxx, final String expx, - final long time) { + final long time) { SetParams setParams = SetParams.setParams(); if (nxxx.equalsIgnoreCase("NX")) { setParams.nx(); @@ -1619,7 +1630,7 @@ public String execute(final Jedis client, final ConnectionContext state) throws }); } } - + @Override public String psetex(final String key, final long milliseconds, final String value) { return d_psetex(key, milliseconds, value).getResult(); @@ -1642,8 +1653,6 @@ public String execute(final Jedis client, final ConnectionContext state) throws }); } } - - @Override @@ -1973,7 +1982,7 @@ public Long zadd(String key, double score, String member, ZAddParams params) { } public OperationResult d_zadd(final String key, final double score, final String member, - final ZAddParams params) { + final ZAddParams params) { return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.ZADD) { @@ -2279,7 +2288,7 @@ public Set zrangeByScore(String key, double min, double max, int offset, } public OperationResult> d_zrangeByScore(final String key, final Double min, final Double max, - final Integer offset, final Integer count) { + final Integer offset, final Integer count) { return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.ZRANGEBYSCORE) { @@ -2314,7 +2323,7 @@ public Set zrangeByScore(String key, String min, String max, int offset, } public OperationResult> d_zrangeByScore(final String key, final String min, final String max, - final Integer offset, final Integer count) { + final Integer offset, final Integer count) { return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.ZRANGEBYSCORE) { @@ -2332,7 +2341,7 @@ public Set zrevrangeByScore(String key, double max, double min, int offs } public OperationResult> d_zrevrangeByScore(final String key, final Double max, final Double min, - final Integer offset, final Integer count) { + final Integer offset, final Integer count) { return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.ZREVRANGEBYSCORE) { @@ -2384,7 +2393,7 @@ public Set zrevrangeByScoreWithScores(String key, double max, double min) } public OperationResult> d_zrevrangeByScoreWithScores(final String key, final Double max, - final Double min) { + final Double min) { return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.ZREVRANGEBYSCOREWITHSCORES) { @@ -2402,7 +2411,7 @@ public Set zrangeByScoreWithScores(String key, double min, double max, in } public OperationResult> d_zrangeByScoreWithScores(final String key, final Double min, final Double max, - final Integer offset, final Integer count) { + final Integer offset, final Integer count) { return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.ZRANGEBYSCOREWITHSCORES) { @@ -2420,7 +2429,7 @@ public Set zrevrangeByScore(String key, String max, String min, int offs } public OperationResult> d_zrevrangeByScore(final String key, final String max, final String min, - final Integer offset, final Integer count) { + final Integer offset, final Integer count) { return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.ZREVRANGEBYSCORE) { @@ -2455,7 +2464,7 @@ public Set zrevrangeByScoreWithScores(String key, String max, String min) } public OperationResult> d_zrevrangeByScoreWithScores(final String key, final String max, - final String min) { + final String min) { return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.ZREVRANGEBYSCOREWITHSCORES) { @@ -2473,7 +2482,7 @@ public Set zrangeByScoreWithScores(String key, String min, String max, in } public OperationResult> d_zrangeByScoreWithScores(final String key, final String min, final String max, - final Integer offset, final Integer count) { + final Integer offset, final Integer count) { return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.ZRANGEBYSCOREWITHSCORES) { @@ -2491,7 +2500,7 @@ public Set zrevrangeByScoreWithScores(String key, double max, double min, } public OperationResult> d_zrevrangeByScoreWithScores(final String key, final Double max, - final Double min, final Integer offset, final Integer count) { + final Double min, final Integer offset, final Integer count) { return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.ZREVRANGEBYSCOREWITHSCORES) { @@ -2509,7 +2518,7 @@ public Set zrevrangeByScoreWithScores(String key, String max, String min, } public OperationResult> d_zrevrangeByScoreWithScores(final String key, final String max, - final String min, final Integer offset, final Integer count) { + final String min, final Integer offset, final Integer count) { return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.ZREVRANGEBYSCOREWITHSCORES) { @@ -2704,7 +2713,7 @@ public Long pfadd(String key, String... elements) { public long pfcount(String key) { throw new UnsupportedOperationException("not yet implemented"); } - + @Override public Long bitcount(String key, long start, long end) { return d_bitcount(key, start, end).getResult(); @@ -2722,7 +2731,9 @@ public Long execute(Jedis client, ConnectionContext state) { }); } - /** MULTI-KEY COMMANDS */ + /** + * MULTI-KEY COMMANDS + */ @Override @@ -2759,8 +2770,7 @@ public Set keys(String pattern) { /** * Use this with care, especially in the context of production databases. * - * @param pattern - * Specifies the mach set for keys + * @param pattern Specifies the mach set for keys * @return a collection of operation results * @see keys */ @@ -2790,8 +2800,7 @@ public Long pexpire(String key, long milliseconds) { * corresponding to individual keys. If one of the key is missing, the * return list has null as its corresponding value. * - * @param keys: - * variable list of keys to query + * @param keys: variable list of keys to query * @return list of string values * @see mget */ @@ -2826,22 +2835,22 @@ public String get(String s) { }); } } - - + + @Override public Long exists(String... arg0) { return d_exists(arg0).getResult(); } - + public OperationResult d_exists(final String... arg0) { return connPool.executeWithFailover(new MultiKeyOperation(Arrays.asList(arg0), OpName.EXISTS) { - @Override - public Long execute(Jedis client, ConnectionContext state) { - return client.exists(arg0); - } + @Override + public Long execute(Jedis client, ConnectionContext state) { + return client.exists(arg0); + } }); } - + @Override public Long del(String... keys) { return d_del(keys).getResult(); @@ -2861,9 +2870,8 @@ public Long execute(Jedis client, ConnectionContext state) { } }); } - - - + + @Override public Long msetnx(String... keysvalues) { return d_msetnx(keysvalues).getResult(); @@ -2874,20 +2882,20 @@ public OperationResult d_msetnx(final String... keysvalues) { return connPool.executeWithFailover(new MultiKeyOperation(Arrays.asList(keysvalues), OpName.MSETNX) { @Override - public Long execute(Jedis client, ConnectionContext state) { + public Long execute(Jedis client, ConnectionContext state) { return client.msetnx(keysvalues); } }); - } else { + } else { return connPool.executeWithFailover(new CompressionValueMultiKeyOperation(Arrays.asList(keysvalues), OpName.MSETNX) { - @Override + @Override public Long execute(final Jedis client, final ConnectionContext state) { - return client.msetnx(compressMultiKeyValue(state,keysvalues)); + return client.msetnx(compressMultiKeyValue(state, keysvalues)); } }); } } - + @Override public String mset(String... keysvalues) { return d_mset(keysvalues).getResult(); @@ -2899,15 +2907,15 @@ public OperationResult d_mset(final String... keysvalues) { return connPool.executeWithFailover(new MultiKeyOperation(Arrays.asList(keysvalues), OpName.MSET) { @Override public String execute(Jedis client, ConnectionContext state) { - + return client.mset(keysvalues); } }); } else { return connPool.executeWithFailover(new CompressionValueMultiKeyOperation(Arrays.asList(keysvalues), OpName.MSET) { - @Override + @Override public String execute(final Jedis client, final ConnectionContext state) { - return client.mset(compressMultiKeyValue(state,keysvalues)); + return client.mset(compressMultiKeyValue(state, keysvalues)); } }); } @@ -3271,12 +3279,12 @@ public byte[] get(final byte[] key) { public OperationResult d_get(final byte[] key) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.GET) { - @Override - public byte[] execute(Jedis client, ConnectionContext state) throws DynoException { - return client.get(key); - } - }); + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.GET) { + @Override + public byte[] execute(Jedis client, ConnectionContext state) throws DynoException { + return client.get(key); + } + }); } @Override @@ -3313,12 +3321,12 @@ public String set(final byte[] key, final byte[] value, final SetParams setParam } public OperationResult d_set(final byte[] key, final byte[] value, final SetParams setParams) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.SET) { - @Override - public String execute(Jedis client, ConnectionContext state) throws DynoException { - return client.set(key, value, setParams); - } - }); + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.SET) { + @Override + public String execute(Jedis client, ConnectionContext state) throws DynoException { + return client.set(key, value, setParams); + } + }); } @Override @@ -3523,12 +3531,12 @@ public Long hset(byte[] key, Map hash) { } public OperationResult d_hset(final byte[] key, final byte[] field, final byte[] value) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.HSET) { - @Override - public Long execute(Jedis client, ConnectionContext state) { - return client.hset(key, field, value); - } - }); + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.HSET) { + @Override + public Long execute(Jedis client, ConnectionContext state) { + return client.hset(key, field, value); + } + }); } @Override @@ -3537,12 +3545,12 @@ public byte[] hget(final byte[] key, final byte[] field) { } public OperationResult d_hget(final byte[] key, final byte[] field) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.HGET) { - @Override - public byte[] execute(Jedis client, ConnectionContext state) throws DynoException { - return client.hget(key, field); - } - }); + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.HGET) { + @Override + public byte[] execute(Jedis client, ConnectionContext state) throws DynoException { + return client.hget(key, field); + } + }); } @Override @@ -3556,12 +3564,12 @@ public String hmset(final byte[] key, final Map hash) { } public OperationResult d_hmset(final byte[] key, final Map hash) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.HMSET) { - @Override - public String execute(Jedis client, ConnectionContext state) { - return client.hmset(key, hash); - } - }); + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.HMSET) { + @Override + public String execute(Jedis client, ConnectionContext state) { + return client.hmset(key, hash); + } + }); } @Override @@ -3570,12 +3578,12 @@ public List hmget(final byte[] key, final byte[]... fields) { } public OperationResult> d_hmget(final byte[] key, final byte[]... fields) { - return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.HMGET) { - @Override - public List execute(Jedis client, ConnectionContext state) { - return client.hmget(key, fields); - } - }); + return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.HMGET) { + @Override + public List execute(Jedis client, ConnectionContext state) { + return client.hmget(key, fields); + } + }); } @Override @@ -3650,17 +3658,17 @@ public Collection hvals(byte[] key) { } @Override - public Map hgetAll(final byte[] key) { + public Map hgetAll(final byte[] key) { return d_hgetAll(key).getResult(); } - public OperationResult> d_hgetAll(final byte[] key) { - return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.HGETALL) { - @Override - public Map< byte[], byte[]> execute(Jedis client, ConnectionContext state) throws DynoException { - return client.hgetAll(key); - } - }); + public OperationResult> d_hgetAll(final byte[] key) { + return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.HGETALL) { + @Override + public Map execute(Jedis client, ConnectionContext state) throws DynoException { + return client.hgetAll(key); + } + }); } @Override @@ -3768,12 +3776,12 @@ public byte[] spop(final byte[] key) { return d_spop(key).getResult(); } - public OperationResult< byte[]> d_spop(final byte[] key) { + public OperationResult d_spop(final byte[] key) { - return connPool.executeWithFailover(new BaseKeyOperation< byte[]>(key, OpName.SPOP) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.SPOP) { @Override - public byte[] execute(Jedis client, ConnectionContext state) { + public byte[] execute(Jedis client, ConnectionContext state) { return client.spop(key); } }); @@ -3800,6 +3808,7 @@ public Long execute(Jedis client, ConnectionContext state) { }); } + @Override public Boolean sismember(byte[] key, byte[] member) { throw new UnsupportedOperationException("not yet implemented"); @@ -3820,7 +3829,7 @@ public Long strlen(final byte[] key) { return d_strlen(key).getResult(); } - public OperationResult d_strlen(final byte[] key) { + public OperationResult d_strlen(final byte[] key) { return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.STRLEN) { @@ -3915,7 +3924,7 @@ public Double execute(Jedis client, ConnectionContext state) { }); } - + @Override public List sort(byte[] key) { throw new UnsupportedOperationException("not yet implemented"); @@ -4170,7 +4179,7 @@ public CursorBasedResult dyno_scan(CursorBasedResult cursor, int for (OperationResult> opResult : opResults) { results.put(opResult.getNode().getHostAddress(), opResult.getResult()); } - return new CursorBasedResultImpl<>(results, ((TokenRackMapper)cursor).getTokenRackMap()); + return new CursorBasedResultImpl<>(results, ((TokenRackMapper) cursor).getTokenRackMap()); } @Override @@ -4901,7 +4910,7 @@ private DynoJedisClient buildDynoJedisClient() { } private ConnectionPoolImpl createConnectionPool(String appName, DynoOPMonitor opMonitor, - ConnectionPoolMonitor cpMonitor) { + ConnectionPoolMonitor cpMonitor) { if (hostSupplier == null) { if (discoveryClient == null) { @@ -4923,7 +4932,7 @@ private ConnectionPoolImpl createConnectionPool(String appName, DynoOPMon } private ConnectionPoolImpl startConnectionPool(String appName, JedisConnectionFactory connFactory, - ConnectionPoolConfigurationImpl cpConfig, ConnectionPoolMonitor cpMonitor) { + ConnectionPoolConfigurationImpl cpConfig, ConnectionPoolMonitor cpMonitor) { final ConnectionPoolImpl pool = new ConnectionPoolImpl(connFactory, cpConfig, cpMonitor); @@ -4977,6 +4986,7 @@ private void setLoadBalancingStrategy(ConnectionPoolConfigurationImpl config) { /** * Set the hash to the connection pool if is provided by Dynomite + * * @param hostSupplier * @param config */ @@ -4995,7 +5005,7 @@ private void setHashtagConnectionPool(HostSupplier hostSupplier, ConnectionPoolC if (tokenMapSupplier != null) { Set hostSet = new HashSet(hosts); hostTokens = tokenMapSupplier.getTokens(hostSet); - /* Dyno cannot reach the TokenMapSupplier endpoint, + /* Dyno cannot reach the TokenMapSupplier endpoint, * therefore no nodes can be retrieved. */ if (hostTokens.isEmpty()) { @@ -5004,7 +5014,7 @@ private void setHashtagConnectionPool(HostSupplier hostSupplier, ConnectionPoolC } else { throw new DynoConnectException("TokenMapSupplier not provided"); } - + String hashtag = hostTokens.get(0).getHost().getHashtag(); short numHosts = 0; // Update inner state with the host tokens. @@ -5105,7 +5115,7 @@ public List georadiusReadonly(byte[] key, double longitude, d @Override public List georadius(byte[] arg0, double arg1, double arg2, double arg3, GeoUnit arg4, - GeoRadiusParam arg5) { + GeoRadiusParam arg5) { throw new UnsupportedOperationException("not yet implemented"); } @@ -5126,7 +5136,7 @@ public List georadiusByMemberReadonly(byte[] key, byte[] memb @Override public List georadiusByMember(byte[] arg0, byte[] arg1, double arg2, GeoUnit arg3, - GeoRadiusParam arg4) { + GeoRadiusParam arg4) { throw new UnsupportedOperationException("not yet implemented"); } @@ -5164,7 +5174,7 @@ public Long zadd(byte[] arg0, Map arg1, ZAddParams arg2) { public Long zadd(byte[] arg0, double arg1, byte[] arg2, ZAddParams arg3) { throw new UnsupportedOperationException("not yet implemented"); } - + @Override public Double zincrby(byte[] arg0, double arg1, byte[] arg2, ZIncrByParams arg3) { throw new UnsupportedOperationException("not yet implemented"); @@ -5242,7 +5252,7 @@ public List georadiusReadonly(String key, double longitude, d @Override public List georadius(String arg0, double arg1, double arg2, double arg3, GeoUnit arg4, - GeoRadiusParam arg5) { + GeoRadiusParam arg5) { throw new UnsupportedOperationException("not yet implemented"); } @@ -5263,7 +5273,7 @@ public List georadiusByMemberReadonly(String key, String memb @Override public List georadiusByMember(String arg0, String arg1, double arg2, GeoUnit arg3, - GeoRadiusParam arg4) { + GeoRadiusParam arg4) { throw new UnsupportedOperationException("not yet implemented"); } diff --git a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisCommands.java b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisCommands.java index d096f764..5431adc8 100644 --- a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisCommands.java +++ b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisCommands.java @@ -28,219 +28,219 @@ public interface DynoJedisCommands { /** * Sets field in the expire hash stored at key to value and ttl. - * @param key expire hash key + * + * @param key expire hash key * @param field hash field * @param value field value - * @param ttl time to live, in seconds - * @return - * 1 - if field is a new field in the expire hash and value, ttl was set. - * 0 - if field already exists and the value, ttl was updated. + * @param ttl time to live, in seconds + * @return 1 - if field is a new field in the expire hash and value, ttl was set. + * 0 - if field already exists and the value, ttl was updated. */ Long ehset(String key, String field, String value, long ttl); /** * Gets the value stored at field in expire hash with key - * @param key expire hash key + * + * @param key expire hash key * @param field hash field - * @return - * String value, if exists - * null - if field doesn't exist. + * @return String value, if exists + * null - if field doesn't exist. */ String ehget(String key, String field); /** * Delete the field in the expire hash with key - * @param key expire hash key + * + * @param key expire hash key * @param fields hash field - * @return - * number of fields deleted. + * @return number of fields deleted. */ Long ehdel(String key, String... fields); /** * Check if a field exists in the expire hash with key - * @param key expire hash key + * + * @param key expire hash key * @param field hash field - * @return - * returns true if field exists, false otherwise. + * @return returns true if field exists, false otherwise. */ Boolean ehexists(String key, String field); /** * Get all fields and its values in the expire hash + * * @param key expire hash key - * @return - * Map of all fields and its values. + * @return Map of all fields and its values. */ Map ehgetall(String key); /** * Get all fields in the expire hash + * * @param key expire hash key - * @return - * Set of all fields. + * @return Set of all fields. */ Set ehkeys(String key); /** * Get all values stored in the expire hash + * * @param key expire hash key - * @return - * List of all values stored. + * @return List of all values stored. */ List ehvals(String key); /** * Get multiple fields from the expire hash - * @param key expire hash key + * + * @param key expire hash key * @param fields hash fields - * @return - * List of requested field values. + * @return List of requested field values. */ List ehmget(String key, String... fields); /** * Set multiple fields in the expire hash - * @param key expire hash key + * + * @param key expire hash key * @param hash Tuple of field, value and its TTL - * @return - * returns "OK" if the values were set. + * @return returns "OK" if the values were set. */ String ehmset(String key, Map> hash); /** * Set a field in the expire hash only if it doesn't exist already - * @param key expire hash key + * + * @param key expire hash key * @param field hash field * @param value field value - * @param ttl time to live - * @return - * returns 1 if field set or 0 otherwise. + * @param ttl time to live + * @return returns 1 if field set or 0 otherwise. */ Long ehsetnx(String key, String field, String value, long ttl); /** * Scan fields in the expire hash - * @param key expire hashkey + * + * @param key expire hashkey * @param cursor cursor - * @return - * Map of fields and values in the expire hash. + * @return Map of fields and values in the expire hash. */ ScanResult> ehscan(String key, String cursor); /** * Increase current value stored in the field of the expire hash - * @param key expire hash key + * + * @param key expire hash key * @param field hash field * @param value value to increment by - * @return - * Value of the field after the increment. + * @return Value of the field after the increment. */ Long ehincrby(String key, String field, long value); /** * Increase current value stored in the field by a double value - * @param key expire hash key + * + * @param key expire hash key * @param field hash field * @param value value to increment by - * @return - * Value of the field after the increment. + * @return Value of the field after the increment. */ Double ehincrbyfloat(String key, String field, double value); /** * Number of fields stored in the expire hash + * * @param key expire hash key - * @return - * Count of fields in the expire hash. + * @return Count of fields in the expire hash. */ Long ehlen(String key); /** * Rename the expire hash key. + * * @param oldKey old expire hash key * @param newKey new expire hash key - * @return - * returns "OK" if rename was successful. + * @return returns "OK" if rename was successful. */ String ehrename(String oldKey, String newKey); /** * Rename the expire hash key if the new key doesn't already exist + * * @param oldKey old expire hash key * @param newKey new expire hash key - * @return - * returns 1 if rename was successful, 0 otherwise. + * @return returns 1 if rename was successful, 0 otherwise. */ Long ehrenamenx(String oldKey, String newKey); /** * Set expiry on the expire hash - * @param key expire hash key + * + * @param key expire hash key * @param seconds expiry in seconds - * @return - * returns 1 if timeout was set, 0 otherwise. + * @return returns 1 if timeout was set, 0 otherwise. */ Long ehexpire(String key, int seconds); /** * Set expiry on the expire hash - * @param key expire hash key + * + * @param key expire hash key * @param timestamp expiry in unix timestamp (seconds) - * @return - * returns 1 if timeout was set, 0 otherwise. + * @return returns 1 if timeout was set, 0 otherwise. */ Long ehexpireat(String key, long timestamp); /** * Set expiry on the expire hash - * @param key expire hash key + * + * @param key expire hash key * @param timestamp expiry in unix timestamp (milliseconds) - * @return - * returns 1 if timeout was set, 0 otherwise. + * @return returns 1 if timeout was set, 0 otherwise. */ Long ehpexpireat(String key, long timestamp); /** * Remove existing timeout on the expire hash + * * @param key expire hash key - * @return - * returns 1 if timeout was removed, 0 otherwise. + * @return returns 1 if timeout was removed, 0 otherwise. */ Long ehpersist(String key); /** * Returns the remaining time on the expire hash + * * @param key expire hash key - * @return - * returns -2 if key does not exist, -1 if the timeout is not set, otherwise returns remaining time. + * @return returns -2 if key does not exist, -1 if the timeout is not set, otherwise returns remaining time. */ Long ehttl(String key); /** * Returns the remaining time on the expire hash field - * @param key expire hash key + * + * @param key expire hash key * @param field hash field - * @return - * returns remaining time in seconds if key and field exists, 0 otherwise. + * @return returns remaining time in seconds if key and field exists, 0 otherwise. */ Long ehttl(String key, String field); /** * Returns the remaining time on the expire hash + * * @param key expire hash key - * @return - * returns -2 if key does not exist, -1 if the timeout is not set, otherwise returns remaining time - * in milliseconds. + * @return returns -2 if key does not exist, -1 if the timeout is not set, otherwise returns remaining time + * in milliseconds. */ Long ehpttl(String key); /** * Returns the remaining time on the expire hash field - * @param key expire hash key + * + * @param key expire hash key * @param field hash field - * @return - * returns remaining time in milliseconds if key and field exists, 0 otherwise. + * @return returns remaining time in milliseconds if key and field exists, 0 otherwise. */ Long ehpttl(String key, String field); } diff --git a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisPipeline.java b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisPipeline.java index 646c5714..8d085c2a 100644 --- a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisPipeline.java +++ b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisPipeline.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -53,3049 +53,3052 @@ @NotThreadSafe public class DynoJedisPipeline implements RedisPipeline, BinaryRedisPipeline, AutoCloseable { - private static final Logger Logger = LoggerFactory.getLogger(DynoJedisPipeline.class); - - // ConnPool and connection to exec the pipeline - private final ConnectionPoolImpl connPool; - private volatile Connection connection; - private final DynoJedisPipelineMonitor opMonitor; - private final ConnectionPoolMonitor cpMonitor; - - // the cached pipeline - private volatile Pipeline jedisPipeline = null; - // the cached row key for the pipeline. all subsequent requests to pipeline - // must be the same. this is used to check that. - private final AtomicReference theKey = new AtomicReference(null); - private final AtomicReference theBinaryKey = new AtomicReference(null); - private final AtomicReference hashtag = new AtomicReference(null); - // used for tracking errors - private final AtomicReference pipelineEx = new AtomicReference(null); - - private static final String DynoPipeline = "DynoPipeline"; - - DynoJedisPipeline(ConnectionPoolImpl cPool, DynoJedisPipelineMonitor operationMonitor, - ConnectionPoolMonitor connPoolMonitor) { - this.connPool = cPool; - this.opMonitor = operationMonitor; - this.cpMonitor = connPoolMonitor; - } - - private void pipelined(final byte[] key) { - try { - try { - connection = connPool.getConnectionForOperation(new BaseOperation() { - - @Override - public String getName() { - return DynoPipeline; - } - - @Override - public String getStringKey() {// we do not use it in this context - return null; - } - - @Override - public byte[] getBinaryKey() { - return key; - } - - }); - } catch (NoAvailableHostsException nahe) { - cpMonitor.incOperationFailure(connection != null ? connection.getHost() : null, nahe); - discardPipelineAndReleaseConnection(); - throw nahe; - } - } catch (NoAvailableHostsException nahe) { - cpMonitor.incOperationFailure(connection != null ? connection.getHost() : null, nahe); - discardPipelineAndReleaseConnection(); - throw nahe; - } - Jedis jedis = ((JedisConnection) connection).getClient(); - jedisPipeline = jedis.pipelined(); - cpMonitor.incOperationSuccess(connection.getHost(), 0); - } - - private void pipelined(final String key) { - try { - try { - connection = connPool.getConnectionForOperation(new BaseOperation() { - - @Override - public String getName() { - return DynoPipeline; - } - - @Override - public String getStringKey() { - return key; - } - - @Override - public byte[] getBinaryKey() { // we do not use it in this context - return null; - } - - }); - } catch (NoAvailableHostsException nahe) { - cpMonitor.incOperationFailure(connection != null ? connection.getHost() : null, nahe); - discardPipelineAndReleaseConnection(); - throw nahe; - } - } catch (NoAvailableHostsException nahe) { - cpMonitor.incOperationFailure(connection != null ? connection.getHost() : null, nahe); - discardPipelineAndReleaseConnection(); - throw nahe; - } - Jedis jedis = ((JedisConnection) connection).getClient(); - jedisPipeline = jedis.pipelined(); - cpMonitor.incOperationSuccess(connection.getHost(), 0); - } - - private void checkHashtag(final String key, final String hashtagValue) { - if (this.hashtag.get() != null) { - verifyHashtagValue(hashtagValue); - } else { - boolean success = this.hashtag.compareAndSet(null, hashtagValue); - if (!success) { - verifyHashtagValue(hashtagValue); - } else { - pipelined(key); - } - } - - } - - /** - * Checks that a pipeline is associated with a single key. Binary keys do not - * support hashtags. - * - * @param key - */ - private void checkKey(final byte[] key) { - if (theBinaryKey.get() != null) { - verifyKey(key); - } else { - boolean success = theBinaryKey.compareAndSet(null, key); - if (!success) { - // someone already beat us to it. that's fine, just verify - // that the key is the same - verifyKey(key); - } else { - pipelined(key); - } - } - } - - /** - * Checks that a pipeline is associated with a single key. If there is a hashtag - * defined in the first host of the connectionpool then we check that first. - * - * @param key - */ - private void checkKey(final String key) { - - /* - * Get hashtag from the first host of the active pool We cannot use the - * connection object because as of now we have not selected a connection. A - * connection is selected based on the key or hashtag respectively. - */ - String hashtag = connPool.getConfiguration().getHashtag(); - if (hashtag == null || hashtag.isEmpty()) { - if (theKey.get() != null) { - verifyKey(key); - } else { - boolean success = theKey.compareAndSet(null, key); - if (!success) { - // someone already beat us to it. that's fine, just verify - // that the key is the same - verifyKey(key); - } else { - pipelined(key); - } - } - } else { - /* - * We have a identified a hashtag in the Host object. That means Dynomite has a - * defined hashtag. Producing the hashvalue out of the hashtag and using that as - * a reference to the pipeline - */ - String hashValue = StringUtils.substringBetween(key, Character.toString(hashtag.charAt(0)), - Character.toString(hashtag.charAt(1))); - if (Strings.isNullOrEmpty(hashValue)) { - hashValue = key; - } - checkHashtag(key, hashValue); - } - } - - /** - * Verifies binary key with pipeline binary key - */ - private void verifyKey(final byte[] key) { - if (!theBinaryKey.get().equals(key)) { - try { - throw new RuntimeException("Must have same key for Redis Pipeline in Dynomite. This key: " + key); - } finally { - discardPipelineAndReleaseConnection(); - } - } - } - - /** - * Verifies key with pipeline key - */ - private void verifyKey(final String key) { - - if (!theKey.get().equals(key)) { - try { - throw new RuntimeException("Must have same key for Redis Pipeline in Dynomite. This key: " + key); - } finally { - discardPipelineAndReleaseConnection(); - } - } - } - - private void verifyHashtagValue(final String hashtagValue) { - - if (!this.hashtag.get().equals(hashtagValue)) { - try { - throw new RuntimeException( - "Must have same hashtag for Redis Pipeline in Dynomite. This hashvalue: " + hashtagValue); - } finally { - discardPipelineAndReleaseConnection(); - } - } - } - - private String decompressValue(String value) { - try { - if (ZipUtils.isCompressed(value)) { - return ZipUtils.decompressFromBase64String(value); - } - } catch (IOException e) { - Logger.warn("Unable to decompress value [" + value + "]"); - } - - return value; - } - - private byte[] decompressValue(byte[] value) { - try { - if (ZipUtils.isCompressed(value)) { - return ZipUtils.decompressBytesNonBase64(value); - } - } catch (IOException e) { - Logger.warn("Unable to decompress byte array value [" + value + "]"); - } - return value; - } - - /** - * As long as jdk 7 and below is supported we need to define our own function - * interfaces - */ - private interface Func0 { - R call(); - } - - public class PipelineResponse extends Response { - - private Response response; - - public PipelineResponse(Builder b) { - super(BuilderFactory.STRING); - } - - public PipelineResponse apply(Func0> f) { - this.response = f.call(); - return this; - } - - @Override - public String get() { - return decompressValue(response.get()); - } - - } - - public class PipelineLongResponse extends Response { - private Response response; - - public PipelineLongResponse(Builder b) { - super(b); - } - - public PipelineLongResponse apply(Func0> f) { - this.response = f.call(); - return this; - } - } - - public class PipelineListResponse extends Response> { - - private Response> response; - - public PipelineListResponse(Builder b) { - super(BuilderFactory.STRING_LIST); - } - - public PipelineListResponse apply(Func0>> f) { - this.response = f.call(); - return this; - } - - @Override - public List get() { - return new ArrayList( - CollectionUtils.transform(response.get(), new CollectionUtils.Transform() { - @Override - public String get(String s) { - return decompressValue(s); - } - })); - } - } - - public class PipelineBinaryResponse extends Response { - - private Response response; - - public PipelineBinaryResponse(Builder b) { - super(BuilderFactory.BYTE_ARRAY); - } - - public PipelineBinaryResponse apply(Func0> f) { - this.response = f.call(); - return this; - } - - @Override - public byte[] get() { - return decompressValue(response.get()); - } - - } - - public class PipelineMapResponse extends Response> { - - private Response> response; - - public PipelineMapResponse(Builder> b) { - super(BuilderFactory.STRING_MAP); - } - - @Override - public Map get() { - return CollectionUtils.transform(response.get(), - new CollectionUtils.MapEntryTransform() { - @Override - public String get(String key, String val) { - return decompressValue(val); - } - }); - } - } - - public class PipelineBinaryMapResponse extends Response> { - - private Response> response; - - public PipelineBinaryMapResponse(Builder> b) { - super(BuilderFactory.BYTE_ARRAY_MAP); - } - - public PipelineBinaryMapResponse apply(Func0>> f) { - this.response = f.call(); - return this; - } - - @Override - public Map get() { - return CollectionUtils.transform(response.get(), - new CollectionUtils.MapEntryTransform() { - @Override - public byte[] get(byte[] key, byte[] val) { - return decompressValue(val); - } - }); - } - - } - - private abstract class PipelineOperation { - - abstract Response execute(Pipeline jedisPipeline) throws DynoException; - - Response execute(final byte[] key, final OpName opName) { - checkKey(key); - return executeOperation(opName); - } - - Response execute(final String key, final OpName opName) { - checkKey(key); - return executeOperation(opName); - } - - Response executeOperation(final OpName opName) { - try { - opMonitor.recordOperation(opName.name()); - return execute(jedisPipeline); - - } catch (JedisConnectionException ex) { - handleConnectionException(ex); - throw ex; - } - } - - void handleConnectionException(JedisConnectionException ex) { - DynoException e = new FatalConnectionException(ex).setAttempt(1); - pipelineEx.set(e); - cpMonitor.incOperationFailure(connection.getHost(), e); - } - } - - private abstract class PipelineCompressionOperation extends PipelineOperation { - - /** - * Compresses the value based on the threshold defined by - * {@link ConnectionPoolConfiguration#getValueCompressionThreshold()} - * - * @param value - * @return - */ - public String compressValue(String value) { - String result = value; - int thresholdBytes = connPool.getConfiguration().getValueCompressionThreshold(); - - try { - // prefer speed over accuracy here so rather than using - // getBytes() to get the actual size - // just estimate using 2 bytes per character - if ((2 * value.length()) > thresholdBytes) { - result = ZipUtils.compressStringToBase64String(value); - } - } catch (IOException e) { - Logger.warn("UNABLE to compress [" + value + "]; sending value uncompressed"); - } - - return result; - } - - public byte[] compressValue(byte[] value) { - int thresholdBytes = connPool.getConfiguration().getValueCompressionThreshold(); - - if (value.length > thresholdBytes) { - try { - return ZipUtils.compressBytesNonBase64(value); - } catch (IOException e) { - Logger.warn("UNABLE to compress byte array [" + value + "]; sending value uncompressed"); - } - } - - return value; - } - - } - - @Override - public Response append(final String key, final String value) { - - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.append(key, value); - } - - }.execute(key, OpName.APPEND); - } - - @Override - public Response> blpop(final String arg) { - - return new PipelineOperation>() { - - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.blpop(arg); - } - }.execute(arg, OpName.BLPOP); - - } - - @Override - public Response> brpop(final String arg) { - return new PipelineOperation>() { - - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.brpop(arg); - } - }.execute(arg, OpName.BRPOP); - - } - - @Override - public Response decr(final String key) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.decr(key); - } - }.execute(key, OpName.DECR); - } - - @Override - public Response decrBy(final String key, final long integer) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.decrBy(key, integer); - } - }.execute(key, OpName.DECRBY); - } - - @Override - public Response del(final String key) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.del(key); - } - }.execute(key, OpName.DEL); - - } - - @Override - public Response unlink(String key) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.unlink(key); - } - }.execute(key, OpName.UNLINK); - } - - @Override - public Response echo(final String string) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.echo(string); - } - }.execute(string, OpName.ECHO); - - } - - @Override - public Response exists(final String key) { - return new PipelineOperation() { - - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.exists(key); - } - }.execute(key, OpName.EXISTS); - } - - @Override - public Response expire(final String key, final int seconds) { - return new PipelineOperation() { - - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return jedisPipeline.expire(key, seconds); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.EXPIRE.name(), duration, TimeUnit.MICROSECONDS); - } - } - }.execute(key, OpName.EXPIRE); - - } - - @Override - public Response pexpire(String key, long milliseconds) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response expireAt(final String key, final long unixTime) { - return new PipelineOperation() { - - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.expireAt(key, unixTime); - } - }.execute(key, OpName.EXPIREAT); - - } - - @Override - public Response pexpireAt(String key, long millisecondsTimestamp) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response get(final String key) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return jedisPipeline.get(key); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.GET.name(), duration, TimeUnit.MICROSECONDS); - } - } - }.execute(key, OpName.GET); - } else { - return new PipelineCompressionOperation() { - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return new PipelineResponse(null).apply(new Func0>() { - @Override - public Response call() { - return jedisPipeline.get(key); - } - }); - } - }.execute(key, OpName.GET); - } - - } - - @Override - public Response getbit(final String key, final long offset) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.getbit(key, offset); - } - }.execute(key, OpName.GETBIT); - - } - - @Override - public Response getrange(final String key, final long startOffset, final long endOffset) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.getrange(key, startOffset, endOffset); - } - }.execute(key, OpName.GETRANGE); - - } - - @Override - public Response getSet(final String key, final String value) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.getSet(key, value); - } - }.execute(key, OpName.GETSET); - } else { - return new PipelineCompressionOperation() { - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return new PipelineResponse(null).apply(new Func0>() { - @Override - public Response call() { - return jedisPipeline.getSet(key, compressValue(value)); - } - }); - } - }.execute(key, OpName.GETSET); - } - } - - @Override - public Response hdel(final String key, final String... field) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hdel(key, field); - } - }.execute(key, OpName.HDEL); - - } - - @Override - public Response hexists(final String key, final String field) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hexists(key, field); - } - }.execute(key, OpName.HEXISTS); - - } - - @Override - public Response hget(final String key, final String field) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hget(key, field); - } - }.execute(key, OpName.HGET); - } else { - return new PipelineCompressionOperation() { - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return new PipelineResponse(null).apply(new Func0>() { - @Override - public Response call() { - return jedisPipeline.hget(key, field); - } - }); - } - }.execute(key, OpName.HGET); - } - - } - - /** - * This method is a BinaryRedisPipeline command which dyno does not yet properly - * support, therefore the interface is not yet implemented. - */ - public Response hget(final byte[] key, final byte[] field) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hget(key, field); - } - }.execute(key, OpName.HGET); - } else { - return new PipelineCompressionOperation() { - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return new PipelineBinaryResponse(null).apply(new Func0>() { - @Override - public Response call() { - return jedisPipeline.hget(key, field); - } - }); - } - }.execute(key, OpName.HGET); - } - } - - @Override - public Response> hgetAll(final String key) { - - return new PipelineOperation>() { - - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return jedisPipeline.hgetAll(key); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.HGETALL.name(), duration, TimeUnit.MICROSECONDS); - } - } - - }.execute(key, OpName.HGETALL); - - } - - public Response> hgetAll(final byte[] key) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return jedisPipeline.hgetAll(key); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.HGETALL.name(), duration, TimeUnit.MICROSECONDS); - } - } - }.execute(key, OpName.HGETALL); - } else { - return new PipelineCompressionOperation>() { - @Override - Response> execute(final Pipeline jedisPipeline) throws DynoException { - return new PipelineBinaryMapResponse(null).apply(new Func0>>() { - @Override - public Response> call() { - return jedisPipeline.hgetAll(key); - } - }); - } - }.execute(key, OpName.HGETALL); - } - } - - @Override - public Response hincrBy(final String key, final String field, final long value) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hincrBy(key, field, value); - } - }.execute(key, OpName.HINCRBY); - } - - /* not supported by RedisPipeline 2.7.3 */ - public Response hincrByFloat(final String key, final String field, final double value) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hincrByFloat(key, field, value); - } - }.execute(key, OpName.HINCRBYFLOAT); - } - - @Override - public Response> hkeys(final String key) { - return new PipelineOperation>() { - - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hkeys(key); - } - }.execute(key, OpName.HKEYS); - - } - - public Response>> hscan(final String key, int cursor) { - throw new UnsupportedOperationException("'HSCAN' cannot be called in pipeline"); - } - - @Override - public Response hlen(final String key) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hlen(key); - } - }.execute(key, OpName.HLEN); - - } - - /** - * This method is a BinaryRedisPipeline command which dyno does not yet properly - * support, therefore the interface is not yet implemented. - */ - public Response> hmget(final byte[] key, final byte[]... fields) { - return new PipelineOperation>() { - - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return jedisPipeline.hmget(key, fields); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.HMGET.name(), duration, TimeUnit.MICROSECONDS); - } - } - }.execute(key, OpName.HMGET); - } - - @Override - public Response> hmget(final String key, final String... fields) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return jedisPipeline.hmget(key, fields); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.HMGET.name(), duration, TimeUnit.MICROSECONDS); - } - } - }.execute(key, OpName.HMGET); - } else { - return new PipelineCompressionOperation>() { - @Override - Response> execute(final Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return new PipelineListResponse(null).apply(new Func0>>() { - @Override - public Response> call() { - return jedisPipeline.hmget(key, fields); - } - }); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.HMGET.name(), duration, TimeUnit.MICROSECONDS); - } - } - }.execute(key, OpName.HGET); - } - } - - /** - * This method is a BinaryRedisPipeline command which dyno does not yet properly - * support, therefore the interface is not yet implemented since only a few - * binary commands are present. - */ - public Response hmset(final byte[] key, final Map hash) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return jedisPipeline.hmset(key, hash); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.HMSET.name(), duration, TimeUnit.MICROSECONDS); - } - } - }.execute(key, OpName.HMSET); - } else { - return new PipelineCompressionOperation() { - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return new PipelineResponse(null).apply(new Func0>() { - @Override - public Response call() { - return jedisPipeline.hmset(key, CollectionUtils.transform(hash, - new CollectionUtils.MapEntryTransform() { - @Override - public byte[] get(byte[] key, byte[] val) { - return compressValue(val); - } - })); - } - }); - } - }.execute(key, OpName.HMSET); - } - } - - @Override - public Response hmset(final String key, final Map hash) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return jedisPipeline.hmset(key, hash); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.HMSET.name(), duration, TimeUnit.MICROSECONDS); - } - } - }.execute(key, OpName.HMSET); - } else { - return new PipelineCompressionOperation() { - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return new PipelineResponse(null).apply(new Func0>() { - @Override - public Response call() { - return jedisPipeline.hmset(key, CollectionUtils.transform(hash, - new CollectionUtils.MapEntryTransform() { - @Override - public String get(String key, String val) { - return compressValue(val); - } - })); - } - }); - } - }.execute(key, OpName.HMSET); - } - - } - - @Override - public Response hset(final String key, final String field, final String value) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hset(key, field, value); - } - }.execute(key, OpName.HSET); - } else { - return new PipelineCompressionOperation() { - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return new PipelineLongResponse(null).apply(new Func0>() { - @Override - public Response call() { - return jedisPipeline.hset(key, field, compressValue(value)); - } - }); - } - }.execute(key, OpName.HSET); - } - } - - @Override - public Response hset(String key, Map hash) { - throw new UnsupportedOperationException("not yet implemented"); - } - - /** - * This method is a BinaryRedisPipeline command which dyno does not yet properly - * support, therefore the interface is not yet implemented. - */ - public Response hset(final byte[] key, final byte[] field, final byte[] value) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hset(key, field, value); - } - }.execute(key, OpName.HSET); - } else { - return new PipelineCompressionOperation() { - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return new PipelineLongResponse(null).apply(new Func0>() { - @Override - public Response call() { - return jedisPipeline.hset(key, field, compressValue(value)); - } - }); - } - }.execute(key, OpName.HSET); - } - } - - @Override - public Response hset(byte[] key, Map hash) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response hsetnx(final String key, final String field, final String value) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hsetnx(key, field, value); - } - }.execute(key, OpName.HSETNX); - } else { - return new PipelineCompressionOperation() { - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return new PipelineLongResponse(null).apply(new Func0>() { - @Override - public Response call() { - return jedisPipeline.hsetnx(key, field, compressValue(value)); - } - }); - } - }.execute(key, OpName.HSETNX); - } - } - - @Override - public Response> hvals(final String key) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hvals(key); - } - }.execute(key, OpName.HVALS); - } else { - return new PipelineCompressionOperation>() { - @Override - Response> execute(final Pipeline jedisPipeline) throws DynoException { - return new PipelineListResponse(null).apply(new Func0>>() { - @Override - public Response> call() { - return jedisPipeline.hvals(key); - } - }); - } - }.execute(key, OpName.HVALS); - } - - } - - @Override - public Response incr(final String key) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.incr(key); - } - - }.execute(key, OpName.INCR); - - } - - @Override - public Response incrBy(final String key, final long integer) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.incrBy(key, integer); - } - - }.execute(key, OpName.INCRBY); - - } - - /* not supported by RedisPipeline 2.7.3 */ - public Response incrByFloat(final String key, final double increment) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.incrByFloat(key, increment); - } - - }.execute(key, OpName.INCRBYFLOAT); - - } - - @Override - public Response lindex(final String key, final long index) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.lindex(key, index); - } - - }.execute(key, OpName.LINDEX); - - } - - @Override - public Response linsert(final String key, final ListPosition where, final String pivot, final String value) { - return new PipelineOperation() { + private static final Logger Logger = LoggerFactory.getLogger(DynoJedisPipeline.class); + + // ConnPool and connection to exec the pipeline + private final ConnectionPoolImpl connPool; + private volatile Connection connection; + private final DynoJedisPipelineMonitor opMonitor; + private final ConnectionPoolMonitor cpMonitor; + + // the cached pipeline + private volatile Pipeline jedisPipeline = null; + // the cached row key for the pipeline. all subsequent requests to pipeline + // must be the same. this is used to check that. + private final AtomicReference theKey = new AtomicReference(null); + private final AtomicReference theBinaryKey = new AtomicReference(null); + private final AtomicReference hashtag = new AtomicReference(null); + // used for tracking errors + private final AtomicReference pipelineEx = new AtomicReference(null); + + private static final String DynoPipeline = "DynoPipeline"; + + DynoJedisPipeline(ConnectionPoolImpl cPool, DynoJedisPipelineMonitor operationMonitor, + ConnectionPoolMonitor connPoolMonitor) { + this.connPool = cPool; + this.opMonitor = operationMonitor; + this.cpMonitor = connPoolMonitor; + } + + private void pipelined(final byte[] key) { + try { + try { + connection = connPool.getConnectionForOperation(new BaseOperation() { + + @Override + public String getName() { + return DynoPipeline; + } + + @Override + public String getStringKey() {// we do not use it in this context + return null; + } + + @Override + public byte[] getBinaryKey() { + return key; + } + + }); + } catch (NoAvailableHostsException nahe) { + cpMonitor.incOperationFailure(connection != null ? connection.getHost() : null, nahe); + discardPipelineAndReleaseConnection(); + throw nahe; + } + } catch (NoAvailableHostsException nahe) { + cpMonitor.incOperationFailure(connection != null ? connection.getHost() : null, nahe); + discardPipelineAndReleaseConnection(); + throw nahe; + } + Jedis jedis = ((JedisConnection) connection).getClient(); + jedisPipeline = jedis.pipelined(); + cpMonitor.incOperationSuccess(connection.getHost(), 0); + } + + private void pipelined(final String key) { + try { + try { + connection = connPool.getConnectionForOperation(new BaseOperation() { + + @Override + public String getName() { + return DynoPipeline; + } + + @Override + public String getStringKey() { + return key; + } + + @Override + public byte[] getBinaryKey() { // we do not use it in this context + return null; + } + + }); + } catch (NoAvailableHostsException nahe) { + cpMonitor.incOperationFailure(connection != null ? connection.getHost() : null, nahe); + discardPipelineAndReleaseConnection(); + throw nahe; + } + } catch (NoAvailableHostsException nahe) { + cpMonitor.incOperationFailure(connection != null ? connection.getHost() : null, nahe); + discardPipelineAndReleaseConnection(); + throw nahe; + } + Jedis jedis = ((JedisConnection) connection).getClient(); + jedisPipeline = jedis.pipelined(); + cpMonitor.incOperationSuccess(connection.getHost(), 0); + } + + private void checkHashtag(final String key, final String hashtagValue) { + if (this.hashtag.get() != null) { + verifyHashtagValue(hashtagValue); + } else { + boolean success = this.hashtag.compareAndSet(null, hashtagValue); + if (!success) { + verifyHashtagValue(hashtagValue); + } else { + pipelined(key); + } + } + + } + + /** + * Checks that a pipeline is associated with a single key. Binary keys do not + * support hashtags. + * + * @param key + */ + private void checkKey(final byte[] key) { + if (theBinaryKey.get() != null) { + verifyKey(key); + } else { + boolean success = theBinaryKey.compareAndSet(null, key); + if (!success) { + // someone already beat us to it. that's fine, just verify + // that the key is the same + verifyKey(key); + } else { + pipelined(key); + } + } + } + + /** + * Checks that a pipeline is associated with a single key. If there is a hashtag + * defined in the first host of the connectionpool then we check that first. + * + * @param key + */ + private void checkKey(final String key) { + + /* + * Get hashtag from the first host of the active pool We cannot use the + * connection object because as of now we have not selected a connection. A + * connection is selected based on the key or hashtag respectively. + */ + String hashtag = connPool.getConfiguration().getHashtag(); + if (hashtag == null || hashtag.isEmpty()) { + if (theKey.get() != null) { + verifyKey(key); + } else { + boolean success = theKey.compareAndSet(null, key); + if (!success) { + // someone already beat us to it. that's fine, just verify + // that the key is the same + verifyKey(key); + } else { + pipelined(key); + } + } + } else { + /* + * We have a identified a hashtag in the Host object. That means Dynomite has a + * defined hashtag. Producing the hashvalue out of the hashtag and using that as + * a reference to the pipeline + */ + String hashValue = StringUtils.substringBetween(key, Character.toString(hashtag.charAt(0)), + Character.toString(hashtag.charAt(1))); + if (Strings.isNullOrEmpty(hashValue)) { + hashValue = key; + } + checkHashtag(key, hashValue); + } + } + + /** + * Verifies binary key with pipeline binary key + */ + private void verifyKey(final byte[] key) { + if (!theBinaryKey.get().equals(key)) { + try { + throw new RuntimeException("Must have same key for Redis Pipeline in Dynomite. This key: " + key); + } finally { + discardPipelineAndReleaseConnection(); + } + } + } + + /** + * Verifies key with pipeline key + */ + private void verifyKey(final String key) { + + if (!theKey.get().equals(key)) { + try { + throw new RuntimeException("Must have same key for Redis Pipeline in Dynomite. This key: " + key); + } finally { + discardPipelineAndReleaseConnection(); + } + } + } + + private void verifyHashtagValue(final String hashtagValue) { + + if (!this.hashtag.get().equals(hashtagValue)) { + try { + throw new RuntimeException( + "Must have same hashtag for Redis Pipeline in Dynomite. This hashvalue: " + hashtagValue); + } finally { + discardPipelineAndReleaseConnection(); + } + } + } + + private String decompressValue(String value) { + try { + if (ZipUtils.isCompressed(value)) { + return ZipUtils.decompressFromBase64String(value); + } + } catch (IOException e) { + Logger.warn("Unable to decompress value [" + value + "]"); + } + + return value; + } + + private byte[] decompressValue(byte[] value) { + try { + if (ZipUtils.isCompressed(value)) { + return ZipUtils.decompressBytesNonBase64(value); + } + } catch (IOException e) { + Logger.warn("Unable to decompress byte array value [" + value + "]"); + } + return value; + } + + /** + * As long as jdk 7 and below is supported we need to define our own function + * interfaces + */ + private interface Func0 { + R call(); + } + + public class PipelineResponse extends Response { + + private Response response; + + public PipelineResponse(Builder b) { + super(BuilderFactory.STRING); + } + + public PipelineResponse apply(Func0> f) { + this.response = f.call(); + return this; + } + + @Override + public String get() { + return decompressValue(response.get()); + } + + } + + public class PipelineLongResponse extends Response { + private Response response; + + public PipelineLongResponse(Builder b) { + super(b); + } + + public PipelineLongResponse apply(Func0> f) { + this.response = f.call(); + return this; + } + } + + public class PipelineListResponse extends Response> { + + private Response> response; + + public PipelineListResponse(Builder b) { + super(BuilderFactory.STRING_LIST); + } + + public PipelineListResponse apply(Func0>> f) { + this.response = f.call(); + return this; + } + + @Override + public List get() { + return new ArrayList( + CollectionUtils.transform(response.get(), new CollectionUtils.Transform() { + @Override + public String get(String s) { + return decompressValue(s); + } + })); + } + } + + public class PipelineBinaryResponse extends Response { + + private Response response; + + public PipelineBinaryResponse(Builder b) { + super(BuilderFactory.BYTE_ARRAY); + } + + public PipelineBinaryResponse apply(Func0> f) { + this.response = f.call(); + return this; + } + + @Override + public byte[] get() { + return decompressValue(response.get()); + } + + } + + public class PipelineMapResponse extends Response> { + + private Response> response; + + public PipelineMapResponse(Builder> b) { + super(BuilderFactory.STRING_MAP); + } + + @Override + public Map get() { + return CollectionUtils.transform(response.get(), + new CollectionUtils.MapEntryTransform() { + @Override + public String get(String key, String val) { + return decompressValue(val); + } + }); + } + } + + public class PipelineBinaryMapResponse extends Response> { + + private Response> response; + + public PipelineBinaryMapResponse(Builder> b) { + super(BuilderFactory.BYTE_ARRAY_MAP); + } + + public PipelineBinaryMapResponse apply(Func0>> f) { + this.response = f.call(); + return this; + } + + @Override + public Map get() { + return CollectionUtils.transform(response.get(), + new CollectionUtils.MapEntryTransform() { + @Override + public byte[] get(byte[] key, byte[] val) { + return decompressValue(val); + } + }); + } + + } + + private abstract class PipelineOperation { + + abstract Response execute(Pipeline jedisPipeline) throws DynoException; + + Response execute(final byte[] key, final OpName opName) { + checkKey(key); + return executeOperation(opName); + } + + Response execute(final String key, final OpName opName) { + checkKey(key); + return executeOperation(opName); + } + + Response executeOperation(final OpName opName) { + try { + opMonitor.recordOperation(opName.name()); + return execute(jedisPipeline); + + } catch (JedisConnectionException ex) { + handleConnectionException(ex); + throw ex; + } + } + + void handleConnectionException(JedisConnectionException ex) { + DynoException e = new FatalConnectionException(ex).setAttempt(1); + pipelineEx.set(e); + cpMonitor.incOperationFailure(connection.getHost(), e); + } + } + + private abstract class PipelineCompressionOperation extends PipelineOperation { + + /** + * Compresses the value based on the threshold defined by + * {@link ConnectionPoolConfiguration#getValueCompressionThreshold()} + * + * @param value + * @return + */ + public String compressValue(String value) { + String result = value; + int thresholdBytes = connPool.getConfiguration().getValueCompressionThreshold(); + + try { + // prefer speed over accuracy here so rather than using + // getBytes() to get the actual size + // just estimate using 2 bytes per character + if ((2 * value.length()) > thresholdBytes) { + result = ZipUtils.compressStringToBase64String(value); + } + } catch (IOException e) { + Logger.warn("UNABLE to compress [" + value + "]; sending value uncompressed"); + } + + return result; + } + + public byte[] compressValue(byte[] value) { + int thresholdBytes = connPool.getConfiguration().getValueCompressionThreshold(); + + if (value.length > thresholdBytes) { + try { + return ZipUtils.compressBytesNonBase64(value); + } catch (IOException e) { + Logger.warn("UNABLE to compress byte array [" + value + "]; sending value uncompressed"); + } + } + + return value; + } + + } + + @Override + public Response append(final String key, final String value) { + + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.append(key, value); + } + + }.execute(key, OpName.APPEND); + } + + @Override + public Response> blpop(final String arg) { + + return new PipelineOperation>() { + + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.blpop(arg); + } + }.execute(arg, OpName.BLPOP); + + } + + @Override + public Response> brpop(final String arg) { + return new PipelineOperation>() { + + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.brpop(arg); + } + }.execute(arg, OpName.BRPOP); + + } + + @Override + public Response decr(final String key) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.decr(key); + } + }.execute(key, OpName.DECR); + } + + @Override + public Response decrBy(final String key, final long integer) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.decrBy(key, integer); + } + }.execute(key, OpName.DECRBY); + } + + @Override + public Response del(final String key) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.del(key); + } + }.execute(key, OpName.DEL); + + } + + @Override + public Response unlink(String key) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.unlink(key); + } + }.execute(key, OpName.UNLINK); + } + + @Override + public Response echo(final String string) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.echo(string); + } + }.execute(string, OpName.ECHO); + + } + + @Override + public Response exists(final String key) { + return new PipelineOperation() { + + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.exists(key); + } + }.execute(key, OpName.EXISTS); + } + + @Override + public Response expire(final String key, final int seconds) { + return new PipelineOperation() { + + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return jedisPipeline.expire(key, seconds); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.EXPIRE.name(), duration, TimeUnit.MICROSECONDS); + } + } + }.execute(key, OpName.EXPIRE); + + } + + @Override + public Response pexpire(String key, long milliseconds) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response expireAt(final String key, final long unixTime) { + return new PipelineOperation() { + + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.expireAt(key, unixTime); + } + }.execute(key, OpName.EXPIREAT); + + } + + @Override + public Response pexpireAt(String key, long millisecondsTimestamp) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response get(final String key) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return jedisPipeline.get(key); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.GET.name(), duration, TimeUnit.MICROSECONDS); + } + } + }.execute(key, OpName.GET); + } else { + return new PipelineCompressionOperation() { + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return new PipelineResponse(null).apply(new Func0>() { + @Override + public Response call() { + return jedisPipeline.get(key); + } + }); + } + }.execute(key, OpName.GET); + } + + } + + @Override + public Response getbit(final String key, final long offset) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.getbit(key, offset); + } + }.execute(key, OpName.GETBIT); + + } + + @Override + public Response getrange(final String key, final long startOffset, final long endOffset) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.getrange(key, startOffset, endOffset); + } + }.execute(key, OpName.GETRANGE); + + } + + @Override + public Response getSet(final String key, final String value) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.getSet(key, value); + } + }.execute(key, OpName.GETSET); + } else { + return new PipelineCompressionOperation() { + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return new PipelineResponse(null).apply(new Func0>() { + @Override + public Response call() { + return jedisPipeline.getSet(key, compressValue(value)); + } + }); + } + }.execute(key, OpName.GETSET); + } + } + + @Override + public Response hdel(final String key, final String... field) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hdel(key, field); + } + }.execute(key, OpName.HDEL); + + } + + @Override + public Response hexists(final String key, final String field) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hexists(key, field); + } + }.execute(key, OpName.HEXISTS); + + } + + @Override + public Response hget(final String key, final String field) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hget(key, field); + } + }.execute(key, OpName.HGET); + } else { + return new PipelineCompressionOperation() { + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return new PipelineResponse(null).apply(new Func0>() { + @Override + public Response call() { + return jedisPipeline.hget(key, field); + } + }); + } + }.execute(key, OpName.HGET); + } + + } + + /** + * This method is a BinaryRedisPipeline command which dyno does not yet properly + * support, therefore the interface is not yet implemented. + */ + public Response hget(final byte[] key, final byte[] field) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hget(key, field); + } + }.execute(key, OpName.HGET); + } else { + return new PipelineCompressionOperation() { + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return new PipelineBinaryResponse(null).apply(new Func0>() { + @Override + public Response call() { + return jedisPipeline.hget(key, field); + } + }); + } + }.execute(key, OpName.HGET); + } + } + + @Override + public Response> hgetAll(final String key) { + + return new PipelineOperation>() { + + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return jedisPipeline.hgetAll(key); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.HGETALL.name(), duration, TimeUnit.MICROSECONDS); + } + } + + }.execute(key, OpName.HGETALL); + + } + + public Response> hgetAll(final byte[] key) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation>() { + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return jedisPipeline.hgetAll(key); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.HGETALL.name(), duration, TimeUnit.MICROSECONDS); + } + } + }.execute(key, OpName.HGETALL); + } else { + return new PipelineCompressionOperation>() { + @Override + Response> execute(final Pipeline jedisPipeline) throws DynoException { + return new PipelineBinaryMapResponse(null).apply(new Func0>>() { + @Override + public Response> call() { + return jedisPipeline.hgetAll(key); + } + }); + } + }.execute(key, OpName.HGETALL); + } + } + + @Override + public Response hincrBy(final String key, final String field, final long value) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hincrBy(key, field, value); + } + }.execute(key, OpName.HINCRBY); + } + + /* not supported by RedisPipeline 2.7.3 */ + public Response hincrByFloat(final String key, final String field, final double value) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hincrByFloat(key, field, value); + } + }.execute(key, OpName.HINCRBYFLOAT); + } + + @Override + public Response> hkeys(final String key) { + return new PipelineOperation>() { + + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hkeys(key); + } + }.execute(key, OpName.HKEYS); + + } + + public Response>> hscan(final String key, int cursor) { + throw new UnsupportedOperationException("'HSCAN' cannot be called in pipeline"); + } + + @Override + public Response hlen(final String key) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hlen(key); + } + }.execute(key, OpName.HLEN); + + } + + /** + * This method is a BinaryRedisPipeline command which dyno does not yet properly + * support, therefore the interface is not yet implemented. + */ + public Response> hmget(final byte[] key, final byte[]... fields) { + return new PipelineOperation>() { + + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return jedisPipeline.hmget(key, fields); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.HMGET.name(), duration, TimeUnit.MICROSECONDS); + } + } + }.execute(key, OpName.HMGET); + } + + @Override + public Response> hmget(final String key, final String... fields) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation>() { + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return jedisPipeline.hmget(key, fields); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.HMGET.name(), duration, TimeUnit.MICROSECONDS); + } + } + }.execute(key, OpName.HMGET); + } else { + return new PipelineCompressionOperation>() { + @Override + Response> execute(final Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return new PipelineListResponse(null).apply(new Func0>>() { + @Override + public Response> call() { + return jedisPipeline.hmget(key, fields); + } + }); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.HMGET.name(), duration, TimeUnit.MICROSECONDS); + } + } + }.execute(key, OpName.HGET); + } + } + + /** + * This method is a BinaryRedisPipeline command which dyno does not yet properly + * support, therefore the interface is not yet implemented since only a few + * binary commands are present. + */ + public Response hmset(final byte[] key, final Map hash) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return jedisPipeline.hmset(key, hash); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.HMSET.name(), duration, TimeUnit.MICROSECONDS); + } + } + }.execute(key, OpName.HMSET); + } else { + return new PipelineCompressionOperation() { + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return new PipelineResponse(null).apply(new Func0>() { + @Override + public Response call() { + return jedisPipeline.hmset(key, CollectionUtils.transform(hash, + new CollectionUtils.MapEntryTransform() { + @Override + public byte[] get(byte[] key, byte[] val) { + return compressValue(val); + } + })); + } + }); + } + }.execute(key, OpName.HMSET); + } + } + + @Override + public Response hmset(final String key, final Map hash) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return jedisPipeline.hmset(key, hash); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.HMSET.name(), duration, TimeUnit.MICROSECONDS); + } + } + }.execute(key, OpName.HMSET); + } else { + return new PipelineCompressionOperation() { + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return new PipelineResponse(null).apply(new Func0>() { + @Override + public Response call() { + return jedisPipeline.hmset(key, CollectionUtils.transform(hash, + new CollectionUtils.MapEntryTransform() { + @Override + public String get(String key, String val) { + return compressValue(val); + } + })); + } + }); + } + }.execute(key, OpName.HMSET); + } + + } + + @Override + public Response hset(final String key, final String field, final String value) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hset(key, field, value); + } + }.execute(key, OpName.HSET); + } else { + return new PipelineCompressionOperation() { + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return new PipelineLongResponse(null).apply(new Func0>() { + @Override + public Response call() { + return jedisPipeline.hset(key, field, compressValue(value)); + } + }); + } + }.execute(key, OpName.HSET); + } + } + + @Override + public Response hset(String key, Map hash) { + throw new UnsupportedOperationException("not yet implemented"); + } + + /** + * This method is a BinaryRedisPipeline command which dyno does not yet properly + * support, therefore the interface is not yet implemented. + */ + public Response hset(final byte[] key, final byte[] field, final byte[] value) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hset(key, field, value); + } + }.execute(key, OpName.HSET); + } else { + return new PipelineCompressionOperation() { + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return new PipelineLongResponse(null).apply(new Func0>() { + @Override + public Response call() { + return jedisPipeline.hset(key, field, compressValue(value)); + } + }); + } + }.execute(key, OpName.HSET); + } + } + + @Override + public Response hset(byte[] key, Map hash) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response hsetnx(final String key, final String field, final String value) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hsetnx(key, field, value); + } + }.execute(key, OpName.HSETNX); + } else { + return new PipelineCompressionOperation() { + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return new PipelineLongResponse(null).apply(new Func0>() { + @Override + public Response call() { + return jedisPipeline.hsetnx(key, field, compressValue(value)); + } + }); + } + }.execute(key, OpName.HSETNX); + } + } + + @Override + public Response> hvals(final String key) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation>() { + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hvals(key); + } + }.execute(key, OpName.HVALS); + } else { + return new PipelineCompressionOperation>() { + @Override + Response> execute(final Pipeline jedisPipeline) throws DynoException { + return new PipelineListResponse(null).apply(new Func0>>() { + @Override + public Response> call() { + return jedisPipeline.hvals(key); + } + }); + } + }.execute(key, OpName.HVALS); + } + + } + + @Override + public Response incr(final String key) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.incr(key); + } + + }.execute(key, OpName.INCR); + + } + + @Override + public Response incrBy(final String key, final long integer) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.incrBy(key, integer); + } + + }.execute(key, OpName.INCRBY); + + } + + /* not supported by RedisPipeline 2.7.3 */ + public Response incrByFloat(final String key, final double increment) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.incrByFloat(key, increment); + } + + }.execute(key, OpName.INCRBYFLOAT); + + } + + @Override + public Response lindex(final String key, final long index) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.lindex(key, index); + } + + }.execute(key, OpName.LINDEX); + + } + + @Override + public Response linsert(final String key, final ListPosition where, final String pivot, final String value) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.linsert(key, where, pivot, value); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.linsert(key, where, pivot, value); + } - }.execute(key, OpName.LINSERT); + }.execute(key, OpName.LINSERT); - } + } - @Override - public Response llen(final String key) { - return new PipelineOperation() { + @Override + public Response llen(final String key) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.llen(key); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.llen(key); + } - }.execute(key, OpName.LLEN); + }.execute(key, OpName.LLEN); - } + } - @Override - public Response lpop(final String key) { - return new PipelineOperation() { + @Override + public Response lpop(final String key) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.lpop(key); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.lpop(key); + } - }.execute(key, OpName.LPOP); + }.execute(key, OpName.LPOP); - } + } - @Override - public Response lpush(final String key, final String... string) { - return new PipelineOperation() { + @Override + public Response lpush(final String key, final String... string) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.lpush(key, string); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.lpush(key, string); + } - }.execute(key, OpName.LPUSH); + }.execute(key, OpName.LPUSH); - } + } - @Override - public Response lpushx(final String key, final String... string) { - return new PipelineOperation() { + @Override + public Response lpushx(final String key, final String... string) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.lpushx(key, string); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.lpushx(key, string); + } - }.execute(key, OpName.LPUSHX); + }.execute(key, OpName.LPUSHX); - } + } - @Override - public Response> lrange(final String key, final long start, final long end) { - return new PipelineOperation>() { + @Override + public Response> lrange(final String key, final long start, final long end) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.lrange(key, start, end); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.lrange(key, start, end); + } - }.execute(key, OpName.LRANGE); + }.execute(key, OpName.LRANGE); - } + } - @Override - public Response lrem(final String key, final long count, final String value) { - return new PipelineOperation() { + @Override + public Response lrem(final String key, final long count, final String value) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.lrem(key, count, value); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.lrem(key, count, value); + } - }.execute(key, OpName.LREM); + }.execute(key, OpName.LREM); - } + } - @Override - public Response lset(final String key, final long index, final String value) { - return new PipelineOperation() { + @Override + public Response lset(final String key, final long index, final String value) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.lset(key, index, value); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.lset(key, index, value); + } - }.execute(key, OpName.LSET); + }.execute(key, OpName.LSET); - } + } - @Override - public Response ltrim(final String key, final long start, final long end) { - return new PipelineOperation() { + @Override + public Response ltrim(final String key, final long start, final long end) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.ltrim(key, start, end); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.ltrim(key, start, end); + } - }.execute(key, OpName.LTRIM); + }.execute(key, OpName.LTRIM); - } + } - @Override - public Response move(final String key, final int dbIndex) { - return new PipelineOperation() { + @Override + public Response move(final String key, final int dbIndex) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.move(key, dbIndex); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.move(key, dbIndex); + } - }.execute(key, OpName.MOVE); + }.execute(key, OpName.MOVE); - } + } - @Override - public Response persist(final String key) { - return new PipelineOperation() { + @Override + public Response persist(final String key) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.persist(key); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.persist(key); + } - }.execute(key, OpName.PERSIST); + }.execute(key, OpName.PERSIST); - } + } - /* not supported by RedisPipeline 2.7.3 */ - public Response rename(final String oldkey, final String newkey) { - return new PipelineOperation() { + /* not supported by RedisPipeline 2.7.3 */ + public Response rename(final String oldkey, final String newkey) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.rename(oldkey, newkey); - } - }.execute(oldkey, OpName.RENAME); + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.rename(oldkey, newkey); + } + }.execute(oldkey, OpName.RENAME); - } + } - /* not supported by RedisPipeline 2.7.3 */ - public Response renamenx(final String oldkey, final String newkey) { - return new PipelineOperation() { + /* not supported by RedisPipeline 2.7.3 */ + public Response renamenx(final String oldkey, final String newkey) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.renamenx(oldkey, newkey); - } - }.execute(oldkey, OpName.RENAMENX); + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.renamenx(oldkey, newkey); + } + }.execute(oldkey, OpName.RENAMENX); - } + } - @Override - public Response rpop(final String key) { - return new PipelineOperation() { + @Override + public Response rpop(final String key) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.rpop(key); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.rpop(key); + } - }.execute(key, OpName.RPOP); + }.execute(key, OpName.RPOP); - } + } - @Override - public Response rpush(final String key, final String... string) { - return new PipelineOperation() { + @Override + public Response rpush(final String key, final String... string) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.rpush(key, string); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.rpush(key, string); + } - }.execute(key, OpName.RPUSH); + }.execute(key, OpName.RPUSH); - } + } - @Override - public Response rpushx(final String key, final String... string) { - return new PipelineOperation() { + @Override + public Response rpushx(final String key, final String... string) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.rpushx(key, string); - } - - }.execute(key, OpName.RPUSHX); - - } - - @Override - public Response sadd(final String key, final String... member) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.sadd(key, member); - } - - }.execute(key, OpName.SADD); - - } - - @Override - public Response scard(final String key) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.scard(key); - } - - }.execute(key, OpName.SCARD); - - } - - @Override - public Response sismember(final String key, final String member) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.sismember(key, member); - } - - }.execute(key, OpName.SISMEMBER); - } - - @Override - public Response set(final String key, final String value) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return jedisPipeline.set(key, value); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.SET.name(), duration, TimeUnit.MICROSECONDS); - } - } - - }.execute(key, OpName.SET); - } else { - return new PipelineCompressionOperation() { - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return new PipelineResponse(null).apply(new Func0>() { - @Override - public Response call() { - return jedisPipeline.set(key, compressValue(value)); - } - }); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.SET.name(), duration, TimeUnit.MICROSECONDS); - } - } - }.execute(key, OpName.SET); - } - } - - @Override - public Response setbit(final String key, final long offset, final boolean value) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.setbit(key, offset, value); - } - - }.execute(key, OpName.SETBIT); - - } - - @Override - public Response setex(final String key, final int seconds, final String value) { - if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.setex(key, seconds, value); - } - }.execute(key, OpName.SETEX); - } else { - return new PipelineCompressionOperation() { - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return new PipelineResponse(null).apply(new Func0>() { - @Override - public Response call() { - return jedisPipeline.setex(key, seconds, compressValue(value)); - } - }); - } - }.execute(key, OpName.SETEX); - } - - } - - @Override - public Response setnx(final String key, final String value) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.setnx(key, value); - } - }.execute(key, OpName.SETNX); - } - - @Override - public Response setrange(final String key, final long offset, final String value) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.setrange(key, offset, value); - } - - }.execute(key, OpName.SETRANGE); - - } - - @Override - public Response> smembers(final String key) { - return new PipelineOperation>() { - - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.smembers(key); - } - - }.execute(key, OpName.SMEMBERS); - - } - - @Override - public Response> sort(final String key) { - return new PipelineOperation>() { - - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.sort(key); - } - - }.execute(key, OpName.SORT); - - } - - @Override - public Response> sort(final String key, final SortingParams sortingParameters) { - return new PipelineOperation>() { - - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.sort(key, sortingParameters); - } - - }.execute(key, OpName.SORT); + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.rpushx(key, string); + } + + }.execute(key, OpName.RPUSHX); + + } + + @Override + public Response sadd(final String key, final String... member) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.sadd(key, member); + } + + }.execute(key, OpName.SADD); + + } + + @Override + public Response scard(final String key) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.scard(key); + } + + }.execute(key, OpName.SCARD); + + } + + @Override + public Response sismember(final String key, final String member) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.sismember(key, member); + } + + }.execute(key, OpName.SISMEMBER); + } + + @Override + public Response set(final String key, final String value) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return jedisPipeline.set(key, value); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.SET.name(), duration, TimeUnit.MICROSECONDS); + } + } + + }.execute(key, OpName.SET); + } else { + return new PipelineCompressionOperation() { + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return new PipelineResponse(null).apply(new Func0>() { + @Override + public Response call() { + return jedisPipeline.set(key, compressValue(value)); + } + }); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.SET.name(), duration, TimeUnit.MICROSECONDS); + } + } + }.execute(key, OpName.SET); + } + } + + @Override + public Response setbit(final String key, final long offset, final boolean value) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.setbit(key, offset, value); + } + + }.execute(key, OpName.SETBIT); + + } + + @Override + public Response setex(final String key, final int seconds, final String value) { + if (CompressionStrategy.NONE == connPool.getConfiguration().getCompressionStrategy()) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.setex(key, seconds, value); + } + }.execute(key, OpName.SETEX); + } else { + return new PipelineCompressionOperation() { + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return new PipelineResponse(null).apply(new Func0>() { + @Override + public Response call() { + return jedisPipeline.setex(key, seconds, compressValue(value)); + } + }); + } + }.execute(key, OpName.SETEX); + } + + } + + @Override + public Response setnx(final String key, final String value) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.setnx(key, value); + } + }.execute(key, OpName.SETNX); + } + + @Override + public Response setrange(final String key, final long offset, final String value) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.setrange(key, offset, value); + } + + }.execute(key, OpName.SETRANGE); + + } + + @Override + public Response> smembers(final String key) { + return new PipelineOperation>() { + + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.smembers(key); + } + + }.execute(key, OpName.SMEMBERS); + + } + + @Override + public Response> sort(final String key) { + return new PipelineOperation>() { + + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.sort(key); + } + + }.execute(key, OpName.SORT); + + } + + @Override + public Response> sort(final String key, final SortingParams sortingParameters) { + return new PipelineOperation>() { + + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.sort(key, sortingParameters); + } + + }.execute(key, OpName.SORT); - } + } - @Override - public Response spop(final String key) { - return new PipelineOperation() { + @Override + public Response spop(final String key) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.spop(key); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.spop(key); + } - }.execute(key, OpName.SPOP); - - } - - @Override - public Response> spop(final String key, final long count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response srandmember(final String key) { - return new PipelineOperation() { + }.execute(key, OpName.SPOP); + + } + + @Override + public Response> spop(final String key, final long count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response srandmember(final String key) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.srandmember(key); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.srandmember(key); + } - }.execute(key, OpName.SRANDMEMBER); + }.execute(key, OpName.SRANDMEMBER); - } + } - @Override - public Response srem(final String key, final String... member) { - return new PipelineOperation() { + @Override + public Response srem(final String key, final String... member) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.srem(key, member); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.srem(key, member); + } - }.execute(key, OpName.SREM); + }.execute(key, OpName.SREM); - } + } - /** - * This method is not supported by the BinaryRedisPipeline interface. - */ - public Response> sscan(final String key, final int cursor) { - throw new UnsupportedOperationException("'SSCAN' cannot be called in pipeline"); - } + /** + * This method is not supported by the BinaryRedisPipeline interface. + */ + public Response> sscan(final String key, final int cursor) { + throw new UnsupportedOperationException("'SSCAN' cannot be called in pipeline"); + } - /** - * This method is not supported by the BinaryRedisPipeline interface. - */ - public Response> sscan(final String key, final String cursor) { - throw new UnsupportedOperationException("'SSCAN' cannot be called in pipeline"); - } + /** + * This method is not supported by the BinaryRedisPipeline interface. + */ + public Response> sscan(final String key, final String cursor) { + throw new UnsupportedOperationException("'SSCAN' cannot be called in pipeline"); + } - @Override - public Response strlen(final String key) { - return new PipelineOperation() { + @Override + public Response strlen(final String key) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.strlen(key); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.strlen(key); + } - }.execute(key, OpName.STRLEN); + }.execute(key, OpName.STRLEN); - } + } - @Override - public Response substr(final String key, final int start, final int end) { - return new PipelineOperation() { + @Override + public Response substr(final String key, final int start, final int end) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.substr(key, start, end); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.substr(key, start, end); + } - }.execute(key, OpName.SUBSTR); + }.execute(key, OpName.SUBSTR); - } + } - @Override - public Response touch(String key) { - throw new UnsupportedOperationException("not yet implemented"); - } + @Override + public Response touch(String key) { + throw new UnsupportedOperationException("not yet implemented"); + } - @Override - public Response ttl(final String key) { - return new PipelineOperation() { + @Override + public Response ttl(final String key) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.ttl(key); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.ttl(key); + } - }.execute(key, OpName.TTL); + }.execute(key, OpName.TTL); - } + } - @Override - public Response pttl(String key) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.pttl(key); - } - }.execute(key, OpName.PTTL); - } + @Override + public Response pttl(String key) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.pttl(key); + } + }.execute(key, OpName.PTTL); + } - @Override - public Response type(final String key) { - return new PipelineOperation() { + @Override + public Response type(final String key) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.type(key); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.type(key); + } - }.execute(key, OpName.TYPE); + }.execute(key, OpName.TYPE); - } + } - @Override - public Response zadd(final String key, final double score, final String member) { - return new PipelineOperation() { + @Override + public Response zadd(final String key, final double score, final String member) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zadd(key, score, member); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zadd(key, score, member); + } - }.execute(key, OpName.ZADD); + }.execute(key, OpName.ZADD); - } + } - @Override - public Response zadd(final String key, final Map scoreMembers) { - return new PipelineOperation() { + @Override + public Response zadd(final String key, final Map scoreMembers) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zadd(key, scoreMembers); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zadd(key, scoreMembers); + } - }.execute(key, OpName.ZADD); + }.execute(key, OpName.ZADD); - } + } - @Override - public Response zcard(final String key) { - return new PipelineOperation() { + @Override + public Response zcard(final String key) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zcard(key); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zcard(key); + } - }.execute(key, OpName.ZCARD); + }.execute(key, OpName.ZCARD); - } + } - @Override - public Response zcount(final String key, final double min, final double max) { - return new PipelineOperation() { + @Override + public Response zcount(final String key, final double min, final double max) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zcount(key, min, max); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zcount(key, min, max); + } - }.execute(key, OpName.ZCOUNT); + }.execute(key, OpName.ZCOUNT); - } + } - @Override - public Response zcount(String key, String min, String max) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zcount(key, min, max); - } - }.execute(key, OpName.ZCOUNT); - } + @Override + public Response zcount(String key, String min, String max) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zcount(key, min, max); + } + }.execute(key, OpName.ZCOUNT); + } - @Override - public Response zincrby(final String key, final double score, final String member) { - return new PipelineOperation() { + @Override + public Response zincrby(final String key, final double score, final String member) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zincrby(key, score, member); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zincrby(key, score, member); + } - }.execute(key, OpName.ZINCRBY); + }.execute(key, OpName.ZINCRBY); - } + } - @Override - public Response> zrange(final String key, final long start, final long end) { - return new PipelineOperation>() { + @Override + public Response> zrange(final String key, final long start, final long end) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrange(key, start, end); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrange(key, start, end); + } - }.execute(key, OpName.ZRANGE); + }.execute(key, OpName.ZRANGE); - } + } - @Override - public Response> zrangeByScore(final String key, final double min, final double max) { - return new PipelineOperation>() { + @Override + public Response> zrangeByScore(final String key, final double min, final double max) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrangeByScore(key, min, max); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrangeByScore(key, min, max); + } - }.execute(key, OpName.ZRANGEBYSCORE); + }.execute(key, OpName.ZRANGEBYSCORE); - } + } - @Override - public Response> zrangeByScore(final String key, final String min, final String max) { - return new PipelineOperation>() { + @Override + public Response> zrangeByScore(final String key, final String min, final String max) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrangeByScore(key, min, max); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrangeByScore(key, min, max); + } - }.execute(key, OpName.ZRANGEBYSCORE); + }.execute(key, OpName.ZRANGEBYSCORE); - } + } - @Override - public Response> zrangeByScore(final String key, final double min, final double max, final int offset, - final int count) { - return new PipelineOperation>() { + @Override + public Response> zrangeByScore(final String key, final double min, final double max, final int offset, + final int count) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrangeByScore(key, min, max, offset, count); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrangeByScore(key, min, max, offset, count); + } - }.execute(key, OpName.ZRANGEBYSCORE); + }.execute(key, OpName.ZRANGEBYSCORE); - } + } - @Override - public Response> zrangeByScore(String key, String min, String max, int offset, int count) { - return new PipelineOperation>() { + @Override + public Response> zrangeByScore(String key, String min, String max, int offset, int count) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrangeByScore(key, min, max, offset, count); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrangeByScore(key, min, max, offset, count); + } - }.execute(key, OpName.ZRANGEBYSCORE); - } + }.execute(key, OpName.ZRANGEBYSCORE); + } - @Override - public Response> zrangeByScoreWithScores(final String key, final double min, final double max) { - return new PipelineOperation>() { + @Override + public Response> zrangeByScoreWithScores(final String key, final double min, final double max) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrangeByScoreWithScores(key, min, max); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrangeByScoreWithScores(key, min, max); + } - }.execute(key, OpName.ZRANGEBYSCOREWITHSCORES); + }.execute(key, OpName.ZRANGEBYSCOREWITHSCORES); - } + } - @Override - public Response> zrangeByScoreWithScores(final String key, final double min, final double max, - final int offset, final int count) { - return new PipelineOperation>() { + @Override + public Response> zrangeByScoreWithScores(final String key, final double min, final double max, + final int offset, final int count) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrangeByScoreWithScores(key, min, max, offset, count); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrangeByScoreWithScores(key, min, max, offset, count); + } - }.execute(key, OpName.ZRANGEBYSCOREWITHSCORES); + }.execute(key, OpName.ZRANGEBYSCOREWITHSCORES); - } + } - @Override - public Response> zrevrangeByScore(final String key, final double max, final double min) { - return new PipelineOperation>() { + @Override + public Response> zrevrangeByScore(final String key, final double max, final double min) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrevrangeByScore(key, max, min); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrevrangeByScore(key, max, min); + } - }.execute(key, OpName.ZREVRANGEBYSCORE); + }.execute(key, OpName.ZREVRANGEBYSCORE); - } + } - @Override - public Response> zrevrangeByScore(final String key, final String max, final String min) { - return new PipelineOperation>() { + @Override + public Response> zrevrangeByScore(final String key, final String max, final String min) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrevrangeByScore(key, max, min); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrevrangeByScore(key, max, min); + } - }.execute(key, OpName.ZREVRANGEBYSCORE); + }.execute(key, OpName.ZREVRANGEBYSCORE); - } + } - @Override - public Response> zrevrangeByScore(final String key, final double max, final double min, - final int offset, final int count) { - return new PipelineOperation>() { + @Override + public Response> zrevrangeByScore(final String key, final double max, final double min, + final int offset, final int count) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrevrangeByScore(key, max, min, offset, count); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrevrangeByScore(key, max, min, offset, count); + } - }.execute(key, OpName.ZREVRANGEBYSCORE); + }.execute(key, OpName.ZREVRANGEBYSCORE); - } + } - @Override - public Response> zrevrangeByScore(String key, String max, String min, int offset, int count) { - return new PipelineOperation>() { + @Override + public Response> zrevrangeByScore(String key, String max, String min, int offset, int count) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrevrangeByScore(key, max, min, offset, count); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrevrangeByScore(key, max, min, offset, count); + } - }.execute(key, OpName.ZREVRANGEBYSCORE); - } + }.execute(key, OpName.ZREVRANGEBYSCORE); + } - @Override - public Response> zrevrangeByScoreWithScores(final String key, final double max, final double min) { - return new PipelineOperation>() { + @Override + public Response> zrevrangeByScoreWithScores(final String key, final double max, final double min) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrevrangeByScoreWithScores(key, max, min); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrevrangeByScoreWithScores(key, max, min); + } - }.execute(key, OpName.ZREVRANGEBYSCOREWITHSCORES); + }.execute(key, OpName.ZREVRANGEBYSCOREWITHSCORES); - } + } - @Override - public Response> zrevrangeByScoreWithScores(String key, String max, String min) { - return new PipelineOperation>() { + @Override + public Response> zrevrangeByScoreWithScores(String key, String max, String min) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrevrangeByScoreWithScores(key, max, min); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrevrangeByScoreWithScores(key, max, min); + } - }.execute(key, OpName.ZREVRANGEBYSCOREWITHSCORES); - } + }.execute(key, OpName.ZREVRANGEBYSCOREWITHSCORES); + } - @Override - public Response> zrevrangeByScoreWithScores(final String key, final double max, final double min, - final int offset, final int count) { - return new PipelineOperation>() { + @Override + public Response> zrevrangeByScoreWithScores(final String key, final double max, final double min, + final int offset, final int count) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrevrangeByScoreWithScores(key, max, min, offset, count); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrevrangeByScoreWithScores(key, max, min, offset, count); + } - }.execute(key, OpName.ZREVRANGEBYSCOREWITHSCORES); + }.execute(key, OpName.ZREVRANGEBYSCOREWITHSCORES); - } + } - @Override - public Response> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count) { - return new PipelineOperation>() { + @Override + public Response> zrevrangeByScoreWithScores(String key, String max, String min, int offset, int count) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrevrangeByScoreWithScores(key, max, min, offset, count); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrevrangeByScoreWithScores(key, max, min, offset, count); + } - }.execute(key, OpName.ZREVRANGEBYSCOREWITHSCORES); - } + }.execute(key, OpName.ZREVRANGEBYSCOREWITHSCORES); + } - @Override - public Response> zrangeWithScores(final String key, final long start, final long end) { - return new PipelineOperation>() { + @Override + public Response> zrangeWithScores(final String key, final long start, final long end) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrangeWithScores(key, start, end); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrangeWithScores(key, start, end); + } - }.execute(key, OpName.ZRANGEWITHSCORES); + }.execute(key, OpName.ZRANGEWITHSCORES); - } + } - @Override - public Response zrank(final String key, final String member) { - return new PipelineOperation() { + @Override + public Response zrank(final String key, final String member) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrank(key, member); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrank(key, member); + } - }.execute(key, OpName.ZRANK); + }.execute(key, OpName.ZRANK); - } + } - @Override - public Response zrem(final String key, final String... member) { - return new PipelineOperation() { + @Override + public Response zrem(final String key, final String... member) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrem(key, member); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrem(key, member); + } - }.execute(key, OpName.ZREM); + }.execute(key, OpName.ZREM); - } + } - @Override - public Response zremrangeByRank(final String key, final long start, final long end) { - return new PipelineOperation() { + @Override + public Response zremrangeByRank(final String key, final long start, final long end) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zremrangeByRank(key, start, end); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zremrangeByRank(key, start, end); + } - }.execute(key, OpName.ZREMRANGEBYRANK); + }.execute(key, OpName.ZREMRANGEBYRANK); - } + } - @Override - public Response zremrangeByScore(final String key, final double start, final double end) { - return new PipelineOperation() { + @Override + public Response zremrangeByScore(final String key, final double start, final double end) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zremrangeByScore(key, start, end); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zremrangeByScore(key, start, end); + } - }.execute(key, OpName.ZREMRANGEBYSCORE); + }.execute(key, OpName.ZREMRANGEBYSCORE); - } + } - @Override - public Response zremrangeByScore(String key, String min, String max) { - return new PipelineOperation() { + @Override + public Response zremrangeByScore(String key, String min, String max) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zremrangeByScore(key, min, max); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zremrangeByScore(key, min, max); + } - }.execute(key, OpName.ZREMRANGEBYSCORE); - } + }.execute(key, OpName.ZREMRANGEBYSCORE); + } - @Override - public Response> zrevrange(final String key, final long start, final long end) { - return new PipelineOperation>() { + @Override + public Response> zrevrange(final String key, final long start, final long end) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrevrange(key, start, end); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrevrange(key, start, end); + } - }.execute(key, OpName.ZREVRANGE); + }.execute(key, OpName.ZREVRANGE); - } + } - @Override - public Response> zrevrangeWithScores(final String key, final long start, final long end) { - return new PipelineOperation>() { + @Override + public Response> zrevrangeWithScores(final String key, final long start, final long end) { + return new PipelineOperation>() { - @Override - Response> execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrevrangeWithScores(key, start, end); - } + @Override + Response> execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrevrangeWithScores(key, start, end); + } - }.execute(key, OpName.ZREVRANGEWITHSCORES); + }.execute(key, OpName.ZREVRANGEWITHSCORES); - } + } - @Override - public Response zrevrank(final String key, final String member) { - return new PipelineOperation() { + @Override + public Response zrevrank(final String key, final String member) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zrevrank(key, member); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zrevrank(key, member); + } - }.execute(key, OpName.ZREVRANK); + }.execute(key, OpName.ZREVRANK); - } + } - @Override - public Response zscore(final String key, final String member) { - return new PipelineOperation() { + @Override + public Response zscore(final String key, final String member) { + return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zscore(key, member); - } + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zscore(key, member); + } - }.execute(key, OpName.ZSCORE); + }.execute(key, OpName.ZSCORE); - } + } - /** - * This method is not supported by the BinaryRedisPipeline interface. - */ - public Response> zscan(final String key, final int cursor) { - throw new UnsupportedOperationException("'ZSCAN' cannot be called in pipeline"); - } + /** + * This method is not supported by the BinaryRedisPipeline interface. + */ + public Response> zscan(final String key, final int cursor) { + throw new UnsupportedOperationException("'ZSCAN' cannot be called in pipeline"); + } - @Override - public Response zlexcount(String key, String min, String max) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeByLex(String key, String min, String max) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeByLex(String key, String min, String max, int offset, int count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zremrangeByLex(String key, String start, String end) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response bitcount(final String key) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.bitcount(key); - } - - }.execute(key, OpName.BITCOUNT); - - } - - @Override - public Response bitcount(final String key, final long start, final long end) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.bitcount(key, start, end); - } - - }.execute(key, OpName.BITCOUNT); - - } - - /**** Binary Operations ****/ - @Override - public Response set(final byte[] key, final byte[] value) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return jedisPipeline.set(key, value); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.SET.name(), duration, TimeUnit.MICROSECONDS); - } - } - - }.execute(key, OpName.SET); - } - - @Override - public Response pfadd(String key, String... elements) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response pfcount(String key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> bitfield(String key, String... arguments) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response hstrlen(String key, String field) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.hstrlen(key, field); - } - }.execute(key, OpName.HSTRLEN); - } - - @Override - public Response dump(String key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response restore(String key, int ttl, byte[] serializedValue) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response restoreReplace(String key, int ttl, byte[] serializedValue) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response migrate(String host, int port, String key, int destinationDB, int timeout) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeByLex(String key, String max, String min) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeByLex(String key, String max, String min, int offset, int count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response geoadd(String arg0, Map arg1) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response geoadd(String arg0, double arg1, double arg2, String arg3) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response geodist(String arg0, String arg1, String arg2) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response geodist(String arg0, String arg1, String arg2, GeoUnit arg3) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> geohash(String arg0, String... arg1) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> geopos(String arg0, String... arg1) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadius(String arg0, double arg1, double arg2, double arg3, - GeoUnit arg4) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadiusReadonly(String key, double longitude, double latitude, double radius, GeoUnit unit) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadius(String arg0, double arg1, double arg2, double arg3, GeoUnit arg4, - GeoRadiusParam arg5) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadiusReadonly(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadiusByMember(String arg0, String arg1, double arg2, GeoUnit arg3) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadiusByMember(String arg0, String arg1, double arg2, GeoUnit arg3, - GeoRadiusParam arg4) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zadd(String key, Map members, ZAddParams params) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zadd(key, members, params); - } - - }.execute(key, OpName.ZADD); - } - - public Response zadd(final String key, final double score, final String member, final ZAddParams params) { - - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.zadd(key, score, member, params); - } - - }.execute(key, OpName.ZADD); - - - } - - - @Override - public Response zincrby(String arg0, double arg1, String arg2, ZIncrByParams arg3) { - throw new UnsupportedOperationException("not yet implemented"); - } - - public void sync() { - long startTime = System.nanoTime() / 1000; - try { - jedisPipeline.sync(); - opMonitor.recordPipelineSync(); - } catch (JedisConnectionException jce) { - String msg = "Failed sync() to host: " + getHostInfo(); - pipelineEx.set(new FatalConnectionException(msg, jce). - setHost(connection == null ? Host.NO_HOST : connection.getHost())); - cpMonitor.incOperationFailure(connection == null ? null : connection.getHost(), jce); - throw jce; - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordLatency(duration, TimeUnit.MICROSECONDS); - discardPipeline(false); - releaseConnection(); - } - } - - public List syncAndReturnAll() { - long startTime = System.nanoTime() / 1000; - try { - List result = jedisPipeline.syncAndReturnAll(); - opMonitor.recordPipelineSync(); - return result; - } catch (JedisConnectionException jce) { - String msg = "Failed syncAndReturnAll() to host: " + getHostInfo(); - pipelineEx.set(new FatalConnectionException(msg, jce). - setHost(connection == null ? Host.NO_HOST : connection.getHost())); - cpMonitor.incOperationFailure(connection == null ? null : connection.getHost(), jce); - throw jce; - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordLatency(duration, TimeUnit.MICROSECONDS); - discardPipeline(false); - releaseConnection(); - } - } - - private void discardPipeline(boolean recordLatency) { - try { - if (jedisPipeline != null) { - long startTime = System.nanoTime() / 1000; - jedisPipeline.sync(); - if (recordLatency) { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordLatency(duration, TimeUnit.MICROSECONDS); - } - jedisPipeline = null; - } - } catch (Exception e) { - Logger.warn(String.format("Failed to discard jedis pipeline, %s", getHostInfo()), e); - } - } - - private void releaseConnection() { - if (connection != null) { - try { - connection.getContext().reset(); - connection.getParentConnectionPool().returnConnection(connection); - if (pipelineEx.get() != null) { - connPool.getHealthTracker().trackConnectionError(connection.getParentConnectionPool(), - pipelineEx.get()); - pipelineEx.set(null); - } - connection = null; - } catch (Exception e) { - Logger.warn(String.format("Failed to return connection in Dyno Jedis Pipeline, %s", getHostInfo()), e); - } - } - } - - public void discardPipelineAndReleaseConnection() { - opMonitor.recordPipelineDiscard(); - discardPipeline(true); - releaseConnection(); - } - - @Override - public void close() throws Exception { - discardPipelineAndReleaseConnection(); - } - - private String getHostInfo() { - if (connection != null && connection.getHost() != null) { - return connection.getHost().toString(); - } - - return "unknown"; - } - - @Override - public Response append(byte[] key, byte[] value) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> blpop(byte[] arg) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> brpop(byte[] arg) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response decr(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response decrBy(final byte[] key, final long integer) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.decrBy(key, integer); - } - }.execute(key, OpName.DECRBY); } - - @Override - public Response del(final byte[] key) { - return new PipelineOperation() { - - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.del(key); - } - }.execute(key, OpName.DEL); - } - - @Override - public Response unlink(byte[] keys) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.unlink(keys); - } - }.execute(keys, OpName.UNLINK); - } - - @Override - public Response echo(byte[] string) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response exists(final byte[] key) { - return new PipelineOperation() { - - @Override - Response execute(final Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.exists(key); - } - }.execute(key, OpName.EXISTS); - } - - @Override - public Response expire(byte[] key, int seconds) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response pexpire(byte[] key, long milliseconds) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response expireAt(byte[] key, long unixTime) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response pexpireAt(byte[] key, long millisecondsTimestamp) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response get(final byte[] key) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - long startTime = System.nanoTime() / 1000; - try { - return jedisPipeline.get(key); - } finally { - long duration = System.nanoTime() / 1000 - startTime; - opMonitor.recordSendLatency(OpName.GET.name(), duration, TimeUnit.MICROSECONDS); - } - } - }.execute(key, OpName.GET); - } - - @Override - public Response getbit(byte[] key, long offset) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response getSet(final byte[] key, final byte[] value) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.getSet(key, value); - } - }.execute(key, OpName.GETSET); } - - @Override - public Response getrange(byte[] key, long startOffset, long endOffset) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response hdel(byte[] key, byte[]... field) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response hexists(byte[] key, byte[] field) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response hincrBy(byte[] key, byte[] field, long value) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> hkeys(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response hlen(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response hsetnx(byte[] key, byte[] field, byte[] value) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> hvals(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response incr(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response incrBy(byte[] key, long integer) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response lindex(byte[] key, long index) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response linsert(byte[] key, ListPosition where, byte[] pivot, byte[] value) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response llen(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response lpop(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response lpush(byte[] key, byte[]... string) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response lpushx(byte[] key, byte[]... bytes) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> lrange(byte[] key, long start, long end) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response lrem(byte[] key, long count, byte[] value) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response lset(byte[] key, long index, byte[] value) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response ltrim(byte[] key, long start, long end) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response move(byte[] key, int dbIndex) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response persist(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response rpop(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response rpush(byte[] key, byte[]... string) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response rpushx(byte[] key, byte[]... string) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response sadd(byte[] key, byte[]... member) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response scard(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response setbit(byte[] key, long offset, byte[] value) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response setrange(byte[] key, long offset, byte[] value) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response setex(final byte[] key, final int seconds, final byte[] value) { - return new PipelineOperation() { - @Override - Response execute(Pipeline jedisPipeline) throws DynoException { - return jedisPipeline.setex(key, seconds, value); - } - }.execute(key, OpName.SETEX); } - - @Override - public Response setnx(byte[] key, byte[] value) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> smembers(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response sismember(byte[] key, byte[] member) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> sort(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> sort(byte[] key, SortingParams sortingParameters) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response spop(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> spop(byte[] key, long count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response srandmember(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response srem(byte[] key, byte[]... member) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response strlen(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response substr(byte[] key, int start, int end) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response touch(byte[] keys) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response ttl(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response pttl(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response type(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zadd(byte[] key, double score, byte[] member) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zadd(byte[] key, double score, byte[] member, ZAddParams params) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zadd(byte[] key, Map scoreMembers) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zadd(byte[] key, Map scoreMembers, ZAddParams params) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zcard(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zcount(byte[] key, double min, double max) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zcount(byte[] key, byte[] min, byte[] max) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zincrby(byte[] key, double score, byte[] member) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zincrby(byte[] key, double score, byte[] member, ZIncrByParams params) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrange(byte[] key, long start, long end) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeByScore(byte[] key, double min, double max) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeByScore(byte[] key, byte[] min, byte[] max) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeByScore(byte[] key, double min, double max, int offset, int count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, int count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, double min, double max) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset, int count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeByScore(byte[] key, double max, double min) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeByScore(byte[] key, double max, double min, int offset, int count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset, int count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset, int count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset, int count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeWithScores(byte[] key, long start, long end) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zrank(byte[] key, byte[] member) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zrem(byte[] key, byte[]... member) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zremrangeByRank(byte[] key, long start, long end) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zremrangeByScore(byte[] key, double start, double end) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zremrangeByScore(byte[] key, byte[] start, byte[] end) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrange(byte[] key, long start, long end) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeWithScores(byte[] key, long start, long end) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zrevrank(byte[] key, byte[] member) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zscore(byte[] key, byte[] member) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zlexcount(byte[] key, byte[] min, byte[] max) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeByLex(byte[] key, byte[] min, byte[] max) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrangeByLex(byte[] key, byte[] min, byte[] max, int offset, int count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeByLex(byte[] key, byte[] max, byte[] min) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> zrevrangeByLex(byte[] key, byte[] max, byte[] min, int offset, int count) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response zremrangeByLex(byte[] key, byte[] min, byte[] max) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response bitcount(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response bitcount(byte[] key, long start, long end) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response pfadd(byte[] key, byte[]... elements) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response pfcount(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response dump(byte[] key) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response restore(byte[] key, int ttl, byte[] serializedValue) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response restoreReplace(byte[] key, int ttl, byte[] serializedValue) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response migrate(String host, int port, byte[] key, int destinationDB, int timeout) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response geoadd(byte[] key, double longitude, double latitude, byte[] member) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response geoadd(byte[] key, Map memberCoordinateMap) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response geodist(byte[] key, byte[] member1, byte[] member2) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> geohash(byte[] key, byte[]... members) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> geopos(byte[] key, byte[]... members) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadius(byte[] key, double longitude, double latitude, double radius, - GeoUnit unit) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadiusReadonly(byte[] key, double longitude, double latitude, double radius, GeoUnit unit) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadius(byte[] key, double longitude, double latitude, double radius, - GeoUnit unit, GeoRadiusParam param) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadiusReadonly(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadiusByMemberReadonly(byte[] key, byte[] member, double radius, GeoUnit unit) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit, - GeoRadiusParam param) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> georadiusByMemberReadonly(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response> bitfield(byte[] key, byte[]... elements) { - throw new UnsupportedOperationException("not yet implemented"); - } - - @Override - public Response hstrlen(byte[] key, byte[] field) { - throw new UnsupportedOperationException("not yet implemented"); - } + @Override + public Response zlexcount(String key, String min, String max) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeByLex(String key, String min, String max) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeByLex(String key, String min, String max, int offset, int count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zremrangeByLex(String key, String start, String end) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response bitcount(final String key) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.bitcount(key); + } + + }.execute(key, OpName.BITCOUNT); + + } + + @Override + public Response bitcount(final String key, final long start, final long end) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.bitcount(key, start, end); + } + + }.execute(key, OpName.BITCOUNT); + + } + + /**** Binary Operations ****/ + @Override + public Response set(final byte[] key, final byte[] value) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return jedisPipeline.set(key, value); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.SET.name(), duration, TimeUnit.MICROSECONDS); + } + } + + }.execute(key, OpName.SET); + } + + @Override + public Response pfadd(String key, String... elements) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response pfcount(String key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> bitfield(String key, String... arguments) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response hstrlen(String key, String field) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.hstrlen(key, field); + } + }.execute(key, OpName.HSTRLEN); + } + + @Override + public Response dump(String key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response restore(String key, int ttl, byte[] serializedValue) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response restoreReplace(String key, int ttl, byte[] serializedValue) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response migrate(String host, int port, String key, int destinationDB, int timeout) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeByLex(String key, String max, String min) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeByLex(String key, String max, String min, int offset, int count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response geoadd(String arg0, Map arg1) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response geoadd(String arg0, double arg1, double arg2, String arg3) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response geodist(String arg0, String arg1, String arg2) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response geodist(String arg0, String arg1, String arg2, GeoUnit arg3) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> geohash(String arg0, String... arg1) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> geopos(String arg0, String... arg1) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadius(String arg0, double arg1, double arg2, double arg3, + GeoUnit arg4) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadiusReadonly(String key, double longitude, double latitude, double radius, GeoUnit unit) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadius(String arg0, double arg1, double arg2, double arg3, GeoUnit arg4, + GeoRadiusParam arg5) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadiusReadonly(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadiusByMember(String arg0, String arg1, double arg2, GeoUnit arg3) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadiusByMember(String arg0, String arg1, double arg2, GeoUnit arg3, + GeoRadiusParam arg4) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadiusByMemberReadonly(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zadd(String key, Map members, ZAddParams params) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zadd(key, members, params); + } + + }.execute(key, OpName.ZADD); + } + + public Response zadd(final String key, final double score, final String member, final ZAddParams params) { + + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.zadd(key, score, member, params); + } + + }.execute(key, OpName.ZADD); + + + } + + + @Override + public Response zincrby(String arg0, double arg1, String arg2, ZIncrByParams arg3) { + throw new UnsupportedOperationException("not yet implemented"); + } + + public void sync() { + long startTime = System.nanoTime() / 1000; + try { + jedisPipeline.sync(); + opMonitor.recordPipelineSync(); + } catch (JedisConnectionException jce) { + String msg = "Failed sync() to host: " + getHostInfo(); + pipelineEx.set(new FatalConnectionException(msg, jce). + setHost(connection == null ? Host.NO_HOST : connection.getHost())); + cpMonitor.incOperationFailure(connection == null ? null : connection.getHost(), jce); + throw jce; + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordLatency(duration, TimeUnit.MICROSECONDS); + discardPipeline(false); + releaseConnection(); + } + } + + public List syncAndReturnAll() { + long startTime = System.nanoTime() / 1000; + try { + List result = jedisPipeline.syncAndReturnAll(); + opMonitor.recordPipelineSync(); + return result; + } catch (JedisConnectionException jce) { + String msg = "Failed syncAndReturnAll() to host: " + getHostInfo(); + pipelineEx.set(new FatalConnectionException(msg, jce). + setHost(connection == null ? Host.NO_HOST : connection.getHost())); + cpMonitor.incOperationFailure(connection == null ? null : connection.getHost(), jce); + throw jce; + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordLatency(duration, TimeUnit.MICROSECONDS); + discardPipeline(false); + releaseConnection(); + } + } + + private void discardPipeline(boolean recordLatency) { + try { + if (jedisPipeline != null) { + long startTime = System.nanoTime() / 1000; + jedisPipeline.sync(); + if (recordLatency) { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordLatency(duration, TimeUnit.MICROSECONDS); + } + jedisPipeline = null; + } + } catch (Exception e) { + Logger.warn(String.format("Failed to discard jedis pipeline, %s", getHostInfo()), e); + } + } + + private void releaseConnection() { + if (connection != null) { + try { + connection.getContext().reset(); + connection.getParentConnectionPool().returnConnection(connection); + if (pipelineEx.get() != null) { + connPool.getHealthTracker().trackConnectionError(connection.getParentConnectionPool(), + pipelineEx.get()); + pipelineEx.set(null); + } + connection = null; + } catch (Exception e) { + Logger.warn(String.format("Failed to return connection in Dyno Jedis Pipeline, %s", getHostInfo()), e); + } + } + } + + public void discardPipelineAndReleaseConnection() { + opMonitor.recordPipelineDiscard(); + discardPipeline(true); + releaseConnection(); + } + + @Override + public void close() throws Exception { + discardPipelineAndReleaseConnection(); + } + + private String getHostInfo() { + if (connection != null && connection.getHost() != null) { + return connection.getHost().toString(); + } + + return "unknown"; + } + + @Override + public Response append(byte[] key, byte[] value) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> blpop(byte[] arg) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> brpop(byte[] arg) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response decr(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response decrBy(final byte[] key, final long integer) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.decrBy(key, integer); + } + }.execute(key, OpName.DECRBY); + } + + @Override + public Response del(final byte[] key) { + return new PipelineOperation() { + + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.del(key); + } + }.execute(key, OpName.DEL); + } + + @Override + public Response unlink(byte[] keys) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.unlink(keys); + } + }.execute(keys, OpName.UNLINK); + } + + @Override + public Response echo(byte[] string) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response exists(final byte[] key) { + return new PipelineOperation() { + + @Override + Response execute(final Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.exists(key); + } + }.execute(key, OpName.EXISTS); + } + + @Override + public Response expire(byte[] key, int seconds) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response pexpire(byte[] key, long milliseconds) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response expireAt(byte[] key, long unixTime) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response pexpireAt(byte[] key, long millisecondsTimestamp) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response get(final byte[] key) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + long startTime = System.nanoTime() / 1000; + try { + return jedisPipeline.get(key); + } finally { + long duration = System.nanoTime() / 1000 - startTime; + opMonitor.recordSendLatency(OpName.GET.name(), duration, TimeUnit.MICROSECONDS); + } + } + }.execute(key, OpName.GET); + } + + @Override + public Response getbit(byte[] key, long offset) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response getSet(final byte[] key, final byte[] value) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.getSet(key, value); + } + }.execute(key, OpName.GETSET); + } + + @Override + public Response getrange(byte[] key, long startOffset, long endOffset) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response hdel(byte[] key, byte[]... field) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response hexists(byte[] key, byte[] field) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response hincrBy(byte[] key, byte[] field, long value) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> hkeys(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response hlen(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response hsetnx(byte[] key, byte[] field, byte[] value) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> hvals(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response incr(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response incrBy(byte[] key, long integer) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response lindex(byte[] key, long index) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response linsert(byte[] key, ListPosition where, byte[] pivot, byte[] value) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response llen(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response lpop(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response lpush(byte[] key, byte[]... string) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response lpushx(byte[] key, byte[]... bytes) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> lrange(byte[] key, long start, long end) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response lrem(byte[] key, long count, byte[] value) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response lset(byte[] key, long index, byte[] value) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response ltrim(byte[] key, long start, long end) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response move(byte[] key, int dbIndex) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response persist(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response rpop(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response rpush(byte[] key, byte[]... string) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response rpushx(byte[] key, byte[]... string) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response sadd(byte[] key, byte[]... member) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response scard(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response setbit(byte[] key, long offset, byte[] value) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response setrange(byte[] key, long offset, byte[] value) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response setex(final byte[] key, final int seconds, final byte[] value) { + return new PipelineOperation() { + @Override + Response execute(Pipeline jedisPipeline) throws DynoException { + return jedisPipeline.setex(key, seconds, value); + } + }.execute(key, OpName.SETEX); + } + + @Override + public Response setnx(byte[] key, byte[] value) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> smembers(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response sismember(byte[] key, byte[] member) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> sort(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> sort(byte[] key, SortingParams sortingParameters) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response spop(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> spop(byte[] key, long count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response srandmember(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response srem(byte[] key, byte[]... member) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response strlen(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response substr(byte[] key, int start, int end) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response touch(byte[] keys) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response ttl(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response pttl(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response type(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zadd(byte[] key, double score, byte[] member) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zadd(byte[] key, double score, byte[] member, ZAddParams params) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zadd(byte[] key, Map scoreMembers) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zadd(byte[] key, Map scoreMembers, ZAddParams params) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zcard(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zcount(byte[] key, double min, double max) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zcount(byte[] key, byte[] min, byte[] max) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zincrby(byte[] key, double score, byte[] member) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zincrby(byte[] key, double score, byte[] member, ZIncrByParams params) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrange(byte[] key, long start, long end) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeByScore(byte[] key, double min, double max) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeByScore(byte[] key, byte[] min, byte[] max) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeByScore(byte[] key, double min, double max, int offset, int count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, int count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeByScoreWithScores(byte[] key, double min, double max) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, int offset, int count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeByScore(byte[] key, double max, double min) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeByScore(byte[] key, double max, double min, int offset, int count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeByScore(byte[] key, byte[] max, byte[] min, int offset, int count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset, int count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, int offset, int count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeWithScores(byte[] key, long start, long end) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zrank(byte[] key, byte[] member) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zrem(byte[] key, byte[]... member) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zremrangeByRank(byte[] key, long start, long end) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zremrangeByScore(byte[] key, double start, double end) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zremrangeByScore(byte[] key, byte[] start, byte[] end) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrange(byte[] key, long start, long end) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeWithScores(byte[] key, long start, long end) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zrevrank(byte[] key, byte[] member) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zscore(byte[] key, byte[] member) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zlexcount(byte[] key, byte[] min, byte[] max) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeByLex(byte[] key, byte[] min, byte[] max) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrangeByLex(byte[] key, byte[] min, byte[] max, int offset, int count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeByLex(byte[] key, byte[] max, byte[] min) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> zrevrangeByLex(byte[] key, byte[] max, byte[] min, int offset, int count) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response zremrangeByLex(byte[] key, byte[] min, byte[] max) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response bitcount(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response bitcount(byte[] key, long start, long end) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response pfadd(byte[] key, byte[]... elements) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response pfcount(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response dump(byte[] key) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response restore(byte[] key, int ttl, byte[] serializedValue) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response restoreReplace(byte[] key, int ttl, byte[] serializedValue) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response migrate(String host, int port, byte[] key, int destinationDB, int timeout) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response geoadd(byte[] key, double longitude, double latitude, byte[] member) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response geoadd(byte[] key, Map memberCoordinateMap) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response geodist(byte[] key, byte[] member1, byte[] member2) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response geodist(byte[] key, byte[] member1, byte[] member2, GeoUnit unit) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> geohash(byte[] key, byte[]... members) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> geopos(byte[] key, byte[]... members) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadius(byte[] key, double longitude, double latitude, double radius, + GeoUnit unit) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadiusReadonly(byte[] key, double longitude, double latitude, double radius, GeoUnit unit) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadius(byte[] key, double longitude, double latitude, double radius, + GeoUnit unit, GeoRadiusParam param) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadiusReadonly(byte[] key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadiusByMemberReadonly(byte[] key, byte[] member, double radius, GeoUnit unit) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadiusByMember(byte[] key, byte[] member, double radius, GeoUnit unit, + GeoRadiusParam param) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> georadiusByMemberReadonly(byte[] key, byte[] member, double radius, GeoUnit unit, GeoRadiusParam param) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response> bitfield(byte[] key, byte[]... elements) { + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public Response hstrlen(byte[] key, byte[] field) { + throw new UnsupportedOperationException("not yet implemented"); + } } diff --git a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisPipelineMonitor.java b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisPipelineMonitor.java index 1bff5da1..75d59615 100644 --- a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisPipelineMonitor.java +++ b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/DynoJedisPipelineMonitor.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -29,77 +29,77 @@ public class DynoJedisPipelineMonitor { - private static final org.slf4j.Logger Logger = LoggerFactory.getLogger(DynoJedisPipelineMonitor.class); + private static final org.slf4j.Logger Logger = LoggerFactory.getLogger(DynoJedisPipelineMonitor.class); - private final ConcurrentHashMap counterMap = new ConcurrentHashMap(); - private final String appName; - private final BasicCounter pipelineSync; - private final BasicCounter pipelineDiscard; - private final PipelineTimer timer; + private final ConcurrentHashMap counterMap = new ConcurrentHashMap(); + private final String appName; + private final BasicCounter pipelineSync; + private final BasicCounter pipelineDiscard; + private final PipelineTimer timer; private final PipelineSendTimer sendTimer; - private final int resetTimingsFrequencyInSeconds; - - private final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(1, new ThreadFactory() { - @Override - public Thread newThread(Runnable r) { - return new Thread(r, "DynoJedisPipelineMonitor"); - } - }); - - public DynoJedisPipelineMonitor(String applicationName, int resetTimingsFrequencyInSeconds) { - appName = applicationName; - pipelineSync = getNewPipelineCounter("SYNC"); - pipelineDiscard = getNewPipelineCounter("DISCARD"); - timer = new PipelineTimer(appName); + private final int resetTimingsFrequencyInSeconds; + + private final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(1, new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "DynoJedisPipelineMonitor"); + } + }); + + public DynoJedisPipelineMonitor(String applicationName, int resetTimingsFrequencyInSeconds) { + appName = applicationName; + pipelineSync = getNewPipelineCounter("SYNC"); + pipelineDiscard = getNewPipelineCounter("DISCARD"); + timer = new PipelineTimer(appName); sendTimer = new PipelineSendTimer(appName); - this.resetTimingsFrequencyInSeconds = resetTimingsFrequencyInSeconds; - } - - public DynoJedisPipelineMonitor(String applicationName) { - this(applicationName, 0); - } - - public void init() { - // register the counters - DefaultMonitorRegistry.getInstance().register(pipelineSync); - DefaultMonitorRegistry.getInstance().register(pipelineDiscard); - // register the pipeline timer - DefaultMonitorRegistry.getInstance().register(timer.latMean); - DefaultMonitorRegistry.getInstance().register(timer.lat99); - DefaultMonitorRegistry.getInstance().register(timer.lat995); - DefaultMonitorRegistry.getInstance().register(timer.lat999); + this.resetTimingsFrequencyInSeconds = resetTimingsFrequencyInSeconds; + } + + public DynoJedisPipelineMonitor(String applicationName) { + this(applicationName, 0); + } + + public void init() { + // register the counters + DefaultMonitorRegistry.getInstance().register(pipelineSync); + DefaultMonitorRegistry.getInstance().register(pipelineDiscard); + // register the pipeline timer + DefaultMonitorRegistry.getInstance().register(timer.latMean); + DefaultMonitorRegistry.getInstance().register(timer.lat99); + DefaultMonitorRegistry.getInstance().register(timer.lat995); + DefaultMonitorRegistry.getInstance().register(timer.lat999); // NOTE -- pipeline 'send' timers are created on demand and are registered // in PipelineSendTimer.getOrCreateHistogram() - Logger.debug(String.format("Initializing DynoJedisPipelineMonitor with timing counter reset frequency %d", + Logger.debug(String.format("Initializing DynoJedisPipelineMonitor with timing counter reset frequency %d", resetTimingsFrequencyInSeconds)); - if (resetTimingsFrequencyInSeconds > 0) { - threadPool.scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - timer.reset(); + if (resetTimingsFrequencyInSeconds > 0) { + threadPool.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + timer.reset(); sendTimer.reset(); - } - }, 1, resetTimingsFrequencyInSeconds, TimeUnit.SECONDS); - } - } - - public void recordOperation(String opName) { - getOrCreateCounter(opName).increment(); - } - - public void recordPipelineSync() { - pipelineSync.increment(); - } - - public void recordPipelineDiscard() { - pipelineDiscard.increment(); - } - - public void recordLatency(long duration, TimeUnit unit) { - timer.recordLatency(duration, unit); - } + } + }, 1, resetTimingsFrequencyInSeconds, TimeUnit.SECONDS); + } + } + + public void recordOperation(String opName) { + getOrCreateCounter(opName).increment(); + } + + public void recordPipelineSync() { + pipelineSync.increment(); + } + + public void recordPipelineDiscard() { + pipelineDiscard.increment(); + } + + public void recordLatency(long duration, TimeUnit unit) { + timer.recordLatency(duration, unit); + } public void recordSendLatency(String opName, long duration, TimeUnit unit) { sendTimer.recordLatency(opName, duration, unit); @@ -108,69 +108,69 @@ public void recordSendLatency(String opName, long duration, TimeUnit unit) { public void stop() { threadPool.shutdownNow(); } - - private BasicCounter getOrCreateCounter(String opName) { - - BasicCounter counter = counterMap.get(opName); - if (counter != null) { - return counter; - } - counter = getNewPipelineCounter(opName); - BasicCounter prevCounter = counterMap.putIfAbsent(opName, counter); - if (prevCounter != null) { - return prevCounter; - } - DefaultMonitorRegistry.getInstance().register(counter); - return counter; - } - - private BasicCounter getNewPipelineCounter(String opName) { - - String metricName = "Dyno__" + appName + "__PL__" + opName; - MonitorConfig config = MonitorConfig.builder(metricName) - .withTag(new BasicTag("dyno_pl_op", opName)) - .build(); - return new BasicCounter(config); - } + + private BasicCounter getOrCreateCounter(String opName) { + + BasicCounter counter = counterMap.get(opName); + if (counter != null) { + return counter; + } + counter = getNewPipelineCounter(opName); + BasicCounter prevCounter = counterMap.putIfAbsent(opName, counter); + if (prevCounter != null) { + return prevCounter; + } + DefaultMonitorRegistry.getInstance().register(counter); + return counter; + } + + private BasicCounter getNewPipelineCounter(String opName) { + + String metricName = "Dyno__" + appName + "__PL__" + opName; + MonitorConfig config = MonitorConfig.builder(metricName) + .withTag(new BasicTag("dyno_pl_op", opName)) + .build(); + return new BasicCounter(config); + } /** * This class measures the latency of a sync() or syncAndReturnAll() operation, which is the time * it takes the client to receive the response of all operations in the pipeline. */ - private class PipelineTimer { - - private final EstimatedHistogramMean latMean; - private final EstimatedHistogramPercentile lat99; - private final EstimatedHistogramPercentile lat995; - private final EstimatedHistogramPercentile lat999; - - private final EstimatedHistogram estHistogram; - - private PipelineTimer(String appName) { - - estHistogram = new EstimatedHistogram(); - latMean = new EstimatedHistogramMean("Dyno__" + appName + "__PL__latMean", "PL", "dyno_pl_op", estHistogram); - lat99 = new EstimatedHistogramPercentile("Dyno__" + appName + "__PL__lat990", "PL", "dyno_pl_op", estHistogram, 0.99); - lat995 = new EstimatedHistogramPercentile("Dyno__" + appName + "__PL__lat995", "PL", "dyno_pl_op", estHistogram, 0.995); - lat999 = new EstimatedHistogramPercentile("Dyno__" + appName + "__PL__lat999", "PL", "dyno_pl_op", estHistogram, 0.999); - } - - public void recordLatency(long duration, TimeUnit unit) { - long durationMicros = TimeUnit.MICROSECONDS.convert(duration, unit); - estHistogram.add(durationMicros); - } - - public void reset() { - Logger.info("resetting histogram"); - estHistogram.getBuckets(true); - } - } + private class PipelineTimer { + + private final EstimatedHistogramMean latMean; + private final EstimatedHistogramPercentile lat99; + private final EstimatedHistogramPercentile lat995; + private final EstimatedHistogramPercentile lat999; + + private final EstimatedHistogram estHistogram; + + private PipelineTimer(String appName) { + + estHistogram = new EstimatedHistogram(); + latMean = new EstimatedHistogramMean("Dyno__" + appName + "__PL__latMean", "PL", "dyno_pl_op", estHistogram); + lat99 = new EstimatedHistogramPercentile("Dyno__" + appName + "__PL__lat990", "PL", "dyno_pl_op", estHistogram, 0.99); + lat995 = new EstimatedHistogramPercentile("Dyno__" + appName + "__PL__lat995", "PL", "dyno_pl_op", estHistogram, 0.995); + lat999 = new EstimatedHistogramPercentile("Dyno__" + appName + "__PL__lat999", "PL", "dyno_pl_op", estHistogram, 0.999); + } + + public void recordLatency(long duration, TimeUnit unit) { + long durationMicros = TimeUnit.MICROSECONDS.convert(duration, unit); + estHistogram.add(durationMicros); + } + + public void reset() { + Logger.info("resetting histogram"); + estHistogram.getBuckets(true); + } + } /** * This class measures the time it takes to send a request from the client to the server via the pipeline. The * 'send' is not asynchronous within the Jedis client */ - private class PipelineSendTimer { + private class PipelineSendTimer { private final Map histograms = new ConcurrentHashMap(); private final String appName; @@ -192,7 +192,7 @@ private EstimatedHistogramMean getOrCreateHistogram(String opName) { EstimatedHistogramMean histogramMean = new EstimatedHistogramMean("Dyno__" + appName + "__PL__latMean", "PL_SEND", opName, histogram); histograms.put(opName, histogramMean); - DefaultMonitorRegistry.getInstance().register(histogramMean); + DefaultMonitorRegistry.getInstance().register(histogramMean); return histogramMean; } } @@ -200,7 +200,7 @@ private EstimatedHistogramMean getOrCreateHistogram(String opName) { public void reset() { Logger.info("resetting all SEND histograms"); - for (EstimatedHistogramMean hm: histograms.values()) { + for (EstimatedHistogramMean hm : histograms.values()) { hm.reset(); } } diff --git a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/JedisConnectionFactory.java b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/JedisConnectionFactory.java index d1026e7f..e07a8f6c 100644 --- a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/JedisConnectionFactory.java +++ b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/JedisConnectionFactory.java @@ -50,141 +50,141 @@ public class JedisConnectionFactory implements ConnectionFactory { private static final org.slf4j.Logger Logger = LoggerFactory.getLogger(JedisConnectionFactory.class); - private final OperationMonitor opMonitor; + private final OperationMonitor opMonitor; private final SSLSocketFactory sslSocketFactory; - public JedisConnectionFactory(OperationMonitor monitor, SSLSocketFactory sslSocketFactory) { - this.opMonitor = monitor; + public JedisConnectionFactory(OperationMonitor monitor, SSLSocketFactory sslSocketFactory) { + this.opMonitor = monitor; this.sslSocketFactory = sslSocketFactory; - } + } - @Override - public Connection createConnection(HostConnectionPool pool, ConnectionObservor connectionObservor) - throws DynoConnectException, ThrottledException { + @Override + public Connection createConnection(HostConnectionPool pool, ConnectionObservor connectionObservor) + throws DynoConnectException, ThrottledException { - return new JedisConnection(pool); - } + return new JedisConnection(pool); + } - public class JedisConnection implements Connection { + public class JedisConnection implements Connection { - private final HostConnectionPool hostPool; - private final Jedis jedisClient; - private final ConnectionContextImpl context = new ConnectionContextImpl(); + private final HostConnectionPool hostPool; + private final Jedis jedisClient; + private final ConnectionContextImpl context = new ConnectionContextImpl(); - private DynoConnectException lastDynoException; + private DynoConnectException lastDynoException; - public JedisConnection(HostConnectionPool hostPool) { - this.hostPool = hostPool; - Host host = hostPool.getHost(); + public JedisConnection(HostConnectionPool hostPool) { + this.hostPool = hostPool; + Host host = hostPool.getHost(); - if (sslSocketFactory == null) { - JedisShardInfo shardInfo = new JedisShardInfo(host.getHostAddress(), host.getPort(), - hostPool.getConnectionTimeout(), hostPool.getSocketTimeout(), Sharded.DEFAULT_WEIGHT); - shardInfo.setPassword(host.getPassword()); + if (sslSocketFactory == null) { + JedisShardInfo shardInfo = new JedisShardInfo(host.getHostAddress(), host.getPort(), + hostPool.getConnectionTimeout(), hostPool.getSocketTimeout(), Sharded.DEFAULT_WEIGHT); + shardInfo.setPassword(host.getPassword()); - jedisClient = new Jedis(shardInfo); - } else { - JedisShardInfo shardInfo = new JedisShardInfo(host.getHostAddress(), host.getPort(), - hostPool.getConnectionTimeout(), hostPool.getSocketTimeout(), Sharded.DEFAULT_WEIGHT, - true, sslSocketFactory, new SSLParameters(), null); - shardInfo.setPassword(host.getPassword()); + jedisClient = new Jedis(shardInfo); + } else { + JedisShardInfo shardInfo = new JedisShardInfo(host.getHostAddress(), host.getPort(), + hostPool.getConnectionTimeout(), hostPool.getSocketTimeout(), Sharded.DEFAULT_WEIGHT, + true, sslSocketFactory, new SSLParameters(), null); + shardInfo.setPassword(host.getPassword()); - jedisClient = new Jedis(shardInfo); - } - } + jedisClient = new Jedis(shardInfo); + } + } - @Override - public OperationResult execute(Operation op) throws DynoException { + @Override + public OperationResult execute(Operation op) throws DynoException { - long startTime = System.nanoTime()/1000; - String opName = op.getName(); + long startTime = System.nanoTime() / 1000; + String opName = op.getName(); - OperationResultImpl opResult = null; + OperationResultImpl opResult = null; - try { - R result = op.execute(jedisClient, context); - if (context.hasMetadata("compression") || context.hasMetadata("decompression")) { + try { + R result = op.execute(jedisClient, context); + if (context.hasMetadata("compression") || context.hasMetadata("decompression")) { opMonitor.recordSuccess(opName, true); } else { opMonitor.recordSuccess(opName); } - opResult = new OperationResultImpl(opName, result, opMonitor); - opResult.addMetadata("connectionId", String.valueOf(this.hashCode())); + opResult = new OperationResultImpl(opName, result, opMonitor); + opResult.addMetadata("connectionId", String.valueOf(this.hashCode())); return opResult; - } catch (JedisConnectionException ex) { + } catch (JedisConnectionException ex) { Logger.warn("Caught JedisConnectionException: " + ex.getMessage()); - opMonitor.recordFailure(opName, ex.getMessage()); - lastDynoException = (DynoConnectException) new FatalConnectionException(ex).setAttempt(1).setHost(this.getHost()); - throw lastDynoException; + opMonitor.recordFailure(opName, ex.getMessage()); + lastDynoException = (DynoConnectException) new FatalConnectionException(ex).setAttempt(1).setHost(this.getHost()); + throw lastDynoException; - } catch (RuntimeException ex) { + } catch (RuntimeException ex) { Logger.warn("Caught RuntimeException: " + ex.getMessage()); - opMonitor.recordFailure(opName, ex.getMessage()); - lastDynoException = (DynoConnectException) new FatalConnectionException(ex).setAttempt(1).setHost(this.getHost()); - throw lastDynoException; - - } finally { - long duration = System.nanoTime()/1000 - startTime; - if (opResult != null) { - opResult.setLatency(duration, TimeUnit.MICROSECONDS); - } - } - } - - @Override - public ListenableFuture> executeAsync(AsyncOperation op) throws DynoException { - throw new NotImplementedException(); - } - - @Override - public void close() { - jedisClient.quit(); - jedisClient.disconnect(); - } - - @Override - public Host getHost() { - return hostPool.getHost(); - } - - @Override - public void open() throws DynoException { - jedisClient.connect(); - } - - @Override - public DynoConnectException getLastException() { - return lastDynoException; - } - - @Override - public HostConnectionPool getParentConnectionPool() { - return hostPool; - } - - @Override - public void execPing() { - final String result; - - try { - result = jedisClient.ping(); - } catch (JedisConnectionException e) { - throw new DynoConnectException("Unsuccessful ping", e); - } - - if (result == null || result.isEmpty()) { - throw new DynoConnectException("Unsuccessful ping, got empty result"); - } - } - - @Override - public ConnectionContext getContext() { - return context; - } - - public Jedis getClient() { - return jedisClient; - } - } + opMonitor.recordFailure(opName, ex.getMessage()); + lastDynoException = (DynoConnectException) new FatalConnectionException(ex).setAttempt(1).setHost(this.getHost()); + throw lastDynoException; + + } finally { + long duration = System.nanoTime() / 1000 - startTime; + if (opResult != null) { + opResult.setLatency(duration, TimeUnit.MICROSECONDS); + } + } + } + + @Override + public ListenableFuture> executeAsync(AsyncOperation op) throws DynoException { + throw new NotImplementedException(); + } + + @Override + public void close() { + jedisClient.quit(); + jedisClient.disconnect(); + } + + @Override + public Host getHost() { + return hostPool.getHost(); + } + + @Override + public void open() throws DynoException { + jedisClient.connect(); + } + + @Override + public DynoConnectException getLastException() { + return lastDynoException; + } + + @Override + public HostConnectionPool getParentConnectionPool() { + return hostPool; + } + + @Override + public void execPing() { + final String result; + + try { + result = jedisClient.ping(); + } catch (JedisConnectionException e) { + throw new DynoConnectException("Unsuccessful ping", e); + } + + if (result == null || result.isEmpty()) { + throw new DynoConnectException("Unsuccessful ping, got empty result"); + } + } + + @Override + public ConnectionContext getContext() { + return context; + } + + public Jedis getClient() { + return jedisClient; + } + } } diff --git a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/OpName.java b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/OpName.java index 50299ee0..14302a63 100644 --- a/dyno-jedis/src/main/java/com/netflix/dyno/jedis/OpName.java +++ b/dyno-jedis/src/main/java/com/netflix/dyno/jedis/OpName.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,27 +16,27 @@ package com.netflix.dyno.jedis; public enum OpName { - APPEND, - BITCOUNT, BLPOP, BRPOP, - DECR, DECRBY, DEL, DUMP, - ECHO, EXISTS, EXPIRE, EXPIREAT, EVAL, EVALSHA, EHSET, EHGET, EHDEL, EHEXISTS, EHGETALL, EHKEYS, EHMGET, EHVALS, - EHMSET, EHSETNX, EHSCAN, EHINCRBY, EHINCRBYFLOAT, - GET, GETBIT, GETRANGE, GETSET, - HDEL, HEXISTS, HGET, HGETALL, HINCRBY, HINCRBYFLOAT, HKEYS, HLEN, HMGET, HMSET, HSET, HSCAN, HSETNX, HVALS, - HSTRLEN, - INCR, INCRBY, INCRBYFLOAT, - KEYS, LINDEX, - LINSERT, LLEN, LPOP, LPUSH, LPUSHX, LRANGE, LREM, LSET, LTRIM, - MOVE, MGET, MSET, MSETNX, - PERSIST, PEXPIRE, PEXPIREAT, PSETEX, PTTL, - RENAME, RENAMENX, RESTORE, RPOP, RPOPLPUSH, RPUSH, RPUSHX, - SADD, SCAN, SCARD, SCRIPT_EXISTS, SCRIPT_FLUSH, SCRIPT_LOAD, SCRIPT_KILL, SDIFF, SDIFFSTORE, SET, SETBIT, SETEX, - SETNX, SETRANGE, SINTER, SINTERSTORE, SISMEMBER, SMEMBERS, SMOVE, SORT, SPOP, SRANDMEMBER, SREM, SSCAN, STRLEN, - SUBSTR, SUNION, SUNIONSTORE, - TTL, TYPE, - UNLINK, - ZADD, ZCARD, ZCOUNT, ZINCRBY, ZLEXCOUNT, ZRANGE, ZRANGEBYLEX, ZRANGEWITHSCORES, ZRANK, ZRANGEBYSCORE, - ZRANGEBYSCOREWITHSCORES, ZREM, ZREMRANGEBYLEX, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREVRANGE, ZREVRANGEBYLEX, - ZREVRANGEBYSCORE, ZREVRANGEBYSCOREWITHSCORES, ZREVRANGEWITHSCORES, ZREVRANK, ZSCAN, ZSCORE + APPEND, + BITCOUNT, BLPOP, BRPOP, + DECR, DECRBY, DEL, DUMP, + ECHO, EXISTS, EXPIRE, EXPIREAT, EVAL, EVALSHA, EHSET, EHGET, EHDEL, EHEXISTS, EHGETALL, EHKEYS, EHMGET, EHVALS, + EHMSET, EHSETNX, EHSCAN, EHINCRBY, EHINCRBYFLOAT, + GET, GETBIT, GETRANGE, GETSET, + HDEL, HEXISTS, HGET, HGETALL, HINCRBY, HINCRBYFLOAT, HKEYS, HLEN, HMGET, HMSET, HSET, HSCAN, HSETNX, HVALS, + HSTRLEN, + INCR, INCRBY, INCRBYFLOAT, + KEYS, LINDEX, + LINSERT, LLEN, LPOP, LPUSH, LPUSHX, LRANGE, LREM, LSET, LTRIM, + MOVE, MGET, MSET, MSETNX, + PERSIST, PEXPIRE, PEXPIREAT, PSETEX, PTTL, + RENAME, RENAMENX, RESTORE, RPOP, RPOPLPUSH, RPUSH, RPUSHX, + SADD, SCAN, SCARD, SCRIPT_EXISTS, SCRIPT_FLUSH, SCRIPT_LOAD, SCRIPT_KILL, SDIFF, SDIFFSTORE, SET, SETBIT, SETEX, + SETNX, SETRANGE, SINTER, SINTERSTORE, SISMEMBER, SMEMBERS, SMOVE, SORT, SPOP, SRANDMEMBER, SREM, SSCAN, STRLEN, + SUBSTR, SUNION, SUNIONSTORE, + TTL, TYPE, + UNLINK, + ZADD, ZCARD, ZCOUNT, ZINCRBY, ZLEXCOUNT, ZRANGE, ZRANGEBYLEX, ZRANGEWITHSCORES, ZRANK, ZRANGEBYSCORE, + ZRANGEBYSCOREWITHSCORES, ZREM, ZREMRANGEBYLEX, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREVRANGE, ZREVRANGEBYLEX, + ZREVRANGEBYSCORE, ZREVRANGEBYSCOREWITHSCORES, ZREVRANGEWITHSCORES, ZREVRANK, ZSCAN, ZSCORE } diff --git a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/CommandTest.java b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/CommandTest.java index 8cee3faa..502999ba 100644 --- a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/CommandTest.java +++ b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/CommandTest.java @@ -1,12 +1,12 @@ /** * Copyright 2017 Netflix, Inc. - * + *

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -76,11 +76,10 @@ public void testDynoJedis_GetSet() { Assert.assertEquals(VALUE_1KB, resultGet); Long resultDel = client.del("keyFor1KBValue"); - Assert.assertEquals((long)1, (long) resultDel); + Assert.assertEquals((long) 1, (long) resultDel); } - public static final String KEY_1KB = "keyFor1KBValue"; public static final String VALUE_1KB = generateValue(1000); diff --git a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/CompressionTest.java b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/CompressionTest.java index 51e81772..ed508165 100644 --- a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/CompressionTest.java +++ b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/CompressionTest.java @@ -34,9 +34,9 @@ /** * Tests compression commands. - * + *

    * Note - The underlying jedis client has been mocked to echo back the value given for SET operations and to - * ensure values over a 2KB threshold are compressed for HMSET operations. + * ensure values over a 2KB threshold are compressed for HMSET operations. */ public class CompressionTest { @@ -61,7 +61,7 @@ public void before() { opMonitor = new LastOperationMonitor(); - connectionPool = new UnitTestConnectionPoolForCompression(config, opMonitor); + connectionPool = new UnitTestConnectionPoolForCompression(config, opMonitor); client = new DynoJedisClient.TestBuilder() .withAppname("CompressionTest") @@ -125,7 +125,7 @@ public void testDynoJedis_Mget() throws IOException { Assert.assertEquals(result.size(), keys.length); - for (int i = 0; i< keys.length; i++) { + for (int i = 0; i < keys.length; i++) { String value = result.get(i); Assert.assertEquals(value, values[i]); } @@ -148,7 +148,7 @@ public void testZipUtilsDecompressBytesNonBase64() throws Exception { String s = "ABCDEFG__abcdefg__1234567890'\"\\+=-::ABCDEFG__abcdefg__1234567890'\"\\+=-::ABCDEFG__abcdefg__1234567890'\"\\+=-"; byte[] val = s.getBytes(); - byte[] compressed = ZipUtils.compressBytesNonBase64(val); + byte[] compressed = ZipUtils.compressBytesNonBase64(val); Assert.assertTrue(compressed.length < val.length); diff --git a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/ExpireHashTest.java b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/ExpireHashTest.java index 0ad617c7..ad47a400 100644 --- a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/ExpireHashTest.java +++ b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/ExpireHashTest.java @@ -31,7 +31,7 @@ /** * Tests generic commands. - * + *

    * Note - The underlying jedis client has been mocked to echo back the value * given for SET operations */ @@ -72,7 +72,7 @@ public void testBasicCommands() { final String expireHashKey = "expireHashKey"; Assert.assertEquals(new Long(1L), client.ehset(expireHashKey, "hello", "world", 900)); - Assert.assertEquals(new Long(0L), client.ehsetnx(expireHashKey, "hello", "world",900)); + Assert.assertEquals(new Long(0L), client.ehsetnx(expireHashKey, "hello", "world", 900)); Assert.assertEquals("world", client.ehget(expireHashKey, "hello")); Assert.assertTrue(client.ehexists(expireHashKey, "hello")); Assert.assertEquals(new Long(1L), client.ehdel(expireHashKey, "hello")); @@ -149,7 +149,7 @@ public void testMultipleFields() throws InterruptedException { fields.put(secondaryKeyPrefix + i, new ImmutablePair<>(valuePrefix + i, i + minTimeout)); } - Assert.assertEquals("OK", client.ehmset(expireHashKey,fields)); + Assert.assertEquals("OK", client.ehmset(expireHashKey, fields)); long startTime = System.currentTimeMillis(); Map allFields = client.ehgetall(expireHashKey); List mgetFields = client.ehmget(expireHashKey, fields.keySet().toArray(new String[0])); @@ -207,7 +207,7 @@ public void testScan() { ScanResult> values = client.ehscan(expireHashKey, cursor); count += values.getResult().size(); cursor = values.getCursor(); - } while(cursor.compareTo("0") != 0); + } while (cursor.compareTo("0") != 0); Assert.assertEquals(fieldCount, count); } diff --git a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/JedisConnectionFactoryIntegrationTest.java b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/JedisConnectionFactoryIntegrationTest.java index 74337130..74679367 100644 --- a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/JedisConnectionFactoryIntegrationTest.java +++ b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/JedisConnectionFactoryIntegrationTest.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/RedisAuthenticationIntegrationTest.java b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/RedisAuthenticationIntegrationTest.java index 9d442dad..fbee1b23 100644 --- a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/RedisAuthenticationIntegrationTest.java +++ b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/RedisAuthenticationIntegrationTest.java @@ -14,10 +14,12 @@ import com.netflix.dyno.connectionpool.impl.HostConnectionPoolImpl; import com.netflix.dyno.connectionpool.impl.lb.HostToken; import com.netflix.dyno.contrib.DynoOPMonitor; + import java.net.ConnectException; import java.util.Collections; import java.util.List; import java.util.Set; + import org.junit.After; import org.junit.Assert; import org.junit.Assume; @@ -30,216 +32,216 @@ public class RedisAuthenticationIntegrationTest { - private static final int REDIS_PORT = 8998; - private static final String REDIS_RACK = "rack-1c"; - private static final String REDIS_DATACENTER = "rack-1"; - - private RedisServer redisServer; - - @Before - public void setUp() throws Exception { - // skip tests on windows due to https://github.com/spinnaker/embedded-redis#redis-version - Assume.assumeFalse(System.getProperty("os.name").toLowerCase().startsWith("win")); - } - - @After - public void tearDown() throws Exception { - if (redisServer != null) { - redisServer.stop(); - } - } - - @Test - public void testDynoClient_noAuthSuccess() throws Exception { - redisServer = new RedisServer(REDIS_PORT); - redisServer.start(); - - Host noAuthHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Host.Status.Up); - TokenMapSupplierImpl tokenMapSupplier = new TokenMapSupplierImpl(noAuthHost); - DynoJedisClient dynoClient = constructJedisClient(tokenMapSupplier, - () -> Collections.singletonList(noAuthHost)); - - String statusCodeReply = dynoClient.set("some-key", "some-value"); - Assert.assertEquals("OK", statusCodeReply); - - String value = dynoClient.get("some-key"); - Assert.assertEquals("some-value", value); - } - - @Test - public void testDynoClient_authSuccess() throws Exception { - redisServer = new RedisServerBuilder() - .port(REDIS_PORT) - .setting("requirepass password") - .build(); - redisServer.start(); - - Host authHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Status.Up, null, "password"); - - TokenMapSupplierImpl tokenMapSupplier = new TokenMapSupplierImpl(authHost); - DynoJedisClient dynoClient = constructJedisClient(tokenMapSupplier, - () -> Collections.singletonList(authHost)); - - String statusCodeReply = dynoClient.set("some-key", "some-value"); - Assert.assertEquals("OK", statusCodeReply); - - String value = dynoClient.get("some-key"); - Assert.assertEquals("some-value", value); - } - - @Test - public void testJedisConnFactory_noAuthSuccess() throws Exception { - redisServer = new RedisServer(REDIS_PORT); - redisServer.start(); - - Host noAuthHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Host.Status.Up); - - JedisConnectionFactory conFactory = - new JedisConnectionFactory(new DynoOPMonitor("some-application-name"), null); - ConnectionPoolConfiguration cpConfig = new ConnectionPoolConfigurationImpl("some-name"); - CountingConnectionPoolMonitor poolMonitor = new CountingConnectionPoolMonitor(); - HostConnectionPool hostConnectionPool = - new HostConnectionPoolImpl<>(noAuthHost, conFactory, cpConfig, poolMonitor); - Connection connection = conFactory - .createConnection(hostConnectionPool, null); - - connection.execPing(); - } - - @Test - public void testJedisConnFactory_authSuccess() throws Exception { - redisServer = new RedisServerBuilder() - .port(REDIS_PORT) - .setting("requirepass password") - .build(); - redisServer.start(); - - Host authHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Status.Up, null, "password"); - - JedisConnectionFactory conFactory = - new JedisConnectionFactory(new DynoOPMonitor("some-application-name"), null); - ConnectionPoolConfiguration cpConfig = new ConnectionPoolConfigurationImpl("some-name"); - CountingConnectionPoolMonitor poolMonitor = new CountingConnectionPoolMonitor(); - HostConnectionPool hostConnectionPool = - new HostConnectionPoolImpl<>(authHost, conFactory, cpConfig, poolMonitor); - Connection connection = conFactory - .createConnection(hostConnectionPool, null); - - connection.execPing(); - } - - @Test - public void testJedisConnFactory_connectionFailed() throws Exception { - Host noAuthHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Host.Status.Up); - - JedisConnectionFactory conFactory = - new JedisConnectionFactory(new DynoOPMonitor("some-application-name"), null); - ConnectionPoolConfiguration cpConfig = new ConnectionPoolConfigurationImpl("some-name"); - CountingConnectionPoolMonitor poolMonitor = new CountingConnectionPoolMonitor(); - HostConnectionPool hostConnectionPool = - new HostConnectionPoolImpl<>(noAuthHost, conFactory, cpConfig, poolMonitor); - Connection connection = conFactory - .createConnection(hostConnectionPool, null); - - try { - connection.execPing(); - Assert.fail("expected to throw"); - } catch (DynoConnectException e) { - Assert.assertTrue("root cause should be connect exception", - Throwables.getRootCause(e) instanceof ConnectException); - } - } - - @Test - public void testJedisConnFactory_authenticationRequired() throws Exception { - redisServer = new RedisServerBuilder() - .port(REDIS_PORT) - .setting("requirepass password") - .build(); - redisServer.start(); - - Host noAuthHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Host.Status.Up); - - JedisConnectionFactory conFactory = - new JedisConnectionFactory(new DynoOPMonitor("some-application-name"), null); - ConnectionPoolConfiguration cpConfig = new ConnectionPoolConfigurationImpl("some-name"); - CountingConnectionPoolMonitor poolMonitor = new CountingConnectionPoolMonitor(); - HostConnectionPool hostConnectionPool = - new HostConnectionPoolImpl<>(noAuthHost, conFactory, cpConfig, poolMonitor); - Connection connection = conFactory - .createConnection(hostConnectionPool, null); - - try { - connection.execPing(); - Assert.fail("expected to throw"); - } catch (JedisDataException e) { - Assert.assertEquals("NOAUTH Authentication required.", e.getMessage()); - } - } - - @Test - public void testJedisConnFactory_invalidPassword() throws Exception { - redisServer = new RedisServerBuilder() - .port(REDIS_PORT) - .setting("requirepass password") - .build(); - redisServer.start(); - - Host authHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Status.Up, null, - "invalid-password"); - - JedisConnectionFactory jedisConnectionFactory = - new JedisConnectionFactory(new DynoOPMonitor("some-application-name"), null); - - ConnectionPoolConfiguration connectionPoolConfiguration = new ConnectionPoolConfigurationImpl( - "some-name"); - HostConnectionPool hostConnectionPool = new HostConnectionPoolImpl<>(authHost, - jedisConnectionFactory, connectionPoolConfiguration, new CountingConnectionPoolMonitor()); - Connection connection = jedisConnectionFactory - .createConnection(hostConnectionPool, null); - - try { - connection.execPing(); - Assert.fail("expected to throw"); - } catch (JedisDataException e) { - Assert.assertEquals("ERR invalid password", e.getMessage()); - } - } - - private DynoJedisClient constructJedisClient(TokenMapSupplier tokenMapSupplier, - HostSupplier hostSupplier) { - - final ConnectionPoolConfigurationImpl connectionPoolConfiguration = - new ConnectionPoolConfigurationImpl(REDIS_RACK); - connectionPoolConfiguration.withTokenSupplier(tokenMapSupplier); - connectionPoolConfiguration.setLocalRack(REDIS_RACK); - connectionPoolConfiguration.setLocalDataCenter(REDIS_DATACENTER); - - return new DynoJedisClient.Builder() - .withApplicationName("some-application-name") - .withDynomiteClusterName(REDIS_RACK) - .withHostSupplier(hostSupplier) - .withCPConfig(connectionPoolConfiguration) - .build(); - } - - private static class TokenMapSupplierImpl implements TokenMapSupplier { - - private final HostToken localHostToken; - - private TokenMapSupplierImpl(Host host) { - this.localHostToken = new HostToken(100000L, host); - } - - @Override - public List getTokens(Set activeHosts) { - return Collections.singletonList(localHostToken); - } - - @Override - public HostToken getTokenForHost(Host host, Set activeHosts) { - return localHostToken; - } - - } + private static final int REDIS_PORT = 8998; + private static final String REDIS_RACK = "rack-1c"; + private static final String REDIS_DATACENTER = "rack-1"; + + private RedisServer redisServer; + + @Before + public void setUp() throws Exception { + // skip tests on windows due to https://github.com/spinnaker/embedded-redis#redis-version + Assume.assumeFalse(System.getProperty("os.name").toLowerCase().startsWith("win")); + } + + @After + public void tearDown() throws Exception { + if (redisServer != null) { + redisServer.stop(); + } + } + + @Test + public void testDynoClient_noAuthSuccess() throws Exception { + redisServer = new RedisServer(REDIS_PORT); + redisServer.start(); + + Host noAuthHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Host.Status.Up); + TokenMapSupplierImpl tokenMapSupplier = new TokenMapSupplierImpl(noAuthHost); + DynoJedisClient dynoClient = constructJedisClient(tokenMapSupplier, + () -> Collections.singletonList(noAuthHost)); + + String statusCodeReply = dynoClient.set("some-key", "some-value"); + Assert.assertEquals("OK", statusCodeReply); + + String value = dynoClient.get("some-key"); + Assert.assertEquals("some-value", value); + } + + @Test + public void testDynoClient_authSuccess() throws Exception { + redisServer = new RedisServerBuilder() + .port(REDIS_PORT) + .setting("requirepass password") + .build(); + redisServer.start(); + + Host authHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Status.Up, null, "password"); + + TokenMapSupplierImpl tokenMapSupplier = new TokenMapSupplierImpl(authHost); + DynoJedisClient dynoClient = constructJedisClient(tokenMapSupplier, + () -> Collections.singletonList(authHost)); + + String statusCodeReply = dynoClient.set("some-key", "some-value"); + Assert.assertEquals("OK", statusCodeReply); + + String value = dynoClient.get("some-key"); + Assert.assertEquals("some-value", value); + } + + @Test + public void testJedisConnFactory_noAuthSuccess() throws Exception { + redisServer = new RedisServer(REDIS_PORT); + redisServer.start(); + + Host noAuthHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Host.Status.Up); + + JedisConnectionFactory conFactory = + new JedisConnectionFactory(new DynoOPMonitor("some-application-name"), null); + ConnectionPoolConfiguration cpConfig = new ConnectionPoolConfigurationImpl("some-name"); + CountingConnectionPoolMonitor poolMonitor = new CountingConnectionPoolMonitor(); + HostConnectionPool hostConnectionPool = + new HostConnectionPoolImpl<>(noAuthHost, conFactory, cpConfig, poolMonitor); + Connection connection = conFactory + .createConnection(hostConnectionPool, null); + + connection.execPing(); + } + + @Test + public void testJedisConnFactory_authSuccess() throws Exception { + redisServer = new RedisServerBuilder() + .port(REDIS_PORT) + .setting("requirepass password") + .build(); + redisServer.start(); + + Host authHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Status.Up, null, "password"); + + JedisConnectionFactory conFactory = + new JedisConnectionFactory(new DynoOPMonitor("some-application-name"), null); + ConnectionPoolConfiguration cpConfig = new ConnectionPoolConfigurationImpl("some-name"); + CountingConnectionPoolMonitor poolMonitor = new CountingConnectionPoolMonitor(); + HostConnectionPool hostConnectionPool = + new HostConnectionPoolImpl<>(authHost, conFactory, cpConfig, poolMonitor); + Connection connection = conFactory + .createConnection(hostConnectionPool, null); + + connection.execPing(); + } + + @Test + public void testJedisConnFactory_connectionFailed() throws Exception { + Host noAuthHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Host.Status.Up); + + JedisConnectionFactory conFactory = + new JedisConnectionFactory(new DynoOPMonitor("some-application-name"), null); + ConnectionPoolConfiguration cpConfig = new ConnectionPoolConfigurationImpl("some-name"); + CountingConnectionPoolMonitor poolMonitor = new CountingConnectionPoolMonitor(); + HostConnectionPool hostConnectionPool = + new HostConnectionPoolImpl<>(noAuthHost, conFactory, cpConfig, poolMonitor); + Connection connection = conFactory + .createConnection(hostConnectionPool, null); + + try { + connection.execPing(); + Assert.fail("expected to throw"); + } catch (DynoConnectException e) { + Assert.assertTrue("root cause should be connect exception", + Throwables.getRootCause(e) instanceof ConnectException); + } + } + + @Test + public void testJedisConnFactory_authenticationRequired() throws Exception { + redisServer = new RedisServerBuilder() + .port(REDIS_PORT) + .setting("requirepass password") + .build(); + redisServer.start(); + + Host noAuthHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Host.Status.Up); + + JedisConnectionFactory conFactory = + new JedisConnectionFactory(new DynoOPMonitor("some-application-name"), null); + ConnectionPoolConfiguration cpConfig = new ConnectionPoolConfigurationImpl("some-name"); + CountingConnectionPoolMonitor poolMonitor = new CountingConnectionPoolMonitor(); + HostConnectionPool hostConnectionPool = + new HostConnectionPoolImpl<>(noAuthHost, conFactory, cpConfig, poolMonitor); + Connection connection = conFactory + .createConnection(hostConnectionPool, null); + + try { + connection.execPing(); + Assert.fail("expected to throw"); + } catch (JedisDataException e) { + Assert.assertEquals("NOAUTH Authentication required.", e.getMessage()); + } + } + + @Test + public void testJedisConnFactory_invalidPassword() throws Exception { + redisServer = new RedisServerBuilder() + .port(REDIS_PORT) + .setting("requirepass password") + .build(); + redisServer.start(); + + Host authHost = new Host("localhost", REDIS_PORT, REDIS_RACK, Status.Up, null, + "invalid-password"); + + JedisConnectionFactory jedisConnectionFactory = + new JedisConnectionFactory(new DynoOPMonitor("some-application-name"), null); + + ConnectionPoolConfiguration connectionPoolConfiguration = new ConnectionPoolConfigurationImpl( + "some-name"); + HostConnectionPool hostConnectionPool = new HostConnectionPoolImpl<>(authHost, + jedisConnectionFactory, connectionPoolConfiguration, new CountingConnectionPoolMonitor()); + Connection connection = jedisConnectionFactory + .createConnection(hostConnectionPool, null); + + try { + connection.execPing(); + Assert.fail("expected to throw"); + } catch (JedisDataException e) { + Assert.assertEquals("ERR invalid password", e.getMessage()); + } + } + + private DynoJedisClient constructJedisClient(TokenMapSupplier tokenMapSupplier, + HostSupplier hostSupplier) { + + final ConnectionPoolConfigurationImpl connectionPoolConfiguration = + new ConnectionPoolConfigurationImpl(REDIS_RACK); + connectionPoolConfiguration.withTokenSupplier(tokenMapSupplier); + connectionPoolConfiguration.setLocalRack(REDIS_RACK); + connectionPoolConfiguration.setLocalDataCenter(REDIS_DATACENTER); + + return new DynoJedisClient.Builder() + .withApplicationName("some-application-name") + .withDynomiteClusterName(REDIS_RACK) + .withHostSupplier(hostSupplier) + .withCPConfig(connectionPoolConfiguration) + .build(); + } + + private static class TokenMapSupplierImpl implements TokenMapSupplier { + + private final HostToken localHostToken; + + private TokenMapSupplierImpl(Host host) { + this.localHostToken = new HostToken(100000L, host); + } + + @Override + public List getTokens(Set activeHosts) { + return Collections.singletonList(localHostToken); + } + + @Override + public HostToken getTokenForHost(Host host, Set activeHosts) { + return localHostToken; + } + + } } diff --git a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/UnitTestConnectionPool.java b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/UnitTestConnectionPool.java index 1456742f..5cb8f1a9 100644 --- a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/UnitTestConnectionPool.java +++ b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/UnitTestConnectionPool.java @@ -1,12 +1,12 @@ /** * Copyright 2017 Netflix, Inc. - * + *

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/UnitTestConnectionPoolForCompression.java b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/UnitTestConnectionPoolForCompression.java index 3b2fb47e..42b043b0 100644 --- a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/UnitTestConnectionPoolForCompression.java +++ b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/UnitTestConnectionPoolForCompression.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -61,8 +61,8 @@ public UnitTestConnectionPoolForCompression(ConnectionPoolConfiguration config, when(client.set(anyString(), anyString())).thenAnswer(new Answer() { @Override public String answer(InvocationOnMock invocation) throws Throwable { - String key = (String)invocation.getArguments()[0]; - String value = (String)invocation.getArguments()[1]; + String key = (String) invocation.getArguments()[0]; + String value = (String) invocation.getArguments()[1]; redis_data.put(key, value); return value; } @@ -99,7 +99,7 @@ public String answer(InvocationOnMock invocation) throws Throwable { } }); - when(client.mget(Matchers.anyVararg())).thenAnswer (new Answer>() { + when(client.mget(Matchers.anyVararg())).thenAnswer(new Answer>() { @Override public List answer(InvocationOnMock invocation) throws Throwable { @@ -110,7 +110,7 @@ public List answer(InvocationOnMock invocation) throws Throwable { for (int i = 0; i < keys.length; i++) { // get the ith key, find the value in redis_data // if found, return that else return nil - String key = (String)keys[i]; + String key = (String) keys[i]; String value = redis_data.get(key); values.add(i, value); } diff --git a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/UnitTestTokenMapAndHostSupplierImpl.java b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/UnitTestTokenMapAndHostSupplierImpl.java index e28c9091..b4d10b7e 100644 --- a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/UnitTestTokenMapAndHostSupplierImpl.java +++ b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/UnitTestTokenMapAndHostSupplierImpl.java @@ -18,7 +18,7 @@ public class UnitTestTokenMapAndHostSupplierImpl implements TokenMapSupplier, Ho public UnitTestTokenMapAndHostSupplierImpl(int serverCount, String rack) throws IOException { int hostTokenStride = Integer.MAX_VALUE / serverCount; - for(int i = 0; i < serverCount; i++) { + for (int i = 0; i < serverCount; i++) { int port = findFreePort(); RedisServer redisServer = new RedisServer(port); redisServer.start(); @@ -59,10 +59,16 @@ public List getHosts() { return new ArrayList<>(hostTokenMap.keySet()); } - public void shutdown() { redisServers.forEach(x -> x.getLeft().stop()); } + public void shutdown() { + redisServers.forEach(x -> x.getLeft().stop()); + } - public void pauseServer(int idx) { redisServers.get(idx).getLeft().stop(); } + public void pauseServer(int idx) { + redisServers.get(idx).getLeft().stop(); + } - public void resumeServer(int idx) { redisServers.get(idx).getLeft().start(); } + public void resumeServer(int idx) { + redisServers.get(idx).getLeft().start(); + } } diff --git a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/utils/MockedRedisResponse.java b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/utils/MockedRedisResponse.java index f12c59a9..db21f70f 100644 --- a/dyno-jedis/src/test/java/com/netflix/dyno/jedis/utils/MockedRedisResponse.java +++ b/dyno-jedis/src/test/java/com/netflix/dyno/jedis/utils/MockedRedisResponse.java @@ -20,7 +20,7 @@ * $4\r\n * test\r\n * - * + *

    * It allows us to test SSL/TLS end to end scenario, assuming that after connection * to redis(here, to MockedRedisResponse server) by Jedis client, only simple GET will be invoked. */ @@ -37,14 +37,12 @@ public class MockedRedisResponse { private EventLoopGroup workerGroup; - public MockedRedisResponse(final String response, final boolean useSsl) - { + public MockedRedisResponse(final String response, final boolean useSsl) { this.response = response; this.useSsl = useSsl; } - public void start() throws Exception - { + public void start() throws Exception { final SSLContext sslContext = createAndInitSSLContext("server.jks"); bossGroup = new NioEventLoopGroup(1); @@ -54,7 +52,7 @@ public void start() throws Exception serverBootstrap.group(bossGroup, workerGroup)// .channel(NioServerSocketChannel.class) // .handler(new LoggingHandler(LogLevel.INFO)) // - .childHandler(new EmbeddedRedisInitializer(sslContext,useSsl,response)); + .childHandler(new EmbeddedRedisInitializer(sslContext, useSsl, response)); serverChannel = serverBootstrap.bind(8998).sync().channel(); } diff --git a/dyno-jedis/src/test/resources/log4j.properties b/dyno-jedis/src/test/resources/log4j.properties index 732176f6..cf5ed8a7 100644 --- a/dyno-jedis/src/test/resources/log4j.properties +++ b/dyno-jedis/src/test/resources/log4j.properties @@ -1,11 +1,9 @@ # logging conf solely for create_delete_tokens tool log4j.rootLogger=DEBUG,stdout - # stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%-5p %d [%t] %c: %m%n - log4j.logger.org.apache.http.wire=FATAL log4j.logger.com.netflix.config=INFO log4j.logger.com.netflix.discovery=INFO diff --git a/dyno-memcache/src/main/conf/eureka-client.properties b/dyno-memcache/src/main/conf/eureka-client.properties index 75e5a911..bfadfc31 100644 --- a/dyno-memcache/src/main/conf/eureka-client.properties +++ b/dyno-memcache/src/main/conf/eureka-client.properties @@ -3,30 +3,20 @@ # Properties based configuration for eureka client. The properties specified here is mostly what the users # need to change. All of these can be specified as a java system property with -D option (eg)-Deureka.region=us-east-1 # Refer to eureka wiki (https://github.com/Netflix/eureka/wiki/Configuring-Eureka) for details about these configurations. - - #Region where eureka is deployed -For AWS specify one of the AWS regions, for other datacenters specify a arbitrary string #indicating the region.This is normally specified as a -D option (eg) -Deureka.region=us-east-1 eureka.region=us-east-1 - #Name of the application to be identified by other services - eureka.name=dynoclient - #Virtual host name by which the clients identifies this service #eureka.vipAddress= - #The port where the service will be running and serving requests eureka.port=80 - #For eureka clients running in eureka server, it needs to connect to servers in other zones eureka.preferSameZone=true - #Change this if you want to use a DNS based lookup for determining other eureka servers. For example #of specifying the DNS entries, check the eureka-client-test.properties, eureka-client-prod.properties eureka.shouldUseDns=false - eureka.us-east-1.availabilityZones=default - eureka.serviceUrl.default=http://us-east-1b.discovery.cloudqa.netflix.net:7001/discovery/v2/ diff --git a/dyno-memcache/src/main/conf/log4j.properties b/dyno-memcache/src/main/conf/log4j.properties index 90330116..9bd8cd4a 100644 --- a/dyno-memcache/src/main/conf/log4j.properties +++ b/dyno-memcache/src/main/conf/log4j.properties @@ -1,11 +1,9 @@ # logging conf solely for create_delete_tokens tool log4j.rootLogger=DEBUG,stdout - # stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%-5p %d [%t] %c: %m%n - log4j.logger.org.apache.http.wire=FATAL log4j.logger.com.netflix.config=INFO log4j.logger.com.netflix.discovery=INFO diff --git a/dyno-memcache/src/main/java/com/netflix/dyno/memcache/DynoMCacheClient.java b/dyno-memcache/src/main/java/com/netflix/dyno/memcache/DynoMCacheClient.java index 981caa73..59ca7f1a 100644 --- a/dyno-memcache/src/main/java/com/netflix/dyno/memcache/DynoMCacheClient.java +++ b/dyno-memcache/src/main/java/com/netflix/dyno/memcache/DynoMCacheClient.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,826 +19,688 @@ /** * Dyno client for Memcached that uses the {@link RollingMemcachedConnectionPoolImpl} for managing connections to {@link MemcachedClient}s * with local zone aware based RR load balancing and fallbacks to the remote zones - * - * @author poberai * + * @author poberai */ public class DynoMCacheClient { /**implements MemcachedClientIF { - private final String cacheName; - - private final ConnectionPool connPool; - - public DynoMCacheClient(String name, ConnectionPool pool) { - this.cacheName = name; - this.connPool = pool; - } - - private enum OpName { - Add, Append, AsyncCas, AsyncDecr, AsyncGet, AsyncGetAndTouch, AsyncGets, AsyncIncr, Cas, Decr, Delete, - Get, GetAndTouch, GetAsync, GetBulk, Gets, Incr, Prepend, Set, Touch - } - - - private abstract class BaseKeyOperation implements Operation { - - private final String key; - private final OpName op; - private BaseKeyOperation(final String k, final OpName o) { - this.key = k; - this.op = o; - } - @Override - public String getName() { - return op.name(); - } - - @Override - public String getKey() { - return key; - } - } - - private abstract class BaseAsyncKeyOperation implements AsyncOperation { - - private final String key; - private final OpName op; - private BaseAsyncKeyOperation(final String k, final OpName o) { - this.key = k; - this.op = o; - } - @Override - public String getName() { - return op.name(); - } - - @Override - public String getKey() { - return key; - } - } - - public String toString() { - return this.cacheName; - } - - public static class Builder { - - private String appName; - private String clusterName; - private ConnectionPoolConfigurationImpl cpConfig; - - public Builder(String name) { - appName = name; - } - - public Builder withDynomiteClusterName(String cluster) { - clusterName = cluster; - return this; - } - - public Builder withConnectionPoolConfig(ConnectionPoolConfigurationImpl config) { - cpConfig = config; - return this; - } - - public DynoMCacheClient build() { - - assert(appName != null); - assert(clusterName != null); - assert(cpConfig != null); - - // TODO: Add conn pool impl for MemcachedClient - throw new RuntimeException("Dyno conn pool for Memcached Client NOT implemented. Coming soon."); - } - - public static Builder withName(String name) { - return new Builder(name); - } - } - - @Override - public Collection getAvailableServers() { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Collection getUnavailableServers() { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Transcoder getTranscoder() { - throw new RuntimeException("Not Implemented"); - } - - @Override - public NodeLocator getNodeLocator() { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Future append(final long cas, final String key, final Object val) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.append(cas, key, val)); - } - })); - } - - @Override - public Future append(final String key, final Object val) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.append(key, val)); - } - })); - } - - @Override - public Future append(final long cas, final String key, final T val, final Transcoder tc) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.append(cas, key, val)); - } - })); - } - - @Override - public Future append(final String key, final T val, final Transcoder tc) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.append(key, val)); - } - })); - } - - @Override - public Future prepend(final long cas, final String key, final Object val) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Prepend) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.prepend(cas, key, val)); - } - })); - } - - @Override - public Future prepend(final String key, final Object val) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Prepend) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.prepend(key, val)); - } - })); - } - - @Override - public Future prepend(final long cas, final String key, final T val, final Transcoder tc) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Prepend) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.prepend(cas, key, val)); - } - })); - } - - @Override - public Future prepend(final String key, final T val, final Transcoder tc) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Prepend) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.prepend(key, val, tc)); - } - })); - } - - @Override - public Future asyncCAS(final String key, final long casId, final T value, final Transcoder tc) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncCas) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.asyncCAS(key, casId, value, tc)); - } - })); - } - - @Override - public Future asyncCAS(final String key, final long casId, final Object value) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncCas) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.asyncCAS(key, casId, value)); - } - })); - } - - @Override - public Future asyncCAS(final String key, final long casId, final int exp, final Object value) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Cas) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.asyncCAS(key, casId, exp, value)); - } - })); - } - - @Override - public CASResponse cas(final String key, final long casId, final int exp, final T value, final Transcoder tc) { - - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Cas) { - @Override - public CASResponse execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.cas(key, casId, exp, value, tc); - } - - }).getResult(); - } - - @Override - public CASResponse cas(final String key, final long casId, final Object value) { - - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Cas) { - @Override - public CASResponse execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.cas(key, casId, value); - } - - }).getResult(); - } - - @Override - public CASResponse cas(final String key, final long casId, final int exp, final Object value) { - - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Cas) { - @Override - public CASResponse execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.cas(key, casId, exp, value); - } - - }).getResult(); - } - - @Override - public Future add(final String key, final int exp, final T o, final Transcoder tc) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Add) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.add(key, exp, o)); - } - })); - } - - @Override - public Future add(final String key, final int exp, final Object o) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Add) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.add(key, exp, o)); - } - })); - } - - @Override - public Future set(final String key, final int exp, final T o, final Transcoder tc) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Set) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.set(key, exp, o, tc)); - } - })); - } - - @Override - public Future set(final String key, final int exp, final Object o) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Set) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.set(key, exp, o)); - } - })); - } - - @Override - public Future replace(final String key, final int exp, final T o, final Transcoder tc) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.replace(key, exp, o, tc)); - } - })); - } - - @Override - public Future replace(final String key, final int exp, final Object o) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.replace(key, exp, o)); - } - })); - } - - @Override - public Future asyncGet(final String key, final Transcoder tc) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncGet) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.asyncGet(key, tc)); - } - })); - } - - @Override - public Future asyncGet(final String key) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncGet) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.asyncGet(key)); - } - })); - } - - @Override - public Future> asyncGetAndTouch(final String key, final int exp) { - - return new DecoratingFuture>(connPool.executeAsync(new BaseAsyncKeyOperation>(key, OpName.AsyncGetAndTouch) { - @Override - public ListenableFuture> executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture>(client.asyncGets(key)); - } - })); - } - - @Override - public Future> asyncGetAndTouch(final String key, final int exp, final Transcoder tc) { - - return new DecoratingFuture>(connPool.executeAsync(new BaseAsyncKeyOperation>(key, OpName.AsyncGetAndTouch) { - @Override - public ListenableFuture> executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture>(client.asyncGetAndTouch(key, exp, tc)); - } - })); - } - - @Override - public Future> asyncGets(final String key, final Transcoder tc) { - - return new DecoratingFuture>(connPool.executeAsync(new BaseAsyncKeyOperation>(key, OpName.AsyncGets) { - @Override - public ListenableFuture> executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture>(client.asyncGets(key, tc)); - } - })); - } - - @Override - public Future> asyncGets(final String key) { - - return new DecoratingFuture>(connPool.executeAsync(new BaseAsyncKeyOperation>(key, OpName.AsyncGets) { - @Override - public ListenableFuture> executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture>(client.asyncGets(key)); - } - })); - } - - @Override - public CASValue gets(final String key, final Transcoder tc) { - - return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.Gets) { - @Override - public CASValue execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.gets(key, tc); - } - - }).getResult(); - } - - @Override - public CASValue gets(final String key) { - - return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.Gets) { - @Override - public CASValue execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.gets(key); - } - - }).getResult(); - } - - @Override - public T get(final String key, final Transcoder tc) { - - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Get) { - @Override - public T execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.get(key, tc); - } - - }).getResult(); - } - - @Override - public BulkFuture> asyncGetBulk(Iterator keys, Iterator> tcs) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public BulkFuture> asyncGetBulk(Collection keys, Iterator> tcs) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public BulkFuture> asyncGetBulk(Iterator keys, Transcoder tc) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public BulkFuture> asyncGetBulk(Collection keys, Transcoder tc) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public BulkFuture> asyncGetBulk(Iterator keys) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public BulkFuture> asyncGetBulk(Collection keys) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public BulkFuture> asyncGetBulk(Transcoder tc, String... keys) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public BulkFuture> asyncGetBulk(String... keys) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Map getBulk(Iterator keys, Transcoder tc) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Map getBulk(Iterator keys) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Future touch(final String key, final int exp, final Transcoder tc) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Touch) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.touch(key, exp, tc)); - } - })); - } - - @Override - public Future touch(final String key, final int exp) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.touch(key, exp)); - } - })); - } - - @Override - public Map getVersions() { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Map> getStats() { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Map> getStats(String prefix) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public long incr(final String key, final long by) { - - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Incr) { - @Override - public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.incr(key, by); - } - - }).getResult(); - } - - @Override - public long incr(final String key, final int by) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Incr) { - @Override - public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.incr(key, by); - } - - }).getResult(); - } - - @Override - public long decr(final String key, final long by) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Decr) { - @Override - public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.decr(key, by); - } - - }).getResult(); - } - - @Override - public long decr(final String key, final int by) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Decr) { - @Override - public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.decr(key, by); - } - - }).getResult(); - } - - @Override - public long incr(final String key, final long by, final long def, final int exp) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Incr) { - @Override - public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.incr(key, by, def, exp); - } - - }).getResult(); - } - - @Override - public long incr(final String key, final int by, final long def, final int exp) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Incr) { - @Override - public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.incr(key, by, def, exp); - } - - }).getResult(); - } - - @Override - public long decr(final String key, final long by, final long def, final int exp) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Decr) { - @Override - public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.incr(key, by, def, exp); - } - - }).getResult(); - } - - @Override - public long decr(final String key, final int by, final long def, final int exp) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Decr) { - @Override - public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.incr(key, by, def, exp); - } - - }).getResult(); - } - - @Override - public Future asyncIncr(final String key, final long by) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncIncr) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.asyncIncr(key, by)); - } - })); - } - - @Override - public Future asyncIncr(final String key, final int by) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncIncr) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.asyncIncr(key, by)); - } - })); - } - - @Override - public Future asyncDecr(final String key, final long by) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncDecr) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.asyncDecr(key, by)); - } - })); - } - - @Override - public Future asyncDecr(final String key, final int by) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncDecr) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.asyncDecr(key, by)); - } - })); - } - - @Override - public long incr(final String key, final long by, final long def) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Incr) { - @Override - public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.incr(key, by, def); - } - - }).getResult(); - } - - @Override - public long incr(final String key, final int by, final long def) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Incr) { - @Override - public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.incr(key, by, def); - } - - }).getResult(); - } - - @Override - public long decr(final String key, final long by, final long def) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Decr) { - @Override - public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.decr(key, by, def); - } - - }).getResult(); - } - - @Override - public long decr(final String key, final int by, final long def) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Decr) { - @Override - public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.decr(key, by, def); - } - - }).getResult(); - } - - @Override - public Future delete(final String key, final long cas) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Delete) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.delete(key, cas)); - } - })); - } - - @Override - public Future flush(int delay) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Future flush() { - throw new RuntimeException("Not Implemented"); - } - - @Override - public void shutdown() { - throw new RuntimeException("Not Implemented"); - } - - @Override - public boolean shutdown(long timeout, TimeUnit unit) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public boolean waitForQueues(long timeout, TimeUnit unit) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public boolean addObserver(ConnectionObserver obs) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public boolean removeObserver(ConnectionObserver obs) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Set listSaslMechanisms() { - throw new RuntimeException("Not Implemented"); - } - - @Override - public CASValue getAndTouch(final String key, final int exp) { - return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.GetAndTouch) { - @Override - public CASValue execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.getAndTouch(key, exp); - } - - }).getResult(); - } - - @Override - public CASValue getAndTouch(final String key, final int exp, final Transcoder tc) { - return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.GetAndTouch) { - @Override - public CASValue execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.getAndTouch(key, exp ,tc); - } - - }).getResult(); - } - - @Override - public Object get(final String key) { - return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Get) { - @Override - public Object execute(final MemcachedClient client, ConnectionContext state) throws DynoException { - return client.get(key); - } - - }).getResult(); - } - - @Override - public Map getBulk(Collection keys, Transcoder tc) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Map getBulk(Collection keys) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Map getBulk(Transcoder tc, String... keys) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Map getBulk(String... keys) { - throw new RuntimeException("Not Implemented"); - } - - @Override - public Future delete(final String key) { - - return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Delete) { - @Override - public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { - return new DecoratingListenableFuture(client.delete(key)); - } - })); - } - */ + private final String cacheName; + + private final ConnectionPool connPool; + + public DynoMCacheClient(String name, ConnectionPool pool) { + this.cacheName = name; + this.connPool = pool; + } + + private enum OpName { + Add, Append, AsyncCas, AsyncDecr, AsyncGet, AsyncGetAndTouch, AsyncGets, AsyncIncr, Cas, Decr, Delete, + Get, GetAndTouch, GetAsync, GetBulk, Gets, Incr, Prepend, Set, Touch + } + + + private abstract class BaseKeyOperation implements Operation { + + private final String key; + private final OpName op; + private BaseKeyOperation(final String k, final OpName o) { + this.key = k; + this.op = o; + } + @Override public String getName() { + return op.name(); + } + + @Override public String getKey() { + return key; + } + } + + private abstract class BaseAsyncKeyOperation implements AsyncOperation { + + private final String key; + private final OpName op; + private BaseAsyncKeyOperation(final String k, final OpName o) { + this.key = k; + this.op = o; + } + @Override public String getName() { + return op.name(); + } + + @Override public String getKey() { + return key; + } + } + + public String toString() { + return this.cacheName; + } + + public static class Builder { + + private String appName; + private String clusterName; + private ConnectionPoolConfigurationImpl cpConfig; + + public Builder(String name) { + appName = name; + } + + public Builder withDynomiteClusterName(String cluster) { + clusterName = cluster; + return this; + } + + public Builder withConnectionPoolConfig(ConnectionPoolConfigurationImpl config) { + cpConfig = config; + return this; + } + + public DynoMCacheClient build() { + + assert(appName != null); + assert(clusterName != null); + assert(cpConfig != null); + + // TODO: Add conn pool impl for MemcachedClient + throw new RuntimeException("Dyno conn pool for Memcached Client NOT implemented. Coming soon."); + } + + public static Builder withName(String name) { + return new Builder(name); + } + } + + @Override public Collection getAvailableServers() { + throw new RuntimeException("Not Implemented"); + } + + @Override public Collection getUnavailableServers() { + throw new RuntimeException("Not Implemented"); + } + + @Override public Transcoder getTranscoder() { + throw new RuntimeException("Not Implemented"); + } + + @Override public NodeLocator getNodeLocator() { + throw new RuntimeException("Not Implemented"); + } + + @Override public Future append(final long cas, final String key, final Object val) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.append(cas, key, val)); + } + })); + } + + @Override public Future append(final String key, final Object val) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.append(key, val)); + } + })); + } + + @Override public Future append(final long cas, final String key, final T val, final Transcoder tc) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.append(cas, key, val)); + } + })); + } + + @Override public Future append(final String key, final T val, final Transcoder tc) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.append(key, val)); + } + })); + } + + @Override public Future prepend(final long cas, final String key, final Object val) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Prepend) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.prepend(cas, key, val)); + } + })); + } + + @Override public Future prepend(final String key, final Object val) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Prepend) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.prepend(key, val)); + } + })); + } + + @Override public Future prepend(final long cas, final String key, final T val, final Transcoder tc) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Prepend) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.prepend(cas, key, val)); + } + })); + } + + @Override public Future prepend(final String key, final T val, final Transcoder tc) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Prepend) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.prepend(key, val, tc)); + } + })); + } + + @Override public Future asyncCAS(final String key, final long casId, final T value, final Transcoder tc) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncCas) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.asyncCAS(key, casId, value, tc)); + } + })); + } + + @Override public Future asyncCAS(final String key, final long casId, final Object value) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncCas) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.asyncCAS(key, casId, value)); + } + })); + } + + @Override public Future asyncCAS(final String key, final long casId, final int exp, final Object value) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Cas) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.asyncCAS(key, casId, exp, value)); + } + })); + } + + @Override public CASResponse cas(final String key, final long casId, final int exp, final T value, final Transcoder tc) { + + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Cas) { + @Override public CASResponse execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.cas(key, casId, exp, value, tc); + } + + }).getResult(); + } + + @Override public CASResponse cas(final String key, final long casId, final Object value) { + + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Cas) { + @Override public CASResponse execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.cas(key, casId, value); + } + + }).getResult(); + } + + @Override public CASResponse cas(final String key, final long casId, final int exp, final Object value) { + + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Cas) { + @Override public CASResponse execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.cas(key, casId, exp, value); + } + + }).getResult(); + } + + @Override public Future add(final String key, final int exp, final T o, final Transcoder tc) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Add) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.add(key, exp, o)); + } + })); + } + + @Override public Future add(final String key, final int exp, final Object o) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Add) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.add(key, exp, o)); + } + })); + } + + @Override public Future set(final String key, final int exp, final T o, final Transcoder tc) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Set) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.set(key, exp, o, tc)); + } + })); + } + + @Override public Future set(final String key, final int exp, final Object o) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Set) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.set(key, exp, o)); + } + })); + } + + @Override public Future replace(final String key, final int exp, final T o, final Transcoder tc) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.replace(key, exp, o, tc)); + } + })); + } + + @Override public Future replace(final String key, final int exp, final Object o) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.replace(key, exp, o)); + } + })); + } + + @Override public Future asyncGet(final String key, final Transcoder tc) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncGet) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.asyncGet(key, tc)); + } + })); + } + + @Override public Future asyncGet(final String key) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncGet) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.asyncGet(key)); + } + })); + } + + @Override public Future> asyncGetAndTouch(final String key, final int exp) { + + return new DecoratingFuture>(connPool.executeAsync(new BaseAsyncKeyOperation>(key, OpName.AsyncGetAndTouch) { + @Override public ListenableFuture> executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture>(client.asyncGets(key)); + } + })); + } + + @Override public Future> asyncGetAndTouch(final String key, final int exp, final Transcoder tc) { + + return new DecoratingFuture>(connPool.executeAsync(new BaseAsyncKeyOperation>(key, OpName.AsyncGetAndTouch) { + @Override public ListenableFuture> executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture>(client.asyncGetAndTouch(key, exp, tc)); + } + })); + } + + @Override public Future> asyncGets(final String key, final Transcoder tc) { + + return new DecoratingFuture>(connPool.executeAsync(new BaseAsyncKeyOperation>(key, OpName.AsyncGets) { + @Override public ListenableFuture> executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture>(client.asyncGets(key, tc)); + } + })); + } + + @Override public Future> asyncGets(final String key) { + + return new DecoratingFuture>(connPool.executeAsync(new BaseAsyncKeyOperation>(key, OpName.AsyncGets) { + @Override public ListenableFuture> executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture>(client.asyncGets(key)); + } + })); + } + + @Override public CASValue gets(final String key, final Transcoder tc) { + + return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.Gets) { + @Override public CASValue execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.gets(key, tc); + } + + }).getResult(); + } + + @Override public CASValue gets(final String key) { + + return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.Gets) { + @Override public CASValue execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.gets(key); + } + + }).getResult(); + } + + @Override public T get(final String key, final Transcoder tc) { + + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Get) { + @Override public T execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.get(key, tc); + } + + }).getResult(); + } + + @Override public BulkFuture> asyncGetBulk(Iterator keys, Iterator> tcs) { + throw new RuntimeException("Not Implemented"); + } + + @Override public BulkFuture> asyncGetBulk(Collection keys, Iterator> tcs) { + throw new RuntimeException("Not Implemented"); + } + + @Override public BulkFuture> asyncGetBulk(Iterator keys, Transcoder tc) { + throw new RuntimeException("Not Implemented"); + } + + @Override public BulkFuture> asyncGetBulk(Collection keys, Transcoder tc) { + throw new RuntimeException("Not Implemented"); + } + + @Override public BulkFuture> asyncGetBulk(Iterator keys) { + throw new RuntimeException("Not Implemented"); + } + + @Override public BulkFuture> asyncGetBulk(Collection keys) { + throw new RuntimeException("Not Implemented"); + } + + @Override public BulkFuture> asyncGetBulk(Transcoder tc, String... keys) { + throw new RuntimeException("Not Implemented"); + } + + @Override public BulkFuture> asyncGetBulk(String... keys) { + throw new RuntimeException("Not Implemented"); + } + + @Override public Map getBulk(Iterator keys, Transcoder tc) { + throw new RuntimeException("Not Implemented"); + } + + @Override public Map getBulk(Iterator keys) { + throw new RuntimeException("Not Implemented"); + } + + @Override public Future touch(final String key, final int exp, final Transcoder tc) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Touch) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.touch(key, exp, tc)); + } + })); + } + + @Override public Future touch(final String key, final int exp) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Append) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.touch(key, exp)); + } + })); + } + + @Override public Map getVersions() { + throw new RuntimeException("Not Implemented"); + } + + @Override public Map> getStats() { + throw new RuntimeException("Not Implemented"); + } + + @Override public Map> getStats(String prefix) { + throw new RuntimeException("Not Implemented"); + } + + @Override public long incr(final String key, final long by) { + + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Incr) { + @Override public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.incr(key, by); + } + + }).getResult(); + } + + @Override public long incr(final String key, final int by) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Incr) { + @Override public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.incr(key, by); + } + + }).getResult(); + } + + @Override public long decr(final String key, final long by) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Decr) { + @Override public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.decr(key, by); + } + + }).getResult(); + } + + @Override public long decr(final String key, final int by) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Decr) { + @Override public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.decr(key, by); + } + + }).getResult(); + } + + @Override public long incr(final String key, final long by, final long def, final int exp) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Incr) { + @Override public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.incr(key, by, def, exp); + } + + }).getResult(); + } + + @Override public long incr(final String key, final int by, final long def, final int exp) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Incr) { + @Override public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.incr(key, by, def, exp); + } + + }).getResult(); + } + + @Override public long decr(final String key, final long by, final long def, final int exp) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Decr) { + @Override public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.incr(key, by, def, exp); + } + + }).getResult(); + } + + @Override public long decr(final String key, final int by, final long def, final int exp) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Decr) { + @Override public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.incr(key, by, def, exp); + } + + }).getResult(); + } + + @Override public Future asyncIncr(final String key, final long by) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncIncr) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.asyncIncr(key, by)); + } + })); + } + + @Override public Future asyncIncr(final String key, final int by) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncIncr) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.asyncIncr(key, by)); + } + })); + } + + @Override public Future asyncDecr(final String key, final long by) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncDecr) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.asyncDecr(key, by)); + } + })); + } + + @Override public Future asyncDecr(final String key, final int by) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.AsyncDecr) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.asyncDecr(key, by)); + } + })); + } + + @Override public long incr(final String key, final long by, final long def) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Incr) { + @Override public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.incr(key, by, def); + } + + }).getResult(); + } + + @Override public long incr(final String key, final int by, final long def) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Incr) { + @Override public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.incr(key, by, def); + } + + }).getResult(); + } + + @Override public long decr(final String key, final long by, final long def) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Decr) { + @Override public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.decr(key, by, def); + } + + }).getResult(); + } + + @Override public long decr(final String key, final int by, final long def) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Decr) { + @Override public Long execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.decr(key, by, def); + } + + }).getResult(); + } + + @Override public Future delete(final String key, final long cas) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Delete) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.delete(key, cas)); + } + })); + } + + @Override public Future flush(int delay) { + throw new RuntimeException("Not Implemented"); + } + + @Override public Future flush() { + throw new RuntimeException("Not Implemented"); + } + + @Override public void shutdown() { + throw new RuntimeException("Not Implemented"); + } + + @Override public boolean shutdown(long timeout, TimeUnit unit) { + throw new RuntimeException("Not Implemented"); + } + + @Override public boolean waitForQueues(long timeout, TimeUnit unit) { + throw new RuntimeException("Not Implemented"); + } + + @Override public boolean addObserver(ConnectionObserver obs) { + throw new RuntimeException("Not Implemented"); + } + + @Override public boolean removeObserver(ConnectionObserver obs) { + throw new RuntimeException("Not Implemented"); + } + + @Override public Set listSaslMechanisms() { + throw new RuntimeException("Not Implemented"); + } + + @Override public CASValue getAndTouch(final String key, final int exp) { + return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.GetAndTouch) { + @Override public CASValue execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.getAndTouch(key, exp); + } + + }).getResult(); + } + + @Override public CASValue getAndTouch(final String key, final int exp, final Transcoder tc) { + return connPool.executeWithFailover(new BaseKeyOperation>(key, OpName.GetAndTouch) { + @Override public CASValue execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.getAndTouch(key, exp ,tc); + } + + }).getResult(); + } + + @Override public Object get(final String key) { + return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.Get) { + @Override public Object execute(final MemcachedClient client, ConnectionContext state) throws DynoException { + return client.get(key); + } + + }).getResult(); + } + + @Override public Map getBulk(Collection keys, Transcoder tc) { + throw new RuntimeException("Not Implemented"); + } + + @Override public Map getBulk(Collection keys) { + throw new RuntimeException("Not Implemented"); + } + + @Override public Map getBulk(Transcoder tc, String... keys) { + throw new RuntimeException("Not Implemented"); + } + + @Override public Map getBulk(String... keys) { + throw new RuntimeException("Not Implemented"); + } + + @Override public Future delete(final String key) { + + return new DecoratingFuture(connPool.executeAsync(new BaseAsyncKeyOperation(key, OpName.Delete) { + @Override public ListenableFuture executeAsync(MemcachedClient client) throws DynoException { + return new DecoratingListenableFuture(client.delete(key)); + } + })); + } + */ } \ No newline at end of file diff --git a/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoCounter.java b/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoCounter.java index 1bd9dc39..b08cada5 100644 --- a/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoCounter.java +++ b/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoCounter.java @@ -26,9 +26,8 @@ * Callers must invoke {@link #close}. *

    * - * @see {@link AutoCloseable} - * * @author jcacciatore + * @see {@link AutoCloseable} */ public interface DynoCounter extends AutoCloseable { diff --git a/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoJedisBatchCounter.java b/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoJedisBatchCounter.java index 7414ef60..65ae5090 100644 --- a/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoJedisBatchCounter.java +++ b/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoJedisBatchCounter.java @@ -29,8 +29,8 @@ import javax.annotation.concurrent.ThreadSafe; /** - * Batch implementation of {@link DynoCounter} that uses an in-memory counter to - * track {@link #incr()} calls and flushes the value at the given frequency. + * Batch implementation of {@link DynoCounter} that uses an in-memory counter to + * track {@link #incr()} calls and flushes the value at the given frequency. */ @ThreadSafe public class DynoJedisBatchCounter implements DynoCounter { diff --git a/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoJedisCounter.java b/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoJedisCounter.java index 230e413a..c25fe2a1 100644 --- a/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoJedisCounter.java +++ b/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoJedisCounter.java @@ -37,9 +37,8 @@ * Redis's atomic increment functionality. *

    * - * @see {@INCR http://redis.io/commands/INCR} - * * @author jcacciatore + * @see {@INCR http://redis.io/commands/INCR} */ @ThreadSafe public class DynoJedisCounter implements DynoCounter { @@ -74,7 +73,7 @@ public void incrBy(long value) { public Long get() { Long result = 0L; ArrayList values = new ArrayList(generatedKeys.size()); - for (String key: generatedKeys) { + for (String key : generatedKeys) { String val = client.get(key); if (val != null) { result += Long.valueOf(val); diff --git a/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoJedisPipelineCounter.java b/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoJedisPipelineCounter.java index eefa03ac..e46ddad0 100644 --- a/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoJedisPipelineCounter.java +++ b/dyno-recipes/src/main/java/com/netflix/dyno/recipes/counter/DynoJedisPipelineCounter.java @@ -40,9 +40,8 @@ * Note that this implementation is thread-safe whereas {@link DynoJedisPipeline} is not. *

    * - * @see Redis Pipelining - * * @author jcacciatore + * @see Redis Pipelining */ @ThreadSafe public class DynoJedisPipelineCounter extends DynoJedisCounter { @@ -150,7 +149,7 @@ public Consumer(final LinkedBlockingQueue queue, final List key this.queue = queue; this.keys = keys; keysAndPipelines = new ArrayList>(keys.size()); - for (String key: keys) { + for (String key : keys) { keysAndPipelines.add(new Tuple(key, client.pipelined())); } } diff --git a/dyno-recipes/src/main/java/com/netflix/dyno/recipes/json/JsonPath.java b/dyno-recipes/src/main/java/com/netflix/dyno/recipes/json/JsonPath.java index e8a67434..15bf7fbd 100644 --- a/dyno-recipes/src/main/java/com/netflix/dyno/recipes/json/JsonPath.java +++ b/dyno-recipes/src/main/java/com/netflix/dyno/recipes/json/JsonPath.java @@ -23,6 +23,7 @@ public class JsonPath { public JsonPath() { pathBuilder = new StringBuilder(); } + public JsonPath(String path) { pathBuilder = new StringBuilder().append(path); } diff --git a/dyno-recipes/src/main/java/com/netflix/dyno/recipes/util/Tuple.java b/dyno-recipes/src/main/java/com/netflix/dyno/recipes/util/Tuple.java index 9472d9e1..07b6f554 100644 --- a/dyno-recipes/src/main/java/com/netflix/dyno/recipes/util/Tuple.java +++ b/dyno-recipes/src/main/java/com/netflix/dyno/recipes/util/Tuple.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,7 +15,7 @@ */ package com.netflix.dyno.recipes.util; -public class Tuple { +public class Tuple { private final T1 a; private final T2 b; diff --git a/dyno-recipes/src/test/java/com/netflix/dyno/recipes/counter/DistributedCounterTest.java b/dyno-recipes/src/test/java/com/netflix/dyno/recipes/counter/DistributedCounterTest.java index 7f9583fb..b15256ed 100644 --- a/dyno-recipes/src/test/java/com/netflix/dyno/recipes/counter/DistributedCounterTest.java +++ b/dyno-recipes/src/test/java/com/netflix/dyno/recipes/counter/DistributedCounterTest.java @@ -94,7 +94,7 @@ public Long answer(InvocationOnMock invocation) throws Throwable { /** * Test the behavior that finds the key that matches the tokens in the ring - * + *

    * Topology view from dynomite server node *

          *   {
    diff --git a/dyno-redisson/src/main/java/com/netflix/dyno/redisson/DynoRedissonClient.java b/dyno-redisson/src/main/java/com/netflix/dyno/redisson/DynoRedissonClient.java
    index c28afd14..0a4ad145 100644
    --- a/dyno-redisson/src/main/java/com/netflix/dyno/redisson/DynoRedissonClient.java
    +++ b/dyno-redisson/src/main/java/com/netflix/dyno/redisson/DynoRedissonClient.java
    @@ -1,12 +1,12 @@
     /**
      * Copyright 2016 Netflix, Inc.
    - *
    + * 

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -69,10 +69,10 @@ public ListenableFuture executeAsync(RedisAsyncConnection((client.get(key))); } - @Override - public byte[] getBinaryKey() { - return null; - } + @Override + public byte[] getBinaryKey() { + return null; + } }); } @@ -96,10 +96,10 @@ public ListenableFuture executeAsync(RedisAsyncConnection((client.get(key))); } - @Override - public byte[] getBinaryKey() { - return null; - } + @Override + public byte[] getBinaryKey() { + return null; + } }); } @@ -123,13 +123,13 @@ public ListenableFuture executeAsync(RedisAsyncConnection((client.set(key, value))); } - @Override - public byte[] getBinaryKey() { - return null; - } + @Override + public byte[] getBinaryKey() { + return null; + } }); } - + // TODO: hashtag has support for this Redisson API is not complete public Future> set(final String key, final String value, final String hashtag) throws DynoException { @@ -144,17 +144,17 @@ public String getName() { public String getStringKey() { return key; } - + @Override public ListenableFuture executeAsync(RedisAsyncConnection client) throws DynoException { return new DecoratingListenableFuture((client.set(key, value))); } - @Override - public byte[] getBinaryKey() { - return null; - } + @Override + public byte[] getBinaryKey() { + return null; + } }); } diff --git a/dyno-redisson/src/main/java/com/netflix/dyno/redisson/DynoRedissonDemoResource.java b/dyno-redisson/src/main/java/com/netflix/dyno/redisson/DynoRedissonDemoResource.java index f8143ba9..b5e03449 100644 --- a/dyno-redisson/src/main/java/com/netflix/dyno/redisson/DynoRedissonDemoResource.java +++ b/dyno-redisson/src/main/java/com/netflix/dyno/redisson/DynoRedissonDemoResource.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,43 +30,43 @@ @Path("/dyno/demo/redisson") public class DynoRedissonDemoResource { - private static final Logger Logger = LoggerFactory.getLogger(DynoRedissonDemoResource.class); + private static final Logger Logger = LoggerFactory.getLogger(DynoRedissonDemoResource.class); - private static final AtomicReference demo = new AtomicReference(null); - - public DynoRedissonDemoResource() { - } + private static final AtomicReference demo = new AtomicReference(null); - @Path("/start/{threads}/{loop}") - @GET - @Consumes(MediaType.TEXT_PLAIN) - @Produces(MediaType.TEXT_PLAIN) - public String startRedisson(@PathParam("threads") int nThreads, @PathParam("loop") int loop) throws Exception { + public DynoRedissonDemoResource() { + } - Logger.info("Starting redisson demo"); - try { - demo.set(new RedissonDemo(nThreads, loop)); - demo.get().run(); - return "redisson demo!" + "\n"; - } catch (Exception e) { - Logger.error("Error starting datafill", e); - return "redisson demo failed"; - } - } + @Path("/start/{threads}/{loop}") + @GET + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public String startRedisson(@PathParam("threads") int nThreads, @PathParam("loop") int loop) throws Exception { - @Path("/stop") - @GET - @Consumes(MediaType.TEXT_PLAIN) - @Produces(MediaType.TEXT_PLAIN) - public String stopRedisson() throws Exception { + Logger.info("Starting redisson demo"); + try { + demo.set(new RedissonDemo(nThreads, loop)); + demo.get().run(); + return "redisson demo!" + "\n"; + } catch (Exception e) { + Logger.error("Error starting datafill", e); + return "redisson demo failed"; + } + } - Logger.info("stopping redisson demo"); - try { - demo.get().stop(); - return "stop!" + "\n"; - } catch (Exception e) { - Logger.error("Error starting datafill", e); - return "redisson demo failed"; - } - } + @Path("/stop") + @GET + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public String stopRedisson() throws Exception { + + Logger.info("stopping redisson demo"); + try { + demo.get().stop(); + return "stop!" + "\n"; + } catch (Exception e) { + Logger.error("Error starting datafill", e); + return "redisson demo failed"; + } + } } diff --git a/dyno-redisson/src/main/java/com/netflix/dyno/redisson/RedissonConnectionFactory.java b/dyno-redisson/src/main/java/com/netflix/dyno/redisson/RedissonConnectionFactory.java index 4ee7cc9f..14127bb4 100644 --- a/dyno-redisson/src/main/java/com/netflix/dyno/redisson/RedissonConnectionFactory.java +++ b/dyno-redisson/src/main/java/com/netflix/dyno/redisson/RedissonConnectionFactory.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -42,104 +42,104 @@ import com.netflix.dyno.connectionpool.impl.OperationResultImpl; public class RedissonConnectionFactory implements ConnectionFactory> { - - private final EventLoopGroup eventGroupLoop; - private final OperationMonitor opMonitor; - - public RedissonConnectionFactory(EventLoopGroup group, OperationMonitor operationMonitor) { - eventGroupLoop = group; - opMonitor = operationMonitor; - } - - @Override - public Connection> createConnection(HostConnectionPool> pool, ConnectionObservor connectionObservor) throws DynoConnectException, ThrottledException { - return new RedissonConnection(pool, eventGroupLoop, opMonitor); - } - - public static class RedissonConnection implements Connection> { - - private final HostConnectionPool> hostPool; - private final RedisClient client; - private final OperationMonitor opMonitor; - - private RedisAsyncConnection rConn = null; - private final AtomicReference lastEx = new AtomicReference(null); - - private final ConnectionContextImpl context = new ConnectionContextImpl(); - - public RedissonConnection(HostConnectionPool> hPool, EventLoopGroup eventGroupLoop, OperationMonitor opMonitor) { - this.hostPool = hPool; - Host host = hostPool.getHost(); - this.opMonitor = opMonitor; - this.client = new RedisClient(eventGroupLoop, host.getHostAddress(), host.getPort()); - } - - @Override - public OperationResult execute(Operation, R> op) throws DynoException { - try { - R result = op.execute(rConn, null); // Note that connection context is not implemented yet - return new OperationResultImpl(op.getName(), result, opMonitor) - .attempts(1) - .setNode(getHost()); - - } catch (DynoConnectException e) { - lastEx.set(e); - throw e; - } - } - - @Override - public ListenableFuture> executeAsync(AsyncOperation, R> op) throws DynoException { - final long start = System.currentTimeMillis(); - try { - Future future = op.executeAsync(rConn); - return new FutureOperationalResultImpl(op.getName(), future, start, opMonitor).node(getHost()); - - } catch (DynoConnectException e) { - lastEx.set(e); - throw e; - } - } - - @Override - public void close() { - rConn.close(); - client.shutdown(); - } - - @Override - public Host getHost() { - return hostPool.getHost(); - } - - @Override - public void open() throws DynoException { - rConn = client.connectAsync(); - } - - @Override - public DynoConnectException getLastException() { - return lastEx.get(); - } - - @Override - public HostConnectionPool> getParentConnectionPool() { - return hostPool; - } - - @Override - public void execPing() { - try { - rConn.ping().get(); - } catch (InterruptedException e) { - } catch (ExecutionException e) { - throw new DynoConnectException(e); - } - } - - @Override - public ConnectionContext getContext() { - return context; - } - } + + private final EventLoopGroup eventGroupLoop; + private final OperationMonitor opMonitor; + + public RedissonConnectionFactory(EventLoopGroup group, OperationMonitor operationMonitor) { + eventGroupLoop = group; + opMonitor = operationMonitor; + } + + @Override + public Connection> createConnection(HostConnectionPool> pool, ConnectionObservor connectionObservor) throws DynoConnectException, ThrottledException { + return new RedissonConnection(pool, eventGroupLoop, opMonitor); + } + + public static class RedissonConnection implements Connection> { + + private final HostConnectionPool> hostPool; + private final RedisClient client; + private final OperationMonitor opMonitor; + + private RedisAsyncConnection rConn = null; + private final AtomicReference lastEx = new AtomicReference(null); + + private final ConnectionContextImpl context = new ConnectionContextImpl(); + + public RedissonConnection(HostConnectionPool> hPool, EventLoopGroup eventGroupLoop, OperationMonitor opMonitor) { + this.hostPool = hPool; + Host host = hostPool.getHost(); + this.opMonitor = opMonitor; + this.client = new RedisClient(eventGroupLoop, host.getHostAddress(), host.getPort()); + } + + @Override + public OperationResult execute(Operation, R> op) throws DynoException { + try { + R result = op.execute(rConn, null); // Note that connection context is not implemented yet + return new OperationResultImpl(op.getName(), result, opMonitor) + .attempts(1) + .setNode(getHost()); + + } catch (DynoConnectException e) { + lastEx.set(e); + throw e; + } + } + + @Override + public ListenableFuture> executeAsync(AsyncOperation, R> op) throws DynoException { + final long start = System.currentTimeMillis(); + try { + Future future = op.executeAsync(rConn); + return new FutureOperationalResultImpl(op.getName(), future, start, opMonitor).node(getHost()); + + } catch (DynoConnectException e) { + lastEx.set(e); + throw e; + } + } + + @Override + public void close() { + rConn.close(); + client.shutdown(); + } + + @Override + public Host getHost() { + return hostPool.getHost(); + } + + @Override + public void open() throws DynoException { + rConn = client.connectAsync(); + } + + @Override + public DynoConnectException getLastException() { + return lastEx.get(); + } + + @Override + public HostConnectionPool> getParentConnectionPool() { + return hostPool; + } + + @Override + public void execPing() { + try { + rConn.ping().get(); + } catch (InterruptedException e) { + } catch (ExecutionException e) { + throw new DynoConnectException(e); + } + } + + @Override + public ConnectionContext getContext() { + return context; + } + } } diff --git a/dyno-redisson/src/main/java/com/netflix/dyno/redisson/RedissonDemo.java b/dyno-redisson/src/main/java/com/netflix/dyno/redisson/RedissonDemo.java index 3aff4e11..7ca3b7c9 100644 --- a/dyno-redisson/src/main/java/com/netflix/dyno/redisson/RedissonDemo.java +++ b/dyno-redisson/src/main/java/com/netflix/dyno/redisson/RedissonDemo.java @@ -1,12 +1,12 @@ /** * Copyright 2016 Netflix, Inc. - * + *

    * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + *

    + * http://www.apache.org/licenses/LICENSE-2.0 + *

    * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -35,113 +35,113 @@ public class RedissonDemo { - int numThreads = 20; - int eventLoop = 4; - - private final EventLoopGroup eg; - private final ExecutorService threadPool; - private final AtomicBoolean stop; - - RedisClient client = null; - RedisAsyncConnection rConn = null; - - RedissonDemo(int nThreads, int eLoop) { - numThreads = nThreads; - eventLoop = eLoop; - - eg = new NioEventLoopGroup(eventLoop); - threadPool = Executors.newFixedThreadPool(numThreads+1); - stop = new AtomicBoolean(false); - client = new RedisClient(eg, "ec2-54-227-136-137.compute-1.amazonaws.com", 8102); - rConn = client.connectAsync(); - } - - public RedissonDemo(String nThreads, String loop) { - this(Integer.parseInt(nThreads), Integer.parseInt(loop)); - } - - public void run() throws Exception { - - System.out.println("\n\nTHREADS: " + numThreads + " LOOP: " + eventLoop); - - final String value1 = "dcfa7d0973834e5c9f480b65de19d684dcfa7d097383dcfa7d0973834e5c9f480b65de19d684dcfa7d097383dcfa7d0973834e5c9f480b65de19d684dcfa7d097383dcfa7d0973834e5c9f480b65de19d684dcfa7d097383"; - final String StaticValue = value1 + value1 + value1 + value1 + value1; - - try { - - - Future result = rConn.get("testPuneet"); - String s = result.get(); - System.out.println("testPuneet: " + s); + int numThreads = 20; + int eventLoop = 4; + + private final EventLoopGroup eg; + private final ExecutorService threadPool; + private final AtomicBoolean stop; + + RedisClient client = null; + RedisAsyncConnection rConn = null; + + RedissonDemo(int nThreads, int eLoop) { + numThreads = nThreads; + eventLoop = eLoop; + + eg = new NioEventLoopGroup(eventLoop); + threadPool = Executors.newFixedThreadPool(numThreads + 1); + stop = new AtomicBoolean(false); + client = new RedisClient(eg, "ec2-54-227-136-137.compute-1.amazonaws.com", 8102); + rConn = client.connectAsync(); + } + + public RedissonDemo(String nThreads, String loop) { + this(Integer.parseInt(nThreads), Integer.parseInt(loop)); + } + + public void run() throws Exception { + + System.out.println("\n\nTHREADS: " + numThreads + " LOOP: " + eventLoop); + + final String value1 = "dcfa7d0973834e5c9f480b65de19d684dcfa7d097383dcfa7d0973834e5c9f480b65de19d684dcfa7d097383dcfa7d0973834e5c9f480b65de19d684dcfa7d097383dcfa7d0973834e5c9f480b65de19d684dcfa7d097383"; + final String StaticValue = value1 + value1 + value1 + value1 + value1; + + try { + + + Future result = rConn.get("testPuneet"); + String s = result.get(); + System.out.println("testPuneet: " + s); // for (int i=0; i<1000; i++) { // System.out.println(i); // rConn.set("T" + i, StaticValue).get(); // } - - - final RedisAsyncConnection asyncConn = rConn; - - //final CountDownLatch latch = new CountDownLatch(10); - final AtomicInteger total = new AtomicInteger(0); - final AtomicInteger prev = new AtomicInteger(0); - - final List list = new ArrayList(); - for (int i=0; i<10000; i++) { - list.add("T"+i); - } - - final int size = list.size(); - final Random random = new Random(); - - for (int i=0; i() { - - @Override - public Void call() throws Exception { - - while (!stop.get() && !Thread.currentThread().isInterrupted()) { - - int index = random.nextInt(size); - try { - asyncConn.get(list.get(index)).get(1000, TimeUnit.MILLISECONDS); - } catch (Exception e) { - //e.printStackTrace(); - break; - } - total.incrementAndGet(); - } - return null; - } - }); - } - - threadPool.submit(new Callable() { - - @Override - public Void call() throws Exception { - while (!stop.get() && !Thread.currentThread().isInterrupted()) { - try { - int tCount = total.get(); - System.out.println("RPS: " + (tCount - prev.get())/5); - prev.set(tCount); - Thread.sleep(5000); - //asyncConn.ping().get(1000, TimeUnit.MILLISECONDS); - } catch (Exception e) { - //System.out.println("PING FAILURE " + e.getMessage()); - e.printStackTrace(); - break; - } - } - return null; - } - - }); - + + + final RedisAsyncConnection asyncConn = rConn; + + //final CountDownLatch latch = new CountDownLatch(10); + final AtomicInteger total = new AtomicInteger(0); + final AtomicInteger prev = new AtomicInteger(0); + + final List list = new ArrayList(); + for (int i = 0; i < 10000; i++) { + list.add("T" + i); + } + + final int size = list.size(); + final Random random = new Random(); + + for (int i = 0; i < numThreads; i++) { + threadPool.submit(new Callable() { + + @Override + public Void call() throws Exception { + + while (!stop.get() && !Thread.currentThread().isInterrupted()) { + + int index = random.nextInt(size); + try { + asyncConn.get(list.get(index)).get(1000, TimeUnit.MILLISECONDS); + } catch (Exception e) { + //e.printStackTrace(); + break; + } + total.incrementAndGet(); + } + return null; + } + }); + } + + threadPool.submit(new Callable() { + + @Override + public Void call() throws Exception { + while (!stop.get() && !Thread.currentThread().isInterrupted()) { + try { + int tCount = total.get(); + System.out.println("RPS: " + (tCount - prev.get()) / 5); + prev.set(tCount); + Thread.sleep(5000); + //asyncConn.ping().get(1000, TimeUnit.MILLISECONDS); + } catch (Exception e) { + //System.out.println("PING FAILURE " + e.getMessage()); + e.printStackTrace(); + break; + } + } + return null; + } + + }); + // Thread.sleep(1000*300); // threadPool.shutdownNow(); - - } finally { + + } finally { // if (rConn != null) { // rConn.close(); // } @@ -149,39 +149,39 @@ public Void call() throws Exception { // client.shutdown(); // } // eg.shutdownGracefully().get(); - } - - } - - public void stop() { - stop.set(true); - threadPool.shutdownNow(); - - if (rConn != null) { - rConn.close(); - } - if (client != null) { - client.shutdown(); - } - try { - eg.shutdownGracefully().get(); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ExecutionException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - - public static void main(String[] args) { - - RedissonDemo demo = new RedissonDemo(10, 2); - try { - demo.run(); - } catch (Exception e) { - e.printStackTrace(); - } - } + } + + } + + public void stop() { + stop.set(true); + threadPool.shutdownNow(); + + if (rConn != null) { + rConn.close(); + } + if (client != null) { + client.shutdown(); + } + try { + eg.shutdownGracefully().get(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + public static void main(String[] args) { + + RedissonDemo demo = new RedissonDemo(10, 2); + try { + demo.run(); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/settings.gradle b/settings.gradle index 56043eba..496d0990 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,2 @@ -rootProject.name='dyno' +rootProject.name = 'dyno' include 'dyno-core', 'dyno-contrib', 'dyno-memcache', 'dyno-jedis', 'dyno-client', 'dyno-redisson', 'dyno-demo', 'dyno-recipes'