You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by st...@apache.org on 2020/05/19 06:54:45 UTC
[phoenix-queryserver] branch master updated: PHOENIX-5826 Remove
guava from queryserver
This is an automated email from the ASF dual-hosted git repository.
stoty pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/phoenix-queryserver.git
The following commit(s) were added to refs/heads/master by this push:
new baa8132 PHOENIX-5826 Remove guava from queryserver
baa8132 is described below
commit baa8132675eeaab7a573cdba0b856761b8cb5d64
Author: Istvan Toth <st...@apache.org>
AuthorDate: Thu May 14 16:34:01 2020 +0200
PHOENIX-5826 Remove guava from queryserver
Closes #33
---
load-balancer/pom.xml | 4 -
.../phoenix/end2end/LoadBalancerEnd2EndIT.java | 2 +-
.../service/LoadBalanceZookeeperConfImpl.java | 5 +-
.../phoenix/loadbalancer/service/LoadBalancer.java | 21 +-
.../queryserver/register/ZookeeperRegistry.java | 2 +-
pom.xml | 8 +-
queryserver-it/pom.xml | 5 -
.../phoenix/end2end/QueryServerEnvironment.java | 10 +-
.../phoenix/end2end/QueryServerTestUtil.java | 4 +-
.../end2end/SecureQueryServerPhoenixDBIT.java | 10 +-
queryserver-orchestrator/pom.xml | 4 -
.../tool/ParameterizedPhoenixCanaryToolIT.java | 5 +-
.../orchestrator/TestExecutorClient.java | 3 +-
.../queryserver/orchestrator/ToolWrapper.java | 3 +-
.../org/apache/phoenix/tool/PhoenixCanaryTool.java | 41 ++-
queryserver/pom.xml | 4 +-
.../service/LoadBalanceZookeeperConf.java | 2 +-
.../queryserver/server/PhoenixMetaFactoryImpl.java | 17 +-
.../phoenix/queryserver/server/QueryServer.java | 81 +++---
.../java/org/apache/phoenix/util/HostAndPort.java | 287 +++++++++++++++++++++
.../org/apache/phoenix/util/InstanceResolver.java | 4 +-
.../org/apache/phoenix/util/SimpleLRUCache.java | 96 +++++++
.../queryserver/util/SimpleLRUCacheTest.java | 58 +++++
23 files changed, 551 insertions(+), 125 deletions(-)
diff --git a/load-balancer/pom.xml b/load-balancer/pom.xml
index c0e01dc..70e072a 100644
--- a/load-balancer/pom.xml
+++ b/load-balancer/pom.xml
@@ -120,10 +120,6 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
<!-- for tests -->
<dependency>
diff --git a/load-balancer/src/it/java/org/apache/phoenix/end2end/LoadBalancerEnd2EndIT.java b/load-balancer/src/it/java/org/apache/phoenix/end2end/LoadBalancerEnd2EndIT.java
index 448c28f..16471a7 100644
--- a/load-balancer/src/it/java/org/apache/phoenix/end2end/LoadBalancerEnd2EndIT.java
+++ b/load-balancer/src/it/java/org/apache/phoenix/end2end/LoadBalancerEnd2EndIT.java
@@ -18,7 +18,6 @@
*/
package org.apache.phoenix.end2end;
-import com.google.common.net.HostAndPort;
import org.apache.curator.CuratorZookeeperClient;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
@@ -30,6 +29,7 @@ import org.apache.phoenix.loadbalancer.service.LoadBalanceZookeeperConf;
import org.apache.phoenix.loadbalancer.service.LoadBalanceZookeeperConfImpl;
import org.apache.phoenix.queryserver.register.Registry;
import org.apache.phoenix.queryserver.register.ZookeeperRegistry;
+import org.apache.phoenix.util.HostAndPort;
import org.apache.zookeeper.KeeperException;
import org.junit.*;
import org.slf4j.Logger;
diff --git a/load-balancer/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalanceZookeeperConfImpl.java b/load-balancer/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalanceZookeeperConfImpl.java
index 17294cb..4aacc08 100644
--- a/load-balancer/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalanceZookeeperConfImpl.java
+++ b/load-balancer/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalanceZookeeperConfImpl.java
@@ -19,13 +19,12 @@
package org.apache.phoenix.loadbalancer.service;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.net.HostAndPort;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.zookeeper.ZKConfig;
import org.apache.phoenix.queryserver.QueryServerOptions;
import org.apache.phoenix.queryserver.QueryServerProperties;
+import org.apache.phoenix.util.HostAndPort;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
@@ -47,7 +46,7 @@ public class LoadBalanceZookeeperConfImpl implements LoadBalanceZookeeperConf {
this.configuration = configuration;
}
- @VisibleForTesting
+ //@VisibleForTesting
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
}
diff --git a/load-balancer/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalancer.java b/load-balancer/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalancer.java
index 9bcf2d4..4cfd1a4 100644
--- a/load-balancer/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalancer.java
+++ b/load-balancer/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalancer.java
@@ -18,9 +18,6 @@
*/
package org.apache.phoenix.loadbalancer.service;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.net.HostAndPort;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.UnhandledErrorListener;
@@ -30,6 +27,7 @@ import org.apache.curator.framework.state.ConnectionStateListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.utils.CloseableUtils;
import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.phoenix.util.HostAndPort;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -54,7 +52,7 @@ public class LoadBalancer {
private static final LoadBalancer loadBalancer = new LoadBalancer();
private ConnectionStateListener connectionStateListener = null;
private UnhandledErrorListener unhandledErrorListener = null;
- private List<Closeable> closeAbles = Lists.newArrayList();
+ private List<Closeable> closeAbles = new ArrayList<>();
private LoadBalancer() {
try {
@@ -87,11 +85,11 @@ public class LoadBalancer {
/**
* It returns the location of Phoenix Query Server
- * in form of Guava <a href="https://google.github.io/guava/releases/19.0/api/docs/com/google/common/net/HostAndPort.html">HostAndPort</a>
+ * in form of a HostAndPort (copied from Guava)
* from the cache. The client should catch Exception incase
* the method is unable to fetch PQS location due to network failure or
* in-correct configuration issues.
- * @return - return Guava HostAndPort. See <a href="http://google.com">http://google.com</a>
+ * @return - return HostAndPort
* @throws Exception
*/
public HostAndPort getSingleServiceLocation() throws Exception{
@@ -103,7 +101,7 @@ public class LoadBalancer {
/**
* return locations of all Phoenix Query Servers
- * in the form of a List of PQS servers <a href="https://google.github.io/guava/releases/19.0/api/docs/com/google/common/net/HostAndPort.html">HostAndPort</a>
+ * in the form of a List of PQS servers
* @return - HostAndPort
* @throws Exception
*/
@@ -112,9 +110,12 @@ public class LoadBalancer {
}
private List<HostAndPort> conductSanityCheckAndReturn() throws Exception{
- Preconditions.checkNotNull(curaFramework
- ," curator framework in not initialized ");
- Preconditions.checkNotNull(cache," cache value is not initialized");
+ if (curaFramework == null) {
+ throw new NullPointerException(String.valueOf(" curator framework in not initialized "));
+ }
+ if (cache == null) {
+ throw new NullPointerException(String.valueOf(" cache value is not initialized"));
+ }
boolean connected = curaFramework.getZookeeperClient().isConnected();
if (!connected) {
String message = " Zookeeper seems to be down. The data is stale ";
diff --git a/load-balancer/src/main/java/org/apache/phoenix/queryserver/register/ZookeeperRegistry.java b/load-balancer/src/main/java/org/apache/phoenix/queryserver/register/ZookeeperRegistry.java
index 7159e14..974be31 100644
--- a/load-balancer/src/main/java/org/apache/phoenix/queryserver/register/ZookeeperRegistry.java
+++ b/load-balancer/src/main/java/org/apache/phoenix/queryserver/register/ZookeeperRegistry.java
@@ -19,12 +19,12 @@
package org.apache.phoenix.queryserver.register;
-import com.google.common.net.HostAndPort;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.utils.CloseableUtils;
import org.apache.phoenix.loadbalancer.service.LoadBalanceZookeeperConf;
+import org.apache.phoenix.util.HostAndPort;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
diff --git a/pom.xml b/pom.xml
index 94258a1..274f522 100644
--- a/pom.xml
+++ b/pom.xml
@@ -79,7 +79,6 @@
<curator.version>2.12.0</curator.version>
<gson.version>2.2.4</gson.version>
- <guava.version>13.0.1</guava.version>
<jetty.version>9.4.27.v20200227</jetty.version>
<commons-io.version>2.5</commons-io.version>
<commons-collections.version>3.2.2</commons-collections.version>
@@ -87,6 +86,7 @@
<slf4j.version>1.7.30</slf4j.version>
<avatica.version>1.16.0</avatica.version>
<servlet.api.version>3.1.0</servlet.api.version>
+ <jsr305.version>3.0.0</jsr305.version>
<!-- Test Dependency versions -->
<mockito-all.version>1.8.5</mockito-all.version>
@@ -409,9 +409,9 @@
<version>${gson.version}</version>
</dependency>
<dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <version>${guava.version}</version>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ <version>${jsr305.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
diff --git a/queryserver-it/pom.xml b/queryserver-it/pom.xml
index fac2c54..e660c71 100644
--- a/queryserver-it/pom.xml
+++ b/queryserver-it/pom.xml
@@ -208,10 +208,5 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <scope>test</scope>
- </dependency>
</dependencies>
</project>
diff --git a/queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerEnvironment.java b/queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerEnvironment.java
index 17c8856..0d1c55f 100644
--- a/queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerEnvironment.java
+++ b/queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerEnvironment.java
@@ -18,6 +18,7 @@ import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.security.PrivilegedAction;
+import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -48,9 +49,6 @@ import org.apache.phoenix.util.ThinClientUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-
/**
* Due to this bug https://bugzilla.redhat.com/show_bug.cgi?id=668830 We need to use
* `localhost.localdomain` as host name when running these tests on Jenkins (Centos) but for Mac OS
@@ -151,8 +149,10 @@ public class QueryServerEnvironment {
}
public Map.Entry<String, File> getUser(int offset) {
- Preconditions.checkArgument(offset > 0 && offset <= NUM_CREATED_USERS);
- return Maps.immutableEntry("user" + offset, USER_KEYTAB_FILES.get(offset - 1));
+ if (!(offset > 0 && offset <= NUM_CREATED_USERS)) {
+ throw new IllegalArgumentException();
+ }
+ return new AbstractMap.SimpleImmutableEntry<String, File>("user" + offset, USER_KEYTAB_FILES.get(offset - 1));
}
/**
diff --git a/queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerTestUtil.java b/queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerTestUtil.java
index e599c26..92977a0 100644
--- a/queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerTestUtil.java
+++ b/queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerTestUtil.java
@@ -37,8 +37,6 @@ import org.apache.phoenix.util.ThinClientUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Strings;
-
public class QueryServerTestUtil {
private static final Logger LOG = LoggerFactory.getLogger(QueryServerTestUtil.class);
@@ -101,7 +99,7 @@ public class QueryServerTestUtil {
public void startQueryServer() throws Exception {
setupQueryServerConfiguration(conf);
executor = Executors.newSingleThreadExecutor();
- if (!Strings.isNullOrEmpty(principal) && null != keytab) {
+ if (principal != null && !principal.isEmpty() && null != keytab) {
// Get the PQS ident for PQS to use
final UserGroupInformation ugi = UserGroupInformation
.loginUserFromKeytabAndReturnUGI(principal, keytab.getAbsolutePath());
diff --git a/queryserver-it/src/it/java/org/apache/phoenix/end2end/SecureQueryServerPhoenixDBIT.java b/queryserver-it/src/it/java/org/apache/phoenix/end2end/SecureQueryServerPhoenixDBIT.java
index b054105..495e5db 100644
--- a/queryserver-it/src/it/java/org/apache/phoenix/end2end/SecureQueryServerPhoenixDBIT.java
+++ b/queryserver-it/src/it/java/org/apache/phoenix/end2end/SecureQueryServerPhoenixDBIT.java
@@ -31,6 +31,7 @@ import java.io.Writer;
import java.lang.reflect.Field;
import java.nio.file.Paths;
import java.security.PrivilegedAction;
+import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -71,9 +72,6 @@ import org.junit.experimental.categories.Category;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-
/**
* This integration test stands up a secured PQS and runs Python code against it. See supporting
* files in phoenix-queryserver/src/it/bin.
@@ -134,8 +132,10 @@ public class SecureQueryServerPhoenixDBIT {
}
private static Entry<String,File> getUser(int offset) {
- Preconditions.checkArgument(offset > 0 && offset <= NUM_CREATED_USERS);
- return Maps.immutableEntry("user" + offset, USER_KEYTAB_FILES.get(offset - 1));
+ if (!(offset > 0 && offset <= NUM_CREATED_USERS)) {
+ throw new IllegalArgumentException();
+ }
+ return new AbstractMap.SimpleImmutableEntry<String,File>("user" + offset, USER_KEYTAB_FILES.get(offset - 1));
}
/**
diff --git a/queryserver-orchestrator/pom.xml b/queryserver-orchestrator/pom.xml
index 852b010..5a3dbff 100644
--- a/queryserver-orchestrator/pom.xml
+++ b/queryserver-orchestrator/pom.xml
@@ -87,10 +87,6 @@
<artifactId>hadoop-common</artifactId>
</dependency>
<dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- <dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
diff --git a/queryserver-orchestrator/src/it/java/org/apache/phoenix/tool/ParameterizedPhoenixCanaryToolIT.java b/queryserver-orchestrator/src/it/java/org/apache/phoenix/tool/ParameterizedPhoenixCanaryToolIT.java
index 815cf67..7b7c02d 100644
--- a/queryserver-orchestrator/src/it/java/org/apache/phoenix/tool/ParameterizedPhoenixCanaryToolIT.java
+++ b/queryserver-orchestrator/src/it/java/org/apache/phoenix/tool/ParameterizedPhoenixCanaryToolIT.java
@@ -17,7 +17,6 @@
*/
package org.apache.phoenix.tool;
-import com.google.common.collect.Maps;
import com.google.gson.Gson;
import org.apache.phoenix.end2end.NeedsOwnMiniClusterTest;
@@ -65,8 +64,8 @@ public class ParameterizedPhoenixCanaryToolIT extends BaseTest {
private static final String fileOutSink
= "org.apache.phoenix.tool.PhoenixCanaryTool$FileOutSink";
- private static Map<String, String> serverProps = Maps.newHashMapWithExpectedSize(2);
- private static Map<String, String> clientProps = Maps.newHashMapWithExpectedSize(2);
+ private static Map<String, String> serverProps = new HashMap<>(2);
+ private static Map<String, String> clientProps = new HashMap<>(2);
private static String connString = "";
private static Properties canaryProp = new Properties();
private static Connection connection = null;
diff --git a/queryserver-orchestrator/src/main/java/org/apache/phoenix/queryserver/orchestrator/TestExecutorClient.java b/queryserver-orchestrator/src/main/java/org/apache/phoenix/queryserver/orchestrator/TestExecutorClient.java
index d252ed2..22a8682 100644
--- a/queryserver-orchestrator/src/main/java/org/apache/phoenix/queryserver/orchestrator/TestExecutorClient.java
+++ b/queryserver-orchestrator/src/main/java/org/apache/phoenix/queryserver/orchestrator/TestExecutorClient.java
@@ -18,7 +18,6 @@
*/
package org.apache.phoenix.queryserver.orchestrator;
-import com.google.common.annotations.VisibleForTesting;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.leader.CancelLeadershipException;
import org.apache.curator.framework.recipes.leader.LeaderSelector;
@@ -110,7 +109,7 @@ public class TestExecutorClient extends LeaderSelectorListenerAdapter implements
}
}
- @VisibleForTesting
+ //@VisibleForTesting
public void executeQueryServerCanaryTool() {
List<String> cmd = new ArrayList<>();
for (Map.Entry<String, String> entry : params.entrySet()) {
diff --git a/queryserver-orchestrator/src/main/java/org/apache/phoenix/queryserver/orchestrator/ToolWrapper.java b/queryserver-orchestrator/src/main/java/org/apache/phoenix/queryserver/orchestrator/ToolWrapper.java
index 62e00a4..01f9dfc 100644
--- a/queryserver-orchestrator/src/main/java/org/apache/phoenix/queryserver/orchestrator/ToolWrapper.java
+++ b/queryserver-orchestrator/src/main/java/org/apache/phoenix/queryserver/orchestrator/ToolWrapper.java
@@ -18,7 +18,6 @@
*/
package org.apache.phoenix.queryserver.orchestrator;
-import com.google.common.base.Joiner;
import org.apache.phoenix.tool.PhoenixCanaryTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +36,7 @@ public class ToolWrapper {
LOGGER.error("Bad argument list passed to executeMain. Skipping QueryServerCanaryTool.");
return;
}
- LOGGER.info("Passing args to QueryServerCanaryTool: " + Joiner.on(",").join(args));
+ LOGGER.info("Passing args to QueryServerCanaryTool: " + String.join(",",args));
PhoenixCanaryTool.main(args);
}
}
diff --git a/queryserver-orchestrator/src/main/java/org/apache/phoenix/tool/PhoenixCanaryTool.java b/queryserver-orchestrator/src/main/java/org/apache/phoenix/tool/PhoenixCanaryTool.java
index a008799..5d346f4 100644
--- a/queryserver-orchestrator/src/main/java/org/apache/phoenix/tool/PhoenixCanaryTool.java
+++ b/queryserver-orchestrator/src/main/java/org/apache/phoenix/tool/PhoenixCanaryTool.java
@@ -17,15 +17,13 @@
*/
package org.apache.phoenix.tool;
-import com.google.common.base.Throwables;
-import com.google.common.io.Files;
-import com.google.common.util.concurrent.SimpleTimeLimiter;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;
+
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.RetryCounter;
@@ -35,7 +33,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
@@ -48,7 +49,11 @@ import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* A Canary Tool to perform synthetic tests for Phoenix
@@ -99,7 +104,7 @@ public class PhoenixCanaryTool extends Configured implements Tool {
result.setMessage("Test " + result.getTestName() + " successful");
} catch (Exception e) {
result.setSuccessful(false);
- result.setMessage(Throwables.getStackTraceAsString(e));
+ result.setMessage(getStackTrace(e));
} finally {
onExit();
}
@@ -226,7 +231,9 @@ public class PhoenixCanaryTool extends Configured implements Tool {
String fileName = logfileName + "-" + new SimpleDateFormat("yyyy.MM.dd.HH" + ".mm" +
".ss").format(new Date()) + ".log";
File file = new File(dir, fileName);
- Files.write(Bytes.toBytes(resultJson), file);
+ try (FileOutputStream fos = new FileOutputStream(file)) {
+ fos.write(Bytes.toBytes(resultJson));
+ }
}
@Override
@@ -330,9 +337,8 @@ public class PhoenixCanaryTool extends Configured implements Tool {
LOGGER.error("Failed to get connection after multiple retries; the connection is null");
}
- SimpleTimeLimiter limiter = new SimpleTimeLimiter();
-
- limiter.callWithTimeout(new Callable<Void>() {
+ ExecutorService executor = Executors.newFixedThreadPool(1);
+ Future<Void> future = executor.submit(new Callable<Void>() {
public Void call() {
@@ -347,16 +353,22 @@ public class PhoenixCanaryTool extends Configured implements Tool {
return null;
}
- }, timeoutVal, TimeUnit.SECONDS, true);
+ });
+ try {
+ future.get(timeoutVal, TimeUnit.SECONDS);
+ } catch (InterruptedException|TimeoutException e) {
+ future.cancel(true);
+ throw e;
+ }
long estimatedTime = System.currentTimeMillis() - startTime;
appInfo.setExecutionTime(estimatedTime);
appInfo.setSuccessful(true);
} catch (Exception e) {
- LOGGER.error(Throwables.getStackTraceAsString(e));
- appInfo.setMessage(Throwables.getStackTraceAsString(e));
+ LOGGER.error("error running tests", e);
+ appInfo.setMessage(getStackTrace(e));
appInfo.setSuccessful(false);
} finally {
@@ -368,6 +380,13 @@ public class PhoenixCanaryTool extends Configured implements Tool {
return 0;
}
+ private static String getStackTrace(Throwable t) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ t.printStackTrace(pw);
+ return sw.toString();
+ }
+
private Connection getConnectionWithRetry(String connectionURL) {
Connection connection=null;
try{
diff --git a/queryserver/pom.xml b/queryserver/pom.xml
index ba0d2c3..b0e7024 100644
--- a/queryserver/pom.xml
+++ b/queryserver/pom.xml
@@ -214,8 +214,8 @@
<artifactId>commons-collections</artifactId>
</dependency>
<dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
</dependency>
<!-- for tests -->
diff --git a/queryserver/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalanceZookeeperConf.java b/queryserver/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalanceZookeeperConf.java
index afce5be..383c20a 100644
--- a/queryserver/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalanceZookeeperConf.java
+++ b/queryserver/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalanceZookeeperConf.java
@@ -18,7 +18,7 @@
*/
package org.apache.phoenix.loadbalancer.service;
-import com.google.common.net.HostAndPort;
+import org.apache.phoenix.util.HostAndPort;
import org.apache.zookeeper.data.ACL;
import java.util.List;
diff --git a/queryserver/src/main/java/org/apache/phoenix/queryserver/server/PhoenixMetaFactoryImpl.java b/queryserver/src/main/java/org/apache/phoenix/queryserver/server/PhoenixMetaFactoryImpl.java
index 88c577f..bc41a77 100644
--- a/queryserver/src/main/java/org/apache/phoenix/queryserver/server/PhoenixMetaFactoryImpl.java
+++ b/queryserver/src/main/java/org/apache/phoenix/queryserver/server/PhoenixMetaFactoryImpl.java
@@ -31,8 +31,6 @@ import org.apache.hadoop.hbase.HConstants;
import org.apache.phoenix.queryserver.QueryServerOptions;
import org.apache.phoenix.queryserver.QueryServerProperties;
-import com.google.common.base.Preconditions;
-
/**
* Bridge between Phoenix and Avatica.
*/
@@ -51,7 +49,10 @@ public class PhoenixMetaFactoryImpl extends Configured implements PhoenixMetaFac
@Override
public Meta create(List<String> args) {
- Configuration conf = Preconditions.checkNotNull(getConf(), "Configuration must not be null.");
+ Configuration conf = getConf();
+ if (conf == null) {
+ throw new NullPointerException(String.valueOf("Configuration must not be null."));
+ }
Properties info = new Properties();
info.putAll(conf.getValByRegex("avatica.*"));
try {
@@ -110,7 +111,9 @@ public class PhoenixMetaFactoryImpl extends Configured implements PhoenixMetaFac
private int getInt(String key, int defaultValue, Properties props, Configuration conf) {
if (conf == null) {
- Preconditions.checkNotNull(props);
+ if (props == null) {
+ throw new NullPointerException();
+ }
return Integer.parseInt(props.getProperty(key, String.valueOf(defaultValue)));
}
return conf.getInt(key, defaultValue);
@@ -118,8 +121,10 @@ public class PhoenixMetaFactoryImpl extends Configured implements PhoenixMetaFac
private String getString(String key, String defaultValue, Properties props, Configuration conf) {
if (conf == null) {
- Preconditions.checkNotNull(props);
- return props.getProperty(key, defaultValue);
+ if (props == null) {
+ throw new NullPointerException();
+ }
+ return props.getProperty(key, defaultValue);
}
return conf.get(key, defaultValue);
}
diff --git a/queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java b/queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java
index 1b29415..b50a44f 100644
--- a/queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java
+++ b/queryserver/src/main/java/org/apache/phoenix/queryserver/server/QueryServer.java
@@ -17,12 +17,6 @@
*/
package org.apache.phoenix.queryserver.server;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-
import org.apache.calcite.avatica.Meta;
import org.apache.calcite.avatica.remote.Driver;
import org.apache.calcite.avatica.remote.LocalService;
@@ -53,6 +47,7 @@ import org.apache.phoenix.queryserver.QueryServerOptions;
import org.apache.phoenix.queryserver.QueryServerProperties;
import org.apache.phoenix.queryserver.register.Registry;
import org.apache.phoenix.util.InstanceResolver;
+import org.apache.phoenix.util.SimpleLRUCache;
import org.eclipse.jetty.server.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -156,7 +151,7 @@ public final class QueryServer extends Configured implements Tool, Runnable {
/**
* @return the port number this instance is bound to, or {@code -1} if the server is not running.
*/
- @VisibleForTesting
+ //@VisibleForTesting
public int getPort() {
if (server == null) return -1;
return server.getPort();
@@ -165,7 +160,7 @@ public final class QueryServer extends Configured implements Tool, Runnable {
/**
* @return the return code from running as a {@link Tool}.
*/
- @VisibleForTesting
+ //@VisibleForTesting
public int getRetCode() {
return retCode;
}
@@ -173,7 +168,7 @@ public final class QueryServer extends Configured implements Tool, Runnable {
/**
* @return the throwable from an unsuccessful run, or null otherwise.
*/
- @VisibleForTesting
+ //@VisibleForTesting
public Throwable getThrowable() {
return t;
}
@@ -295,7 +290,7 @@ public final class QueryServer extends Configured implements Tool, Runnable {
}
}
-@VisibleForTesting
+ //@VisibleForTesting
void configureClientAuthentication(final HttpServer.Builder builder, boolean disableSpnego, UserGroupInformation ugi) throws IOException {
// Enable SPNEGO for client authentication unless it's explicitly disabled
@@ -305,7 +300,7 @@ public final class QueryServer extends Configured implements Tool, Runnable {
configureCallBack(builder, ugi);
}
- @VisibleForTesting
+ //@VisibleForTesting
void configureSpnegoAuthentication(HttpServer.Builder builder, UserGroupInformation ugi) throws IOException {
String keytabPath = getConf().get(QueryServerProperties.QUERY_SERVER_KEYTAB_FILENAME_ATTRIB);
File keytab = new File(keytabPath);
@@ -350,7 +345,7 @@ public final class QueryServer extends Configured implements Tool, Runnable {
return SecurityUtil.getServerPrincipal(httpPrincipal, hostname);
}
- @VisibleForTesting
+ //@VisibleForTesting
UserGroupInformation getUserGroupInformation() throws IOException {
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
LOG.debug("Current user is " + ugi);
@@ -361,7 +356,7 @@ public final class QueryServer extends Configured implements Tool, Runnable {
return ugi;
}
- @VisibleForTesting
+ //@VisibleForTesting
void configureCallBack(HttpServer.Builder<Server> builder, UserGroupInformation ugi) {
builder.withImpersonation(new PhoenixDoAsCallback(ugi, getConf()));
}
@@ -386,9 +381,14 @@ public final class QueryServer extends Configured implements Tool, Runnable {
boolean success = true ;
try {
LoadBalanceZookeeperConf loadBalanceConfiguration = getLoadBalanceConfiguration();
- Preconditions.checkNotNull(loadBalanceConfiguration);
+ if (loadBalanceConfiguration == null) {
+ throw new NullPointerException();
+ }
this.registry = getRegistry();
- Preconditions.checkNotNull(registry);
+
+ if (registry == null) {
+ throw new NullPointerException();
+ }
String zkConnectString = loadBalanceConfiguration.getZkConnectString();
this.registry.registerServer(loadBalanceConfiguration, getPort(), zkConnectString, hostName);
} catch(Throwable ex){
@@ -464,7 +464,7 @@ public final class QueryServer extends Configured implements Tool, Runnable {
}
// add remoteUserExtractor to builder if enabled
- @VisibleForTesting
+ //@VisibleForTesting
public void setRemoteUserExtractorIfNecessary(HttpServer.Builder builder, Configuration conf) {
if (conf.getBoolean(QueryServerProperties.QUERY_SERVER_WITH_REMOTEUSEREXTRACTOR_ATTRIB,
QueryServerOptions.DEFAULT_QUERY_SERVER_WITH_REMOTEUSEREXTRACTOR)) {
@@ -472,7 +472,7 @@ public final class QueryServer extends Configured implements Tool, Runnable {
}
}
- @VisibleForTesting
+ //@VisibleForTesting
public void enableServerCustomizersIfNecessary(HttpServer.Builder<Server> builder,
Configuration conf, AvaticaServerConfiguration avaticaServerConfiguration) {
// Always try to enable the "provided" ServerCustomizers. The expectation is that the Factory implementation
@@ -483,7 +483,7 @@ public final class QueryServer extends Configured implements Tool, Runnable {
}
}
- @VisibleForTesting
+ //@VisibleForTesting
public AvaticaServerConfiguration enableCustomAuth(HttpServer.Builder<Server> builder,
Configuration conf, UserGroupInformation ugi) {
AvaticaServerConfiguration avaticaServerConfiguration = createAvaticaServerConfig(conf, ugi);
@@ -500,21 +500,21 @@ public final class QueryServer extends Configured implements Tool, Runnable {
private static final AvaticaServerConfigurationFactory DEFAULT_SERVER_CONFIG =
new AvaticaServerConfigurationFactory.AvaticaServerConfigurationFactoryImpl();
- @VisibleForTesting
+ //@VisibleForTesting
RemoteUserExtractor createRemoteUserExtractor(Configuration conf) {
RemoteUserExtractorFactory factory =
InstanceResolver.getSingleton(RemoteUserExtractorFactory.class, DEFAULT_USER_EXTRACTOR);
return factory.createRemoteUserExtractor(conf);
}
- @VisibleForTesting
+ //@VisibleForTesting
List<ServerCustomizer<Server>> createServerCustomizers(Configuration conf, AvaticaServerConfiguration avaticaServerConfiguration) {
ServerCustomizersFactory factory =
InstanceResolver.getSingleton(ServerCustomizersFactory.class, DEFAULT_SERVER_CUSTOMIZERS);
return factory.createServerCustomizers(conf, avaticaServerConfiguration);
}
- @VisibleForTesting
+ //@VisibleForTesting
AvaticaServerConfiguration createAvaticaServerConfig(Configuration conf, UserGroupInformation ugi) {
AvaticaServerConfigurationFactory factory =
InstanceResolver.getSingleton(AvaticaServerConfigurationFactory.class, DEFAULT_SERVER_CONFIG);
@@ -566,18 +566,15 @@ public final class QueryServer extends Configured implements Tool, Runnable {
*/
public static class PhoenixDoAsCallback implements DoAsRemoteUserCallback {
private final UserGroupInformation serverUgi;
- private final LoadingCache<String,UserGroupInformation> ugiCache;
+ private final SimpleLRUCache<String,UserGroupInformation> ugiCache;
public PhoenixDoAsCallback(UserGroupInformation serverUgi, Configuration conf) {
this.serverUgi = Objects.requireNonNull(serverUgi);
- this.ugiCache = CacheBuilder.newBuilder()
- .initialCapacity(conf.getInt(QueryServerProperties.QUERY_SERVER_UGI_CACHE_INITIAL_SIZE,
- QueryServerOptions.DEFAULT_QUERY_SERVER_UGI_CACHE_INITIAL_SIZE))
- .concurrencyLevel(conf.getInt(QueryServerProperties.QUERY_SERVER_UGI_CACHE_CONCURRENCY,
- QueryServerOptions.DEFAULT_QUERY_SERVER_UGI_CACHE_CONCURRENCY))
- .maximumSize(conf.getLong(QueryServerProperties.QUERY_SERVER_UGI_CACHE_MAX_SIZE,
- QueryServerOptions.DEFAULT_QUERY_SERVER_UGI_CACHE_MAX_SIZE))
- .build(new UgiCacheLoader(this.serverUgi));
+ this.ugiCache = new SimpleLRUCache<String,UserGroupInformation>(
+ conf.getLong(QueryServerProperties.QUERY_SERVER_UGI_CACHE_MAX_SIZE,
+ QueryServerOptions.DEFAULT_QUERY_SERVER_UGI_CACHE_MAX_SIZE),
+ conf.getInt(QueryServerProperties.QUERY_SERVER_UGI_CACHE_CONCURRENCY,
+ QueryServerOptions.DEFAULT_QUERY_SERVER_UGI_CACHE_CONCURRENCY));
}
@Override
@@ -600,37 +597,21 @@ public final class QueryServer extends Configured implements Tool, Runnable {
});
}
- @VisibleForTesting
+ //@VisibleForTesting
UserGroupInformation createProxyUser(String remoteUserName) throws ExecutionException {
// PHOENIX-3164 UGI's hashCode and equals methods rely on reference checks, not
// value-based checks. We need to make sure we return the same UGI instance for a remote
// user, otherwise downstream code in Phoenix and HBase may not treat two of the same
// calls from one user as equivalent.
- return ugiCache.get(remoteUserName);
+ return ugiCache.computeIfAbsent(remoteUserName, f -> UserGroupInformation.createProxyUser(f, serverUgi));
}
- @VisibleForTesting
- LoadingCache<String,UserGroupInformation> getCache() {
+ //@VisibleForTesting
+ SimpleLRUCache<String,UserGroupInformation> getCache() {
return ugiCache;
}
}
- /**
- * CacheLoader implementation which creates a "proxy" UGI instance for the given user name.
- */
- static class UgiCacheLoader extends CacheLoader<String,UserGroupInformation> {
- private final UserGroupInformation serverUgi;
-
- public UgiCacheLoader(UserGroupInformation serverUgi) {
- this.serverUgi = Objects.requireNonNull(serverUgi);
- }
-
- @Override
- public UserGroupInformation load(String remoteUserName) throws Exception {
- return UserGroupInformation.createProxyUser(remoteUserName, serverUgi);
- }
- }
-
public static void main(String[] argv) throws Exception {
int ret = ToolRunner.run(HBaseConfiguration.create(), new QueryServer(), argv);
System.exit(ret);
diff --git a/queryserver/src/main/java/org/apache/phoenix/util/HostAndPort.java b/queryserver/src/main/java/org/apache/phoenix/util/HostAndPort.java
new file mode 100644
index 0000000..e01a005
--- /dev/null
+++ b/queryserver/src/main/java/org/apache/phoenix/util/HostAndPort.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.phoenix.util;
+
+import java.io.Serializable;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * This class has been copied from Guava 13.0.1, and modified so that it works without the rest
+ * of Guava.
+ *
+ * An immutable representation of a host and port.
+ *
+ * <p>Example usage:
+ * <pre>
+ * HostAndPort hp = HostAndPort.fromString("[2001:db8::1]")
+ * .withDefaultPort(80)
+ * .requireBracketsForIPv6();
+ * hp.getHostText(); // returns "2001:db8::1"
+ * hp.getPort(); // returns 80
+ * hp.toString(); // returns "[2001:db8::1]:80"
+ * </pre>
+ *
+ * <p>Here are some examples of recognized formats:
+ * <ul>
+ * <li>example.com
+ * <li>example.com:80
+ * <li>192.0.2.1
+ * <li>192.0.2.1:80
+ * <li>[2001:db8::1] - {@link #getHostText()} omits brackets
+ * <li>[2001:db8::1]:80 - {@link #getHostText()} omits brackets
+ * <li>2001:db8::1 - Use {@link #requireBracketsForIPv6()} to prohibit this
+ * </ul>
+ *
+ * <p>Note that this is not an exhaustive list, because these methods are only
+ * concerned with brackets, colons, and port numbers. Full validation of the
+ * host field (if desired) is the caller's responsibility.
+ *
+ * @author Paul Marks
+ * @since 10.0
+ */
+@Immutable
+public final class HostAndPort implements Serializable {
+ /** Magic value indicating the absence of a port number. */
+ private static final int NO_PORT = -1;
+
+ /** Hostname, IPv4/IPv6 literal, or unvalidated nonsense. */
+ private final String host;
+
+ /** Validated port number in the range [0..65535], or NO_PORT */
+ private final int port;
+
+ /** True if the parsed host has colons, but no surrounding brackets. */
+ private final boolean hasBracketlessColons;
+
+ private HostAndPort(String host, int port, boolean hasBracketlessColons) {
+ this.host = host;
+ this.port = port;
+ this.hasBracketlessColons = hasBracketlessColons;
+ }
+
+ /**
+ * Returns the portion of this {@code HostAndPort} instance that should
+ * represent the hostname or IPv4/IPv6 literal.
+ *
+ * A successful parse does not imply any degree of sanity in this field.
+ * For additional validation, see the HostSpecifier class.
+ */
+ public String getHostText() {
+ return host;
+ }
+
+ /** Return true if this instance has a defined port. */
+ public boolean hasPort() {
+ return port >= 0;
+ }
+
+ /**
+ * Get the current port number, failing if no port is defined.
+ *
+ * @return a validated port number, in the range [0..65535]
+ * @throws IllegalStateException if no port is defined. You can use
+ * {@link #withDefaultPort(int)} to prevent this from occurring.
+ */
+ public int getPort() {
+ if (!hasPort()) {
+ throw new IllegalStateException();
+ }
+ return port;
+ }
+
+ /**
+ * Returns the current port number, with a default if no port is defined.
+ */
+ public int getPortOrDefault(int defaultPort) {
+ return hasPort() ? port : defaultPort;
+ }
+
+ /**
+ * Build a HostAndPort instance from separate host and port values.
+ *
+ * <p>Note: Non-bracketed IPv6 literals are allowed.
+ * Use {@link #requireBracketsForIPv6()} to prohibit these.
+ *
+ * @param host the host string to parse. Must not contain a port number.
+ * @param port a port number from [0..65535]
+ * @return if parsing was successful, a populated HostAndPort object.
+ * @throws IllegalArgumentException if {@code host} contains a port number,
+ * or {@code port} is out of range.
+ */
+ public static HostAndPort fromParts(String host, int port) {
+ if (!isValidPort(port)) {
+ throw new IllegalArgumentException();
+ }
+ HostAndPort parsedHost = fromString(host);
+ if (parsedHost.hasPort()) {
+ throw new IllegalArgumentException();
+ }
+ return new HostAndPort(parsedHost.host, port, parsedHost.hasBracketlessColons);
+ }
+
+ private static final Pattern BRACKET_PATTERN = Pattern.compile("^\\[(.*:.*)\\](?::(\\d*))?$");
+
+ /**
+ * Split a freeform string into a host and port, without strict validation.
+ *
+ * Note that the host-only formats will leave the port field undefined. You
+ * can use {@link #withDefaultPort(int)} to patch in a default value.
+ *
+ * @param hostPortString the input string to parse.
+ * @return if parsing was successful, a populated HostAndPort object.
+ * @throws IllegalArgumentException if nothing meaningful could be parsed.
+ */
+ public static HostAndPort fromString(String hostPortString) {
+ if(hostPortString == null) {
+ throw new NullPointerException();
+ }
+ String host;
+ String portString = null;
+ boolean hasBracketlessColons = false;
+
+ if (hostPortString.startsWith("[")) {
+ // Parse a bracketed host, typically an IPv6 literal.
+ Matcher matcher = BRACKET_PATTERN.matcher(hostPortString);
+ if (!matcher.matches()) {
+ throw new IllegalArgumentException(
+ String.format("Invalid bracketed host/port: %s", hostPortString));
+ }
+ host = matcher.group(1);
+ portString = matcher.group(2); // could be null
+ } else {
+ int colonPos = hostPortString.indexOf(':');
+ if (colonPos >= 0 && hostPortString.indexOf(':', colonPos + 1) == -1) {
+ // Exactly 1 colon. Split into host:port.
+ host = hostPortString.substring(0, colonPos);
+ portString = hostPortString.substring(colonPos + 1);
+ } else {
+ // 0 or 2+ colons. Bare hostname or IPv6 literal.
+ host = hostPortString;
+ hasBracketlessColons = (colonPos >= 0);
+ }
+ }
+
+ int port = NO_PORT;
+ if (portString != null) {
+ // Try to parse the whole port string as a number.
+ // JDK7 accepts leading plus signs. We don't want to.
+ if (!!portString.startsWith("+")) {
+ throw new IllegalArgumentException(
+ String.format("Unparseable port number: %s", hostPortString));
+ }
+ try {
+ port = Integer.parseInt(portString);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Unparseable port number: " + hostPortString);
+ }
+ if (!isValidPort(port)) {
+ throw new IllegalArgumentException(
+ String.format("Port number out of range: %s", hostPortString));
+ }
+ }
+
+ return new HostAndPort(host, port, hasBracketlessColons);
+ }
+
+ /**
+ * Provide a default port if the parsed string contained only a host.
+ *
+ * You can chain this after {@link #fromString(String)} to include a port in
+ * case the port was omitted from the input string. If a port was already
+ * provided, then this method is a no-op.
+ *
+ * @param defaultPort a port number, from [0..65535]
+ * @return a HostAndPort instance, guaranteed to have a defined port.
+ */
+ public HostAndPort withDefaultPort(int defaultPort) {
+ if (!isValidPort(defaultPort)) {
+ throw new IllegalArgumentException();
+ }
+ if (hasPort() || port == defaultPort) {
+ return this;
+ }
+ return new HostAndPort(host, defaultPort, hasBracketlessColons);
+ }
+
+ /**
+ * Generate an error if the host might be a non-bracketed IPv6 literal.
+ *
+ * <p>URI formatting requires that IPv6 literals be surrounded by brackets,
+ * like "[2001:db8::1]". Chain this call after {@link #fromString(String)}
+ * to increase the strictness of the parser, and disallow IPv6 literals
+ * that don't contain these brackets.
+ *
+ * <p>Note that this parser identifies IPv6 literals solely based on the
+ * presence of a colon. To perform actual validation of IP addresses, see
+ * the InetAddresses#forString(String) method.
+ *
+ * @return {@code this}, to enable chaining of calls.
+ * @throws IllegalArgumentException if bracketless IPv6 is detected.
+ */
+ public HostAndPort requireBracketsForIPv6() {
+ if (hasBracketlessColons) {
+ throw new IllegalArgumentException(
+ String.format("Possible bracketless IPv6 literal: %s", host));
+ }
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (other instanceof HostAndPort) {
+ HostAndPort that = (HostAndPort) other;
+ return Objects.equals(this.host, that.host)
+ && this.port == that.port
+ && this.hasBracketlessColons == that.hasBracketlessColons;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(host, port, hasBracketlessColons);
+ }
+
+ /** Rebuild the host:port string, including brackets if necessary. */
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder(host.length() + 7);
+ if (host.indexOf(':') >= 0) {
+ builder.append('[').append(host).append(']');
+ } else {
+ builder.append(host);
+ }
+ if (hasPort()) {
+ builder.append(':').append(port);
+ }
+ return builder.toString();
+ }
+
+ /** Return true for valid port numbers. */
+ private static boolean isValidPort(int port) {
+ return port >= 0 && port <= 65535;
+ }
+
+ private static final long serialVersionUID = 0;
+}
diff --git a/queryserver/src/main/java/org/apache/phoenix/util/InstanceResolver.java b/queryserver/src/main/java/org/apache/phoenix/util/InstanceResolver.java
index 4757e46..8a84a92 100644
--- a/queryserver/src/main/java/org/apache/phoenix/util/InstanceResolver.java
+++ b/queryserver/src/main/java/org/apache/phoenix/util/InstanceResolver.java
@@ -19,8 +19,6 @@ package org.apache.phoenix.util;
import org.apache.commons.collections.IteratorUtils;
-import com.google.common.annotations.VisibleForTesting;
-
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
@@ -88,7 +86,7 @@ public class InstanceResolver {
return defaultInstance;
}
- @VisibleForTesting
+ //@VisibleForTesting
public static void clearSingletons() {
RESOLVED_SINGLETONS.clear();
}
diff --git a/queryserver/src/main/java/org/apache/phoenix/util/SimpleLRUCache.java b/queryserver/src/main/java/org/apache/phoenix/util/SimpleLRUCache.java
new file mode 100644
index 0000000..97e47f3
--- /dev/null
+++ b/queryserver/src/main/java/org/apache/phoenix/util/SimpleLRUCache.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.util;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Minimal Cache implementation based on ConcurrentHashMap.
+ *
+ * The maxSize logic will only work if all access is via the the computeIfAbsent() method.
+ *
+ */
+public class SimpleLRUCache <K extends Comparable, V> extends ConcurrentHashMap<K,V> {
+
+ protected static final Logger LOG = LoggerFactory.getLogger(SimpleLRUCache.class);
+
+ int maxSize;
+ int triggerSize;
+
+ private ConcurrentHashMap<K, AtomicLong> accessed =
+ new ConcurrentHashMap<>();
+
+ public SimpleLRUCache (long maxSize, int concurrencyLevel) {
+ super((int)(maxSize * 1.1), (float)0.75, concurrencyLevel);
+ this.maxSize = (int)maxSize;
+ this.triggerSize = (int)(maxSize * 1.1)+1 ;
+ }
+
+ @Override
+ public V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction) {
+ V value = super.computeIfAbsent(key, mappingFunction);
+ if (value != null) {
+ accessed.put(key, new AtomicLong(System.currentTimeMillis()));
+ if (this.size() > triggerSize) {
+ evict();
+ }
+ }
+ return value;
+ }
+
+ private void evict() {
+ synchronized(this) {
+ int currentSize = this.size();
+ if (currentSize <= triggerSize) {
+ return;
+ }
+ LOG.warn("UGI Cache capacity exceeded, you may want to increase its size");
+ TreeSet<Entry<K, AtomicLong>> sortedByLRU = new TreeSet<>(
+ new Comparator<Entry<K, AtomicLong>>() {
+ @Override
+ public int compare(Entry<K, AtomicLong> o1, Entry<K, AtomicLong> o2) {
+ int keyResult =
+ Long.compare(o2.getValue().get(), o1.getValue().get());
+ if(keyResult == 0) {
+ return o2.getKey().compareTo(o1.getKey());
+ } else {
+ return keyResult;
+ }
+ }
+ });
+ sortedByLRU.addAll(accessed.entrySet());
+ Entry<Object, AtomicLong>[] toRetain =
+ Arrays.copyOfRange(sortedByLRU.toArray(new Entry[currentSize]), 0, maxSize);
+ java.util.List<Object> retainList =
+ Arrays.stream(toRetain).map( f -> f.getKey()).collect(Collectors.toList());
+ this.keySet().retainAll(retainList);
+ accessed.keySet().retainAll(this.keySet());
+ }
+ }
+
+}
diff --git a/queryserver/src/test/java/org/apache/phoenix/queryserver/util/SimpleLRUCacheTest.java b/queryserver/src/test/java/org/apache/phoenix/queryserver/util/SimpleLRUCacheTest.java
new file mode 100644
index 0000000..e1e6d88
--- /dev/null
+++ b/queryserver/src/test/java/org/apache/phoenix/queryserver/util/SimpleLRUCacheTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.queryserver.util;
+
+import static org.junit.Assert.assertTrue;
+
+import org.apache.phoenix.util.SimpleLRUCache;
+import org.junit.Test;
+
+public class SimpleLRUCacheTest {
+
+ @Test
+ public void testCache() throws InterruptedException {
+ SimpleLRUCache<String, String> cache = new SimpleLRUCache<>(10, 1);
+
+ String zero = access(cache, "0");
+ //Make sure we actually cache objects
+ assertTrue(zero == access(cache, "0"));
+
+ for(int c=1; c<9; c++) {
+ access(cache, Integer.toString(c));
+ Thread.sleep(5);
+ }
+
+ //Access these to make sure that they don't get evicted.
+ String one = access(cache, "1");
+ String two = access(cache, "2");
+
+ for(int c=10; c<13; c++) {
+ access(cache, Integer.toString(c));
+ Thread.sleep(5);
+ }
+
+ assertTrue(one == access(cache, one));
+ assertTrue(two == access(cache, two));
+
+ assertTrue(cache.size() <= 12);
+ }
+
+ private String access(SimpleLRUCache<String, String> cache, String key) {
+ return cache.computeIfAbsent(key, k -> new String(key));
+ }
+}