From e7a50011edc19aea3b9ef1c611e4e59d8df2227e Mon Sep 17 00:00:00 2001 From: Alex Moore Date: Wed, 28 Sep 2016 11:58:26 -0400 Subject: [PATCH 1/4] Adding cleanup method for container environments --- .../com/basho/riak/client/api/RiakClient.java | 14 ++++++++ .../basho/riak/client/core/RiakCluster.java | 15 ++++++++ .../riak/client/core/RiakClusterTest.java | 36 +++++++++++++++++-- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/basho/riak/client/api/RiakClient.java b/src/main/java/com/basho/riak/client/api/RiakClient.java index 6ce3d0677..f835ac315 100644 --- a/src/main/java/com/basho/riak/client/api/RiakClient.java +++ b/src/main/java/com/basho/riak/client/api/RiakClient.java @@ -190,6 +190,7 @@ public static RiakClient newClient() throws UnknownHostException RiakCluster cluster = new RiakCluster.Builder(builder.build()).build(); cluster.start(); return new RiakClient(cluster); + } /** @@ -427,4 +428,17 @@ public RiakCluster getRiakCluster() { return cluster; } + + /** + * Cleans up any Thread-Local variables after shutdown. + * This operation is useful when you are in a container environment, and you + * do not want to leave the thread local variables in the threads you do not manage. + * Call this method when your application is being unloaded from the container, after + * all {@link RiakNode}, {@link RiakCluster}, and {@link com.basho.riak.client.api.RiakClient} + * objects are in the shutdown state. + */ + public void cleanup() + { + cluster.cleanup(); + } } diff --git a/src/main/java/com/basho/riak/client/core/RiakCluster.java b/src/main/java/com/basho/riak/client/core/RiakCluster.java index 91f5f0a32..e49a84e83 100644 --- a/src/main/java/com/basho/riak/client/core/RiakCluster.java +++ b/src/main/java/com/basho/riak/client/core/RiakCluster.java @@ -635,6 +635,21 @@ public static Builder builder(RiakNode node) return new Builder(node); } + /** + * Cleans up any Thread-Local variables after shutdown. + * This operation is useful when you are in a container environment, and you + * do not want to leave the thread local variables in the threads you do not manage. + * Call this method when your application is being unloaded from the container, after + * all {@link RiakNode}, {@link RiakCluster}, and {@link com.basho.riak.client.api.RiakClient} + * objects are in the shutdown state. + */ + public synchronized void cleanup() + { + stateCheck(State.SHUTDOWN); + io.netty.util.concurrent.FastThreadLocal.removeAll(); + io.netty.util.concurrent.FastThreadLocal.destroy(); + } + /** * Builder used to create {@link RiakCluster} instances. */ diff --git a/src/test/java/com/basho/riak/client/core/RiakClusterTest.java b/src/test/java/com/basho/riak/client/core/RiakClusterTest.java index a19ed3b72..9eb48c080 100644 --- a/src/test/java/com/basho/riak/client/core/RiakClusterTest.java +++ b/src/test/java/com/basho/riak/client/core/RiakClusterTest.java @@ -16,6 +16,7 @@ package com.basho.riak.client.core; import com.google.protobuf.Message; +import io.netty.util.concurrent.FastThreadLocal; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; @@ -30,14 +31,14 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.*; - +import static org.powermock.api.mockito.PowerMockito.verifyStatic; /** * * @author Brian Roach * @author Sergey Galkin */ @RunWith(PowerMockRunner.class) -@PrepareForTest(FutureOperation.class) +@PrepareForTest({FutureOperation.class, FastThreadLocal.class}) public class RiakClusterTest { @Test @@ -222,6 +223,37 @@ public void nodeOperationQueue() throws Exception verify(nodeManager, times(1)).executeOnNode(operation4, null); } + @Test + public void testCleanup() throws Exception + { + RiakNode node = mock(RiakNode.class); + RiakNode.Builder nodeBuilder = spy(new RiakNode.Builder()); + doReturn(node).when(nodeBuilder).build(); + PowerMockito.mockStatic(FastThreadLocal.class); + PowerMockito.doNothing().when(FastThreadLocal.class, "destroy"); + PowerMockito.doNothing().when(FastThreadLocal.class, "removeAll"); + + RiakCluster cluster = new RiakCluster.Builder(nodeBuilder.build()).build(); + Whitebox.setInternalState(cluster, "state", RiakCluster.State.SHUTDOWN); + + cluster.cleanup(); + + verifyStatic(times(2)); + } + + @Test(expected = IllegalStateException.class) + public void testCleanupNotShutdown() + { + RiakNode node = mock(RiakNode.class); + RiakNode.Builder nodeBuilder = spy(new RiakNode.Builder()); + doReturn(node).when(nodeBuilder).build(); + + RiakCluster cluster = new RiakCluster.Builder(nodeBuilder.build()).build(); + Whitebox.setInternalState(cluster, "state", RiakCluster.State.RUNNING); + + cluster.cleanup(); + } + private void assertQueueStatus(RiakCluster cluster, Integer expectedQueueSize, RiakCluster.State expectedClusterState, FutureOperation expectedQueueHead) From 41e2cfc35ea44dafe48b8295ce05140d57db04d1 Mon Sep 17 00:00:00 2001 From: Alex Moore Date: Wed, 28 Sep 2016 13:19:05 -0400 Subject: [PATCH 2/4] Run flaky test a few times --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 01f4ce99e..3af779c08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,9 @@ before_script: false script: - if [ $RIAK_FLAVOR == "riak-kv" ]; then mvn -Pitest,default -Dcom.basho.riak.yokozuna=false - verify; else echo "Not riak-kv flavor"; fi + verify; for i in {1..10}; do mvn -Ptest-debug-logging surefire:test -Dtest=RiakClusterTest; done; else echo "Not riak-kv flavor"; fi - if [ $RIAK_FLAVOR == "riak-ts" ]; then mvn -Pitest,default -Dcom.basho.riak.yokozuna=false - -Dcom.basho.riak.timeseries=true verify; else echo "Not riak-ts flavor"; fi + -Dcom.basho.riak.timeseries=true verify; for i in {1..10}; do mvn -Ptest-debug-logging surefire:test -Dtest=RiakClusterTest; done; else echo "Not riak-ts flavor"; fi after_script: - docker rm -f $RIAK_FLAVOR env: From d89528b64fa76044f65b22096aedb5f31b3f2898 Mon Sep 17 00:00:00 2001 From: Alex Moore Date: Wed, 28 Sep 2016 16:09:30 -0400 Subject: [PATCH 3/4] Remove empty line, cleanup travis script --- .travis.yml | 6 ++---- src/main/java/com/basho/riak/client/api/RiakClient.java | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3af779c08..f1c87ec2b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,10 +13,8 @@ before_script: - tools/devrel/riak-cluster-config "docker exec $RIAK_FLAVOR riak-admin" 8098 false false script: -- if [ $RIAK_FLAVOR == "riak-kv" ]; then mvn -Pitest,default -Dcom.basho.riak.yokozuna=false - verify; for i in {1..10}; do mvn -Ptest-debug-logging surefire:test -Dtest=RiakClusterTest; done; else echo "Not riak-kv flavor"; fi -- if [ $RIAK_FLAVOR == "riak-ts" ]; then mvn -Pitest,default -Dcom.basho.riak.yokozuna=false - -Dcom.basho.riak.timeseries=true verify; for i in {1..10}; do mvn -Ptest-debug-logging surefire:test -Dtest=RiakClusterTest; done; else echo "Not riak-ts flavor"; fi +- if [[ $RIAK_FLAVOR == "riak-kv" ]]; then mvn -Pitest,default -Dcom.basho.riak.yokozuna=false verify; fi +- if [[ $RIAK_FLAVOR == "riak-ts" ]]; then mvn -Pitest,default -Dcom.basho.riak.yokozuna=false -Dcom.basho.riak.timeseries=true verify; fi after_script: - docker rm -f $RIAK_FLAVOR env: diff --git a/src/main/java/com/basho/riak/client/api/RiakClient.java b/src/main/java/com/basho/riak/client/api/RiakClient.java index f835ac315..114c31b38 100644 --- a/src/main/java/com/basho/riak/client/api/RiakClient.java +++ b/src/main/java/com/basho/riak/client/api/RiakClient.java @@ -190,7 +190,6 @@ public static RiakClient newClient() throws UnknownHostException RiakCluster cluster = new RiakCluster.Builder(builder.build()).build(); cluster.start(); return new RiakClient(cluster); - } /** From 4ea6eeaa3adbf6fd00f2a6901b508f2c0ebe34c7 Mon Sep 17 00:00:00 2001 From: Alex Moore Date: Wed, 28 Sep 2016 20:08:48 -0400 Subject: [PATCH 4/4] Bump tools version so we can have the proper travis scripts --- tools | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools b/tools index 8d1b6e502..f00acf115 160000 --- a/tools +++ b/tools @@ -1 +1 @@ -Subproject commit 8d1b6e502a4082693e935774a77a73d4896e4bf5 +Subproject commit f00acf1152e1dc493737939ac338a02215177345